diff --git a/blas/.travis/check-generate.sh b/blas/.travis/check-generate.sh new file mode 100755 index 00000000..167c98bf --- /dev/null +++ b/blas/.travis/check-generate.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -ex + +go generate github.com/gonum/blas/native +go generate github.com/gonum/blas/cgo +if [ -n "$(git diff)" ]; then + exit 1 +fi diff --git a/blas/.travis/linux/ATLAS/install.sh b/blas/.travis/linux/ATLAS/install.sh new file mode 100644 index 00000000..923dcf5e --- /dev/null +++ b/blas/.travis/linux/ATLAS/install.sh @@ -0,0 +1,21 @@ +set -ex + +# fetch and install ATLAS libs +sudo apt-get update -qq && sudo apt-get install -qq libatlas-base-dev + +# fetch and install gonum/blas against ATLAS +export CGO_LDFLAGS="-L/usr/lib -lblas" +go get github.com/gonum/blas + +# run the OS common installation script +source ${TRAVIS_BUILD_DIR}/.travis/$TRAVIS_OS_NAME/install.sh + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/linux/ATLAS/test.sh b/blas/.travis/linux/ATLAS/test.sh new file mode 100644 index 00000000..37dc167d --- /dev/null +++ b/blas/.travis/linux/ATLAS/test.sh @@ -0,0 +1,17 @@ +set -ex + +go env +go get -d -t -v ./... +go test -a -v ./... +go test -a -tags noasm -v ./... +if [[ $TRAVIS_SECURE_ENV_VARS = "true" ]]; then bash -c "$GOPATH/src/github.com/$TRAVIS_REPO_SLUG/.travis/test-coverage.sh"; fi + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/linux/OpenBLAS/install.sh b/blas/.travis/linux/OpenBLAS/install.sh new file mode 100644 index 00000000..97c4ace3 --- /dev/null +++ b/blas/.travis/linux/OpenBLAS/install.sh @@ -0,0 +1,71 @@ +set -ex + +CACHE_DIR=${TRAVIS_BUILD_DIR}/.travis/${BLAS_LIB}.cache + +# fetch fortran to build OpenBLAS +sudo apt-get update -qq && sudo apt-get install -qq gfortran + +# check if cache exists +if [ -e ${CACHE_DIR}/last_commit_id ]; then + echo "Cache $CACHE_DIR hit" + LAST_COMMIT="$(git ls-remote git://github.com/xianyi/OpenBLAS HEAD | grep -o '^\S*')" + CACHED_COMMIT="$(cat ${CACHE_DIR}/last_commit_id)" + # determine current OpenBLAS master commit id and compare + # with commit id in cache directory + if [ "$LAST_COMMIT" != "$CACHED_COMMIT" ]; then + echo "Cache Directory $CACHE_DIR has stale commit" + # if commit is different, delete the cache + rm -rf ${CACHE_DIR} + fi +fi + +if [ ! -e ${CACHE_DIR}/last_commit_id ]; then + # Clear cache. + rm -rf ${CACHE_DIR} + + # cache generation + echo "Building cache at $CACHE_DIR" + mkdir ${CACHE_DIR} + sudo git clone --depth=1 git://github.com/xianyi/OpenBLAS + + pushd OpenBLAS + sudo make FC=gfortran &> /dev/null && sudo make PREFIX=${CACHE_DIR} install + popd + + curl http://www.netlib.org/blas/blast-forum/cblas.tgz | tar -zx + + pushd CBLAS + sudo mv Makefile.LINUX Makefile.in + sudo BLLIB=${CACHE_DIR}/lib/libopenblas.a make alllib + sudo mv lib/cblas_LINUX.a ${CACHE_DIR}/lib/libcblas.a + popd + + # Record commit id used to generate cache. + pushd OpenBLAS + echo $(git rev-parse HEAD) > ${CACHE_DIR}/last_commit_id + popd + +fi + +# copy the cache files into /usr +sudo cp -r ${CACHE_DIR}/* /usr/ + +# install gonum/blas against OpenBLAS +export CGO_LDFLAGS="-L/usr/lib -lopenblas" +go get github.com/gonum/blas +pushd cgo +go install -v -x +popd + +# run the OS common installation script +source ${TRAVIS_BUILD_DIR}/.travis/$TRAVIS_OS_NAME/install.sh + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/linux/OpenBLAS/test.sh b/blas/.travis/linux/OpenBLAS/test.sh new file mode 100644 index 00000000..37dc167d --- /dev/null +++ b/blas/.travis/linux/OpenBLAS/test.sh @@ -0,0 +1,17 @@ +set -ex + +go env +go get -d -t -v ./... +go test -a -v ./... +go test -a -tags noasm -v ./... +if [[ $TRAVIS_SECURE_ENV_VARS = "true" ]]; then bash -c "$GOPATH/src/github.com/$TRAVIS_REPO_SLUG/.travis/test-coverage.sh"; fi + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/linux/gonum/install.sh b/blas/.travis/linux/gonum/install.sh new file mode 100644 index 00000000..266fa0ca --- /dev/null +++ b/blas/.travis/linux/gonum/install.sh @@ -0,0 +1,18 @@ +set -ex + +# run the OS common installation script +source ${TRAVIS_BUILD_DIR}/.travis/$TRAVIS_OS_NAME/install.sh + +# change to native directory so we don't test code that depends on an external +# blas library +cd native + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/linux/gonum/test.sh b/blas/.travis/linux/gonum/test.sh new file mode 100644 index 00000000..37dc167d --- /dev/null +++ b/blas/.travis/linux/gonum/test.sh @@ -0,0 +1,17 @@ +set -ex + +go env +go get -d -t -v ./... +go test -a -v ./... +go test -a -tags noasm -v ./... +if [[ $TRAVIS_SECURE_ENV_VARS = "true" ]]; then bash -c "$GOPATH/src/github.com/$TRAVIS_REPO_SLUG/.travis/test-coverage.sh"; fi + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/linux/install.sh b/blas/.travis/linux/install.sh new file mode 100644 index 00000000..842385a0 --- /dev/null +++ b/blas/.travis/linux/install.sh @@ -0,0 +1,21 @@ +set -ex + +# This script contains common installation commands for linux. It should be run +# prior to more specific installation commands for a particular blas library. +go get golang.org/x/tools/cmd/cover +go get github.com/mattn/goveralls +go get github.com/gonum/floats + +# Repositories for code generation. +go get github.com/gonum/internal/binding +go get github.com/cznic/cc + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/osx/Accelerate/install.sh b/blas/.travis/osx/Accelerate/install.sh new file mode 100644 index 00000000..1dd9a1d6 --- /dev/null +++ b/blas/.travis/osx/Accelerate/install.sh @@ -0,0 +1,20 @@ +set -ex + +export CGO_LDFLAGS="-framework Accelerate" +go get github.com/gonum/blas +pushd cgo +go install -v -x +popd + +# run the OS common installation script +source ${TRAVIS_BUILD_DIR}/.travis/$TRAVIS_OS_NAME/install.sh + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/osx/Accelerate/test.sh b/blas/.travis/osx/Accelerate/test.sh new file mode 100644 index 00000000..37dc167d --- /dev/null +++ b/blas/.travis/osx/Accelerate/test.sh @@ -0,0 +1,17 @@ +set -ex + +go env +go get -d -t -v ./... +go test -a -v ./... +go test -a -tags noasm -v ./... +if [[ $TRAVIS_SECURE_ENV_VARS = "true" ]]; then bash -c "$GOPATH/src/github.com/$TRAVIS_REPO_SLUG/.travis/test-coverage.sh"; fi + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/osx/OpenBLAS/install.sh b/blas/.travis/osx/OpenBLAS/install.sh new file mode 100644 index 00000000..5b60bdc3 --- /dev/null +++ b/blas/.travis/osx/OpenBLAS/install.sh @@ -0,0 +1,24 @@ +set -ex + +# fetch and install OpenBLAS using homebrew +brew install homebrew/science/openblas + +# fetch and install gonum/blas against OpenBLAS +export CGO_LDFLAGS="-L/usr/local/opt/openblas/lib -lopenblas" +go get github.com/gonum/blas +pushd cgo +go install -v -x +popd + +# run the OS common installation script +source ${TRAVIS_BUILD_DIR}/.travis/$TRAVIS_OS_NAME/install.sh + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/osx/OpenBLAS/test.sh b/blas/.travis/osx/OpenBLAS/test.sh new file mode 100644 index 00000000..37dc167d --- /dev/null +++ b/blas/.travis/osx/OpenBLAS/test.sh @@ -0,0 +1,17 @@ +set -ex + +go env +go get -d -t -v ./... +go test -a -v ./... +go test -a -tags noasm -v ./... +if [[ $TRAVIS_SECURE_ENV_VARS = "true" ]]; then bash -c "$GOPATH/src/github.com/$TRAVIS_REPO_SLUG/.travis/test-coverage.sh"; fi + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/osx/gonum/install.sh b/blas/.travis/osx/gonum/install.sh new file mode 100644 index 00000000..266fa0ca --- /dev/null +++ b/blas/.travis/osx/gonum/install.sh @@ -0,0 +1,18 @@ +set -ex + +# run the OS common installation script +source ${TRAVIS_BUILD_DIR}/.travis/$TRAVIS_OS_NAME/install.sh + +# change to native directory so we don't test code that depends on an external +# blas library +cd native + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/osx/gonum/test.sh b/blas/.travis/osx/gonum/test.sh new file mode 100644 index 00000000..37dc167d --- /dev/null +++ b/blas/.travis/osx/gonum/test.sh @@ -0,0 +1,17 @@ +set -ex + +go env +go get -d -t -v ./... +go test -a -v ./... +go test -a -tags noasm -v ./... +if [[ $TRAVIS_SECURE_ENV_VARS = "true" ]]; then bash -c "$GOPATH/src/github.com/$TRAVIS_REPO_SLUG/.travis/test-coverage.sh"; fi + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/.travis/osx/install.sh b/blas/.travis/osx/install.sh new file mode 100644 index 00000000..0403e7c8 --- /dev/null +++ b/blas/.travis/osx/install.sh @@ -0,0 +1,23 @@ +set -ex + +#!/bin/bash + +# This script contains common installation commands for osx. It should be run +# prior to more specific installation commands for a particular blas library. +go get golang.org/x/tools/cmd/cover +go get github.com/mattn/goveralls +go get github.com/gonum/floats + +# Repositories for code generation. +go get github.com/gonum/internal/binding +go get github.com/cznic/cc + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/blas/README.md b/blas/README.md new file mode 100644 index 00000000..5e5cf886 --- /dev/null +++ b/blas/README.md @@ -0,0 +1,96 @@ +# Gonum BLAS [![Build Status](https://travis-ci.org/gonum/blas.svg?branch=master)](https://travis-ci.org/gonum/blas) [![Coverage Status](https://coveralls.io/repos/gonum/blas/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/blas?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/blas?status.svg)](https://godoc.org/github.com/gonum/blas) + +A collection of packages to provide BLAS functionality for the [Go programming +language](http://golang.org) + +## Installation +```sh + go get github.com/gonum/blas +``` + +### BLAS C-bindings + +If you want to use OpenBLAS, install it in any directory: +```sh + git clone https://github.com/xianyi/OpenBLAS + cd OpenBLAS + make +``` + +The blas/cgo package provides bindings to C-backed BLAS packages. blas/cgo needs the `CGO_LDFLAGS` +environment variable to point to the blas installation. More information can be found in the +[cgo command documentation](http://golang.org/cmd/cgo/). + +Then install the blas/cgo package: +```sh + CGO_LDFLAGS="-L/path/to/OpenBLAS -lopenblas" go install github.com/gonum/blas/cgo +``` + +For Windows you can download binary packages for OpenBLAS at +[SourceForge](http://sourceforge.net/projects/openblas/files/). + +If you want to use a different BLAS package such as the Intel MKL you can +adjust the `CGO_LDFLAGS` variable: +```sh + CGO_LDFLAGS="-lmkl_rt" go install github.com/gonum/blas/cgo +``` + +On OS X the easiest solution is to use the libraries provided by the system: +```sh + CGO_LDFLAGS="-framework Accelerate" go install github.com/gonum/blas/cgo +``` + +## Packages + +### blas + +Defines [BLAS API](http://www.netlib.org/blas/blast-forum/cinterface.pdf) split in several +interfaces. + +### blas/native + +Go implementation of the BLAS API (incomplete, implements the `float32` and `float64` API) + +### blas/cgo + +Binding to a C implementation of the cblas interface (e.g. ATLAS, OpenBLAS, Intel MKL) + +The recommended (free) option for good performance on both Linux and Darwin is OpenBLAS. + +### blas/blas64 and blas/blas32 + +Wrappers for an implementation of the double (i.e., `float64`) and single (`float32`) +precision real parts of the blas API + +```Go +package main + +import ( + "fmt" + + "github.com/gonum/blas/blas64" +) + +func main() { + v := blas64.Vector{Inc: 1, Data: []float64{1, 1, 1}} + fmt.Println("v has length:", blas64.Nrm2(len(v.Data), v)) +} +``` + +### blas/cblas128 and blas/cblas64 + +Wrappers for an implementation of the double (i.e., `complex128`) and single (`complex64`) +precision complex parts of the blas API + +Currently blas/cblas64 and blas/cblas128 require blas/cgo. + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. +Discussions on API changes, added features, code review, or similar requests +are preferred on the [gonum-dev Google Group](https://groups.google.com/forum/#!forum/gonum-dev). + +## License + +Please see [github.com/gonum/license](https://github.com/gonum/license) for general +license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/blas/blas.go b/blas/blas.go new file mode 100644 index 00000000..6c14aac4 --- /dev/null +++ b/blas/blas.go @@ -0,0 +1,388 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package blas provides interfaces for the BLAS linear algebra standard. + +All methods must perform appropriate parameter checking and panic if +provided parameters that do not conform to the requirements specified +by the BLAS standard. + +Quick Reference Guide to the BLAS from http://www.netlib.org/lapack/lug/node145.html + +This version is modified to remove the "order" option. All matrix operations are +on row-order matrices. + +Level 1 BLAS + + dim scalar vector vector scalars 5-element prefixes + struct + + _rotg ( a, b ) S, D + _rotmg( d1, d2, a, b ) S, D + _rot ( n, x, incX, y, incY, c, s ) S, D + _rotm ( n, x, incX, y, incY, param ) S, D + _swap ( n, x, incX, y, incY ) S, D, C, Z + _scal ( n, alpha, x, incX ) S, D, C, Z, Cs, Zd + _copy ( n, x, incX, y, incY ) S, D, C, Z + _axpy ( n, alpha, x, incX, y, incY ) S, D, C, Z + _dot ( n, x, incX, y, incY ) S, D, Ds + _dotu ( n, x, incX, y, incY ) C, Z + _dotc ( n, x, incX, y, incY ) C, Z + __dot ( n, alpha, x, incX, y, incY ) Sds + _nrm2 ( n, x, incX ) S, D, Sc, Dz + _asum ( n, x, incX ) S, D, Sc, Dz + I_amax( n, x, incX ) s, d, c, z + +Level 2 BLAS + + options dim b-width scalar matrix vector scalar vector prefixes + + _gemv ( trans, m, n, alpha, a, lda, x, incX, beta, y, incY ) S, D, C, Z + _gbmv ( trans, m, n, kL, kU, alpha, a, lda, x, incX, beta, y, incY ) S, D, C, Z + _hemv ( uplo, n, alpha, a, lda, x, incX, beta, y, incY ) C, Z + _hbmv ( uplo, n, k, alpha, a, lda, x, incX, beta, y, incY ) C, Z + _hpmv ( uplo, n, alpha, ap, x, incX, beta, y, incY ) C, Z + _symv ( uplo, n, alpha, a, lda, x, incX, beta, y, incY ) S, D + _sbmv ( uplo, n, k, alpha, a, lda, x, incX, beta, y, incY ) S, D + _spmv ( uplo, n, alpha, ap, x, incX, beta, y, incY ) S, D + _trmv ( uplo, trans, diag, n, a, lda, x, incX ) S, D, C, Z + _tbmv ( uplo, trans, diag, n, k, a, lda, x, incX ) S, D, C, Z + _tpmv ( uplo, trans, diag, n, ap, x, incX ) S, D, C, Z + _trsv ( uplo, trans, diag, n, a, lda, x, incX ) S, D, C, Z + _tbsv ( uplo, trans, diag, n, k, a, lda, x, incX ) S, D, C, Z + _tpsv ( uplo, trans, diag, n, ap, x, incX ) S, D, C, Z + + options dim scalar vector vector matrix prefixes + + _ger ( m, n, alpha, x, incX, y, incY, a, lda ) S, D + _geru ( m, n, alpha, x, incX, y, incY, a, lda ) C, Z + _gerc ( m, n, alpha, x, incX, y, incY, a, lda ) C, Z + _her ( uplo, n, alpha, x, incX, a, lda ) C, Z + _hpr ( uplo, n, alpha, x, incX, ap ) C, Z + _her2 ( uplo, n, alpha, x, incX, y, incY, a, lda ) C, Z + _hpr2 ( uplo, n, alpha, x, incX, y, incY, ap ) C, Z + _syr ( uplo, n, alpha, x, incX, a, lda ) S, D + _spr ( uplo, n, alpha, x, incX, ap ) S, D + _syr2 ( uplo, n, alpha, x, incX, y, incY, a, lda ) S, D + _spr2 ( uplo, n, alpha, x, incX, y, incY, ap ) S, D + +Level 3 BLAS + + options dim scalar matrix matrix scalar matrix prefixes + + _gemm ( transA, transB, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) S, D, C, Z + _symm ( side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc ) S, D, C, Z + _hemm ( side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc ) C, Z + _syrk ( uplo, trans, n, k, alpha, a, lda, beta, c, ldc ) S, D, C, Z + _herk ( uplo, trans, n, k, alpha, a, lda, beta, c, ldc ) C, Z + _syr2k( uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) S, D, C, Z + _her2k( uplo, trans, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) C, Z + _trmm ( side, uplo, transA, diag, m, n, alpha, a, lda, b, ldb ) S, D, C, Z + _trsm ( side, uplo, transA, diag, m, n, alpha, a, lda, b, ldb ) S, D, C, Z + +Meaning of prefixes + + S - float32 C - complex64 + D - float64 Z - complex128 + +Matrix types + + GE - GEneral GB - General Band + SY - SYmmetric SB - Symmetric Band SP - Symmetric Packed + HE - HErmitian HB - Hermitian Band HP - Hermitian Packed + TR - TRiangular TB - Triangular Band TP - Triangular Packed + +Options + + trans = NoTrans, Trans, ConjTrans + uplo = Upper, Lower + diag = Nonunit, Unit + side = Left, Right (A or op(A) on the left, or A or op(A) on the right) + +For real matrices, Trans and ConjTrans have the same meaning. +For Hermitian matrices, trans = Trans is not allowed. +For complex symmetric matrices, trans = ConjTrans is not allowed. +*/ +package blas + +// Flag constants indicate Givens transformation H matrix state. +type Flag int + +const ( + Identity Flag = iota - 2 // H is the identity matrix; no rotation is needed. + Rescaling // H specifies rescaling. + OffDiagonal // Off-diagonal elements of H are units. + Diagonal // Diagonal elements of H are units. +) + +// SrotmParams contains Givens transformation parameters returned +// by the Float32 Srotm method. +type SrotmParams struct { + Flag + H [4]float32 // Column-major 2 by 2 matrix. +} + +// DrotmParams contains Givens transformation parameters returned +// by the Float64 Drotm method. +type DrotmParams struct { + Flag + H [4]float64 // Column-major 2 by 2 matrix. +} + +// Transpose is used to specify the transposition operation for a +// routine. +type Transpose int + +const ( + NoTrans Transpose = 111 + iota + Trans + ConjTrans +) + +// Uplo is used to specify whether the matrix is an upper or lower +// triangular matrix. +type Uplo int + +const ( + All Uplo = 120 + iota + Upper + Lower +) + +// Diag is used to specify whether the matrix is a unit or non-unit +// triangular matrix. +type Diag int + +const ( + NonUnit Diag = 131 + iota + Unit +) + +// Side is used to specify from which side a multiplication operation +// is performed. +type Side int + +const ( + Left Side = 141 + iota + Right +) + +// Float32 implements the single precision real BLAS routines. +type Float32 interface { + Float32Level1 + Float32Level2 + Float32Level3 +} + +// Float32Level1 implements the single precision real BLAS Level 1 routines. +type Float32Level1 interface { + Sdsdot(n int, alpha float32, x []float32, incX int, y []float32, incY int) float32 + Dsdot(n int, x []float32, incX int, y []float32, incY int) float64 + Sdot(n int, x []float32, incX int, y []float32, incY int) float32 + Snrm2(n int, x []float32, incX int) float32 + Sasum(n int, x []float32, incX int) float32 + Isamax(n int, x []float32, incX int) int + Sswap(n int, x []float32, incX int, y []float32, incY int) + Scopy(n int, x []float32, incX int, y []float32, incY int) + Saxpy(n int, alpha float32, x []float32, incX int, y []float32, incY int) + Srotg(a, b float32) (c, s, r, z float32) + Srotmg(d1, d2, b1, b2 float32) (p SrotmParams, rd1, rd2, rb1 float32) + Srot(n int, x []float32, incX int, y []float32, incY int, c, s float32) + Srotm(n int, x []float32, incX int, y []float32, incY int, p SrotmParams) + Sscal(n int, alpha float32, x []float32, incX int) +} + +// Float32Level2 implements the single precision real BLAS Level 2 routines. +type Float32Level2 interface { + Sgemv(tA Transpose, m, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) + Sgbmv(tA Transpose, m, n, kL, kU int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) + Strmv(ul Uplo, tA Transpose, d Diag, n int, a []float32, lda int, x []float32, incX int) + Stbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []float32, lda int, x []float32, incX int) + Stpmv(ul Uplo, tA Transpose, d Diag, n int, ap []float32, x []float32, incX int) + Strsv(ul Uplo, tA Transpose, d Diag, n int, a []float32, lda int, x []float32, incX int) + Stbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []float32, lda int, x []float32, incX int) + Stpsv(ul Uplo, tA Transpose, d Diag, n int, ap []float32, x []float32, incX int) + Ssymv(ul Uplo, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) + Ssbmv(ul Uplo, n, k int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) + Sspmv(ul Uplo, n int, alpha float32, ap []float32, x []float32, incX int, beta float32, y []float32, incY int) + Sger(m, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) + Ssyr(ul Uplo, n int, alpha float32, x []float32, incX int, a []float32, lda int) + Sspr(ul Uplo, n int, alpha float32, x []float32, incX int, ap []float32) + Ssyr2(ul Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) + Sspr2(ul Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32) +} + +// Float32Level3 implements the single precision real BLAS Level 3 routines. +type Float32Level3 interface { + Sgemm(tA, tB Transpose, m, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) + Ssymm(s Side, ul Uplo, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) + Ssyrk(ul Uplo, t Transpose, n, k int, alpha float32, a []float32, lda int, beta float32, c []float32, ldc int) + Ssyr2k(ul Uplo, t Transpose, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) + Strmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) + Strsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) +} + +// Float64 implements the single precision real BLAS routines. +type Float64 interface { + Float64Level1 + Float64Level2 + Float64Level3 +} + +// Float64Level1 implements the double precision real BLAS Level 1 routines. +type Float64Level1 interface { + Ddot(n int, x []float64, incX int, y []float64, incY int) float64 + Dnrm2(n int, x []float64, incX int) float64 + Dasum(n int, x []float64, incX int) float64 + Idamax(n int, x []float64, incX int) int + Dswap(n int, x []float64, incX int, y []float64, incY int) + Dcopy(n int, x []float64, incX int, y []float64, incY int) + Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) + Drotg(a, b float64) (c, s, r, z float64) + Drotmg(d1, d2, b1, b2 float64) (p DrotmParams, rd1, rd2, rb1 float64) + Drot(n int, x []float64, incX int, y []float64, incY int, c float64, s float64) + Drotm(n int, x []float64, incX int, y []float64, incY int, p DrotmParams) + Dscal(n int, alpha float64, x []float64, incX int) +} + +// Float64Level2 implements the double precision real BLAS Level 2 routines. +type Float64Level2 interface { + Dgemv(tA Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) + Dgbmv(tA Transpose, m, n, kL, kU int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) + Dtrmv(ul Uplo, tA Transpose, d Diag, n int, a []float64, lda int, x []float64, incX int) + Dtbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []float64, lda int, x []float64, incX int) + Dtpmv(ul Uplo, tA Transpose, d Diag, n int, ap []float64, x []float64, incX int) + Dtrsv(ul Uplo, tA Transpose, d Diag, n int, a []float64, lda int, x []float64, incX int) + Dtbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []float64, lda int, x []float64, incX int) + Dtpsv(ul Uplo, tA Transpose, d Diag, n int, ap []float64, x []float64, incX int) + Dsymv(ul Uplo, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) + Dsbmv(ul Uplo, n, k int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) + Dspmv(ul Uplo, n int, alpha float64, ap []float64, x []float64, incX int, beta float64, y []float64, incY int) + Dger(m, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) + Dsyr(ul Uplo, n int, alpha float64, x []float64, incX int, a []float64, lda int) + Dspr(ul Uplo, n int, alpha float64, x []float64, incX int, ap []float64) + Dsyr2(ul Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) + Dspr2(ul Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64) +} + +// Float64Level3 implements the double precision real BLAS Level 3 routines. +type Float64Level3 interface { + Dgemm(tA, tB Transpose, m, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) + Dsymm(s Side, ul Uplo, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) + Dsyrk(ul Uplo, t Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64, ldc int) + Dsyr2k(ul Uplo, t Transpose, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) + Dtrmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) + Dtrsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) +} + +// Complex64 implements the single precision complex BLAS routines. +type Complex64 interface { + Complex64Level1 + Complex64Level2 + Complex64Level3 +} + +// Complex64Level1 implements the single precision complex BLAS Level 1 routines. +type Complex64Level1 interface { + Cdotu(n int, x []complex64, incX int, y []complex64, incY int) (dotu complex64) + Cdotc(n int, x []complex64, incX int, y []complex64, incY int) (dotc complex64) + Scnrm2(n int, x []complex64, incX int) float32 + Scasum(n int, x []complex64, incX int) float32 + Icamax(n int, x []complex64, incX int) int + Cswap(n int, x []complex64, incX int, y []complex64, incY int) + Ccopy(n int, x []complex64, incX int, y []complex64, incY int) + Caxpy(n int, alpha complex64, x []complex64, incX int, y []complex64, incY int) + Cscal(n int, alpha complex64, x []complex64, incX int) + Csscal(n int, alpha float32, x []complex64, incX int) +} + +// Complex64Level2 implements the single precision complex BLAS routines Level 2 routines. +type Complex64Level2 interface { + Cgemv(tA Transpose, m, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) + Cgbmv(tA Transpose, m, n, kL, kU int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) + Ctrmv(ul Uplo, tA Transpose, d Diag, n int, a []complex64, lda int, x []complex64, incX int) + Ctbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex64, lda int, x []complex64, incX int) + Ctpmv(ul Uplo, tA Transpose, d Diag, n int, ap []complex64, x []complex64, incX int) + Ctrsv(ul Uplo, tA Transpose, d Diag, n int, a []complex64, lda int, x []complex64, incX int) + Ctbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex64, lda int, x []complex64, incX int) + Ctpsv(ul Uplo, tA Transpose, d Diag, n int, ap []complex64, x []complex64, incX int) + Chemv(ul Uplo, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) + Chbmv(ul Uplo, n, k int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) + Chpmv(ul Uplo, n int, alpha complex64, ap []complex64, x []complex64, incX int, beta complex64, y []complex64, incY int) + Cgeru(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) + Cgerc(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) + Cher(ul Uplo, n int, alpha float32, x []complex64, incX int, a []complex64, lda int) + Chpr(ul Uplo, n int, alpha float32, x []complex64, incX int, a []complex64) + Cher2(ul Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) + Chpr2(ul Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, ap []complex64) +} + +// Complex64Level3 implements the single precision complex BLAS Level 3 routines. +type Complex64Level3 interface { + Cgemm(tA, tB Transpose, m, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) + Csymm(s Side, ul Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) + Csyrk(ul Uplo, t Transpose, n, k int, alpha complex64, a []complex64, lda int, beta complex64, c []complex64, ldc int) + Csyr2k(ul Uplo, t Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) + Ctrmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) + Ctrsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) + Chemm(s Side, ul Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) + Cherk(ul Uplo, t Transpose, n, k int, alpha float32, a []complex64, lda int, beta float32, c []complex64, ldc int) + Cher2k(ul Uplo, t Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta float32, c []complex64, ldc int) +} + +// Complex128 implements the double precision complex BLAS routines. +type Complex128 interface { + Complex128Level1 + Complex128Level2 + Complex128Level3 +} + +// Complex128Level1 implements the double precision complex BLAS Level 1 routines. +type Complex128Level1 interface { + Zdotu(n int, x []complex128, incX int, y []complex128, incY int) (dotu complex128) + Zdotc(n int, x []complex128, incX int, y []complex128, incY int) (dotc complex128) + Dznrm2(n int, x []complex128, incX int) float64 + Dzasum(n int, x []complex128, incX int) float64 + Izamax(n int, x []complex128, incX int) int + Zswap(n int, x []complex128, incX int, y []complex128, incY int) + Zcopy(n int, x []complex128, incX int, y []complex128, incY int) + Zaxpy(n int, alpha complex128, x []complex128, incX int, y []complex128, incY int) + Zscal(n int, alpha complex128, x []complex128, incX int) + Zdscal(n int, alpha float64, x []complex128, incX int) +} + +// Complex128Level2 implements the double precision complex BLAS Level 2 routines. +type Complex128Level2 interface { + Zgemv(tA Transpose, m, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) + Zgbmv(tA Transpose, m, n int, kL int, kU int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) + Ztrmv(ul Uplo, tA Transpose, d Diag, n int, a []complex128, lda int, x []complex128, incX int) + Ztbmv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex128, lda int, x []complex128, incX int) + Ztpmv(ul Uplo, tA Transpose, d Diag, n int, ap []complex128, x []complex128, incX int) + Ztrsv(ul Uplo, tA Transpose, d Diag, n int, a []complex128, lda int, x []complex128, incX int) + Ztbsv(ul Uplo, tA Transpose, d Diag, n, k int, a []complex128, lda int, x []complex128, incX int) + Ztpsv(ul Uplo, tA Transpose, d Diag, n int, ap []complex128, x []complex128, incX int) + Zhemv(ul Uplo, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) + Zhbmv(ul Uplo, n, k int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) + Zhpmv(ul Uplo, n int, alpha complex128, ap []complex128, x []complex128, incX int, beta complex128, y []complex128, incY int) + Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) + Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) + Zher(ul Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) + Zhpr(ul Uplo, n int, alpha float64, x []complex128, incX int, a []complex128) + Zher2(ul Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) + Zhpr2(ul Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, ap []complex128) +} + +// Complex128Level3 implements the double precision complex BLAS Level 3 routines. +type Complex128Level3 interface { + Zgemm(tA, tB Transpose, m, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) + Zsymm(s Side, ul Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) + Zsyrk(ul Uplo, t Transpose, n, k int, alpha complex128, a []complex128, lda int, beta complex128, c []complex128, ldc int) + Zsyr2k(ul Uplo, t Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) + Ztrmm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) + Ztrsm(s Side, ul Uplo, tA Transpose, d Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) + Zhemm(s Side, ul Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) + Zherk(ul Uplo, t Transpose, n, k int, alpha float64, a []complex128, lda int, beta float64, c []complex128, ldc int) + Zher2k(ul Uplo, t Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta float64, c []complex128, ldc int) +} diff --git a/blas/blas32/blas32.go b/blas/blas32/blas32.go new file mode 100644 index 00000000..980dd888 --- /dev/null +++ b/blas/blas32/blas32.go @@ -0,0 +1,458 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package blas32 provides a simple interface to the float32 BLAS API. +package blas32 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/native" +) + +var blas32 blas.Float32 = native.Implementation{} + +// Use sets the BLAS float32 implementation to be used by subsequent BLAS calls. +// The default implementation is native.Implementation. +func Use(b blas.Float32) { + blas32 = b +} + +// Implementation returns the current BLAS float32 implementation. +// +// Implementation allows direct calls to the current the BLAS float32 implementation +// giving finer control of parameters. +func Implementation() blas.Float32 { + return blas32 +} + +// Vector represents a vector with an associated element increment. +type Vector struct { + Inc int + Data []float32 +} + +// General represents a matrix using the conventional storage scheme. +type General struct { + Rows, Cols int + Stride int + Data []float32 +} + +// Band represents a band matrix using the band storage scheme. +type Band struct { + Rows, Cols int + KL, KU int + Stride int + Data []float32 +} + +// Triangular represents a triangular matrix using the conventional storage scheme. +type Triangular struct { + N int + Stride int + Data []float32 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularBand represents a triangular matrix using the band storage scheme. +type TriangularBand struct { + N, K int + Stride int + Data []float32 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularPacked represents a triangular matrix using the packed storage scheme. +type TriangularPacked struct { + N int + Data []float32 + Uplo blas.Uplo + Diag blas.Diag +} + +// Symmetric represents a symmetric matrix using the conventional storage scheme. +type Symmetric struct { + N int + Stride int + Data []float32 + Uplo blas.Uplo +} + +// SymmetricBand represents a symmetric matrix using the band storage scheme. +type SymmetricBand struct { + N, K int + Stride int + Data []float32 + Uplo blas.Uplo +} + +// SymmetricPacked represents a symmetric matrix using the packed storage scheme. +type SymmetricPacked struct { + N int + Data []float32 + Uplo blas.Uplo +} + +// Level 1 + +const negInc = "blas32: negative vector increment" + +// Dot computes the dot product of the two vectors: +// \sum_i x[i]*y[i]. +func Dot(n int, x, y Vector) float32 { + return blas32.Sdot(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// DDot computes the dot product of the two vectors: +// \sum_i x[i]*y[i]. +func DDot(n int, x, y Vector) float64 { + return blas32.Dsdot(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// SDDot computes the dot product of the two vectors adding a constant: +// alpha + \sum_i x[i]*y[i]. +func SDDot(n int, alpha float32, x, y Vector) float32 { + return blas32.Sdsdot(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Nrm2 computes the Euclidean norm of the vector x: +// sqrt(\sum_i x[i]*x[i]). +// +// Nrm2 will panic if the vector increment is negative. +func Nrm2(n int, x Vector) float32 { + if x.Inc < 0 { + panic(negInc) + } + return blas32.Snrm2(n, x.Data, x.Inc) +} + +// Asum computes the sum of the absolute values of the elements of x: +// \sum_i |x[i]|. +// +// Asum will panic if the vector increment is negative. +func Asum(n int, x Vector) float32 { + if x.Inc < 0 { + panic(negInc) + } + return blas32.Sasum(n, x.Data, x.Inc) +} + +// Iamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Iamax returns -1 if n == 0. +// +// Iamax will panic if the vector increment is negative. +func Iamax(n int, x Vector) int { + if x.Inc < 0 { + panic(negInc) + } + return blas32.Isamax(n, x.Data, x.Inc) +} + +// Swap exchanges the elements of the two vectors: +// x[i], y[i] = y[i], x[i] for all i. +func Swap(n int, x, y Vector) { + blas32.Sswap(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Copy copies the elements of x into the elements of y: +// y[i] = x[i] for all i. +func Copy(n int, x, y Vector) { + blas32.Scopy(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Axpy adds x scaled by alpha to y: +// y[i] += alpha*x[i] for all i. +func Axpy(n int, alpha float32, x, y Vector) { + blas32.Saxpy(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Rotg computes the parameters of a Givens plane rotation so that +// ⎡ c s⎤ ⎡a⎤ ⎡r⎤ +// ⎣-s c⎦ * ⎣b⎦ = ⎣0⎦ +// where a and b are the Cartesian coordinates of a given point. +// c, s, and r are defined as +// r = ±Sqrt(a^2 + b^2), +// c = a/r, the cosine of the rotation angle, +// s = a/r, the sine of the rotation angle, +// and z is defined such that +// if |a| > |b|, z = s, +// otherwise if c != 0, z = 1/c, +// otherwise z = 1. +func Rotg(a, b float32) (c, s, r, z float32) { + return blas32.Srotg(a, b) +} + +// Rotmg computes the modified Givens rotation. See +// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html +// for more details. +func Rotmg(d1, d2, b1, b2 float32) (p blas.SrotmParams, rd1, rd2, rb1 float32) { + return blas32.Srotmg(d1, d2, b1, b2) +} + +// Rot applies a plane transformation to n points represented by the vectors x +// and y: +// x[i] = c*x[i] + s*y[i], +// y[i] = -s*x[i] + c*y[i], for all i. +func Rot(n int, x, y Vector, c, s float32) { + blas32.Srot(n, x.Data, x.Inc, y.Data, y.Inc, c, s) +} + +// Rotm applies the modified Givens rotation to n points represented by the +// vectors x and y. +func Rotm(n int, x, y Vector, p blas.SrotmParams) { + blas32.Srotm(n, x.Data, x.Inc, y.Data, y.Inc, p) +} + +// Scal scales the vector x by alpha: +// x[i] *= alpha for all i. +// +// Scal will panic if the vector increment is negative. +func Scal(n int, alpha float32, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + blas32.Sscal(n, alpha, x.Data, x.Inc) +} + +// Level 2 + +// Gemv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans or blas.ConjTrans, +// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. +func Gemv(t blas.Transpose, alpha float32, a General, x Vector, beta float32, y Vector) { + blas32.Sgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Gbmv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans or blas.ConjTrans, +// where A is an m×n band matrix, x and y are vectors, and alpha and beta are scalars. +func Gbmv(t blas.Transpose, alpha float32, a Band, x Vector, beta float32, y Vector) { + blas32.Sgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Trmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix, and x is a vector. +func Trmv(t blas.Transpose, a Triangular, x Vector) { + blas32.Strmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { + blas32.Stbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x is a vector. +func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { + blas32.Stpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Trsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix, and x and b are vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Trsv(t blas.Transpose, a Triangular, x Vector) { + blas32.Strsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular band matrix, and x and b are vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { + blas32.Stbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x and b are +// vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { + blas32.Stpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Symv computes +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +func Symv(alpha float32, a Symmetric, x Vector, beta float32, y Vector) { + blas32.Ssymv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Sbmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric band matrix, x and y are vectors, and alpha +// and beta are scalars. +func Sbmv(alpha float32, a SymmetricBand, x Vector, beta float32, y Vector) { + blas32.Ssbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Spmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha and beta are scalars. +func Spmv(alpha float32, a SymmetricPacked, x Vector, beta float32, y Vector) { + blas32.Sspmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Ger performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Ger(alpha float32, x, y Vector, a General) { + blas32.Sger(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Syr performs a rank-1 update +// A += alpha * x * x^T, +// where A is an n×n symmetric matrix, x is a vector, and alpha is a scalar. +func Syr(alpha float32, x Vector, a Symmetric) { + blas32.Ssyr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) +} + +// Spr performs the rank-1 update +// A += alpha * x * x^T, +// where A is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +func Spr(alpha float32, x Vector, a SymmetricPacked) { + blas32.Sspr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) +} + +// Syr2 performs a rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +func Syr2(alpha float32, x, y Vector, a Symmetric) { + blas32.Ssyr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Spr2 performs a rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func Spr2(alpha float32, x, y Vector, a SymmetricPacked) { + blas32.Sspr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) +} + +// Level 3 + +// Gemm computes +// C = alpha * A * B + beta * C, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +func Gemm(tA, tB blas.Transpose, alpha float32, a, b General, beta float32, c General) { + var m, n, k int + if tA == blas.NoTrans { + m, k = a.Rows, a.Cols + } else { + m, k = a.Cols, a.Rows + } + if tB == blas.NoTrans { + n = b.Cols + } else { + n = b.Rows + } + blas32.Sgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Symm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and +// alpha is a scalar. +func Symm(s blas.Side, alpha float32, a Symmetric, b General, beta float32, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + blas32.Ssymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Syrk performs a symmetric rank-k update +// C = alpha * A * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * A + beta * C, if t == blas.Trans or blas.ConjTrans, +// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans and +// a k×n matrix otherwise, and alpha and beta are scalars. +func Syrk(t blas.Transpose, alpha float32, a General, beta float32, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + blas32.Ssyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Syr2k performs a symmetric rank-2k update +// C = alpha * A * B^T + alpha * B * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * B + alpha * B^T * A + beta * C, if t == blas.Trans or blas.ConjTrans, +// where C is an n×n symmetric matrix, A and B are n×k matrices if t == NoTrans +// and k×n matrices otherwise, and alpha and beta are scalars. +func Syr2k(t blas.Transpose, alpha float32, a, b General, beta float32, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + blas32.Ssyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Trmm performs +// B = alpha * A * B, if tA == blas.NoTrans and s == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and s == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, +// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is +// a scalar. +func Trmm(s blas.Side, tA blas.Transpose, alpha float32, a Triangular, b General) { + blas32.Strmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Trsm solves +// A * X = alpha * B, if tA == blas.NoTrans and s == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans and s == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, +// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and +// alpha is a scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in-place into X. +// +// No check is made that A is invertible. +func Trsm(s blas.Side, tA blas.Transpose, alpha float32, a Triangular, b General) { + blas32.Strsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} diff --git a/blas/blas64/blas64.go b/blas/blas64/blas64.go new file mode 100644 index 00000000..da49fecc --- /dev/null +++ b/blas/blas64/blas64.go @@ -0,0 +1,446 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package blas64 provides a simple interface to the float64 BLAS API. +package blas64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/native" +) + +var blas64 blas.Float64 = native.Implementation{} + +// Use sets the BLAS float64 implementation to be used by subsequent BLAS calls. +// The default implementation is native.Implementation. +func Use(b blas.Float64) { + blas64 = b +} + +// Implementation returns the current BLAS float64 implementation. +// +// Implementation allows direct calls to the current the BLAS float64 implementation +// giving finer control of parameters. +func Implementation() blas.Float64 { + return blas64 +} + +// Vector represents a vector with an associated element increment. +type Vector struct { + Inc int + Data []float64 +} + +// General represents a matrix using the conventional storage scheme. +type General struct { + Rows, Cols int + Stride int + Data []float64 +} + +// Band represents a band matrix using the band storage scheme. +type Band struct { + Rows, Cols int + KL, KU int + Stride int + Data []float64 +} + +// Triangular represents a triangular matrix using the conventional storage scheme. +type Triangular struct { + N int + Stride int + Data []float64 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularBand represents a triangular matrix using the band storage scheme. +type TriangularBand struct { + N, K int + Stride int + Data []float64 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularPacked represents a triangular matrix using the packed storage scheme. +type TriangularPacked struct { + N int + Data []float64 + Uplo blas.Uplo + Diag blas.Diag +} + +// Symmetric represents a symmetric matrix using the conventional storage scheme. +type Symmetric struct { + N int + Stride int + Data []float64 + Uplo blas.Uplo +} + +// SymmetricBand represents a symmetric matrix using the band storage scheme. +type SymmetricBand struct { + N, K int + Stride int + Data []float64 + Uplo blas.Uplo +} + +// SymmetricPacked represents a symmetric matrix using the packed storage scheme. +type SymmetricPacked struct { + N int + Data []float64 + Uplo blas.Uplo +} + +// Level 1 + +const negInc = "blas64: negative vector increment" + +// Dot computes the dot product of the two vectors: +// \sum_i x[i]*y[i]. +func Dot(n int, x, y Vector) float64 { + return blas64.Ddot(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Nrm2 computes the Euclidean norm of the vector x: +// sqrt(\sum_i x[i]*x[i]). +// +// Nrm2 will panic if the vector increment is negative. +func Nrm2(n int, x Vector) float64 { + if x.Inc < 0 { + panic(negInc) + } + return blas64.Dnrm2(n, x.Data, x.Inc) +} + +// Asum computes the sum of the absolute values of the elements of x: +// \sum_i |x[i]|. +// +// Asum will panic if the vector increment is negative. +func Asum(n int, x Vector) float64 { + if x.Inc < 0 { + panic(negInc) + } + return blas64.Dasum(n, x.Data, x.Inc) +} + +// Iamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Iamax returns -1 if n == 0. +// +// Iamax will panic if the vector increment is negative. +func Iamax(n int, x Vector) int { + if x.Inc < 0 { + panic(negInc) + } + return blas64.Idamax(n, x.Data, x.Inc) +} + +// Swap exchanges the elements of the two vectors: +// x[i], y[i] = y[i], x[i] for all i. +func Swap(n int, x, y Vector) { + blas64.Dswap(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Copy copies the elements of x into the elements of y: +// y[i] = x[i] for all i. +func Copy(n int, x, y Vector) { + blas64.Dcopy(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Axpy adds x scaled by alpha to y: +// y[i] += alpha*x[i] for all i. +func Axpy(n int, alpha float64, x, y Vector) { + blas64.Daxpy(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Rotg computes the parameters of a Givens plane rotation so that +// ⎡ c s⎤ ⎡a⎤ ⎡r⎤ +// ⎣-s c⎦ * ⎣b⎦ = ⎣0⎦ +// where a and b are the Cartesian coordinates of a given point. +// c, s, and r are defined as +// r = ±Sqrt(a^2 + b^2), +// c = a/r, the cosine of the rotation angle, +// s = a/r, the sine of the rotation angle, +// and z is defined such that +// if |a| > |b|, z = s, +// otherwise if c != 0, z = 1/c, +// otherwise z = 1. +func Rotg(a, b float64) (c, s, r, z float64) { + return blas64.Drotg(a, b) +} + +// Rotmg computes the modified Givens rotation. See +// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html +// for more details. +func Rotmg(d1, d2, b1, b2 float64) (p blas.DrotmParams, rd1, rd2, rb1 float64) { + return blas64.Drotmg(d1, d2, b1, b2) +} + +// Rot applies a plane transformation to n points represented by the vectors x +// and y: +// x[i] = c*x[i] + s*y[i], +// y[i] = -s*x[i] + c*y[i], for all i. +func Rot(n int, x, y Vector, c, s float64) { + blas64.Drot(n, x.Data, x.Inc, y.Data, y.Inc, c, s) +} + +// Rotm applies the modified Givens rotation to n points represented by the +// vectors x and y. +func Rotm(n int, x, y Vector, p blas.DrotmParams) { + blas64.Drotm(n, x.Data, x.Inc, y.Data, y.Inc, p) +} + +// Scal scales the vector x by alpha: +// x[i] *= alpha for all i. +// +// Scal will panic if the vector increment is negative. +func Scal(n int, alpha float64, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + blas64.Dscal(n, alpha, x.Data, x.Inc) +} + +// Level 2 + +// Gemv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans or blas.ConjTrans, +// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are scalars. +func Gemv(t blas.Transpose, alpha float64, a General, x Vector, beta float64, y Vector) { + blas64.Dgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Gbmv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans or blas.ConjTrans, +// where A is an m×n band matrix, x and y are vectors, and alpha and beta are scalars. +func Gbmv(t blas.Transpose, alpha float64, a Band, x Vector, beta float64, y Vector) { + blas64.Dgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Trmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix, and x is a vector. +func Trmv(t blas.Transpose, a Triangular, x Vector) { + blas64.Dtrmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { + blas64.Dtbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x is a vector. +func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { + blas64.Dtpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Trsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix, and x and b are vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Trsv(t blas.Transpose, a Triangular, x Vector) { + blas64.Dtrsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular band matrix, and x and b are vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { + blas64.Dtbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans or blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x and b are +// vectors. +// +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { + blas64.Dtpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Symv computes +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +func Symv(alpha float64, a Symmetric, x Vector, beta float64, y Vector) { + blas64.Dsymv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Sbmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric band matrix, x and y are vectors, and alpha +// and beta are scalars. +func Sbmv(alpha float64, a SymmetricBand, x Vector, beta float64, y Vector) { + blas64.Dsbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Spmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha and beta are scalars. +func Spmv(alpha float64, a SymmetricPacked, x Vector, beta float64, y Vector) { + blas64.Dspmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Ger performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Ger(alpha float64, x, y Vector, a General) { + blas64.Dger(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Syr performs a rank-1 update +// A += alpha * x * x^T, +// where A is an n×n symmetric matrix, x is a vector, and alpha is a scalar. +func Syr(alpha float64, x Vector, a Symmetric) { + blas64.Dsyr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) +} + +// Spr performs the rank-1 update +// A += alpha * x * x^T, +// where A is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +func Spr(alpha float64, x Vector, a SymmetricPacked) { + blas64.Dspr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) +} + +// Syr2 performs a rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +func Syr2(alpha float64, x, y Vector, a Symmetric) { + blas64.Dsyr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Spr2 performs a rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func Spr2(alpha float64, x, y Vector, a SymmetricPacked) { + blas64.Dspr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) +} + +// Level 3 + +// Gemm computes +// C = alpha * A * B + beta * C, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +func Gemm(tA, tB blas.Transpose, alpha float64, a, b General, beta float64, c General) { + var m, n, k int + if tA == blas.NoTrans { + m, k = a.Rows, a.Cols + } else { + m, k = a.Cols, a.Rows + } + if tB == blas.NoTrans { + n = b.Cols + } else { + n = b.Rows + } + blas64.Dgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Symm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and +// alpha is a scalar. +func Symm(s blas.Side, alpha float64, a Symmetric, b General, beta float64, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + blas64.Dsymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Syrk performs a symmetric rank-k update +// C = alpha * A * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * A + beta * C, if t == blas.Trans or blas.ConjTrans, +// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans and +// a k×n matrix otherwise, and alpha and beta are scalars. +func Syrk(t blas.Transpose, alpha float64, a General, beta float64, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + blas64.Dsyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Syr2k performs a symmetric rank-2k update +// C = alpha * A * B^T + alpha * B * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * B + alpha * B^T * A + beta * C, if t == blas.Trans or blas.ConjTrans, +// where C is an n×n symmetric matrix, A and B are n×k matrices if t == NoTrans +// and k×n matrices otherwise, and alpha and beta are scalars. +func Syr2k(t blas.Transpose, alpha float64, a, b General, beta float64, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + blas64.Dsyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Trmm performs +// B = alpha * A * B, if tA == blas.NoTrans and s == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and s == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, +// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is +// a scalar. +func Trmm(s blas.Side, tA blas.Transpose, alpha float64, a Triangular, b General) { + blas64.Dtrmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Trsm solves +// A * X = alpha * B, if tA == blas.NoTrans and s == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans and s == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and s == blas.Right, +// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and +// alpha is a scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in-place into X. +// +// No check is made that A is invertible. +func Trsm(s blas.Side, tA blas.Transpose, alpha float64, a Triangular, b General) { + blas64.Dtrsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} diff --git a/blas/cblas128/cblas128.go b/blas/cblas128/cblas128.go new file mode 100644 index 00000000..46343912 --- /dev/null +++ b/blas/cblas128/cblas128.go @@ -0,0 +1,510 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cblas128 provides a simple interface to the complex128 BLAS API. +package cblas128 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/cgo" +) + +// TODO(kortschak): Change this and the comment below to native.Implementation +// when blas/native covers the complex BLAS API. +var cblas128 blas.Complex128 = cgo.Implementation{} + +// Use sets the BLAS complex128 implementation to be used by subsequent BLAS calls. +// The default implementation is cgo.Implementation. +func Use(b blas.Complex128) { + cblas128 = b +} + +// Implementation returns the current BLAS complex128 implementation. +// +// Implementation allows direct calls to the current the BLAS complex128 implementation +// giving finer control of parameters. +func Implementation() blas.Complex128 { + return cblas128 +} + +// Vector represents a vector with an associated element increment. +type Vector struct { + Inc int + Data []complex128 +} + +// General represents a matrix using the conventional storage scheme. +type General struct { + Rows, Cols int + Stride int + Data []complex128 +} + +// Band represents a band matrix using the band storage scheme. +type Band struct { + Rows, Cols int + KL, KU int + Stride int + Data []complex128 +} + +// Triangular represents a triangular matrix using the conventional storage scheme. +type Triangular struct { + N int + Stride int + Data []complex128 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularBand represents a triangular matrix using the band storage scheme. +type TriangularBand struct { + N, K int + Stride int + Data []complex128 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularPacked represents a triangular matrix using the packed storage scheme. +type TriangularPacked struct { + N int + Data []complex128 + Uplo blas.Uplo + Diag blas.Diag +} + +// Symmetric represents a symmetric matrix using the conventional storage scheme. +type Symmetric struct { + N int + Stride int + Data []complex128 + Uplo blas.Uplo +} + +// SymmetricBand represents a symmetric matrix using the band storage scheme. +type SymmetricBand struct { + N, K int + Stride int + Data []complex128 + Uplo blas.Uplo +} + +// SymmetricPacked represents a symmetric matrix using the packed storage scheme. +type SymmetricPacked struct { + N int + Data []complex128 + Uplo blas.Uplo +} + +// Hermitian represents an Hermitian matrix using the conventional storage scheme. +type Hermitian Symmetric + +// HermitianBand represents an Hermitian matrix using the band storage scheme. +type HermitianBand SymmetricBand + +// HermitianPacked represents an Hermitian matrix using the packed storage scheme. +type HermitianPacked SymmetricPacked + +// Level 1 + +const negInc = "cblas128: negative vector increment" + +// Dotu computes the dot product of the two vectors without +// complex conjugation: +// x^T * y. +func Dotu(n int, x, y Vector) complex128 { + return cblas128.Zdotu(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Dotc computes the dot product of the two vectors with +// complex conjugation: +// x^H * y. +func Dotc(n int, x, y Vector) complex128 { + return cblas128.Zdotc(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Nrm2 computes the Euclidean norm of the vector x: +// sqrt(\sum_i x[i] * x[i]). +// +// Nrm2 will panic if the vector increment is negative. +func Nrm2(n int, x Vector) float64 { + if x.Inc < 0 { + panic(negInc) + } + return cblas128.Dznrm2(n, x.Data, x.Inc) +} + +// Asum computes the sum of magnitudes of the real and imaginary parts of +// elements of the vector x: +// \sum_i (|Re x[i]| + |Im x[i]|). +// +// Asum will panic if the vector increment is negative. +func Asum(n int, x Vector) float64 { + if x.Inc < 0 { + panic(negInc) + } + return cblas128.Dzasum(n, x.Data, x.Inc) +} + +// Iamax returns the index of an element of x with the largest sum of +// magnitudes of the real and imaginary parts (|Re x[i]|+|Im x[i]|). +// If there are multiple such indices, the earliest is returned. +// +// Iamax returns -1 if n == 0. +// +// Iamax will panic if the vector increment is negative. +func Iamax(n int, x Vector) int { + if x.Inc < 0 { + panic(negInc) + } + return cblas128.Izamax(n, x.Data, x.Inc) +} + +// Swap exchanges the elements of two vectors: +// x[i], y[i] = y[i], x[i] for all i. +func Swap(n int, x, y Vector) { + cblas128.Zswap(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Copy copies the elements of x into the elements of y: +// y[i] = x[i] for all i. +func Copy(n int, x, y Vector) { + cblas128.Zcopy(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Axpy computes +// y = alpha * x + y, +// where x and y are vectors, and alpha is a scalar. +func Axpy(n int, alpha complex128, x, y Vector) { + cblas128.Zaxpy(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Scal computes +// x = alpha * x, +// where x is a vector, and alpha is a scalar. +// +// Scal will panic if the vector increment is negative. +func Scal(n int, alpha complex128, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + cblas128.Zscal(n, alpha, x.Data, x.Inc) +} + +// Dscal computes +// x = alpha * x, +// where x is a vector, and alpha is a real scalar. +// +// Dscal will panic if the vector increment is negative. +func Dscal(n int, alpha float64, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + cblas128.Zdscal(n, alpha, x.Data, x.Inc) +} + +// Level 2 + +// Gemv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans, +// y = alpha * A^H * x + beta * y, if t == blas.ConjTrans, +// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are +// scalars. +func Gemv(t blas.Transpose, alpha complex128, a General, x Vector, beta complex128, y Vector) { + cblas128.Zgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Gbmv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans, +// y = alpha * A^H * x + beta * y, if t == blas.ConjTrans, +// where A is an m×n band matrix, x and y are vectors, and alpha and beta are +// scalars. +func Gbmv(t blas.Transpose, alpha complex128, a Band, x Vector, beta complex128, y Vector) { + cblas128.Zgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Trmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular matrix, and x is a vector. +func Trmv(t blas.Transpose, a Triangular, x Vector) { + cblas128.Ztrmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { + cblas128.Ztbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x is a vector. +func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { + cblas128.Ztpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Trsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular matrix and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Trsv(t blas.Transpose, a Triangular, x Vector) { + cblas128.Ztrsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { + cblas128.Ztbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular matrix in packed format and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { + cblas128.Ztpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Hemv computes +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian matrix, x and y are vectors, and alpha and +// beta are scalars. +func Hemv(alpha complex128, a Hermitian, x Vector, beta complex128, y Vector) { + cblas128.Zhemv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Hbmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian band matrix, x and y are vectors, and alpha +// and beta are scalars. +func Hbmv(alpha complex128, a HermitianBand, x Vector, beta complex128, y Vector) { + cblas128.Zhbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Hpmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian matrix in packed format, x and y are vectors, +// and alpha and beta are scalars. +func Hpmv(alpha complex128, a HermitianPacked, x Vector, beta complex128, y Vector) { + cblas128.Zhpmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Geru performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Geru(alpha complex128, x, y Vector, a General) { + cblas128.Zgeru(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Gerc performs a rank-1 update +// A += alpha * x * y^H, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Gerc(alpha complex128, x, y Vector, a General) { + cblas128.Zgerc(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Her performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n Hermitian matrix, x and y are vectors, and alpha is a scalar. +func Her(alpha float64, x Vector, a Hermitian) { + cblas128.Zher(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) +} + +// Hpr performs a rank-1 update +// A += alpha * x * x^H, +// where A is an n×n Hermitian matrix in packed format, x is a vector, and +// alpha is a scalar. +func Hpr(alpha float64, x Vector, a HermitianPacked) { + cblas128.Zhpr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) +} + +// Her2 performs a rank-2 update +// A += alpha * x * y^H + conj(alpha) * y * x^H, +// where A is an n×n Hermitian matrix, x and y are vectors, and alpha is a scalar. +func Her2(alpha complex128, x, y Vector, a Hermitian) { + cblas128.Zher2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Hpr2 performs a rank-2 update +// A += alpha * x * y^H + conj(alpha) * y * x^H, +// where A is an n×n Hermitian matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func Hpr2(alpha complex128, x, y Vector, a HermitianPacked) { + cblas128.Zhpr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) +} + +// Level 3 + +// Gemm computes +// C = alpha * A * B + beta * C, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed or conjugated. +func Gemm(tA, tB blas.Transpose, alpha complex128, a, b General, beta complex128, c General) { + var m, n, k int + if tA == blas.NoTrans { + m, k = a.Rows, a.Cols + } else { + m, k = a.Cols, a.Rows + } + if tB == blas.NoTrans { + n = b.Cols + } else { + n = b.Rows + } + cblas128.Zgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Symm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and +// alpha and beta are scalars. +func Symm(s blas.Side, alpha complex128, a Symmetric, b General, beta complex128, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + cblas128.Zsymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Syrk performs a symmetric rank-k update +// C = alpha * A * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * A + beta * C, if t == blas.Trans, +// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans +// and a k×n matrix otherwise, and alpha and beta are scalars. +func Syrk(t blas.Transpose, alpha complex128, a General, beta complex128, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas128.Zsyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Syr2k performs a symmetric rank-2k update +// C = alpha * A * B^T + alpha * B * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * B + alpha * B^T * A + beta * C, if t == blas.Trans, +// where C is an n×n symmetric matrix, A and B are n×k matrices if +// t == blas.NoTrans and k×n otherwise, and alpha and beta are scalars. +func Syr2k(t blas.Transpose, alpha complex128, a, b General, beta complex128, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas128.Zsyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Trmm performs +// B = alpha * A * B, if tA == blas.NoTrans and s == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans and s == blas.Left, +// B = alpha * A^H * B, if tA == blas.ConjTrans and s == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and s == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans and s == blas.Right, +// B = alpha * B * A^H, if tA == blas.ConjTrans and s == blas.Right, +// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is +// a scalar. +func Trmm(s blas.Side, tA blas.Transpose, alpha complex128, a Triangular, b General) { + cblas128.Ztrmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Trsm solves +// A * X = alpha * B, if tA == blas.NoTrans and s == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans and s == blas.Left, +// A^H * X = alpha * B, if tA == blas.ConjTrans and s == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans and s == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans and s == blas.Right, +// X * A^H = alpha * B, if tA == blas.ConjTrans and s == blas.Right, +// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and +// alpha is a scalar. +// +// At entry to the function, b contains the values of B, and the result is +// stored in-place into b. +// +// No check is made that A is invertible. +func Trsm(s blas.Side, tA blas.Transpose, alpha complex128, a Triangular, b General) { + cblas128.Ztrsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Hemm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m Hermitian matrix, B and C are m×n matrices, and +// alpha and beta are scalars. +func Hemm(s blas.Side, alpha complex128, a Hermitian, b General, beta complex128, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + cblas128.Zhemm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Herk performs the Hermitian rank-k update +// C = alpha * A * A^H + beta*C, if t == blas.NoTrans, +// C = alpha * A^H * A + beta*C, if t == blas.ConjTrans, +// where C is an n×n Hermitian matrix, A is an n×k matrix if t == blas.NoTrans +// and a k×n matrix otherwise, and alpha and beta are scalars. +func Herk(t blas.Transpose, alpha float64, a General, beta float64, c Hermitian) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas128.Zherk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Her2k performs the Hermitian rank-2k update +// C = alpha * A * B^H + conj(alpha) * B * A^H + beta * C, if t == blas.NoTrans, +// C = alpha * A^H * B + conj(alpha) * B^H * A + beta * C, if t == blas.ConjTrans, +// where C is an n×n Hermitian matrix, A and B are n×k matrices if t == NoTrans +// and k×n matrices otherwise, and alpha and beta are scalars. +func Her2k(t blas.Transpose, alpha complex128, a, b General, beta float64, c Hermitian) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas128.Zher2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} diff --git a/blas/cblas64/cblas64.go b/blas/cblas64/cblas64.go new file mode 100644 index 00000000..f494a050 --- /dev/null +++ b/blas/cblas64/cblas64.go @@ -0,0 +1,510 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cblas64 provides a simple interface to the complex64 BLAS API. +package cblas64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/cgo" +) + +// TODO(kortschak): Change this and the comment below to native.Implementation +// when blas/native covers the complex BLAS API. +var cblas64 blas.Complex64 = cgo.Implementation{} + +// Use sets the BLAS complex64 implementation to be used by subsequent BLAS calls. +// The default implementation is cgo.Implementation. +func Use(b blas.Complex64) { + cblas64 = b +} + +// Implementation returns the current BLAS complex64 implementation. +// +// Implementation allows direct calls to the current the BLAS complex64 implementation +// giving finer control of parameters. +func Implementation() blas.Complex64 { + return cblas64 +} + +// Vector represents a vector with an associated element increment. +type Vector struct { + Inc int + Data []complex64 +} + +// General represents a matrix using the conventional storage scheme. +type General struct { + Rows, Cols int + Stride int + Data []complex64 +} + +// Band represents a band matrix using the band storage scheme. +type Band struct { + Rows, Cols int + KL, KU int + Stride int + Data []complex64 +} + +// Triangular represents a triangular matrix using the conventional storage scheme. +type Triangular struct { + N int + Stride int + Data []complex64 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularBand represents a triangular matrix using the band storage scheme. +type TriangularBand struct { + N, K int + Stride int + Data []complex64 + Uplo blas.Uplo + Diag blas.Diag +} + +// TriangularPacked represents a triangular matrix using the packed storage scheme. +type TriangularPacked struct { + N int + Data []complex64 + Uplo blas.Uplo + Diag blas.Diag +} + +// Symmetric represents a symmetric matrix using the conventional storage scheme. +type Symmetric struct { + N int + Stride int + Data []complex64 + Uplo blas.Uplo +} + +// SymmetricBand represents a symmetric matrix using the band storage scheme. +type SymmetricBand struct { + N, K int + Stride int + Data []complex64 + Uplo blas.Uplo +} + +// SymmetricPacked represents a symmetric matrix using the packed storage scheme. +type SymmetricPacked struct { + N int + Data []complex64 + Uplo blas.Uplo +} + +// Hermitian represents an Hermitian matrix using the conventional storage scheme. +type Hermitian Symmetric + +// HermitianBand represents an Hermitian matrix using the band storage scheme. +type HermitianBand SymmetricBand + +// HermitianPacked represents an Hermitian matrix using the packed storage scheme. +type HermitianPacked SymmetricPacked + +// Level 1 + +const negInc = "cblas64: negative vector increment" + +// Dotu computes the dot product of the two vectors without +// complex conjugation: +// x^T * y +func Dotu(n int, x, y Vector) complex64 { + return cblas64.Cdotu(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Dotc computes the dot product of the two vectors with +// complex conjugation: +// x^H * y. +func Dotc(n int, x, y Vector) complex64 { + return cblas64.Cdotc(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Nrm2 computes the Euclidean norm of the vector x: +// sqrt(\sum_i x[i] * x[i]). +// +// Nrm2 will panic if the vector increment is negative. +func Nrm2(n int, x Vector) float32 { + if x.Inc < 0 { + panic(negInc) + } + return cblas64.Scnrm2(n, x.Data, x.Inc) +} + +// Asum computes the sum of magnitudes of the real and imaginary parts of +// elements of the vector x: +// \sum_i (|Re x[i]| + |Im x[i]|). +// +// Asum will panic if the vector increment is negative. +func Asum(n int, x Vector) float32 { + if x.Inc < 0 { + panic(negInc) + } + return cblas64.Scasum(n, x.Data, x.Inc) +} + +// Iamax returns the index of an element of x with the largest sum of +// magnitudes of the real and imaginary parts (|Re x[i]|+|Im x[i]|). +// If there are multiple such indices, the earliest is returned. +// +// Iamax returns -1 if n == 0. +// +// Iamax will panic if the vector increment is negative. +func Iamax(n int, x Vector) int { + if x.Inc < 0 { + panic(negInc) + } + return cblas64.Icamax(n, x.Data, x.Inc) +} + +// Swap exchanges the elements of two vectors: +// x[i], y[i] = y[i], x[i] for all i. +func Swap(n int, x, y Vector) { + cblas64.Cswap(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Copy copies the elements of x into the elements of y: +// y[i] = x[i] for all i. +func Copy(n int, x, y Vector) { + cblas64.Ccopy(n, x.Data, x.Inc, y.Data, y.Inc) +} + +// Axpy computes +// y = alpha * x + y, +// where x and y are vectors, and alpha is a scalar. +func Axpy(n int, alpha complex64, x, y Vector) { + cblas64.Caxpy(n, alpha, x.Data, x.Inc, y.Data, y.Inc) +} + +// Scal computes +// x = alpha * x, +// where x is a vector, and alpha is a scalar. +// +// Scal will panic if the vector increment is negative. +func Scal(n int, alpha complex64, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + cblas64.Cscal(n, alpha, x.Data, x.Inc) +} + +// Dscal computes +// x = alpha * x, +// where x is a vector, and alpha is a real scalar. +// +// Dscal will panic if the vector increment is negative. +func Dscal(n int, alpha float32, x Vector) { + if x.Inc < 0 { + panic(negInc) + } + cblas64.Csscal(n, alpha, x.Data, x.Inc) +} + +// Level 2 + +// Gemv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans, +// y = alpha * A^H * x + beta * y, if t == blas.ConjTrans, +// where A is an m×n dense matrix, x and y are vectors, and alpha and beta are +// scalars. +func Gemv(t blas.Transpose, alpha complex64, a General, x Vector, beta complex64, y Vector) { + cblas64.Cgemv(t, a.Rows, a.Cols, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Gbmv computes +// y = alpha * A * x + beta * y, if t == blas.NoTrans, +// y = alpha * A^T * x + beta * y, if t == blas.Trans, +// y = alpha * A^H * x + beta * y, if t == blas.ConjTrans, +// where A is an m×n band matrix, x and y are vectors, and alpha and beta are +// scalars. +func Gbmv(t blas.Transpose, alpha complex64, a Band, x Vector, beta complex64, y Vector) { + cblas64.Cgbmv(t, a.Rows, a.Cols, a.KL, a.KU, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Trmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular matrix, and x is a vector. +func Trmv(t blas.Transpose, a Triangular, x Vector) { + cblas64.Ctrmv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +func Tbmv(t blas.Transpose, a TriangularBand, x Vector) { + cblas64.Ctbmv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpmv computes +// x = A * x, if t == blas.NoTrans, +// x = A^T * x, if t == blas.Trans, +// x = A^H * x, if t == blas.ConjTrans, +// where A is an n×n triangular matrix in packed format, and x is a vector. +func Tpmv(t blas.Transpose, a TriangularPacked, x Vector) { + cblas64.Ctpmv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Trsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular matrix and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Trsv(t blas.Transpose, a Triangular, x Vector) { + cblas64.Ctrsv(a.Uplo, t, a.Diag, a.N, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tbsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular band matrix, and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tbsv(t blas.Transpose, a TriangularBand, x Vector) { + cblas64.Ctbsv(a.Uplo, t, a.Diag, a.N, a.K, a.Data, a.Stride, x.Data, x.Inc) +} + +// Tpsv solves +// A * x = b, if t == blas.NoTrans, +// A^T * x = b, if t == blas.Trans, +// A^H * x = b, if t == blas.ConjTrans, +// where A is an n×n triangular matrix in packed format and x is a vector. +// +// At entry to the function, x contains the values of b, and the result is +// stored in-place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func Tpsv(t blas.Transpose, a TriangularPacked, x Vector) { + cblas64.Ctpsv(a.Uplo, t, a.Diag, a.N, a.Data, x.Data, x.Inc) +} + +// Hemv computes +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian matrix, x and y are vectors, and alpha and +// beta are scalars. +func Hemv(alpha complex64, a Hermitian, x Vector, beta complex64, y Vector) { + cblas64.Chemv(a.Uplo, a.N, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Hbmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian band matrix, x and y are vectors, and alpha +// and beta are scalars. +func Hbmv(alpha complex64, a HermitianBand, x Vector, beta complex64, y Vector) { + cblas64.Chbmv(a.Uplo, a.N, a.K, alpha, a.Data, a.Stride, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Hpmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n Hermitian matrix in packed format, x and y are vectors, +// and alpha and beta are scalars. +func Hpmv(alpha complex64, a HermitianPacked, x Vector, beta complex64, y Vector) { + cblas64.Chpmv(a.Uplo, a.N, alpha, a.Data, x.Data, x.Inc, beta, y.Data, y.Inc) +} + +// Geru performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Geru(alpha complex64, x, y Vector, a General) { + cblas64.Cgeru(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Gerc performs a rank-1 update +// A += alpha * x * y^H, +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func Gerc(alpha complex64, x, y Vector, a General) { + cblas64.Cgerc(a.Rows, a.Cols, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Her performs a rank-1 update +// A += alpha * x * y^T, +// where A is an m×n Hermitian matrix, x and y are vectors, and alpha is a scalar. +func Her(alpha float32, x Vector, a Hermitian) { + cblas64.Cher(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data, a.Stride) +} + +// Hpr performs a rank-1 update +// A += alpha * x * x^H, +// where A is an n×n Hermitian matrix in packed format, x is a vector, and +// alpha is a scalar. +func Hpr(alpha float32, x Vector, a HermitianPacked) { + cblas64.Chpr(a.Uplo, a.N, alpha, x.Data, x.Inc, a.Data) +} + +// Her2 performs a rank-2 update +// A += alpha * x * y^H + conj(alpha) * y * x^H, +// where A is an n×n Hermitian matrix, x and y are vectors, and alpha is a scalar. +func Her2(alpha complex64, x, y Vector, a Hermitian) { + cblas64.Cher2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data, a.Stride) +} + +// Hpr2 performs a rank-2 update +// A += alpha * x * y^H + conj(alpha) * y * x^H, +// where A is an n×n Hermitian matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func Hpr2(alpha complex64, x, y Vector, a HermitianPacked) { + cblas64.Chpr2(a.Uplo, a.N, alpha, x.Data, x.Inc, y.Data, y.Inc, a.Data) +} + +// Level 3 + +// Gemm computes +// C = alpha * A * B + beta * C, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed or conjugated. +func Gemm(tA, tB blas.Transpose, alpha complex64, a, b General, beta complex64, c General) { + var m, n, k int + if tA == blas.NoTrans { + m, k = a.Rows, a.Cols + } else { + m, k = a.Cols, a.Rows + } + if tB == blas.NoTrans { + n = b.Cols + } else { + n = b.Rows + } + cblas64.Cgemm(tA, tB, m, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Symm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and +// alpha and beta are scalars. +func Symm(s blas.Side, alpha complex64, a Symmetric, b General, beta complex64, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + cblas64.Csymm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Syrk performs a symmetric rank-k update +// C = alpha * A * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * A + beta * C, if t == blas.Trans, +// where C is an n×n symmetric matrix, A is an n×k matrix if t == blas.NoTrans +// and a k×n matrix otherwise, and alpha and beta are scalars. +func Syrk(t blas.Transpose, alpha complex64, a General, beta complex64, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas64.Csyrk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Syr2k performs a symmetric rank-2k update +// C = alpha * A * B^T + alpha * B * A^T + beta * C, if t == blas.NoTrans, +// C = alpha * A^T * B + alpha * B^T * A + beta * C, if t == blas.Trans, +// where C is an n×n symmetric matrix, A and B are n×k matrices if +// t == blas.NoTrans and k×n otherwise, and alpha and beta are scalars. +func Syr2k(t blas.Transpose, alpha complex64, a, b General, beta complex64, c Symmetric) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas64.Csyr2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Trmm performs +// B = alpha * A * B, if tA == blas.NoTrans and s == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans and s == blas.Left, +// B = alpha * A^H * B, if tA == blas.ConjTrans and s == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and s == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans and s == blas.Right, +// B = alpha * B * A^H, if tA == blas.ConjTrans and s == blas.Right, +// where A is an n×n or m×m triangular matrix, B is an m×n matrix, and alpha is +// a scalar. +func Trmm(s blas.Side, tA blas.Transpose, alpha complex64, a Triangular, b General) { + cblas64.Ctrmm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Trsm solves +// A * X = alpha * B, if tA == blas.NoTrans and s == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans and s == blas.Left, +// A^H * X = alpha * B, if tA == blas.ConjTrans and s == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans and s == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans and s == blas.Right, +// X * A^H = alpha * B, if tA == blas.ConjTrans and s == blas.Right, +// where A is an n×n or m×m triangular matrix, X and B are m×n matrices, and +// alpha is a scalar. +// +// At entry to the function, b contains the values of B, and the result is +// stored in-place into b. +// +// No check is made that A is invertible. +func Trsm(s blas.Side, tA blas.Transpose, alpha complex64, a Triangular, b General) { + cblas64.Ctrsm(s, a.Uplo, tA, a.Diag, b.Rows, b.Cols, alpha, a.Data, a.Stride, b.Data, b.Stride) +} + +// Hemm performs +// C = alpha * A * B + beta * C, if s == blas.Left, +// C = alpha * B * A + beta * C, if s == blas.Right, +// where A is an n×n or m×m Hermitian matrix, B and C are m×n matrices, and +// alpha and beta are scalars. +func Hemm(s blas.Side, alpha complex64, a Hermitian, b General, beta complex64, c General) { + var m, n int + if s == blas.Left { + m, n = a.N, b.Cols + } else { + m, n = b.Rows, a.N + } + cblas64.Chemm(s, a.Uplo, m, n, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} + +// Herk performs the Hermitian rank-k update +// C = alpha * A * A^H + beta*C, if t == blas.NoTrans, +// C = alpha * A^H * A + beta*C, if t == blas.ConjTrans, +// where C is an n×n Hermitian matrix, A is an n×k matrix if t == blas.NoTrans +// and a k×n matrix otherwise, and alpha and beta are scalars. +func Herk(t blas.Transpose, alpha float32, a General, beta float32, c Hermitian) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas64.Cherk(c.Uplo, t, n, k, alpha, a.Data, a.Stride, beta, c.Data, c.Stride) +} + +// Her2k performs the Hermitian rank-2k update +// C = alpha * A * B^H + conj(alpha) * B * A^H + beta * C, if t == blas.NoTrans, +// C = alpha * A^H * B + conj(alpha) * B^H * A + beta * C, if t == blas.ConjTrans, +// where C is an n×n Hermitian matrix, A and B are n×k matrices if t == NoTrans +// and k×n matrices otherwise, and alpha and beta are scalars. +func Her2k(t blas.Transpose, alpha complex64, a, b General, beta float32, c Hermitian) { + var n, k int + if t == blas.NoTrans { + n, k = a.Rows, a.Cols + } else { + n, k = a.Cols, a.Rows + } + cblas64.Cher2k(c.Uplo, t, n, k, alpha, a.Data, a.Stride, b.Data, b.Stride, beta, c.Data, c.Stride) +} diff --git a/blas/cgo/bench_test.go b/blas/cgo/bench_test.go new file mode 100644 index 00000000..ee19a465 --- /dev/null +++ b/blas/cgo/bench_test.go @@ -0,0 +1,18 @@ +package cgo + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/testblas" +) + +const ( + Sm = testblas.SmallMat + Med = testblas.MediumMat + Lg = testblas.LargeMat + Hg = testblas.HugeMat +) + +const ( + T = blas.Trans + NT = blas.NoTrans +) diff --git a/blas/cgo/blas.go b/blas/cgo/blas.go new file mode 100644 index 00000000..c53c4acd --- /dev/null +++ b/blas/cgo/blas.go @@ -0,0 +1,4258 @@ +// Do not manually edit this file. It was created by the generate_blas.go from cblas.h. + +// Copyright ©2014 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgo + +/* +#cgo CFLAGS: -g -O2 +#include "cblas.h" +*/ +import "C" + +import ( + "unsafe" + + "gonum.org/v1/gonum/blas" +) + +// Type check assertions: +var ( + _ blas.Float32 = Implementation{} + _ blas.Float64 = Implementation{} + _ blas.Complex64 = Implementation{} + _ blas.Complex128 = Implementation{} +) + +// Type order is used to specify the matrix storage format. We still interact with +// an API that allows client calls to specify order, so this is here to document that fact. +type order int + +const ( + rowMajor order = 101 + iota +) + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +type Implementation struct{} + +// Special cases... + +type srotmParams struct { + flag float32 + h [4]float32 +} + +type drotmParams struct { + flag float64 + h [4]float64 +} + +func (Implementation) Srotg(a float32, b float32) (c float32, s float32, r float32, z float32) { + C.cblas_srotg((*C.float)(&a), (*C.float)(&b), (*C.float)(&c), (*C.float)(&s)) + return c, s, a, b +} +func (Implementation) Srotmg(d1 float32, d2 float32, b1 float32, b2 float32) (p blas.SrotmParams, rd1 float32, rd2 float32, rb1 float32) { + var pi srotmParams + C.cblas_srotmg((*C.float)(&d1), (*C.float)(&d2), (*C.float)(&b1), C.float(b2), (*C.float)(unsafe.Pointer(&pi))) + return blas.SrotmParams{Flag: blas.Flag(pi.flag), H: pi.h}, d1, d2, b1 +} +func (Implementation) Srotm(n int, x []float32, incX int, y []float32, incY int, p blas.SrotmParams) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if p.Flag < blas.Identity || p.Flag > blas.Diagonal { + panic("blas: illegal blas.Flag value") + } + if n == 0 { + return + } + pi := srotmParams{ + flag: float32(p.Flag), + h: p.H, + } + C.cblas_srotm(C.int(n), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY), (*C.float)(unsafe.Pointer(&pi))) +} +func (Implementation) Drotg(a float64, b float64) (c float64, s float64, r float64, z float64) { + C.cblas_drotg((*C.double)(&a), (*C.double)(&b), (*C.double)(&c), (*C.double)(&s)) + return c, s, a, b +} +func (Implementation) Drotmg(d1 float64, d2 float64, b1 float64, b2 float64) (p blas.DrotmParams, rd1 float64, rd2 float64, rb1 float64) { + var pi drotmParams + C.cblas_drotmg((*C.double)(&d1), (*C.double)(&d2), (*C.double)(&b1), C.double(b2), (*C.double)(unsafe.Pointer(&pi))) + return blas.DrotmParams{Flag: blas.Flag(pi.flag), H: pi.h}, d1, d2, b1 +} +func (Implementation) Drotm(n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if p.Flag < blas.Identity || p.Flag > blas.Diagonal { + panic("blas: illegal blas.Flag value") + } + if n == 0 { + return + } + pi := drotmParams{ + flag: float64(p.Flag), + h: p.H, + } + C.cblas_drotm(C.int(n), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY), (*C.double)(unsafe.Pointer(&pi))) +} +func (Implementation) Cdotu(n int, x []complex64, incX int, y []complex64, incY int) (dotu complex64) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + C.cblas_cdotu_sub(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&dotu)) + return dotu +} +func (Implementation) Cdotc(n int, x []complex64, incX int, y []complex64, incY int) (dotc complex64) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + C.cblas_cdotc_sub(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&dotc)) + return dotc +} +func (Implementation) Zdotu(n int, x []complex128, incX int, y []complex128, incY int) (dotu complex128) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + C.cblas_zdotu_sub(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&dotu)) + return dotu +} +func (Implementation) Zdotc(n int, x []complex128, incX int, y []complex128, incY int) (dotc complex128) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + C.cblas_zdotc_sub(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&dotc)) + return dotc +} + +// Generated cases ... + +// Sdsdot computes the dot product of the two vectors plus a constant +// alpha + \sum_i x[i]*y[i] +func (Implementation) Sdsdot(n int, alpha float32, x []float32, incX int, y []float32, incY int) float32 { + // declared at cblas.h:24:8 float cblas_sdsdot ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + return float32(C.cblas_sdsdot(C.int(n), C.float(alpha), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY))) +} + +// Dsdot computes the dot product of the two vectors +// \sum_i x[i]*y[i] +func (Implementation) Dsdot(n int, x []float32, incX int, y []float32, incY int) float64 { + // declared at cblas.h:26:8 double cblas_dsdot ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + return float64(C.cblas_dsdot(C.int(n), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY))) +} + +// Sdot computes the dot product of the two vectors +// \sum_i x[i]*y[i] +func (Implementation) Sdot(n int, x []float32, incX int, y []float32, incY int) float32 { + // declared at cblas.h:28:8 float cblas_sdot ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + return float32(C.cblas_sdot(C.int(n), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY))) +} + +// Ddot computes the dot product of the two vectors +// \sum_i x[i]*y[i] +func (Implementation) Ddot(n int, x []float64, incX int, y []float64, incY int) float64 { + // declared at cblas.h:30:8 double cblas_ddot ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + return float64(C.cblas_ddot(C.int(n), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY))) +} + +// Snrm2 computes the Euclidean norm of a vector, +// sqrt(\sum_i x[i] * x[i]). +// This function returns 0 if incX is negative. +func (Implementation) Snrm2(n int, x []float32, incX int) float32 { + // declared at cblas.h:49:8 float cblas_snrm2 ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return 0 + } + return float32(C.cblas_snrm2(C.int(n), (*C.float)(&x[0]), C.int(incX))) +} + +// Sasum computes the sum of the absolute values of the elements of x. +// \sum_i |x[i]| +// Sasum returns 0 if incX is negative. +func (Implementation) Sasum(n int, x []float32, incX int) float32 { + // declared at cblas.h:50:8 float cblas_sasum ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return 0 + } + return float32(C.cblas_sasum(C.int(n), (*C.float)(&x[0]), C.int(incX))) +} + +// Dnrm2 computes the Euclidean norm of a vector, +// sqrt(\sum_i x[i] * x[i]). +// This function returns 0 if incX is negative. +func (Implementation) Dnrm2(n int, x []float64, incX int) float64 { + // declared at cblas.h:52:8 double cblas_dnrm2 ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return 0 + } + return float64(C.cblas_dnrm2(C.int(n), (*C.double)(&x[0]), C.int(incX))) +} + +// Dasum computes the sum of the absolute values of the elements of x. +// \sum_i |x[i]| +// Dasum returns 0 if incX is negative. +func (Implementation) Dasum(n int, x []float64, incX int) float64 { + // declared at cblas.h:53:8 double cblas_dasum ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return 0 + } + return float64(C.cblas_dasum(C.int(n), (*C.double)(&x[0]), C.int(incX))) +} + +func (Implementation) Scnrm2(n int, x []complex64, incX int) float32 { + // declared at cblas.h:55:8 float cblas_scnrm2 ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return 0 + } + return float32(C.cblas_scnrm2(C.int(n), unsafe.Pointer(&x[0]), C.int(incX))) +} + +func (Implementation) Scasum(n int, x []complex64, incX int) float32 { + // declared at cblas.h:56:8 float cblas_scasum ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return 0 + } + return float32(C.cblas_scasum(C.int(n), unsafe.Pointer(&x[0]), C.int(incX))) +} + +func (Implementation) Dznrm2(n int, x []complex128, incX int) float64 { + // declared at cblas.h:58:8 double cblas_dznrm2 ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return 0 + } + return float64(C.cblas_dznrm2(C.int(n), unsafe.Pointer(&x[0]), C.int(incX))) +} + +func (Implementation) Dzasum(n int, x []complex128, incX int) float64 { + // declared at cblas.h:59:8 double cblas_dzasum ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return 0 + } + return float64(C.cblas_dzasum(C.int(n), unsafe.Pointer(&x[0]), C.int(incX))) +} + +// Isamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Isamax returns -1 if n == 0. +func (Implementation) Isamax(n int, x []float32, incX int) int { + // declared at cblas.h:65:13 int cblas_isamax ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if n == 0 || incX < 0 { + return -1 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return -1 + } + return int(C.cblas_isamax(C.int(n), (*C.float)(&x[0]), C.int(incX))) +} + +// Idamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Idamax returns -1 if n == 0. +func (Implementation) Idamax(n int, x []float64, incX int) int { + // declared at cblas.h:66:13 int cblas_idamax ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if n == 0 || incX < 0 { + return -1 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return -1 + } + return int(C.cblas_idamax(C.int(n), (*C.double)(&x[0]), C.int(incX))) +} + +func (Implementation) Icamax(n int, x []complex64, incX int) int { + // declared at cblas.h:67:13 int cblas_icamax ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if n == 0 || incX < 0 { + return -1 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return -1 + } + return int(C.cblas_icamax(C.int(n), unsafe.Pointer(&x[0]), C.int(incX))) +} + +func (Implementation) Izamax(n int, x []complex128, incX int) int { + // declared at cblas.h:68:13 int cblas_izamax ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if n == 0 || incX < 0 { + return -1 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return -1 + } + return int(C.cblas_izamax(C.int(n), unsafe.Pointer(&x[0]), C.int(incX))) +} + +// Sswap exchanges the elements of two vectors. +// x[i], y[i] = y[i], x[i] for all i +func (Implementation) Sswap(n int, x []float32, incX int, y []float32, incY int) { + // declared at cblas.h:79:6 void cblas_sswap ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_sswap(C.int(n), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY)) +} + +// Scopy copies the elements of x into the elements of y. +// y[i] = x[i] for all i +func (Implementation) Scopy(n int, x []float32, incX int, y []float32, incY int) { + // declared at cblas.h:81:6 void cblas_scopy ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_scopy(C.int(n), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY)) +} + +// Saxpy adds alpha times x to y +// y[i] += alpha * x[i] for all i +func (Implementation) Saxpy(n int, alpha float32, x []float32, incX int, y []float32, incY int) { + // declared at cblas.h:83:6 void cblas_saxpy ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_saxpy(C.int(n), C.float(alpha), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY)) +} + +// Dswap exchanges the elements of two vectors. +// x[i], y[i] = y[i], x[i] for all i +func (Implementation) Dswap(n int, x []float64, incX int, y []float64, incY int) { + // declared at cblas.h:90:6 void cblas_dswap ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_dswap(C.int(n), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY)) +} + +// Dcopy copies the elements of x into the elements of y. +// y[i] = x[i] for all i +func (Implementation) Dcopy(n int, x []float64, incX int, y []float64, incY int) { + // declared at cblas.h:92:6 void cblas_dcopy ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_dcopy(C.int(n), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY)) +} + +// Daxpy adds alpha times x to y +// y[i] += alpha * x[i] for all i +func (Implementation) Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) { + // declared at cblas.h:94:6 void cblas_daxpy ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_daxpy(C.int(n), C.double(alpha), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY)) +} + +func (Implementation) Cswap(n int, x []complex64, incX int, y []complex64, incY int) { + // declared at cblas.h:101:6 void cblas_cswap ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_cswap(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Ccopy(n int, x []complex64, incX int, y []complex64, incY int) { + // declared at cblas.h:103:6 void cblas_ccopy ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_ccopy(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Caxpy(n int, alpha complex64, x []complex64, incX int, y []complex64, incY int) { + // declared at cblas.h:105:6 void cblas_caxpy ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_caxpy(C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Zswap(n int, x []complex128, incX int, y []complex128, incY int) { + // declared at cblas.h:112:6 void cblas_zswap ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_zswap(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Zcopy(n int, x []complex128, incX int, y []complex128, incY int) { + // declared at cblas.h:114:6 void cblas_zcopy ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_zcopy(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Zaxpy(n int, alpha complex128, x []complex128, incX int, y []complex128, incY int) { + // declared at cblas.h:116:6 void cblas_zaxpy ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_zaxpy(C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY)) +} + +// Srot applies a plane transformation. +// x[i] = c * x[i] + s * y[i] +// y[i] = c * y[i] - s * x[i] +func (Implementation) Srot(n int, x []float32, incX int, y []float32, incY int, c, s float32) { + // declared at cblas.h:129:6 void cblas_srot ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_srot(C.int(n), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY), C.float(c), C.float(s)) +} + +// Drot applies a plane transformation. +// x[i] = c * x[i] + s * y[i] +// y[i] = c * y[i] - s * x[i] +func (Implementation) Drot(n int, x []float64, incX int, y []float64, incY int, c, s float64) { + // declared at cblas.h:136:6 void cblas_drot ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_drot(C.int(n), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY), C.double(c), C.double(s)) +} + +// Sscal scales x by alpha. +// x[i] *= alpha +// Sscal has no effect if incX < 0. +func (Implementation) Sscal(n int, alpha float32, x []float32, incX int) { + // declared at cblas.h:145:6 void cblas_sscal ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_sscal(C.int(n), C.float(alpha), (*C.float)(&x[0]), C.int(incX)) +} + +// Dscal scales x by alpha. +// x[i] *= alpha +// Dscal has no effect if incX < 0. +func (Implementation) Dscal(n int, alpha float64, x []float64, incX int) { + // declared at cblas.h:146:6 void cblas_dscal ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_dscal(C.int(n), C.double(alpha), (*C.double)(&x[0]), C.int(incX)) +} + +func (Implementation) Cscal(n int, alpha complex64, x []complex64, incX int) { + // declared at cblas.h:147:6 void cblas_cscal ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_cscal(C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Zscal(n int, alpha complex128, x []complex128, incX int) { + // declared at cblas.h:148:6 void cblas_zscal ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_zscal(C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Csscal(n int, alpha float32, x []complex64, incX int) { + // declared at cblas.h:149:6 void cblas_csscal ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incX < 0 { + return + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_csscal(C.int(n), C.float(alpha), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Zdscal(n int, alpha float64, x []complex128, incX int) { + // declared at cblas.h:150:6 void cblas_zdscal ... + + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_zdscal(C.int(n), C.double(alpha), unsafe.Pointer(&x[0]), C.int(incX)) +} + +// Sgemv computes +// y = alpha * a * x + beta * y if tA = blas.NoTrans +// y = alpha * A^T * x + beta * y if tA = blas.Trans or blas.ConjTrans +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Sgemv(tA blas.Transpose, m, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + // declared at cblas.h:171:6 void cblas_sgemv ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + var lenX, lenY int + if tA == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_sgemv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.int(m), C.int(n), C.float(alpha), (*C.float)(&a[0]), C.int(lda), (*C.float)(&x[0]), C.int(incX), C.float(beta), (*C.float)(&y[0]), C.int(incY)) +} + +// Sgbmv computes +// y = alpha * A * x + beta * y if tA == blas.NoTrans +// y = alpha * A^T * x + beta * y if tA == blas.Trans or blas.ConjTrans +// where a is an m×n band matrix kL subdiagonals and kU super-diagonals, and +// m and n refer to the size of the full dense matrix it represents. +// x and y are vectors, and alpha and beta are scalars. +func (Implementation) Sgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + // declared at cblas.h:176:6 void cblas_sgbmv ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if kL < 0 { + panic("blas: kL < 0") + } + if kU < 0 { + panic("blas: kU < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + var lenX, lenY int + if tA == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { + panic("blas: index of a out of range") + } + C.cblas_sgbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.int(m), C.int(n), C.int(kL), C.int(kU), C.float(alpha), (*C.float)(&a[0]), C.int(lda), (*C.float)(&x[0]), C.int(incX), C.float(beta), (*C.float)(&y[0]), C.int(incY)) +} + +// Strmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// A is an n×n Triangular matrix and x is a vector. +func (Implementation) Strmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float32, lda int, x []float32, incX int) { + // declared at cblas.h:181:6 void cblas_strmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_strmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), (*C.float)(&a[0]), C.int(lda), (*C.float)(&x[0]), C.int(incX)) +} + +// Stbmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular banded matrix with k diagonals, and x is a vector. +func (Implementation) Stbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float32, lda int, x []float32, incX int) { + // declared at cblas.h:185:6 void cblas_stbmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_stbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), C.int(k), (*C.float)(&a[0]), C.int(lda), (*C.float)(&x[0]), C.int(incX)) +} + +// Stpmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n unit triangular matrix in packed format, and x is a vector. +func (Implementation) Stpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap, x []float32, incX int) { + // declared at cblas.h:189:6 void cblas_stpmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_stpmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), (*C.float)(&ap[0]), (*C.float)(&x[0]), C.int(incX)) +} + +// Strsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// A is an n×n triangular matrix and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Strsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float32, lda int, x []float32, incX int) { + // declared at cblas.h:192:6 void cblas_strsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_strsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), (*C.float)(&a[0]), C.int(lda), (*C.float)(&x[0]), C.int(incX)) +} + +// Stbsv solves +// A * x = b +// where A is an n×n triangular banded matrix with k diagonals in packed format, +// and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Stbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float32, lda int, x []float32, incX int) { + // declared at cblas.h:196:6 void cblas_stbsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_stbsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), C.int(k), (*C.float)(&a[0]), C.int(lda), (*C.float)(&x[0]), C.int(incX)) +} + +// Stpsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular matrix in packed format and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Stpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap, x []float32, incX int) { + // declared at cblas.h:200:6 void cblas_stpsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_stpsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), (*C.float)(&ap[0]), (*C.float)(&x[0]), C.int(incX)) +} + +// Dgemv computes +// y = alpha * a * x + beta * y if tA = blas.NoTrans +// y = alpha * A^T * x + beta * y if tA = blas.Trans or blas.ConjTrans +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Dgemv(tA blas.Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + // declared at cblas.h:204:6 void cblas_dgemv ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + var lenX, lenY int + if tA == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_dgemv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.int(m), C.int(n), C.double(alpha), (*C.double)(&a[0]), C.int(lda), (*C.double)(&x[0]), C.int(incX), C.double(beta), (*C.double)(&y[0]), C.int(incY)) +} + +// Dgbmv computes +// y = alpha * A * x + beta * y if tA == blas.NoTrans +// y = alpha * A^T * x + beta * y if tA == blas.Trans or blas.ConjTrans +// where a is an m×n band matrix kL subdiagonals and kU super-diagonals, and +// m and n refer to the size of the full dense matrix it represents. +// x and y are vectors, and alpha and beta are scalars. +func (Implementation) Dgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + // declared at cblas.h:209:6 void cblas_dgbmv ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if kL < 0 { + panic("blas: kL < 0") + } + if kU < 0 { + panic("blas: kU < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + var lenX, lenY int + if tA == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { + panic("blas: index of a out of range") + } + C.cblas_dgbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.int(m), C.int(n), C.int(kL), C.int(kU), C.double(alpha), (*C.double)(&a[0]), C.int(lda), (*C.double)(&x[0]), C.int(incX), C.double(beta), (*C.double)(&y[0]), C.int(incY)) +} + +// Dtrmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// A is an n×n Triangular matrix and x is a vector. +func (Implementation) Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) { + // declared at cblas.h:214:6 void cblas_dtrmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_dtrmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), (*C.double)(&a[0]), C.int(lda), (*C.double)(&x[0]), C.int(incX)) +} + +// Dtbmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular banded matrix with k diagonals, and x is a vector. +func (Implementation) Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) { + // declared at cblas.h:218:6 void cblas_dtbmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_dtbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), C.int(k), (*C.double)(&a[0]), C.int(lda), (*C.double)(&x[0]), C.int(incX)) +} + +// Dtpmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n unit triangular matrix in packed format, and x is a vector. +func (Implementation) Dtpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap, x []float64, incX int) { + // declared at cblas.h:222:6 void cblas_dtpmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_dtpmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), (*C.double)(&ap[0]), (*C.double)(&x[0]), C.int(incX)) +} + +// Dtrsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// A is an n×n triangular matrix and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) { + // declared at cblas.h:225:6 void cblas_dtrsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_dtrsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), (*C.double)(&a[0]), C.int(lda), (*C.double)(&x[0]), C.int(incX)) +} + +// Dtbsv solves +// A * x = b +// where A is an n×n triangular banded matrix with k diagonals in packed format, +// and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Dtbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) { + // declared at cblas.h:229:6 void cblas_dtbsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_dtbsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), C.int(k), (*C.double)(&a[0]), C.int(lda), (*C.double)(&x[0]), C.int(incX)) +} + +// Dtpsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular matrix in packed format and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Dtpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap, x []float64, incX int) { + // declared at cblas.h:233:6 void cblas_dtpsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_dtpsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), (*C.double)(&ap[0]), (*C.double)(&x[0]), C.int(incX)) +} + +func (Implementation) Cgemv(tA blas.Transpose, m, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + // declared at cblas.h:237:6 void cblas_cgemv ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + var lenX, lenY int + if tA == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_cgemv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Cgbmv(tA blas.Transpose, m, n, kL, kU int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + // declared at cblas.h:242:6 void cblas_cgbmv ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if kL < 0 { + panic("blas: kL < 0") + } + if kU < 0 { + panic("blas: kU < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + var lenX, lenY int + if tA == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { + panic("blas: index of a out of range") + } + C.cblas_cgbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.int(m), C.int(n), C.int(kL), C.int(kU), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Ctrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { + // declared at cblas.h:247:6 void cblas_ctrmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_ctrmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ctbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { + // declared at cblas.h:251:6 void cblas_ctbmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_ctbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), C.int(k), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ctpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap, x []complex64, incX int) { + // declared at cblas.h:255:6 void cblas_ctpmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_ctpmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), unsafe.Pointer(&ap[0]), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ctrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { + // declared at cblas.h:258:6 void cblas_ctrsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_ctrsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ctbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { + // declared at cblas.h:262:6 void cblas_ctbsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_ctbsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), C.int(k), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ctpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap, x []complex64, incX int) { + // declared at cblas.h:266:6 void cblas_ctpsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_ctpsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), unsafe.Pointer(&ap[0]), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Zgemv(tA blas.Transpose, m, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { + // declared at cblas.h:270:6 void cblas_zgemv ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + var lenX, lenY int + if tA == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_zgemv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Zgbmv(tA blas.Transpose, m, n, kL, kU int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { + // declared at cblas.h:275:6 void cblas_zgbmv ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if kL < 0 { + panic("blas: kL < 0") + } + if kU < 0 { + panic("blas: kU < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + var lenX, lenY int + if tA == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { + panic("blas: index of a out of range") + } + C.cblas_zgbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.int(m), C.int(n), C.int(kL), C.int(kU), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Ztrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { + // declared at cblas.h:280:6 void cblas_ztrmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_ztrmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ztbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { + // declared at cblas.h:284:6 void cblas_ztbmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_ztbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), C.int(k), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ztpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap, x []complex128, incX int) { + // declared at cblas.h:288:6 void cblas_ztpmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_ztpmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), unsafe.Pointer(&ap[0]), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ztrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { + // declared at cblas.h:291:6 void cblas_ztrsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_ztrsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ztbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { + // declared at cblas.h:295:6 void cblas_ztbsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_ztbsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), C.int(k), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX)) +} + +func (Implementation) Ztpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap, x []complex128, incX int) { + // declared at cblas.h:299:6 void cblas_ztpsv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_ztpsv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(n), unsafe.Pointer(&ap[0]), unsafe.Pointer(&x[0]), C.int(incX)) +} + +// Ssymv computes +// y = alpha * A * x + beta * y, +// where a is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +func (Implementation) Ssymv(ul blas.Uplo, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + // declared at cblas.h:307:6 void cblas_ssymv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_ssymv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.float(alpha), (*C.float)(&a[0]), C.int(lda), (*C.float)(&x[0]), C.int(incX), C.float(beta), (*C.float)(&y[0]), C.int(incY)) +} + +// Ssbmv performs +// y = alpha * A * x + beta * y +// where A is an n×n symmetric banded matrix, x and y are vectors, and alpha +// and beta are scalars. +func (Implementation) Ssbmv(ul blas.Uplo, n, k int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + // declared at cblas.h:311:6 void cblas_ssbmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_ssbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.int(k), C.float(alpha), (*C.float)(&a[0]), C.int(lda), (*C.float)(&x[0]), C.int(incX), C.float(beta), (*C.float)(&y[0]), C.int(incY)) +} + +// Sspmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors +// and alpha and beta are scalars. +func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, ap, x []float32, incX int, beta float32, y []float32, incY int) { + // declared at cblas.h:315:6 void cblas_sspmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_sspmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.float(alpha), (*C.float)(&ap[0]), (*C.float)(&x[0]), C.int(incX), C.float(beta), (*C.float)(&y[0]), C.int(incY)) +} + +// Sger performs the rank-one operation +// A += alpha * x * y^T +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Sger(m, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) { + // declared at cblas.h:319:6 void cblas_sger ... + + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_sger(C.enum_CBLAS_ORDER(rowMajor), C.int(m), C.int(n), C.float(alpha), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY), (*C.float)(&a[0]), C.int(lda)) +} + +// Ssyr performs the rank-one update +// a += alpha * x * x^T +// where a is an n×n symmetric matrix, and x is a vector. +func (Implementation) Ssyr(ul blas.Uplo, n int, alpha float32, x []float32, incX int, a []float32, lda int) { + // declared at cblas.h:322:6 void cblas_ssyr ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_ssyr(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.float(alpha), (*C.float)(&x[0]), C.int(incX), (*C.float)(&a[0]), C.int(lda)) +} + +// Sspr computes the rank-one operation +// a += alpha * x * x^T +// where a is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX int, ap []float32) { + // declared at cblas.h:325:6 void cblas_sspr ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_sspr(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.float(alpha), (*C.float)(&x[0]), C.int(incX), (*C.float)(&ap[0])) +} + +// Ssyr2 performs the symmetric rank-two update +// A += alpha * x * y^T + alpha * y * x^T +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Ssyr2(ul blas.Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) { + // declared at cblas.h:328:6 void cblas_ssyr2 ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_ssyr2(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.float(alpha), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY), (*C.float)(&a[0]), C.int(lda)) +} + +// Sspr2 performs the symmetric rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func (Implementation) Sspr2(ul blas.Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, ap []float32) { + // declared at cblas.h:332:6 void cblas_sspr2 ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_sspr2(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.float(alpha), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY), (*C.float)(&ap[0])) +} + +// Dsymv computes +// y = alpha * A * x + beta * y, +// where a is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +func (Implementation) Dsymv(ul blas.Uplo, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + // declared at cblas.h:336:6 void cblas_dsymv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_dsymv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.double(alpha), (*C.double)(&a[0]), C.int(lda), (*C.double)(&x[0]), C.int(incX), C.double(beta), (*C.double)(&y[0]), C.int(incY)) +} + +// Dsbmv performs +// y = alpha * A * x + beta * y +// where A is an n×n symmetric banded matrix, x and y are vectors, and alpha +// and beta are scalars. +func (Implementation) Dsbmv(ul blas.Uplo, n, k int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + // declared at cblas.h:340:6 void cblas_dsbmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_dsbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.int(k), C.double(alpha), (*C.double)(&a[0]), C.int(lda), (*C.double)(&x[0]), C.int(incX), C.double(beta), (*C.double)(&y[0]), C.int(incY)) +} + +// Dspmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors +// and alpha and beta are scalars. +func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, ap, x []float64, incX int, beta float64, y []float64, incY int) { + // declared at cblas.h:344:6 void cblas_dspmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_dspmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.double(alpha), (*C.double)(&ap[0]), (*C.double)(&x[0]), C.int(incX), C.double(beta), (*C.double)(&y[0]), C.int(incY)) +} + +// Dger performs the rank-one operation +// A += alpha * x * y^T +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Dger(m, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) { + // declared at cblas.h:348:6 void cblas_dger ... + + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_dger(C.enum_CBLAS_ORDER(rowMajor), C.int(m), C.int(n), C.double(alpha), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY), (*C.double)(&a[0]), C.int(lda)) +} + +// Dsyr performs the rank-one update +// a += alpha * x * x^T +// where a is an n×n symmetric matrix, and x is a vector. +func (Implementation) Dsyr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64, lda int) { + // declared at cblas.h:351:6 void cblas_dsyr ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_dsyr(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.double(alpha), (*C.double)(&x[0]), C.int(incX), (*C.double)(&a[0]), C.int(lda)) +} + +// Dspr computes the rank-one operation +// a += alpha * x * x^T +// where a is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, ap []float64) { + // declared at cblas.h:354:6 void cblas_dspr ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_dspr(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.double(alpha), (*C.double)(&x[0]), C.int(incX), (*C.double)(&ap[0])) +} + +// Dsyr2 performs the symmetric rank-two update +// A += alpha * x * y^T + alpha * y * x^T +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Dsyr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) { + // declared at cblas.h:357:6 void cblas_dsyr2 ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_dsyr2(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.double(alpha), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY), (*C.double)(&a[0]), C.int(lda)) +} + +// Dspr2 performs the symmetric rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func (Implementation) Dspr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, ap []float64) { + // declared at cblas.h:361:6 void cblas_dspr2 ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_dspr2(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.double(alpha), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY), (*C.double)(&ap[0])) +} + +func (Implementation) Chemv(ul blas.Uplo, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + // declared at cblas.h:369:6 void cblas_chemv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_chemv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Chbmv(ul blas.Uplo, n, k int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + // declared at cblas.h:373:6 void cblas_chbmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_chbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Chpmv(ul blas.Uplo, n int, alpha complex64, ap, x []complex64, incX int, beta complex64, y []complex64, incY int) { + // declared at cblas.h:377:6 void cblas_chpmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_chpmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&ap[0]), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Cgeru(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { + // declared at cblas.h:381:6 void cblas_cgeru ... + + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_cgeru(C.enum_CBLAS_ORDER(rowMajor), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&a[0]), C.int(lda)) +} + +func (Implementation) Cgerc(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { + // declared at cblas.h:384:6 void cblas_cgerc ... + + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_cgerc(C.enum_CBLAS_ORDER(rowMajor), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&a[0]), C.int(lda)) +} + +func (Implementation) Cher(ul blas.Uplo, n int, alpha float32, x []complex64, incX int, a []complex64, lda int) { + // declared at cblas.h:387:6 void cblas_cher ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_cher(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.float(alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&a[0]), C.int(lda)) +} + +func (Implementation) Chpr(ul blas.Uplo, n int, alpha float32, x []complex64, incX int, ap []complex64) { + // declared at cblas.h:390:6 void cblas_chpr ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_chpr(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.float(alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&ap[0])) +} + +func (Implementation) Cher2(ul blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { + // declared at cblas.h:393:6 void cblas_cher2 ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_cher2(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&a[0]), C.int(lda)) +} + +func (Implementation) Chpr2(ul blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, ap []complex64) { + // declared at cblas.h:396:6 void cblas_chpr2 ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_chpr2(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&ap[0])) +} + +func (Implementation) Zhemv(ul blas.Uplo, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { + // declared at cblas.h:400:6 void cblas_zhemv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_zhemv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Zhbmv(ul blas.Uplo, n, k int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { + // declared at cblas.h:404:6 void cblas_zhbmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } + C.cblas_zhbmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Zhpmv(ul blas.Uplo, n int, alpha complex128, ap, x []complex128, incX int, beta complex128, y []complex128, incY int) { + // declared at cblas.h:408:6 void cblas_zhpmv ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_zhpmv(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&ap[0]), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&beta), unsafe.Pointer(&y[0]), C.int(incY)) +} + +func (Implementation) Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { + // declared at cblas.h:412:6 void cblas_zgeru ... + + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_zgeru(C.enum_CBLAS_ORDER(rowMajor), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&a[0]), C.int(lda)) +} + +func (Implementation) Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { + // declared at cblas.h:415:6 void cblas_zgerc ... + + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_zgerc(C.enum_CBLAS_ORDER(rowMajor), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&a[0]), C.int(lda)) +} + +func (Implementation) Zher(ul blas.Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) { + // declared at cblas.h:418:6 void cblas_zher ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_zher(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.double(alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&a[0]), C.int(lda)) +} + +func (Implementation) Zhpr(ul blas.Uplo, n int, alpha float64, x []complex128, incX int, ap []complex128) { + // declared at cblas.h:421:6 void cblas_zhpr ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if n == 0 { + return + } + C.cblas_zhpr(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), C.double(alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&ap[0])) +} + +func (Implementation) Zher2(ul blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { + // declared at cblas.h:424:6 void cblas_zher2 ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } + C.cblas_zher2(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&a[0]), C.int(lda)) +} + +func (Implementation) Zhpr2(ul blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, ap []complex128) { + // declared at cblas.h:427:6 void cblas_zhpr2 ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return + } + C.cblas_zhpr2(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&ap[0])) +} + +// Sgemm computes +// C = beta * C + alpha * A * B, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +func (Implementation) Sgemm(tA, tB blas.Transpose, m, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { + // declared at cblas.h:440:6 void cblas_sgemm ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var rowA, colA, rowB, colB int + if tA == blas.NoTrans { + rowA, colA = m, k + } else { + rowA, colA = k, m + } + if tB == blas.NoTrans { + rowB, colB = k, n + } else { + rowB, colB = n, k + } + if lda*(rowA-1)+colA > len(a) || lda < max(1, colA) { + panic("blas: index of a out of range") + } + if ldb*(rowB-1)+colB > len(b) || ldb < max(1, colB) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_sgemm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_TRANSPOSE(tB), C.int(m), C.int(n), C.int(k), C.float(alpha), (*C.float)(&a[0]), C.int(lda), (*C.float)(&b[0]), C.int(ldb), C.float(beta), (*C.float)(&c[0]), C.int(ldc)) +} + +// Ssymm performs one of +// C = alpha * A * B + beta * C, if side == blas.Left, +// C = alpha * B * A + beta * C, if side == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and alpha +// is a scalar. +func (Implementation) Ssymm(s blas.Side, ul blas.Uplo, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { + // declared at cblas.h:445:6 void cblas_ssymm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_ssymm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.int(m), C.int(n), C.float(alpha), (*C.float)(&a[0]), C.int(lda), (*C.float)(&b[0]), C.int(ldb), C.float(beta), (*C.float)(&c[0]), C.int(ldc)) +} + +// Ssyrk performs the symmetric rank-k operation +// C = alpha * A * A^T + beta*C +// C is an n×n symmetric matrix. A is an n×k matrix if tA == blas.NoTrans, and +// a k×n matrix otherwise. alpha and beta are scalars. +func (Implementation) Ssyrk(ul blas.Uplo, t blas.Transpose, n, k int, alpha float32, a []float32, lda int, beta float32, c []float32, ldc int) { + // declared at cblas.h:450:6 void cblas_ssyrk ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.Trans && t != blas.ConjTrans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_ssyrk(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), C.float(alpha), (*C.float)(&a[0]), C.int(lda), C.float(beta), (*C.float)(&c[0]), C.int(ldc)) +} + +// Ssyr2k performs the symmetric rank 2k operation +// C = alpha * A * B^T + alpha * B * A^T + beta * C +// where C is an n×n symmetric matrix. A and B are n×k matrices if +// tA == NoTrans and k×n otherwise. alpha and beta are scalars. +func (Implementation) Ssyr2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { + // declared at cblas.h:454:6 void cblas_ssyr2k ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.Trans && t != blas.ConjTrans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic("blas: index of b out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_ssyr2k(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), C.float(alpha), (*C.float)(&a[0]), C.int(lda), (*C.float)(&b[0]), C.int(ldb), C.float(beta), (*C.float)(&c[0]), C.int(ldc)) +} + +// Strmm performs +// B = alpha * A * B, if tA == blas.NoTrans and side == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and side == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, and B is an m×n matrix. +func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) { + // declared at cblas.h:459:6 void cblas_strmm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + C.cblas_strmm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(m), C.int(n), C.float(alpha), (*C.float)(&a[0]), C.int(lda), (*C.float)(&b[0]), C.int(ldb)) +} + +// Strsm solves +// A * X = alpha * B, if tA == blas.NoTrans side == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans side == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, X is an m×n matrix, and alpha is a +// scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in place into X. +// +// No check is made that A is invertible. +func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) { + // declared at cblas.h:464:6 void cblas_strsm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + C.cblas_strsm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(m), C.int(n), C.float(alpha), (*C.float)(&a[0]), C.int(lda), (*C.float)(&b[0]), C.int(ldb)) +} + +// Dgemm computes +// C = beta * C + alpha * A * B, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +func (Implementation) Dgemm(tA, tB blas.Transpose, m, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { + // declared at cblas.h:470:6 void cblas_dgemm ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var rowA, colA, rowB, colB int + if tA == blas.NoTrans { + rowA, colA = m, k + } else { + rowA, colA = k, m + } + if tB == blas.NoTrans { + rowB, colB = k, n + } else { + rowB, colB = n, k + } + if lda*(rowA-1)+colA > len(a) || lda < max(1, colA) { + panic("blas: index of a out of range") + } + if ldb*(rowB-1)+colB > len(b) || ldb < max(1, colB) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_dgemm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_TRANSPOSE(tB), C.int(m), C.int(n), C.int(k), C.double(alpha), (*C.double)(&a[0]), C.int(lda), (*C.double)(&b[0]), C.int(ldb), C.double(beta), (*C.double)(&c[0]), C.int(ldc)) +} + +// Dsymm performs one of +// C = alpha * A * B + beta * C, if side == blas.Left, +// C = alpha * B * A + beta * C, if side == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and alpha +// is a scalar. +func (Implementation) Dsymm(s blas.Side, ul blas.Uplo, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { + // declared at cblas.h:475:6 void cblas_dsymm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_dsymm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.int(m), C.int(n), C.double(alpha), (*C.double)(&a[0]), C.int(lda), (*C.double)(&b[0]), C.int(ldb), C.double(beta), (*C.double)(&c[0]), C.int(ldc)) +} + +// Dsyrk performs the symmetric rank-k operation +// C = alpha * A * A^T + beta*C +// C is an n×n symmetric matrix. A is an n×k matrix if tA == blas.NoTrans, and +// a k×n matrix otherwise. alpha and beta are scalars. +func (Implementation) Dsyrk(ul blas.Uplo, t blas.Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64, ldc int) { + // declared at cblas.h:480:6 void cblas_dsyrk ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.Trans && t != blas.ConjTrans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_dsyrk(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), C.double(alpha), (*C.double)(&a[0]), C.int(lda), C.double(beta), (*C.double)(&c[0]), C.int(ldc)) +} + +// Dsyr2k performs the symmetric rank 2k operation +// C = alpha * A * B^T + alpha * B * A^T + beta * C +// where C is an n×n symmetric matrix. A and B are n×k matrices if +// tA == NoTrans and k×n otherwise. alpha and beta are scalars. +func (Implementation) Dsyr2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { + // declared at cblas.h:484:6 void cblas_dsyr2k ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.Trans && t != blas.ConjTrans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic("blas: index of b out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_dsyr2k(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), C.double(alpha), (*C.double)(&a[0]), C.int(lda), (*C.double)(&b[0]), C.int(ldb), C.double(beta), (*C.double)(&c[0]), C.int(ldc)) +} + +// Dtrmm performs +// B = alpha * A * B, if tA == blas.NoTrans and side == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and side == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, and B is an m×n matrix. +func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) { + // declared at cblas.h:489:6 void cblas_dtrmm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + C.cblas_dtrmm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(m), C.int(n), C.double(alpha), (*C.double)(&a[0]), C.int(lda), (*C.double)(&b[0]), C.int(ldb)) +} + +// Dtrsm solves +// A * X = alpha * B, if tA == blas.NoTrans side == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans side == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, X is an m×n matrix, and alpha is a +// scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in place into X. +// +// No check is made that A is invertible. +func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) { + // declared at cblas.h:494:6 void cblas_dtrsm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + C.cblas_dtrsm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(m), C.int(n), C.double(alpha), (*C.double)(&a[0]), C.int(lda), (*C.double)(&b[0]), C.int(ldb)) +} + +func (Implementation) Cgemm(tA, tB blas.Transpose, m, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + // declared at cblas.h:500:6 void cblas_cgemm ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var rowA, colA, rowB, colB int + if tA == blas.NoTrans { + rowA, colA = m, k + } else { + rowA, colA = k, m + } + if tB == blas.NoTrans { + rowB, colB = k, n + } else { + rowB, colB = n, k + } + if lda*(rowA-1)+colA > len(a) || lda < max(1, colA) { + panic("blas: index of a out of range") + } + if ldb*(rowB-1)+colB > len(b) || ldb < max(1, colB) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_cgemm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_TRANSPOSE(tB), C.int(m), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Csymm(s blas.Side, ul blas.Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + // declared at cblas.h:505:6 void cblas_csymm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_csymm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Csyrk(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, beta complex64, c []complex64, ldc int) { + // declared at cblas.h:510:6 void cblas_csyrk ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.Trans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_csyrk(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Csyr2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + // declared at cblas.h:514:6 void cblas_csyr2k ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.Trans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic("blas: index of b out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_csyr2k(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Ctrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) { + // declared at cblas.h:519:6 void cblas_ctrmm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + C.cblas_ctrmm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb)) +} + +func (Implementation) Ctrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) { + // declared at cblas.h:524:6 void cblas_ctrsm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + C.cblas_ctrsm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb)) +} + +func (Implementation) Zgemm(tA, tB blas.Transpose, m, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + // declared at cblas.h:530:6 void cblas_zgemm ... + + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + panic("blas: illegal transpose") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var rowA, colA, rowB, colB int + if tA == blas.NoTrans { + rowA, colA = m, k + } else { + rowA, colA = k, m + } + if tB == blas.NoTrans { + rowB, colB = k, n + } else { + rowB, colB = n, k + } + if lda*(rowA-1)+colA > len(a) || lda < max(1, colA) { + panic("blas: index of a out of range") + } + if ldb*(rowB-1)+colB > len(b) || ldb < max(1, colB) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_zgemm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_TRANSPOSE(tB), C.int(m), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Zsymm(s blas.Side, ul blas.Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + // declared at cblas.h:535:6 void cblas_zsymm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_zsymm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Zsyrk(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, beta complex128, c []complex128, ldc int) { + // declared at cblas.h:540:6 void cblas_zsyrk ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.Trans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_zsyrk(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Zsyr2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + // declared at cblas.h:544:6 void cblas_zsyr2k ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.Trans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic("blas: index of b out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_zsyr2k(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Ztrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) { + // declared at cblas.h:549:6 void cblas_ztrmm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + C.cblas_ztrmm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb)) +} + +func (Implementation) Ztrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) { + // declared at cblas.h:554:6 void cblas_ztrsm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic("blas: illegal transpose") + } + if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + C.cblas_ztrsm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(tA), C.enum_CBLAS_DIAG(d), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb)) +} + +func (Implementation) Chemm(s blas.Side, ul blas.Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + // declared at cblas.h:564:6 void cblas_chemm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_chemm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Cherk(ul blas.Uplo, t blas.Transpose, n, k int, alpha float32, a []complex64, lda int, beta float32, c []complex64, ldc int) { + // declared at cblas.h:569:6 void cblas_cherk ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.ConjTrans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_cherk(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), C.float(alpha), unsafe.Pointer(&a[0]), C.int(lda), C.float(beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Cher2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta float32, c []complex64, ldc int) { + // declared at cblas.h:573:6 void cblas_cher2k ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.ConjTrans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic("blas: index of b out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_cher2k(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), C.float(beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Zhemm(s blas.Side, ul blas.Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + // declared at cblas.h:578:6 void cblas_zhemm ... + + if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if m < 0 { + panic("blas: m < 0") + } + if n < 0 { + panic("blas: n < 0") + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_zhemm(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_SIDE(s), C.enum_CBLAS_UPLO(ul), C.int(m), C.int(n), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), unsafe.Pointer(&beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Zherk(ul blas.Uplo, t blas.Transpose, n, k int, alpha float64, a []complex128, lda int, beta float64, c []complex128, ldc int) { + // declared at cblas.h:583:6 void cblas_zherk ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.ConjTrans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_zherk(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), C.double(alpha), unsafe.Pointer(&a[0]), C.int(lda), C.double(beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} + +func (Implementation) Zher2k(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta float64, c []complex128, ldc int) { + // declared at cblas.h:587:6 void cblas_zher2k ... + + if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } + if t != blas.NoTrans && t != blas.ConjTrans { + panic("blas: illegal transpose") + } + if n < 0 { + panic("blas: n < 0") + } + if k < 0 { + panic("blas: k < 0") + } + var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic("blas: index of a out of range") + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic("blas: index of b out of range") + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } + C.cblas_zher2k(C.enum_CBLAS_ORDER(rowMajor), C.enum_CBLAS_UPLO(ul), C.enum_CBLAS_TRANSPOSE(t), C.int(n), C.int(k), unsafe.Pointer(&alpha), unsafe.Pointer(&a[0]), C.int(lda), unsafe.Pointer(&b[0]), C.int(ldb), C.double(beta), unsafe.Pointer(&c[0]), C.int(ldc)) +} diff --git a/blas/cgo/cblas.h b/blas/cgo/cblas.h new file mode 100644 index 00000000..b8ac9a5f --- /dev/null +++ b/blas/cgo/cblas.h @@ -0,0 +1,596 @@ +#ifndef CBLAS_H + +#ifndef CBLAS_ENUM_DEFINED_H + #define CBLAS_ENUM_DEFINED_H + enum CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102 }; + enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113, + AtlasConj=114}; + enum CBLAS_UPLO {CblasUpper=121, CblasLower=122}; + enum CBLAS_DIAG {CblasNonUnit=131, CblasUnit=132}; + enum CBLAS_SIDE {CblasLeft=141, CblasRight=142}; +#endif + +#ifndef CBLAS_ENUM_ONLY +#define CBLAS_H +#define CBLAS_INDEX int + +int cblas_errprn(int ierr, int info, char *form, ...); + +/* + * =========================================================================== + * Prototypes for level 1 BLAS functions (complex are recast as routines) + * =========================================================================== + */ +float cblas_sdsdot(const int N, const float alpha, const float *X, + const int incX, const float *Y, const int incY); +double cblas_dsdot(const int N, const float *X, const int incX, const float *Y, + const int incY); +float cblas_sdot(const int N, const float *X, const int incX, + const float *Y, const int incY); +double cblas_ddot(const int N, const double *X, const int incX, + const double *Y, const int incY); +/* + * Functions having prefixes Z and C only + */ +void cblas_cdotu_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotu); +void cblas_cdotc_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotc); + +void cblas_zdotu_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotu); +void cblas_zdotc_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotc); + + +/* + * Functions having prefixes S D SC DZ + */ +float cblas_snrm2(const int N, const float *X, const int incX); +float cblas_sasum(const int N, const float *X, const int incX); + +double cblas_dnrm2(const int N, const double *X, const int incX); +double cblas_dasum(const int N, const double *X, const int incX); + +float cblas_scnrm2(const int N, const void *X, const int incX); +float cblas_scasum(const int N, const void *X, const int incX); + +double cblas_dznrm2(const int N, const void *X, const int incX); +double cblas_dzasum(const int N, const void *X, const int incX); + + +/* + * Functions having standard 4 prefixes (S D C Z) + */ +CBLAS_INDEX cblas_isamax(const int N, const float *X, const int incX); +CBLAS_INDEX cblas_idamax(const int N, const double *X, const int incX); +CBLAS_INDEX cblas_icamax(const int N, const void *X, const int incX); +CBLAS_INDEX cblas_izamax(const int N, const void *X, const int incX); + +/* + * =========================================================================== + * Prototypes for level 1 BLAS routines + * =========================================================================== + */ + +/* + * Routines with standard 4 prefixes (s, d, c, z) + */ +void cblas_sswap(const int N, float *X, const int incX, + float *Y, const int incY); +void cblas_scopy(const int N, const float *X, const int incX, + float *Y, const int incY); +void cblas_saxpy(const int N, const float alpha, const float *X, + const int incX, float *Y, const int incY); +void catlas_saxpby(const int N, const float alpha, const float *X, + const int incX, const float beta, float *Y, const int incY); +void catlas_sset + (const int N, const float alpha, float *X, const int incX); + +void cblas_dswap(const int N, double *X, const int incX, + double *Y, const int incY); +void cblas_dcopy(const int N, const double *X, const int incX, + double *Y, const int incY); +void cblas_daxpy(const int N, const double alpha, const double *X, + const int incX, double *Y, const int incY); +void catlas_daxpby(const int N, const double alpha, const double *X, + const int incX, const double beta, double *Y, const int incY); +void catlas_dset + (const int N, const double alpha, double *X, const int incX); + +void cblas_cswap(const int N, void *X, const int incX, + void *Y, const int incY); +void cblas_ccopy(const int N, const void *X, const int incX, + void *Y, const int incY); +void cblas_caxpy(const int N, const void *alpha, const void *X, + const int incX, void *Y, const int incY); +void catlas_caxpby(const int N, const void *alpha, const void *X, + const int incX, const void *beta, void *Y, const int incY); +void catlas_cset + (const int N, const void *alpha, void *X, const int incX); + +void cblas_zswap(const int N, void *X, const int incX, + void *Y, const int incY); +void cblas_zcopy(const int N, const void *X, const int incX, + void *Y, const int incY); +void cblas_zaxpy(const int N, const void *alpha, const void *X, + const int incX, void *Y, const int incY); +void catlas_zaxpby(const int N, const void *alpha, const void *X, + const int incX, const void *beta, void *Y, const int incY); +void catlas_zset + (const int N, const void *alpha, void *X, const int incX); + + +/* + * Routines with S and D prefix only + */ +void cblas_srotg(float *a, float *b, float *c, float *s); +void cblas_srotmg(float *d1, float *d2, float *b1, const float b2, float *P); +void cblas_srot(const int N, float *X, const int incX, + float *Y, const int incY, const float c, const float s); +void cblas_srotm(const int N, float *X, const int incX, + float *Y, const int incY, const float *P); + +void cblas_drotg(double *a, double *b, double *c, double *s); +void cblas_drotmg(double *d1, double *d2, double *b1, const double b2, double *P); +void cblas_drot(const int N, double *X, const int incX, + double *Y, const int incY, const double c, const double s); +void cblas_drotm(const int N, double *X, const int incX, + double *Y, const int incY, const double *P); + + +/* + * Routines with S D C Z CS and ZD prefixes + */ +void cblas_sscal(const int N, const float alpha, float *X, const int incX); +void cblas_dscal(const int N, const double alpha, double *X, const int incX); +void cblas_cscal(const int N, const void *alpha, void *X, const int incX); +void cblas_zscal(const int N, const void *alpha, void *X, const int incX); +void cblas_csscal(const int N, const float alpha, void *X, const int incX); +void cblas_zdscal(const int N, const double alpha, void *X, const int incX); + +/* + * Extra reference routines provided by ATLAS, but not mandated by the standard + */ +void cblas_crotg(void *a, void *b, void *c, void *s); +void cblas_zrotg(void *a, void *b, void *c, void *s); +void cblas_csrot(const int N, void *X, const int incX, void *Y, const int incY, + const float c, const float s); +void cblas_zdrot(const int N, void *X, const int incX, void *Y, const int incY, + const double c, const double s); + +/* + * =========================================================================== + * Prototypes for level 2 BLAS + * =========================================================================== + */ + +/* + * Routines with standard 4 prefixes (S, D, C, Z) + */ +void cblas_sgemv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const float alpha, const float *A, const int lda, + const float *X, const int incX, const float beta, + float *Y, const int incY); +void cblas_sgbmv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const int KL, const int KU, const float alpha, + const float *A, const int lda, const float *X, + const int incX, const float beta, float *Y, const int incY); +void cblas_strmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const float *A, const int lda, + float *X, const int incX); +void cblas_stbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const float *A, const int lda, + float *X, const int incX); +void cblas_stpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const float *Ap, float *X, const int incX); +void cblas_strsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const float *A, const int lda, float *X, + const int incX); +void cblas_stbsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const float *A, const int lda, + float *X, const int incX); +void cblas_stpsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const float *Ap, float *X, const int incX); + +void cblas_dgemv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const double alpha, const double *A, const int lda, + const double *X, const int incX, const double beta, + double *Y, const int incY); +void cblas_dgbmv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const int KL, const int KU, const double alpha, + const double *A, const int lda, const double *X, + const int incX, const double beta, double *Y, const int incY); +void cblas_dtrmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const double *A, const int lda, + double *X, const int incX); +void cblas_dtbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const double *A, const int lda, + double *X, const int incX); +void cblas_dtpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const double *Ap, double *X, const int incX); +void cblas_dtrsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const double *A, const int lda, double *X, + const int incX); +void cblas_dtbsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const double *A, const int lda, + double *X, const int incX); +void cblas_dtpsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const double *Ap, double *X, const int incX); + +void cblas_cgemv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *X, const int incX, const void *beta, + void *Y, const int incY); +void cblas_cgbmv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const int KL, const int KU, const void *alpha, + const void *A, const int lda, const void *X, + const int incX, const void *beta, void *Y, const int incY); +void cblas_ctrmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *A, const int lda, + void *X, const int incX); +void cblas_ctbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const void *A, const int lda, + void *X, const int incX); +void cblas_ctpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *Ap, void *X, const int incX); +void cblas_ctrsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *A, const int lda, void *X, + const int incX); +void cblas_ctbsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const void *A, const int lda, + void *X, const int incX); +void cblas_ctpsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *Ap, void *X, const int incX); + +void cblas_zgemv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *X, const int incX, const void *beta, + void *Y, const int incY); +void cblas_zgbmv(const enum CBLAS_ORDER Order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const int KL, const int KU, const void *alpha, + const void *A, const int lda, const void *X, + const int incX, const void *beta, void *Y, const int incY); +void cblas_ztrmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *A, const int lda, + void *X, const int incX); +void cblas_ztbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const void *A, const int lda, + void *X, const int incX); +void cblas_ztpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *Ap, void *X, const int incX); +void cblas_ztrsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *A, const int lda, void *X, + const int incX); +void cblas_ztbsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const int K, const void *A, const int lda, + void *X, const int incX); +void cblas_ztpsv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, + const int N, const void *Ap, void *X, const int incX); + + +/* + * Routines with S and D prefixes only + */ +void cblas_ssymv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *A, + const int lda, const float *X, const int incX, + const float beta, float *Y, const int incY); +void cblas_ssbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int K, const float alpha, const float *A, + const int lda, const float *X, const int incX, + const float beta, float *Y, const int incY); +void cblas_sspmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *Ap, + const float *X, const int incX, + const float beta, float *Y, const int incY); +void cblas_sger(const enum CBLAS_ORDER Order, const int M, const int N, + const float alpha, const float *X, const int incX, + const float *Y, const int incY, float *A, const int lda); +void cblas_ssyr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *X, + const int incX, float *A, const int lda); +void cblas_sspr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *X, + const int incX, float *Ap); +void cblas_ssyr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *X, + const int incX, const float *Y, const int incY, float *A, + const int lda); +void cblas_sspr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const float *X, + const int incX, const float *Y, const int incY, float *Ap); + +void cblas_dsymv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *A, + const int lda, const double *X, const int incX, + const double beta, double *Y, const int incY); +void cblas_dsbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int K, const double alpha, const double *A, + const int lda, const double *X, const int incX, + const double beta, double *Y, const int incY); +void cblas_dspmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *Ap, + const double *X, const int incX, + const double beta, double *Y, const int incY); +void cblas_dger(const enum CBLAS_ORDER Order, const int M, const int N, + const double alpha, const double *X, const int incX, + const double *Y, const int incY, double *A, const int lda); +void cblas_dsyr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *X, + const int incX, double *A, const int lda); +void cblas_dspr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *X, + const int incX, double *Ap); +void cblas_dsyr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *X, + const int incX, const double *Y, const int incY, double *A, + const int lda); +void cblas_dspr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const double *X, + const int incX, const double *Y, const int incY, double *Ap); + + +/* + * Routines with C and Z prefixes only + */ +void cblas_chemv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const void *alpha, const void *A, + const int lda, const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_chbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int K, const void *alpha, const void *A, + const int lda, const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_chpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const void *alpha, const void *Ap, + const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_cgeru(const enum CBLAS_ORDER Order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_cgerc(const enum CBLAS_ORDER Order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_cher(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const void *X, const int incX, + void *A, const int lda); +void cblas_chpr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const float alpha, const void *X, + const int incX, void *Ap); +void cblas_cher2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_chpr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *Ap); + +void cblas_zhemv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const void *alpha, const void *A, + const int lda, const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_zhbmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const int K, const void *alpha, const void *A, + const int lda, const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_zhpmv(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const void *alpha, const void *Ap, + const void *X, const int incX, + const void *beta, void *Y, const int incY); +void cblas_zgeru(const enum CBLAS_ORDER Order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_zgerc(const enum CBLAS_ORDER Order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_zher(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const void *X, const int incX, + void *A, const int lda); +void cblas_zhpr(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const int N, const double alpha, const void *X, + const int incX, void *Ap); +void cblas_zher2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); +void cblas_zhpr2(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *Ap); + +/* + * =========================================================================== + * Prototypes for level 3 BLAS + * =========================================================================== + */ + +/* + * Routines with standard 4 prefixes (S, D, C, Z) + */ +void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const float alpha, const float *A, + const int lda, const float *B, const int ldb, + const float beta, float *C, const int ldc); +void cblas_ssymm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const float alpha, const float *A, const int lda, + const float *B, const int ldb, const float beta, + float *C, const int ldc); +void cblas_ssyrk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const float alpha, const float *A, const int lda, + const float beta, float *C, const int ldc); +void cblas_ssyr2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const float alpha, const float *A, const int lda, + const float *B, const int ldb, const float beta, + float *C, const int ldc); +void cblas_strmm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const float alpha, const float *A, const int lda, + float *B, const int ldb); +void cblas_strsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const float alpha, const float *A, const int lda, + float *B, const int ldb); + +void cblas_dgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const double alpha, const double *A, + const int lda, const double *B, const int ldb, + const double beta, double *C, const int ldc); +void cblas_dsymm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const double alpha, const double *A, const int lda, + const double *B, const int ldb, const double beta, + double *C, const int ldc); +void cblas_dsyrk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const double alpha, const double *A, const int lda, + const double beta, double *C, const int ldc); +void cblas_dsyr2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const double alpha, const double *A, const int lda, + const double *B, const int ldb, const double beta, + double *C, const int ldc); +void cblas_dtrmm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const double alpha, const double *A, const int lda, + double *B, const int ldb); +void cblas_dtrsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const double alpha, const double *A, const int lda, + double *B, const int ldb); + +void cblas_cgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const void *alpha, const void *A, + const int lda, const void *B, const int ldb, + const void *beta, void *C, const int ldc); +void cblas_csymm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_csyrk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *beta, void *C, const int ldc); +void cblas_csyr2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_ctrmm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const void *alpha, const void *A, const int lda, + void *B, const int ldb); +void cblas_ctrsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const void *alpha, const void *A, const int lda, + void *B, const int ldb); + +void cblas_zgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const void *alpha, const void *A, + const int lda, const void *B, const int ldb, + const void *beta, void *C, const int ldc); +void cblas_zsymm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_zsyrk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *beta, void *C, const int ldc); +void cblas_zsyr2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_ztrmm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const void *alpha, const void *A, const int lda, + void *B, const int ldb); +void cblas_ztrsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const void *alpha, const void *A, const int lda, + void *B, const int ldb); + + +/* + * Routines with prefixes C and Z only + */ +void cblas_chemm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_cherk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const float alpha, const void *A, const int lda, + const float beta, void *C, const int ldc); +void cblas_cher2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const float beta, + void *C, const int ldc); +void cblas_zhemm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const void *beta, + void *C, const int ldc); +void cblas_zherk(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const double alpha, const void *A, const int lda, + const double beta, void *C, const int ldc); +void cblas_zher2k(const enum CBLAS_ORDER Order, const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE Trans, const int N, const int K, + const void *alpha, const void *A, const int lda, + const void *B, const int ldb, const double beta, + void *C, const int ldc); + +int cblas_errprn(int ierr, int info, char *form, ...); + +#endif /* end #ifdef CBLAS_ENUM_ONLY */ +#endif diff --git a/blas/cgo/dgemmbench_test.go b/blas/cgo/dgemmbench_test.go new file mode 100644 index 00000000..3a9e3397 --- /dev/null +++ b/blas/cgo/dgemmbench_test.go @@ -0,0 +1,47 @@ +package cgo + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDgemmSmSmSm(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Sm, Sm, Sm, NT, NT) +} + +func BenchmarkDgemmMedMedMed(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, NT, NT) +} + +func BenchmarkDgemmMedLgMed(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Lg, Med, NT, NT) +} + +func BenchmarkDgemmLgLgLg(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Lg, Lg, Lg, NT, NT) +} + +func BenchmarkDgemmLgSmLg(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Lg, Sm, Lg, NT, NT) +} + +func BenchmarkDgemmLgLgSm(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Lg, Lg, Sm, NT, NT) +} + +func BenchmarkDgemmHgHgSm(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Hg, Hg, Sm, NT, NT) +} + +func BenchmarkDgemmMedMedMedTNT(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, T, NT) +} + +func BenchmarkDgemmMedMedMedNTT(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, NT, T) +} + +func BenchmarkDgemmMedMedMedTT(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, T, T) +} diff --git a/blas/cgo/dgemvbench_test.go b/blas/cgo/dgemvbench_test.go new file mode 100644 index 00000000..63caee79 --- /dev/null +++ b/blas/cgo/dgemvbench_test.go @@ -0,0 +1,87 @@ +package cgo + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDgemvSmSmNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Sm, 1, 1) +} + +func BenchmarkDgemvSmSmNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Sm, 2, 3) +} + +func BenchmarkDgemvSmSmTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Sm, 1, 1) +} + +func BenchmarkDgemvSmSmTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Sm, 2, 3) +} + +func BenchmarkDgemvMedMedNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Med, Med, 1, 1) +} + +func BenchmarkDgemvMedMedNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Med, Med, 2, 3) +} + +func BenchmarkDgemvMedMedTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Med, Med, 1, 1) +} + +func BenchmarkDgemvMedMedTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Med, Med, 2, 3) +} + +func BenchmarkDgemvLgLgNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Lg, 1, 1) +} + +func BenchmarkDgemvLgLgNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Lg, 2, 3) +} + +func BenchmarkDgemvLgLgTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Lg, 1, 1) +} + +func BenchmarkDgemvLgLgTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Lg, 2, 3) +} + +func BenchmarkDgemvLgSmNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Sm, 1, 1) +} + +func BenchmarkDgemvLgSmNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Sm, 2, 3) +} + +func BenchmarkDgemvLgSmTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Sm, 1, 1) +} + +func BenchmarkDgemvLgSmTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Sm, 2, 3) +} + +func BenchmarkDgemvSmLgNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Lg, 1, 1) +} + +func BenchmarkDgemvSmLgNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Lg, 2, 3) +} + +func BenchmarkDgemvSmLgTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Lg, 1, 1) +} + +func BenchmarkDgemvSmLgTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Lg, 2, 3) +} diff --git a/blas/cgo/dgerbench_test.go b/blas/cgo/dgerbench_test.go new file mode 100644 index 00000000..06ed2fdd --- /dev/null +++ b/blas/cgo/dgerbench_test.go @@ -0,0 +1,47 @@ +package cgo + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDgerSmSmInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Sm, 1, 1) +} + +func BenchmarkDgerSmSmIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Sm, 2, 3) +} + +func BenchmarkDgerMedMedInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Med, Med, 1, 1) +} + +func BenchmarkDgerMedMedIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Med, Med, 2, 3) +} + +func BenchmarkDgerLgLgInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Lg, 1, 1) +} + +func BenchmarkDgerLgLgIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Lg, 2, 3) +} + +func BenchmarkDgerLgSmInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Sm, 1, 1) +} + +func BenchmarkDgerLgSmIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Sm, 2, 3) +} + +func BenchmarkDgerSmLgInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Lg, 1, 1) +} + +func BenchmarkDgerSmLgIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Lg, 2, 3) +} diff --git a/blas/cgo/doc.go b/blas/cgo/doc.go new file mode 100644 index 00000000..4e3efcf2 --- /dev/null +++ b/blas/cgo/doc.go @@ -0,0 +1,95 @@ +// Copyright ©2015 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run generate_blas.go + +// Ensure changes made to blas/cgo are reflected in blas/native where relevant. + +/* +Package cgo provides bindings to a C BLAS library. This wrapper interface +panics when the input arguments are invalid as per the standard, for example +if a vector increment is zero. Please note that the treatment of NaN values +is not specified, and differs among the BLAS implementations. +github.com/gonum/blas/blas64 provides helpful wrapper functions to the BLAS +interface. The rest of this text describes the layout of the data for the input types. + +Please note that in the function documentation, x[i] refers to the i^th element +of the vector, which will be different from the i^th element of the slice if +incX != 1. + +Vector arguments are effectively strided slices. They have two input arguments, +a number of elements, n, and an increment, incX. The increment specifies the +distance between elements of the vector. The actual Go slice may be longer +than necessary. +The increment may be positive or negative, except in functions with only +a single vector argument where the increment may only be positive. If the increment +is negative, s[0] is the last element in the slice. Note that this is not the same +as counting backward from the end of the slice, as len(s) may be longer than +necessary. So, for example, if n = 5 and incX = 3, the elements of s are + [0 * * 1 * * 2 * * 3 * * 4 * * * ...] +where ∗ elements are never accessed. If incX = -3, the same elements are +accessed, just in reverse order (4, 3, 2, 1, 0). + +Dense matrices are specified by a number of rows, a number of columns, and a stride. +The stride specifies the number of entries in the slice between the first element +of successive rows. The stride must be at least as large as the number of columns +but may be longer. + [a00 ... a0n a0* ... a1stride-1 a21 ... amn am* ... amstride-1] +Thus, dense[i*ld + j] refers to the {i, j}th element of the matrix. + +Symmetric and triangular matrices (non-packed) are stored identically to Dense, +except that only elements in one triangle of the matrix are accessed. + +Packed symmetric and packed triangular matrices are laid out with the entries +condensed such that all of the unreferenced elements are removed. So, the upper triangular +matrix + [ + 1 2 3 + 0 4 5 + 0 0 6 + ] +and the lower-triangular matrix + [ + 1 0 0 + 2 3 0 + 4 5 6 + ] +will both be compacted as [1 2 3 4 5 6]. The (i, j) element of the original +dense matrix can be found at element i*n - (i-1)*i/2 + j for upper triangular, +and at element i * (i+1) /2 + j for lower triangular. + +Banded matrices are laid out in a compact format, constructed by removing the +zeros in the rows and aligning the diagonals. For example, the matrix + [ + 1 2 3 0 0 0 + 4 5 6 7 0 0 + 0 8 9 10 11 0 + 0 0 12 13 14 15 + 0 0 0 16 17 18 + 0 0 0 0 19 20 + ] + +implicitly becomes (∗ entries are never accessed) + [ + * 1 2 3 + 4 5 6 7 + 8 9 10 11 + 12 13 14 15 + 16 17 18 * + 19 20 * * + ] +which is given to the BLAS routine as [∗ 1 2 3 4 ...]. + +See http://www.crest.iu.edu/research/mtl/reference/html/banded.html +for more information + +*/ +package cgo + +// BUG(btracey): The cgo package is intrinsically dependent on the underlying C +// implementation. The BLAS standard is silent on a number of behaviors, including +// but not limited to how NaN values are treated. For this reason the result of +// computations performed by the cgo BLAS package may disagree with the results +// produced by the native BLAS package. The cgo package is tested against OpenBLAS; +// use of other backing BLAS C libraries may result in test failure because of this. diff --git a/blas/cgo/dtrmvbench_test.go b/blas/cgo/dtrmvbench_test.go new file mode 100644 index 00000000..0bd44420 --- /dev/null +++ b/blas/cgo/dtrmvbench_test.go @@ -0,0 +1,54 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package cgo + +import ( + "strconv" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDtrmv(b *testing.B) { + for _, n := range []int{testblas.MediumMat, testblas.LargeMat} { + for _, incX := range []int{1, 5} { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, unit := range []blas.Diag{blas.NonUnit, blas.Unit} { + var str string + if n == testblas.MediumMat { + str += "Med" + } else if n == testblas.LargeMat { + str += "Large" + } + str += "_Inc" + strconv.Itoa(incX) + if uplo == blas.Upper { + str += "_UP" + } else { + str += "_LO" + } + if trans == blas.NoTrans { + str += "_NT" + } else { + str += "_TR" + } + if unit == blas.NonUnit { + str += "_NU" + } else { + str += "_UN" + } + lda := n + b.Run(str, func(b *testing.B) { + testblas.DtrmvBenchmark(b, Implementation{}, n, lda, incX, uplo, trans, unit) + }) + } + } + } + } + } +} diff --git a/blas/cgo/generate_blas.go b/blas/cgo/generate_blas.go new file mode 100644 index 00000000..428a48ed --- /dev/null +++ b/blas/cgo/generate_blas.go @@ -0,0 +1,978 @@ +// Copyright ©2016 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// generate_blas creates a blas.go file from the provided C header file +// with optionally added documentation from the documentation package. +package main + +import ( + "bytes" + "fmt" + "go/ast" + "go/format" + "io/ioutil" + "log" + "strings" + "text/template" + + "github.com/cznic/cc" + + "gonum.org/v1/gonum/internal/binding" +) + +const ( + header = "cblas.h" + documentation = "../native" + target = "blas.go" + + typ = "Implementation" + + prefix = "cblas_" + + warning = "Float32 implementations are autogenerated and not directly tested." +) + +const ( + cribDocs = true + elideRepeat = true + noteOrigin = true + separateFuncs = false +) + +var skip = map[string]bool{ + "cblas_errprn": true, + "cblas_srotg": true, + "cblas_srotmg": true, + "cblas_srotm": true, + "cblas_drotg": true, + "cblas_drotmg": true, + "cblas_drotm": true, + "cblas_crotg": true, + "cblas_zrotg": true, + "cblas_cdotu_sub": true, + "cblas_cdotc_sub": true, + "cblas_zdotu_sub": true, + "cblas_zdotc_sub": true, + + // ATLAS extensions. + "cblas_csrot": true, + "cblas_zdrot": true, +} + +var cToGoType = map[string]string{ + "int": "int", + "float": "float32", + "double": "float64", +} + +var blasEnums = map[string]*template.Template{ + "CBLAS_ORDER": template.Must(template.New("order").Parse("order")), + "CBLAS_DIAG": template.Must(template.New("diag").Parse("blas.Diag")), + "CBLAS_TRANSPOSE": template.Must(template.New("trans").Parse("blas.Transpose")), + "CBLAS_UPLO": template.Must(template.New("uplo").Parse("blas.Uplo")), + "CBLAS_SIDE": template.Must(template.New("side").Parse("blas.Side")), +} + +var cgoEnums = map[string]*template.Template{ + "CBLAS_ORDER": template.Must(template.New("order").Parse("C.enum_CBLAS_ORDER(rowMajor)")), + "CBLAS_DIAG": template.Must(template.New("diag").Parse("C.enum_CBLAS_DIAG({{.}})")), + "CBLAS_TRANSPOSE": template.Must(template.New("trans").Parse("C.enum_CBLAS_TRANSPOSE({{.}})")), + "CBLAS_UPLO": template.Must(template.New("uplo").Parse("C.enum_CBLAS_UPLO({{.}})")), + "CBLAS_SIDE": template.Must(template.New("side").Parse("C.enum_CBLAS_SIDE({{.}})")), +} + +var cgoTypes = map[binding.TypeKey]*template.Template{ + {Kind: cc.Void, IsPointer: true}: template.Must(template.New("void*").Parse( + `unsafe.Pointer(&{{.}}{{if eq . "alpha" "beta"}}{{else}}[0]{{end}})`, + )), +} + +var ( + complex64Type = map[binding.TypeKey]*template.Template{ + {Kind: cc.Void, IsPointer: true}: template.Must(template.New("void*").Parse( + `{{if eq . "alpha" "beta"}}complex64{{else}}[]complex64{{end}}`, + ))} + + complex128Type = map[binding.TypeKey]*template.Template{ + {Kind: cc.Void, IsPointer: true}: template.Must(template.New("void*").Parse( + `{{if eq . "alpha" "beta"}}complex128{{else}}[]complex128{{end}}`, + ))} +) + +var names = map[string]string{ + "uplo": "ul", + "trans": "t", + "transA": "tA", + "transB": "tB", + "side": "s", + "diag": "d", +} + +func shorten(n string) string { + s, ok := names[n] + if ok { + return s + } + return n +} + +func main() { + decls, err := binding.Declarations(header) + if err != nil { + log.Fatal(err) + } + var docs map[string]map[string][]*ast.Comment + if cribDocs { + docs, err = binding.DocComments(documentation) + if err != nil { + log.Fatal(err) + } + } + + var buf bytes.Buffer + + h, err := template.New("handwritten").Parse(handwritten) + if err != nil { + log.Fatal(err) + } + err = h.Execute(&buf, header) + if err != nil { + log.Fatal(err) + } + + var n int + for _, d := range decls { + if !strings.HasPrefix(d.Name, prefix) || skip[d.Name] { + continue + } + if n != 0 && (separateFuncs || cribDocs) { + buf.WriteByte('\n') + } + n++ + goSignature(&buf, d, docs[typ]) + if noteOrigin { + fmt.Fprintf(&buf, "\t// declared at %s %s %s ...\n\n", d.Position(), d.Return, d.Name) + } + parameterChecks(&buf, d, parameterCheckRules) + buf.WriteByte('\t') + cgoCall(&buf, d) + buf.WriteString("}\n") + } + + b, err := format.Source(buf.Bytes()) + if err != nil { + log.Fatal(err) + } + err = ioutil.WriteFile(target, b, 0664) + if err != nil { + log.Fatal(err) + } +} + +func goSignature(buf *bytes.Buffer, d binding.Declaration, docs map[string][]*ast.Comment) { + blasName := strings.TrimPrefix(d.Name, prefix) + goName := binding.UpperCaseFirst(blasName) + + if docs != nil { + if doc, ok := docs[goName]; ok { + if strings.Contains(doc[len(doc)-1].Text, warning) { + doc = doc[:len(doc)-2] + } + for _, c := range doc { + buf.WriteString(c.Text) + buf.WriteByte('\n') + } + } + } + + parameters := d.Parameters() + + var voidPtrType map[binding.TypeKey]*template.Template + for _, p := range parameters { + if p.Kind() == cc.Ptr && p.Elem().Kind() == cc.Void { + switch { + case blasName[0] == 'c', blasName[1] == 'c' && blasName[0] != 'z': + voidPtrType = complex64Type + case blasName[0] == 'z', blasName[1] == 'z': + voidPtrType = complex128Type + } + break + } + } + + fmt.Fprintf(buf, "func (%s) %s(", typ, goName) + c := 0 + for i, p := range parameters { + if p.Kind() == cc.Enum && binding.GoTypeForEnum(p.Type(), "", blasEnums) == "order" { + continue + } + if c != 0 { + buf.WriteString(", ") + } + c++ + + n := shorten(binding.LowerCaseFirst(p.Name())) + var this, next string + + if p.Kind() == cc.Enum { + this = binding.GoTypeForEnum(p.Type(), n, blasEnums) + } else { + this = binding.GoTypeFor(p.Type(), n, voidPtrType) + } + + if elideRepeat && i < len(parameters)-1 && p.Type().Kind() == parameters[i+1].Type().Kind() { + p := parameters[i+1] + n := shorten(binding.LowerCaseFirst(p.Name())) + if p.Kind() == cc.Enum { + next = binding.GoTypeForEnum(p.Type(), n, blasEnums) + } else { + next = binding.GoTypeFor(p.Type(), n, voidPtrType) + } + } + if next == this { + buf.WriteString(n) + } else { + fmt.Fprintf(buf, "%s %s", n, this) + } + } + if d.Return.Kind() != cc.Void { + fmt.Fprintf(buf, ") %s {\n", cToGoType[d.Return.String()]) + } else { + buf.WriteString(") {\n") + } +} + +func parameterChecks(buf *bytes.Buffer, d binding.Declaration, rules []func(*bytes.Buffer, binding.Declaration, binding.Parameter) bool) { + done := make(map[int]bool) + for _, p := range d.Parameters() { + for i, r := range rules { + if done[i] { + continue + } + done[i] = r(buf, d, p) + } + } +} + +func cgoCall(buf *bytes.Buffer, d binding.Declaration) { + if d.Return.Kind() != cc.Void { + fmt.Fprintf(buf, "return %s(", cToGoType[d.Return.String()]) + } + fmt.Fprintf(buf, "C.%s(", d.Name) + for i, p := range d.Parameters() { + if i != 0 { + buf.WriteString(", ") + } + if p.Type().Kind() == cc.Enum { + buf.WriteString(binding.CgoConversionForEnum(shorten(binding.LowerCaseFirst(p.Name())), p.Type(), cgoEnums)) + } else { + buf.WriteString(binding.CgoConversionFor(shorten(binding.LowerCaseFirst(p.Name())), p.Type(), cgoTypes)) + } + } + if d.Return.Kind() != cc.Void { + buf.WriteString(")") + } + buf.WriteString(")\n") +} + +var parameterCheckRules = []func(*bytes.Buffer, binding.Declaration, binding.Parameter) bool{ + trans, + uplo, + diag, + side, + + shape, + apShape, + zeroInc, + sidedShape, + mvShape, + rkShape, + gemmShape, + scalShape, + amaxShape, + nrmSumShape, + vectorShape, + othersShape, + + noWork, +} + +func amaxShape(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + switch d.Name { + case "cblas_isamax", "cblas_idamax", "cblas_icamax", "cblas_izamax": + default: + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + fmt.Fprint(buf, ` if n == 0 || incX < 0 { + return -1 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } +`) + return true +} + +func apShape(buf *bytes.Buffer, _ binding.Declaration, p binding.Parameter) bool { + n := binding.LowerCaseFirst(p.Name()) + if n != "ap" { + return false + } + fmt.Fprint(buf, ` if n*(n+1)/2 > len(ap) { + panic("blas: index of ap out of range") + } +`) + return true +} + +func diag(buf *bytes.Buffer, _ binding.Declaration, p binding.Parameter) bool { + if p.Name() != "Diag" { + return false + } + fmt.Fprint(buf, ` if d != blas.NonUnit && d != blas.Unit { + panic("blas: illegal diagonal") + } +`) + return true +} + +func gemmShape(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + switch d.Name { + case "cblas_sgemm", "cblas_dgemm", "cblas_cgemm", "cblas_zgemm": + default: + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + fmt.Fprint(buf, ` var rowA, colA, rowB, colB int + if tA == blas.NoTrans { + rowA, colA = m, k + } else { + rowA, colA = k, m + } + if tB == blas.NoTrans { + rowB, colB = k, n + } else { + rowB, colB = n, k + } + if lda*(rowA-1)+colA > len(a) || lda < max(1, colA) { + panic("blas: index of a out of range") + } + if ldb*(rowB-1)+colB > len(b) || ldb < max(1, colB) { + panic("blas: index of b out of range") + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } +`) + return true +} + +func mvShape(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + switch d.Name { + case "cblas_sgbmv", "cblas_dgbmv", "cblas_cgbmv", "cblas_zgbmv", + "cblas_sgemv", "cblas_dgemv", "cblas_cgemv", "cblas_zgemv": + default: + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + fmt.Fprint(buf, ` var lenX, lenY int + if tA == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic("blas: y index out of range") + } +`) + return true +} + +func noWork(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + var hasN, hasLda, hasLdb bool + for _, p := range d.Parameters() { + switch shorten(binding.LowerCaseFirst(p.Name())) { + case "n": + hasN = true + case "lda": + hasLda = true + case "ldb": + hasLdb = true + } + } + if !hasN || hasLda || hasLdb { + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + var value string + switch d.Return.String() { + case "int": + value = " -1" + case "float", "double": + value = " 0" + } + fmt.Fprintf(buf, ` if n == 0 { + return%s + } +`, value) + return true +} + +func nrmSumShape(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + switch d.Name { + case "cblas_snrm2", "cblas_dnrm2", "cblas_scnrm2", "cblas_dznrm2", + "cblas_sasum", "cblas_dasum", "cblas_scasum", "cblas_dzasum": + default: + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + fmt.Fprint(buf, ` if incX < 0 { + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } +`) + return true +} + +func rkShape(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + switch d.Name { + case "cblas_ssyrk", "cblas_dsyrk", "cblas_csyrk", "cblas_zsyrk", + "cblas_ssyr2k", "cblas_dsyr2k", "cblas_csyr2k", "cblas_zsyr2k", + "cblas_cherk", "cblas_zherk", "cblas_cher2k", "cblas_zher2k": + default: + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + fmt.Fprint(buf, ` var row, col int + if t == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } +`) + has := make(map[string]bool) + for _, p := range d.Parameters() { + if p.Kind() != cc.Ptr { + continue + } + has[shorten(binding.LowerCaseFirst(p.Name()))] = true + } + for _, label := range []string{"a", "b"} { + if has[label] { + fmt.Fprintf(buf, ` if ld%[1]s*(row-1)+col > len(%[1]s) || ld%[1]s < max(1, col) { + panic("blas: index of %[1]s out of range") + } +`, label) + } + } + if has["c"] { + fmt.Fprint(buf, ` if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } +`) + } + + return true +} + +func scalShape(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + switch d.Name { + case "cblas_sscal", "cblas_dscal", "cblas_cscal", "cblas_zscal", "cblas_csscal": + default: + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + fmt.Fprint(buf, ` if incX < 0 { + return + } + if incX > 0 && (n-1)*incX >= len(x) { + panic("blas: x index out of range") + } +`) + return true +} + +func shape(buf *bytes.Buffer, _ binding.Declaration, p binding.Parameter) bool { + switch n := binding.LowerCaseFirst(p.Name()); n { + case "m", "n", "k", "kL", "kU": + fmt.Fprintf(buf, ` if %[1]s < 0 { + panic("blas: %[1]s < 0") + } +`, n) + return false + } + return false +} + +func side(buf *bytes.Buffer, _ binding.Declaration, p binding.Parameter) bool { + if p.Name() != "Side" { + return false + } + fmt.Fprint(buf, ` if s != blas.Left && s != blas.Right { + panic("blas: illegal side") + } +`) + return true +} + +func sidedShape(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + var hasS, hasA, hasB, hasC bool + for _, p := range d.Parameters() { + switch shorten(binding.LowerCaseFirst(p.Name())) { + case "s": + hasS = true + case "a": + hasA = true + case "b": + hasB = true + case "c": + hasC = true + } + } + if !hasS { + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + if hasA && hasB { + fmt.Fprint(buf, ` var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic("blas: index of a out of range") + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic("blas: index of b out of range") + } +`) + } else { + return true + } + if hasC { + fmt.Fprint(buf, ` if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic("blas: index of c out of range") + } +`) + } + + return true +} + +func trans(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + switch n := shorten(binding.LowerCaseFirst(p.Name())); n { + case "t", "tA", "tB": + switch { + case strings.HasPrefix(d.Name, "cblas_ch"), strings.HasPrefix(d.Name, "cblas_zh"): + fmt.Fprintf(buf, ` if %[1]s != blas.NoTrans && %[1]s != blas.ConjTrans { + panic("blas: illegal transpose") + } +`, n) + case strings.HasPrefix(d.Name, "cblas_cs"), strings.HasPrefix(d.Name, "cblas_zs"): + fmt.Fprintf(buf, ` if %[1]s != blas.NoTrans && %[1]s != blas.Trans { + panic("blas: illegal transpose") + } +`, n) + default: + fmt.Fprintf(buf, ` if %[1]s != blas.NoTrans && %[1]s != blas.Trans && %[1]s != blas.ConjTrans { + panic("blas: illegal transpose") + } +`, n) + } + } + return false +} + +func uplo(buf *bytes.Buffer, _ binding.Declaration, p binding.Parameter) bool { + if p.Name() != "Uplo" { + return false + } + fmt.Fprint(buf, ` if ul != blas.Upper && ul != blas.Lower { + panic("blas: illegal triangle") + } +`) + return true +} + +func vectorShape(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + switch d.Name { + case "cblas_sgbmv", "cblas_dgbmv", "cblas_cgbmv", "cblas_zgbmv", + "cblas_sgemv", "cblas_dgemv", "cblas_cgemv", "cblas_zgemv", + "cblas_sscal", "cblas_dscal", "cblas_cscal", "cblas_zscal", "cblas_csscal", + "cblas_isamax", "cblas_idamax", "cblas_icamax", "cblas_izamax", + "cblas_snrm2", "cblas_dnrm2", "cblas_scnrm2", "cblas_dznrm2", + "cblas_sasum", "cblas_dasum", "cblas_scasum", "cblas_dzasum": + return true + } + + var hasN, hasM, hasIncX, hasIncY bool + for _, p := range d.Parameters() { + switch shorten(binding.LowerCaseFirst(p.Name())) { + case "n": + hasN = true + case "m": + hasM = true + case "incX": + hasIncX = true + case "incY": + hasIncY = true + } + } + if !hasN && !hasM { + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + var label string + if hasM { + label = "m" + } else { + label = "n" + } + if hasIncX { + fmt.Fprintf(buf, ` if (incX > 0 && (%[1]s-1)*incX >= len(x)) || (incX < 0 && (1-%[1]s)*incX >= len(x)) { + panic("blas: x index out of range") + } +`, label) + } + if hasIncY { + fmt.Fprint(buf, ` if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } +`) + } + return true +} + +func zeroInc(buf *bytes.Buffer, _ binding.Declaration, p binding.Parameter) bool { + switch n := binding.LowerCaseFirst(p.Name()); n { + case "incX": + fmt.Fprintf(buf, ` if incX == 0 { + panic("blas: zero x index increment") + } +`) + case "incY": + fmt.Fprintf(buf, ` if incY == 0 { + panic("blas: zero y index increment") + } +`) + return true + } + return false +} + +func othersShape(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + switch d.Name { + case "cblas_sgemm", "cblas_dgemm", "cblas_cgemm", "cblas_zgemm", + "cblas_ssyrk", "cblas_dsyrk", "cblas_csyrk", "cblas_zsyrk", + "cblas_ssyr2k", "cblas_dsyr2k", "cblas_csyr2k", "cblas_zsyr2k", + "cblas_cherk", "cblas_zherk", "cblas_cher2k", "cblas_zher2k": + return true + } + + has := make(map[string]bool) + for _, p := range d.Parameters() { + has[shorten(binding.LowerCaseFirst(p.Name()))] = true + } + if !has["a"] || has["s"] { + return true + } + + if d.CParameters[len(d.CParameters)-1] != p.Parameter { + return false // Come back later. + } + + switch { + case has["kL"] && has["kU"]: + fmt.Fprintf(buf, ` if lda*(m-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { + panic("blas: index of a out of range") + } +`) + case has["m"]: + fmt.Fprintf(buf, ` if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } +`) + case has["k"]: + fmt.Fprintf(buf, ` if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic("blas: index of a out of range") + } +`) + default: + fmt.Fprintf(buf, ` if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic("blas: index of a out of range") + } +`) + } + + return true +} + +const handwritten = `// Do not manually edit this file. It was created by the generate_blas.go from {{.}}. + +// Copyright ©2014 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgo + +/* +#cgo CFLAGS: -g -O2 +#include "{{.}}" +*/ +import "C" + +import ( + "unsafe" + + "github.com/gonum/blas" +) + +// Type check assertions: +var ( + _ blas.Float32 = Implementation{} + _ blas.Float64 = Implementation{} + _ blas.Complex64 = Implementation{} + _ blas.Complex128 = Implementation{} +) + +// Type order is used to specify the matrix storage format. We still interact with +// an API that allows client calls to specify order, so this is here to document that fact. +type order int + +const ( + rowMajor order = 101 + iota +) + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +type Implementation struct{} + +// Special cases... + +type srotmParams struct { + flag float32 + h [4]float32 +} + +type drotmParams struct { + flag float64 + h [4]float64 +} + +func (Implementation) Srotg(a float32, b float32) (c float32, s float32, r float32, z float32) { + C.cblas_srotg((*C.float)(&a), (*C.float)(&b), (*C.float)(&c), (*C.float)(&s)) + return c, s, a, b +} +func (Implementation) Srotmg(d1 float32, d2 float32, b1 float32, b2 float32) (p blas.SrotmParams, rd1 float32, rd2 float32, rb1 float32) { + var pi srotmParams + C.cblas_srotmg((*C.float)(&d1), (*C.float)(&d2), (*C.float)(&b1), C.float(b2), (*C.float)(unsafe.Pointer(&pi))) + return blas.SrotmParams{Flag: blas.Flag(pi.flag), H: pi.h}, d1, d2, b1 +} +func (Implementation) Srotm(n int, x []float32, incX int, y []float32, incY int, p blas.SrotmParams) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if p.Flag < blas.Identity || p.Flag > blas.Diagonal { + panic("blas: illegal blas.Flag value") + } + if n == 0 { + return + } + pi := srotmParams{ + flag: float32(p.Flag), + h: p.H, + } + C.cblas_srotm(C.int(n), (*C.float)(&x[0]), C.int(incX), (*C.float)(&y[0]), C.int(incY), (*C.float)(unsafe.Pointer(&pi))) +} +func (Implementation) Drotg(a float64, b float64) (c float64, s float64, r float64, z float64) { + C.cblas_drotg((*C.double)(&a), (*C.double)(&b), (*C.double)(&c), (*C.double)(&s)) + return c, s, a, b +} +func (Implementation) Drotmg(d1 float64, d2 float64, b1 float64, b2 float64) (p blas.DrotmParams, rd1 float64, rd2 float64, rb1 float64) { + var pi drotmParams + C.cblas_drotmg((*C.double)(&d1), (*C.double)(&d2), (*C.double)(&b1), C.double(b2), (*C.double)(unsafe.Pointer(&pi))) + return blas.DrotmParams{Flag: blas.Flag(pi.flag), H: pi.h}, d1, d2, b1 +} +func (Implementation) Drotm(n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if p.Flag < blas.Identity || p.Flag > blas.Diagonal { + panic("blas: illegal blas.Flag value") + } + if n == 0 { + return + } + pi := drotmParams{ + flag: float64(p.Flag), + h: p.H, + } + C.cblas_drotm(C.int(n), (*C.double)(&x[0]), C.int(incX), (*C.double)(&y[0]), C.int(incY), (*C.double)(unsafe.Pointer(&pi))) +} +func (Implementation) Cdotu(n int, x []complex64, incX int, y []complex64, incY int) (dotu complex64) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + C.cblas_cdotu_sub(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&dotu)) + return dotu +} +func (Implementation) Cdotc(n int, x []complex64, incX int, y []complex64, incY int) (dotc complex64) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + C.cblas_cdotc_sub(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&dotc)) + return dotc +} +func (Implementation) Zdotu(n int, x []complex128, incX int, y []complex128, incY int) (dotu complex128) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + C.cblas_zdotu_sub(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&dotu)) + return dotu +} +func (Implementation) Zdotc(n int, x []complex128, incX int, y []complex128, incY int) (dotc complex128) { + if n < 0 { + panic("blas: n < 0") + } + if incX == 0 { + panic("blas: zero x index increment") + } + if incY == 0 { + panic("blas: zero y index increment") + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic("blas: x index out of range") + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic("blas: y index out of range") + } + if n == 0 { + return 0 + } + C.cblas_zdotc_sub(C.int(n), unsafe.Pointer(&x[0]), C.int(incX), unsafe.Pointer(&y[0]), C.int(incY), unsafe.Pointer(&dotc)) + return dotc +} + +// Generated cases ... + +` diff --git a/blas/cgo/level1doubleBench_auto_test.go b/blas/cgo/level1doubleBench_auto_test.go new file mode 100644 index 00000000..db44b809 --- /dev/null +++ b/blas/cgo/level1doubleBench_auto_test.go @@ -0,0 +1,1685 @@ +// Code generated by "go run github.com/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go"; DO NOT EDIT. + +// Copyright 2014 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package cgo + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +const ( + posInc1 = 5 + posInc2 = 3 + negInc1 = -3 + negInc2 = -4 + SMALL_SLICE = 10 + MEDIUM_SLICE = 1000 + LARGE_SLICE = 100000 + HUGE_SLICE = 10000000 +) + +func randomSlice(l, idx int) []float64 { + if idx < 0 { + idx = -idx + } + s := make([]float64, l*idx) + for i := range s { + s[i] = rand.Float64() + } + return s +} + +func benchmarkDdot(b *testing.B, n int, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Ddot(n, x, incX, y, incY) + } +} + +func BenchmarkDdotSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDnrm2(b *testing.B, n int, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dnrm2(n, x, incX) + } +} + +func BenchmarkDnrm2SmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2SmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2MediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2MediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2LargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2LargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2HugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2HugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +/* ------------------ */ +func benchmarkDasum(b *testing.B, n int, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dasum(n, x, incX) + } +} + +func BenchmarkDasumSmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumSmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumMediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumMediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumLargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumLargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumHugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumHugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +/* ------------------ */ +func benchmarkIdamax(b *testing.B, n int, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Idamax(n, x, incX) + } +} + +func BenchmarkIdamaxSmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxSmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxMediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxMediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxLargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxLargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxHugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxHugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +/* ------------------ */ +func benchmarkDswap(b *testing.B, n int, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dswap(n, x, incX, y, incY) + } +} + +func BenchmarkDswapSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDcopy(b *testing.B, n int, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dcopy(n, x, incX, y, incY) + } +} + +func BenchmarkDcopySmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopySmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopySmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopySmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDaxpy(b *testing.B, n int, alpha float64, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Daxpy(n, alpha, x, incX, y, incY) + } +} + +func BenchmarkDaxpySmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpySmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpySmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpySmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDrot(b *testing.B, n int, x []float64, incX int, y []float64, incY int, c, s float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drot(n, x, incX, y, incY, c, s) + } +} + +func BenchmarkDrotSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +/* ------------------ */ +func benchmarkDrotmOffDia(b *testing.B, n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drotm(n, x, incX, y, incY, p) + } +} + +func BenchmarkDrotmOffDiaSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +/* ------------------ */ +func benchmarkDrotmDia(b *testing.B, n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drotm(n, x, incX, y, incY, p) + } +} + +func BenchmarkDrotmDiaSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +/* ------------------ */ +func benchmarkDrotmResc(b *testing.B, n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drotm(n, x, incX, y, incY, p) + } +} + +func BenchmarkDrotmRescSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +/* ------------------ */ +func benchmarkDscal(b *testing.B, n int, alpha float64, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dscal(n, alpha, x, incX) + } +} + +func BenchmarkDscalSmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalSmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalMediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalMediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalLargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalLargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalHugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalHugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +/* ------------------ */ diff --git a/blas/cgo/level1double_test.go b/blas/cgo/level1double_test.go new file mode 100644 index 00000000..b5f40cb8 --- /dev/null +++ b/blas/cgo/level1double_test.go @@ -0,0 +1,57 @@ +package cgo + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +var impl Implementation + +func TestDasum(t *testing.T) { + testblas.DasumTest(t, impl) +} + +func TestDaxpy(t *testing.T) { + testblas.DaxpyTest(t, impl) +} + +func TestDdot(t *testing.T) { + testblas.DdotTest(t, impl) +} + +func TestDnrm2(t *testing.T) { + testblas.Dnrm2Test(t, impl) +} + +func TestIdamax(t *testing.T) { + testblas.IdamaxTest(t, impl) +} + +func TestDswap(t *testing.T) { + testblas.DswapTest(t, impl) +} + +func TestDcopy(t *testing.T) { + testblas.DcopyTest(t, impl) +} + +func TestDrotg(t *testing.T) { + testblas.DrotgTest(t, impl) +} + +func TestDrotmg(t *testing.T) { + testblas.DrotmgTest(t, impl) +} + +func TestDrot(t *testing.T) { + testblas.DrotTest(t, impl) +} + +func TestDrotm(t *testing.T) { + testblas.DrotmTest(t, impl) +} + +func TestDscal(t *testing.T) { + testblas.DscalTest(t, impl) +} diff --git a/blas/cgo/level2double_test.go b/blas/cgo/level2double_test.go new file mode 100644 index 00000000..f3b66f83 --- /dev/null +++ b/blas/cgo/level2double_test.go @@ -0,0 +1,75 @@ +package cgo + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func TestDgemv(t *testing.T) { + testblas.DgemvTest(t, impl) +} + +func TestDger(t *testing.T) { + testblas.DgerTest(t, impl) +} + +func TestDtbmv(t *testing.T) { + testblas.DtbmvTest(t, impl) +} + +func TestDtxmv(t *testing.T) { + testblas.DtxmvTest(t, impl) +} + +func TestDgbmv(t *testing.T) { + testblas.DgbmvTest(t, impl) +} + +func TestDtbsv(t *testing.T) { + testblas.DtbsvTest(t, impl) +} + +func TestDsbmv(t *testing.T) { + testblas.DsbmvTest(t, impl) +} + +func TestDtrsv(t *testing.T) { + testblas.DtrsvTest(t, impl) +} + +func TestDsyr(t *testing.T) { + testblas.DsyrTest(t, impl) +} + +func TestDsymv(t *testing.T) { + testblas.DsymvTest(t, impl) +} + +func TestDtrmv(t *testing.T) { + testblas.DtrmvTest(t, impl) +} + +func TestDsyr2(t *testing.T) { + testblas.Dsyr2Test(t, impl) +} + +func TestDspr2(t *testing.T) { + testblas.Dspr2Test(t, impl) +} + +func TestDspr(t *testing.T) { + testblas.DsprTest(t, impl) +} + +func TestDspmv(t *testing.T) { + testblas.DspmvTest(t, impl) +} + +func TestDtpsv(t *testing.T) { + testblas.DtpsvTest(t, impl) +} + +func TestDtmpv(t *testing.T) { + testblas.DtpmvTest(t, impl) +} diff --git a/blas/cgo/level3double_test.go b/blas/cgo/level3double_test.go new file mode 100644 index 00000000..4c815f3c --- /dev/null +++ b/blas/cgo/level3double_test.go @@ -0,0 +1,31 @@ +package cgo + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func TestDgemm(t *testing.T) { + testblas.TestDgemm(t, impl) +} + +func TestDsymm(t *testing.T) { + testblas.DsymmTest(t, impl) +} + +func TestDtrsm(t *testing.T) { + testblas.DtrsmTest(t, impl) +} + +func TestDsyrk(t *testing.T) { + testblas.DsyrkTest(t, impl) +} + +func TestDsyr2k(t *testing.T) { + testblas.Dsyr2kTest(t, impl) +} + +func TestDtrmm(t *testing.T) { + testblas.DtrmmTest(t, impl) +} diff --git a/blas/native/bench_test.go b/blas/native/bench_test.go new file mode 100644 index 00000000..bcab67cc --- /dev/null +++ b/blas/native/bench_test.go @@ -0,0 +1,22 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/testblas" +) + +const ( + Sm = testblas.SmallMat + Med = testblas.MediumMat + Lg = testblas.LargeMat + Hg = testblas.HugeMat +) + +const ( + T = blas.Trans + NT = blas.NoTrans +) diff --git a/blas/native/dgemm.go b/blas/native/dgemm.go new file mode 100644 index 00000000..91fd7699 --- /dev/null +++ b/blas/native/dgemm.go @@ -0,0 +1,276 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "runtime" + "sync" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f64" +) + +// Dgemm computes +// C = beta * C + alpha * A * B, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +func (Implementation) Dgemm(tA, tB blas.Transpose, m, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + panic(badTranspose) + } + aTrans := tA == blas.Trans || tA == blas.ConjTrans + if aTrans { + checkMatrix64(k, m, a, lda) + } else { + checkMatrix64(m, k, a, lda) + } + bTrans := tB == blas.Trans || tB == blas.ConjTrans + if bTrans { + checkMatrix64(n, k, b, ldb) + } else { + checkMatrix64(k, n, b, ldb) + } + checkMatrix64(m, n, c, ldc) + + // scale c + if beta != 1 { + if beta == 0 { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + } + } + + dgemmParallel(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) +} + +func dgemmParallel(aTrans, bTrans bool, m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // dgemmParallel computes a parallel matrix multiplication by partitioning + // a and b into sub-blocks, and updating c with the multiplication of the sub-block + // In all cases, + // A = [ A_11 A_12 ... A_1j + // A_21 A_22 ... A_2j + // ... + // A_i1 A_i2 ... A_ij] + // + // and same for B. All of the submatrix sizes are blockSize×blockSize except + // at the edges. + // + // In all cases, there is one dimension for each matrix along which + // C must be updated sequentially. + // Cij = \sum_k Aik Bki, (A * B) + // Cij = \sum_k Aki Bkj, (A^T * B) + // Cij = \sum_k Aik Bjk, (A * B^T) + // Cij = \sum_k Aki Bjk, (A^T * B^T) + // + // This code computes one {i, j} block sequentially along the k dimension, + // and computes all of the {i, j} blocks concurrently. This + // partitioning allows Cij to be updated in-place without race-conditions. + // Instead of launching a goroutine for each possible concurrent computation, + // a number of worker goroutines are created and channels are used to pass + // available and completed cases. + // + // http://alexkr.com/docs/matrixmult.pdf is a good reference on matrix-matrix + // multiplies, though this code does not copy matrices to attempt to eliminate + // cache misses. + + maxKLen := k + parBlocks := blocks(m, blockSize) * blocks(n, blockSize) + if parBlocks < minParBlock { + // The matrix multiplication is small in the dimensions where it can be + // computed concurrently. Just do it in serial. + dgemmSerial(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + } + + nWorkers := runtime.GOMAXPROCS(0) + if parBlocks < nWorkers { + nWorkers = parBlocks + } + // There is a tradeoff between the workers having to wait for work + // and a large buffer making operations slow. + buf := buffMul * nWorkers + if buf > parBlocks { + buf = parBlocks + } + + sendChan := make(chan subMul, buf) + + // Launch workers. A worker receives an {i, j} submatrix of c, and computes + // A_ik B_ki (or the transposed version) storing the result in c_ij. When the + // channel is finally closed, it signals to the waitgroup that it has finished + // computing. + var wg sync.WaitGroup + for i := 0; i < nWorkers; i++ { + wg.Add(1) + go func() { + defer wg.Done() + // Make local copies of otherwise global variables to reduce shared memory. + // This has a noticable effect on benchmarks in some cases. + alpha := alpha + aTrans := aTrans + bTrans := bTrans + m := m + n := n + for sub := range sendChan { + i := sub.i + j := sub.j + leni := blockSize + if i+leni > m { + leni = m - i + } + lenj := blockSize + if j+lenj > n { + lenj = n - j + } + + cSub := sliceView64(c, ldc, i, j, leni, lenj) + + // Compute A_ik B_kj for all k + for k := 0; k < maxKLen; k += blockSize { + lenk := blockSize + if k+lenk > maxKLen { + lenk = maxKLen - k + } + var aSub, bSub []float64 + if aTrans { + aSub = sliceView64(a, lda, k, i, lenk, leni) + } else { + aSub = sliceView64(a, lda, i, k, leni, lenk) + } + if bTrans { + bSub = sliceView64(b, ldb, j, k, lenj, lenk) + } else { + bSub = sliceView64(b, ldb, k, j, lenk, lenj) + } + dgemmSerial(aTrans, bTrans, leni, lenj, lenk, aSub, lda, bSub, ldb, cSub, ldc, alpha) + } + } + }() + } + + // Send out all of the {i, j} subblocks for computation. + for i := 0; i < m; i += blockSize { + for j := 0; j < n; j += blockSize { + sendChan <- subMul{ + i: i, + j: j, + } + } + } + close(sendChan) + wg.Wait() +} + +// dgemmSerial is serial matrix multiply +func dgemmSerial(aTrans, bTrans bool, m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + switch { + case !aTrans && !bTrans: + dgemmSerialNotNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case aTrans && !bTrans: + dgemmSerialTransNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case !aTrans && bTrans: + dgemmSerialNotTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case aTrans && bTrans: + dgemmSerialTransTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + default: + panic("unreachable") + } +} + +// dgemmSerial where neither a nor b are transposed +func dgemmSerialNotNot(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for l, v := range a[i*lda : i*lda+k] { + tmp := alpha * v + if tmp != 0 { + f64.AxpyUnitaryTo(ctmp, tmp, b[l*ldb:l*ldb+n], ctmp) + } + } + } +} + +// dgemmSerial where neither a is transposed and b is not +func dgemmSerialTransNot(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for l := 0; l < k; l++ { + btmp := b[l*ldb : l*ldb+n] + for i, v := range a[l*lda : l*lda+m] { + tmp := alpha * v + if tmp != 0 { + ctmp := c[i*ldc : i*ldc+n] + f64.AxpyUnitaryTo(ctmp, tmp, btmp, ctmp) + } + } + } +} + +// dgemmSerial where neither a is not transposed and b is +func dgemmSerialNotTrans(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for i := 0; i < m; i++ { + atmp := a[i*lda : i*lda+k] + ctmp := c[i*ldc : i*ldc+n] + for j := 0; j < n; j++ { + ctmp[j] += alpha * f64.DotUnitary(atmp, b[j*ldb:j*ldb+k]) + } + } +} + +// dgemmSerial where both are transposed +func dgemmSerialTransTrans(m, n, k int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, alpha float64) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for l := 0; l < k; l++ { + for i, v := range a[l*lda : l*lda+m] { + tmp := alpha * v + if tmp != 0 { + ctmp := c[i*ldc : i*ldc+n] + f64.AxpyInc(tmp, b[l:], ctmp, uintptr(n), uintptr(ldb), 1, 0, 0) + } + } + } +} + +func sliceView64(a []float64, lda, i, j, r, c int) []float64 { + return a[i*lda+j : (i+r-1)*lda+j+c] +} + +func checkMatrix64(m, n int, a []float64, lda int) { + if m < 0 { + panic("blas: rows < 0") + } + if n < 0 { + panic("blas: cols < 0") + } + if lda < n { + panic("blas: illegal stride") + } + if len(a) < (m-1)*lda+n { + panic("blas: insufficient matrix slice length") + } +} diff --git a/blas/native/dgemmbench_test.go b/blas/native/dgemmbench_test.go new file mode 100644 index 00000000..4717ecc5 --- /dev/null +++ b/blas/native/dgemmbench_test.go @@ -0,0 +1,51 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDgemmSmSmSm(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Sm, Sm, Sm, NT, NT) +} + +func BenchmarkDgemmMedMedMed(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, NT, NT) +} + +func BenchmarkDgemmMedLgMed(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Lg, Med, NT, NT) +} + +func BenchmarkDgemmLgLgLg(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Lg, Lg, Lg, NT, NT) +} + +func BenchmarkDgemmLgSmLg(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Lg, Sm, Lg, NT, NT) +} + +func BenchmarkDgemmLgLgSm(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Lg, Lg, Sm, NT, NT) +} + +func BenchmarkDgemmHgHgSm(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Hg, Hg, Sm, NT, NT) +} + +func BenchmarkDgemmMedMedMedTNT(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, T, NT) +} + +func BenchmarkDgemmMedMedMedNTT(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, NT, T) +} + +func BenchmarkDgemmMedMedMedTT(b *testing.B) { + testblas.DgemmBenchmark(b, impl, Med, Med, Med, T, T) +} diff --git a/blas/native/dgemvbench_test.go b/blas/native/dgemvbench_test.go new file mode 100644 index 00000000..8b6690c6 --- /dev/null +++ b/blas/native/dgemvbench_test.go @@ -0,0 +1,91 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDgemvSmSmNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Sm, 1, 1) +} + +func BenchmarkDgemvSmSmNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Sm, 2, 3) +} + +func BenchmarkDgemvSmSmTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Sm, 1, 1) +} + +func BenchmarkDgemvSmSmTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Sm, 2, 3) +} + +func BenchmarkDgemvMedMedNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Med, Med, 1, 1) +} + +func BenchmarkDgemvMedMedNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Med, Med, 2, 3) +} + +func BenchmarkDgemvMedMedTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Med, Med, 1, 1) +} + +func BenchmarkDgemvMedMedTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Med, Med, 2, 3) +} + +func BenchmarkDgemvLgLgNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Lg, 1, 1) +} + +func BenchmarkDgemvLgLgNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Lg, 2, 3) +} + +func BenchmarkDgemvLgLgTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Lg, 1, 1) +} + +func BenchmarkDgemvLgLgTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Lg, 2, 3) +} + +func BenchmarkDgemvLgSmNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Sm, 1, 1) +} + +func BenchmarkDgemvLgSmNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Lg, Sm, 2, 3) +} + +func BenchmarkDgemvLgSmTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Sm, 1, 1) +} + +func BenchmarkDgemvLgSmTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Lg, Sm, 2, 3) +} + +func BenchmarkDgemvSmLgNoTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Lg, 1, 1) +} + +func BenchmarkDgemvSmLgNoTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, NT, Sm, Lg, 2, 3) +} + +func BenchmarkDgemvSmLgTransInc1(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Lg, 1, 1) +} + +func BenchmarkDgemvSmLgTransIncN(b *testing.B) { + testblas.DgemvBenchmark(b, impl, T, Sm, Lg, 2, 3) +} diff --git a/blas/native/dgerbench_test.go b/blas/native/dgerbench_test.go new file mode 100644 index 00000000..81aa1147 --- /dev/null +++ b/blas/native/dgerbench_test.go @@ -0,0 +1,51 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDgerSmSmInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Sm, 1, 1) +} + +func BenchmarkDgerSmSmIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Sm, 2, 3) +} + +func BenchmarkDgerMedMedInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Med, Med, 1, 1) +} + +func BenchmarkDgerMedMedIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Med, Med, 2, 3) +} + +func BenchmarkDgerLgLgInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Lg, 1, 1) +} + +func BenchmarkDgerLgLgIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Lg, 2, 3) +} + +func BenchmarkDgerLgSmInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Sm, 1, 1) +} + +func BenchmarkDgerLgSmIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Lg, Sm, 2, 3) +} + +func BenchmarkDgerSmLgInc1(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Lg, 1, 1) +} + +func BenchmarkDgerSmLgIncN(b *testing.B) { + testblas.DgerBenchmark(b, impl, Sm, Lg, 2, 3) +} diff --git a/blas/native/doc.go b/blas/native/doc.go new file mode 100644 index 00000000..cb63fe77 --- /dev/null +++ b/blas/native/doc.go @@ -0,0 +1,88 @@ +// Copyright ©2015 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Ensure changes made to blas/native are reflected in blas/cgo where relevant. + +/* +Package native is a Go implementation of the BLAS API. This implementation +panics when the input arguments are invalid as per the standard, for example +if a vector increment is zero. Please note that the treatment of NaN values +is not specified, and differs among the BLAS implementations. +github.com/gonum/blas/blas64 provides helpful wrapper functions to the BLAS +interface. The rest of this text describes the layout of the data for the input types. + +Please note that in the function documentation, x[i] refers to the i^th element +of the vector, which will be different from the i^th element of the slice if +incX != 1. + +See http://www.netlib.org/lapack/explore-html/d4/de1/_l_i_c_e_n_s_e_source.html +for more license information. + +Vector arguments are effectively strided slices. They have two input arguments, +a number of elements, n, and an increment, incX. The increment specifies the +distance between elements of the vector. The actual Go slice may be longer +than necessary. +The increment may be positive or negative, except in functions with only +a single vector argument where the increment may only be positive. If the increment +is negative, s[0] is the last element in the slice. Note that this is not the same +as counting backward from the end of the slice, as len(s) may be longer than +necessary. So, for example, if n = 5 and incX = 3, the elements of s are + [0 * * 1 * * 2 * * 3 * * 4 * * * ...] +where ∗ elements are never accessed. If incX = -3, the same elements are +accessed, just in reverse order (4, 3, 2, 1, 0). + +Dense matrices are specified by a number of rows, a number of columns, and a stride. +The stride specifies the number of entries in the slice between the first element +of successive rows. The stride must be at least as large as the number of columns +but may be longer. + [a00 ... a0n a0* ... a1stride-1 a21 ... amn am* ... amstride-1] +Thus, dense[i*ld + j] refers to the {i, j}th element of the matrix. + +Symmetric and triangular matrices (non-packed) are stored identically to Dense, +except that only elements in one triangle of the matrix are accessed. + +Packed symmetric and packed triangular matrices are laid out with the entries +condensed such that all of the unreferenced elements are removed. So, the upper triangular +matrix + [ + 1 2 3 + 0 4 5 + 0 0 6 + ] +and the lower-triangular matrix + [ + 1 0 0 + 2 3 0 + 4 5 6 + ] +will both be compacted as [1 2 3 4 5 6]. The (i, j) element of the original +dense matrix can be found at element i*n - (i-1)*i/2 + j for upper triangular, +and at element i * (i+1) /2 + j for lower triangular. + +Banded matrices are laid out in a compact format, constructed by removing the +zeros in the rows and aligning the diagonals. For example, the matrix + [ + 1 2 3 0 0 0 + 4 5 6 7 0 0 + 0 8 9 10 11 0 + 0 0 12 13 14 15 + 0 0 0 16 17 18 + 0 0 0 0 19 20 + ] + +implicitly becomes (∗ entries are never accessed) + [ + * 1 2 3 + 4 5 6 7 + 8 9 10 11 + 12 13 14 15 + 16 17 18 * + 19 20 * * + ] +which is given to the BLAS routine as [∗ 1 2 3 4 ...]. + +See http://www.crest.iu.edu/research/mtl/reference/html/banded.html +for more information +*/ +package native diff --git a/blas/native/dtrmvbench_test.go b/blas/native/dtrmvbench_test.go new file mode 100644 index 00000000..c657211d --- /dev/null +++ b/blas/native/dtrmvbench_test.go @@ -0,0 +1,54 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package native + +import ( + "strconv" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/testblas" +) + +func BenchmarkDtrmv(b *testing.B) { + for _, n := range []int{testblas.MediumMat, testblas.LargeMat} { + for _, incX := range []int{1, 5} { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, unit := range []blas.Diag{blas.NonUnit, blas.Unit} { + var str string + if n == testblas.MediumMat { + str += "Med" + } else if n == testblas.LargeMat { + str += "Large" + } + str += "_Inc" + strconv.Itoa(incX) + if uplo == blas.Upper { + str += "_UP" + } else { + str += "_LO" + } + if trans == blas.NoTrans { + str += "_NT" + } else { + str += "_TR" + } + if unit == blas.NonUnit { + str += "_NU" + } else { + str += "_UN" + } + lda := n + b.Run(str, func(b *testing.B) { + testblas.DtrmvBenchmark(b, Implementation{}, n, lda, incX, uplo, trans, unit) + }) + } + } + } + } + } +} diff --git a/blas/native/general_double.go b/blas/native/general_double.go new file mode 100644 index 00000000..0fa6cb74 --- /dev/null +++ b/blas/native/general_double.go @@ -0,0 +1,155 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "errors" + "fmt" + "math" +) + +func newGeneral64(r, c int) general64 { + return general64{ + data: make([]float64, r*c), + rows: r, + cols: c, + stride: c, + } +} + +type general64 struct { + data []float64 + rows, cols int + stride int +} + +// adds element-wise into receiver. rows and columns must match +func (g general64) add(h general64) { + if debug { + if g.rows != h.rows { + panic("blas: row size mismatch") + } + if g.cols != h.cols { + panic("blas: col size mismatch") + } + } + for i := 0; i < g.rows; i++ { + gtmp := g.data[i*g.stride : i*g.stride+g.cols] + for j, v := range h.data[i*h.stride : i*h.stride+h.cols] { + gtmp[j] += v + } + } +} + +// at returns the value at the ith row and jth column. For speed reasons, the +// rows and columns are not bounds checked. +func (g general64) at(i, j int) float64 { + if debug { + if i < 0 || i >= g.rows { + panic("blas: row out of bounds") + } + if j < 0 || j >= g.cols { + panic("blas: col out of bounds") + } + } + return g.data[i*g.stride+j] +} + +func (g general64) check(c byte) error { + if g.rows < 0 { + return errors.New("blas: rows < 0") + } + if g.cols < 0 { + return errors.New("blas: cols < 0") + } + if g.stride < 1 { + return errors.New("blas: stride < 1") + } + if g.stride < g.cols { + return errors.New("blas: illegal stride") + } + if (g.rows-1)*g.stride+g.cols > len(g.data) { + return fmt.Errorf("blas: index of %c out of range", c) + } + return nil +} + +func (g general64) clone() general64 { + data := make([]float64, len(g.data)) + copy(data, g.data) + return general64{ + data: data, + rows: g.rows, + cols: g.cols, + stride: g.stride, + } +} + +// assumes they are the same size +func (g general64) copy(h general64) { + if debug { + if g.rows != h.rows { + panic("blas: row mismatch") + } + if g.cols != h.cols { + panic("blas: col mismatch") + } + } + for k := 0; k < g.rows; k++ { + copy(g.data[k*g.stride:(k+1)*g.stride], h.data[k*h.stride:(k+1)*h.stride]) + } +} + +func (g general64) equal(a general64) bool { + if g.rows != a.rows || g.cols != a.cols || g.stride != a.stride { + return false + } + for i, v := range g.data { + if a.data[i] != v { + return false + } + } + return true +} + +/* +// print is to aid debugging. Commented out to avoid fmt import +func (g general64) print() { + fmt.Println("r = ", g.rows, "c = ", g.cols, "stride: ", g.stride) + for i := 0; i < g.rows; i++ { + fmt.Println(g.data[i*g.stride : (i+1)*g.stride]) + } + +} +*/ + +func (g general64) view(i, j, r, c int) general64 { + if debug { + if i < 0 || i+r > g.rows { + panic("blas: row out of bounds") + } + if j < 0 || j+c > g.cols { + panic("blas: col out of bounds") + } + } + return general64{ + data: g.data[i*g.stride+j : (i+r-1)*g.stride+j+c], + rows: r, + cols: c, + stride: g.stride, + } +} + +func (g general64) equalWithinAbs(a general64, tol float64) bool { + if g.rows != a.rows || g.cols != a.cols || g.stride != a.stride { + return false + } + for i, v := range g.data { + if math.Abs(a.data[i]-v) > tol { + return false + } + } + return true +} diff --git a/blas/native/general_single.go b/blas/native/general_single.go new file mode 100644 index 00000000..d3f6582e --- /dev/null +++ b/blas/native/general_single.go @@ -0,0 +1,157 @@ +// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT. + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "errors" + "fmt" + math "gonum.org/v1/gonum/blas/native/internal/math32" +) + +func newGeneral32(r, c int) general32 { + return general32{ + data: make([]float32, r*c), + rows: r, + cols: c, + stride: c, + } +} + +type general32 struct { + data []float32 + rows, cols int + stride int +} + +// adds element-wise into receiver. rows and columns must match +func (g general32) add(h general32) { + if debug { + if g.rows != h.rows { + panic("blas: row size mismatch") + } + if g.cols != h.cols { + panic("blas: col size mismatch") + } + } + for i := 0; i < g.rows; i++ { + gtmp := g.data[i*g.stride : i*g.stride+g.cols] + for j, v := range h.data[i*h.stride : i*h.stride+h.cols] { + gtmp[j] += v + } + } +} + +// at returns the value at the ith row and jth column. For speed reasons, the +// rows and columns are not bounds checked. +func (g general32) at(i, j int) float32 { + if debug { + if i < 0 || i >= g.rows { + panic("blas: row out of bounds") + } + if j < 0 || j >= g.cols { + panic("blas: col out of bounds") + } + } + return g.data[i*g.stride+j] +} + +func (g general32) check(c byte) error { + if g.rows < 0 { + return errors.New("blas: rows < 0") + } + if g.cols < 0 { + return errors.New("blas: cols < 0") + } + if g.stride < 1 { + return errors.New("blas: stride < 1") + } + if g.stride < g.cols { + return errors.New("blas: illegal stride") + } + if (g.rows-1)*g.stride+g.cols > len(g.data) { + return fmt.Errorf("blas: index of %c out of range", c) + } + return nil +} + +func (g general32) clone() general32 { + data := make([]float32, len(g.data)) + copy(data, g.data) + return general32{ + data: data, + rows: g.rows, + cols: g.cols, + stride: g.stride, + } +} + +// assumes they are the same size +func (g general32) copy(h general32) { + if debug { + if g.rows != h.rows { + panic("blas: row mismatch") + } + if g.cols != h.cols { + panic("blas: col mismatch") + } + } + for k := 0; k < g.rows; k++ { + copy(g.data[k*g.stride:(k+1)*g.stride], h.data[k*h.stride:(k+1)*h.stride]) + } +} + +func (g general32) equal(a general32) bool { + if g.rows != a.rows || g.cols != a.cols || g.stride != a.stride { + return false + } + for i, v := range g.data { + if a.data[i] != v { + return false + } + } + return true +} + +/* +// print is to aid debugging. Commented out to avoid fmt import +func (g general32) print() { + fmt.Println("r = ", g.rows, "c = ", g.cols, "stride: ", g.stride) + for i := 0; i < g.rows; i++ { + fmt.Println(g.data[i*g.stride : (i+1)*g.stride]) + } + +} +*/ + +func (g general32) view(i, j, r, c int) general32 { + if debug { + if i < 0 || i+r > g.rows { + panic("blas: row out of bounds") + } + if j < 0 || j+c > g.cols { + panic("blas: col out of bounds") + } + } + return general32{ + data: g.data[i*g.stride+j : (i+r-1)*g.stride+j+c], + rows: r, + cols: c, + stride: g.stride, + } +} + +func (g general32) equalWithinAbs(a general32, tol float32) bool { + if g.rows != a.rows || g.cols != a.cols || g.stride != a.stride { + return false + } + for i, v := range g.data { + if math.Abs(a.data[i]-v) > tol { + return false + } + } + return true +} diff --git a/blas/native/internal/math32/math.go b/blas/native/internal/math32/math.go new file mode 100644 index 00000000..b33401b9 --- /dev/null +++ b/blas/native/internal/math32/math.go @@ -0,0 +1,113 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package math32 provides float32 versions of standard library math package +// routines used by gonum/blas/native. +package math32 + +import ( + "math" +) + +const ( + unan = 0x7fc00000 + uinf = 0x7f800000 + uneginf = 0xff800000 + mask = 0x7f8 >> 3 + shift = 32 - 8 - 1 + bias = 127 +) + +// Abs returns the absolute value of x. +// +// Special cases are: +// Abs(±Inf) = +Inf +// Abs(NaN) = NaN +func Abs(x float32) float32 { + switch { + case x < 0: + return -x + case x == 0: + return 0 // return correctly abs(-0) + } + return x +} + +// Copysign returns a value with the magnitude +// of x and the sign of y. +func Copysign(x, y float32) float32 { + const sign = 1 << 31 + return math.Float32frombits(math.Float32bits(x)&^sign | math.Float32bits(y)&sign) +} + +// Hypot returns Sqrt(p*p + q*q), taking care to avoid +// unnecessary overflow and underflow. +// +// Special cases are: +// Hypot(±Inf, q) = +Inf +// Hypot(p, ±Inf) = +Inf +// Hypot(NaN, q) = NaN +// Hypot(p, NaN) = NaN +func Hypot(p, q float32) float32 { + // special cases + switch { + case IsInf(p, 0) || IsInf(q, 0): + return Inf(1) + case IsNaN(p) || IsNaN(q): + return NaN() + } + if p < 0 { + p = -p + } + if q < 0 { + q = -q + } + if p < q { + p, q = q, p + } + if p == 0 { + return 0 + } + q = q / p + return p * Sqrt(1+q*q) +} + +// Inf returns positive infinity if sign >= 0, negative infinity if sign < 0. +func Inf(sign int) float32 { + var v uint32 + if sign >= 0 { + v = uinf + } else { + v = uneginf + } + return math.Float32frombits(v) +} + +// IsInf reports whether f is an infinity, according to sign. +// If sign > 0, IsInf reports whether f is positive infinity. +// If sign < 0, IsInf reports whether f is negative infinity. +// If sign == 0, IsInf reports whether f is either infinity. +func IsInf(f float32, sign int) bool { + // Test for infinity by comparing against maximum float. + // To avoid the floating-point hardware, could use: + // x := math.Float32bits(f); + // return sign >= 0 && x == uinf || sign <= 0 && x == uneginf; + return sign >= 0 && f > math.MaxFloat32 || sign <= 0 && f < -math.MaxFloat32 +} + +// IsNaN reports whether f is an IEEE 754 ``not-a-number'' value. +func IsNaN(f float32) (is bool) { + // IEEE 754 says that only NaNs satisfy f != f. + // To avoid the floating-point hardware, could use: + // x := math.Float32bits(f); + // return uint32(x>>shift)&mask == mask && x != uinf && x != uneginf + return f != f +} + +// NaN returns an IEEE 754 ``not-a-number'' value. +func NaN() float32 { return math.Float32frombits(unan) } diff --git a/blas/native/internal/math32/math_test.go b/blas/native/internal/math32/math_test.go new file mode 100644 index 00000000..2a20bb5c --- /dev/null +++ b/blas/native/internal/math32/math_test.go @@ -0,0 +1,226 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package math32 + +import ( + "math" + "testing" + "testing/quick" + + "gonum.org/v1/gonum/floats" +) + +const tol = 1e-7 + +func TestAbs(t *testing.T) { + f := func(x float32) bool { + y := Abs(x) + return y == float32(math.Abs(float64(x))) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestCopySign(t *testing.T) { + f := func(x struct{ X, Y float32 }) bool { + y := Copysign(x.X, x.Y) + return y == float32(math.Copysign(float64(x.X), float64(x.Y))) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestHypot(t *testing.T) { + f := func(x struct{ X, Y float32 }) bool { + y := Hypot(x.X, x.Y) + if math.Hypot(float64(x.X), float64(x.Y)) > math.MaxFloat32 { + return true + } + return floats.EqualWithinRel(float64(y), math.Hypot(float64(x.X), float64(x.Y)), tol) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestInf(t *testing.T) { + if float64(Inf(1)) != math.Inf(1) || float64(Inf(-1)) != math.Inf(-1) { + t.Error("float32(inf) not infinite") + } +} + +func TestIsInf(t *testing.T) { + posInf := float32(math.Inf(1)) + negInf := float32(math.Inf(-1)) + if !IsInf(posInf, 0) || !IsInf(negInf, 0) || !IsInf(posInf, 1) || !IsInf(negInf, -1) || IsInf(posInf, -1) || IsInf(negInf, 1) { + t.Error("unexpected isInf value") + } + f := func(x struct { + F float32 + Sign int + }) bool { + y := IsInf(x.F, x.Sign) + return y == math.IsInf(float64(x.F), x.Sign) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestIsNaN(t *testing.T) { + f := func(x float32) bool { + y := IsNaN(x) + return y == math.IsNaN(float64(x)) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +func TestNaN(t *testing.T) { + if !math.IsNaN(float64(NaN())) { + t.Errorf("float32(nan) is a number: %f", NaN()) + } +} + +func TestSqrt(t *testing.T) { + f := func(x float32) bool { + y := Sqrt(x) + if IsNaN(y) && IsNaN(sqrt(x)) { + return true + } + return floats.EqualWithinRel(float64(y), float64(sqrt(x)), tol) + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} + +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The original C code and the long comment below are +// from FreeBSD's /usr/src/lib/msun/src/e_sqrt.c and +// came with this notice. The go code is a simplified +// version of the original C. +// +// ==================================================== +// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +// +// Developed at SunPro, a Sun Microsystems, Inc. business. +// Permission to use, copy, modify, and distribute this +// software is freely granted, provided that this notice +// is preserved. +// ==================================================== +// +// __ieee754_sqrt(x) +// Return correctly rounded sqrt. +// ----------------------------------------- +// | Use the hardware sqrt if you have one | +// ----------------------------------------- +// Method: +// Bit by bit method using integer arithmetic. (Slow, but portable) +// 1. Normalization +// Scale x to y in [1,4) with even powers of 2: +// find an integer k such that 1 <= (y=x*2**(2k)) < 4, then +// sqrt(x) = 2**k * sqrt(y) +// 2. Bit by bit computation +// Let q = sqrt(y) truncated to i bit after binary point (q = 1), +// i 0 +// i+1 2 +// s = 2*q , and y = 2 * ( y - q ). (1) +// i i i i +// +// To compute q from q , one checks whether +// i+1 i +// +// -(i+1) 2 +// (q + 2 ) <= y. (2) +// i +// -(i+1) +// If (2) is false, then q = q ; otherwise q = q + 2 . +// i+1 i i+1 i +// +// With some algebraic manipulation, it is not difficult to see +// that (2) is equivalent to +// -(i+1) +// s + 2 <= y (3) +// i i +// +// The advantage of (3) is that s and y can be computed by +// i i +// the following recurrence formula: +// if (3) is false +// +// s = s , y = y ; (4) +// i+1 i i+1 i +// +// otherwise, +// -i -(i+1) +// s = s + 2 , y = y - s - 2 (5) +// i+1 i i+1 i i +// +// One may easily use induction to prove (4) and (5). +// Note. Since the left hand side of (3) contain only i+2 bits, +// it does not necessary to do a full (53-bit) comparison +// in (3). +// 3. Final rounding +// After generating the 53 bits result, we compute one more bit. +// Together with the remainder, we can decide whether the +// result is exact, bigger than 1/2ulp, or less than 1/2ulp +// (it will never equal to 1/2ulp). +// The rounding mode can be detected by checking whether +// huge + tiny is equal to huge, and whether huge - tiny is +// equal to huge for some floating point number "huge" and "tiny". +// +func sqrt(x float32) float32 { + // special cases + switch { + case x == 0 || IsNaN(x) || IsInf(x, 1): + return x + case x < 0: + return NaN() + } + ix := math.Float32bits(x) + // normalize x + exp := int((ix >> shift) & mask) + if exp == 0 { // subnormal x + for ix&1<>= 1 // exp = exp/2, exponent of square root + // generate sqrt(x) bit by bit + ix <<= 1 + var q, s uint32 // q = sqrt(x) + r := uint32(1 << (shift + 1)) // r = moving bit from MSB to LSB + for r != 0 { + t := s + r + if t <= ix { + s = t + r + ix -= t + q += r + } + ix <<= 1 + r >>= 1 + } + // final rounding + if ix != 0 { // remainder, result not exact + q += q & 1 // round according to extra bit + } + ix = q>>1 + uint32(exp-1+bias)< 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if n < 2 { + if n == 1 { + return math.Abs(x[0]) + } + if n == 0 { + return 0 + } + if n < 1 { + panic(negativeN) + } + } + var ( + scale float64 = 0 + sumSquares float64 = 1 + ) + if incX == 1 { + x = x[:n] + for _, v := range x { + if v == 0 { + continue + } + absxi := math.Abs(v) + if math.IsNaN(absxi) { + return math.NaN() + } + if scale < absxi { + sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumSquares = sumSquares + (absxi/scale)*(absxi/scale) + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(sumSquares) + } + for ix := 0; ix < n*incX; ix += incX { + val := x[ix] + if val == 0 { + continue + } + absxi := math.Abs(val) + if math.IsNaN(absxi) { + return math.NaN() + } + if scale < absxi { + sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumSquares = sumSquares + (absxi/scale)*(absxi/scale) + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(sumSquares) +} + +// Dasum computes the sum of the absolute values of the elements of x. +// \sum_i |x[i]| +// Dasum returns 0 if incX is negative. +func (Implementation) Dasum(n int, x []float64, incX int) float64 { + var sum float64 + if n < 0 { + panic(negativeN) + } + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if incX == 1 { + x = x[:n] + for _, v := range x { + sum += math.Abs(v) + } + return sum + } + for i := 0; i < n; i++ { + sum += math.Abs(x[i*incX]) + } + return sum +} + +// Idamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Idamax returns -1 if n == 0. +func (Implementation) Idamax(n int, x []float64, incX int) int { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return -1 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if n < 2 { + if n == 1 { + return 0 + } + if n == 0 { + return -1 // Netlib returns invalid index when n == 0 + } + if n < 1 { + panic(negativeN) + } + } + idx := 0 + max := math.Abs(x[0]) + if incX == 1 { + for i, v := range x[:n] { + absV := math.Abs(v) + if absV > max { + max = absV + idx = i + } + } + return idx + } + ix := incX + for i := 1; i < n; i++ { + v := x[ix] + absV := math.Abs(v) + if absV > max { + max = absV + idx = i + } + ix += incX + } + return idx +} + +// Dswap exchanges the elements of two vectors. +// x[i], y[i] = y[i], x[i] for all i +func (Implementation) Dswap(n int, x []float64, incX int, y []float64, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, v := range x { + x[i], y[i] = y[i], v + } + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + x[ix], y[iy] = y[iy], x[ix] + ix += incX + iy += incY + } +} + +// Dcopy copies the elements of x into the elements of y. +// y[i] = x[i] for all i +func (Implementation) Dcopy(n int, x []float64, incX int, y []float64, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + copy(y[:n], x[:n]) + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + y[iy] = x[ix] + ix += incX + iy += incY + } +} + +// Daxpy adds alpha times x to y +// y[i] += alpha * x[i] for all i +func (Implementation) Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if alpha == 0 { + return + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + f64.AxpyUnitaryTo(y, alpha, x[:n], y) + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + f64.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Drotg computes the plane rotation +// _ _ _ _ _ _ +// | c s | | a | | r | +// | -s c | * | b | = | 0 | +// ‾ ‾ ‾ ‾ ‾ ‾ +// where +// r = ±√(a^2 + b^2) +// c = a/r, the cosine of the plane rotation +// s = b/r, the sine of the plane rotation +// +// NOTE: There is a discrepancy between the refence implementation and the BLAS +// technical manual regarding the sign for r when a or b are zero. +// Drotg agrees with the definition in the manual and other +// common BLAS implementations. +func (Implementation) Drotg(a, b float64) (c, s, r, z float64) { + if b == 0 && a == 0 { + return 1, 0, a, 0 + } + absA := math.Abs(a) + absB := math.Abs(b) + aGTb := absA > absB + r = math.Hypot(a, b) + if aGTb { + r = math.Copysign(r, a) + } else { + r = math.Copysign(r, b) + } + c = a / r + s = b / r + if aGTb { + z = s + } else if c != 0 { // r == 0 case handled above + z = 1 / c + } else { + z = 1 + } + return +} + +// Drotmg computes the modified Givens rotation. See +// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html +// for more details. +func (Implementation) Drotmg(d1, d2, x1, y1 float64) (p blas.DrotmParams, rd1, rd2, rx1 float64) { + var p1, p2, q1, q2, u float64 + + const ( + gam = 4096.0 + gamsq = 16777216.0 + rgamsq = 5.9604645e-8 + ) + + if d1 < 0 { + p.Flag = blas.Rescaling + return + } + + p2 = d2 * y1 + if p2 == 0 { + p.Flag = blas.Identity + rd1 = d1 + rd2 = d2 + rx1 = x1 + return + } + p1 = d1 * x1 + q2 = p2 * y1 + q1 = p1 * x1 + + absQ1 := math.Abs(q1) + absQ2 := math.Abs(q2) + + if absQ1 < absQ2 && q2 < 0 { + p.Flag = blas.Rescaling + return + } + + if d1 == 0 { + p.Flag = blas.Diagonal + p.H[0] = p1 / p2 + p.H[3] = x1 / y1 + u = 1 + p.H[0]*p.H[3] + rd1, rd2 = d2/u, d1/u + rx1 = y1 / u + return + } + + // Now we know that d1 != 0, and d2 != 0. If d2 == 0, it would be caught + // when p2 == 0, and if d1 == 0, then it is caught above + + if absQ1 > absQ2 { + p.H[1] = -y1 / x1 + p.H[2] = p2 / p1 + u = 1 - p.H[2]*p.H[1] + rd1 = d1 + rd2 = d2 + rx1 = x1 + p.Flag = blas.OffDiagonal + // u must be greater than zero because |q1| > |q2|, so check from netlib + // is unnecessary + // This is left in for ease of comparison with complex routines + //if u > 0 { + rd1 /= u + rd2 /= u + rx1 *= u + //} + } else { + p.Flag = blas.Diagonal + p.H[0] = p1 / p2 + p.H[3] = x1 / y1 + u = 1 + p.H[0]*p.H[3] + rd1 = d2 / u + rd2 = d1 / u + rx1 = y1 * u + } + + for rd1 <= rgamsq || rd1 >= gamsq { + if p.Flag == blas.OffDiagonal { + p.H[0] = 1 + p.H[3] = 1 + p.Flag = blas.Rescaling + } else if p.Flag == blas.Diagonal { + p.H[1] = -1 + p.H[2] = 1 + p.Flag = blas.Rescaling + } + if rd1 <= rgamsq { + rd1 *= gam * gam + rx1 /= gam + p.H[0] /= gam + p.H[2] /= gam + } else { + rd1 /= gam * gam + rx1 *= gam + p.H[0] *= gam + p.H[2] *= gam + } + } + + for math.Abs(rd2) <= rgamsq || math.Abs(rd2) >= gamsq { + if p.Flag == blas.OffDiagonal { + p.H[0] = 1 + p.H[3] = 1 + p.Flag = blas.Rescaling + } else if p.Flag == blas.Diagonal { + p.H[1] = -1 + p.H[2] = 1 + p.Flag = blas.Rescaling + } + if math.Abs(rd2) <= rgamsq { + rd2 *= gam * gam + p.H[1] /= gam + p.H[3] /= gam + } else { + rd2 /= gam * gam + p.H[1] *= gam + p.H[3] *= gam + } + } + return +} + +// Drot applies a plane transformation. +// x[i] = c * x[i] + s * y[i] +// y[i] = c * y[i] - s * x[i] +func (Implementation) Drot(n int, x []float64, incX int, y []float64, incY int, c float64, s float64) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, vx := range x { + vy := y[i] + x[i], y[i] = c*vx+s*vy, c*vy-s*vx + } + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + vx := x[ix] + vy := y[iy] + x[ix], y[iy] = c*vx+s*vy, c*vy-s*vx + ix += incX + iy += incY + } +} + +// Drotm applies the modified Givens rotation to the 2×n matrix. +func (Implementation) Drotm(n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + + var h11, h12, h21, h22 float64 + var ix, iy int + switch p.Flag { + case blas.Identity: + return + case blas.Rescaling: + h11 = p.H[0] + h12 = p.H[2] + h21 = p.H[1] + h22 = p.H[3] + case blas.OffDiagonal: + h11 = 1 + h12 = p.H[2] + h21 = p.H[1] + h22 = 1 + case blas.Diagonal: + h11 = p.H[0] + h12 = 1 + h21 = -1 + h22 = p.H[3] + } + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, vx := range x { + vy := y[i] + x[i], y[i] = vx*h11+vy*h12, vx*h21+vy*h22 + } + return + } + for i := 0; i < n; i++ { + vx := x[ix] + vy := y[iy] + x[ix], y[iy] = vx*h11+vy*h12, vx*h21+vy*h22 + ix += incX + iy += incY + } + return +} + +// Dscal scales x by alpha. +// x[i] *= alpha +// Dscal has no effect if incX < 0. +func (Implementation) Dscal(n int, alpha float64, x []float64, incX int) { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return + } + if (n-1)*incX >= len(x) { + panic(badX) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if alpha == 0 { + if incX == 1 { + x = x[:n] + for i := range x { + x[i] = 0 + } + return + } + for ix := 0; ix < n*incX; ix += incX { + x[ix] = 0 + } + return + } + if incX == 1 { + f64.ScalUnitary(alpha, x[:n]) + return + } + for ix := 0; ix < n*incX; ix += incX { + x[ix] *= alpha + } +} diff --git a/blas/native/level1doubleBench_auto_test.go b/blas/native/level1doubleBench_auto_test.go new file mode 100644 index 00000000..8ca4071a --- /dev/null +++ b/blas/native/level1doubleBench_auto_test.go @@ -0,0 +1,1685 @@ +// Code generated by "go run github.com/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go"; DO NOT EDIT. + +// Copyright 2014 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package native + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +const ( + posInc1 = 5 + posInc2 = 3 + negInc1 = -3 + negInc2 = -4 + SMALL_SLICE = 10 + MEDIUM_SLICE = 1000 + LARGE_SLICE = 100000 + HUGE_SLICE = 10000000 +) + +func randomSlice(l, idx int) []float64 { + if idx < 0 { + idx = -idx + } + s := make([]float64, l*idx) + for i := range s { + s[i] = rand.Float64() + } + return s +} + +func benchmarkDdot(b *testing.B, n int, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Ddot(n, x, incX, y, incY) + } +} + +func BenchmarkDdotSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +func BenchmarkDdotHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDdot(b, n, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDnrm2(b *testing.B, n int, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dnrm2(n, x, incX) + } +} + +func BenchmarkDnrm2SmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2SmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2MediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2MediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2LargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2LargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2HugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +func BenchmarkDnrm2HugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDnrm2(b, n, x, incX) +} + +/* ------------------ */ +func benchmarkDasum(b *testing.B, n int, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dasum(n, x, incX) + } +} + +func BenchmarkDasumSmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumSmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumMediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumMediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumLargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumLargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumHugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +func BenchmarkDasumHugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkDasum(b, n, x, incX) +} + +/* ------------------ */ +func benchmarkIdamax(b *testing.B, n int, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Idamax(n, x, incX) + } +} + +func BenchmarkIdamaxSmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxSmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxMediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxMediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxLargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxLargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxHugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +func BenchmarkIdamaxHugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + + benchmarkIdamax(b, n, x, incX) +} + +/* ------------------ */ +func benchmarkDswap(b *testing.B, n int, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dswap(n, x, incX, y, incY) + } +} + +func BenchmarkDswapSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +func BenchmarkDswapHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDswap(b, n, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDcopy(b *testing.B, n int, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dcopy(n, x, incX, y, incY) + } +} + +func BenchmarkDcopySmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopySmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopySmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopySmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +func BenchmarkDcopyHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + + benchmarkDcopy(b, n, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDaxpy(b *testing.B, n int, alpha float64, x []float64, incX int, y []float64, incY int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Daxpy(n, alpha, x, incX, y, incY) + } +} + +func BenchmarkDaxpySmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpySmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpySmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpySmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +func BenchmarkDaxpyHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + alpha := 2.4 + benchmarkDaxpy(b, n, alpha, x, incX, y, incY) +} + +/* ------------------ */ +func benchmarkDrot(b *testing.B, n int, x []float64, incX int, y []float64, incY int, c, s float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drot(n, x, incX, y, incY, c, s) + } +} + +func BenchmarkDrotSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +func BenchmarkDrotHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + c := 0.89725836967 + s := 0.44150585279 + benchmarkDrot(b, n, x, incX, y, incY, c, s) +} + +/* ------------------ */ +func benchmarkDrotmOffDia(b *testing.B, n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drotm(n, x, incX, y, incY, p) + } +} + +func BenchmarkDrotmOffDiaSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmOffDiaHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375, 0}} + benchmarkDrotmOffDia(b, n, x, incX, y, incY, p) +} + +/* ------------------ */ +func benchmarkDrotmDia(b *testing.B, n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drotm(n, x, incX, y, incY, p) + } +} + +func BenchmarkDrotmDiaSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmDiaHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}} + benchmarkDrotmDia(b, n, x, incX, y, incY, p) +} + +/* ------------------ */ +func benchmarkDrotmResc(b *testing.B, n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Drotm(n, x, incX, y, incY, p) + } +} + +func BenchmarkDrotmRescSmallBothUnitary(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescSmallIncUni(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescSmallUniInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescSmallBothInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumBothUnitary(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumIncUni(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumUniInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescMediumBothInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeBothUnitary(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeIncUni(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeUniInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescLargeBothInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeBothUnitary(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeIncUni(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := 1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeUniInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +func BenchmarkDrotmRescHugeBothInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + incY := negInc1 + y := randomSlice(n, incY) + p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}} + benchmarkDrotmResc(b, n, x, incX, y, incY, p) +} + +/* ------------------ */ +func benchmarkDscal(b *testing.B, n int, alpha float64, x []float64, incX int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + impl.Dscal(n, alpha, x, incX) + } +} + +func BenchmarkDscalSmallUnitaryInc(b *testing.B) { + n := SMALL_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalSmallPosInc(b *testing.B) { + n := SMALL_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalMediumUnitaryInc(b *testing.B) { + n := MEDIUM_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalMediumPosInc(b *testing.B) { + n := MEDIUM_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalLargeUnitaryInc(b *testing.B) { + n := LARGE_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalLargePosInc(b *testing.B) { + n := LARGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalHugeUnitaryInc(b *testing.B) { + n := HUGE_SLICE + incX := 1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +func BenchmarkDscalHugePosInc(b *testing.B) { + n := HUGE_SLICE + incX := posInc1 + x := randomSlice(n, incX) + alpha := 2.4 + benchmarkDscal(b, n, alpha, x, incX) +} + +/* ------------------ */ diff --git a/blas/native/level1double_ddot.go b/blas/native/level1double_ddot.go new file mode 100644 index 00000000..21af53f0 --- /dev/null +++ b/blas/native/level1double_ddot.go @@ -0,0 +1,49 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/internal/asm/f64" +) + +// Ddot computes the dot product of the two vectors +// \sum_i x[i]*y[i] +func (Implementation) Ddot(n int, x []float64, incX int, y []float64, incY int) float64 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + return f64.DotUnitary(x[:n], y) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + return f64.DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} diff --git a/blas/native/level1double_test.go b/blas/native/level1double_test.go new file mode 100644 index 00000000..b9c825ef --- /dev/null +++ b/blas/native/level1double_test.go @@ -0,0 +1,61 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +var impl Implementation + +func TestDasum(t *testing.T) { + testblas.DasumTest(t, impl) +} + +func TestDaxpy(t *testing.T) { + testblas.DaxpyTest(t, impl) +} + +func TestDdot(t *testing.T) { + testblas.DdotTest(t, impl) +} + +func TestDnrm2(t *testing.T) { + testblas.Dnrm2Test(t, impl) +} + +func TestIdamax(t *testing.T) { + testblas.IdamaxTest(t, impl) +} + +func TestDswap(t *testing.T) { + testblas.DswapTest(t, impl) +} + +func TestDcopy(t *testing.T) { + testblas.DcopyTest(t, impl) +} + +func TestDrotg(t *testing.T) { + testblas.DrotgTest(t, impl) +} + +func TestDrotmg(t *testing.T) { + testblas.DrotmgTest(t, impl) +} + +func TestDrot(t *testing.T) { + testblas.DrotTest(t, impl) +} + +func TestDrotm(t *testing.T) { + testblas.DrotmTest(t, impl) +} + +func TestDscal(t *testing.T) { + testblas.DscalTest(t, impl) +} diff --git a/blas/native/level1single.go b/blas/native/level1single.go new file mode 100644 index 00000000..a57237d8 --- /dev/null +++ b/blas/native/level1single.go @@ -0,0 +1,634 @@ +// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT. + +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + math "gonum.org/v1/gonum/blas/native/internal/math32" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f32" +) + +var _ blas.Float32Level1 = Implementation{} + +// Snrm2 computes the Euclidean norm of a vector, +// sqrt(\sum_i x[i] * x[i]). +// This function returns 0 if incX is negative. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Snrm2(n int, x []float32, incX int) float32 { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if n < 2 { + if n == 1 { + return math.Abs(x[0]) + } + if n == 0 { + return 0 + } + if n < 1 { + panic(negativeN) + } + } + var ( + scale float32 = 0 + sumSquares float32 = 1 + ) + if incX == 1 { + x = x[:n] + for _, v := range x { + if v == 0 { + continue + } + absxi := math.Abs(v) + if math.IsNaN(absxi) { + return math.NaN() + } + if scale < absxi { + sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumSquares = sumSquares + (absxi/scale)*(absxi/scale) + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(sumSquares) + } + for ix := 0; ix < n*incX; ix += incX { + val := x[ix] + if val == 0 { + continue + } + absxi := math.Abs(val) + if math.IsNaN(absxi) { + return math.NaN() + } + if scale < absxi { + sumSquares = 1 + sumSquares*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumSquares = sumSquares + (absxi/scale)*(absxi/scale) + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(sumSquares) +} + +// Sasum computes the sum of the absolute values of the elements of x. +// \sum_i |x[i]| +// Sasum returns 0 if incX is negative. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sasum(n int, x []float32, incX int) float32 { + var sum float32 + if n < 0 { + panic(negativeN) + } + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if incX == 1 { + x = x[:n] + for _, v := range x { + sum += math.Abs(v) + } + return sum + } + for i := 0; i < n; i++ { + sum += math.Abs(x[i*incX]) + } + return sum +} + +// Isamax returns the index of an element of x with the largest absolute value. +// If there are multiple such indices the earliest is returned. +// Isamax returns -1 if n == 0. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Isamax(n int, x []float32, incX int) int { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return -1 + } + if incX > 0 && (n-1)*incX >= len(x) { + panic(badX) + } + if n < 2 { + if n == 1 { + return 0 + } + if n == 0 { + return -1 // Netlib returns invalid index when n == 0 + } + if n < 1 { + panic(negativeN) + } + } + idx := 0 + max := math.Abs(x[0]) + if incX == 1 { + for i, v := range x[:n] { + absV := math.Abs(v) + if absV > max { + max = absV + idx = i + } + } + return idx + } + ix := incX + for i := 1; i < n; i++ { + v := x[ix] + absV := math.Abs(v) + if absV > max { + max = absV + idx = i + } + ix += incX + } + return idx +} + +// Sswap exchanges the elements of two vectors. +// x[i], y[i] = y[i], x[i] for all i +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sswap(n int, x []float32, incX int, y []float32, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, v := range x { + x[i], y[i] = y[i], v + } + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + x[ix], y[iy] = y[iy], x[ix] + ix += incX + iy += incY + } +} + +// Scopy copies the elements of x into the elements of y. +// y[i] = x[i] for all i +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Scopy(n int, x []float32, incX int, y []float32, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + copy(y[:n], x[:n]) + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + y[iy] = x[ix] + ix += incX + iy += incY + } +} + +// Saxpy adds alpha times x to y +// y[i] += alpha * x[i] for all i +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Saxpy(n int, alpha float32, x []float32, incX int, y []float32, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if alpha == 0 { + return + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + f32.AxpyUnitaryTo(y, alpha, x[:n], y) + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + f32.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Srotg computes the plane rotation +// _ _ _ _ _ _ +// | c s | | a | | r | +// | -s c | * | b | = | 0 | +// ‾ ‾ ‾ ‾ ‾ ‾ +// where +// r = ±√(a^2 + b^2) +// c = a/r, the cosine of the plane rotation +// s = b/r, the sine of the plane rotation +// +// NOTE: There is a discrepancy between the refence implementation and the BLAS +// technical manual regarding the sign for r when a or b are zero. +// Srotg agrees with the definition in the manual and other +// common BLAS implementations. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Srotg(a, b float32) (c, s, r, z float32) { + if b == 0 && a == 0 { + return 1, 0, a, 0 + } + absA := math.Abs(a) + absB := math.Abs(b) + aGTb := absA > absB + r = math.Hypot(a, b) + if aGTb { + r = math.Copysign(r, a) + } else { + r = math.Copysign(r, b) + } + c = a / r + s = b / r + if aGTb { + z = s + } else if c != 0 { // r == 0 case handled above + z = 1 / c + } else { + z = 1 + } + return +} + +// Srotmg computes the modified Givens rotation. See +// http://www.netlib.org/lapack/explore-html/df/deb/drotmg_8f.html +// for more details. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Srotmg(d1, d2, x1, y1 float32) (p blas.SrotmParams, rd1, rd2, rx1 float32) { + var p1, p2, q1, q2, u float32 + + const ( + gam = 4096.0 + gamsq = 16777216.0 + rgamsq = 5.9604645e-8 + ) + + if d1 < 0 { + p.Flag = blas.Rescaling + return + } + + p2 = d2 * y1 + if p2 == 0 { + p.Flag = blas.Identity + rd1 = d1 + rd2 = d2 + rx1 = x1 + return + } + p1 = d1 * x1 + q2 = p2 * y1 + q1 = p1 * x1 + + absQ1 := math.Abs(q1) + absQ2 := math.Abs(q2) + + if absQ1 < absQ2 && q2 < 0 { + p.Flag = blas.Rescaling + return + } + + if d1 == 0 { + p.Flag = blas.Diagonal + p.H[0] = p1 / p2 + p.H[3] = x1 / y1 + u = 1 + p.H[0]*p.H[3] + rd1, rd2 = d2/u, d1/u + rx1 = y1 / u + return + } + + // Now we know that d1 != 0, and d2 != 0. If d2 == 0, it would be caught + // when p2 == 0, and if d1 == 0, then it is caught above + + if absQ1 > absQ2 { + p.H[1] = -y1 / x1 + p.H[2] = p2 / p1 + u = 1 - p.H[2]*p.H[1] + rd1 = d1 + rd2 = d2 + rx1 = x1 + p.Flag = blas.OffDiagonal + // u must be greater than zero because |q1| > |q2|, so check from netlib + // is unnecessary + // This is left in for ease of comparison with complex routines + //if u > 0 { + rd1 /= u + rd2 /= u + rx1 *= u + //} + } else { + p.Flag = blas.Diagonal + p.H[0] = p1 / p2 + p.H[3] = x1 / y1 + u = 1 + p.H[0]*p.H[3] + rd1 = d2 / u + rd2 = d1 / u + rx1 = y1 * u + } + + for rd1 <= rgamsq || rd1 >= gamsq { + if p.Flag == blas.OffDiagonal { + p.H[0] = 1 + p.H[3] = 1 + p.Flag = blas.Rescaling + } else if p.Flag == blas.Diagonal { + p.H[1] = -1 + p.H[2] = 1 + p.Flag = blas.Rescaling + } + if rd1 <= rgamsq { + rd1 *= gam * gam + rx1 /= gam + p.H[0] /= gam + p.H[2] /= gam + } else { + rd1 /= gam * gam + rx1 *= gam + p.H[0] *= gam + p.H[2] *= gam + } + } + + for math.Abs(rd2) <= rgamsq || math.Abs(rd2) >= gamsq { + if p.Flag == blas.OffDiagonal { + p.H[0] = 1 + p.H[3] = 1 + p.Flag = blas.Rescaling + } else if p.Flag == blas.Diagonal { + p.H[1] = -1 + p.H[2] = 1 + p.Flag = blas.Rescaling + } + if math.Abs(rd2) <= rgamsq { + rd2 *= gam * gam + p.H[1] /= gam + p.H[3] /= gam + } else { + rd2 /= gam * gam + p.H[1] *= gam + p.H[3] *= gam + } + } + return +} + +// Srot applies a plane transformation. +// x[i] = c * x[i] + s * y[i] +// y[i] = c * y[i] - s * x[i] +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Srot(n int, x []float32, incX int, y []float32, incY int, c float32, s float32) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, vx := range x { + vy := y[i] + x[i], y[i] = c*vx+s*vy, c*vy-s*vx + } + return + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + for i := 0; i < n; i++ { + vx := x[ix] + vy := y[iy] + x[ix], y[iy] = c*vx+s*vy, c*vy-s*vx + ix += incX + iy += incY + } +} + +// Srotm applies the modified Givens rotation to the 2×n matrix. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Srotm(n int, x []float32, incX int, y []float32, incY int, p blas.SrotmParams) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return + } + panic(negativeN) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + + var h11, h12, h21, h22 float32 + var ix, iy int + switch p.Flag { + case blas.Identity: + return + case blas.Rescaling: + h11 = p.H[0] + h12 = p.H[2] + h21 = p.H[1] + h22 = p.H[3] + case blas.OffDiagonal: + h11 = 1 + h12 = p.H[2] + h21 = p.H[1] + h22 = 1 + case blas.Diagonal: + h11 = p.H[0] + h12 = 1 + h21 = -1 + h22 = p.H[3] + } + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if incX == 1 && incY == 1 { + x = x[:n] + for i, vx := range x { + vy := y[i] + x[i], y[i] = vx*h11+vy*h12, vx*h21+vy*h22 + } + return + } + for i := 0; i < n; i++ { + vx := x[ix] + vy := y[iy] + x[ix], y[iy] = vx*h11+vy*h12, vx*h21+vy*h22 + ix += incX + iy += incY + } + return +} + +// Sscal scales x by alpha. +// x[i] *= alpha +// Sscal has no effect if incX < 0. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sscal(n int, alpha float32, x []float32, incX int) { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return + } + if (n-1)*incX >= len(x) { + panic(badX) + } + if n < 1 { + if n == 0 { + return + } + panic(negativeN) + } + if alpha == 0 { + if incX == 1 { + x = x[:n] + for i := range x { + x[i] = 0 + } + return + } + for ix := 0; ix < n*incX; ix += incX { + x[ix] = 0 + } + return + } + if incX == 1 { + f32.ScalUnitary(alpha, x[:n]) + return + } + for ix := 0; ix < n*incX; ix += incX { + x[ix] *= alpha + } +} diff --git a/blas/native/level1single_dsdot.go b/blas/native/level1single_dsdot.go new file mode 100644 index 00000000..e3cef432 --- /dev/null +++ b/blas/native/level1single_dsdot.go @@ -0,0 +1,53 @@ +// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT. + +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/internal/asm/f32" +) + +// Dsdot computes the dot product of the two vectors +// \sum_i x[i]*y[i] +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Dsdot(n int, x []float32, incX int, y []float32, incY int) float64 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + return f32.DdotUnitary(x[:n], y) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + return f32.DdotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} diff --git a/blas/native/level1single_sdot.go b/blas/native/level1single_sdot.go new file mode 100644 index 00000000..66c80472 --- /dev/null +++ b/blas/native/level1single_sdot.go @@ -0,0 +1,53 @@ +// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT. + +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/internal/asm/f32" +) + +// Sdot computes the dot product of the two vectors +// \sum_i x[i]*y[i] +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sdot(n int, x []float32, incX int, y []float32, incY int) float32 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + return f32.DotUnitary(x[:n], y) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + return f32.DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} diff --git a/blas/native/level1single_sdsdot.go b/blas/native/level1single_sdsdot.go new file mode 100644 index 00000000..af1f984a --- /dev/null +++ b/blas/native/level1single_sdsdot.go @@ -0,0 +1,53 @@ +// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT. + +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/internal/asm/f32" +) + +// Sdsdot computes the dot product of the two vectors plus a constant +// alpha + \sum_i x[i]*y[i] +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sdsdot(n int, alpha float32, x []float32, incX int, y []float32, incY int) float32 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(negativeN) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(badLenX) + } + if len(y) < n { + panic(badLenY) + } + return alpha + float32(f32.DdotUnitary(x[:n], y)) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || ix+(n-1)*incX >= len(x) { + panic(badLenX) + } + if iy >= len(y) || iy+(n-1)*incY >= len(y) { + panic(badLenY) + } + return alpha + float32(f32.DdotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy))) +} diff --git a/blas/native/level2double.go b/blas/native/level2double.go new file mode 100644 index 00000000..2868ccc1 --- /dev/null +++ b/blas/native/level2double.go @@ -0,0 +1,2236 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f64" +) + +var _ blas.Float64Level2 = Implementation{} + +// Dgemv computes +// y = alpha * a * x + beta * y if tA = blas.NoTrans +// y = alpha * A^T * x + beta * y if tA = blas.Trans or blas.ConjTrans +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Dgemv(tA blas.Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + // Set up indexes + lenX := m + lenY := n + if tA == blas.NoTrans { + lenX = n + lenY = m + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + return + } + + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Dscal(lenY, beta, y, incY) + } else { + Implementation{}.Dscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + // Form y := alpha * A * x + y + if tA == blas.NoTrans { + if incX == 1 && incY == 1 { + for i := 0; i < m; i++ { + y[i] += alpha * f64.DotUnitary(a[lda*i:lda*i+n], x) + } + return + } + iy := ky + for i := 0; i < m; i++ { + y[iy] += alpha * f64.DotInc(x, a[lda*i:lda*i+n], uintptr(n), uintptr(incX), 1, uintptr(kx), 0) + iy += incY + } + return + } + // Cases where a is transposed. + if incX == 1 && incY == 1 { + for i := 0; i < m; i++ { + tmp := alpha * x[i] + if tmp != 0 { + f64.AxpyUnitaryTo(y, tmp, a[lda*i:lda*i+n], y) + } + } + return + } + ix := kx + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + if tmp != 0 { + f64.AxpyInc(tmp, a[lda*i:lda*i+n], y, uintptr(n), 1, uintptr(incY), 0, uintptr(ky)) + } + ix += incX + } +} + +// Dger performs the rank-one operation +// A += alpha * x * y^T +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Dger(m, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) { + // Check inputs + if m < 0 { + panic("m < 0") + } + if n < 0 { + panic(negativeN) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if lda < max(1, n) { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || alpha == 0 { + return + } + + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + if incX > 0 { + kx = 0 + } else { + kx = -(m - 1) * incX + } + + if incX == 1 && incY == 1 { + x = x[:m] + y = y[:n] + for i, xv := range x { + tmp := alpha * xv + if tmp != 0 { + atmp := a[i*lda : i*lda+n] + f64.AxpyUnitaryTo(atmp, tmp, y, atmp) + } + } + return + } + + ix := kx + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + if tmp != 0 { + f64.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(ky), 0) + } + ix += incX + } +} + +// Dgbmv computes +// y = alpha * A * x + beta * y if tA == blas.NoTrans +// y = alpha * A^T * x + beta * y if tA == blas.Trans or blas.ConjTrans +// where a is an m×n band matrix kL subdiagonals and kU super-diagonals, and +// m and n refer to the size of the full dense matrix it represents. +// x and y are vectors, and alpha and beta are scalars. +func (Implementation) Dgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if kL < 0 { + panic(kLLT0) + } + if kL < 0 { + panic(kULT0) + } + if lda < kL+kU+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + // Set up indexes + lenX := m + lenY := n + if tA == blas.NoTrans { + lenX = n + lenY = m + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + return + } + + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Dscal(lenY, beta, y, incY) + } else { + Implementation{}.Dscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + // i and j are indices of the compacted banded matrix. + // off is the offset into the dense matrix (off + j = densej) + ld := min(m, n) + nCol := kU + 1 + kL + if tA == blas.NoTrans { + iy := ky + if incX == 1 { + for i := 0; i < m; i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + xtmp := x[off : off+u-l] + var sum float64 + for j, v := range atmp { + sum += xtmp[j] * v + } + y[iy] += sum * alpha + iy += incY + } + return + } + for i := 0; i < m; i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + jx := kx + var sum float64 + for _, v := range atmp { + sum += x[off*incX+jx] * v + jx += incX + } + y[iy] += sum * alpha + iy += incY + } + return + } + if incX == 1 { + for i := 0; i < m; i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + tmp := alpha * x[i] + jy := ky + for _, v := range atmp { + y[jy+off*incY] += tmp * v + jy += incY + } + } + return + } + ix := kx + for i := 0; i < m; i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + tmp := alpha * x[ix] + jy := ky + for _, v := range atmp { + y[jy+off*incY] += tmp * v + jy += incY + } + ix += incX + } +} + +// Dtrmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// A is an n×n Triangular matrix and x is a vector. +func (Implementation) Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda < n { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if n == 0 { + return + } + nonUnit := d != blas.Unit + if n == 1 { + if nonUnit { + x[0] *= a[0] + } + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + ilda := i * lda + var tmp float64 + if nonUnit { + tmp = a[ilda+i] * x[i] + } else { + tmp = x[i] + } + xtmp := x[i+1:] + x[i] = tmp + f64.DotUnitary(a[ilda+i+1:ilda+n], xtmp) + } + return + } + ix := kx + for i := 0; i < n; i++ { + ilda := i * lda + var tmp float64 + if nonUnit { + tmp = a[ilda+i] * x[ix] + } else { + tmp = x[ix] + } + x[ix] = tmp + f64.DotInc(x, a[ilda+i+1:ilda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + ilda := i * lda + var tmp float64 + if nonUnit { + tmp += a[ilda+i] * x[i] + } else { + tmp = x[i] + } + x[i] = tmp + f64.DotUnitary(a[ilda:ilda+i], x) + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + ilda := i * lda + var tmp float64 + if nonUnit { + tmp = a[ilda+i] * x[ix] + } else { + tmp = x[ix] + } + x[ix] = tmp + f64.DotInc(x, a[ilda:ilda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) + ix -= incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + ilda := i * lda + xi := x[i] + f64.AxpyUnitary(xi, a[ilda+i+1:ilda+n], x[i+1:n]) + if nonUnit { + x[i] *= a[ilda+i] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + ilda := i * lda + xi := x[ix] + f64.AxpyInc(xi, a[ilda+i+1:ilda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(kx+(i+1)*incX)) + if nonUnit { + x[ix] *= a[ilda+i] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + ilda := i * lda + xi := x[i] + f64.AxpyUnitary(xi, a[ilda:ilda+i], x) + if nonUnit { + x[i] *= a[i*lda+i] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + ilda := i * lda + xi := x[ix] + f64.AxpyInc(xi, a[ilda:ilda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) + if nonUnit { + x[ix] *= a[ilda+i] + } + ix += incX + } +} + +// Dtrsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// A is an n×n triangular matrix and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) { + // Test the input parameters + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + // Quick return if possible + if n == 0 { + return + } + if n == 1 { + if d == blas.NonUnit { + x[0] /= a[0] + } + return + } + + var kx int + if incX < 0 { + kx = -(n - 1) * incX + } + nonUnit := d == blas.NonUnit + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + var sum float64 + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jv := i + j + 1 + sum += x[jv] * v + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+i] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + var sum float64 + jx := ix + incX + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + sum += x[jx] * v + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+i] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + var sum float64 + atmp := a[i*lda : i*lda+i] + for j, v := range atmp { + sum += x[j] * v + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+i] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + var sum float64 + atmp := a[i*lda : i*lda+i] + for _, v := range atmp { + sum += x[jx] * v + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+i] + } + ix += incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if nonUnit { + x[i] /= a[i*lda+i] + } + xi := x[i] + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jv := j + i + 1 + x[jv] -= v * xi + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + if nonUnit { + x[ix] /= a[i*lda+i] + } + xi := x[ix] + jx := kx + (i+1)*incX + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + x[jx] -= v * xi + jx += incX + } + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[i] /= a[i*lda+i] + } + xi := x[i] + atmp := a[i*lda : i*lda+i] + for j, v := range atmp { + x[j] -= v * xi + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[ix] /= a[i*lda+i] + } + xi := x[ix] + jx := kx + atmp := a[i*lda : i*lda+i] + for _, v := range atmp { + x[jx] -= v * xi + jx += incX + } + ix -= incX + } +} + +// Dsymv computes +// y = alpha * A * x + beta * y, +// where a is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +func (Implementation) Dsymv(ul blas.Uplo, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + // Check inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(negativeN) + } + if lda > 1 && lda < n { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up start points + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + // Form y = beta * y + if beta != 1 { + if incY > 0 { + Implementation{}.Dscal(n, beta, y, incY) + } else { + Implementation{}.Dscal(n, beta, y, -incY) + } + } + + if alpha == 0 { + return + } + + if n == 1 { + y[0] += alpha * a[0] * x[0] + return + } + + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + sum := x[i] * a[i*lda+i] + jy := ky + (i+1)*incY + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jp := j + i + 1 + sum += x[jp] * v + y[jy] += xv * v + jy += incY + } + y[iy] += alpha * sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + sum := x[ix] * a[i*lda+i] + jx := kx + (i+1)*incX + jy := ky + (i+1)*incY + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + sum += x[jx] * v + y[jy] += xv * v + jx += incX + jy += incY + } + y[iy] += alpha * sum + ix += incX + iy += incY + } + return + } + // Cases where a is lower triangular. + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + jy := ky + xv := alpha * x[i] + atmp := a[i*lda : i*lda+i] + var sum float64 + for j, v := range atmp { + sum += x[j] * v + y[jy] += xv * v + jy += incY + } + sum += x[i] * a[i*lda+i] + sum *= alpha + y[iy] += sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + xv := alpha * x[ix] + atmp := a[i*lda : i*lda+i] + var sum float64 + for _, v := range atmp { + sum += x[jx] * v + y[jy] += xv * v + jx += incX + jy += incY + } + sum += x[ix] * a[i*lda+i] + sum *= alpha + y[iy] += sum + ix += incX + iy += incY + } +} + +// Dtbmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular banded matrix with k diagonals, and x is a vector. +func (Implementation) Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } else if incX != 1 { + kx = 0 + } + + nonunit := d != blas.Unit + + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + u := min(1+k, n-i) + var sum float64 + atmp := a[i*lda:] + xtmp := x[i:] + for j := 1; j < u; j++ { + sum += xtmp[j] * atmp[j] + } + if nonunit { + sum += xtmp[0] * atmp[0] + } else { + sum += xtmp[0] + } + x[i] = sum + } + return + } + ix := kx + for i := 0; i < n; i++ { + u := min(1+k, n-i) + var sum float64 + atmp := a[i*lda:] + jx := incX + for j := 1; j < u; j++ { + sum += x[ix+jx] * atmp[j] + jx += incX + } + if nonunit { + sum += x[ix] * atmp[0] + } else { + sum += x[ix] + } + x[ix] = sum + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + l := max(0, k-i) + atmp := a[i*lda:] + var sum float64 + for j := l; j < k; j++ { + sum += x[i-k+j] * atmp[j] + } + if nonunit { + sum += x[i] * atmp[k] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + l := max(0, k-i) + atmp := a[i*lda:] + var sum float64 + jx := l * incX + for j := l; j < k; j++ { + sum += x[ix-k*incX+jx] * atmp[j] + jx += incX + } + if nonunit { + sum += x[ix] * atmp[k] + } else { + sum += x[ix] + } + x[ix] = sum + ix -= incX + } + return + } + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + u := k + 1 + if i < u { + u = i + 1 + } + var sum float64 + for j := 1; j < u; j++ { + sum += x[i-j] * a[(i-j)*lda+j] + } + if nonunit { + sum += x[i] * a[i*lda] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + u := k + 1 + if i < u { + u = i + 1 + } + var sum float64 + jx := incX + for j := 1; j < u; j++ { + sum += x[ix-jx] * a[(i-j)*lda+j] + jx += incX + } + if nonunit { + sum += x[ix] * a[i*lda] + } else { + sum += x[ix] + } + x[ix] = sum + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + u := k + if i+k >= n { + u = n - i - 1 + } + var sum float64 + for j := 0; j < u; j++ { + sum += x[i+j+1] * a[(i+j+1)*lda+k-j-1] + } + if nonunit { + sum += x[i] * a[i*lda+k] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + for i := 0; i < n; i++ { + u := k + if i+k >= n { + u = n - i - 1 + } + var ( + sum float64 + jx int + ) + for j := 0; j < u; j++ { + sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] + jx += incX + } + if nonunit { + sum += x[ix] * a[i*lda+k] + } else { + sum += x[ix] + } + x[ix] = sum + ix += incX + } +} + +// Dtpmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n unit triangular matrix in packed format, and x is a vector. +func (Implementation) Dtpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + + nonUnit := d == blas.NonUnit + var offset int // Offset is the index of (i,i) + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + if nonUnit { + xi *= ap[offset] + } + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xi += v * xtmp[j] + } + x[i] = xi + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + xix := x[ix] + if nonUnit { + xix *= ap[offset] + } + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + for _, v := range atmp { + xix += v * x[jx] + jx += incX + } + x[ix] = xix + offset += n - i + ix += incX + } + return + } + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xi := x[i] + if nonUnit { + xi *= ap[offset] + } + atmp := ap[offset-i : offset] + for j, v := range atmp { + xi += v * x[j] + } + x[i] = xi + offset -= i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xix := x[ix] + if nonUnit { + xix *= ap[offset] + } + atmp := ap[offset-i : offset] + jx := kx + for _, v := range atmp { + xix += v * x[jx] + jx += incX + } + x[ix] = xix + offset -= i + 1 + ix -= incX + } + return + } + // Cases where ap is transposed. + if ul == blas.Upper { + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xi := x[i] + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xtmp[j] += v * xi + } + if nonUnit { + x[i] *= ap[offset] + } + offset -= n - i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xix := x[ix] + jx := kx + (i+1)*incX + atmp := ap[offset+1 : offset+n-i] + for _, v := range atmp { + x[jx] += v * xix + jx += incX + } + if nonUnit { + x[ix] *= ap[offset] + } + offset -= n - i + 1 + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + atmp := ap[offset-i : offset] + for j, v := range atmp { + x[j] += v * xi + } + if nonUnit { + x[i] *= ap[offset] + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + xix := x[ix] + jx := kx + atmp := ap[offset-i : offset] + for _, v := range atmp { + x[jx] += v * xix + jx += incX + } + if nonUnit { + x[ix] *= ap[offset] + } + ix += incX + offset += i + 2 + } +} + +// Dtbsv solves +// A * x = b +// where A is an n×n triangular banded matrix with k diagonals in packed format, +// and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Dtbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX < 0 { + kx = -(n - 1) * incX + } else { + kx = 0 + } + nonUnit := d == blas.NonUnit + // Form x = A^-1 x. + // Several cases below use subslices for speed improvement. + // The incX != 1 cases usually do not because incX may be negative. + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + atmp := a[i*lda+1:] + xtmp := x[i+1 : i+bands+1] + var sum float64 + for j, v := range xtmp { + sum += v * atmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + max := k + 1 + if i+max > n { + max = n - i + } + atmp := a[i*lda:] + var ( + jx int + sum float64 + ) + for j := 1; j < max; j++ { + jx += incX + sum += x[ix+jx] * atmp[j] + } + x[ix] -= sum + if nonUnit { + x[ix] /= atmp[0] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + atmp := a[i*lda+k-bands:] + xtmp := x[i-bands : i] + var sum float64 + for j, v := range xtmp { + sum += v * atmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= atmp[bands] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + atmp := a[i*lda+k-bands:] + var ( + sum float64 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix-bands*incX+jx] * atmp[j] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= atmp[bands] + } + ix += incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + var sum float64 + for j := 0; j < bands; j++ { + sum += x[i-bands+j] * a[(i-bands+j)*lda+bands-j] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + var ( + sum float64 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix-bands*incX+jx] * a[(i-bands+j)*lda+bands-j] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda] + } + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + var sum float64 + xtmp := x[i+1 : i+1+bands] + for j, v := range xtmp { + sum += v * a[(i+j+1)*lda+k-j-1] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+k] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + var ( + sum float64 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+k] + } + ix -= incX + } +} + +// Dsbmv performs +// y = alpha * A * x + beta * y +// where A is an n×n symmetric banded matrix, x and y are vectors, and alpha +// and beta are scalars. +func (Implementation) Dsbmv(ul blas.Uplo, n, k int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up indexes + lenX := n + lenY := n + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Dscal(lenY, beta, y, incY) + } else { + Implementation{}.Dscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + atmp := a[i*lda:] + tmp := alpha * x[i] + sum := tmp * atmp[0] + u := min(k, n-i-1) + jy := incY + for j := 1; j <= u; j++ { + v := atmp[j] + sum += alpha * x[i+j] * v + y[iy+jy] += tmp * v + jy += incY + } + y[iy] += sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + atmp := a[i*lda:] + tmp := alpha * x[ix] + sum := tmp * atmp[0] + u := min(k, n-i-1) + jx := incX + jy := incY + for j := 1; j <= u; j++ { + v := atmp[j] + sum += alpha * x[ix+jx] * v + y[iy+jy] += tmp * v + jx += incX + jy += incY + } + y[iy] += sum + ix += incX + iy += incY + } + return + } + + // Casses where a has bands below the diagonal. + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + l := max(0, k-i) + tmp := alpha * x[i] + jy := l * incY + atmp := a[i*lda:] + for j := l; j < k; j++ { + v := atmp[j] + y[iy] += alpha * v * x[i-k+j] + y[iy-k*incY+jy] += tmp * v + jy += incY + } + y[iy] += tmp * atmp[k] + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + l := max(0, k-i) + tmp := alpha * x[ix] + jx := l * incX + jy := l * incY + atmp := a[i*lda:] + for j := l; j < k; j++ { + v := atmp[j] + y[iy] += alpha * v * x[ix-k*incX+jx] + y[iy-k*incY+jy] += tmp * v + jx += incX + jy += incY + } + y[iy] += tmp * atmp[k] + ix += incX + iy += incY + } + return +} + +// Dsyr performs the rank-one update +// a += alpha * x * x^T +// where a is an n×n symmetric matrix, and x is a vector. +func (Implementation) Dsyr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64, lda int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if alpha == 0 || n == 0 { + return + } + + lenX := n + var kx int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + tmp := x[i] * alpha + if tmp != 0 { + atmp := a[i*lda+i : i*lda+n] + xtmp := x[i:n] + for j, v := range xtmp { + atmp[j] += v * tmp + } + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + tmp := x[ix] * alpha + if tmp != 0 { + jx := ix + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += x[jx] * tmp + jx += incX + } + } + ix += incX + } + return + } + // Cases where a is lower triangular. + if incX == 1 { + for i := 0; i < n; i++ { + tmp := x[i] * alpha + if tmp != 0 { + atmp := a[i*lda:] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += tmp * v + } + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + tmp := x[ix] * alpha + if tmp != 0 { + atmp := a[i*lda:] + jx := kx + for j := 0; j < i+1; j++ { + atmp[j] += tmp * x[jx] + jx += incX + } + } + ix += incX + } +} + +// Dsyr2 performs the symmetric rank-two update +// A += alpha * x * y^T + alpha * y * x^T +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +func (Implementation) Dsyr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if alpha == 0 { + return + } + + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if ul == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + xi := x[i] + yi := y[i] + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += alpha * (xi*y[j] + x[j]*yi) + } + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + i*incX + jy := ky + i*incY + xi := x[ix] + yi := y[iy] + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + } + return + } + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + xi := x[i] + yi := y[i] + atmp := a[i*lda:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (xi*y[j] + x[j]*yi) + } + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + xi := x[ix] + yi := y[iy] + atmp := a[i*lda:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + } + return +} + +// Dtpsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular matrix in packed format and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +func (Implementation) Dtpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + + nonUnit := d == blas.NonUnit + var offset int // Offset is the index of (i,i) + if tA == blas.NoTrans { + if ul == blas.Upper { + offset = n*(n+1)/2 - 1 + if incX == 1 { + for i := n - 1; i >= 0; i-- { + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + var sum float64 + for j, v := range atmp { + sum += v * xtmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= ap[offset] + } + offset -= n - i + 1 + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + var sum float64 + for _, v := range atmp { + sum += v * x[jx] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= ap[offset] + } + ix -= incX + offset -= n - i + 1 + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset-i : offset] + var sum float64 + for j, v := range atmp { + sum += v * x[j] + } + x[i] -= sum + if nonUnit { + x[i] /= ap[offset] + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + atmp := ap[offset-i : offset] + var sum float64 + for _, v := range atmp { + sum += v * x[jx] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= ap[offset] + } + ix += incX + offset += i + 2 + } + return + } + // Cases where ap is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if nonUnit { + x[i] /= ap[offset] + } + xi := x[i] + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xtmp[j] -= v * xi + } + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + if nonUnit { + x[ix] /= ap[offset] + } + xix := x[ix] + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + for _, v := range atmp { + x[jx] -= v * xix + jx += incX + } + ix += incX + offset += n - i + } + return + } + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[i] /= ap[offset] + } + xi := x[i] + atmp := ap[offset-i : offset] + for j, v := range atmp { + x[j] -= v * xi + } + offset -= i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[ix] /= ap[offset] + } + xix := x[ix] + atmp := ap[offset-i : offset] + jx := kx + for _, v := range atmp { + x[jx] -= v * xix + jx += incX + } + ix -= incX + offset -= i + 1 + } +} + +// Dspmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors +// and alpha and beta are scalars. +func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x []float64, incX int, beta float64, y []float64, incY int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if len(a) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up start points + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + // Form y = beta * y + if beta != 1 { + if incY > 0 { + Implementation{}.Dscal(n, beta, y, incY) + } else { + Implementation{}.Dscal(n, beta, y, -incY) + } + } + + if alpha == 0 { + return + } + + if n == 1 { + y[0] += alpha * a[0] * x[0] + return + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + sum := a[offset] * x[i] + atmp := a[offset+1 : offset+n-i] + xtmp := x[i+1:] + jy := ky + (i+1)*incY + for j, v := range atmp { + sum += v * xtmp[j] + y[jy] += v * xv + jy += incY + } + y[iy] += alpha * sum + iy += incY + offset += n - i + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + sum := a[offset] * x[ix] + atmp := a[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + jy := ky + (i+1)*incY + for _, v := range atmp { + sum += v * x[jx] + y[jy] += v * xv + jx += incX + jy += incY + } + y[iy] += alpha * sum + ix += incX + iy += incY + offset += n - i + } + return + } + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + atmp := a[offset-i : offset] + jy := ky + var sum float64 + for j, v := range atmp { + sum += v * x[j] + y[jy] += v * xv + jy += incY + } + sum += a[offset] * x[i] + y[iy] += alpha * sum + iy += incY + offset += i + 2 + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + atmp := a[offset-i : offset] + jx := kx + jy := ky + var sum float64 + for _, v := range atmp { + sum += v * x[jx] + y[jy] += v * xv + jx += incX + jy += incY + } + + sum += a[offset] * x[ix] + y[iy] += alpha * sum + ix += incX + iy += incY + offset += i + 2 + } +} + +// Dspr computes the rank-one operation +// a += alpha * x * x^T +// where a is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if len(a) < (n*(n+1))/2 { + panic(badLdA) + } + if alpha == 0 || n == 0 { + return + } + lenX := n + var kx int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + atmp := a[offset:] + xv := alpha * x[i] + xtmp := x[i:n] + for j, v := range xtmp { + atmp[j] += xv * v + } + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + i*incX + atmp := a[offset:] + xv := alpha * x[ix] + for j := 0; j < n-i; j++ { + atmp[j] += xv * x[jx] + jx += incX + } + ix += incX + offset += n - i + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + atmp := a[offset-i:] + xv := alpha * x[i] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += xv * v + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + atmp := a[offset-i:] + xv := alpha * x[ix] + for j := 0; j <= i; j++ { + atmp[j] += xv * x[jx] + jx += incX + } + ix += incX + offset += i + 2 + } +} + +// Dspr2 performs the symmetric rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +func (Implementation) Dspr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, ap []float64) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if alpha == 0 { + return + } + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset:] + xi := x[i] + yi := y[i] + xtmp := x[i:n] + ytmp := y[i:n] + for j, v := range xtmp { + atmp[j] += alpha * (xi*ytmp[j] + v*yi) + } + offset += n - i + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + i*incX + jy := ky + i*incY + atmp := ap[offset:] + xi := x[ix] + yi := y[iy] + for j := 0; j < n-i; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + offset += n - i + } + return + } + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset-i:] + xi := x[i] + yi := y[i] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += alpha * (xi*y[j] + v*yi) + } + offset += i + 2 + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + atmp := ap[offset-i:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (x[ix]*y[jy] + x[jx]*y[iy]) + jx += incX + jy += incY + } + ix += incX + iy += incY + offset += i + 2 + } +} diff --git a/blas/native/level2double_test.go b/blas/native/level2double_test.go new file mode 100644 index 00000000..591d9810 --- /dev/null +++ b/blas/native/level2double_test.go @@ -0,0 +1,79 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func TestDgemv(t *testing.T) { + testblas.DgemvTest(t, impl) +} + +func TestDger(t *testing.T) { + testblas.DgerTest(t, impl) +} + +func TestDtxmv(t *testing.T) { + testblas.DtxmvTest(t, impl) +} + +func TestDgbmv(t *testing.T) { + testblas.DgbmvTest(t, impl) +} + +func TestDtbsv(t *testing.T) { + testblas.DtbsvTest(t, impl) +} + +func TestDsbmv(t *testing.T) { + testblas.DsbmvTest(t, impl) +} + +func TestDtbmv(t *testing.T) { + testblas.DtbmvTest(t, impl) +} + +func TestDtrsv(t *testing.T) { + testblas.DtrsvTest(t, impl) +} + +func TestDtrmv(t *testing.T) { + testblas.DtrmvTest(t, impl) +} + +func TestDsymv(t *testing.T) { + testblas.DsymvTest(t, impl) +} + +func TestDsyr(t *testing.T) { + testblas.DsyrTest(t, impl) +} + +func TestDsyr2(t *testing.T) { + testblas.Dsyr2Test(t, impl) +} + +func TestDspr2(t *testing.T) { + testblas.Dspr2Test(t, impl) +} + +func TestDspr(t *testing.T) { + testblas.DsprTest(t, impl) +} + +func TestDspmv(t *testing.T) { + testblas.DspmvTest(t, impl) +} + +func TestDtpsv(t *testing.T) { + testblas.DtpsvTest(t, impl) +} + +func TestDtpmv(t *testing.T) { + testblas.DtpmvTest(t, impl) +} diff --git a/blas/native/level2single.go b/blas/native/level2single.go new file mode 100644 index 00000000..8a367445 --- /dev/null +++ b/blas/native/level2single.go @@ -0,0 +1,2270 @@ +// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT. + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f32" +) + +var _ blas.Float32Level2 = Implementation{} + +// Sgemv computes +// y = alpha * a * x + beta * y if tA = blas.NoTrans +// y = alpha * A^T * x + beta * y if tA = blas.Trans or blas.ConjTrans +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sgemv(tA blas.Transpose, m, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + // Set up indexes + lenX := m + lenY := n + if tA == blas.NoTrans { + lenX = n + lenY = m + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + return + } + + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Sscal(lenY, beta, y, incY) + } else { + Implementation{}.Sscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + // Form y := alpha * A * x + y + if tA == blas.NoTrans { + if incX == 1 && incY == 1 { + for i := 0; i < m; i++ { + y[i] += alpha * f32.DotUnitary(a[lda*i:lda*i+n], x) + } + return + } + iy := ky + for i := 0; i < m; i++ { + y[iy] += alpha * f32.DotInc(x, a[lda*i:lda*i+n], uintptr(n), uintptr(incX), 1, uintptr(kx), 0) + iy += incY + } + return + } + // Cases where a is transposed. + if incX == 1 && incY == 1 { + for i := 0; i < m; i++ { + tmp := alpha * x[i] + if tmp != 0 { + f32.AxpyUnitaryTo(y, tmp, a[lda*i:lda*i+n], y) + } + } + return + } + ix := kx + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + if tmp != 0 { + f32.AxpyInc(tmp, a[lda*i:lda*i+n], y, uintptr(n), 1, uintptr(incY), 0, uintptr(ky)) + } + ix += incX + } +} + +// Sger performs the rank-one operation +// A += alpha * x * y^T +// where A is an m×n dense matrix, x and y are vectors, and alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sger(m, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) { + // Check inputs + if m < 0 { + panic("m < 0") + } + if n < 0 { + panic(negativeN) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (m-1)*incX >= len(x)) || (incX < 0 && (1-m)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if lda < max(1, n) { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || alpha == 0 { + return + } + + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + if incX > 0 { + kx = 0 + } else { + kx = -(m - 1) * incX + } + + if incX == 1 && incY == 1 { + x = x[:m] + y = y[:n] + for i, xv := range x { + tmp := alpha * xv + if tmp != 0 { + atmp := a[i*lda : i*lda+n] + f32.AxpyUnitaryTo(atmp, tmp, y, atmp) + } + } + return + } + + ix := kx + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + if tmp != 0 { + f32.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(ky), 0) + } + ix += incX + } +} + +// Sgbmv computes +// y = alpha * A * x + beta * y if tA == blas.NoTrans +// y = alpha * A^T * x + beta * y if tA == blas.Trans or blas.ConjTrans +// where a is an m×n band matrix kL subdiagonals and kU super-diagonals, and +// m and n refer to the size of the full dense matrix it represents. +// x and y are vectors, and alpha and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if kL < 0 { + panic(kLLT0) + } + if kL < 0 { + panic(kULT0) + } + if lda < kL+kU+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + // Set up indexes + lenX := m + lenY := n + if tA == blas.NoTrans { + lenX = n + lenY = m + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { + panic(badY) + } + if lda*(m-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { + panic(badLdA) + } + + // Quick return if possible + if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + return + } + + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Sscal(lenY, beta, y, incY) + } else { + Implementation{}.Sscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + // i and j are indices of the compacted banded matrix. + // off is the offset into the dense matrix (off + j = densej) + ld := min(m, n) + nCol := kU + 1 + kL + if tA == blas.NoTrans { + iy := ky + if incX == 1 { + for i := 0; i < m; i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + xtmp := x[off : off+u-l] + var sum float32 + for j, v := range atmp { + sum += xtmp[j] * v + } + y[iy] += sum * alpha + iy += incY + } + return + } + for i := 0; i < m; i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + jx := kx + var sum float32 + for _, v := range atmp { + sum += x[off*incX+jx] * v + jx += incX + } + y[iy] += sum * alpha + iy += incY + } + return + } + if incX == 1 { + for i := 0; i < m; i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + tmp := alpha * x[i] + jy := ky + for _, v := range atmp { + y[jy+off*incY] += tmp * v + jy += incY + } + } + return + } + ix := kx + for i := 0; i < m; i++ { + l := max(0, kL-i) + u := min(nCol, ld+kL-i) + off := max(0, i-kL) + atmp := a[i*lda+l : i*lda+u] + tmp := alpha * x[ix] + jy := ky + for _, v := range atmp { + y[jy+off*incY] += tmp * v + jy += incY + } + ix += incX + } +} + +// Strmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// A is an n×n Triangular matrix and x is a vector. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Strmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float32, lda int, x []float32, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda < n { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if n == 0 { + return + } + nonUnit := d != blas.Unit + if n == 1 { + if nonUnit { + x[0] *= a[0] + } + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + ilda := i * lda + var tmp float32 + if nonUnit { + tmp = a[ilda+i] * x[i] + } else { + tmp = x[i] + } + xtmp := x[i+1:] + x[i] = tmp + f32.DotUnitary(a[ilda+i+1:ilda+n], xtmp) + } + return + } + ix := kx + for i := 0; i < n; i++ { + ilda := i * lda + var tmp float32 + if nonUnit { + tmp = a[ilda+i] * x[ix] + } else { + tmp = x[ix] + } + x[ix] = tmp + f32.DotInc(x, a[ilda+i+1:ilda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + ilda := i * lda + var tmp float32 + if nonUnit { + tmp += a[ilda+i] * x[i] + } else { + tmp = x[i] + } + x[i] = tmp + f32.DotUnitary(a[ilda:ilda+i], x) + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + ilda := i * lda + var tmp float32 + if nonUnit { + tmp = a[ilda+i] * x[ix] + } else { + tmp = x[ix] + } + x[ix] = tmp + f32.DotInc(x, a[ilda:ilda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) + ix -= incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + ilda := i * lda + xi := x[i] + f32.AxpyUnitary(xi, a[ilda+i+1:ilda+n], x[i+1:n]) + if nonUnit { + x[i] *= a[ilda+i] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + ilda := i * lda + xi := x[ix] + f32.AxpyInc(xi, a[ilda+i+1:ilda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(kx+(i+1)*incX)) + if nonUnit { + x[ix] *= a[ilda+i] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + ilda := i * lda + xi := x[i] + f32.AxpyUnitary(xi, a[ilda:ilda+i], x) + if nonUnit { + x[i] *= a[i*lda+i] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + ilda := i * lda + xi := x[ix] + f32.AxpyInc(xi, a[ilda:ilda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) + if nonUnit { + x[ix] *= a[ilda+i] + } + ix += incX + } +} + +// Strsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// A is an n×n triangular matrix and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Strsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float32, lda int, x []float32, incX int) { + // Test the input parameters + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + // Quick return if possible + if n == 0 { + return + } + if n == 1 { + if d == blas.NonUnit { + x[0] /= a[0] + } + return + } + + var kx int + if incX < 0 { + kx = -(n - 1) * incX + } + nonUnit := d == blas.NonUnit + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + var sum float32 + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jv := i + j + 1 + sum += x[jv] * v + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+i] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + var sum float32 + jx := ix + incX + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + sum += x[jx] * v + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+i] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + var sum float32 + atmp := a[i*lda : i*lda+i] + for j, v := range atmp { + sum += x[j] * v + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+i] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + var sum float32 + atmp := a[i*lda : i*lda+i] + for _, v := range atmp { + sum += x[jx] * v + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+i] + } + ix += incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if nonUnit { + x[i] /= a[i*lda+i] + } + xi := x[i] + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jv := j + i + 1 + x[jv] -= v * xi + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + if nonUnit { + x[ix] /= a[i*lda+i] + } + xi := x[ix] + jx := kx + (i+1)*incX + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + x[jx] -= v * xi + jx += incX + } + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[i] /= a[i*lda+i] + } + xi := x[i] + atmp := a[i*lda : i*lda+i] + for j, v := range atmp { + x[j] -= v * xi + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[ix] /= a[i*lda+i] + } + xi := x[ix] + jx := kx + atmp := a[i*lda : i*lda+i] + for _, v := range atmp { + x[jx] -= v * xi + jx += incX + } + ix -= incX + } +} + +// Ssymv computes +// y = alpha * A * x + beta * y, +// where a is an n×n symmetric matrix, x and y are vectors, and alpha and +// beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssymv(ul blas.Uplo, n int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + // Check inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(negativeN) + } + if lda > 1 && lda < n { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up start points + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + // Form y = beta * y + if beta != 1 { + if incY > 0 { + Implementation{}.Sscal(n, beta, y, incY) + } else { + Implementation{}.Sscal(n, beta, y, -incY) + } + } + + if alpha == 0 { + return + } + + if n == 1 { + y[0] += alpha * a[0] * x[0] + return + } + + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + sum := x[i] * a[i*lda+i] + jy := ky + (i+1)*incY + atmp := a[i*lda+i+1 : i*lda+n] + for j, v := range atmp { + jp := j + i + 1 + sum += x[jp] * v + y[jy] += xv * v + jy += incY + } + y[iy] += alpha * sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + sum := x[ix] * a[i*lda+i] + jx := kx + (i+1)*incX + jy := ky + (i+1)*incY + atmp := a[i*lda+i+1 : i*lda+n] + for _, v := range atmp { + sum += x[jx] * v + y[jy] += xv * v + jx += incX + jy += incY + } + y[iy] += alpha * sum + ix += incX + iy += incY + } + return + } + // Cases where a is lower triangular. + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + jy := ky + xv := alpha * x[i] + atmp := a[i*lda : i*lda+i] + var sum float32 + for j, v := range atmp { + sum += x[j] * v + y[jy] += xv * v + jy += incY + } + sum += x[i] * a[i*lda+i] + sum *= alpha + y[iy] += sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + xv := alpha * x[ix] + atmp := a[i*lda : i*lda+i] + var sum float32 + for _, v := range atmp { + sum += x[jx] * v + y[jy] += xv * v + jx += incX + jy += incY + } + sum += x[ix] * a[i*lda+i] + sum *= alpha + y[iy] += sum + ix += incX + iy += incY + } +} + +// Stbmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular banded matrix with k diagonals, and x is a vector. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Stbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float32, lda int, x []float32, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } else if incX != 1 { + kx = 0 + } + + nonunit := d != blas.Unit + + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + u := min(1+k, n-i) + var sum float32 + atmp := a[i*lda:] + xtmp := x[i:] + for j := 1; j < u; j++ { + sum += xtmp[j] * atmp[j] + } + if nonunit { + sum += xtmp[0] * atmp[0] + } else { + sum += xtmp[0] + } + x[i] = sum + } + return + } + ix := kx + for i := 0; i < n; i++ { + u := min(1+k, n-i) + var sum float32 + atmp := a[i*lda:] + jx := incX + for j := 1; j < u; j++ { + sum += x[ix+jx] * atmp[j] + jx += incX + } + if nonunit { + sum += x[ix] * atmp[0] + } else { + sum += x[ix] + } + x[ix] = sum + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + l := max(0, k-i) + atmp := a[i*lda:] + var sum float32 + for j := l; j < k; j++ { + sum += x[i-k+j] * atmp[j] + } + if nonunit { + sum += x[i] * atmp[k] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + l := max(0, k-i) + atmp := a[i*lda:] + var sum float32 + jx := l * incX + for j := l; j < k; j++ { + sum += x[ix-k*incX+jx] * atmp[j] + jx += incX + } + if nonunit { + sum += x[ix] * atmp[k] + } else { + sum += x[ix] + } + x[ix] = sum + ix -= incX + } + return + } + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + u := k + 1 + if i < u { + u = i + 1 + } + var sum float32 + for j := 1; j < u; j++ { + sum += x[i-j] * a[(i-j)*lda+j] + } + if nonunit { + sum += x[i] * a[i*lda] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + u := k + 1 + if i < u { + u = i + 1 + } + var sum float32 + jx := incX + for j := 1; j < u; j++ { + sum += x[ix-jx] * a[(i-j)*lda+j] + jx += incX + } + if nonunit { + sum += x[ix] * a[i*lda] + } else { + sum += x[ix] + } + x[ix] = sum + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + u := k + if i+k >= n { + u = n - i - 1 + } + var sum float32 + for j := 0; j < u; j++ { + sum += x[i+j+1] * a[(i+j+1)*lda+k-j-1] + } + if nonunit { + sum += x[i] * a[i*lda+k] + } else { + sum += x[i] + } + x[i] = sum + } + return + } + ix := kx + for i := 0; i < n; i++ { + u := k + if i+k >= n { + u = n - i - 1 + } + var ( + sum float32 + jx int + ) + for j := 0; j < u; j++ { + sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] + jx += incX + } + if nonunit { + sum += x[ix] * a[i*lda+k] + } else { + sum += x[ix] + } + x[ix] = sum + ix += incX + } +} + +// Stpmv computes +// x = A * x if tA == blas.NoTrans +// x = A^T * x if tA == blas.Trans or blas.ConjTrans +// where A is an n×n unit triangular matrix in packed format, and x is a vector. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Stpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float32, x []float32, incX int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + + nonUnit := d == blas.NonUnit + var offset int // Offset is the index of (i,i) + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + if nonUnit { + xi *= ap[offset] + } + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xi += v * xtmp[j] + } + x[i] = xi + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + xix := x[ix] + if nonUnit { + xix *= ap[offset] + } + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + for _, v := range atmp { + xix += v * x[jx] + jx += incX + } + x[ix] = xix + offset += n - i + ix += incX + } + return + } + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xi := x[i] + if nonUnit { + xi *= ap[offset] + } + atmp := ap[offset-i : offset] + for j, v := range atmp { + xi += v * x[j] + } + x[i] = xi + offset -= i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xix := x[ix] + if nonUnit { + xix *= ap[offset] + } + atmp := ap[offset-i : offset] + jx := kx + for _, v := range atmp { + xix += v * x[jx] + jx += incX + } + x[ix] = xix + offset -= i + 1 + ix -= incX + } + return + } + // Cases where ap is transposed. + if ul == blas.Upper { + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xi := x[i] + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xtmp[j] += v * xi + } + if nonUnit { + x[i] *= ap[offset] + } + offset -= n - i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + xix := x[ix] + jx := kx + (i+1)*incX + atmp := ap[offset+1 : offset+n-i] + for _, v := range atmp { + x[jx] += v * xix + jx += incX + } + if nonUnit { + x[ix] *= ap[offset] + } + offset -= n - i + 1 + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + atmp := ap[offset-i : offset] + for j, v := range atmp { + x[j] += v * xi + } + if nonUnit { + x[i] *= ap[offset] + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + xix := x[ix] + jx := kx + atmp := ap[offset-i : offset] + for _, v := range atmp { + x[jx] += v * xix + jx += incX + } + if nonUnit { + x[ix] *= ap[offset] + } + ix += incX + offset += i + 2 + } +} + +// Stbsv solves +// A * x = b +// where A is an n×n triangular banded matrix with k diagonals in packed format, +// and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Stbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float32, lda int, x []float32, incX int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX < 0 { + kx = -(n - 1) * incX + } else { + kx = 0 + } + nonUnit := d == blas.NonUnit + // Form x = A^-1 x. + // Several cases below use subslices for speed improvement. + // The incX != 1 cases usually do not because incX may be negative. + if tA == blas.NoTrans { + if ul == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + atmp := a[i*lda+1:] + xtmp := x[i+1 : i+bands+1] + var sum float32 + for j, v := range xtmp { + sum += v * atmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + max := k + 1 + if i+max > n { + max = n - i + } + atmp := a[i*lda:] + var ( + jx int + sum float32 + ) + for j := 1; j < max; j++ { + jx += incX + sum += x[ix+jx] * atmp[j] + } + x[ix] -= sum + if nonUnit { + x[ix] /= atmp[0] + } + ix -= incX + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + atmp := a[i*lda+k-bands:] + xtmp := x[i-bands : i] + var sum float32 + for j, v := range xtmp { + sum += v * atmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= atmp[bands] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + atmp := a[i*lda+k-bands:] + var ( + sum float32 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix-bands*incX+jx] * atmp[j] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= atmp[bands] + } + ix += incX + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + var sum float32 + for j := 0; j < bands; j++ { + sum += x[i-bands+j] * a[(i-bands+j)*lda+bands-j] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda] + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + bands := k + if i-k < 0 { + bands = i + } + var ( + sum float32 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix-bands*incX+jx] * a[(i-bands+j)*lda+bands-j] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda] + } + ix += incX + } + return + } + if incX == 1 { + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + var sum float32 + xtmp := x[i+1 : i+1+bands] + for j, v := range xtmp { + sum += v * a[(i+j+1)*lda+k-j-1] + } + x[i] -= sum + if nonUnit { + x[i] /= a[i*lda+k] + } + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + bands := k + if i+bands >= n { + bands = n - i - 1 + } + var ( + sum float32 + jx int + ) + for j := 0; j < bands; j++ { + sum += x[ix+jx+incX] * a[(i+j+1)*lda+k-j-1] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= a[i*lda+k] + } + ix -= incX + } +} + +// Ssbmv performs +// y = alpha * A * x + beta * y +// where A is an n×n symmetric banded matrix, x and y are vectors, and alpha +// and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssbmv(ul blas.Uplo, n, k int, alpha float32, a []float32, lda int, x []float32, incX int, beta float32, y []float32, incY int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+k+1 > len(a) || lda < k+1 { + panic(badLdA) + } + + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up indexes + lenX := n + lenY := n + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(lenY - 1) * incY + } + + // First form y := beta * y + if incY > 0 { + Implementation{}.Sscal(lenY, beta, y, incY) + } else { + Implementation{}.Sscal(lenY, beta, y, -incY) + } + + if alpha == 0 { + return + } + + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + atmp := a[i*lda:] + tmp := alpha * x[i] + sum := tmp * atmp[0] + u := min(k, n-i-1) + jy := incY + for j := 1; j <= u; j++ { + v := atmp[j] + sum += alpha * x[i+j] * v + y[iy+jy] += tmp * v + jy += incY + } + y[iy] += sum + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + atmp := a[i*lda:] + tmp := alpha * x[ix] + sum := tmp * atmp[0] + u := min(k, n-i-1) + jx := incX + jy := incY + for j := 1; j <= u; j++ { + v := atmp[j] + sum += alpha * x[ix+jx] * v + y[iy+jy] += tmp * v + jx += incX + jy += incY + } + y[iy] += sum + ix += incX + iy += incY + } + return + } + + // Casses where a has bands below the diagonal. + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + l := max(0, k-i) + tmp := alpha * x[i] + jy := l * incY + atmp := a[i*lda:] + for j := l; j < k; j++ { + v := atmp[j] + y[iy] += alpha * v * x[i-k+j] + y[iy-k*incY+jy] += tmp * v + jy += incY + } + y[iy] += tmp * atmp[k] + iy += incY + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + l := max(0, k-i) + tmp := alpha * x[ix] + jx := l * incX + jy := l * incY + atmp := a[i*lda:] + for j := l; j < k; j++ { + v := atmp[j] + y[iy] += alpha * v * x[ix-k*incX+jx] + y[iy-k*incY+jy] += tmp * v + jx += incX + jy += incY + } + y[iy] += tmp * atmp[k] + ix += incX + iy += incY + } + return +} + +// Ssyr performs the rank-one update +// a += alpha * x * x^T +// where a is an n×n symmetric matrix, and x is a vector. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssyr(ul blas.Uplo, n int, alpha float32, x []float32, incX int, a []float32, lda int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if alpha == 0 || n == 0 { + return + } + + lenX := n + var kx int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + tmp := x[i] * alpha + if tmp != 0 { + atmp := a[i*lda+i : i*lda+n] + xtmp := x[i:n] + for j, v := range xtmp { + atmp[j] += v * tmp + } + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + tmp := x[ix] * alpha + if tmp != 0 { + jx := ix + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += x[jx] * tmp + jx += incX + } + } + ix += incX + } + return + } + // Cases where a is lower triangular. + if incX == 1 { + for i := 0; i < n; i++ { + tmp := x[i] * alpha + if tmp != 0 { + atmp := a[i*lda:] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += tmp * v + } + } + } + return + } + ix := kx + for i := 0; i < n; i++ { + tmp := x[ix] * alpha + if tmp != 0 { + atmp := a[i*lda:] + jx := kx + for j := 0; j < i+1; j++ { + atmp[j] += tmp * x[jx] + jx += incX + } + } + ix += incX + } +} + +// Ssyr2 performs the symmetric rank-two update +// A += alpha * x * y^T + alpha * y * x^T +// where A is a symmetric n×n matrix, x and y are vectors, and alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssyr2(ul blas.Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, a []float32, lda int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if lda*(n-1)+n > len(a) || lda < max(1, n) { + panic(badLdA) + } + if alpha == 0 { + return + } + + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if ul == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + xi := x[i] + yi := y[i] + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += alpha * (xi*y[j] + x[j]*yi) + } + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + i*incX + jy := ky + i*incY + xi := x[ix] + yi := y[iy] + atmp := a[i*lda:] + for j := i; j < n; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + } + return + } + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + xi := x[i] + yi := y[i] + atmp := a[i*lda:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (xi*y[j] + x[j]*yi) + } + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + xi := x[ix] + yi := y[iy] + atmp := a[i*lda:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + } + return +} + +// Stpsv solves +// A * x = b if tA == blas.NoTrans +// A^T * x = b if tA == blas.Trans or blas.ConjTrans +// where A is an n×n triangular matrix in packed format and x is a vector. +// At entry to the function, x contains the values of b, and the result is +// stored in place into x. +// +// No test for singularity or near-singularity is included in this +// routine. Such tests must be performed before calling this routine. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Stpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float32, x []float32, incX int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if n < 0 { + panic(nLT0) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if n == 0 { + return + } + var kx int + if incX <= 0 { + kx = -(n - 1) * incX + } + + nonUnit := d == blas.NonUnit + var offset int // Offset is the index of (i,i) + if tA == blas.NoTrans { + if ul == blas.Upper { + offset = n*(n+1)/2 - 1 + if incX == 1 { + for i := n - 1; i >= 0; i-- { + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + var sum float32 + for j, v := range atmp { + sum += v * xtmp[j] + } + x[i] -= sum + if nonUnit { + x[i] /= ap[offset] + } + offset -= n - i + 1 + } + return + } + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + var sum float32 + for _, v := range atmp { + sum += v * x[jx] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= ap[offset] + } + ix -= incX + offset -= n - i + 1 + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset-i : offset] + var sum float32 + for j, v := range atmp { + sum += v * x[j] + } + x[i] -= sum + if nonUnit { + x[i] /= ap[offset] + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + atmp := ap[offset-i : offset] + var sum float32 + for _, v := range atmp { + sum += v * x[jx] + jx += incX + } + x[ix] -= sum + if nonUnit { + x[ix] /= ap[offset] + } + ix += incX + offset += i + 2 + } + return + } + // Cases where ap is transposed. + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if nonUnit { + x[i] /= ap[offset] + } + xi := x[i] + atmp := ap[offset+1 : offset+n-i] + xtmp := x[i+1:] + for j, v := range atmp { + xtmp[j] -= v * xi + } + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + if nonUnit { + x[ix] /= ap[offset] + } + xix := x[ix] + atmp := ap[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + for _, v := range atmp { + x[jx] -= v * xix + jx += incX + } + ix += incX + offset += n - i + } + return + } + if incX == 1 { + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[i] /= ap[offset] + } + xi := x[i] + atmp := ap[offset-i : offset] + for j, v := range atmp { + x[j] -= v * xi + } + offset -= i + 1 + } + return + } + ix := kx + (n-1)*incX + offset = n*(n+1)/2 - 1 + for i := n - 1; i >= 0; i-- { + if nonUnit { + x[ix] /= ap[offset] + } + xix := x[ix] + atmp := ap[offset-i : offset] + jx := kx + for _, v := range atmp { + x[jx] -= v * xix + jx += incX + } + ix -= incX + offset -= i + 1 + } +} + +// Sspmv performs +// y = alpha * A * x + beta * y, +// where A is an n×n symmetric matrix in packed format, x and y are vectors +// and alpha and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x []float32, incX int, beta float32, y []float32, incY int) { + // Verify inputs + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if len(a) < (n*(n+1))/2 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + // Quick return if possible + if n == 0 || (alpha == 0 && beta == 1) { + return + } + + // Set up start points + var kx, ky int + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + + // Form y = beta * y + if beta != 1 { + if incY > 0 { + Implementation{}.Sscal(n, beta, y, incY) + } else { + Implementation{}.Sscal(n, beta, y, -incY) + } + } + + if alpha == 0 { + return + } + + if n == 1 { + y[0] += alpha * a[0] * x[0] + return + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + sum := a[offset] * x[i] + atmp := a[offset+1 : offset+n-i] + xtmp := x[i+1:] + jy := ky + (i+1)*incY + for j, v := range atmp { + sum += v * xtmp[j] + y[jy] += v * xv + jy += incY + } + y[iy] += alpha * sum + iy += incY + offset += n - i + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + sum := a[offset] * x[ix] + atmp := a[offset+1 : offset+n-i] + jx := kx + (i+1)*incX + jy := ky + (i+1)*incY + for _, v := range atmp { + sum += v * x[jx] + y[jy] += v * xv + jx += incX + jy += incY + } + y[iy] += alpha * sum + ix += incX + iy += incY + offset += n - i + } + return + } + if incX == 1 { + iy := ky + for i := 0; i < n; i++ { + xv := x[i] * alpha + atmp := a[offset-i : offset] + jy := ky + var sum float32 + for j, v := range atmp { + sum += v * x[j] + y[jy] += v * xv + jy += incY + } + sum += a[offset] * x[i] + y[iy] += alpha * sum + iy += incY + offset += i + 2 + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + xv := x[ix] * alpha + atmp := a[offset-i : offset] + jx := kx + jy := ky + var sum float32 + for _, v := range atmp { + sum += v * x[jx] + y[jy] += v * xv + jx += incX + jy += incY + } + + sum += a[offset] * x[ix] + y[iy] += alpha * sum + ix += incX + iy += incY + offset += i + 2 + } +} + +// Sspr computes the rank-one operation +// a += alpha * x * x^T +// where a is an n×n symmetric matrix in packed format, x is a vector, and +// alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX int, a []float32) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if len(a) < (n*(n+1))/2 { + panic(badLdA) + } + if alpha == 0 || n == 0 { + return + } + lenX := n + var kx int + if incX > 0 { + kx = 0 + } else { + kx = -(lenX - 1) * incX + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + atmp := a[offset:] + xv := alpha * x[i] + xtmp := x[i:n] + for j, v := range xtmp { + atmp[j] += xv * v + } + offset += n - i + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + i*incX + atmp := a[offset:] + xv := alpha * x[ix] + for j := 0; j < n-i; j++ { + atmp[j] += xv * x[jx] + jx += incX + } + ix += incX + offset += n - i + } + return + } + if incX == 1 { + for i := 0; i < n; i++ { + atmp := a[offset-i:] + xv := alpha * x[i] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += xv * v + } + offset += i + 2 + } + return + } + ix := kx + for i := 0; i < n; i++ { + jx := kx + atmp := a[offset-i:] + xv := alpha * x[ix] + for j := 0; j <= i; j++ { + atmp[j] += xv * x[jx] + jx += incX + } + ix += incX + offset += i + 2 + } +} + +// Sspr2 performs the symmetric rank-2 update +// A += alpha * x * y^T + alpha * y * x^T, +// where A is an n×n symmetric matrix in packed format, x and y are vectors, +// and alpha is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sspr2(ul blas.Uplo, n int, alpha float32, x []float32, incX int, y []float32, incY int, ap []float32) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(badX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(badY) + } + if len(ap) < (n*(n+1))/2 { + panic(badLdA) + } + if alpha == 0 { + return + } + var ky, kx int + if incY > 0 { + ky = 0 + } else { + ky = -(n - 1) * incY + } + if incX > 0 { + kx = 0 + } else { + kx = -(n - 1) * incX + } + var offset int // Offset is the index of (i,i). + if ul == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset:] + xi := x[i] + yi := y[i] + xtmp := x[i:n] + ytmp := y[i:n] + for j, v := range xtmp { + atmp[j] += alpha * (xi*ytmp[j] + v*yi) + } + offset += n - i + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + i*incX + jy := ky + i*incY + atmp := ap[offset:] + xi := x[ix] + yi := y[iy] + for j := 0; j < n-i; j++ { + atmp[j] += alpha * (xi*y[jy] + x[jx]*yi) + jx += incX + jy += incY + } + ix += incX + iy += incY + offset += n - i + } + return + } + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + atmp := ap[offset-i:] + xi := x[i] + yi := y[i] + xtmp := x[:i+1] + for j, v := range xtmp { + atmp[j] += alpha * (xi*y[j] + v*yi) + } + offset += i + 2 + } + return + } + ix := kx + iy := ky + for i := 0; i < n; i++ { + jx := kx + jy := ky + atmp := ap[offset-i:] + for j := 0; j <= i; j++ { + atmp[j] += alpha * (x[ix]*y[jy] + x[jx]*y[iy]) + jx += incX + jy += incY + } + ix += incX + iy += incY + offset += i + 2 + } +} diff --git a/blas/native/level3double.go b/blas/native/level3double.go new file mode 100644 index 00000000..8605cdbb --- /dev/null +++ b/blas/native/level3double.go @@ -0,0 +1,831 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f64" +) + +var _ blas.Float64Level3 = Implementation{} + +// Dtrsm solves +// A * X = alpha * B, if tA == blas.NoTrans side == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans side == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, X is an m×n matrix, and alpha is a +// scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in place into X. +// +// No check is made that A is invertible. +func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) { + if s != blas.Left && s != blas.Right { + panic(badSide) + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if ldb < n { + panic(badLdB) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + + if m == 0 || n == 0 { + return + } + + if alpha == 0 { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] = 0 + } + } + return + } + nonUnit := d == blas.NonUnit + if s == blas.Left { + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := m - 1; i >= 0; i-- { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := range btmp { + btmp[j] *= alpha + } + } + for ka, va := range a[i*lda+i+1 : i*lda+m] { + k := ka + i + 1 + if va != 0 { + f64.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + } + } + if nonUnit { + tmp := 1 / a[i*lda+i] + for j := 0; j < n; j++ { + btmp[j] *= tmp + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k, va := range a[i*lda : i*lda+i] { + if va != 0 { + f64.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + } + } + if nonUnit { + tmp := 1 / a[i*lda+i] + for j := 0; j < n; j++ { + btmp[j] *= tmp + } + } + } + return + } + // Cases where a is transposed + if ul == blas.Upper { + for k := 0; k < m; k++ { + btmpk := b[k*ldb : k*ldb+n] + if nonUnit { + tmp := 1 / a[k*lda+k] + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + for ia, va := range a[k*lda+k+1 : k*lda+m] { + i := ia + k + 1 + if va != 0 { + btmp := b[i*ldb : i*ldb+n] + f64.AxpyUnitaryTo(btmp, -va, btmpk, btmp) + } + } + if alpha != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= alpha + } + } + } + return + } + for k := m - 1; k >= 0; k-- { + btmpk := b[k*ldb : k*ldb+n] + if nonUnit { + tmp := 1 / a[k*lda+k] + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + for i, va := range a[k*lda : k*lda+k] { + if va != 0 { + btmp := b[i*ldb : i*ldb+n] + f64.AxpyUnitaryTo(btmp, -va, btmpk, btmp) + } + } + if alpha != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= alpha + } + } + } + return + } + // Cases where a is to the right of X. + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k, vb := range btmp { + if vb != 0 { + if btmp[k] != 0 { + if nonUnit { + btmp[k] /= a[k*lda+k] + } + btmpk := btmp[k+1 : n] + f64.AxpyUnitaryTo(btmpk, -btmp[k], a[k*lda+k+1:k*lda+n], btmpk) + } + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k := n - 1; k >= 0; k-- { + if btmp[k] != 0 { + if nonUnit { + btmp[k] /= a[k*lda+k] + } + f64.AxpyUnitaryTo(btmp, -btmp[k], a[k*lda:k*lda+k], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + for j := n - 1; j >= 0; j-- { + tmp := alpha*btmp[j] - f64.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:]) + if nonUnit { + tmp /= a[j*lda+j] + } + btmp[j] = tmp + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + for j := 0; j < n; j++ { + tmp := alpha*btmp[j] - f64.DotUnitary(a[j*lda:j*lda+j], btmp) + if nonUnit { + tmp /= a[j*lda+j] + } + btmp[j] = tmp + } + } +} + +// Dsymm performs one of +// C = alpha * A * B + beta * C, if side == blas.Left, +// C = alpha * B * A + beta * C, if side == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and alpha +// is a scalar. +func (Implementation) Dsymm(s blas.Side, ul blas.Uplo, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { + if s != blas.Right && s != blas.Left { + panic("goblas: bad side") + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if m == 0 || n == 0 { + return + } + if alpha == 0 && beta == 1 { + return + } + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := 0; j < n; j++ { + ctmp[j] *= beta + } + } + return + } + + isUpper := ul == blas.Upper + if s == blas.Left { + for i := 0; i < m; i++ { + atmp := alpha * a[i*lda+i] + btmp := b[i*ldb : i*ldb+n] + ctmp := c[i*ldc : i*ldc+n] + for j, v := range btmp { + ctmp[j] *= beta + ctmp[j] += atmp * v + } + + for k := 0; k < i; k++ { + var atmp float64 + if isUpper { + atmp = a[k*lda+i] + } else { + atmp = a[i*lda+k] + } + atmp *= alpha + ctmp := c[i*ldc : i*ldc+n] + f64.AxpyUnitaryTo(ctmp, atmp, b[k*ldb:k*ldb+n], ctmp) + } + for k := i + 1; k < m; k++ { + var atmp float64 + if isUpper { + atmp = a[i*lda+k] + } else { + atmp = a[k*lda+i] + } + atmp *= alpha + ctmp := c[i*ldc : i*ldc+n] + f64.AxpyUnitaryTo(ctmp, atmp, b[k*ldb:k*ldb+n], ctmp) + } + } + return + } + if isUpper { + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + tmp := alpha * b[i*ldb+j] + var tmp2 float64 + atmp := a[j*lda+j+1 : j*lda+n] + btmp := b[i*ldb+j+1 : i*ldb+n] + ctmp := c[i*ldc+j+1 : i*ldc+n] + for k, v := range atmp { + ctmp[k] += tmp * v + tmp2 += btmp[k] * v + } + c[i*ldc+j] *= beta + c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 + } + } + return + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + tmp := alpha * b[i*ldb+j] + var tmp2 float64 + atmp := a[j*lda : j*lda+j] + btmp := b[i*ldb : i*ldb+j] + ctmp := c[i*ldc : i*ldc+j] + for k, v := range atmp { + ctmp[k] += tmp * v + tmp2 += btmp[k] * v + } + c[i*ldc+j] *= beta + c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 + } + } +} + +// Dsyrk performs the symmetric rank-k operation +// C = alpha * A * A^T + beta*C +// C is an n×n symmetric matrix. A is an n×k matrix if tA == blas.NoTrans, and +// a k×n matrix otherwise. alpha and beta are scalars. +func (Implementation) Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64, ldc int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { + panic(badTranspose) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if ldc < n { + panic(badLdC) + } + var row, col int + if tA == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic(badLdA) + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if alpha == 0 { + if beta == 0 { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + atmp := a[i*lda : i*lda+k] + for jc, vc := range ctmp { + j := jc + i + ctmp[jc] = vc*beta + alpha*f64.DotUnitary(atmp, a[j*lda:j*lda+k]) + } + } + return + } + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + for j, vc := range c[i*ldc : i*ldc+i+1] { + c[i*ldc+j] = vc*beta + alpha*f64.DotUnitary(a[j*lda:j*lda+k], atmp) + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[l*lda+i] + if tmp != 0 { + f64.AxpyUnitaryTo(ctmp, tmp, a[l*lda+i:l*lda+n], ctmp) + } + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + if beta != 0 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[l*lda+i] + if tmp != 0 { + f64.AxpyUnitaryTo(ctmp, tmp, a[l*lda:l*lda+i+1], ctmp) + } + } + } +} + +// Dsyr2k performs the symmetric rank 2k operation +// C = alpha * A * B^T + alpha * B * A^T + beta * C +// where C is an n×n symmetric matrix. A and B are n×k matrices if +// tA == NoTrans and k×n otherwise. alpha and beta are scalars. +func (Implementation) Dsyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { + panic(badTranspose) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if ldc < n { + panic(badLdC) + } + var row, col int + if tA == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic(badLdA) + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic(badLdB) + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if alpha == 0 { + if beta == 0 { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + btmp := b[i*ldb : i*ldb+k] + ctmp := c[i*ldc+i : i*ldc+n] + for jc := range ctmp { + j := i + jc + var tmp1, tmp2 float64 + binner := b[j*ldb : j*ldb+k] + for l, v := range a[j*lda : j*lda+k] { + tmp1 += v * btmp[l] + tmp2 += atmp[l] * binner[l] + } + ctmp[jc] *= beta + ctmp[jc] += alpha * (tmp1 + tmp2) + } + } + return + } + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + btmp := b[i*ldb : i*ldb+k] + ctmp := c[i*ldc : i*ldc+i+1] + for j := 0; j <= i; j++ { + var tmp1, tmp2 float64 + binner := b[j*ldb : j*ldb+k] + for l, v := range a[j*lda : j*lda+k] { + tmp1 += v * btmp[l] + tmp2 += atmp[l] * binner[l] + } + ctmp[j] *= beta + ctmp[j] += alpha * (tmp1 + tmp2) + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp1 := alpha * b[l*lda+i] + tmp2 := alpha * a[l*lda+i] + btmp := b[l*ldb+i : l*ldb+n] + if tmp1 != 0 || tmp2 != 0 { + for j, v := range a[l*lda+i : l*lda+n] { + ctmp[j] += v*tmp1 + btmp[j]*tmp2 + } + } + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp1 := alpha * b[l*lda+i] + tmp2 := alpha * a[l*lda+i] + btmp := b[l*ldb : l*ldb+i+1] + if tmp1 != 0 || tmp2 != 0 { + for j, v := range a[l*lda : l*lda+i+1] { + ctmp[j] += v*tmp1 + btmp[j]*tmp2 + } + } + } + } +} + +// Dtrmm performs +// B = alpha * A * B, if tA == blas.NoTrans and side == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and side == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, and B is an m×n matrix. +func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) { + if s != blas.Left && s != blas.Right { + panic(badSide) + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + if alpha == 0 { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] = 0 + } + } + return + } + + nonUnit := d == blas.NonUnit + if s == blas.Left { + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + tmp := alpha + if nonUnit { + tmp *= a[i*lda+i] + } + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] *= tmp + } + for ka, va := range a[i*lda+i+1 : i*lda+m] { + k := ka + i + 1 + tmp := alpha * va + if tmp != 0 { + f64.AxpyUnitaryTo(btmp, tmp, b[k*ldb:k*ldb+n], btmp) + } + } + } + return + } + for i := m - 1; i >= 0; i-- { + tmp := alpha + if nonUnit { + tmp *= a[i*lda+i] + } + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] *= tmp + } + for k, va := range a[i*lda : i*lda+i] { + tmp := alpha * va + if tmp != 0 { + f64.AxpyUnitaryTo(btmp, tmp, b[k*ldb:k*ldb+n], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for k := m - 1; k >= 0; k-- { + btmpk := b[k*ldb : k*ldb+n] + for ia, va := range a[k*lda+k+1 : k*lda+m] { + i := ia + k + 1 + btmp := b[i*ldb : i*ldb+n] + tmp := alpha * va + if tmp != 0 { + f64.AxpyUnitaryTo(btmp, tmp, btmpk, btmp) + } + } + tmp := alpha + if nonUnit { + tmp *= a[k*lda+k] + } + if tmp != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + } + return + } + for k := 0; k < m; k++ { + btmpk := b[k*ldb : k*ldb+n] + for i, va := range a[k*lda : k*lda+k] { + btmp := b[i*ldb : i*ldb+n] + tmp := alpha * va + if tmp != 0 { + f64.AxpyUnitaryTo(btmp, tmp, btmpk, btmp) + } + } + tmp := alpha + if nonUnit { + tmp *= a[k*lda+k] + } + if tmp != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + } + return + } + // Cases where a is on the right + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for k := n - 1; k >= 0; k-- { + tmp := alpha * btmp[k] + if tmp != 0 { + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + for ja, v := range a[k*lda+k+1 : k*lda+n] { + j := ja + k + 1 + btmp[j] += tmp * v + } + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for k := 0; k < n; k++ { + tmp := alpha * btmp[k] + if tmp != 0 { + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + f64.AxpyUnitaryTo(btmp, tmp, a[k*lda:k*lda+k], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j, vb := range btmp { + tmp := vb + if nonUnit { + tmp *= a[j*lda+j] + } + tmp += f64.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:n]) + btmp[j] = alpha * tmp + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := n - 1; j >= 0; j-- { + tmp := btmp[j] + if nonUnit { + tmp *= a[j*lda+j] + } + tmp += f64.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) + btmp[j] = alpha * tmp + } + } +} diff --git a/blas/native/level3double_test.go b/blas/native/level3double_test.go new file mode 100644 index 00000000..c2123a7e --- /dev/null +++ b/blas/native/level3double_test.go @@ -0,0 +1,35 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "testing" + + "gonum.org/v1/gonum/blas/testblas" +) + +func TestDgemm(t *testing.T) { + testblas.TestDgemm(t, impl) +} + +func TestDsymm(t *testing.T) { + testblas.DsymmTest(t, impl) +} + +func TestDtrsm(t *testing.T) { + testblas.DtrsmTest(t, impl) +} + +func TestDsyrk(t *testing.T) { + testblas.DsyrkTest(t, impl) +} + +func TestDsyr2k(t *testing.T) { + testblas.Dsyr2kTest(t, impl) +} + +func TestDtrmm(t *testing.T) { + testblas.DtrmmTest(t, impl) +} diff --git a/blas/native/level3single.go b/blas/native/level3single.go new file mode 100644 index 00000000..ead11996 --- /dev/null +++ b/blas/native/level3single.go @@ -0,0 +1,843 @@ +// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT. + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f32" +) + +var _ blas.Float32Level3 = Implementation{} + +// Strsm solves +// A * X = alpha * B, if tA == blas.NoTrans side == blas.Left, +// A^T * X = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// X * A = alpha * B, if tA == blas.NoTrans side == blas.Right, +// X * A^T = alpha * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, X is an m×n matrix, and alpha is a +// scalar. +// +// At entry to the function, X contains the values of B, and the result is +// stored in place into X. +// +// No check is made that A is invertible. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) { + if s != blas.Left && s != blas.Right { + panic(badSide) + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if ldb < n { + panic(badLdB) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + + if m == 0 || n == 0 { + return + } + + if alpha == 0 { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] = 0 + } + } + return + } + nonUnit := d == blas.NonUnit + if s == blas.Left { + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := m - 1; i >= 0; i-- { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := range btmp { + btmp[j] *= alpha + } + } + for ka, va := range a[i*lda+i+1 : i*lda+m] { + k := ka + i + 1 + if va != 0 { + f32.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + } + } + if nonUnit { + tmp := 1 / a[i*lda+i] + for j := 0; j < n; j++ { + btmp[j] *= tmp + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k, va := range a[i*lda : i*lda+i] { + if va != 0 { + f32.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + } + } + if nonUnit { + tmp := 1 / a[i*lda+i] + for j := 0; j < n; j++ { + btmp[j] *= tmp + } + } + } + return + } + // Cases where a is transposed + if ul == blas.Upper { + for k := 0; k < m; k++ { + btmpk := b[k*ldb : k*ldb+n] + if nonUnit { + tmp := 1 / a[k*lda+k] + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + for ia, va := range a[k*lda+k+1 : k*lda+m] { + i := ia + k + 1 + if va != 0 { + btmp := b[i*ldb : i*ldb+n] + f32.AxpyUnitaryTo(btmp, -va, btmpk, btmp) + } + } + if alpha != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= alpha + } + } + } + return + } + for k := m - 1; k >= 0; k-- { + btmpk := b[k*ldb : k*ldb+n] + if nonUnit { + tmp := 1 / a[k*lda+k] + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + for i, va := range a[k*lda : k*lda+k] { + if va != 0 { + btmp := b[i*ldb : i*ldb+n] + f32.AxpyUnitaryTo(btmp, -va, btmpk, btmp) + } + } + if alpha != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= alpha + } + } + } + return + } + // Cases where a is to the right of X. + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k, vb := range btmp { + if vb != 0 { + if btmp[k] != 0 { + if nonUnit { + btmp[k] /= a[k*lda+k] + } + btmpk := btmp[k+1 : n] + f32.AxpyUnitaryTo(btmpk, -btmp[k], a[k*lda+k+1:k*lda+n], btmpk) + } + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + if alpha != 1 { + for j := 0; j < n; j++ { + btmp[j] *= alpha + } + } + for k := n - 1; k >= 0; k-- { + if btmp[k] != 0 { + if nonUnit { + btmp[k] /= a[k*lda+k] + } + f32.AxpyUnitaryTo(btmp, -btmp[k], a[k*lda:k*lda+k], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + for j := n - 1; j >= 0; j-- { + tmp := alpha*btmp[j] - f32.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:]) + if nonUnit { + tmp /= a[j*lda+j] + } + btmp[j] = tmp + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*lda : i*lda+n] + for j := 0; j < n; j++ { + tmp := alpha*btmp[j] - f32.DotUnitary(a[j*lda:j*lda+j], btmp) + if nonUnit { + tmp /= a[j*lda+j] + } + btmp[j] = tmp + } + } +} + +// Ssymm performs one of +// C = alpha * A * B + beta * C, if side == blas.Left, +// C = alpha * B * A + beta * C, if side == blas.Right, +// where A is an n×n or m×m symmetric matrix, B and C are m×n matrices, and alpha +// is a scalar. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssymm(s blas.Side, ul blas.Uplo, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { + if s != blas.Right && s != blas.Left { + panic("goblas: bad side") + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if m == 0 || n == 0 { + return + } + if alpha == 0 && beta == 1 { + return + } + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := 0; j < n; j++ { + ctmp[j] *= beta + } + } + return + } + + isUpper := ul == blas.Upper + if s == blas.Left { + for i := 0; i < m; i++ { + atmp := alpha * a[i*lda+i] + btmp := b[i*ldb : i*ldb+n] + ctmp := c[i*ldc : i*ldc+n] + for j, v := range btmp { + ctmp[j] *= beta + ctmp[j] += atmp * v + } + + for k := 0; k < i; k++ { + var atmp float32 + if isUpper { + atmp = a[k*lda+i] + } else { + atmp = a[i*lda+k] + } + atmp *= alpha + ctmp := c[i*ldc : i*ldc+n] + f32.AxpyUnitaryTo(ctmp, atmp, b[k*ldb:k*ldb+n], ctmp) + } + for k := i + 1; k < m; k++ { + var atmp float32 + if isUpper { + atmp = a[i*lda+k] + } else { + atmp = a[k*lda+i] + } + atmp *= alpha + ctmp := c[i*ldc : i*ldc+n] + f32.AxpyUnitaryTo(ctmp, atmp, b[k*ldb:k*ldb+n], ctmp) + } + } + return + } + if isUpper { + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + tmp := alpha * b[i*ldb+j] + var tmp2 float32 + atmp := a[j*lda+j+1 : j*lda+n] + btmp := b[i*ldb+j+1 : i*ldb+n] + ctmp := c[i*ldc+j+1 : i*ldc+n] + for k, v := range atmp { + ctmp[k] += tmp * v + tmp2 += btmp[k] * v + } + c[i*ldc+j] *= beta + c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 + } + } + return + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + tmp := alpha * b[i*ldb+j] + var tmp2 float32 + atmp := a[j*lda : j*lda+j] + btmp := b[i*ldb : i*ldb+j] + ctmp := c[i*ldc : i*ldc+j] + for k, v := range atmp { + ctmp[k] += tmp * v + tmp2 += btmp[k] * v + } + c[i*ldc+j] *= beta + c[i*ldc+j] += tmp*a[j*lda+j] + alpha*tmp2 + } + } +} + +// Ssyrk performs the symmetric rank-k operation +// C = alpha * A * A^T + beta*C +// C is an n×n symmetric matrix. A is an n×k matrix if tA == blas.NoTrans, and +// a k×n matrix otherwise. alpha and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float32, a []float32, lda int, beta float32, c []float32, ldc int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { + panic(badTranspose) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if ldc < n { + panic(badLdC) + } + var row, col int + if tA == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic(badLdA) + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if alpha == 0 { + if beta == 0 { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + atmp := a[i*lda : i*lda+k] + for jc, vc := range ctmp { + j := jc + i + ctmp[jc] = vc*beta + alpha*f32.DotUnitary(atmp, a[j*lda:j*lda+k]) + } + } + return + } + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + for j, vc := range c[i*ldc : i*ldc+i+1] { + c[i*ldc+j] = vc*beta + alpha*f32.DotUnitary(a[j*lda:j*lda+k], atmp) + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[l*lda+i] + if tmp != 0 { + f32.AxpyUnitaryTo(ctmp, tmp, a[l*lda+i:l*lda+n], ctmp) + } + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + if beta != 0 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[l*lda+i] + if tmp != 0 { + f32.AxpyUnitaryTo(ctmp, tmp, a[l*lda:l*lda+i+1], ctmp) + } + } + } +} + +// Ssyr2k performs the symmetric rank 2k operation +// C = alpha * A * B^T + alpha * B * A^T + beta * C +// where C is an n×n symmetric matrix. A and B are n×k matrices if +// tA == NoTrans and k×n otherwise. alpha and beta are scalars. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Ssyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.Trans && tA != blas.NoTrans && tA != blas.ConjTrans { + panic(badTranspose) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if ldc < n { + panic(badLdC) + } + var row, col int + if tA == blas.NoTrans { + row, col = n, k + } else { + row, col = k, n + } + if lda*(row-1)+col > len(a) || lda < max(1, col) { + panic(badLdA) + } + if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + panic(badLdB) + } + if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + panic(badLdC) + } + if alpha == 0 { + if beta == 0 { + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] = 0 + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + for j := range ctmp { + ctmp[j] *= beta + } + } + return + } + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + btmp := b[i*ldb : i*ldb+k] + ctmp := c[i*ldc+i : i*ldc+n] + for jc := range ctmp { + j := i + jc + var tmp1, tmp2 float32 + binner := b[j*ldb : j*ldb+k] + for l, v := range a[j*lda : j*lda+k] { + tmp1 += v * btmp[l] + tmp2 += atmp[l] * binner[l] + } + ctmp[jc] *= beta + ctmp[jc] += alpha * (tmp1 + tmp2) + } + } + return + } + for i := 0; i < n; i++ { + atmp := a[i*lda : i*lda+k] + btmp := b[i*ldb : i*ldb+k] + ctmp := c[i*ldc : i*ldc+i+1] + for j := 0; j <= i; j++ { + var tmp1, tmp2 float32 + binner := b[j*ldb : j*ldb+k] + for l, v := range a[j*lda : j*lda+k] { + tmp1 += v * btmp[l] + tmp2 += atmp[l] * binner[l] + } + ctmp[j] *= beta + ctmp[j] += alpha * (tmp1 + tmp2) + } + } + return + } + if ul == blas.Upper { + for i := 0; i < n; i++ { + ctmp := c[i*ldc+i : i*ldc+n] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp1 := alpha * b[l*lda+i] + tmp2 := alpha * a[l*lda+i] + btmp := b[l*ldb+i : l*ldb+n] + if tmp1 != 0 || tmp2 != 0 { + for j, v := range a[l*lda+i : l*lda+n] { + ctmp[j] += v*tmp1 + btmp[j]*tmp2 + } + } + } + } + return + } + for i := 0; i < n; i++ { + ctmp := c[i*ldc : i*ldc+i+1] + if beta != 1 { + for j := range ctmp { + ctmp[j] *= beta + } + } + for l := 0; l < k; l++ { + tmp1 := alpha * b[l*lda+i] + tmp2 := alpha * a[l*lda+i] + btmp := b[l*ldb : l*ldb+i+1] + if tmp1 != 0 || tmp2 != 0 { + for j, v := range a[l*lda : l*lda+i+1] { + ctmp[j] += v*tmp1 + btmp[j]*tmp2 + } + } + } + } +} + +// Strmm performs +// B = alpha * A * B, if tA == blas.NoTrans and side == blas.Left, +// B = alpha * A^T * B, if tA == blas.Trans or blas.ConjTrans, and side == blas.Left, +// B = alpha * B * A, if tA == blas.NoTrans and side == blas.Right, +// B = alpha * B * A^T, if tA == blas.Trans or blas.ConjTrans, and side == blas.Right, +// where A is an n×n or m×m triangular matrix, and B is an m×n matrix. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float32, a []float32, lda int, b []float32, ldb int) { + if s != blas.Left && s != blas.Right { + panic(badSide) + } + if ul != blas.Lower && ul != blas.Upper { + panic(badUplo) + } + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if d != blas.NonUnit && d != blas.Unit { + panic(badDiag) + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + var k int + if s == blas.Left { + k = m + } else { + k = n + } + if lda*(k-1)+k > len(a) || lda < max(1, k) { + panic(badLdA) + } + if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + panic(badLdB) + } + if alpha == 0 { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] = 0 + } + } + return + } + + nonUnit := d == blas.NonUnit + if s == blas.Left { + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + tmp := alpha + if nonUnit { + tmp *= a[i*lda+i] + } + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] *= tmp + } + for ka, va := range a[i*lda+i+1 : i*lda+m] { + k := ka + i + 1 + tmp := alpha * va + if tmp != 0 { + f32.AxpyUnitaryTo(btmp, tmp, b[k*ldb:k*ldb+n], btmp) + } + } + } + return + } + for i := m - 1; i >= 0; i-- { + tmp := alpha + if nonUnit { + tmp *= a[i*lda+i] + } + btmp := b[i*ldb : i*ldb+n] + for j := range btmp { + btmp[j] *= tmp + } + for k, va := range a[i*lda : i*lda+i] { + tmp := alpha * va + if tmp != 0 { + f32.AxpyUnitaryTo(btmp, tmp, b[k*ldb:k*ldb+n], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for k := m - 1; k >= 0; k-- { + btmpk := b[k*ldb : k*ldb+n] + for ia, va := range a[k*lda+k+1 : k*lda+m] { + i := ia + k + 1 + btmp := b[i*ldb : i*ldb+n] + tmp := alpha * va + if tmp != 0 { + f32.AxpyUnitaryTo(btmp, tmp, btmpk, btmp) + } + } + tmp := alpha + if nonUnit { + tmp *= a[k*lda+k] + } + if tmp != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + } + return + } + for k := 0; k < m; k++ { + btmpk := b[k*ldb : k*ldb+n] + for i, va := range a[k*lda : k*lda+k] { + btmp := b[i*ldb : i*ldb+n] + tmp := alpha * va + if tmp != 0 { + f32.AxpyUnitaryTo(btmp, tmp, btmpk, btmp) + } + } + tmp := alpha + if nonUnit { + tmp *= a[k*lda+k] + } + if tmp != 1 { + for j := 0; j < n; j++ { + btmpk[j] *= tmp + } + } + } + return + } + // Cases where a is on the right + if tA == blas.NoTrans { + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for k := n - 1; k >= 0; k-- { + tmp := alpha * btmp[k] + if tmp != 0 { + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + for ja, v := range a[k*lda+k+1 : k*lda+n] { + j := ja + k + 1 + btmp[j] += tmp * v + } + } + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for k := 0; k < n; k++ { + tmp := alpha * btmp[k] + if tmp != 0 { + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + f32.AxpyUnitaryTo(btmp, tmp, a[k*lda:k*lda+k], btmp) + } + } + } + return + } + // Cases where a is transposed. + if ul == blas.Upper { + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j, vb := range btmp { + tmp := vb + if nonUnit { + tmp *= a[j*lda+j] + } + tmp += f32.DotUnitary(a[j*lda+j+1:j*lda+n], btmp[j+1:n]) + btmp[j] = alpha * tmp + } + } + return + } + for i := 0; i < m; i++ { + btmp := b[i*ldb : i*ldb+n] + for j := n - 1; j >= 0; j-- { + tmp := btmp[j] + if nonUnit { + tmp *= a[j*lda+j] + } + tmp += f32.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) + btmp[j] = alpha * tmp + } + } +} diff --git a/blas/native/native.go b/blas/native/native.go new file mode 100644 index 00000000..00126769 --- /dev/null +++ b/blas/native/native.go @@ -0,0 +1,72 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate ./single_precision.bash + +package native + +type Implementation struct{} + +// The following are panic strings used during parameter checks. +const ( + negativeN = "blas: n < 0" + zeroIncX = "blas: zero x index increment" + zeroIncY = "blas: zero y index increment" + badLenX = "blas: x index out of range" + badLenY = "blas: y index out of range" + + mLT0 = "blas: m < 0" + nLT0 = "blas: n < 0" + kLT0 = "blas: k < 0" + kLLT0 = "blas: kL < 0" + kULT0 = "blas: kU < 0" + + badUplo = "blas: illegal triangle" + badTranspose = "blas: illegal transpose" + badDiag = "blas: illegal diagonal" + badSide = "blas: illegal side" + + badLdA = "blas: index of a out of range" + badLdB = "blas: index of b out of range" + badLdC = "blas: index of c out of range" + + badX = "blas: x index out of range" + badY = "blas: y index out of range" +) + +// [SD]gemm behavior constants. These are kept here to keep them out of the +// way during single precision code genration. +const ( + blockSize = 64 // b x b matrix + minParBlock = 4 // minimum number of blocks needed to go parallel + buffMul = 4 // how big is the buffer relative to the number of workers +) + +// [SD]gemm debugging constant. +const debug = false + +// subMul is a common type shared by [SD]gemm. +type subMul struct { + i, j int // index of block +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func min(a, b int) int { + if a > b { + return b + } + return a +} + +// blocks returns the number of divisons of the dimension length with the given +// block size. +func blocks(dim, bsize int) int { + return (dim + bsize - 1) / bsize +} diff --git a/blas/native/pardgemm_test.go b/blas/native/pardgemm_test.go new file mode 100644 index 00000000..da36590e --- /dev/null +++ b/blas/native/pardgemm_test.go @@ -0,0 +1,181 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func TestDgemmParallel(t *testing.T) { + for i, test := range []struct { + m int + n int + k int + alpha float64 + tA blas.Transpose + tB blas.Transpose + }{ + { + m: 3, + n: 4, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize*2 + 5, + n: 3, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 3, + n: blockSize * 2, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 2, + n: 3, + k: blockSize*3 - 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize * minParBlock, + n: 3, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 3, + n: blockSize * minParBlock, + k: 2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 2, + n: 3, + k: blockSize * minParBlock, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize*minParBlock + 1, + n: blockSize * minParBlock, + k: 3, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: 3, + n: blockSize*minParBlock + 2, + k: blockSize * 3, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize * minParBlock, + n: 3, + k: blockSize * minParBlock, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize * minParBlock, + n: blockSize * minParBlock, + k: blockSize * 3, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + { + m: blockSize + blockSize/2, + n: blockSize + blockSize/2, + k: blockSize + blockSize/2, + alpha: 2.5, + tA: blas.NoTrans, + tB: blas.NoTrans, + }, + } { + testMatchParallelSerial(t, i, blas.NoTrans, blas.NoTrans, test.m, test.n, test.k, test.alpha) + testMatchParallelSerial(t, i, blas.Trans, blas.NoTrans, test.m, test.n, test.k, test.alpha) + testMatchParallelSerial(t, i, blas.NoTrans, blas.Trans, test.m, test.n, test.k, test.alpha) + testMatchParallelSerial(t, i, blas.Trans, blas.Trans, test.m, test.n, test.k, test.alpha) + } +} + +func testMatchParallelSerial(t *testing.T, i int, tA, tB blas.Transpose, m, n, k int, alpha float64) { + var ( + rowA, colA int + rowB, colB int + ) + if tA == blas.NoTrans { + rowA = m + colA = k + } else { + rowA = k + colA = m + } + if tB == blas.NoTrans { + rowB = k + colB = n + } else { + rowB = n + colB = k + } + a := randmat(rowA, colA, colA) + b := randmat(rowB, colB, colB) + c := randmat(m, n, n) + + aClone := a.clone() + bClone := b.clone() + cClone := c.clone() + + lda := colA + ldb := colB + ldc := n + dgemmSerial(tA == blas.Trans, tB == blas.Trans, m, n, k, a.data, lda, b.data, ldb, cClone.data, ldc, alpha) + dgemmParallel(tA == blas.Trans, tB == blas.Trans, m, n, k, a.data, lda, b.data, ldb, c.data, ldc, alpha) + if !a.equal(aClone) { + t.Errorf("Case %v: a changed during call to dgemmParallel", i) + } + if !b.equal(bClone) { + t.Errorf("Case %v: b changed during call to dgemmParallel", i) + } + if !c.equalWithinAbs(cClone, 1e-12) { + t.Errorf("Case %v: answer not equal parallel and serial", i) + } +} + +func randmat(r, c, stride int) general64 { + data := make([]float64, r*stride+c) + for i := range data { + data[i] = rand.Float64() + } + return general64{ + data: data, + rows: r, + cols: c, + stride: stride, + } +} diff --git a/blas/native/sgemm.go b/blas/native/sgemm.go new file mode 100644 index 00000000..2384d1b2 --- /dev/null +++ b/blas/native/sgemm.go @@ -0,0 +1,280 @@ +// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT. + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "runtime" + "sync" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f32" +) + +// Sgemm computes +// C = beta * C + alpha * A * B, +// where A, B, and C are dense matrices, and alpha and beta are scalars. +// tA and tB specify whether A or B are transposed. +// +// Float32 implementations are autogenerated and not directly tested. +func (Implementation) Sgemm(tA, tB blas.Transpose, m, n, k int, alpha float32, a []float32, lda int, b []float32, ldb int, beta float32, c []float32, ldc int) { + if tA != blas.NoTrans && tA != blas.Trans && tA != blas.ConjTrans { + panic(badTranspose) + } + if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + panic(badTranspose) + } + aTrans := tA == blas.Trans || tA == blas.ConjTrans + if aTrans { + checkMatrix32(k, m, a, lda) + } else { + checkMatrix32(m, k, a, lda) + } + bTrans := tB == blas.Trans || tB == blas.ConjTrans + if bTrans { + checkMatrix32(n, k, b, ldb) + } else { + checkMatrix32(k, n, b, ldb) + } + checkMatrix32(m, n, c, ldc) + + // scale c + if beta != 1 { + if beta == 0 { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for j := range ctmp { + ctmp[j] *= beta + } + } + } + } + + sgemmParallel(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) +} + +func sgemmParallel(aTrans, bTrans bool, m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // dgemmParallel computes a parallel matrix multiplication by partitioning + // a and b into sub-blocks, and updating c with the multiplication of the sub-block + // In all cases, + // A = [ A_11 A_12 ... A_1j + // A_21 A_22 ... A_2j + // ... + // A_i1 A_i2 ... A_ij] + // + // and same for B. All of the submatrix sizes are blockSize×blockSize except + // at the edges. + // + // In all cases, there is one dimension for each matrix along which + // C must be updated sequentially. + // Cij = \sum_k Aik Bki, (A * B) + // Cij = \sum_k Aki Bkj, (A^T * B) + // Cij = \sum_k Aik Bjk, (A * B^T) + // Cij = \sum_k Aki Bjk, (A^T * B^T) + // + // This code computes one {i, j} block sequentially along the k dimension, + // and computes all of the {i, j} blocks concurrently. This + // partitioning allows Cij to be updated in-place without race-conditions. + // Instead of launching a goroutine for each possible concurrent computation, + // a number of worker goroutines are created and channels are used to pass + // available and completed cases. + // + // http://alexkr.com/docs/matrixmult.pdf is a good reference on matrix-matrix + // multiplies, though this code does not copy matrices to attempt to eliminate + // cache misses. + + maxKLen := k + parBlocks := blocks(m, blockSize) * blocks(n, blockSize) + if parBlocks < minParBlock { + // The matrix multiplication is small in the dimensions where it can be + // computed concurrently. Just do it in serial. + sgemmSerial(aTrans, bTrans, m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + } + + nWorkers := runtime.GOMAXPROCS(0) + if parBlocks < nWorkers { + nWorkers = parBlocks + } + // There is a tradeoff between the workers having to wait for work + // and a large buffer making operations slow. + buf := buffMul * nWorkers + if buf > parBlocks { + buf = parBlocks + } + + sendChan := make(chan subMul, buf) + + // Launch workers. A worker receives an {i, j} submatrix of c, and computes + // A_ik B_ki (or the transposed version) storing the result in c_ij. When the + // channel is finally closed, it signals to the waitgroup that it has finished + // computing. + var wg sync.WaitGroup + for i := 0; i < nWorkers; i++ { + wg.Add(1) + go func() { + defer wg.Done() + // Make local copies of otherwise global variables to reduce shared memory. + // This has a noticable effect on benchmarks in some cases. + alpha := alpha + aTrans := aTrans + bTrans := bTrans + m := m + n := n + for sub := range sendChan { + i := sub.i + j := sub.j + leni := blockSize + if i+leni > m { + leni = m - i + } + lenj := blockSize + if j+lenj > n { + lenj = n - j + } + + cSub := sliceView32(c, ldc, i, j, leni, lenj) + + // Compute A_ik B_kj for all k + for k := 0; k < maxKLen; k += blockSize { + lenk := blockSize + if k+lenk > maxKLen { + lenk = maxKLen - k + } + var aSub, bSub []float32 + if aTrans { + aSub = sliceView32(a, lda, k, i, lenk, leni) + } else { + aSub = sliceView32(a, lda, i, k, leni, lenk) + } + if bTrans { + bSub = sliceView32(b, ldb, j, k, lenj, lenk) + } else { + bSub = sliceView32(b, ldb, k, j, lenk, lenj) + } + sgemmSerial(aTrans, bTrans, leni, lenj, lenk, aSub, lda, bSub, ldb, cSub, ldc, alpha) + } + } + }() + } + + // Send out all of the {i, j} subblocks for computation. + for i := 0; i < m; i += blockSize { + for j := 0; j < n; j += blockSize { + sendChan <- subMul{ + i: i, + j: j, + } + } + } + close(sendChan) + wg.Wait() +} + +// sgemmSerial is serial matrix multiply +func sgemmSerial(aTrans, bTrans bool, m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + switch { + case !aTrans && !bTrans: + sgemmSerialNotNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case aTrans && !bTrans: + sgemmSerialTransNot(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case !aTrans && bTrans: + sgemmSerialNotTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + case aTrans && bTrans: + sgemmSerialTransTrans(m, n, k, a, lda, b, ldb, c, ldc, alpha) + return + default: + panic("unreachable") + } +} + +// sgemmSerial where neither a nor b are transposed +func sgemmSerialNotNot(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for i := 0; i < m; i++ { + ctmp := c[i*ldc : i*ldc+n] + for l, v := range a[i*lda : i*lda+k] { + tmp := alpha * v + if tmp != 0 { + f32.AxpyUnitaryTo(ctmp, tmp, b[l*ldb:l*ldb+n], ctmp) + } + } + } +} + +// sgemmSerial where neither a is transposed and b is not +func sgemmSerialTransNot(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for l := 0; l < k; l++ { + btmp := b[l*ldb : l*ldb+n] + for i, v := range a[l*lda : l*lda+m] { + tmp := alpha * v + if tmp != 0 { + ctmp := c[i*ldc : i*ldc+n] + f32.AxpyUnitaryTo(ctmp, tmp, btmp, ctmp) + } + } + } +} + +// sgemmSerial where neither a is not transposed and b is +func sgemmSerialNotTrans(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for i := 0; i < m; i++ { + atmp := a[i*lda : i*lda+k] + ctmp := c[i*ldc : i*ldc+n] + for j := 0; j < n; j++ { + ctmp[j] += alpha * f32.DotUnitary(atmp, b[j*ldb:j*ldb+k]) + } + } +} + +// sgemmSerial where both are transposed +func sgemmSerialTransTrans(m, n, k int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, alpha float32) { + // This style is used instead of the literal [i*stride +j]) is used because + // approximately 5 times faster as of go 1.3. + for l := 0; l < k; l++ { + for i, v := range a[l*lda : l*lda+m] { + tmp := alpha * v + if tmp != 0 { + ctmp := c[i*ldc : i*ldc+n] + f32.AxpyInc(tmp, b[l:], ctmp, uintptr(n), uintptr(ldb), 1, 0, 0) + } + } + } +} + +func sliceView32(a []float32, lda, i, j, r, c int) []float32 { + return a[i*lda+j : (i+r-1)*lda+j+c] +} + +func checkMatrix32(m, n int, a []float32, lda int) { + if m < 0 { + panic("blas: rows < 0") + } + if n < 0 { + panic("blas: cols < 0") + } + if lda < n { + panic("blas: illegal stride") + } + if len(a) < (m-1)*lda+n { + panic("blas: insufficient matrix slice length") + } +} diff --git a/blas/native/single_precision.bash b/blas/native/single_precision.bash new file mode 100755 index 00000000..72a75b99 --- /dev/null +++ b/blas/native/single_precision.bash @@ -0,0 +1,156 @@ +#!/usr/bin/env bash + +# Copyright ©2015 The gonum Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +WARNING='//\ +// Float32 implementations are autogenerated and not directly tested.\ +' + +# Level1 routines. + +echo Generating level1single.go +echo -e '// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT.\n' > level1single.go +cat level1double.go \ +| gofmt -r 'blas.Float64Level1 -> blas.Float32Level1' \ +\ +| gofmt -r 'float64 -> float32' \ +| gofmt -r 'blas.DrotmParams -> blas.SrotmParams' \ +\ +| gofmt -r 'f64.AxpyInc -> f32.AxpyInc' \ +| gofmt -r 'f64.AxpyIncTo -> f32.AxpyIncTo' \ +| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +| gofmt -r 'f64.ScalUnitary -> f32.ScalUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e "s_^\(func (Implementation) \)Id\(.*\)\$_$WARNING\1Is\2_" \ + -e 's_^// Id_// Is_' \ + -e 's_"github.com/gonum/internal/asm/f64"_"github.com/gonum/internal/asm/f32"_' \ + -e 's_"math"_math "github.com/gonum/blas/native/internal/math32"_' \ +>> level1single.go + +echo Generating level1single_sdot.go +echo -e '// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT.\n' > level1single_sdot.go +cat level1double_ddot.go \ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'f64.DotInc -> f32.DotInc' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e 's_"github.com/gonum/internal/asm/f64"_"github.com/gonum/internal/asm/f32"_' \ +>> level1single_sdot.go + +echo Generating level1single_dsdot.go +echo -e '// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT.\n' > level1single_dsdot.go +cat level1double_ddot.go \ +| gofmt -r '[]float64 -> []float32' \ +\ +| gofmt -r 'f64.DotInc -> f32.DdotInc' \ +| gofmt -r 'f64.DotUnitary -> f32.DdotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1Ds\2_" \ + -e 's_^// D_// Ds_' \ + -e 's_"github.com/gonum/internal/asm/f64"_"github.com/gonum/internal/asm/f32"_' \ +>> level1single_dsdot.go + +echo Generating level1single_sdsdot.go +echo -e '// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT.\n' > level1single_sdsdot.go +cat level1double_ddot.go \ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'f64.DotInc(x, y, f(n), f(incX), f(incY), f(ix), f(iy)) -> alpha + float32(f32.DdotInc(x, y, f(n), f(incX), f(incY), f(ix), f(iy)))' \ +| gofmt -r 'f64.DotUnitary(a, b) -> alpha + float32(f32.DdotUnitary(a, b))' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1Sds\2_" \ + -e 's_^// D\(.*\)$_// Sds\1 plus a constant_' \ + -e 's_\\sum_alpha + \\sum_' \ + -e 's/n int/n int, alpha float32/' \ + -e 's_"github.com/gonum/internal/asm/f64"_"github.com/gonum/internal/asm/f32"_' \ +>> level1single_sdsdot.go + + +# Level2 routines. + +echo Generating level2single.go +echo -e '// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT.\n' > level2single.go +cat level2double.go \ +| gofmt -r 'blas.Float64Level2 -> blas.Float32Level2' \ +\ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'Dscal -> Sscal' \ +\ +| gofmt -r 'f64.AxpyInc -> f32.AxpyInc' \ +| gofmt -r 'f64.AxpyIncTo -> f32.AxpyIncTo' \ +| gofmt -r 'f64.AxpyUnitary -> f32.AxpyUnitary' \ +| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ +| gofmt -r 'f64.DotInc -> f32.DotInc' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e 's_"github.com/gonum/internal/asm/f64"_"github.com/gonum/internal/asm/f32"_' \ +>> level2single.go + + +# Level3 routines. + +echo Generating level3single.go +echo -e '// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT.\n' > level3single.go +cat level3double.go \ +| gofmt -r 'blas.Float64Level3 -> blas.Float32Level3' \ +\ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e 's_"github.com/gonum/internal/asm/f64"_"github.com/gonum/internal/asm/f32"_' \ +>> level3single.go + +echo Generating general_single.go +echo -e '// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT.\n' > general_single.go +cat general_double.go \ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'general64 -> general32' \ +| gofmt -r 'newGeneral64 -> newGeneral32' \ +\ +| sed -e 's/(g general64) print()/(g general32) print()/' \ + -e 's_"math"_math "github.com/gonum/blas/native/internal/math32"_' \ + -e 's_"github.com/gonum/internal/asm/f64"_"github.com/gonum/internal/asm/f32"_' \ +>> general_single.go + +echo Generating sgemm.go +echo -e '// Code generated by "go generate github.com/gonum/blas/native"; DO NOT EDIT.\n' > sgemm.go +cat dgemm.go \ +| gofmt -r 'float64 -> float32' \ +| gofmt -r 'general64 -> general32' \ +| gofmt -r 'sliceView64 -> sliceView32' \ +| gofmt -r 'checkMatrix64 -> checkMatrix32' \ +\ +| gofmt -r 'dgemmParallel -> sgemmParallel' \ +| gofmt -r 'computeNumBlocks64 -> computeNumBlocks32' \ +| gofmt -r 'dgemmSerial -> sgemmSerial' \ +| gofmt -r 'dgemmSerialNotNot -> sgemmSerialNotNot' \ +| gofmt -r 'dgemmSerialTransNot -> sgemmSerialTransNot' \ +| gofmt -r 'dgemmSerialNotTrans -> sgemmSerialNotTrans' \ +| gofmt -r 'dgemmSerialTransTrans -> sgemmSerialTransTrans' \ +\ +| gofmt -r 'f64.AxpyInc -> f32.AxpyInc' \ +| gofmt -r 'f64.AxpyIncTo -> f32.AxpyIncTo' \ +| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ +| gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ + -e 's_^// D_// S_' \ + -e 's_^// d_// s_' \ + -e 's_"github.com/gonum/internal/asm/f64"_"github.com/gonum/internal/asm/f32"_' \ +>> sgemm.go diff --git a/blas/testblas/benchautogen/autogen_bench_level1double.go b/blas/testblas/benchautogen/autogen_bench_level1double.go new file mode 100644 index 00000000..12141afa --- /dev/null +++ b/blas/testblas/benchautogen/autogen_bench_level1double.go @@ -0,0 +1,292 @@ +// Copyright 2014 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +// Script for automatic code generation of the benchmark routines +package main + +import ( + "fmt" + "os" + "os/exec" + "path" + "path/filepath" + "strconv" +) + +var gopath string + +var copyrightnotice = []byte(`// Copyright 2014 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file`) + +var autogen = []byte("// Code generated by \"go run github.com/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go\"; DO NOT EDIT.\n") + +var imports = []byte(`import( + "math/rand" + "testing" + + "github.com/gonum/blas" +)`) + +var randomSliceFunction = []byte(`func randomSlice(l, idx int) ([]float64) { + if idx < 0{ + idx = -idx + } + s := make([]float64, l * idx) + for i := range s { + s[i] = rand.Float64() + } + return s +}`) + +const ( + posInc1 = 5 + posInc2 = 3 + negInc1 = -3 + negInc2 = -4 +) + +var level1Sizes = []struct { + lower string + upper string + camel string + size int +}{ + { + lower: "small", + upper: "SMALL_SLICE", + camel: "Small", + size: 10, + }, + { + lower: "medium", + upper: "MEDIUM_SLICE", + camel: "Medium", + size: 1000, + }, + { + lower: "large", + upper: "LARGE_SLICE", + camel: "Large", + size: 100000, + }, + { + lower: "huge", + upper: "HUGE_SLICE", + camel: "Huge", + size: 10000000, + }, +} + +type level1functionStruct struct { + camel string + sig string + call string + extraSetup string + oneInput bool + extraName string // if have a couple different cases for the same function +} + +var level1Functions = []level1functionStruct{ + { + camel: "Ddot", + sig: "n int, x []float64, incX int, y []float64, incY int", + call: "n, x, incX, y, incY", + oneInput: false, + }, + { + camel: "Dnrm2", + sig: "n int, x []float64, incX int", + call: "n, x, incX", + oneInput: true, + }, + { + camel: "Dasum", + sig: "n int, x []float64, incX int", + call: "n, x, incX", + oneInput: true, + }, + { + camel: "Idamax", + sig: "n int, x []float64, incX int", + call: "n, x, incX", + oneInput: true, + }, + { + camel: "Dswap", + sig: "n int, x []float64, incX int, y []float64, incY int", + call: "n, x, incX, y, incY", + oneInput: false, + }, + { + camel: "Dcopy", + sig: "n int, x []float64, incX int, y []float64, incY int", + call: "n, x, incX, y, incY", + oneInput: false, + }, + { + camel: "Daxpy", + sig: "n int, alpha float64, x []float64, incX int, y []float64, incY int", + call: "n, alpha, x, incX, y, incY", + extraSetup: "alpha := 2.4", + oneInput: false, + }, + { + camel: "Drot", + sig: "n int, x []float64, incX int, y []float64, incY int, c, s float64", + call: "n, x, incX, y, incY, c, s", + extraSetup: "c := 0.89725836967\ns:= 0.44150585279", + oneInput: false, + }, + { + camel: "Drotm", + sig: "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams", + call: "n, x, incX, y, incY, p", + extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375,0}}", + oneInput: false, + extraName: "OffDia", + }, + { + camel: "Drotm", + sig: "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams", + call: "n, x, incX, y, incY, p", + extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}}", + oneInput: false, + extraName: "Dia", + }, + { + camel: "Drotm", + sig: "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams", + call: "n, x, incX, y, incY, p", + extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}}", + oneInput: false, + extraName: "Resc", + }, + { + camel: "Dscal", + sig: "n int, alpha float64, x []float64, incX int", + call: "n, alpha, x, incX", + extraSetup: "alpha := 2.4", + oneInput: true, + }, +} + +func init() { + gopath = os.Getenv("GOPATH") + if gopath == "" { + panic("gopath not set") + } +} + +func main() { + blasPath := filepath.Join(gopath, "src", "github.com", "gonum", "blas") + + pkgs := []struct{ name string }{{name: "native"}, {name: "cgo"}} + + for _, pkg := range pkgs { + err := level1(filepath.Join(blasPath, pkg.name), pkg.name) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + err = exec.Command("go", "fmt", path.Join("github.com", "gonum", "blas", pkg.name)).Run() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } +} + +func printHeader(f *os.File, name string) error { + if _, err := f.Write(autogen); err != nil { + return err + } + f.WriteString("\n\n") + f.Write(copyrightnotice) + f.WriteString("\n\n") + f.WriteString("package " + name) + f.WriteString("\n\n") + f.Write(imports) + f.WriteString("\n\n") + return nil +} + +// Generate the benchmark scripts for level1 +func level1(benchPath string, pkgname string) error { + // Generate level 1 benchmarks + level1Filepath := filepath.Join(benchPath, "level1doubleBench_auto_test.go") + f, err := os.Create(level1Filepath) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + defer f.Close() + printHeader(f, pkgname) + + // Print all of the constants + f.WriteString("const (\n") + f.WriteString("\tposInc1 = " + strconv.Itoa(posInc1) + "\n") + f.WriteString("\tposInc2 = " + strconv.Itoa(posInc2) + "\n") + f.WriteString("\tnegInc1 = " + strconv.Itoa(negInc1) + "\n") + f.WriteString("\tnegInc2 = " + strconv.Itoa(negInc2) + "\n") + for _, con := range level1Sizes { + f.WriteString("\t" + con.upper + " = " + strconv.Itoa(con.size) + "\n") + } + f.WriteString(")\n") + f.WriteString("\n") + + // Write the randomSlice function + f.Write(randomSliceFunction) + f.WriteString("\n\n") + + // Start writing the benchmarks + for _, fun := range level1Functions { + writeLevel1Benchmark(fun, f) + f.WriteString("\n/* ------------------ */ \n") + } + + return nil +} + +func writeLevel1Benchmark(fun level1functionStruct, f *os.File) { + // First, write the base benchmark file + f.WriteString("func benchmark" + fun.camel + fun.extraName + "(b *testing.B, ") + f.WriteString(fun.sig) + f.WriteString(") {\n") + + f.WriteString("b.ResetTimer()\n") + f.WriteString("for i := 0; i < b.N; i++{\n") + f.WriteString("\timpl." + fun.camel + "(") + + f.WriteString(fun.call) + f.WriteString(")\n}\n}\n") + f.WriteString("\n") + + // Write all of the benchmarks to call it + for _, sz := range level1Sizes { + lambda := func(incX, incY, name string, twoInput bool) { + f.WriteString("func Benchmark" + fun.camel + fun.extraName + sz.camel + name + "(b *testing.B){\n") + f.WriteString("n := " + sz.upper + "\n") + f.WriteString("incX := " + incX + "\n") + f.WriteString("x := randomSlice(n, incX)\n") + if twoInput { + f.WriteString("incY := " + incY + "\n") + f.WriteString("y := randomSlice(n, incY)\n") + } + f.WriteString(fun.extraSetup + "\n") + f.WriteString("benchmark" + fun.camel + fun.extraName + "(b, " + fun.call + ")\n") + f.WriteString("}\n\n") + } + if fun.oneInput { + lambda("1", "", "UnitaryInc", false) + lambda("posInc1", "", "PosInc", false) + } else { + lambda("1", "1", "BothUnitary", true) + lambda("posInc1", "1", "IncUni", true) + lambda("1", "negInc1", "UniInc", true) + lambda("posInc1", "negInc1", "BothInc", true) + } + } +} diff --git a/blas/testblas/benchsize.go b/blas/testblas/benchsize.go new file mode 100644 index 00000000..41d132be --- /dev/null +++ b/blas/testblas/benchsize.go @@ -0,0 +1,8 @@ +package testblas + +const ( + SmallMat = 10 + MediumMat = 100 + LargeMat = 1000 + HugeMat = 10000 +) diff --git a/blas/testblas/common.go b/blas/testblas/common.go new file mode 100644 index 00000000..469a11a5 --- /dev/null +++ b/blas/testblas/common.go @@ -0,0 +1,237 @@ +package testblas + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/blas" +) + +// throwPanic will throw unexpected panics if true, or will just report them as errors if false +const throwPanic = true + +func dTolEqual(a, b float64) bool { + if math.IsNaN(a) && math.IsNaN(b) { + return true + } + if a == b { + return true + } + m := math.Max(math.Abs(a), math.Abs(b)) + if m > 1 { + a /= m + b /= m + } + if math.Abs(a-b) < 1e-14 { + return true + } + return false +} + +func dSliceTolEqual(a, b []float64) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if !dTolEqual(a[i], b[i]) { + return false + } + } + return true +} + +func dStridedSliceTolEqual(n int, a []float64, inca int, b []float64, incb int) bool { + ia := 0 + ib := 0 + if inca <= 0 { + ia = -(n - 1) * inca + } + if incb <= 0 { + ib = -(n - 1) * incb + } + for i := 0; i < n; i++ { + if !dTolEqual(a[ia], b[ib]) { + return false + } + ia += inca + ib += incb + } + return true +} + +func dSliceEqual(a, b []float64) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if !(a[i] == b[i]) { + return false + } + } + return true +} + +func dCopyTwoTmp(x, xTmp, y, yTmp []float64) { + if len(x) != len(xTmp) { + panic("x size mismatch") + } + if len(y) != len(yTmp) { + panic("y size mismatch") + } + for i, val := range x { + xTmp[i] = val + } + for i, val := range y { + yTmp[i] = val + } +} + +// returns true if the function panics +func panics(f func()) (b bool) { + defer func() { + err := recover() + if err != nil { + b = true + } + }() + f() + return +} + +func testpanics(f func(), name string, t *testing.T) { + b := panics(f) + if !b { + t.Errorf("%v should panic and does not", name) + } +} + +func sliceOfSliceCopy(a [][]float64) [][]float64 { + n := make([][]float64, len(a)) + for i := range a { + n[i] = make([]float64, len(a[i])) + copy(n[i], a[i]) + } + return n +} + +func sliceCopy(a []float64) []float64 { + n := make([]float64, len(a)) + copy(n, a) + return n +} + +func flatten(a [][]float64) []float64 { + if len(a) == 0 { + return nil + } + m := len(a) + n := len(a[0]) + s := make([]float64, m*n) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + s[i*n+j] = a[i][j] + } + } + return s +} + +func unflatten(a []float64, m, n int) [][]float64 { + s := make([][]float64, m) + for i := 0; i < m; i++ { + s[i] = make([]float64, n) + for j := 0; j < n; j++ { + s[i][j] = a[i*n+j] + } + } + return s +} + +// flattenTriangular turns the upper or lower triangle of a dense slice of slice +// into a single slice with packed storage. a must be a square matrix. +func flattenTriangular(a [][]float64, ul blas.Uplo) []float64 { + m := len(a) + aFlat := make([]float64, m*(m+1)/2) + var k int + if ul == blas.Upper { + for i := 0; i < m; i++ { + k += copy(aFlat[k:], a[i][i:]) + } + return aFlat + } + for i := 0; i < m; i++ { + k += copy(aFlat[k:], a[i][:i+1]) + } + return aFlat +} + +// flattenBanded turns a dense banded slice of slice into the compact banded matrix format +func flattenBanded(a [][]float64, ku, kl int) []float64 { + m := len(a) + n := len(a[0]) + if ku < 0 || kl < 0 { + panic("testblas: negative band length") + } + nRows := m + nCols := (ku + kl + 1) + aflat := make([]float64, nRows*nCols) + for i := range aflat { + aflat[i] = math.NaN() + } + // loop over the rows, and then the bands + // elements in the ith row stay in the ith row + // order in bands is kept + for i := 0; i < nRows; i++ { + min := -kl + if i-kl < 0 { + min = -i + } + max := ku + if i+ku >= n { + max = n - i - 1 + } + for j := min; j <= max; j++ { + col := kl + j + aflat[i*nCols+col] = a[i][i+j] + } + } + return aflat +} + +// makeIncremented takes a slice with inc == 1 and makes an incremented version +// and adds extra values on the end +func makeIncremented(x []float64, inc int, extra int) []float64 { + if inc == 0 { + panic("zero inc") + } + absinc := inc + if absinc < 0 { + absinc = -inc + } + xcopy := make([]float64, len(x)) + if inc > 0 { + copy(xcopy, x) + } else { + for i := 0; i < len(x); i++ { + xcopy[i] = x[len(x)-i-1] + } + } + + // don't use NaN because it makes comparison hard + // Do use a weird unique value for easier debugging + counter := 100.0 + var xnew []float64 + for i, v := range xcopy { + xnew = append(xnew, v) + if i != len(x)-1 { + for j := 0; j < absinc-1; j++ { + xnew = append(xnew, counter) + counter++ + } + } + } + for i := 0; i < extra; i++ { + xnew = append(xnew, counter) + counter++ + } + return xnew +} diff --git a/blas/testblas/common_test.go b/blas/testblas/common_test.go new file mode 100644 index 00000000..852a939e --- /dev/null +++ b/blas/testblas/common_test.go @@ -0,0 +1,187 @@ +package testblas + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +func TestFlattenBanded(t *testing.T) { + for i, test := range []struct { + dense [][]float64 + ku int + kl int + condensed [][]float64 + }{ + { + dense: [][]float64{{3}}, + ku: 0, + kl: 0, + condensed: [][]float64{{3}}, + }, + { + dense: [][]float64{ + {3, 4, 0}, + }, + ku: 1, + kl: 0, + condensed: [][]float64{ + {3, 4}, + }, + }, + { + dense: [][]float64{ + {3, 4, 0, 0, 0}, + }, + ku: 1, + kl: 0, + condensed: [][]float64{ + {3, 4}, + }, + }, + { + dense: [][]float64{ + {3, 4, 0}, + {0, 5, 8}, + {0, 0, 2}, + {0, 0, 0}, + {0, 0, 0}, + }, + ku: 1, + kl: 0, + condensed: [][]float64{ + {3, 4}, + {5, 8}, + {2, math.NaN()}, + {math.NaN(), math.NaN()}, + {math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {3, 4, 6}, + {0, 5, 8}, + {0, 0, 2}, + {0, 0, 0}, + {0, 0, 0}, + }, + ku: 2, + kl: 0, + condensed: [][]float64{ + {3, 4, 6}, + {5, 8, math.NaN()}, + {2, math.NaN(), math.NaN()}, + {math.NaN(), math.NaN(), math.NaN()}, + {math.NaN(), math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {3, 4, 6}, + {1, 5, 8}, + {0, 6, 2}, + {0, 0, 7}, + {0, 0, 0}, + }, + ku: 2, + kl: 1, + condensed: [][]float64{ + {math.NaN(), 3, 4, 6}, + {1, 5, 8, math.NaN()}, + {6, 2, math.NaN(), math.NaN()}, + {7, math.NaN(), math.NaN(), math.NaN()}, + {math.NaN(), math.NaN(), math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {1, 2, 0}, + {3, 4, 5}, + {6, 7, 8}, + {0, 9, 10}, + {0, 0, 11}, + }, + ku: 1, + kl: 2, + condensed: [][]float64{ + {math.NaN(), math.NaN(), 1, 2}, + {math.NaN(), 3, 4, 5}, + {6, 7, 8, math.NaN()}, + {9, 10, math.NaN(), math.NaN()}, + {11, math.NaN(), math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {1, 0, 0}, + {3, 4, 0}, + {6, 7, 8}, + {0, 9, 10}, + {0, 0, 11}, + }, + ku: 0, + kl: 2, + condensed: [][]float64{ + {math.NaN(), math.NaN(), 1}, + {math.NaN(), 3, 4}, + {6, 7, 8}, + {9, 10, math.NaN()}, + {11, math.NaN(), math.NaN()}, + }, + }, + { + dense: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 4, 0, 0, 0}, + {1, 3, 5, 0, 0}, + }, + ku: 0, + kl: 2, + condensed: [][]float64{ + {math.NaN(), math.NaN(), 1}, + {math.NaN(), 3, 4}, + {1, 3, 5}, + }, + }, + } { + condensed := flattenBanded(test.dense, test.ku, test.kl) + correct := flatten(test.condensed) + if !floats.Same(condensed, correct) { + t.Errorf("Case %v mismatch. Want %v, got %v.", i, correct, condensed) + } + } +} + +func TestFlattenTriangular(t *testing.T) { + for i, test := range []struct { + a [][]float64 + ans []float64 + ul blas.Uplo + }{ + { + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + ul: blas.Upper, + ans: []float64{1, 2, 3, 4, 5, 6}, + }, + { + a: [][]float64{ + {1, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + ul: blas.Lower, + ans: []float64{1, 2, 3, 4, 5, 6}, + }, + } { + a := flattenTriangular(test.a, test.ul) + if !floats.Equal(a, test.ans) { + t.Errorf("Case %v. Want %v, got %v.", i, test.ans, a) + } + } +} diff --git a/blas/testblas/dgbmv.go b/blas/testblas/dgbmv.go new file mode 100644 index 00000000..985c6e7a --- /dev/null +++ b/blas/testblas/dgbmv.go @@ -0,0 +1,94 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dgbmver interface { + Dgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DgbmvTest(t *testing.T, blasser Dgbmver) { + for i, test := range []struct { + tA blas.Transpose + m, n int + kL, kU int + alpha float64 + a [][]float64 + lda int + x []float64 + beta float64 + y []float64 + ans []float64 + }{ + { + tA: blas.NoTrans, + m: 9, + n: 6, + lda: 4, + kL: 2, + kU: 1, + alpha: 3.0, + beta: 2.0, + a: [][]float64{ + {5, 3, 0, 0, 0, 0}, + {-1, 2, 9, 0, 0, 0}, + {4, 8, 3, 6, 0, 0}, + {0, -1, 8, 2, 1, 0}, + {0, 0, 9, 9, 9, 5}, + {0, 0, 0, 2, -3, 2}, + {0, 0, 0, 0, 1, 5}, + {0, 0, 0, 0, 0, 6}, + {0, 0, 0, 0, 0, 0}, + }, + x: []float64{1, 2, 3, 4, 5, 6}, + y: []float64{-1, -2, -3, -4, -5, -6, -7, -8, -9}, + ans: []float64{31, 86, 153, 97, 404, 3, 91, 92, -18}, + }, + { + tA: blas.Trans, + m: 9, + n: 6, + lda: 4, + kL: 2, + kU: 1, + alpha: 3.0, + beta: 2.0, + a: [][]float64{ + {5, 3, 0, 0, 0, 0}, + {-1, 2, 9, 0, 0, 0}, + {4, 8, 3, 6, 0, 0}, + {0, -1, 8, 2, 1, 0}, + {0, 0, 9, 9, 9, 5}, + {0, 0, 0, 2, -3, 2}, + {0, 0, 0, 0, 1, 5}, + {0, 0, 0, 0, 0, 6}, + {0, 0, 0, 0, 0, 0}, + }, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + y: []float64{-1, -2, -3, -4, -5, -6}, + ans: []float64{43, 77, 306, 241, 104, 348}, + }, + } { + extra := 3 + aFlat := flattenBanded(test.a, test.kU, test.kL) + incTest := func(incX, incY, extra int) { + xnew := makeIncremented(test.x, incX, extra) + ynew := makeIncremented(test.y, incY, extra) + ans := makeIncremented(test.ans, incY, extra) + blasser.Dgbmv(test.tA, test.m, test.n, test.kL, test.kU, test.alpha, aFlat, test.lda, xnew, incX, test.beta, ynew, incY) + if !dSliceTolEqual(ans, ynew) { + t.Errorf("Case %v: Want %v, got %v", i, ans, ynew) + } + } + incTest(1, 1, extra) + incTest(1, 3, extra) + incTest(1, -3, extra) + incTest(2, 3, extra) + incTest(2, -3, extra) + incTest(3, 2, extra) + incTest(-3, 2, extra) + } +} diff --git a/blas/testblas/dgemm.go b/blas/testblas/dgemm.go new file mode 100644 index 00000000..f51f0c95 --- /dev/null +++ b/blas/testblas/dgemm.go @@ -0,0 +1,252 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dgemmer interface { + Dgemm(tA, tB blas.Transpose, m, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) +} + +type DgemmCase struct { + isATrans bool + m, n, k int + alpha, beta float64 + a [][]float64 + aTrans [][]float64 // transpose of a + b [][]float64 + c [][]float64 + ans [][]float64 +} + +var DgemmCases = []DgemmCase{ + + { + m: 4, + n: 3, + k: 2, + isATrans: false, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2}, + {4, 5}, + {7, 8}, + {10, 11}, + }, + b: [][]float64{ + {1, 5, 6}, + {5, -8, 8}, + }, + c: [][]float64{ + {4, 8, -9}, + {12, 16, -8}, + {1, 5, 15}, + {-3, -4, 7}, + }, + ans: [][]float64{ + {24, -18, 39.5}, + {64, -32, 124}, + {94.5, -55.5, 219.5}, + {128.5, -78, 299.5}, + }, + }, + { + m: 4, + n: 2, + k: 3, + isATrans: false, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + {10, 11, 12}, + }, + b: [][]float64{ + {1, 5}, + {5, -8}, + {6, 2}, + }, + c: [][]float64{ + {4, 8}, + {12, 16}, + {1, 5}, + {-3, -4}, + }, + ans: [][]float64{ + {60, -6}, + {136, -8}, + {202.5, -19.5}, + {272.5, -30}, + }, + }, + { + m: 3, + n: 2, + k: 4, + isATrans: false, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2, 3, 4}, + {4, 5, 6, 7}, + {8, 9, 10, 11}, + }, + b: [][]float64{ + {1, 5}, + {5, -8}, + {6, 2}, + {8, 10}, + }, + c: [][]float64{ + {4, 8}, + {12, 16}, + {9, -10}, + }, + ans: [][]float64{ + {124, 74}, + {248, 132}, + {406.5, 191}, + }, + }, + { + m: 3, + n: 4, + k: 2, + isATrans: false, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2}, + {4, 5}, + {8, 9}, + }, + b: [][]float64{ + {1, 5, 2, 1}, + {5, -8, 2, 1}, + }, + c: [][]float64{ + {4, 8, 2, 2}, + {12, 16, 8, 9}, + {9, -10, 10, 10}, + }, + ans: [][]float64{ + {24, -18, 13, 7}, + {64, -32, 40, 22.5}, + {110.5, -69, 73, 39}, + }, + }, + { + m: 2, + n: 4, + k: 3, + isATrans: false, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2, 3}, + {4, 5, 6}, + }, + b: [][]float64{ + {1, 5, 8, 8}, + {5, -8, 9, 10}, + {6, 2, -3, 2}, + }, + c: [][]float64{ + {4, 8, 7, 8}, + {12, 16, -2, 6}, + }, + ans: [][]float64{ + {60, -6, 37.5, 72}, + {136, -8, 117, 191}, + }, + }, + { + m: 2, + n: 3, + k: 4, + isATrans: false, + alpha: 2, + beta: 0.5, + a: [][]float64{ + {1, 2, 3, 4}, + {4, 5, 6, 7}, + }, + b: [][]float64{ + {1, 5, 8}, + {5, -8, 9}, + {6, 2, -3}, + {8, 10, 2}, + }, + c: [][]float64{ + {4, 8, 1}, + {12, 16, 6}, + }, + ans: [][]float64{ + {124, 74, 50.5}, + {248, 132, 149}, + }, + }, +} + +// assumes [][]float64 is actually a matrix +func transpose(a [][]float64) [][]float64 { + b := make([][]float64, len(a[0])) + for i := range b { + b[i] = make([]float64, len(a)) + for j := range b[i] { + b[i][j] = a[j][i] + } + } + return b +} + +func TestDgemm(t *testing.T, blasser Dgemmer) { + for i, test := range DgemmCases { + // Test that it passes row major + dgemmcomp(i, "RowMajorNoTrans", t, blasser, blas.NoTrans, blas.NoTrans, + test.m, test.n, test.k, test.alpha, test.beta, test.a, test.b, test.c, test.ans) + // Try with A transposed + dgemmcomp(i, "RowMajorTransA", t, blasser, blas.Trans, blas.NoTrans, + test.m, test.n, test.k, test.alpha, test.beta, transpose(test.a), test.b, test.c, test.ans) + // Try with B transposed + dgemmcomp(i, "RowMajorTransB", t, blasser, blas.NoTrans, blas.Trans, + test.m, test.n, test.k, test.alpha, test.beta, test.a, transpose(test.b), test.c, test.ans) + // Try with both transposed + dgemmcomp(i, "RowMajorTransBoth", t, blasser, blas.Trans, blas.Trans, + test.m, test.n, test.k, test.alpha, test.beta, transpose(test.a), transpose(test.b), test.c, test.ans) + } +} + +func dgemmcomp(i int, name string, t *testing.T, blasser Dgemmer, tA, tB blas.Transpose, m, n, k int, + alpha, beta float64, a [][]float64, b [][]float64, c [][]float64, ans [][]float64) { + + aFlat := flatten(a) + aCopy := flatten(a) + bFlat := flatten(b) + bCopy := flatten(b) + cFlat := flatten(c) + ansFlat := flatten(ans) + lda := len(a[0]) + ldb := len(b[0]) + ldc := len(c[0]) + + // Compute the matrix multiplication + blasser.Dgemm(tA, tB, m, n, k, alpha, aFlat, lda, bFlat, ldb, beta, cFlat, ldc) + + if !dSliceEqual(aFlat, aCopy) { + t.Errorf("Test %v case %v: a changed during call to Dgemm", i, name) + } + if !dSliceEqual(bFlat, bCopy) { + t.Errorf("Test %v case %v: b changed during call to Dgemm", i, name) + } + + if !dSliceTolEqual(ansFlat, cFlat) { + t.Errorf("Test %v case %v: answer mismatch. Expected %v, Found %v", i, name, ansFlat, cFlat) + } + // TODO: Need to add a sub-slice test where don't use up full matrix +} diff --git a/blas/testblas/dgemmbench.go b/blas/testblas/dgemmbench.go new file mode 100644 index 00000000..512f4eca --- /dev/null +++ b/blas/testblas/dgemmbench.go @@ -0,0 +1,39 @@ +package testblas + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func DgemmBenchmark(b *testing.B, dgemm Dgemmer, m, n, k int, tA, tB blas.Transpose) { + a := make([]float64, m*k) + for i := range a { + a[i] = rand.Float64() + } + bv := make([]float64, k*n) + for i := range bv { + bv[i] = rand.Float64() + } + c := make([]float64, m*n) + for i := range c { + c[i] = rand.Float64() + } + var lda, ldb int + if tA == blas.Trans { + lda = m + } else { + lda = k + } + if tB == blas.Trans { + ldb = k + } else { + ldb = n + } + ldc := n + b.ResetTimer() + for i := 0; i < b.N; i++ { + dgemm.Dgemm(tA, tB, m, n, k, 3.0, a, lda, bv, ldb, 1.0, c, ldc) + } +} diff --git a/blas/testblas/dgemv.go b/blas/testblas/dgemv.go new file mode 100644 index 00000000..b8dbab7f --- /dev/null +++ b/blas/testblas/dgemv.go @@ -0,0 +1,680 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type DgemvCase struct { + Name string + m int + n int + A [][]float64 + tA blas.Transpose + x []float64 + incX int + y []float64 + incY int + xCopy []float64 + yCopy []float64 + + Subcases []DgemvSubcase +} + +type DgemvSubcase struct { + mulXNeg1 bool + mulYNeg1 bool + alpha float64 + beta float64 + ans []float64 +} + +var DgemvCases = []DgemvCase{ + { + Name: "M_gt_N_Inc1_NoTrans", + tA: blas.NoTrans, + m: 5, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3}, + y: []float64{7, 8, 9, 10, 11}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 0, 0, 0, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 8, 9, 10, 11}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{40.8, 43.9, 33, 9, 28}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{284.4, 303.2, 210, 12, 158}, + }, + }, + }, + { + Name: "M_gt_N_Inc1_Trans", + tA: blas.Trans, + m: 5, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3, -4, 5}, + y: []float64{7, 8, 9}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 0, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 8, 9}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{94.3, 40.2, 52.3}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{712.4, 273.6, 364.4}, + }, + }, + }, + { + Name: "M_eq_N_Inc1_NoTrans", + tA: blas.NoTrans, + m: 3, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3}, + y: []float64{7, 2, 2}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 0, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 2, 2}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{40.8, 43.9, 33}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{40.8*8 - 6*7, 43.9*8 - 6*2, 33*8 - 6*2}, + }, + }, + }, + { + Name: "M_eq_N_Inc1_Trans", + tA: blas.Trans, + m: 3, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3}, + y: []float64{7, 2, 2}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{384.4, 261.6, 270.4}, + }, + }, + }, + { + Name: "M_lt_N_Inc1_NoTrans", + tA: blas.NoTrans, + m: 3, + n: 5, + A: [][]float64{ + {4.1, 6.2, 8.1, 10, 7}, + {9.6, 3.5, 9.1, -2, 9}, + {10, 7, 3, 1, -5}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3, -7.6, 8.1}, + y: []float64{7, 2, 2}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 0, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 2, 2}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{21.5, 132, -15.1}, + }, + + { + alpha: 8, + beta: -6, + ans: []float64{21.5*8 - 6*7, 132*8 - 6*2, -15.1*8 - 6*2}, + }, + }, + }, + { + Name: "M_lt_N_Inc1_Trans", + tA: blas.Trans, + m: 3, + n: 5, + A: [][]float64{ + {4.1, 6.2, 8.1, 10, 7}, + {9.6, 3.5, 9.1, -2, 9}, + {10, 7, 3, 1, -5}, + }, + incX: 1, + incY: 1, + x: []float64{1, 2, 3}, + y: []float64{7, 2, 2, -3, 5}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{384.4, 261.6, 270.4, 90, 50}, + }, + }, + }, + { + Name: "M_gt_N_Part1_NoTrans", + tA: blas.NoTrans, + m: 5, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 1, + incY: 2, + x: []float64{1, 2, 3}, + y: []float64{7, 100, 8, 101, 9, 102, 10, 103, 11}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 100, 0, 101, 0, 102, 0, 103, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 100, 8, 101, 9, 102, 10, 103, 11}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{40.8, 100, 43.9, 101, 33, 102, 9, 103, 28}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{284.4, 100, 303.2, 101, 210, 102, 12, 103, 158}, + }, + }, + }, + { + Name: "M_gt_N_Part1_Trans", + tA: blas.Trans, + m: 5, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 1, + incY: 2, + x: []float64{1, 2, 3, -4, 5}, + y: []float64{7, 100, 8, 101, 9}, + + Subcases: []DgemvSubcase{ + { + alpha: 0, + beta: 0, + ans: []float64{0, 100, 0, 101, 0}, + }, + { + alpha: 0, + beta: 1, + ans: []float64{7, 100, 8, 101, 9}, + }, + { + alpha: 1, + beta: 0, + ans: []float64{94.3, 100, 40.2, 101, 52.3}, + }, + { + alpha: 8, + beta: -6, + ans: []float64{712.4, 100, 273.6, 101, 364.4}, + }, + }, + }, + { + Name: "M_gt_N_IncNot1_NoTrans", + tA: blas.NoTrans, + m: 5, + n: 3, + + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3}, + y: []float64{7, 2, 6, 8, -4, -5, 9, 1, 1, 10, 19, 22, 11}, + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{284.4, 2, 6, 303.2, -4, -5, 210, 1, 1, 12, 19, 22, 158}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{220.4, 2, 6, 311.2, -4, -5, 322, 1, 1, -4, 19, 22, 222}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{182, 2, 6, 24, -4, -5, 210, 1, 1, 291.2, 19, 22, 260.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{246, 2, 6, 8, -4, -5, 322, 1, 1, 299.2, 19, 22, 196.4}, + }, + }, + }, + { + Name: "M_gt_N_IncNot1_Trans", + tA: blas.Trans, + m: 5, + n: 3, + + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + {1, 1, 2}, + {9, 2, 5}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3, 8, -3, 6, 5}, + y: []float64{7, 2, 6, 8, -4, -5, 9}, + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{720.4, 2, 6, 281.6, -4, -5, 380.4}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{219.6, 2, 6, 316, -4, -5, 195.6}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{392.4, 2, 6, 281.6, -4, -5, 708.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{207.6, 2, 6, 316, -4, -5, 207.6}, + }, + }, + }, + { + Name: "M_eq_N_IncNot1_NoTrans", + tA: blas.NoTrans, + m: 3, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3}, + y: []float64{7, 2, 6, 8, -4, -5, 9}, + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{284.4, 2, 6, 303.2, -4, -5, 210}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{220.4, 2, 6, 311.2, -4, -5, 322}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{222, 2, 6, 303.2, -4, -5, 272.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{334, 2, 6, 311.2, -4, -5, 208.4}, + }, + }, + }, + { + Name: "M_eq_N_IncNot1_Trans", + tA: blas.Trans, + m: 3, + n: 3, + A: [][]float64{ + {4.1, 6.2, 8.1}, + {9.6, 3.5, 9.1}, + {10, 7, 3}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3}, + y: []float64{7, 2, 6, 8, -4, -5, 9}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{384.4, 2, 6, 225.6, -4, -5, 228.4}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{290, 2, 6, 212.8, -4, -5, 310}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{240.4, 2, 6, 225.6, -4, -5, 372.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{322, 2, 6, 212.8, -4, -5, 278}, + }, + }, + }, + { + Name: "M_lt_N_IncNot1_NoTrans", + tA: blas.NoTrans, + m: 3, + n: 5, + A: [][]float64{ + {4.1, 6.2, 8.1, 10, 11}, + {9.6, 3.5, 9.1, -3, -2}, + {10, 7, 3, -7, -4}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3, -2, -4, 8, -9}, + y: []float64{7, 2, 6, 8, -4, -5, 9}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{-827.6, 2, 6, 543.2, -4, -5, 722}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{-93.2, 2, 6, -696.8, -4, -5, -1070}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{734, 2, 6, 543.2, -4, -5, -839.6}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{-1058, 2, 6, -696.8, -4, -5, -105.2}, + }, + }, + }, + { + Name: "M_lt_N_IncNot1_Trans", + tA: blas.Trans, + m: 3, + n: 5, + A: [][]float64{ + {4.1, 6.2, 8.1, 10, 11}, + {9.6, 3.5, 9.1, -3, -2}, + {10, 7, 3, -7, -4}, + }, + incX: 2, + incY: 3, + x: []float64{1, 15, 2, 150, 3}, + y: []float64{7, 2, 6, 8, -4, -5, 9, -4, -1, -9, 1, 1, 2}, + + Subcases: []DgemvSubcase{ + { + alpha: 8, + beta: -6, + ans: []float64{384.4, 2, 6, 225.6, -4, -5, 228.4, -4, -1, -82, 1, 1, -52}, + }, + { + mulXNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{290, 2, 6, 212.8, -4, -5, 310, -4, -1, 190, 1, 1, 188}, + }, + { + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{-82, 2, 6, -184, -4, -5, 228.4, -4, -1, 327.6, 1, 1, 414.4}, + }, + { + mulXNeg1: true, + mulYNeg1: true, + alpha: 8, + beta: -6, + ans: []float64{158, 2, 6, 88, -4, -5, 310, -4, -1, 314.8, 1, 1, 320}, + }, + }, + }, + + // TODO: A can be longer than mxn. Add cases where it is longer + // TODO: x and y can also be longer. Add tests for these + // TODO: Add tests for dimension mismatch + // TODO: Add places with a "submatrix view", where lda != m +} + +type Dgemver interface { + Dgemv(tA blas.Transpose, m, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DgemvTest(t *testing.T, blasser Dgemver) { + for _, test := range DgemvCases { + for i, cas := range test.Subcases { + // Test that it passes with row-major + dgemvcomp(t, test, cas, i, blasser) + + // Test the bad inputs + dgemvbad(t, test, cas, i, blasser) + } + } +} + +func dgemvcomp(t *testing.T, test DgemvCase, cas DgemvSubcase, i int, blasser Dgemver) { + x := sliceCopy(test.x) + y := sliceCopy(test.y) + a := sliceOfSliceCopy(test.A) + aFlat := flatten(a) + + lda := test.n + + incX := test.incX + if cas.mulXNeg1 { + incX *= -1 + } + incY := test.incY + if cas.mulYNeg1 { + incY *= -1 + } + + f := func() { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlat, lda, x, incX, cas.beta, y, incY) + } + if panics(f) { + t.Errorf("Test %v case %v: unexpected panic", test.Name, i) + if throwPanic { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlat, lda, x, incX, cas.beta, y, incY) + } + return + } + // Check that x and a are unchanged + if !dSliceEqual(x, test.x) { + t.Errorf("Test %v, case %v: x modified during call", test.Name, i) + } + aFlat2 := flatten(sliceOfSliceCopy(test.A)) + if !dSliceEqual(aFlat2, aFlat) { + t.Errorf("Test %v, case %v: a modified during call", test.Name, i) + } + + // Check that the answer matches + if !dSliceTolEqual(cas.ans, y) { + t.Errorf("Test %v, case %v: answer mismatch: Expected %v, Found %v", test.Name, i, cas.ans, y) + } +} + +func dgemvbad(t *testing.T, test DgemvCase, cas DgemvSubcase, i int, blasser Dgemver) { + x := sliceCopy(test.x) + y := sliceCopy(test.y) + a := sliceOfSliceCopy(test.A) + aFlatRow := flatten(a) + ldaRow := test.n + + f := func() { + blasser.Dgemv(312, test.m, test.n, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for bad transpose", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, -2, test.n, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for m negative", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, test.m, -4, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for n negative", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlatRow, ldaRow, x, 0, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for incX zero", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlatRow, ldaRow, x, test.incX, cas.beta, y, 0) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for incY zero", test.Name, i) + } + f = func() { + blasser.Dgemv(test.tA, test.m, test.n, cas.alpha, aFlatRow, ldaRow-1, x, test.incX, cas.beta, y, test.incY) + } + if !panics(f) { + t.Errorf("Test %v case %v: no panic for lda too small row major", test.Name, i) + } +} diff --git a/blas/testblas/dger.go b/blas/testblas/dger.go new file mode 100644 index 00000000..c7c87965 --- /dev/null +++ b/blas/testblas/dger.go @@ -0,0 +1,164 @@ +package testblas + +import "testing" + +type Dgerer interface { + Dger(m, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) +} + +func DgerTest(t *testing.T, blasser Dgerer) { + for _, test := range []struct { + name string + a [][]float64 + m int + n int + x []float64 + y []float64 + incX int + incY int + ansAlphaEq1 []float64 + + trueAns [][]float64 + }{ + { + name: "M gt N inc 1", + m: 5, + n: 3, + a: [][]float64{ + {1.3, 2.4, 3.5}, + {2.6, 2.8, 3.3}, + {-1.3, -4.3, -9.7}, + {8, 9, -10}, + {-12, -14, -6}, + }, + x: []float64{-2, -3, 0, 1, 2}, + y: []float64{-1.1, 5, 0}, + incX: 1, + incY: 1, + trueAns: [][]float64{{3.5, -7.6, 3.5}, {5.9, -12.2, 3.3}, {-1.3, -4.3, -9.7}, {6.9, 14, -10}, {-14.2, -4, -6}}, + }, + { + name: "M eq N inc 1", + m: 3, + n: 3, + a: [][]float64{ + {1.3, 2.4, 3.5}, + {2.6, 2.8, 3.3}, + {-1.3, -4.3, -9.7}, + }, + x: []float64{-2, -3, 0}, + y: []float64{-1.1, 5, 0}, + incX: 1, + incY: 1, + trueAns: [][]float64{{3.5, -7.6, 3.5}, {5.9, -12.2, 3.3}, {-1.3, -4.3, -9.7}}, + }, + + { + name: "M lt N inc 1", + m: 3, + n: 6, + a: [][]float64{ + {1.3, 2.4, 3.5, 4.8, 1.11, -9}, + {2.6, 2.8, 3.3, -3.4, 6.2, -8.7}, + {-1.3, -4.3, -9.7, -3.1, 8.9, 8.9}, + }, + x: []float64{-2, -3, 0}, + y: []float64{-1.1, 5, 0, 9, 19, 22}, + incX: 1, + incY: 1, + trueAns: [][]float64{{3.5, -7.6, 3.5, -13.2, -36.89, -53}, {5.9, -12.2, 3.3, -30.4, -50.8, -74.7}, {-1.3, -4.3, -9.7, -3.1, 8.9, 8.9}}, + }, + { + name: "M gt N inc not 1", + m: 5, + n: 3, + a: [][]float64{ + {1.3, 2.4, 3.5}, + {2.6, 2.8, 3.3}, + {-1.3, -4.3, -9.7}, + {8, 9, -10}, + {-12, -14, -6}, + }, + x: []float64{-2, -3, 0, 1, 2, 6, 0, 9, 7}, + y: []float64{-1.1, 5, 0, 8, 7, -5, 7}, + incX: 2, + incY: 3, + trueAns: [][]float64{{3.5, -13.6, -10.5}, {2.6, 2.8, 3.3}, {-3.5, 11.7, 4.3}, {8, 9, -10}, {-19.700000000000003, 42, 43}}, + }, + { + name: "M eq N inc not 1", + m: 3, + n: 3, + a: [][]float64{ + {1.3, 2.4, 3.5}, + {2.6, 2.8, 3.3}, + {-1.3, -4.3, -9.7}, + }, + x: []float64{-2, -3, 0, 8, 7, -9, 7, -6, 12, 6, 6, 6, -11}, + y: []float64{-1.1, 5, 0, 0, 9, 8, 6}, + incX: 4, + incY: 3, + trueAns: [][]float64{{3.5, 2.4, -8.5}, {-5.1, 2.8, 45.3}, {-14.5, -4.3, 62.3}}, + }, + { + name: "M lt N inc not 1", + m: 3, + n: 6, + a: [][]float64{ + {1.3, 2.4, 3.5, 4.8, 1.11, -9}, + {2.6, 2.8, 3.3, -3.4, 6.2, -8.7}, + {-1.3, -4.3, -9.7, -3.1, 8.9, 8.9}, + }, + x: []float64{-2, -3, 0, 0, 8, 0, 9, -3}, + y: []float64{-1.1, 5, 0, 9, 19, 22, 11, -8.11, -9.22, 9.87, 7}, + incX: 3, + incY: 2, + trueAns: [][]float64{{3.5, 2.4, -34.5, -17.2, 19.55, -23}, {2.6, 2.8, 3.3, -3.4, 6.2, -8.7}, {-11.2, -4.3, 161.3, 95.9, -74.08, 71.9}}, + }, + } { + // TODO: Add tests where a is longer + // TODO: Add panic tests + // TODO: Add negative increment tests + + x := sliceCopy(test.x) + y := sliceCopy(test.y) + + a := sliceOfSliceCopy(test.a) + + // Test with row major + alpha := 1.0 + aFlat := flatten(a) + blasser.Dger(test.m, test.n, alpha, x, test.incX, y, test.incY, aFlat, test.n) + ans := unflatten(aFlat, test.m, test.n) + dgercomp(t, x, test.x, y, test.y, ans, test.trueAns, test.name+" row maj") + + // Test with different alpha + alpha = 4.0 + aFlat = flatten(a) + blasser.Dger(test.m, test.n, alpha, x, test.incX, y, test.incY, aFlat, test.n) + ans = unflatten(aFlat, test.m, test.n) + trueCopy := sliceOfSliceCopy(test.trueAns) + for i := range trueCopy { + for j := range trueCopy[i] { + trueCopy[i][j] = alpha*(trueCopy[i][j]-a[i][j]) + a[i][j] + } + } + dgercomp(t, x, test.x, y, test.y, ans, trueCopy, test.name+" row maj alpha") + } +} + +func dgercomp(t *testing.T, x, xCopy, y, yCopy []float64, ans [][]float64, trueAns [][]float64, name string) { + if !dSliceEqual(x, xCopy) { + t.Errorf("case %v: x modified during call to dger", name) + } + if !dSliceEqual(y, yCopy) { + t.Errorf("case %v: x modified during call to dger", name) + } + + for i := range ans { + if !dSliceTolEqual(ans[i], trueAns[i]) { + t.Errorf("case %v: answer mismatch. Expected %v, Found %v", name, trueAns, ans) + break + } + } +} diff --git a/blas/testblas/dsbmv.go b/blas/testblas/dsbmv.go new file mode 100644 index 00000000..1a8c9c35 --- /dev/null +++ b/blas/testblas/dsbmv.go @@ -0,0 +1,83 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dsbmver interface { + Dsbmv(ul blas.Uplo, n, k int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DsbmvTest(t *testing.T, blasser Dsbmver) { + for i, test := range []struct { + ul blas.Uplo + n int + k int + alpha float64 + beta float64 + a [][]float64 + x []float64 + y []float64 + + ans []float64 + }{ + { + ul: blas.Upper, + n: 4, + k: 2, + alpha: 2, + beta: 3, + a: [][]float64{ + {7, 8, 2, 0}, + {0, 8, 2, -3}, + {0, 0, 3, 6}, + {0, 0, 0, 9}, + }, + x: []float64{1, 2, 3, 4}, + y: []float64{-1, -2, -3, -4}, + ans: []float64{55, 30, 69, 84}, + }, + { + ul: blas.Lower, + n: 4, + k: 2, + alpha: 2, + beta: 3, + a: [][]float64{ + {7, 0, 0, 0}, + {8, 8, 0, 0}, + {2, 2, 3, 0}, + {0, -3, 6, 9}, + }, + x: []float64{1, 2, 3, 4}, + y: []float64{-1, -2, -3, -4}, + ans: []float64{55, 30, 69, 84}, + }, + } { + extra := 0 + var aFlat []float64 + if test.ul == blas.Upper { + aFlat = flattenBanded(test.a, test.k, 0) + } else { + aFlat = flattenBanded(test.a, 0, test.k) + } + incTest := func(incX, incY, extra int) { + xnew := makeIncremented(test.x, incX, extra) + ynew := makeIncremented(test.y, incY, extra) + ans := makeIncremented(test.ans, incY, extra) + blasser.Dsbmv(test.ul, test.n, test.k, test.alpha, aFlat, test.k+1, xnew, incX, test.beta, ynew, incY) + if !dSliceTolEqual(ans, ynew) { + t.Errorf("Case %v: Want %v, got %v", i, ans, ynew) + } + } + incTest(1, 1, extra) + incTest(1, 3, extra) + incTest(1, -3, extra) + incTest(2, 3, extra) + incTest(2, -3, extra) + incTest(3, 2, extra) + incTest(-3, 2, extra) + } +} diff --git a/blas/testblas/dspmv.go b/blas/testblas/dspmv.go new file mode 100644 index 00000000..352bc4a9 --- /dev/null +++ b/blas/testblas/dspmv.go @@ -0,0 +1,73 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dspmver interface { + Dspmv(ul blas.Uplo, n int, alpha float64, ap []float64, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DspmvTest(t *testing.T, blasser Dspmver) { + for i, test := range []struct { + ul blas.Uplo + n int + a [][]float64 + x []float64 + y []float64 + alpha float64 + beta float64 + ans []float64 + }{ + { + ul: blas.Upper, + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 8, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + y: []float64{6, 7, 8}, + alpha: 2.1, + beta: -3, + ans: []float64{137.4, 189, 240.6}, + }, + { + ul: blas.Lower, + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 8, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + y: []float64{6, 7, 8}, + alpha: 2.1, + beta: -3, + ans: []float64{137.4, 189, 240.6}, + }, + } { + incTest := func(incX, incY, extra int) { + x := makeIncremented(test.x, incX, extra) + y := makeIncremented(test.y, incY, extra) + aFlat := flattenTriangular(test.a, test.ul) + ans := makeIncremented(test.ans, incY, extra) + + blasser.Dspmv(test.ul, test.n, test.alpha, aFlat, x, incX, test.beta, y, incY) + if !floats.EqualApprox(ans, y, 1e-14) { + t.Errorf("Case %v, incX=%v, incY=%v: Want %v, got %v.", i, incX, incY, ans, y) + } + } + incTest(1, 1, 0) + incTest(2, 3, 0) + incTest(3, 2, 0) + incTest(-3, 2, 0) + incTest(-2, 4, 0) + incTest(2, -1, 0) + incTest(-3, -4, 3) + } +} diff --git a/blas/testblas/dspr.go b/blas/testblas/dspr.go new file mode 100644 index 00000000..25e0ee40 --- /dev/null +++ b/blas/testblas/dspr.go @@ -0,0 +1,71 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dsprer interface { + Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64) +} + +func DsprTest(t *testing.T, blasser Dsprer) { + for i, test := range []struct { + ul blas.Uplo + n int + a [][]float64 + x []float64 + alpha float64 + ans [][]float64 + }{ + { + ul: blas.Upper, + n: 4, + a: [][]float64{ + {10, 2, 0, 1}, + {0, 1, 2, 3}, + {0, 0, 9, 15}, + {0, 0, 0, -6}, + }, + x: []float64{1, 2, 0, 5}, + alpha: 8, + ans: [][]float64{ + {18, 18, 0, 41}, + {0, 33, 2, 83}, + {0, 0, 9, 15}, + {0, 0, 0, 194}, + }, + }, + { + ul: blas.Lower, + n: 3, + a: [][]float64{ + {10, 2, 0}, + {4, 1, 2}, + {2, 7, 9}, + }, + x: []float64{3, 0, 5}, + alpha: 8, + ans: [][]float64{ + {82, 2, 0}, + {4, 1, 2}, + {122, 7, 209}, + }, + }, + } { + incTest := func(incX, extra int) { + xnew := makeIncremented(test.x, incX, extra) + aFlat := flattenTriangular(test.a, test.ul) + ans := flattenTriangular(test.ans, test.ul) + blasser.Dspr(test.ul, test.n, test.alpha, xnew, incX, aFlat) + if !dSliceTolEqual(aFlat, ans) { + t.Errorf("Case %v, idx %v: Want %v, got %v.", i, incX, ans, aFlat) + } + } + incTest(1, 3) + incTest(1, 0) + incTest(3, 2) + incTest(-2, 2) + } +} diff --git a/blas/testblas/dspr2.go b/blas/testblas/dspr2.go new file mode 100644 index 00000000..40b0cd32 --- /dev/null +++ b/blas/testblas/dspr2.go @@ -0,0 +1,76 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dspr2er interface { + Dspr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64) +} + +func Dspr2Test(t *testing.T, blasser Dspr2er) { + for i, test := range []struct { + n int + a [][]float64 + ul blas.Uplo + x []float64 + y []float64 + alpha float64 + ans [][]float64 + }{ + { + n: 3, + a: [][]float64{ + {7, 2, 4}, + {0, 3, 5}, + {0, 0, 6}, + }, + x: []float64{2, 3, 4}, + y: []float64{5, 6, 7}, + alpha: 2, + ul: blas.Upper, + ans: [][]float64{ + {47, 56, 72}, + {0, 75, 95}, + {0, 0, 118}, + }, + }, + { + n: 3, + a: [][]float64{ + {7, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + x: []float64{2, 3, 4}, + y: []float64{5, 6, 7}, + alpha: 2, + ul: blas.Lower, + ans: [][]float64{ + {47, 0, 0}, + {56, 75, 0}, + {72, 95, 118}, + }, + }, + } { + incTest := func(incX, incY, extra int) { + aFlat := flattenTriangular(test.a, test.ul) + x := makeIncremented(test.x, incX, extra) + y := makeIncremented(test.y, incY, extra) + blasser.Dspr2(test.ul, test.n, test.alpha, x, incX, y, incY, aFlat) + ansFlat := flattenTriangular(test.ans, test.ul) + if !floats.EqualApprox(aFlat, ansFlat, 1e-14) { + t.Errorf("Case %v, incX = %v, incY = %v. Want %v, got %v.", i, incX, incY, ansFlat, aFlat) + } + } + incTest(1, 1, 0) + incTest(-2, 1, 0) + incTest(-2, 3, 0) + incTest(2, -3, 0) + incTest(3, -2, 0) + incTest(-3, -4, 0) + } +} diff --git a/blas/testblas/dsymm.go b/blas/testblas/dsymm.go new file mode 100644 index 00000000..5e07e07d --- /dev/null +++ b/blas/testblas/dsymm.go @@ -0,0 +1,277 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsymmer interface { + Dsymm(s blas.Side, ul blas.Uplo, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) +} + +func DsymmTest(t *testing.T, blasser Dsymmer) { + for i, test := range []struct { + m int + n int + side blas.Side + ul blas.Uplo + a [][]float64 + b [][]float64 + c [][]float64 + alpha float64 + beta float64 + ans [][]float64 + }{ + { + side: blas.Left, + ul: blas.Upper, + m: 3, + n: 4, + a: [][]float64{ + {2, 3, 4}, + {0, 6, 7}, + {0, 0, 10}, + }, + b: [][]float64{ + {2, 3, 4, 8}, + {5, 6, 7, 15}, + {8, 9, 10, 20}, + }, + c: [][]float64{ + {8, 12, 2, 1}, + {9, 12, 9, 9}, + {12, 1, -1, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {126, 156, 144, 285}, + {211, 252, 275, 535}, + {282, 291, 327, 689}, + }, + }, + { + side: blas.Left, + ul: blas.Upper, + m: 4, + n: 3, + a: [][]float64{ + {2, 3, 4, 8}, + {0, 6, 7, 9}, + {0, 0, 10, 10}, + {0, 0, 0, 11}, + }, + b: [][]float64{ + {2, 3, 4}, + {5, 6, 7}, + {8, 9, 10}, + {2, 1, 1}, + }, + c: [][]float64{ + {8, 12, 2}, + {9, 12, 9}, + {12, 1, -1}, + {1, 9, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {158, 172, 160}, + {247, 270, 293}, + {322, 311, 347}, + {329, 385, 427}, + }, + }, + { + side: blas.Left, + ul: blas.Lower, + m: 3, + n: 4, + a: [][]float64{ + {2, 0, 0}, + {3, 6, 0}, + {4, 7, 10}, + }, + b: [][]float64{ + {2, 3, 4, 8}, + {5, 6, 7, 15}, + {8, 9, 10, 20}, + }, + c: [][]float64{ + {8, 12, 2, 1}, + {9, 12, 9, 9}, + {12, 1, -1, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {126, 156, 144, 285}, + {211, 252, 275, 535}, + {282, 291, 327, 689}, + }, + }, + { + side: blas.Left, + ul: blas.Lower, + m: 4, + n: 3, + a: [][]float64{ + {2, 0, 0, 0}, + {3, 6, 0, 0}, + {4, 7, 10, 0}, + {8, 9, 10, 11}, + }, + b: [][]float64{ + {2, 3, 4}, + {5, 6, 7}, + {8, 9, 10}, + {2, 1, 1}, + }, + c: [][]float64{ + {8, 12, 2}, + {9, 12, 9}, + {12, 1, -1}, + {1, 9, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {158, 172, 160}, + {247, 270, 293}, + {322, 311, 347}, + {329, 385, 427}, + }, + }, + { + side: blas.Right, + ul: blas.Upper, + m: 3, + n: 4, + a: [][]float64{ + {2, 0, 0, 0}, + {3, 6, 0, 0}, + {4, 7, 10, 0}, + {3, 4, 5, 6}, + }, + b: [][]float64{ + {2, 3, 4, 9}, + {5, 6, 7, -3}, + {8, 9, 10, -2}, + }, + c: [][]float64{ + {8, 12, 2, 10}, + {9, 12, 9, 10}, + {12, 1, -1, 10}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {32, 72, 86, 138}, + {47, 108, 167, -6}, + {68, 111, 197, 6}, + }, + }, + { + side: blas.Right, + ul: blas.Upper, + m: 4, + n: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 6, 0}, + {4, 7, 10}, + }, + b: [][]float64{ + {2, 3, 4}, + {5, 6, 7}, + {8, 9, 10}, + {2, 1, 1}, + }, + c: [][]float64{ + {8, 12, 2}, + {9, 12, 9}, + {12, 1, -1}, + {1, 9, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {32, 72, 86}, + {47, 108, 167}, + {68, 111, 197}, + {11, 39, 35}, + }, + }, + { + side: blas.Right, + ul: blas.Lower, + m: 3, + n: 4, + a: [][]float64{ + {2, 0, 0, 0}, + {3, 6, 0, 0}, + {4, 7, 10, 0}, + {3, 4, 5, 6}, + }, + b: [][]float64{ + {2, 3, 4, 2}, + {5, 6, 7, 1}, + {8, 9, 10, 1}, + }, + c: [][]float64{ + {8, 12, 2, 1}, + {9, 12, 9, 9}, + {12, 1, -1, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {94, 156, 164, 103}, + {145, 244, 301, 187}, + {208, 307, 397, 247}, + }, + }, + { + side: blas.Right, + ul: blas.Lower, + m: 4, + n: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 6, 0}, + {4, 7, 10}, + }, + b: [][]float64{ + {2, 3, 4}, + {5, 6, 7}, + {8, 9, 10}, + {2, 1, 1}, + }, + c: [][]float64{ + {8, 12, 2}, + {9, 12, 9}, + {12, 1, -1}, + {1, 9, 5}, + }, + alpha: 2, + beta: 3, + ans: [][]float64{ + {82, 140, 144}, + {139, 236, 291}, + {202, 299, 387}, + {25, 65, 65}, + }, + }, + } { + aFlat := flatten(test.a) + bFlat := flatten(test.b) + cFlat := flatten(test.c) + ansFlat := flatten(test.ans) + blasser.Dsymm(test.side, test.ul, test.m, test.n, test.alpha, aFlat, len(test.a[0]), bFlat, test.n, test.beta, cFlat, test.n) + if !floats.EqualApprox(cFlat, ansFlat, 1e-14) { + t.Errorf("Case %v: Want %v, got %v.", i, ansFlat, cFlat) + } + } +} diff --git a/blas/testblas/dsymv.go b/blas/testblas/dsymv.go new file mode 100644 index 00000000..b3fd4ec2 --- /dev/null +++ b/blas/testblas/dsymv.go @@ -0,0 +1,73 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsymver interface { + Dsymv(ul blas.Uplo, n int, alpha float64, a []float64, lda int, x []float64, incX int, beta float64, y []float64, incY int) +} + +func DsymvTest(t *testing.T, blasser Dsymver) { + for i, test := range []struct { + ul blas.Uplo + n int + a [][]float64 + x []float64 + y []float64 + alpha float64 + beta float64 + ans []float64 + }{ + { + ul: blas.Upper, + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 8, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + y: []float64{6, 7, 8}, + alpha: 2.1, + beta: -3, + ans: []float64{137.4, 189, 240.6}, + }, + { + ul: blas.Lower, + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 8, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + y: []float64{6, 7, 8}, + alpha: 2.1, + beta: -3, + ans: []float64{137.4, 189, 240.6}, + }, + } { + incTest := func(incX, incY, extra int) { + x := makeIncremented(test.x, incX, extra) + y := makeIncremented(test.y, incY, extra) + aFlat := flatten(test.a) + ans := makeIncremented(test.ans, incY, extra) + + blasser.Dsymv(test.ul, test.n, test.alpha, aFlat, test.n, x, incX, test.beta, y, incY) + if !floats.EqualApprox(ans, y, 1e-14) { + t.Errorf("Case %v, incX=%v, incY=%v: Want %v, got %v.", i, incX, incY, ans, y) + } + } + incTest(1, 1, 0) + incTest(2, 3, 0) + incTest(3, 2, 0) + incTest(-3, 2, 0) + incTest(-2, 4, 0) + incTest(2, -1, 0) + incTest(-3, -4, 3) + } +} diff --git a/blas/testblas/dsyr.go b/blas/testblas/dsyr.go new file mode 100644 index 00000000..4c404794 --- /dev/null +++ b/blas/testblas/dsyr.go @@ -0,0 +1,72 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dsyrer interface { + Dsyr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, a []float64, lda int) +} + +func DsyrTest(t *testing.T, blasser Dsyrer) { + for i, test := range []struct { + ul blas.Uplo + n int + a [][]float64 + x []float64 + alpha float64 + ans [][]float64 + }{ + { + ul: blas.Upper, + n: 4, + a: [][]float64{ + {10, 2, 0, 1}, + {0, 1, 2, 3}, + {0, 0, 9, 15}, + {0, 0, 0, -6}, + }, + x: []float64{1, 2, 0, 5}, + alpha: 8, + ans: [][]float64{ + {18, 18, 0, 41}, + {0, 33, 2, 83}, + {0, 0, 9, 15}, + {0, 0, 0, 194}, + }, + }, + { + ul: blas.Lower, + n: 3, + a: [][]float64{ + {10, 2, 0}, + {4, 1, 2}, + {2, 7, 9}, + }, + x: []float64{3, 0, 5}, + alpha: 8, + ans: [][]float64{ + {82, 2, 0}, + {4, 1, 2}, + {122, 7, 209}, + }, + }, + } { + incTest := func(incX, extra int) { + xnew := makeIncremented(test.x, incX, extra) + aFlat := flatten(test.a) + ans := flatten(test.ans) + lda := test.n + blasser.Dsyr(test.ul, test.n, test.alpha, xnew, incX, aFlat, lda) + if !dSliceTolEqual(aFlat, ans) { + t.Errorf("Case %v, idx %v: Want %v, got %v.", i, incX, ans, aFlat) + } + } + incTest(1, 3) + incTest(1, 0) + incTest(3, 2) + incTest(-2, 2) + } +} diff --git a/blas/testblas/dsyr2.go b/blas/testblas/dsyr2.go new file mode 100644 index 00000000..e9069592 --- /dev/null +++ b/blas/testblas/dsyr2.go @@ -0,0 +1,76 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsyr2er interface { + Dsyr2(ul blas.Uplo, n int, alpha float64, x []float64, incX int, y []float64, incY int, a []float64, lda int) +} + +func Dsyr2Test(t *testing.T, blasser Dsyr2er) { + for i, test := range []struct { + n int + a [][]float64 + ul blas.Uplo + x []float64 + y []float64 + alpha float64 + ans [][]float64 + }{ + { + n: 3, + a: [][]float64{ + {7, 2, 4}, + {0, 3, 5}, + {0, 0, 6}, + }, + x: []float64{2, 3, 4}, + y: []float64{5, 6, 7}, + alpha: 2, + ul: blas.Upper, + ans: [][]float64{ + {47, 56, 72}, + {0, 75, 95}, + {0, 0, 118}, + }, + }, + { + n: 3, + a: [][]float64{ + {7, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + x: []float64{2, 3, 4}, + y: []float64{5, 6, 7}, + alpha: 2, + ul: blas.Lower, + ans: [][]float64{ + {47, 0, 0}, + {56, 75, 0}, + {72, 95, 118}, + }, + }, + } { + incTest := func(incX, incY, extra int) { + aFlat := flatten(test.a) + x := makeIncremented(test.x, incX, extra) + y := makeIncremented(test.y, incY, extra) + blasser.Dsyr2(test.ul, test.n, test.alpha, x, incX, y, incY, aFlat, test.n) + ansFlat := flatten(test.ans) + if !floats.EqualApprox(aFlat, ansFlat, 1e-14) { + t.Errorf("Case %v, incX = %v, incY = %v. Want %v, got %v.", i, incX, incY, ansFlat, aFlat) + } + } + incTest(1, 1, 0) + incTest(-2, 1, 0) + incTest(-2, 3, 0) + incTest(2, -3, 0) + incTest(3, -2, 0) + incTest(-3, -4, 0) + } +} diff --git a/blas/testblas/dsyr2k.go b/blas/testblas/dsyr2k.go new file mode 100644 index 00000000..7c8600b5 --- /dev/null +++ b/blas/testblas/dsyr2k.go @@ -0,0 +1,201 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsyr2ker interface { + Dsyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, b []float64, ldb int, beta float64, c []float64, ldc int) +} + +func Dsyr2kTest(t *testing.T, blasser Dsyr2ker) { + for i, test := range []struct { + ul blas.Uplo + tA blas.Transpose + n int + k int + alpha float64 + a [][]float64 + b [][]float64 + c [][]float64 + beta float64 + ans [][]float64 + }{ + { + ul: blas.Upper, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 0, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + b: [][]float64{ + {7, 8}, + {9, 10}, + {11, 12}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 5, 6}, + {0, 0, 9}, + }, + beta: 2, + ans: [][]float64{ + {2, 4, 6}, + {0, 10, 12}, + {0, 0, 18}, + }, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 0, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + b: [][]float64{ + {7, 8}, + {9, 10}, + {11, 12}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {2, 0, 0}, + {4, 6, 0}, + {8, 10, 12}, + }, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + b: [][]float64{ + {7, 8}, + {9, 10}, + {11, 12}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + beta: 2, + ans: [][]float64{ + {140, 250, 360}, + {0, 410, 568}, + {0, 0, 774}, + }, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + b: [][]float64{ + {7, 8}, + {9, 10}, + {11, 12}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {140, 0, 0}, + {250, 410, 0}, + {360, 568, 774}, + }, + }, + { + ul: blas.Upper, + tA: blas.Trans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 3, 5}, + {2, 4, 6}, + }, + b: [][]float64{ + {7, 9, 11}, + {8, 10, 12}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + beta: 2, + ans: [][]float64{ + {140, 250, 360}, + {0, 410, 568}, + {0, 0, 774}, + }, + }, + { + ul: blas.Lower, + tA: blas.Trans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 3, 5}, + {2, 4, 6}, + }, + b: [][]float64{ + {7, 9, 11}, + {8, 10, 12}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {140, 0, 0}, + {250, 410, 0}, + {360, 568, 774}, + }, + }, + } { + aFlat := flatten(test.a) + bFlat := flatten(test.b) + cFlat := flatten(test.c) + ansFlat := flatten(test.ans) + blasser.Dsyr2k(test.ul, test.tA, test.n, test.k, test.alpha, aFlat, len(test.a[0]), bFlat, len(test.b[0]), test.beta, cFlat, len(test.c[0])) + if !floats.EqualApprox(ansFlat, cFlat, 1e-14) { + t.Errorf("Case %v. Want %v, got %v.", i, ansFlat, cFlat) + } + } +} diff --git a/blas/testblas/dsyrk.go b/blas/testblas/dsyrk.go new file mode 100644 index 00000000..99e18ebb --- /dev/null +++ b/blas/testblas/dsyrk.go @@ -0,0 +1,171 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dsyker interface { + Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64, ldc int) +} + +func DsyrkTest(t *testing.T, blasser Dsyker) { + for i, test := range []struct { + ul blas.Uplo + tA blas.Transpose + n int + k int + alpha float64 + a [][]float64 + c [][]float64 + beta float64 + ans [][]float64 + }{ + { + ul: blas.Upper, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 0, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 5, 6}, + {0, 0, 9}, + }, + beta: 2, + ans: [][]float64{ + {2, 4, 6}, + {0, 10, 12}, + {0, 0, 18}, + }, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 0, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 3, 0}, + {4, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {2, 0, 0}, + {4, 6, 0}, + {8, 10, 12}, + }, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + beta: 2, + ans: [][]float64{ + {17, 37, 57}, + {0, 83, 127}, + {0, 0, 195}, + }, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 2}, + {3, 4}, + {5, 6}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {17, 0, 0}, + {37, 83, 0}, + {57, 127, 195}, + }, + }, + { + ul: blas.Upper, + tA: blas.Trans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 3, 5}, + {2, 4, 6}, + }, + c: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + beta: 2, + ans: [][]float64{ + {17, 37, 57}, + {0, 83, 127}, + {0, 0, 195}, + }, + }, + { + ul: blas.Lower, + tA: blas.Trans, + n: 3, + k: 2, + alpha: 3, + a: [][]float64{ + {1, 3, 5}, + {2, 4, 6}, + }, + c: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + beta: 2, + ans: [][]float64{ + {17, 0, 0}, + {37, 83, 0}, + {57, 127, 195}, + }, + }, + } { + aFlat := flatten(test.a) + cFlat := flatten(test.c) + ansFlat := flatten(test.ans) + blasser.Dsyrk(test.ul, test.tA, test.n, test.k, test.alpha, aFlat, len(test.a[0]), test.beta, cFlat, len(test.c[0])) + if !floats.EqualApprox(ansFlat, cFlat, 1e-14) { + t.Errorf("Case %v. Want %v, got %v.", i, ansFlat, cFlat) + } + } +} diff --git a/blas/testblas/dtbmv.go b/blas/testblas/dtbmv.go new file mode 100644 index 00000000..b0dee676 --- /dev/null +++ b/blas/testblas/dtbmv.go @@ -0,0 +1,123 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dtbmver interface { + Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) +} + +func DtbmvTest(t *testing.T, blasser Dtbmver) { + for i, test := range []struct { + ul blas.Uplo + tA blas.Transpose + d blas.Diag + n int + k int + a [][]float64 + x []float64 + ans []float64 + }{ + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + n: 3, + k: 1, + a: [][]float64{ + {1, 2, 0}, + {0, 1, 4}, + {0, 0, 1}, + }, + x: []float64{2, 3, 4}, + ans: []float64{8, 19, 4}, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 1, + a: [][]float64{ + {1, 3, 0, 0, 0}, + {0, 6, 7, 0, 0}, + {0, 0, 2, 1, 0}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + ans: []float64{7, 33, 10, 63, -5}, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 1, + a: [][]float64{ + {7, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {0, 7, 2, 0, 0}, + {0, 0, 1, 12, 0}, + {0, 0, 0, 3, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + ans: []float64{7, 15, 20, 51, 7}, + }, + { + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {7, 3, 9, 0, 0}, + {0, 6, 7, 10, 0}, + {0, 0, 2, 1, 11}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + ans: []float64{7, 15, 29, 71, 40}, + }, + { + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {7, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {9, 7, 2, 0, 0}, + {0, 10, 1, 12, 0}, + {0, 0, 11, 3, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + ans: []float64{40, 73, 65, 63, -5}, + }, + } { + extra := 0 + var aFlat []float64 + if test.ul == blas.Upper { + aFlat = flattenBanded(test.a, test.k, 0) + } else { + aFlat = flattenBanded(test.a, 0, test.k) + } + incTest := func(incX, extra int) { + xnew := makeIncremented(test.x, incX, extra) + ans := makeIncremented(test.ans, incX, extra) + lda := test.k + 1 + blasser.Dtbmv(test.ul, test.tA, test.d, test.n, test.k, aFlat, lda, xnew, incX) + if !dSliceTolEqual(ans, xnew) { + t.Errorf("Case %v, Inc %v: Want %v, got %v", i, incX, ans, xnew) + } + } + incTest(1, extra) + incTest(3, extra) + incTest(-2, extra) + } +} diff --git a/blas/testblas/dtbsv.go b/blas/testblas/dtbsv.go new file mode 100644 index 00000000..b609cbfa --- /dev/null +++ b/blas/testblas/dtbsv.go @@ -0,0 +1,256 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dtbsver interface { + Dtbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) + Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) +} + +func DtbsvTest(t *testing.T, blasser Dtbsver) { + for i, test := range []struct { + ul blas.Uplo + tA blas.Transpose + d blas.Diag + n, k int + a [][]float64 + lda int + x []float64 + incX int + ans []float64 + }{ + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 1, + a: [][]float64{ + {1, 3, 0, 0, 0}, + {0, 6, 7, 0, 0}, + {0, 0, 2, 1, 0}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{2.479166666666667, -0.493055555555556, 0.708333333333333, 1.583333333333333, -5.000000000000000}, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 3, 5, 0, 0}, + {0, 6, 7, 5, 0}, + {0, 0, 2, 1, 5}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{-15.854166666666664, -16.395833333333336, 13.208333333333334, 1.583333333333333, -5.000000000000000}, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 1, + a: [][]float64{ + {1, 3, 0, 0, 0}, + {0, 6, 7, 0, 0}, + {0, 0, 2, 1, 0}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{2.479166666666667, -101, -0.493055555555556, -201, 0.708333333333333, -301, 1.583333333333333, -401, -5.000000000000000, -501, -601, -701}, + }, + { + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 3, 5, 0, 0}, + {0, 6, 7, 5, 0}, + {0, 0, 2, 1, 5}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{-15.854166666666664, -101, -16.395833333333336, -201, 13.208333333333334, -301, 1.583333333333333, -401, -5.000000000000000, -501, -601, -701}, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {5, 7, 2, 0, 0}, + {0, 5, 1, 12, 0}, + {0, 0, 5, 3, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{1, -0.166666666666667, -0.416666666666667, 0.437500000000000, -5.770833333333334}, + }, + { + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {5, 7, 2, 0, 0}, + {0, 5, 1, 12, 0}, + {0, 0, 5, 3, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{1, -101, -0.166666666666667, -201, -0.416666666666667, -301, 0.437500000000000, -401, -5.770833333333334, -501, -601, -701}, + }, + { + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 3, 5, 0, 0}, + {0, 6, 7, 5, 0}, + {0, 0, 2, 1, 5}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{1, -0.166666666666667, -0.416666666666667, 0.437500000000000, -5.770833333333334}, + }, + { + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 3, 5, 0, 0}, + {0, 6, 7, 5, 0}, + {0, 0, 2, 1, 5}, + {0, 0, 0, 12, 3}, + {0, 0, 0, 0, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{1, -101, -0.166666666666667, -201, -0.416666666666667, -301, 0.437500000000000, -401, -5.770833333333334, -501, -601, -701}, + }, + { + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {5, 7, 2, 0, 0}, + {0, 5, 1, 12, 0}, + {0, 0, 5, 3, -1}, + }, + x: []float64{1, 2, 3, 4, 5}, + incX: 1, + ans: []float64{-15.854166666666664, -16.395833333333336, 13.208333333333334, 1.583333333333333, -5.000000000000000}, + }, + { + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + n: 5, + k: 2, + a: [][]float64{ + {1, 0, 0, 0, 0}, + {3, 6, 0, 0, 0}, + {5, 7, 2, 0, 0}, + {0, 5, 1, 12, 0}, + {0, 0, 5, 3, -1}, + }, + x: []float64{1, -101, 2, -201, 3, -301, 4, -401, 5, -501, -601, -701}, + incX: 2, + ans: []float64{-15.854166666666664, -101, -16.395833333333336, -201, 13.208333333333334, -301, 1.583333333333333, -401, -5.000000000000000, -501, -601, -701}, + }, + } { + var aFlat []float64 + if test.ul == blas.Upper { + aFlat = flattenBanded(test.a, test.k, 0) + } else { + aFlat = flattenBanded(test.a, 0, test.k) + } + xCopy := sliceCopy(test.x) + // TODO: Have tests where the banded matrix is constructed explicitly + // to allow testing for lda =! k+1 + blasser.Dtbsv(test.ul, test.tA, test.d, test.n, test.k, aFlat, test.k+1, xCopy, test.incX) + if !dSliceTolEqual(test.ans, xCopy) { + t.Errorf("Case %v: Want %v, got %v", i, test.ans, xCopy) + } + } + + /* + // TODO: Uncomment when Dtrsv is fixed + // Compare with dense for larger matrices + for _, ul := range [...]blas.Uplo{blas.Upper, blas.Lower} { + for _, tA := range [...]blas.Transpose{blas.NoTrans, blas.Trans} { + for _, n := range [...]int{7, 8, 11} { + for _, d := range [...]blas.Diag{blas.NonUnit, blas.Unit} { + for _, k := range [...]int{0, 1, 3} { + for _, incX := range [...]int{1, 3} { + a := make([][]float64, n) + for i := range a { + a[i] = make([]float64, n) + for j := range a[i] { + a[i][j] = rand.Float64() + } + } + x := make([]float64, n) + for i := range x { + x[i] = rand.Float64() + } + extra := 3 + xinc := makeIncremented(x, incX, extra) + bandX := sliceCopy(xinc) + var aFlatBand []float64 + if ul == blas.Upper { + aFlatBand = flattenBanded(a, k, 0) + } else { + aFlatBand = flattenBanded(a, 0, k) + } + blasser.Dtbsv(ul, tA, d, n, k, aFlatBand, k+1, bandX, incX) + + aFlatDense := flatten(a) + denseX := sliceCopy(xinc) + blasser.Dtrsv(ul, tA, d, n, aFlatDense, n, denseX, incX) + if !dSliceTolEqual(denseX, bandX) { + t.Errorf("Case %v: dense banded mismatch") + } + } + } + } + } + } + } + */ +} diff --git a/blas/testblas/dtpmv.go b/blas/testblas/dtpmv.go new file mode 100644 index 00000000..04af1641 --- /dev/null +++ b/blas/testblas/dtpmv.go @@ -0,0 +1,129 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtpmver interface { + Dtpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) +} + +func DtpmvTest(t *testing.T, blasser Dtpmver) { + for i, test := range []struct { + n int + a [][]float64 + x []float64 + d blas.Diag + ul blas.Uplo + tA blas.Transpose + ans []float64 + }{ + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{74, 86, 65}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{62, 54, 5}, + }, + { + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 9, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Lower, + tA: blas.NoTrans, + ans: []float64{15, 54, 126}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {6, 1, 0}, + {7, 10, 1}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Lower, + tA: blas.NoTrans, + ans: []float64{3, 22, 66}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.Trans, + ans: []float64{15, 54, 126}, + }, + { + n: 3, + a: [][]float64{ + {1, 6, 7}, + {0, 1, 10}, + {0, 0, 1}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.Trans, + ans: []float64{3, 22, 66}, + }, + { + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 9, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Lower, + tA: blas.Trans, + ans: []float64{74, 86, 65}, + }, + } { + incTest := func(incX, extra int) { + aFlat := flattenTriangular(test.a, test.ul) + x := makeIncremented(test.x, incX, extra) + blasser.Dtpmv(test.ul, test.tA, test.d, test.n, aFlat, x, incX) + ans := makeIncremented(test.ans, incX, extra) + if !floats.EqualApprox(x, ans, 1e-14) { + t.Errorf("Case %v, idx %v: Want %v, got %v.", i, incX, ans, x) + } + } + incTest(1, 0) + incTest(-3, 3) + incTest(4, 3) + } +} diff --git a/blas/testblas/dtpsv.go b/blas/testblas/dtpsv.go new file mode 100644 index 00000000..9fee545e --- /dev/null +++ b/blas/testblas/dtpsv.go @@ -0,0 +1,144 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtpsver interface { + Dtpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []float64, x []float64, incX int) +} + +func DtpsvTest(t *testing.T, blasser Dtpsver) { + for i, test := range []struct { + n int + a [][]float64 + ul blas.Uplo + tA blas.Transpose + d blas.Diag + x []float64 + ans []float64 + }{ + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{4.15625, -0.890625, 0.875}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 1, 15}, + {0, 0, 1}, + }, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{182, -99, 7}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{5, -0.5, -0.0625}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{5, -4, 52}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{5, -0.5, -0.0625}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{5, -4, 52}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{4.15625, -0.890625, 0.875}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 1, 0}, + {3, 15, 1}, + }, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{182, -99, 7}, + }, + } { + incTest := func(incX, extra int) { + aFlat := flattenTriangular(test.a, test.ul) + x := makeIncremented(test.x, incX, extra) + blasser.Dtpsv(test.ul, test.tA, test.d, test.n, aFlat, x, incX) + ans := makeIncremented(test.ans, incX, extra) + if !floats.EqualApprox(x, ans, 1e-14) { + t.Errorf("Case %v, incX = %v: Want %v, got %v.", i, incX, ans, x) + } + } + incTest(1, 0) + incTest(-2, 0) + incTest(3, 0) + incTest(-3, 8) + incTest(4, 2) + } +} diff --git a/blas/testblas/dtrmm.go b/blas/testblas/dtrmm.go new file mode 100644 index 00000000..95cccec5 --- /dev/null +++ b/blas/testblas/dtrmm.go @@ -0,0 +1,806 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtrmmer interface { + Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, alpha float64, a []float64, lda int, b []float64, ldb int) +} + +func DtrmmTest(t *testing.T, blasser Dtrmmer) { + for i, test := range []struct { + s blas.Side + ul blas.Uplo + tA blas.Transpose + d blas.Diag + m int + n int + alpha float64 + a [][]float64 + b [][]float64 + ans [][]float64 + }{ + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3, 4}, + {0, 5, 6, 7}, + {0, 0, 8, 9}, + {0, 0, 0, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {320, 340, 360}, + {588, 624, 660}, + {598, 632, 666}, + {380, 400, 420}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2}, + {0, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {72, 78, 84}, + {130, 140, 150}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3, 4}, + {0, 5, 6, 7}, + {0, 0, 8, 9}, + {0, 0, 0, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {320, 340, 360}, + {484, 512, 540}, + {374, 394, 414}, + {38, 40, 42}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2}, + {0, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {72, 78, 84}, + {26, 28, 30}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0, 0}, + {2, 5, 0, 0}, + {3, 6, 8, 0}, + {4, 7, 9, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 22, 24}, + {170, 184, 198}, + {472, 506, 540}, + {930, 990, 1050}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0}, + {2, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 22, 24}, + {170, 184, 198}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0, 0}, + {2, 5, 0, 0}, + {3, 6, 8, 0}, + {4, 7, 9, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 22, 24}, + {66, 72, 78}, + {248, 268, 288}, + {588, 630, 672}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0}, + {2, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 22, 24}, + {66, 72, 78}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3, 4}, + {0, 5, 6, 7}, + {0, 0, 8, 9}, + {0, 0, 0, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 22, 24}, + {170, 184, 198}, + {472, 506, 540}, + {930, 990, 1050}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2}, + {0, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 22, 24}, + {170, 184, 198}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3, 4}, + {0, 5, 6, 7}, + {0, 0, 8, 9}, + {0, 0, 0, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 22, 24}, + {66, 72, 78}, + {248, 268, 288}, + {588, 630, 672}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2}, + {0, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 22, 24}, + {66, 72, 78}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0, 0}, + {2, 5, 0, 0}, + {3, 6, 8, 0}, + {4, 7, 9, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {320, 340, 360}, + {588, 624, 660}, + {598, 632, 666}, + {380, 400, 420}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0}, + {2, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {72, 78, 84}, + {130, 140, 150}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0, 0}, + {2, 5, 0, 0}, + {3, 6, 8, 0}, + {4, 7, 9, 10}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {320, 340, 360}, + {484, 512, 540}, + {374, 394, 414}, + {38, 40, 42}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0}, + {2, 5}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {72, 78, 84}, + {26, 28, 30}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 128, 314}, + {26, 164, 398}, + {32, 200, 482}, + {38, 236, 566}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 128, 314}, + {26, 164, 398}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 62, 194}, + {26, 80, 248}, + {32, 98, 302}, + {38, 116, 356}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 62, 194}, + {26, 80, 248}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {136, 208, 144}, + {172, 262, 180}, + {208, 316, 216}, + {244, 370, 252}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {136, 208, 144}, + {172, 262, 180}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {136, 142, 24}, + {172, 178, 30}, + {208, 214, 36}, + {244, 250, 42}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {136, 142, 24}, + {172, 178, 30}, + }, + }, + + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {136, 208, 144}, + {172, 262, 180}, + {208, 316, 216}, + {244, 370, 252}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {136, 208, 144}, + {172, 262, 180}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {136, 142, 24}, + {172, 178, 30}, + {208, 214, 36}, + {244, 250, 42}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {136, 142, 24}, + {172, 178, 30}, + }, + }, + + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 128, 314}, + {26, 164, 398}, + {32, 200, 482}, + {38, 236, 566}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 128, 314}, + {26, 164, 398}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {20, 62, 194}, + {26, 80, 248}, + {32, 98, 302}, + {38, 116, 356}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 2, + a: [][]float64{ + {1, 0, 0}, + {2, 4, 0}, + {3, 5, 6}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {20, 62, 194}, + {26, 80, 248}, + }, + }, + } { + aFlat := flatten(test.a) + bFlat := flatten(test.b) + ansFlat := flatten(test.ans) + blasser.Dtrmm(test.s, test.ul, test.tA, test.d, test.m, test.n, test.alpha, aFlat, len(test.a[0]), bFlat, len(test.b[0])) + if !floats.EqualApprox(ansFlat, bFlat, 1e-14) { + t.Errorf("Case %v. Want %v, got %v.", i, ansFlat, bFlat) + } + } +} diff --git a/blas/testblas/dtrmv.go b/blas/testblas/dtrmv.go new file mode 100644 index 00000000..8f3b6d35 --- /dev/null +++ b/blas/testblas/dtrmv.go @@ -0,0 +1,147 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtrmver interface { + Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) +} + +func DtrmvTest(t *testing.T, blasser Dtrmver) { + for i, test := range []struct { + n int + a [][]float64 + x []float64 + d blas.Diag + ul blas.Uplo + tA blas.Transpose + ans []float64 + }{ + { + n: 1, + a: [][]float64{{5}}, + x: []float64{2}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{10}, + }, + { + n: 1, + a: [][]float64{{5}}, + x: []float64{2}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{2}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{74, 86, 65}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.NoTrans, + ans: []float64{62, 54, 5}, + }, + { + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 9, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Lower, + tA: blas.NoTrans, + ans: []float64{15, 54, 126}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {6, 1, 0}, + {7, 10, 1}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Lower, + tA: blas.NoTrans, + ans: []float64{3, 22, 66}, + }, + { + n: 3, + a: [][]float64{ + {5, 6, 7}, + {0, 9, 10}, + {0, 0, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Upper, + tA: blas.Trans, + ans: []float64{15, 54, 126}, + }, + { + n: 3, + a: [][]float64{ + {1, 6, 7}, + {0, 1, 10}, + {0, 0, 1}, + }, + x: []float64{3, 4, 5}, + d: blas.Unit, + ul: blas.Upper, + tA: blas.Trans, + ans: []float64{3, 22, 66}, + }, + { + n: 3, + a: [][]float64{ + {5, 0, 0}, + {6, 9, 0}, + {7, 10, 13}, + }, + x: []float64{3, 4, 5}, + d: blas.NonUnit, + ul: blas.Lower, + tA: blas.Trans, + ans: []float64{74, 86, 65}, + }, + } { + incTest := func(incX, extra int) { + aFlat := flatten(test.a) + x := makeIncremented(test.x, incX, extra) + blasser.Dtrmv(test.ul, test.tA, test.d, test.n, aFlat, test.n, x, incX) + ans := makeIncremented(test.ans, incX, extra) + if !floats.EqualApprox(x, ans, 1e-14) { + t.Errorf("Case %v, idx %v: Want %v, got %v.", i, incX, ans, x) + } + } + incTest(1, 3) + incTest(-3, 3) + incTest(4, 3) + } +} diff --git a/blas/testblas/dtrmvbench.go b/blas/testblas/dtrmvbench.go new file mode 100644 index 00000000..c6b439e9 --- /dev/null +++ b/blas/testblas/dtrmvbench.go @@ -0,0 +1,30 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testblas + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func DtrmvBenchmark(b *testing.B, dtrmv Dtrmver, n, lda, incX int, ul blas.Uplo, tA blas.Transpose, d blas.Diag) { + rnd := rand.New(rand.NewSource(0)) + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + } + + x := make([]float64, n*incX) + for i := range x { + x[i] = rnd.Float64() + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + dtrmv.Dtrmv(ul, tA, d, n, a, lda, x, incX) + } +} diff --git a/blas/testblas/dtrsm.go b/blas/testblas/dtrsm.go new file mode 100644 index 00000000..9623397c --- /dev/null +++ b/blas/testblas/dtrsm.go @@ -0,0 +1,811 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtrsmer interface { + Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas.Diag, m, n int, + alpha float64, a []float64, lda int, b []float64, ldb int) +} + +func DtrsmTest(t *testing.T, blasser Dtrsmer) { + for i, test := range []struct { + s blas.Side + ul blas.Uplo + tA blas.Transpose + d blas.Diag + m int + n int + alpha float64 + a [][]float64 + b [][]float64 + ans [][]float64 + }{ + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 3, + n: 2, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 5}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {1, 3.4}, + {-0.5, -0.5}, + {2, 3.2}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 3, + n: 2, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 5}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {60, 96}, + {-42, -66}, + {10, 16}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 3, + n: 4, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 5}, + }, + b: [][]float64{ + {3, 6, 2, 9}, + {4, 7, 1, 3}, + {5, 8, 9, 10}, + }, + ans: [][]float64{ + {1, 3.4, 1.2, 13}, + {-0.5, -0.5, -4, -3.5}, + {2, 3.2, 3.6, 4}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 3, + n: 4, + alpha: 2, + a: [][]float64{ + {1, 2, 3}, + {0, 4, 5}, + {0, 0, 5}, + }, + b: [][]float64{ + {3, 6, 2, 9}, + {4, 7, 1, 3}, + {5, 8, 9, 10}, + }, + ans: [][]float64{ + {60, 96, 126, 146}, + {-42, -66, -88, -94}, + {10, 16, 18, 20}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 7}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {4.5, 9}, + {-0.375, -1.5}, + {-0.75, -12.0 / 7}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 7}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {9, 18}, + {-15, -33}, + {60, 132}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 7}, + }, + b: [][]float64{ + {3, 6, 2, 9}, + {4, 7, 1, 3}, + {5, 8, 9, 10}, + }, + ans: [][]float64{ + {4.5, 9, 3, 13.5}, + {-0.375, -1.5, -1.5, -63.0 / 8}, + {-0.75, -12.0 / 7, 3, 39.0 / 28}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 7}, + }, + b: [][]float64{ + {3, 6, 2, 9}, + {4, 7, 1, 3}, + {5, 8, 9, 10}, + }, + ans: [][]float64{ + {9, 18, 6, 27}, + {-15, -33, -15, -72}, + {60, 132, 87, 327}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {4.5, 9}, + {-0.30, -1.2}, + {-6.0 / 35, -24.0 / 35}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {9, 18}, + {-15, -33}, + {69, 150}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {3, 6, 6, 7}, + {4, 7, 8, 9}, + {5, 8, 10, 11}, + }, + ans: [][]float64{ + {4.5, 9, 9, 10.5}, + {-0.3, -1.2, -0.6, -0.9}, + {-6.0 / 35, -24.0 / 35, -12.0 / 35, -18.0 / 35}, + }, + }, + { + s: blas.Left, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {3, 6, 6, 7}, + {4, 7, 8, 9}, + {5, 8, 10, 11}, + }, + ans: [][]float64{ + {9, 18, 18, 21}, + {-15, -33, -30, -36}, + {69, 150, 138, 165}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 8}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {-0.46875, 0.375}, + {0.1875, 0.75}, + {1.875, 3}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 3, + n: 2, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 8}, + }, + b: [][]float64{ + {3, 6}, + {4, 7}, + {5, 8}, + }, + ans: [][]float64{ + {168, 267}, + {-78, -123}, + {15, 24}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 8}, + }, + b: [][]float64{ + {3, 6, 2, 3}, + {4, 7, 4, 5}, + {5, 8, 6, 7}, + }, + ans: [][]float64{ + {-0.46875, 0.375, -2.0625, -1.78125}, + {0.1875, 0.75, -0.375, -0.1875}, + {1.875, 3, 2.25, 2.625}, + }, + }, + { + s: blas.Left, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 3, + n: 4, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 4, 0}, + {5, 6, 8}, + }, + b: [][]float64{ + {3, 6, 2, 3}, + {4, 7, 4, 5}, + {5, 8, 6, 7}, + }, + ans: [][]float64{ + {168, 267, 204, 237}, + {-78, -123, -96, -111}, + {15, 24, 18, 21}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {15, -2.4, -48.0 / 35}, + {19.5, -3.3, -66.0 / 35}, + {24, -4.2, -2.4}, + {28.5, -5.1, -102.0 / 35}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {30, -57, 258}, + {39, -75, 339}, + {48, -93, 420}, + {57, -111, 501}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 7}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {15, -2.4, -48.0 / 35}, + {19.5, -3.3, -66.0 / 35}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {30, -57, 258}, + {39, -75, 339}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {4.2, 1.2, 4.5}, + {5.775, 1.65, 5.625}, + {7.35, 2.1, 6.75}, + {8.925, 2.55, 7.875}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {435, -183, 36}, + {543, -228, 45}, + {651, -273, 54}, + {759, -318, 63}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {4.2, 1.2, 4.5}, + {5.775, 1.65, 5.625}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {435, -183, 36}, + {543, -228, 45}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {4.2, 1.2, 4.5}, + {5.775, 1.65, 5.625}, + {7.35, 2.1, 6.75}, + {8.925, 2.55, 7.875}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {435, -183, 36}, + {543, -228, 45}, + {651, -273, 54}, + {759, -318, 63}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {4.2, 1.2, 4.5}, + {5.775, 1.65, 5.625}, + }, + }, + { + s: blas.Right, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 3, 4}, + {0, 5, 6}, + {0, 0, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {435, -183, 36}, + {543, -228, 45}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {15, -2.4, -1.2}, + {19.5, -3.3, -1.65}, + {24, -4.2, -2.1}, + {28.5, -5.1, -2.55}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 4, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + {16, 17, 18}, + {19, 20, 21}, + }, + ans: [][]float64{ + {30, -57, 258}, + {39, -75, 339}, + {48, -93, 420}, + {57, -111, 501}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {15, -2.4, -1.2}, + {19.5, -3.3, -1.65}, + }, + }, + { + s: blas.Right, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + m: 2, + n: 3, + alpha: 3, + a: [][]float64{ + {2, 0, 0}, + {3, 5, 0}, + {4, 6, 8}, + }, + b: [][]float64{ + {10, 11, 12}, + {13, 14, 15}, + }, + ans: [][]float64{ + {30, -57, 258}, + {39, -75, 339}, + }, + }, + } { + aFlat := flatten(test.a) + bFlat := flatten(test.b) + ansFlat := flatten(test.ans) + var lda int + if test.s == blas.Left { + lda = test.m + } else { + lda = test.n + } + blasser.Dtrsm(test.s, test.ul, test.tA, test.d, test.m, test.n, test.alpha, aFlat, lda, bFlat, test.n) + if !floats.EqualApprox(ansFlat, bFlat, 1e-13) { + t.Errorf("Case %v: Want %v, got %v.", i, ansFlat, bFlat) + } + } +} diff --git a/blas/testblas/dtrsv.go b/blas/testblas/dtrsv.go new file mode 100644 index 00000000..1638177c --- /dev/null +++ b/blas/testblas/dtrsv.go @@ -0,0 +1,144 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dtrsver interface { + Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) +} + +func DtrsvTest(t *testing.T, blasser Dtrsver) { + for i, test := range []struct { + n int + a [][]float64 + ul blas.Uplo + tA blas.Transpose + d blas.Diag + x []float64 + ans []float64 + }{ + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{4.15625, -0.890625, 0.875}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 1, 15}, + {0, 0, 1}, + }, + ul: blas.Upper, + tA: blas.NoTrans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{182, -99, 7}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{5, -0.5, -0.0625}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.NoTrans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{5, -4, 52}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.Trans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{5, -0.5, -0.0625}, + }, + { + n: 3, + a: [][]float64{ + {1, 2, 3}, + {0, 8, 15}, + {0, 0, 8}, + }, + ul: blas.Upper, + tA: blas.Trans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{5, -4, 52}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 8, 0}, + {3, 15, 8}, + }, + ul: blas.Lower, + tA: blas.Trans, + d: blas.NonUnit, + x: []float64{5, 6, 7}, + ans: []float64{4.15625, -0.890625, 0.875}, + }, + { + n: 3, + a: [][]float64{ + {1, 0, 0}, + {2, 1, 0}, + {3, 15, 1}, + }, + ul: blas.Lower, + tA: blas.Trans, + d: blas.Unit, + x: []float64{5, 6, 7}, + ans: []float64{182, -99, 7}, + }, + } { + incTest := func(incX, extra int) { + aFlat := flatten(test.a) + x := makeIncremented(test.x, incX, extra) + blasser.Dtrsv(test.ul, test.tA, test.d, test.n, aFlat, test.n, x, incX) + ans := makeIncremented(test.ans, incX, extra) + if !floats.EqualApprox(x, ans, 1e-14) { + t.Errorf("Case %v, incX = %v: Want %v, got %v.", i, incX, ans, x) + } + } + incTest(1, 0) + incTest(-2, 0) + incTest(3, 0) + incTest(-3, 8) + incTest(4, 2) + } +} diff --git a/blas/testblas/dtxmv.go b/blas/testblas/dtxmv.go new file mode 100644 index 00000000..c55da3bd --- /dev/null +++ b/blas/testblas/dtxmv.go @@ -0,0 +1,145 @@ +package testblas + +import ( + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dtxmver interface { + Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, lda int, x []float64, incX int) + Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []float64, lda int, x []float64, incX int) + Dtpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []float64, x []float64, incX int) +} + +type vec struct { + data []float64 + inc int +} + +var cases = []struct { + n, k int + ul blas.Uplo + d blas.Diag + ldab int + tr, tb, tp []float64 + ins []vec + solNoTrans []float64 + solTrans []float64 +}{ + { + n: 3, + k: 1, + ul: blas.Upper, + d: blas.NonUnit, + tr: []float64{1, 2, 0, 0, 3, 4, 0, 0, 5}, + tb: []float64{1, 2, 3, 4, 5, 0}, + ldab: 2, + tp: []float64{1, 2, 0, 3, 4, 5}, + ins: []vec{ + {[]float64{2, 3, 4}, 1}, + {[]float64{2, 1, 3, 1, 4}, 2}, + {[]float64{4, 1, 3, 1, 2}, -2}, + }, + solNoTrans: []float64{8, 25, 20}, + solTrans: []float64{2, 13, 32}, + }, + { + n: 3, + k: 1, + ul: blas.Upper, + d: blas.Unit, + tr: []float64{1, 2, 0, 0, 3, 4, 0, 0, 5}, + tb: []float64{1, 2, 3, 4, 5, 0}, + ldab: 2, + tp: []float64{1, 2, 0, 3, 4, 5}, + ins: []vec{ + {[]float64{2, 3, 4}, 1}, + {[]float64{2, 1, 3, 1, 4}, 2}, + {[]float64{4, 1, 3, 1, 2}, -2}, + }, + solNoTrans: []float64{8, 19, 4}, + solTrans: []float64{2, 7, 16}, + }, + { + n: 3, + k: 1, + ul: blas.Lower, + d: blas.NonUnit, + tr: []float64{1, 0, 0, 2, 3, 0, 0, 4, 5}, + tb: []float64{0, 1, 2, 3, 4, 5}, + ldab: 2, + tp: []float64{1, 2, 3, 0, 4, 5}, + ins: []vec{ + {[]float64{2, 3, 4}, 1}, + {[]float64{2, 1, 3, 1, 4}, 2}, + {[]float64{4, 1, 3, 1, 2}, -2}, + }, + solNoTrans: []float64{2, 13, 32}, + solTrans: []float64{8, 25, 20}, + }, + { + n: 3, + k: 1, + ul: blas.Lower, + d: blas.Unit, + tr: []float64{1, 0, 0, 2, 3, 0, 0, 4, 5}, + tb: []float64{0, 1, 2, 3, 4, 5}, + ldab: 2, + tp: []float64{1, 2, 3, 0, 4, 5}, + ins: []vec{ + {[]float64{2, 3, 4}, 1}, + {[]float64{2, 1, 3, 1, 4}, 2}, + {[]float64{4, 1, 3, 1, 2}, -2}, + }, + solNoTrans: []float64{2, 7, 16}, + solTrans: []float64{8, 19, 4}, + }, +} + +func DtxmvTest(t *testing.T, blasser Dtxmver) { + + for nc, c := range cases { + for nx, x := range c.ins { + in := make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtrmv(c.ul, blas.NoTrans, c.d, c.n, c.tr, c.n, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solNoTrans, 1) { + t.Error("Wrong Dtrmv result for: NoTrans in Case:", nc, "input:", nx) + } + + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtrmv(c.ul, blas.Trans, c.d, c.n, c.tr, c.n, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solTrans, 1) { + t.Error("Wrong Dtrmv result for: Trans in Case:", nc, "input:", nx) + } + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtbmv(c.ul, blas.NoTrans, c.d, c.n, c.k, c.tb, c.ldab, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solNoTrans, 1) { + t.Error("Wrong Dtbmv result for: NoTrans in Case:", nc, "input:", nx) + } + + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtbmv(c.ul, blas.Trans, c.d, c.n, c.k, c.tb, c.ldab, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solTrans, 1) { + t.Error("Wrong Dtbmv result for: Trans in Case:", nc, "input:", nx) + } + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtpmv(c.ul, blas.NoTrans, c.d, c.n, c.tp, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solNoTrans, 1) { + t.Error("Wrong Dtpmv result for: NoTrans in Case:", nc, "input:", nx) + } + + in = make([]float64, len(x.data)) + copy(in, x.data) + blasser.Dtpmv(c.ul, blas.Trans, c.d, c.n, c.tp, in, x.inc) + if !dStridedSliceTolEqual(c.n, in, x.inc, c.solTrans, 1) { + t.Error("Wrong Dtpmv result for: Trans in Case:", nc, "input:", nx) + } + } + } +} diff --git a/blas/testblas/level1double.go b/blas/testblas/level1double.go new file mode 100644 index 00000000..b4acd85a --- /dev/null +++ b/blas/testblas/level1double.go @@ -0,0 +1,2049 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package testblas provides tests for blas implementations. +package testblas + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" + + "math" + "testing" +) + +type DoubleOneVectorCase struct { + Name string + X []float64 + Incx int + N int + Panic bool + Dasum float64 + Dnrm2 float64 + Idamax int + DscalCases []DScalCase +} + +type DScalCase struct { + Alpha float64 + Ans []float64 + Name string +} + +var DoubleOneVectorCases = []DoubleOneVectorCase{ + { + Name: "AllPositive", + X: []float64{6, 5, 4, 2, 6}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 23, + Dnrm2: 10.81665382639196787935766380241148783875388972153573863813135, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: 0, + Ans: []float64{0, 0, 0, 0, 0}, + }, + { + Alpha: 1, + Ans: []float64{6, 5, 4, 2, 6}, + }, + { + Alpha: -2, + Ans: []float64{-12, -10, -8, -4, -12}, + }, + }, + }, + { + Name: "LeadingZero", + X: []float64{0, 1}, + Incx: 1, + N: 2, + Panic: false, + Dasum: 1, + Dnrm2: 1, + Idamax: 1, + DscalCases: []DScalCase{ + { + Alpha: 0, + Ans: []float64{0, 0}, + }, + { + Alpha: 1, + Ans: []float64{0, 1}, + }, + { + Alpha: -2, + Ans: []float64{0, -2}, + }, + }, + }, + { + Name: "MaxInMiddle", + X: []float64{6, 5, 9, 0, 6}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 26, + Dnrm2: 13.34166406412633371248943627250846646911846482744007727141318, + Idamax: 2, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-12, -10, -18, 0, -12}, + }, + }, + }, + { + Name: "MaxAtEnd", + X: []float64{6, 5, -9, 0, 10}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 30, + Dnrm2: 15.55634918610404553681857596630667886426639062914642880494347, + Idamax: 4, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-12, -10, 18, 0, -20}, + }, + }, + }, + { + Name: "AllNegative", + X: []float64{-6, -5, -4, -2, -6}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 23, + Dnrm2: 10.81665382639196787935766380241148783875388972153573863813135, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 10, 8, 4, 12}, + }, + }, + }, + { + Name: "AllMixed", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 1, + N: 5, + Panic: false, + Dasum: 23, + Dnrm2: 10.81665382639196787935766380241148783875388972153573863813135, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, -10, -8, 4, 12}, + }, + }, + }, + { + Name: "ZeroN", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 1, + N: 0, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "OneN", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 1, + N: 1, + Panic: false, + Dasum: 6, + Dnrm2: 6, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "PositiveExactInc", + X: []float64{-6, 5, 10, -2, -5}, + Incx: 2, + N: 3, + Panic: false, + Dasum: 21, + Dnrm2: 12.68857754044952038019377274608948979173952662752515253090272, + Idamax: 1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 5, -20, -2, 10}, + }, + }, + }, + { + Name: "PositiveOffInc", + X: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + Incx: 3, + N: 3, + Panic: false, + Dasum: 18, + Dnrm2: 11.83215956619923208513465658312323409683100246158868064575943, + Idamax: 2, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 5, 4, 4, -6, 8, -20, 11}, + }, + }, + }, + { + Name: "PositiveShortInc", + X: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + Incx: 3, + N: 2, + Panic: false, + Dasum: 8, + Dnrm2: 6.324555320336758663997787088865437067439110278650433653715009, + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{12, 5, 4, 4, -6, 8, 10, 11}, + }, + }, + }, + { + Name: "NegativeInc", + X: []float64{-6, 5, 4, -2, -6}, + Incx: -1, + N: 5, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "NegativeExactInc", + X: []float64{-6, 5, 4, -2, -6}, + Incx: -2, + N: 3, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "NegativeOffInc", + X: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + Incx: -3, + N: 2, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + }, + }, + }, + { + Name: "NegativeShortInc", + X: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + Incx: -3, + N: 2, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6, 8, 10, 11}, + }, + }, + }, + { + Name: "NegativeN", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 2, + N: -5, + Panic: true, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "ZeroInc", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 0, + N: 5, + Panic: true, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "OutOfBounds", + X: []float64{-6, 5, 4, -2, -6}, + Incx: 2, + N: 6, + Panic: true, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "NegativeOutOfBounds", + X: []float64{-6, 5, 4, -2, -6}, + Incx: -2, + N: 6, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-6, 5, 4, -2, -6}, + }, + }, + }, + { + Name: "NaN", + X: []float64{math.NaN(), 2.0}, + Incx: 1, + N: 2, + Panic: false, + Dasum: math.NaN(), + Dnrm2: math.NaN(), + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{math.NaN(), -4.0}, + }, + { + Alpha: 0, + Ans: []float64{0, 0}, + }, + }, + }, + { + Name: "NaNInc", + X: []float64{math.NaN(), math.NaN(), 2.0}, + Incx: 2, + N: 2, + Panic: false, + Dasum: math.NaN(), + Dnrm2: math.NaN(), + Idamax: 0, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{math.NaN(), math.NaN(), -4.0}, + }, + { + Alpha: 0, + Ans: []float64{0, math.NaN(), 0}, + }, + }, + }, + { + Name: "Empty", + X: []float64{}, + Incx: 1, + N: 0, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{}, + }, + { + Alpha: 0, + Ans: []float64{}, + }, + }, + }, + { + Name: "EmptyZeroInc", + X: []float64{}, + Incx: 0, + N: 0, + Panic: true, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{}, + }, + { + Alpha: 0, + Ans: []float64{}, + }, + }, + }, + { + Name: "EmptyReverse", + X: []float64{}, + Incx: -1, + N: 0, + Panic: false, + Dasum: 0, + Dnrm2: 0, + Idamax: -1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{}, + }, + { + Alpha: 0, + Ans: []float64{}, + }, + }, + }, + { + Name: "MultiInf", + X: []float64{5, math.Inf(1), math.Inf(-1), 8, 9}, + Incx: 1, + N: 5, + Panic: false, + Dasum: math.Inf(1), + Dnrm2: math.Inf(1), + Idamax: 1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-10, math.Inf(-1), math.Inf(1), -16, -18}, + }, + { + Alpha: 0, + Ans: []float64{0, 0, 0, 0, 0}, + }, + }, + }, + { + Name: "NaNInf", + X: []float64{5, math.NaN(), math.Inf(-1), 8, 9}, + Incx: 1, + N: 5, + Panic: false, + Dasum: math.NaN(), + Dnrm2: math.NaN(), + Idamax: 2, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-10, math.NaN(), math.Inf(1), -16, -18}, + }, + { + Alpha: 0, + Ans: []float64{0, 0, 0, 0, 0}, + }, + }, + }, + { + Name: "InfNaN", + X: []float64{5, math.Inf(1), math.NaN(), 8, 9}, + Incx: 1, + N: 5, + Panic: false, + Dasum: math.NaN(), + Dnrm2: math.NaN(), + Idamax: 1, + DscalCases: []DScalCase{ + { + Alpha: -2, + Ans: []float64{-10, math.Inf(-1), math.NaN(), -16, -18}, + }, + { + Alpha: 0, + Ans: []float64{0, 0, 0, 0, 0}, + }, + }, + }, +} + +type DoubleTwoVectorCase struct { + Name string + X []float64 + Y []float64 + XTmp []float64 + YTmp []float64 + Incx int + Incy int + N int + Panic bool + // For Daxpy + DaxpyCases []DaxpyCase + DdotAns float64 + DswapAns DTwoVecAnswer + DcopyAns DTwoVecAnswer + DrotCases []DrotCase + DrotmCases []DrotmCase +} + +type DaxpyCase struct { + Alpha float64 + Ans []float64 +} + +type DrotCase struct { + C float64 + S float64 + XAns []float64 + YAns []float64 +} + +type DrotmCase struct { + P blas.DrotmParams + XAns []float64 + YAns []float64 + Name string +} + +type DTwoVecAnswer struct { + X []float64 + Y []float64 +} + +var DoubleTwoVectorCases = []DoubleTwoVectorCase{ + { + Name: "UnitaryInc", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0}, + Incx: 1, + Incy: 1, + N: 6, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 1, + Ans: []float64{18, 13, -2, 10, 20, 4}, + }, + { + Alpha: 2, + Ans: []float64{28, 28, -8, 13, 34, 11}, + }, + { + Alpha: -3, + Ans: []float64{-22, -47, 22, -2, -36, -24}, + }, + { + Alpha: 0, + Ans: []float64{8, -2, 4, 7, 6, -3}, + }, + }, + DdotAns: 110, + DswapAns: DTwoVecAnswer{ + X: []float64{8, -2, 4, 7, 6, -3}, + Y: []float64{10, 15, -6, 3, 14, 7}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{10, 15, -6, 3, 14, 7}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(0), + S: math.Sin(0), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3}, + }, + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{12.444023964292095, 12.749380282068351, -3.7473736752571014, 5.677251193294846, 15.224018588957296, 5.076299724034451}, + YAns: []float64{3.024279678886205, -8.151889500183792, 6.160940718590796, 5.076299724034451, -0.4788089421498931, -5.677251193294846}, + }, + { + C: math.Cos(0.5 * math.Pi), + S: math.Sin(0.5 * math.Pi), + XAns: []float64{8, -2, 4, 7, 6, -3}, + YAns: []float64{-10, -15, 6, -3, -14, -7}, + }, + { + C: math.Cos(math.Pi), + S: math.Sin(math.Pi), + XAns: []float64{-10, -15, 6, -3, -14, -7}, + YAns: []float64{-8, 2, -4, -7, -6, 3}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Identity, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3}, + Name: "Neg2Flag", + }, + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + Name: "Neg1Flag", + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{9.2, 15.2, -6.4, 2.3, 13.4, 7.3}, + YAns: []float64{9, -0.5, 3.4, 7.3, 7.4, -2.3}, + Name: "ZeroFlag", + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{13, 5.5, 1, 8.5, 13, 0.5}, + YAns: []float64{-4.4, -16.4, 8.8, 1.9, -9.8, -9.1}, + Name: "OneFlag", + }, + }, + }, + { + Name: "UnitaryIncLong", + X: []float64{10, 15, -6, 3, 14, 7, 8, -9, 10}, + Y: []float64{8, -2, 4, 7, 6, -3, 7, -6}, + XTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 1, + Incy: 1, + N: 6, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 1, + Ans: []float64{18, 13, -2, 10, 20, 4, 7, -6}, + }, + { + Alpha: 2, + Ans: []float64{28, 28, -8, 13, 34, 11, 7, -6}, + }, + { + Alpha: -3, + Ans: []float64{-22, -47, 22, -2, -36, -24, 7, -6}, + }, + { + Alpha: 0, + Ans: []float64{8, -2, 4, 7, 6, -3, 7, -6}, + }, + }, + DdotAns: 110, + DswapAns: DTwoVecAnswer{ + X: []float64{8, -2, 4, 7, 6, -3, 8, -9, 10}, + Y: []float64{10, 15, -6, 3, 14, 7, 7, -6}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7, 8, -9, 10}, + Y: []float64{10, 15, -6, 3, 14, 7, 7, -6}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(0), + S: math.Sin(0), + XAns: []float64{10, 15, -6, 3, 14, 7, 8, -9, 10}, + YAns: []float64{8, -2, 4, 7, 6, -3, 7, -6}, + }, + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{12.444023964292095, 12.749380282068351, -3.7473736752571014, 5.677251193294846, 15.224018588957296, 5.076299724034451, 8, -9, 10}, + YAns: []float64{3.024279678886205, -8.151889500183792, 6.160940718590796, 5.076299724034451, -0.4788089421498931, -5.677251193294846, 7, -6}, + }, + { + C: math.Cos(0.5 * math.Pi), + S: math.Sin(0.5 * math.Pi), + XAns: []float64{8, -2, 4, 7, 6, -3, 8, -9, 10}, + YAns: []float64{-10, -15, 6, -3, -14, -7, 7, -6}, + }, + { + C: math.Cos(math.Pi), + S: math.Sin(math.Pi), + XAns: []float64{-10, -15, 6, -3, -14, -7, 8, -9, 10}, + YAns: []float64{-8, 2, -4, -7, -6, 3, 7, -6}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Identity, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{10, 15, -6, 3, 14, 7, 8, -9, 10}, + YAns: []float64{8, -2, 4, 7, 6, -3, 7, -6}, + Name: "Neg2Flag", + }, + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6, 8, -9, 10}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8, 7, -6}, + Name: "Neg1Flag", + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{9.2, 15.2, -6.4, 2.3, 13.4, 7.3, 8, -9, 10}, + YAns: []float64{9, -0.5, 3.4, 7.3, 7.4, -2.3, 7, -6}, + Name: "ZeroFlag", + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{13, 5.5, 1, 8.5, 13, 0.5, 8, -9, 10}, + YAns: []float64{-4.4, -16.4, 8.8, 1.9, -9.8, -9.1, 7, -6}, + Name: "OneFlag", + }, + }, + }, + { + Name: "PositiveInc", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 2, + Incy: 3, + N: 3, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{28, -2, 4, -5, 6, -3, 24, 10}, + }, + }, + DdotAns: -18, + DswapAns: DTwoVecAnswer{ + X: []float64{8, 15, 7, 3, -4, 7}, + Y: []float64{10, -2, 4, -6, 6, -3, 14, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{10, -2, 4, -6, 6, -3, 14, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{12.444023964292095, 15, -2.479518890035003, 3, 10.997835971550302, 7}, + YAns: []float64{3.024279678886205, -2, 4, 8.879864079700745, 6, -3, -9.541886812516392, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 15, -6.1, 3, 13, 7}, + YAns: []float64{5, -2, 4, 2.9, 6, -3, -0.6, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{9.2, 15, -6.7, 3, 14.4, 7}, + YAns: []float64{9, -2, 4, 6.4, 6, -3, -2.6, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{13, 15, 4, 3, 3, 7}, + YAns: []float64{-4.4, -2, 4, 10.9, 6, -3, -16.8, 10}, + }, + }, + }, + { + Name: "NegativeInc", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: -2, + Incy: -3, + N: 3, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{28, -2, 4, -5, 6, -3, 24, 10}, + }, + }, + DdotAns: -18, + DswapAns: DTwoVecAnswer{ + X: []float64{8, 15, 7, 3, -4, 7}, + Y: []float64{10, -2, 4, -6, 6, -3, 14, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{10, -2, 4, -6, 6, -3, 14, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{12.444023964292095, 15, -2.479518890035003, 3, 10.997835971550302, 7}, + YAns: []float64{3.024279678886205, -2, 4, 8.879864079700745, 6, -3, -9.541886812516392, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 15, -6.1, 3, 13, 7}, + YAns: []float64{5, -2, 4, 2.9, 6, -3, -0.6, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{9.2, 15, -6.7, 3, 14.4, 7}, + YAns: []float64{9, -2, 4, 6.4, 6, -3, -2.6, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{13, 15, 4, 3, 3, 7}, + YAns: []float64{-4.4, -2, 4, 10.9, 6, -3, -16.8, 10}, + }, + }, + }, + { + Name: "MixedInc1", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 2, + Incy: -3, + N: 3, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DdotAns: 30, + DswapAns: DTwoVecAnswer{ + X: []float64{-4, 15, 7, 3, 8, 7}, + Y: []float64{14, -2, 4, -6, 6, -3, 10, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{14, -2, 4, -6, 6, -3, 10, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{7.372604823403701, 15, -2.479518890035003, 3, 16.069255112438693, 7}, + YAns: []float64{1.333806631923407, -2, 4, 8.879864079700745, 6, -3, -7.851413765553595, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{9.4, 15, -6.1, 3, 11.8, 7}, + YAns: []float64{5.4, -2, 4, 2.9, 6, -3, -1, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{10.4, 15, -6.7, 3, 13.2, 7}, + YAns: []float64{9.4, -2, 4, 6.4, 6, -3, -3, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{1, 15, 4, 3, 15, 7}, + YAns: []float64{-8.4, -2, 4, 10.9, 6, -3, -12.8, 10}, + }, + }, + }, + { + Name: "MixedInc2", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: -2, + Incy: 3, + N: 3, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DdotAns: 30, + DswapAns: DTwoVecAnswer{ + X: []float64{-4, 15, 7, 3, 8, 7}, + Y: []float64{14, -2, 4, -6, 6, -3, 10, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{14, -2, 4, -6, 6, -3, 10, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{7.372604823403701, 15, -2.479518890035003, 3, 16.069255112438693, 7}, + YAns: []float64{1.333806631923407, -2, 4, 8.879864079700745, 6, -3, -7.851413765553595, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{9.4, 15, -6.1, 3, 11.8, 7}, + YAns: []float64{5.4, -2, 4, 2.9, 6, -3, -1, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{1, 0.1, -0.1, 1}, + }, + XAns: []float64{10.4, 15, -6.7, 3, 13.2, 7}, + YAns: []float64{9.4, -2, 4, 6.4, 6, -3, -3, 10}, + }, + { + P: blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0.5, -1, 1, 0.7}, + }, + XAns: []float64{1, 15, 4, 3, 15, 7}, + YAns: []float64{-8.4, -2, 4, 10.9, 6, -3, -12.8, 10}, + }, + }, + }, + { + Name: "ZeroN", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: -2, + Incy: 3, + N: 0, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DswapAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + DcopyAns: DTwoVecAnswer{ + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + }, + { + Name: "NegativeN", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: -2, + Incy: 3, + N: -3, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + }, + }, + }, + { + Name: "ZeroIncX", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 0, + Incy: 3, + N: 2, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + }, + }, + }, + { + Name: "ZeroIncY", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 1, + Incy: 0, + N: 2, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + }, + }, + }, + { + Name: "OutOfBoundsX", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 8, + Incy: 2, + N: 2, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{8.2, 13.7, -5.8, 2, 12, 6.6}, + YAns: []float64{5, 0.5, 1.4, 3.8, 4.4, -0.8}, + }, + }, + }, + { + Name: "OutOfBoundsY", + X: []float64{10, 15, -6, 3, 14, 7}, + Y: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + XTmp: []float64{0, 0, 0, 0, 0, 0}, + YTmp: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + Incx: 2, + Incy: 8, + N: 2, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{36, -2, 4, -5, 6, -3, 16, 10}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{10, 15, -6, 3, 14, 7}, + YAns: []float64{8, -2, 4, 7, 6, -3, -4, 10}, + }, + }, + }, + { + Name: "Empty", + X: []float64{}, + Y: []float64{}, + Incx: 1, + Incy: 1, + N: 0, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{}, + YAns: []float64{}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{}, + YAns: []float64{}, + }, + }, + }, + { + Name: "EmptyZeroIncX", + X: []float64{}, + Y: []float64{}, + Incx: 0, + Incy: 1, + N: 0, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{}, + YAns: []float64{}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{}, + YAns: []float64{}, + }, + }, + }, + { + Name: "EmptyZeroIncY", + X: []float64{}, + Y: []float64{}, + Incx: 1, + Incy: 0, + N: 0, + Panic: true, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{}, + YAns: []float64{}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{}, + YAns: []float64{}, + }, + }, + }, + { + Name: "EmptyReverse", + X: []float64{}, + Y: []float64{}, + Incx: -1, + Incy: -1, + N: 0, + Panic: false, + DaxpyCases: []DaxpyCase{ + { + Alpha: 2, + Ans: []float64{}, + }, + }, + DrotCases: []DrotCase{ + { + C: math.Cos(25 * math.Pi / 180), + S: math.Sin(25 * math.Pi / 180), + XAns: []float64{}, + YAns: []float64{}, + }, + }, + DrotmCases: []DrotmCase{ + { + P: blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.9, 0.1, -0.1, 0.5}, + }, + XAns: []float64{}, + YAns: []float64{}, + }, + }, + }, +} + +type Ddotter interface { + Ddot(n int, x []float64, incX int, y []float64, incY int) float64 +} + +func DdotTest(t *testing.T, d Ddotter) { + ddot := d.Ddot + for _, c := range DoubleTwoVectorCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { ddot(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) } + testpanics(f, c.Name, t) + continue + } + dot := ddot(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) + if !dTolEqual(dot, c.DdotAns) { + t.Errorf("ddot: mismatch %v: expected %v, found %v", c.Name, c.DdotAns, dot) + } + } + + // check it works for 16-byte unaligned slices + x := []float64{1, 1, 1, 1, 1} + if n := ddot(4, x[:4], 1, x[1:], 1); n != 4 { + t.Errorf("ddot: mismatch Unaligned: expected %v, found %v", 4, n) + } + if n := ddot(2, x[:4], 2, x[1:], 2); n != 2 { + t.Errorf("ddot: mismatch Unaligned: expected %v, found %v", 2, n) + } + if n := ddot(2, x[:4], 3, x[1:], 3); n != 2 { + t.Errorf("ddot: mismatch Unaligned: expected %v, found %v", 2, n) + } +} + +type Dnrm2er interface { + Dnrm2(n int, x []float64, incX int) float64 +} + +func Dnrm2Test(t *testing.T, blasser Dnrm2er) { + dnrm2 := blasser.Dnrm2 + for _, c := range DoubleOneVectorCases { + if c.Panic { + f := func() { dnrm2(c.N, c.X, c.Incx) } + testpanics(f, c.Name, t) + continue + } + v := dnrm2(c.N, c.X, c.Incx) + if !dTolEqual(v, c.Dnrm2) { + t.Errorf("dnrm2: mismatch %v: expected %v, found %v", c.Name, c.Dnrm2, v) + } + } +} + +type Dasumer interface { + Dasum(n int, x []float64, incX int) float64 +} + +func DasumTest(t *testing.T, blasser Dasumer) { + dasum := blasser.Dasum + for _, c := range DoubleOneVectorCases { + if c.Panic { + f := func() { dasum(c.N, c.X, c.Incx) } + testpanics(f, c.Name, t) + continue + } + v := dasum(c.N, c.X, c.Incx) + if !dTolEqual(v, c.Dasum) { + t.Errorf("dasum: mismatch %v: expected %v, found %v", c.Name, c.Dasum, v) + } + } +} + +type Idamaxer interface { + Idamax(n int, x []float64, incX int) int +} + +func IdamaxTest(t *testing.T, blasser Idamaxer) { + idamax := blasser.Idamax + for _, c := range DoubleOneVectorCases { + if c.Panic { + f := func() { idamax(c.N, c.X, c.Incx) } + testpanics(f, c.Name, t) + continue + } + v := idamax(c.N, c.X, c.Incx) + if v != c.Idamax { + s := fmt.Sprintf("idamax: mismatch %v: expected %v, found %v", c.Name, c.Idamax, v) + if floats.HasNaN(c.X) { + log.Println(s) + } else { + t.Errorf(s) + } + } + } +} + +type Dswapper interface { + Dswap(n int, x []float64, incX int, y []float64, incY int) +} + +func DswapTest(t *testing.T, d Dswapper) { + dswap := d.Dswap + for _, c := range DoubleTwoVectorCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { dswap(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) } + testpanics(f, c.Name, t) + continue + } + dswap(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) + if !dSliceTolEqual(c.XTmp, c.DswapAns.X) { + t.Errorf("dswap: x mismatch %v: expected %v, found %v", c.Name, c.DswapAns.X, c.XTmp) + } + if !dSliceTolEqual(c.YTmp, c.DswapAns.Y) { + t.Errorf("dswap: y mismatch %v: expected %v, found %v", c.Name, c.DswapAns.Y, c.YTmp) + } + } +} + +type Dcopier interface { + Dcopy(n int, x []float64, incX int, y []float64, incY int) +} + +func DcopyTest(t *testing.T, d Dcopier) { + dcopy := d.Dcopy + for _, c := range DoubleTwoVectorCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { dcopy(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) } + testpanics(f, c.Name, t) + continue + } + dcopy(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy) + if !dSliceTolEqual(c.XTmp, c.DcopyAns.X) { + t.Errorf("dswap: x mismatch %v: expected %v, found %v", c.Name, c.DcopyAns.X, c.XTmp) + } + if !dSliceTolEqual(c.YTmp, c.DcopyAns.Y) { + t.Errorf("dswap: y mismatch %v: expected %v, found %v", c.Name, c.DcopyAns.Y, c.YTmp) + } + } +} + +type Daxpyer interface { + Daxpy(n int, alpha float64, x []float64, incX int, y []float64, incY int) +} + +func DaxpyTest(t *testing.T, d Daxpyer) { + daxpy := d.Daxpy + for _, c := range DoubleTwoVectorCases { + for _, kind := range c.DaxpyCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { daxpy(c.N, kind.Alpha, c.XTmp, c.Incx, c.YTmp, c.Incy) } + testpanics(f, c.Name, t) + continue + } + daxpy(c.N, kind.Alpha, c.XTmp, c.Incx, c.YTmp, c.Incy) + if !dSliceTolEqual(c.YTmp, kind.Ans) { + t.Errorf("daxpy: mismatch %v: expected %v, found %v", c.Name, kind.Ans, c.YTmp) + } + } + } +} + +type DrotgTestStruct struct { + Name string + A, B float64 + C, S, R, Z float64 +} + +var DrotgTests = []DrotgTestStruct{ + { + Name: "ZeroAB", + C: 1, + }, + { + Name: "PosA_ZeroB", + A: 0.5, + C: 1, + R: 0.5, + }, + { + Name: "NegA_ZeroB", + A: -4.6, + C: 1, + R: -4.6, + }, + { + Name: "ZeroA_PosB", + B: 3, + S: 1, + R: 3, + Z: 1, + }, + { + Name: "ZeroA_NegB", + B: -0.3, + S: 1, + R: -0.3, + Z: 1, + }, + { + Name: "PosA_PosB_AGTB", + A: 5, + B: 0.3, + C: 0.99820484546577868593549038000, + S: 0.05989229072794672115612942280, + R: 5.00899191454727744602429072688, + Z: 0.05989229072794672115612942280, + }, + { + Name: "PosA_PosB_ALTB", + A: 3, + B: 4, + C: 3.0 / 5, + S: 4.0 / 5, + R: 5, + Z: 5.0 / 3.0, + }, + + { + Name: "PosA_NegB_AGTB", + A: 2.6, + B: -0.9, + C: 0.94498607344025815971847507095, + S: -0.32711056388316628605639521686, + R: 2.751363298439520872718790879655, + Z: -0.3271105638831662860563952168, + }, + { + Name: "PosA_NegB_ALTB", + A: 2.6, + B: -2.9, + C: -0.6675450157520258540548049558, + S: 0.7445694406464903756765132200, + R: -3.8948684188300893100043812234, + Z: 1 / -0.6675450157520258540548049558, + }, + { + Name: "NegA_PosB_AGTB", + A: -11.4, + B: 10.3, + C: 0.7419981952497362418487847947, + S: -0.6704018781642353764072353847, + R: -15.363918770938617534070671122, + Z: -0.6704018781642353764072353847, + }, + { + Name: "NegA_PosB_ALTB", + A: -1.4, + B: 10.3, + C: -0.1346838895922121112404717523, + S: 0.9908886162855605326977564640, + R: 10.394710193170370442523552032, + Z: 1 / -0.1346838895922121112404717523, + }, + { + Name: "NegA_NegB_AGTB", + A: -11.4, + B: 10.3, + C: 0.7419981952497362418487847947, + S: -0.6704018781642353764072353847, + R: -15.363918770938617534070671122, + Z: -0.6704018781642353764072353847, + }, + { + Name: "NegA_NegB_ALTB", + A: -1.4, + B: -10.3, + C: 0.1346838895922121112404717523, + S: 0.9908886162855605326977564640, + R: -10.394710193170370442523552032, + Z: 1 / 0.1346838895922121112404717523, + }, +} + +type Drotger interface { + Drotg(a, b float64) (c, s, r, z float64) +} + +func DrotgTest(t *testing.T, d Drotger) { + drotg := d.Drotg + for _, test := range DrotgTests { + c, s, r, z := drotg(test.A, test.B) + if !dTolEqual(c, test.C) { + t.Errorf("drotg: c mismatch %v: expected %v, found %v", test.Name, test.C, c) + } + if !dTolEqual(s, test.S) { + t.Errorf("drotg: s mismatch %v: expected %v, found %v", test.Name, test.S, s) + } + if !dTolEqual(r, test.R) { + t.Errorf("drotg: r mismatch %v: expected %v, found %v", test.Name, test.R, r) + } + if !dTolEqual(z, test.Z) { + t.Errorf("drotg: z mismatch %v: expected %v, found %v", test.Name, test.Z, z) + } + } +} + +type DrotmgTestStruct struct { + Name string + D1, D2, X1, Y1 float64 + P *blas.DrotmParams + Rd1, Rd2, Rx1 float64 +} + +var DrotmgTests = []DrotmgTestStruct{ + { + Name: "NegD1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + }, + D1: -4, + D2: 6, + X1: 8, + Y1: -4, + }, + { + Name: "ZeroD2", + P: &blas.DrotmParams{ + Flag: blas.Identity, + }, + D1: 4, + X1: 8, + Y1: -5, + Rd1: 4, + Rx1: 8, + }, + { + Name: "ZeroY1", + P: &blas.DrotmParams{ + Flag: blas.Identity, + }, + D1: 4, + D2: -6, + X1: 8, + Rd1: 4, + Rd2: -6, + Rx1: 8, + }, + { + Name: "NegQ2_and_AQ1_LT_AQ2", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + }, + D1: 8, + D2: -6, + X1: 4, + Y1: 8, + Rd1: 0, + Rd2: 0, + Rx1: 0, + }, + { + Name: "ZeroD1", + P: &blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{0, 0, 0, 2}, + }, + D1: 0, + D2: 2, + X1: 8, + Y1: 4, + Rd1: 2, + Rd2: 0, + Rx1: 4, + }, + { + Name: "AbsQ1_GT_AbsQU__D2_Pos", + P: &blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{0, -0.625, 0.9375, 0}, + }, + D1: 2, + D2: 3, + X1: 8, + Y1: 5, + Rd1: 1.2610837438423645, + Rd2: 1.8916256157635467, + Rx1: 12.6875, + }, + { + Name: "AbsQ1_GT_AbsQU__D2_Neg", + P: &blas.DrotmParams{ + Flag: blas.OffDiagonal, + H: [4]float64{0, -0.625, -0.9375, 0}, + }, + D1: 2, + D2: -3, + X1: 8, + Y1: 5, + Rd1: 4.830188679245283, + Rd2: -7.245283018867925, + Rx1: 3.3125, + }, + { + Name: "AbsQ1_LT_AbsQU__D2_Pos", + P: &blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{5.0 / 12, 0, 0, 0.625}, + }, + D1: 2, + D2: 3, + X1: 5, + Y1: 8, + Rd1: 2.3801652892561984, + Rd2: 1.586776859504132, + Rx1: 121.0 / 12, + }, + { + Name: "D1=D2_X1=X2", + P: &blas.DrotmParams{ + Flag: blas.Diagonal, + H: [4]float64{1, 0, 0, 1}, + }, + D1: 2, + D2: 2, + X1: 8, + Y1: 8, + Rd1: 1, + Rd2: 1, + Rx1: 16, + }, + { + Name: "RD1_Big_RD2_Big_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{4096, -3584, 1792, 4096}, + }, + D1: 1600000000, + D2: 800000000, + X1: 8, + Y1: 7, + Rd1: 68.96627824858757, + Rd2: 34.483139124293785, + Rx1: 45312, + }, + { + Name: "RD1_Big_RD2_Big_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{2340.5714285714284, -4096, 4096, 4681.142857142857}, + }, + D1: 800000000, + D2: 1600000000, + X1: 8, + Y1: 7, + Rd1: 57.6914092640818, + Rd2: 28.8457046320409, + Rx1: 47396.57142857142, + }, + { + Name: "RD1_Big_RD2_Med_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{4096, -1, 0.0004096, 1}, + }, + D1: 20000000, + D2: 2, + X1: 8, + Y1: 8, + Rd1: 1.1920927762985347, + Rd2: 1.9999998000000199, + Rx1: 32768.0032768, + }, + { + Name: "RD1_Big_RD2_Med_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{4.096e-17, -1, 4096, 1e-10}, + }, + D1: 2, + D2: 20000000000, + X1: 8, + Y1: 80000000000, + Rd1: 1192.0928955078125, + Rd2: 2, + Rx1: 3.2768e+14, + }, + + // TODO: Add D1 big, D2 small, Flag = 0 + { + Name: "D1_Big_D2_Small_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{2.8671999999999997e-26, -0.000244140625, 4096, 2.44140625e-16}, + }, + D1: 0.000000014, + D2: 2000000000, + X1: 0.000008, + Y1: 8000000, + Rd1: 119.20928955078125, + Rd2: 0.234881024, + Rx1: 3.2768e+10, + }, + + { + Name: "RD1_Med_RD2_Big_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{1, -0.0004096, 1000, 4096}, + }, + D1: 2, + D2: 20000000000, + X1: 80000000, + Y1: 8, + Rd1: 1.9998000199980002, + Rd2: 1191.9736981379988, + Rx1: 8.0008e+07, + }, + { + Name: "D1_Med_D2_Big_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{50, -4096, 1, 4.096e-06}, + }, + D1: 20000000000, + D2: 0.4, + X1: 80000000, + Y1: 80000000000000000, + Rd1: 0.39999998000000103, + Rd2: 1192.092835903171, + Rx1: 8.0000004e+16, + }, + { + Name: "RD1_Med_RD2_Small_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{1, -0.0007233796296296296, 1.1111111111111111e-10, 0.000244140625}, + }, + D1: 1.2, + D2: 0.000000000045, + X1: 2.7, + Y1: 8, + Rd1: 1.1999999996049382, + Rd2: 0.0007549747197514486, + Rx1: 2.700000000888889, + }, + { + Name: "RD1_Med_RD2_Small_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.0002197265625, -1, 0.000244140625, 3.375e-11}, + }, + D1: 1.2, + D2: 0.000000000045, + X1: 2.7, + Y1: 80000000000, + Rd1: 0.0007549747199770676, + Rd2: 1.19999999996355, + Rx1: 1.9531250000593264e+07, + }, + // TODO: Add Small, Big, 0 case + { + Name: "D1_Small_D2_Big_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{2.3731773997569866e+10, -1.6777216e+07, 0.000244140625, 1.6777216e-07}, + }, + D1: 120000000000000000, + D2: 0.000000000012345, + X1: 0.08, + Y1: 8000000000000, + Rd1: 0.00010502490698765249, + Rd2: 216.1836123957717, + Rx1: 3.8516669198055897e+09, + }, + { + Name: "RD1_Small_RD2_Med_Flag_0", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.000244140625, -1e-08, 0.24414062499999997, 1}, + }, + D1: 0.0000000002, + D2: 20, + X1: 0.8, + Y1: 0.000000008, + Rd1: 0.003355409645903541, + Rd2: 19.99980000199998, + Rx1: 0.000195314453125, + }, + { + Name: "RD1_Small_RD2_Med_Flag_1", + P: &blas.DrotmParams{ + Flag: blas.Rescaling, + H: [4]float64{0.0012207031250000002, -1, 0.000244140625, 1e-09}, + }, + D1: 0.02, + D2: 0.000000000004, + X1: 0.008, + Y1: 8000000, + Rd1: 6.710886366445568e-05, + Rd2: 0.019999999900000003, + Rx1: 1953.125009765625, + }, + // TODO: Add Small, Small, 0 case + // TODO: Add Small, Small, 1 case +} + +type Drotmger interface { + Drotmg(d1, d2, x1, y1 float64) (p blas.DrotmParams, rd1, rd2, rx1 float64) +} + +func DrotmgTest(t *testing.T, d Drotmger) { + for _, test := range DrotmgTests { + + p, rd1, rd2, rx1 := d.Drotmg(test.D1, test.D2, test.X1, test.Y1) + + if p.Flag != test.P.Flag { + t.Errorf("drotmg flag mismatch %v: expected %v, found %v", test.Name, test.P.Flag, p.Flag) + } + for i, val := range p.H { + if !dTolEqual(test.P.H[i], val) { + t.Errorf("drotmg H mismatch %v: expected %v, found %v", test.Name, test.P.H, p.H) + break + } + } + if !dTolEqual(rd1, test.Rd1) { + t.Errorf("drotmg rd1 mismatch %v: expected %v, found %v", test.Name, test.Rd1, rd1) + } + if !dTolEqual(rd2, test.Rd2) { + t.Errorf("drotmg rd2 mismatch %v: expected %v, found %v", test.Name, test.Rd2, rd2) + } + if !dTolEqual(rx1, test.Rx1) { + t.Errorf("drotmg rx1 mismatch %v: expected %v, found %v", test.Name, test.Rx1, rx1) + } + } +} + +type Droter interface { + Drot(n int, x []float64, incX int, y []float64, incY int, c, s float64) +} + +func DrotTest(t *testing.T, d Droter) { + drot := d.Drot + for _, c := range DoubleTwoVectorCases { + for _, kind := range c.DrotCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { drot(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy, kind.C, kind.S) } + testpanics(f, c.Name, t) + continue + } + drot(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy, kind.C, kind.S) + if !dSliceTolEqual(c.XTmp, kind.XAns) { + t.Errorf("drot: x mismatch %v: expected %v, found %v", c.Name, kind.XAns, c.XTmp) + } + if !dSliceTolEqual(c.YTmp, kind.YAns) { + t.Errorf("drot: y mismatch %v: expected %v, found %v", c.Name, kind.YAns, c.YTmp) + } + } + } +} + +type Drotmer interface { + Drotm(n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams) +} + +func DrotmTest(t *testing.T, d Drotmer) { + drotm := d.Drotm + for _, c := range DoubleTwoVectorCases { + for _, kind := range c.DrotmCases { + dCopyTwoTmp(c.X, c.XTmp, c.Y, c.YTmp) + if c.Panic { + f := func() { drotm(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy, kind.P) } + testpanics(f, c.Name+", "+kind.Name, t) + continue + } + drotm(c.N, c.XTmp, c.Incx, c.YTmp, c.Incy, kind.P) + if !dSliceTolEqual(c.XTmp, kind.XAns) { + t.Errorf("drotm: mismatch %v: expected %v, found %v", c.Name, kind.XAns, c.XTmp) + } + if !dSliceTolEqual(c.YTmp, kind.YAns) { + t.Errorf("drotm: mismatch %v: expected %v, found %v", c.Name, kind.YAns, c.YTmp) + } + } + } +} + +type Dscaler interface { + Dscal(n int, alpha float64, x []float64, incX int) +} + +func DscalTest(t *testing.T, blasser Dscaler) { + dscal := blasser.Dscal + for _, c := range DoubleOneVectorCases { + for _, kind := range c.DscalCases { + xTmp := make([]float64, len(c.X)) + copy(xTmp, c.X) + if c.Panic { + f := func() { dscal(c.N, kind.Alpha, xTmp, c.Incx) } + testpanics(f, c.Name, t) + continue + } + dscal(c.N, kind.Alpha, xTmp, c.Incx) + if !dSliceTolEqual(xTmp, kind.Ans) { + t.Errorf("dscal: mismatch %v, %v: expected %v, found %v", c.Name, kind.Name, kind.Ans, xTmp) + } + } + } +} diff --git a/blas/testblas/level2bench.go b/blas/testblas/level2bench.go new file mode 100644 index 00000000..387ffcce --- /dev/null +++ b/blas/testblas/level2bench.go @@ -0,0 +1,60 @@ +package testblas + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +func DgemvBenchmark(b *testing.B, blasser Dgemver, tA blas.Transpose, m, n, incX, incY int) { + var lenX, lenY int + if tA == blas.NoTrans { + lenX = n + lenY = m + } else { + lenX = m + lenY = n + } + xr := make([]float64, lenX) + for i := range xr { + xr[i] = rand.Float64() + } + x := makeIncremented(xr, incX, 0) + yr := make([]float64, lenY) + for i := range yr { + yr[i] = rand.Float64() + } + y := makeIncremented(yr, incY, 0) + a := make([]float64, m*n) + for i := range a { + a[i] = rand.Float64() + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + blasser.Dgemv(tA, m, n, 2, a, n, x, incX, 3, y, incY) + } +} + +func DgerBenchmark(b *testing.B, blasser Dgerer, m, n, incX, incY int) { + xr := make([]float64, m) + for i := range xr { + xr[i] = rand.Float64() + } + x := makeIncremented(xr, incX, 0) + yr := make([]float64, n) + for i := range yr { + yr[i] = rand.Float64() + } + y := makeIncremented(yr, incY, 0) + a := make([]float64, m*n) + for i := range a { + a[i] = rand.Float64() + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + blasser.Dger(m, n, 2, x, incX, y, incY, a, n) + } +} diff --git a/diff/README.md b/diff/README.md new file mode 100644 index 00000000..03ba1b8c --- /dev/null +++ b/diff/README.md @@ -0,0 +1,13 @@ +# Gonum diff [![Build Status](https://travis-ci.org/gonum/diff.svg)](https://travis-ci.org/gonum/diff) [![Coverage Status](https://coveralls.io/repos/gonum/diff/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/diff?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/diff?status.svg)](https://godoc.org/github.com/gonum/diff) + +This is a package for computing derivatives of functions for the Go language. + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/diff/fd/diff.go b/diff/fd/diff.go new file mode 100644 index 00000000..518d2a94 --- /dev/null +++ b/diff/fd/diff.go @@ -0,0 +1,276 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package fd provides functions to approximate derivatives using finite differences. +package fd + +import ( + "math" + "runtime" + "sync" + + "gonum.org/v1/gonum/floats" +) + +// A Point is a stencil location in a finite difference formula. +type Point struct { + Loc float64 + Coeff float64 +} + +// Formula represents a finite difference formula on a regularly spaced grid +// that approximates the derivative of order k of a function f at x as +// d^k f(x) ≈ (1 / Step^k) * \sum_i Coeff_i * f(x + Step * Loc_i). +type Formula struct { + // Stencil is the set of sampling Points which are used to estimate the + // derivative. The locations will be scaled by Step and are relative to x. + Stencil []Point + Derivative int // The order of the approximated derivative. + Step float64 // Default step size for the formula. +} + +func (f Formula) isZero() bool { + return f.Stencil == nil && f.Derivative == 0 && f.Step == 0 +} + +// Settings is the settings structure for computing finite differences. +type Settings struct { + // Formula is the finite difference formula used + // for approximating the derivative. + // Zero value indicates a default formula. + Formula Formula + // Step is the distance between points of the stencil. + // If equal to 0, formula's default step will be used. + Step float64 + + OriginKnown bool // Flag that the value at the origin x is known. + OriginValue float64 // Value at the origin (only used if OriginKnown is true). + + Concurrent bool // Should the function calls be executed concurrently. +} + +// Derivative estimates the derivative of the function f at the given location. +// The finite difference formula, the step size, and other options are +// specified by settings. If settings is nil, the first derivative will be +// estimated using the Forward formula and a default step size. +func Derivative(f func(float64) float64, x float64, settings *Settings) float64 { + if settings == nil { + settings = &Settings{} + } + formula := settings.Formula + if formula.isZero() { + formula = Forward + } + if formula.Derivative == 0 || formula.Stencil == nil || formula.Step == 0 { + panic("fd: bad formula") + } + step := settings.Step + if step == 0 { + step = formula.Step + } + + var deriv float64 + if !settings.Concurrent || runtime.GOMAXPROCS(0) == 1 { + for _, pt := range formula.Stencil { + if settings.OriginKnown && pt.Loc == 0 { + deriv += pt.Coeff * settings.OriginValue + continue + } + deriv += pt.Coeff * f(x+step*pt.Loc) + } + return deriv / math.Pow(step, float64(formula.Derivative)) + } + + wg := &sync.WaitGroup{} + mux := &sync.Mutex{} + for _, pt := range formula.Stencil { + if settings.OriginKnown && pt.Loc == 0 { + mux.Lock() + deriv += pt.Coeff * settings.OriginValue + mux.Unlock() + continue + } + wg.Add(1) + go func(pt Point) { + defer wg.Done() + fofx := f(x + step*pt.Loc) + mux.Lock() + defer mux.Unlock() + deriv += pt.Coeff * fofx + }(pt) + } + wg.Wait() + return deriv / math.Pow(step, float64(formula.Derivative)) +} + +// Gradient estimates the gradient of the multivariate function f at the +// location x. If dst is not nil, the result will be stored in-place into dst +// and returned, otherwise a new slice will be allocated first. Finite +// difference kernel and other options are specified by settings. If settings is +// nil, the gradient will be estimated using the Forward formula and a default +// step size. +// +// Gradient panics if the length of dst and x is not equal, or if the derivative +// order of the formula is not 1. +func Gradient(dst []float64, f func([]float64) float64, x []float64, settings *Settings) []float64 { + if dst == nil { + dst = make([]float64, len(x)) + } + if len(dst) != len(x) { + panic("fd: slice length mismatch") + } + if settings == nil { + settings = &Settings{} + } + + formula := settings.Formula + if formula.isZero() { + formula = Forward + } + if formula.Derivative == 0 || formula.Stencil == nil || formula.Step == 0 { + panic("fd: bad formula") + } + if formula.Derivative != 1 { + panic("fd: invalid derivative order") + } + + step := settings.Step + if step == 0 { + step = formula.Step + } + + expect := len(formula.Stencil) * len(x) + nWorkers := 1 + if settings.Concurrent { + nWorkers = runtime.GOMAXPROCS(0) + if nWorkers > expect { + nWorkers = expect + } + } + + var hasOrigin bool + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + hasOrigin = true + break + } + } + xcopy := make([]float64, len(x)) // So that x is not modified during the call. + originValue := settings.OriginValue + if hasOrigin && !settings.OriginKnown { + copy(xcopy, x) + originValue = f(xcopy) + } + + if nWorkers == 1 { + for i := range xcopy { + var deriv float64 + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + deriv += pt.Coeff * originValue + continue + } + copy(xcopy, x) + xcopy[i] += pt.Loc * step + deriv += pt.Coeff * f(xcopy) + } + dst[i] = deriv / step + } + return dst + } + + sendChan := make(chan fdrun, expect) + ansChan := make(chan fdrun, expect) + quit := make(chan struct{}) + defer close(quit) + + // Launch workers. Workers receive an index and a step, and compute the answer. + for i := 0; i < nWorkers; i++ { + go func(sendChan <-chan fdrun, ansChan chan<- fdrun, quit <-chan struct{}) { + xcopy := make([]float64, len(x)) + for { + select { + case <-quit: + return + case run := <-sendChan: + copy(xcopy, x) + xcopy[run.idx] += run.pt.Loc * step + run.result = f(xcopy) + ansChan <- run + } + } + }(sendChan, ansChan, quit) + } + + // Launch the distributor. Distributor sends the cases to be computed. + go func(sendChan chan<- fdrun, ansChan chan<- fdrun) { + for i := range x { + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + // Answer already known. Send the answer on the answer channel. + ansChan <- fdrun{ + idx: i, + pt: pt, + result: originValue, + } + continue + } + // Answer not known, send the answer to be computed. + sendChan <- fdrun{ + idx: i, + pt: pt, + } + } + } + }(sendChan, ansChan) + + for i := range dst { + dst[i] = 0 + } + // Read in all of the results. + for i := 0; i < expect; i++ { + run := <-ansChan + dst[run.idx] += run.pt.Coeff * run.result + } + floats.Scale(1/step, dst) + return dst +} + +type fdrun struct { + idx int + pt Point + result float64 +} + +// Forward represents a first-order accurate forward approximation +// to the first derivative. +var Forward = Formula{ + Stencil: []Point{{Loc: 0, Coeff: -1}, {Loc: 1, Coeff: 1}}, + Derivative: 1, + Step: 2e-8, +} + +// Backward represents a first-order accurate backward approximation +// to the first derivative. +var Backward = Formula{ + Stencil: []Point{{Loc: -1, Coeff: -1}, {Loc: 0, Coeff: 1}}, + Derivative: 1, + Step: 2e-8, +} + +// Central represents a second-order accurate centered approximation +// to the first derivative. +var Central = Formula{ + Stencil: []Point{{Loc: -1, Coeff: -0.5}, {Loc: 1, Coeff: 0.5}}, + Derivative: 1, + Step: 6e-6, +} + +// Central2nd represents a secord-order accurate centered approximation +// to the second derivative. +var Central2nd = Formula{ + Stencil: []Point{{Loc: -1, Coeff: 1}, {Loc: 0, Coeff: -2}, {Loc: 1, Coeff: 1}}, + Derivative: 2, + Step: 1e-4, +} diff --git a/diff/fd/diff_test.go b/diff/fd/diff_test.go new file mode 100644 index 00000000..35d4f0f3 --- /dev/null +++ b/diff/fd/diff_test.go @@ -0,0 +1,145 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fd + +import ( + "math" + "testing" +) + +var xSquared = func(x float64) float64 { return x * x } + +type testPoint struct { + f func(float64) float64 + loc float64 + fofx float64 + ans float64 +} + +var testsFirst = []testPoint{ + { + f: xSquared, + loc: 0, + fofx: 0, + ans: 0, + }, + { + f: xSquared, + loc: 5, + fofx: 25, + ans: 10, + }, + { + f: xSquared, + loc: 2, + fofx: 4, + ans: 4, + }, + { + f: xSquared, + loc: -5, + fofx: 25, + ans: -10, + }, +} + +var testsSecond = []testPoint{ + { + f: xSquared, + loc: 0, + fofx: 0, + ans: 2, + }, + { + f: xSquared, + loc: 5, + fofx: 25, + ans: 2, + }, + { + f: xSquared, + loc: 2, + fofx: 4, + ans: 2, + }, + { + f: xSquared, + loc: -5, + fofx: 25, + ans: 2, + }, +} + +func testDerivative(t *testing.T, formula Formula, tol float64, tests []testPoint) { + for i, test := range tests { + + ans := Derivative(test.f, test.loc, &Settings{ + Formula: formula, + }) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch serial: expected %v, found %v", i, test.ans, ans) + } + + ans = Derivative(test.f, test.loc, &Settings{ + Formula: formula, + OriginKnown: true, + OriginValue: test.fofx, + }) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch serial origin known: expected %v, found %v", i, test.ans, ans) + } + + ans = Derivative(test.f, test.loc, &Settings{ + Formula: formula, + Concurrent: true, + }) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch concurrent: expected %v, found %v", i, test.ans, ans) + } + + ans = Derivative(test.f, test.loc, &Settings{ + Formula: formula, + OriginKnown: true, + OriginValue: test.fofx, + Concurrent: true, + }) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch concurrent: expected %v, found %v", i, test.ans, ans) + } + } +} + +func TestForward(t *testing.T) { + testDerivative(t, Forward, 2e-4, testsFirst) +} + +func TestBackward(t *testing.T) { + testDerivative(t, Backward, 2e-4, testsFirst) +} + +func TestCentral(t *testing.T) { + testDerivative(t, Central, 1e-6, testsFirst) +} + +func TestCentralSecond(t *testing.T) { + testDerivative(t, Central2nd, 1e-3, testsSecond) +} + +// TestDerivativeDefault checks that the derivative works when settings is nil +// or zero value. +func TestDerivativeDefault(t *testing.T) { + tol := 1e-6 + for i, test := range testsFirst { + ans := Derivative(test.f, test.loc, nil) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch default: expected %v, found %v", i, test.ans, ans) + } + + ans = Derivative(test.f, test.loc, &Settings{}) + if math.Abs(test.ans-ans) > tol { + t.Errorf("Case %v: ans mismatch zero value: expected %v, found %v", i, test.ans, ans) + } + } +} diff --git a/diff/fd/example_test.go b/diff/fd/example_test.go new file mode 100644 index 00000000..13a68fa0 --- /dev/null +++ b/diff/fd/example_test.go @@ -0,0 +1,68 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fd_test + +import ( + "fmt" + "math" + + "gonum.org/v1/gonum/diff/fd" + "gonum.org/v1/gonum/matrix/mat64" +) + +func ExampleDerivative() { + f := func(x float64) float64 { + return math.Sin(x) + } + // Compute the first derivative of f at 0 using the default settings. + fmt.Println("f'(0) ≈", fd.Derivative(f, 0, nil)) + // Compute the first derivative of f at 0 using the forward approximation + // with a custom step size. + df := fd.Derivative(f, 0, &fd.Settings{ + Formula: fd.Forward, + Step: 1e-3, + }) + fmt.Println("f'(0) ≈", df) + + f = func(x float64) float64 { + return math.Pow(math.Cos(x), 3) + } + // Compute the second derivative of f at 0 using + // the centered approximation, concurrent evaluation, + // and a known function value at x. + df = fd.Derivative(f, 0, &fd.Settings{ + Formula: fd.Central2nd, + Concurrent: true, + OriginKnown: true, + OriginValue: f(0), + }) + fmt.Println("f''(0) ≈", df) + + // Output: + // f'(0) ≈ 1 + // f'(0) ≈ 0.9999998333333416 + // f''(0) ≈ -2.999999981767587 +} + +func ExampleJacobian() { + f := func(dst, x []float64) { + dst[0] = x[0] + 1 + dst[1] = 5 * x[2] + dst[2] = 4*x[1]*x[1] - 2*x[2] + dst[3] = x[2] * math.Sin(x[0]) + } + jac := mat64.NewDense(4, 3, nil) + fd.Jacobian(jac, f, []float64{1, 2, 3}, &fd.JacobianSettings{ + Formula: fd.Central, + Concurrent: true, + }) + fmt.Printf("J ≈ %.6v\n", mat64.Formatted(jac, mat64.Prefix(" "))) + + // Output: + // J ≈ ⎡ 1 0 0⎤ + // ⎢ 0 0 5⎥ + // ⎢ 0 16 -2⎥ + // ⎣ 1.62091 0 0.841471⎦ +} diff --git a/diff/fd/gradient_test.go b/diff/fd/gradient_test.go new file mode 100644 index 00000000..0774ad73 --- /dev/null +++ b/diff/fd/gradient_test.go @@ -0,0 +1,187 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fd + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Rosenbrock struct { + nDim int +} + +func (r Rosenbrock) F(x []float64) (sum float64) { + deriv := make([]float64, len(x)) + return r.FDf(x, deriv) +} + +func (r Rosenbrock) FDf(x []float64, deriv []float64) (sum float64) { + for i := range deriv { + deriv[i] = 0 + } + + for i := 0; i < len(x)-1; i++ { + sum += math.Pow(1-x[i], 2) + 100*math.Pow(x[i+1]-math.Pow(x[i], 2), 2) + } + for i := 0; i < len(x)-1; i++ { + deriv[i] += -1 * 2 * (1 - x[i]) + deriv[i] += 2 * 100 * (x[i+1] - math.Pow(x[i], 2)) * (-2 * x[i]) + } + for i := 1; i < len(x); i++ { + deriv[i] += 2 * 100 * (x[i] - math.Pow(x[i-1], 2)) + } + + return sum +} + +func TestGradient(t *testing.T) { + rand.Seed(1) + for i, test := range []struct { + nDim int + tol float64 + formula Formula + }{ + { + nDim: 2, + tol: 2e-4, + formula: Forward, + }, + { + nDim: 2, + tol: 1e-6, + formula: Central, + }, + { + nDim: 40, + tol: 2e-4, + formula: Forward, + }, + { + nDim: 40, + tol: 1e-6, + formula: Central, + }, + } { + x := make([]float64, test.nDim) + for i := range x { + x[i] = rand.Float64() + } + xcopy := make([]float64, len(x)) + copy(xcopy, x) + + r := Rosenbrock{len(x)} + trueGradient := make([]float64, len(x)) + r.FDf(x, trueGradient) + + // Try with gradient nil. + gradient := Gradient(nil, r.F, x, &Settings{ + Formula: test.formula, + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch in serial with nil. Want: %v, Got: %v.", i, trueGradient, gradient) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %v: x modified during call to gradient in serial with nil.", i) + } + + // Try with provided gradient. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{ + Formula: test.formula, + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch in serial. Want: %v, Got: %v.", i, trueGradient, gradient) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %v: x modified during call to gradient in serial with non-nil.", i) + } + + // Try with known value. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{ + Formula: test.formula, + OriginKnown: true, + OriginValue: r.F(x), + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with known origin in serial. Want: %v, Got: %v.", i, trueGradient, gradient) + } + + // Try with concurrent evaluation. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{ + Formula: test.formula, + Concurrent: true, + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with unknown origin in parallel. Want: %v, Got: %v.", i, trueGradient, gradient) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %v: x modified during call to gradient in parallel", i) + } + + // Try with concurrent evaluation with origin known. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{ + Formula: test.formula, + Concurrent: true, + OriginKnown: true, + OriginValue: r.F(x), + }) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with known origin in parallel. Want: %v, Got: %v.", i, trueGradient, gradient) + } + + // Try with nil settings. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, nil) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with default settings. Want: %v, Got: %v.", i, trueGradient, gradient) + } + + // Try with zero-valued settings. + for i := range gradient { + gradient[i] = rand.Float64() + } + Gradient(gradient, r.F, x, &Settings{}) + if !floats.EqualApprox(gradient, trueGradient, test.tol) { + t.Errorf("Case %v: gradient mismatch with zero settings. Want: %v, Got: %v.", i, trueGradient, gradient) + } + } +} + +func Panics(fun func()) (b bool) { + defer func() { + err := recover() + if err != nil { + b = true + } + }() + fun() + return +} + +func TestGradientPanics(t *testing.T) { + // Test that it panics + if !Panics(func() { + Gradient([]float64{0.0}, func(x []float64) float64 { return x[0] * x[0] }, []float64{0.0, 0.0}, nil) + }) { + t.Errorf("Gradient did not panic with length mismatch") + } +} diff --git a/diff/fd/jacobian.go b/diff/fd/jacobian.go new file mode 100644 index 00000000..ea42f233 --- /dev/null +++ b/diff/fd/jacobian.go @@ -0,0 +1,203 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fd + +import ( + "runtime" + "sync" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +type JacobianSettings struct { + Formula Formula + OriginValue []float64 + Step float64 + Concurrent bool +} + +// Jacobian approximates the Jacobian matrix of a vector-valued function f at +// the location x and stores the result in-place into dst. +// +// Finite difference formula and other options are specified by settings. If +// settings is nil, the Jacobian will be estimated using the Forward formula and +// a default step size. +// +// The Jacobian matrix J is the matrix of all first-order partial derivatives of f. +// If f maps an n-dimensional vector x to an m-dimensional vector y = f(x), J is +// an m×n matrix whose elements are given as +// J_{i,j} = ∂f_i/∂x_j, +// or expanded out +// [ ∂f_1/∂x_1 ... ∂f_1/∂x_n ] +// [ . . . ] +// J = [ . . . ] +// [ . . . ] +// [ ∂f_m/∂x_1 ... ∂f_m/∂x_n ] +// +// dst must be non-nil, the number of its columns must equal the length of x, and +// the derivative order of the formula must be 1, otherwise Jacobian will panic. +func Jacobian(dst *mat64.Dense, f func(y, x []float64), x []float64, settings *JacobianSettings) { + n := len(x) + if n == 0 { + panic("jacobian: x has zero length") + } + m, c := dst.Dims() + if c != n { + panic("jacobian: mismatched matrix size") + } + + if settings == nil { + settings = &JacobianSettings{} + } + if settings.OriginValue != nil && len(settings.OriginValue) != m { + panic("jacobian: mismatched OriginValue slice length") + } + + formula := settings.Formula + if formula.isZero() { + formula = Forward + } + if formula.Derivative == 0 || formula.Stencil == nil || formula.Step == 0 { + panic("jacobian: bad formula") + } + if formula.Derivative != 1 { + panic("jacobian: invalid derivative order") + } + + step := settings.Step + if step == 0 { + step = formula.Step + } + + evals := n * len(formula.Stencil) + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + evals -= n - 1 + break + } + } + nWorkers := 1 + if settings.Concurrent { + nWorkers = runtime.GOMAXPROCS(0) + if nWorkers > evals { + nWorkers = evals + } + } + if nWorkers == 1 { + jacobianSerial(dst, f, x, settings.OriginValue, formula, step) + } else { + jacobianConcurrent(dst, f, x, settings.OriginValue, formula, step, nWorkers) + } +} + +func jacobianSerial(dst *mat64.Dense, f func([]float64, []float64), x, origin []float64, formula Formula, step float64) { + m, n := dst.Dims() + xcopy := make([]float64, n) + y := make([]float64, m) + col := make([]float64, m) + for j := 0; j < n; j++ { + for i := range col { + col[i] = 0 + } + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + if origin == nil { + origin = make([]float64, m) + copy(xcopy, x) + f(origin, xcopy) + } + floats.AddScaled(col, pt.Coeff, origin) + } else { + copy(xcopy, x) + xcopy[j] += pt.Loc * step + f(y, xcopy) + floats.AddScaled(col, pt.Coeff, y) + } + } + dst.SetCol(j, col) + } + dst.Scale(1/step, dst) +} + +func jacobianConcurrent(dst *mat64.Dense, f func([]float64, []float64), x, origin []float64, formula Formula, step float64, nWorkers int) { + m, n := dst.Dims() + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + dst.Set(i, j, 0) + } + } + + var ( + wg sync.WaitGroup + mu = make([]sync.Mutex, n) // Guard access to individual columns. + ) + worker := func(jobs <-chan jacJob) { + defer wg.Done() + xcopy := make([]float64, n) + y := make([]float64, m) + yVec := mat64.NewVector(m, y) + for job := range jobs { + copy(xcopy, x) + xcopy[job.j] += job.pt.Loc * step + f(y, xcopy) + col := dst.ColView(job.j) + mu[job.j].Lock() + col.AddScaledVec(col, job.pt.Coeff, yVec) + mu[job.j].Unlock() + } + } + jobs := make(chan jacJob, nWorkers) + for i := 0; i < nWorkers; i++ { + wg.Add(1) + go worker(jobs) + } + var hasOrigin bool + for _, pt := range formula.Stencil { + if pt.Loc == 0 { + hasOrigin = true + continue + } + for j := 0; j < n; j++ { + jobs <- jacJob{j, pt} + } + } + close(jobs) + if hasOrigin && origin == nil { + wg.Add(1) + go func() { + defer wg.Done() + origin = make([]float64, m) + xcopy := make([]float64, n) + copy(xcopy, x) + f(origin, xcopy) + }() + } + wg.Wait() + + if hasOrigin { + // The formula evaluated at x, we need to add scaled origin to + // all columns of dst. Iterate again over all Formula points + // because we don't forbid repeated locations. + + originVec := mat64.NewVector(m, origin) + for _, pt := range formula.Stencil { + if pt.Loc != 0 { + continue + } + for j := 0; j < n; j++ { + col := dst.ColView(j) + col.AddScaledVec(col, pt.Coeff, originVec) + } + } + } + + dst.Scale(1/step, dst) +} + +type jacJob struct { + j int + pt Point +} diff --git a/diff/fd/jacobian_test.go b/diff/fd/jacobian_test.go new file mode 100644 index 00000000..04dc5bfb --- /dev/null +++ b/diff/fd/jacobian_test.go @@ -0,0 +1,268 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fd + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +func vecFunc13(y, x []float64) { + y[0] = 5*x[0] + x[2]*math.Sin(x[1]) + 1 +} +func vecFunc13Jac(jac *mat64.Dense, x []float64) { + jac.Set(0, 0, 5) + jac.Set(0, 1, x[2]*math.Cos(x[1])) + jac.Set(0, 2, math.Sin(x[1])) +} + +func vecFunc22(y, x []float64) { + y[0] = x[0]*x[0]*x[1] + 1 + y[1] = 5*x[0] + math.Sin(x[1]) + 1 +} +func vecFunc22Jac(jac *mat64.Dense, x []float64) { + jac.Set(0, 0, 2*x[0]*x[1]) + jac.Set(0, 1, x[0]*x[0]) + jac.Set(1, 0, 5) + jac.Set(1, 1, math.Cos(x[1])) +} + +func vecFunc43(y, x []float64) { + y[0] = x[0] + 1 + y[1] = 5*x[2] + 1 + y[2] = 4*x[1]*x[1] - 2*x[2] + 1 + y[3] = x[2]*math.Sin(x[0]) + 1 +} +func vecFunc43Jac(jac *mat64.Dense, x []float64) { + jac.Set(0, 0, 1) + jac.Set(0, 1, 0) + jac.Set(0, 2, 0) + jac.Set(1, 0, 0) + jac.Set(1, 1, 0) + jac.Set(1, 2, 5) + jac.Set(2, 0, 0) + jac.Set(2, 1, 8*x[1]) + jac.Set(2, 2, -2) + jac.Set(3, 0, x[2]*math.Cos(x[0])) + jac.Set(3, 1, 0) + jac.Set(3, 2, math.Sin(x[0])) +} + +func TestJacobian(t *testing.T) { + rand.Seed(1) + + // Test with default settings. + for tc, test := range []struct { + m, n int + f func([]float64, []float64) + jac func(*mat64.Dense, []float64) + }{ + { + m: 1, + n: 3, + f: vecFunc13, + jac: vecFunc13Jac, + }, + { + m: 2, + n: 2, + f: vecFunc22, + jac: vecFunc22Jac, + }, + { + m: 4, + n: 3, + f: vecFunc43, + jac: vecFunc43Jac, + }, + } { + const tol = 1e-6 + + x := randomSlice(test.n, 10) + xcopy := make([]float64, test.n) + copy(xcopy, x) + + want := mat64.NewDense(test.m, test.n, nil) + test.jac(want, x) + + got := mat64.NewDense(test.m, test.n, nil) + fillNaNDense(got) + Jacobian(got, test.f, x, nil) + if !mat64.EqualApprox(want, got, tol) { + t.Errorf("Case %d (default settings): unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat64.Formatted(want, mat64.Prefix(" ")), mat64.Formatted(got, mat64.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d (default settings): x modified", tc) + } + } + + // Test with non-default settings. + for tc, test := range []struct { + m, n int + f func([]float64, []float64) + jac func(*mat64.Dense, []float64) + tol float64 + formula Formula + }{ + { + m: 1, + n: 3, + f: vecFunc13, + jac: vecFunc13Jac, + tol: 1e-6, + formula: Forward, + }, + { + m: 1, + n: 3, + f: vecFunc13, + jac: vecFunc13Jac, + tol: 1e-6, + formula: Backward, + }, + { + m: 1, + n: 3, + f: vecFunc13, + jac: vecFunc13Jac, + tol: 1e-9, + formula: Central, + }, + { + m: 2, + n: 2, + f: vecFunc22, + jac: vecFunc22Jac, + tol: 1e-6, + formula: Forward, + }, + { + m: 2, + n: 2, + f: vecFunc22, + jac: vecFunc22Jac, + tol: 1e-6, + formula: Backward, + }, + { + m: 2, + n: 2, + f: vecFunc22, + jac: vecFunc22Jac, + tol: 1e-9, + formula: Central, + }, + { + m: 4, + n: 3, + f: vecFunc43, + jac: vecFunc43Jac, + tol: 1e-6, + formula: Forward, + }, + { + m: 4, + n: 3, + f: vecFunc43, + jac: vecFunc43Jac, + tol: 1e-6, + formula: Backward, + }, + { + m: 4, + n: 3, + f: vecFunc43, + jac: vecFunc43Jac, + tol: 1e-9, + formula: Central, + }, + } { + x := randomSlice(test.n, 10) + xcopy := make([]float64, test.n) + copy(xcopy, x) + + want := mat64.NewDense(test.m, test.n, nil) + test.jac(want, x) + + got := mat64.NewDense(test.m, test.n, nil) + fillNaNDense(got) + Jacobian(got, test.f, x, &JacobianSettings{ + Formula: test.formula, + }) + if !mat64.EqualApprox(want, got, test.tol) { + t.Errorf("Case %d: unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat64.Formatted(want, mat64.Prefix(" ")), mat64.Formatted(got, mat64.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d: x modified", tc) + } + + fillNaNDense(got) + Jacobian(got, test.f, x, &JacobianSettings{ + Formula: test.formula, + Concurrent: true, + }) + if !mat64.EqualApprox(want, got, test.tol) { + t.Errorf("Case %d (concurrent): unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat64.Formatted(want, mat64.Prefix(" ")), mat64.Formatted(got, mat64.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d (concurrent): x modified", tc) + } + + fillNaNDense(got) + origin := make([]float64, test.m) + test.f(origin, x) + Jacobian(got, test.f, x, &JacobianSettings{ + Formula: test.formula, + OriginValue: origin, + }) + if !mat64.EqualApprox(want, got, test.tol) { + t.Errorf("Case %d (origin): unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat64.Formatted(want, mat64.Prefix(" ")), mat64.Formatted(got, mat64.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d (origin): x modified", tc) + } + + fillNaNDense(got) + Jacobian(got, test.f, x, &JacobianSettings{ + Formula: test.formula, + OriginValue: origin, + Concurrent: true, + }) + if !mat64.EqualApprox(want, got, test.tol) { + t.Errorf("Case %d (concurrent, origin): unexpected Jacobian.\nwant: %v\ngot: %v", + tc, mat64.Formatted(want, mat64.Prefix(" ")), mat64.Formatted(got, mat64.Prefix(" "))) + } + if !floats.Equal(x, xcopy) { + t.Errorf("Case %d (concurrent, origin): x modified", tc) + } + } +} + +// randomSlice returns a slice of n elements from the interval [-bound,bound). +func randomSlice(n int, bound float64) []float64 { + x := make([]float64, n) + for i := range x { + x[i] = 2*bound*rand.Float64() - bound + } + return x +} + +// fillNaNDense fills the matrix m with NaN values. +func fillNaNDense(m *mat64.Dense) { + r, c := m.Dims() + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + m.Set(i, j, math.NaN()) + } + } +} diff --git a/floats/README.md b/floats/README.md new file mode 100644 index 00000000..7dafcbd9 --- /dev/null +++ b/floats/README.md @@ -0,0 +1,13 @@ +# Gonum floats [![travis-build-status](https://travis-ci.org/gonum/floats.svg?branch=master)](https://travis-ci.org/gonum/floats) [![Coverage Status](https://coveralls.io/repos/gonum/floats/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/floats?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/floats?status.svg)](https://godoc.org/github.com/gonum/floats) + +package floats provides a set of helper routines for dealing with slices of float64. The functions avoid allocations to allow for use within tight loops without garbage collection overhead. + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/floats/examples_test.go b/floats/examples_test.go new file mode 100644 index 00000000..3bc59ad1 --- /dev/null +++ b/floats/examples_test.go @@ -0,0 +1,104 @@ +// Copyright 2013 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package floats + +import ( + "fmt" +) + +// Set of examples for all the functions + +func ExampleAdd_simple() { + // Adding three slices together. Note that + // the result is stored in the first slice + s1 := []float64{1, 2, 3, 4} + s2 := []float64{5, 6, 7, 8} + s3 := []float64{1, 1, 1, 1} + Add(s1, s2) + Add(s1, s3) + + fmt.Println("s1 =", s1) + fmt.Println("s2 =", s2) + fmt.Println("s3 =", s3) + // Output: + // s1 = [7 9 11 13] + // s2 = [5 6 7 8] + // s3 = [1 1 1 1] +} + +func ExampleAdd_newslice() { + // If one wants to store the result in a + // new container, just make a new slice + s1 := []float64{1, 2, 3, 4} + s2 := []float64{5, 6, 7, 8} + s3 := []float64{1, 1, 1, 1} + dst := make([]float64, len(s1)) + + AddTo(dst, s1, s2) + Add(dst, s3) + + fmt.Println("dst =", dst) + fmt.Println("s1 =", s1) + fmt.Println("s2 =", s2) + fmt.Println("s3 =", s3) + // Output: + // dst = [7 9 11 13] + // s1 = [1 2 3 4] + // s2 = [5 6 7 8] + // s3 = [1 1 1 1] +} + +func ExampleAdd_unequallengths() { + // If the lengths of the slices are unknown, + // use Eqlen to check + s1 := []float64{1, 2, 3} + s2 := []float64{5, 6, 7, 8} + + eq := EqualLengths(s1, s2) + if eq { + Add(s1, s2) + } else { + fmt.Println("Unequal lengths") + } + // Output: + // Unequal lengths +} + +func ExampleAddConst() { + s := []float64{1, -2, 3, -4} + c := 5.0 + + AddConst(c, s) + + fmt.Println("s =", s) + // Output: + // s = [6 3 8 1] +} + +func ExampleCumProd() { + s := []float64{1, -2, 3, -4} + dst := make([]float64, len(s)) + + CumProd(dst, s) + + fmt.Println("dst =", dst) + fmt.Println("s =", s) + // Output: + // dst = [1 -2 -6 24] + // s = [1 -2 3 -4] +} + +func ExampleCumSum() { + s := []float64{1, -2, 3, -4} + dst := make([]float64, len(s)) + + CumSum(dst, s) + + fmt.Println("dst =", dst) + fmt.Println("s =", s) + // Output: + // dst = [1 -1 2 -2] + // s = [1 -2 3 -4] +} diff --git a/floats/floats.go b/floats/floats.go new file mode 100644 index 00000000..7707e371 --- /dev/null +++ b/floats/floats.go @@ -0,0 +1,763 @@ +// Copyright 2013 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +// Package floats provides a set of helper routines for dealing with slices +// of float64. The functions avoid allocations to allow for use within tight +// loops without garbage collection overhead. +// +// The convention used is that when a slice is being modified in place, it has +// the name dst. +package floats + +import ( + "errors" + "math" + "sort" + + "gonum.org/v1/gonum/internal/asm/f64" +) + +// Add adds, element-wise, the elements of s and dst, and stores in dst. +// Panics if the lengths of dst and s do not match. +func Add(dst, s []float64) { + if len(dst) != len(s) { + panic("floats: length of the slices do not match") + } + f64.AxpyUnitaryTo(dst, 1, s, dst) +} + +// AddTo adds, element-wise, the elements of s and t and +// stores the result in dst. Panics if the lengths of s, t and dst do not match. +func AddTo(dst, s, t []float64) []float64 { + if len(s) != len(t) { + panic("floats: length of adders do not match") + } + if len(dst) != len(s) { + panic("floats: length of destination does not match length of adder") + } + f64.AxpyUnitaryTo(dst, 1, s, t) + return dst +} + +// AddConst adds the scalar c to all of the values in dst. +func AddConst(c float64, dst []float64) { + for i := range dst { + dst[i] += c + } +} + +// AddScaled performs dst = dst + alpha * s. +// It panics if the lengths of dst and s are not equal. +func AddScaled(dst []float64, alpha float64, s []float64) { + if len(dst) != len(s) { + panic("floats: length of destination and source to not match") + } + f64.AxpyUnitaryTo(dst, alpha, s, dst) +} + +// AddScaledTo performs dst = y + alpha * s, where alpha is a scalar, +// and dst, y and s are all slices. +// It panics if the lengths of dst, y, and s are not equal. +// +// At the return of the function, dst[i] = y[i] + alpha * s[i] +func AddScaledTo(dst, y []float64, alpha float64, s []float64) []float64 { + if len(dst) != len(s) || len(dst) != len(y) { + panic("floats: lengths of slices do not match") + } + f64.AxpyUnitaryTo(dst, alpha, s, y) + return dst +} + +// argsort is a helper that implements sort.Interface, as used by +// Argsort. +type argsort struct { + s []float64 + inds []int +} + +func (a argsort) Len() int { + return len(a.s) +} + +func (a argsort) Less(i, j int) bool { + return a.s[i] < a.s[j] +} + +func (a argsort) Swap(i, j int) { + a.s[i], a.s[j] = a.s[j], a.s[i] + a.inds[i], a.inds[j] = a.inds[j], a.inds[i] +} + +// Argsort sorts the elements of s while tracking their original order. +// At the conclusion of Argsort, s will contain the original elements of s +// but sorted in increasing order, and inds will contain the original position +// of the elements in the slice such that dst[i] = origDst[inds[i]]. +// It panics if the lengths of dst and inds do not match. +func Argsort(dst []float64, inds []int) { + if len(dst) != len(inds) { + panic("floats: length of inds does not match length of slice") + } + for i := range dst { + inds[i] = i + } + + a := argsort{s: dst, inds: inds} + sort.Sort(a) +} + +// Count applies the function f to every element of s and returns the number +// of times the function returned true. +func Count(f func(float64) bool, s []float64) int { + var n int + for _, val := range s { + if f(val) { + n++ + } + } + return n +} + +// CumProd finds the cumulative product of the first i elements in +// s and puts them in place into the ith element of the +// destination dst. A panic will occur if the lengths of arguments +// do not match. +// +// At the return of the function, dst[i] = s[i] * s[i-1] * s[i-2] * ... +func CumProd(dst, s []float64) []float64 { + if len(dst) != len(s) { + panic("floats: length of destination does not match length of the source") + } + if len(dst) == 0 { + return dst + } + return f64.CumProd(dst, s) +} + +// CumSum finds the cumulative sum of the first i elements in +// s and puts them in place into the ith element of the +// destination dst. A panic will occur if the lengths of arguments +// do not match. +// +// At the return of the function, dst[i] = s[i] + s[i-1] + s[i-2] + ... +func CumSum(dst, s []float64) []float64 { + if len(dst) != len(s) { + panic("floats: length of destination does not match length of the source") + } + if len(dst) == 0 { + return dst + } + return f64.CumSum(dst, s) +} + +// Distance computes the L-norm of s - t. See Norm for special cases. +// A panic will occur if the lengths of s and t do not match. +func Distance(s, t []float64, L float64) float64 { + if len(s) != len(t) { + panic("floats: slice lengths do not match") + } + if len(s) == 0 { + return 0 + } + var norm float64 + if L == 2 { + for i, v := range s { + diff := t[i] - v + norm = math.Hypot(norm, diff) + } + return norm + } + if L == 1 { + for i, v := range s { + norm += math.Abs(t[i] - v) + } + return norm + } + if math.IsInf(L, 1) { + for i, v := range s { + absDiff := math.Abs(t[i] - v) + if absDiff > norm { + norm = absDiff + } + } + return norm + } + for i, v := range s { + norm += math.Pow(math.Abs(t[i]-v), L) + } + return math.Pow(norm, 1/L) +} + +// Div performs element-wise division dst / s +// and stores the value in dst. It panics if the +// lengths of s and t are not equal. +func Div(dst, s []float64) { + if len(dst) != len(s) { + panic("floats: slice lengths do not match") + } + f64.Div(dst, s) +} + +// DivTo performs element-wise division s / t +// and stores the value in dst. It panics if the +// lengths of s, t, and dst are not equal. +func DivTo(dst, s, t []float64) []float64 { + if len(s) != len(t) || len(dst) != len(t) { + panic("floats: slice lengths do not match") + } + return f64.DivTo(dst, s, t) +} + +// Dot computes the dot product of s1 and s2, i.e. +// sum_{i = 1}^N s1[i]*s2[i]. +// A panic will occur if lengths of arguments do not match. +func Dot(s1, s2 []float64) float64 { + if len(s1) != len(s2) { + panic("floats: lengths of the slices do not match") + } + return f64.DotUnitary(s1, s2) +} + +// Equal returns true if the slices have equal lengths and +// all elements are numerically identical. +func Equal(s1, s2 []float64) bool { + if len(s1) != len(s2) { + return false + } + for i, val := range s1 { + if s2[i] != val { + return false + } + } + return true +} + +// EqualApprox returns true if the slices have equal lengths and +// all element pairs have an absolute tolerance less than tol or a +// relative tolerance less than tol. +func EqualApprox(s1, s2 []float64, tol float64) bool { + if len(s1) != len(s2) { + return false + } + for i, a := range s1 { + if !EqualWithinAbsOrRel(a, s2[i], tol, tol) { + return false + } + } + return true +} + +// EqualFunc returns true if the slices have the same lengths +// and the function returns true for all element pairs. +func EqualFunc(s1, s2 []float64, f func(float64, float64) bool) bool { + if len(s1) != len(s2) { + return false + } + for i, val := range s1 { + if !f(val, s2[i]) { + return false + } + } + return true +} + +// EqualWithinAbs returns true if a and b have an absolute +// difference of less than tol. +func EqualWithinAbs(a, b, tol float64) bool { + return a == b || math.Abs(a-b) <= tol +} + +const minNormalFloat64 = 2.2250738585072014e-308 + +// EqualWithinRel returns true if the difference between a and b +// is not greater than tol times the greater value. +func EqualWithinRel(a, b, tol float64) bool { + if a == b { + return true + } + delta := math.Abs(a - b) + if delta <= minNormalFloat64 { + return delta <= tol*minNormalFloat64 + } + // We depend on the division in this relationship to identify + // infinities (we rely on the NaN to fail the test) otherwise + // we compare Infs of the same sign and evaluate Infs as equal + // independent of sign. + return delta/math.Max(math.Abs(a), math.Abs(b)) <= tol +} + +// EqualWithinAbsOrRel returns true if a and b are equal to within +// the absolute tolerance. +func EqualWithinAbsOrRel(a, b, absTol, relTol float64) bool { + if EqualWithinAbs(a, b, absTol) { + return true + } + return EqualWithinRel(a, b, relTol) +} + +// EqualWithinULP returns true if a and b are equal to within +// the specified number of floating point units in the last place. +func EqualWithinULP(a, b float64, ulp uint) bool { + if a == b { + return true + } + if math.IsNaN(a) || math.IsNaN(b) { + return false + } + if math.Signbit(a) != math.Signbit(b) { + return math.Float64bits(math.Abs(a))+math.Float64bits(math.Abs(b)) <= uint64(ulp) + } + return ulpDiff(math.Float64bits(a), math.Float64bits(b)) <= uint64(ulp) +} + +func ulpDiff(a, b uint64) uint64 { + if a > b { + return a - b + } + return b - a +} + +// EqualLengths returns true if all of the slices have equal length, +// and false otherwise. Returns true if there are no input slices. +func EqualLengths(slices ...[]float64) bool { + // This length check is needed: http://play.golang.org/p/sdty6YiLhM + if len(slices) == 0 { + return true + } + l := len(slices[0]) + for i := 1; i < len(slices); i++ { + if len(slices[i]) != l { + return false + } + } + return true +} + +// Find applies f to every element of s and returns the indices of the first +// k elements for which the f returns true, or all such elements +// if k < 0. +// Find will reslice inds to have 0 length, and will append +// found indices to inds. +// If k > 0 and there are fewer than k elements in s satisfying f, +// all of the found elements will be returned along with an error. +// At the return of the function, the input inds will be in an undetermined state. +func Find(inds []int, f func(float64) bool, s []float64, k int) ([]int, error) { + + // inds is also returned to allow for calling with nil + + // Reslice inds to have zero length + inds = inds[:0] + + // If zero elements requested, can just return + if k == 0 { + return inds, nil + } + + // If k < 0, return all of the found indices + if k < 0 { + for i, val := range s { + if f(val) { + inds = append(inds, i) + } + } + return inds, nil + } + + // Otherwise, find the first k elements + nFound := 0 + for i, val := range s { + if f(val) { + inds = append(inds, i) + nFound++ + if nFound == k { + return inds, nil + } + } + } + // Finished iterating over the loop, which means k elements were not found + return inds, errors.New("floats: insufficient elements found") +} + +// HasNaN returns true if the slice s has any values that are NaN and false +// otherwise. +func HasNaN(s []float64) bool { + for _, v := range s { + if math.IsNaN(v) { + return true + } + } + return false +} + +// LogSpan returns a set of n equally spaced points in log space between, +// l and u where N is equal to len(dst). The first element of the +// resulting dst will be l and the final element of dst will be u. +// Panics if len(dst) < 2 +// Note that this call will return NaNs if either l or u are negative, and +// will return all zeros if l or u is zero. +// Also returns the mutated slice dst, so that it can be used in range, like: +// +// for i, x := range LogSpan(dst, l, u) { ... } +func LogSpan(dst []float64, l, u float64) []float64 { + Span(dst, math.Log(l), math.Log(u)) + for i := range dst { + dst[i] = math.Exp(dst[i]) + } + return dst +} + +// LogSumExp returns the log of the sum of the exponentials of the values in s. +// Panics if s is an empty slice. +func LogSumExp(s []float64) float64 { + // Want to do this in a numerically stable way which avoids + // overflow and underflow + // First, find the maximum value in the slice. + maxval := Max(s) + if math.IsInf(maxval, 0) { + // If it's infinity either way, the logsumexp will be infinity as well + // returning now avoids NaNs + return maxval + } + var lse float64 + // Compute the sumexp part + for _, val := range s { + lse += math.Exp(val - maxval) + } + // Take the log and add back on the constant taken out + return math.Log(lse) + maxval +} + +// Max returns the maximum value in the input slice. If the slice is empty, Max will panic. +func Max(s []float64) float64 { + return s[MaxIdx(s)] +} + +// MaxIdx returns the index of the maximum value in the input slice. If several +// entries have the maximum value, the first such index is returned. If the slice +// is empty, MaxIdx will panic. +func MaxIdx(s []float64) int { + if len(s) == 0 { + panic("floats: zero slice length") + } + max := s[0] + var ind int + for i, v := range s { + if v > max { + max = v + ind = i + } + } + return ind +} + +// Min returns the maximum value in the input slice. If the slice is empty, Min will panic. +func Min(s []float64) float64 { + return s[MinIdx(s)] +} + +// MinIdx returns the index of the minimum value in the input slice. If several +// entries have the maximum value, the first such index is returned. If the slice +// is empty, MinIdx will panic. +func MinIdx(s []float64) int { + min := s[0] + var ind int + for i, v := range s { + if v < min { + min = v + ind = i + } + } + return ind +} + +// Mul performs element-wise multiplication between dst +// and s and stores the value in dst. Panics if the +// lengths of s and t are not equal. +func Mul(dst, s []float64) { + if len(dst) != len(s) { + panic("floats: slice lengths do not match") + } + for i, val := range s { + dst[i] *= val + } +} + +// MulTo performs element-wise multiplication between s +// and t and stores the value in dst. Panics if the +// lengths of s, t, and dst are not equal. +func MulTo(dst, s, t []float64) []float64 { + if len(s) != len(t) || len(dst) != len(t) { + panic("floats: slice lengths do not match") + } + for i, val := range t { + dst[i] = val * s[i] + } + return dst +} + +// Nearest returns the index of the element in s +// whose value is nearest to v. If several such +// elements exist, the lowest index is returned. +// Panics if len(s) == 0. +func Nearest(s []float64, v float64) int { + var ind int + dist := math.Abs(v - s[0]) + for i, val := range s { + newDist := math.Abs(v - val) + if newDist < dist { + dist = newDist + ind = i + } + } + return ind +} + +// NearestWithinSpan return the index of a hypothetical vector created +// by Span with length n and bounds l and u whose value is closest +// to v. NearestWithinSpan panics if u < l. If the value is greater than u or +// less than l, the function returns -1. +func NearestWithinSpan(n int, l, u float64, v float64) int { + if u < l { + panic("floats: upper bound greater than lower bound") + } + if v < l || v > u { + return -1 + } + // Can't guarantee anything about exactly halfway between + // because of floating point weirdness. + return int((float64(n)-1)/(u-l)*(v-l) + 0.5) +} + +// Norm returns the L norm of the slice S, defined as +// (sum_{i=1}^N s[i]^L)^{1/L} +// Special cases: +// L = math.Inf(1) gives the maximum absolute value. +// Does not correctly compute the zero norm (use Count). +func Norm(s []float64, L float64) float64 { + // Should this complain if L is not positive? + // Should this be done in log space for better numerical stability? + // would be more cost + // maybe only if L is high? + if len(s) == 0 { + return 0 + } + if L == 2 { + twoNorm := math.Abs(s[0]) + for i := 1; i < len(s); i++ { + twoNorm = math.Hypot(twoNorm, s[i]) + } + return twoNorm + } + var norm float64 + if L == 1 { + for _, val := range s { + norm += math.Abs(val) + } + return norm + } + if math.IsInf(L, 1) { + for _, val := range s { + norm = math.Max(norm, math.Abs(val)) + } + return norm + } + for _, val := range s { + norm += math.Pow(math.Abs(val), L) + } + return math.Pow(norm, 1/L) +} + +// Prod returns the product of the elements of the slice. +// Returns 1 if len(s) = 0. +func Prod(s []float64) float64 { + prod := 1.0 + for _, val := range s { + prod *= val + } + return prod +} + +// Reverse reverses the order of elements in the slice. +func Reverse(s []float64) { + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + s[i], s[j] = s[j], s[i] + } +} + +// Round returns the half away from zero rounded value of x with prec precision. +// +// Special cases are: +// Round(±0) = +0 +// Round(±Inf) = ±Inf +// Round(NaN) = NaN +func Round(x float64, prec int) float64 { + if x == 0 { + // Make sure zero is returned + // without the negative bit set. + return 0 + } + // Fast path for positive precision on integers. + if prec >= 0 && x == math.Trunc(x) { + return x + } + pow := math.Pow10(prec) + intermed := x * pow + if math.IsInf(intermed, 0) { + return x + } + if x < 0 { + x = math.Ceil(intermed - 0.5) + } else { + x = math.Floor(intermed + 0.5) + } + + if x == 0 { + return 0 + } + + return x / pow +} + +// RoundEven returns the half even rounded value of x with prec precision. +// +// Special cases are: +// RoundEven(±0) = +0 +// RoundEven(±Inf) = ±Inf +// RoundEven(NaN) = NaN +func RoundEven(x float64, prec int) float64 { + if x == 0 { + // Make sure zero is returned + // without the negative bit set. + return 0 + } + // Fast path for positive precision on integers. + if prec >= 0 && x == math.Trunc(x) { + return x + } + pow := math.Pow10(prec) + intermed := x * pow + if math.IsInf(intermed, 0) { + return x + } + if isHalfway(intermed) { + correction, _ := math.Modf(math.Mod(intermed, 2)) + intermed += correction + if intermed > 0 { + x = math.Floor(intermed) + } else { + x = math.Ceil(intermed) + } + } else { + if x < 0 { + x = math.Ceil(intermed - 0.5) + } else { + x = math.Floor(intermed + 0.5) + } + } + + if x == 0 { + return 0 + } + + return x / pow +} + +func isHalfway(x float64) bool { + _, frac := math.Modf(x) + frac = math.Abs(frac) + return frac == 0.5 || (math.Nextafter(frac, math.Inf(-1)) < 0.5 && math.Nextafter(frac, math.Inf(1)) > 0.5) +} + +// Same returns true if the input slices have the same length and the all elements +// have the same value with NaN treated as the same. +func Same(s, t []float64) bool { + if len(s) != len(t) { + return false + } + for i, v := range s { + w := t[i] + if v != w && !math.IsNaN(v) && !math.IsNaN(w) { + return false + } + } + return true +} + +// Scale multiplies every element in dst by the scalar c. +func Scale(c float64, dst []float64) { + if len(dst) > 0 { + f64.ScalUnitary(c, dst) + } +} + +// Span returns a set of N equally spaced points between l and u, where N +// is equal to the length of the destination. The first element of the destination +// is l, the final element of the destination is u. +// Panics if len(dst) < 2. +// +// Also returns the mutated slice dst, so that it can be used in range expressions, like: +// +// for i, x := range Span(dst, l, u) { ... } +func Span(dst []float64, l, u float64) []float64 { + n := len(dst) + if n < 2 { + panic("floats: destination must have length >1") + } + step := (u - l) / float64(n-1) + for i := range dst { + dst[i] = l + step*float64(i) + } + return dst +} + +// Sub subtracts, element-wise, the elements of s from dst. Panics if +// the lengths of dst and s do not match. +func Sub(dst, s []float64) { + if len(dst) != len(s) { + panic("floats: length of the slices do not match") + } + f64.AxpyUnitaryTo(dst, -1, s, dst) +} + +// SubTo subtracts, element-wise, the elements of t from s and +// stores the result in dst. Panics if the lengths of s, t and dst do not match. +func SubTo(dst, s, t []float64) []float64 { + if len(s) != len(t) { + panic("floats: length of subtractor and subtractee do not match") + } + if len(dst) != len(s) { + panic("floats: length of destination does not match length of subtractor") + } + f64.AxpyUnitaryTo(dst, -1, t, s) + return dst +} + +// Sum returns the sum of the elements of the slice. +func Sum(s []float64) float64 { + var sum float64 + for _, val := range s { + sum += val + } + return sum +} + +// Within returns the first index i where s[i] <= v < s[i+1]. Within panics if: +// - len(s) < 2 +// - s is not sorted +func Within(s []float64, v float64) int { + if len(s) < 2 { + panic("floats: slice length less than 2") + } + if !sort.Float64sAreSorted(s) { + panic("floats: input slice not sorted") + } + if v < s[0] || v >= s[len(s)-1] || math.IsNaN(v) { + return -1 + } + for i, f := range s[1:] { + if v < f { + return i + } + } + return -1 +} diff --git a/floats/floats_test.go b/floats/floats_test.go new file mode 100644 index 00000000..d5a2f8db --- /dev/null +++ b/floats/floats_test.go @@ -0,0 +1,1468 @@ +// Copyright 2013 The Gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package floats + +import ( + "math" + "math/rand" + "strconv" + "testing" + "testing/quick" +) + +const ( + EqTolerance = 1E-14 + Small = 10 + Medium = 1000 + Large = 100000 + Huge = 10000000 +) + +func AreSlicesEqual(t *testing.T, truth, comp []float64, str string) { + if !EqualApprox(comp, truth, EqTolerance) { + t.Errorf(str+". Expected %v, returned %v", truth, comp) + } +} + +func Panics(fun func()) (b bool) { + defer func() { + err := recover() + if err != nil { + b = true + } + }() + fun() + return +} + +func TestAdd(t *testing.T) { + a := []float64{1, 2, 3} + b := []float64{4, 5, 6} + c := []float64{7, 8, 9} + truth := []float64{12, 15, 18} + n := make([]float64, len(a)) + + Add(n, a) + Add(n, b) + Add(n, c) + AreSlicesEqual(t, truth, n, "Wrong addition of slices new receiver") + Add(a, b) + Add(a, c) + AreSlicesEqual(t, truth, n, "Wrong addition of slices for no new receiver") + + // Test that it panics + if !Panics(func() { Add(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } +} + +func TestAddTo(t *testing.T) { + a := []float64{1, 2, 3} + b := []float64{4, 5, 6} + truth := []float64{5, 7, 9} + n1 := make([]float64, len(a)) + + n2 := AddTo(n1, a, b) + AreSlicesEqual(t, truth, n1, "Bad addition from mutator") + AreSlicesEqual(t, truth, n2, "Bad addition from returned slice") + + // Test that it panics + if !Panics(func() { AddTo(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } + if !Panics(func() { AddTo(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Did not panic with length mismatch") + } + +} + +func TestAddConst(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + c := 6.0 + truth := []float64{9, 10, 7, 13, 11} + AddConst(c, s) + AreSlicesEqual(t, truth, s, "Wrong addition of constant") +} + +func TestAddScaled(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + alpha := 6.0 + dst := []float64{1, 2, 3, 4, 5} + ans := []float64{19, 26, 9, 46, 35} + AddScaled(dst, alpha, s) + if !EqualApprox(dst, ans, EqTolerance) { + t.Errorf("Adding scaled did not match") + } + short := []float64{1} + if !Panics(func() { AddScaled(dst, alpha, short) }) { + t.Errorf("Doesn't panic if s is smaller than dst") + } + if !Panics(func() { AddScaled(short, alpha, s) }) { + t.Errorf("Doesn't panic if dst is smaller than s") + } +} + +func TestAddScaledTo(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + alpha := 6.0 + y := []float64{1, 2, 3, 4, 5} + dst1 := make([]float64, 5) + ans := []float64{19, 26, 9, 46, 35} + dst2 := AddScaledTo(dst1, y, alpha, s) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("AddScaledTo did not match for mutator") + } + if !EqualApprox(dst2, ans, EqTolerance) { + t.Errorf("AddScaledTo did not match for returned slice") + } + AddScaledTo(dst1, y, alpha, s) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("Reusing dst did not match") + } + short := []float64{1} + if !Panics(func() { AddScaledTo(dst1, y, alpha, short) }) { + t.Errorf("Doesn't panic if s is smaller than dst") + } + if !Panics(func() { AddScaledTo(short, y, alpha, s) }) { + t.Errorf("Doesn't panic if dst is smaller than s") + } + if !Panics(func() { AddScaledTo(dst1, short, alpha, s) }) { + t.Errorf("Doesn't panic if y is smaller than dst") + } +} + +func TestArgsort(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + inds := make([]int, len(s)) + + Argsort(s, inds) + + sortedS := []float64{1, 3, 4, 5, 7} + trueInds := []int{2, 0, 1, 4, 3} + + if !Equal(s, sortedS) { + t.Error("elements not sorted correctly") + } + for i := range trueInds { + if trueInds[i] != inds[i] { + t.Error("inds not correct") + } + } + + inds = []int{1, 2} + if !Panics(func() { Argsort(s, inds) }) { + t.Error("does not panic if lengths do not match") + } +} + +func TestCount(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + f := func(v float64) bool { return v > 3.5 } + truth := 3 + n := Count(f, s) + if n != truth { + t.Errorf("Wrong number of elements counted") + } +} + +func TestCumProd(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + receiver := make([]float64, len(s)) + result := CumProd(receiver, s) + truth := []float64{3, 12, 12, 84, 420} + AreSlicesEqual(t, truth, receiver, "Wrong cumprod mutated with new receiver") + AreSlicesEqual(t, truth, result, "Wrong cumprod result with new receiver") + CumProd(receiver, s) + AreSlicesEqual(t, truth, receiver, "Wrong cumprod returned with reused receiver") + + // Test that it panics + if !Panics(func() { CumProd(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } + + // Test empty CumProd + emptyReceiver := make([]float64, 0) + truth = []float64{} + CumProd(emptyReceiver, emptyReceiver) + AreSlicesEqual(t, truth, emptyReceiver, "Wrong cumprod returned with emtpy receiver") + +} + +func TestCumSum(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + receiver := make([]float64, len(s)) + result := CumSum(receiver, s) + truth := []float64{3, 7, 8, 15, 20} + AreSlicesEqual(t, truth, receiver, "Wrong cumsum mutated with new receiver") + AreSlicesEqual(t, truth, result, "Wrong cumsum returned with new receiver") + CumSum(receiver, s) + AreSlicesEqual(t, truth, receiver, "Wrong cumsum returned with reused receiver") + + // Test that it panics + if !Panics(func() { CumSum(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } + + // Test empty CumSum + emptyReceiver := make([]float64, 0) + truth = []float64{} + CumSum(emptyReceiver, emptyReceiver) + AreSlicesEqual(t, truth, emptyReceiver, "Wrong cumsum returned with emtpy receiver") + +} + +func TestDistance(t *testing.T) { + norms := []float64{1, 2, 4, math.Inf(1)} + slices := []struct { + s []float64 + t []float64 + }{ + { + nil, + nil, + }, + { + []float64{8, 9, 10, -12}, + []float64{8, 9, 10, -12}, + }, + { + []float64{1, 2, 3, -4, -5, 8}, + []float64{-9.2, -6.8, 9, -3, -2, 1}, + }, + } + + for j, test := range slices { + tmp := make([]float64, len(test.s)) + for i, L := range norms { + dist := Distance(test.s, test.t, L) + copy(tmp, test.s) + Sub(tmp, test.t) + norm := Norm(tmp, L) + if dist != norm { // Use equality because they should be identical + t.Errorf("Distance does not match norm for case %v, %v. Expected %v, Found %v.", i, j, norm, dist) + } + } + } + + if !Panics(func() { Distance([]float64{}, norms, 1) }) { + t.Errorf("Did not panic with unequal lengths") + } + +} + +func TestDiv(t *testing.T) { + s1 := []float64{5, 12, 27} + s2 := []float64{1, 2, 3} + ans := []float64{5, 6, 9} + Div(s1, s2) + if !EqualApprox(s1, ans, EqTolerance) { + t.Errorf("Mul doesn't give correct answer") + } + s1short := []float64{1} + if !Panics(func() { Div(s1short, s2) }) { + t.Errorf("Did not panic with unequal lengths") + } + s2short := []float64{1} + if !Panics(func() { Div(s1, s2short) }) { + t.Errorf("Did not panic with unequal lengths") + } +} + +func TestDivTo(t *testing.T) { + s1 := []float64{5, 12, 27} + s1orig := []float64{5, 12, 27} + s2 := []float64{1, 2, 3} + s2orig := []float64{1, 2, 3} + dst1 := make([]float64, 3) + ans := []float64{5, 6, 9} + dst2 := DivTo(dst1, s1, s2) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("DivTo doesn't give correct answer in mutated slice") + } + if !EqualApprox(dst2, ans, EqTolerance) { + t.Errorf("DivTo doesn't give correct answer in returned slice") + } + if !EqualApprox(s1, s1orig, EqTolerance) { + t.Errorf("S1 changes during multo") + } + if !EqualApprox(s2, s2orig, EqTolerance) { + t.Errorf("s2 changes during multo") + } + DivTo(dst1, s1, s2) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("DivTo doesn't give correct answer reusing dst") + } + dstShort := []float64{1} + if !Panics(func() { DivTo(dstShort, s1, s2) }) { + t.Errorf("Did not panic with s1 wrong length") + } + s1short := []float64{1} + if !Panics(func() { DivTo(dst1, s1short, s2) }) { + t.Errorf("Did not panic with s1 wrong length") + } + s2short := []float64{1} + if !Panics(func() { DivTo(dst1, s1, s2short) }) { + t.Errorf("Did not panic with s2 wrong length") + } +} + +func TestDot(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{-3, 4, 5, -6} + truth := -4.0 + ans := Dot(s1, s2) + if ans != truth { + t.Errorf("Dot product computed incorrectly") + } + + // Test that it panics + if !Panics(func() { Dot(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } +} + +func TestEquals(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4} + if !Equal(s1, s2) { + t.Errorf("Equal slices returned as unequal") + } + s2 = []float64{1, 2, 3, 4 + 1e-14} + if Equal(s1, s2) { + t.Errorf("Unequal slices returned as equal") + } + if Equal(s1, []float64{}) { + t.Errorf("Unequal slice lengths returned as equal") + } +} + +func TestEqualApprox(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4 + 1e-10} + if EqualApprox(s1, s2, 1e-13) { + t.Errorf("Unequal slices returned as equal for absolute") + } + if !EqualApprox(s1, s2, 1e-5) { + t.Errorf("Equal slices returned as unequal for absolute") + } + s1 = []float64{1, 2, 3, 1000} + s2 = []float64{1, 2, 3, 1000 * (1 + 1e-7)} + if EqualApprox(s1, s2, 1e-8) { + t.Errorf("Unequal slices returned as equal for relative") + } + if !EqualApprox(s1, s2, 1e-5) { + t.Errorf("Equal slices returned as unequal for relative") + } + if EqualApprox(s1, []float64{}, 1e-5) { + t.Errorf("Unequal slice lengths returned as equal") + } +} + +func TestEqualFunc(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4} + eq := func(x, y float64) bool { return x == y } + if !EqualFunc(s1, s2, eq) { + t.Errorf("Equal slices returned as unequal") + } + s2 = []float64{1, 2, 3, 4 + 1e-14} + if EqualFunc(s1, s2, eq) { + t.Errorf("Unequal slices returned as equal") + } + if EqualFunc(s1, []float64{}, eq) { + t.Errorf("Unequal slice lengths returned as equal") + } +} + +func TestEqualsRelative(t *testing.T) { + var equalityTests = []struct { + a, b float64 + tol float64 + equal bool + }{ + {1000000, 1000001, 0, true}, + {1000001, 1000000, 0, true}, + {10000, 10001, 0, false}, + {10001, 10000, 0, false}, + {-1000000, -1000001, 0, true}, + {-1000001, -1000000, 0, true}, + {-10000, -10001, 0, false}, + {-10001, -10000, 0, false}, + {1.0000001, 1.0000002, 0, true}, + {1.0000002, 1.0000001, 0, true}, + {1.0002, 1.0001, 0, false}, + {1.0001, 1.0002, 0, false}, + {-1.000001, -1.000002, 0, true}, + {-1.000002, -1.000001, 0, true}, + {-1.0001, -1.0002, 0, false}, + {-1.0002, -1.0001, 0, false}, + {0.000000001000001, 0.000000001000002, 0, true}, + {0.000000001000002, 0.000000001000001, 0, true}, + {0.000000000001002, 0.000000000001001, 0, false}, + {0.000000000001001, 0.000000000001002, 0, false}, + {-0.000000001000001, -0.000000001000002, 0, true}, + {-0.000000001000002, -0.000000001000001, 0, true}, + {-0.000000000001002, -0.000000000001001, 0, false}, + {-0.000000000001001, -0.000000000001002, 0, false}, + {0, 0, 0, true}, + {0, -0, 0, true}, + {-0, -0, 0, true}, + {0.00000001, 0, 0, false}, + {0, 0.00000001, 0, false}, + {-0.00000001, 0, 0, false}, + {0, -0.00000001, 0, false}, + {0, 1e-310, 0.01, true}, + {1e-310, 0, 0.01, true}, + {1e-310, 0, 0.000001, false}, + {0, 1e-310, 0.000001, false}, + {0, -1e-310, 0.1, true}, + {-1e-310, 0, 0.1, true}, + {-1e-310, 0, 0.00000001, false}, + {0, -1e-310, 0.00000001, false}, + {math.Inf(1), math.Inf(1), 0, true}, + {math.Inf(-1), math.Inf(-1), 0, true}, + {math.Inf(-1), math.Inf(1), 0, false}, + {math.Inf(1), math.MaxFloat64, 0, false}, + {math.Inf(-1), -math.MaxFloat64, 0, false}, + {math.NaN(), math.NaN(), 0, false}, + {math.NaN(), 0, 0, false}, + {-0, math.NaN(), 0, false}, + {math.NaN(), -0, 0, false}, + {0, math.NaN(), 0, false}, + {math.NaN(), math.Inf(1), 0, false}, + {math.Inf(1), math.NaN(), 0, false}, + {math.NaN(), math.Inf(-1), 0, false}, + {math.Inf(-1), math.NaN(), 0, false}, + {math.NaN(), math.MaxFloat64, 0, false}, + {math.MaxFloat64, math.NaN(), 0, false}, + {math.NaN(), -math.MaxFloat64, 0, false}, + {-math.MaxFloat64, math.NaN(), 0, false}, + {math.NaN(), math.SmallestNonzeroFloat64, 0, false}, + {math.SmallestNonzeroFloat64, math.NaN(), 0, false}, + {math.NaN(), -math.SmallestNonzeroFloat64, 0, false}, + {-math.SmallestNonzeroFloat64, math.NaN(), 0, false}, + {1.000000001, -1.0, 0, false}, + {-1.0, 1.000000001, 0, false}, + {-1.000000001, 1.0, 0, false}, + {1.0, -1.000000001, 0, false}, + {10 * math.SmallestNonzeroFloat64, 10 * -math.SmallestNonzeroFloat64, 0, true}, + {1e11 * math.SmallestNonzeroFloat64, 1e11 * -math.SmallestNonzeroFloat64, 0, false}, + {math.SmallestNonzeroFloat64, -math.SmallestNonzeroFloat64, 0, true}, + {-math.SmallestNonzeroFloat64, math.SmallestNonzeroFloat64, 0, true}, + {math.SmallestNonzeroFloat64, 0, 0, true}, + {0, math.SmallestNonzeroFloat64, 0, true}, + {-math.SmallestNonzeroFloat64, 0, 0, true}, + {0, -math.SmallestNonzeroFloat64, 0, true}, + {0.000000001, -math.SmallestNonzeroFloat64, 0, false}, + {0.000000001, math.SmallestNonzeroFloat64, 0, false}, + {math.SmallestNonzeroFloat64, 0.000000001, 0, false}, + {-math.SmallestNonzeroFloat64, 0.000000001, 0, false}, + } + for _, ts := range equalityTests { + if ts.tol == 0 { + ts.tol = 1e-5 + } + if equal := EqualWithinRel(ts.a, ts.b, ts.tol); equal != ts.equal { + t.Errorf("Relative equality of %g and %g with tolerance %g returned: %v. Expected: %v", + ts.a, ts.b, ts.tol, equal, ts.equal) + } + } +} + +func nextAfterN(x, y float64, n int) float64 { + for i := 0; i < n; i++ { + x = math.Nextafter(x, y) + } + return x +} + +func TestEqualsULP(t *testing.T) { + if f := 67329.242; !EqualWithinULP(f, nextAfterN(f, math.Inf(1), 10), 10) { + t.Errorf("Equal values returned as unequal") + } + if f := 67329.242; EqualWithinULP(f, nextAfterN(f, math.Inf(1), 5), 1) { + t.Errorf("Unequal values returned as equal") + } + if f := 67329.242; EqualWithinULP(nextAfterN(f, math.Inf(1), 5), f, 1) { + t.Errorf("Unequal values returned as equal") + } + if f := nextAfterN(0, math.Inf(1), 2); !EqualWithinULP(f, nextAfterN(f, math.Inf(-1), 5), 10) { + t.Errorf("Equal values returned as unequal") + } + if !EqualWithinULP(67329.242, 67329.242, 10) { + t.Errorf("Equal float64s not returned as equal") + } + if EqualWithinULP(1, math.NaN(), 10) { + t.Errorf("NaN returned as equal") + } + +} + +func TestEqualLengths(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4} + s3 := []float64{1, 2, 3} + if !EqualLengths(s1, s2) { + t.Errorf("Equal lengths returned as unequal") + } + if EqualLengths(s1, s3) { + t.Errorf("Unequal lengths returned as equal") + } + if !EqualLengths(s1) { + t.Errorf("Single slice returned as unequal") + } + if !EqualLengths() { + t.Errorf("No slices returned as unequal") + } +} + +func eqIntSlice(one, two []int) string { + if len(one) != len(two) { + return "Length mismatch" + } + for i, val := range one { + if val != two[i] { + return "Index " + strconv.Itoa(i) + " mismatch" + } + } + return "" +} + +func TestFind(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + f := func(v float64) bool { return v > 3.5 } + allTrueInds := []int{1, 3, 4} + + // Test finding first two elements + inds, err := Find(nil, f, s, 2) + if err != nil { + t.Errorf("Find first two: Improper error return") + } + trueInds := allTrueInds[:2] + str := eqIntSlice(inds, trueInds) + if str != "" { + t.Errorf("Find first two: " + str) + } + + // Test finding no elements with non nil slice + inds = []int{1, 2, 3, 4, 5, 6} + inds, err = Find(inds, f, s, 0) + if err != nil { + t.Errorf("Find no elements: Improper error return") + } + str = eqIntSlice(inds, []int{}) + if str != "" { + t.Errorf("Find no non-nil: " + str) + } + + // Test finding first two elements with non nil slice + inds = []int{1, 2, 3, 4, 5, 6} + inds, err = Find(inds, f, s, 2) + if err != nil { + t.Errorf("Find first two non-nil: Improper error return") + } + str = eqIntSlice(inds, trueInds) + if str != "" { + t.Errorf("Find first two non-nil: " + str) + } + + // Test finding too many elements + inds, err = Find(inds, f, s, 4) + if err == nil { + t.Errorf("Request too many: No error returned") + } + str = eqIntSlice(inds, allTrueInds) + if str != "" { + t.Errorf("Request too many: Does not match all of the inds: " + str) + } + + // Test finding all elements + inds, err = Find(nil, f, s, -1) + if err != nil { + t.Errorf("Find all: Improper error returned") + } + str = eqIntSlice(inds, allTrueInds) + if str != "" { + t.Errorf("Find all: Does not match all of the inds: " + str) + } +} + +func TestHasNaN(t *testing.T) { + for i, test := range []struct { + s []float64 + ans bool + }{ + {}, + { + s: []float64{1, 2, 3, 4}, + }, + { + s: []float64{1, math.NaN(), 3, 4}, + ans: true, + }, + { + s: []float64{1, 2, 3, math.NaN()}, + ans: true, + }, + } { + b := HasNaN(test.s) + if b != test.ans { + t.Errorf("HasNaN mismatch case %d. Expected %v, Found %v", i, test.ans, b) + } + } +} + +func TestLogSpan(t *testing.T) { + receiver1 := make([]float64, 6) + truth := []float64{0.001, 0.01, 0.1, 1, 10, 100} + receiver2 := LogSpan(receiver1, 0.001, 100) + tst := make([]float64, 6) + for i := range truth { + tst[i] = receiver1[i] / truth[i] + } + comp := make([]float64, 6) + for i := range comp { + comp[i] = 1 + } + AreSlicesEqual(t, comp, tst, "Improper logspace from mutator") + + for i := range truth { + tst[i] = receiver2[i] / truth[i] + } + AreSlicesEqual(t, comp, tst, "Improper logspace from returned slice") + + if !Panics(func() { LogSpan(nil, 1, 5) }) { + t.Errorf("Span accepts nil argument") + } + if !Panics(func() { LogSpan(make([]float64, 1), 1, 5) }) { + t.Errorf("Span accepts argument of len = 1") + } +} + +func TestLogSumExp(t *testing.T) { + s := []float64{1, 2, 3, 4, 5} + val := LogSumExp(s) + // http://www.wolframalpha.com/input/?i=log%28exp%281%29+%2B+exp%282%29+%2B+exp%283%29+%2B+exp%284%29+%2B+exp%285%29%29 + truth := 5.4519143959375933331957225109748087179338972737576824 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Wrong logsumexp for many values") + } + s = []float64{1, 2} + // http://www.wolframalpha.com/input/?i=log%28exp%281%29+%2B+exp%282%29%29 + truth = 2.3132616875182228340489954949678556419152800856703483 + val = LogSumExp(s) + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Wrong logsumexp for two values. %v expected, %v found", truth, val) + } + // This case would normally underflow + s = []float64{-1001, -1002, -1003, -1004, -1005} + // http://www.wolframalpha.com/input/?i=log%28exp%28-1001%29%2Bexp%28-1002%29%2Bexp%28-1003%29%2Bexp%28-1004%29%2Bexp%28-1005%29%29 + truth = -1000.54808560406240666680427748902519128206610272624 + val = LogSumExp(s) + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for underflow case. %v expected, %v found", truth, val) + } + // positive infinite case + s = []float64{1, 2, 3, 4, 5, math.Inf(1)} + val = LogSumExp(s) + truth = math.Inf(1) + if val != truth { + t.Errorf("Doesn't match for pos Infinity case. %v expected, %v found", truth, val) + } + // negative infinite case + s = []float64{1, 2, 3, 4, 5, math.Inf(-1)} + val = LogSumExp(s) + truth = 5.4519143959375933331957225109748087179338972737576824 // same as first case + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Wrong logsumexp for values with negative infinity") + } + +} + +func TestMaxAndIdx(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + ind := MaxIdx(s) + val := Max(s) + if val != 7 { + t.Errorf("Wrong value returned") + } + if ind != 3 { + t.Errorf("Wrong index returned") + } +} + +func TestMinAndIdx(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + ind := MinIdx(s) + val := Min(s) + if val != 1 { + t.Errorf("Wrong value returned") + } + if ind != 2 { + t.Errorf("Wrong index returned") + } +} + +func TestMul(t *testing.T) { + s1 := []float64{1, 2, 3} + s2 := []float64{1, 2, 3} + ans := []float64{1, 4, 9} + Mul(s1, s2) + if !EqualApprox(s1, ans, EqTolerance) { + t.Errorf("Mul doesn't give correct answer") + } + s1short := []float64{1} + if !Panics(func() { Mul(s1short, s2) }) { + t.Errorf("Did not panic with unequal lengths") + } + s2short := []float64{1} + if !Panics(func() { Mul(s1, s2short) }) { + t.Errorf("Did not panic with unequal lengths") + } +} + +func TestMulTo(t *testing.T) { + s1 := []float64{1, 2, 3} + s1orig := []float64{1, 2, 3} + s2 := []float64{1, 2, 3} + s2orig := []float64{1, 2, 3} + dst1 := make([]float64, 3) + ans := []float64{1, 4, 9} + dst2 := MulTo(dst1, s1, s2) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("MulTo doesn't give correct answer in mutated slice") + } + if !EqualApprox(dst2, ans, EqTolerance) { + t.Errorf("MulTo doesn't give correct answer in returned slice") + } + if !EqualApprox(s1, s1orig, EqTolerance) { + t.Errorf("S1 changes during multo") + } + if !EqualApprox(s2, s2orig, EqTolerance) { + t.Errorf("s2 changes during multo") + } + MulTo(dst1, s1, s2) + if !EqualApprox(dst1, ans, EqTolerance) { + t.Errorf("MulTo doesn't give correct answer reusing dst") + } + dstShort := []float64{1} + if !Panics(func() { MulTo(dstShort, s1, s2) }) { + t.Errorf("Did not panic with s1 wrong length") + } + s1short := []float64{1} + if !Panics(func() { MulTo(dst1, s1short, s2) }) { + t.Errorf("Did not panic with s1 wrong length") + } + s2short := []float64{1} + if !Panics(func() { MulTo(dst1, s1, s2short) }) { + t.Errorf("Did not panic with s2 wrong length") + } +} + +func TestNearest(t *testing.T) { + s := []float64{6.2, 3, 5, 6.2, 8} + ind := Nearest(s, 2.0) + if ind != 1 { + t.Errorf("Wrong index returned when value is less than all of elements") + } + ind = Nearest(s, 9.0) + if ind != 4 { + t.Errorf("Wrong index returned when value is greater than all of elements") + } + ind = Nearest(s, 3.1) + if ind != 1 { + t.Errorf("Wrong index returned when value is greater than closest element") + } + ind = Nearest(s, 3.1) + if ind != 1 { + t.Errorf("Wrong index returned when value is greater than closest element") + } + ind = Nearest(s, 2.9) + if ind != 1 { + t.Errorf("Wrong index returned when value is less than closest element") + } + ind = Nearest(s, 3) + if ind != 1 { + t.Errorf("Wrong index returned when value is equal to element") + } + ind = Nearest(s, 6.2) + if ind != 0 { + t.Errorf("Wrong index returned when value is equal to several elements") + } + ind = Nearest(s, 4) + if ind != 1 { + t.Errorf("Wrong index returned when value is exactly between two closest elements") + } +} + +func TestNearestWithinSpan(t *testing.T) { + if !Panics(func() { NearestWithinSpan(10, 8, 2, 4.5) }) { + t.Errorf("Did not panic when upper bound is lower than greater bound") + } + for i, test := range []struct { + length int + lower float64 + upper float64 + value float64 + idx int + }{ + { + length: 13, + lower: 7, + upper: 8.2, + value: 6, + idx: -1, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 10, + idx: -1, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.19, + idx: 2, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.21, + idx: 2, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.2, + idx: 2, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.151, + idx: 2, + }, + { + length: 13, + lower: 7, + upper: 8.2, + value: 7.249, + idx: 2, + }, + } { + if idx := NearestWithinSpan(test.length, test.lower, test.upper, test.value); test.idx != idx { + t.Errorf("Case %v mismatch: Want: %v, Got: %v", i, test.idx, idx) + } + } +} + +func TestNorm(t *testing.T) { + s := []float64{-1, -3.4, 5, -6} + val := Norm(s, math.Inf(1)) + truth := 6.0 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val) + } + // http://www.wolframalpha.com/input/?i=%28%28-1%29%5E2+%2B++%28-3.4%29%5E2+%2B+5%5E2%2B++6%5E2%29%5E%281%2F2%29 + val = Norm(s, 2) + truth = 8.5767126569566267590651614132751986658027271236078592 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val) + } + // http://www.wolframalpha.com/input/?i=%28%28%7C-1%7C%29%5E3+%2B++%28%7C-3.4%7C%29%5E3+%2B+%7C5%7C%5E3%2B++%7C6%7C%5E3%29%5E%281%2F3%29 + val = Norm(s, 3) + truth = 7.2514321388020228478109121239004816430071237369356233 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val) + } + + //http://www.wolframalpha.com/input/?i=%7C-1%7C+%2B+%7C-3.4%7C+%2B+%7C5%7C%2B++%7C6%7C + val = Norm(s, 1) + truth = 15.4 + if math.Abs(val-truth) > EqTolerance { + t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val) + } +} + +func TestProd(t *testing.T) { + s := []float64{} + val := Prod(s) + if val != 1 { + t.Errorf("Val not returned as default when slice length is zero") + } + s = []float64{3, 4, 1, 7, 5} + val = Prod(s) + if val != 420 { + t.Errorf("Wrong prod returned. Expected %v returned %v", 420, val) + } +} + +func TestReverse(t *testing.T) { + for _, s := range [][]float64{ + {0}, + {1, 0}, + {2, 1, 0}, + {3, 2, 1, 0}, + {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + } { + Reverse(s) + for i, v := range s { + if v != float64(i) { + t.Errorf("unexpected values for element %d: got:%v want:%v", i, v, i) + } + } + } +} + +func roundFloat(x float64, prec int) float64 { + f, _ := strconv.ParseFloat(strconv.FormatFloat(x, 'f', prec, 64), 64) + if f == 0 { + return math.Abs(f) + } + return f +} + +func TestRound(t *testing.T) { + for _, x := range []float64{ + 0, + math.Inf(1), + math.NaN(), + func() float64 { var f float64; return -f }(), + math.MaxFloat64 / 2, + 1 << 64, + 454.4445, + 454.44445, + 0.42499, + 0.42599, + 0.424999999999993, + 0.425000000000001, + 123.42499999999993, + + // FIXME(kortschak): These values fail due to roundFloat rounding + // 454.45 to ±454.4 when prec=1 and 454.445 to ±454.44 when prec=2. + // This is a result of fmt's rendering of the value. + // 454.45, + // 454.445, + } { + for _, sign := range []float64{1, -1} { + for prec := 0; prec < 10; prec++ { + got := Round(sign*x, prec) + want := roundFloat(sign*x, prec) + if (got != want || math.Signbit(got) != math.Signbit(want)) && !(math.IsNaN(got) && math.IsNaN(want)) { + t.Errorf("unexpected result for Round(%g, %d): got: %g, want: %g", x, prec, got, want) + } + } + } + } + + // Special cases. + for _, test := range []struct { + x float64 + prec int + want float64 + }{ + // Failing cases above. + {x: 454.45, prec: 0, want: 454}, + {x: 454.45, prec: 1, want: 454.5}, + {x: 454.45, prec: 2, want: 454.45}, + {x: 454.45, prec: 3, want: 454.45}, + {x: 454.445, prec: 0, want: 454}, + {x: 454.445, prec: 1, want: 454.4}, + {x: 454.445, prec: 2, want: 454.45}, + {x: 454.445, prec: 3, want: 454.445}, + {x: 454.445, prec: 4, want: 454.445}, + + // Negative precision. + {x: 454.45, prec: -1, want: 450}, + {x: 454.45, prec: -2, want: 500}, + {x: 500, prec: -3, want: 1000}, + {x: 500, prec: -4, want: 0}, + } { + for _, sign := range []float64{1, -1} { + got := Round(sign*test.x, test.prec) + want := sign * test.want + if want == 0 { + want = 0 + } + if got != want || math.Signbit(got) != math.Signbit(want) { + t.Errorf("unexpected result for Round(%g, %d): got: %g, want: %g", test.x, test.prec, got, test.want) + } + } + } + + // Test many large numbers. We hit float precision + // issues below 1e16 so we avoid that domain. + err := quick.Check(func(x float64, prec int) bool { + prec %= 20 + if prec < 0 { + prec = -prec + } + for x > 1e16 { + got := Round(x, prec) + want := roundFloat(x, prec) + if (got != want || math.Signbit(got) != math.Signbit(want)) && !(math.IsNaN(got) && math.IsNaN(want)) { + t.Logf("big numbers failed with prec=%d x=%f got=%f want=%f", prec, x, got, want) + return false + } + x /= 10 + } + return true + }, nil) + if err != nil { + t.Error(err) + } + + // Test many small numbers. + err = quick.Check(func(mant, exp int, prec int) bool { + prec %= 20 + if prec < 0 { + prec = -prec + } + mant %= 1e10 + exp %= 40 + if exp > 0 { + exp = -exp + } + x := float64(mant) * math.Pow10(exp) + _, x = math.Modf(x) + if prec > -exp { + prec = -exp + } + got := strconv.FormatFloat(Round(x, prec), 'g', prec, 64) + want := strconv.FormatFloat(roundFloat(x, prec), 'g', prec, 64) + if got != want { + t.Logf("small numbers failed with prec=%d x=%f got=%s want=%s", prec, x, got, want) + return false + } + return true + }, nil) + if err != nil { + t.Error(err) + } +} + +func TestRoundEven(t *testing.T) { + for _, test := range []struct { + x float64 + prec int + want float64 + }{ + {x: 0, prec: 1, want: 0}, + {x: math.Inf(1), prec: 1, want: math.Inf(1)}, + {x: math.NaN(), prec: 1, want: math.NaN()}, + {x: func() float64 { var f float64; return -f }(), prec: 1, want: 0}, + {x: math.MaxFloat64 / 2, prec: 1, want: math.MaxFloat64 / 2}, + {x: 1 << 64, prec: 1, want: 1 << 64}, + {x: 454.4445, prec: 3, want: 454.444}, + {x: 454.44445, prec: 4, want: 454.4444}, + {x: 0.42499, prec: 4, want: 0.425}, + {x: 0.42599, prec: 4, want: 0.426}, + {x: 0.424999999999993, prec: 2, want: 0.42}, + {x: 0.425, prec: 2, want: 0.42}, + {x: 0.425000000000001, prec: 2, want: 0.43}, + {x: 123.4244999999999, prec: 3, want: 123.424}, + {x: 123.4245, prec: 3, want: 123.424}, + {x: 123.4245000000001, prec: 3, want: 123.425}, + + {x: 454.45, prec: 0, want: 454}, + {x: 454.45, prec: 1, want: 454.4}, + {x: 454.45, prec: 2, want: 454.45}, + {x: 454.45, prec: 3, want: 454.45}, + {x: 454.445, prec: 0, want: 454}, + {x: 454.445, prec: 1, want: 454.4}, + {x: 454.445, prec: 2, want: 454.44}, + {x: 454.445, prec: 3, want: 454.445}, + {x: 454.445, prec: 4, want: 454.445}, + {x: 454.55, prec: 0, want: 455}, + {x: 454.55, prec: 1, want: 454.6}, + {x: 454.55, prec: 2, want: 454.55}, + {x: 454.55, prec: 3, want: 454.55}, + {x: 454.455, prec: 0, want: 454}, + {x: 454.455, prec: 1, want: 454.5}, + {x: 454.455, prec: 2, want: 454.46}, + {x: 454.455, prec: 3, want: 454.455}, + {x: 454.455, prec: 4, want: 454.455}, + + // Negative precision. + {x: 454.45, prec: -1, want: 450}, + {x: 454.45, prec: -2, want: 500}, + {x: 500, prec: -3, want: 0}, + {x: 500, prec: -4, want: 0}, + {x: 1500, prec: -3, want: 2000}, + {x: 1500, prec: -4, want: 0}, + } { + for _, sign := range []float64{1, -1} { + got := RoundEven(sign*test.x, test.prec) + want := sign * test.want + if want == 0 { + want = 0 + } + if (got != want || math.Signbit(got) != math.Signbit(want)) && !(math.IsNaN(got) && math.IsNaN(want)) { + t.Errorf("unexpected result for RoundEven(%g, %d): got: %g, want: %g", sign*test.x, test.prec, got, want) + } + } + } +} + +func TestSame(t *testing.T) { + s1 := []float64{1, 2, 3, 4} + s2 := []float64{1, 2, 3, 4} + if !Same(s1, s2) { + t.Errorf("Equal slices returned as unequal") + } + s2 = []float64{1, 2, 3, 4 + 1e-14} + if Same(s1, s2) { + t.Errorf("Unequal slices returned as equal") + } + if Same(s1, []float64{}) { + t.Errorf("Unequal slice lengths returned as equal") + } + s1 = []float64{1, 2, math.NaN(), 4} + s2 = []float64{1, 2, math.NaN(), 4} + if !Same(s1, s2) { + t.Errorf("Slices with matching NaN values returned as unequal") + } + s1 = []float64{1, 2, math.NaN(), 4} + s2 = []float64{1, math.NaN(), 3, 4} + if !Same(s1, s2) { + t.Errorf("Slices with unmatching NaN values returned as equal") + } +} + +func TestScale(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + c := 5.0 + truth := []float64{15, 20, 5, 35, 25} + Scale(c, s) + AreSlicesEqual(t, truth, s, "Bad scaling") +} + +func TestSpan(t *testing.T) { + receiver1 := make([]float64, 5) + truth := []float64{1, 2, 3, 4, 5} + receiver2 := Span(receiver1, 1, 5) + AreSlicesEqual(t, truth, receiver1, "Improper linspace from mutator") + AreSlicesEqual(t, truth, receiver2, "Improper linspace from returned slice") + receiver1 = make([]float64, 6) + truth = []float64{0, 0.2, 0.4, 0.6, 0.8, 1.0} + Span(receiver1, 0, 1) + AreSlicesEqual(t, truth, receiver1, "Improper linspace") + if !Panics(func() { Span(nil, 1, 5) }) { + t.Errorf("Span accepts nil argument") + } + if !Panics(func() { Span(make([]float64, 1), 1, 5) }) { + t.Errorf("Span accepts argument of len = 1") + } +} + +func TestSub(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + v := []float64{1, 2, 3, 4, 5} + truth := []float64{2, 2, -2, 3, 0} + Sub(s, v) + AreSlicesEqual(t, truth, s, "Bad subtract") + // Test that it panics + if !Panics(func() { Sub(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with length mismatch") + } +} + +func TestSubTo(t *testing.T) { + s := []float64{3, 4, 1, 7, 5} + v := []float64{1, 2, 3, 4, 5} + truth := []float64{2, 2, -2, 3, 0} + dst1 := make([]float64, len(s)) + dst2 := SubTo(dst1, s, v) + AreSlicesEqual(t, truth, dst1, "Bad subtract from mutator") + AreSlicesEqual(t, truth, dst2, "Bad subtract from returned slice") + // Test that all mismatch combinations panic + if !Panics(func() { SubTo(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) { + t.Errorf("Did not panic with dst different length") + } + if !Panics(func() { SubTo(make([]float64, 3), make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Did not panic with subtractor different length") + } + if !Panics(func() { SubTo(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Did not panic with subtractee different length") + } +} + +func TestSum(t *testing.T) { + s := []float64{} + val := Sum(s) + if val != 0 { + t.Errorf("Val not returned as default when slice length is zero") + } + s = []float64{3, 4, 1, 7, 5} + val = Sum(s) + if val != 20 { + t.Errorf("Wrong sum returned") + } +} + +func TestWithin(t *testing.T) { + for i, test := range []struct { + s []float64 + v float64 + idx int + panics bool + }{ + { + s: []float64{1, 2, 5, 9}, + v: 1, + idx: 0, + }, + { + s: []float64{1, 2, 5, 9}, + v: 9, + idx: -1, + }, + { + s: []float64{1, 2, 5, 9}, + v: 1.5, + idx: 0, + }, + { + s: []float64{1, 2, 5, 9}, + v: 2, + idx: 1, + }, + { + s: []float64{1, 2, 5, 9}, + v: 2.5, + idx: 1, + }, + { + s: []float64{1, 2, 5, 9}, + v: -3, + idx: -1, + }, + { + s: []float64{1, 2, 5, 9}, + v: 15, + idx: -1, + }, + { + s: []float64{1, 2, 5, 9}, + v: math.NaN(), + idx: -1, + }, + { + s: []float64{5, 2, 6}, + panics: true, + }, + { + panics: true, + }, + { + s: []float64{1}, + panics: true, + }, + } { + var idx int + panics := Panics(func() { idx = Within(test.s, test.v) }) + if panics { + if !test.panics { + t.Errorf("Case %v: bad panic", i) + } + continue + } + if test.panics { + if !panics { + t.Errorf("Case %v: did not panic when it should", i) + } + continue + } + if idx != test.idx { + t.Errorf("Case %v: Idx mismatch. Want: %v, got: %v", i, test.idx, idx) + } + } + +} + +func randomSlice(l int) []float64 { + s := make([]float64, l) + for i := range s { + s[i] = rand.Float64() + } + return s +} + +func benchmarkMin(b *testing.B, size int) { + s := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Min(s) + } +} +func BenchmarkMinSmall(b *testing.B) { benchmarkMin(b, Small) } +func BenchmarkMinMed(b *testing.B) { benchmarkMin(b, Medium) } +func BenchmarkMinLarge(b *testing.B) { benchmarkMin(b, Large) } +func BenchmarkMinHuge(b *testing.B) { benchmarkMin(b, Huge) } + +func benchmarkAdd(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Add(s1, s2) + } +} +func BenchmarkAddSmall(b *testing.B) { benchmarkAdd(b, Small) } +func BenchmarkAddMed(b *testing.B) { benchmarkAdd(b, Medium) } +func BenchmarkAddLarge(b *testing.B) { benchmarkAdd(b, Large) } +func BenchmarkAddHuge(b *testing.B) { benchmarkAdd(b, Huge) } + +func benchmarkAddTo(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + AddTo(dst, s1, s2) + } +} +func BenchmarkAddToSmall(b *testing.B) { benchmarkAddTo(b, Small) } +func BenchmarkAddToMed(b *testing.B) { benchmarkAddTo(b, Medium) } +func BenchmarkAddToLarge(b *testing.B) { benchmarkAddTo(b, Large) } +func BenchmarkAddToHuge(b *testing.B) { benchmarkAddTo(b, Huge) } + +func benchmarkCumProd(b *testing.B, size int) { + s := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + CumProd(dst, s) + } +} +func BenchmarkCumProdSmall(b *testing.B) { benchmarkCumProd(b, Small) } +func BenchmarkCumProdMed(b *testing.B) { benchmarkCumProd(b, Medium) } +func BenchmarkCumProdLarge(b *testing.B) { benchmarkCumProd(b, Large) } +func BenchmarkCumProdHuge(b *testing.B) { benchmarkCumProd(b, Huge) } + +func benchmarkCumSum(b *testing.B, size int) { + s := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + CumSum(dst, s) + } +} +func BenchmarkCumSumSmall(b *testing.B) { benchmarkCumSum(b, Small) } +func BenchmarkCumSumMed(b *testing.B) { benchmarkCumSum(b, Medium) } +func BenchmarkCumSumLarge(b *testing.B) { benchmarkCumSum(b, Large) } +func BenchmarkCumSumHuge(b *testing.B) { benchmarkCumSum(b, Huge) } + +func benchmarkDiv(b *testing.B, size int) { + s := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Div(dst, s) + } +} +func BenchmarkDivSmall(b *testing.B) { benchmarkDiv(b, Small) } +func BenchmarkDivMed(b *testing.B) { benchmarkDiv(b, Medium) } +func BenchmarkDivLarge(b *testing.B) { benchmarkDiv(b, Large) } +func BenchmarkDivHuge(b *testing.B) { benchmarkDiv(b, Huge) } + +func benchmarkDivTo(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + DivTo(dst, s1, s2) + } +} +func BenchmarkDivToSmall(b *testing.B) { benchmarkDivTo(b, Small) } +func BenchmarkDivToMed(b *testing.B) { benchmarkDivTo(b, Medium) } +func BenchmarkDivToLarge(b *testing.B) { benchmarkDivTo(b, Large) } +func BenchmarkDivToHuge(b *testing.B) { benchmarkDivTo(b, Huge) } + +func benchmarkSub(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sub(s1, s2) + } +} +func BenchmarkSubSmall(b *testing.B) { benchmarkSub(b, Small) } +func BenchmarkSubMed(b *testing.B) { benchmarkSub(b, Medium) } +func BenchmarkSubLarge(b *testing.B) { benchmarkSub(b, Large) } +func BenchmarkSubHuge(b *testing.B) { benchmarkSub(b, Huge) } + +func benchmarkSubTo(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + SubTo(dst, s1, s2) + } +} +func BenchmarkSubToSmall(b *testing.B) { benchmarkSubTo(b, Small) } +func BenchmarkSubToMed(b *testing.B) { benchmarkSubTo(b, Medium) } +func BenchmarkSubToLarge(b *testing.B) { benchmarkSubTo(b, Large) } +func BenchmarkSubToHuge(b *testing.B) { benchmarkSubTo(b, Huge) } + +func benchmarkLogSumExp(b *testing.B, size int) { + s := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + LogSumExp(s) + } +} +func BenchmarkLogSumExpSmall(b *testing.B) { benchmarkLogSumExp(b, Small) } +func BenchmarkLogSumExpMed(b *testing.B) { benchmarkLogSumExp(b, Medium) } +func BenchmarkLogSumExpLarge(b *testing.B) { benchmarkLogSumExp(b, Large) } +func BenchmarkLogSumExpHuge(b *testing.B) { benchmarkLogSumExp(b, Huge) } + +func benchmarkDot(b *testing.B, size int) { + s1 := randomSlice(size) + s2 := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Dot(s1, s2) + } +} +func BenchmarkDotSmall(b *testing.B) { benchmarkDot(b, Small) } +func BenchmarkDotMed(b *testing.B) { benchmarkDot(b, Medium) } +func BenchmarkDotLarge(b *testing.B) { benchmarkDot(b, Large) } +func BenchmarkDotHuge(b *testing.B) { benchmarkDot(b, Huge) } + +func benchmarkAddScaledTo(b *testing.B, size int) { + dst := randomSlice(size) + y := randomSlice(size) + s := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i++ { + AddScaledTo(dst, y, 2.3, s) + } +} +func BenchmarkAddScaledToSmall(b *testing.B) { benchmarkAddScaledTo(b, Small) } +func BenchmarkAddScaledToMedium(b *testing.B) { benchmarkAddScaledTo(b, Medium) } +func BenchmarkAddScaledToLarge(b *testing.B) { benchmarkAddScaledTo(b, Large) } +func BenchmarkAddScaledToHuge(b *testing.B) { benchmarkAddScaledTo(b, Huge) } + +func benchmarkScale(b *testing.B, size int) { + dst := randomSlice(size) + b.ResetTimer() + for i := 0; i < b.N; i += 2 { + Scale(2.0, dst) + Scale(0.5, dst) + } +} +func BenchmarkScaleSmall(b *testing.B) { benchmarkScale(b, Small) } +func BenchmarkScaleMedium(b *testing.B) { benchmarkScale(b, Medium) } +func BenchmarkScaleLarge(b *testing.B) { benchmarkScale(b, Large) } +func BenchmarkScaleHuge(b *testing.B) { benchmarkScale(b, Huge) } diff --git a/graph/.gitignore b/graph/.gitignore new file mode 100644 index 00000000..86e0d240 --- /dev/null +++ b/graph/.gitignore @@ -0,0 +1 @@ +test.out \ No newline at end of file diff --git a/graph/README.md b/graph/README.md new file mode 100644 index 00000000..469a8f60 --- /dev/null +++ b/graph/README.md @@ -0,0 +1,15 @@ +# Gonum Graph [![Build Status](https://travis-ci.org/gonum/graph.svg?branch=master)](https://travis-ci.org/gonum/graph) [![Coverage Status](https://coveralls.io/repos/gonum/graph/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/graph?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/graph?status.svg)](https://godoc.org/github.com/gonum/graph) + +This is a generalized graph package for the Go language. It aims to provide a clean, transparent API for common algorithms on arbitrary graphs such as finding the graph's strongly connected components, dominators, or searces. + +The package is currently in testing, and the API is "semi-stable". The signatures of any functions like AStar are unlikely to change much, but the Graph, Node, and Edge interfaces may change a bit. + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the Gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/graph/community/bisect.go b/graph/community/bisect.go new file mode 100644 index 00000000..ddfdb0a9 --- /dev/null +++ b/graph/community/bisect.go @@ -0,0 +1,248 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "errors" + "fmt" + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" +) + +// Interval is an interval of resolutions with a common score. +type Interval struct { + // Low and High delimit the interval + // such that the interval is [low, high). + Low, High float64 + + // Score is the score of the interval. + Score float64 + + // Reduced is the best scoring + // community membership found for the + // interval. + Reduced +} + +// Reduced is a graph reduction. +type Reduced interface { + // Communities returns the community + // structure of the reduction. + Communities() [][]graph.Node +} + +// Size is a score function that is the reciprocal of the number of communities. +func Size(g ReducedGraph) float64 { return 1 / float64(len(g.Structure())) } + +// Weight is a score function that is the sum of community weights. The concrete +// type of g must be a pointer to a ReducedUndirected or a ReducedDirected, otherwise +// Weight will panic. +func Weight(g ReducedGraph) float64 { + var w float64 + switch g := g.(type) { + case *ReducedUndirected: + for _, n := range g.nodes { + w += n.weight + } + case *ReducedDirected: + for _, n := range g.nodes { + w += n.weight + } + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } + return w +} + +// ModularScore returns a modularized scoring function for Profile based on the +// graph g and the given score function. The effort parameter determines how +// many attempts will be made to get an improved score for any given resolution. +func ModularScore(g graph.Graph, score func(ReducedGraph) float64, effort int, src *rand.Rand) func(float64) (float64, Reduced) { + return func(resolution float64) (float64, Reduced) { + max := math.Inf(-1) + var best Reduced + for i := 0; i < effort; i++ { + r := Modularize(g, resolution, src) + s := score(r) + if s > max { + max = s + best = r + } + } + return max, best + } +} + +// SizeMultiplex is a score function that is the reciprocal of the number of communities. +func SizeMultiplex(g ReducedMultiplex) float64 { return 1 / float64(len(g.Structure())) } + +// WeightMultiplex is a score function that is the sum of community weights. The concrete +// type of g must be pointer to a ReducedUndirectedMultiplex or a ReducedDirectedMultiplex, +// otherwise WeightMultiplex will panic. +func WeightMultiplex(g ReducedMultiplex) float64 { + var w float64 + switch g := g.(type) { + case *ReducedUndirectedMultiplex: + for _, n := range g.nodes { + for _, lw := range n.weights { + w += lw + } + } + case *ReducedDirectedMultiplex: + for _, n := range g.nodes { + for _, lw := range n.weights { + w += lw + } + } + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } + return w +} + +// ModularMultiplexScore returns a modularized scoring function for Profile based +// on the graph g and the given score function. The effort parameter determines how +// many attempts will be made to get an improved score for any given resolution. +func ModularMultiplexScore(g Multiplex, weights []float64, all bool, score func(ReducedMultiplex) float64, effort int, src *rand.Rand) func(float64) (float64, Reduced) { + return func(resolution float64) (float64, Reduced) { + max := math.Inf(-1) + var best Reduced + for i := 0; i < effort; i++ { + r := ModularizeMultiplex(g, weights, []float64{resolution}, all, src) + s := score(r) + if s > max { + max = s + best = r + } + } + return max, best + } +} + +// Profile returns an approximate profile of score values in the resolution domain [low,high) +// at the given granularity. The score is calculated by bisecting calls to fn. If log is true, +// log space bisection is used, otherwise bisection is linear. The function fn should be +// monotonically decreasing in at least 1/grain evaluations. Profile will attempt to detect +// non-monotonicity during the bisection. +// +// Since exact modularity optimization is known to be NP-hard and Profile calls modularization +// routines repeatedly, it is unlikely to return the exact resolution profile. +func Profile(fn func(float64) (float64, Reduced), log bool, grain, low, high float64) (profile []Interval, err error) { + if low >= high { + return nil, errors.New("community: zero or negative width domain") + } + + defer func() { + r := recover() + e, ok := r.(nonDecreasing) + if ok { + err = e + return + } + if r != nil { + panic(r) + } + }() + left, comm := fn(low) + right, _ := fn(high) + for i := 1; i < int(1/grain); i++ { + rt, _ := fn(high) + right = math.Max(right, rt) + } + profile = bisect(fn, log, grain, low, left, high, right, comm) + + // We may have missed some non-monotonicity, + // so merge low score discordant domains into + // their lower resolution neighbours. + return fixUp(profile), nil +} + +type nonDecreasing int + +func (n nonDecreasing) Error() string { + return fmt.Sprintf("community: profile does not reliably monotonically decrease: tried %d times", n) +} + +func bisect(fn func(float64) (float64, Reduced), log bool, grain, low, scoreLow, high, scoreHigh float64, comm Reduced) []Interval { + if low >= high { + panic("community: zero or negative width domain") + } + if math.IsNaN(scoreLow) || math.IsNaN(scoreHigh) { + return nil + } + + // Heuristically determine a reasonable number + // of times to try to get a higher value. + maxIter := int(1 / grain) + + lowComm := comm + for n := 0; scoreLow < scoreHigh; n++ { + if n > maxIter { + panic(nonDecreasing(n)) + } + scoreLow, lowComm = fn(low) + } + + if scoreLow == scoreHigh || tooSmall(low, high, grain, log) { + return []Interval{{Low: low, High: high, Score: scoreLow, Reduced: lowComm}} + } + + var mid float64 + if log { + mid = math.Sqrt(low * high) + } else { + mid = (low + high) / 2 + } + + scoreMid := math.Inf(-1) + var midComm Reduced + for n := 0; scoreMid < scoreHigh; n++ { + if n > maxIter { + panic(nonDecreasing(n)) + } + scoreMid, midComm = fn(mid) + } + + lower := bisect(fn, log, grain, low, scoreLow, mid, scoreMid, lowComm) + higher := bisect(fn, log, grain, mid, scoreMid, high, scoreHigh, midComm) + for n := 0; lower[len(lower)-1].Score < higher[0].Score; n++ { + if n > maxIter { + panic(nonDecreasing(n)) + } + lower[len(lower)-1].Score, lower[len(lower)-1].Reduced = fn(low) + } + + if lower[len(lower)-1].Score == higher[0].Score { + higher[0].Low = lower[len(lower)-1].Low + lower = lower[:len(lower)-1] + if len(lower) == 0 { + return higher + } + } + return append(lower, higher...) +} + +// fixUp non-monotonically decreasing interval scores. +func fixUp(profile []Interval) []Interval { + max := profile[len(profile)-1].Score + for i := len(profile) - 2; i >= 0; i-- { + if profile[i].Score > max { + max = profile[i].Score + continue + } + profile[i+1].Low = profile[i].Low + profile = append(profile[:i], profile[i+1:]...) + } + return profile +} + +func tooSmall(low, high, grain float64, log bool) bool { + if log { + return math.Log(high/low) < grain + } + return high-low < grain +} diff --git a/graph/community/bisect_test.go b/graph/community/bisect_test.go new file mode 100644 index 00000000..210ab7f2 --- /dev/null +++ b/graph/community/bisect_test.go @@ -0,0 +1,269 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "fmt" + "log" + "sort" + "testing" + + "gonum.org/v1/gonum/graph/internal/ordered" + + "gonum.org/v1/gonum/graph/simple" +) + +func ExampleProfile_simple() { + // Create dumbell graph: + // + // 0 4 + // |\ /| + // | 2 - 3 | + // |/ \| + // 1 5 + // + g := simple.NewUndirectedGraph(0, 0) + for u, e := range smallDumbell { + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + // Get the profile of internal node weight for resolutions + // between 0.1 and 10 using logarithmic bisection. + p, err := Profile(ModularScore(g, Weight, 10, nil), true, 1e-3, 0.1, 10) + if err != nil { + log.Fatal(err) + } + + // Print out each step with communities ordered. + for _, d := range p { + comm := d.Communities() + for _, c := range comm { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(comm)) + fmt.Printf("Low:%.2v High:%.2v Score:%v Communities:%v Q=%.3v\n", + d.Low, d.High, d.Score, comm, Q(g, comm, d.Low)) + } + + // Output: + // Low:0.1 High:0.29 Score:14 Communities:[[0 1 2 3 4 5]] Q=0.9 + // Low:0.29 High:2.3 Score:12 Communities:[[0 1 2] [3 4 5]] Q=0.714 + // Low:2.3 High:3.5 Score:4 Communities:[[0 1] [2] [3] [4 5]] Q=-0.31 + // Low:3.5 High:10 Score:0 Communities:[[0] [1] [2] [3] [4] [5]] Q=-0.607 +} + +var friends, enemies *simple.UndirectedGraph + +func init() { + friends = simple.NewUndirectedGraph(0, 0) + for u, e := range middleEast.friends { + // Ensure unconnected nodes are included. + if !friends.Has(simple.Node(u)) { + friends.AddNode(simple.Node(u)) + } + for v := range e { + friends.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + enemies = simple.NewUndirectedGraph(0, 0) + for u, e := range middleEast.enemies { + // Ensure unconnected nodes are included. + if !enemies.Has(simple.Node(u)) { + enemies.AddNode(simple.Node(u)) + } + for v := range e { + enemies.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: -1}) + } + } +} + +func ExampleProfile_multiplex() { + // The undirected graphs, friends and enemies, are the political relationships + // in the Middle East as described in the Slate article: + // http://www.slate.com/blogs/the_world_/2014/07/17/the_middle_east_friendship_chart.html + g, err := NewUndirectedLayers(friends, enemies) + if err != nil { + log.Fatal(err) + } + weights := []float64{1, -1} + + // Get the profile of internal node weight for resolutions + // between 0.1 and 10 using logarithmic bisection. + p, err := Profile(ModularMultiplexScore(g, weights, true, WeightMultiplex, 10, nil), true, 1e-3, 0.1, 10) + if err != nil { + log.Fatal(err) + } + + // Print out each step with communities ordered. + for _, d := range p { + comm := d.Communities() + for _, c := range comm { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(comm)) + fmt.Printf("Low:%.2v High:%.2v Score:%v Communities:%v Q=%.3v\n", + d.Low, d.High, d.Score, comm, QMultiplex(g, comm, weights, []float64{d.Low})) + } + + // Output: + // Low:0.1 High:0.72 Score:26 Communities:[[0] [1 7 9 12] [2 8 11] [3 4 5 10] [6]] Q=[24.7 1.97] + // Low:0.72 High:1.1 Score:24 Communities:[[0 6] [1 7 9 12] [2 8 11] [3 4 5 10]] Q=[16.9 14.1] + // Low:1.1 High:1.2 Score:18 Communities:[[0 2 6 11] [1 7 9 12] [3 4 5 8 10]] Q=[9.16 25.1] + // Low:1.2 High:1.6 Score:10 Communities:[[0 3 4 5 6 10] [1 7 9 12] [2 8 11]] Q=[11.4 24.1] + // Low:1.6 High:1.6 Score:8 Communities:[[0 1 6 7 9 12] [2 8 11] [3 4 5 10]] Q=[5.56 39.8] + // Low:1.6 High:1.8 Score:2 Communities:[[0 2 3 4 5 6 10] [1 7 8 9 11 12]] Q=[-1.82 48.6] + // Low:1.8 High:2.3 Score:-6 Communities:[[0 2 3 4 5 6 8 10 11] [1 7 9 12]] Q=[-5 57.5] + // Low:2.3 High:2.4 Score:-10 Communities:[[0 1 2 6 7 8 9 11 12] [3 4 5 10]] Q=[-11.2 79] + // Low:2.4 High:4.3 Score:-52 Communities:[[0 1 2 3 4 5 6 7 8 9 10 11 12]] Q=[-46.1 117] + // Low:4.3 High:10 Score:-54 Communities:[[0 1 2 3 4 6 7 8 9 10 11 12] [5]] Q=[-82 254] +} + +func TestProfileUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + fn := ModularScore(g, Weight, 10, nil) + p, err := Profile(fn, true, 1e-3, 0.1, 10) + if err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + + const tries = 1000 + for i, d := range p { + var score float64 + for i := 0; i < tries; i++ { + score, _ = fn(d.Low) + if score >= d.Score { + break + } + } + if score < d.Score { + t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score) + } + if i != 0 && d.Score >= p[i-1].Score { + t.Errorf("%s: not monotonically decreasing: ", test.name, p[i-1], d) + } + } + } +} + +func TestProfileDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + fn := ModularScore(g, Weight, 10, nil) + p, err := Profile(fn, true, 1e-3, 0.1, 10) + if err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + + const tries = 1000 + for i, d := range p { + var score float64 + for i := 0; i < tries; i++ { + score, _ = fn(d.Low) + if score >= d.Score { + break + } + } + if score < d.Score { + t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score) + } + if i != 0 && d.Score >= p[i-1].Score { + t.Errorf("%s: not monotonically decreasing: ", test.name, p[i-1], d) + } + } + } +} + +func TestProfileUndirectedMultiplex(t *testing.T) { + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + const all = true + + fn := ModularMultiplexScore(g, weights, all, WeightMultiplex, 10, nil) + p, err := Profile(fn, true, 1e-3, 0.1, 10) + if err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + + const tries = 1000 + for i, d := range p { + var score float64 + for i := 0; i < tries; i++ { + score, _ = fn(d.Low) + if score >= d.Score { + break + } + } + if score < d.Score { + t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score) + } + if i != 0 && d.Score >= p[i-1].Score { + t.Errorf("%s: not monotonically decreasing: ", test.name, p[i-1], d) + } + } + } +} + +func TestProfileDirectedMultiplex(t *testing.T) { + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + const all = true + + fn := ModularMultiplexScore(g, weights, all, WeightMultiplex, 10, nil) + p, err := Profile(fn, true, 1e-3, 0.1, 10) + if err != nil { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + + const tries = 1000 + for i, d := range p { + var score float64 + for i := 0; i < tries; i++ { + score, _ = fn(d.Low) + if score >= d.Score { + break + } + } + if score < d.Score { + t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score) + } + if i != 0 && d.Score >= p[i-1].Score { + t.Errorf("%s: not monotonically decreasing: ", test.name, p[i-1], d) + } + } + } +} diff --git a/graph/community/louvain.tex b/graph/community/louvain.tex new file mode 100644 index 00000000..046c02ba --- /dev/null +++ b/graph/community/louvain.tex @@ -0,0 +1,466 @@ +% Copyright ©2015 The gonum Authors. All rights reserved. +% Use of this source code is governed by a BSD-style +% license that can be found in the LICENSE file. + +\documentclass{article} + +\usepackage{amsmath,amsfonts} +\usepackage[margin=4cm]{geometry} + +\title{Louvain algorithm for undirected and directed graphs} +\author{The {\tt gonum} Authors} + +\begin{document} + +\maketitle + +The algorithm attempts to find communities (highly connected sub-graphs), +and it does this by minimising the modularity function +\begin{equation} + Q(c) = \frac{1}{2m}\sum_i\sum_j\left[ A_{ij} - \gamma \frac{k_ik_j}{2m} \right] \delta_{ij}(c), +\end{equation} +where $c$ is a partition of nodes into subsets or communities, +$A_{ij}$ is the edge weight between nodes $i$ and $j$, +$\gamma$ is a tuning parameter, +\begin{equation} +m = \frac{1}{2}\sum_i\sum_jA_{ij}, +\end{equation} +\begin{equation} +k_i = \sum_j{A_{ij}}, +\end{equation} +and +\begin{equation} + \delta_{ij}(c) = \left \{ \begin{array}{ll} + 1 & \text{if} \quad c(i) = c(j) \\ + 0 & \text{otherwise} \end{array} \right .. +\end{equation} +Here $c(i)$ denotes the community to which node $i$ belongs +in the partitioning $c$. + +The algorithm finds a hierarchical community structure by iterating +between two phases: +\begin{enumerate} + \item Find a set of communities that minimise $Q$. + \item Construct a new graph, whose nodes are the communities + found in the preceding phase one step. +\end{enumerate} +Each iteration of these two phases is called a `pass'. +In this way, the algorithm obtains a nested community structure, +where at each level $Q$ is minimised for the relevant graph. +We consider this process in more detail, in particular looking +at phase one first in the first pass, when each node is a single +node, and then how this generalises to later passes when each node +is a community. + +\section{Undirected Graphs} + +\subsection{Initial Pass} +\label{sec:initialPass} + +The initial pass is simple as the initial pass uses the original graph, +and in all following passes graphs constructed in the previous pass's +phase two are used. +Here we will consider this initial simple formulation for phase one, and +in Section~\ref{sec:laterPasses} we consider how this generalises for +passes two and onwards. +Phase one works by initially allocating each node to a separate community, +and then iterating through each node $a$ and checking if moving it into +a different community $\beta$ will reduce $Q$. +If there are possible moves that will reduce $Q$, $a$ is moved into the +the community which will generate the largest reduction in $Q$. +This process is continued until there are no moves left to reduce $Q$ +further, meaning a local minimum for $Q$ has been achieved. +Then the algorithm moves to phase two (constructing a new graph where +each node in the new graph is a community in the old graph). + +Note that we assume the original graph to be simple and undirected. +First, we introduce some notation that will be useful: +Let $c(i)$ denote the community to which node $i$ belongs, +and let $\alpha$ be the community that the node $a$ mentioned above +belongs to, i.e., $\alpha = c_a$. +Then we define +\newcommand{\Stot}[1]{\Sigma_{\text{tot}}^{#1}} +\begin{equation} + \Stot{\alpha} = \sum_{i \in \alpha}\sum_{j}A_{ij} = \sum_{i \in \alpha}k_i, +\end{equation} +\newcommand{\kin}[2]{k_{#1}^{#2}} +\begin{equation} + \kin{i}{\alpha} = \sum_{j \in \alpha}A_{ij}, +\end{equation} +and +\newcommand{\Sin}[1]{\Sigma_{\text{in}}^{#1}} +\begin{equation} + \Sin{\alpha} = \sum_{i \in \alpha}\sum_{j \in \alpha}A_{ij} = \sum_{i \in \alpha}\kin{i}{\alpha}. +\end{equation} + +We are interested in how $Q$ will change if we move a node $a$ from its +current community $\alpha$, to a new community $\beta$. +This will have two effects, it will remove the terms from $Q$ +related to $a$ in $\alpha$, which we will call $Q^-$ and it will add terms +related to $a$ in $\beta$, which we will call $Q^+$. +The total change in $Q$ caused by the movement of $a$ from $\alpha$ to $\beta$ is +\begin{equation} + \Delta Q = Q^{+} - Q^{-}, +\end{equation} +where +\begin{align*} +Q^- &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2\sum_{i \in \alpha, \, i \neq a} \left( A_{ia} - \gamma \frac{k_ik_a}{2m} \right) \right] \\ + &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2 \left( \kin{a}{\alpha} -A_{aa}\right) - \gamma \frac{2k_a}{2m}\sum_{i \in \alpha, \, i \neq a} k_i \right] \\ + &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2 \left( \kin{a}{\alpha} -A_{aa}\right) - \gamma \frac{2k_a}{2m}\left( \Stot{\alpha} - k_a \right) \right], \\ +\end{align*} +and +\begin{align*} +Q^+ &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2\sum_{i \in \beta} \left( A_{ia} - \gamma \frac{k_ik_a}{2m} \right) \right] \\ + &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2\kin{a}{\beta} - \gamma \frac{2k_a}{2m}\sum_{i \in \beta} k_i \right] \\ + &= \frac{1}{2m}\left[ \left( A_{aa} - \gamma \frac{k_a^2}{2m} \right) ++ 2\kin{a}{\beta} - \gamma \frac{2k_a\Stot{\beta}}{2m} \right]. \\ +\end{align*} +The first term in both these expressions ($Q^-$ and $Q^+$) is the same, and so cancels: +\begin{equation} +\Delta Q = \frac{1}{2m}\left[ \left( 2\kin{a}{\beta} - \gamma \frac{2k_a\Stot{\beta}}{2m} \right) + - \left( 2 \left( \kin{a}{\alpha} -A_{aa}\right) - \gamma \frac{2k_a}{2m}\left( \Stot{\alpha} - k_a \right) \right) \right]. +\end{equation} + +\subsection{Later Passes} +\label{sec:laterPasses} + +In phase two a `meta-graph' is constructed where nodes correspond to +the communities found in the preceding phase one step, and edge weight +between two such communities (nodes, in the meta-graph) +$\alpha$ and $\beta$ are defined to be +\begin{equation} + A_{\alpha \beta}^* = \sum_{i \in \alpha}\sum_{j \in \beta}A_{ij}. + \label{eqn:Aij*} +\end{equation} +Note that $i$ and $j$ refer to nodes in the original graph, not nodes +in the previous graph, and so holds any meta-graph, not just the first. +Also note that this definition of $A^*_{\alpha \beta}$ allows for +$A^*_{\alpha \alpha}$ to be non-zero as +\begin{equation} +A_{\alpha \alpha}^* = \sum_{i \in \alpha}\sum_{j \in \alpha}A_{ij} = \Sin{\alpha}. +\end{equation} + +In this newly constructed graph, $\alpha$ and $\beta$ are nodes, but +also refer to communities (sets of nodes) in the original graph, and I +use these two interpretations interchangeably. +This should be the only ambiguous bit of notation in this document, I hope. + +The results of Section~\ref{sec:initialPass} generalise to these meta-graphs, +and the generalised results mirror those of Section~\ref{sec:initialPass} closely +-- I distinguish the new results from those of Section~\ref{sec:initialPass} by a +superscript $*$. +I use $i$ and $j$ to denote nodes of the original graph as in Section~\ref{sec:initialPass}, +and use $z$ and $w$ to denote nodes of the meta-graph (communities of the original). +I use analogous notation to Section~\ref{sec:initialPass}, $c^*(z)$, to +denote the community to which node $z$ of the meta-graph belongs, +and let $\mathfrak{a}$ be the community that the node $\alpha$ belongs to +($c^*(\alpha) = \mathfrak{a}$), i.e. +\begin{equation} + \mathfrak{a} = \{z | c^*(z) = c^*(\alpha) \}. +\end{equation} + +Given this notation, we can observe that +\begin{equation} +m^* = \frac{1}{2}\sum_{z}\sum_{w}{A_{zw}^*} = \frac{1}{2}\sum_{z}\sum_{w}{\sum_{i \in z}\sum_{j \in w}A_{ij}} = \frac{1}{2}\sum_i\sum_jA_{ij} = m, +\end{equation} +\begin{equation} +k_{z}^* = \sum_{w}{A_{zw}^*} = \sum_{w}{\sum_{i \in z}\sum_{j \in w}A_{ij}} = \sum_{i \in z}\sum_{j}A_{ij} = \Stot{z}, +\end{equation} +\begin{equation} + \Stot{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w}A_{zw}^* = \sum_{z \in \mathfrak{a}}k_z^* = \sum_{z \in \mathfrak{a}}\Stot{z}, +\end{equation} +\begin{equation} + \kin{z}{\mathfrak{a} *} = \sum_{w \in \mathfrak{a}}{A_{zw}^*} = \sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}A_{ij}}, +\end{equation} +and +\begin{equation} +\Sin{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w \in \mathfrak{a}}A_{zw}^* = \sum_{z \in \mathfrak{a}}\kin{z}{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}A_{ij}}. + %\label{eqn:Sin} +\end{equation} + +If we let $\mathfrak{b}$ denote the community to which we are considering moving $\alpha$, +then the expression for $\Delta Q$ from Section~\ref{sec:initialPass} trivially generalises to +\begin{equation} +\Delta Q = \frac{1}{2m}\left[ \left( 2 \kin{\alpha}{\mathfrak{b} *} - \gamma \frac{2k_{\alpha}^*\Stot{\mathfrak{b} *}}{2m} \right) + - \left( 2\left( \kin{\alpha}{\mathfrak{a} *} - A_{\alpha \alpha}^* \right) - \gamma \frac{2k_{\alpha}^*}{2m} \left( \Stot{\mathfrak{a} *} - k_{\alpha}^* \right ) \right) \right] \\ +\end{equation} + +\section{Directed Graphs} +\label{sec:directedGraphs} + +It is of interest to consider how this generalises to directed graphs. +If we are to treat incoming and outgoing nodes equally, there are several +thoughts on how to extend the algorithm to directed graphs, of which we +will explore three: +\begin{itemize} + \item Construct an undirected graph first, and then use the undirected case. + \item Generalise the expressions from the undirected case to the directed case, + we will consider two different suggestions for such generalisations. +\end{itemize} +We will show that one of the two `generalisation of expressions' approaches is +equivalent to constructing an undirected graph, and the other is not. + +\subsection{Construction of an undirected graph} +A simple approach to generalising to directed graphs is to construct +an undirected graph with edge weights +\begin{equation} +A_{ij} = B_{ij} + B_{ji}, +\label{eqn:undirectedAB} +\end{equation} +and simply use the undirected algorithm. +Another suggestion is to average the directed edges to make +an undirected graph, i.e. to use a directed graph with edge weights +\begin{equation} +A_{ij} = \frac{B_{ij} + B_{ji}}{2}. +\end{equation} +This raises an important question: does scaling all edge weights across +the entire graph by a constant affect the results of the algorithm? +Hopefully not, but worth checking. +We can follow this through the results for the undirected graph by +substituting $A_{ij}^{(1)} = pA_{ij}$, $p \in \mathbb{R}$, and +distinguishing the new expressions by a superscript ${(1)}$. These +new expressions are: +\begin{equation} +m^{(1)} = \frac{1}{2}\sum_i\sum_jpA_{ij} = p\frac{1}{2}\sum_i\sum_j A_{ij} = pm , +\end{equation} +\begin{equation} +k_i^{(1)} = \sum_j{pA_{ij}} = p\sum_j{A_{ij}} = pk_i, +\end{equation} +and so +\begin{align*} + Q^{(1)}(c) &= \frac{1}{2pm}\sum_i\sum_j\left[ pA_{ij} - \gamma \frac{pk_ipk_j}{2pm} \right] \delta_{ij}(c) \\ + &= \frac{1}{2m}\sum_i\sum_j\left[ A_{ij} - \gamma \frac{k_ik_j}{2m} \right] \delta_{ij}(c) \\ + &= Q(c) +\end{align*} +Note that as we have shown $Q^{(1)} = Q$ there is no need to go into the remainder of the terms +involved in the algorithm, as they all derive from $Q$. + +\subsection{First generalisation of expressions approach} + +One suggested extension to directed graphs is to modify the expressions +involved by adding the `from' case and the `to' case for each term. +If we let $B_{ij}$ be the edge weight between nodes $i$ and $j$ in +the directed graph, and distinguishing these extended expressions by +a superscript $(2)$, the extended expressions become: +\begin{equation} +m^{(2)} = \frac{1}{2}\left ( \sum_i\sum_jB_{ij} + \sum_i\sum_jB_{ji}\right) = \frac{1}{2}\sum_i\sum_j \left( B_{ij} + B_{ji} \right) , +\end{equation} +\begin{equation} +k_i^{(2)} = \sum_jB_{ij} + \sum_jB_{ji} = \sum_j{\left( B_{ij} + B_{ji} \right)}, +\end{equation} +and similarly +\begin{equation} + Q^{(2)}(c) = \frac{1}{2m}\sum_i\sum_j\left[ \left( B_{ij} + B_{ji} \right) - \gamma \frac{k_i^{(2)}k_j^{(2)}}{2m} \right] \delta_{ij}(c). +\end{equation} + +Note how this is equivalent to the construction of an undirected graph as +per Equation~(\ref{eqn:undirectedAB}). Similarly to above, +there is no need to go into the remainder of the terms +involved in the algorithm, as they all derive from $Q$. + + +\subsection{Second generalisation of expressions approach} + +Another approach to generalising the expressions to the +directed case, that still treats incoming and outgoing edges +as equally important, is to propose an alternative modularity +expression: +\newcommand{\dkin}[1]{k_{#1}^{\text{in}}} +\newcommand{\dkout}[1]{k_{#1}^{\text{out}}} +\begin{equation} +Q^{(3)}(c) = \frac{1}{2m}\sum_i\sum_j\left[ 2B_{ij} - 2\gamma \frac{\dkin{i}\dkout{j}}{2m} \right] \delta_{ij}(c), \\ +\end{equation} +where +\begin{equation} +\dkout{i} = \sum_j{B_{ij}} +\quad \quad \text{and} \quad \quad +\dkin{i} = \sum_j{B_{ji}}, +\end{equation} +so $k_i^{(2)} = \dkin{i} + \dkout{i}$. +Note I leave the factor of two in the expression for $Q^{(3)}$ so that it +remains as comparable to that for $Q^{(2)}$ as possible. +There is no need for alternative $m$, as it will still be the same as above. +$Q^{(3)}$ will differ from $Q^{(2)}$ in two ways. +Firstly, as $k_i^{(2)} = \dkin{i} + \dkout{i}$, +\begin{align*} +\sum_i\sum_j k_i^{(2)} k_j^{(2)} \delta_{ij}(c) &= \sum_i\sum_j (\dkin{i} + \dkout{i}) (\dkin{j} + \dkout{j}) \delta_{ij}(c) \\ + &= \sum_i\sum_j \left[ (\dkin{i}\dkin{j} + \dkout{i}\dkout{j}) + (\dkin{i}\dkout{j} + \dkin{j}\dkout{i}) \right] \delta_{ij}(c). \\ + &= \sum_i\sum_j \left[ (\dkin{i}\dkin{j} + \dkout{i}\dkout{j}) + 2\dkin{i}\dkout{j} \right] \delta_{ij}(c), \\ +\end{align*} +and similarly, +\begin{equation} +\sum_i\sum_j \left( B_{ij} + B_{ji} \right) \delta_{ij}(c) = 2\sum_i\sum_j B_{ij} \delta_{ij}(c). +\end{equation} +From these two expressions, we can see that +\begin{equation} +Q^{(3)} - Q^{(2)} = \frac{1}{2m}\sum_i\sum_j \gamma \frac{\dkin{i}\dkin{j} + \dkout{i}\dkout{j}}{2m} \delta_{ij}(c). +\end{equation} + + +\section{Directed Graphs in more detail} +\label{sec:directedGraphsDetail} + +In Section \ref{sec:directedGraphs} we essentially showed three +things: +\begin{itemize} + \item How an undirected graph could be constructed from a directed + graph, thereby allowing the undirected algorithm to be used for + directed graphs. + \item How scaling all edge weights by a non-zero constant would not + affect the modularity function. + \item An alternative approach to extending the algorithm to + directed graphs that is not equivalent to first reducing it + to an undirected graph. +\end{itemize} +It is this third point that we will explore here. +Analogously to Sections \ref{sec:initialPass} and \ref{sec:laterPasses} we will +break this up into the initial pass and the later passes. + +\subsection{Initial pass} +\label{sec:initialPassDirected} + +Continuing with the notation of Section \ref{sec:initialPass}, in which +$c(i)$ denotes the community to which node $i$ belongs, +and $\alpha = c(a)$, we define +\newcommand{\dinStot}[1]{\Sigma_{\text{tot}}^{\text{in}(#1)}} +\newcommand{\doutStot}[1]{\Sigma_{\text{tot}}^{\text{out}(#1)}} +\begin{equation} + \doutStot{\alpha} = \sum_{i \in \alpha}\sum_{j}B_{ij} = \sum_{i \in \alpha}\dkout{i} + \quad \quad \text{and} \quad \quad + \dinStot{\alpha} = \sum_{i \in \alpha}\sum_{j}B_{ji} = \sum_{i \in \alpha}\dkin{i}, +\end{equation} +\newcommand{\dinkin}[2]{k_{#1}^{\text{in}(#2)}} +\newcommand{\doutkin}[2]{k_{#1}^{\text{out}(#2)}} +\begin{equation} + \doutkin{i}{\alpha} = \sum_{j \in \alpha}B_{ij} + \quad \quad \text{and} \quad \quad + \dinkin{i}{\alpha} = \sum_{j \in \alpha}B_{ji}, +\end{equation} +and we will entertain one more ambiguous notation choice: +%\newcommand{\Sin}[1]{\Sigma_{\text{in}}^{#1}} +\begin{equation} + \Sin{\alpha} = \sum_{i \in \alpha}\sum_{j \in \alpha}B_{ij} = \sum_{i \in \alpha}\doutkin{i}{\alpha} = \sum_{i \in \alpha}\dinkin{i}{\alpha}. +\end{equation} + +Analogously to Section \ref{sec:initialPass}, we are interested in how +$Q^{(3)}$ will change if we move a node $a$ from its +current community $\alpha$, to a new community $\beta$, +and analogously this will have two effects -- it will remove the terms +from $Q^{(3)}$ related to $a$ in $\alpha$, which we will call $Q^{-(3)}$ +and it will add terms related to $a$ in $\beta$, which we will call $Q^{+(3)}$. +The total change in $Q^{(3)}$ caused by the movement of $a$ from $\alpha$ to $\beta$ is +\begin{equation} + \Delta Q^{(3)} = Q^{+(3)} - Q^{-(3)}, +\end{equation} +where +\begin{align*} +Q^{-(3)} &= \frac{1}{2m}\left[ \left( 2B_{aa} - 2\gamma \frac{\dkin{a}\dkout{a}}{2m} \right) ++ \sum_{i \in \alpha, \, i \neq a} \left( 2B_{ia} + 2B_{ai} - 2\gamma \frac{\dkin{i}\dkout{a}}{2m} - 2\gamma \frac{\dkin{a}\dkout{i}}{2m} \right) \right] \\ + &= \frac{1}{2m}\left[ \left( 2B_{aa} - 2\gamma \frac{\dkin{a}\dkout{a}}{2m} \right) ++ 2(\dinkin{a}{\alpha} - B_{aa}) + 2(\doutkin{a}{\alpha} - B_{aa}) \hdots \right . \\ + & \quad \quad \quad \quad \quad \quad \left . +- \frac{2\gamma\dkout{a}}{2m} (\dinStot{\alpha} - \dkin{a}) - \frac{2\gamma\dkin{a}}{2m} (\doutStot{\alpha} - \dkout{a}) \right] \\ +\end{align*} +and +\begin{align*} +Q^{+(3)} &= \frac{1}{2m}\left[ \left( 2B_{aa} - 2\gamma \frac{\dkin{a}\dkout{a}}{2m} \right) ++ \sum_{i \in \beta} \left( 2B_{ia} + 2B_{ai} - 2\gamma \frac{\dkin{i}\dkout{a}}{2m} - 2\gamma \frac{\dkin{a}\dkout{i}}{2m} \right) \right] \\ + &= \frac{1}{2m}\left[ \left( 2B_{aa} - 2\gamma \frac{\dkin{a}\dkout{a}}{2m} \right) ++ 2\dinkin{a}{\beta} + 2\doutkin{a}{\beta} - \frac{2\gamma\dkout{a}}{2m} \dinStot{\beta} - \frac{2\gamma\dkin{a}}{2m} \doutStot{\beta} \right] \\ +\end{align*} +Similarly to Section \ref{sec:initialPass}, the first term in both these expressions is the same, and so cancels, leaving: +\begin{align*} +\Delta Q^{(3)} &= \frac{2}{2m}\left[ +\left( \dinkin{a}{\beta} + \doutkin{a}{\beta} - \frac{\gamma\dkout{a}}{2m} \dinStot{\beta} - \frac{\gamma\dkin{a}}{2m} \doutStot{\beta} \right) \right. \\ +& \hspace{-1cm} +- \left. \left( (\dinkin{a}{\alpha} - B_{aa}) + (\doutkin{a}{\alpha} - B_{aa}) - \frac{\gamma\dkout{a}}{2m} (\dinStot{\alpha} - \dkin{a}) - \frac{\gamma\dkin{a}}{2m} (\doutStot{\alpha} - \dkout{a}) \right) \right] \\ + &= \frac{2}{2m}\left[ (\dinkin{a}{\beta}-\dinkin{a}{\alpha}) + (\doutkin{a}{\beta}-\doutkin{a}{\alpha}) + 2B_{aa} \right. \\ +& \hspace{-1cm} \left. +- \frac{\gamma\dkout{a}}{2m} (\dinStot{\beta}-\dinStot{\alpha}) - \frac{\gamma\dkin{a}}{2m} (\doutStot{\beta} - \doutStot{\alpha}) - \frac{2\gamma\dkin{a}\dkout{a}}{2m} \right] +\end{align*} + + + +\subsection{Later passes} +\label{sec:laterPassesDirected} + +In phase two a `meta-graph' is constructed where nodes correspond to +the communities found in the preceding phase one step, and edge weight +between two such communities (nodes, in the meta-graph) +$\alpha$ and $\beta$ are defined to be +\begin{equation} + B_{\alpha \beta}^* = \sum_{i \in \alpha}\sum_{j \in \beta}B_{ij}. + \label{eqn:Bij*} +\end{equation} +Note that $i$ and $j$ refer to nodes in the original graph, not nodes +in the previous graph, and so holds any meta-graph, not just the first. +Also note that this definition of $B^*_{\alpha \beta}$ allows for +$B^*_{\alpha \alpha}$ to be non-zero, in fact +\begin{equation} +B_{\alpha \alpha}^* = \sum_{i \in \alpha}\sum_{j \in \alpha}B_{ij} = \Sin{\alpha}. +\end{equation} + +In this newly constructed graph, $\alpha$ and $\beta$ are nodes, but +also refer to communities (sets of nodes) in the original graph, and I +use these two interpretations interchangeably, completely analogously to +Section \ref{sec:laterPasses}. + +The results of Section~\ref{sec:initialPassDirected} generalise to these meta-graphs, +and the generalised results mirror those of Section~\ref{sec:initialPassDirected} closely +-- I distinguish the new results from those of Section~\ref{sec:initialPassDirected} by a +superscript $*$. +I use $i$ and $j$ to denote nodes of the original graph as in Sections~\ref{sec:initialPass} +and \ref{sec:initialPassDirected}, +and use $z$ and $w$ to denote nodes of the meta-graph (communities of the original). +I use analogous notation to Section~\ref{sec:initialPass}, $c^*(z)$, to +denote the community to which node $z$ of the meta-graph belongs, +and let $\mathfrak{a}$ be the community that the node $\alpha$ belongs to, +i.e., $\mathfrak{a} = c^*(\alpha) $. + +Given this notation, we get all the same results as in \ref{sec:laterPasses}, but +each split into two cases `out' and `in', separating by direction, essentially, so +\newcommand{\dkinStar}[1]{k_{#1}^{\text{in} *}} +\newcommand{\dkoutStar}[1]{k_{#1}^{\text{out} *}} +\begin{equation} +\dkoutStar{z} = \sum_w{B_{zw}^*} = \sum_w\sum_{i \in z}\sum_{j \in w}B_{ij} = \sum_{i \in z}\sum_jB_{ij} = \doutStot{z}, +\end{equation} +\begin{equation} +\dkinStar{z} = \sum_w{B_{wz}^*} = \sum_w\sum_{i \in z}\sum_{j \in w}B_{ji} = \sum_{i \in z}\sum_jB_{ji} = \dinStot{z}, +\end{equation} +\newcommand{\dinStotStar}[1]{\Sigma_{\text{tot}}^{\text{in}(#1) *}} +\newcommand{\doutStotStar}[1]{\Sigma_{\text{tot}}^{\text{out}(#1) *}} +\begin{equation} + \doutStotStar{\mathfrak{a}} = \sum_{z \in \mathfrak{a}}\sum_{w}B_{zw}^* = \sum_{z \in \mathfrak{a}}\dkoutStar{z} = \sum_{z \in \mathfrak{a}}\doutStot{z}, +\end{equation} +\begin{equation} + \dinStotStar{\mathfrak{a}} = \sum_{z \in \mathfrak{a}}\sum_{w}B_{wz}^* = \sum_{z \in \mathfrak{a}}\dkinStar{z} = \sum_{z \in \mathfrak{a}}\dinStot{z}, +\end{equation} +\newcommand{\dinkinStar}[2]{k_{#1}^{\text{in}(#2) *}} +\newcommand{\doutkinStar}[2]{k_{#1}^{\text{out}(#2) *}} +\begin{equation} + \doutkinStar{z}{\mathfrak{a}} = \sum_{w \in \mathfrak{a}}{B_{zw}^*} = \sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}B_{ij}}, +\end{equation} +\begin{equation} + \dinkinStar{z}{\mathfrak{a}} = \sum_{w \in \mathfrak{a}}{B_{wz}^*} = \sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}B_{ji}}, +\end{equation} +and +\begin{equation} +\Sin{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w \in \mathfrak{a}}A_{zw}^* = \sum_{z \in \mathfrak{a}}\kin{z}{\mathfrak{a} *} = \sum_{z \in \mathfrak{a}}\sum_{w \in \mathfrak{a}}{\sum_{i \in z}\sum_{j \in w}A_{ij}}. + %\label{eqn:Sin} +\end{equation} + +If we let $\mathfrak{b}$ denote the community to which we are considering moving $\alpha$, +then the expression for $\Delta Q$ from Section~\ref{sec:initialPassDirected} simply generalises as +\begin{align*} +\Delta Q^{(3)} &= \frac{2}{2m}\left[ (\dinkinStar{\alpha}{\mathfrak{b}}-\dinkinStar{\alpha}{\mathfrak{a}}) + (\doutkinStar{\alpha}{\mathfrak{b}}-\doutkinStar{\alpha}{\mathfrak{a}}) + 2B_{\alpha\alpha}^* \right. \\ +& \hspace{-1cm} \left. +- \frac{\gamma\dkoutStar{\alpha}}{2m} (\dinStotStar{\mathfrak{b}}-\dinStotStar{\mathfrak{a}}) - \frac{\gamma\dkinStar{\alpha}}{2m} (\doutStotStar{\mathfrak{b}} - \doutStotStar{\mathfrak{a}}) - \frac{2\gamma\dkinStar{\alpha}\dkoutStar{\alpha}}{2m} \right] +\end{align*} + + +\end{document} diff --git a/graph/community/louvain_common.go b/graph/community/louvain_common.go new file mode 100644 index 00000000..a24897af --- /dev/null +++ b/graph/community/louvain_common.go @@ -0,0 +1,377 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package community provides graph community detection functions. +package community + +import ( + "fmt" + "math/rand" + + "gonum.org/v1/gonum/graph" +) + +// Q returns the modularity Q score of the graph g subdivided into the +// given communities at the given resolution. If communities is nil, the +// unclustered modularity score is returned. The resolution parameter +// is γ as defined in Reichardt and Bornholdt doi:10.1103/PhysRevE.74.016110. +// Q will panic if g has any edge with negative edge weight. +// +// If g is undirected, Q is calculated according to +// Q = 1/2m \sum_{ij} [ A_{ij} - (\gamma k_i k_j)/2m ] \delta(c_i,c_j), +// If g is directed, it is calculated according to +// Q = 1/m \sum_{ij} [ A_{ij} - (\gamma k_i^in k_j^out)/m ] \delta(c_i,c_j). +// +// graph.Undirect may be used as a shim to allow calculation of Q for +// directed graphs with the undirected modularity function. +func Q(g graph.Graph, communities [][]graph.Node, resolution float64) float64 { + switch g := g.(type) { + case graph.Undirected: + return qUndirected(g, communities, resolution) + case graph.Directed: + return qDirected(g, communities, resolution) + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } +} + +// ReducedGraph is a modularised graph. +type ReducedGraph interface { + graph.Graph + + // Communities returns the community memberships + // of the nodes in the graph used to generate + // the reduced graph. + Communities() [][]graph.Node + + // Structure returns the community structure of + // the current level of the module clustering. + // Each slice in the returned value recursively + // describes the membership of a community at + // the current level by indexing via the node + // ID into the structure of the non-nil + // ReducedGraph returned by Expanded, or when the + // ReducedGraph is nil, by containing nodes + // from the original input graph. + // + // The returned value should not be mutated. + Structure() [][]graph.Node + + // Expanded returns the next lower level of the + // module clustering or nil if at the lowest level. + // + // The returned ReducedGraph will be the same + // concrete type as the receiver. + Expanded() ReducedGraph +} + +// Modularize returns the hierarchical modularization of g at the given resolution +// using the Louvain algorithm. If src is nil, rand.Intn is used as the random +// generator. Modularize will panic if g has any edge with negative edge weight. +// +// If g is undirected it is modularised to minimise +// Q = 1/2m \sum_{ij} [ A_{ij} - (\gamma k_i k_j)/2m ] \delta(c_i,c_j), +// If g is directed it is modularised to minimise +// Q = 1/m \sum_{ij} [ A_{ij} - (\gamma k_i^in k_j^out)/m ] \delta(c_i,c_j). +// +// The concrete type of the ReducedGraph will be a pointer to either a +// ReducedUndirected or a ReducedDirected depending on the type of g. +// +// graph.Undirect may be used as a shim to allow modularization of +// directed graphs with the undirected modularity function. +func Modularize(g graph.Graph, resolution float64, src *rand.Rand) ReducedGraph { + switch g := g.(type) { + case graph.Undirected: + return louvainUndirected(g, resolution, src) + case graph.Directed: + return louvainDirected(g, resolution, src) + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } +} + +// Multiplex is a multiplex graph. +type Multiplex interface { + // Nodes returns the slice of nodes + // for the multiplex graph. + // All layers must refer to the same + // set of nodes. + Nodes() []graph.Node + + // Depth returns the number of layers + // in the multiplex graph. + Depth() int +} + +// QMultiplex returns the modularity Q score of the multiplex graph layers +// subdivided into the given communities at the given resolutions and weights. Q is +// returned as the vector of weighted Q scores for each layer of the multiplex graph. +// If communities is nil, the unclustered modularity score is returned. +// If weights is nil layers are equally weighted, otherwise the length of +// weights must equal the number of layers. If resolutions is nil, a resolution +// of 1.0 is used for all layers, otherwise either a single element slice may be used +// to specify a global resolution, or the length of resolutions must equal the number +// of layers. The resolution parameter is γ as defined in Reichardt and Bornholdt +// doi:10.1103/PhysRevE.74.016110. +// QMultiplex will panic if the graph has any layer weight-scaled edge with +// negative edge weight. +// +// If g is undirected, Q is calculated according to +// Q_{layer} = w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i k_j)/2m_{layer} ] \delta(c_i,c_j), +// If g is directed, it is calculated according to +// Q_{layer} = w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i^in k_j^out)/m_{layer} ] \delta(c_i,c_j). +// +// Note that Q values for multiplex graphs are not scaled by the total layer edge weight. +// +// graph.Undirect may be used as a shim to allow calculation of Q for +// directed graphs. +func QMultiplex(g Multiplex, communities [][]graph.Node, weights, resolutions []float64) []float64 { + if weights != nil && len(weights) != g.Depth() { + panic("community: weights vector length mismatch") + } + if resolutions != nil && len(resolutions) != 1 && len(resolutions) != g.Depth() { + panic("community: resolutions vector length mismatch") + } + + switch g := g.(type) { + case UndirectedMultiplex: + return qUndirectedMultiplex(g, communities, weights, resolutions) + case DirectedMultiplex: + return qDirectedMultiplex(g, communities, weights, resolutions) + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } +} + +// ReducedMultiplex is a modularised multiplex graph. +type ReducedMultiplex interface { + Multiplex + + // Communities returns the community memberships + // of the nodes in the graph used to generate + // the reduced graph. + Communities() [][]graph.Node + + // Structure returns the community structure of + // the current level of the module clustering. + // Each slice in the returned value recursively + // describes the membership of a community at + // the current level by indexing via the node + // ID into the structure of the non-nil + // ReducedGraph returned by Expanded, or when the + // ReducedGraph is nil, by containing nodes + // from the original input graph. + // + // The returned value should not be mutated. + Structure() [][]graph.Node + + // Expanded returns the next lower level of the + // module clustering or nil if at the lowest level. + // + // The returned ReducedGraph will be the same + // concrete type as the receiver. + Expanded() ReducedMultiplex +} + +// ModularizeMultiplex returns the hierarchical modularization of g at the given resolution +// using the Louvain algorithm. If all is true and g have negatively weighted layers, all +// communities will be searched during the modularization. If src is nil, rand.Intn is +// used as the random generator. ModularizeMultiplex will panic if g has any edge with +// edge weight that does not sign-match the layer weight. +// +// If g is undirected it is modularised to minimise +// Q = \sum w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i k_j)/2m ] \delta(c_i,c_j). +// If g is directed it is modularised to minimise +// Q = \sum w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i^in k_j^out)/m_{layer} ] \delta(c_i,c_j). +// +// The concrete type of the ReducedMultiplex will be a pointer to a +// ReducedUndirectedMultiplex. +// +// graph.Undirect may be used as a shim to allow modularization of +// directed graphs with the undirected modularity function. +func ModularizeMultiplex(g Multiplex, weights, resolutions []float64, all bool, src *rand.Rand) ReducedMultiplex { + if weights != nil && len(weights) != g.Depth() { + panic("community: weights vector length mismatch") + } + if resolutions != nil && len(resolutions) != 1 && len(resolutions) != g.Depth() { + panic("community: resolutions vector length mismatch") + } + + switch g := g.(type) { + case UndirectedMultiplex: + return louvainUndirectedMultiplex(g, weights, resolutions, all, src) + case DirectedMultiplex: + return louvainDirectedMultiplex(g, weights, resolutions, all, src) + default: + panic(fmt.Sprintf("community: invalid graph type: %T", g)) + } +} + +// undirectedEdges is the edge structure of a reduced undirected graph. +type undirectedEdges struct { + // edges and weights is the set + // of edges between nodes. + // weights is keyed such that + // the first element of the key + // is less than the second. + edges [][]int + weights map[[2]int]float64 +} + +// directedEdges is the edge structure of a reduced directed graph. +type directedEdges struct { + // edgesFrom, edgesTo and weights + // is the set of edges between nodes. + edgesFrom [][]int + edgesTo [][]int + weights map[[2]int]float64 +} + +// community is a reduced graph node describing its membership. +type community struct { + id int + + nodes []graph.Node + + weight float64 +} + +func (n community) ID() int { return n.id } + +// edge is a reduced graph edge. +type edge struct { + from, to community + weight float64 +} + +func (e edge) From() graph.Node { return e.from } +func (e edge) To() graph.Node { return e.to } +func (e edge) Weight() float64 { return e.weight } + +// multiplexCommunity is a reduced multiplex graph node describing its membership. +type multiplexCommunity struct { + id int + + nodes []graph.Node + + weights []float64 +} + +func (n multiplexCommunity) ID() int { return n.id } + +// multiplexEdge is a reduced graph edge for a multiplex graph. +type multiplexEdge struct { + from, to multiplexCommunity + weight float64 +} + +func (e multiplexEdge) From() graph.Node { return e.from } +func (e multiplexEdge) To() graph.Node { return e.to } +func (e multiplexEdge) Weight() float64 { return e.weight } + +// commIdx is an index of a node in a community held by a localMover. +type commIdx struct { + community int + node int +} + +// node is defined to avoid an import of .../graph/simple. +type node int + +func (n node) ID() int { return int(n) } + +// minTaker is a set iterator. +type minTaker interface { + TakeMin(p *int) bool +} + +// dense is a dense integer set iterator. +type dense struct { + pos int + n int +} + +// TakeMin mimics intsets.Sparse TakeMin for dense sets. If the dense +// iterator position is less than the iterator size, TakeMin sets *p +// to the the iterator position and increments the position and returns +// true. +// Otherwise, it returns false and *p is undefined. +func (d *dense) TakeMin(p *int) bool { + if d.pos >= d.n { + return false + } + *p = d.pos + d.pos++ + return true +} + +const ( + negativeWeight = "community: unexpected negative edge weight" + positiveWeight = "community: unexpected positive edge weight" +) + +// positiveWeightFuncFor returns a constructed weight function for the +// positively weighted g. +func positiveWeightFuncFor(g graph.Graph) func(x, y graph.Node) float64 { + if wg, ok := g.(graph.Weighter); ok { + return func(x, y graph.Node) float64 { + w, ok := wg.Weight(x, y) + if !ok { + return 0 + } + if w < 0 { + panic(negativeWeight) + } + return w + } + } + return func(x, y graph.Node) float64 { + e := g.Edge(x, y) + if e == nil { + return 0 + } + w := e.Weight() + if w < 0 { + panic(negativeWeight) + } + return w + } +} + +// negativeWeightFuncFor returns a constructed weight function for the +// negatively weighted g. +func negativeWeightFuncFor(g graph.Graph) func(x, y graph.Node) float64 { + if wg, ok := g.(graph.Weighter); ok { + return func(x, y graph.Node) float64 { + w, ok := wg.Weight(x, y) + if !ok { + return 0 + } + if w > 0 { + panic(positiveWeight) + } + return -w + } + } + return func(x, y graph.Node) float64 { + e := g.Edge(x, y) + if e == nil { + return 0 + } + w := e.Weight() + if w > 0 { + panic(positiveWeight) + } + return -w + } +} + +// depth returns max(1, len(weights)). It is used to ensure +// that multiplex community weights are properly initialised. +func depth(weights []float64) int { + if weights == nil { + return 1 + } + return len(weights) +} diff --git a/graph/community/louvain_directed.go b/graph/community/louvain_directed.go new file mode 100644 index 00000000..efcc6d74 --- /dev/null +++ b/graph/community/louvain_directed.go @@ -0,0 +1,633 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "math" + "math/rand" + "sort" + + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +// qDirected returns the modularity Q score of the graph g subdivided into the +// given communities at the given resolution. If communities is nil, the +// unclustered modularity score is returned. The resolution parameter +// is γ as defined in Reichardt and Bornholdt doi:10.1103/PhysRevE.74.016110. +// qDirected will panic if g has any edge with negative edge weight. +// +// Q = 1/m \sum_{ij} [ A_{ij} - (\gamma k_i^in k_j^out)/m ] \delta(c_i,c_j) +// +func qDirected(g graph.Directed, communities [][]graph.Node, resolution float64) float64 { + nodes := g.Nodes() + weight := positiveWeightFuncFor(g) + + // Calculate the total edge weight of the graph + // and the table of penetrating edge weight sums. + var m float64 + k := make(map[int]directedWeights, len(nodes)) + for _, n := range nodes { + var wOut float64 + u := n + for _, v := range g.From(u) { + wOut += weight(u, v) + } + var wIn float64 + v := n + for _, u := range g.To(v) { + wIn += weight(u, v) + } + w := weight(n, n) + m += w + wOut // We only need to count edges once. + k[n.ID()] = directedWeights{out: w + wOut, in: w + wIn} + } + + if communities == nil { + var q float64 + for _, u := range nodes { + kU := k[u.ID()] + q += weight(u, u) - resolution*kU.out*kU.in/m + } + return q / m + } + + var q float64 + for _, c := range communities { + for _, u := range c { + kU := k[u.ID()] + for _, v := range c { + kV := k[v.ID()] + q += weight(u, v) - resolution*kU.out*kV.in/m + } + } + } + return q / m +} + +// louvainDirected returns the hierarchical modularization of g at the given +// resolution using the Louvain algorithm. If src is nil, rand.Intn is used +// as the random generator. louvainDirected will panic if g has any edge with negative +// edge weight. +func louvainDirected(g graph.Directed, resolution float64, src *rand.Rand) ReducedGraph { + // See louvain.tex for a detailed description + // of the algorithm used here. + + c := reduceDirected(g, nil) + rnd := rand.Intn + if src != nil { + rnd = src.Intn + } + for { + l := newDirectedLocalMover(c, c.communities, resolution) + if l == nil { + return c + } + if done := l.localMovingHeuristic(rnd); done { + return c + } + c = reduceDirected(c, l.communities) + } +} + +// ReducedDirected is a directed graph of communities derived from a +// parent graph by reduction. +type ReducedDirected struct { + // nodes is the set of nodes held + // by the graph. In a ReducedDirected + // the node ID is the index into + // nodes. + nodes []community + directedEdges + + // communities is the community + // structure of the graph. + communities [][]graph.Node + + parent *ReducedDirected +} + +var ( + _ graph.Directed = (*ReducedDirected)(nil) + _ graph.Weighter = (*ReducedDirected)(nil) + _ ReducedGraph = (*ReducedUndirected)(nil) +) + +// Communities returns the community memberships of the nodes in the +// graph used to generate the reduced graph. +func (g *ReducedDirected) Communities() [][]graph.Node { + communities := make([][]graph.Node, len(g.communities)) + if g.parent == nil { + for i, members := range g.communities { + comm := make([]graph.Node, len(members)) + for j, n := range members { + nodes := g.nodes[n.ID()].nodes + if len(nodes) != 1 { + panic("community: unexpected number of nodes in base graph community") + } + comm[j] = nodes[0] + } + communities[i] = comm + } + return communities + } + sub := g.parent.Communities() + for i, members := range g.communities { + var comm []graph.Node + for _, n := range members { + comm = append(comm, sub[n.ID()]...) + } + communities[i] = comm + } + return communities +} + +// Structure returns the community structure of the current level of +// the module clustering. The first index of the returned value +// corresponds to the index of the nodes in the next higher level if +// it exists. The returned value should not be mutated. +func (g *ReducedDirected) Structure() [][]graph.Node { + return g.communities +} + +// Expanded returns the next lower level of the module clustering or nil +// if at the lowest level. +func (g *ReducedDirected) Expanded() ReducedGraph { + return g.parent +} + +// reduceDirected returns a reduced graph constructed from g divided +// into the given communities. The communities value is mutated +// by the call to reduceDirected. If communities is nil and g is a +// ReducedDirected, it is returned unaltered. +func reduceDirected(g graph.Directed, communities [][]graph.Node) *ReducedDirected { + if communities == nil { + if r, ok := g.(*ReducedDirected); ok { + return r + } + + nodes := g.Nodes() + // TODO(kortschak) This sort is necessary really only + // for testing. In practice we would not be using the + // community provided by the user for a Q calculation. + // Probably we should use a function to map the + // communities in the test sets to the remapped order. + sort.Sort(ordered.ByID(nodes)) + communities = make([][]graph.Node, len(nodes)) + for i := range nodes { + communities[i] = []graph.Node{node(i)} + } + + weight := positiveWeightFuncFor(g) + r := ReducedDirected{ + nodes: make([]community, len(nodes)), + directedEdges: directedEdges{ + edgesFrom: make([][]int, len(nodes)), + edgesTo: make([][]int, len(nodes)), + weights: make(map[[2]int]float64), + }, + communities: communities, + } + communityOf := make(map[int]int, len(nodes)) + for i, n := range nodes { + r.nodes[i] = community{id: i, nodes: []graph.Node{n}} + communityOf[n.ID()] = i + } + for _, n := range nodes { + id := communityOf[n.ID()] + + var out []int + u := n + for _, v := range g.From(u) { + vid := communityOf[v.ID()] + if vid != id { + out = append(out, vid) + } + r.weights[[2]int{id, vid}] = weight(u, v) + } + r.edgesFrom[id] = out + + var in []int + v := n + for _, u := range g.To(v) { + uid := communityOf[u.ID()] + if uid != id { + in = append(in, uid) + } + r.weights[[2]int{uid, id}] = weight(u, v) + } + r.edgesTo[id] = in + } + return &r + } + + // Remove zero length communities destructively. + var commNodes int + for i := 0; i < len(communities); { + comm := communities[i] + if len(comm) == 0 { + communities[i] = communities[len(communities)-1] + communities[len(communities)-1] = nil + communities = communities[:len(communities)-1] + } else { + commNodes += len(comm) + i++ + } + } + + r := ReducedDirected{ + nodes: make([]community, len(communities)), + directedEdges: directedEdges{ + edgesFrom: make([][]int, len(communities)), + edgesTo: make([][]int, len(communities)), + weights: make(map[[2]int]float64), + }, + } + r.communities = make([][]graph.Node, len(communities)) + for i := range r.communities { + r.communities[i] = []graph.Node{node(i)} + } + if g, ok := g.(*ReducedDirected); ok { + // Make sure we retain the truncated + // community structure. + g.communities = communities + r.parent = g + } + weight := positiveWeightFuncFor(g) + communityOf := make(map[int]int, commNodes) + for i, comm := range communities { + r.nodes[i] = community{id: i, nodes: comm} + for _, n := range comm { + communityOf[n.ID()] = i + } + } + for id, comm := range communities { + var out, in []int + for _, n := range comm { + u := n + for _, v := range comm { + r.nodes[id].weight += weight(u, v) + } + + for _, v := range g.From(u) { + vid := communityOf[v.ID()] + found := false + for _, e := range out { + if e == vid { + found = true + break + } + } + if !found && vid != id { + out = append(out, vid) + } + // Add half weights because the other + // ends of edges are also counted. + r.weights[[2]int{id, vid}] += weight(u, v) / 2 + } + + v := n + for _, u := range g.To(v) { + uid := communityOf[u.ID()] + found := false + for _, e := range in { + if e == uid { + found = true + break + } + } + if !found && uid != id { + in = append(in, uid) + } + // Add half weights because the other + // ends of edges are also counted. + r.weights[[2]int{uid, id}] += weight(u, v) / 2 + } + } + r.edgesFrom[id] = out + r.edgesTo[id] = in + } + return &r +} + +// Has returns whether the node exists within the graph. +func (g *ReducedDirected) Has(n graph.Node) bool { + id := n.ID() + return id >= 0 || id < len(g.nodes) +} + +// Nodes returns all the nodes in the graph. +func (g *ReducedDirected) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + for i := range g.nodes { + nodes[i] = node(i) + } + return nodes +} + +// From returns all nodes in g that can be reached directly from u. +func (g *ReducedDirected) From(u graph.Node) []graph.Node { + out := g.edgesFrom[u.ID()] + nodes := make([]graph.Node, len(out)) + for i, vid := range out { + nodes[i] = g.nodes[vid] + } + return nodes +} + +// To returns all nodes in g that can reach directly to v. +func (g *ReducedDirected) To(v graph.Node) []graph.Node { + in := g.edgesTo[v.ID()] + nodes := make([]graph.Node, len(in)) + for i, uid := range in { + nodes[i] = g.nodes[uid] + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *ReducedDirected) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if xid == yid { + return false + } + _, ok := g.weights[[2]int{xid, yid}] + if ok { + return true + } + _, ok = g.weights[[2]int{yid, xid}] + return ok +} + +// HasEdgeFromTo returns whether an edge exists from node u to v. +func (g *ReducedDirected) HasEdgeFromTo(u, v graph.Node) bool { + uid := u.ID() + vid := v.ID() + if uid == vid { + return false + } + _, ok := g.weights[[2]int{uid, vid}] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *ReducedDirected) Edge(u, v graph.Node) graph.Edge { + uid := u.ID() + vid := v.ID() + w, ok := g.weights[[2]int{uid, vid}] + if !ok { + return nil + } + return edge{from: g.nodes[uid], to: g.nodes[vid], weight: w} +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *ReducedDirected) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.nodes[xid].weight, true + } + w, ok = g.weights[[2]int{xid, yid}] + return w, ok +} + +// directedLocalMover is a step in graph modularity optimization. +type directedLocalMover struct { + g *ReducedDirected + + // nodes is the set of working nodes. + nodes []graph.Node + // edgeWeightsOf is the weighted degree + // of each node indexed by ID. + edgeWeightsOf []directedWeights + + // m is the total sum of edge + // weights in g. + m float64 + + // weight is the weight function + // provided by g or a function + // that returns the Weight value + // of the non-nil edge between x + // and y. + weight func(x, y graph.Node) float64 + + // communities is the current + // division of g. + communities [][]graph.Node + // memberships is a mapping between + // node ID and community membership. + memberships []int + + // resolution is the Reichardt and + // Bornholdt γ parameter as defined + // in doi:10.1103/PhysRevE.74.016110. + resolution float64 + + // moved indicates that a call to + // move has been made since the last + // call to shuffle. + moved bool + + // changed indicates that a move + // has been made since the creation + // of the local mover. + changed bool +} + +type directedWeights struct { + out, in float64 +} + +// newDirectedLocalMover returns a new directedLocalMover initialized with +// the graph g, a set of communities and a modularity resolution parameter. +// The node IDs of g must be contiguous in [0,n) where n is the number of +// nodes. +// If g has a zero edge weight sum, nil is returned. +func newDirectedLocalMover(g *ReducedDirected, communities [][]graph.Node, resolution float64) *directedLocalMover { + nodes := g.Nodes() + l := directedLocalMover{ + g: g, + nodes: nodes, + edgeWeightsOf: make([]directedWeights, len(nodes)), + communities: communities, + memberships: make([]int, len(nodes)), + resolution: resolution, + weight: positiveWeightFuncFor(g), + } + + // Calculate the total edge weight of the graph + // and degree weights for each node. + for _, n := range l.nodes { + u := n + var wOut float64 + for _, v := range g.From(u) { + wOut += l.weight(u, v) + } + + v := n + var wIn float64 + for _, u := range g.To(v) { + wIn += l.weight(u, v) + } + + w := l.weight(n, n) + l.edgeWeightsOf[n.ID()] = directedWeights{out: w + wOut, in: w + wIn} + l.m += w + wOut + } + + // Assign membership mappings. + for i, c := range communities { + for _, n := range c { + l.memberships[n.ID()] = i + } + } + + return &l +} + +// localMovingHeuristic performs the Louvain local moving heuristic until +// no further moves can be made. It returns a boolean indicating that the +// directedLocalMover has not made any improvement to the community structure and +// so the Louvain algorithm is done. +func (l *directedLocalMover) localMovingHeuristic(rnd func(int) int) (done bool) { + for { + l.shuffle(rnd) + for _, n := range l.nodes { + dQ, dst, src := l.deltaQ(n) + if dQ <= 0 { + continue + } + l.move(dst, src) + } + if !l.moved { + return !l.changed + } + } +} + +// shuffle performs a Fisher-Yates shuffle on the nodes held by the +// directedLocalMover using the random source rnd which should return an +// integer in the range [0,n). +func (l *directedLocalMover) shuffle(rnd func(n int) int) { + l.moved = false + for i := range l.nodes[:len(l.nodes)-1] { + j := i + rnd(len(l.nodes)-i) + l.nodes[i], l.nodes[j] = l.nodes[j], l.nodes[i] + } +} + +// move moves the node at src to the community at dst. +func (l *directedLocalMover) move(dst int, src commIdx) { + l.moved = true + l.changed = true + + srcComm := l.communities[src.community] + n := srcComm[src.node] + + l.memberships[n.ID()] = dst + + l.communities[dst] = append(l.communities[dst], n) + srcComm[src.node], srcComm[len(srcComm)-1] = srcComm[len(srcComm)-1], nil + l.communities[src.community] = srcComm[:len(srcComm)-1] +} + +// deltaQ returns the highest gain in modularity attainable by moving +// n from its current community to another connected community and +// the index of the chosen destination. The index into the directedLocalMover's +// communities field is returned in src if n is in communities. +func (l *directedLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, src commIdx) { + id := n.ID() + + a_aa := l.weight(n, n) + k_a := l.edgeWeightsOf[id] + m := l.m + gamma := l.resolution + + // Find communites connected to n. + var connected intsets.Sparse + // The following for loop is equivalent to: + // + // for _, v := range l.g.From(n) { + // connected.Insert(l.memberships[v.ID()]) + // } + // for _, v := range l.g.To(n) { + // connected.Insert(l.memberships[v.ID()]) + // } + // + // This is done to avoid two allocations. + for _, vid := range l.g.edgesFrom[id] { + connected.Insert(l.memberships[vid]) + } + for _, vid := range l.g.edgesTo[id] { + connected.Insert(l.memberships[vid]) + } + // Insert the node's own community. + connected.Insert(l.memberships[id]) + + // Calculate the highest modularity gain + // from moving into another community and + // keep the index of that community. + var dQremove float64 + dQadd, dst, src := math.Inf(-1), -1, commIdx{-1, -1} + var i int + for connected.TakeMin(&i) { + c := l.communities[i] + var k_aC, sigma_totC directedWeights // C is a substitution for ^𝛼 or ^𝛽. + var removal bool + for j, u := range c { + uid := u.ID() + if uid == id { + if src.community != -1 { + panic("community: multiple sources") + } + src = commIdx{i, j} + removal = true + } + + k_aC.in += l.weight(u, n) + k_aC.out += l.weight(n, u) + // sigma_totC could be kept for each community + // and updated for moves, changing the calculation + // of sigma_totC here from O(n_c) to O(1), but + // in practice the time savings do not appear + // to be compelling and do not make up for the + // increase in code complexity and space required. + w := l.edgeWeightsOf[uid] + sigma_totC.in += w.in + sigma_totC.out += w.out + } + + // See louvain.tex for a derivation of these equations. + switch { + case removal: + // The community c was the current community, + // so calculate the change due to removal. + dQremove = (k_aC.in /*^𝛼*/ - a_aa) + (k_aC.out /*^𝛼*/ - a_aa) - + gamma*(k_a.in*(sigma_totC.out /*^𝛼*/ -k_a.out)+k_a.out*(sigma_totC.in /*^𝛼*/ -k_a.in))/m + + default: + // Otherwise calculate the change due to an addition + // to c and retain if it is the current best. + dQ := k_aC.in /*^𝛽*/ + k_aC.out /*^𝛽*/ - + gamma*(k_a.in*sigma_totC.out /*^𝛽*/ +k_a.out*sigma_totC.in /*^𝛽*/)/m + + if dQ > dQadd { + dQadd = dQ + dst = i + } + } + } + + return (dQadd - dQremove) / m, dst, src +} diff --git a/graph/community/louvain_directed_multiplex.go b/graph/community/louvain_directed_multiplex.go new file mode 100644 index 00000000..a3d6497f --- /dev/null +++ b/graph/community/louvain_directed_multiplex.go @@ -0,0 +1,880 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "fmt" + "math" + "math/rand" + "sort" + + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +// DirectedMultiplex is a directed multiplex graph. +type DirectedMultiplex interface { + Multiplex + + // Layer returns the lth layer of the + // multiplex graph. + Layer(l int) graph.Directed +} + +// qDirectedMultiplex returns the modularity Q score of the multiplex graph layers +// subdivided into the given communities at the given resolutions and weights. Q is +// returned as the vector of weighted Q scores for each layer of the multiplex graph. +// If communities is nil, the unclustered modularity score is returned. +// If weights is nil layers are equally weighted, otherwise the length of +// weights must equal the number of layers. If resolutions is nil, a resolution +// of 1.0 is used for all layers, otherwise either a single element slice may be used +// to specify a global resolution, or the length of resolutions must equal the number +// of layers. The resolution parameter is γ as defined in Reichardt and Bornholdt +// doi:10.1103/PhysRevE.74.016110. +// qUndirectedMultiplex will panic if the graph has any layer weight-scaled edge with +// negative edge weight. +// +// Q_{layer} = w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i k_j)/2m ] \delta(c_i,c_j) +// +// Note that Q values for multiplex graphs are not scaled by the total layer edge weight. +func qDirectedMultiplex(g DirectedMultiplex, communities [][]graph.Node, weights, resolutions []float64) []float64 { + q := make([]float64, g.Depth()) + nodes := g.Nodes() + layerWeight := 1.0 + layerResolution := 1.0 + if len(resolutions) == 1 { + layerResolution = resolutions[0] + } + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + + if weights != nil { + layerWeight = weights[l] + } + if layerWeight == 0 { + continue + } + + if len(resolutions) > 1 { + layerResolution = resolutions[l] + } + + var weight func(x, y graph.Node) float64 + if layerWeight < 0 { + weight = negativeWeightFuncFor(layer) + } else { + weight = positiveWeightFuncFor(layer) + } + + // Calculate the total edge weight of the layer + // and the table of penetrating edge weight sums. + var m float64 + k := make(map[int]directedWeights, len(nodes)) + for _, n := range nodes { + var wOut float64 + u := n + for _, v := range layer.From(u) { + wOut += weight(u, v) + } + var wIn float64 + v := n + for _, u := range layer.To(v) { + wIn += weight(u, v) + } + w := weight(n, n) + m += w + wOut // We only need to count edges once. + k[n.ID()] = directedWeights{out: w + wOut, in: w + wIn} + } + + if communities == nil { + var qLayer float64 + for _, u := range nodes { + kU := k[u.ID()] + qLayer += weight(u, u) - layerResolution*kU.out*kU.in/m + } + q[l] = layerWeight * qLayer + continue + } + + var qLayer float64 + for _, c := range communities { + for _, u := range c { + kU := k[u.ID()] + for _, v := range c { + kV := k[v.ID()] + qLayer += weight(u, v) - layerResolution*kU.out*kV.in/m + } + } + } + q[l] = layerWeight * qLayer + } + + return q +} + +// DirectedLayers implements DirectedMultiplex. +type DirectedLayers []graph.Directed + +// NewDirectedLayers returns a DirectedLayers using the provided layers +// ensuring there is a match between IDs for each layer. +func NewDirectedLayers(layers ...graph.Directed) (DirectedLayers, error) { + if len(layers) == 0 { + return nil, nil + } + var base, next intsets.Sparse + for _, n := range layers[0].Nodes() { + base.Insert(n.ID()) + } + for i, l := range layers[1:] { + next.Clear() + for _, n := range l.Nodes() { + next.Insert(n.ID()) + } + if !next.Equals(&base) { + return nil, fmt.Errorf("community: layer ID mismatch between layers: %d", i+1) + } + } + return layers, nil +} + +// Nodes returns the nodes of the receiver. +func (g DirectedLayers) Nodes() []graph.Node { + if len(g) == 0 { + return nil + } + return g[0].Nodes() +} + +// Depth returns the depth of the multiplex graph. +func (g DirectedLayers) Depth() int { return len(g) } + +// Layer returns the lth layer of the multiplex graph. +func (g DirectedLayers) Layer(l int) graph.Directed { return g[l] } + +// louvainDirectedMultiplex returns the hierarchical modularization of g at the given resolution +// using the Louvain algorithm. If all is true and g has negatively weighted layers, all +// communities will be searched during the modularization. If src is nil, rand.Intn is +// used as the random generator. louvainDirectedMultiplex will panic if g has any edge with +// edge weight that does not sign-match the layer weight. +// +// graph.Undirect may be used as a shim to allow modularization of directed graphs. +func louvainDirectedMultiplex(g DirectedMultiplex, weights, resolutions []float64, all bool, src *rand.Rand) *ReducedDirectedMultiplex { + if weights != nil && len(weights) != g.Depth() { + panic("community: weights vector length mismatch") + } + if resolutions != nil && len(resolutions) != 1 && len(resolutions) != g.Depth() { + panic("community: resolutions vector length mismatch") + } + + // See louvain.tex for a detailed description + // of the algorithm used here. + + c := reduceDirectedMultiplex(g, nil, weights) + rnd := rand.Intn + if src != nil { + rnd = src.Intn + } + for { + l := newDirectedMultiplexLocalMover(c, c.communities, weights, resolutions, all) + if l == nil { + return c + } + if done := l.localMovingHeuristic(rnd); done { + return c + } + c = reduceDirectedMultiplex(c, l.communities, weights) + } +} + +// ReducedDirectedMultiplex is a directed graph of communities derived from a +// parent graph by reduction. +type ReducedDirectedMultiplex struct { + // nodes is the set of nodes held + // by the graph. In a ReducedDirectedMultiplex + // the node ID is the index into + // nodes. + nodes []multiplexCommunity + layers []directedEdges + + // communities is the community + // structure of the graph. + communities [][]graph.Node + + parent *ReducedDirectedMultiplex +} + +var ( + _ DirectedMultiplex = (*ReducedDirectedMultiplex)(nil) + _ graph.Directed = (*directedLayerHandle)(nil) + _ graph.Weighter = (*directedLayerHandle)(nil) +) + +// Nodes returns all the nodes in the graph. +func (g *ReducedDirectedMultiplex) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + for i := range g.nodes { + nodes[i] = node(i) + } + return nodes +} + +// Depth returns the number of layers in the multiplex graph. +func (g *ReducedDirectedMultiplex) Depth() int { return len(g.layers) } + +// Layer returns the lth layer of the multiplex graph. +func (g *ReducedDirectedMultiplex) Layer(l int) graph.Directed { + return directedLayerHandle{multiplex: g, layer: l} +} + +// Communities returns the community memberships of the nodes in the +// graph used to generate the reduced graph. +func (g *ReducedDirectedMultiplex) Communities() [][]graph.Node { + communities := make([][]graph.Node, len(g.communities)) + if g.parent == nil { + for i, members := range g.communities { + comm := make([]graph.Node, len(members)) + for j, n := range members { + nodes := g.nodes[n.ID()].nodes + if len(nodes) != 1 { + panic("community: unexpected number of nodes in base graph community") + } + comm[j] = nodes[0] + } + communities[i] = comm + } + return communities + } + sub := g.parent.Communities() + for i, members := range g.communities { + var comm []graph.Node + for _, n := range members { + comm = append(comm, sub[n.ID()]...) + } + communities[i] = comm + } + return communities +} + +// Structure returns the community structure of the current level of +// the module clustering. The first index of the returned value +// corresponds to the index of the nodes in the next higher level if +// it exists. The returned value should not be mutated. +func (g *ReducedDirectedMultiplex) Structure() [][]graph.Node { + return g.communities +} + +// Expanded returns the next lower level of the module clustering or nil +// if at the lowest level. +func (g *ReducedDirectedMultiplex) Expanded() ReducedMultiplex { + return g.parent +} + +// reduceDirectedMultiplex returns a reduced graph constructed from g divided +// into the given communities. The communities value is mutated +// by the call to reduceDirectedMultiplex. If communities is nil and g is a +// ReducedDirectedMultiplex, it is returned unaltered. +func reduceDirectedMultiplex(g DirectedMultiplex, communities [][]graph.Node, weights []float64) *ReducedDirectedMultiplex { + if communities == nil { + if r, ok := g.(*ReducedDirectedMultiplex); ok { + return r + } + + nodes := g.Nodes() + // TODO(kortschak) This sort is necessary really only + // for testing. In practice we would not be using the + // community provided by the user for a Q calculation. + // Probably we should use a function to map the + // communities in the test sets to the remapped order. + sort.Sort(ordered.ByID(nodes)) + communities = make([][]graph.Node, len(nodes)) + for i := range nodes { + communities[i] = []graph.Node{node(i)} + } + + r := ReducedDirectedMultiplex{ + nodes: make([]multiplexCommunity, len(nodes)), + layers: make([]directedEdges, g.Depth()), + communities: communities, + } + communityOf := make(map[int]int, len(nodes)) + for i, n := range nodes { + r.nodes[i] = multiplexCommunity{id: i, nodes: []graph.Node{n}, weights: make([]float64, depth(weights))} + communityOf[n.ID()] = i + } + for i := range r.layers { + r.layers[i] = directedEdges{ + edgesFrom: make([][]int, len(nodes)), + edgesTo: make([][]int, len(nodes)), + weights: make(map[[2]int]float64), + } + } + w := 1.0 + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + if weights != nil { + w = weights[l] + } + if w == 0 { + continue + } + var sign float64 + var weight func(x, y graph.Node) float64 + if w < 0 { + sign, weight = -1, negativeWeightFuncFor(layer) + } else { + sign, weight = 1, positiveWeightFuncFor(layer) + } + for _, n := range nodes { + id := communityOf[n.ID()] + + var out []int + u := n + for _, v := range layer.From(u) { + vid := communityOf[v.ID()] + if vid != id { + out = append(out, vid) + } + r.layers[l].weights[[2]int{id, vid}] = sign * weight(u, v) + } + r.layers[l].edgesFrom[id] = out + + var in []int + v := n + for _, u := range layer.To(v) { + uid := communityOf[u.ID()] + if uid != id { + in = append(in, uid) + } + r.layers[l].weights[[2]int{uid, id}] = sign * weight(u, v) + } + r.layers[l].edgesTo[id] = in + } + } + return &r + } + + // Remove zero length communities destructively. + var commNodes int + for i := 0; i < len(communities); { + comm := communities[i] + if len(comm) == 0 { + communities[i] = communities[len(communities)-1] + communities[len(communities)-1] = nil + communities = communities[:len(communities)-1] + } else { + commNodes += len(comm) + i++ + } + } + + r := ReducedDirectedMultiplex{ + nodes: make([]multiplexCommunity, len(communities)), + layers: make([]directedEdges, g.Depth()), + } + communityOf := make(map[int]int, commNodes) + for i, comm := range communities { + r.nodes[i] = multiplexCommunity{id: i, nodes: comm, weights: make([]float64, depth(weights))} + for _, n := range comm { + communityOf[n.ID()] = i + } + } + for i := range r.layers { + r.layers[i] = directedEdges{ + edgesFrom: make([][]int, len(communities)), + edgesTo: make([][]int, len(communities)), + weights: make(map[[2]int]float64), + } + } + r.communities = make([][]graph.Node, len(communities)) + for i := range r.communities { + r.communities[i] = []graph.Node{node(i)} + } + if g, ok := g.(*ReducedDirectedMultiplex); ok { + // Make sure we retain the truncated + // community structure. + g.communities = communities + r.parent = g + } + w := 1.0 + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + if weights != nil { + w = weights[l] + } + if w == 0 { + continue + } + var sign float64 + var weight func(x, y graph.Node) float64 + if w < 0 { + sign, weight = -1, negativeWeightFuncFor(layer) + } else { + sign, weight = 1, positiveWeightFuncFor(layer) + } + for id, comm := range communities { + var out, in []int + for _, n := range comm { + u := n + for _, v := range comm { + r.nodes[id].weights[l] += sign * weight(u, v) + } + + for _, v := range layer.From(u) { + vid := communityOf[v.ID()] + found := false + for _, e := range out { + if e == vid { + found = true + break + } + } + if !found && vid != id { + out = append(out, vid) + } + // Add half weights because the other + // ends of edges are also counted. + r.layers[l].weights[[2]int{id, vid}] += sign * weight(u, v) / 2 + } + + v := n + for _, u := range layer.To(v) { + uid := communityOf[u.ID()] + found := false + for _, e := range in { + if e == uid { + found = true + break + } + } + if !found && uid != id { + in = append(in, uid) + } + // Add half weights because the other + // ends of edges are also counted. + r.layers[l].weights[[2]int{uid, id}] += sign * weight(u, v) / 2 + } + + } + r.layers[l].edgesFrom[id] = out + r.layers[l].edgesTo[id] = in + } + } + return &r +} + +// directedLayerHandle is a handle to a multiplex graph layer. +type directedLayerHandle struct { + // multiplex is the complete + // multiplex graph. + multiplex *ReducedDirectedMultiplex + + // layer is an index into the + // multiplex for the current + // layer. + layer int +} + +// Has returns whether the node exists within the graph. +func (g directedLayerHandle) Has(n graph.Node) bool { + id := n.ID() + return id >= 0 || id < len(g.multiplex.nodes) +} + +// Nodes returns all the nodes in the graph. +func (g directedLayerHandle) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.multiplex.nodes)) + for i := range g.multiplex.nodes { + nodes[i] = node(i) + } + return nodes +} + +// From returns all nodes in g that can be reached directly from u. +func (g directedLayerHandle) From(u graph.Node) []graph.Node { + out := g.multiplex.layers[g.layer].edgesFrom[u.ID()] + nodes := make([]graph.Node, len(out)) + for i, vid := range out { + nodes[i] = g.multiplex.nodes[vid] + } + return nodes +} + +// To returns all nodes in g that can reach directly to v. +func (g directedLayerHandle) To(v graph.Node) []graph.Node { + in := g.multiplex.layers[g.layer].edgesTo[v.ID()] + nodes := make([]graph.Node, len(in)) + for i, uid := range in { + nodes[i] = g.multiplex.nodes[uid] + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g directedLayerHandle) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if xid == yid { + return false + } + _, ok := g.multiplex.layers[g.layer].weights[[2]int{xid, yid}] + if ok { + return true + } + _, ok = g.multiplex.layers[g.layer].weights[[2]int{yid, xid}] + return ok +} + +// HasEdgeFromTo returns whether an edge exists from node u to v. +func (g directedLayerHandle) HasEdgeFromTo(u, v graph.Node) bool { + uid := u.ID() + vid := v.ID() + if uid == vid { + return false + } + _, ok := g.multiplex.layers[g.layer].weights[[2]int{uid, vid}] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g directedLayerHandle) Edge(u, v graph.Node) graph.Edge { + uid := u.ID() + vid := v.ID() + w, ok := g.multiplex.layers[g.layer].weights[[2]int{uid, vid}] + if !ok { + return nil + } + return multiplexEdge{from: g.multiplex.nodes[u.ID()], to: g.multiplex.nodes[v.ID()], weight: w} +} + +// EdgeBetween returns the edge between nodes x and y. +func (g directedLayerHandle) EdgeBetween(x, y graph.Node) graph.Edge { + return g.Edge(x, y) +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g directedLayerHandle) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.multiplex.nodes[xid].weights[g.layer], true + } + w, ok = g.multiplex.layers[g.layer].weights[[2]int{xid, yid}] + return w, ok +} + +// directedMultiplexLocalMover is a step in graph modularity optimization. +type directedMultiplexLocalMover struct { + g *ReducedDirectedMultiplex + + // nodes is the set of working nodes. + nodes []graph.Node + // edgeWeightsOf is the weighted degree + // of each node indexed by ID. + edgeWeightsOf [][]directedWeights + + // m is the total sum of + // edge weights in g. + m []float64 + + // weight is the weight function + // provided by g or a function + // that returns the Weight value + // of the non-nil edge between x + // and y. + weight []func(x, y graph.Node) float64 + + // communities is the current + // division of g. + communities [][]graph.Node + // memberships is a mapping between + // node ID and community membership. + memberships []int + + // resolution is the Reichardt and + // Bornholdt γ parameter as defined + // in doi:10.1103/PhysRevE.74.016110. + resolutions []float64 + + // weights is the layer weights for + // the modularisation. + weights []float64 + + // searchAll specifies whether the local + // mover should consider non-connected + // communities during the local moving + // heuristic. + searchAll bool + + // moved indicates that a call to + // move has been made since the last + // call to shuffle. + moved bool + + // changed indicates that a move + // has been made since the creation + // of the local mover. + changed bool +} + +// newDirectedMultiplexLocalMover returns a new directedMultiplexLocalMover initialized with +// the graph g, a set of communities and a modularity resolution parameter. The +// node IDs of g must be contiguous in [0,n) where n is the number of nodes. +// If g has a zero edge weight sum, nil is returned. +func newDirectedMultiplexLocalMover(g *ReducedDirectedMultiplex, communities [][]graph.Node, weights, resolutions []float64, all bool) *directedMultiplexLocalMover { + nodes := g.Nodes() + l := directedMultiplexLocalMover{ + g: g, + nodes: nodes, + edgeWeightsOf: make([][]directedWeights, g.Depth()), + m: make([]float64, g.Depth()), + communities: communities, + memberships: make([]int, len(nodes)), + resolutions: resolutions, + weights: weights, + weight: make([]func(x, y graph.Node) float64, g.Depth()), + } + + // Calculate the total edge weight of the graph + // and degree weights for each node. + var zero int + for i := 0; i < g.Depth(); i++ { + l.edgeWeightsOf[i] = make([]directedWeights, len(nodes)) + var weight func(x, y graph.Node) float64 + + if weights != nil { + if weights[i] == 0 { + zero++ + continue + } + if weights[i] < 0 { + weight = negativeWeightFuncFor(g.Layer(i)) + l.searchAll = all + } else { + weight = positiveWeightFuncFor(g.Layer(i)) + } + } else { + weight = positiveWeightFuncFor(g.Layer(i)) + } + + l.weight[i] = weight + layer := g.Layer(i) + for _, n := range l.nodes { + u := n + var wOut float64 + for _, v := range layer.From(u) { + wOut += weight(u, v) + } + + v := n + var wIn float64 + for _, u := range layer.To(v) { + wIn += weight(u, v) + } + + w := weight(n, n) + l.edgeWeightsOf[i][u.ID()] = directedWeights{out: w + wOut, in: w + wIn} + l.m[i] += w + wOut + } + if l.m[i] == 0 { + zero++ + } + } + if zero == g.Depth() { + return nil + } + + // Assign membership mappings. + for i, c := range communities { + for _, n := range c { + l.memberships[n.ID()] = i + } + } + + return &l +} + +// localMovingHeuristic performs the Louvain local moving heuristic until +// no further moves can be made. It returns a boolean indicating that the +// directedMultiplexLocalMover has not made any improvement to the community +// structure and so the Louvain algorithm is done. +func (l *directedMultiplexLocalMover) localMovingHeuristic(rnd func(int) int) (done bool) { + for { + l.shuffle(rnd) + for _, n := range l.nodes { + dQ, dst, src := l.deltaQ(n) + if dQ <= 0 { + continue + } + l.move(dst, src) + } + if !l.moved { + return !l.changed + } + } +} + +// shuffle performs a Fisher-Yates shuffle on the nodes held by the +// directedMultiplexLocalMover using the random source rnd which should return +// an integer in the range [0,n). +func (l *directedMultiplexLocalMover) shuffle(rnd func(n int) int) { + l.moved = false + for i := range l.nodes[:len(l.nodes)-1] { + j := i + rnd(len(l.nodes)-i) + l.nodes[i], l.nodes[j] = l.nodes[j], l.nodes[i] + } +} + +// move moves the node at src to the community at dst. +func (l *directedMultiplexLocalMover) move(dst int, src commIdx) { + l.moved = true + l.changed = true + + srcComm := l.communities[src.community] + n := srcComm[src.node] + + l.memberships[n.ID()] = dst + + l.communities[dst] = append(l.communities[dst], n) + srcComm[src.node], srcComm[len(srcComm)-1] = srcComm[len(srcComm)-1], nil + l.communities[src.community] = srcComm[:len(srcComm)-1] +} + +// deltaQ returns the highest gain in modularity attainable by moving +// n from its current community to another connected community and +// the index of the chosen destination. The index into the +// directedMultiplexLocalMover's communities field is returned in src if n +// is in communities. +func (l *directedMultiplexLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, src commIdx) { + id := n.ID() + + var iterator minTaker + if l.searchAll { + iterator = &dense{n: len(l.communities)} + } else { + // Find communities connected to n. + var connected intsets.Sparse + // The following for loop is equivalent to: + // + // for i := 0; i < l.g.Depth(); i++ { + // for _, v := range l.g.Layer(i).From(n) { + // connected.Insert(l.memberships[v.ID()]) + // } + // for _, v := range l.g.Layer(i).To(n) { + // connected.Insert(l.memberships[v.ID()]) + // } + // } + // + // This is done to avoid an allocation for + // each layer. + for _, layer := range l.g.layers { + for _, vid := range layer.edgesFrom[id] { + connected.Insert(l.memberships[vid]) + } + for _, vid := range layer.edgesTo[id] { + connected.Insert(l.memberships[vid]) + } + } + // Insert the node's own community. + connected.Insert(l.memberships[id]) + iterator = &connected + } + + // Calculate the highest modularity gain + // from moving into another community and + // keep the index of that community. + var dQremove float64 + dQadd, dst, src := math.Inf(-1), -1, commIdx{-1, -1} + var i int + for iterator.TakeMin(&i) { + c := l.communities[i] + var removal bool + var _dQadd float64 + for layer := 0; layer < l.g.Depth(); layer++ { + m := l.m[layer] + if m == 0 { + // Do not consider layers with zero sum edge weight. + continue + } + w := 1.0 + if l.weights != nil { + w = l.weights[layer] + } + if w == 0 { + // Do not consider layers with zero weighting. + continue + } + + var k_aC, sigma_totC directedWeights // C is a substitution for ^𝛼 or ^𝛽. + removal = false + for j, u := range c { + uid := u.ID() + if uid == id { + // Only mark and check src community on the first layer. + if layer == 0 { + if src.community != -1 { + panic("community: multiple sources") + } + src = commIdx{i, j} + } + removal = true + } + + k_aC.in += l.weight[layer](n, u) + k_aC.out += l.weight[layer](u, n) + // sigma_totC could be kept for each community + // and updated for moves, changing the calculation + // of sigma_totC here from O(n_c) to O(1), but + // in practice the time savings do not appear + // to be compelling and do not make up for the + // increase in code complexity and space required. + w := l.edgeWeightsOf[layer][uid] + sigma_totC.in += w.in + sigma_totC.out += w.out + } + + a_aa := l.weight[layer](n, n) + k_a := l.edgeWeightsOf[layer][id] + gamma := 1.0 + if l.resolutions != nil { + if len(l.resolutions) == 1 { + gamma = l.resolutions[0] + } else { + gamma = l.resolutions[layer] + } + } + + // See louvain.tex for a derivation of these equations. + // The weighting term, w, is described in V Traag, + // "Algorithms and dynamical models for communities and + // reputation in social networks", chapter 5. + // http://www.traag.net/wp/wp-content/papercite-data/pdf/traag_algorithms_2013.pdf + switch { + case removal: + // The community c was the current community, + // so calculate the change due to removal. + dQremove += w * ((k_aC.in /*^𝛼*/ - a_aa) + (k_aC.out /*^𝛼*/ - a_aa) - + gamma*(k_a.in*(sigma_totC.out /*^𝛼*/ -k_a.out)+k_a.out*(sigma_totC.in /*^𝛼*/ -k_a.in))/m) + + default: + // Otherwise calculate the change due to an addition + // to c. + _dQadd += w * (k_aC.in /*^𝛽*/ + k_aC.out /*^𝛽*/ - + gamma*(k_a.in*sigma_totC.out /*^𝛽*/ +k_a.out*sigma_totC.in /*^𝛽*/)/m) + } + } + if !removal && _dQadd > dQadd { + dQadd = _dQadd + dst = i + } + } + + return dQadd - dQremove, dst, src +} diff --git a/graph/community/louvain_directed_multiplex_test.go b/graph/community/louvain_directed_multiplex_test.go new file mode 100644 index 00000000..1ad986ab --- /dev/null +++ b/graph/community/louvain_directed_multiplex_test.go @@ -0,0 +1,700 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "math" + "math/rand" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var communityDirectedMultiplexQTests = []struct { + name string + layers []layer + structures []structure + + wantLevels []level +}{ + { + name: "unconnected", + layers: []layer{{g: unconnected, weight: 1}}, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: math.NaN(), + }, + }, + wantLevels: []level{ + { + q: math.Inf(-1), // Here math.Inf(-1) is used as a place holder for NaN to allow use of reflect.DeepEqual. + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "simple_directed", + layers: []layer{{g: simpleDirected, weight: 1}}, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1), + 1: linksTo(2, 3, 4), + }, + want: 0.5714285714285716, + tol: 1e-10, + }, + }, + wantLevels: []level{ + { + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1)}, + {simple.Node(2), simple.Node(3), simple.Node(4)}, + }, + q: 0.5714285714285716, + }, + { + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + }, + q: -1.2857142857142856, + }, + }, + }, + { + name: "simple_directed_twice", + layers: []layer{ + {g: simpleDirected, weight: 0.5}, + {g: simpleDirected, weight: 0.5}, + }, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1), + 1: linksTo(2, 3, 4), + }, + want: 0.5714285714285716, + tol: 1e-10, + }, + }, + wantLevels: []level{ + { + q: 0.5714285714285716, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1)}, + {simple.Node(2), simple.Node(3), simple.Node(4)}, + }, + }, + { + q: -1.2857142857142856, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + }, + }, + }, + }, + { + name: "small_dumbell", + layers: []layer{ + {g: smallDumbell, edgeWeight: 1, weight: 1}, + {g: dumbellRepulsion, edgeWeight: -1, weight: -1}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 2.5714285714285716, tol: 1e-10, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 4, 5), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 2.5714285714285716, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: -0.857142857142857, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "repulsion", + layers: []layer{{g: repulsion, edgeWeight: -1, weight: -1}}, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 9.0, tol: 1e-10, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: 3, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 9.0, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: 3.0, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "middle_east", + layers: []layer{ + {g: middleEast.friends, edgeWeight: 1, weight: 1}, + {g: middleEast.enemies, edgeWeight: -1, weight: -1}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 6), + 1: linksTo(1, 7, 9, 12), + 2: linksTo(2, 8, 11), + 3: linksTo(3, 4, 5, 10), + }, + want: 33.818057455540355, tol: 1e-9, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 2, 3, 4, 5, 10), + 1: linksTo(1, 7, 9, 12), + 2: linksTo(6), + 3: linksTo(8, 11), + }, + want: 30.92749658, tol: 1e-7, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 33.818057455540355, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(6)}, + {simple.Node(1), simple.Node(7), simple.Node(9), simple.Node(12)}, + {simple.Node(2), simple.Node(8), simple.Node(11)}, + {simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(10)}, + }, + }, + { + q: 3.8071135430916545, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + }, + }, + }, + }, +} + +func TestCommunityQDirectedMultiplex(t *testing.T) { + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + } + q := QMultiplex(g, communities, weights, []float64{structure.resolution}) + got := floats.Sum(q) + if !floats.EqualWithinAbsOrRel(got, structure.want, structure.tol, structure.tol) && !math.IsNaN(structure.want) { + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + t.Errorf("unexpected Q value for %q %v: got: %v %.3v want: %v", + test.name, communities, got, q, structure.want) + } + } + } +} + +func TestCommunityDeltaQDirectedMultiplex(t *testing.T) { +tests: + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + rnd := rand.New(rand.NewSource(1)).Intn + for _, structure := range test.structures { + communityOf := make(map[int]int) + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communityOf[n] = i + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + resolution := []float64{structure.resolution} + + before := QMultiplex(g, communities, weights, resolution) + + // We test exhaustively. + const all = true + + l := newDirectedMultiplexLocalMover( + reduceDirectedMultiplex(g, nil, weights), + communities, weights, resolution, all) + if l == nil { + if !math.IsNaN(floats.Sum(before)) { + t.Errorf("unexpected nil localMover with non-NaN Q graph: Q=%.4v", before) + } + continue tests + } + + // This is done to avoid run-to-run + // variation due to map iteration order. + sort.Sort(ordered.ByID(l.nodes)) + + l.shuffle(rnd) + + for _, target := range l.nodes { + got, gotDst, gotSrc := l.deltaQ(target) + + want, wantDst := math.Inf(-1), -1 + migrated := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + if n == target.ID() { + continue + } + migrated[i] = append(migrated[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(migrated[i])) + } + + for i, c := range structure.memberships { + if i == communityOf[target.ID()] { + continue + } + if !(all && hasNegative(weights)) { + connected := false + search: + for l := 0; l < g.Depth(); l++ { + if weights[l] < 0 { + connected = true + break search + } + layer := g.Layer(l) + for n := range c { + if layer.HasEdgeBetween(simple.Node(n), target) { + connected = true + break search + } + } + } + if !connected { + continue + } + } + migrated[i] = append(migrated[i], target) + after := QMultiplex(g, migrated, weights, resolution) + migrated[i] = migrated[i][:len(migrated[i])-1] + if delta := floats.Sum(after) - floats.Sum(before); delta > want { + want = delta + wantDst = i + } + } + + if !floats.EqualWithinAbsOrRel(got, want, structure.tol, structure.tol) || gotDst != wantDst { + t.Errorf("unexpected result moving n=%d in c=%d of %s/%.4v: got: %.4v,%d want: %.4v,%d"+ + "\n\t%v\n\t%v", + target.ID(), communityOf[target.ID()], test.name, structure.resolution, got, gotDst, want, wantDst, + communities, migrated) + } + if gotSrc.community != communityOf[target.ID()] { + t.Errorf("unexpected source community index: got: %d want: %d", gotSrc, communityOf[target.ID()]) + } else if communities[gotSrc.community][gotSrc.node].ID() != target.ID() { + wantNodeIdx := -1 + for i, n := range communities[gotSrc.community] { + if n.ID() == target.ID() { + wantNodeIdx = i + break + } + } + t.Errorf("unexpected source node index: got: %d want: %d", gotSrc.node, wantNodeIdx) + } + } + } + } +} + +func TestReduceQConsistencyDirectedMultiplex(t *testing.T) { +tests: + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + if math.IsNaN(structure.want) { + continue tests + } + + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + gQ := QMultiplex(g, communities, weights, []float64{structure.resolution}) + gQnull := QMultiplex(g, nil, weights, nil) + + cg0 := reduceDirectedMultiplex(g, nil, weights) + cg0Qnull := QMultiplex(cg0, cg0.Structure(), weights, nil) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQnull), floats.Sum(cg0Qnull), structure.tol, structure.tol) { + t.Errorf("disagreement between null Q from method: %v and function: %v", cg0Qnull, gQnull) + } + cg0Q := QMultiplex(cg0, communities, weights, []float64{structure.resolution}) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQ), floats.Sum(cg0Q), structure.tol, structure.tol) { + t.Errorf("unexpected Q result after initial reduction: got: %v want :%v", cg0Q, gQ) + } + + cg1 := reduceDirectedMultiplex(cg0, communities, weights) + cg1Q := QMultiplex(cg1, cg1.Structure(), weights, []float64{structure.resolution}) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQ), floats.Sum(cg1Q), structure.tol, structure.tol) { + t.Errorf("unexpected Q result after second reduction: got: %v want :%v", cg1Q, gQ) + } + } + } +} + +var localDirectedMultiplexMoveTests = []struct { + name string + layers []layer + structures []moveStructures +}{ + { + name: "blondel", + layers: []layer{{g: blondel, weight: 1}, {g: blondel, weight: 0.5}}, + structures: []moveStructures{ + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(0)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(3)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + // Case to demonstrate when A_aa != k_a^𝛼. + targetNodes: []graph.Node{simple.Node(3), simple.Node(2)}, + resolution: 1, + tol: 1e-14, + }, + }, + }, +} + +func TestMoveLocalDirectedMultiplex(t *testing.T) { + for _, test := range localDirectedMultiplexMoveTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + r := reduceDirectedMultiplex(reduceDirectedMultiplex(g, nil, weights), communities, weights) + + l := newDirectedMultiplexLocalMover(r, r.communities, weights, []float64{structure.resolution}, true) + for _, n := range structure.targetNodes { + dQ, dst, src := l.deltaQ(n) + if dQ > 0 { + before := floats.Sum(QMultiplex(r, l.communities, weights, []float64{structure.resolution})) + l.move(dst, src) + after := floats.Sum(QMultiplex(r, l.communities, weights, []float64{structure.resolution})) + want := after - before + if !floats.EqualWithinAbsOrRel(dQ, want, structure.tol, structure.tol) { + t.Errorf("unexpected deltaQ: got: %v want: %v", dQ, want) + } + } + } + } + } +} + +func TestLouvainDirectedMultiplex(t *testing.T) { + const louvainIterations = 20 + + for _, test := range communityDirectedMultiplexQTests { + g, weights, err := directedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + if test.structures[0].resolution != 1 { + panic("bad test: expect resolution=1") + } + want := make([][]graph.Node, len(test.structures[0].memberships)) + for i, c := range test.structures[0].memberships { + for n := range c { + want[i] = append(want[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(want[i])) + } + sort.Sort(ordered.BySliceIDs(want)) + + var ( + got *ReducedDirectedMultiplex + bestQ = math.Inf(-1) + ) + // Modularize is randomised so we do this to + // ensure the level tests are consistent. + src := rand.New(rand.NewSource(1)) + for i := 0; i < louvainIterations; i++ { + r := ModularizeMultiplex(g, weights, nil, true, src).(*ReducedDirectedMultiplex) + if q := floats.Sum(QMultiplex(r, nil, weights, nil)); q > bestQ || math.IsNaN(q) { + bestQ = q + got = r + + if math.IsNaN(q) { + // Don't try again for non-connected case. + break + } + } + + var qs []float64 + for p := r; p != nil; p = p.Expanded().(*ReducedDirectedMultiplex) { + qs = append(qs, floats.Sum(QMultiplex(p, nil, weights, nil))) + } + + // Recovery of Q values is reversed. + if reverse(qs); !sort.Float64sAreSorted(qs) { + t.Errorf("Q values not monotonically increasing: %.5v", qs) + } + } + + gotCommunities := got.Communities() + for _, c := range gotCommunities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(gotCommunities)) + if !reflect.DeepEqual(gotCommunities, want) { + t.Errorf("unexpected community membership for %s Q=%.4v:\n\tgot: %v\n\twant:%v", + test.name, bestQ, gotCommunities, want) + continue + } + + var levels []level + for p := got; p != nil; p = p.Expanded().(*ReducedDirectedMultiplex) { + var communities [][]graph.Node + if p.parent != nil { + communities = p.parent.Communities() + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(communities)) + } else { + communities = reduceDirectedMultiplex(g, nil, weights).Communities() + } + q := floats.Sum(QMultiplex(p, nil, weights, nil)) + if math.IsNaN(q) { + // Use an equalable flag value in place of NaN. + q = math.Inf(-1) + } + levels = append(levels, level{q: q, communities: communities}) + } + if !reflect.DeepEqual(levels, test.wantLevels) { + t.Errorf("unexpected level structure:\n\tgot: %v\n\twant:%v", levels, test.wantLevels) + } + } +} + +func TestNonContiguousDirectedMultiplex(t *testing.T) { + g := simple.NewDirectedGraph(0, 0) + for _, e := range []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(4), T: simple.Node(5), W: 1}, + } { + g.SetEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + ModularizeMultiplex(DirectedLayers{g}, nil, nil, true, nil) + }() +} + +func BenchmarkLouvainDirectedMultiplex(b *testing.B) { + src := rand.New(rand.NewSource(1)) + for i := 0; i < b.N; i++ { + ModularizeMultiplex(DirectedLayers{dupGraphDirected}, nil, nil, true, src) + } +} + +func directedMultiplexFrom(raw []layer) (DirectedLayers, []float64, error) { + var layers []graph.Directed + var weights []float64 + for _, l := range raw { + g := simple.NewDirectedGraph(0, 0) + for u, e := range l.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + w := 1.0 + if l.edgeWeight != 0 { + w = l.edgeWeight + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: w}) + } + } + layers = append(layers, g) + weights = append(weights, l.weight) + } + g, err := NewDirectedLayers(layers...) + if err != nil { + return nil, nil, err + } + return g, weights, nil +} diff --git a/graph/community/louvain_directed_test.go b/graph/community/louvain_directed_test.go new file mode 100644 index 00000000..82336106 --- /dev/null +++ b/graph/community/louvain_directed_test.go @@ -0,0 +1,589 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "math" + "math/rand" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var communityDirectedQTests = []struct { + name string + g []set + structures []structure + + wantLevels []level +}{ + { + name: "simple_directed", + g: simpleDirected, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1), + 1: linksTo(2, 3, 4), + }, + want: 0.5714285714285716 / 7, + tol: 1e-10, + }, + }, + wantLevels: []level{ + { + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1)}, + {simple.Node(2), simple.Node(3), simple.Node(4)}, + }, + q: 0.5714285714285716 / 7, + }, + { + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + }, + q: -1.2857142857142856 / 7, + }, + }, + }, + { + name: "zachary", + g: zachary, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 7, 11, 12, 13, 17, 19, 21), + 1: linksTo(4, 5, 6, 10, 16), + 2: linksTo(8, 9, 14, 15, 18, 20, 22, 26, 29, 30, 32, 33), + 3: linksTo(23, 24, 25, 27, 28, 31), + }, + want: 34.3417721519 / 79 /* 5->6 and 6->5 because of co-equal rank */, tol: 1e-4, + }, + }, + wantLevels: []level{ + { + q: 0.43470597660631316, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(7), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(17), simple.Node(19), simple.Node(21)}, + {simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(10), simple.Node(16)}, + {simple.Node(8), simple.Node(9), simple.Node(14), simple.Node(15), simple.Node(18), simple.Node(20), simple.Node(22), simple.Node(26), simple.Node(29), simple.Node(30), simple.Node(32), simple.Node(33)}, + {simple.Node(23), simple.Node(24), simple.Node(25), simple.Node(27), simple.Node(28), simple.Node(31)}, + }, + }, + { + q: 0.3911232174331037, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(7), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(17), simple.Node(19), simple.Node(21)}, + {simple.Node(4), simple.Node(10)}, + {simple.Node(5), simple.Node(6), simple.Node(16)}, + {simple.Node(8), simple.Node(30)}, + {simple.Node(9), simple.Node(14), simple.Node(15), simple.Node(18), simple.Node(20), simple.Node(22), simple.Node(32), simple.Node(33)}, + {simple.Node(23), simple.Node(24), simple.Node(25), simple.Node(27), simple.Node(28), simple.Node(31)}, + {simple.Node(26), simple.Node(29)}, + }, + }, + { + q: -0.014580996635154624, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + {simple.Node(13)}, + {simple.Node(14)}, + {simple.Node(15)}, + {simple.Node(16)}, + {simple.Node(17)}, + {simple.Node(18)}, + {simple.Node(19)}, + {simple.Node(20)}, + {simple.Node(21)}, + {simple.Node(22)}, + {simple.Node(23)}, + {simple.Node(24)}, + {simple.Node(25)}, + {simple.Node(26)}, + {simple.Node(27)}, + {simple.Node(28)}, + {simple.Node(29)}, + {simple.Node(30)}, + {simple.Node(31)}, + {simple.Node(32)}, + {simple.Node(33)}, + }, + }, + }, + }, + { + name: "blondel", + g: blondel, + // community structure and modularity calculated by C++ implementation: louvain igraph. + // Note that louvain igraph returns Q as an unscaled value. + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7), + 1: linksTo(8, 9, 10, 11, 12, 13, 14, 15), + }, + want: 11.1428571429 / 28, tol: 1e-4, + }, + }, + wantLevels: []level{ + { + q: 0.3979591836734694, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(7)}, + {simple.Node(8), simple.Node(9), simple.Node(10), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(14), simple.Node(15)}, + }, + }, + { + q: 0.32525510204081637, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(3), simple.Node(5), simple.Node(7)}, + {simple.Node(1), simple.Node(2), simple.Node(4), simple.Node(6)}, + {simple.Node(8), simple.Node(10), simple.Node(11), simple.Node(13), simple.Node(15)}, + {simple.Node(9), simple.Node(12), simple.Node(14)}, + }, + }, + { + q: -0.022959183673469385, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + {simple.Node(13)}, + {simple.Node(14)}, + {simple.Node(15)}, + }, + }, + }, + }, +} + +func TestCommunityQDirected(t *testing.T) { + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + } + got := Q(g, communities, structure.resolution) + if !floats.EqualWithinAbsOrRel(got, structure.want, structure.tol, structure.tol) && !math.IsNaN(structure.want) { + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + t.Errorf("unexpected Q value for %q %v: got: %v want: %v", + test.name, communities, got, structure.want) + } + } + } +} + +func TestCommunityDeltaQDirected(t *testing.T) { +tests: + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + rnd := rand.New(rand.NewSource(1)).Intn + for _, structure := range test.structures { + communityOf := make(map[int]int) + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communityOf[n] = i + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + before := Q(g, communities, structure.resolution) + + l := newDirectedLocalMover(reduceDirected(g, nil), communities, structure.resolution) + if l == nil { + if !math.IsNaN(before) { + t.Errorf("unexpected nil localMover with non-NaN Q graph: Q=%.4v", before) + } + continue tests + } + + // This is done to avoid run-to-run + // variation due to map iteration order. + sort.Sort(ordered.ByID(l.nodes)) + + l.shuffle(rnd) + + for _, target := range l.nodes { + got, gotDst, gotSrc := l.deltaQ(target) + + want, wantDst := math.Inf(-1), -1 + migrated := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + if n == target.ID() { + continue + } + migrated[i] = append(migrated[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(migrated[i])) + } + + for i, c := range structure.memberships { + if i == communityOf[target.ID()] { + continue + } + connected := false + for n := range c { + if g.HasEdgeBetween(simple.Node(n), target) { + connected = true + break + } + } + if !connected { + continue + } + migrated[i] = append(migrated[i], target) + after := Q(g, migrated, structure.resolution) + migrated[i] = migrated[i][:len(migrated[i])-1] + if after-before > want { + want = after - before + wantDst = i + } + } + + if !floats.EqualWithinAbsOrRel(got, want, structure.tol, structure.tol) || gotDst != wantDst { + t.Errorf("unexpected result moving n=%d in c=%d of %s/%.4v: got: %.4v,%d want: %.4v,%d"+ + "\n\t%v\n\t%v", + target.ID(), communityOf[target.ID()], test.name, structure.resolution, got, gotDst, want, wantDst, + communities, migrated) + } + if gotSrc.community != communityOf[target.ID()] { + t.Errorf("unexpected source community index: got: %d want: %d", gotSrc, communityOf[target.ID()]) + } else if communities[gotSrc.community][gotSrc.node].ID() != target.ID() { + wantNodeIdx := -1 + for i, n := range communities[gotSrc.community] { + if n.ID() == target.ID() { + wantNodeIdx = i + break + } + } + t.Errorf("unexpected source node index: got: %d want: %d", gotSrc.node, wantNodeIdx) + } + } + } + } +} + +func TestReduceQConsistencyDirected(t *testing.T) { +tests: + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + for _, structure := range test.structures { + if math.IsNaN(structure.want) { + continue tests + } + + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + gQ := Q(g, communities, structure.resolution) + gQnull := Q(g, nil, 1) + + cg0 := reduceDirected(g, nil) + cg0Qnull := Q(cg0, cg0.Structure(), 1) + if !floats.EqualWithinAbsOrRel(gQnull, cg0Qnull, structure.tol, structure.tol) { + t.Errorf("disagreement between null Q from method: %v and function: %v", cg0Qnull, gQnull) + } + cg0Q := Q(cg0, communities, structure.resolution) + if !floats.EqualWithinAbsOrRel(gQ, cg0Q, structure.tol, structure.tol) { + t.Errorf("unexpected Q result after initial reduction: got: %v want :%v", cg0Q, gQ) + } + + cg1 := reduceDirected(cg0, communities) + cg1Q := Q(cg1, cg1.Structure(), structure.resolution) + if !floats.EqualWithinAbsOrRel(gQ, cg1Q, structure.tol, structure.tol) { + t.Errorf("unexpected Q result after second reduction: got: %v want :%v", cg1Q, gQ) + } + } + } +} + +var localDirectedMoveTests = []struct { + name string + g []set + structures []moveStructures +}{ + { + name: "blondel", + g: blondel, + structures: []moveStructures{ + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(0)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(3)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + // Case to demonstrate when A_aa != k_a^𝛼. + targetNodes: []graph.Node{simple.Node(3), simple.Node(2)}, + resolution: 1, + tol: 1e-14, + }, + }, + }, +} + +func TestMoveLocalDirected(t *testing.T) { + for _, test := range localDirectedMoveTests { + g := simple.NewDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + r := reduceDirected(reduceDirected(g, nil), communities) + + l := newDirectedLocalMover(r, r.communities, structure.resolution) + for _, n := range structure.targetNodes { + dQ, dst, src := l.deltaQ(n) + if dQ > 0 { + before := Q(r, l.communities, structure.resolution) + l.move(dst, src) + after := Q(r, l.communities, structure.resolution) + want := after - before + if !floats.EqualWithinAbsOrRel(dQ, want, structure.tol, structure.tol) { + t.Errorf("unexpected deltaQ: got: %v want: %v", dQ, want) + } + } + } + } + } +} + +func TestModularizeDirected(t *testing.T) { + const louvainIterations = 20 + + for _, test := range communityDirectedQTests { + g := simple.NewDirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + if test.structures[0].resolution != 1 { + panic("bad test: expect resolution=1") + } + want := make([][]graph.Node, len(test.structures[0].memberships)) + for i, c := range test.structures[0].memberships { + for n := range c { + want[i] = append(want[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(want[i])) + } + sort.Sort(ordered.BySliceIDs(want)) + + var ( + got *ReducedDirected + bestQ = math.Inf(-1) + ) + // Modularize is randomised so we do this to + // ensure the level tests are consistent. + src := rand.New(rand.NewSource(1)) + for i := 0; i < louvainIterations; i++ { + r := Modularize(g, 1, src).(*ReducedDirected) + if q := Q(r, nil, 1); q > bestQ || math.IsNaN(q) { + bestQ = q + got = r + + if math.IsNaN(q) { + // Don't try again for non-connected case. + break + } + } + + var qs []float64 + for p := r; p != nil; p = p.Expanded().(*ReducedDirected) { + qs = append(qs, Q(p, nil, 1)) + } + + // Recovery of Q values is reversed. + if reverse(qs); !sort.Float64sAreSorted(qs) { + t.Errorf("Q values not monotonically increasing: %.5v", qs) + } + } + + gotCommunities := got.Communities() + for _, c := range gotCommunities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(gotCommunities)) + if !reflect.DeepEqual(gotCommunities, want) { + t.Errorf("unexpected community membership for %s Q=%.4v:\n\tgot: %v\n\twant:%v", + test.name, bestQ, gotCommunities, want) + continue + } + + var levels []level + for p := got; p != nil; p = p.Expanded().(*ReducedDirected) { + var communities [][]graph.Node + if p.parent != nil { + communities = p.parent.Communities() + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(communities)) + } else { + communities = reduceDirected(g, nil).Communities() + } + q := Q(p, nil, 1) + if math.IsNaN(q) { + // Use an equalable flag value in place of NaN. + q = math.Inf(-1) + } + levels = append(levels, level{q: q, communities: communities}) + } + if !reflect.DeepEqual(levels, test.wantLevels) { + t.Errorf("unexpected level structure:\n\tgot: %v\n\twant:%v", levels, test.wantLevels) + } + } +} + +func TestNonContiguousDirected(t *testing.T) { + g := simple.NewDirectedGraph(0, 0) + for _, e := range []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(4), T: simple.Node(5), W: 1}, + } { + g.SetEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + Modularize(g, 1, nil) + }() +} + +func BenchmarkLouvainDirected(b *testing.B) { + src := rand.New(rand.NewSource(1)) + for i := 0; i < b.N; i++ { + Modularize(dupGraphDirected, 1, src) + } +} diff --git a/graph/community/louvain_test.go b/graph/community/louvain_test.go new file mode 100644 index 00000000..b3630b8a --- /dev/null +++ b/graph/community/louvain_test.go @@ -0,0 +1,277 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "fmt" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/graphs/gen" + "gonum.org/v1/gonum/graph/simple" +) + +// set is an integer set. +type set map[int]struct{} + +func linksTo(i ...int) set { + if len(i) == 0 { + return nil + } + s := make(set) + for _, v := range i { + s[v] = struct{}{} + } + return s +} + +type layer struct { + g []set + edgeWeight float64 // Zero edge weight is interpreted as 1.0. + weight float64 +} + +var ( + unconnected = []set{ /* Nodes 0-4 are implicit .*/ 5: nil} + + smallDumbell = []set{ + 0: linksTo(1, 2), + 1: linksTo(2), + 2: linksTo(3), + 3: linksTo(4, 5), + 4: linksTo(5), + 5: nil, + } + dumbellRepulsion = []set{ + 0: linksTo(4), + 1: linksTo(5), + 2: nil, + 3: nil, + 4: nil, + 5: nil, + } + + repulsion = []set{ + 0: linksTo(3, 4, 5), + 1: linksTo(3, 4, 5), + 2: linksTo(3, 4, 5), + 3: linksTo(0, 1, 2), + 4: linksTo(0, 1, 2), + 5: linksTo(0, 1, 2), + } + + simpleDirected = []set{ + 0: linksTo(1), + 1: linksTo(0, 4), + 2: linksTo(1), + 3: linksTo(0, 4), + 4: linksTo(2), + } + + // http://www.slate.com/blogs/the_world_/2014/07/17/the_middle_east_friendship_chart.html + middleEast = struct{ friends, complicated, enemies []set }{ + // green cells + friends: []set{ + 0: nil, + 1: linksTo(5, 7, 9, 12), + 2: linksTo(11), + 3: linksTo(4, 5, 10), + 4: linksTo(3, 5, 10), + 5: linksTo(1, 3, 4, 8, 10, 12), + 6: nil, + 7: linksTo(1, 12), + 8: linksTo(5, 9, 11), + 9: linksTo(1, 8, 12), + 10: linksTo(3, 4, 5), + 11: linksTo(2, 8), + 12: linksTo(1, 5, 7, 9), + }, + + // yellow cells + complicated: []set{ + 0: linksTo(2, 4), + 1: linksTo(4, 8), + 2: linksTo(0, 3, 4, 5, 8, 9), + 3: linksTo(2, 8, 11), + 4: linksTo(0, 1, 2, 8), + 5: linksTo(2), + 6: nil, + 7: linksTo(9, 11), + 8: linksTo(1, 2, 3, 4, 10, 12), + 9: linksTo(2, 7, 11), + 10: linksTo(8), + 11: linksTo(3, 7, 9, 12), + 12: linksTo(8, 11), + }, + + // red cells + enemies: []set{ + 0: linksTo(1, 3, 5, 6, 7, 8, 9, 10, 11, 12), + 1: linksTo(0, 2, 3, 6, 10, 11), + 2: linksTo(1, 6, 7, 10, 12), + 3: linksTo(0, 1, 6, 7, 9, 12), + 4: linksTo(6, 7, 9, 11, 12), + 5: linksTo(0, 6, 7, 9, 11), + 6: linksTo(0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12), + 7: linksTo(0, 2, 3, 4, 5, 6, 8, 10), + 8: linksTo(0, 6, 7), + 9: linksTo(0, 3, 4, 5, 6, 10), + 10: linksTo(0, 1, 2, 6, 7, 9, 11, 12), + 11: linksTo(0, 1, 4, 5, 6, 10), + 12: linksTo(0, 2, 3, 4, 6, 10), + }, + } + + // W. W. Zachary, An information flow model for conflict and fission in small groups, + // Journal of Anthropological Research 33, 452-473 (1977). + // + // The edge list here is constructed such that all link descriptions + // head from a node with lower Page Rank to a node with higher Page + // Rank. This has no impact on undirected tests, but allows a sensible + // view for directed tests. + zachary = []set{ + 0: nil, // rank=0.097 + 1: linksTo(0, 2), // rank=0.05288 + 2: linksTo(0, 32), // rank=0.05708 + 3: linksTo(0, 1, 2), // rank=0.03586 + 4: linksTo(0, 6, 10), // rank=0.02198 + 5: linksTo(0, 6), // rank=0.02911 + 6: linksTo(0, 5), // rank=0.02911 + 7: linksTo(0, 1, 2, 3), // rank=0.02449 + 8: linksTo(0, 2, 32, 33), // rank=0.02977 + 9: linksTo(2, 33), // rank=0.01431 + 10: linksTo(0, 5), // rank=0.02198 + 11: linksTo(0), // rank=0.009565 + 12: linksTo(0, 3), // rank=0.01464 + 13: linksTo(0, 1, 2, 3, 33), // rank=0.02954 + 14: linksTo(32, 33), // rank=0.01454 + 15: linksTo(32, 33), // rank=0.01454 + 16: linksTo(5, 6), // rank=0.01678 + 17: linksTo(0, 1), // rank=0.01456 + 18: linksTo(32, 33), // rank=0.01454 + 19: linksTo(0, 1, 33), // rank=0.0196 + 20: linksTo(32, 33), // rank=0.01454 + 21: linksTo(0, 1), // rank=0.01456 + 22: linksTo(32, 33), // rank=0.01454 + 23: linksTo(32, 33), // rank=0.03152 + 24: linksTo(27, 31), // rank=0.02108 + 25: linksTo(23, 24, 31), // rank=0.02101 + 26: linksTo(29, 33), // rank=0.01504 + 27: linksTo(2, 23, 33), // rank=0.02564 + 28: linksTo(2, 31, 33), // rank=0.01957 + 29: linksTo(23, 32, 33), // rank=0.02629 + 30: linksTo(1, 8, 32, 33), // rank=0.02459 + 31: linksTo(0, 32, 33), // rank=0.03716 + 32: linksTo(33), // rank=0.07169 + 33: nil, // rank=0.1009 + } + + // doi:10.1088/1742-5468/2008/10/P10008 figure 1 + // + // The edge list here is constructed such that all link descriptions + // head from a node with lower Page Rank to a node with higher Page + // Rank. This has no impact on undirected tests, but allows a sensible + // view for directed tests. + blondel = []set{ + 0: linksTo(2), // rank=0.06858 + 1: linksTo(2, 4, 7), // rank=0.05264 + 2: nil, // rank=0.08249 + 3: linksTo(0, 7), // rank=0.03884 + 4: linksTo(0, 2, 10), // rank=0.06754 + 5: linksTo(0, 2, 7, 11), // rank=0.06738 + 6: linksTo(2, 7, 11), // rank=0.0528 + 7: nil, // rank=0.07008 + 8: linksTo(10), // rank=0.09226 + 9: linksTo(8), // rank=0.05821 + 10: nil, // rank=0.1035 + 11: linksTo(8, 10), // rank=0.08538 + 12: linksTo(9, 10), // rank=0.04052 + 13: linksTo(10, 11), // rank=0.03855 + 14: linksTo(8, 9, 10), // rank=0.05621 + 15: linksTo(8), // rank=0.02506 + } +) + +type structure struct { + resolution float64 + memberships []set + want, tol float64 +} + +type level struct { + q float64 + communities [][]graph.Node +} + +type moveStructures struct { + memberships []set + targetNodes []graph.Node + + resolution float64 + tol float64 +} + +func reverse(f []float64) { + for i, j := 0, len(f)-1; i < j; i, j = i+1, j-1 { + f[i], f[j] = f[j], f[i] + } +} + +func hasNegative(f []float64) bool { + for _, v := range f { + if v < 0 { + return true + } + } + return false +} + +var ( + dupGraph = simple.NewUndirectedGraph(0, 0) + dupGraphDirected = simple.NewDirectedGraph(0, 0) +) + +func init() { + err := gen.Duplication(dupGraph, 1000, 0.8, 0.1, 0.5, rand.New(rand.NewSource(1))) + if err != nil { + panic(err) + } + + // Construct a directed graph from dupGraph + // such that every edge dupGraph is replaced + // with an edge that flows from the low node + // ID to the high node ID. + for _, e := range dupGraph.Edges() { + if e.To().ID() < e.From().ID() { + se := e.(simple.Edge) + se.F, se.T = se.T, se.F + e = se + } + dupGraphDirected.SetEdge(e) + } +} + +// This init function checks the Middle East relationship data. +func init() { + world := make([]set, len(middleEast.friends)) + for i := range world { + world[i] = make(set) + } + for _, relationships := range [][]set{middleEast.friends, middleEast.complicated, middleEast.enemies} { + for i, rel := range relationships { + for inter := range rel { + if _, ok := world[i][inter]; ok { + panic(fmt.Sprintf("unexpected relationship: %v--%v", i, inter)) + } + world[i][inter] = struct{}{} + } + } + } + for i := range world { + if len(world[i]) != len(middleEast.friends)-1 { + panic(fmt.Sprintf("missing relationship in %v: %v", i, world[i])) + } + } +} diff --git a/graph/community/louvain_undirected.go b/graph/community/louvain_undirected.go new file mode 100644 index 00000000..475756c9 --- /dev/null +++ b/graph/community/louvain_undirected.go @@ -0,0 +1,568 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "math" + "math/rand" + "sort" + + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +// qUndirected returns the modularity Q score of the graph g subdivided into the +// given communities at the given resolution. If communities is nil, the +// unclustered modularity score is returned. The resolution parameter +// is γ as defined in Reichardt and Bornholdt doi:10.1103/PhysRevE.74.016110. +// qUndirected will panic if g has any edge with negative edge weight. +// +// Q = 1/2m \sum_{ij} [ A_{ij} - (\gamma k_i k_j)/2m ] \delta(c_i,c_j) +// +// graph.Undirect may be used as a shim to allow calculation of Q for +// directed graphs. +func qUndirected(g graph.Undirected, communities [][]graph.Node, resolution float64) float64 { + nodes := g.Nodes() + weight := positiveWeightFuncFor(g) + + // Calculate the total edge weight of the graph + // and the table of penetrating edge weight sums. + var m2 float64 + k := make(map[int]float64, len(nodes)) + for _, u := range nodes { + w := weight(u, u) + for _, v := range g.From(u) { + w += weight(u, v) + } + m2 += w + k[u.ID()] = w + } + + if communities == nil { + var q float64 + for _, u := range nodes { + kU := k[u.ID()] + q += weight(u, u) - resolution*kU*kU/m2 + } + return q / m2 + } + + // Iterate over the communities, calculating + // the non-self edge weights for the upper + // triangle and adjust the diagonal. + var q float64 + for _, c := range communities { + for i, u := range c { + kU := k[u.ID()] + q += weight(u, u) - resolution*kU*kU/m2 + for _, v := range c[i+1:] { + q += 2 * (weight(u, v) - resolution*kU*k[v.ID()]/m2) + } + } + } + return q / m2 +} + +// louvainUndirected returns the hierarchical modularization of g at the given +// resolution using the Louvain algorithm. If src is nil, rand.Intn is used as +// the random generator. louvainUndirected will panic if g has any edge with negative edge +// weight. +// +// graph.Undirect may be used as a shim to allow modularization of directed graphs. +func louvainUndirected(g graph.Undirected, resolution float64, src *rand.Rand) *ReducedUndirected { + // See louvain.tex for a detailed description + // of the algorithm used here. + + c := reduceUndirected(g, nil) + rnd := rand.Intn + if src != nil { + rnd = src.Intn + } + for { + l := newUndirectedLocalMover(c, c.communities, resolution) + if l == nil { + return c + } + if done := l.localMovingHeuristic(rnd); done { + return c + } + c = reduceUndirected(c, l.communities) + } +} + +// ReducedUndirected is an undirected graph of communities derived from a +// parent graph by reduction. +type ReducedUndirected struct { + // nodes is the set of nodes held + // by the graph. In a ReducedUndirected + // the node ID is the index into + // nodes. + nodes []community + undirectedEdges + + // communities is the community + // structure of the graph. + communities [][]graph.Node + + parent *ReducedUndirected +} + +var ( + _ graph.Undirected = (*ReducedUndirected)(nil) + _ graph.Weighter = (*ReducedUndirected)(nil) + _ ReducedGraph = (*ReducedUndirected)(nil) +) + +// Communities returns the community memberships of the nodes in the +// graph used to generate the reduced graph. +func (g *ReducedUndirected) Communities() [][]graph.Node { + communities := make([][]graph.Node, len(g.communities)) + if g.parent == nil { + for i, members := range g.communities { + comm := make([]graph.Node, len(members)) + for j, n := range members { + nodes := g.nodes[n.ID()].nodes + if len(nodes) != 1 { + panic("community: unexpected number of nodes in base graph community") + } + comm[j] = nodes[0] + } + communities[i] = comm + } + return communities + } + sub := g.parent.Communities() + for i, members := range g.communities { + var comm []graph.Node + for _, n := range members { + comm = append(comm, sub[n.ID()]...) + } + communities[i] = comm + } + return communities +} + +// Structure returns the community structure of the current level of +// the module clustering. The first index of the returned value +// corresponds to the index of the nodes in the next higher level if +// it exists. The returned value should not be mutated. +func (g *ReducedUndirected) Structure() [][]graph.Node { + return g.communities +} + +// Expanded returns the next lower level of the module clustering or nil +// if at the lowest level. +func (g *ReducedUndirected) Expanded() ReducedGraph { + return g.parent +} + +// reduceUndirected returns a reduced graph constructed from g divided +// into the given communities. The communities value is mutated +// by the call to reduceUndirected. If communities is nil and g is a +// ReducedUndirected, it is returned unaltered. +func reduceUndirected(g graph.Undirected, communities [][]graph.Node) *ReducedUndirected { + if communities == nil { + if r, ok := g.(*ReducedUndirected); ok { + return r + } + + nodes := g.Nodes() + // TODO(kortschak) This sort is necessary really only + // for testing. In practice we would not be using the + // community provided by the user for a Q calculation. + // Probably we should use a function to map the + // communities in the test sets to the remapped order. + sort.Sort(ordered.ByID(nodes)) + communities = make([][]graph.Node, len(nodes)) + for i := range nodes { + communities[i] = []graph.Node{node(i)} + } + + weight := positiveWeightFuncFor(g) + r := ReducedUndirected{ + nodes: make([]community, len(nodes)), + undirectedEdges: undirectedEdges{ + edges: make([][]int, len(nodes)), + weights: make(map[[2]int]float64), + }, + communities: communities, + } + communityOf := make(map[int]int, len(nodes)) + for i, n := range nodes { + r.nodes[i] = community{id: i, nodes: []graph.Node{n}} + communityOf[n.ID()] = i + } + for _, u := range nodes { + var out []int + uid := communityOf[u.ID()] + for _, v := range g.From(u) { + vid := communityOf[v.ID()] + if vid != uid { + out = append(out, vid) + } + if uid < vid { + // Only store the weight once. + r.weights[[2]int{uid, vid}] = weight(u, v) + } + } + r.edges[uid] = out + } + return &r + } + + // Remove zero length communities destructively. + var commNodes int + for i := 0; i < len(communities); { + comm := communities[i] + if len(comm) == 0 { + communities[i] = communities[len(communities)-1] + communities[len(communities)-1] = nil + communities = communities[:len(communities)-1] + } else { + commNodes += len(comm) + i++ + } + } + + r := ReducedUndirected{ + nodes: make([]community, len(communities)), + undirectedEdges: undirectedEdges{ + edges: make([][]int, len(communities)), + weights: make(map[[2]int]float64), + }, + } + r.communities = make([][]graph.Node, len(communities)) + for i := range r.communities { + r.communities[i] = []graph.Node{node(i)} + } + if g, ok := g.(*ReducedUndirected); ok { + // Make sure we retain the truncated + // community structure. + g.communities = communities + r.parent = g + } + weight := positiveWeightFuncFor(g) + communityOf := make(map[int]int, commNodes) + for i, comm := range communities { + r.nodes[i] = community{id: i, nodes: comm} + for _, n := range comm { + communityOf[n.ID()] = i + } + } + for uid, comm := range communities { + var out []int + for i, u := range comm { + r.nodes[uid].weight += weight(u, u) + for _, v := range comm[i+1:] { + r.nodes[uid].weight += 2 * weight(u, v) + } + for _, v := range g.From(u) { + vid := communityOf[v.ID()] + found := false + for _, e := range out { + if e == vid { + found = true + break + } + } + if !found && vid != uid { + out = append(out, vid) + } + if uid < vid { + // Only store the weight once. + r.weights[[2]int{uid, vid}] += weight(u, v) + } + } + } + r.edges[uid] = out + } + return &r +} + +// Has returns whether the node exists within the graph. +func (g *ReducedUndirected) Has(n graph.Node) bool { + id := n.ID() + return id >= 0 || id < len(g.nodes) +} + +// Nodes returns all the nodes in the graph. +func (g *ReducedUndirected) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + for i := range g.nodes { + nodes[i] = node(i) + } + return nodes +} + +// From returns all nodes in g that can be reached directly from u. +func (g *ReducedUndirected) From(u graph.Node) []graph.Node { + out := g.edges[u.ID()] + nodes := make([]graph.Node, len(out)) + for i, vid := range out { + nodes[i] = g.nodes[vid] + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *ReducedUndirected) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if xid == yid { + return false + } + if xid > yid { + xid, yid = yid, xid + } + _, ok := g.weights[[2]int{xid, yid}] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *ReducedUndirected) Edge(u, v graph.Node) graph.Edge { + uid := u.ID() + vid := v.ID() + if vid < uid { + uid, vid = vid, uid + } + w, ok := g.weights[[2]int{uid, vid}] + if !ok { + return nil + } + return edge{from: g.nodes[u.ID()], to: g.nodes[v.ID()], weight: w} +} + +// EdgeBetween returns the edge between nodes x and y. +func (g *ReducedUndirected) EdgeBetween(x, y graph.Node) graph.Edge { + return g.Edge(x, y) +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *ReducedUndirected) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.nodes[xid].weight, true + } + if xid > yid { + xid, yid = yid, xid + } + w, ok = g.weights[[2]int{xid, yid}] + return w, ok +} + +// undirectedLocalMover is a step in graph modularity optimization. +type undirectedLocalMover struct { + g *ReducedUndirected + + // nodes is the set of working nodes. + nodes []graph.Node + // edgeWeightOf is the weighted degree + // of each node indexed by ID. + edgeWeightOf []float64 + + // m2 is the total sum of + // edge weights in g. + m2 float64 + + // weight is the weight function + // provided by g or a function + // that returns the Weight value + // of the non-nil edge between x + // and y. + weight func(x, y graph.Node) float64 + + // communities is the current + // division of g. + communities [][]graph.Node + // memberships is a mapping between + // node ID and community membership. + memberships []int + + // resolution is the Reichardt and + // Bornholdt γ parameter as defined + // in doi:10.1103/PhysRevE.74.016110. + resolution float64 + + // moved indicates that a call to + // move has been made since the last + // call to shuffle. + moved bool + + // changed indicates that a move + // has been made since the creation + // of the local mover. + changed bool +} + +// newUndirectedLocalMover returns a new undirectedLocalMover initialized with +// the graph g, a set of communities and a modularity resolution parameter. The +// node IDs of g must be contiguous in [0,n) where n is the number of nodes. +// If g has a zero edge weight sum, nil is returned. +func newUndirectedLocalMover(g *ReducedUndirected, communities [][]graph.Node, resolution float64) *undirectedLocalMover { + nodes := g.Nodes() + l := undirectedLocalMover{ + g: g, + nodes: nodes, + edgeWeightOf: make([]float64, len(nodes)), + communities: communities, + memberships: make([]int, len(nodes)), + resolution: resolution, + weight: positiveWeightFuncFor(g), + } + + // Calculate the total edge weight of the graph + // and degree weights for each node. + for _, u := range l.nodes { + w := l.weight(u, u) + for _, v := range g.From(u) { + w += l.weight(u, v) + } + l.edgeWeightOf[u.ID()] = w + l.m2 += w + } + if l.m2 == 0 { + return nil + } + + // Assign membership mappings. + for i, c := range communities { + for _, u := range c { + l.memberships[u.ID()] = i + } + } + + return &l +} + +// localMovingHeuristic performs the Louvain local moving heuristic until +// no further moves can be made. It returns a boolean indicating that the +// undirectedLocalMover has not made any improvement to the community +// structure and so the Louvain algorithm is done. +func (l *undirectedLocalMover) localMovingHeuristic(rnd func(int) int) (done bool) { + for { + l.shuffle(rnd) + for _, n := range l.nodes { + dQ, dst, src := l.deltaQ(n) + if dQ <= 0 { + continue + } + l.move(dst, src) + } + if !l.moved { + return !l.changed + } + } +} + +// shuffle performs a Fisher-Yates shuffle on the nodes held by the +// undirectedLocalMover using the random source rnd which should return +// an integer in the range [0,n). +func (l *undirectedLocalMover) shuffle(rnd func(n int) int) { + l.moved = false + for i := range l.nodes[:len(l.nodes)-1] { + j := i + rnd(len(l.nodes)-i) + l.nodes[i], l.nodes[j] = l.nodes[j], l.nodes[i] + } +} + +// move moves the node at src to the community at dst. +func (l *undirectedLocalMover) move(dst int, src commIdx) { + l.moved = true + l.changed = true + + srcComm := l.communities[src.community] + n := srcComm[src.node] + + l.memberships[n.ID()] = dst + + l.communities[dst] = append(l.communities[dst], n) + srcComm[src.node], srcComm[len(srcComm)-1] = srcComm[len(srcComm)-1], nil + l.communities[src.community] = srcComm[:len(srcComm)-1] +} + +// deltaQ returns the highest gain in modularity attainable by moving +// n from its current community to another connected community and +// the index of the chosen destination. The index into the +// undirectedLocalMover's communities field is returned in src if n +// is in communities. +func (l *undirectedLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, src commIdx) { + id := n.ID() + a_aa := l.weight(n, n) + k_a := l.edgeWeightOf[id] + m2 := l.m2 + gamma := l.resolution + + // Find communites connected to n. + var connected intsets.Sparse + // The following for loop is equivalent to: + // + // for _, v := range l.g.From(n) { + // connected.Insert(l.memberships[v.ID()]) + // } + // + // This is done to avoid an allocation. + for _, vid := range l.g.edges[id] { + connected.Insert(l.memberships[vid]) + } + // Insert the node's own community. + connected.Insert(l.memberships[id]) + + // Calculate the highest modularity gain + // from moving into another community and + // keep the index of that community. + var dQremove float64 + dQadd, dst, src := math.Inf(-1), -1, commIdx{-1, -1} + var i int + for connected.TakeMin(&i) { + c := l.communities[i] + var k_aC, sigma_totC float64 // C is a substitution for ^𝛼 or ^𝛽. + var removal bool + for j, u := range c { + uid := u.ID() + if uid == id { + if src.community != -1 { + panic("community: multiple sources") + } + src = commIdx{i, j} + removal = true + } + + k_aC += l.weight(n, u) + // sigma_totC could be kept for each community + // and updated for moves, changing the calculation + // of sigma_totC here from O(n_c) to O(1), but + // in practice the time savings do not appear + // to be compelling and do not make up for the + // increase in code complexity and space required. + sigma_totC += l.edgeWeightOf[uid] + } + + // See louvain.tex for a derivation of these equations. + switch { + case removal: + // The community c was the current community, + // so calculate the change due to removal. + dQremove = k_aC /*^𝛼*/ - a_aa - gamma*k_a*(sigma_totC /*^𝛼*/ -k_a)/m2 + + default: + // Otherwise calculate the change due to an addition + // to c and retain if it is the current best. + dQ := k_aC /*^𝛽*/ - gamma*k_a*sigma_totC /*^𝛽*/ /m2 + if dQ > dQadd { + dQadd = dQ + dst = i + } + } + } + + return 2 * (dQadd - dQremove) / m2, dst, src +} diff --git a/graph/community/louvain_undirected_multiplex.go b/graph/community/louvain_undirected_multiplex.go new file mode 100644 index 00000000..cad5eb4e --- /dev/null +++ b/graph/community/louvain_undirected_multiplex.go @@ -0,0 +1,811 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "fmt" + "math" + "math/rand" + "sort" + + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +// UndirectedMultiplex is an undirected multiplex graph. +type UndirectedMultiplex interface { + Multiplex + + // Layer returns the lth layer of the + // multiplex graph. + Layer(l int) graph.Undirected +} + +// qUndirectedMultiplex returns the modularity Q score of the multiplex graph layers +// subdivided into the given communities at the given resolutions and weights. Q is +// returned as the vector of weighted Q scores for each layer of the multiplex graph. +// If communities is nil, the unclustered modularity score is returned. +// If weights is nil layers are equally weighted, otherwise the length of +// weights must equal the number of layers. If resolutions is nil, a resolution +// of 1.0 is used for all layers, otherwise either a single element slice may be used +// to specify a global resolution, or the length of resolutions must equal the number +// of layers. The resolution parameter is γ as defined in Reichardt and Bornholdt +// doi:10.1103/PhysRevE.74.016110. +// qUndirectedMultiplex will panic if the graph has any layer weight-scaled edge with +// negative edge weight. +// +// Q_{layer} = w_{layer} \sum_{ij} [ A_{layer}*_{ij} - (\gamma_{layer} k_i k_j)/2m ] \delta(c_i,c_j) +// +// Note that Q values for multiplex graphs are not scaled by the total layer edge weight. +// +// graph.Undirect may be used as a shim to allow calculation of Q for +// directed graphs. +func qUndirectedMultiplex(g UndirectedMultiplex, communities [][]graph.Node, weights, resolutions []float64) []float64 { + q := make([]float64, g.Depth()) + nodes := g.Nodes() + layerWeight := 1.0 + layerResolution := 1.0 + if len(resolutions) == 1 { + layerResolution = resolutions[0] + } + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + + if weights != nil { + layerWeight = weights[l] + } + if layerWeight == 0 { + continue + } + + if len(resolutions) > 1 { + layerResolution = resolutions[l] + } + + var weight func(x, y graph.Node) float64 + if layerWeight < 0 { + weight = negativeWeightFuncFor(layer) + } else { + weight = positiveWeightFuncFor(layer) + } + + // Calculate the total edge weight of the layer + // and the table of penetrating edge weight sums. + var m2 float64 + k := make(map[int]float64, len(nodes)) + for _, u := range nodes { + w := weight(u, u) + for _, v := range layer.From(u) { + w += weight(u, v) + } + m2 += w + k[u.ID()] = w + } + + if communities == nil { + var qLayer float64 + for _, u := range nodes { + kU := k[u.ID()] + qLayer += weight(u, u) - layerResolution*kU*kU/m2 + } + q[l] = layerWeight * qLayer + continue + } + + // Iterate over the communities, calculating + // the non-self edge weights for the upper + // triangle and adjust the diagonal. + var qLayer float64 + for _, c := range communities { + for i, u := range c { + kU := k[u.ID()] + qLayer += weight(u, u) - layerResolution*kU*kU/m2 + for _, v := range c[i+1:] { + qLayer += 2 * (weight(u, v) - layerResolution*kU*k[v.ID()]/m2) + } + } + } + q[l] = layerWeight * qLayer + } + + return q +} + +// UndirectedLayers implements UndirectedMultiplex. +type UndirectedLayers []graph.Undirected + +// NewUndirectedLayers returns an UndirectedLayers using the provided layers +// ensuring there is a match between IDs for each layer. +func NewUndirectedLayers(layers ...graph.Undirected) (UndirectedLayers, error) { + if len(layers) == 0 { + return nil, nil + } + var base, next intsets.Sparse + for _, n := range layers[0].Nodes() { + base.Insert(n.ID()) + } + for i, l := range layers[1:] { + next.Clear() + for _, n := range l.Nodes() { + next.Insert(n.ID()) + } + if !next.Equals(&base) { + return nil, fmt.Errorf("community: layer ID mismatch between layers: %d", i+1) + } + } + return layers, nil +} + +// Nodes returns the nodes of the receiver. +func (g UndirectedLayers) Nodes() []graph.Node { + if len(g) == 0 { + return nil + } + return g[0].Nodes() +} + +// Depth returns the depth of the multiplex graph. +func (g UndirectedLayers) Depth() int { return len(g) } + +// Layer returns the lth layer of the multiplex graph. +func (g UndirectedLayers) Layer(l int) graph.Undirected { return g[l] } + +// louvainUndirectedMultiplex returns the hierarchical modularization of g at the given resolution +// using the Louvain algorithm. If all is true and g has negatively weighted layers, all +// communities will be searched during the modularization. If src is nil, rand.Intn is +// used as the random generator. louvainUndirectedMultiplex will panic if g has any edge with +// edge weight that does not sign-match the layer weight. +// +// graph.Undirect may be used as a shim to allow modularization of directed graphs. +func louvainUndirectedMultiplex(g UndirectedMultiplex, weights, resolutions []float64, all bool, src *rand.Rand) *ReducedUndirectedMultiplex { + if weights != nil && len(weights) != g.Depth() { + panic("community: weights vector length mismatch") + } + if resolutions != nil && len(resolutions) != 1 && len(resolutions) != g.Depth() { + panic("community: resolutions vector length mismatch") + } + + // See louvain.tex for a detailed description + // of the algorithm used here. + + c := reduceUndirectedMultiplex(g, nil, weights) + rnd := rand.Intn + if src != nil { + rnd = src.Intn + } + for { + l := newUndirectedMultiplexLocalMover(c, c.communities, weights, resolutions, all) + if l == nil { + return c + } + if done := l.localMovingHeuristic(rnd); done { + return c + } + c = reduceUndirectedMultiplex(c, l.communities, weights) + } +} + +// ReducedUndirectedMultiplex is an undirected graph of communities derived from a +// parent graph by reduction. +type ReducedUndirectedMultiplex struct { + // nodes is the set of nodes held + // by the graph. In a ReducedUndirectedMultiplex + // the node ID is the index into + // nodes. + nodes []multiplexCommunity + layers []undirectedEdges + + // communities is the community + // structure of the graph. + communities [][]graph.Node + + parent *ReducedUndirectedMultiplex +} + +var ( + _ UndirectedMultiplex = (*ReducedUndirectedMultiplex)(nil) + _ graph.Undirected = (*undirectedLayerHandle)(nil) + _ graph.Weighter = (*undirectedLayerHandle)(nil) +) + +// Nodes returns all the nodes in the graph. +func (g *ReducedUndirectedMultiplex) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + for i := range g.nodes { + nodes[i] = node(i) + } + return nodes +} + +// Depth returns the number of layers in the multiplex graph. +func (g *ReducedUndirectedMultiplex) Depth() int { return len(g.layers) } + +// Layer returns the lth layer of the multiplex graph. +func (g *ReducedUndirectedMultiplex) Layer(l int) graph.Undirected { + return undirectedLayerHandle{multiplex: g, layer: l} +} + +// Communities returns the community memberships of the nodes in the +// graph used to generate the reduced graph. +func (g *ReducedUndirectedMultiplex) Communities() [][]graph.Node { + communities := make([][]graph.Node, len(g.communities)) + if g.parent == nil { + for i, members := range g.communities { + comm := make([]graph.Node, len(members)) + for j, n := range members { + nodes := g.nodes[n.ID()].nodes + if len(nodes) != 1 { + panic("community: unexpected number of nodes in base graph community") + } + comm[j] = nodes[0] + } + communities[i] = comm + } + return communities + } + sub := g.parent.Communities() + for i, members := range g.communities { + var comm []graph.Node + for _, n := range members { + comm = append(comm, sub[n.ID()]...) + } + communities[i] = comm + } + return communities +} + +// Structure returns the community structure of the current level of +// the module clustering. The first index of the returned value +// corresponds to the index of the nodes in the next higher level if +// it exists. The returned value should not be mutated. +func (g *ReducedUndirectedMultiplex) Structure() [][]graph.Node { + return g.communities +} + +// Expanded returns the next lower level of the module clustering or nil +// if at the lowest level. +func (g *ReducedUndirectedMultiplex) Expanded() ReducedMultiplex { + return g.parent +} + +// reduceUndirectedMultiplex returns a reduced graph constructed from g divided +// into the given communities. The communities value is mutated +// by the call to reduceUndirectedMultiplex. If communities is nil and g is a +// ReducedUndirectedMultiplex, it is returned unaltered. +func reduceUndirectedMultiplex(g UndirectedMultiplex, communities [][]graph.Node, weights []float64) *ReducedUndirectedMultiplex { + if communities == nil { + if r, ok := g.(*ReducedUndirectedMultiplex); ok { + return r + } + + nodes := g.Nodes() + // TODO(kortschak) This sort is necessary really only + // for testing. In practice we would not be using the + // community provided by the user for a Q calculation. + // Probably we should use a function to map the + // communities in the test sets to the remapped order. + sort.Sort(ordered.ByID(nodes)) + communities = make([][]graph.Node, len(nodes)) + for i := range nodes { + communities[i] = []graph.Node{node(i)} + } + + r := ReducedUndirectedMultiplex{ + nodes: make([]multiplexCommunity, len(nodes)), + layers: make([]undirectedEdges, g.Depth()), + communities: communities, + } + communityOf := make(map[int]int, len(nodes)) + for i, n := range nodes { + r.nodes[i] = multiplexCommunity{id: i, nodes: []graph.Node{n}, weights: make([]float64, depth(weights))} + communityOf[n.ID()] = i + } + for i := range r.layers { + r.layers[i] = undirectedEdges{ + edges: make([][]int, len(nodes)), + weights: make(map[[2]int]float64), + } + } + w := 1.0 + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + if weights != nil { + w = weights[l] + } + if w == 0 { + continue + } + var sign float64 + var weight func(x, y graph.Node) float64 + if w < 0 { + sign, weight = -1, negativeWeightFuncFor(layer) + } else { + sign, weight = 1, positiveWeightFuncFor(layer) + } + for _, u := range nodes { + var out []int + uid := communityOf[u.ID()] + for _, v := range layer.From(u) { + vid := communityOf[v.ID()] + if vid != uid { + out = append(out, vid) + } + if uid < vid { + // Only store the weight once. + r.layers[l].weights[[2]int{uid, vid}] = sign * weight(u, v) + } + } + r.layers[l].edges[uid] = out + } + } + return &r + } + + // Remove zero length communities destructively. + var commNodes int + for i := 0; i < len(communities); { + comm := communities[i] + if len(comm) == 0 { + communities[i] = communities[len(communities)-1] + communities[len(communities)-1] = nil + communities = communities[:len(communities)-1] + } else { + commNodes += len(comm) + i++ + } + } + + r := ReducedUndirectedMultiplex{ + nodes: make([]multiplexCommunity, len(communities)), + layers: make([]undirectedEdges, g.Depth()), + } + communityOf := make(map[int]int, commNodes) + for i, comm := range communities { + r.nodes[i] = multiplexCommunity{id: i, nodes: comm, weights: make([]float64, depth(weights))} + for _, n := range comm { + communityOf[n.ID()] = i + } + } + for i := range r.layers { + r.layers[i] = undirectedEdges{ + edges: make([][]int, len(communities)), + weights: make(map[[2]int]float64), + } + } + r.communities = make([][]graph.Node, len(communities)) + for i := range r.communities { + r.communities[i] = []graph.Node{node(i)} + } + if g, ok := g.(*ReducedUndirectedMultiplex); ok { + // Make sure we retain the truncated + // community structure. + g.communities = communities + r.parent = g + } + w := 1.0 + for l := 0; l < g.Depth(); l++ { + layer := g.Layer(l) + if weights != nil { + w = weights[l] + } + if w == 0 { + continue + } + var sign float64 + var weight func(x, y graph.Node) float64 + if w < 0 { + sign, weight = -1, negativeWeightFuncFor(layer) + } else { + sign, weight = 1, positiveWeightFuncFor(layer) + } + for uid, comm := range communities { + var out []int + for i, u := range comm { + r.nodes[uid].weights[l] += sign * weight(u, u) + for _, v := range comm[i+1:] { + r.nodes[uid].weights[l] += 2 * sign * weight(u, v) + } + for _, v := range layer.From(u) { + vid := communityOf[v.ID()] + found := false + for _, e := range out { + if e == vid { + found = true + break + } + } + if !found && vid != uid { + out = append(out, vid) + } + if uid < vid { + // Only store the weight once. + r.layers[l].weights[[2]int{uid, vid}] += sign * weight(u, v) + } + } + } + r.layers[l].edges[uid] = out + } + } + return &r +} + +// undirectedLayerHandle is a handle to a multiplex graph layer. +type undirectedLayerHandle struct { + // multiplex is the complete + // multiplex graph. + multiplex *ReducedUndirectedMultiplex + + // layer is an index into the + // multiplex for the current + // layer. + layer int +} + +// Has returns whether the node exists within the graph. +func (g undirectedLayerHandle) Has(n graph.Node) bool { + id := n.ID() + return id >= 0 || id < len(g.multiplex.nodes) +} + +// Nodes returns all the nodes in the graph. +func (g undirectedLayerHandle) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.multiplex.nodes)) + for i := range g.multiplex.nodes { + nodes[i] = node(i) + } + return nodes +} + +// From returns all nodes in g that can be reached directly from u. +func (g undirectedLayerHandle) From(u graph.Node) []graph.Node { + out := g.multiplex.layers[g.layer].edges[u.ID()] + nodes := make([]graph.Node, len(out)) + for i, vid := range out { + nodes[i] = g.multiplex.nodes[vid] + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g undirectedLayerHandle) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if xid == yid { + return false + } + if xid > yid { + xid, yid = yid, xid + } + _, ok := g.multiplex.layers[g.layer].weights[[2]int{xid, yid}] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g undirectedLayerHandle) Edge(u, v graph.Node) graph.Edge { + uid := u.ID() + vid := v.ID() + if vid < uid { + uid, vid = vid, uid + } + w, ok := g.multiplex.layers[g.layer].weights[[2]int{uid, vid}] + if !ok { + return nil + } + return multiplexEdge{from: g.multiplex.nodes[u.ID()], to: g.multiplex.nodes[v.ID()], weight: w} +} + +// EdgeBetween returns the edge between nodes x and y. +func (g undirectedLayerHandle) EdgeBetween(x, y graph.Node) graph.Edge { + return g.Edge(x, y) +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g undirectedLayerHandle) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.multiplex.nodes[xid].weights[g.layer], true + } + if xid > yid { + xid, yid = yid, xid + } + w, ok = g.multiplex.layers[g.layer].weights[[2]int{xid, yid}] + return w, ok +} + +// undirectedMultiplexLocalMover is a step in graph modularity optimization. +type undirectedMultiplexLocalMover struct { + g *ReducedUndirectedMultiplex + + // nodes is the set of working nodes. + nodes []graph.Node + // edgeWeightOf is the weighted degree + // of each node indexed by ID. + edgeWeightOf [][]float64 + + // m2 is the total sum of + // edge weights in g. + m2 []float64 + + // weight is the weight function + // provided by g or a function + // that returns the Weight value + // of the non-nil edge between x + // and y. + weight []func(x, y graph.Node) float64 + + // communities is the current + // division of g. + communities [][]graph.Node + // memberships is a mapping between + // node ID and community membership. + memberships []int + + // resolution is the Reichardt and + // Bornholdt γ parameter as defined + // in doi:10.1103/PhysRevE.74.016110. + resolutions []float64 + + // weights is the layer weights for + // the modularisation. + weights []float64 + + // searchAll specifies whether the local + // mover should consider non-connected + // communities during the local moving + // heuristic. + searchAll bool + + // moved indicates that a call to + // move has been made since the last + // call to shuffle. + moved bool + + // changed indicates that a move + // has been made since the creation + // of the local mover. + changed bool +} + +// newUndirectedMultiplexLocalMover returns a new undirectedMultiplexLocalMover initialized with +// the graph g, a set of communities and a modularity resolution parameter. The +// node IDs of g must be contiguous in [0,n) where n is the number of nodes. +// If g has a zero edge weight sum, nil is returned. +func newUndirectedMultiplexLocalMover(g *ReducedUndirectedMultiplex, communities [][]graph.Node, weights, resolutions []float64, all bool) *undirectedMultiplexLocalMover { + nodes := g.Nodes() + l := undirectedMultiplexLocalMover{ + g: g, + nodes: nodes, + edgeWeightOf: make([][]float64, g.Depth()), + m2: make([]float64, g.Depth()), + communities: communities, + memberships: make([]int, len(nodes)), + resolutions: resolutions, + weights: weights, + weight: make([]func(x, y graph.Node) float64, g.Depth()), + } + + // Calculate the total edge weight of the graph + // and degree weights for each node. + var zero int + for i := 0; i < g.Depth(); i++ { + l.edgeWeightOf[i] = make([]float64, len(nodes)) + var weight func(x, y graph.Node) float64 + + if weights != nil { + if weights[i] == 0 { + zero++ + continue + } + if weights[i] < 0 { + weight = negativeWeightFuncFor(g.Layer(i)) + l.searchAll = all + } else { + weight = positiveWeightFuncFor(g.Layer(i)) + } + } else { + weight = positiveWeightFuncFor(g.Layer(i)) + } + + l.weight[i] = weight + layer := g.Layer(i) + for _, u := range l.nodes { + w := weight(u, u) + for _, v := range layer.From(u) { + w += weight(u, v) + } + l.edgeWeightOf[i][u.ID()] = w + l.m2[i] += w + } + if l.m2[i] == 0 { + zero++ + } + } + if zero == g.Depth() { + return nil + } + + // Assign membership mappings. + for i, c := range communities { + for _, u := range c { + l.memberships[u.ID()] = i + } + } + + return &l +} + +// localMovingHeuristic performs the Louvain local moving heuristic until +// no further moves can be made. It returns a boolean indicating that the +// undirectedMultiplexLocalMover has not made any improvement to the community +// structure and so the Louvain algorithm is done. +func (l *undirectedMultiplexLocalMover) localMovingHeuristic(rnd func(int) int) (done bool) { + for { + l.shuffle(rnd) + for _, n := range l.nodes { + dQ, dst, src := l.deltaQ(n) + if dQ <= 0 { + continue + } + l.move(dst, src) + } + if !l.moved { + return !l.changed + } + } +} + +// shuffle performs a Fisher-Yates shuffle on the nodes held by the +// undirectedMultiplexLocalMover using the random source rnd which should return +// an integer in the range [0,n). +func (l *undirectedMultiplexLocalMover) shuffle(rnd func(n int) int) { + l.moved = false + for i := range l.nodes[:len(l.nodes)-1] { + j := i + rnd(len(l.nodes)-i) + l.nodes[i], l.nodes[j] = l.nodes[j], l.nodes[i] + } +} + +// move moves the node at src to the community at dst. +func (l *undirectedMultiplexLocalMover) move(dst int, src commIdx) { + l.moved = true + l.changed = true + + srcComm := l.communities[src.community] + n := srcComm[src.node] + + l.memberships[n.ID()] = dst + + l.communities[dst] = append(l.communities[dst], n) + srcComm[src.node], srcComm[len(srcComm)-1] = srcComm[len(srcComm)-1], nil + l.communities[src.community] = srcComm[:len(srcComm)-1] +} + +// deltaQ returns the highest gain in modularity attainable by moving +// n from its current community to another connected community and +// the index of the chosen destination. The index into the +// undirectedMultiplexLocalMover's communities field is returned in src if n +// is in communities. +func (l *undirectedMultiplexLocalMover) deltaQ(n graph.Node) (deltaQ float64, dst int, src commIdx) { + id := n.ID() + + var iterator minTaker + if l.searchAll { + iterator = &dense{n: len(l.communities)} + } else { + // Find communities connected to n. + var connected intsets.Sparse + // The following for loop is equivalent to: + // + // for i := 0; i < l.g.Depth(); i++ { + // for _, v := range l.g.Layer(i).From(n) { + // connected.Insert(l.memberships[v.ID()]) + // } + // } + // + // This is done to avoid an allocation for + // each layer. + for _, layer := range l.g.layers { + for _, vid := range layer.edges[id] { + connected.Insert(l.memberships[vid]) + } + } + // Insert the node's own community. + connected.Insert(l.memberships[id]) + iterator = &connected + } + + // Calculate the highest modularity gain + // from moving into another community and + // keep the index of that community. + var dQremove float64 + dQadd, dst, src := math.Inf(-1), -1, commIdx{-1, -1} + var i int + for iterator.TakeMin(&i) { + c := l.communities[i] + var removal bool + var _dQadd float64 + for layer := 0; layer < l.g.Depth(); layer++ { + m2 := l.m2[layer] + if m2 == 0 { + // Do not consider layers with zero sum edge weight. + continue + } + w := 1.0 + if l.weights != nil { + w = l.weights[layer] + } + if w == 0 { + // Do not consider layers with zero weighting. + continue + } + + var k_aC, sigma_totC float64 // C is a substitution for ^𝛼 or ^𝛽. + removal = false + for j, u := range c { + uid := u.ID() + if uid == id { + // Only mark and check src community on the first layer. + if layer == 0 { + if src.community != -1 { + panic("community: multiple sources") + } + src = commIdx{i, j} + } + removal = true + } + + k_aC += l.weight[layer](n, u) + // sigma_totC could be kept for each community + // and updated for moves, changing the calculation + // of sigma_totC here from O(n_c) to O(1), but + // in practice the time savings do not appear + // to be compelling and do not make up for the + // increase in code complexity and space required. + sigma_totC += l.edgeWeightOf[layer][uid] + } + + a_aa := l.weight[layer](n, n) + k_a := l.edgeWeightOf[layer][id] + gamma := 1.0 + if l.resolutions != nil { + if len(l.resolutions) == 1 { + gamma = l.resolutions[0] + } else { + gamma = l.resolutions[layer] + } + } + + // See louvain.tex for a derivation of these equations. + // The weighting term, w, is described in V Traag, + // "Algorithms and dynamical models for communities and + // reputation in social networks", chapter 5. + // http://www.traag.net/wp/wp-content/papercite-data/pdf/traag_algorithms_2013.pdf + switch { + case removal: + // The community c was the current community, + // so calculate the change due to removal. + dQremove += w * (k_aC /*^𝛼*/ - a_aa - gamma*k_a*(sigma_totC /*^𝛼*/ -k_a)/m2) + + default: + // Otherwise calculate the change due to an addition + // to c. + _dQadd += w * (k_aC /*^𝛽*/ - gamma*k_a*sigma_totC /*^𝛽*/ /m2) + } + } + if !removal && _dQadd > dQadd { + dQadd = _dQadd + dst = i + } + } + + return 2 * (dQadd - dQremove), dst, src +} diff --git a/graph/community/louvain_undirected_multiplex_test.go b/graph/community/louvain_undirected_multiplex_test.go new file mode 100644 index 00000000..101726f3 --- /dev/null +++ b/graph/community/louvain_undirected_multiplex_test.go @@ -0,0 +1,669 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "math" + "math/rand" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var communityUndirectedMultiplexQTests = []struct { + name string + layers []layer + structures []structure + + wantLevels []level +}{ + { + name: "unconnected", + layers: []layer{{g: unconnected, weight: 1}}, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: math.NaN(), + }, + }, + wantLevels: []level{ + { + q: math.Inf(-1), // Here math.Inf(-1) is used as a place holder for NaN to allow use of reflect.DeepEqual. + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "small_dumbell", + layers: []layer{ + {g: smallDumbell, edgeWeight: 1, weight: 1}, + {g: dumbellRepulsion, edgeWeight: -1, weight: -1}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 7.0, tol: 1e-10, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 4, 5), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 7.0, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: -1.4285714285714284, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "small_dumbell_twice", + layers: []layer{ + {g: smallDumbell, weight: 0.5}, + {g: smallDumbell, weight: 0.5}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 5, tol: 1e-10, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 4, 5), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 0.35714285714285715 * 14, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: -0.17346938775510204 * 14, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "repulsion", + layers: []layer{{g: repulsion, edgeWeight: -1, weight: -1}}, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 9.0, tol: 1e-10, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: 3, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 9.0, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: 3.0, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "middle_east", + layers: []layer{ + {g: middleEast.friends, edgeWeight: 1, weight: 1}, + {g: middleEast.enemies, edgeWeight: -1, weight: -1}, + }, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 6), + 1: linksTo(1, 7, 9, 12), + 2: linksTo(2, 8, 11), + 3: linksTo(3, 4, 5, 10), + }, + want: 33.8180574555, tol: 1e-9, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 2, 3, 4, 5, 10), + 1: linksTo(1, 7, 9, 12), + 2: linksTo(6), + 3: linksTo(8, 11), + }, + want: 30.92749658, tol: 1e-7, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), + }, + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 33.818057455540355, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(6)}, + {simple.Node(1), simple.Node(7), simple.Node(9), simple.Node(12)}, + {simple.Node(2), simple.Node(8), simple.Node(11)}, + {simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(10)}, + }, + }, + { + q: 3.8071135430916545, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + }, + }, + }, + }, +} + +func TestCommunityQUndirectedMultiplex(t *testing.T) { + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + } + q := QMultiplex(g, communities, weights, []float64{structure.resolution}) + got := floats.Sum(q) + if !floats.EqualWithinAbsOrRel(got, structure.want, structure.tol, structure.tol) && !math.IsNaN(structure.want) { + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + t.Errorf("unexpected Q value for %q %v: got: %v %.3v want: %v", + test.name, communities, got, q, structure.want) + } + } + } +} + +func TestCommunityDeltaQUndirectedMultiplex(t *testing.T) { +tests: + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + rnd := rand.New(rand.NewSource(1)).Intn + for _, structure := range test.structures { + communityOf := make(map[int]int) + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communityOf[n] = i + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + resolution := []float64{structure.resolution} + + before := QMultiplex(g, communities, weights, resolution) + + // We test exhaustively. + const all = true + + l := newUndirectedMultiplexLocalMover( + reduceUndirectedMultiplex(g, nil, weights), + communities, weights, resolution, all) + if l == nil { + if !math.IsNaN(floats.Sum(before)) { + t.Errorf("unexpected nil localMover with non-NaN Q graph: Q=%.4v", before) + } + continue tests + } + + // This is done to avoid run-to-run + // variation due to map iteration order. + sort.Sort(ordered.ByID(l.nodes)) + + l.shuffle(rnd) + + for _, target := range l.nodes { + got, gotDst, gotSrc := l.deltaQ(target) + + want, wantDst := math.Inf(-1), -1 + migrated := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + if n == target.ID() { + continue + } + migrated[i] = append(migrated[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(migrated[i])) + } + + for i, c := range structure.memberships { + if i == communityOf[target.ID()] { + continue + } + if !(all && hasNegative(weights)) { + connected := false + search: + for l := 0; l < g.Depth(); l++ { + if weights[l] < 0 { + connected = true + break search + } + layer := g.Layer(l) + for n := range c { + if layer.HasEdgeBetween(simple.Node(n), target) { + connected = true + break search + } + } + } + if !connected { + continue + } + } + migrated[i] = append(migrated[i], target) + after := QMultiplex(g, migrated, weights, resolution) + migrated[i] = migrated[i][:len(migrated[i])-1] + if delta := floats.Sum(after) - floats.Sum(before); delta > want { + want = delta + wantDst = i + } + } + + if !floats.EqualWithinAbsOrRel(got, want, structure.tol, structure.tol) || gotDst != wantDst { + t.Errorf("unexpected result moving n=%d in c=%d of %s/%.4v: got: %.4v,%d want: %.4v,%d"+ + "\n\t%v\n\t%v", + target.ID(), communityOf[target.ID()], test.name, structure.resolution, got, gotDst, want, wantDst, + communities, migrated) + } + if gotSrc.community != communityOf[target.ID()] { + t.Errorf("unexpected source community index: got: %d want: %d", gotSrc, communityOf[target.ID()]) + } else if communities[gotSrc.community][gotSrc.node].ID() != target.ID() { + wantNodeIdx := -1 + for i, n := range communities[gotSrc.community] { + if n.ID() == target.ID() { + wantNodeIdx = i + break + } + } + t.Errorf("unexpected source node index: got: %d want: %d", gotSrc.node, wantNodeIdx) + } + } + } + } +} + +func TestReduceQConsistencyUndirectedMultiplex(t *testing.T) { +tests: + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + if math.IsNaN(structure.want) { + continue tests + } + + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + gQ := QMultiplex(g, communities, weights, []float64{structure.resolution}) + gQnull := QMultiplex(g, nil, weights, nil) + + cg0 := reduceUndirectedMultiplex(g, nil, weights) + cg0Qnull := QMultiplex(cg0, cg0.Structure(), weights, nil) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQnull), floats.Sum(cg0Qnull), structure.tol, structure.tol) { + t.Errorf("disagreement between null Q from method: %v and function: %v", cg0Qnull, gQnull) + } + cg0Q := QMultiplex(cg0, communities, weights, []float64{structure.resolution}) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQ), floats.Sum(cg0Q), structure.tol, structure.tol) { + t.Errorf("unexpected Q result after initial reduction: got: %v want :%v", cg0Q, gQ) + } + + cg1 := reduceUndirectedMultiplex(cg0, communities, weights) + cg1Q := QMultiplex(cg1, cg1.Structure(), weights, []float64{structure.resolution}) + if !floats.EqualWithinAbsOrRel(floats.Sum(gQ), floats.Sum(cg1Q), structure.tol, structure.tol) { + t.Errorf("unexpected Q result after second reduction: got: %v want :%v", cg1Q, gQ) + } + } + } +} + +var localUndirectedMultiplexMoveTests = []struct { + name string + layers []layer + structures []moveStructures +}{ + { + name: "blondel", + layers: []layer{{g: blondel, weight: 1}, {g: blondel, weight: 0.5}}, + structures: []moveStructures{ + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(0)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(3)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + // Case to demonstrate when A_aa != k_a^𝛼. + targetNodes: []graph.Node{simple.Node(3), simple.Node(2)}, + resolution: 1, + tol: 1e-14, + }, + }, + }, +} + +func TestMoveLocalUndirectedMultiplex(t *testing.T) { + for _, test := range localUndirectedMultiplexMoveTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + r := reduceUndirectedMultiplex(reduceUndirectedMultiplex(g, nil, weights), communities, weights) + + l := newUndirectedMultiplexLocalMover(r, r.communities, weights, []float64{structure.resolution}, true) + for _, n := range structure.targetNodes { + dQ, dst, src := l.deltaQ(n) + if dQ > 0 { + before := floats.Sum(QMultiplex(r, l.communities, weights, []float64{structure.resolution})) + l.move(dst, src) + after := floats.Sum(QMultiplex(r, l.communities, weights, []float64{structure.resolution})) + want := after - before + if !floats.EqualWithinAbsOrRel(dQ, want, structure.tol, structure.tol) { + t.Errorf("unexpected deltaQ: got: %v want: %v", dQ, want) + } + } + } + } + } +} + +func TestLouvainMultiplex(t *testing.T) { + const louvainIterations = 20 + + for _, test := range communityUndirectedMultiplexQTests { + g, weights, err := undirectedMultiplexFrom(test.layers) + if err != nil { + t.Errorf("unexpected error creating multiplex: %v", err) + continue + } + + if test.structures[0].resolution != 1 { + panic("bad test: expect resolution=1") + } + want := make([][]graph.Node, len(test.structures[0].memberships)) + for i, c := range test.structures[0].memberships { + for n := range c { + want[i] = append(want[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(want[i])) + } + sort.Sort(ordered.BySliceIDs(want)) + + var ( + got *ReducedUndirectedMultiplex + bestQ = math.Inf(-1) + ) + // Modularize is randomised so we do this to + // ensure the level tests are consistent. + src := rand.New(rand.NewSource(1)) + for i := 0; i < louvainIterations; i++ { + r := ModularizeMultiplex(g, weights, nil, true, src).(*ReducedUndirectedMultiplex) + if q := floats.Sum(QMultiplex(r, nil, weights, nil)); q > bestQ || math.IsNaN(q) { + bestQ = q + got = r + + if math.IsNaN(q) { + // Don't try again for non-connected case. + break + } + } + + var qs []float64 + for p := r; p != nil; p = p.Expanded().(*ReducedUndirectedMultiplex) { + qs = append(qs, floats.Sum(QMultiplex(p, nil, weights, nil))) + } + + // Recovery of Q values is reversed. + if reverse(qs); !sort.Float64sAreSorted(qs) { + t.Errorf("Q values not monotonically increasing: %.5v", qs) + } + } + + gotCommunities := got.Communities() + for _, c := range gotCommunities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(gotCommunities)) + if !reflect.DeepEqual(gotCommunities, want) { + t.Errorf("unexpected community membership for %s Q=%.4v:\n\tgot: %v\n\twant:%v", + test.name, bestQ, gotCommunities, want) + continue + } + + var levels []level + for p := got; p != nil; p = p.Expanded().(*ReducedUndirectedMultiplex) { + var communities [][]graph.Node + if p.parent != nil { + communities = p.parent.Communities() + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(communities)) + } else { + communities = reduceUndirectedMultiplex(g, nil, weights).Communities() + } + q := floats.Sum(QMultiplex(p, nil, weights, nil)) + if math.IsNaN(q) { + // Use an equalable flag value in place of NaN. + q = math.Inf(-1) + } + levels = append(levels, level{q: q, communities: communities}) + } + if !reflect.DeepEqual(levels, test.wantLevels) { + t.Errorf("unexpected level structure:\n\tgot: %v\n\twant:%v", levels, test.wantLevels) + } + } +} + +func TestNonContiguousUndirectedMultiplex(t *testing.T) { + g := simple.NewUndirectedGraph(0, 0) + for _, e := range []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(4), T: simple.Node(5), W: 1}, + } { + g.SetEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + ModularizeMultiplex(UndirectedLayers{g}, nil, nil, true, nil) + }() +} + +func BenchmarkLouvainMultiplex(b *testing.B) { + src := rand.New(rand.NewSource(1)) + for i := 0; i < b.N; i++ { + ModularizeMultiplex(UndirectedLayers{dupGraph}, nil, nil, true, src) + } +} + +func undirectedMultiplexFrom(raw []layer) (UndirectedLayers, []float64, error) { + var layers []graph.Undirected + var weights []float64 + for _, l := range raw { + g := simple.NewUndirectedGraph(0, 0) + for u, e := range l.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + w := 1.0 + if l.edgeWeight != 0 { + w = l.edgeWeight + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: w}) + } + } + layers = append(layers, g) + weights = append(weights, l.weight) + } + g, err := NewUndirectedLayers(layers...) + if err != nil { + return nil, nil, err + } + return g, weights, nil +} diff --git a/graph/community/louvain_undirected_test.go b/graph/community/louvain_undirected_test.go new file mode 100644 index 00000000..6315d8da --- /dev/null +++ b/graph/community/louvain_undirected_test.go @@ -0,0 +1,648 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package community + +import ( + "math" + "math/rand" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var communityUndirectedQTests = []struct { + name string + g []set + structures []structure + + wantLevels []level +}{ + // The java reference implementation is available from http://www.ludowaltman.nl/slm/. + { + name: "unconnected", + g: unconnected, + structures: []structure{ + { + resolution: 1, + memberships: []set{ + 0: linksTo(0), + 1: linksTo(1), + 2: linksTo(2), + 3: linksTo(3), + 4: linksTo(4), + 5: linksTo(5), + }, + want: math.NaN(), + }, + }, + wantLevels: []level{ + { + q: math.Inf(-1), // Here math.Inf(-1) is used as a place holder for NaN to allow use of reflect.DeepEqual. + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "small_dumbell", + g: smallDumbell, + structures: []structure{ + { + resolution: 1, + // community structure and modularity calculated by java reference implementation. + memberships: []set{ + 0: linksTo(0, 1, 2), + 1: linksTo(3, 4, 5), + }, + want: 0.357, tol: 1e-3, + }, + { + resolution: 1, + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 4, 5), + }, + // theoretical expectation. + want: 0, tol: 1e-14, + }, + }, + wantLevels: []level{ + { + q: 0.35714285714285715, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4), simple.Node(5)}, + }, + }, + { + q: -0.17346938775510204, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + }, + }, + }, + }, + { + name: "zachary", + g: zachary, + structures: []structure{ + { + resolution: 1, + // community structure and modularity from doi: 10.1140/epjb/e2013-40829-0 + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 7, 11, 12, 13, 17, 19, 21), + 1: linksTo(4, 5, 6, 10, 16), + 2: linksTo(8, 9, 14, 15, 18, 20, 22, 26, 29, 30, 32, 33), + 3: linksTo(23, 24, 25, 27, 28, 31), + }, + // Noted to be the optimal modularisation in the paper above. + want: 0.4198, tol: 1e-4, + }, + { + resolution: 0.5, + // community structure and modularity calculated by java reference implementation. + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 16, 17, 19, 21), + 1: linksTo(8, 14, 15, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33), + }, + want: 0.6218, tol: 1e-3, + }, + { + resolution: 2, + // community structure and modularity calculated by java reference implementation. + memberships: []set{ + 0: linksTo(14, 18, 20, 22, 32, 33, 15), + 1: linksTo(0, 1, 11, 17, 19, 21), + 2: linksTo(2, 3, 7, 9, 12, 13), + 3: linksTo(4, 5, 6, 10, 16), + 4: linksTo(24, 25, 28, 31), + 5: linksTo(23, 26, 27, 29), + 6: linksTo(8, 30), + }, + want: 0.1645, tol: 1e-3, + }, + }, + wantLevels: []level{ + { + q: 0.4197896120973044, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(7), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(17), simple.Node(19), simple.Node(21)}, + {simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(10), simple.Node(16)}, + {simple.Node(8), simple.Node(9), simple.Node(14), simple.Node(15), simple.Node(18), simple.Node(20), simple.Node(22), simple.Node(26), simple.Node(29), simple.Node(30), simple.Node(32), simple.Node(33)}, + {simple.Node(23), simple.Node(24), simple.Node(25), simple.Node(27), simple.Node(28), simple.Node(31)}, + }, + }, + { + q: 0.39907955292570674, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(7), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(17), simple.Node(19), simple.Node(21)}, + {simple.Node(4), simple.Node(10)}, + {simple.Node(5), simple.Node(6), simple.Node(16)}, + {simple.Node(8), simple.Node(9), simple.Node(14), simple.Node(15), simple.Node(18), simple.Node(20), simple.Node(22), simple.Node(26), simple.Node(29), simple.Node(30), simple.Node(32), simple.Node(33)}, + {simple.Node(23), simple.Node(24), simple.Node(25), simple.Node(27), simple.Node(28), simple.Node(31)}, + }, + }, + { + q: -0.04980276134122286, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + {simple.Node(13)}, + {simple.Node(14)}, + {simple.Node(15)}, + {simple.Node(16)}, + {simple.Node(17)}, + {simple.Node(18)}, + {simple.Node(19)}, + {simple.Node(20)}, + {simple.Node(21)}, + {simple.Node(22)}, + {simple.Node(23)}, + {simple.Node(24)}, + {simple.Node(25)}, + {simple.Node(26)}, + {simple.Node(27)}, + {simple.Node(28)}, + {simple.Node(29)}, + {simple.Node(30)}, + {simple.Node(31)}, + {simple.Node(32)}, + {simple.Node(33)}, + }, + }, + }, + }, + { + name: "blondel", + g: blondel, + structures: []structure{ + { + resolution: 1, + // community structure and modularity calculated by java reference implementation. + memberships: []set{ + 0: linksTo(0, 1, 2, 3, 4, 5, 6, 7), + 1: linksTo(8, 9, 10, 11, 12, 13, 14, 15), + }, + want: 0.3922, tol: 1e-4, + }, + }, + wantLevels: []level{ + { + q: 0.39221938775510207, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(7)}, + {simple.Node(8), simple.Node(9), simple.Node(10), simple.Node(11), simple.Node(12), simple.Node(13), simple.Node(14), simple.Node(15)}, + }, + }, + { + q: 0.34630102040816324, + communities: [][]graph.Node{ + {simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(4), simple.Node(5)}, + {simple.Node(3), simple.Node(6), simple.Node(7)}, + {simple.Node(8), simple.Node(9), simple.Node(10), simple.Node(12), simple.Node(14), simple.Node(15)}, + {simple.Node(11), simple.Node(13)}, + }, + }, + { + q: -0.07142857142857144, + communities: [][]graph.Node{ + {simple.Node(0)}, + {simple.Node(1)}, + {simple.Node(2)}, + {simple.Node(3)}, + {simple.Node(4)}, + {simple.Node(5)}, + {simple.Node(6)}, + {simple.Node(7)}, + {simple.Node(8)}, + {simple.Node(9)}, + {simple.Node(10)}, + {simple.Node(11)}, + {simple.Node(12)}, + {simple.Node(13)}, + {simple.Node(14)}, + {simple.Node(15)}, + }, + }, + }, + }, +} + +func TestCommunityQUndirected(t *testing.T) { + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + } + got := Q(g, communities, structure.resolution) + if !floats.EqualWithinAbsOrRel(got, structure.want, structure.tol, structure.tol) && !math.IsNaN(structure.want) { + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + t.Errorf("unexpected Q value for %q %v: got: %v want: %v", + test.name, communities, got, structure.want) + } + } + } +} + +func TestCommunityDeltaQUndirected(t *testing.T) { +tests: + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + rnd := rand.New(rand.NewSource(1)).Intn + for _, structure := range test.structures { + communityOf := make(map[int]int) + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communityOf[n] = i + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + before := Q(g, communities, structure.resolution) + + l := newUndirectedLocalMover(reduceUndirected(g, nil), communities, structure.resolution) + if l == nil { + if !math.IsNaN(before) { + t.Errorf("unexpected nil localMover with non-NaN Q graph: Q=%.4v", before) + } + continue tests + } + + // This is done to avoid run-to-run + // variation due to map iteration order. + sort.Sort(ordered.ByID(l.nodes)) + + l.shuffle(rnd) + + for _, target := range l.nodes { + got, gotDst, gotSrc := l.deltaQ(target) + + want, wantDst := math.Inf(-1), -1 + migrated := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + if n == target.ID() { + continue + } + migrated[i] = append(migrated[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(migrated[i])) + } + + for i, c := range structure.memberships { + if i == communityOf[target.ID()] { + continue + } + connected := false + for n := range c { + if g.HasEdgeBetween(simple.Node(n), target) { + connected = true + break + } + } + if !connected { + continue + } + migrated[i] = append(migrated[i], target) + after := Q(g, migrated, structure.resolution) + migrated[i] = migrated[i][:len(migrated[i])-1] + if after-before > want { + want = after - before + wantDst = i + } + } + + if !floats.EqualWithinAbsOrRel(got, want, structure.tol, structure.tol) || gotDst != wantDst { + t.Errorf("unexpected result moving n=%d in c=%d of %s/%.4v: got: %.4v,%d want: %.4v,%d"+ + "\n\t%v\n\t%v", + target.ID(), communityOf[target.ID()], test.name, structure.resolution, got, gotDst, want, wantDst, + communities, migrated) + } + if gotSrc.community != communityOf[target.ID()] { + t.Errorf("unexpected source community index: got: %d want: %d", gotSrc, communityOf[target.ID()]) + } else if communities[gotSrc.community][gotSrc.node].ID() != target.ID() { + wantNodeIdx := -1 + for i, n := range communities[gotSrc.community] { + if n.ID() == target.ID() { + wantNodeIdx = i + break + } + } + t.Errorf("unexpected source node index: got: %d want: %d", gotSrc.node, wantNodeIdx) + } + } + } + } +} + +func TestReduceQConsistencyUndirected(t *testing.T) { +tests: + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + for _, structure := range test.structures { + if math.IsNaN(structure.want) { + continue tests + } + + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + gQ := Q(g, communities, structure.resolution) + gQnull := Q(g, nil, 1) + + cg0 := reduceUndirected(g, nil) + cg0Qnull := Q(cg0, cg0.Structure(), 1) + if !floats.EqualWithinAbsOrRel(gQnull, cg0Qnull, structure.tol, structure.tol) { + t.Errorf("disagreement between null Q from method: %v and function: %v", cg0Qnull, gQnull) + } + cg0Q := Q(cg0, communities, structure.resolution) + if !floats.EqualWithinAbsOrRel(gQ, cg0Q, structure.tol, structure.tol) { + t.Errorf("unexpected Q result after initial reduction: got: %v want :%v", cg0Q, gQ) + } + + cg1 := reduceUndirected(cg0, communities) + cg1Q := Q(cg1, cg1.Structure(), structure.resolution) + if !floats.EqualWithinAbsOrRel(gQ, cg1Q, structure.tol, structure.tol) { + t.Errorf("unexpected Q result after second reduction: got: %v want :%v", cg1Q, gQ) + } + } + } +} + +var localUndirectedMoveTests = []struct { + name string + g []set + structures []moveStructures +}{ + { + name: "blondel", + g: blondel, + structures: []moveStructures{ + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(0)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + targetNodes: []graph.Node{simple.Node(3)}, + resolution: 1, + tol: 1e-14, + }, + { + memberships: []set{ + 0: linksTo(0, 1, 2, 4, 5), + 1: linksTo(3, 6, 7), + 2: linksTo(8, 9, 10, 12, 14, 15), + 3: linksTo(11, 13), + }, + // Case to demonstrate when A_aa != k_a^𝛼. + targetNodes: []graph.Node{simple.Node(3), simple.Node(2)}, + resolution: 1, + tol: 1e-14, + }, + }, + }, +} + +func TestMoveLocalUndirected(t *testing.T) { + for _, test := range localUndirectedMoveTests { + g := simple.NewUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + for _, structure := range test.structures { + communities := make([][]graph.Node, len(structure.memberships)) + for i, c := range structure.memberships { + for n := range c { + communities[i] = append(communities[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(communities[i])) + } + + r := reduceUndirected(reduceUndirected(g, nil), communities) + + l := newUndirectedLocalMover(r, r.communities, structure.resolution) + for _, n := range structure.targetNodes { + dQ, dst, src := l.deltaQ(n) + if dQ > 0 { + before := Q(r, l.communities, structure.resolution) + l.move(dst, src) + after := Q(r, l.communities, structure.resolution) + want := after - before + if !floats.EqualWithinAbsOrRel(dQ, want, structure.tol, structure.tol) { + t.Errorf("unexpected deltaQ: got: %v want: %v", dQ, want) + } + } + } + } + } +} + +func TestModularizeUndirected(t *testing.T) { + const louvainIterations = 20 + + for _, test := range communityUndirectedQTests { + g := simple.NewUndirectedGraph(0, 0) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + if test.structures[0].resolution != 1 { + panic("bad test: expect resolution=1") + } + want := make([][]graph.Node, len(test.structures[0].memberships)) + for i, c := range test.structures[0].memberships { + for n := range c { + want[i] = append(want[i], simple.Node(n)) + } + sort.Sort(ordered.ByID(want[i])) + } + sort.Sort(ordered.BySliceIDs(want)) + + var ( + got *ReducedUndirected + bestQ = math.Inf(-1) + ) + // Modularize is randomised so we do this to + // ensure the level tests are consistent. + src := rand.New(rand.NewSource(1)) + for i := 0; i < louvainIterations; i++ { + r := Modularize(g, 1, src).(*ReducedUndirected) + if q := Q(r, nil, 1); q > bestQ || math.IsNaN(q) { + bestQ = q + got = r + + if math.IsNaN(q) { + // Don't try again for non-connected case. + break + } + } + + var qs []float64 + for p := r; p != nil; p = p.Expanded().(*ReducedUndirected) { + qs = append(qs, Q(p, nil, 1)) + } + + // Recovery of Q values is reversed. + if reverse(qs); !sort.Float64sAreSorted(qs) { + t.Errorf("Q values not monotonically increasing: %.5v", qs) + } + } + + gotCommunities := got.Communities() + for _, c := range gotCommunities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(gotCommunities)) + if !reflect.DeepEqual(gotCommunities, want) { + t.Errorf("unexpected community membership for %s Q=%.4v:\n\tgot: %v\n\twant:%v", + test.name, bestQ, gotCommunities, want) + continue + } + + var levels []level + for p := got; p != nil; p = p.Expanded().(*ReducedUndirected) { + var communities [][]graph.Node + if p.parent != nil { + communities = p.parent.Communities() + for _, c := range communities { + sort.Sort(ordered.ByID(c)) + } + sort.Sort(ordered.BySliceIDs(communities)) + } else { + communities = reduceUndirected(g, nil).Communities() + } + q := Q(p, nil, 1) + if math.IsNaN(q) { + // Use an equalable flag value in place of NaN. + q = math.Inf(-1) + } + levels = append(levels, level{q: q, communities: communities}) + } + if !reflect.DeepEqual(levels, test.wantLevels) { + t.Errorf("unexpected level structure:\n\tgot: %v\n\twant:%v", levels, test.wantLevels) + } + } +} + +func TestNonContiguousUndirected(t *testing.T) { + g := simple.NewUndirectedGraph(0, 0) + for _, e := range []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(4), T: simple.Node(5), W: 1}, + } { + g.SetEdge(e) + } + + func() { + defer func() { + r := recover() + if r != nil { + t.Error("unexpected panic with non-contiguous ID range") + } + }() + Modularize(g, 1, nil) + }() +} + +func BenchmarkLouvain(b *testing.B) { + src := rand.New(rand.NewSource(1)) + for i := 0; i < b.N; i++ { + Modularize(dupGraph, 1, src) + } +} diff --git a/graph/community/printgraphs.go b/graph/community/printgraphs.go new file mode 100644 index 00000000..9d8eb1b7 --- /dev/null +++ b/graph/community/printgraphs.go @@ -0,0 +1,142 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// printgraphs allows us to generate a consistent directed view of +// a set of edges that follows a reasonably real-world-meaningful +// graph. The interpretation of the links in the resulting directed +// graphs are either "suggests" in the context of a Page Ranking or +// possibly "looks up to" in the Zachary graph. +package main + +import ( + "fmt" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/network" + "gonum.org/v1/gonum/graph/simple" +) + +// set is an integer set. +type set map[int]struct{} + +func linksTo(i ...int) set { + if len(i) == 0 { + return nil + } + s := make(set) + for _, v := range i { + s[v] = struct{}{} + } + return s +} + +var ( + zachary = []set{ + 0: linksTo(1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 17, 19, 21, 31), + 1: linksTo(2, 3, 7, 13, 17, 19, 21, 30), + 2: linksTo(3, 7, 8, 9, 13, 27, 28, 32), + 3: linksTo(7, 12, 13), + 4: linksTo(6, 10), + 5: linksTo(6, 10, 16), + 6: linksTo(16), + 8: linksTo(30, 32, 33), + 9: linksTo(33), + 13: linksTo(33), + 14: linksTo(32, 33), + 15: linksTo(32, 33), + 18: linksTo(32, 33), + 19: linksTo(33), + 20: linksTo(32, 33), + 22: linksTo(32, 33), + 23: linksTo(25, 27, 29, 32, 33), + 24: linksTo(25, 27, 31), + 25: linksTo(31), + 26: linksTo(29, 33), + 27: linksTo(33), + 28: linksTo(31, 33), + 29: linksTo(32, 33), + 30: linksTo(32, 33), + 31: linksTo(32, 33), + 32: linksTo(33), + 33: nil, + } + + blondel = []set{ + 0: linksTo(2, 3, 4, 5), + 1: linksTo(2, 4, 7), + 2: linksTo(4, 5, 6), + 3: linksTo(7), + 4: linksTo(10), + 5: linksTo(7, 11), + 6: linksTo(7, 11), + 8: linksTo(9, 10, 11, 14, 15), + 9: linksTo(12, 14), + 10: linksTo(11, 12, 13, 14), + 11: linksTo(13), + 15: nil, + } +) + +func main() { + for _, raw := range []struct { + name string + set []set + }{ + {"zachary", zachary}, + {"blondel", blondel}, + } { + g := simple.NewUndirectedGraph(0, 0) + for u, e := range raw.set { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + nodes := g.Nodes() + sort.Sort(ordered.ByID(nodes)) + + fmt.Printf("%s = []set{\n", raw.name) + rank := network.PageRank(asDirected{g}, 0.85, 1e-8) + for _, u := range nodes { + to := g.From(nodes[u.ID()]) + sort.Sort(ordered.ByID(to)) + var links []int + for _, v := range to { + if rank[u.ID()] <= rank[v.ID()] { + links = append(links, v.ID()) + } + } + + if links == nil { + fmt.Printf("\t%d: nil, // rank=%.4v\n", u.ID(), rank[u.ID()]) + continue + } + + fmt.Printf("\t%d: linksTo(", u.ID()) + for i, v := range links { + if i != 0 { + fmt.Print(", ") + } + fmt.Print(v) + } + fmt.Printf("), // rank=%.4v\n", rank[u.ID()]) + } + fmt.Println("}") + } +} + +type asDirected struct{ *simple.UndirectedGraph } + +func (g asDirected) HasEdgeFromTo(u, v graph.Node) bool { + return g.UndirectedGraph.HasEdgeBetween(u, v) +} +func (g asDirected) To(v graph.Node) []graph.Node { return g.From(v) } diff --git a/graph/doc.go b/graph/doc.go new file mode 100644 index 00000000..7b7b3cc8 --- /dev/null +++ b/graph/doc.go @@ -0,0 +1,38 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package graph implements functions and interfaces to deal with formal discrete graphs. It aims to +be first and foremost flexible, with speed as a strong second priority. + +In this package, graphs are taken to be directed, and undirected graphs are considered to be a +special case of directed graphs that happen to have reciprocal edges. Graphs are, by default, +unweighted, but functions that require weighted edges have several methods of dealing with this. +In order of precedence: + +1. These functions have an argument called Cost (and in some cases, HeuristicCost). If this is +present, it will always be used to determine the cost between two nodes. + +2. These functions will check if your graph implements the Coster (and/or HeuristicCoster) +interface. If this is present, and the Cost (or HeuristicCost) argument is nil, these functions +will be used. + +3. Finally, if no user data is supplied, it will use the functions UniformCost (always returns 1) +and/or NulLHeuristic (always returns 0). + +For information on the specification for Cost functions, please see the Coster interface. + +Finally, although the functions take in a Graph -- they will always use the correct behavior. +If your graph implements DirectedGraph, it will use Successors and To where applicable, +if undirected, it will use From instead. If it implements neither, it will scan the edge list +for successors and predecessors where applicable. (This is slow, you should always implement either +Directed or Undirected) + +This package will never modify a graph that is not Mutable (and the interface does not allow it to +do so). However, return values are free to be modified, so never pass a reference to your own edge +list or node list. It also guarantees that any nodes passed back to the user will be the same +nodes returned to it -- that is, it will never take a Node's ID and then wrap the ID in a new +struct and return that. You'll always get back your original data. +*/ +package graph diff --git a/graph/encoding/dot/decode.go b/graph/encoding/dot/decode.go new file mode 100644 index 00000000..0140c442 --- /dev/null +++ b/graph/encoding/dot/decode.go @@ -0,0 +1,237 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dot + +import ( + "fmt" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/formats/dot" + "gonum.org/v1/gonum/graph/formats/dot/ast" + "golang.org/x/tools/container/intsets" +) + +// Builder is a graph that can have user-defined nodes and edges added. +type Builder interface { + graph.Graph + graph.Builder + // NewNode adds a new node with a unique node ID to the graph. + NewNode() graph.Node + // NewEdge adds a new edge from the source to the destination node to the + // graph, or returns the existing edge if already present. + NewEdge(from, to graph.Node) graph.Edge +} + +// UnmarshalerAttr is the interface implemented by objects that can unmarshal a +// DOT attribute description of themselves. +type UnmarshalerAttr interface { + // UnmarshalDOTAttr decodes a single DOT attribute. + UnmarshalDOTAttr(attr Attribute) error +} + +// Unmarshal parses the Graphviz DOT-encoded data and stores the result in dst. +func Unmarshal(data []byte, dst Builder) error { + file, err := dot.ParseBytes(data) + if err != nil { + return err + } + if len(file.Graphs) != 1 { + return fmt.Errorf("invalid number of graphs; expected 1, got %d", len(file.Graphs)) + } + return copyGraph(dst, file.Graphs[0]) +} + +// copyGraph copies the nodes and edges from the Graphviz AST source graph to +// the destination graph. Edge direction is maintained if present. +func copyGraph(dst Builder, src *ast.Graph) (err error) { + defer func() { + switch e := recover().(type) { + case nil: + case error: + err = e + default: + panic(e) + } + }() + gen := &generator{ + directed: src.Directed, + ids: make(map[string]graph.Node), + } + for _, stmt := range src.Stmts { + gen.addStmt(dst, stmt) + } + return err +} + +// A generator keeps track of the information required for generating a gonum +// graph from a dot AST graph. +type generator struct { + // Directed graph. + directed bool + // Map from dot AST node ID to gonum node. + ids map[string]graph.Node + // Nodes processed within the context of a subgraph, that is to be used as a + // vertex of an edge. + subNodes []graph.Node + // Stack of start indices into the subgraph node slice. The top element + // corresponds to the start index of the active (or inner-most) subgraph. + subStart []int +} + +// node returns the gonum node corresponding to the given dot AST node ID, +// generating a new such node if none exist. +func (gen *generator) node(dst Builder, id string) graph.Node { + if n, ok := gen.ids[id]; ok { + return n + } + n := dst.NewNode() + gen.ids[id] = n + // Check if within the context of a subgraph, that is to be used as a vertex + // of an edge. + if gen.isInSubgraph() { + // Append node processed within the context of a subgraph, that is to be + // used as a vertex of an edge + gen.appendSubgraphNode(n) + } + return n +} + +// addStmt adds the given statement to the graph. +func (gen *generator) addStmt(dst Builder, stmt ast.Stmt) { + switch stmt := stmt.(type) { + case *ast.NodeStmt: + n := gen.node(dst, stmt.Node.ID) + if n, ok := n.(UnmarshalerAttr); ok { + for _, attr := range stmt.Attrs { + a := Attribute{ + Key: attr.Key, + Value: attr.Val, + } + if err := n.UnmarshalDOTAttr(a); err != nil { + panic(fmt.Errorf("unable to unmarshal node DOT attribute (%s=%s)", a.Key, a.Value)) + } + } + } + case *ast.EdgeStmt: + gen.addEdgeStmt(dst, stmt) + case *ast.AttrStmt: + // ignore. + case *ast.Attr: + // ignore. + case *ast.Subgraph: + for _, stmt := range stmt.Stmts { + gen.addStmt(dst, stmt) + } + default: + panic(fmt.Sprintf("unknown statement type %T", stmt)) + } +} + +// addEdgeStmt adds the given edge statement to the graph. +func (gen *generator) addEdgeStmt(dst Builder, e *ast.EdgeStmt) { + fs := gen.addVertex(dst, e.From) + ts := gen.addEdge(dst, e.To) + for _, f := range fs { + for _, t := range ts { + edge := dst.NewEdge(f, t) + if edge, ok := edge.(UnmarshalerAttr); ok { + for _, attr := range e.Attrs { + a := Attribute{ + Key: attr.Key, + Value: attr.Val, + } + if err := edge.UnmarshalDOTAttr(a); err != nil { + panic(fmt.Errorf("unable to unmarshal edge DOT attribute (%s=%s)", a.Key, a.Value)) + } + } + } + } + } +} + +// addVertex adds the given vertex to the graph, and returns its set of nodes. +func (gen *generator) addVertex(dst Builder, v ast.Vertex) []graph.Node { + switch v := v.(type) { + case *ast.Node: + n := gen.node(dst, v.ID) + return []graph.Node{n} + case *ast.Subgraph: + gen.pushSubgraph() + for _, stmt := range v.Stmts { + gen.addStmt(dst, stmt) + } + return gen.popSubgraph() + default: + panic(fmt.Sprintf("unknown vertex type %T", v)) + } +} + +// addEdge adds the given edge to the graph, and returns its set of nodes. +func (gen *generator) addEdge(dst Builder, to *ast.Edge) []graph.Node { + if !gen.directed && to.Directed { + panic(fmt.Errorf("directed edge to %v in undirected graph", to.Vertex)) + } + fs := gen.addVertex(dst, to.Vertex) + if to.To != nil { + ts := gen.addEdge(dst, to.To) + for _, f := range fs { + for _, t := range ts { + dst.NewEdge(f, t) + } + } + } + return fs +} + +// pushSubgraph pushes the node start index of the active subgraph onto the +// stack. +func (gen *generator) pushSubgraph() { + gen.subStart = append(gen.subStart, len(gen.subNodes)) +} + +// popSubgraph pops the node start index of the active subgraph from the stack, +// and returns the nodes processed since. +func (gen *generator) popSubgraph() []graph.Node { + // Get nodes processed since the subgraph became active. + start := gen.subStart[len(gen.subStart)-1] + // TODO: Figure out a better way to store subgraph nodes, so that duplicates + // may not occur. + nodes := unique(gen.subNodes[start:]) + // Remove subgraph from stack. + gen.subStart = gen.subStart[:len(gen.subStart)-1] + if len(gen.subStart) == 0 { + // Remove subgraph nodes when the bottom-most subgraph has been processed. + gen.subNodes = gen.subNodes[:0] + } + return nodes +} + +// unique returns the set of unique nodes contained within ns. +func unique(ns []graph.Node) []graph.Node { + var nodes []graph.Node + var set intsets.Sparse + for _, n := range ns { + id := n.ID() + if set.Has(id) { + // skip duplicate node + continue + } + set.Insert(id) + nodes = append(nodes, n) + } + return nodes +} + +// isInSubgraph reports whether the active context is within a subgraph, that is +// to be used as a vertex of an edge. +func (gen *generator) isInSubgraph() bool { + return len(gen.subStart) > 0 +} + +// appendSubgraphNode appends the given node to the slice of nodes processed +// within the context of a subgraph. +func (gen *generator) appendSubgraphNode(n graph.Node) { + gen.subNodes = append(gen.subNodes, n) +} diff --git a/graph/encoding/dot/decode_test.go b/graph/encoding/dot/decode_test.go new file mode 100644 index 00000000..7860d6c3 --- /dev/null +++ b/graph/encoding/dot/decode_test.go @@ -0,0 +1,196 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dot + +import ( + "fmt" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +func TestRoundTrip(t *testing.T) { + golden := []struct { + want string + directed bool + }{ + { + want: directed, + directed: true, + }, + { + want: undirected, + directed: false, + }, + } + for i, g := range golden { + var dst Builder + if g.directed { + dst = newDotDirectedGraph() + } else { + dst = newDotUndirectedGraph() + } + data := []byte(g.want) + if err := Unmarshal(data, dst); err != nil { + t.Errorf("i=%d: unable to unmarshal DOT graph; %v", i, err) + continue + } + buf, err := Marshal(dst, "", "", "\t", false) + if err != nil { + t.Errorf("i=%d: unable to marshal graph; %v", i, dst) + continue + } + got := string(buf) + if got != g.want { + t.Errorf("i=%d: graph content mismatch; expected `%s`, got `%s`", i, g.want, got) + continue + } + } +} + +const directed = `digraph { + // Node definitions. + 0 [label="foo 2"]; + 1 [label="bar 2"]; + + // Edge definitions. + 0 -> 1 [label="baz 2"]; +}` + +const undirected = `graph { + // Node definitions. + 0 [label="foo 2"]; + 1 [label="bar 2"]; + + // Edge definitions. + 0 -- 1 [label="baz 2"]; +}` + +// Below follows a minimal implementation of a graph capable of validating the +// round-trip encoding and decoding of DOT graphs with nodes and edges +// containing DOT attributes. + +// dotDirectedGraph extends simple.DirectedGraph to add NewNode and NewEdge +// methods for creating user-defined nodes and edges. +// +// dotDirectedGraph implements the dot.Builder interface. +type dotDirectedGraph struct { + *simple.DirectedGraph +} + +// newDotDirectedGraph returns a new directed capable of creating user-defined +// nodes and edges. +func newDotDirectedGraph() *dotDirectedGraph { + return &dotDirectedGraph{DirectedGraph: simple.NewDirectedGraph(0, 0)} +} + +// NewNode adds a new node with a unique node ID to the graph. +func (g *dotDirectedGraph) NewNode() graph.Node { + n := &dotNode{Node: simple.Node(g.NewNodeID())} + g.AddNode(n) + return n +} + +// NewEdge adds a new edge from the source to the destination node to the graph, +// or returns the existing edge if already present. +func (g *dotDirectedGraph) NewEdge(from, to graph.Node) graph.Edge { + if e := g.Edge(from, to); e != nil { + return e + } + e := &dotEdge{Edge: simple.Edge{F: from, T: to}} + g.SetEdge(e) + return e +} + +// dotUndirectedGraph extends simple.UndirectedGraph to add NewNode and NewEdge +// methods for creating user-defined nodes and edges. +// +// dotUndirectedGraph implements the dot.Builder interface. +type dotUndirectedGraph struct { + *simple.UndirectedGraph +} + +// newDotUndirectedGraph returns a new undirected capable of creating user- +// defined nodes and edges. +func newDotUndirectedGraph() *dotUndirectedGraph { + return &dotUndirectedGraph{UndirectedGraph: simple.NewUndirectedGraph(0, 0)} +} + +// NewNode adds a new node with a unique node ID to the graph. +func (g *dotUndirectedGraph) NewNode() graph.Node { + n := &dotNode{Node: simple.Node(g.NewNodeID())} + g.AddNode(n) + return n +} + +// NewEdge adds a new edge from the source to the destination node to the graph, +// or returns the existing edge if already present. +func (g *dotUndirectedGraph) NewEdge(from, to graph.Node) graph.Edge { + if e := g.Edge(from, to); e != nil { + return e + } + e := &dotEdge{Edge: simple.Edge{F: from, T: to}} + g.SetEdge(e) + return e +} + +// dotNode extends simple.Node with a label field to test round-trip encoding +// and decoding of node DOT label attributes. +type dotNode struct { + simple.Node + // Node label. + Label string +} + +// UnmarshalDOTAttr decodes a single DOT attribute. +func (n *dotNode) UnmarshalDOTAttr(attr Attribute) error { + if attr.Key != "label" { + return fmt.Errorf("unable to unmarshal node DOT attribute with key %q", attr.Key) + } + n.Label = attr.Value + return nil +} + +// DOTAttributes returns the DOT attributes of the node. +func (n *dotNode) DOTAttributes() []Attribute { + if len(n.Label) == 0 { + return nil + } + attr := Attribute{ + Key: "label", + Value: n.Label, + } + return []Attribute{attr} +} + +// dotEdge extends simple.Edge with a label field to test round-trip encoding and +// decoding of edge DOT label attributes. +type dotEdge struct { + simple.Edge + // Edge label. + Label string +} + +// UnmarshalDOTAttr decodes a single DOT attribute. +func (e *dotEdge) UnmarshalDOTAttr(attr Attribute) error { + if attr.Key != "label" { + return fmt.Errorf("unable to unmarshal node DOT attribute with key %q", attr.Key) + } + e.Label = attr.Value + return nil +} + +// DOTAttributes returns the DOT attributes of the edge. +func (e *dotEdge) DOTAttributes() []Attribute { + if len(e.Label) == 0 { + return nil + } + attr := Attribute{ + Key: "label", + Value: e.Label, + } + return []Attribute{attr} +} diff --git a/graph/encoding/dot/dot.go b/graph/encoding/dot/dot.go new file mode 100644 index 00000000..da7d2d0a --- /dev/null +++ b/graph/encoding/dot/dot.go @@ -0,0 +1,378 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package dot implements GraphViz DOT marshaling of graphs. +// +// See the GraphViz DOT Guide and the DOT grammar for more information +// on using specific aspects of the DOT language: +// +// DOT Guide: http://www.graphviz.org/Documentation/dotguide.pdf +// +// DOT grammar: http://www.graphviz.org/doc/info/lang.html +// +package dot + +import ( + "bytes" + "errors" + "fmt" + "sort" + "strings" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +// Node is a DOT graph node. +type Node interface { + // DOTID returns a DOT node ID. + // + // An ID is one of the following: + // + // - a string of alphabetic ([a-zA-Z\x80-\xff]) characters, underscores ('_'). + // digits ([0-9]), not beginning with a digit. + // - a numeral [-]?(.[0-9]+ | [0-9]+(.[0-9]*)?). + // - a double-quoted string ("...") possibly containing escaped quotes (\"). + // - an HTML string (<...>). + DOTID() string +} + +// Attributers are graph.Graph values that specify top-level DOT +// attributes. +type Attributers interface { + DOTAttributers() (graph, node, edge Attributer) +} + +// Attributer defines graph.Node or graph.Edge values that can +// specify DOT attributes. +type Attributer interface { + DOTAttributes() []Attribute +} + +// Attribute is a DOT language key value attribute pair. +type Attribute struct { + Key, Value string +} + +// Porter defines the behavior of graph.Edge values that can specify +// connection ports for their end points. The returned port corresponds +// to the the DOT node port to be used by the edge, compass corresponds +// to DOT compass point to which the edge will be aimed. +type Porter interface { + FromPort() (port, compass string) + ToPort() (port, compass string) +} + +// Structurer represents a graph.Graph that can define subgraphs. +type Structurer interface { + Structure() []Graph +} + +// Graph wraps named graph.Graph values. +type Graph interface { + graph.Graph + DOTID() string +} + +// Subgrapher wraps graph.Node values that represent subgraphs. +type Subgrapher interface { + Subgraph() graph.Graph +} + +// Marshal returns the DOT encoding for the graph g, applying the prefix +// and indent to the encoding. Name is used to specify the graph name. If +// name is empty and g implements Graph, the returned string from DOTID +// will be used. If strict is true the output bytes will be prefixed with +// the DOT "strict" keyword. +// +// Graph serialization will work for a graph.Graph without modification, +// however, advanced GraphViz DOT features provided by Marshal depend on +// implementation of the Node, Attributer, Porter, Attributers, Structurer, +// Subgrapher and Graph interfaces. +func Marshal(g graph.Graph, name, prefix, indent string, strict bool) ([]byte, error) { + var p printer + p.indent = indent + p.prefix = prefix + p.visited = make(map[edge]bool) + if strict { + p.buf.WriteString("strict ") + } + err := p.print(g, name, false, false) + if err != nil { + return nil, err + } + return p.buf.Bytes(), nil +} + +type printer struct { + buf bytes.Buffer + + prefix string + indent string + depth int + + visited map[edge]bool + + err error +} + +type edge struct { + inGraph string + from, to int +} + +func (p *printer) print(g graph.Graph, name string, needsIndent, isSubgraph bool) error { + nodes := g.Nodes() + sort.Sort(ordered.ByID(nodes)) + + p.buf.WriteString(p.prefix) + if needsIndent { + for i := 0; i < p.depth; i++ { + p.buf.WriteString(p.indent) + } + } + _, isDirected := g.(graph.Directed) + if isSubgraph { + p.buf.WriteString("sub") + } else if isDirected { + p.buf.WriteString("di") + } + p.buf.WriteString("graph") + + if name == "" { + if g, ok := g.(Graph); ok { + name = g.DOTID() + } + } + if name != "" { + p.buf.WriteByte(' ') + p.buf.WriteString(name) + } + + p.openBlock(" {") + if a, ok := g.(Attributers); ok { + p.writeAttributeComplex(a) + } + if s, ok := g.(Structurer); ok { + for _, g := range s.Structure() { + _, subIsDirected := g.(graph.Directed) + if subIsDirected != isDirected { + return errors.New("dot: mismatched graph type") + } + p.buf.WriteByte('\n') + p.print(g, g.DOTID(), true, true) + } + } + + havePrintedNodeHeader := false + for _, n := range nodes { + if s, ok := n.(Subgrapher); ok { + // If the node is not linked to any other node + // the graph needs to be written now. + if len(g.From(n)) == 0 { + g := s.Subgraph() + _, subIsDirected := g.(graph.Directed) + if subIsDirected != isDirected { + return errors.New("dot: mismatched graph type") + } + if !havePrintedNodeHeader { + p.newline() + p.buf.WriteString("// Node definitions.") + havePrintedNodeHeader = true + } + p.newline() + p.print(g, graphID(g, n), false, true) + } + continue + } + if !havePrintedNodeHeader { + p.newline() + p.buf.WriteString("// Node definitions.") + havePrintedNodeHeader = true + } + p.newline() + p.writeNode(n) + if a, ok := n.(Attributer); ok { + p.writeAttributeList(a) + } + p.buf.WriteByte(';') + } + + havePrintedEdgeHeader := false + for _, n := range nodes { + to := g.From(n) + sort.Sort(ordered.ByID(to)) + for _, t := range to { + if isDirected { + if p.visited[edge{inGraph: name, from: n.ID(), to: t.ID()}] { + continue + } + p.visited[edge{inGraph: name, from: n.ID(), to: t.ID()}] = true + } else { + if p.visited[edge{inGraph: name, from: n.ID(), to: t.ID()}] { + continue + } + p.visited[edge{inGraph: name, from: n.ID(), to: t.ID()}] = true + p.visited[edge{inGraph: name, from: t.ID(), to: n.ID()}] = true + } + + if !havePrintedEdgeHeader { + p.buf.WriteByte('\n') + p.buf.WriteString(strings.TrimRight(p.prefix, " \t\n")) // Trim whitespace suffix. + p.newline() + p.buf.WriteString("// Edge definitions.") + havePrintedEdgeHeader = true + } + p.newline() + + if s, ok := n.(Subgrapher); ok { + g := s.Subgraph() + _, subIsDirected := g.(graph.Directed) + if subIsDirected != isDirected { + return errors.New("dot: mismatched graph type") + } + p.print(g, graphID(g, n), false, true) + } else { + p.writeNode(n) + } + e, edgeIsPorter := g.Edge(n, t).(Porter) + if edgeIsPorter { + p.writePorts(e.FromPort()) + } + + if isDirected { + p.buf.WriteString(" -> ") + } else { + p.buf.WriteString(" -- ") + } + + if s, ok := t.(Subgrapher); ok { + g := s.Subgraph() + _, subIsDirected := g.(graph.Directed) + if subIsDirected != isDirected { + return errors.New("dot: mismatched graph type") + } + p.print(g, graphID(g, t), false, true) + } else { + p.writeNode(t) + } + if edgeIsPorter { + p.writePorts(e.ToPort()) + } + + if a, ok := g.Edge(n, t).(Attributer); ok { + p.writeAttributeList(a) + } + + p.buf.WriteByte(';') + } + } + p.closeBlock("}") + + return nil +} + +func (p *printer) writeNode(n graph.Node) { + p.buf.WriteString(nodeID(n)) +} + +func (p *printer) writePorts(port, cp string) { + if port != "" { + p.buf.WriteByte(':') + p.buf.WriteString(port) + } + if cp != "" { + p.buf.WriteByte(':') + p.buf.WriteString(cp) + } +} + +func nodeID(n graph.Node) string { + switch n := n.(type) { + case Node: + return n.DOTID() + default: + return fmt.Sprint(n.ID()) + } +} + +func graphID(g graph.Graph, n graph.Node) string { + switch g := g.(type) { + case Node: + return g.DOTID() + default: + return nodeID(n) + } +} + +func (p *printer) writeAttributeList(a Attributer) { + attributes := a.DOTAttributes() + switch len(attributes) { + case 0: + case 1: + p.buf.WriteString(" [") + p.buf.WriteString(attributes[0].Key) + p.buf.WriteByte('=') + p.buf.WriteString(attributes[0].Value) + p.buf.WriteString("]") + default: + p.openBlock(" [") + for _, att := range attributes { + p.newline() + p.buf.WriteString(att.Key) + p.buf.WriteByte('=') + p.buf.WriteString(att.Value) + } + p.closeBlock("]") + } +} + +var attType = []string{"graph", "node", "edge"} + +func (p *printer) writeAttributeComplex(ca Attributers) { + g, n, e := ca.DOTAttributers() + haveWrittenBlock := false + for i, a := range []Attributer{g, n, e} { + attributes := a.DOTAttributes() + if len(attributes) == 0 { + continue + } + if haveWrittenBlock { + p.buf.WriteByte(';') + } + p.newline() + p.buf.WriteString(attType[i]) + p.openBlock(" [") + for _, att := range attributes { + p.newline() + p.buf.WriteString(att.Key) + p.buf.WriteByte('=') + p.buf.WriteString(att.Value) + } + p.closeBlock("]") + haveWrittenBlock = true + } + if haveWrittenBlock { + p.buf.WriteString(";\n") + } +} + +func (p *printer) newline() { + p.buf.WriteByte('\n') + p.buf.WriteString(p.prefix) + for i := 0; i < p.depth; i++ { + p.buf.WriteString(p.indent) + } +} + +func (p *printer) openBlock(b string) { + p.buf.WriteString(b) + p.depth++ +} + +func (p *printer) closeBlock(b string) { + p.depth-- + p.newline() + p.buf.WriteString(b) +} diff --git a/graph/encoding/dot/dot_test.go b/graph/encoding/dot/dot_test.go new file mode 100644 index 00000000..c2bf7e04 --- /dev/null +++ b/graph/encoding/dot/dot_test.go @@ -0,0 +1,1423 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dot + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +// set is an integer set. +type set map[int]struct{} + +func linksTo(i ...int) set { + if len(i) == 0 { + return nil + } + s := make(set) + for _, v := range i { + s[v] = struct{}{} + } + return s +} + +var ( + // Example graph from http://en.wikipedia.org/wiki/File:PageRanks-Example.svg 16:17, 8 July 2009 + // Node identities are rewritten here to use integers from 0 to match with the DOT output. + pageRankGraph = []set{ + 0: nil, + 1: linksTo(2), + 2: linksTo(1), + 3: linksTo(0, 1), + 4: linksTo(3, 1, 5), + 5: linksTo(1, 4), + 6: linksTo(1, 4), + 7: linksTo(1, 4), + 8: linksTo(1, 4), + 9: linksTo(4), + 10: linksTo(4), + } + + // Example graph from http://en.wikipedia.org/w/index.php?title=PageRank&oldid=659286279#Power_Method + powerMethodGraph = []set{ + 0: linksTo(1, 2), + 1: linksTo(3), + 2: linksTo(3, 4), + 3: linksTo(4), + 4: linksTo(0), + } +) + +func directedGraphFrom(g []set) graph.Directed { + dg := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range g { + for v := range e { + dg.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + return dg +} + +func undirectedGraphFrom(g []set) graph.Graph { + dg := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range g { + for v := range e { + dg.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + return dg +} + +const alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +type namedNode struct { + id int + name string +} + +func (n namedNode) ID() int { return n.id } +func (n namedNode) DOTID() string { return n.name } + +func directedNamedIDGraphFrom(g []set) graph.Directed { + dg := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range g { + nu := namedNode{id: u, name: alpha[u : u+1]} + for v := range e { + nv := namedNode{id: v, name: alpha[v : v+1]} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +func undirectedNamedIDGraphFrom(g []set) graph.Graph { + dg := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range g { + nu := namedNode{id: u, name: alpha[u : u+1]} + for v := range e { + nv := namedNode{id: v, name: alpha[v : v+1]} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +type attrNode struct { + id int + name string + attr []Attribute +} + +func (n attrNode) ID() int { return n.id } +func (n attrNode) DOTAttributes() []Attribute { return n.attr } + +func directedNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Directed { + dg := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range g { + var at []Attribute + if u < len(attr) { + at = attr[u] + } + nu := attrNode{id: u, attr: at} + for v := range e { + if v < len(attr) { + at = attr[v] + } + nv := attrNode{id: v, attr: at} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +func undirectedNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Graph { + dg := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range g { + var at []Attribute + if u < len(attr) { + at = attr[u] + } + nu := attrNode{id: u, attr: at} + for v := range e { + if v < len(attr) { + at = attr[v] + } + nv := attrNode{id: v, attr: at} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +type namedAttrNode struct { + id int + name string + attr []Attribute +} + +func (n namedAttrNode) ID() int { return n.id } +func (n namedAttrNode) DOTID() string { return n.name } +func (n namedAttrNode) DOTAttributes() []Attribute { return n.attr } + +func directedNamedIDNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Directed { + dg := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range g { + var at []Attribute + if u < len(attr) { + at = attr[u] + } + nu := namedAttrNode{id: u, name: alpha[u : u+1], attr: at} + for v := range e { + if v < len(attr) { + at = attr[v] + } + nv := namedAttrNode{id: v, name: alpha[v : v+1], attr: at} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +func undirectedNamedIDNodeAttrGraphFrom(g []set, attr [][]Attribute) graph.Graph { + dg := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range g { + var at []Attribute + if u < len(attr) { + at = attr[u] + } + nu := namedAttrNode{id: u, name: alpha[u : u+1], attr: at} + for v := range e { + if v < len(attr) { + at = attr[v] + } + nv := namedAttrNode{id: v, name: alpha[v : v+1], attr: at} + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +type attrEdge struct { + from, to graph.Node + + attr []Attribute +} + +func (e attrEdge) From() graph.Node { return e.from } +func (e attrEdge) To() graph.Node { return e.to } +func (e attrEdge) Weight() float64 { return 0 } +func (e attrEdge) DOTAttributes() []Attribute { return e.attr } + +func directedEdgeAttrGraphFrom(g []set, attr map[edge][]Attribute) graph.Directed { + dg := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range g { + for v := range e { + dg.SetEdge(attrEdge{from: simple.Node(u), to: simple.Node(v), attr: attr[edge{from: u, to: v}]}) + } + } + return dg +} + +func undirectedEdgeAttrGraphFrom(g []set, attr map[edge][]Attribute) graph.Graph { + dg := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range g { + for v := range e { + dg.SetEdge(attrEdge{from: simple.Node(u), to: simple.Node(v), attr: attr[edge{from: u, to: v}]}) + } + } + return dg +} + +type portedEdge struct { + from, to graph.Node + + directed bool + + fromPort string + fromCompass string + toPort string + toCompass string +} + +func (e portedEdge) From() graph.Node { return e.from } +func (e portedEdge) To() graph.Node { return e.to } +func (e portedEdge) Weight() float64 { return 0 } + +// TODO(kortschak): Figure out a better way to handle the fact that +// headedness is an undefined concept in undirected graphs. We sort +// nodes by ID, so lower ID nodes are always from nodes in undirected +// graphs. We can probably do this in the printer, but I am leaving +// this here as a WARNING. +// Maybe the approach should be to document that for undirected graphs +// the low ID node should be returned by the FromPort and the high ID +// by the ToPort calls. +func (e portedEdge) FromPort() (port, compass string) { + return e.fromPort, e.fromCompass +} +func (e portedEdge) ToPort() (port, compass string) { + return e.toPort, e.toCompass +} + +func directedPortedAttrGraphFrom(g []set, attr [][]Attribute, ports map[edge]portedEdge) graph.Directed { + dg := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range g { + var at []Attribute + if u < len(attr) { + at = attr[u] + } + nu := attrNode{id: u, attr: at} + for v := range e { + if v < len(attr) { + at = attr[v] + } + pe := ports[edge{from: u, to: v}] + pe.from = nu + pe.to = attrNode{id: v, attr: at} + dg.SetEdge(pe) + } + } + return dg +} + +func undirectedPortedAttrGraphFrom(g []set, attr [][]Attribute, ports map[edge]portedEdge) graph.Graph { + dg := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range g { + var at []Attribute + if u < len(attr) { + at = attr[u] + } + nu := attrNode{id: u, attr: at} + for v := range e { + if v < len(attr) { + at = attr[v] + } + pe := ports[edge{from: u, to: v}] + pe.from = nu + pe.to = attrNode{id: v, attr: at} + dg.SetEdge(pe) + } + } + return dg +} + +type graphAttributer struct { + graph.Graph + graph attributer + node attributer + edge attributer +} + +type attributer []Attribute + +func (a attributer) DOTAttributes() []Attribute { return a } + +func (g graphAttributer) DOTAttributers() (graph, node, edge Attributer) { + return g.graph, g.node, g.edge +} + +type structuredGraph struct { + *simple.UndirectedGraph + sub []Graph +} + +func undirectedStructuredGraphFrom(c []edge, g ...[]set) graph.Graph { + s := &structuredGraph{UndirectedGraph: simple.NewUndirectedGraph(0, math.Inf(1))} + var base int + for i, sg := range g { + sub := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range sg { + for v := range e { + ce := simple.Edge{F: simple.Node(u + base), T: simple.Node(v + base)} + sub.SetEdge(ce) + } + } + s.sub = append(s.sub, namedGraph{id: i, Graph: sub}) + base += len(sg) + } + for _, e := range c { + s.SetEdge(simple.Edge{F: simple.Node(e.from), T: simple.Node(e.to)}) + } + return s +} + +func (g structuredGraph) Structure() []Graph { + return g.sub +} + +type namedGraph struct { + id int + graph.Graph +} + +func (g namedGraph) DOTID() string { return alpha[g.id : g.id+1] } + +type subGraph struct { + id int + graph.Graph +} + +func (g subGraph) ID() int { return g.id } +func (g subGraph) Subgraph() graph.Graph { + return namedGraph{id: g.id, Graph: g.Graph} +} + +func undirectedSubGraphFrom(g []set, s map[int][]set) graph.Graph { + var base int + subs := make(map[int]subGraph) + for i, sg := range s { + sub := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range sg { + for v := range e { + ce := simple.Edge{F: simple.Node(u + base), T: simple.Node(v + base)} + sub.SetEdge(ce) + } + } + subs[i] = subGraph{id: i, Graph: sub} + base += len(sg) + } + + dg := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range g { + var nu graph.Node + if sg, ok := subs[u]; ok { + sg.id += base + nu = sg + } else { + nu = simple.Node(u + base) + } + for v := range e { + var nv graph.Node + if sg, ok := subs[v]; ok { + sg.id += base + nv = sg + } else { + nv = simple.Node(v + base) + } + dg.SetEdge(simple.Edge{F: nu, T: nv}) + } + } + return dg +} + +var encodeTests = []struct { + name string + g graph.Graph + strict bool + + prefix string + + want string +}{ + // Basic graph.Graph handling. + { + name: "PageRank", + g: directedGraphFrom(pageRankGraph), + + want: `digraph PageRank { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + 5; + 6; + 7; + 8; + 9; + 10; + + // Edge definitions. + 1 -> 2; + 2 -> 1; + 3 -> 0; + 3 -> 1; + 4 -> 1; + 4 -> 3; + 4 -> 5; + 5 -> 1; + 5 -> 4; + 6 -> 1; + 6 -> 4; + 7 -> 1; + 7 -> 4; + 8 -> 1; + 8 -> 4; + 9 -> 4; + 10 -> 4; +}`, + }, + { + g: undirectedGraphFrom(pageRankGraph), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + 5; + 6; + 7; + 8; + 9; + 10; + + // Edge definitions. + 0 -- 3; + 1 -- 2; + 1 -- 3; + 1 -- 4; + 1 -- 5; + 1 -- 6; + 1 -- 7; + 1 -- 8; + 3 -- 4; + 4 -- 5; + 4 -- 6; + 4 -- 7; + 4 -- 8; + 4 -- 9; + 4 -- 10; +}`, + }, + { + g: directedGraphFrom(powerMethodGraph), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedGraphFrom(powerMethodGraph), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: undirectedGraphFrom(powerMethodGraph), + prefix: "# ", + + want: `# graph { +# // Node definitions. +# 0; +# 1; +# 2; +# 3; +# 4; +# +# // Edge definitions. +# 0 -- 1; +# 0 -- 2; +# 0 -- 4; +# 1 -- 3; +# 2 -- 3; +# 2 -- 4; +# 3 -- 4; +# }`, + }, + + // Names named nodes. + { + name: "PageRank", + g: directedNamedIDGraphFrom(pageRankGraph), + + want: `digraph PageRank { + // Node definitions. + A; + B; + C; + D; + E; + F; + G; + H; + I; + J; + K; + + // Edge definitions. + B -> C; + C -> B; + D -> A; + D -> B; + E -> B; + E -> D; + E -> F; + F -> B; + F -> E; + G -> B; + G -> E; + H -> B; + H -> E; + I -> B; + I -> E; + J -> E; + K -> E; +}`, + }, + { + g: undirectedNamedIDGraphFrom(pageRankGraph), + + want: `graph { + // Node definitions. + A; + B; + C; + D; + E; + F; + G; + H; + I; + J; + K; + + // Edge definitions. + A -- D; + B -- C; + B -- D; + B -- E; + B -- F; + B -- G; + B -- H; + B -- I; + D -- E; + E -- F; + E -- G; + E -- H; + E -- I; + E -- J; + E -- K; +}`, + }, + { + g: directedNamedIDGraphFrom(powerMethodGraph), + + want: `digraph { + // Node definitions. + A; + B; + C; + D; + E; + + // Edge definitions. + A -> B; + A -> C; + B -> D; + C -> D; + C -> E; + D -> E; + E -> A; +}`, + }, + { + g: undirectedNamedIDGraphFrom(powerMethodGraph), + + want: `graph { + // Node definitions. + A; + B; + C; + D; + E; + + // Edge definitions. + A -- B; + A -- C; + A -- E; + B -- D; + C -- D; + C -- E; + D -- E; +}`, + }, + { + g: undirectedNamedIDGraphFrom(powerMethodGraph), + prefix: "# ", + + want: `# graph { +# // Node definitions. +# A; +# B; +# C; +# D; +# E; +# +# // Edge definitions. +# A -- B; +# A -- C; +# A -- E; +# B -- D; +# C -- D; +# C -- E; +# D -- E; +# }`, + }, + + // Handling nodes with attributes. + { + g: directedNodeAttrGraphFrom(powerMethodGraph, nil), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedNodeAttrGraphFrom(powerMethodGraph, nil), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: directedNodeAttrGraphFrom(powerMethodGraph, [][]Attribute{ + 2: {{"fontsize", "16"}, {"shape", "ellipse"}}, + 4: {}, + }), + + want: `digraph { + // Node definitions. + 0; + 1; + 2 [ + fontsize=16 + shape=ellipse + ]; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedNodeAttrGraphFrom(powerMethodGraph, [][]Attribute{ + 2: {{"fontsize", "16"}, {"shape", "ellipse"}}, + 4: {}, + }), + + want: `graph { + // Node definitions. + 0; + 1; + 2 [ + fontsize=16 + shape=ellipse + ]; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: directedNamedIDNodeAttrGraphFrom(powerMethodGraph, [][]Attribute{ + 2: {{"fontsize", "16"}, {"shape", "ellipse"}}, + 4: {}, + }), + + want: `digraph { + // Node definitions. + A; + B; + C [ + fontsize=16 + shape=ellipse + ]; + D; + E; + + // Edge definitions. + A -> B; + A -> C; + B -> D; + C -> D; + C -> E; + D -> E; + E -> A; +}`, + }, + { + g: undirectedNamedIDNodeAttrGraphFrom(powerMethodGraph, [][]Attribute{ + 0: nil, + 1: nil, + 2: {{"fontsize", "16"}, {"shape", "ellipse"}}, + 3: nil, + 4: {}, + }), + + want: `graph { + // Node definitions. + A; + B; + C [ + fontsize=16 + shape=ellipse + ]; + D; + E; + + // Edge definitions. + A -- B; + A -- C; + A -- E; + B -- D; + C -- D; + C -- E; + D -- E; +}`, + }, + + // Handling edge with attributes. + { + g: directedEdgeAttrGraphFrom(powerMethodGraph, nil), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedEdgeAttrGraphFrom(powerMethodGraph, nil), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: directedEdgeAttrGraphFrom(powerMethodGraph, map[edge][]Attribute{ + edge{from: 0, to: 2}: {{"label", `"???"`}, {"style", "dashed"}}, + edge{from: 2, to: 4}: {}, + edge{from: 3, to: 4}: {{"color", "red"}}, + }), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2 [ + label="???" + style=dashed + ]; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4 [color=red]; + 4 -> 0; +}`, + }, + { + g: undirectedEdgeAttrGraphFrom(powerMethodGraph, map[edge][]Attribute{ + edge{from: 0, to: 2}: {{"label", `"???"`}, {"style", "dashed"}}, + edge{from: 2, to: 4}: {}, + edge{from: 3, to: 4}: {{"color", "red"}}, + }), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2 [ + label="???" + style=dashed + ]; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4 [color=red]; +}`, + }, + + // Handling nodes with ports. + { + g: directedPortedAttrGraphFrom(powerMethodGraph, nil, nil), + + want: `digraph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -> 1; + 0 -> 2; + 1 -> 3; + 2 -> 3; + 2 -> 4; + 3 -> 4; + 4 -> 0; +}`, + }, + { + g: undirectedPortedAttrGraphFrom(powerMethodGraph, nil, nil), + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; +}`, + }, + { + g: directedPortedAttrGraphFrom(powerMethodGraph, + [][]Attribute{ + 2: {{"shape", "record"}, {"label", `"English|German"`}}, + 4: {{"shape", "record"}, {"label", `"English|German"`}}, + }, + map[edge]portedEdge{ + edge{from: 0, to: 1}: {fromCompass: "s"}, + edge{from: 0, to: 2}: {fromCompass: "s", toPort: "Zwei", toCompass: "e"}, + edge{from: 2, to: 3}: {fromPort: "Zwei", fromCompass: "e"}, + edge{from: 2, to: 4}: {fromPort: "Two", fromCompass: "w", toPort: "Four", toCompass: "w"}, + edge{from: 3, to: 4}: {toPort: "Four", toCompass: "w"}, + edge{from: 4, to: 0}: {fromPort: "Four", fromCompass: "_", toCompass: "s"}, + }, + ), + + want: `digraph { + // Node definitions. + 0; + 1; + 2 [ + shape=record + label="English|German" + ]; + 3; + 4 [ + shape=record + label="English|German" + ]; + + // Edge definitions. + 0:s -> 1; + 0:s -> 2:Zwei:e; + 1 -> 3; + 2:Zwei:e -> 3; + 2:Two:w -> 4:Four:w; + 3 -> 4:Four:w; + 4:Four:_ -> 0:s; +}`, + }, + { + g: undirectedPortedAttrGraphFrom(powerMethodGraph, + [][]Attribute{ + 2: {{"shape", "record"}, {"label", `"English|German"`}}, + 4: {{"shape", "record"}, {"label", `"English|German"`}}, + }, + map[edge]portedEdge{ + edge{from: 0, to: 1}: {fromCompass: "s"}, + edge{from: 0, to: 2}: {fromCompass: "s", toPort: "Zwei", toCompass: "e"}, + edge{from: 2, to: 3}: {fromPort: "Zwei", fromCompass: "e"}, + edge{from: 2, to: 4}: {fromPort: "Two", fromCompass: "w", toPort: "Four", toCompass: "w"}, + edge{from: 3, to: 4}: {toPort: "Four", toCompass: "w"}, + + // This definition is reversed (see comment above at portedEdge + // definition) so that 4 gets the from port. This is a result + // of the fact that we sort nodes by ID, so the lower node + // will be always be printed first when the graph is undirected, + // thus becoming the from port, but we define the edges here + // from a directed adjacency list. + edge{from: 4, to: 0}: {fromCompass: "s", toPort: "Four", toCompass: "_"}, + }, + ), + + want: `graph { + // Node definitions. + 0; + 1; + 2 [ + shape=record + label="English|German" + ]; + 3; + 4 [ + shape=record + label="English|German" + ]; + + // Edge definitions. + 0:s -- 1; + 0:s -- 2:Zwei:e; + 0:s -- 4:Four:_; + 1 -- 3; + 2:Zwei:e -- 3; + 2:Two:w -- 4:Four:w; + 3 -- 4:Four:w; +}`, + }, + + // Handling graph attributes. + { + g: graphAttributer{Graph: undirectedEdgeAttrGraphFrom(powerMethodGraph, map[edge][]Attribute{ + edge{from: 0, to: 2}: {{"label", `"???"`}, {"style", "dashed"}}, + edge{from: 2, to: 4}: {}, + edge{from: 3, to: 4}: {{"color", "red"}}, + })}, + + want: `graph { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2 [ + label="???" + style=dashed + ]; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4 [color=red]; +}`, + }, + { + g: graphAttributer{Graph: undirectedEdgeAttrGraphFrom(powerMethodGraph, map[edge][]Attribute{ + edge{from: 0, to: 2}: {{"label", `"???"`}, {"style", "dashed"}}, + edge{from: 2, to: 4}: {}, + edge{from: 3, to: 4}: {{"color", "red"}}, + }), + graph: []Attribute{{"rankdir", `"LR"`}}, + node: []Attribute{{"fontsize", "16"}, {"shape", "ellipse"}}, + }, + + want: `graph { + graph [ + rankdir="LR" + ]; + node [ + fontsize=16 + shape=ellipse + ]; + + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2 [ + label="???" + style=dashed + ]; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4 [color=red]; +}`, + }, + + // Handling structured graphs. + { + g: undirectedStructuredGraphFrom(nil, powerMethodGraph, pageRankGraph), + + want: `graph { + subgraph A { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; + } + subgraph B { + // Node definitions. + 5; + 6; + 7; + 8; + 9; + 10; + 11; + 12; + 13; + 14; + 15; + + // Edge definitions. + 5 -- 8; + 6 -- 7; + 6 -- 8; + 6 -- 9; + 6 -- 10; + 6 -- 11; + 6 -- 12; + 6 -- 13; + 8 -- 9; + 9 -- 10; + 9 -- 11; + 9 -- 12; + 9 -- 13; + 9 -- 14; + 9 -- 15; + } +}`, + }, + { + g: undirectedStructuredGraphFrom([]edge{{from: 0, to: 9}}, powerMethodGraph, pageRankGraph), + + want: `graph { + subgraph A { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; + } + subgraph B { + // Node definitions. + 5; + 6; + 7; + 8; + 9; + 10; + 11; + 12; + 13; + 14; + 15; + + // Edge definitions. + 5 -- 8; + 6 -- 7; + 6 -- 8; + 6 -- 9; + 6 -- 10; + 6 -- 11; + 6 -- 12; + 6 -- 13; + 8 -- 9; + 9 -- 10; + 9 -- 11; + 9 -- 12; + 9 -- 13; + 9 -- 14; + 9 -- 15; + } + // Node definitions. + 0; + 9; + + // Edge definitions. + 0 -- 9; +}`, + }, + + // Handling subgraphs. + { + g: undirectedSubGraphFrom(pageRankGraph, map[int][]set{2: powerMethodGraph}), + + want: `graph { + // Node definitions. + 5; + 6; + 8; + 9; + 10; + 11; + 12; + 13; + 14; + 15; + + // Edge definitions. + 5 -- 8; + 6 -- subgraph H { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; + }; + 6 -- 8; + 6 -- 9; + 6 -- 10; + 6 -- 11; + 6 -- 12; + 6 -- 13; + 8 -- 9; + 9 -- 10; + 9 -- 11; + 9 -- 12; + 9 -- 13; + 9 -- 14; + 9 -- 15; +}`, + }, + { + name: "H", + g: undirectedSubGraphFrom(pageRankGraph, map[int][]set{1: powerMethodGraph}), + strict: true, + + want: `strict graph H { + // Node definitions. + 5; + 7; + 8; + 9; + 10; + 11; + 12; + 13; + 14; + 15; + + // Edge definitions. + 5 -- 8; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + + // Edge definitions. + 0 -- 1; + 0 -- 2; + 0 -- 4; + 1 -- 3; + 2 -- 3; + 2 -- 4; + 3 -- 4; + } -- 7; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 8; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 9; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 10; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 11; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 12; + subgraph G { + // Node definitions. + 0; + 1; + 2; + 3; + 4; + } -- 13; + 8 -- 9; + 9 -- 10; + 9 -- 11; + 9 -- 12; + 9 -- 13; + 9 -- 14; + 9 -- 15; +}`, + }, +} + +func TestEncode(t *testing.T) { + for i, test := range encodeTests { + got, err := Marshal(test.g, test.name, test.prefix, "\t", test.strict) + if err != nil { + t.Errorf("unexpected error: %v", err) + continue + } + if string(got) != test.want { + t.Errorf("unexpected DOT result for test %d:\ngot: %s\nwant:%s", i, got, test.want) + } + } +} diff --git a/graph/ex/fdpclust/gn.go b/graph/ex/fdpclust/gn.go new file mode 100644 index 00000000..f7d1a692 --- /dev/null +++ b/graph/ex/fdpclust/gn.go @@ -0,0 +1,278 @@ +package main + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +type GraphNode struct { + id int + neighbors []graph.Node + roots []*GraphNode +} + +func (g *GraphNode) Has(n graph.Node) bool { + if n.ID() == g.id { + return true + } + + visited := map[int]struct{}{g.id: struct{}{}} + for _, root := range g.roots { + if root.ID() == n.ID() { + return true + } + + if root.has(n, visited) { + return true + } + } + + for _, neigh := range g.neighbors { + if neigh.ID() == n.ID() { + return true + } + + if gn, ok := neigh.(*GraphNode); ok { + if gn.has(n, visited) { + return true + } + } + } + + return false +} + +func (g *GraphNode) has(n graph.Node, visited map[int]struct{}) bool { + for _, root := range g.roots { + if _, ok := visited[root.ID()]; ok { + continue + } + + visited[root.ID()] = struct{}{} + if root.ID() == n.ID() { + return true + } + + if root.has(n, visited) { + return true + } + + } + + for _, neigh := range g.neighbors { + if _, ok := visited[neigh.ID()]; ok { + continue + } + + visited[neigh.ID()] = struct{}{} + if neigh.ID() == n.ID() { + return true + } + + if gn, ok := neigh.(*GraphNode); ok { + if gn.has(n, visited) { + return true + } + } + + } + + return false +} + +func (g *GraphNode) Nodes() []graph.Node { + toReturn := []graph.Node{g} + visited := map[int]struct{}{g.id: struct{}{}} + + for _, root := range g.roots { + toReturn = append(toReturn, root) + visited[root.ID()] = struct{}{} + + toReturn = root.nodes(toReturn, visited) + } + + for _, neigh := range g.neighbors { + toReturn = append(toReturn, neigh) + visited[neigh.ID()] = struct{}{} + + if gn, ok := neigh.(*GraphNode); ok { + toReturn = gn.nodes(toReturn, visited) + } + } + + return toReturn +} + +func (g *GraphNode) nodes(list []graph.Node, visited map[int]struct{}) []graph.Node { + for _, root := range g.roots { + if _, ok := visited[root.ID()]; ok { + continue + } + visited[root.ID()] = struct{}{} + list = append(list, graph.Node(root)) + + list = root.nodes(list, visited) + } + + for _, neigh := range g.neighbors { + if _, ok := visited[neigh.ID()]; ok { + continue + } + + list = append(list, neigh) + if gn, ok := neigh.(*GraphNode); ok { + list = gn.nodes(list, visited) + } + } + + return list +} + +func (g *GraphNode) From(n graph.Node) []graph.Node { + if n.ID() == g.ID() { + return g.neighbors + } + + visited := map[int]struct{}{g.id: struct{}{}} + for _, root := range g.roots { + visited[root.ID()] = struct{}{} + + if result := root.findNeighbors(n, visited); result != nil { + return result + } + } + + for _, neigh := range g.neighbors { + visited[neigh.ID()] = struct{}{} + + if gn, ok := neigh.(*GraphNode); ok { + if result := gn.findNeighbors(n, visited); result != nil { + return result + } + } + } + + return nil +} + +func (g *GraphNode) findNeighbors(n graph.Node, visited map[int]struct{}) []graph.Node { + if n.ID() == g.ID() { + return g.neighbors + } + + for _, root := range g.roots { + if _, ok := visited[root.ID()]; ok { + continue + } + visited[root.ID()] = struct{}{} + + if result := root.findNeighbors(n, visited); result != nil { + return result + } + } + + for _, neigh := range g.neighbors { + if _, ok := visited[neigh.ID()]; ok { + continue + } + visited[neigh.ID()] = struct{}{} + + if gn, ok := neigh.(*GraphNode); ok { + if result := gn.findNeighbors(n, visited); result != nil { + return result + } + } + } + + return nil +} + +func (g *GraphNode) HasEdgeBetween(u, v graph.Node) bool { + return g.EdgeBetween(u, v) != nil +} + +func (g *GraphNode) Edge(u, v graph.Node) graph.Edge { + return g.EdgeBetween(u, v) +} + +func (g *GraphNode) EdgeBetween(u, v graph.Node) graph.Edge { + if u.ID() == g.id || v.ID() == g.id { + for _, neigh := range g.neighbors { + if neigh.ID() == u.ID() || neigh.ID() == v.ID() { + return simple.Edge{F: g, T: neigh} + } + } + return nil + } + + visited := map[int]struct{}{g.id: struct{}{}} + for _, root := range g.roots { + visited[root.ID()] = struct{}{} + if result := root.edgeBetween(u, v, visited); result != nil { + return result + } + } + + for _, neigh := range g.neighbors { + visited[neigh.ID()] = struct{}{} + if gn, ok := neigh.(*GraphNode); ok { + if result := gn.edgeBetween(u, v, visited); result != nil { + return result + } + } + } + + return nil +} + +func (g *GraphNode) edgeBetween(u, v graph.Node, visited map[int]struct{}) graph.Edge { + if u.ID() == g.id || v.ID() == g.id { + for _, neigh := range g.neighbors { + if neigh.ID() == u.ID() || neigh.ID() == v.ID() { + return simple.Edge{F: g, T: neigh} + } + } + return nil + } + + for _, root := range g.roots { + if _, ok := visited[root.ID()]; ok { + continue + } + visited[root.ID()] = struct{}{} + if result := root.edgeBetween(u, v, visited); result != nil { + return result + } + } + + for _, neigh := range g.neighbors { + if _, ok := visited[neigh.ID()]; ok { + continue + } + + visited[neigh.ID()] = struct{}{} + if gn, ok := neigh.(*GraphNode); ok { + if result := gn.edgeBetween(u, v, visited); result != nil { + return result + } + } + } + + return nil +} + +func (g *GraphNode) ID() int { + return g.id +} + +func (g *GraphNode) AddNeighbor(n *GraphNode) { + g.neighbors = append(g.neighbors, graph.Node(n)) +} + +func (g *GraphNode) AddRoot(n *GraphNode) { + g.roots = append(g.roots, n) +} + +func NewGraphNode(id int) *GraphNode { + return &GraphNode{id: id, neighbors: make([]graph.Node, 0), roots: make([]*GraphNode, 0)} +} diff --git a/graph/ex/fdpclust/main.go b/graph/ex/fdpclust/main.go new file mode 100644 index 00000000..eb14226a --- /dev/null +++ b/graph/ex/fdpclust/main.go @@ -0,0 +1,75 @@ +package main + +import ( + "fmt" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/topo" +) + +func main() { + // graph G { + G := NewGraphNode(0) + // e + e := NewGraphNode(1) + + // subgraph clusterA { + clusterA := NewGraphNode(2) + + // a -- b + a := NewGraphNode(3) + b := NewGraphNode(4) + a.AddNeighbor(b) + b.AddNeighbor(a) + clusterA.AddRoot(a) + clusterA.AddRoot(b) + + // subgraph clusterC { + clusterC := NewGraphNode(5) + // C -- D + C := NewGraphNode(6) + D := NewGraphNode(7) + C.AddNeighbor(D) + D.AddNeighbor(C) + + clusterC.AddRoot(C) + clusterC.AddRoot(D) + // } + clusterA.AddRoot(clusterC) + // } + + // subgraph clusterB { + clusterB := NewGraphNode(8) + + // d -- f + d := NewGraphNode(9) + f := NewGraphNode(10) + d.AddNeighbor(f) + f.AddNeighbor(d) + clusterB.AddRoot(d) + clusterB.AddRoot(f) + // } + + // d -- D + d.AddNeighbor(D) + D.AddNeighbor(d) + + // e -- clusterB + e.AddNeighbor(clusterB) + clusterB.AddNeighbor(e) + + // clusterC -- clusterB + clusterC.AddNeighbor(clusterB) + clusterB.AddNeighbor(clusterC) + + G.AddRoot(e) + G.AddRoot(clusterA) + G.AddRoot(clusterB) + // } + + if !topo.IsPathIn(G, []graph.Node{C, D, d, f}) { + fmt.Println("Not working!") + } else { + fmt.Println("Working!") + } +} diff --git a/graph/formats/dot/README.md b/graph/formats/dot/README.md new file mode 100644 index 00000000..6949ce03 --- /dev/null +++ b/graph/formats/dot/README.md @@ -0,0 +1,9 @@ +# formats/dot + +## License + +The source code and any original content of the formats/dot directory is released under [Public Domain Dedication](https://creativecommons.org/publicdomain/zero/1.0/). + +The source code is also licensed under the gonum license, and users are free to choice the license which suits their needs. + +Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/graph/formats/dot/ast/ast.go b/graph/formats/dot/ast/ast.go new file mode 100644 index 00000000..a8ac7bf8 --- /dev/null +++ b/graph/formats/dot/ast/ast.go @@ -0,0 +1,408 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +// Package ast declares the types used to represent abstract syntax trees of +// Graphviz DOT graphs. +package ast + +import ( + "bytes" + "fmt" +) + +// === [ File ] ================================================================ + +// A File represents a DOT file. +// +// Examples. +// +// digraph G { +// A -> B +// } +// graph H { +// C - D +// } +type File struct { + // Graphs. + Graphs []*Graph +} + +// String returns the string representation of the file. +func (f *File) String() string { + buf := new(bytes.Buffer) + for i, graph := range f.Graphs { + if i != 0 { + buf.WriteString("\n") + } + buf.WriteString(graph.String()) + } + return buf.String() +} + +// === [ Graphs ] ============================================================== + +// A Graph represents a directed or an undirected graph. +// +// Examples. +// +// digraph G { +// A -> {B C} +// B -> C +// } +type Graph struct { + // Strict graph; multi-edges forbidden. + Strict bool + // Directed graph. + Directed bool + // Graph ID; or empty if anonymous. + ID string + // Graph statements. + Stmts []Stmt +} + +// String returns the string representation of the graph. +func (g *Graph) String() string { + buf := new(bytes.Buffer) + if g.Strict { + buf.WriteString("strict ") + } + if g.Directed { + buf.WriteString("digraph ") + } else { + buf.WriteString("graph ") + } + if len(g.ID) > 0 { + fmt.Fprintf(buf, "%s ", g.ID) + } + buf.WriteString("{\n") + for _, stmt := range g.Stmts { + fmt.Fprintf(buf, "\t%s\n", stmt) + } + buf.WriteString("}") + return buf.String() +} + +// === [ Statements ] ========================================================== + +// A Stmt represents a statement, and has one of the following underlying types. +// +// *NodeStmt +// *EdgeStmt +// *AttrStmt +// *Attr +// *Subgraph +type Stmt interface { + fmt.Stringer + // isStmt ensures that only statements can be assigned to the Stmt interface. + isStmt() +} + +// --- [ Node statement ] ------------------------------------------------------ + +// A NodeStmt represents a node statement. +// +// Examples. +// +// A [color=blue] +type NodeStmt struct { + // Node. + Node *Node + // Node attributes. + Attrs []*Attr +} + +// String returns the string representation of the node statement. +func (e *NodeStmt) String() string { + buf := new(bytes.Buffer) + buf.WriteString(e.Node.String()) + if len(e.Attrs) > 0 { + buf.WriteString(" [") + for i, attr := range e.Attrs { + if i != 0 { + buf.WriteString(" ") + } + buf.WriteString(attr.String()) + } + buf.WriteString("]") + } + return buf.String() +} + +// --- [ Edge statement ] ------------------------------------------------------ + +// An EdgeStmt represents an edge statement. +// +// Examples. +// +// A -> B +// A -> {B C} +// A -> B -> C +type EdgeStmt struct { + // Source vertex. + From Vertex + // Outgoing edge. + To *Edge + // Edge attributes. + Attrs []*Attr +} + +// String returns the string representation of the edge statement. +func (e *EdgeStmt) String() string { + buf := new(bytes.Buffer) + fmt.Fprintf(buf, "%s %s", e.From, e.To) + if len(e.Attrs) > 0 { + buf.WriteString(" [") + for i, attr := range e.Attrs { + if i != 0 { + buf.WriteString(" ") + } + buf.WriteString(attr.String()) + } + buf.WriteString("]") + } + return buf.String() +} + +// An Edge represents an edge between two vertices. +type Edge struct { + // Directed edge. + Directed bool + // Destination vertex. + Vertex Vertex + // Outgoing edge; or nil if none. + To *Edge +} + +// String returns the string representation of the edge. +func (e *Edge) String() string { + op := "--" + if e.Directed { + op = "->" + } + if e.To != nil { + return fmt.Sprintf("%s %s %s", op, e.Vertex, e.To) + } + return fmt.Sprintf("%s %s", op, e.Vertex) +} + +// --- [ Attribute statement ] ------------------------------------------------- + +// An AttrStmt represents an attribute statement. +// +// Examples. +// +// graph [rankdir=LR] +// node [color=blue fillcolor=red] +// edge [minlen=1] +type AttrStmt struct { + // Graph component kind to which the attributes are assigned. + Kind Kind + // Attributes. + Attrs []*Attr +} + +// String returns the string representation of the attribute statement. +func (a *AttrStmt) String() string { + buf := new(bytes.Buffer) + fmt.Fprintf(buf, "%s [", a.Kind) + for i, attr := range a.Attrs { + if i != 0 { + buf.WriteString(" ") + } + buf.WriteString(attr.String()) + } + buf.WriteString("]") + return buf.String() +} + +// Kind specifies the set of graph components to which attribute statements may +// be assigned. +type Kind uint + +// Graph component kinds. +const ( + KindGraph Kind = iota // graph + KindNode // node + KindEdge // edge +) + +// String returns the string representation of the graph component kind. +func (k Kind) String() string { + switch k { + case KindGraph: + return "graph" + case KindNode: + return "node" + case KindEdge: + return "edge" + } + panic(fmt.Sprintf("invalid graph component kind (%d)", uint(k))) +} + +// --- [ Attribute ] ----------------------------------------------------------- + +// An Attr represents an attribute. +// +// Examples. +// +// rank=same +type Attr struct { + // Attribute key. + Key string + // Attribute value. + Val string +} + +// String returns the string representation of the attribute. +func (a *Attr) String() string { + return fmt.Sprintf("%s=%s", a.Key, a.Val) +} + +// --- [ Subgraph ] ------------------------------------------------------------ + +// A Subgraph represents a subgraph vertex. +// +// Examples. +// +// subgraph S {A B C} +type Subgraph struct { + // Subgraph ID; or empty if none. + ID string + // Subgraph statements. + Stmts []Stmt +} + +// String returns the string representation of the subgraph. +func (s *Subgraph) String() string { + buf := new(bytes.Buffer) + if len(s.ID) > 0 { + fmt.Fprintf(buf, "subgraph %s ", s.ID) + } + buf.WriteString("{") + for i, stmt := range s.Stmts { + if i != 0 { + buf.WriteString(" ") + } + buf.WriteString(stmt.String()) + } + buf.WriteString("}") + return buf.String() +} + +// isStmt ensures that only statements can be assigned to the Stmt interface. +func (*NodeStmt) isStmt() {} +func (*EdgeStmt) isStmt() {} +func (*AttrStmt) isStmt() {} +func (*Attr) isStmt() {} +func (*Subgraph) isStmt() {} + +// === [ Vertices ] ============================================================ + +// A Vertex represents a vertex, and has one of the following underlying types. +// +// *Node +// *Subgraph +type Vertex interface { + fmt.Stringer + // isVertex ensures that only vertices can be assigned to the Vertex + // interface. + isVertex() +} + +// --- [ Node identifier ] ----------------------------------------------------- + +// A Node represents a node vertex. +// +// Examples. +// +// A +// A:nw +type Node struct { + // Node ID. + ID string + // Node port; or nil if none. + Port *Port +} + +// String returns the string representation of the node. +func (n *Node) String() string { + if n.Port != nil { + return fmt.Sprintf("%s%s", n.ID, n.Port) + } + return n.ID +} + +// A Port specifies where on a node an edge should be aimed. +type Port struct { + // Port ID; or empty if none. + ID string + // Compass point. + CompassPoint CompassPoint +} + +// String returns the string representation of the port. +func (p *Port) String() string { + buf := new(bytes.Buffer) + if len(p.ID) > 0 { + fmt.Fprintf(buf, ":%s", p.ID) + } + if p.CompassPoint != CompassPointDefault { + fmt.Fprintf(buf, ":%s", p.CompassPoint) + } + return buf.String() +} + +// CompassPoint specifies the set of compass points. +type CompassPoint uint + +// Compass points. +const ( + CompassPointDefault CompassPoint = iota // _ + CompassPointNorth // n + CompassPointNorthEast // ne + CompassPointEast // e + CompassPointSouthEast // se + CompassPointSouth // s + CompassPointSouthWest // sw + CompassPointWest // w + CompassPointNorthWest // nw + CompassPointCenter // c +) + +// String returns the string representation of the compass point. +func (c CompassPoint) String() string { + switch c { + case CompassPointDefault: + return "_" + case CompassPointNorth: + return "n" + case CompassPointNorthEast: + return "ne" + case CompassPointEast: + return "e" + case CompassPointSouthEast: + return "se" + case CompassPointSouth: + return "s" + case CompassPointSouthWest: + return "sw" + case CompassPointWest: + return "w" + case CompassPointNorthWest: + return "nw" + case CompassPointCenter: + return "c" + } + panic(fmt.Sprintf("invalid compass point (%d)", uint(c))) +} + +// isVertex ensures that only vertices can be assigned to the Vertex interface. +func (*Node) isVertex() {} +func (*Subgraph) isVertex() {} diff --git a/graph/formats/dot/ast/ast_test.go b/graph/formats/dot/ast/ast_test.go new file mode 100644 index 00000000..2417dce5 --- /dev/null +++ b/graph/formats/dot/ast/ast_test.go @@ -0,0 +1,101 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package ast_test + +import ( + "bytes" + "io/ioutil" + "testing" + + "gonum.org/v1/gonum/graph/formats/dot" + "gonum.org/v1/gonum/graph/formats/dot/ast" +) + +func TestParseFile(t *testing.T) { + golden := []struct { + in string + out string + }{ + {in: "../internal/testdata/empty.dot"}, + {in: "../internal/testdata/graph.dot"}, + {in: "../internal/testdata/digraph.dot"}, + {in: "../internal/testdata/strict.dot"}, + {in: "../internal/testdata/multi.dot"}, + {in: "../internal/testdata/named_graph.dot"}, + {in: "../internal/testdata/node_stmt.dot"}, + {in: "../internal/testdata/edge_stmt.dot"}, + {in: "../internal/testdata/attr_stmt.dot"}, + {in: "../internal/testdata/attr.dot"}, + { + in: "../internal/testdata/subgraph.dot", + out: "../internal/testdata/subgraph.golden", + }, + { + in: "../internal/testdata/semi.dot", + out: "../internal/testdata/semi.golden", + }, + { + in: "../internal/testdata/empty_attr.dot", + out: "../internal/testdata/empty_attr.golden", + }, + { + in: "../internal/testdata/attr_lists.dot", + out: "../internal/testdata/attr_lists.golden", + }, + { + in: "../internal/testdata/attr_sep.dot", + out: "../internal/testdata/attr_sep.golden", + }, + {in: "../internal/testdata/subgraph_vertex.dot"}, + { + in: "../internal/testdata/port.dot", + out: "../internal/testdata/port.golden", + }, + } + for _, g := range golden { + file, err := dot.ParseFile(g.in) + if err != nil { + t.Errorf("%q: unable to parse file; %v", g.in, err) + continue + } + // If no output path is specified, the input is already golden. + out := g.in + if len(g.out) > 0 { + out = g.out + } + buf, err := ioutil.ReadFile(out) + if err != nil { + t.Errorf("%q: unable to read file; %v", g.in, err) + continue + } + got := file.String() + // Remove trailing newline. + want := string(bytes.TrimSpace(buf)) + if got != want { + t.Errorf("%q: graph mismatch; expected %q, got %q", g.in, want, got) + } + } +} + +// Verify that all statements implement the Stmt interface. +var ( + _ ast.Stmt = (*ast.NodeStmt)(nil) + _ ast.Stmt = (*ast.EdgeStmt)(nil) + _ ast.Stmt = (*ast.AttrStmt)(nil) + _ ast.Stmt = (*ast.Attr)(nil) + _ ast.Stmt = (*ast.Subgraph)(nil) +) + +// Verify that all vertices implement the Vertex interface. +var ( + _ ast.Vertex = (*ast.Node)(nil) + _ ast.Vertex = (*ast.Subgraph)(nil) +) diff --git a/graph/formats/dot/dot.go b/graph/formats/dot/dot.go new file mode 100644 index 00000000..6fbbe3b2 --- /dev/null +++ b/graph/formats/dot/dot.go @@ -0,0 +1,63 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +// Package dot implements a parser for Graphviz DOT files. +package dot + +import ( + "fmt" + "io" + "io/ioutil" + + "gonum.org/v1/gonum/graph/formats/dot/ast" + "gonum.org/v1/gonum/graph/formats/dot/internal/lexer" + "gonum.org/v1/gonum/graph/formats/dot/internal/parser" +) + +// ParseFile parses the given Graphviz DOT file into an AST. +func ParseFile(path string) (*ast.File, error) { + buf, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + return ParseBytes(buf) +} + +// Parse parses the given Graphviz DOT file into an AST, reading from r. +func Parse(r io.Reader) (*ast.File, error) { + buf, err := ioutil.ReadAll(r) + if err != nil { + return nil, err + } + return ParseBytes(buf) +} + +// ParseBytes parses the given Graphviz DOT file into an AST, reading from b. +func ParseBytes(b []byte) (*ast.File, error) { + l := lexer.NewLexer(b) + p := parser.NewParser() + file, err := p.Parse(l) + if err != nil { + return nil, err + } + f, ok := file.(*ast.File) + if !ok { + return nil, fmt.Errorf("invalid file type; expected *ast.File, got %T", file) + } + if err := check(f); err != nil { + return nil, err + } + return f, nil +} + +// ParseString parses the given Graphviz DOT file into an AST, reading from s. +func ParseString(s string) (*ast.File, error) { + return ParseBytes([]byte(s)) +} diff --git a/graph/formats/dot/internal/Makefile b/graph/formats/dot/internal/Makefile new file mode 100644 index 00000000..e31b4612 --- /dev/null +++ b/graph/formats/dot/internal/Makefile @@ -0,0 +1,37 @@ +gen: dot.bnf + gocc $< + # TODO: Remove once https://github.com/goccmack/gocc/issues/36 gets resolved. + ./paste_copyright.bash + find . -type f -name '*.go' | xargs goimports -w + +debug_lexer: dot.bnf + gocc -debug_lexer -v -a $< + # TODO: Remove once https://github.com/goccmack/gocc/issues/36 gets resolved. + find . -type f -name '*.go' | xargs goimports -w + +debug_parser: dot.bnf + gocc -debug_parser -v -a $< + # TODO: Remove once https://github.com/goccmack/gocc/issues/36 gets resolved. + find . -type f -name '*.go' | xargs goimports -w + +clean: + rm -f errors/errors.go + rm -f lexer/acttab.go + rm -f lexer/lexer.go + rm -f lexer/transitiontable.go + rm -f parser/action.go + rm -f parser/actiontable.go + rm -f parser/gototable.go + rm -f parser/parser.go + rm -f parser/productionstable.go + rm -f token/token.go + rm -f util/litconv.go + rm -f util/rune.go + -rmdir --ignore-fail-on-non-empty errors + -rmdir --ignore-fail-on-non-empty lexer + -rmdir --ignore-fail-on-non-empty parser + -rmdir --ignore-fail-on-non-empty token + -rmdir --ignore-fail-on-non-empty util + rm -f terminals.txt LR1_conflicts.txt LR1_sets.txt first.txt lexer_sets.txt + +.PHONY: gen debug_lexer debug_parser clean diff --git a/graph/formats/dot/internal/astx/astx.go b/graph/formats/dot/internal/astx/astx.go new file mode 100644 index 00000000..e52a5e7c --- /dev/null +++ b/graph/formats/dot/internal/astx/astx.go @@ -0,0 +1,328 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +// Package astx implements utility functions for generating abstract syntax +// trees of Graphviz DOT graphs. +package astx + +import ( + "fmt" + "strings" + + "gonum.org/v1/gonum/graph/formats/dot/ast" + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +// === [ File ] ================================================================ + +// NewFile returns a new file based on the given graph. +func NewFile(graph interface{}) (*ast.File, error) { + g, ok := graph.(*ast.Graph) + if !ok { + return nil, fmt.Errorf("invalid graph type; expected *ast.Graph, got %T", graph) + } + return &ast.File{Graphs: []*ast.Graph{g}}, nil +} + +// AppendGraph appends graph to the given file. +func AppendGraph(file, graph interface{}) (*ast.File, error) { + f, ok := file.(*ast.File) + if !ok { + return nil, fmt.Errorf("invalid file type; expected *ast.File, got %T", file) + } + g, ok := graph.(*ast.Graph) + if !ok { + return nil, fmt.Errorf("invalid graph type; expected *ast.Graph, got %T", graph) + } + f.Graphs = append(f.Graphs, g) + return f, nil +} + +// === [ Graphs ] ============================================================== + +// NewGraph returns a new graph based on the given graph strictness, direction, +// optional ID and optional statements. +func NewGraph(strict, directed, optID, optStmts interface{}) (*ast.Graph, error) { + s, ok := strict.(bool) + if !ok { + return nil, fmt.Errorf("invalid strictness type; expected bool, got %T", strict) + } + d, ok := directed.(bool) + if !ok { + return nil, fmt.Errorf("invalid direction type; expected bool, got %T", directed) + } + id, ok := optID.(string) + if optID != nil && !ok { + return nil, fmt.Errorf("invalid ID type; expected string or nil, got %T", optID) + } + stmts, ok := optStmts.([]ast.Stmt) + if optStmts != nil && !ok { + return nil, fmt.Errorf("invalid statements type; expected []ast.Stmt or nil, got %T", optStmts) + } + return &ast.Graph{Strict: s, Directed: d, ID: id, Stmts: stmts}, nil +} + +// === [ Statements ] ========================================================== + +// NewStmtList returns a new statement list based on the given statement. +func NewStmtList(stmt interface{}) ([]ast.Stmt, error) { + s, ok := stmt.(ast.Stmt) + if !ok { + return nil, fmt.Errorf("invalid statement type; expected ast.Stmt, got %T", stmt) + } + return []ast.Stmt{s}, nil +} + +// AppendStmt appends stmt to the given statement list. +func AppendStmt(list, stmt interface{}) ([]ast.Stmt, error) { + l, ok := list.([]ast.Stmt) + if !ok { + return nil, fmt.Errorf("invalid statement list type; expected []ast.Stmt, got %T", list) + } + s, ok := stmt.(ast.Stmt) + if !ok { + return nil, fmt.Errorf("invalid statement type; expected ast.Stmt, got %T", stmt) + } + return append(l, s), nil +} + +// --- [ Node statement ] ------------------------------------------------------ + +// NewNodeStmt returns a new node statement based on the given node and optional +// attributes. +func NewNodeStmt(node, optAttrs interface{}) (*ast.NodeStmt, error) { + n, ok := node.(*ast.Node) + if !ok { + return nil, fmt.Errorf("invalid node type; expected *ast.Node, got %T", node) + } + attrs, ok := optAttrs.([]*ast.Attr) + if optAttrs != nil && !ok { + return nil, fmt.Errorf("invalid attributes type; expected []*ast.Attr or nil, got %T", optAttrs) + } + return &ast.NodeStmt{Node: n, Attrs: attrs}, nil +} + +// --- [ Edge statement ] ------------------------------------------------------ + +// NewEdgeStmt returns a new edge statement based on the given source vertex, +// outgoing edge and optional attributes. +func NewEdgeStmt(from, to, optAttrs interface{}) (*ast.EdgeStmt, error) { + f, ok := from.(ast.Vertex) + if !ok { + return nil, fmt.Errorf("invalid source vertex type; expected ast.Vertex, got %T", from) + } + t, ok := to.(*ast.Edge) + if !ok { + return nil, fmt.Errorf("invalid outgoing edge type; expected *ast.Edge, got %T", to) + } + attrs, ok := optAttrs.([]*ast.Attr) + if optAttrs != nil && !ok { + return nil, fmt.Errorf("invalid attributes type; expected []*ast.Attr or nil, got %T", optAttrs) + } + return &ast.EdgeStmt{From: f, To: t, Attrs: attrs}, nil +} + +// NewEdge returns a new edge based on the given edge direction, destination +// vertex and optional outgoing edge. +func NewEdge(directed, vertex, optTo interface{}) (*ast.Edge, error) { + d, ok := directed.(bool) + if !ok { + return nil, fmt.Errorf("invalid direction type; expected bool, got %T", directed) + } + v, ok := vertex.(ast.Vertex) + if !ok { + return nil, fmt.Errorf("invalid destination vertex type; expected ast.Vertex, got %T", vertex) + } + to, ok := optTo.(*ast.Edge) + if optTo != nil && !ok { + return nil, fmt.Errorf("invalid outgoing edge type; expected *ast.Edge or nil, got %T", optTo) + } + return &ast.Edge{Directed: d, Vertex: v, To: to}, nil +} + +// --- [ Attribute statement ] ------------------------------------------------- + +// NewAttrStmt returns a new attribute statement based on the given graph +// component kind and attributes. +func NewAttrStmt(kind, optAttrs interface{}) (*ast.AttrStmt, error) { + k, ok := kind.(ast.Kind) + if !ok { + return nil, fmt.Errorf("invalid graph component kind type; expected ast.Kind, got %T", kind) + } + attrs, ok := optAttrs.([]*ast.Attr) + if optAttrs != nil && !ok { + return nil, fmt.Errorf("invalid attributes type; expected []*ast.Attr or nil, got %T", optAttrs) + } + return &ast.AttrStmt{Kind: k, Attrs: attrs}, nil +} + +// NewAttrList returns a new attribute list based on the given attribute. +func NewAttrList(attr interface{}) ([]*ast.Attr, error) { + a, ok := attr.(*ast.Attr) + if !ok { + return nil, fmt.Errorf("invalid attribute type; expected *ast.Attr, got %T", attr) + } + return []*ast.Attr{a}, nil +} + +// AppendAttr appends attr to the given attribute list. +func AppendAttr(list, attr interface{}) ([]*ast.Attr, error) { + l, ok := list.([]*ast.Attr) + if !ok { + return nil, fmt.Errorf("invalid attribute list type; expected []*ast.Attr, got %T", list) + } + a, ok := attr.(*ast.Attr) + if !ok { + return nil, fmt.Errorf("invalid attribute type; expected *ast.Attr, got %T", attr) + } + return append(l, a), nil +} + +// AppendAttrList appends the optional attrs to the given optional attribute +// list. +func AppendAttrList(optList, optAttrs interface{}) ([]*ast.Attr, error) { + list, ok := optList.([]*ast.Attr) + if optList != nil && !ok { + return nil, fmt.Errorf("invalid attribute list type; expected []*ast.Attr or nil, got %T", optList) + } + attrs, ok := optAttrs.([]*ast.Attr) + if optAttrs != nil && !ok { + return nil, fmt.Errorf("invalid attributes type; expected []*ast.Attr or nil, got %T", optAttrs) + } + return append(list, attrs...), nil +} + +// --- [ Attribute ] ----------------------------------------------------------- + +// NewAttr returns a new attribute based on the given key-value pair. +func NewAttr(key, val interface{}) (*ast.Attr, error) { + k, ok := key.(string) + if !ok { + return nil, fmt.Errorf("invalid key type; expected string, got %T", key) + } + v, ok := val.(string) + if !ok { + return nil, fmt.Errorf("invalid value type; expected string, got %T", val) + } + return &ast.Attr{Key: k, Val: v}, nil +} + +// --- [ Subgraph ] ------------------------------------------------------------ + +// NewSubgraph returns a new subgraph based on the given optional subgraph ID +// and optional statements. +func NewSubgraph(optID, optStmts interface{}) (*ast.Subgraph, error) { + id, ok := optID.(string) + if optID != nil && !ok { + return nil, fmt.Errorf("invalid ID type; expected string or nil, got %T", optID) + } + stmts, ok := optStmts.([]ast.Stmt) + if optStmts != nil && !ok { + return nil, fmt.Errorf("invalid statements type; expected []ast.Stmt or nil, got %T", optStmts) + } + return &ast.Subgraph{ID: id, Stmts: stmts}, nil +} + +// === [ Vertices ] ============================================================ + +// --- [ Node identifier ] ----------------------------------------------------- + +// NewNode returns a new node based on the given node id and optional port. +func NewNode(id, optPort interface{}) (*ast.Node, error) { + i, ok := id.(string) + if !ok { + return nil, fmt.Errorf("invalid ID type; expected string, got %T", id) + } + port, ok := optPort.(*ast.Port) + if optPort != nil && !ok { + return nil, fmt.Errorf("invalid port type; expected *ast.Port or nil, got %T", optPort) + } + return &ast.Node{ID: i, Port: port}, nil +} + +// NewPort returns a new port based on the given id and optional compass point. +func NewPort(id, optCompassPoint interface{}) (*ast.Port, error) { + // Note, if optCompassPoint is nil, id may be either an identifier or a + // compass point. + // + // The following strings are valid compass points: + // + // "n", "ne", "e", "se", "s", "sw", "w", "nw", "c" and "_" + i, ok := id.(string) + if !ok { + return nil, fmt.Errorf("invalid ID type; expected string, got %T", id) + } + + // Early return if optional compass point is absent and ID is a valid compass + // point. + if optCompassPoint == nil { + if compassPoint, ok := getCompassPoint(i); ok { + return &ast.Port{CompassPoint: compassPoint}, nil + } + } + + c, ok := optCompassPoint.(string) + if optCompassPoint != nil && !ok { + return nil, fmt.Errorf("invalid compass point type; expected string or nil, got %T", optCompassPoint) + } + compassPoint, _ := getCompassPoint(c) + return &ast.Port{ID: i, CompassPoint: compassPoint}, nil +} + +// getCompassPoint returns the corresponding compass point to the given string, +// and a boolean value indicating if such a compass point exists. +func getCompassPoint(s string) (ast.CompassPoint, bool) { + switch s { + case "_": + return ast.CompassPointDefault, true + case "n": + return ast.CompassPointNorth, true + case "ne": + return ast.CompassPointNorthEast, true + case "e": + return ast.CompassPointEast, true + case "se": + return ast.CompassPointSouthEast, true + case "s": + return ast.CompassPointSouth, true + case "sw": + return ast.CompassPointSouthWest, true + case "w": + return ast.CompassPointWest, true + case "nw": + return ast.CompassPointNorthWest, true + case "c": + return ast.CompassPointCenter, true + } + return ast.CompassPointDefault, false +} + +// === [ Identifiers ] ========================================================= + +// NewID returns a new identifier based on the given ID token. +func NewID(id interface{}) (string, error) { + i, ok := id.(*token.Token) + if !ok { + return "", fmt.Errorf("invalid identifier type; expected *token.Token, got %T", id) + } + s := string(i.Lit) + + // As another aid for readability, dot allows double-quoted strings to span + // multiple physical lines using the standard C convention of a backslash + // immediately preceding a newline character. + if strings.HasPrefix(s, `"`) && strings.HasSuffix(s, `"`) { + // Strip "\\\n" sequences. + s = strings.Replace(s, "\\\n", "", -1) + } + + // TODO: Add support for concatenated using a '+' operator. + + return s, nil +} diff --git a/graph/formats/dot/internal/astx/astx_test.go b/graph/formats/dot/internal/astx/astx_test.go new file mode 100644 index 00000000..4ec55000 --- /dev/null +++ b/graph/formats/dot/internal/astx/astx_test.go @@ -0,0 +1,90 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package astx_test + +import ( + "bytes" + "io/ioutil" + "testing" + + "gonum.org/v1/gonum/graph/formats/dot" +) + +func TestParseFile(t *testing.T) { + golden := []struct { + in string + out string + }{ + {in: "../testdata/empty.dot"}, + {in: "../testdata/graph.dot"}, + {in: "../testdata/digraph.dot"}, + {in: "../testdata/strict.dot"}, + {in: "../testdata/multi.dot"}, + {in: "../testdata/named_graph.dot"}, + {in: "../testdata/node_stmt.dot"}, + {in: "../testdata/edge_stmt.dot"}, + {in: "../testdata/attr_stmt.dot"}, + {in: "../testdata/attr.dot"}, + { + in: "../testdata/subgraph.dot", + out: "../testdata/subgraph.golden", + }, + { + in: "../testdata/semi.dot", + out: "../testdata/semi.golden", + }, + { + in: "../testdata/empty_attr.dot", + out: "../testdata/empty_attr.golden", + }, + { + in: "../testdata/attr_lists.dot", + out: "../testdata/attr_lists.golden", + }, + { + in: "../testdata/attr_sep.dot", + out: "../testdata/attr_sep.golden", + }, + {in: "../testdata/subgraph_vertex.dot"}, + { + in: "../testdata/port.dot", + out: "../testdata/port.golden", + }, + {in: "../testdata/quoted_id.dot"}, + { + in: "../testdata/backslash_newline_id.dot", + out: "../testdata/backslash_newline_id.golden", + }, + } + for _, g := range golden { + file, err := dot.ParseFile(g.in) + if err != nil { + t.Errorf("%q: unable to parse file; %v", g.in, err) + continue + } + // If no output path is specified, the input is already golden. + out := g.in + if len(g.out) > 0 { + out = g.out + } + buf, err := ioutil.ReadFile(out) + if err != nil { + t.Errorf("%q: unable to read file; %v", g.in, err) + continue + } + got := file.String() + // Remove trailing newline. + want := string(bytes.TrimSpace(buf)) + if got != want { + t.Errorf("%q: graph mismatch; expected `%s`, got `%s`", g.in, want, got) + } + } +} diff --git a/graph/formats/dot/internal/dot.bnf b/graph/formats/dot/internal/dot.bnf new file mode 100644 index 00000000..a86a867c --- /dev/null +++ b/graph/formats/dot/internal/dot.bnf @@ -0,0 +1,358 @@ +// The DOT Language +// +// http://www.graphviz.org/doc/info/lang.html + +// ### [ Tokens ] ############################################################## + +// The keywords node, edge, graph, digraph, subgraph, and strict are case- +// independent. + +node + : 'n' 'o' 'd' 'e' + | 'N' 'o' 'd' 'e' + | 'N' 'O' 'D' 'E' +; + +edge + : 'e' 'd' 'g' 'e' + | 'E' 'd' 'g' 'e' + | 'E' 'D' 'G' 'E' +; + +// TODO: Rename graphx to graph once gocc#20 is fixed [1]. +// +// [1]: https://github.com/goccmack/gocc/issues/20 + +graphx + : 'g' 'r' 'a' 'p' 'h' + | 'G' 'r' 'a' 'p' 'h' + | 'G' 'R' 'A' 'P' 'H' +; + +digraph + : 'd' 'i' 'g' 'r' 'a' 'p' 'h' + | 'D' 'i' 'g' 'r' 'a' 'p' 'h' + | 'd' 'i' 'G' 'r' 'a' 'p' 'h' + | 'D' 'i' 'G' 'r' 'a' 'p' 'h' + | 'D' 'I' 'G' 'R' 'A' 'P' 'H' +; + +subgraph + : 's' 'u' 'b' 'g' 'r' 'a' 'p' 'h' + | 'S' 'u' 'b' 'g' 'r' 'a' 'p' 'h' + | 's' 'u' 'b' 'G' 'r' 'a' 'p' 'h' + | 'S' 'u' 'b' 'G' 'r' 'a' 'p' 'h' + | 'S' 'U' 'B' 'G' 'R' 'A' 'P' 'H' +; + +strict + : 's' 't' 'r' 'i' 'c' 't' + | 'S' 't' 'r' 'i' 'c' 't' + | 'S' 'T' 'R' 'I' 'C' 'T' +; + +// An arbitrary ASCII character except null (0x00), double quote (0x22) and +// backslash (0x5C). +_ascii_char + // skip null (0x00) + : '\x01' - '\x21' + // skip double quote (0x22) + | '\x23' - '\x5B' + // skip backslash (0x5C) + | '\x5D' - '\x7F' +; + +_ascii_letter + : 'a' - 'z' + | 'A' - 'Z' +; + +_ascii_digit : '0' - '9' ; + +_unicode_char + : _ascii_char + | _unicode_byte +; + +_unicode_byte + : '\u0080' - '\uFFFC' + // skip invalid code point (\uFFFD) + | '\uFFFE' - '\U0010FFFF' +; + +_letter : _ascii_letter | _unicode_byte | '_' ; +_decimal_digit : _ascii_digit ; +_decimals : _decimal_digit { _decimal_digit } ; + +// An ID is one of the following: +// +// 1) Any string of alphabetic ([a-zA-Z\200-\377]) characters, underscores +// ('_') or digits ([0-9]), not beginning with a digit; +// +// 2) a numeral [-]?(.[0-9]+ | [0-9]+(.[0-9]*)? ); +// +// 3) any double-quoted string ("...") possibly containing escaped quotes +// (\"); +// +// 4) an HTML string (<...>). + +id + : _letter { _letter | _decimal_digit } + | _int_lit + | _string_lit + | _html_lit +; + +_int_lit + : [ '-' ] '.' _decimals + | [ '-' ] _decimals [ '.' { _decimal_digit } ] +; + +// In quoted strings in DOT, the only escaped character is double-quote ("). +// That is, in quoted strings, the dyad \" is converted to "; all other +// characters are left unchanged. In particular, \\ remains \\. + +// As another aid for readability, dot allows double-quoted strings to span +// multiple physical lines using the standard C convention of a backslash +// immediately preceding a newline character. + +// In addition, double-quoted strings can be concatenated using a '+' operator. + +_escaped_char : '\\' ( _unicode_char | '"' | '\\' ) ; +_char : _unicode_char | _escaped_char ; +_string_lit : '"' { _char } '"' ; + +// An arbitrary HTML character except null (0x00), left angle bracket (0x3C) and +// right angle bracket (0x3E). +_html_char + // skip null (0x00) + : '\x01' - '\x3B' + // skip left angle bracket (0x3C) + | '\x3D' + // skip right angle bracket (0x3E) + | '\x3F' - '\xFF' +; + +_html_chars : { _html_char } ; +_html_tag : '<' _html_chars '>' ; +_html_lit : '<' { _html_chars | _html_tag } '>' ; + +// The language supports C++-style comments: /* */ and //. In addition, a line +// beginning with a '#' character is considered a line output from a C +// preprocessor (e.g., # 34 to indicate line 34 ) and discarded. + +_line_comment + : '/' '/' { . } '\n' + | '#' { . } '\n' +; + +_block_comment : '/' '*' { . | '*' } '*' '/' ; +!comment : _line_comment | _block_comment ; + +!whitespace : ' ' | '\t' | '\r' | '\n' ; + +// ### [ Syntax ] ############################################################## + +<< import ( + "github.com/gonum/graph/formats/dot/ast" + "github.com/gonum/graph/formats/dot/internal/astx" +) >> + +// === [ Files ] =============================================================== + +File + : Graph << astx.NewFile($0) >> + | File Graph << astx.AppendGraph($0, $1) >> +; + +// === [ Graphs ] ============================================================== + +// Graph : [ "strict" ] ( "graph" | "digraph" ) [ ID ] "{" [ StmtList ] "}" + +Graph + : OptStrict DirectedGraph OptID + "{" OptStmtList "}" << astx.NewGraph($0, $1, $2, $4) >> +; + +OptStrict + : empty << false, nil >> + | strict << true, nil >> +; + +DirectedGraph + : graphx << false, nil >> + | digraph << true, nil >> +; + +// === [ Statements ] ========================================================== + +// StmtList +// : Stmt [ ";" ] +// | StmtList Stmt [ ";" ] + +StmtList + : Stmt OptSemi << astx.NewStmtList($0) >> + | StmtList Stmt OptSemi << astx.AppendStmt($0, $1) >> +; + +OptStmtList + : empty + | StmtList +; + +Stmt + : NodeStmt + | EdgeStmt + | AttrStmt + | Attr + | Subgraph +; + +OptSemi + : empty + | ";" +; + +// --- [ Node statement ] ------------------------------------------------------ + +// NodeStmt : Node [ AttrList ] + +NodeStmt + : Node OptAttrList << astx.NewNodeStmt($0, $1) >> +; + +// --- [ Edge statement ] ------------------------------------------------------ + +// EdgeStmt : ( Node | Subgraph ) Edge [ AttrList ] + +EdgeStmt + : Vertex Edge OptAttrList << astx.NewEdgeStmt($0, $1, $2) >> +; + +// Edge : ( "--" | "-->" ) ( Node | Subgraph ) [ Edge ] + +Edge + : DirectedEdge Vertex OptEdge << astx.NewEdge($0, $1, $2) >> +; + +DirectedEdge + : "--" << false, nil >> + | "->" << true, nil >> +; + +OptEdge + : empty + | Edge +; + +// --- [ Attribute statement ] ------------------------------------------------- + +// AttrStmt : ( "graph" | "node" | "edge" ) AttrList + +AttrStmt + : Component AttrList << astx.NewAttrStmt($0, $1) >> +; + +Component + : graphx << ast.KindGraph, nil >> + | node << ast.KindNode, nil >> + | edge << ast.KindEdge, nil >> +; + +// AttrList : "[" [ AList ] "]" [ AttrList ] + +AttrList + : "[" OptAList "]" << $1, nil >> + | AttrList "[" OptAList "]" << astx.AppendAttrList($0, $2) >> +; + +OptAttrList + : empty + | AttrList +; + +// AList +// : Attr [ ( ";" | "," ) ] +// | AList Attr [ ( ";" | "," ) ] + +AList + : Attr OptSep << astx.NewAttrList($0) >> + | AList Attr OptSep << astx.AppendAttr($0, $1) >> +; + +OptAList + : empty + | AList +; + +OptSep + : empty + | ";" + | "," +; + +// --- [ Attribute ] ----------------------------------------------------------- + +Attr + : ID "=" ID << astx.NewAttr($0, $2) >> +; + +// --- [ Subgraph ] ------------------------------------------------------------ + +// Subgraph : [ "subgraph" [ ID ] ] "{" [ StmtList ] "}" + +Subgraph + : OptSubgraphID "{" OptStmtList "}" << astx.NewSubgraph($0, $2) >> +; + +OptSubgraphID + : empty + | subgraph OptID << $1, nil >> +; + +// === [ Vertices ] ============================================================ + +Vertex + : Node + | Subgraph +; + +// --- [ Node identifier ] ----------------------------------------------------- + +// Node : ID [ Port ] + +Node + : ID OptPort << astx.NewNode($0, $1) >> +; + +// Port +// : ":" ID [ ":" CompassPoint ] +// | ":" CompassPoint +// +// CompassPoint +// : "n" | "ne" | "e" | "se" | "s" | "sw" | "w" | "nw" | "c" | "_" + +// Note also that the allowed compass point values are not keywords, so these +// strings can be used elsewhere as ordinary identifiers and, conversely, the +// parser will actually accept any identifier. + +Port + : ":" ID << astx.NewPort($1, nil) >> + | ":" ID ":" ID << astx.NewPort($1, $3) >> +; + +OptPort + : empty + | Port +; + +// === [ Identifiers ] ========================================================= + +ID + : id << astx.NewID($0) >> +; + +OptID + : empty << "", nil >> + | ID +; diff --git a/graph/formats/dot/internal/errors/errors.go b/graph/formats/dot/internal/errors/errors.go new file mode 100644 index 00000000..1843da8e --- /dev/null +++ b/graph/formats/dot/internal/errors/errors.go @@ -0,0 +1,66 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package errors + +import ( + "bytes" + "fmt" + + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (E *Error) String() string { + w := new(bytes.Buffer) + fmt.Fprintf(w, "Error") + if E.Err != nil { + fmt.Fprintf(w, " %s\n", E.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", E.ErrorToken.Type, E.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", E.ErrorToken.Pos.Offset, E.ErrorToken.Pos.Line, E.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range E.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range E.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(bytes.Buffer) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, e.Err.Error()) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/graph/formats/dot/internal/lexer/acttab.go b/graph/formats/dot/internal/lexer/acttab.go new file mode 100644 index 00000000..d63702ed --- /dev/null +++ b/graph/formats/dot/internal/lexer/acttab.go @@ -0,0 +1,597 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package lexer + +import ( + "fmt" + + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +type ActionTable [NumStates]ActionRow + +type ActionRow struct { + Accept token.Type + Ignore string +} + +func (this ActionRow) String() string { + return fmt.Sprintf("Accept=%d, Ignore=%s", this.Accept, this.Ignore) +} + +var ActTab = ActionTable{ + ActionRow{ // S0 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S1 + Accept: -1, + Ignore: "!whitespace", + }, + ActionRow{ // S2 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S3 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S4 + Accept: 15, + Ignore: "", + }, + ActionRow{ // S5 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S6 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S7 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S8 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S9 + Accept: 18, + Ignore: "", + }, + ActionRow{ // S10 + Accept: 8, + Ignore: "", + }, + ActionRow{ // S11 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S12 + Accept: 16, + Ignore: "", + }, + ActionRow{ // S13 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S14 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S15 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S16 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S17 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S18 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S19 + Accept: 13, + Ignore: "", + }, + ActionRow{ // S20 + Accept: 14, + Ignore: "", + }, + ActionRow{ // S21 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S22 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S23 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S24 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S25 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S26 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S27 + Accept: 2, + Ignore: "", + }, + ActionRow{ // S28 + Accept: 3, + Ignore: "", + }, + ActionRow{ // S29 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S30 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S31 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S32 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S33 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S34 + Accept: -1, + Ignore: "!comment", + }, + ActionRow{ // S35 + Accept: 9, + Ignore: "", + }, + ActionRow{ // S36 + Accept: 10, + Ignore: "", + }, + ActionRow{ // S37 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S38 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S39 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S40 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S41 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S42 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S43 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S44 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S45 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S46 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S47 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S48 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S49 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S50 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S51 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S52 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S53 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S54 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S55 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S56 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S57 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S58 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S59 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S60 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S61 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S62 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S63 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S64 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S65 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S66 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S67 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S68 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S69 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S70 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S71 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S72 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S73 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S74 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S75 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S76 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S77 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S78 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S79 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S80 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S81 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S82 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S83 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S84 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S85 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S86 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S87 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S88 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S89 + Accept: -1, + Ignore: "!comment", + }, + ActionRow{ // S90 + Accept: 0, + Ignore: "", + }, + ActionRow{ // S91 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S92 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S93 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S94 + Accept: 12, + Ignore: "", + }, + ActionRow{ // S95 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S96 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S97 + Accept: 11, + Ignore: "", + }, + ActionRow{ // S98 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S99 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S100 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S101 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S102 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S103 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S104 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S105 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S106 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S107 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S108 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S109 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S110 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S111 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S112 + Accept: 6, + Ignore: "", + }, + ActionRow{ // S113 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S114 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S115 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S116 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S117 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S118 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S119 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S120 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S121 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S122 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S123 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S124 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S125 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S126 + Accept: 5, + Ignore: "", + }, + ActionRow{ // S127 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S128 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S129 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S130 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S131 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S132 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S133 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S134 + Accept: 7, + Ignore: "", + }, + ActionRow{ // S135 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S136 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S137 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S138 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S139 + Accept: 19, + Ignore: "", + }, + ActionRow{ // S140 + Accept: 17, + Ignore: "", + }, +} diff --git a/graph/formats/dot/internal/lexer/lexer.go b/graph/formats/dot/internal/lexer/lexer.go new file mode 100644 index 00000000..20807b04 --- /dev/null +++ b/graph/formats/dot/internal/lexer/lexer.go @@ -0,0 +1,338 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package lexer + +import ( + // "fmt" + "io/ioutil" + "unicode/utf8" + + // "github.com/gonum/graph/formats/dot/internal/util" + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +const ( + NoState = -1 + NumStates = 141 + NumSymbols = 184 +) + +type Lexer struct { + src []byte + pos int + line int + column int +} + +func NewLexer(src []byte) *Lexer { + lexer := &Lexer{ + src: src, + pos: 0, + line: 1, + column: 1, + } + return lexer +} + +func NewLexerFile(fpath string) (*Lexer, error) { + src, err := ioutil.ReadFile(fpath) + if err != nil { + return nil, err + } + return NewLexer(src), nil +} + +func (this *Lexer) Scan() (tok *token.Token) { + + // fmt.Printf("Lexer.Scan() pos=%d\n", this.pos) + + tok = new(token.Token) + if this.pos >= len(this.src) { + tok.Type = token.EOF + tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = this.pos, this.line, this.column + return + } + start, startLine, startColumn, end := this.pos, this.line, this.column, 0 + tok.Type = token.INVALID + state, rune1, size := 0, rune(-1), 0 + for state != -1 { + + // fmt.Printf("\tpos=%d, line=%d, col=%d, state=%d\n", this.pos, this.line, this.column, state) + + if this.pos >= len(this.src) { + rune1 = -1 + } else { + rune1, size = utf8.DecodeRune(this.src[this.pos:]) + this.pos += size + } + + // Production start + if rune1 != -1 { + state = TransTab[state](rune1) + } else { + state = -1 + } + // Production end + + // Debug start + // nextState := -1 + // if rune1 != -1 { + // nextState = TransTab[state](rune1) + // } + // fmt.Printf("\tS%d, : tok=%s, rune == %s(%x), next state == %d\n", state, token.TokMap.Id(tok.Type), util.RuneToString(rune1), rune1, nextState) + // fmt.Printf("\t\tpos=%d, size=%d, start=%d, end=%d\n", this.pos, size, start, end) + // if nextState != -1 { + // fmt.Printf("\t\taction:%s\n", ActTab[nextState].String()) + // } + // state = nextState + // Debug end + + if state != -1 { + + switch rune1 { + case '\n': + this.line++ + this.column = 1 + case '\r': + this.column = 1 + case '\t': + this.column += 4 + default: + this.column++ + } + + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + // fmt.Printf("\t Accept(%s), %s(%d)\n", string(act), token.TokMap.Id(tok), tok) + end = this.pos + case ActTab[state].Ignore != "": + // fmt.Printf("\t Ignore(%s)\n", string(act)) + start, startLine, startColumn = this.pos, this.line, this.column + state = 0 + if start >= len(this.src) { + tok.Type = token.EOF + } + + } + } else { + if tok.Type == token.INVALID { + end = this.pos + } + } + } + if end > start { + this.pos = end + tok.Lit = this.src[start:end] + } else { + tok.Lit = []byte{} + } + tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn + + // fmt.Printf("Token at %s: %s \"%s\"\n", tok.String(), token.TokMap.Id(tok.Type), tok.Lit) + + return +} + +func (this *Lexer) Reset() { + this.pos = 0 +} + +/* +Lexer symbols: +0: 'n' +1: 'o' +2: 'd' +3: 'e' +4: 'N' +5: 'o' +6: 'd' +7: 'e' +8: 'N' +9: 'O' +10: 'D' +11: 'E' +12: 'e' +13: 'd' +14: 'g' +15: 'e' +16: 'E' +17: 'd' +18: 'g' +19: 'e' +20: 'E' +21: 'D' +22: 'G' +23: 'E' +24: 'g' +25: 'r' +26: 'a' +27: 'p' +28: 'h' +29: 'G' +30: 'r' +31: 'a' +32: 'p' +33: 'h' +34: 'G' +35: 'R' +36: 'A' +37: 'P' +38: 'H' +39: 'd' +40: 'i' +41: 'g' +42: 'r' +43: 'a' +44: 'p' +45: 'h' +46: 'D' +47: 'i' +48: 'g' +49: 'r' +50: 'a' +51: 'p' +52: 'h' +53: 'd' +54: 'i' +55: 'G' +56: 'r' +57: 'a' +58: 'p' +59: 'h' +60: 'D' +61: 'i' +62: 'G' +63: 'r' +64: 'a' +65: 'p' +66: 'h' +67: 'D' +68: 'I' +69: 'G' +70: 'R' +71: 'A' +72: 'P' +73: 'H' +74: 's' +75: 'u' +76: 'b' +77: 'g' +78: 'r' +79: 'a' +80: 'p' +81: 'h' +82: 'S' +83: 'u' +84: 'b' +85: 'g' +86: 'r' +87: 'a' +88: 'p' +89: 'h' +90: 's' +91: 'u' +92: 'b' +93: 'G' +94: 'r' +95: 'a' +96: 'p' +97: 'h' +98: 'S' +99: 'u' +100: 'b' +101: 'G' +102: 'r' +103: 'a' +104: 'p' +105: 'h' +106: 'S' +107: 'U' +108: 'B' +109: 'G' +110: 'R' +111: 'A' +112: 'P' +113: 'H' +114: 's' +115: 't' +116: 'r' +117: 'i' +118: 'c' +119: 't' +120: 'S' +121: 't' +122: 'r' +123: 'i' +124: 'c' +125: 't' +126: 'S' +127: 'T' +128: 'R' +129: 'I' +130: 'C' +131: 'T' +132: '{' +133: '}' +134: ';' +135: '-' +136: '-' +137: '-' +138: '>' +139: '[' +140: ']' +141: ',' +142: '=' +143: ':' +144: '_' +145: '-' +146: '.' +147: '-' +148: '.' +149: '\' +150: '"' +151: '\' +152: '"' +153: '"' +154: '=' +155: '<' +156: '>' +157: '<' +158: '>' +159: '/' +160: '/' +161: '\n' +162: '#' +163: '\n' +164: '/' +165: '*' +166: '*' +167: '*' +168: '/' +169: ' ' +170: '\t' +171: '\r' +172: '\n' +173: \u0001-'!' +174: '#'-'[' +175: ']'-\u007f +176: 'a'-'z' +177: 'A'-'Z' +178: '0'-'9' +179: \u0080-\ufffc +180: \ufffe-\U0010ffff +181: \u0001-';' +182: '?'-\u00ff +183: . + +*/ diff --git a/graph/formats/dot/internal/lexer/lexer_test.go b/graph/formats/dot/internal/lexer/lexer_test.go new file mode 100644 index 00000000..f90964fc --- /dev/null +++ b/graph/formats/dot/internal/lexer/lexer_test.go @@ -0,0 +1,54 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package lexer_test + +import ( + "bytes" + "io/ioutil" + "testing" + + "gonum.org/v1/gonum/graph/formats/dot" +) + +func TestParseFile(t *testing.T) { + golden := []struct { + in string + out string + }{ + { + in: "testdata/tokens.dot", + out: "testdata/tokens.golden", + }, + } + for _, g := range golden { + file, err := dot.ParseFile(g.in) + if err != nil { + t.Errorf("%q: unable to parse file; %v", g.in, err) + continue + } + // If no output path is specified, the input is already golden. + out := g.in + if len(g.out) > 0 { + out = g.out + } + buf, err := ioutil.ReadFile(out) + if err != nil { + t.Errorf("%q: unable to read file; %v", g.in, err) + continue + } + got := file.String() + // Remove trailing newline. + want := string(bytes.TrimSpace(buf)) + if got != want { + t.Errorf("%q: graph mismatch; expected %q, got %q", g.in, want, got) + } + } +} diff --git a/graph/formats/dot/internal/lexer/testdata/tokens.dot b/graph/formats/dot/internal/lexer/testdata/tokens.dot new file mode 100644 index 00000000..3a161951 --- /dev/null +++ b/graph/formats/dot/internal/lexer/testdata/tokens.dot @@ -0,0 +1,39 @@ +# C preprocessing directives act as comments. +/* block comment */ +// keywords are case-insensitive. +graph { + node [] + Node [] + NODE [] + edge [] + Edge [] + EDGE [] + subgraph {} + subGraph {} + Subgraph {} + SubGraph {} + SUBGRAPH S {} + A; B [style=filled, fillcolor=red] + C:nw -- D:se + "foo" + .10 + -20 + 3.14 + F [label=<
foo
>] + _foo + a10 +} +Graph { +} +GRAPH { +} +digraph { +} +Digraph { +} +diGraph { +} +DiGraph { +} +DIGRAPH { +} diff --git a/graph/formats/dot/internal/lexer/testdata/tokens.golden b/graph/formats/dot/internal/lexer/testdata/tokens.golden new file mode 100644 index 00000000..f64bdefc --- /dev/null +++ b/graph/formats/dot/internal/lexer/testdata/tokens.golden @@ -0,0 +1,37 @@ +graph { + node [] + node [] + node [] + edge [] + edge [] + edge [] + {} + {} + {} + {} + subgraph S {} + A + B [style=filled fillcolor=red] + C:nw -- D:se + "foo" + .10 + -20 + 3.14 + F [label=<
foo
>] + _foo + a10 +} +graph { +} +graph { +} +digraph { +} +digraph { +} +digraph { +} +digraph { +} +digraph { +} diff --git a/graph/formats/dot/internal/lexer/transitiontable.go b/graph/formats/dot/internal/lexer/transitiontable.go new file mode 100644 index 00000000..98c1d051 --- /dev/null +++ b/graph/formats/dot/internal/lexer/transitiontable.go @@ -0,0 +1,3027 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package lexer + +/* +Let s be the current state +Let r be the current input rune +transitionTable[s](r) returns the next state. +*/ +type TransitionTable [NumStates]func(rune) int + +var TransTab = TransitionTable{ + + // S0 + func(r rune) int { + switch { + case r == 9: // ['\t','\t'] + return 1 + case r == 10: // ['\n','\n'] + return 1 + case r == 13: // ['\r','\r'] + return 1 + case r == 32: // [' ',' '] + return 1 + case r == 34: // ['"','"'] + return 2 + case r == 35: // ['#','#'] + return 3 + case r == 44: // [',',','] + return 4 + case r == 45: // ['-','-'] + return 5 + case r == 46: // ['.','.'] + return 6 + case r == 47: // ['/','/'] + return 7 + case 48 <= r && r <= 57: // ['0','9'] + return 8 + case r == 58: // [':',':'] + return 9 + case r == 59: // [';',';'] + return 10 + case r == 60: // ['<','<'] + return 11 + case r == 61: // ['=','='] + return 12 + case 65 <= r && r <= 67: // ['A','C'] + return 13 + case r == 68: // ['D','D'] + return 14 + case r == 69: // ['E','E'] + return 15 + case r == 70: // ['F','F'] + return 13 + case r == 71: // ['G','G'] + return 16 + case 72 <= r && r <= 77: // ['H','M'] + return 13 + case r == 78: // ['N','N'] + return 17 + case 79 <= r && r <= 82: // ['O','R'] + return 13 + case r == 83: // ['S','S'] + return 18 + case 84 <= r && r <= 90: // ['T','Z'] + return 13 + case r == 91: // ['[','['] + return 19 + case r == 93: // [']',']'] + return 20 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 22 + case r == 101: // ['e','e'] + return 23 + case r == 102: // ['f','f'] + return 13 + case r == 103: // ['g','g'] + return 24 + case 104 <= r && r <= 109: // ['h','m'] + return 13 + case r == 110: // ['n','n'] + return 25 + case 111 <= r && r <= 114: // ['o','r'] + return 13 + case r == 115: // ['s','s'] + return 26 + case 116 <= r && r <= 122: // ['t','z'] + return 13 + case r == 123: // ['{','{'] + return 27 + case r == 125: // ['}','}'] + return 28 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S1 + func(r rune) int { + switch { + + } + return NoState + }, + + // S2 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + + } + return NoState + }, + + // S3 + func(r rune) int { + switch { + case r == 10: // ['\n','\n'] + return 34 + + default: + return 3 + } + + }, + + // S4 + func(r rune) int { + switch { + + } + return NoState + }, + + // S5 + func(r rune) int { + switch { + case r == 45: // ['-','-'] + return 35 + case r == 46: // ['.','.'] + return 6 + case 48 <= r && r <= 57: // ['0','9'] + return 8 + case r == 62: // ['>','>'] + return 36 + + } + return NoState + }, + + // S6 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 37 + + } + return NoState + }, + + // S7 + func(r rune) int { + switch { + case r == 42: // ['*','*'] + return 38 + case r == 47: // ['/','/'] + return 39 + + } + return NoState + }, + + // S8 + func(r rune) int { + switch { + case r == 46: // ['.','.'] + return 40 + case 48 <= r && r <= 57: // ['0','9'] + return 8 + + } + return NoState + }, + + // S9 + func(r rune) int { + switch { + + } + return NoState + }, + + // S10 + func(r rune) int { + switch { + + } + return NoState + }, + + // S11 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 41 + case r == 60: // ['<','<'] + return 42 + case r == 61: // ['=','='] + return 41 + case r == 62: // ['>','>'] + return 43 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 41 + + } + return NoState + }, + + // S12 + func(r rune) int { + switch { + + } + return NoState + }, + + // S13 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S14 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 72: // ['A','H'] + return 13 + case r == 73: // ['I','I'] + return 45 + case 74 <= r && r <= 90: // ['J','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 104: // ['a','h'] + return 13 + case r == 105: // ['i','i'] + return 46 + case 106 <= r && r <= 122: // ['j','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S15 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 67: // ['A','C'] + return 13 + case r == 68: // ['D','D'] + return 47 + case 69 <= r && r <= 90: // ['E','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 48 + case 101 <= r && r <= 122: // ['e','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S16 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 81: // ['A','Q'] + return 13 + case r == 82: // ['R','R'] + return 49 + case 83 <= r && r <= 90: // ['S','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 50 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S17 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 78: // ['A','N'] + return 13 + case r == 79: // ['O','O'] + return 51 + case 80 <= r && r <= 90: // ['P','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 110: // ['a','n'] + return 13 + case r == 111: // ['o','o'] + return 52 + case 112 <= r && r <= 122: // ['p','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S18 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 83: // ['A','S'] + return 13 + case r == 84: // ['T','T'] + return 53 + case r == 85: // ['U','U'] + return 54 + case 86 <= r && r <= 90: // ['V','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 115: // ['a','s'] + return 13 + case r == 116: // ['t','t'] + return 55 + case r == 117: // ['u','u'] + return 56 + case 118 <= r && r <= 122: // ['v','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S19 + func(r rune) int { + switch { + + } + return NoState + }, + + // S20 + func(r rune) int { + switch { + + } + return NoState + }, + + // S21 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S22 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 104: // ['a','h'] + return 13 + case r == 105: // ['i','i'] + return 57 + case 106 <= r && r <= 122: // ['j','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S23 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 58 + case 101 <= r && r <= 122: // ['e','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S24 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 59 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S25 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 110: // ['a','n'] + return 13 + case r == 111: // ['o','o'] + return 60 + case 112 <= r && r <= 122: // ['p','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S26 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 115: // ['a','s'] + return 13 + case r == 116: // ['t','t'] + return 61 + case r == 117: // ['u','u'] + return 62 + case 118 <= r && r <= 122: // ['v','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S27 + func(r rune) int { + switch { + + } + return NoState + }, + + // S28 + func(r rune) int { + switch { + + } + return NoState + }, + + // S29 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S30 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + + } + return NoState + }, + + // S31 + func(r rune) int { + switch { + + } + return NoState + }, + + // S32 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 63 + case r == 34: // ['"','"'] + return 64 + case 35 <= r && r <= 91: // ['#','['] + return 63 + case r == 92: // ['\','\'] + return 64 + case 93 <= r && r <= 127: // [']',\u007f] + return 63 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 65 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 65 + + } + return NoState + }, + + // S33 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + + } + return NoState + }, + + // S34 + func(r rune) int { + switch { + + } + return NoState + }, + + // S35 + func(r rune) int { + switch { + + } + return NoState + }, + + // S36 + func(r rune) int { + switch { + + } + return NoState + }, + + // S37 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 37 + + } + return NoState + }, + + // S38 + func(r rune) int { + switch { + case r == 42: // ['*','*'] + return 66 + + default: + return 38 + } + + }, + + // S39 + func(r rune) int { + switch { + case r == 10: // ['\n','\n'] + return 34 + + default: + return 39 + } + + }, + + // S40 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 67 + + } + return NoState + }, + + // S41 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 41 + case r == 60: // ['<','<'] + return 42 + case r == 61: // ['=','='] + return 41 + case r == 62: // ['>','>'] + return 43 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 41 + + } + return NoState + }, + + // S42 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 68 + case r == 61: // ['=','='] + return 68 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 68 + + } + return NoState + }, + + // S43 + func(r rune) int { + switch { + + } + return NoState + }, + + // S44 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S45 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 69 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S46 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 70 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 71 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S47 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 72 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S48 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 73 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S49 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case r == 65: // ['A','A'] + return 74 + case 66 <= r && r <= 90: // ['B','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S50 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 75 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S51 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 67: // ['A','C'] + return 13 + case r == 68: // ['D','D'] + return 76 + case 69 <= r && r <= 90: // ['E','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S52 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 77 + case 101 <= r && r <= 122: // ['e','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S53 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 81: // ['A','Q'] + return 13 + case r == 82: // ['R','R'] + return 78 + case 83 <= r && r <= 90: // ['S','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S54 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case r == 65: // ['A','A'] + return 13 + case r == 66: // ['B','B'] + return 79 + case 67 <= r && r <= 90: // ['C','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S55 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 80 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S56 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 13 + case r == 98: // ['b','b'] + return 81 + case 99 <= r && r <= 122: // ['c','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S57 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 82 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 83 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S58 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 84 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S59 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 85 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S60 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 99: // ['a','c'] + return 13 + case r == 100: // ['d','d'] + return 86 + case 101 <= r && r <= 122: // ['e','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S61 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 87 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S62 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 13 + case r == 98: // ['b','b'] + return 88 + case 99 <= r && r <= 122: // ['c','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S63 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + + } + return NoState + }, + + // S64 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + + } + return NoState + }, + + // S65 + func(r rune) int { + switch { + case 1 <= r && r <= 33: // [\u0001,'!'] + return 30 + case r == 34: // ['"','"'] + return 31 + case 35 <= r && r <= 91: // ['#','['] + return 30 + case r == 92: // ['\','\'] + return 32 + case 93 <= r && r <= 127: // [']',\u007f] + return 30 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 33 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 33 + + } + return NoState + }, + + // S66 + func(r rune) int { + switch { + case r == 42: // ['*','*'] + return 66 + case r == 47: // ['/','/'] + return 89 + + default: + return 38 + } + + }, + + // S67 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 67 + + } + return NoState + }, + + // S68 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 68 + case r == 61: // ['=','='] + return 68 + case r == 62: // ['>','>'] + return 90 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 68 + + } + return NoState + }, + + // S69 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 81: // ['A','Q'] + return 13 + case r == 82: // ['R','R'] + return 91 + case 83 <= r && r <= 90: // ['S','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S70 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 92 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S71 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 93 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S72 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 68: // ['A','D'] + return 13 + case r == 69: // ['E','E'] + return 94 + case 70 <= r && r <= 90: // ['F','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S73 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 100: // ['a','d'] + return 13 + case r == 101: // ['e','e'] + return 94 + case 102 <= r && r <= 122: // ['f','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S74 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 79: // ['A','O'] + return 13 + case r == 80: // ['P','P'] + return 95 + case 81 <= r && r <= 90: // ['Q','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S75 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 96 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S76 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 68: // ['A','D'] + return 13 + case r == 69: // ['E','E'] + return 97 + case 70 <= r && r <= 90: // ['F','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S77 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 100: // ['a','d'] + return 13 + case r == 101: // ['e','e'] + return 97 + case 102 <= r && r <= 122: // ['f','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S78 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 72: // ['A','H'] + return 13 + case r == 73: // ['I','I'] + return 98 + case 74 <= r && r <= 90: // ['J','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S79 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 99 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S80 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 104: // ['a','h'] + return 13 + case r == 105: // ['i','i'] + return 100 + case 106 <= r && r <= 122: // ['j','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S81 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 101 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 102 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S82 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 103 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S83 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 104 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S84 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 100: // ['a','d'] + return 13 + case r == 101: // ['e','e'] + return 94 + case 102 <= r && r <= 122: // ['f','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S85 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 105 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S86 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 100: // ['a','d'] + return 13 + case r == 101: // ['e','e'] + return 97 + case 102 <= r && r <= 122: // ['f','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S87 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 104: // ['a','h'] + return 13 + case r == 105: // ['i','i'] + return 106 + case 106 <= r && r <= 122: // ['j','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S88 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 70: // ['A','F'] + return 13 + case r == 71: // ['G','G'] + return 107 + case 72 <= r && r <= 90: // ['H','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 102: // ['a','f'] + return 13 + case r == 103: // ['g','g'] + return 108 + case 104 <= r && r <= 122: // ['h','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S89 + func(r rune) int { + switch { + + } + return NoState + }, + + // S90 + func(r rune) int { + switch { + case 1 <= r && r <= 59: // [\u0001,';'] + return 41 + case r == 60: // ['<','<'] + return 42 + case r == 61: // ['=','='] + return 41 + case r == 62: // ['>','>'] + return 43 + case 63 <= r && r <= 255: // ['?',\u00ff] + return 41 + + } + return NoState + }, + + // S91 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case r == 65: // ['A','A'] + return 109 + case 66 <= r && r <= 90: // ['B','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S92 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 110 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S93 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 111 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S94 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S95 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 71: // ['A','G'] + return 13 + case r == 72: // ['H','H'] + return 112 + case 73 <= r && r <= 90: // ['I','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S96 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 112 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S97 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S98 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 66: // ['A','B'] + return 13 + case r == 67: // ['C','C'] + return 113 + case 68 <= r && r <= 90: // ['D','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S99 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 81: // ['A','Q'] + return 13 + case r == 82: // ['R','R'] + return 114 + case 83 <= r && r <= 90: // ['S','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S100 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 98: // ['a','b'] + return 13 + case r == 99: // ['c','c'] + return 115 + case 100 <= r && r <= 122: // ['d','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S101 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 116 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S102 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 117 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S103 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 118 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S104 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 119 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S105 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 112 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S106 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 98: // ['a','b'] + return 13 + case r == 99: // ['c','c'] + return 120 + case 100 <= r && r <= 122: // ['d','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S107 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 121 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S108 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 113: // ['a','q'] + return 13 + case r == 114: // ['r','r'] + return 122 + case 115 <= r && r <= 122: // ['s','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S109 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 79: // ['A','O'] + return 13 + case r == 80: // ['P','P'] + return 123 + case 81 <= r && r <= 90: // ['Q','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S110 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 124 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S111 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 125 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S112 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S113 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 83: // ['A','S'] + return 13 + case r == 84: // ['T','T'] + return 126 + case 85 <= r && r <= 90: // ['U','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S114 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case r == 65: // ['A','A'] + return 127 + case 66 <= r && r <= 90: // ['B','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S115 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 115: // ['a','s'] + return 13 + case r == 116: // ['t','t'] + return 126 + case 117 <= r && r <= 122: // ['u','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S116 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 128 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S117 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 129 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S118 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 130 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S119 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 131 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S120 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 115: // ['a','s'] + return 13 + case r == 116: // ['t','t'] + return 126 + case 117 <= r && r <= 122: // ['u','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S121 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 132 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S122 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case r == 97: // ['a','a'] + return 133 + case 98 <= r && r <= 122: // ['b','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S123 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 71: // ['A','G'] + return 13 + case r == 72: // ['H','H'] + return 134 + case 73 <= r && r <= 90: // ['I','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S124 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 134 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S125 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 134 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S126 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S127 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 79: // ['A','O'] + return 13 + case r == 80: // ['P','P'] + return 135 + case 81 <= r && r <= 90: // ['Q','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S128 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 136 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S129 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 137 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S130 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 134 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S131 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 134 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S132 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 138 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S133 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 111: // ['a','o'] + return 13 + case r == 112: // ['p','p'] + return 139 + case 113 <= r && r <= 122: // ['q','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S134 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S135 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 71: // ['A','G'] + return 13 + case r == 72: // ['H','H'] + return 140 + case 73 <= r && r <= 90: // ['I','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S136 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 140 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S137 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 140 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S138 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 140 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S139 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 103: // ['a','g'] + return 13 + case r == 104: // ['h','h'] + return 140 + case 105 <= r && r <= 122: // ['i','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, + + // S140 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 44 + case 65 <= r && r <= 90: // ['A','Z'] + return 13 + case r == 95: // ['_','_'] + return 21 + case 97 <= r && r <= 122: // ['a','z'] + return 13 + case 128 <= r && r <= 65532: // [\u0080,\ufffc] + return 29 + case 65534 <= r && r <= 1114111: // [\ufffe,\U0010ffff] + return 29 + + } + return NoState + }, +} diff --git a/graph/formats/dot/internal/parser/action.go b/graph/formats/dot/internal/parser/action.go new file mode 100644 index 00000000..10d7eccb --- /dev/null +++ b/graph/formats/dot/internal/parser/action.go @@ -0,0 +1,61 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +import ( + "fmt" +) + +type action interface { + act() + String() string +} + +type ( + accept bool + shift int // value is next state index + reduce int // value is production index +) + +func (this accept) act() {} +func (this shift) act() {} +func (this reduce) act() {} + +func (this accept) Equal(that action) bool { + if _, ok := that.(accept); ok { + return true + } + return false +} + +func (this reduce) Equal(that action) bool { + that1, ok := that.(reduce) + if !ok { + return false + } + return this == that1 +} + +func (this shift) Equal(that action) bool { + that1, ok := that.(shift) + if !ok { + return false + } + return this == that1 +} + +func (this accept) String() string { return "accept(0)" } +func (this shift) String() string { return fmt.Sprintf("shift:%d", this) } +func (this reduce) String() string { + return fmt.Sprintf("reduce:%d(%s)", this, productionsTable[this].String) +} diff --git a/graph/formats/dot/internal/parser/actiontable.go b/graph/formats/dot/internal/parser/actiontable.go new file mode 100644 index 00000000..bffc8f3c --- /dev/null +++ b/graph/formats/dot/internal/parser/actiontable.go @@ -0,0 +1,2286 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +type ( + actionTable [numStates]actionRow + actionRow struct { + canRecover bool + actions [numSymbols]action + } +) + +var actionTab = actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + shift(4), /* strict */ + reduce(4), /* graphx, reduce: OptStrict */ + reduce(4), /* digraph, reduce: OptStrict */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + accept(true), /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + shift(4), /* strict */ + reduce(4), /* graphx, reduce: OptStrict */ + reduce(4), /* digraph, reduce: OptStrict */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + reduce(1), /* $, reduce: File */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + reduce(1), /* strict, reduce: File */ + reduce(1), /* graphx, reduce: File */ + reduce(1), /* digraph, reduce: File */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + shift(7), /* graphx */ + shift(8), /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + reduce(5), /* graphx, reduce: OptStrict */ + reduce(5), /* digraph, reduce: OptStrict */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + reduce(2), /* $, reduce: File */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + reduce(2), /* strict, reduce: File */ + reduce(2), /* graphx, reduce: File */ + reduce(2), /* digraph, reduce: File */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S6 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(53), /* {, reduce: OptID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(11), /* id */ + + }, + }, + actionRow{ // S7 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(6), /* {, reduce: DirectedGraph */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(6), /* id, reduce: DirectedGraph */ + + }, + }, + actionRow{ // S8 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(7), /* {, reduce: DirectedGraph */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(7), /* id, reduce: DirectedGraph */ + + }, + }, + actionRow{ // S9 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + shift(12), /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S10 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(54), /* {, reduce: OptID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S11 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S12 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + reduce(10), /* }, reduce: OptStmtList */ + nil, /* empty */ + nil, /* strict */ + shift(14), /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + shift(25), /* node */ + shift(26), /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(30), /* id */ + + }, + }, + actionRow{ // S13 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + shift(31), /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S14 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + reduce(27), /* [, reduce: Component */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S15 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + reduce(11), /* }, reduce: OptStmtList */ + nil, /* empty */ + nil, /* strict */ + shift(14), /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + shift(25), /* node */ + shift(26), /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(30), /* id */ + + }, + }, + actionRow{ // S16 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(17), /* {, reduce: OptSemi */ + reduce(17), /* }, reduce: OptSemi */ + nil, /* empty */ + nil, /* strict */ + reduce(17), /* graphx, reduce: OptSemi */ + nil, /* digraph */ + shift(34), /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(17), /* node, reduce: OptSemi */ + reduce(17), /* edge, reduce: OptSemi */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(17), /* subgraph, reduce: OptSemi */ + nil, /* : */ + reduce(17), /* id, reduce: OptSemi */ + + }, + }, + actionRow{ // S17 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(12), /* {, reduce: Stmt */ + reduce(12), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(12), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(12), /* ;, reduce: Stmt */ + nil, /* -- */ + nil, /* -> */ + reduce(12), /* node, reduce: Stmt */ + reduce(12), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(12), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(12), /* id, reduce: Stmt */ + + }, + }, + actionRow{ // S18 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(13), /* {, reduce: Stmt */ + reduce(13), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(13), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(13), /* ;, reduce: Stmt */ + nil, /* -- */ + nil, /* -> */ + reduce(13), /* node, reduce: Stmt */ + reduce(13), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(13), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(13), /* id, reduce: Stmt */ + + }, + }, + actionRow{ // S19 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(14), /* {, reduce: Stmt */ + reduce(14), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(14), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(14), /* ;, reduce: Stmt */ + nil, /* -- */ + nil, /* -> */ + reduce(14), /* node, reduce: Stmt */ + reduce(14), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(14), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(14), /* id, reduce: Stmt */ + + }, + }, + actionRow{ // S20 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(15), /* {, reduce: Stmt */ + reduce(15), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(15), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(15), /* ;, reduce: Stmt */ + nil, /* -- */ + nil, /* -> */ + reduce(15), /* node, reduce: Stmt */ + reduce(15), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(15), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(15), /* id, reduce: Stmt */ + + }, + }, + actionRow{ // S21 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(16), /* {, reduce: Stmt */ + reduce(16), /* }, reduce: Stmt */ + nil, /* empty */ + nil, /* strict */ + reduce(16), /* graphx, reduce: Stmt */ + nil, /* digraph */ + reduce(16), /* ;, reduce: Stmt */ + reduce(46), /* --, reduce: Vertex */ + reduce(46), /* ->, reduce: Vertex */ + reduce(16), /* node, reduce: Stmt */ + reduce(16), /* edge, reduce: Stmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(16), /* subgraph, reduce: Stmt */ + nil, /* : */ + reduce(16), /* id, reduce: Stmt */ + + }, + }, + actionRow{ // S22 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(32), /* {, reduce: OptAttrList */ + reduce(32), /* }, reduce: OptAttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(32), /* graphx, reduce: OptAttrList */ + nil, /* digraph */ + reduce(32), /* ;, reduce: OptAttrList */ + reduce(45), /* --, reduce: Vertex */ + reduce(45), /* ->, reduce: Vertex */ + reduce(32), /* node, reduce: OptAttrList */ + reduce(32), /* edge, reduce: OptAttrList */ + shift(37), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(32), /* subgraph, reduce: OptAttrList */ + nil, /* : */ + reduce(32), /* id, reduce: OptAttrList */ + + }, + }, + actionRow{ // S23 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + shift(40), /* -- */ + shift(41), /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S24 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + shift(37), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S25 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + reduce(28), /* [, reduce: Component */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S26 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + reduce(29), /* [, reduce: Component */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S27 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(50), /* {, reduce: OptPort */ + reduce(50), /* }, reduce: OptPort */ + nil, /* empty */ + nil, /* strict */ + reduce(50), /* graphx, reduce: OptPort */ + nil, /* digraph */ + reduce(50), /* ;, reduce: OptPort */ + reduce(50), /* --, reduce: OptPort */ + reduce(50), /* ->, reduce: OptPort */ + reduce(50), /* node, reduce: OptPort */ + reduce(50), /* edge, reduce: OptPort */ + reduce(50), /* [, reduce: OptPort */ + nil, /* ] */ + nil, /* , */ + shift(43), /* = */ + reduce(50), /* subgraph, reduce: OptPort */ + shift(46), /* : */ + reduce(50), /* id, reduce: OptPort */ + + }, + }, + actionRow{ // S28 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + shift(47), /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S29 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(53), /* {, reduce: OptID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(11), /* id */ + + }, + }, + actionRow{ // S30 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + reduce(52), /* }, reduce: ID */ + nil, /* empty */ + nil, /* strict */ + reduce(52), /* graphx, reduce: ID */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + reduce(52), /* --, reduce: ID */ + reduce(52), /* ->, reduce: ID */ + reduce(52), /* node, reduce: ID */ + reduce(52), /* edge, reduce: ID */ + reduce(52), /* [, reduce: ID */ + nil, /* ] */ + nil, /* , */ + reduce(52), /* =, reduce: ID */ + reduce(52), /* subgraph, reduce: ID */ + reduce(52), /* :, reduce: ID */ + reduce(52), /* id, reduce: ID */ + + }, + }, + actionRow{ // S31 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + reduce(3), /* $, reduce: Graph */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + reduce(3), /* strict, reduce: Graph */ + reduce(3), /* graphx, reduce: Graph */ + reduce(3), /* digraph, reduce: Graph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S32 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(17), /* {, reduce: OptSemi */ + reduce(17), /* }, reduce: OptSemi */ + nil, /* empty */ + nil, /* strict */ + reduce(17), /* graphx, reduce: OptSemi */ + nil, /* digraph */ + shift(34), /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(17), /* node, reduce: OptSemi */ + reduce(17), /* edge, reduce: OptSemi */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(17), /* subgraph, reduce: OptSemi */ + nil, /* : */ + reduce(17), /* id, reduce: OptSemi */ + + }, + }, + actionRow{ // S33 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(8), /* {, reduce: StmtList */ + reduce(8), /* }, reduce: StmtList */ + nil, /* empty */ + nil, /* strict */ + reduce(8), /* graphx, reduce: StmtList */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(8), /* node, reduce: StmtList */ + reduce(8), /* edge, reduce: StmtList */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(8), /* subgraph, reduce: StmtList */ + nil, /* : */ + reduce(8), /* id, reduce: StmtList */ + + }, + }, + actionRow{ // S34 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(18), /* {, reduce: OptSemi */ + reduce(18), /* }, reduce: OptSemi */ + nil, /* empty */ + nil, /* strict */ + reduce(18), /* graphx, reduce: OptSemi */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(18), /* node, reduce: OptSemi */ + reduce(18), /* edge, reduce: OptSemi */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(18), /* subgraph, reduce: OptSemi */ + nil, /* : */ + reduce(18), /* id, reduce: OptSemi */ + + }, + }, + actionRow{ // S35 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(19), /* {, reduce: NodeStmt */ + reduce(19), /* }, reduce: NodeStmt */ + nil, /* empty */ + nil, /* strict */ + reduce(19), /* graphx, reduce: NodeStmt */ + nil, /* digraph */ + reduce(19), /* ;, reduce: NodeStmt */ + nil, /* -- */ + nil, /* -> */ + reduce(19), /* node, reduce: NodeStmt */ + reduce(19), /* edge, reduce: NodeStmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(19), /* subgraph, reduce: NodeStmt */ + nil, /* : */ + reduce(19), /* id, reduce: NodeStmt */ + + }, + }, + actionRow{ // S36 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(33), /* {, reduce: OptAttrList */ + reduce(33), /* }, reduce: OptAttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(33), /* graphx, reduce: OptAttrList */ + nil, /* digraph */ + reduce(33), /* ;, reduce: OptAttrList */ + nil, /* -- */ + nil, /* -> */ + reduce(33), /* node, reduce: OptAttrList */ + reduce(33), /* edge, reduce: OptAttrList */ + shift(50), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(33), /* subgraph, reduce: OptAttrList */ + nil, /* : */ + reduce(33), /* id, reduce: OptAttrList */ + + }, + }, + actionRow{ // S37 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(36), /* ], reduce: OptAList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(55), /* id */ + + }, + }, + actionRow{ // S38 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(32), /* {, reduce: OptAttrList */ + reduce(32), /* }, reduce: OptAttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(32), /* graphx, reduce: OptAttrList */ + nil, /* digraph */ + reduce(32), /* ;, reduce: OptAttrList */ + nil, /* -- */ + nil, /* -> */ + reduce(32), /* node, reduce: OptAttrList */ + reduce(32), /* edge, reduce: OptAttrList */ + shift(37), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(32), /* subgraph, reduce: OptAttrList */ + nil, /* : */ + reduce(32), /* id, reduce: OptAttrList */ + + }, + }, + actionRow{ // S39 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(62), /* id */ + + }, + }, + actionRow{ // S40 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(22), /* {, reduce: DirectedEdge */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(22), /* subgraph, reduce: DirectedEdge */ + nil, /* : */ + reduce(22), /* id, reduce: DirectedEdge */ + + }, + }, + actionRow{ // S41 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(23), /* {, reduce: DirectedEdge */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(23), /* subgraph, reduce: DirectedEdge */ + nil, /* : */ + reduce(23), /* id, reduce: DirectedEdge */ + + }, + }, + actionRow{ // S42 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(26), /* {, reduce: AttrStmt */ + reduce(26), /* }, reduce: AttrStmt */ + nil, /* empty */ + nil, /* strict */ + reduce(26), /* graphx, reduce: AttrStmt */ + nil, /* digraph */ + reduce(26), /* ;, reduce: AttrStmt */ + nil, /* -- */ + nil, /* -> */ + reduce(26), /* node, reduce: AttrStmt */ + reduce(26), /* edge, reduce: AttrStmt */ + shift(50), /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(26), /* subgraph, reduce: AttrStmt */ + nil, /* : */ + reduce(26), /* id, reduce: AttrStmt */ + + }, + }, + actionRow{ // S43 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(64), /* id */ + + }, + }, + actionRow{ // S44 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(47), /* {, reduce: Node */ + reduce(47), /* }, reduce: Node */ + nil, /* empty */ + nil, /* strict */ + reduce(47), /* graphx, reduce: Node */ + nil, /* digraph */ + reduce(47), /* ;, reduce: Node */ + reduce(47), /* --, reduce: Node */ + reduce(47), /* ->, reduce: Node */ + reduce(47), /* node, reduce: Node */ + reduce(47), /* edge, reduce: Node */ + reduce(47), /* [, reduce: Node */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(47), /* subgraph, reduce: Node */ + nil, /* : */ + reduce(47), /* id, reduce: Node */ + + }, + }, + actionRow{ // S45 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(51), /* {, reduce: OptPort */ + reduce(51), /* }, reduce: OptPort */ + nil, /* empty */ + nil, /* strict */ + reduce(51), /* graphx, reduce: OptPort */ + nil, /* digraph */ + reduce(51), /* ;, reduce: OptPort */ + reduce(51), /* --, reduce: OptPort */ + reduce(51), /* ->, reduce: OptPort */ + reduce(51), /* node, reduce: OptPort */ + reduce(51), /* edge, reduce: OptPort */ + reduce(51), /* [, reduce: OptPort */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(51), /* subgraph, reduce: OptPort */ + nil, /* : */ + reduce(51), /* id, reduce: OptPort */ + + }, + }, + actionRow{ // S46 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(62), /* id */ + + }, + }, + actionRow{ // S47 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + reduce(10), /* }, reduce: OptStmtList */ + nil, /* empty */ + nil, /* strict */ + shift(14), /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + shift(25), /* node */ + shift(26), /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(30), /* id */ + + }, + }, + actionRow{ // S48 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(44), /* {, reduce: OptSubgraphID */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S49 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(9), /* {, reduce: StmtList */ + reduce(9), /* }, reduce: StmtList */ + nil, /* empty */ + nil, /* strict */ + reduce(9), /* graphx, reduce: StmtList */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + reduce(9), /* node, reduce: StmtList */ + reduce(9), /* edge, reduce: StmtList */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(9), /* subgraph, reduce: StmtList */ + nil, /* : */ + reduce(9), /* id, reduce: StmtList */ + + }, + }, + actionRow{ // S50 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(36), /* ], reduce: OptAList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(55), /* id */ + + }, + }, + actionRow{ // S51 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + shift(68), /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(38), /* ], reduce: OptSep */ + shift(70), /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(38), /* id, reduce: OptSep */ + + }, + }, + actionRow{ // S52 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + shift(71), /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S53 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(37), /* ], reduce: OptAList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(55), /* id */ + + }, + }, + actionRow{ // S54 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + shift(73), /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S55 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + reduce(52), /* =, reduce: ID */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S56 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(20), /* {, reduce: EdgeStmt */ + reduce(20), /* }, reduce: EdgeStmt */ + nil, /* empty */ + nil, /* strict */ + reduce(20), /* graphx, reduce: EdgeStmt */ + nil, /* digraph */ + reduce(20), /* ;, reduce: EdgeStmt */ + nil, /* -- */ + nil, /* -> */ + reduce(20), /* node, reduce: EdgeStmt */ + reduce(20), /* edge, reduce: EdgeStmt */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(20), /* subgraph, reduce: EdgeStmt */ + nil, /* : */ + reduce(20), /* id, reduce: EdgeStmt */ + + }, + }, + actionRow{ // S57 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(46), /* {, reduce: Vertex */ + reduce(46), /* }, reduce: Vertex */ + nil, /* empty */ + nil, /* strict */ + reduce(46), /* graphx, reduce: Vertex */ + nil, /* digraph */ + reduce(46), /* ;, reduce: Vertex */ + reduce(46), /* --, reduce: Vertex */ + reduce(46), /* ->, reduce: Vertex */ + reduce(46), /* node, reduce: Vertex */ + reduce(46), /* edge, reduce: Vertex */ + reduce(46), /* [, reduce: Vertex */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(46), /* subgraph, reduce: Vertex */ + nil, /* : */ + reduce(46), /* id, reduce: Vertex */ + + }, + }, + actionRow{ // S58 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(45), /* {, reduce: Vertex */ + reduce(45), /* }, reduce: Vertex */ + nil, /* empty */ + nil, /* strict */ + reduce(45), /* graphx, reduce: Vertex */ + nil, /* digraph */ + reduce(45), /* ;, reduce: Vertex */ + reduce(45), /* --, reduce: Vertex */ + reduce(45), /* ->, reduce: Vertex */ + reduce(45), /* node, reduce: Vertex */ + reduce(45), /* edge, reduce: Vertex */ + reduce(45), /* [, reduce: Vertex */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(45), /* subgraph, reduce: Vertex */ + nil, /* : */ + reduce(45), /* id, reduce: Vertex */ + + }, + }, + actionRow{ // S59 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(24), /* {, reduce: OptEdge */ + reduce(24), /* }, reduce: OptEdge */ + nil, /* empty */ + nil, /* strict */ + reduce(24), /* graphx, reduce: OptEdge */ + nil, /* digraph */ + reduce(24), /* ;, reduce: OptEdge */ + shift(40), /* -- */ + shift(41), /* -> */ + reduce(24), /* node, reduce: OptEdge */ + reduce(24), /* edge, reduce: OptEdge */ + reduce(24), /* [, reduce: OptEdge */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(24), /* subgraph, reduce: OptEdge */ + nil, /* : */ + reduce(24), /* id, reduce: OptEdge */ + + }, + }, + actionRow{ // S60 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(50), /* {, reduce: OptPort */ + reduce(50), /* }, reduce: OptPort */ + nil, /* empty */ + nil, /* strict */ + reduce(50), /* graphx, reduce: OptPort */ + nil, /* digraph */ + reduce(50), /* ;, reduce: OptPort */ + reduce(50), /* --, reduce: OptPort */ + reduce(50), /* ->, reduce: OptPort */ + reduce(50), /* node, reduce: OptPort */ + reduce(50), /* edge, reduce: OptPort */ + reduce(50), /* [, reduce: OptPort */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(50), /* subgraph, reduce: OptPort */ + shift(46), /* : */ + reduce(50), /* id, reduce: OptPort */ + + }, + }, + actionRow{ // S61 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + shift(76), /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S62 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + reduce(52), /* }, reduce: ID */ + nil, /* empty */ + nil, /* strict */ + reduce(52), /* graphx, reduce: ID */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + reduce(52), /* --, reduce: ID */ + reduce(52), /* ->, reduce: ID */ + reduce(52), /* node, reduce: ID */ + reduce(52), /* edge, reduce: ID */ + reduce(52), /* [, reduce: ID */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(52), /* subgraph, reduce: ID */ + reduce(52), /* :, reduce: ID */ + reduce(52), /* id, reduce: ID */ + + }, + }, + actionRow{ // S63 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(41), /* {, reduce: Attr */ + reduce(41), /* }, reduce: Attr */ + nil, /* empty */ + nil, /* strict */ + reduce(41), /* graphx, reduce: Attr */ + nil, /* digraph */ + reduce(41), /* ;, reduce: Attr */ + nil, /* -- */ + nil, /* -> */ + reduce(41), /* node, reduce: Attr */ + reduce(41), /* edge, reduce: Attr */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(41), /* subgraph, reduce: Attr */ + nil, /* : */ + reduce(41), /* id, reduce: Attr */ + + }, + }, + actionRow{ // S64 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + reduce(52), /* }, reduce: ID */ + nil, /* empty */ + nil, /* strict */ + reduce(52), /* graphx, reduce: ID */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + nil, /* -- */ + nil, /* -> */ + reduce(52), /* node, reduce: ID */ + reduce(52), /* edge, reduce: ID */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(52), /* subgraph, reduce: ID */ + nil, /* : */ + reduce(52), /* id, reduce: ID */ + + }, + }, + actionRow{ // S65 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(48), /* {, reduce: Port */ + reduce(48), /* }, reduce: Port */ + nil, /* empty */ + nil, /* strict */ + reduce(48), /* graphx, reduce: Port */ + nil, /* digraph */ + reduce(48), /* ;, reduce: Port */ + reduce(48), /* --, reduce: Port */ + reduce(48), /* ->, reduce: Port */ + reduce(48), /* node, reduce: Port */ + reduce(48), /* edge, reduce: Port */ + reduce(48), /* [, reduce: Port */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(48), /* subgraph, reduce: Port */ + shift(77), /* : */ + reduce(48), /* id, reduce: Port */ + + }, + }, + actionRow{ // S66 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + shift(78), /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S67 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + shift(79), /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S68 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(39), /* ], reduce: OptSep */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(39), /* id, reduce: OptSep */ + + }, + }, + actionRow{ // S69 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(34), /* ], reduce: AList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(34), /* id, reduce: AList */ + + }, + }, + actionRow{ // S70 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(40), /* ], reduce: OptSep */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(40), /* id, reduce: OptSep */ + + }, + }, + actionRow{ // S71 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(30), /* {, reduce: AttrList */ + reduce(30), /* }, reduce: AttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(30), /* graphx, reduce: AttrList */ + nil, /* digraph */ + reduce(30), /* ;, reduce: AttrList */ + nil, /* -- */ + nil, /* -> */ + reduce(30), /* node, reduce: AttrList */ + reduce(30), /* edge, reduce: AttrList */ + reduce(30), /* [, reduce: AttrList */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(30), /* subgraph, reduce: AttrList */ + nil, /* : */ + reduce(30), /* id, reduce: AttrList */ + + }, + }, + actionRow{ // S72 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + shift(68), /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(38), /* ], reduce: OptSep */ + shift(70), /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(38), /* id, reduce: OptSep */ + + }, + }, + actionRow{ // S73 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(82), /* id */ + + }, + }, + actionRow{ // S74 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(25), /* {, reduce: OptEdge */ + reduce(25), /* }, reduce: OptEdge */ + nil, /* empty */ + nil, /* strict */ + reduce(25), /* graphx, reduce: OptEdge */ + nil, /* digraph */ + reduce(25), /* ;, reduce: OptEdge */ + nil, /* -- */ + nil, /* -> */ + reduce(25), /* node, reduce: OptEdge */ + reduce(25), /* edge, reduce: OptEdge */ + reduce(25), /* [, reduce: OptEdge */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(25), /* subgraph, reduce: OptEdge */ + nil, /* : */ + reduce(25), /* id, reduce: OptEdge */ + + }, + }, + actionRow{ // S75 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(21), /* {, reduce: Edge */ + reduce(21), /* }, reduce: Edge */ + nil, /* empty */ + nil, /* strict */ + reduce(21), /* graphx, reduce: Edge */ + nil, /* digraph */ + reduce(21), /* ;, reduce: Edge */ + nil, /* -- */ + nil, /* -> */ + reduce(21), /* node, reduce: Edge */ + reduce(21), /* edge, reduce: Edge */ + reduce(21), /* [, reduce: Edge */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(21), /* subgraph, reduce: Edge */ + nil, /* : */ + reduce(21), /* id, reduce: Edge */ + + }, + }, + actionRow{ // S76 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(43), /* {, reduce: OptSubgraphID */ + reduce(10), /* }, reduce: OptStmtList */ + nil, /* empty */ + nil, /* strict */ + shift(14), /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + shift(25), /* node */ + shift(26), /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + shift(29), /* subgraph */ + nil, /* : */ + shift(30), /* id */ + + }, + }, + actionRow{ // S77 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + shift(85), /* id */ + + }, + }, + actionRow{ // S78 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(42), /* {, reduce: Subgraph */ + reduce(42), /* }, reduce: Subgraph */ + nil, /* empty */ + nil, /* strict */ + reduce(42), /* graphx, reduce: Subgraph */ + nil, /* digraph */ + reduce(42), /* ;, reduce: Subgraph */ + reduce(42), /* --, reduce: Subgraph */ + reduce(42), /* ->, reduce: Subgraph */ + reduce(42), /* node, reduce: Subgraph */ + reduce(42), /* edge, reduce: Subgraph */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(42), /* subgraph, reduce: Subgraph */ + nil, /* : */ + reduce(42), /* id, reduce: Subgraph */ + + }, + }, + actionRow{ // S79 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(31), /* {, reduce: AttrList */ + reduce(31), /* }, reduce: AttrList */ + nil, /* empty */ + nil, /* strict */ + reduce(31), /* graphx, reduce: AttrList */ + nil, /* digraph */ + reduce(31), /* ;, reduce: AttrList */ + nil, /* -- */ + nil, /* -> */ + reduce(31), /* node, reduce: AttrList */ + reduce(31), /* edge, reduce: AttrList */ + reduce(31), /* [, reduce: AttrList */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(31), /* subgraph, reduce: AttrList */ + nil, /* : */ + reduce(31), /* id, reduce: AttrList */ + + }, + }, + actionRow{ // S80 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(35), /* ], reduce: AList */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(35), /* id, reduce: AList */ + + }, + }, + actionRow{ // S81 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + reduce(41), /* ;, reduce: Attr */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(41), /* ], reduce: Attr */ + reduce(41), /* ,, reduce: Attr */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(41), /* id, reduce: Attr */ + + }, + }, + actionRow{ // S82 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + nil, /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + reduce(52), /* ], reduce: ID */ + reduce(52), /* ,, reduce: ID */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + reduce(52), /* id, reduce: ID */ + + }, + }, + actionRow{ // S83 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + nil, /* { */ + shift(86), /* } */ + nil, /* empty */ + nil, /* strict */ + nil, /* graphx */ + nil, /* digraph */ + nil, /* ; */ + nil, /* -- */ + nil, /* -> */ + nil, /* node */ + nil, /* edge */ + nil, /* [ */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + nil, /* subgraph */ + nil, /* : */ + nil, /* id */ + + }, + }, + actionRow{ // S84 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(49), /* {, reduce: Port */ + reduce(49), /* }, reduce: Port */ + nil, /* empty */ + nil, /* strict */ + reduce(49), /* graphx, reduce: Port */ + nil, /* digraph */ + reduce(49), /* ;, reduce: Port */ + reduce(49), /* --, reduce: Port */ + reduce(49), /* ->, reduce: Port */ + reduce(49), /* node, reduce: Port */ + reduce(49), /* edge, reduce: Port */ + reduce(49), /* [, reduce: Port */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(49), /* subgraph, reduce: Port */ + nil, /* : */ + reduce(49), /* id, reduce: Port */ + + }, + }, + actionRow{ // S85 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(52), /* {, reduce: ID */ + reduce(52), /* }, reduce: ID */ + nil, /* empty */ + nil, /* strict */ + reduce(52), /* graphx, reduce: ID */ + nil, /* digraph */ + reduce(52), /* ;, reduce: ID */ + reduce(52), /* --, reduce: ID */ + reduce(52), /* ->, reduce: ID */ + reduce(52), /* node, reduce: ID */ + reduce(52), /* edge, reduce: ID */ + reduce(52), /* [, reduce: ID */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(52), /* subgraph, reduce: ID */ + nil, /* : */ + reduce(52), /* id, reduce: ID */ + + }, + }, + actionRow{ // S86 + canRecover: false, + actions: [numSymbols]action{ + nil, /* INVALID */ + nil, /* $ */ + reduce(42), /* {, reduce: Subgraph */ + reduce(42), /* }, reduce: Subgraph */ + nil, /* empty */ + nil, /* strict */ + reduce(42), /* graphx, reduce: Subgraph */ + nil, /* digraph */ + reduce(42), /* ;, reduce: Subgraph */ + reduce(42), /* --, reduce: Subgraph */ + reduce(42), /* ->, reduce: Subgraph */ + reduce(42), /* node, reduce: Subgraph */ + reduce(42), /* edge, reduce: Subgraph */ + reduce(42), /* [, reduce: Subgraph */ + nil, /* ] */ + nil, /* , */ + nil, /* = */ + reduce(42), /* subgraph, reduce: Subgraph */ + nil, /* : */ + reduce(42), /* id, reduce: Subgraph */ + + }, + }, +} diff --git a/graph/formats/dot/internal/parser/gototable.go b/graph/formats/dot/internal/parser/gototable.go new file mode 100644 index 00000000..b4539576 --- /dev/null +++ b/graph/formats/dot/internal/parser/gototable.go @@ -0,0 +1,2894 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +const numNTSymbols = 30 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // S' + 1, // File + 2, // Graph + 3, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S1 + -1, // S' + -1, // File + 5, // Graph + 3, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S2 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S3 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + 6, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S4 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S5 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S6 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 10, // ID + 9, // OptID + + }, + gotoRow{ // S7 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S8 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S9 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S10 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S11 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S12 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + 15, // StmtList + 13, // OptStmtList + 16, // Stmt + -1, // OptSemi + 17, // NodeStmt + 18, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + 19, // AttrStmt + 24, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 20, // Attr + 21, // Subgraph + 28, // OptSubgraphID + 23, // Vertex + 22, // Node + -1, // Port + -1, // OptPort + 27, // ID + -1, // OptID + + }, + gotoRow{ // S13 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S14 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S15 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + 32, // Stmt + -1, // OptSemi + 17, // NodeStmt + 18, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + 19, // AttrStmt + 24, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 20, // Attr + 21, // Subgraph + 28, // OptSubgraphID + 23, // Vertex + 22, // Node + -1, // Port + -1, // OptPort + 27, // ID + -1, // OptID + + }, + gotoRow{ // S16 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + 33, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S17 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S18 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S19 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S20 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S21 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S22 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + 36, // AttrList + 35, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S23 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + 38, // Edge + 39, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S24 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + 42, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S25 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S26 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S27 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + 45, // Port + 44, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S28 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S29 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 10, // ID + 48, // OptID + + }, + gotoRow{ // S30 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S31 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S32 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + 49, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S33 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S34 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S35 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S36 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S37 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + 53, // AList + 52, // OptAList + -1, // OptSep + 51, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 54, // ID + -1, // OptID + + }, + gotoRow{ // S38 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + 36, // AttrList + 56, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S39 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + 57, // Subgraph + 61, // OptSubgraphID + 59, // Vertex + 58, // Node + -1, // Port + -1, // OptPort + 60, // ID + -1, // OptID + + }, + gotoRow{ // S40 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S41 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S42 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S43 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 63, // ID + -1, // OptID + + }, + gotoRow{ // S44 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S45 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S46 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 65, // ID + -1, // OptID + + }, + gotoRow{ // S47 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + 15, // StmtList + 66, // OptStmtList + 16, // Stmt + -1, // OptSemi + 17, // NodeStmt + 18, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + 19, // AttrStmt + 24, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 20, // Attr + 21, // Subgraph + 28, // OptSubgraphID + 23, // Vertex + 22, // Node + -1, // Port + -1, // OptPort + 27, // ID + -1, // OptID + + }, + gotoRow{ // S48 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S49 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S50 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + 53, // AList + 67, // OptAList + -1, // OptSep + 51, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 54, // ID + -1, // OptID + + }, + gotoRow{ // S51 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + 69, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S52 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S53 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 72, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 54, // ID + -1, // OptID + + }, + gotoRow{ // S54 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S55 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S56 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S57 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S58 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S59 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + 74, // Edge + 39, // DirectedEdge + 75, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S60 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + 45, // Port + 44, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S61 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S62 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S63 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S64 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S65 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S66 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S67 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S68 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S69 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S70 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S71 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S72 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + 80, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S73 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 81, // ID + -1, // OptID + + }, + gotoRow{ // S74 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S75 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S76 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + 15, // StmtList + 83, // OptStmtList + 16, // Stmt + -1, // OptSemi + 17, // NodeStmt + 18, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + 19, // AttrStmt + 24, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + 20, // Attr + 21, // Subgraph + 28, // OptSubgraphID + 23, // Vertex + 22, // Node + -1, // Port + -1, // OptPort + 27, // ID + -1, // OptID + + }, + gotoRow{ // S77 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + 84, // ID + -1, // OptID + + }, + gotoRow{ // S78 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S79 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S80 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S81 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S82 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S83 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S84 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S85 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, + gotoRow{ // S86 + -1, // S' + -1, // File + -1, // Graph + -1, // OptStrict + -1, // DirectedGraph + -1, // StmtList + -1, // OptStmtList + -1, // Stmt + -1, // OptSemi + -1, // NodeStmt + -1, // EdgeStmt + -1, // Edge + -1, // DirectedEdge + -1, // OptEdge + -1, // AttrStmt + -1, // Component + -1, // AttrList + -1, // OptAttrList + -1, // AList + -1, // OptAList + -1, // OptSep + -1, // Attr + -1, // Subgraph + -1, // OptSubgraphID + -1, // Vertex + -1, // Node + -1, // Port + -1, // OptPort + -1, // ID + -1, // OptID + + }, +} diff --git a/graph/formats/dot/internal/parser/parser.go b/graph/formats/dot/internal/parser/parser.go new file mode 100644 index 00000000..450abd12 --- /dev/null +++ b/graph/formats/dot/internal/parser/parser.go @@ -0,0 +1,222 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +import ( + "bytes" + "fmt" + + parseError "gonum.org/v1/gonum/graph/formats/dot/internal/errors" + "gonum.org/v1/gonum/graph/formats/dot/internal/token" +) + +const ( + numProductions = 55 + numStates = 87 + numSymbols = 50 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const iNITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{state: make([]int, 0, iNITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), + } +} + +func (this *stack) reset() { + this.state = this.state[0:0] + this.attrib = this.attrib[0:0] +} + +func (this *stack) push(s int, a Attrib) { + this.state = append(this.state, s) + this.attrib = append(this.attrib, a) +} + +func (this *stack) top() int { + return this.state[len(this.state)-1] +} + +func (this *stack) peek(pos int) int { + return this.state[pos] +} + +func (this *stack) topIndex() int { + return len(this.state) - 1 +} + +func (this *stack) popN(items int) []Attrib { + lo, hi := len(this.state)-items, len(this.state) + + attrib := this.attrib[lo:hi] + + this.state = this.state[:lo] + this.attrib = this.attrib[:lo] + + return attrib +} + +func (S *stack) String() string { + w := new(bytes.Buffer) + fmt.Fprintf(w, "stack:\n") + for i, st := range S.state { + fmt.Fprintf(w, "\t%d:%d , ", i, st) + if S.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + fmt.Fprintf(w, "%v", S.attrib[i]) + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + pos int +} + +type Scanner interface { + Scan() (tok *token.Token) +} + +func NewParser() *Parser { + p := &Parser{stack: newStack()} + p.Reset() + return p +} + +func (P *Parser) Reset() { + P.stack.reset() + P.stack.push(0, nil) +} + +func (P *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: P.nextToken, + ErrorSymbols: P.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range actionTab[P.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := actionTab[P.stack.top()].actions[token.TokMap.Type("error")]; action != nil { + P.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := actionTab[P.stack.top()].actions[P.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && P.nextToken.Type != token.EOF { + P.nextToken = scanner.Scan() + if action := actionTab[P.stack.top()].actions[P.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (P *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := P.firstRecoveryState(); ok { + errorSymbols := P.stack.popN(int(P.stack.topIndex() - rs)) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (P *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = P.stack.topIndex(), actionTab[P.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = actionTab[P.stack.peek(recoveryState)].canRecover + } + return +} + +func (P *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: P.stack.top(), + ErrorToken: P.nextToken, + } + actRow := actionTab[P.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (this *Parser) Parse(scanner Scanner) (res interface{}, err error) { + this.Reset() + this.nextToken = scanner.Scan() + for acc := false; !acc; { + action := actionTab[this.stack.top()].actions[this.nextToken.Type] + if action == nil { + if recovered, errAttrib := this.Error(nil, scanner); !recovered { + this.nextToken = errAttrib.ErrorToken + return nil, this.newError(nil) + } + if action = actionTab[this.stack.top()].actions[this.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + // fmt.Printf("S%d %s %s\n", this.stack.top(), token.TokMap.TokenString(this.nextToken), action.String()) + + switch act := action.(type) { + case accept: + res = this.stack.popN(1)[0] + acc = true + case shift: + this.stack.push(int(act), this.nextToken) + this.nextToken = scanner.Scan() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(this.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, this.newError(err) + } else { + this.stack.push(gotoTab[this.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/graph/formats/dot/internal/parser/parser_test.go b/graph/formats/dot/internal/parser/parser_test.go new file mode 100644 index 00000000..c48cd6f6 --- /dev/null +++ b/graph/formats/dot/internal/parser/parser_test.go @@ -0,0 +1,114 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser_test + +import ( + "bytes" + "io/ioutil" + "testing" + + "gonum.org/v1/gonum/graph/formats/dot" +) + +func TestParseFile(t *testing.T) { + golden := []struct { + in string + out string + }{ + {in: "../testdata/empty.dot"}, + {in: "../testdata/graph.dot"}, + {in: "../testdata/digraph.dot"}, + {in: "../testdata/strict.dot"}, + {in: "../testdata/multi.dot"}, + {in: "../testdata/named_graph.dot"}, + {in: "../testdata/node_stmt.dot"}, + {in: "../testdata/edge_stmt.dot"}, + {in: "../testdata/attr_stmt.dot"}, + {in: "../testdata/attr.dot"}, + { + in: "../testdata/subgraph.dot", + out: "../testdata/subgraph.golden", + }, + { + in: "../testdata/semi.dot", + out: "../testdata/semi.golden", + }, + { + in: "../testdata/empty_attr.dot", + out: "../testdata/empty_attr.golden", + }, + { + in: "../testdata/attr_lists.dot", + out: "../testdata/attr_lists.golden", + }, + { + in: "../testdata/attr_sep.dot", + out: "../testdata/attr_sep.golden", + }, + {in: "../testdata/subgraph_vertex.dot"}, + { + in: "../testdata/port.dot", + out: "../testdata/port.golden", + }, + {in: "../testdata/quoted_id.dot"}, + { + in: "../testdata/backslash_newline_id.dot", + out: "../testdata/backslash_newline_id.golden", + }, + } + for _, g := range golden { + file, err := dot.ParseFile(g.in) + if err != nil { + t.Errorf("%q: unable to parse file; %v", g.in, err) + continue + } + // If no output path is specified, the input is already golden. + out := g.in + if len(g.out) > 0 { + out = g.out + } + buf, err := ioutil.ReadFile(out) + if err != nil { + t.Errorf("%q: unable to read file; %v", g.in, err) + continue + } + got := file.String() + // Remove trailing newline. + want := string(bytes.TrimSpace(buf)) + if got != want { + t.Errorf("%q: graph mismatch; expected `%s`, got `%s`", g.in, want, got) + } + } +} + +func TestParseError(t *testing.T) { + golden := []struct { + path string + want string + }{ + { + path: "../testdata/error.dot", + want: `Error in S30: INVALID(0,~), Pos(offset=13, line=2, column=7), expected one of: { } graphx ; -- -> node edge [ = subgraph : id `, + }, + } + for _, g := range golden { + _, err := dot.ParseFile(g.path) + if err == nil { + t.Errorf("%q: expected error, got nil", g.path) + continue + } + got := err.Error() + if got != g.want { + t.Errorf("%q: error mismatch; expected `%v`, got `%v`", g.path, g.want, got) + continue + } + } +} diff --git a/graph/formats/dot/internal/parser/productionstable.go b/graph/formats/dot/internal/parser/productionstable.go new file mode 100644 index 00000000..07f11a76 --- /dev/null +++ b/graph/formats/dot/internal/parser/productionstable.go @@ -0,0 +1,586 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package parser + +import ( + "gonum.org/v1/gonum/graph/formats/dot/ast" + "gonum.org/v1/gonum/graph/formats/dot/internal/astx" +) + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func([]Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : File << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `File : Graph << astx.NewFile(X[0]) >>`, + Id: "File", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewFile(X[0]) + }, + }, + ProdTabEntry{ + String: `File : File Graph << astx.AppendGraph(X[0], X[1]) >>`, + Id: "File", + NTType: 1, + Index: 2, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.AppendGraph(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Graph : OptStrict DirectedGraph OptID "{" OptStmtList "}" << astx.NewGraph(X[0], X[1], X[2], X[4]) >>`, + Id: "Graph", + NTType: 2, + Index: 3, + NumSymbols: 6, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewGraph(X[0], X[1], X[2], X[4]) + }, + }, + ProdTabEntry{ + String: `OptStrict : empty << false, nil >>`, + Id: "OptStrict", + NTType: 3, + Index: 4, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return false, nil + }, + }, + ProdTabEntry{ + String: `OptStrict : strict << true, nil >>`, + Id: "OptStrict", + NTType: 3, + Index: 5, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return true, nil + }, + }, + ProdTabEntry{ + String: `DirectedGraph : graphx << false, nil >>`, + Id: "DirectedGraph", + NTType: 4, + Index: 6, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return false, nil + }, + }, + ProdTabEntry{ + String: `DirectedGraph : digraph << true, nil >>`, + Id: "DirectedGraph", + NTType: 4, + Index: 7, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return true, nil + }, + }, + ProdTabEntry{ + String: `StmtList : Stmt OptSemi << astx.NewStmtList(X[0]) >>`, + Id: "StmtList", + NTType: 5, + Index: 8, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewStmtList(X[0]) + }, + }, + ProdTabEntry{ + String: `StmtList : StmtList Stmt OptSemi << astx.AppendStmt(X[0], X[1]) >>`, + Id: "StmtList", + NTType: 5, + Index: 9, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.AppendStmt(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `OptStmtList : empty << >>`, + Id: "OptStmtList", + NTType: 6, + Index: 10, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptStmtList : StmtList << >>`, + Id: "OptStmtList", + NTType: 6, + Index: 11, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : NodeStmt << >>`, + Id: "Stmt", + NTType: 7, + Index: 12, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : EdgeStmt << >>`, + Id: "Stmt", + NTType: 7, + Index: 13, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : AttrStmt << >>`, + Id: "Stmt", + NTType: 7, + Index: 14, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : Attr << >>`, + Id: "Stmt", + NTType: 7, + Index: 15, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : Subgraph << >>`, + Id: "Stmt", + NTType: 7, + Index: 16, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `OptSemi : empty << >>`, + Id: "OptSemi", + NTType: 8, + Index: 17, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptSemi : ";" << >>`, + Id: "OptSemi", + NTType: 8, + Index: 18, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `NodeStmt : Node OptAttrList << astx.NewNodeStmt(X[0], X[1]) >>`, + Id: "NodeStmt", + NTType: 9, + Index: 19, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewNodeStmt(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `EdgeStmt : Vertex Edge OptAttrList << astx.NewEdgeStmt(X[0], X[1], X[2]) >>`, + Id: "EdgeStmt", + NTType: 10, + Index: 20, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewEdgeStmt(X[0], X[1], X[2]) + }, + }, + ProdTabEntry{ + String: `Edge : DirectedEdge Vertex OptEdge << astx.NewEdge(X[0], X[1], X[2]) >>`, + Id: "Edge", + NTType: 11, + Index: 21, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewEdge(X[0], X[1], X[2]) + }, + }, + ProdTabEntry{ + String: `DirectedEdge : "--" << false, nil >>`, + Id: "DirectedEdge", + NTType: 12, + Index: 22, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return false, nil + }, + }, + ProdTabEntry{ + String: `DirectedEdge : "->" << true, nil >>`, + Id: "DirectedEdge", + NTType: 12, + Index: 23, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return true, nil + }, + }, + ProdTabEntry{ + String: `OptEdge : empty << >>`, + Id: "OptEdge", + NTType: 13, + Index: 24, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptEdge : Edge << >>`, + Id: "OptEdge", + NTType: 13, + Index: 25, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `AttrStmt : Component AttrList << astx.NewAttrStmt(X[0], X[1]) >>`, + Id: "AttrStmt", + NTType: 14, + Index: 26, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewAttrStmt(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Component : graphx << ast.KindGraph, nil >>`, + Id: "Component", + NTType: 15, + Index: 27, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return ast.KindGraph, nil + }, + }, + ProdTabEntry{ + String: `Component : node << ast.KindNode, nil >>`, + Id: "Component", + NTType: 15, + Index: 28, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return ast.KindNode, nil + }, + }, + ProdTabEntry{ + String: `Component : edge << ast.KindEdge, nil >>`, + Id: "Component", + NTType: 15, + Index: 29, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return ast.KindEdge, nil + }, + }, + ProdTabEntry{ + String: `AttrList : "[" OptAList "]" << X[1], nil >>`, + Id: "AttrList", + NTType: 16, + Index: 30, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[1], nil + }, + }, + ProdTabEntry{ + String: `AttrList : AttrList "[" OptAList "]" << astx.AppendAttrList(X[0], X[2]) >>`, + Id: "AttrList", + NTType: 16, + Index: 31, + NumSymbols: 4, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.AppendAttrList(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `OptAttrList : empty << >>`, + Id: "OptAttrList", + NTType: 17, + Index: 32, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptAttrList : AttrList << >>`, + Id: "OptAttrList", + NTType: 17, + Index: 33, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `AList : Attr OptSep << astx.NewAttrList(X[0]) >>`, + Id: "AList", + NTType: 18, + Index: 34, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewAttrList(X[0]) + }, + }, + ProdTabEntry{ + String: `AList : AList Attr OptSep << astx.AppendAttr(X[0], X[1]) >>`, + Id: "AList", + NTType: 18, + Index: 35, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.AppendAttr(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `OptAList : empty << >>`, + Id: "OptAList", + NTType: 19, + Index: 36, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptAList : AList << >>`, + Id: "OptAList", + NTType: 19, + Index: 37, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `OptSep : empty << >>`, + Id: "OptSep", + NTType: 20, + Index: 38, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptSep : ";" << >>`, + Id: "OptSep", + NTType: 20, + Index: 39, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `OptSep : "," << >>`, + Id: "OptSep", + NTType: 20, + Index: 40, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Attr : ID "=" ID << astx.NewAttr(X[0], X[2]) >>`, + Id: "Attr", + NTType: 21, + Index: 41, + NumSymbols: 3, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewAttr(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `Subgraph : OptSubgraphID "{" OptStmtList "}" << astx.NewSubgraph(X[0], X[2]) >>`, + Id: "Subgraph", + NTType: 22, + Index: 42, + NumSymbols: 4, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewSubgraph(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `OptSubgraphID : empty << >>`, + Id: "OptSubgraphID", + NTType: 23, + Index: 43, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptSubgraphID : subgraph OptID << X[1], nil >>`, + Id: "OptSubgraphID", + NTType: 23, + Index: 44, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[1], nil + }, + }, + ProdTabEntry{ + String: `Vertex : Node << >>`, + Id: "Vertex", + NTType: 24, + Index: 45, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Vertex : Subgraph << >>`, + Id: "Vertex", + NTType: 24, + Index: 46, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Node : ID OptPort << astx.NewNode(X[0], X[1]) >>`, + Id: "Node", + NTType: 25, + Index: 47, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewNode(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Port : ":" ID << astx.NewPort(X[1], nil) >>`, + Id: "Port", + NTType: 26, + Index: 48, + NumSymbols: 2, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewPort(X[1], nil) + }, + }, + ProdTabEntry{ + String: `Port : ":" ID ":" ID << astx.NewPort(X[1], X[3]) >>`, + Id: "Port", + NTType: 26, + Index: 49, + NumSymbols: 4, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewPort(X[1], X[3]) + }, + }, + ProdTabEntry{ + String: `OptPort : empty << >>`, + Id: "OptPort", + NTType: 27, + Index: 50, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return nil, nil + }, + }, + ProdTabEntry{ + String: `OptPort : Port << >>`, + Id: "OptPort", + NTType: 27, + Index: 51, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `ID : id << astx.NewID(X[0]) >>`, + Id: "ID", + NTType: 28, + Index: 52, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return astx.NewID(X[0]) + }, + }, + ProdTabEntry{ + String: `OptID : empty << "", nil >>`, + Id: "OptID", + NTType: 29, + Index: 53, + NumSymbols: 0, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return "", nil + }, + }, + ProdTabEntry{ + String: `OptID : ID << >>`, + Id: "OptID", + NTType: 29, + Index: 54, + NumSymbols: 1, + ReduceFunc: func(X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, +} diff --git a/graph/formats/dot/internal/paste_copyright.bash b/graph/formats/dot/internal/paste_copyright.bash new file mode 100755 index 00000000..83319810 --- /dev/null +++ b/graph/formats/dot/internal/paste_copyright.bash @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +find . -type f -name '*.go' \ +| xargs sed -i -e "s|// Code generated by gocc; DO NOT EDIT.|\ +// Code generated by gocc; DO NOT EDIT.\n\ +\n\ +// This file is dual licensed under CC0 and The gonum license.\n\ +//\n\ +// Copyright ©2017 The gonum Authors. All rights reserved.\n\ +// Use of this source code is governed by a BSD-style\n\ +// license that can be found in the LICENSE file.\n\ +//\n\ +// Copyright ©2017 Robin Eklind.\n\ +// This file is made available under a Creative Commons CC0 1.0\n\ +// Universal Public Domain Dedication.\n\ +|" + diff --git a/graph/formats/dot/internal/testdata/attr.dot b/graph/formats/dot/internal/testdata/attr.dot new file mode 100644 index 00000000..dabe9734 --- /dev/null +++ b/graph/formats/dot/internal/testdata/attr.dot @@ -0,0 +1,4 @@ +digraph { + bgcolor=transparent + A +} diff --git a/graph/formats/dot/internal/testdata/attr_lists.dot b/graph/formats/dot/internal/testdata/attr_lists.dot new file mode 100644 index 00000000..b71411cd --- /dev/null +++ b/graph/formats/dot/internal/testdata/attr_lists.dot @@ -0,0 +1,3 @@ +digraph { + A [style=filled] [fillcolor=red] +} diff --git a/graph/formats/dot/internal/testdata/attr_lists.golden b/graph/formats/dot/internal/testdata/attr_lists.golden new file mode 100644 index 00000000..14316d93 --- /dev/null +++ b/graph/formats/dot/internal/testdata/attr_lists.golden @@ -0,0 +1,3 @@ +digraph { + A [style=filled fillcolor=red] +} diff --git a/graph/formats/dot/internal/testdata/attr_sep.dot b/graph/formats/dot/internal/testdata/attr_sep.dot new file mode 100644 index 00000000..ef47a120 --- /dev/null +++ b/graph/formats/dot/internal/testdata/attr_sep.dot @@ -0,0 +1,3 @@ +digraph { + A [style=filled, fillcolor=red; color=blue] +} diff --git a/graph/formats/dot/internal/testdata/attr_sep.golden b/graph/formats/dot/internal/testdata/attr_sep.golden new file mode 100644 index 00000000..95bfd972 --- /dev/null +++ b/graph/formats/dot/internal/testdata/attr_sep.golden @@ -0,0 +1,3 @@ +digraph { + A [style=filled fillcolor=red color=blue] +} diff --git a/graph/formats/dot/internal/testdata/attr_stmt.dot b/graph/formats/dot/internal/testdata/attr_stmt.dot new file mode 100644 index 00000000..e87d70a4 --- /dev/null +++ b/graph/formats/dot/internal/testdata/attr_stmt.dot @@ -0,0 +1,6 @@ +digraph { + graph [bgcolor=transparent] + node [style=filled fillcolor=white] + edge [minlen=2] + A -> B +} diff --git a/graph/formats/dot/internal/testdata/backslash_newline_id.dot b/graph/formats/dot/internal/testdata/backslash_newline_id.dot new file mode 100644 index 00000000..81051384 --- /dev/null +++ b/graph/formats/dot/internal/testdata/backslash_newline_id.dot @@ -0,0 +1,4 @@ +digraph { + A [name="hello \ +world"] +} diff --git a/graph/formats/dot/internal/testdata/backslash_newline_id.golden b/graph/formats/dot/internal/testdata/backslash_newline_id.golden new file mode 100644 index 00000000..449c3a3e --- /dev/null +++ b/graph/formats/dot/internal/testdata/backslash_newline_id.golden @@ -0,0 +1,3 @@ +digraph { + A [name="hello world"] +} diff --git a/graph/formats/dot/internal/testdata/digraph.dot b/graph/formats/dot/internal/testdata/digraph.dot new file mode 100644 index 00000000..1063ebfa --- /dev/null +++ b/graph/formats/dot/internal/testdata/digraph.dot @@ -0,0 +1,3 @@ +digraph { + A -> B +} diff --git a/graph/formats/dot/internal/testdata/edge_stmt.dot b/graph/formats/dot/internal/testdata/edge_stmt.dot new file mode 100644 index 00000000..019d23d7 --- /dev/null +++ b/graph/formats/dot/internal/testdata/edge_stmt.dot @@ -0,0 +1,4 @@ +digraph { + A -> B -> C + D -> E [color=red minlen=2] +} diff --git a/graph/formats/dot/internal/testdata/empty.dot b/graph/formats/dot/internal/testdata/empty.dot new file mode 100644 index 00000000..418b7bca --- /dev/null +++ b/graph/formats/dot/internal/testdata/empty.dot @@ -0,0 +1,2 @@ +graph { +} diff --git a/graph/formats/dot/internal/testdata/empty_attr.dot b/graph/formats/dot/internal/testdata/empty_attr.dot new file mode 100644 index 00000000..b92d60e5 --- /dev/null +++ b/graph/formats/dot/internal/testdata/empty_attr.dot @@ -0,0 +1,3 @@ +digraph { + A [] +} diff --git a/graph/formats/dot/internal/testdata/empty_attr.golden b/graph/formats/dot/internal/testdata/empty_attr.golden new file mode 100644 index 00000000..369e4495 --- /dev/null +++ b/graph/formats/dot/internal/testdata/empty_attr.golden @@ -0,0 +1,3 @@ +digraph { + A +} diff --git a/graph/formats/dot/internal/testdata/error.dot b/graph/formats/dot/internal/testdata/error.dot new file mode 100644 index 00000000..ad77f61f --- /dev/null +++ b/graph/formats/dot/internal/testdata/error.dot @@ -0,0 +1,3 @@ +digraph { + A ~ B +} diff --git a/graph/formats/dot/internal/testdata/graph.dot b/graph/formats/dot/internal/testdata/graph.dot new file mode 100644 index 00000000..0524c144 --- /dev/null +++ b/graph/formats/dot/internal/testdata/graph.dot @@ -0,0 +1,3 @@ +graph { + A -- B +} diff --git a/graph/formats/dot/internal/testdata/multi.dot b/graph/formats/dot/internal/testdata/multi.dot new file mode 100644 index 00000000..21945188 --- /dev/null +++ b/graph/formats/dot/internal/testdata/multi.dot @@ -0,0 +1,6 @@ +digraph { + A -> B +} +digraph { + C -> D +} diff --git a/graph/formats/dot/internal/testdata/named_graph.dot b/graph/formats/dot/internal/testdata/named_graph.dot new file mode 100644 index 00000000..3fc680da --- /dev/null +++ b/graph/formats/dot/internal/testdata/named_graph.dot @@ -0,0 +1,3 @@ +graph G { + A +} diff --git a/graph/formats/dot/internal/testdata/node_stmt.dot b/graph/formats/dot/internal/testdata/node_stmt.dot new file mode 100644 index 00000000..369e4495 --- /dev/null +++ b/graph/formats/dot/internal/testdata/node_stmt.dot @@ -0,0 +1,3 @@ +digraph { + A +} diff --git a/graph/formats/dot/internal/testdata/port.dot b/graph/formats/dot/internal/testdata/port.dot new file mode 100644 index 00000000..1d4bf415 --- /dev/null +++ b/graph/formats/dot/internal/testdata/port.dot @@ -0,0 +1,11 @@ +digraph { + A:ne -> B:sw + C:foo -> D:bar:se + E:_ -> F + G:n + H:e + I:s + J:w + K:nw + L:c +} diff --git a/graph/formats/dot/internal/testdata/port.golden b/graph/formats/dot/internal/testdata/port.golden new file mode 100644 index 00000000..18ca1f30 --- /dev/null +++ b/graph/formats/dot/internal/testdata/port.golden @@ -0,0 +1,11 @@ +digraph { + A:ne -> B:sw + C:foo -> D:bar:se + E -> F + G:n + H:e + I:s + J:w + K:nw + L:c +} diff --git a/graph/formats/dot/internal/testdata/quoted_id.dot b/graph/formats/dot/internal/testdata/quoted_id.dot new file mode 100644 index 00000000..0c3b5652 --- /dev/null +++ b/graph/formats/dot/internal/testdata/quoted_id.dot @@ -0,0 +1,3 @@ +digraph { + "A" -> "B" ["color"="red"] +} diff --git a/graph/formats/dot/internal/testdata/semi.dot b/graph/formats/dot/internal/testdata/semi.dot new file mode 100644 index 00000000..c8bcbf34 --- /dev/null +++ b/graph/formats/dot/internal/testdata/semi.dot @@ -0,0 +1,3 @@ +digraph { + A -> B; C +} diff --git a/graph/formats/dot/internal/testdata/semi.golden b/graph/formats/dot/internal/testdata/semi.golden new file mode 100644 index 00000000..61bca268 --- /dev/null +++ b/graph/formats/dot/internal/testdata/semi.golden @@ -0,0 +1,4 @@ +digraph { + A -> B + C +} diff --git a/graph/formats/dot/internal/testdata/strict.dot b/graph/formats/dot/internal/testdata/strict.dot new file mode 100644 index 00000000..bf222ad9 --- /dev/null +++ b/graph/formats/dot/internal/testdata/strict.dot @@ -0,0 +1,4 @@ +strict digraph { + A -> B + A -> B +} diff --git a/graph/formats/dot/internal/testdata/subgraph.dot b/graph/formats/dot/internal/testdata/subgraph.dot new file mode 100644 index 00000000..a03667dd --- /dev/null +++ b/graph/formats/dot/internal/testdata/subgraph.dot @@ -0,0 +1,5 @@ +digraph { + {A} + subgraph {B} + subgraph S {C} +} diff --git a/graph/formats/dot/internal/testdata/subgraph.golden b/graph/formats/dot/internal/testdata/subgraph.golden new file mode 100644 index 00000000..0cd6fe72 --- /dev/null +++ b/graph/formats/dot/internal/testdata/subgraph.golden @@ -0,0 +1,5 @@ +digraph { + {A} + {B} + subgraph S {C} +} diff --git a/graph/formats/dot/internal/testdata/subgraph_vertex.dot b/graph/formats/dot/internal/testdata/subgraph_vertex.dot new file mode 100644 index 00000000..b414ad84 --- /dev/null +++ b/graph/formats/dot/internal/testdata/subgraph_vertex.dot @@ -0,0 +1,3 @@ +digraph { + {A B} -> C +} diff --git a/graph/formats/dot/internal/token/token.go b/graph/formats/dot/internal/token/token.go new file mode 100644 index 00000000..31db6035 --- /dev/null +++ b/graph/formats/dot/internal/token/token.go @@ -0,0 +1,116 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package token + +import ( + "fmt" +) + +type Token struct { + Type + Lit []byte + Pos +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int +} + +func (this Pos) String() string { + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", this.Offset, this.Line, this.Column) +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type +} + +func (this TokenMap) Id(tok Type) string { + if int(tok) < len(this.typeMap) { + return this.typeMap[tok] + } + return "unknown" +} + +func (this TokenMap) Type(tok string) Type { + if typ, exist := this.idMap[tok]; exist { + return typ + } + return INVALID +} + +func (this TokenMap) TokenString(tok *Token) string { + //TODO: refactor to print pos & token string properly + return fmt.Sprintf("%s(%d,%s)", this.Id(tok.Type), tok.Type, tok.Lit) +} + +func (this TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", this.Id(typ), typ) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "$", + "{", + "}", + "empty", + "strict", + "graphx", + "digraph", + ";", + "--", + "->", + "node", + "edge", + "[", + "]", + ",", + "=", + "subgraph", + ":", + "id", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "$": 1, + "{": 2, + "}": 3, + "empty": 4, + "strict": 5, + "graphx": 6, + "digraph": 7, + ";": 8, + "--": 9, + "->": 10, + "node": 11, + "edge": 12, + "[": 13, + "]": 14, + ",": 15, + "=": 16, + "subgraph": 17, + ":": 18, + "id": 19, + }, +} diff --git a/graph/formats/dot/internal/util/litconv.go b/graph/formats/dot/internal/util/litconv.go new file mode 100644 index 00000000..ed6e348b --- /dev/null +++ b/graph/formats/dot/internal/util/litconv.go @@ -0,0 +1,118 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package util + +import ( + "fmt" + "strconv" + "unicode" + "unicode/utf8" +) + +/* Interface */ + +/* +Convert the literal value of a scanned token to rune +*/ +func RuneValue(lit []byte) rune { + if lit[1] == '\\' { + return escapeCharVal(lit) + } + r, size := utf8.DecodeRune(lit[1:]) + if size != len(lit)-2 { + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + } + return r +} + +/* +Convert the literal value of a scanned token to int64 +*/ +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + +/* +Convert the literal value of a scanned token to uint64 +*/ +func UintValue(lit []byte) (uint64, error) { + return strconv.ParseUint(string(lit), 10, 64) +} + +/* Util */ + +func escapeCharVal(lit []byte) rune { + var i, base, max uint32 + offset := 2 + switch lit[offset] { + case 'a': + return '\a' + case 'b': + return '\b' + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + case 'v': + return '\v' + case '\\': + return '\\' + case '\'': + return '\'' + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 16, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", lit)) + } + + var x uint32 + for ; i > 0 && offset < len(lit)-1; i-- { + ch, size := utf8.DecodeRune(lit[offset:]) + offset += size + d := uint32(digitVal(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", lit, ch, size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", lit, offset)) + } + + return rune(x) +} + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/graph/formats/dot/internal/util/rune.go b/graph/formats/dot/internal/util/rune.go new file mode 100644 index 00000000..583b1e06 --- /dev/null +++ b/graph/formats/dot/internal/util/rune.go @@ -0,0 +1,49 @@ +// Code generated by gocc; DO NOT EDIT. + +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package util + +import ( + "fmt" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} diff --git a/graph/formats/dot/sem.go b/graph/formats/dot/sem.go new file mode 100644 index 00000000..799e21d3 --- /dev/null +++ b/graph/formats/dot/sem.go @@ -0,0 +1,160 @@ +// This file is dual licensed under CC0 and The gonum license. +// +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Copyright ©2017 Robin Eklind. +// This file is made available under a Creative Commons CC0 1.0 +// Universal Public Domain Dedication. + +package dot + +import ( + "fmt" + + "gonum.org/v1/gonum/graph/formats/dot/ast" +) + +// check validates the semantics of the given DOT file. +func check(file *ast.File) error { + for _, graph := range file.Graphs { + // TODO: Check graph.ID for duplicates? + if err := checkGraph(graph); err != nil { + return err + } + } + return nil +} + +// check validates the semantics of the given graph. +func checkGraph(graph *ast.Graph) error { + for _, stmt := range graph.Stmts { + if err := checkStmt(graph, stmt); err != nil { + return err + } + } + return nil +} + +// check validates the semantics of the given statement. +func checkStmt(graph *ast.Graph, stmt ast.Stmt) error { + switch stmt := stmt.(type) { + case *ast.NodeStmt: + return checkNodeStmt(graph, stmt) + case *ast.EdgeStmt: + return checkEdgeStmt(graph, stmt) + case *ast.AttrStmt: + return checkAttrStmt(graph, stmt) + case *ast.Attr: + // TODO: Verify that the attribute is indeed of graph component kind. + return checkAttr(graph, ast.KindGraph, stmt) + case *ast.Subgraph: + return checkSubgraph(graph, stmt) + default: + panic(fmt.Sprintf("support for statement of type %T not yet implemented", stmt)) + } +} + +// checkNodeStmt validates the semantics of the given node statement. +func checkNodeStmt(graph *ast.Graph, stmt *ast.NodeStmt) error { + if err := checkNode(graph, stmt.Node); err != nil { + return err + } + for _, attr := range stmt.Attrs { + // TODO: Verify that the attribute is indeed of node component kind. + if err := checkAttr(graph, ast.KindNode, attr); err != nil { + return err + } + } + return nil +} + +// checkEdgeStmt validates the semantics of the given edge statement. +func checkEdgeStmt(graph *ast.Graph, stmt *ast.EdgeStmt) error { + // TODO: if graph.Strict, check for multi-edges. + if err := checkVertex(graph, stmt.From); err != nil { + return err + } + for _, attr := range stmt.Attrs { + // TODO: Verify that the attribute is indeed of edge component kind. + if err := checkAttr(graph, ast.KindEdge, attr); err != nil { + return err + } + } + return checkEdge(graph, stmt.From, stmt.To) +} + +// checkEdge validates the semantics of the given edge. +func checkEdge(graph *ast.Graph, from ast.Vertex, to *ast.Edge) error { + if !graph.Directed && to.Directed { + return fmt.Errorf("undirected graph %q contains directed edge from %q to %q", graph.ID, from, to.Vertex) + } + if err := checkVertex(graph, to.Vertex); err != nil { + return err + } + if to.To != nil { + return checkEdge(graph, to.Vertex, to.To) + } + return nil +} + +// checkAttrStmt validates the semantics of the given attribute statement. +func checkAttrStmt(graph *ast.Graph, stmt *ast.AttrStmt) error { + for _, attr := range stmt.Attrs { + if err := checkAttr(graph, stmt.Kind, attr); err != nil { + return err + } + } + return nil +} + +// checkAttr validates the semantics of the given attribute for the given +// component kind. +func checkAttr(graph *ast.Graph, kind ast.Kind, attr *ast.Attr) error { + switch kind { + case ast.KindGraph: + // TODO: Validate key-value pairs for graphs. + return nil + case ast.KindNode: + // TODO: Validate key-value pairs for nodes. + return nil + case ast.KindEdge: + // TODO: Validate key-value pairs for edges. + return nil + default: + panic(fmt.Sprintf("support for component kind %v not yet supported", kind)) + } +} + +// checkSubgraph validates the semantics of the given subgraph. +func checkSubgraph(graph *ast.Graph, subgraph *ast.Subgraph) error { + // TODO: Check subgraph.ID for duplicates? + for _, stmt := range subgraph.Stmts { + // TODO: Refine handling of subgraph statements? + // checkSubgraphStmt(graph, subgraph, stmt) + if err := checkStmt(graph, stmt); err != nil { + return err + } + } + return nil +} + +// checkVertex validates the semantics of the given vertex. +func checkVertex(graph *ast.Graph, vertex ast.Vertex) error { + switch vertex := vertex.(type) { + case *ast.Node: + return checkNode(graph, vertex) + case *ast.Subgraph: + return checkSubgraph(graph, vertex) + default: + panic(fmt.Sprintf("support for vertex of type %T not yet supported", vertex)) + } +} + +// checNode validates the semantics of the given node. +func checkNode(graph *ast.Graph, node *ast.Node) error { + // TODO: Check node.ID for duplicates? + // TODO: Validate node.Port. + return nil +} diff --git a/graph/formats/dot/testdata/.gitignore b/graph/formats/dot/testdata/.gitignore new file mode 100644 index 00000000..90453be2 --- /dev/null +++ b/graph/formats/dot/testdata/.gitignore @@ -0,0 +1,5 @@ +*.dot +*.png +graphviz +input +output diff --git a/graph/formats/dot/testdata/Makefile b/graph/formats/dot/testdata/Makefile new file mode 100644 index 00000000..c3bfcb9b --- /dev/null +++ b/graph/formats/dot/testdata/Makefile @@ -0,0 +1,106 @@ +# Dependencies: +# +# * imgcmp +# go get github.com/mewkiz/cmd/imgcmp +# * dotfmt +# go get github.com/graphism/dot/cmd/dotfmt +# * dot +# sudo pacman -S graphviz +# * recode +# sudo pacman -S recode + +DOT=$(wildcard *.dot) + +# Skip DOT files for which the generated PNG images mismatch. +# +# ref: https://github.com/graphism/dot/issues/2 +# +# pixel colors differ at x=550, y=1885 +DOT:=$(filter-out b51.dot, $(DOT)) +# pixel colors differ at x=5395, y=1920 +DOT:=$(filter-out b106.dot, $(DOT)) + +# Skip segfaulting files. +# +# Segmentation fault (core dumped) +DOT:=$(filter-out b15.dot, $(DOT)) +# Segmentation fault (core dumped) +DOT:=$(filter-out b81.dot, $(DOT)) +# *** stack smashing detected ***: dot terminated +DOT:=$(filter-out sides.dot, $(DOT)) +# *** stack smashing detected ***: dot terminated +DOT:=$(filter-out tee.dot, $(DOT)) + +# Skip DOT files above 100 kB. +DOT:=$(filter-out 4elt.dot, $(DOT)) +DOT:=$(filter-out b29.dot, $(DOT)) +DOT:=$(filter-out b81.dot, $(DOT)) +DOT:=$(filter-out b100.dot, $(DOT)) +DOT:=$(filter-out b102.dot, $(DOT)) +DOT:=$(filter-out b103.dot, $(DOT)) +DOT:=$(filter-out b104.dot, $(DOT)) +DOT:=$(filter-out root.dot, $(DOT)) +DOT:=$(filter-out root_circo.dot, $(DOT)) +DOT:=$(filter-out root_twopi.dot, $(DOT)) + +# Skip invalid DOT file. +# +# Error: No or improper image file="eqn.png" +# in label of node struct1 +DOT:=$(filter-out html4.dot, $(DOT)) + +# Skip multi-graph DOT file which outputs to standard output. +DOT:=$(filter-out multi.dot, $(DOT)) + +# *.dot -> *.png +PNG=$(DOT:.dot=.png) + +INPUT_PNG=$(addprefix input/,$(PNG)) +OUTPUT_PNG=$(addprefix output/,$(PNG)) + +all: + +test: input $(INPUT_PNG) output $(OUTPUT_PNG) + @echo "PASS" + +input: + mkdir -p $@ + dot -V + +input/%.png: %.dot + dot -Tpng -o $@ $< + +output: + mkdir -p $@ + +output/%.png: %.dot + dotfmt -o "output/$<" $< + dot -Tpng -o $@ "output/$<" + imgcmp "input/$(notdir $@)" $@ + +fetch: graphviz + # Copy *.gv and *.dot files. + find graphviz -type f -name '*.gv' -not -wholename "graphviz/rtest/share/b545.gv" -not -name "base.gv" | xargs -I '{}' cp "{}" . + find graphviz -type f -name '*.dot' | xargs -I '{}' cp "{}" . + + # Rename *.gv to *.dot. + #rename .gv .dot *.gv + ls *.gv | xargs -I '{}' basename "{}" .gv | xargs -I '{}' mv "{}.gv" "{}.dot" + + # Remove execute permissions. + chmod 0644 *.dot + + # Convert Latin1 encoded files to UTF-8. + grep -l "charset=latin1" *.dot | xargs -I '{}' recode ISO-8859-1..UTF8 "{}" + recode ISO-8859-1..UTF8 Latin1.dot + + # Clean up. + rm -rf graphviz + +graphviz: + git clone https://github.com/ellson/graphviz.git + +clean: + rm -rf *.dot input output + +.PHONY: all test fetch clean diff --git a/graph/graph.go b/graph/graph.go new file mode 100644 index 00000000..adade5d7 --- /dev/null +++ b/graph/graph.go @@ -0,0 +1,153 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package graph + +// Node is a graph node. It returns a graph-unique integer ID. +type Node interface { + ID() int +} + +// Edge is a graph edge. In directed graphs, the direction of the +// edge is given from -> to, otherwise the edge is semantically +// unordered. +type Edge interface { + From() Node + To() Node + Weight() float64 +} + +// Graph is a generalized graph. +type Graph interface { + // Has returns whether the node exists within the graph. + Has(Node) bool + + // Nodes returns all the nodes in the graph. + Nodes() []Node + + // From returns all nodes that can be reached directly + // from the given node. + From(Node) []Node + + // HasEdgeBeteen returns whether an edge exists between + // nodes x and y without considering direction. + HasEdgeBetween(x, y Node) bool + + // Edge returns the edge from u to v if such an edge + // exists and nil otherwise. The node v must be directly + // reachable from u as defined by the From method. + Edge(u, v Node) Edge +} + +// Undirected is an undirected graph. +type Undirected interface { + Graph + + // EdgeBetween returns the edge between nodes x and y. + EdgeBetween(x, y Node) Edge +} + +// Directed is a directed graph. +type Directed interface { + Graph + + // HasEdgeFromTo returns whether an edge exists + // in the graph from u to v. + HasEdgeFromTo(u, v Node) bool + + // To returns all nodes that can reach directly + // to the given node. + To(Node) []Node +} + +// Weighter defines graphs that can report edge weights. +type Weighter interface { + // Weight returns the weight for the edge between + // x and y if Edge(x, y) returns a non-nil Edge. + // If x and y are the same node or there is no + // joining edge between the two nodes the weight + // value returned is implementation dependent. + // Weight returns true if an edge exists between + // x and y or if x and y have the same ID, false + // otherwise. + Weight(x, y Node) (w float64, ok bool) +} + +// NodeAdder is an interface for adding arbitrary nodes to a graph. +type NodeAdder interface { + // NewNodeID returns a new unique arbitrary ID. + NewNodeID() int + + // Adds a node to the graph. AddNode panics if + // the added node ID matches an existing node ID. + AddNode(Node) +} + +// NodeRemover is an interface for removing nodes from a graph. +type NodeRemover interface { + // RemoveNode removes a node from the graph, as + // well as any edges attached to it. If the node + // is not in the graph it is a no-op. + RemoveNode(Node) +} + +// EdgeSetter is an interface for adding edges to a graph. +type EdgeSetter interface { + // SetEdge adds an edge from one node to another. + // If the graph supports node addition the nodes + // will be added if they do not exist, otherwise + // SetEdge will panic. + // If the IDs returned by e.From and e.To are + // equal, SetEdge will panic. + SetEdge(e Edge) +} + +// EdgeRemover is an interface for removing nodes from a graph. +type EdgeRemover interface { + // RemoveEdge removes the given edge, leaving the + // terminal nodes. If the edge does not exist it + // is a no-op. + RemoveEdge(Edge) +} + +// Builder is a graph that can have nodes and edges added. +type Builder interface { + NodeAdder + EdgeSetter +} + +// UndirectedBuilder is an undirected graph builder. +type UndirectedBuilder interface { + Undirected + Builder +} + +// DirectedBuilder is a directed graph builder. +type DirectedBuilder interface { + Directed + Builder +} + +// Copy copies nodes and edges as undirected edges from the source to the destination +// without first clearing the destination. Copy will panic if a node ID in the source +// graph matches a node ID in the destination. +// +// If the source is undirected and the destination is directed both directions will +// be present in the destination after the copy is complete. +// +// If the source is a directed graph, the destination is undirected, and a fundamental +// cycle exists with two nodes where the edge weights differ, the resulting destination +// graph's edge weight between those nodes is undefined. If there is a defined function +// to resolve such conflicts, an Undirect may be used to do this. +func Copy(dst Builder, src Graph) { + nodes := src.Nodes() + for _, n := range nodes { + dst.AddNode(n) + } + for _, u := range nodes { + for _, v := range src.From(u) { + dst.SetEdge(src.Edge(u, v)) + } + } +} diff --git a/graph/graphs/gen/batagelj_brandes.go b/graph/graphs/gen/batagelj_brandes.go new file mode 100644 index 00000000..4565ce32 --- /dev/null +++ b/graph/graphs/gen/batagelj_brandes.go @@ -0,0 +1,357 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The functions in this file are random graph generators from the paper +// by Batagelj and Brandes http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + +package gen + +import ( + "fmt" + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +// Gnp constructs a Gilbert’s model graph in the destination, dst, of order n. Edges +// between nodes are formed with the probability, p. If src is not nil it is used +// as the random source, otherwise rand.Float64 is used. The graph is constructed +// in O(n+m) time where m is the number of edges added. +func Gnp(dst GraphBuilder, n int, p float64, src *rand.Rand) error { + if p == 0 { + return nil + } + if p < 0 || p > 1 { + return fmt.Errorf("gen: bad probability: p=%v", p) + } + var r func() float64 + if src == nil { + r = rand.Float64 + } else { + r = src.Float64 + } + + for i := 0; i < n; i++ { + if !dst.Has(simple.Node(i)) { + dst.AddNode(simple.Node(i)) + } + } + + lp := math.Log(1 - p) + + // Add forward edges for all graphs. + for v, w := 1, -1; v < n; { + w += 1 + int(math.Log(1-r())/lp) + for w >= v && v < n { + w -= v + v++ + } + if v < n { + dst.SetEdge(simple.Edge{F: simple.Node(w), T: simple.Node(v), W: 1}) + } + } + + // Add backward edges for directed graphs. + if _, ok := dst.(graph.Directed); !ok { + return nil + } + for v, w := 1, -1; v < n; { + w += 1 + int(math.Log(1-r())/lp) + for w >= v && v < n { + w -= v + v++ + } + if v < n { + dst.SetEdge(simple.Edge{F: simple.Node(v), T: simple.Node(w), W: 1}) + } + } + + return nil +} + +// edgeNodesFor returns the pair of nodes for the ith edge in a simple +// undirected graph. The pair is returned such that w.ID < v.ID. +func edgeNodesFor(i int) (v, w simple.Node) { + // This is an algebraic simplification of the expressions described + // on p3 of http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + v = simple.Node(0.5 + math.Sqrt(float64(1+8*i))/2) + w = simple.Node(i) - v*(v-1)/2 + return v, w +} + +// Gnm constructs a Erdős-Rényi model graph in the destination, dst, of +// order n and size m. If src is not nil it is used as the random source, +// otherwise rand.Intn is used. The graph is constructed in O(m) expected +// time for m ≤ (n choose 2)/2. +func Gnm(dst GraphBuilder, n, m int, src *rand.Rand) error { + if m == 0 { + return nil + } + + hasEdge := dst.HasEdgeBetween + d, isDirected := dst.(graph.Directed) + if isDirected { + m /= 2 + hasEdge = d.HasEdgeFromTo + } + + nChoose2 := (n - 1) * n / 2 + if m < 0 || m > nChoose2 { + return fmt.Errorf("gen: bad size: m=%d", m) + } + + var rnd func(int) int + if src == nil { + rnd = rand.Intn + } else { + rnd = src.Intn + } + + for i := 0; i < n; i++ { + if !dst.Has(simple.Node(i)) { + dst.AddNode(simple.Node(i)) + } + } + + // Add forward edges for all graphs. + for i := 0; i < m; i++ { + for { + v, w := edgeNodesFor(rnd(nChoose2)) + e := simple.Edge{F: w, T: v, W: 1} + if !hasEdge(e.F, e.T) { + dst.SetEdge(e) + break + } + } + } + + // Add backward edges for directed graphs. + if !isDirected { + return nil + } + for i := 0; i < m; i++ { + for { + v, w := edgeNodesFor(rnd(nChoose2)) + e := simple.Edge{F: v, T: w, W: 1} + if !hasEdge(e.F, e.T) { + dst.SetEdge(e) + break + } + } + } + + return nil +} + +// SmallWorldsBB constructs a small worlds graph of order n in the destination, dst. +// Node degree is specified by d and edge replacement by the probability, p. +// If src is not nil it is used as the random source, otherwise rand.Float64 is used. +// The graph is constructed in O(nd) time. +// +// The algorithm used is described in http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf +func SmallWorldsBB(dst GraphBuilder, n, d int, p float64, src *rand.Rand) error { + if d < 1 || d > (n-1)/2 { + return fmt.Errorf("gen: bad degree: d=%d", d) + } + if p == 0 { + return nil + } + if p < 0 || p >= 1 { + return fmt.Errorf("gen: bad replacement: p=%v", p) + } + var ( + rnd func() float64 + rndN func(int) int + ) + if src == nil { + rnd = rand.Float64 + rndN = rand.Intn + } else { + rnd = src.Float64 + rndN = src.Intn + } + + hasEdge := dst.HasEdgeBetween + dg, isDirected := dst.(graph.Directed) + if isDirected { + hasEdge = dg.HasEdgeFromTo + } + + for i := 0; i < n; i++ { + if !dst.Has(simple.Node(i)) { + dst.AddNode(simple.Node(i)) + } + } + + nChoose2 := (n - 1) * n / 2 + + lp := math.Log(1 - p) + + // Add forward edges for all graphs. + k := int(math.Log(1-rnd()) / lp) + m := 0 + replace := make(map[int]int) + for v := 0; v < n; v++ { + for i := 1; i <= d; i++ { + if k > 0 { + j := v*(v-1)/2 + (v+i)%n + ej := simple.Edge{W: 1} + ej.T, ej.F = edgeNodesFor(j) + if !hasEdge(ej.From(), ej.To()) { + dst.SetEdge(ej) + } + k-- + m++ + em := simple.Edge{W: 1} + em.T, em.F = edgeNodesFor(m) + if !hasEdge(em.From(), em.To()) { + replace[j] = m + } else { + replace[j] = replace[m] + } + } else { + k = int(math.Log(1-rnd()) / lp) + } + } + } + for i := m + 1; i <= n*d && i < nChoose2; i++ { + r := rndN(nChoose2-i) + i + er := simple.Edge{W: 1} + er.T, er.F = edgeNodesFor(r) + if !hasEdge(er.From(), er.To()) { + dst.SetEdge(er) + } else { + er.T, er.F = edgeNodesFor(replace[r]) + if !hasEdge(er.From(), er.To()) { + dst.SetEdge(er) + } + } + ei := simple.Edge{W: 1} + ei.T, ei.F = edgeNodesFor(i) + if !hasEdge(ei.From(), ei.To()) { + replace[r] = i + } else { + replace[r] = replace[i] + } + } + + // Add backward edges for directed graphs. + if !isDirected { + return nil + } + k = int(math.Log(1-rnd()) / lp) + m = 0 + replace = make(map[int]int) + for v := 0; v < n; v++ { + for i := 1; i <= d; i++ { + if k > 0 { + j := v*(v-1)/2 + (v+i)%n + ej := simple.Edge{W: 1} + ej.F, ej.T = edgeNodesFor(j) + if !hasEdge(ej.From(), ej.To()) { + dst.SetEdge(ej) + } + k-- + m++ + if !hasEdge(edgeNodesFor(m)) { + replace[j] = m + } else { + replace[j] = replace[m] + } + } else { + k = int(math.Log(1-rnd()) / lp) + } + } + } + for i := m + 1; i <= n*d && i < nChoose2; i++ { + r := rndN(nChoose2-i) + i + er := simple.Edge{W: 1} + er.F, er.T = edgeNodesFor(r) + if !hasEdge(er.From(), er.To()) { + dst.SetEdge(er) + } else { + er.F, er.T = edgeNodesFor(replace[r]) + if !hasEdge(er.From(), er.To()) { + dst.SetEdge(er) + } + } + if !hasEdge(edgeNodesFor(i)) { + replace[r] = i + } else { + replace[r] = replace[i] + } + } + + return nil +} + +/* +// Multigraph generators. + +type EdgeAdder interface { + AddEdge(graph.Edge) +} + +func PreferentialAttachment(dst EdgeAdder, n, d int, src *rand.Rand) { + if d < 1 { + panic("gen: bad d") + } + var rnd func(int) int + if src == nil { + rnd = rand.Intn + } else { + rnd = src.Intn + } + + m := make([]simple.Node, 2*n*d) + for v := 0; v < n; v++ { + for i := 0; i < d; i++ { + m[2*(v*d+i)] = simple.Node(v) + m[2*(v*d+i)+1] = simple.Node(m[rnd(2*v*d+i+1)]) + } + } + for i := 0; i < n*d; i++ { + dst.AddEdge(simple.Edge{F: m[2*i], T: m[2*i+1], W: 1}) + } +} + +func BipartitePreferentialAttachment(dst EdgeAdder, n, d int, src *rand.Rand) { + if d < 1 { + panic("gen: bad d") + } + var rnd func(int) int + if src == nil { + rnd = rand.Intn + } else { + rnd = src.Intn + } + + m1 := make([]simple.Node, 2*n*d) + m2 := make([]simple.Node, 2*n*d) + for v := 0; v < n; v++ { + for i := 0; i < d; i++ { + m1[2*(v*d+i)] = simple.Node(v) + m2[2*(v*d+i)] = simple.Node(n + v) + + if r := rnd(2*v*d + i + 1); r&0x1 == 0 { + m1[2*(v*d+i)+1] = m2[r] + } else { + m1[2*(v*d+i)+1] = m1[r] + } + + if r := rnd(2*v*d + i + 1); r&0x1 == 0 { + m2[2*(v*d+i)+1] = m1[r] + } else { + m2[2*(v*d+i)+1] = m2[r] + } + } + } + for i := 0; i < n*d; i++ { + dst.AddEdge(simple.Edge{F: m1[2*i], T: m1[2*i+1], W: 1}) + dst.AddEdge(simple.Edge{F: m2[2*i], T: m2[2*i+1], W: 1}) + } +} +*/ diff --git a/graph/graphs/gen/batagelj_brandes_test.go b/graph/graphs/gen/batagelj_brandes_test.go new file mode 100644 index 00000000..b9993934 --- /dev/null +++ b/graph/graphs/gen/batagelj_brandes_test.go @@ -0,0 +1,175 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gen + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +type gnUndirected struct { + graph.UndirectedBuilder + addBackwards bool + addSelfLoop bool + addMultipleEdge bool +} + +func (g *gnUndirected) SetEdge(e graph.Edge) { + switch { + case e.From().ID() == e.To().ID(): + g.addSelfLoop = true + return + case e.From().ID() > e.To().ID(): + g.addBackwards = true + case g.UndirectedBuilder.HasEdgeBetween(e.From(), e.To()): + g.addMultipleEdge = true + } + + g.UndirectedBuilder.SetEdge(e) +} + +type gnDirected struct { + graph.DirectedBuilder + addSelfLoop bool + addMultipleEdge bool +} + +func (g *gnDirected) SetEdge(e graph.Edge) { + switch { + case e.From().ID() == e.To().ID(): + g.addSelfLoop = true + return + case g.DirectedBuilder.HasEdgeFromTo(e.From(), e.To()): + g.addMultipleEdge = true + } + + g.DirectedBuilder.SetEdge(e) +} + +func TestGnpUndirected(t *testing.T) { + for n := 2; n <= 20; n++ { + for p := 0.; p <= 1; p += 0.1 { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph(0, math.Inf(1))} + err := Gnp(g, n, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, p=%v: %v", n, p, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, p=%v", n, p) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, p=%v", n, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, p=%v", n, p) + } + } + } +} + +func TestGnpDirected(t *testing.T) { + for n := 2; n <= 20; n++ { + for p := 0.; p <= 1; p += 0.1 { + g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph(0, math.Inf(1))} + err := Gnp(g, n, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, p=%v: %v", n, p, err) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, p=%v", n, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, p=%v", n, p) + } + } + } +} + +func TestGnmUndirected(t *testing.T) { + for n := 2; n <= 20; n++ { + nChoose2 := (n - 1) * n / 2 + for m := 0; m <= nChoose2; m++ { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph(0, math.Inf(1))} + err := Gnm(g, n, m, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, m=%d: %v", n, m, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, m=%d", n, m) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, m=%d", n, m) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, m=%d", n, m) + } + } + } +} + +func TestGnmDirected(t *testing.T) { + for n := 2; n <= 20; n++ { + nChoose2 := (n - 1) * n / 2 + for m := 0; m <= nChoose2*2; m++ { + g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph(0, math.Inf(1))} + err := Gnm(g, n, m, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, m=%d: %v", n, m, err) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, m=%d", n, m) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, m=%d", n, m) + } + } + } +} + +func TestSmallWorldsBBUndirected(t *testing.T) { + for n := 2; n <= 20; n++ { + for d := 1; d <= (n-1)/2; d++ { + for p := 0.; p < 1; p += 0.1 { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph(0, math.Inf(1))} + err := SmallWorldsBB(g, n, d, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, d=%d, p=%v: %v", n, d, p, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, d=%d, p=%v", n, d, p) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, d=%d, p=%v", n, d, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, d=%d, p=%v", n, d, p) + } + } + } + } +} + +func TestSmallWorldsBBDirected(t *testing.T) { + for n := 2; n <= 20; n++ { + for d := 1; d <= (n-1)/2; d++ { + for p := 0.; p < 1; p += 0.1 { + g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph(0, math.Inf(1))} + err := SmallWorldsBB(g, n, d, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, d=%d, p=%v: %v", n, d, p, err) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, d=%d, p=%v", n, d, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, d=%d, p=%v", n, d, p) + } + } + } + } +} diff --git a/graph/graphs/gen/duplication.go b/graph/graphs/gen/duplication.go new file mode 100644 index 00000000..f66721bb --- /dev/null +++ b/graph/graphs/gen/duplication.go @@ -0,0 +1,125 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gen + +import ( + "fmt" + "math" + "math/rand" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +// UndirectedMutator is an undirected graph builder that can remove edges. +type UndirectedMutator interface { + graph.UndirectedBuilder + graph.EdgeRemover +} + +// Duplication constructs a graph in the destination, dst, of order n. New nodes +// are created by duplicating an existing node and all its edges. Each new edge is +// deleted with probability delta. Additional edges are added between the new node +// and existing nodes with probability alpha/|V|. An exception to this addition +// rule is made for the parent node when sigma is not NaN; in this case an edge is +// created with probability sigma. With the exception of the sigma parameter, this +// corresponds to the completely correlated case in doi:10.1016/S0022-5193(03)00028-6. +// If src is not nil it is used as the random source, otherwise rand.Float64 is used. +func Duplication(dst UndirectedMutator, n int, delta, alpha, sigma float64, src *rand.Rand) error { + // As described in doi:10.1016/S0022-5193(03)00028-6 but + // also clarified in doi:10.1186/gb-2007-8-4-r51. + + if delta < 0 || delta > 1 { + return fmt.Errorf("gen: bad delta: delta=%v", delta) + } + if alpha <= 0 || alpha > 1 { + return fmt.Errorf("gen: bad alpha: alpha=%v", alpha) + } + if sigma < 0 || sigma > 1 { + return fmt.Errorf("gen: bad sigma: sigma=%v", sigma) + } + + var ( + rnd func() float64 + rndN func(int) int + ) + if src == nil { + rnd = rand.Float64 + rndN = rand.Intn + } else { + rnd = src.Float64 + rndN = src.Intn + } + + nodes := dst.Nodes() + sort.Sort(ordered.ByID(nodes)) + if len(nodes) == 0 { + n-- + dst.AddNode(simple.Node(0)) + nodes = append(nodes, simple.Node(0)) + } + for i := 0; i < n; i++ { + u := nodes[rndN(len(nodes))] + d := simple.Node(dst.NewNodeID()) + + // Add the duplicate node. + dst.AddNode(d) + + // Loop until we have connectivity + // into the rest of the graph. + for { + // Add edges to parent's neigbours. + to := dst.From(u) + sort.Sort(ordered.ByID(to)) + for _, v := range to { + if rnd() < delta || dst.HasEdgeBetween(v, d) { + continue + } + if v.ID() < d.ID() { + dst.SetEdge(simple.Edge{F: v, T: d, W: 1}) + } else { + dst.SetEdge(simple.Edge{F: d, T: v, W: 1}) + } + } + + // Add edges to old nodes. + scaledAlpha := alpha / float64(len(nodes)) + for _, v := range nodes { + switch v.ID() { + case u.ID(): + if !math.IsNaN(sigma) { + if i == 0 || rnd() < sigma { + if v.ID() < d.ID() { + dst.SetEdge(simple.Edge{F: v, T: d, W: 1}) + } else { + dst.SetEdge(simple.Edge{F: d, T: v, W: 1}) + } + } + continue + } + fallthrough + default: + if rnd() < scaledAlpha && !dst.HasEdgeBetween(v, d) { + if v.ID() < d.ID() { + dst.SetEdge(simple.Edge{F: v, T: d, W: 1}) + } else { + dst.SetEdge(simple.Edge{F: d, T: v, W: 1}) + } + } + } + } + + if len(dst.From(d)) != 0 { + break + } + } + + nodes = append(nodes, d) + } + + return nil +} diff --git a/graph/graphs/gen/duplication_test.go b/graph/graphs/gen/duplication_test.go new file mode 100644 index 00000000..56e7d05a --- /dev/null +++ b/graph/graphs/gen/duplication_test.go @@ -0,0 +1,59 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gen + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +type duplication struct { + UndirectedMutator + addBackwards bool + addSelfLoop bool + addMultipleEdge bool +} + +func (g *duplication) SetEdge(e graph.Edge) { + switch { + case e.From().ID() == e.To().ID(): + g.addSelfLoop = true + return + case e.From().ID() > e.To().ID(): + g.addBackwards = true + case g.UndirectedMutator.HasEdgeBetween(e.From(), e.To()): + g.addMultipleEdge = true + } + + g.UndirectedMutator.SetEdge(e) +} + +func TestDuplication(t *testing.T) { + for n := 2; n <= 50; n++ { + for alpha := 0.1; alpha <= 1; alpha += 0.1 { + for delta := 0.; delta <= 1; delta += 0.2 { + for sigma := 0.; sigma <= 1; sigma += 0.2 { + g := &duplication{UndirectedMutator: simple.NewUndirectedGraph(0, math.Inf(1))} + err := Duplication(g, n, delta, alpha, sigma, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, alpha=%v, delta=%v sigma=%v: %v", n, alpha, delta, sigma, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, alpha=%v, delta=%v sigma=%v", n, alpha, delta, sigma) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, alpha=%v, delta=%v sigma=%v", n, alpha, delta, sigma) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, alpha=%v, delta=%v sigma=%v", n, alpha, delta, sigma) + } + } + } + } + } +} diff --git a/graph/graphs/gen/gen.go b/graph/graphs/gen/gen.go new file mode 100644 index 00000000..993d6c75 --- /dev/null +++ b/graph/graphs/gen/gen.go @@ -0,0 +1,22 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package gen provides random graph generation functions. +package gen + +import "gonum.org/v1/gonum/graph" + +// GraphBuilder is a graph that can have nodes and edges added. +type GraphBuilder interface { + Has(graph.Node) bool + HasEdgeBetween(x, y graph.Node) bool + graph.Builder +} + +func abs(a int) int { + if a < 0 { + return -a + } + return a +} diff --git a/graph/graphs/gen/holme_kim.go b/graph/graphs/gen/holme_kim.go new file mode 100644 index 00000000..924bb235 --- /dev/null +++ b/graph/graphs/gen/holme_kim.go @@ -0,0 +1,160 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gen + +import ( + "errors" + "fmt" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/stat/sampleuv" +) + +// TunableClusteringScaleFree constructs a graph in the destination, dst, of order n. +// The graph is constructed successively starting from an m order graph with one node +// having degree m-1. At each iteration of graph addition, one node is added with m +// additional edges joining existing nodes with probability proportional to the nodes' +// degrees. The edges are formed as a triad with probability, p. +// If src is not nil it is used as the random source, otherwise rand.Float64 and +// rand.Intn are used. +// +// The algorithm is essentially as described in http://arxiv.org/abs/cond-mat/0110452. +func TunableClusteringScaleFree(dst graph.UndirectedBuilder, n, m int, p float64, src *rand.Rand) error { + if p < 0 || p > 1 { + return fmt.Errorf("gen: bad probability: p=%v", p) + } + if n <= m { + return fmt.Errorf("gen: n <= m: n=%v m=%d", n, m) + } + + var ( + rnd func() float64 + rndN func(int) int + ) + if src == nil { + rnd = rand.Float64 + rndN = rand.Intn + } else { + rnd = src.Float64 + rndN = src.Intn + } + + // Initial condition. + wt := make([]float64, n) + for u := 0; u < m; u++ { + if !dst.Has(simple.Node(u)) { + dst.AddNode(simple.Node(u)) + } + // We need to give equal probability for + // adding the first generation of edges. + wt[u] = 1 + } + ws := sampleuv.NewWeighted(wt, src) + for i := range wt { + // These weights will organically grow + // after the first growth iteration. + wt[i] = 0 + } + + // Growth. + for v := m; v < n; v++ { + var u int + pa: + for i := 0; i < m; i++ { + // Triad formation. + if i != 0 && rnd() < p { + for _, w := range permute(dst.From(simple.Node(u)), rndN) { + wid := w.ID() + if wid == v || dst.HasEdgeBetween(w, simple.Node(v)) { + continue + } + dst.SetEdge(simple.Edge{F: w, T: simple.Node(v), W: 1}) + wt[wid]++ + wt[v]++ + continue pa + } + } + + // Preferential attachment. + for { + var ok bool + u, ok = ws.Take() + if !ok { + return errors.New("gen: depleted distribution") + } + if u == v || dst.HasEdgeBetween(simple.Node(u), simple.Node(v)) { + continue + } + dst.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + wt[u]++ + wt[v]++ + break + } + } + + ws.ReweightAll(wt) + } + + return nil +} + +func permute(n []graph.Node, rnd func(int) int) []graph.Node { + for i := range n[:len(n)-1] { + j := rnd(len(n)-i) + i + n[i], n[j] = n[j], n[i] + } + return n +} + +// PreferentialAttachment constructs a graph in the destination, dst, of order n. +// The graph is constructed successively starting from an m order graph with one +// node having degree m-1. At each iteration of graph addition, one node is added +// with m additional edges joining existing nodes with probability proportional +// to the nodes' degrees. If src is not nil it is used as the random source, +// otherwise rand.Float64 is used. +// +// The algorithm is essentially as described in http://arxiv.org/abs/cond-mat/0110452 +// after 10.1126/science.286.5439.509. +func PreferentialAttachment(dst graph.UndirectedBuilder, n, m int, src *rand.Rand) error { + if n <= m { + return fmt.Errorf("gen: n <= m: n=%v m=%d", n, m) + } + + // Initial condition. + wt := make([]float64, n) + for u := 0; u < m; u++ { + if !dst.Has(simple.Node(u)) { + dst.AddNode(simple.Node(u)) + } + // We need to give equal probability for + // adding the first generation of edges. + wt[u] = 1 + } + ws := sampleuv.NewWeighted(wt, src) + for i := range wt { + // These weights will organically grow + // after the first growth iteration. + wt[i] = 0 + } + + // Growth. + for v := m; v < n; v++ { + for i := 0; i < m; i++ { + // Preferential attachment. + u, ok := ws.Take() + if !ok { + return errors.New("gen: depleted distribution") + } + dst.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + wt[u]++ + wt[v]++ + } + ws.ReweightAll(wt) + } + + return nil +} diff --git a/graph/graphs/gen/holme_kim_test.go b/graph/graphs/gen/holme_kim_test.go new file mode 100644 index 00000000..370c42c7 --- /dev/null +++ b/graph/graphs/gen/holme_kim_test.go @@ -0,0 +1,56 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gen + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph/simple" +) + +func TestTunableClusteringScaleFree(t *testing.T) { + for n := 2; n <= 20; n++ { + for m := 0; m < n; m++ { + for p := 0.; p <= 1; p += 0.1 { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph(0, math.Inf(1))} + err := TunableClusteringScaleFree(g, n, m, p, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, m=%d, p=%v: %v", n, m, p, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, m=%d, p=%v", n, m, p) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, m=%d, p=%v", n, m, p) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, m=%d, p=%v", n, m, p) + } + } + } + } +} + +func TestPreferentialAttachment(t *testing.T) { + for n := 2; n <= 20; n++ { + for m := 0; m < n; m++ { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph(0, math.Inf(1))} + err := PreferentialAttachment(g, n, m, nil) + if err != nil { + t.Fatalf("unexpected error: n=%d, m=%d: %v", n, m, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: n=%d, m=%d", n, m) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: n=%d, m=%d", n, m) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: n=%d, m=%d", n, m) + } + } + } +} diff --git a/graph/graphs/gen/small_world.go b/graph/graphs/gen/small_world.go new file mode 100644 index 00000000..6bf44932 --- /dev/null +++ b/graph/graphs/gen/small_world.go @@ -0,0 +1,204 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gen + +import ( + "errors" + "fmt" + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/stat/sampleuv" +) + +// NavigableSmallWorld constructs an N-dimensional grid with guaranteed local connectivity +// and random long-range connectivity in the destination, dst. The dims parameters specifies +// the length of each of the N dimensions, p defines the Manhattan distance between local +// nodes, and q defines the number of out-going long-range connections from each node. Long- +// range connections are made with a probability proportional to |d(u,v)|^-r where d is the +// Manhattan distance between non-local nodes. +// +// The algorithm is essentially as described on p4 of http://www.cs.cornell.edu/home/kleinber/swn.pdf. +func NavigableSmallWorld(dst GraphBuilder, dims []int, p, q int, r float64, src *rand.Rand) (err error) { + if p < 1 { + return fmt.Errorf("gen: bad local distance: p=%v", p) + } + if q < 0 { + return fmt.Errorf("gen: bad distant link count: q=%v", q) + } + if r < 0 { + return fmt.Errorf("gen: bad decay constant: r=%v", r) + } + + n := 1 + for _, d := range dims { + n *= d + } + for i := 0; i < n; i++ { + if !dst.Has(simple.Node(i)) { + dst.AddNode(simple.Node(i)) + } + } + + hasEdge := dst.HasEdgeBetween + d, isDirected := dst.(graph.Directed) + if isDirected { + hasEdge = d.HasEdgeFromTo + } + + locality := make([]int, len(dims)) + for i := range locality { + locality[i] = p*2 + 1 + } + iterateOver(dims, func(u []int) { + uid := idFrom(u, dims) + iterateOver(locality, func(delta []int) { + d := manhattanDelta(u, delta, dims, -p) + if d == 0 || d > p { + return + } + vid := idFromDelta(u, delta, dims, -p) + e := simple.Edge{F: simple.Node(uid), T: simple.Node(vid), W: 1} + if uid > vid { + e.F, e.T = e.T, e.F + } + if !hasEdge(e.From(), e.To()) { + dst.SetEdge(e) + } + if !isDirected { + return + } + e.F, e.T = e.T, e.F + if !hasEdge(e.From(), e.To()) { + dst.SetEdge(e) + } + }) + }) + + defer func() { + r := recover() + if r != nil { + if r != "depleted distribution" { + panic(r) + } + err = errors.New("depleted distribution") + } + }() + w := make([]float64, n) + ws := sampleuv.NewWeighted(w, src) + iterateOver(dims, func(u []int) { + uid := idFrom(u, dims) + iterateOver(dims, func(v []int) { + d := manhattanBetween(u, v) + if d <= p { + return + } + w[idFrom(v, dims)] = math.Pow(float64(d), -r) + }) + ws.ReweightAll(w) + for i := 0; i < q; i++ { + vid, ok := ws.Take() + if !ok { + panic("depleted distribution") + } + e := simple.Edge{F: simple.Node(uid), T: simple.Node(vid), W: 1} + if !isDirected && uid > vid { + e.F, e.T = e.T, e.F + } + if !hasEdge(e.From(), e.To()) { + dst.SetEdge(e) + } + } + for i := range w { + w[i] = 0 + } + }) + + return nil +} + +// iterateOver performs an iteration over all dimensions of dims, calling fn +// for each state. The elements of state must not be mutated by fn. +func iterateOver(dims []int, fn func(state []int)) { + iterator(0, dims, make([]int, len(dims)), fn) +} + +func iterator(d int, dims, state []int, fn func(state []int)) { + if d >= len(dims) { + fn(state) + return + } + for i := 0; i < dims[d]; i++ { + state[d] = i + iterator(d+1, dims, state, fn) + } +} + +// manhattanBetween returns the Manhattan distance between a and b. +func manhattanBetween(a, b []int) int { + if len(a) != len(b) { + panic("gen: unexpected dimension") + } + var d int + for i, v := range a { + d += abs(v - b[i]) + } + return d +} + +// manhattanDelta returns the Manhattan norm of delta+translate. If a +// translated by delta+translate is out of the range given by dims, +// zero is returned. +func manhattanDelta(a, delta, dims []int, translate int) int { + if len(a) != len(dims) { + panic("gen: unexpected dimension") + } + if len(delta) != len(dims) { + panic("gen: unexpected dimension") + } + var d int + for i, v := range delta { + v += translate + t := a[i] + v + if t < 0 || t >= dims[i] { + return 0 + } + d += abs(v) + } + return d +} + +// idFrom returns a node id for the slice n over the given dimensions. +func idFrom(n, dims []int) int { + s := 1 + var id int + for d, m := range dims { + p := n[d] + if p < 0 || p >= m { + panic("gen: element out of range") + } + id += p * s + s *= m + } + return id +} + +// idFromDelta returns a node id for the slice base plus the delta over the given +// dimensions and applying the translation. +func idFromDelta(base, delta, dims []int, translate int) int { + s := 1 + var id int + for d, m := range dims { + n := base[d] + delta[d] + translate + if n < 0 || n >= m { + panic("gen: element out of range") + } + id += n * s + s *= m + } + return id +} diff --git a/graph/graphs/gen/small_world_test.go b/graph/graphs/gen/small_world_test.go new file mode 100644 index 00000000..8caa1787 --- /dev/null +++ b/graph/graphs/gen/small_world_test.go @@ -0,0 +1,73 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gen + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph/simple" +) + +var smallWorldDimensionParameters = [][]int{ + {50}, + {10, 10}, + {6, 5, 4}, +} + +func TestNavigableSmallWorldUndirected(t *testing.T) { + for p := 1; p < 5; p++ { + for q := 0; q < 10; q++ { + for r := 0.5; r < 10; r++ { + for _, dims := range smallWorldDimensionParameters { + g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph(0, math.Inf(1))} + err := NavigableSmallWorld(g, dims, p, q, r, nil) + n := 1 + for _, d := range dims { + n *= d + } + if err != nil { + t.Fatalf("unexpected error: dims=%v n=%d, p=%d, q=%d, r=%v: %v", dims, n, p, q, r, err) + } + if g.addBackwards { + t.Errorf("edge added with From.ID > To.ID: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + } + } + } + } +} + +func TestNavigableSmallWorldDirected(t *testing.T) { + for p := 1; p < 5; p++ { + for q := 0; q < 10; q++ { + for r := 0.5; r < 10; r++ { + for _, dims := range smallWorldDimensionParameters { + g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph(0, math.Inf(1))} + err := NavigableSmallWorld(g, dims, p, q, r, nil) + n := 1 + for _, d := range dims { + n *= d + } + if err != nil { + t.Fatalf("unexpected error: dims=%v n=%d, p=%d, q=%d, r=%v, r=%v: %v", dims, n, p, q, r, err) + } + if g.addSelfLoop { + t.Errorf("unexpected self edge: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + if g.addMultipleEdge { + t.Errorf("unexpected multiple edge: dims=%v n=%d, p=%d, q=%d, r=%v", dims, n, p, q, r) + } + } + } + } + } +} diff --git a/graph/internal/linear/linear.go b/graph/internal/linear/linear.go new file mode 100644 index 00000000..cd3f4bda --- /dev/null +++ b/graph/internal/linear/linear.go @@ -0,0 +1,74 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package linear provides common linear data structures. +package linear + +import ( + "gonum.org/v1/gonum/graph" +) + +// NodeStack implements a LIFO stack of graph.Node. +type NodeStack []graph.Node + +// Len returns the number of graph.Nodes on the stack. +func (s *NodeStack) Len() int { return len(*s) } + +// Pop returns the last graph.Node on the stack and removes it +// from the stack. +func (s *NodeStack) Pop() graph.Node { + v := *s + v, n := v[:len(v)-1], v[len(v)-1] + *s = v + return n +} + +// Push adds the node n to the stack at the last position. +func (s *NodeStack) Push(n graph.Node) { *s = append(*s, n) } + +// NodeQueue implements a FIFO queue. +type NodeQueue struct { + head int + data []graph.Node +} + +// Len returns the number of graph.Nodes in the queue. +func (q *NodeQueue) Len() int { return len(q.data) - q.head } + +// Enqueue adds the node n to the back of the queue. +func (q *NodeQueue) Enqueue(n graph.Node) { + if len(q.data) == cap(q.data) && q.head > 0 { + l := q.Len() + copy(q.data, q.data[q.head:]) + q.head = 0 + q.data = append(q.data[:l], n) + } else { + q.data = append(q.data, n) + } +} + +// Dequeue returns the graph.Node at the front of the queue and +// removes it from the queue. +func (q *NodeQueue) Dequeue() graph.Node { + if q.Len() == 0 { + panic("queue: empty queue") + } + + var n graph.Node + n, q.data[q.head] = q.data[q.head], nil + q.head++ + + if q.Len() == 0 { + q.head = 0 + q.data = q.data[:0] + } + + return n +} + +// Reset clears the queue for reuse. +func (q *NodeQueue) Reset() { + q.head = 0 + q.data = q.data[:0] +} diff --git a/graph/internal/ordered/sort.go b/graph/internal/ordered/sort.go new file mode 100644 index 00000000..787be17e --- /dev/null +++ b/graph/internal/ordered/sort.go @@ -0,0 +1,62 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package ordered provides common sort ordering types. +package ordered + +import "gonum.org/v1/gonum/graph" + +// ByID implements the sort.Interface sorting a slice of graph.Node +// by ID. +type ByID []graph.Node + +func (n ByID) Len() int { return len(n) } +func (n ByID) Less(i, j int) bool { return n[i].ID() < n[j].ID() } +func (n ByID) Swap(i, j int) { n[i], n[j] = n[j], n[i] } + +// BySliceValues implements the sort.Interface sorting a slice of +// []int lexically by the values of the []int. +type BySliceValues [][]int + +func (c BySliceValues) Len() int { return len(c) } +func (c BySliceValues) Less(i, j int) bool { + a, b := c[i], c[j] + l := len(a) + if len(b) < l { + l = len(b) + } + for k, v := range a[:l] { + if v < b[k] { + return true + } + if v > b[k] { + return false + } + } + return len(a) < len(b) +} +func (c BySliceValues) Swap(i, j int) { c[i], c[j] = c[j], c[i] } + +// BySliceIDs implements the sort.Interface sorting a slice of +// []graph.Node lexically by the IDs of the []graph.Node. +type BySliceIDs [][]graph.Node + +func (c BySliceIDs) Len() int { return len(c) } +func (c BySliceIDs) Less(i, j int) bool { + a, b := c[i], c[j] + l := len(a) + if len(b) < l { + l = len(b) + } + for k, v := range a[:l] { + if v.ID() < b[k].ID() { + return true + } + if v.ID() > b[k].ID() { + return false + } + } + return len(a) < len(b) +} +func (c BySliceIDs) Swap(i, j int) { c[i], c[j] = c[j], c[i] } diff --git a/graph/internal/set/same.go b/graph/internal/set/same.go new file mode 100644 index 00000000..d2555782 --- /dev/null +++ b/graph/internal/set/same.go @@ -0,0 +1,18 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !appengine + +package set + +import "unsafe" + +// same determines whether two sets are backed by the same store. In the +// current implementation using hash maps it makes use of the fact that +// hash maps are passed as a pointer to a runtime Hmap struct. A map is +// not seen by the runtime as a pointer though, so we use unsafe to get +// the maps' pointer values to compare. +func same(a, b Nodes) bool { + return *(*uintptr)(unsafe.Pointer(&a)) == *(*uintptr)(unsafe.Pointer(&b)) +} diff --git a/graph/internal/set/same_appengine.go b/graph/internal/set/same_appengine.go new file mode 100644 index 00000000..53780411 --- /dev/null +++ b/graph/internal/set/same_appengine.go @@ -0,0 +1,18 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build appengine + +package set + +import "reflect" + +// same determines whether two sets are backed by the same store. In the +// current implementation using hash maps it makes use of the fact that +// hash maps are passed as a pointer to a runtime Hmap struct. A map is +// not seen by the runtime as a pointer though, so we use reflect to get +// the maps' pointer values to compare. +func same(a, b Nodes) bool { + return reflect.ValueOf(a).Pointer() == reflect.ValueOf(b).Pointer() +} diff --git a/graph/internal/set/set.go b/graph/internal/set/set.go new file mode 100644 index 00000000..3166f14d --- /dev/null +++ b/graph/internal/set/set.go @@ -0,0 +1,190 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package set provides integer and graph.Node sets. +package set + +import "gonum.org/v1/gonum/graph" + +// Ints is a set of integer identifiers. +type Ints map[int]struct{} + +// The simple accessor methods for Ints are provided to allow ease of +// implementation change should the need arise. + +// Add inserts an element into the set. +func (s Ints) Add(e int) { + s[e] = struct{}{} +} + +// Has reports the existence of the element in the set. +func (s Ints) Has(e int) bool { + _, ok := s[e] + return ok +} + +// Remove deletes the specified element from the set. +func (s Ints) Remove(e int) { + delete(s, e) +} + +// Count reports the number of elements stored in the set. +func (s Ints) Count() int { + return len(s) +} + +// Nodes is a set of nodes keyed in their integer identifiers. +type Nodes map[int]graph.Node + +// The simple accessor methods for Nodes are provided to allow ease of +// implementation change should the need arise. + +// Add inserts an element into the set. +func (s Nodes) Add(n graph.Node) { + s[n.ID()] = n +} + +// Remove deletes the specified element from the set. +func (s Nodes) Remove(e graph.Node) { + delete(s, e.ID()) +} + +// Has reports the existence of the element in the set. +func (s Nodes) Has(n graph.Node) bool { + _, ok := s[n.ID()] + return ok +} + +// clear clears the set, possibly using the same backing store. +func (s *Nodes) clear() { + if len(*s) != 0 { + *s = make(Nodes) + } +} + +// Copy performs a perfect copy from src to dst (meaning the sets will +// be equal). +func (dst Nodes) Copy(src Nodes) Nodes { + if same(src, dst) { + return dst + } + + if len(dst) > 0 { + dst = make(Nodes, len(src)) + } + + for e, n := range src { + dst[e] = n + } + + return dst +} + +// Equal reports set equality between the parameters. Sets are equal if +// and only if they have the same elements. +func Equal(a, b Nodes) bool { + if same(a, b) { + return true + } + + if len(a) != len(b) { + return false + } + + for e := range a { + if _, ok := b[e]; !ok { + return false + } + } + + return true +} + +// Union takes the union of a and b, and stores it in dst. +// +// The union of two sets, a and b, is the set containing all the +// elements of each, for instance: +// +// {a,b,c} UNION {d,e,f} = {a,b,c,d,e,f} +// +// Since sets may not have repetition, unions of two sets that overlap +// do not contain repeat elements, that is: +// +// {a,b,c} UNION {b,c,d} = {a,b,c,d} +// +func (dst Nodes) Union(a, b Nodes) Nodes { + if same(a, b) { + return dst.Copy(a) + } + + if !same(a, dst) && !same(b, dst) { + dst.clear() + } + + if !same(dst, a) { + for e, n := range a { + dst[e] = n + } + } + + if !same(dst, b) { + for e, n := range b { + dst[e] = n + } + } + + return dst +} + +// Intersect takes the intersection of a and b, and stores it in dst. +// +// The intersection of two sets, a and b, is the set containing all +// the elements shared between the two sets, for instance: +// +// {a,b,c} INTERSECT {b,c,d} = {b,c} +// +// The intersection between a set and itself is itself, and thus +// effectively a copy operation: +// +// {a,b,c} INTERSECT {a,b,c} = {a,b,c} +// +// The intersection between two sets that share no elements is the empty +// set: +// +// {a,b,c} INTERSECT {d,e,f} = {} +// +func (dst Nodes) Intersect(a, b Nodes) Nodes { + var swap Nodes + + if same(a, b) { + return dst.Copy(a) + } + if same(a, dst) { + swap = b + } else if same(b, dst) { + swap = a + } else { + dst.clear() + + if len(a) > len(b) { + a, b = b, a + } + + for e, n := range a { + if _, ok := b[e]; ok { + dst[e] = n + } + } + + return dst + } + + for e := range dst { + if _, ok := swap[e]; !ok { + delete(dst, e) + } + } + + return dst +} diff --git a/graph/internal/set/set_test.go b/graph/internal/set/set_test.go new file mode 100644 index 00000000..bc8de46f --- /dev/null +++ b/graph/internal/set/set_test.go @@ -0,0 +1,413 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package set + +import "testing" + +type node int + +func (n node) ID() int { return int(n) } + +// count reports the number of elements stored in the node set. +func (s Nodes) count() int { + return len(s) +} + +// TestSame tests the assumption that pointer equality via unsafe conversion +// of a map[int]struct{} to uintptr is a valid test for perfect identity between +// set values. If any of the tests in TestSame fail, the package is broken and same +// must be reimplemented to conform to the runtime map implementation. The relevant +// code to look at (at least for gc) is in runtime/hashmap.{h,goc}. +func TestSame(t *testing.T) { + var ( + a = make(Nodes) + b = make(Nodes) + c = a + ) + + if same(a, b) { + t.Error("Independently created sets test as same") + } + if !same(a, c) { + t.Error("Set copy and original test as not same.") + } + a.Add(node(1)) + if !same(a, c) { + t.Error("Set copy and original test as not same after addition.") + } + if !same(nil, nil) { + t.Error("nil sets test as not same.") + } + if same(b, nil) { + t.Error("nil and empty sets test as same.") + } +} + +func TestAdd(t *testing.T) { + s := make(Nodes) + if s == nil { + t.Fatal("Set cannot be created successfully") + } + + if s.count() != 0 { + t.Error("Set somehow contains new elements upon creation") + } + + s.Add(node(1)) + s.Add(node(3)) + s.Add(node(5)) + + if s.count() != 3 { + t.Error("Incorrect number of set elements after adding") + } + + if !s.Has(node(1)) || !s.Has(node(3)) || !s.Has(node(5)) { + t.Error("Set doesn't contain element that was added") + } + + s.Add(node(1)) + + if s.count() > 3 { + t.Error("Set double-adds element (element not unique)") + } else if s.count() < 3 { + t.Error("Set double-add lowered len") + } + + if !s.Has(node(1)) { + t.Error("Set doesn't contain double-added element") + } + + if !s.Has(node(3)) || !s.Has(node(5)) { + t.Error("Set removes element on double-add") + } + + for e, n := range s { + if e != n.ID() { + t.Error("Element ID did not match key: %d != %d", e, n.ID()) + } + } +} + +func TestRemove(t *testing.T) { + s := make(Nodes) + + s.Add(node(1)) + s.Add(node(3)) + s.Add(node(5)) + + s.Remove(node(1)) + + if s.count() != 2 { + t.Error("Incorrect number of set elements after removing an element") + } + + if s.Has(node(1)) { + t.Error("Element present after removal") + } + + if !s.Has(node(3)) || !s.Has(node(5)) { + t.Error("Set remove removed wrong element") + } + + s.Remove(node(1)) + + if s.count() != 2 || s.Has(node(1)) { + t.Error("Double set remove does something strange") + } + + s.Add(node(1)) + + if s.count() != 3 || !s.Has(node(1)) { + t.Error("Cannot add element after removal") + } +} + +func TestClear(t *testing.T) { + s := make(Nodes) + + s.Add(node(8)) + s.Add(node(9)) + s.Add(node(10)) + + s.clear() + + if s.count() != 0 { + t.Error("clear did not properly reset set to size 0") + } +} + +func TestSelfEqual(t *testing.T) { + s := make(Nodes) + + if !Equal(s, s) { + t.Error("Set is not equal to itself") + } + + s.Add(node(1)) + + if !Equal(s, s) { + t.Error("Set ceases self equality after adding element") + } +} + +func TestEqual(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + + if !Equal(a, b) { + t.Error("Two different empty sets not equal") + } + + a.Add(node(1)) + if Equal(a, b) { + t.Error("Two different sets with different elements not equal") + } + + b.Add(node(1)) + if !Equal(a, b) { + t.Error("Two sets with same element not equal") + } +} + +func TestCopy(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + a.Add(node(3)) + + b.Copy(a) + + if !Equal(a, b) { + t.Fatalf("Two sets not equal after copy") + } + + b.Remove(node(1)) + + if Equal(a, b) { + t.Errorf("Mutating one set mutated another after copy") + } +} + +func TestSelfCopy(t *testing.T) { + a := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + + a.Copy(a) + + if a.count() != 2 { + t.Error("Something strange happened when copying into self") + } +} + +func TestUnionSame(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + + b.Add(node(1)) + b.Add(node(2)) + + c.Union(a, b) + + if c.count() != 2 { + t.Error("Union of same sets yields set with wrong len") + } + + if !c.Has(node(1)) || !c.Has(node(2)) { + t.Error("Union of same sets yields wrong elements") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Error("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestUnionDiff(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + + b.Add(node(3)) + + c.Union(a, b) + + if c.count() != 3 { + t.Error("Union of different sets yields set with wrong len") + } + + if !c.Has(node(1)) || !c.Has(node(2)) || !c.Has(node(3)) { + t.Error("Union of different sets yields set with wrong elements") + } + + if a.Has(node(3)) || !a.Has(node(2)) || !a.Has(node(1)) || a.count() != 2 { + t.Error("Union of sets mutates non-destination set (argument 1)") + } + + if !b.Has(node(3)) || b.Has(node(1)) || b.Has(node(2)) || b.count() != 1 { + t.Error("Union of sets mutates non-destination set (argument 2)") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Error("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestUnionOverlapping(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(1)) + a.Add(node(2)) + + b.Add(node(2)) + b.Add(node(3)) + + c.Union(a, b) + + if c.count() != 3 { + t.Error("Union of overlapping sets yields set with wrong len") + } + + if !c.Has(node(1)) || !c.Has(node(2)) || !c.Has(node(3)) { + t.Error("Union of overlapping sets yields set with wrong elements") + } + + if a.Has(node(3)) || !a.Has(node(2)) || !a.Has(node(1)) || a.count() != 2 { + t.Error("Union of sets mutates non-destination set (argument 1)") + } + + if !b.Has(node(3)) || b.Has(node(1)) || !b.Has(node(2)) || b.count() != 2 { + t.Error("Union of sets mutates non-destination set (argument 2)") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Error("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestIntersectSame(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(2)) + a.Add(node(3)) + + b.Add(node(2)) + b.Add(node(3)) + + c.Intersect(a, b) + + if card := c.count(); card != 2 { + t.Errorf("Intersection of identical sets yields set of wrong len %d", card) + } + + if !c.Has(node(2)) || !c.Has(node(3)) { + t.Error("Intersection of identical sets yields set of wrong elements") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Error("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestIntersectDiff(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(2)) + a.Add(node(3)) + + b.Add(node(1)) + b.Add(node(4)) + + c.Intersect(a, b) + + if card := c.count(); card != 0 { + t.Errorf("Intersection of different yields non-empty set %d", card) + } + + if !a.Has(node(2)) || !a.Has(node(3)) || a.Has(node(1)) || a.Has(node(4)) || a.count() != 2 { + t.Error("Intersection of sets mutates non-destination set (argument 1)") + } + + if b.Has(node(2)) || b.Has(node(3)) || !b.Has(node(1)) || !b.Has(node(4)) || b.count() != 2 { + t.Error("Intersection of sets mutates non-destination set (argument 1)") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Error("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} + +func TestIntersectOverlapping(t *testing.T) { + a := make(Nodes) + b := make(Nodes) + c := make(Nodes) + + a.Add(node(2)) + a.Add(node(3)) + + b.Add(node(3)) + b.Add(node(4)) + + c.Intersect(a, b) + + if card := c.count(); card != 1 { + t.Errorf("Intersection of overlapping sets yields set of incorrect len %d", card) + } + + if !c.Has(node(3)) { + t.Errorf("Intersection of overlapping sets yields set with wrong element") + } + + if !a.Has(node(2)) || !a.Has(node(3)) || a.Has(node(4)) || a.count() != 2 { + t.Error("Intersection of sets mutates non-destination set (argument 1)") + } + + if b.Has(node(2)) || !b.Has(node(3)) || !b.Has(node(4)) || b.count() != 2 { + t.Error("Intersection of sets mutates non-destination set (argument 1)") + } + + for i, s := range []Nodes{a, b, c} { + for e, n := range s { + if e != n.ID() { + t.Error("Element ID did not match key in s%d: %d != %d", i+1, e, n.ID()) + } + } + } +} diff --git a/graph/network/betweenness.go b/graph/network/betweenness.go new file mode 100644 index 00000000..31f42950 --- /dev/null +++ b/graph/network/betweenness.go @@ -0,0 +1,256 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package network + +import ( + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/linear" + "gonum.org/v1/gonum/graph/path" +) + +// Betweenness returns the non-zero betweenness centrality for nodes in the unweighted graph g. +// +// C_B(v) = \sum_{s ≠ v ≠ t ∈ V} (\sigma_{st}(v) / \sigma_{st}) +// +// where \sigma_{st} and \sigma_{st}(v) are the number of shortest paths from s to t, +// and the subset of those paths containing v respectively. +func Betweenness(g graph.Graph) map[int]float64 { + // Brandes' algorithm for finding betweenness centrality for nodes in + // and unweighted graph: + // + // http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf + + // TODO(kortschak): Consider using the parallel algorithm when + // GOMAXPROCS != 1. + // + // http://htor.inf.ethz.ch/publications/img/edmonds-hoefler-lumsdaine-bc.pdf + + // Also note special case for sparse networks: + // http://wwwold.iit.cnr.it/staff/marco.pellegrini/papiri/asonam-final.pdf + + cb := make(map[int]float64) + brandes(g, func(s graph.Node, stack linear.NodeStack, p map[int][]graph.Node, delta, sigma map[int]float64) { + for stack.Len() != 0 { + w := stack.Pop() + for _, v := range p[w.ID()] { + delta[v.ID()] += sigma[v.ID()] / sigma[w.ID()] * (1 + delta[w.ID()]) + } + if w.ID() != s.ID() { + if d := delta[w.ID()]; d != 0 { + cb[w.ID()] += d + } + } + } + }) + return cb +} + +// EdgeBetweenness returns the non-zero betweenness centrality for edges in the +// unweighted graph g. For an edge e the centrality C_B is computed as +// +// C_B(e) = \sum_{s ≠ t ∈ V} (\sigma_{st}(e) / \sigma_{st}), +// +// where \sigma_{st} and \sigma_{st}(e) are the number of shortest paths from s +// to t, and the subset of those paths containing e, respectively. +// +// If g is undirected, edges are retained such that u.ID < v.ID where u and v are +// the nodes of e. +func EdgeBetweenness(g graph.Graph) map[[2]int]float64 { + // Modified from Brandes' original algorithm as described in Algorithm 7 + // with the exception that node betweenness is not calculated: + // + // http://algo.uni-konstanz.de/publications/b-vspbc-08.pdf + + _, isUndirected := g.(graph.Undirected) + cb := make(map[[2]int]float64) + brandes(g, func(s graph.Node, stack linear.NodeStack, p map[int][]graph.Node, delta, sigma map[int]float64) { + for stack.Len() != 0 { + w := stack.Pop() + for _, v := range p[w.ID()] { + c := sigma[v.ID()] / sigma[w.ID()] * (1 + delta[w.ID()]) + vid := v.ID() + wid := w.ID() + if isUndirected && wid < vid { + vid, wid = wid, vid + } + cb[[2]int{vid, wid}] += c + delta[v.ID()] += c + } + } + }) + return cb +} + +// brandes is the common code for Betweenness and EdgeBetweenness. It corresponds +// to algorithm 1 in http://algo.uni-konstanz.de/publications/b-vspbc-08.pdf with +// the accumulation loop provided by the accumulate closure. +func brandes(g graph.Graph, accumulate func(s graph.Node, stack linear.NodeStack, p map[int][]graph.Node, delta, sigma map[int]float64)) { + var ( + nodes = g.Nodes() + stack linear.NodeStack + p = make(map[int][]graph.Node, len(nodes)) + sigma = make(map[int]float64, len(nodes)) + d = make(map[int]int, len(nodes)) + delta = make(map[int]float64, len(nodes)) + queue linear.NodeQueue + ) + for _, s := range nodes { + stack = stack[:0] + + for _, w := range nodes { + p[w.ID()] = p[w.ID()][:0] + } + + for _, t := range nodes { + sigma[t.ID()] = 0 + d[t.ID()] = -1 + } + sigma[s.ID()] = 1 + d[s.ID()] = 0 + + queue.Enqueue(s) + for queue.Len() != 0 { + v := queue.Dequeue() + stack.Push(v) + for _, w := range g.From(v) { + // w found for the first time? + if d[w.ID()] < 0 { + queue.Enqueue(w) + d[w.ID()] = d[v.ID()] + 1 + } + // shortest path to w via v? + if d[w.ID()] == d[v.ID()]+1 { + sigma[w.ID()] += sigma[v.ID()] + p[w.ID()] = append(p[w.ID()], v) + } + } + } + + for _, v := range nodes { + delta[v.ID()] = 0 + } + + // S returns vertices in order of non-increasing distance from s + accumulate(s, stack, p, delta, sigma) + } +} + +// WeightedGraph is a graph with edge weights. +type WeightedGraph interface { + graph.Graph + graph.Weighter +} + +// BetweennessWeighted returns the non-zero betweenness centrality for nodes in the weighted +// graph g used to construct the given shortest paths. +// +// C_B(v) = \sum_{s ≠ v ≠ t ∈ V} (\sigma_{st}(v) / \sigma_{st}) +// +// where \sigma_{st} and \sigma_{st}(v) are the number of shortest paths from s to t, +// and the subset of those paths containing v respectively. +func BetweennessWeighted(g WeightedGraph, p path.AllShortest) map[int]float64 { + cb := make(map[int]float64) + + nodes := g.Nodes() + for i, s := range nodes { + for j, t := range nodes { + if i == j { + continue + } + d := p.Weight(s, t) + if math.IsInf(d, 0) { + continue + } + + // If we have a unique path, don't do the + // extra work needed to get all paths. + path, _, unique := p.Between(s, t) + if unique { + for _, v := range path[1 : len(path)-1] { + // For undirected graphs we double count + // passage though nodes. This is consistent + // with Brandes' algorithm's behaviour. + cb[v.ID()]++ + } + continue + } + + // Otherwise iterate over all paths. + paths, _ := p.AllBetween(s, t) + stFrac := 1 / float64(len(paths)) + for _, path := range paths { + for _, v := range path[1 : len(path)-1] { + cb[v.ID()] += stFrac + } + } + } + } + + return cb +} + +// EdgeBetweennessWeighted returns the non-zero betweenness centrality for edges in +// the weighted graph g. For an edge e the centrality C_B is computed as +// +// C_B(e) = \sum_{s ≠ t ∈ V} (\sigma_{st}(e) / \sigma_{st}), +// +// where \sigma_{st} and \sigma_{st}(e) are the number of shortest paths from s +// to t, and the subset of those paths containing e, respectively. +// +// If g is undirected, edges are retained such that u.ID < v.ID where u and v are +// the nodes of e. +func EdgeBetweennessWeighted(g WeightedGraph, p path.AllShortest) map[[2]int]float64 { + cb := make(map[[2]int]float64) + + _, isUndirected := g.(graph.Undirected) + nodes := g.Nodes() + for i, s := range nodes { + for j, t := range nodes { + if i == j { + continue + } + d := p.Weight(s, t) + if math.IsInf(d, 0) { + continue + } + + // If we have a unique path, don't do the + // extra work needed to get all paths. + path, _, unique := p.Between(s, t) + if unique { + for k, v := range path[1:] { + // For undirected graphs we double count + // passage though edges. This is consistent + // with Brandes' algorithm's behaviour. + uid := path[k].ID() + vid := v.ID() + if isUndirected && vid < uid { + uid, vid = vid, uid + } + cb[[2]int{uid, vid}]++ + } + continue + } + + // Otherwise iterate over all paths. + paths, _ := p.AllBetween(s, t) + stFrac := 1 / float64(len(paths)) + for _, path := range paths { + for k, v := range path[1:] { + uid := path[k].ID() + vid := v.ID() + if isUndirected && vid < uid { + uid, vid = vid, uid + } + cb[[2]int{uid, vid}] += stFrac + } + } + } + } + + return cb +} diff --git a/graph/network/betweenness_test.go b/graph/network/betweenness_test.go new file mode 100644 index 00000000..c34cb3bc --- /dev/null +++ b/graph/network/betweenness_test.go @@ -0,0 +1,340 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package network + +import ( + "fmt" + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph/path" + "gonum.org/v1/gonum/graph/simple" +) + +var betweennessTests = []struct { + g []set + + wantTol float64 + want map[int]float64 + wantEdges map[[2]int]float64 +}{ + { + // Example graph from http://en.wikipedia.org/wiki/File:PageRanks-Example.svg 16:17, 8 July 2009 + g: []set{ + A: nil, + B: linksTo(C), + C: linksTo(B), + D: linksTo(A, B), + E: linksTo(D, B, F), + F: linksTo(B, E), + G: linksTo(B, E), + H: linksTo(B, E), + I: linksTo(B, E), + J: linksTo(E), + K: linksTo(E), + }, + + wantTol: 1e-1, + want: map[int]float64{ + B: 32, + D: 18, + E: 48, + }, + wantEdges: map[[2]int]float64{ + [2]int{A, D}: 20, + [2]int{B, C}: 20, + [2]int{B, D}: 16, + [2]int{B, E}: 12, + [2]int{B, F}: 9, + [2]int{B, G}: 9, + [2]int{B, H}: 9, + [2]int{B, I}: 9, + [2]int{D, E}: 20, + [2]int{E, F}: 11, + [2]int{E, G}: 11, + [2]int{E, H}: 11, + [2]int{E, I}: 11, + [2]int{E, J}: 20, + [2]int{E, K}: 20, + }, + }, + { + // Example graph from http://en.wikipedia.org/w/index.php?title=PageRank&oldid=659286279#Power_Method + g: []set{ + A: linksTo(B, C), + B: linksTo(D), + C: linksTo(D, E), + D: linksTo(E), + E: linksTo(A), + }, + + wantTol: 1e-3, + want: map[int]float64{ + A: 2, + B: 0.6667, + C: 0.6667, + D: 2, + E: 0.6667, + }, + wantEdges: map[[2]int]float64{ + [2]int{A, B}: 2 + 2/3. + 4/2., + [2]int{A, C}: 2 + 2/3. + 2/2., + [2]int{A, E}: 2 + 2/3. + 2/2., + [2]int{B, D}: 2 + 2/3. + 4/2., + [2]int{C, D}: 2 + 2/3. + 2/2., + [2]int{C, E}: 2, + [2]int{D, E}: 2 + 2/3. + 2/2., + }, + }, + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: nil, + }, + + wantTol: 1e-3, + want: map[int]float64{ + B: 2, + }, + wantEdges: map[[2]int]float64{ + [2]int{A, B}: 4, + [2]int{B, C}: 4, + }, + }, + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: linksTo(D), + D: linksTo(E), + E: nil, + }, + + wantTol: 1e-3, + want: map[int]float64{ + B: 6, + C: 8, + D: 6, + }, + wantEdges: map[[2]int]float64{ + [2]int{A, B}: 8, + [2]int{B, C}: 12, + [2]int{C, D}: 12, + [2]int{D, E}: 8, + }, + }, + { + g: []set{ + A: linksTo(C), + B: linksTo(C), + C: nil, + D: linksTo(C), + E: linksTo(C), + }, + + wantTol: 1e-3, + want: map[int]float64{ + C: 12, + }, + wantEdges: map[[2]int]float64{ + [2]int{A, C}: 8, + [2]int{B, C}: 8, + [2]int{C, D}: 8, + [2]int{C, E}: 8, + }, + }, + { + g: []set{ + A: linksTo(B, C, D, E), + B: linksTo(C, D, E), + C: linksTo(D, E), + D: linksTo(E), + E: nil, + }, + + wantTol: 1e-3, + want: map[int]float64{}, + wantEdges: map[[2]int]float64{ + [2]int{A, B}: 2, + [2]int{A, C}: 2, + [2]int{A, D}: 2, + [2]int{A, E}: 2, + [2]int{B, C}: 2, + [2]int{B, D}: 2, + [2]int{B, E}: 2, + [2]int{C, D}: 2, + [2]int{C, E}: 2, + [2]int{D, E}: 2, + }, + }, +} + +func TestBetweenness(t *testing.T) { + for i, test := range betweennessTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + // Weight omitted to show weight-independence. + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 0}) + } + } + got := Betweenness(g) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + wantN, gotOK := got[n] + gotN, wantOK := test.want[n] + if gotOK != wantOK { + t.Errorf("unexpected betweenness result for test %d, node %c", i, n+'A') + } + if !floats.EqualWithinAbsOrRel(gotN, wantN, test.wantTol, test.wantTol) { + t.Errorf("unexpected betweenness result for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.want, prec)) + break + } + } + } +} + +func TestEdgeBetweenness(t *testing.T) { + for i, test := range betweennessTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + // Weight omitted to show weight-independence. + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 0}) + } + } + got := EdgeBetweenness(g) + prec := 1 - int(math.Log10(test.wantTol)) + outer: + for u := range test.g { + for v := range test.g { + wantQ, gotOK := got[[2]int{u, v}] + gotQ, wantOK := test.wantEdges[[2]int{u, v}] + if gotOK != wantOK { + t.Errorf("unexpected betweenness result for test %d, edge (%c,%c)", i, u+'A', v+'A') + } + if !floats.EqualWithinAbsOrRel(gotQ, wantQ, test.wantTol, test.wantTol) { + t.Errorf("unexpected betweenness result for test %d:\ngot: %v\nwant:%v", + i, orderedPairFloats(got, prec), orderedPairFloats(test.wantEdges, prec)) + break outer + } + } + } + } +} + +func TestBetweennessWeighted(t *testing.T) { + for i, test := range betweennessTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + p, ok := path.FloydWarshall(g) + if !ok { + t.Errorf("unexpected negative cycle in test %d", i) + continue + } + + got := BetweennessWeighted(g, p) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + gotN, gotOK := got[n] + wantN, wantOK := test.want[n] + if gotOK != wantOK { + t.Errorf("unexpected betweenness existence for test %d, node %c", i, n+'A') + } + if !floats.EqualWithinAbsOrRel(gotN, wantN, test.wantTol, test.wantTol) { + t.Errorf("unexpected betweenness result for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.want, prec)) + break + } + } + } +} + +func TestEdgeBetweennessWeighted(t *testing.T) { + for i, test := range betweennessTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + + p, ok := path.FloydWarshall(g) + if !ok { + t.Errorf("unexpected negative cycle in test %d", i) + continue + } + + got := EdgeBetweennessWeighted(g, p) + prec := 1 - int(math.Log10(test.wantTol)) + outer: + for u := range test.g { + for v := range test.g { + wantQ, gotOK := got[[2]int{u, v}] + gotQ, wantOK := test.wantEdges[[2]int{u, v}] + if gotOK != wantOK { + t.Errorf("unexpected betweenness result for test %d, edge (%c,%c)", i, u+'A', v+'A') + } + if !floats.EqualWithinAbsOrRel(gotQ, wantQ, test.wantTol, test.wantTol) { + t.Errorf("unexpected betweenness result for test %d:\ngot: %v\nwant:%v", + i, orderedPairFloats(got, prec), orderedPairFloats(test.wantEdges, prec)) + break outer + } + } + } + } +} + +func orderedPairFloats(w map[[2]int]float64, prec int) []pairKeyFloatVal { + o := make(orderedPairFloatsMap, 0, len(w)) + for k, v := range w { + o = append(o, pairKeyFloatVal{prec: prec, key: k, val: v}) + } + sort.Sort(o) + return o +} + +type pairKeyFloatVal struct { + prec int + key [2]int + val float64 +} + +func (kv pairKeyFloatVal) String() string { + return fmt.Sprintf("(%c,%c):%.*f", kv.key[0]+'A', kv.key[1]+'A', kv.prec, kv.val) +} + +type orderedPairFloatsMap []pairKeyFloatVal + +func (o orderedPairFloatsMap) Len() int { return len(o) } +func (o orderedPairFloatsMap) Less(i, j int) bool { + return o[i].key[0] < o[j].key[0] || (o[i].key[0] == o[j].key[0] && o[i].key[1] < o[j].key[1]) +} +func (o orderedPairFloatsMap) Swap(i, j int) { o[i], o[j] = o[j], o[i] } diff --git a/graph/network/distance.go b/graph/network/distance.go new file mode 100644 index 00000000..ad8f54da --- /dev/null +++ b/graph/network/distance.go @@ -0,0 +1,124 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package network + +import ( + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path" +) + +// Closeness returns the closeness centrality for nodes in the graph g used to +// construct the given shortest paths. +// +// C(v) = 1 / \sum_u d(u,v) +// +// For directed graphs the incoming paths are used. Infinite distances are +// not considered. +func Closeness(g graph.Graph, p path.AllShortest) map[int]float64 { + nodes := g.Nodes() + c := make(map[int]float64, len(nodes)) + for _, u := range nodes { + var sum float64 + for _, v := range nodes { + // The ordering here is not relevant for + // undirected graphs, but we make sure we + // are counting incoming paths. + d := p.Weight(v, u) + if math.IsInf(d, 0) { + continue + } + sum += d + } + c[u.ID()] = 1 / sum + } + return c +} + +// Farness returns the farness for nodes in the graph g used to construct +// the given shortest paths. +// +// F(v) = \sum_u d(u,v) +// +// For directed graphs the incoming paths are used. Infinite distances are +// not considered. +func Farness(g graph.Graph, p path.AllShortest) map[int]float64 { + nodes := g.Nodes() + f := make(map[int]float64, len(nodes)) + for _, u := range nodes { + var sum float64 + for _, v := range nodes { + // The ordering here is not relevant for + // undirected graphs, but we make sure we + // are counting incoming paths. + d := p.Weight(v, u) + if math.IsInf(d, 0) { + continue + } + sum += d + } + f[u.ID()] = sum + } + return f +} + +// Harmonic returns the harmonic centrality for nodes in the graph g used to +// construct the given shortest paths. +// +// H(v)= \sum_{u ≠ v} 1 / d(u,v) +// +// For directed graphs the incoming paths are used. Infinite distances are +// not considered. +func Harmonic(g graph.Graph, p path.AllShortest) map[int]float64 { + nodes := g.Nodes() + h := make(map[int]float64, len(nodes)) + for i, u := range nodes { + var sum float64 + for j, v := range nodes { + // The ordering here is not relevant for + // undirected graphs, but we make sure we + // are counting incoming paths. + d := p.Weight(v, u) + if math.IsInf(d, 0) { + continue + } + if i != j { + sum += 1 / d + } + } + h[u.ID()] = sum + } + return h +} + +// Residual returns the Dangalchev's residual closeness for nodes in the graph +// g used to construct the given shortest paths. +// +// C(v)= \sum_{u ≠ v} 1 / 2^d(u,v) +// +// For directed graphs the incoming paths are used. Infinite distances are +// not considered. +func Residual(g graph.Graph, p path.AllShortest) map[int]float64 { + nodes := g.Nodes() + r := make(map[int]float64, len(nodes)) + for i, u := range nodes { + var sum float64 + for j, v := range nodes { + // The ordering here is not relevant for + // undirected graphs, but we make sure we + // are counting incoming paths. + d := p.Weight(v, u) + if math.IsInf(d, 0) { + continue + } + if i != j { + sum += math.Exp2(-d) + } + } + r[u.ID()] = sum + } + return r +} diff --git a/graph/network/distance_test.go b/graph/network/distance_test.go new file mode 100644 index 00000000..6eafb855 --- /dev/null +++ b/graph/network/distance_test.go @@ -0,0 +1,394 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package network + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph/path" + "gonum.org/v1/gonum/graph/simple" +) + +var undirectedCentralityTests = []struct { + g []set + + farness map[int]float64 + harmonic map[int]float64 + residual map[int]float64 +}{ + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: nil, + }, + + farness: map[int]float64{ + A: 1 + 2, + B: 1 + 1, + C: 2 + 1, + }, + harmonic: map[int]float64{ + A: 1 + 1.0/2.0, + B: 1 + 1, + C: 1.0/2.0 + 1, + }, + residual: map[int]float64{ + A: 1/math.Exp2(1) + 1/math.Exp2(2), + B: 1/math.Exp2(1) + 1/math.Exp2(1), + C: 1/math.Exp2(2) + 1/math.Exp2(1), + }, + }, + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: linksTo(D), + D: linksTo(E), + E: nil, + }, + + farness: map[int]float64{ + A: 1 + 2 + 3 + 4, + B: 1 + 1 + 2 + 3, + C: 2 + 1 + 1 + 2, + D: 3 + 2 + 1 + 1, + E: 4 + 3 + 2 + 1, + }, + harmonic: map[int]float64{ + A: 1 + 1.0/2.0 + 1.0/3.0 + 1.0/4.0, + B: 1 + 1 + 1.0/2.0 + 1.0/3.0, + C: 1.0/2.0 + 1 + 1 + 1.0/2.0, + D: 1.0/3.0 + 1.0/2.0 + 1 + 1, + E: 1.0/4.0 + 1.0/3.0 + 1.0/2.0 + 1, + }, + residual: map[int]float64{ + A: 1/math.Exp2(1) + 1/math.Exp2(2) + 1/math.Exp2(3) + 1/math.Exp2(4), + B: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(2) + 1/math.Exp2(3), + C: 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(2), + D: 1/math.Exp2(3) + 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(1), + E: 1/math.Exp2(4) + 1/math.Exp2(3) + 1/math.Exp2(2) + 1/math.Exp2(1), + }, + }, + { + g: []set{ + A: linksTo(C), + B: linksTo(C), + C: nil, + D: linksTo(C), + E: linksTo(C), + }, + + farness: map[int]float64{ + A: 2 + 2 + 1 + 2, + B: 2 + 1 + 2 + 2, + C: 1 + 1 + 1 + 1, + D: 2 + 1 + 2 + 2, + E: 2 + 2 + 1 + 2, + }, + harmonic: map[int]float64{ + A: 1.0/2.0 + 1.0/2.0 + 1 + 1.0/2.0, + B: 1.0/2.0 + 1 + 1.0/2.0 + 1.0/2.0, + C: 1 + 1 + 1 + 1, + D: 1.0/2.0 + 1 + 1.0/2.0 + 1.0/2.0, + E: 1.0/2.0 + 1.0/2.0 + 1 + 1.0/2.0, + }, + residual: map[int]float64{ + A: 1/math.Exp2(2) + 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(2), + B: 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(2) + 1/math.Exp2(2), + C: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + D: 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(2) + 1/math.Exp2(2), + E: 1/math.Exp2(2) + 1/math.Exp2(2) + 1/math.Exp2(1) + 1/math.Exp2(2), + }, + }, + { + g: []set{ + A: linksTo(B, C, D, E), + B: linksTo(C, D, E), + C: linksTo(D, E), + D: linksTo(E), + E: nil, + }, + + farness: map[int]float64{ + A: 1 + 1 + 1 + 1, + B: 1 + 1 + 1 + 1, + C: 1 + 1 + 1 + 1, + D: 1 + 1 + 1 + 1, + E: 1 + 1 + 1 + 1, + }, + harmonic: map[int]float64{ + A: 1 + 1 + 1 + 1, + B: 1 + 1 + 1 + 1, + C: 1 + 1 + 1 + 1, + D: 1 + 1 + 1 + 1, + E: 1 + 1 + 1 + 1, + }, + residual: map[int]float64{ + A: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + B: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + C: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + D: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + E: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + }, + }, +} + +func TestDistanceCentralityUndirected(t *testing.T) { + const tol = 1e-12 + prec := 1 - int(math.Log10(tol)) + + for i, test := range undirectedCentralityTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + p, ok := path.FloydWarshall(g) + if !ok { + t.Errorf("unexpected negative cycle in test %d", i) + continue + } + + var got map[int]float64 + + got = Closeness(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], 1/test.farness[n], tol, tol) { + want := make(map[int]float64) + for n, v := range test.farness { + want[n] = 1 / v + } + t.Errorf("unexpected closeness centrality for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(want, prec)) + break + } + } + + got = Farness(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], test.farness[n], tol, tol) { + t.Errorf("unexpected farness for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.farness, prec)) + break + } + } + + got = Harmonic(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], test.harmonic[n], tol, tol) { + t.Errorf("unexpected harmonic centrality for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.harmonic, prec)) + break + } + } + + got = Residual(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], test.residual[n], tol, tol) { + t.Errorf("unexpected residual closeness for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.residual, prec)) + break + } + } + } +} + +var directedCentralityTests = []struct { + g []set + + farness map[int]float64 + harmonic map[int]float64 + residual map[int]float64 +}{ + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: nil, + }, + + farness: map[int]float64{ + A: 0, + B: 1, + C: 2 + 1, + }, + harmonic: map[int]float64{ + A: 0, + B: 1, + C: 1.0/2.0 + 1, + }, + residual: map[int]float64{ + A: 0, + B: 1 / math.Exp2(1), + C: 1/math.Exp2(2) + 1/math.Exp2(1), + }, + }, + { + g: []set{ + A: linksTo(B), + B: linksTo(C), + C: linksTo(D), + D: linksTo(E), + E: nil, + }, + + farness: map[int]float64{ + A: 0, + B: 1, + C: 2 + 1, + D: 3 + 2 + 1, + E: 4 + 3 + 2 + 1, + }, + harmonic: map[int]float64{ + A: 0, + B: 1, + C: 1.0/2.0 + 1, + D: 1.0/3.0 + 1.0/2.0 + 1, + E: 1.0/4.0 + 1.0/3.0 + 1.0/2.0 + 1, + }, + residual: map[int]float64{ + A: 0, + B: 1 / math.Exp2(1), + C: 1/math.Exp2(2) + 1/math.Exp2(1), + D: 1/math.Exp2(3) + 1/math.Exp2(2) + 1/math.Exp2(1), + E: 1/math.Exp2(4) + 1/math.Exp2(3) + 1/math.Exp2(2) + 1/math.Exp2(1), + }, + }, + { + g: []set{ + A: linksTo(C), + B: linksTo(C), + C: nil, + D: linksTo(C), + E: linksTo(C), + }, + + farness: map[int]float64{ + A: 0, + B: 0, + C: 1 + 1 + 1 + 1, + D: 0, + E: 0, + }, + harmonic: map[int]float64{ + A: 0, + B: 0, + C: 1 + 1 + 1 + 1, + D: 0, + E: 0, + }, + residual: map[int]float64{ + A: 0, + B: 0, + C: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + D: 0, + E: 0, + }, + }, + { + g: []set{ + A: linksTo(B, C, D, E), + B: linksTo(C, D, E), + C: linksTo(D, E), + D: linksTo(E), + E: nil, + }, + + farness: map[int]float64{ + A: 0, + B: 1, + C: 1 + 1, + D: 1 + 1 + 1, + E: 1 + 1 + 1 + 1, + }, + harmonic: map[int]float64{ + A: 0, + B: 1, + C: 1 + 1, + D: 1 + 1 + 1, + E: 1 + 1 + 1 + 1, + }, + residual: map[int]float64{ + A: 0, + B: 1 / math.Exp2(1), + C: 1/math.Exp2(1) + 1/math.Exp2(1), + D: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + E: 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1) + 1/math.Exp2(1), + }, + }, +} + +func TestDistanceCentralityDirected(t *testing.T) { + const tol = 1e-12 + prec := 1 - int(math.Log10(tol)) + + for i, test := range directedCentralityTests { + g := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v), W: 1}) + } + } + p, ok := path.FloydWarshall(g) + if !ok { + t.Errorf("unexpected negative cycle in test %d", i) + continue + } + + var got map[int]float64 + + got = Closeness(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], 1/test.farness[n], tol, tol) { + want := make(map[int]float64) + for n, v := range test.farness { + want[n] = 1 / v + } + t.Errorf("unexpected closeness centrality for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(want, prec)) + break + } + } + + got = Farness(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], test.farness[n], tol, tol) { + t.Errorf("unexpected farness for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.farness, prec)) + break + } + } + + got = Harmonic(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], test.harmonic[n], tol, tol) { + t.Errorf("unexpected harmonic centrality for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.harmonic, prec)) + break + } + } + + got = Residual(g, p) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], test.residual[n], tol, tol) { + t.Errorf("unexpected residual closeness for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.residual, prec)) + break + } + } + } +} diff --git a/graph/network/hits.go b/graph/network/hits.go new file mode 100644 index 00000000..32f90418 --- /dev/null +++ b/graph/network/hits.go @@ -0,0 +1,101 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package network + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" +) + +// HubAuthority is a Hyperlink-Induced Topic Search hub-authority score pair. +type HubAuthority struct { + Hub float64 + Authority float64 +} + +// HITS returns the Hyperlink-Induced Topic Search hub-authority scores for +// nodes of the directed graph g. HITS terminates when the 2-norm of the +// vector difference between iterations is below tol. The returned map is +// keyed on the graph node IDs. +func HITS(g graph.Directed, tol float64) map[int]HubAuthority { + nodes := g.Nodes() + + // Make a topological copy of g with dense node IDs. + indexOf := make(map[int]int, len(nodes)) + for i, n := range nodes { + indexOf[n.ID()] = i + } + nodesLinkingTo := make([][]int, len(nodes)) + nodesLinkedFrom := make([][]int, len(nodes)) + for i, n := range nodes { + for _, u := range g.To(n) { + nodesLinkingTo[i] = append(nodesLinkingTo[i], indexOf[u.ID()]) + } + for _, v := range g.From(n) { + nodesLinkedFrom[i] = append(nodesLinkedFrom[i], indexOf[v.ID()]) + } + } + indexOf = nil + + w := make([]float64, 4*len(nodes)) + auth := w[:len(nodes)] + hub := w[len(nodes) : 2*len(nodes)] + for i := range nodes { + auth[i] = 1 + hub[i] = 1 + } + deltaAuth := w[2*len(nodes) : 3*len(nodes)] + deltaHub := w[3*len(nodes):] + + var norm float64 + for { + norm = 0 + for v := range nodes { + var a float64 + for _, u := range nodesLinkingTo[v] { + a += hub[u] + } + deltaAuth[v] = auth[v] + auth[v] = a + norm += a * a + } + norm = math.Sqrt(norm) + + for i := range auth { + auth[i] /= norm + deltaAuth[i] -= auth[i] + } + + norm = 0 + for u := range nodes { + var h float64 + for _, v := range nodesLinkedFrom[u] { + h += auth[v] + } + deltaHub[u] = hub[u] + hub[u] = h + norm += h * h + } + norm = math.Sqrt(norm) + + for i := range hub { + hub[i] /= norm + deltaHub[i] -= hub[i] + } + + if floats.Norm(deltaAuth, 2) < tol && floats.Norm(deltaHub, 2) < tol { + break + } + } + + hubAuth := make(map[int]HubAuthority, len(nodes)) + for i, n := range nodes { + hubAuth[n.ID()] = HubAuthority{Hub: hub[i], Authority: auth[i]} + } + + return hubAuth +} diff --git a/graph/network/hits_test.go b/graph/network/hits_test.go new file mode 100644 index 00000000..ac6b5102 --- /dev/null +++ b/graph/network/hits_test.go @@ -0,0 +1,98 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package network + +import ( + "fmt" + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph/simple" +) + +var hitsTests = []struct { + g []set + tol float64 + + wantTol float64 + want map[int]HubAuthority +}{ + { + // Example graph from http://www.cis.hut.fi/Opinnot/T-61.6020/2008/pagerank_hits.pdf page 8. + g: []set{ + A: linksTo(B, C, D), + B: linksTo(C, D), + C: linksTo(B), + D: nil, + }, + tol: 1e-4, + + wantTol: 1e-4, + want: map[int]HubAuthority{ + A: {Hub: 0.7887, Authority: 0}, + B: {Hub: 0.5774, Authority: 0.4597}, + C: {Hub: 0.2113, Authority: 0.6280}, + D: {Hub: 0, Authority: 0.6280}, + }, + }, +} + +func TestHITS(t *testing.T) { + for i, test := range hitsTests { + g := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got := HITS(g, test.tol) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n].Hub, test.want[n].Hub, test.wantTol, test.wantTol) { + t.Errorf("unexpected HITS result for test %d:\ngot: %v\nwant:%v", + i, orderedHubAuth(got, prec), orderedHubAuth(test.want, prec)) + break + } + if !floats.EqualWithinAbsOrRel(got[n].Authority, test.want[n].Authority, test.wantTol, test.wantTol) { + t.Errorf("unexpected HITS result for test %d:\ngot: %v\nwant:%v", + i, orderedHubAuth(got, prec), orderedHubAuth(test.want, prec)) + break + } + } + } +} + +func orderedHubAuth(w map[int]HubAuthority, prec int) []keyHubAuthVal { + o := make(orderedHubAuthMap, 0, len(w)) + for k, v := range w { + o = append(o, keyHubAuthVal{prec: prec, key: k, val: v}) + } + sort.Sort(o) + return o +} + +type keyHubAuthVal struct { + prec int + key int + val HubAuthority +} + +func (kv keyHubAuthVal) String() string { + return fmt.Sprintf("%d:{H:%.*f, A:%.*f}", + kv.key, kv.prec, kv.val.Hub, kv.prec, kv.val.Authority, + ) +} + +type orderedHubAuthMap []keyHubAuthVal + +func (o orderedHubAuthMap) Len() int { return len(o) } +func (o orderedHubAuthMap) Less(i, j int) bool { return o[i].key < o[j].key } +func (o orderedHubAuthMap) Swap(i, j int) { o[i], o[j] = o[j], o[i] } diff --git a/graph/network/network.go b/graph/network/network.go new file mode 100644 index 00000000..f0ead5bc --- /dev/null +++ b/graph/network/network.go @@ -0,0 +1,14 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TODO(kortschak): Implement: +// * edge-weighted PageRank and HITS +// * PersonalizedPageRank: +// http://infolab.stanford.edu/~backrub/google.html 2.1.2 Intuitive Justification +// http://ilpubs.stanford.edu:8090/596/1/2003-35.pdf +// http://www.vldb.org/pvldb/vol7/p1023-maehara.pdf +// * other centrality measures + +// Package network provides network analysis functions. +package network diff --git a/graph/network/network_test.go b/graph/network/network_test.go new file mode 100644 index 00000000..cd05bf21 --- /dev/null +++ b/graph/network/network_test.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package network + +const ( + A = iota + B + C + D + E + F + G + H + I + J + K +) + +// set is an integer set. +type set map[int]struct{} + +func linksTo(i ...int) set { + if len(i) == 0 { + return nil + } + s := make(set) + for _, v := range i { + s[v] = struct{}{} + } + return s +} diff --git a/graph/network/page.go b/graph/network/page.go new file mode 100644 index 00000000..4036e20e --- /dev/null +++ b/graph/network/page.go @@ -0,0 +1,228 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package network + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/matrix/mat64" +) + +// PageRank returns the PageRank weights for nodes of the directed graph g +// using the given damping factor and terminating when the 2-norm of the +// vector difference between iterations is below tol. The returned map is +// keyed on the graph node IDs. +func PageRank(g graph.Directed, damp, tol float64) map[int]float64 { + // PageRank is implemented according to "How Google Finds Your Needle + // in the Web's Haystack". + // + // G.I^k = alpha.S.I^k + (1-alpha).1/n.1.I^k + // + // http://www.ams.org/samplings/feature-column/fcarc-pagerank + + nodes := g.Nodes() + indexOf := make(map[int]int, len(nodes)) + for i, n := range nodes { + indexOf[n.ID()] = i + } + + m := mat64.NewDense(len(nodes), len(nodes), nil) + dangling := damp / float64(len(nodes)) + for j, u := range nodes { + to := g.From(u) + f := damp / float64(len(to)) + for _, v := range to { + m.Set(indexOf[v.ID()], j, f) + } + if len(to) == 0 { + for i := range nodes { + m.Set(i, j, dangling) + } + } + } + mat := m.RawMatrix().Data + dt := (1 - damp) / float64(len(nodes)) + for i := range mat { + mat[i] += dt + } + + last := make([]float64, len(nodes)) + for i := range last { + last[i] = 1 + } + lastV := mat64.NewVector(len(nodes), last) + + vec := make([]float64, len(nodes)) + var sum float64 + for i := range vec { + r := rand.NormFloat64() + sum += r + vec[i] = r + } + f := 1 / sum + for i := range vec { + vec[i] *= f + } + v := mat64.NewVector(len(nodes), vec) + + for { + lastV, v = v, lastV + v.MulVec(m, lastV) + if normDiff(vec, last) < tol { + break + } + } + + ranks := make(map[int]float64, len(nodes)) + for i, r := range v.RawVector().Data { + ranks[nodes[i].ID()] = r + } + + return ranks +} + +// PageRankSparse returns the PageRank weights for nodes of the sparse directed +// graph g using the given damping factor and terminating when the 2-norm of the +// vector difference between iterations is below tol. The returned map is +// keyed on the graph node IDs. +func PageRankSparse(g graph.Directed, damp, tol float64) map[int]float64 { + // PageRankSparse is implemented according to "How Google Finds Your Needle + // in the Web's Haystack". + // + // G.I^k = alpha.H.I^k + alpha.A.I^k + (1-alpha).1/n.1.I^k + // + // http://www.ams.org/samplings/feature-column/fcarc-pagerank + + nodes := g.Nodes() + indexOf := make(map[int]int, len(nodes)) + for i, n := range nodes { + indexOf[n.ID()] = i + } + + m := make(rowCompressedMatrix, len(nodes)) + var dangling compressedRow + df := damp / float64(len(nodes)) + for j, u := range nodes { + to := g.From(u) + f := damp / float64(len(to)) + for _, v := range to { + m.addTo(indexOf[v.ID()], j, f) + } + if len(to) == 0 { + dangling.addTo(j, df) + } + } + + last := make([]float64, len(nodes)) + for i := range last { + last[i] = 1 + } + lastV := mat64.NewVector(len(nodes), last) + + vec := make([]float64, len(nodes)) + var sum float64 + for i := range vec { + r := rand.NormFloat64() + sum += r + vec[i] = r + } + f := 1 / sum + for i := range vec { + vec[i] *= f + } + v := mat64.NewVector(len(nodes), vec) + + dt := (1 - damp) / float64(len(nodes)) + for { + lastV, v = v, lastV + + m.mulVecUnitary(v, lastV) // First term of the G matrix equation; + with := dangling.dotUnitary(lastV) // Second term; + away := onesDotUnitary(dt, lastV) // Last term. + + floats.AddConst(with+away, v.RawVector().Data) + if normDiff(vec, last) < tol { + break + } + } + + ranks := make(map[int]float64, len(nodes)) + for i, r := range v.RawVector().Data { + ranks[nodes[i].ID()] = r + } + + return ranks +} + +// rowCompressedMatrix implements row-compressed +// matrix/vector multiplication. +type rowCompressedMatrix []compressedRow + +// addTo adds the value v to the matrix element at (i,j). Repeated +// calls to addTo with the same column index will result in +// non-unique element representation. +func (m rowCompressedMatrix) addTo(i, j int, v float64) { m[i].addTo(j, v) } + +// mulVecUnitary multiplies the receiver by the src vector, storing +// the result in dst. It assumes src and dst are the same length as m +// and that both have unitary vector increments. +func (m rowCompressedMatrix) mulVecUnitary(dst, src *mat64.Vector) { + dMat := dst.RawVector().Data + for i, r := range m { + dMat[i] = r.dotUnitary(src) + } +} + +// compressedRow implements a simplified scatter-based Ddot. +type compressedRow []sparseElement + +// addTo adds the value v to the vector element at j. Repeated +// calls to addTo with the same vector index will result in +// non-unique element representation. +func (r *compressedRow) addTo(j int, v float64) { + *r = append(*r, sparseElement{index: j, value: v}) +} + +// dotUnitary performs a simplified scatter-based Ddot operations on +// v and the receiver. v must have have a unitary vector increment. +func (r compressedRow) dotUnitary(v *mat64.Vector) float64 { + var sum float64 + vec := v.RawVector().Data + for _, e := range r { + sum += vec[e.index] * e.value + } + return sum +} + +// sparseElement is a sparse vector or matrix element. +type sparseElement struct { + index int + value float64 +} + +// onesDotUnitary performs the equivalent of a Ddot of v with +// a ones vector of equal length. v must have have a unitary +// vector increment. +func onesDotUnitary(alpha float64, v *mat64.Vector) float64 { + var sum float64 + for _, f := range v.RawVector().Data { + sum += alpha * f + } + return sum +} + +// normDiff returns the 2-norm of the difference between x and y. +// This is a cut down version of gonum/floats.Distance. +func normDiff(x, y []float64) float64 { + var sum float64 + for i, v := range x { + d := v - y[i] + sum += d * d + } + return math.Sqrt(sum) +} diff --git a/graph/network/page_test.go b/graph/network/page_test.go new file mode 100644 index 00000000..548bf2d4 --- /dev/null +++ b/graph/network/page_test.go @@ -0,0 +1,151 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package network + +import ( + "fmt" + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/graph/simple" +) + +var pageRankTests = []struct { + g []set + damp float64 + tol float64 + + wantTol float64 + want map[int]float64 +}{ + { + // Example graph from http://en.wikipedia.org/wiki/File:PageRanks-Example.svg 16:17, 8 July 2009 + g: []set{ + A: nil, + B: linksTo(C), + C: linksTo(B), + D: linksTo(A, B), + E: linksTo(D, B, F), + F: linksTo(B, E), + G: linksTo(B, E), + H: linksTo(B, E), + I: linksTo(B, E), + J: linksTo(E), + K: linksTo(E), + }, + damp: 0.85, + tol: 1e-8, + + wantTol: 1e-8, + want: map[int]float64{ + A: 0.03278149, + B: 0.38440095, + C: 0.34291029, + D: 0.03908709, + E: 0.08088569, + F: 0.03908709, + G: 0.01616948, + H: 0.01616948, + I: 0.01616948, + J: 0.01616948, + K: 0.01616948, + }, + }, + { + // Example graph from http://en.wikipedia.org/w/index.php?title=PageRank&oldid=659286279#Power_Method + // Expected result calculated with the given MATLAB code. + g: []set{ + A: linksTo(B, C), + B: linksTo(D), + C: linksTo(D, E), + D: linksTo(E), + E: linksTo(A), + }, + damp: 0.80, + tol: 1e-3, + + wantTol: 1e-3, + want: map[int]float64{ + A: 0.250, + B: 0.140, + C: 0.140, + D: 0.208, + E: 0.262, + }, + }, +} + +func TestPageRank(t *testing.T) { + for i, test := range pageRankTests { + g := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got := PageRank(g, test.damp, test.tol) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], test.want[n], test.wantTol, test.wantTol) { + t.Errorf("unexpected PageRank result for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.want, prec)) + break + } + } + } +} + +func TestPageRankSparse(t *testing.T) { + for i, test := range pageRankTests { + g := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got := PageRankSparse(g, test.damp, test.tol) + prec := 1 - int(math.Log10(test.wantTol)) + for n := range test.g { + if !floats.EqualWithinAbsOrRel(got[n], test.want[n], test.wantTol, test.wantTol) { + t.Errorf("unexpected PageRank result for test %d:\ngot: %v\nwant:%v", + i, orderedFloats(got, prec), orderedFloats(test.want, prec)) + break + } + } + } +} + +func orderedFloats(w map[int]float64, prec int) []keyFloatVal { + o := make(orderedFloatsMap, 0, len(w)) + for k, v := range w { + o = append(o, keyFloatVal{prec: prec, key: k, val: v}) + } + sort.Sort(o) + return o +} + +type keyFloatVal struct { + prec int + key int + val float64 +} + +func (kv keyFloatVal) String() string { return fmt.Sprintf("%c:%.*f", kv.key+'A', kv.prec, kv.val) } + +type orderedFloatsMap []keyFloatVal + +func (o orderedFloatsMap) Len() int { return len(o) } +func (o orderedFloatsMap) Less(i, j int) bool { return o[i].key < o[j].key } +func (o orderedFloatsMap) Swap(i, j int) { o[i], o[j] = o[j], o[i] } diff --git a/graph/path/a_star.go b/graph/path/a_star.go new file mode 100644 index 00000000..f914e73c --- /dev/null +++ b/graph/path/a_star.go @@ -0,0 +1,151 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "container/heap" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/set" +) + +// AStar finds the A*-shortest path from s to t in g using the heuristic h. The path and +// its cost are returned in a Shortest along with paths and costs to all nodes explored +// during the search. The number of expanded nodes is also returned. This value may help +// with heuristic tuning. +// +// The path will be the shortest path if the heuristic is admissible. A heuristic is +// admissible if for any node, n, in the graph, the heuristic estimate of the cost of +// the path from n to t is less than or equal to the true cost of that path. +// +// If h is nil, AStar will use the g.HeuristicCost method if g implements HeuristicCoster, +// falling back to NullHeuristic otherwise. If the graph does not implement graph.Weighter, +// UniformCost is used. AStar will panic if g has an A*-reachable negative edge weight. +func AStar(s, t graph.Node, g graph.Graph, h Heuristic) (path Shortest, expanded int) { + if !g.Has(s) || !g.Has(t) { + return Shortest{from: s}, 0 + } + var weight Weighting + if wg, ok := g.(graph.Weighter); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + if h == nil { + if g, ok := g.(HeuristicCoster); ok { + h = g.HeuristicCost + } else { + h = NullHeuristic + } + } + + path = newShortestFrom(s, g.Nodes()) + tid := t.ID() + + visited := make(set.Ints) + open := &aStarQueue{indexOf: make(map[int]int)} + heap.Push(open, aStarNode{node: s, gscore: 0, fscore: h(s, t)}) + + for open.Len() != 0 { + u := heap.Pop(open).(aStarNode) + uid := u.node.ID() + i := path.indexOf[uid] + expanded++ + + if uid == tid { + break + } + + visited.Add(uid) + for _, v := range g.From(u.node) { + vid := v.ID() + if visited.Has(vid) { + continue + } + j := path.indexOf[vid] + + w, ok := weight(u.node, v) + if !ok { + panic("A*: unexpected invalid weight") + } + if w < 0 { + panic("A*: negative edge weight") + } + g := u.gscore + w + if n, ok := open.node(vid); !ok { + path.set(j, g, i) + heap.Push(open, aStarNode{node: v, gscore: g, fscore: g + h(v, t)}) + } else if g < n.gscore { + path.set(j, g, i) + open.update(vid, g, g+h(v, t)) + } + } + } + + return path, expanded +} + +// NullHeuristic is an admissible, consistent heuristic that will not speed up computation. +func NullHeuristic(_, _ graph.Node) float64 { + return 0 +} + +// aStarNode adds A* accounting to a graph.Node. +type aStarNode struct { + node graph.Node + gscore float64 + fscore float64 +} + +// aStarQueue is an A* priority queue. +type aStarQueue struct { + indexOf map[int]int + nodes []aStarNode +} + +func (q *aStarQueue) Less(i, j int) bool { + return q.nodes[i].fscore < q.nodes[j].fscore +} + +func (q *aStarQueue) Swap(i, j int) { + q.indexOf[q.nodes[i].node.ID()] = j + q.indexOf[q.nodes[j].node.ID()] = i + q.nodes[i], q.nodes[j] = q.nodes[j], q.nodes[i] +} + +func (q *aStarQueue) Len() int { + return len(q.nodes) +} + +func (q *aStarQueue) Push(x interface{}) { + n := x.(aStarNode) + q.indexOf[n.node.ID()] = len(q.nodes) + q.nodes = append(q.nodes, n) +} + +func (q *aStarQueue) Pop() interface{} { + n := q.nodes[len(q.nodes)-1] + q.nodes = q.nodes[:len(q.nodes)-1] + delete(q.indexOf, n.node.ID()) + return n +} + +func (q *aStarQueue) update(id int, g, f float64) { + i, ok := q.indexOf[id] + if !ok { + return + } + q.nodes[i].gscore = g + q.nodes[i].fscore = f + heap.Fix(q, i) +} + +func (q *aStarQueue) node(id int) (aStarNode, bool) { + loc, ok := q.indexOf[id] + if ok { + return q.nodes[loc], true + } + return aStarNode{}, false +} diff --git a/graph/path/a_star_test.go b/graph/path/a_star_test.go new file mode 100644 index 00000000..085bbb17 --- /dev/null +++ b/graph/path/a_star_test.go @@ -0,0 +1,310 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path/internal" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/graph/topo" +) + +var aStarTests = []struct { + name string + g graph.Graph + + s, t int + heuristic Heuristic + wantPath []int +}{ + { + name: "simple path", + g: func() graph.Graph { + return internal.NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ) + }(), + + s: 1, t: 14, + wantPath: []int{1, 2, 6, 10, 14}, + }, + { + name: "small open graph", + g: internal.NewGrid(3, 3, true), + + s: 0, t: 8, + }, + { + name: "large open graph", + g: internal.NewGrid(1000, 1000, true), + + s: 0, t: 999*1000 + 999, + }, + { + name: "no path", + g: func() graph.Graph { + tg := internal.NewGrid(5, 5, true) + + // Create a complete "wall" across the middle row. + tg.Set(2, 0, false) + tg.Set(2, 1, false) + tg.Set(2, 2, false) + tg.Set(2, 3, false) + tg.Set(2, 4, false) + + return tg + }(), + + s: 2, t: 22, + }, + { + name: "partially obstructed", + g: func() graph.Graph { + tg := internal.NewGrid(10, 10, true) + + // Create a partial "wall" accross the middle + // row with a gap at the left-hand end. + tg.Set(4, 1, false) + tg.Set(4, 2, false) + tg.Set(4, 3, false) + tg.Set(4, 4, false) + tg.Set(4, 5, false) + tg.Set(4, 6, false) + tg.Set(4, 7, false) + tg.Set(4, 8, false) + tg.Set(4, 9, false) + + return tg + }(), + + s: 5, t: 9*10 + 9, + }, + { + name: "partially obstructed with heuristic", + g: func() graph.Graph { + tg := internal.NewGrid(10, 10, true) + + // Create a partial "wall" accross the middle + // row with a gap at the left-hand end. + tg.Set(4, 1, false) + tg.Set(4, 2, false) + tg.Set(4, 3, false) + tg.Set(4, 4, false) + tg.Set(4, 5, false) + tg.Set(4, 6, false) + tg.Set(4, 7, false) + tg.Set(4, 8, false) + tg.Set(4, 9, false) + + return tg + }(), + + s: 5, t: 9*10 + 9, + // Manhattan Heuristic + heuristic: func(u, v graph.Node) float64 { + uid := u.ID() + cu := (uid % 10) + ru := (uid - cu) / 10 + + vid := v.ID() + cv := (vid % 10) + rv := (vid - cv) / 10 + + return math.Abs(float64(ru-rv)) + math.Abs(float64(cu-cv)) + }, + }, +} + +func TestAStar(t *testing.T) { + for _, test := range aStarTests { + pt, _ := AStar(simple.Node(test.s), simple.Node(test.t), test.g, test.heuristic) + + p, cost := pt.To(simple.Node(test.t)) + + if !topo.IsPathIn(test.g, p) { + t.Error("got path that is not path in input graph for %q", test.name) + } + + bfp, ok := BellmanFordFrom(simple.Node(test.s), test.g) + if !ok { + t.Fatalf("unexpected negative cycle in %q", test.name) + } + if want := bfp.WeightTo(simple.Node(test.t)); cost != want { + t.Errorf("unexpected cost for %q: got:%v want:%v", test.name, cost, want) + } + + var got = make([]int, 0, len(p)) + for _, n := range p { + got = append(got, n.ID()) + } + if test.wantPath != nil && !reflect.DeepEqual(got, test.wantPath) { + t.Errorf("unexpected result for %q:\ngot: %v\nwant:%v", test.name, got, test.wantPath) + } + } +} + +func TestExhaustiveAStar(t *testing.T) { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + nodes := []locatedNode{ + {id: 1, x: 0, y: 6}, + {id: 2, x: 1, y: 0}, + {id: 3, x: 8, y: 7}, + {id: 4, x: 16, y: 0}, + {id: 5, x: 17, y: 6}, + {id: 6, x: 9, y: 8}, + } + for _, n := range nodes { + g.AddNode(n) + } + + edges := []weightedEdge{ + {from: g.Node(1), to: g.Node(2), cost: 7}, + {from: g.Node(1), to: g.Node(3), cost: 9}, + {from: g.Node(1), to: g.Node(6), cost: 14}, + {from: g.Node(2), to: g.Node(3), cost: 10}, + {from: g.Node(2), to: g.Node(4), cost: 15}, + {from: g.Node(3), to: g.Node(4), cost: 11}, + {from: g.Node(3), to: g.Node(6), cost: 2}, + {from: g.Node(4), to: g.Node(5), cost: 7}, + {from: g.Node(5), to: g.Node(6), cost: 9}, + } + for _, e := range edges { + g.SetEdge(e) + } + + heuristic := func(u, v graph.Node) float64 { + lu := u.(locatedNode) + lv := v.(locatedNode) + return math.Hypot(lu.x-lv.x, lu.y-lv.y) + } + + if ok, edge, goal := isMonotonic(g, heuristic); !ok { + t.Fatalf("non-monotonic heuristic at edge:%v for goal:%v", edge, goal) + } + + ps := DijkstraAllPaths(g) + for _, start := range g.Nodes() { + for _, goal := range g.Nodes() { + pt, _ := AStar(start, goal, g, heuristic) + gotPath, gotWeight := pt.To(goal) + wantPath, wantWeight, _ := ps.Between(start, goal) + if gotWeight != wantWeight { + t.Errorf("unexpected path weight from %v to %v result: got:%s want:%s", + start, goal, gotWeight, wantWeight) + } + if !reflect.DeepEqual(gotPath, wantPath) { + t.Errorf("unexpected path from %v to %v result:\ngot: %v\nwant:%v", + start, goal, gotPath, wantPath) + } + } + } +} + +type locatedNode struct { + id int + x, y float64 +} + +func (n locatedNode) ID() int { return n.id } + +type weightedEdge struct { + from, to graph.Node + cost float64 +} + +func (e weightedEdge) From() graph.Node { return e.from } +func (e weightedEdge) To() graph.Node { return e.to } +func (e weightedEdge) Weight() float64 { return e.cost } + +func isMonotonic(g UndirectedWeightLister, h Heuristic) (ok bool, at graph.Edge, goal graph.Node) { + for _, goal := range g.Nodes() { + for _, edge := range g.Edges() { + from := edge.From() + to := edge.To() + w, ok := g.Weight(from, to) + if !ok { + panic("A*: unexpected invalid weight") + } + if h(from, goal) > w+h(to, goal) { + return false, edge, goal + } + } + } + return true, nil, nil +} + +func TestAStarNullHeuristic(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetEdge(e) + } + + var ( + pt Shortest + + panicked bool + ) + func() { + defer func() { + panicked = recover() != nil + }() + pt, _ = AStar(test.Query.From(), test.Query.To(), g.(graph.Graph), nil) + }() + if panicked || test.HasNegativeWeight { + if !test.HasNegativeWeight { + t.Errorf("%q: unexpected panic", test.Name) + } + if !panicked { + t.Errorf("%q: expected panic for negative edge weight", test.Name) + } + continue + } + + if pt.From().ID() != test.Query.From().ID() { + t.Fatalf("%q: unexpected from node ID: got:%d want:%d", pt.From().ID(), test.Query.From().ID()) + } + + p, weight := pt.To(test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.WeightTo(test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got []int + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + + np, weight := pt.To(test.NoPathFor.To()) + if pt.From().ID() == test.NoPathFor.From().ID() && (np != nil || !math.IsInf(weight, 1)) { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f\nwant:path= weight=+Inf", + test.Name, np, weight) + } + } +} diff --git a/graph/path/bellman_ford_moore.go b/graph/path/bellman_ford_moore.go new file mode 100644 index 00000000..906a57c8 --- /dev/null +++ b/graph/path/bellman_ford_moore.go @@ -0,0 +1,67 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import "gonum.org/v1/gonum/graph" + +// BellmanFordFrom returns a shortest-path tree for a shortest path from u to all nodes in +// the graph g, or false indicating that a negative cycle exists in the graph. If the graph +// does not implement graph.Weighter, UniformCost is used. +// +// The time complexity of BellmanFordFrom is O(|V|.|E|). +func BellmanFordFrom(u graph.Node, g graph.Graph) (path Shortest, ok bool) { + if !g.Has(u) { + return Shortest{from: u}, true + } + var weight Weighting + if wg, ok := g.(graph.Weighter); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + + nodes := g.Nodes() + + path = newShortestFrom(u, nodes) + path.dist[path.indexOf[u.ID()]] = 0 + + // TODO(kortschak): Consider adding further optimisations + // from http://arxiv.org/abs/1111.5414. + for i := 1; i < len(nodes); i++ { + changed := false + for j, u := range nodes { + for _, v := range g.From(u) { + k := path.indexOf[v.ID()] + w, ok := weight(u, v) + if !ok { + panic("bellman-ford: unexpected invalid weight") + } + joint := path.dist[j] + w + if joint < path.dist[k] { + path.set(k, joint, j) + changed = true + } + } + } + if !changed { + break + } + } + + for j, u := range nodes { + for _, v := range g.From(u) { + k := path.indexOf[v.ID()] + w, ok := weight(u, v) + if !ok { + panic("bellman-ford: unexpected invalid weight") + } + if path.dist[j]+w < path.dist[k] { + return path, false + } + } + } + + return path, true +} diff --git a/graph/path/bellman_ford_moore_test.go b/graph/path/bellman_ford_moore_test.go new file mode 100644 index 00000000..69307d6c --- /dev/null +++ b/graph/path/bellman_ford_moore_test.go @@ -0,0 +1,70 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" +) + +func TestBellmanFordFrom(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetEdge(e) + } + + pt, ok := BellmanFordFrom(test.Query.From(), g.(graph.Graph)) + if test.HasNegativeCycle { + if ok { + t.Errorf("%q: expected negative cycle", test.Name) + } + continue + } + if !ok { + t.Fatalf("%q: unexpected negative cycle", test.Name) + } + + if pt.From().ID() != test.Query.From().ID() { + t.Fatalf("%q: unexpected from node ID: got:%d want:%d", pt.From().ID(), test.Query.From().ID()) + } + + p, weight := pt.To(test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.WeightTo(test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got []int + for _, n := range p { + got = append(got, n.ID()) + } + ok = len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + + np, weight := pt.To(test.NoPathFor.To()) + if pt.From().ID() == test.NoPathFor.From().ID() && (np != nil || !math.IsInf(weight, 1)) { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f\nwant:path= weight=+Inf", + test.Name, np, weight) + } + } +} diff --git a/graph/path/bench_test.go b/graph/path/bench_test.go new file mode 100644 index 00000000..8fc7a9dd --- /dev/null +++ b/graph/path/bench_test.go @@ -0,0 +1,142 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/graphs/gen" + "gonum.org/v1/gonum/graph/simple" +) + +var ( + gnpUndirected_10_tenth = gnpUndirected(10, 0.1) + gnpUndirected_100_tenth = gnpUndirected(100, 0.1) + gnpUndirected_1000_tenth = gnpUndirected(1000, 0.1) + gnpUndirected_10_half = gnpUndirected(10, 0.5) + gnpUndirected_100_half = gnpUndirected(100, 0.5) + gnpUndirected_1000_half = gnpUndirected(1000, 0.5) +) + +func gnpUndirected(n int, p float64) graph.Undirected { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + gen.Gnp(g, n, p, nil) + return g +} + +func benchmarkAStarNilHeuristic(b *testing.B, g graph.Undirected) { + var expanded int + for i := 0; i < b.N; i++ { + _, expanded = AStar(simple.Node(0), simple.Node(1), g, nil) + } + if expanded == 0 { + b.Fatal("unexpected number of expanded nodes") + } +} + +func BenchmarkAStarGnp_10_tenth(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_10_tenth) +} +func BenchmarkAStarGnp_100_tenth(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_100_tenth) +} +func BenchmarkAStarGnp_1000_tenth(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_1000_tenth) +} +func BenchmarkAStarGnp_10_half(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_10_half) +} +func BenchmarkAStarGnp_100_half(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_100_half) +} +func BenchmarkAStarGnp_1000_half(b *testing.B) { + benchmarkAStarNilHeuristic(b, gnpUndirected_1000_half) +} + +var ( + nswUndirected_10_2_2_2 = navigableSmallWorldUndirected(10, 2, 2, 2) + nswUndirected_10_2_5_2 = navigableSmallWorldUndirected(10, 2, 5, 2) + nswUndirected_100_5_10_2 = navigableSmallWorldUndirected(100, 5, 10, 2) + nswUndirected_100_5_20_2 = navigableSmallWorldUndirected(100, 5, 20, 2) +) + +func navigableSmallWorldUndirected(n, p, q int, r float64) graph.Undirected { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + gen.NavigableSmallWorld(g, []int{n, n}, p, q, r, nil) + return g +} + +func coordinatesForID(n graph.Node, c, r int) [2]int { + id := n.ID() + if id >= c*r { + panic("out of range") + } + return [2]int{id / r, id % r} +} + +// manhattanBetween returns the Manhattan distance between a and b. +func manhattanBetween(a, b [2]int) float64 { + var d int + for i, v := range a { + d += abs(v - b[i]) + } + return float64(d) +} + +func abs(a int) int { + if a < 0 { + return -a + } + return a +} + +func benchmarkAStarHeuristic(b *testing.B, g graph.Undirected, h Heuristic) { + var expanded int + for i := 0; i < b.N; i++ { + _, expanded = AStar(simple.Node(0), simple.Node(1), g, h) + } + if expanded == 0 { + b.Fatal("unexpected number of expanded nodes") + } +} + +func BenchmarkAStarUndirectedmallWorld_10_2_2_2(b *testing.B) { + benchmarkAStarHeuristic(b, nswUndirected_10_2_2_2, nil) +} +func BenchmarkAStarUndirectedmallWorld_10_2_2_2_Heur(b *testing.B) { + h := func(x, y graph.Node) float64 { + return manhattanBetween(coordinatesForID(x, 10, 10), coordinatesForID(y, 10, 10)) + } + benchmarkAStarHeuristic(b, nswUndirected_10_2_2_2, h) +} +func BenchmarkAStarUndirectedmallWorld_10_2_5_2(b *testing.B) { + benchmarkAStarHeuristic(b, nswUndirected_10_2_5_2, nil) +} +func BenchmarkAStarUndirectedmallWorld_10_2_5_2_Heur(b *testing.B) { + h := func(x, y graph.Node) float64 { + return manhattanBetween(coordinatesForID(x, 10, 10), coordinatesForID(y, 10, 10)) + } + benchmarkAStarHeuristic(b, nswUndirected_10_2_5_2, h) +} +func BenchmarkAStarUndirectedmallWorld_100_5_10_2(b *testing.B) { + benchmarkAStarHeuristic(b, nswUndirected_100_5_10_2, nil) +} +func BenchmarkAStarUndirectedmallWorld_100_5_10_2_Heur(b *testing.B) { + h := func(x, y graph.Node) float64 { + return manhattanBetween(coordinatesForID(x, 100, 100), coordinatesForID(y, 100, 100)) + } + benchmarkAStarHeuristic(b, nswUndirected_100_5_10_2, h) +} +func BenchmarkAStarUndirectedmallWorld_100_5_20_2(b *testing.B) { + benchmarkAStarHeuristic(b, nswUndirected_100_5_20_2, nil) +} +func BenchmarkAStarUndirectedmallWorld_100_5_20_2_Heur(b *testing.B) { + h := func(x, y graph.Node) float64 { + return manhattanBetween(coordinatesForID(x, 100, 100), coordinatesForID(y, 100, 100)) + } + benchmarkAStarHeuristic(b, nswUndirected_100_5_20_2, h) +} diff --git a/graph/path/control_flow.go b/graph/path/control_flow.go new file mode 100644 index 00000000..26b732bd --- /dev/null +++ b/graph/path/control_flow.go @@ -0,0 +1,118 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/set" +) + +// Dominators returns all dominators for all nodes in g. It does not +// prune for strict post-dominators, immediate dominators etc. +// +// A dominates B if and only if the only path through B travels through A. +func Dominators(start graph.Node, g graph.Graph) map[int]set.Nodes { + allNodes := make(set.Nodes) + nlist := g.Nodes() + dominators := make(map[int]set.Nodes, len(nlist)) + for _, node := range nlist { + allNodes.Add(node) + } + + var to func(graph.Node) []graph.Node + switch g := g.(type) { + case graph.Directed: + to = g.To + default: + to = g.From + } + + for _, node := range nlist { + dominators[node.ID()] = make(set.Nodes) + if node.ID() == start.ID() { + dominators[node.ID()].Add(start) + } else { + dominators[node.ID()].Copy(allNodes) + } + } + + for somethingChanged := true; somethingChanged; { + somethingChanged = false + for _, node := range nlist { + if node.ID() == start.ID() { + continue + } + preds := to(node) + if len(preds) == 0 { + continue + } + tmp := make(set.Nodes).Copy(dominators[preds[0].ID()]) + for _, pred := range preds[1:] { + tmp.Intersect(tmp, dominators[pred.ID()]) + } + + dom := make(set.Nodes) + dom.Add(node) + + dom.Union(dom, tmp) + if !set.Equal(dom, dominators[node.ID()]) { + dominators[node.ID()] = dom + somethingChanged = true + } + } + } + + return dominators +} + +// PostDominators returns all post-dominators for all nodes in g. It does not +// prune for strict post-dominators, immediate post-dominators etc. +// +// A post-dominates B if and only if all paths from B travel through A. +func PostDominators(end graph.Node, g graph.Graph) map[int]set.Nodes { + allNodes := make(set.Nodes) + nlist := g.Nodes() + dominators := make(map[int]set.Nodes, len(nlist)) + for _, node := range nlist { + allNodes.Add(node) + } + + for _, node := range nlist { + dominators[node.ID()] = make(set.Nodes) + if node.ID() == end.ID() { + dominators[node.ID()].Add(end) + } else { + dominators[node.ID()].Copy(allNodes) + } + } + + for somethingChanged := true; somethingChanged; { + somethingChanged = false + for _, node := range nlist { + if node.ID() == end.ID() { + continue + } + succs := g.From(node) + if len(succs) == 0 { + continue + } + tmp := make(set.Nodes).Copy(dominators[succs[0].ID()]) + for _, succ := range succs[1:] { + tmp.Intersect(tmp, dominators[succ.ID()]) + } + + dom := make(set.Nodes) + dom.Add(node) + + dom.Union(dom, tmp) + if !set.Equal(dom, dominators[node.ID()]) { + dominators[node.ID()] = dom + somethingChanged = true + } + } + } + + return dominators +} diff --git a/graph/path/dijkstra.go b/graph/path/dijkstra.go new file mode 100644 index 00000000..62ec5e29 --- /dev/null +++ b/graph/path/dijkstra.go @@ -0,0 +1,147 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "container/heap" + + "gonum.org/v1/gonum/graph" +) + +// DijkstraFrom returns a shortest-path tree for a shortest path from u to all nodes in +// the graph g. If the graph does not implement graph.Weighter, UniformCost is used. +// DijkstraFrom will panic if g has a u-reachable negative edge weight. +// +// The time complexity of DijkstrFrom is O(|E|.log|V|). +func DijkstraFrom(u graph.Node, g graph.Graph) Shortest { + if !g.Has(u) { + return Shortest{from: u} + } + var weight Weighting + if wg, ok := g.(graph.Weighter); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + + nodes := g.Nodes() + path := newShortestFrom(u, nodes) + + // Dijkstra's algorithm here is implemented essentially as + // described in Function B.2 in figure 6 of UTCS Technical + // Report TR-07-54. + // + // This implementation deviates from the report as follows: + // - the value of path.dist for the start vertex u is initialized to 0; + // - outdated elements from the priority queue (i.e. with respect to the dist value) + // are skipped. + // + // http://www.cs.utexas.edu/ftp/techreports/tr07-54.pdf + Q := priorityQueue{{node: u, dist: 0}} + for Q.Len() != 0 { + mid := heap.Pop(&Q).(distanceNode) + k := path.indexOf[mid.node.ID()] + if mid.dist > path.dist[k] { + continue + } + for _, v := range g.From(mid.node) { + j := path.indexOf[v.ID()] + w, ok := weight(mid.node, v) + if !ok { + panic("dijkstra: unexpected invalid weight") + } + if w < 0 { + panic("dijkstra: negative edge weight") + } + joint := path.dist[k] + w + if joint < path.dist[j] { + heap.Push(&Q, distanceNode{node: v, dist: joint}) + path.set(j, joint, k) + } + } + } + + return path +} + +// DijkstraAllPaths returns a shortest-path tree for shortest paths in the graph g. +// If the graph does not implement graph.Weighter, UniformCost is used. +// DijkstraAllPaths will panic if g has a negative edge weight. +// +// The time complexity of DijkstrAllPaths is O(|V|.|E|+|V|^2.log|V|). +func DijkstraAllPaths(g graph.Graph) (paths AllShortest) { + paths = newAllShortest(g.Nodes(), false) + dijkstraAllPaths(g, paths) + return paths +} + +// dijkstraAllPaths is the all-paths implementation of Dijkstra. It is shared +// between DijkstraAllPaths and JohnsonAllPaths to avoid repeated allocation +// of the nodes slice and the indexOf map. It returns nothing, but stores the +// result of the work in the paths parameter which is a reference type. +func dijkstraAllPaths(g graph.Graph, paths AllShortest) { + var weight Weighting + if wg, ok := g.(graph.Weighter); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + + var Q priorityQueue + for i, u := range paths.nodes { + // Dijkstra's algorithm here is implemented essentially as + // described in Function B.2 in figure 6 of UTCS Technical + // Report TR-07-54 with the addition of handling multiple + // co-equal paths. + // + // http://www.cs.utexas.edu/ftp/techreports/tr07-54.pdf + + // Q must be empty at this point. + heap.Push(&Q, distanceNode{node: u, dist: 0}) + for Q.Len() != 0 { + mid := heap.Pop(&Q).(distanceNode) + k := paths.indexOf[mid.node.ID()] + if mid.dist < paths.dist.At(i, k) { + paths.dist.Set(i, k, mid.dist) + } + for _, v := range g.From(mid.node) { + j := paths.indexOf[v.ID()] + w, ok := weight(mid.node, v) + if !ok { + panic("dijkstra: unexpected invalid weight") + } + if w < 0 { + panic("dijkstra: negative edge weight") + } + joint := paths.dist.At(i, k) + w + if joint < paths.dist.At(i, j) { + heap.Push(&Q, distanceNode{node: v, dist: joint}) + paths.set(i, j, joint, k) + } else if joint == paths.dist.At(i, j) { + paths.add(i, j, k) + } + } + } + } +} + +type distanceNode struct { + node graph.Node + dist float64 +} + +// priorityQueue implements a no-dec priority queue. +type priorityQueue []distanceNode + +func (q priorityQueue) Len() int { return len(q) } +func (q priorityQueue) Less(i, j int) bool { return q[i].dist < q[j].dist } +func (q priorityQueue) Swap(i, j int) { q[i], q[j] = q[j], q[i] } +func (q *priorityQueue) Push(n interface{}) { *q = append(*q, n.(distanceNode)) } +func (q *priorityQueue) Pop() interface{} { + t := *q + var n interface{} + n, *q = t[len(t)-1], t[:len(t)-1] + return n +} diff --git a/graph/path/dijkstra_test.go b/graph/path/dijkstra_test.go new file mode 100644 index 00000000..12dd417d --- /dev/null +++ b/graph/path/dijkstra_test.go @@ -0,0 +1,178 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" +) + +func TestDijkstraFrom(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetEdge(e) + } + + var ( + pt Shortest + + panicked bool + ) + func() { + defer func() { + panicked = recover() != nil + }() + pt = DijkstraFrom(test.Query.From(), g.(graph.Graph)) + }() + if panicked || test.HasNegativeWeight { + if !test.HasNegativeWeight { + t.Errorf("%q: unexpected panic", test.Name) + } + if !panicked { + t.Errorf("%q: expected panic for negative edge weight", test.Name) + } + continue + } + + if pt.From().ID() != test.Query.From().ID() { + t.Fatalf("%q: unexpected from node ID: got:%d want:%d", pt.From().ID(), test.Query.From().ID()) + } + + p, weight := pt.To(test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.WeightTo(test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got []int + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + + np, weight := pt.To(test.NoPathFor.To()) + if pt.From().ID() == test.NoPathFor.From().ID() && (np != nil || !math.IsInf(weight, 1)) { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f\nwant:path= weight=+Inf", + test.Name, np, weight) + } + } +} + +func TestDijkstraAllPaths(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetEdge(e) + } + + var ( + pt AllShortest + + panicked bool + ) + func() { + defer func() { + panicked = recover() != nil + }() + pt = DijkstraAllPaths(g.(graph.Graph)) + }() + if panicked || test.HasNegativeWeight { + if !test.HasNegativeWeight { + t.Errorf("%q: unexpected panic", test.Name) + } + if !panicked { + t.Errorf("%q: expected panic for negative edge weight", test.Name) + } + continue + } + + // Check all random paths returned are OK. + for i := 0; i < 10; i++ { + p, weight, unique := pt.Between(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.Weight(test.Query.From(), test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + if unique != test.HasUniquePath { + t.Errorf("%q: unexpected number of paths: got: unique=%t want: unique=%t", + test.Name, unique, test.HasUniquePath) + } + + var got []int + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + } + + np, weight, unique := pt.Between(test.NoPathFor.From(), test.NoPathFor.To()) + if np != nil || !math.IsInf(weight, 1) || unique != false { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f unique=%t\nwant:path= weight=+Inf unique=false", + test.Name, np, weight, unique) + } + + paths, weight := pt.AllBetween(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got [][]int + if len(paths) != 0 { + got = make([][]int, len(paths)) + } + for i, p := range paths { + for _, v := range p { + got[i] = append(got[i], v.ID()) + } + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.WantPaths) { + t.Errorf("testing %q: unexpected shortest paths:\ngot: %v\nwant:%v", + test.Name, got, test.WantPaths) + } + + nps, weight := pt.AllBetween(test.NoPathFor.From(), test.NoPathFor.To()) + if nps != nil || !math.IsInf(weight, 1) { + t.Errorf("%q: unexpected path:\ngot: paths=%v weight=%f\nwant:path= weight=+Inf", + test.Name, nps, weight) + } + } +} diff --git a/graph/path/disjoint.go b/graph/path/disjoint.go new file mode 100644 index 00000000..1840d380 --- /dev/null +++ b/graph/path/disjoint.go @@ -0,0 +1,87 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +// A disjoint set is a collection of non-overlapping sets. That is, for any two sets in the +// disjoint set, their intersection is the empty set. +// +// A disjoint set has three principle operations: Make Set, Find, and Union. +// +// Make set creates a new set for an element (presuming it does not already exist in any set in +// the disjoint set), Find finds the set containing that element (if any), and Union merges two +// sets in the disjoint set. In general, algorithms operating on disjoint sets are "union-find" +// algorithms, where two sets are found with Find, and then joined with Union. +// +// A concrete example of a union-find algorithm can be found as discrete.Kruskal -- which unions +// two sets when an edge is created between two vertices, and refuses to make an edge between two +// vertices if they're part of the same set. +type disjointSet struct { + master map[int]*disjointSetNode +} + +type disjointSetNode struct { + parent *disjointSetNode + rank int +} + +func newDisjointSet() *disjointSet { + return &disjointSet{master: make(map[int]*disjointSetNode)} +} + +// If the element isn't already somewhere in there, adds it to the master set and its own tiny set. +func (ds *disjointSet) makeSet(e int) { + if _, ok := ds.master[e]; ok { + return + } + dsNode := &disjointSetNode{rank: 0} + dsNode.parent = dsNode + ds.master[e] = dsNode +} + +// Returns the set the element belongs to, or nil if none. +func (ds *disjointSet) find(e int) *disjointSetNode { + dsNode, ok := ds.master[e] + if !ok { + return nil + } + + return find(dsNode) +} + +func find(dsNode *disjointSetNode) *disjointSetNode { + if dsNode.parent != dsNode { + dsNode.parent = find(dsNode.parent) + } + + return dsNode.parent +} + +// Unions two subsets within the disjointSet. +// +// If x or y are not in this disjoint set, the behavior is undefined. If either pointer is nil, +// this function will panic. +func (ds *disjointSet) union(x, y *disjointSetNode) { + if x == nil || y == nil { + panic("Disjoint Set union on nil sets") + } + xRoot := find(x) + yRoot := find(y) + if xRoot == nil || yRoot == nil { + return + } + + if xRoot == yRoot { + return + } + + if xRoot.rank < yRoot.rank { + xRoot.parent = yRoot + } else if yRoot.rank < xRoot.rank { + yRoot.parent = xRoot + } else { + yRoot.parent = xRoot + xRoot.rank++ + } +} diff --git a/graph/path/disjoint_test.go b/graph/path/disjoint_test.go new file mode 100644 index 00000000..2639592a --- /dev/null +++ b/graph/path/disjoint_test.go @@ -0,0 +1,63 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "testing" +) + +func TestDisjointSetMakeSet(t *testing.T) { + ds := newDisjointSet() + if ds.master == nil { + t.Fatal("Internal disjoint set map erroneously nil") + } else if len(ds.master) != 0 { + t.Error("Disjoint set master map of wrong size") + } + + ds.makeSet(3) + if len(ds.master) != 1 { + t.Error("Disjoint set master map of wrong size") + } + + if node, ok := ds.master[3]; !ok { + t.Error("Make set did not successfully add element") + } else { + if node == nil { + t.Fatal("Disjoint set node from makeSet is nil") + } + + if node.rank != 0 { + t.Error("Node rank set incorrectly") + } + + if node.parent != node { + t.Error("Node parent set incorrectly") + } + } +} + +func TestDisjointSetFind(t *testing.T) { + ds := newDisjointSet() + + ds.makeSet(3) + ds.makeSet(5) + + if ds.find(3) == ds.find(5) { + t.Error("Disjoint sets incorrectly found to be the same") + } +} + +func TestUnion(t *testing.T) { + ds := newDisjointSet() + + ds.makeSet(3) + ds.makeSet(5) + + ds.union(ds.find(3), ds.find(5)) + + if ds.find(3) != ds.find(5) { + t.Error("Sets found to be disjoint after union") + } +} diff --git a/graph/path/doc.go b/graph/path/doc.go new file mode 100644 index 00000000..2a86fed0 --- /dev/null +++ b/graph/path/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package path provides graph path finding functions. +package path diff --git a/graph/path/dynamic/doc.go b/graph/path/dynamic/doc.go new file mode 100644 index 00000000..597bd956 --- /dev/null +++ b/graph/path/dynamic/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package dynamic provides incremental heuristic graph path finding functions. +package dynamic diff --git a/graph/path/dynamic/dstarlite.go b/graph/path/dynamic/dstarlite.go new file mode 100644 index 00000000..7849f6ed --- /dev/null +++ b/graph/path/dynamic/dstarlite.go @@ -0,0 +1,491 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dynamic + +import ( + "container/heap" + "fmt" + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path" + "gonum.org/v1/gonum/graph/simple" +) + +// DStarLite implements the D* Lite dynamic re-planning path search algorithm. +// +// doi:10.1109/tro.2004.838026 and ISBN:0-262-51129-0 pp476-483 +// +type DStarLite struct { + s, t *dStarLiteNode + last *dStarLiteNode + + model WorldModel + queue dStarLiteQueue + keyModifier float64 + + weight path.Weighting + heuristic path.Heuristic +} + +// WorldModel is a mutable weighted directed graph that returns nodes identified +// by id number. +type WorldModel interface { + graph.DirectedBuilder + graph.Weighter + Node(id int) graph.Node +} + +// NewDStarLite returns a new DStarLite planner for the path from s to t in g using the +// heuristic h. The world model, m, is used to store shortest path information during path +// planning. The world model must be an empty graph when NewDStarLite is called. +// +// If h is nil, the DStarLite will use the g.HeuristicCost method if g implements +// path.HeuristicCoster, falling back to path.NullHeuristic otherwise. If the graph does not +// implement graph.Weighter, path.UniformCost is used. NewDStarLite will panic if g has +// a negative edge weight. +func NewDStarLite(s, t graph.Node, g graph.Graph, h path.Heuristic, m WorldModel) *DStarLite { + /* + procedure Initialize() + {02”} U = ∅; + {03”} k_m = 0; + {04”} for all s ∈ S rhs(s) = g(s) = ∞; + {05”} rhs(s_goal) = 0; + {06”} U.Insert(s_goal, [h(s_start, s_goal); 0]); + */ + + d := &DStarLite{ + s: newDStarLiteNode(s), + t: newDStarLiteNode(t), // badKey is overwritten below. + + model: m, + + heuristic: h, + } + d.t.rhs = 0 + + /* + procedure Main() + {29”} s_last = s_start; + {30”} Initialize(); + */ + d.last = d.s + + if wg, ok := g.(graph.Weighter); ok { + d.weight = wg.Weight + } else { + d.weight = path.UniformCost(g) + } + if d.heuristic == nil { + if g, ok := g.(path.HeuristicCoster); ok { + d.heuristic = g.HeuristicCost + } else { + d.heuristic = path.NullHeuristic + } + } + + d.queue.insert(d.t, key{d.heuristic(s, t), 0}) + + for _, n := range g.Nodes() { + switch n.ID() { + case d.s.ID(): + d.model.AddNode(d.s) + case d.t.ID(): + d.model.AddNode(d.t) + default: + d.model.AddNode(newDStarLiteNode(n)) + } + } + for _, u := range d.model.Nodes() { + for _, v := range g.From(u) { + w := edgeWeight(d.weight, u, v) + if w < 0 { + panic("D* Lite: negative edge weight") + } + d.model.SetEdge(simple.Edge{F: u, T: d.model.Node(v.ID()), W: w}) + } + } + + /* + procedure Main() + {31”} ComputeShortestPath(); + */ + d.findShortestPath() + + return d +} + +// edgeWeight is a helper function that returns the weight of the edge between +// two connected nodes, u and v, using the provided weight function. It panics +// if there is no edge between u and v. +func edgeWeight(weight path.Weighting, u, v graph.Node) float64 { + w, ok := weight(u, v) + if !ok { + panic("D* Lite: unexpected invalid weight") + } + return w +} + +// keyFor is the CalculateKey procedure in the D* Lite papers. +func (d *DStarLite) keyFor(s *dStarLiteNode) key { + /* + procedure CalculateKey(s) + {01”} return [min(g(s), rhs(s)) + h(s_start, s) + k_m; min(g(s), rhs(s))]; + */ + k := key{1: math.Min(s.g, s.rhs)} + k[0] = k[1] + d.heuristic(d.s.Node, s.Node) + d.keyModifier + return k +} + +// update is the UpdateVertex procedure in the D* Lite papers. +func (d *DStarLite) update(u *dStarLiteNode) { + /* + procedure UpdateVertex(u) + {07”} if (g(u) != rhs(u) AND u ∈ U) U.Update(u,CalculateKey(u)); + {08”} else if (g(u) != rhs(u) AND u /∈ U) U.Insert(u,CalculateKey(u)); + {09”} else if (g(u) = rhs(u) AND u ∈ U) U.Remove(u); + */ + inQueue := u.inQueue() + switch { + case inQueue && u.g != u.rhs: + d.queue.update(u, d.keyFor(u)) + case !inQueue && u.g != u.rhs: + d.queue.insert(u, d.keyFor(u)) + case inQueue && u.g == u.rhs: + d.queue.remove(u) + } +} + +// findShortestPath is the ComputeShortestPath procedure in the D* Lite papers. +func (d *DStarLite) findShortestPath() { + /* + procedure ComputeShortestPath() + {10”} while (U.TopKey() < CalculateKey(s_start) OR rhs(s_start) > g(s_start)) + {11”} u = U.Top(); + {12”} k_old = U.TopKey(); + {13”} k_new = CalculateKey(u); + {14”} if(k_old < k_new) + {15”} U.Update(u, k_new); + {16”} else if (g(u) > rhs(u)) + {17”} g(u) = rhs(u); + {18”} U.Remove(u); + {19”} for all s ∈ Pred(u) + {20”} if (s != s_goal) rhs(s) = min(rhs(s), c(s, u) + g(u)); + {21”} UpdateVertex(s); + {22”} else + {23”} g_old = g(u); + {24”} g(u) = ∞; + {25”} for all s ∈ Pred(u) ∪ {u} + {26”} if (rhs(s) = c(s, u) + g_old) + {27”} if (s != s_goal) rhs(s) = min s'∈Succ(s)(c(s, s') + g(s')); + {28”} UpdateVertex(s); + */ + for d.queue.Len() != 0 { // We use d.queue.Len since d.queue does not return an infinite key when empty. + u := d.queue.top() + if !u.key.less(d.keyFor(d.s)) && d.s.rhs <= d.s.g { + break + } + switch kNew := d.keyFor(u); { + case u.key.less(kNew): + d.queue.update(u, kNew) + case u.g > u.rhs: + u.g = u.rhs + d.queue.remove(u) + for _, _s := range d.model.To(u) { + s := _s.(*dStarLiteNode) + if s.ID() != d.t.ID() { + s.rhs = math.Min(s.rhs, edgeWeight(d.model.Weight, s, u)+u.g) + } + d.update(s) + } + default: + gOld := u.g + u.g = math.Inf(1) + for _, _s := range append(d.model.To(u), u) { + s := _s.(*dStarLiteNode) + if s.rhs == edgeWeight(d.model.Weight, s, u)+gOld { + if s.ID() != d.t.ID() { + s.rhs = math.Inf(1) + for _, t := range d.model.From(s) { + s.rhs = math.Min(s.rhs, edgeWeight(d.model.Weight, s, t)+t.(*dStarLiteNode).g) + } + } + } + d.update(s) + } + } + } +} + +// Step performs one movement step along the best path towards the goal. +// It returns false if no further progression toward the goal can be +// achieved, either because the goal has been reached or because there +// is no path. +func (d *DStarLite) Step() bool { + /* + procedure Main() + {32”} while (s_start != s_goal) + {33”} // if (rhs(s_start) = ∞) then there is no known path + {34”} s_start = argmin s'∈Succ(s_start)(c(s_start, s') + g(s')); + */ + if d.s.ID() == d.t.ID() { + return false + } + if math.IsInf(d.s.rhs, 1) { + return false + } + + // We use rhs comparison to break ties + // between coequally weighted nodes. + rhs := math.Inf(1) + min := math.Inf(1) + + var next *dStarLiteNode + for _, _s := range d.model.From(d.s) { + s := _s.(*dStarLiteNode) + w := edgeWeight(d.model.Weight, d.s, s) + s.g + if w < min || (w == min && s.rhs < rhs) { + next = s + min = w + rhs = s.rhs + } + } + d.s = next + + /* + procedure Main() + {35”} Move to s_start; + */ + return true +} + +// MoveTo moves to n in the world graph. +func (d *DStarLite) MoveTo(n graph.Node) { + d.last = d.s + d.s = d.model.Node(n.ID()).(*dStarLiteNode) + d.keyModifier += d.heuristic(d.last, d.s) +} + +// UpdateWorld updates or adds edges in the world graph. UpdateWorld will +// panic if changes include a negative edge weight. +func (d *DStarLite) UpdateWorld(changes []graph.Edge) { + /* + procedure Main() + {36”} Scan graph for changed edge costs; + {37”} if any edge costs changed + {38”} k_m = k_m + h(s_last, s_start); + {39”} s_last = s_start; + {40”} for all directed edges (u, v) with changed edge costs + {41”} c_old = c(u, v); + {42”} Update the edge cost c(u, v); + {43”} if (c_old > c(u, v)) + {44”} if (u != s_goal) rhs(u) = min(rhs(u), c(u, v) + g(v)); + {45”} else if (rhs(u) = c_old + g(v)) + {46”} if (u != s_goal) rhs(u) = min s'∈Succ(u)(c(u, s') + g(s')); + {47”} UpdateVertex(u); + {48”} ComputeShortestPath() + */ + if len(changes) == 0 { + return + } + d.keyModifier += d.heuristic(d.last, d.s) + d.last = d.s + for _, e := range changes { + from := e.From() + to := e.To() + c, _ := d.weight(from, to) + if c < 0 { + panic("D* Lite: negative edge weight") + } + cOld, _ := d.model.Weight(from, to) + u := d.worldNodeFor(from) + v := d.worldNodeFor(to) + d.model.SetEdge(simple.Edge{F: u, T: v, W: c}) + if cOld > c { + if u.ID() != d.t.ID() { + u.rhs = math.Min(u.rhs, c+v.g) + } + } else if u.rhs == cOld+v.g { + if u.ID() != d.t.ID() { + u.rhs = math.Inf(1) + for _, t := range d.model.From(u) { + u.rhs = math.Min(u.rhs, edgeWeight(d.model.Weight, u, t)+t.(*dStarLiteNode).g) + } + } + } + d.update(u) + } + d.findShortestPath() +} + +func (d *DStarLite) worldNodeFor(n graph.Node) *dStarLiteNode { + switch w := d.model.Node(n.ID()).(type) { + case *dStarLiteNode: + return w + case graph.Node: + panic(fmt.Sprintf("D* Lite: illegal world model node type: %T", w)) + default: + return newDStarLiteNode(n) + } +} + +// Here returns the current location. +func (d *DStarLite) Here() graph.Node { + return d.s.Node +} + +// Path returns the path from the current location to the goal and the +// weight of the path. +func (d *DStarLite) Path() (p []graph.Node, weight float64) { + u := d.s + p = []graph.Node{u.Node} + for u.ID() != d.t.ID() { + if math.IsInf(u.rhs, 1) { + return nil, math.Inf(1) + } + + // We use stored rhs comparison to break + // ties between calculated rhs-coequal nodes. + rhsMin := math.Inf(1) + min := math.Inf(1) + var ( + next *dStarLiteNode + cost float64 + ) + for _, _v := range d.model.From(u) { + v := _v.(*dStarLiteNode) + w := edgeWeight(d.model.Weight, u, v) + if rhs := w + v.g; rhs < min || (rhs == min && v.rhs < rhsMin) { + next = v + min = rhs + rhsMin = v.rhs + cost = w + } + } + if next == nil { + return nil, math.NaN() + } + u = next + weight += cost + p = append(p, u.Node) + } + return p, weight +} + +/* +The pseudocode uses the following functions to manage the priority +queue: + + * U.Top() returns a vertex with the smallest priority of all + vertices in priority queue U. + * U.TopKey() returns the smallest priority of all vertices in + priority queue U. (If is empty, then U.TopKey() returns [∞;∞].) + * U.Pop() deletes the vertex with the smallest priority in + priority queue U and returns the vertex. + * U.Insert(s, k) inserts vertex s into priority queue with + priority k. + * U.Update(s, k) changes the priority of vertex s in priority + queue U to k. (It does nothing if the current priority of vertex + s already equals k.) + * Finally, U.Remove(s) removes vertex s from priority queue U. +*/ + +// key is a D* Lite priority queue key. +type key [2]float64 + +var badKey = key{math.NaN(), math.NaN()} + +// less returns whether k is less than other. From ISBN:0-262-51129-0 pp476-483: +// +// k ≤ k' iff k₁ < k'₁ OR (k₁ == k'₁ AND k₂ ≤ k'₂) +// +func (k key) less(other key) bool { + if k != k || other != other { + panic("D* Lite: poisoned key") + } + return k[0] < other[0] || (k[0] == other[0] && k[1] < other[1]) +} + +// dStarLiteNode adds D* Lite accounting to a graph.Node. +type dStarLiteNode struct { + graph.Node + key key + idx int + rhs float64 + g float64 +} + +// newDStarLiteNode returns a dStarLite node that is in a legal state +// for existence outside the DStarLite priority queue. +func newDStarLiteNode(n graph.Node) *dStarLiteNode { + return &dStarLiteNode{ + Node: n, + rhs: math.Inf(1), + g: math.Inf(1), + key: badKey, + idx: -1, + } +} + +// inQueue returns whether the node is in the queue. +func (q *dStarLiteNode) inQueue() bool { + return q.idx >= 0 +} + +// dStarLiteQueue is a D* Lite priority queue. +type dStarLiteQueue []*dStarLiteNode + +func (q dStarLiteQueue) Less(i, j int) bool { + return q[i].key.less(q[j].key) +} + +func (q dStarLiteQueue) Swap(i, j int) { + q[i], q[j] = q[j], q[i] + q[i].idx = i + q[j].idx = j +} + +func (q dStarLiteQueue) Len() int { + return len(q) +} + +func (q *dStarLiteQueue) Push(x interface{}) { + n := x.(*dStarLiteNode) + n.idx = len(*q) + *q = append(*q, n) +} + +func (q *dStarLiteQueue) Pop() interface{} { + n := (*q)[len(*q)-1] + n.idx = -1 + *q = (*q)[:len(*q)-1] + return n +} + +// top returns the top node in the queue. Note that instead of +// returning a key [∞;∞] when q is empty, the caller checks for +// an empty queue by calling q.Len. +func (q dStarLiteQueue) top() *dStarLiteNode { + return q[0] +} + +// insert puts the node u into the queue with the key k. +func (q *dStarLiteQueue) insert(u *dStarLiteNode, k key) { + u.key = k + heap.Push(q, u) +} + +// update updates the node in the queue identified by id with the key k. +func (q *dStarLiteQueue) update(n *dStarLiteNode, k key) { + n.key = k + heap.Fix(q, n.idx) +} + +// remove removes the node identified by id from the queue. +func (q *dStarLiteQueue) remove(n *dStarLiteNode) { + heap.Remove(q, n.idx) + n.key = badKey + n.idx = -1 +} diff --git a/graph/path/dynamic/dstarlite_test.go b/graph/path/dynamic/dstarlite_test.go new file mode 100644 index 00000000..4a8f239b --- /dev/null +++ b/graph/path/dynamic/dstarlite_test.go @@ -0,0 +1,685 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dynamic + +import ( + "bytes" + "flag" + "fmt" + "math" + "reflect" + "strings" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/path" + "gonum.org/v1/gonum/graph/path/internal" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" + "gonum.org/v1/gonum/graph/simple" +) + +var ( + debug = flag.Bool("debug", false, "write path progress for failing dynamic case tests") + vdebug = flag.Bool("vdebug", false, "write path progress for all dynamic case tests (requires test.v)") + maxWide = flag.Int("maxwidth", 5, "maximum width grid to dump for debugging") +) + +func TestDStarLiteNullHeuristic(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + // Skip zero-weight cycles. + if strings.HasPrefix(test.Name, "zero-weight") { + continue + } + + g := test.Graph() + for _, e := range test.Edges { + g.SetEdge(e) + } + + var ( + d *DStarLite + + panicked bool + ) + func() { + defer func() { + panicked = recover() != nil + }() + d = NewDStarLite(test.Query.From(), test.Query.To(), g.(graph.Graph), path.NullHeuristic, simple.NewDirectedGraph(0, math.Inf(1))) + }() + if panicked || test.HasNegativeWeight { + if !test.HasNegativeWeight { + t.Errorf("%q: unexpected panic", test.Name) + } + if !panicked { + t.Errorf("%q: expected panic for negative edge weight", test.Name) + } + continue + } + + p, weight := d.Path() + + if !math.IsInf(weight, 1) && p[0].ID() != test.Query.From().ID() { + t.Fatalf("%q: unexpected from node ID: got:%d want:%d", p[0].ID(), test.Query.From().ID()) + } + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got []int + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + } +} + +var dynamicDStarLiteTests = []struct { + g *internal.Grid + radius float64 + all bool + diag, unit bool + remember []bool + modify func(*internal.LimitedVisionGrid) + + heuristic func(dx, dy float64) float64 + + s, t graph.Node + + want []graph.Node + weight float64 + wantedPaths map[int][]graph.Node +}{ + { + // This is the example shown in figures 6 and 7 of doi:10.1109/tro.2004.838026. + g: internal.NewGridFrom( + "...", + ".*.", + ".*.", + ".*.", + "...", + ), + radius: 1.5, + all: true, + diag: true, + unit: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(3), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(3), + simple.Node(6), + simple.Node(9), + simple.Node(13), + simple.Node(14), + }, + weight: 4, + }, + { + // This is a small example that has the property that the first corner + // may be taken incorrectly at 90° or correctly at 45° because the + // calculated rhs values of 12 and 17 are tied when moving from node + // 16, and the grid is small enough to examine by a dump. + g: internal.NewGridFrom( + ".....", + "...*.", + "**.*.", + "...*.", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(15), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(15), + simple.Node(16), + simple.Node(12), + simple.Node(7), + simple.Node(3), + simple.Node(9), + simple.Node(14), + }, + weight: 7.242640687119285, + wantedPaths: map[int][]graph.Node{ + 12: []graph.Node{simple.Node(12), simple.Node(7), simple.Node(3), simple.Node(9), simple.Node(14)}, + }, + }, + { + // This is the example shown in figure 2 of doi:10.1109/tro.2004.838026 + // with the exception that diagonal edge weights are calculated with the hypot + // function instead of a step count and only allowing information to be known + // from exploration. + g: internal.NewGridFrom( + "..................", + "..................", + "..................", + "..................", + "..................", + "..................", + "....*.*...........", + "*****.***.........", + "......*...........", + "......***.........", + "......*...........", + "......*...........", + "......*...........", + "*****.*...........", + "......*...........", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(253), + t: simple.Node(122), + + want: []graph.Node{ + simple.Node(253), + simple.Node(254), + simple.Node(255), + simple.Node(256), + simple.Node(239), + simple.Node(221), + simple.Node(203), + simple.Node(185), + simple.Node(167), + simple.Node(149), + simple.Node(131), + simple.Node(113), + simple.Node(96), + + // The following section depends + // on map iteration order. + nil, + nil, + nil, + nil, + nil, + nil, + nil, + + simple.Node(122), + }, + weight: 21.242640687119287, + }, + { + // This is the example shown in figure 2 of doi:10.1109/tro.2004.838026 + // with the exception that diagonal edge weights are calculated with the hypot + // function instead of a step count, not closing the exit and only allowing + // information to be known from exploration. + g: internal.NewGridFrom( + "..................", + "..................", + "..................", + "..................", + "..................", + "..................", + "....*.*...........", + "*****.***.........", + "..................", // Keep open. + "......***.........", + "......*...........", + "......*...........", + "......*...........", + "*****.*...........", + "......*...........", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(253), + t: simple.Node(122), + + want: []graph.Node{ + simple.Node(253), + simple.Node(254), + simple.Node(255), + simple.Node(256), + simple.Node(239), + simple.Node(221), + simple.Node(203), + simple.Node(185), + simple.Node(167), + simple.Node(150), + simple.Node(151), + simple.Node(152), + + // The following section depends + // on map iteration order. + nil, + nil, + nil, + nil, + nil, + + simple.Node(122), + }, + weight: 18.656854249492383, + }, + { + // This is the example shown in figure 2 of doi:10.1109/tro.2004.838026 + // with the exception that diagonal edge weights are calculated with the hypot + // function instead of a step count, the exit is closed at a distance and + // information is allowed to be known from exploration. + g: internal.NewGridFrom( + "..................", + "..................", + "..................", + "..................", + "..................", + "..................", + "....*.*...........", + "*****.***.........", + "........*.........", + "......***.........", + "......*...........", + "......*...........", + "......*...........", + "*****.*...........", + "......*...........", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(253), + t: simple.Node(122), + + want: []graph.Node{ + simple.Node(253), + simple.Node(254), + simple.Node(255), + simple.Node(256), + simple.Node(239), + simple.Node(221), + simple.Node(203), + simple.Node(185), + simple.Node(167), + simple.Node(150), + simple.Node(151), + simple.Node(150), + simple.Node(131), + simple.Node(113), + simple.Node(96), + + // The following section depends + // on map iteration order. + nil, + nil, + nil, + nil, + nil, + nil, + nil, + + simple.Node(122), + }, + weight: 24.07106781186548, + }, + { + // This is the example shown in figure 2 of doi:10.1109/tro.2004.838026 + // with the exception that diagonal edge weights are calculated with the hypot + // function instead of a step count. + g: internal.NewGridFrom( + "..................", + "..................", + "..................", + "..................", + "..................", + "..................", + "....*.*...........", + "*****.***.........", + "......*...........", // Forget this wall. + "......***.........", + "......*...........", + "......*...........", + "......*...........", + "*****.*...........", + "......*...........", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{true}, + + modify: func(l *internal.LimitedVisionGrid) { + all := l.Grid.AllVisible + l.Grid.AllVisible = false + for _, n := range l.Nodes() { + l.Known[n.ID()] = !l.Grid.Has(n) + } + l.Grid.AllVisible = all + + const ( + wallRow = 8 + wallCol = 6 + ) + l.Known[l.NodeAt(wallRow, wallCol).ID()] = false + + // Check we have a correctly modified representation. + for _, u := range l.Nodes() { + for _, v := range l.Nodes() { + if l.HasEdgeBetween(u, v) != l.Grid.HasEdgeBetween(u, v) { + ur, uc := l.RowCol(u.ID()) + vr, vc := l.RowCol(v.ID()) + if (ur == wallRow && uc == wallCol) || (vr == wallRow && vc == wallCol) { + if !l.HasEdgeBetween(u, v) { + panic(fmt.Sprintf("expected to believe edge between %v (%d,%d) and %v (%d,%d) is passable", + u, v, ur, uc, vr, vc)) + } + continue + } + panic(fmt.Sprintf("disagreement about edge between %v (%d,%d) and %v (%d,%d): got:%t want:%t", + u, v, ur, uc, vr, vc, l.HasEdgeBetween(u, v), l.Grid.HasEdgeBetween(u, v))) + } + } + } + }, + + heuristic: func(dx, dy float64) float64 { + return math.Max(math.Abs(dx), math.Abs(dy)) + }, + + s: simple.Node(253), + t: simple.Node(122), + + want: []graph.Node{ + simple.Node(253), + simple.Node(254), + simple.Node(255), + simple.Node(256), + simple.Node(239), + simple.Node(221), + simple.Node(203), + simple.Node(185), + simple.Node(167), + simple.Node(149), + simple.Node(131), + simple.Node(113), + simple.Node(96), + + // The following section depends + // on map iteration order. + nil, + nil, + nil, + nil, + nil, + nil, + nil, + + simple.Node(122), + }, + weight: 21.242640687119287, + }, + { + g: internal.NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + all: true, + diag: false, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Hypot(dx, dy) + }, + + s: simple.Node(1), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(1), + simple.Node(2), + simple.Node(6), + simple.Node(10), + simple.Node(14), + }, + weight: 4, + }, + { + g: internal.NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + all: true, + diag: true, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Hypot(dx, dy) + }, + + s: simple.Node(1), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(1), + simple.Node(6), + simple.Node(10), + simple.Node(14), + }, + weight: math.Sqrt2 + 2, + }, + { + g: internal.NewGridFrom( + "...", + ".*.", + ".*.", + ".*.", + ".*.", + ), + radius: 1, + all: true, + diag: false, + remember: []bool{false, true}, + + heuristic: func(dx, dy float64) float64 { + return math.Hypot(dx, dy) + }, + + s: simple.Node(6), + t: simple.Node(14), + + want: []graph.Node{ + simple.Node(6), + simple.Node(9), + simple.Node(12), + simple.Node(9), + simple.Node(6), + simple.Node(3), + simple.Node(0), + simple.Node(1), + simple.Node(2), + simple.Node(5), + simple.Node(8), + simple.Node(11), + simple.Node(14), + }, + weight: 12, + }, +} + +func TestDStarLiteDynamic(t *testing.T) { + for i, test := range dynamicDStarLiteTests { + for _, remember := range test.remember { + l := &internal.LimitedVisionGrid{ + Grid: test.g, + VisionRadius: test.radius, + Location: test.s, + } + if remember { + l.Known = make(map[int]bool) + } + + l.Grid.AllVisible = test.all + + l.Grid.AllowDiagonal = test.diag + l.Grid.UnitEdgeWeight = test.unit + + if test.modify != nil { + test.modify(l) + } + + got := []graph.Node{test.s} + l.MoveTo(test.s) + + heuristic := func(a, b graph.Node) float64 { + ax, ay := l.XY(a) + bx, by := l.XY(b) + return test.heuristic(ax-bx, ay-by) + } + + world := simple.NewDirectedGraph(0, math.Inf(1)) + d := NewDStarLite(test.s, test.t, l, heuristic, world) + var ( + dp *dumper + buf bytes.Buffer + ) + _, c := l.Grid.Dims() + if c <= *maxWide && (*debug || *vdebug) { + dp = &dumper{ + w: &buf, + + dStarLite: d, + grid: l, + } + } + + dp.dump(true) + dp.printEdges("Initial world knowledge: %s\n\n", simpleEdgesOf(l, world.Edges())) + for d.Step() { + changes, _ := l.MoveTo(d.Here()) + got = append(got, l.Location) + d.UpdateWorld(changes) + dp.dump(true) + if wantedPath, ok := test.wantedPaths[l.Location.ID()]; ok { + gotPath, _ := d.Path() + if !samePath(gotPath, wantedPath) { + t.Errorf("unexpected intermediate path estimation for test %d %s memory:\ngot: %v\nwant:%v", + i, memory(remember), gotPath, wantedPath) + } + } + dp.printEdges("Edges changing after last step:\n%s\n\n", simpleEdgesOf(l, changes)) + } + + if weight := weightOf(got, l.Grid); !samePath(got, test.want) || weight != test.weight { + t.Errorf("unexpected path for test %d %s memory got weight:%v want weight:%v:\ngot: %v\nwant:%v", + i, memory(remember), weight, test.weight, got, test.want) + b, err := l.Render(got) + t.Errorf("path taken (err:%v):\n%s", err, b) + if c <= *maxWide && (*debug || *vdebug) { + t.Error(buf.String()) + } + } else if c <= *maxWide && *vdebug { + t.Logf("Test %d:\n%s", i, buf.String()) + } + } + } +} + +type memory bool + +func (m memory) String() string { + if m { + return "with" + } + return "without" +} + +// samePath compares two paths for equality ignoring nodes that are nil. +func samePath(a, b []graph.Node) bool { + if len(a) != len(b) { + return false + } + for i, e := range a { + if e == nil || b[i] == nil { + continue + } + if e.ID() != b[i].ID() { + return false + } + } + return true +} + +type weightedGraph interface { + graph.Graph + graph.Weighter +} + +// weightOf return the weight of the path in g. +func weightOf(path []graph.Node, g weightedGraph) float64 { + var w float64 + if len(path) > 1 { + for p, n := range path[1:] { + ew, ok := g.Weight(path[p], n) + if !ok { + return math.Inf(1) + } + w += ew + } + } + return w +} + +// simpleEdgesOf returns the weighted edges in g corresponding to the given edges. +func simpleEdgesOf(g weightedGraph, edges []graph.Edge) []simple.Edge { + w := make([]simple.Edge, len(edges)) + for i, e := range edges { + w[i].F = e.From() + w[i].T = e.To() + ew, _ := g.Weight(e.From(), e.To()) + w[i].W = ew + } + return w +} diff --git a/graph/path/dynamic/dumper_test.go b/graph/path/dynamic/dumper_test.go new file mode 100644 index 00000000..75e31b36 --- /dev/null +++ b/graph/path/dynamic/dumper_test.go @@ -0,0 +1,153 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dynamic + +import ( + "bytes" + "fmt" + "io" + "sort" + "text/tabwriter" + + "gonum.org/v1/gonum/graph/path/internal" + "gonum.org/v1/gonum/graph/simple" +) + +// dumper implements a grid D* Lite statistics dump. +type dumper struct { + step int + + dStarLite *DStarLite + grid *internal.LimitedVisionGrid + + w io.Writer +} + +// dump writes a single step of a D* Lite path search to the dumper's io.Writer. +func (d *dumper) dump(withpath bool) { + if d == nil { + return + } + var pathStep map[int]int + if withpath { + pathStep = make(map[int]int) + path, _ := d.dStarLite.Path() + for i, n := range path { + pathStep[n.ID()] = i + } + } + fmt.Fprintf(d.w, "Step:%d kₘ=%v\n", d.step, d.dStarLite.keyModifier) + d.step++ + w := tabwriter.NewWriter(d.w, 0, 0, 0, ' ', tabwriter.Debug) + rows, cols := d.grid.Grid.Dims() + for r := 0; r < rows; r++ { + if r == 0 { + for c := 0; c < cols; c++ { + if c != 0 { + fmt.Fprint(w, "\t") + } + fmt.Fprint(w, "-------------------") + } + fmt.Fprintln(w) + } + for ln := 0; ln < 6; ln++ { + for c := 0; c < cols; c++ { + if c != 0 { + fmt.Fprint(w, "\t") + } + n := d.dStarLite.model.Node(d.grid.NodeAt(r, c).ID()).(*dStarLiteNode) + switch ln { + case 0: + if n.ID() == d.grid.Location.ID() { + if d.grid.Grid.HasOpen(n) { + fmt.Fprintf(w, "id:%2d >@<", n.ID()) + } else { + // Mark location as illegal. + fmt.Fprintf(w, "id:%2d >!<", n.ID()) + } + } else if n.ID() == d.dStarLite.t.ID() { + fmt.Fprintf(w, "id:%2d G", n.ID()) + // Mark goal cell as illegal. + if !d.grid.Grid.HasOpen(n) { + fmt.Fprint(w, "!") + } + } else if pathStep[n.ID()] > 0 { + fmt.Fprintf(w, "id:%2d %2d", n.ID(), pathStep[n.ID()]) + // Mark path cells with an obstruction. + if !d.grid.Grid.HasOpen(n) { + fmt.Fprint(w, "!") + } + } else { + fmt.Fprintf(w, "id:%2d", n.ID()) + // Mark cells with an obstruction. + if !d.grid.Grid.HasOpen(n) { + fmt.Fprint(w, " *") + } + } + case 1: + fmt.Fprintf(w, "h: %.4v", d.dStarLite.heuristic(n, d.dStarLite.Here())) + case 2: + fmt.Fprintf(w, "g: %.4v", n.g) + case 3: + fmt.Fprintf(w, "rhs:%.4v", n.rhs) + case 4: + if n.g != n.rhs { + fmt.Fprintf(w, "key:%.3f", n.key) + } + if n.key == n.key { + // Mark keys for nodes in the priority queue. + // We use NaN inequality for this check since all + // keys not in the queue must have their key set + // to badKey. + // + // This should always mark cells where key is + // printed. + fmt.Fprint(w, "*") + } + if n.g > n.rhs { + fmt.Fprint(w, "^") + } + if n.g < n.rhs { + fmt.Fprint(w, "v") + } + default: + fmt.Fprint(w, "-------------------") + } + } + fmt.Fprintln(w) + } + } + w.Flush() + fmt.Fprintln(d.w) +} + +// printEdges pretty prints the given edges to the dumper's io.Writer using the provided +// format string. The edges are first formated to a string, so the format string must use +// the %s verb to indicate where the edges are to be printed. +func (d *dumper) printEdges(format string, edges []simple.Edge) { + if d == nil { + return + } + var buf bytes.Buffer + sort.Sort(lexically(edges)) + for i, e := range edges { + if i != 0 { + fmt.Fprint(&buf, ", ") + } + fmt.Fprintf(&buf, "%d->%d:%.4v", e.From().ID(), e.To().ID(), e.Weight()) + } + if len(edges) == 0 { + fmt.Fprint(&buf, "none") + } + fmt.Fprintf(d.w, format, buf.Bytes()) +} + +type lexically []simple.Edge + +func (l lexically) Len() int { return len(l) } +func (l lexically) Less(i, j int) bool { + return l[i].From().ID() < l[j].From().ID() || (l[i].From().ID() == l[j].From().ID() && l[i].To().ID() < l[j].To().ID()) +} +func (l lexically) Swap(i, j int) { l[i], l[j] = l[j], l[i] } diff --git a/graph/path/floydwarshall.go b/graph/path/floydwarshall.go new file mode 100644 index 00000000..3f27678f --- /dev/null +++ b/graph/path/floydwarshall.go @@ -0,0 +1,59 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import "gonum.org/v1/gonum/graph" + +// FloydWarshall returns a shortest-path tree for the graph g or false indicating +// that a negative cycle exists in the graph. If the graph does not implement +// graph.Weighter, UniformCost is used. +// +// The time complexity of FloydWarshall is O(|V|^3). +func FloydWarshall(g graph.Graph) (paths AllShortest, ok bool) { + var weight Weighting + if wg, ok := g.(graph.Weighter); ok { + weight = wg.Weight + } else { + weight = UniformCost(g) + } + + nodes := g.Nodes() + paths = newAllShortest(nodes, true) + for i, u := range nodes { + paths.dist.Set(i, i, 0) + for _, v := range g.From(u) { + j := paths.indexOf[v.ID()] + w, ok := weight(u, v) + if !ok { + panic("floyd-warshall: unexpected invalid weight") + } + paths.set(i, j, w, j) + } + } + + for k := range nodes { + for i := range nodes { + for j := range nodes { + ij := paths.dist.At(i, j) + joint := paths.dist.At(i, k) + paths.dist.At(k, j) + if ij > joint { + paths.set(i, j, joint, paths.at(i, k)...) + } else if ij-joint == 0 { + paths.add(i, j, paths.at(i, k)...) + } + } + } + } + + ok = true + for i := range nodes { + if paths.dist.At(i, i) < 0 { + ok = false + break + } + } + + return paths, ok +} diff --git a/graph/path/floydwarshall_test.go b/graph/path/floydwarshall_test.go new file mode 100644 index 00000000..1c2b47f6 --- /dev/null +++ b/graph/path/floydwarshall_test.go @@ -0,0 +1,102 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" +) + +func TestFloydWarshall(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetEdge(e) + } + + pt, ok := FloydWarshall(g.(graph.Graph)) + if test.HasNegativeCycle { + if ok { + t.Errorf("%q: expected negative cycle", test.Name) + } + continue + } + if !ok { + t.Fatalf("%q: unexpected negative cycle", test.Name) + } + + // Check all random paths returned are OK. + for i := 0; i < 10; i++ { + p, weight, unique := pt.Between(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.Weight(test.Query.From(), test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + if unique != test.HasUniquePath { + t.Errorf("%q: unexpected number of paths: got: unique=%t want: unique=%t", + test.Name, unique, test.HasUniquePath) + } + + var got []int + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + } + + np, weight, unique := pt.Between(test.NoPathFor.From(), test.NoPathFor.To()) + if np != nil || !math.IsInf(weight, 1) || unique != false { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f unique=%t\nwant:path= weight=+Inf unique=false", + test.Name, np, weight, unique) + } + + paths, weight := pt.AllBetween(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got [][]int + if len(paths) != 0 { + got = make([][]int, len(paths)) + } + for i, p := range paths { + for _, v := range p { + got[i] = append(got[i], v.ID()) + } + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.WantPaths) { + t.Errorf("testing %q: unexpected shortest paths:\ngot: %v\nwant:%v", + test.Name, got, test.WantPaths) + } + + nps, weight := pt.AllBetween(test.NoPathFor.From(), test.NoPathFor.To()) + if nps != nil || !math.IsInf(weight, 1) { + t.Errorf("%q: unexpected path:\ngot: paths=%v weight=%f\nwant:path= weight=+Inf", + test.Name, nps, weight) + } + } +} diff --git a/graph/path/internal/grid.go b/graph/path/internal/grid.go new file mode 100644 index 00000000..7f0bbc8f --- /dev/null +++ b/graph/path/internal/grid.go @@ -0,0 +1,286 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +import ( + "errors" + "fmt" + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +const ( + Closed = '*' // Closed is the closed grid node representation. + Open = '.' // Open is the open grid node repesentation. + Unknown = '?' // Unknown is the unknown grid node repesentation. +) + +// Grid is a 2D grid planar undirected graph. +type Grid struct { + // AllowDiagonal specifies whether + // diagonally adjacent nodes can + // be connected by an edge. + AllowDiagonal bool + // UnitEdgeWeight specifies whether + // finite edge weights are returned as + // the unit length. Otherwise edge + // weights are the Euclidean distance + // between connected nodes. + UnitEdgeWeight bool + + // AllVisible specifies whether + // non-open nodes are visible + // in calls to Nodes and HasNode. + AllVisible bool + + open []bool + r, c int +} + +// NewGrid returns an r by c grid with all positions +// set to the specified open state. +func NewGrid(r, c int, open bool) *Grid { + states := make([]bool, r*c) + if open { + for i := range states { + states[i] = true + } + } + return &Grid{ + open: states, + r: r, + c: c, + } +} + +// NewGridFrom returns a grid specified by the rows strings. All rows must +// be the same length and must only contain the Open or Closed characters, +// NewGridFrom will panic otherwise. +func NewGridFrom(rows ...string) *Grid { + if len(rows) == 0 { + return nil + } + for i, r := range rows[:len(rows)-1] { + if len(r) != len(rows[i+1]) { + panic("grid: unequal row lengths") + } + } + states := make([]bool, 0, len(rows)*len(rows[0])) + for _, r := range rows { + for _, b := range r { + switch b { + case Closed: + states = append(states, false) + case Open: + states = append(states, true) + default: + panic(fmt.Sprintf("grid: invalid state: %q", r)) + } + } + } + return &Grid{ + open: states, + r: len(rows), + c: len(rows[0]), + } +} + +// Nodes returns all the open nodes in the grid if AllVisible is +// false, otherwise all nodes are returned. +func (g *Grid) Nodes() []graph.Node { + var nodes []graph.Node + for id, ok := range g.open { + if ok || g.AllVisible { + nodes = append(nodes, simple.Node(id)) + } + } + return nodes +} + +// Has returns whether n is a node in the grid. The state of +// the AllVisible field determines whether a non-open node is +// present. +func (g *Grid) Has(n graph.Node) bool { + return g.has(n.ID()) +} + +func (g *Grid) has(id int) bool { + return id >= 0 && id < len(g.open) && (g.AllVisible || g.open[id]) +} + +// HasOpen returns whether n is an open node in the grid. +func (g *Grid) HasOpen(n graph.Node) bool { + id := n.ID() + return id >= 0 && id < len(g.open) && g.open[id] +} + +// Set sets the node at position (r, c) to the specified open state. +func (g *Grid) Set(r, c int, open bool) { + if r < 0 || r >= g.r { + panic("grid: illegal row index") + } + if c < 0 || c >= g.c { + panic("grid: illegal column index") + } + g.open[r*g.c+c] = open +} + +// Dims returns the dimensions of the grid. +func (g *Grid) Dims() (r, c int) { + return g.r, g.c +} + +// RowCol returns the row and column of the id. RowCol will panic if the +// node id is outside the range of the grid. +func (g *Grid) RowCol(id int) (r, c int) { + if id < 0 || id >= len(g.open) { + panic("grid: illegal node id") + } + return id / g.c, id % g.c +} + +// XY returns the cartesian coordinates of n. If n is not a node +// in the grid, (NaN, NaN) is returned. +func (g *Grid) XY(n graph.Node) (x, y float64) { + if !g.Has(n) { + return math.NaN(), math.NaN() + } + r, c := g.RowCol(n.ID()) + return float64(c), float64(r) +} + +// NodeAt returns the node at (r, c). The returned node may be open or closed. +func (g *Grid) NodeAt(r, c int) graph.Node { + if r < 0 || r >= g.r || c < 0 || c >= g.c { + return nil + } + return simple.Node(r*g.c + c) +} + +// From returns all the nodes reachable from u. Reachabilty requires that both +// ends of an edge must be open. +func (g *Grid) From(u graph.Node) []graph.Node { + if !g.HasOpen(u) { + return nil + } + nr, nc := g.RowCol(u.ID()) + var to []graph.Node + for r := nr - 1; r <= nr+1; r++ { + for c := nc - 1; c <= nc+1; c++ { + if v := g.NodeAt(r, c); v != nil && g.HasEdgeBetween(u, v) { + to = append(to, v) + } + } + } + return to +} + +// HasEdgeBetween returns whether there is an edge between u and v. +func (g *Grid) HasEdgeBetween(u, v graph.Node) bool { + if !g.HasOpen(u) || !g.HasOpen(v) || u.ID() == v.ID() { + return false + } + ur, uc := g.RowCol(u.ID()) + vr, vc := g.RowCol(v.ID()) + if abs(ur-vr) > 1 || abs(uc-vc) > 1 { + return false + } + return g.AllowDiagonal || ur == vr || uc == vc +} + +func abs(i int) int { + if i < 0 { + return -i + } + return i +} + +// Edge returns the edge between u and v. +func (g *Grid) Edge(u, v graph.Node) graph.Edge { + return g.EdgeBetween(u, v) +} + +// EdgeBetween returns the edge between u and v. +func (g *Grid) EdgeBetween(u, v graph.Node) graph.Edge { + if g.HasEdgeBetween(u, v) { + if !g.AllowDiagonal || g.UnitEdgeWeight { + return simple.Edge{F: u, T: v, W: 1} + } + ux, uy := g.XY(u) + vx, vy := g.XY(v) + return simple.Edge{F: u, T: v, W: math.Hypot(ux-vx, uy-vy)} + } + return nil +} + +// Weight returns the weight of the given edge. +func (g *Grid) Weight(x, y graph.Node) (w float64, ok bool) { + if x.ID() == y.ID() { + return 0, true + } + if !g.HasEdgeBetween(x, y) { + return math.Inf(1), false + } + if e := g.EdgeBetween(x, y); e != nil { + if !g.AllowDiagonal || g.UnitEdgeWeight { + return 1, true + } + ux, uy := g.XY(e.From()) + vx, vy := g.XY(e.To()) + return math.Hypot(ux-vx, uy-vy), true + } + return math.Inf(1), true +} + +// String returns a string representation of the grid. +func (g *Grid) String() string { + b, _ := g.Render(nil) + return string(b) +} + +// Render returns a text representation of the graph +// with the given path included. If the path is not a path +// in the grid Render returns a non-nil error and the +// path up to that point. +func (g *Grid) Render(path []graph.Node) ([]byte, error) { + b := make([]byte, g.r*(g.c+1)-1) + for r := 0; r < g.r; r++ { + for c := 0; c < g.c; c++ { + if g.open[r*g.c+c] { + b[r*(g.c+1)+c] = Open + } else { + b[r*(g.c+1)+c] = Closed + } + } + if r < g.r-1 { + b[r*(g.c+1)+g.c] = '\n' + } + } + + // We don't use topo.IsPathIn at the outset because we + // want to draw as much as possible before failing. + for i, n := range path { + if !g.Has(n) || (i != 0 && !g.HasEdgeBetween(path[i-1], n)) { + id := n.ID() + if id >= 0 && id < len(g.open) { + r, c := g.RowCol(n.ID()) + b[r*(g.c+1)+c] = '!' + } + return b, errors.New("grid: not a path in graph") + } + r, c := g.RowCol(n.ID()) + switch i { + case len(path) - 1: + b[r*(g.c+1)+c] = 'G' + case 0: + b[r*(g.c+1)+c] = 'S' + default: + b[r*(g.c+1)+c] = 'o' + } + } + return b, nil +} diff --git a/graph/path/internal/grid_test.go b/graph/path/internal/grid_test.go new file mode 100644 index 00000000..89711e3f --- /dev/null +++ b/graph/path/internal/grid_test.go @@ -0,0 +1,258 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +import ( + "bytes" + "errors" + "reflect" + "strings" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +var _ graph.Graph = (*Grid)(nil) + +func join(g ...string) string { return strings.Join(g, "\n") } + +type node int + +func (n node) ID() int { return int(n) } + +func TestGrid(t *testing.T) { + g := NewGrid(4, 4, false) + + got := g.String() + want := join( + "****", + "****", + "****", + "****", + ) + if got != want { + t.Fatalf("unexpected grid rendering:\ngot: %q\nwant:%q", got, want) + } + + var ops = []struct { + r, c int + state bool + want string + }{ + { + r: 0, c: 1, + state: true, + want: join( + "*.**", + "****", + "****", + "****", + ), + }, + { + r: 0, c: 1, + state: false, + want: join( + "****", + "****", + "****", + "****", + ), + }, + { + r: 0, c: 1, + state: true, + want: join( + "*.**", + "****", + "****", + "****", + ), + }, + { + r: 0, c: 2, + state: true, + want: join( + "*..*", + "****", + "****", + "****", + ), + }, + { + r: 1, c: 2, + state: true, + want: join( + "*..*", + "**.*", + "****", + "****", + ), + }, + { + r: 2, c: 2, + state: true, + want: join( + "*..*", + "**.*", + "**.*", + "****", + ), + }, + { + r: 3, c: 2, + state: true, + want: join( + "*..*", + "**.*", + "**.*", + "**.*", + ), + }, + } + for _, test := range ops { + g.Set(test.r, test.c, test.state) + got := g.String() + if got != test.want { + t.Fatalf("unexpected grid rendering after set (%d, %d) open state to %t:\ngot: %q\nwant:%q", + test.r, test.c, test.state, got, test.want) + } + } + + // Match the last state from the loop against the + // explicit description of the grid. + got = NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ).String() + want = g.String() + if got != want { + t.Fatalf("unexpected grid rendering from NewGridFrom:\ngot: %q\nwant:%q", got, want) + } + + var paths = []struct { + path []graph.Node + diagonal bool + want string + }{ + { + path: nil, + diagonal: false, + want: join( + "*..*", + "**.*", + "**.*", + "**.*", + ), + }, + { + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + diagonal: false, + want: join( + "*So*", + "**o*", + "**o*", + "**G*", + ), + }, + { + path: []graph.Node{node(1), node(6), node(10), node(14)}, + diagonal: false, + want: join( + "*S.*", + "**!*", + "**.*", + "**.*", + ), + }, + { + path: []graph.Node{node(1), node(6), node(10), node(14)}, + diagonal: true, + want: join( + "*S.*", + "**o*", + "**o*", + "**G*", + ), + }, + { + path: []graph.Node{node(1), node(5), node(9)}, + diagonal: false, + want: join( + "*S.*", + "*!.*", + "**.*", + "**.*", + ), + }, + } + for _, test := range paths { + g.AllowDiagonal = test.diagonal + got, err := g.Render(test.path) + errored := err != nil + if bytes.Contains(got, []byte{'!'}) != errored { + t.Fatalf("unexpected error return: got:%v want:%v", err, errors.New("grid: not a path in graph")) + } + if string(got) != test.want { + t.Fatalf("unexpected grid path rendering for %v:\ngot: %q\nwant:%q", test.path, got, want) + } + } + + var coords = []struct { + r, c int + id int + }{ + {r: 0, c: 0, id: 0}, + {r: 0, c: 3, id: 3}, + {r: 3, c: 0, id: 12}, + {r: 3, c: 3, id: 15}, + } + for _, test := range coords { + if id := g.NodeAt(test.r, test.c).ID(); id != test.id { + t.Fatalf("unexpected ID for node at (%d, %d):\ngot: %d\nwant:%d", test.r, test.c, id, test.id) + } + if r, c := g.RowCol(test.id); r != test.r || c != test.c { + t.Fatalf("unexpected row/col for node %d:\ngot: (%d, %d)\nwant:(%d, %d)", test.id, r, c, test.r, test.c) + } + } + + var reach = []struct { + from graph.Node + diagonal bool + to []graph.Node + }{ + { + from: node(0), + diagonal: false, + to: nil, + }, + { + from: node(2), + diagonal: false, + to: []graph.Node{simple.Node(1), simple.Node(6)}, + }, + { + from: node(1), + diagonal: false, + to: []graph.Node{simple.Node(2)}, + }, + { + from: node(1), + diagonal: true, + to: []graph.Node{simple.Node(2), simple.Node(6)}, + }, + } + for _, test := range reach { + g.AllowDiagonal = test.diagonal + got := g.From(test.from) + if !reflect.DeepEqual(got, test.to) { + t.Fatalf("unexpected nodes from %d with allow diagonal=%t:\ngot: %v\nwant:%v", + test.from, test.diagonal, got, test.to) + } + } +} diff --git a/graph/path/internal/limited.go b/graph/path/internal/limited.go new file mode 100644 index 00000000..7044c079 --- /dev/null +++ b/graph/path/internal/limited.go @@ -0,0 +1,306 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +import ( + "errors" + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +// LimitedVisionGrid is a 2D grid planar undirected graph where the capacity +// to determine the presence of edges is dependent on the current and past +// positions on the grid. In the absence of information, the grid is +// optimistic. +type LimitedVisionGrid struct { + Grid *Grid + + // Location is the current + // location on the grid. + Location graph.Node + + // VisionRadius specifies how far + // away edges can be detected. + VisionRadius float64 + + // Known holds a store of known + // nodes, if not nil. + Known map[int]bool +} + +// MoveTo moves to the node n on the grid and returns a slice of newly seen and +// already known edges. MoveTo panics if n is nil. +func (l *LimitedVisionGrid) MoveTo(n graph.Node) (new, old []graph.Edge) { + l.Location = n + row, column := l.RowCol(n.ID()) + x := float64(column) + y := float64(row) + seen := make(map[[2]int]bool) + bound := int(l.VisionRadius + 0.5) + for r := row - bound; r <= row+bound; r++ { + for c := column - bound; c <= column+bound; c++ { + u := l.NodeAt(r, c) + if u == nil { + continue + } + ux, uy := l.XY(u) + if math.Hypot(x-ux, y-uy) > l.VisionRadius { + continue + } + for _, v := range l.allPossibleFrom(u) { + if seen[[2]int{u.ID(), v.ID()}] { + continue + } + seen[[2]int{u.ID(), v.ID()}] = true + + vx, vy := l.XY(v) + if !l.Known[v.ID()] && math.Hypot(x-vx, y-vy) > l.VisionRadius { + continue + } + + e := simple.Edge{F: u, T: v} + if !l.Known[u.ID()] || !l.Known[v.ID()] { + new = append(new, e) + } else { + old = append(old, e) + } + } + } + } + + if l.Known != nil { + for r := row - bound; r <= row+bound; r++ { + for c := column - bound; c <= column+bound; c++ { + u := l.NodeAt(r, c) + if u == nil { + continue + } + ux, uy := l.XY(u) + if math.Hypot(x-ux, y-uy) > l.VisionRadius { + continue + } + for _, v := range l.allPossibleFrom(u) { + vx, vy := l.XY(v) + if math.Hypot(x-vx, y-vy) > l.VisionRadius { + continue + } + l.Known[v.ID()] = true + } + l.Known[u.ID()] = true + } + } + + } + + return new, old +} + +// allPossibleFrom returns all the nodes possibly reachable from u. +func (l *LimitedVisionGrid) allPossibleFrom(u graph.Node) []graph.Node { + if !l.Has(u) { + return nil + } + nr, nc := l.RowCol(u.ID()) + var to []graph.Node + for r := nr - 1; r <= nr+1; r++ { + for c := nc - 1; c <= nc+1; c++ { + v := l.NodeAt(r, c) + if v == nil || u.ID() == v.ID() { + continue + } + ur, uc := l.RowCol(u.ID()) + vr, vc := l.RowCol(v.ID()) + if abs(ur-vr) > 1 || abs(uc-vc) > 1 { + continue + } + if !l.Grid.AllowDiagonal && ur != vr && uc != vc { + continue + } + to = append(to, v) + } + } + return to +} + +// RowCol returns the row and column of the id. RowCol will panic if the +// node id is outside the range of the grid. +func (l *LimitedVisionGrid) RowCol(id int) (r, c int) { + return l.Grid.RowCol(id) +} + +// XY returns the cartesian coordinates of n. If n is not a node +// in the grid, (NaN, NaN) is returned. +func (l *LimitedVisionGrid) XY(n graph.Node) (x, y float64) { + if !l.Has(n) { + return math.NaN(), math.NaN() + } + r, c := l.RowCol(n.ID()) + return float64(c), float64(r) +} + +// Nodes returns all the nodes in the grid. +func (l *LimitedVisionGrid) Nodes() []graph.Node { + nodes := make([]graph.Node, 0, len(l.Grid.open)) + for id := range l.Grid.open { + nodes = append(nodes, simple.Node(id)) + } + return nodes +} + +// NodeAt returns the node at (r, c). The returned node may be open or closed. +func (l *LimitedVisionGrid) NodeAt(r, c int) graph.Node { + return l.Grid.NodeAt(r, c) +} + +// Has returns whether n is a node in the grid. +func (l *LimitedVisionGrid) Has(n graph.Node) bool { + return l.has(n.ID()) +} + +func (l *LimitedVisionGrid) has(id int) bool { + return id >= 0 && id < len(l.Grid.open) +} + +// From returns nodes that are optimistically reachable from u. +func (l *LimitedVisionGrid) From(u graph.Node) []graph.Node { + if !l.Has(u) { + return nil + } + + nr, nc := l.RowCol(u.ID()) + var to []graph.Node + for r := nr - 1; r <= nr+1; r++ { + for c := nc - 1; c <= nc+1; c++ { + if v := l.NodeAt(r, c); v != nil && l.HasEdgeBetween(u, v) { + to = append(to, v) + } + } + } + return to +} + +// HasEdgeBetween optimistically returns whether an edge is exists between u and v. +func (l *LimitedVisionGrid) HasEdgeBetween(u, v graph.Node) bool { + if u.ID() == v.ID() { + return false + } + ur, uc := l.RowCol(u.ID()) + vr, vc := l.RowCol(v.ID()) + if abs(ur-vr) > 1 || abs(uc-vc) > 1 { + return false + } + if !l.Grid.AllowDiagonal && ur != vr && uc != vc { + return false + } + + x, y := l.XY(l.Location) + ux, uy := l.XY(u) + vx, vy := l.XY(v) + uKnown := l.Known[u.ID()] || math.Hypot(x-ux, y-uy) <= l.VisionRadius + vKnown := l.Known[v.ID()] || math.Hypot(x-vx, y-vy) <= l.VisionRadius + + switch { + case uKnown && vKnown: + return l.Grid.HasEdgeBetween(u, v) + case uKnown: + return l.Grid.HasOpen(u) + case vKnown: + return l.Grid.HasOpen(v) + default: + return true + } +} + +// Edge optimistically returns the edge from u to v. +func (l *LimitedVisionGrid) Edge(u, v graph.Node) graph.Edge { + return l.EdgeBetween(u, v) +} + +// EdgeBetween optimistically returns the edge between u and v. +func (l *LimitedVisionGrid) EdgeBetween(u, v graph.Node) graph.Edge { + if l.HasEdgeBetween(u, v) { + if !l.Grid.AllowDiagonal || l.Grid.UnitEdgeWeight { + return simple.Edge{F: u, T: v, W: 1} + } + ux, uy := l.XY(u) + vx, vy := l.XY(v) + return simple.Edge{F: u, T: v, W: math.Hypot(ux-vx, uy-vy)} + } + return nil +} + +// Weight returns the weight of the given edge. +func (l *LimitedVisionGrid) Weight(x, y graph.Node) (w float64, ok bool) { + if x.ID() == y.ID() { + return 0, true + } + if !l.HasEdgeBetween(x, y) { + return math.Inf(1), false + } + if e := l.EdgeBetween(x, y); e != nil { + if !l.Grid.AllowDiagonal || l.Grid.UnitEdgeWeight { + return 1, true + } + ux, uy := l.XY(e.From()) + vx, vy := l.XY(e.To()) + return math.Hypot(ux-vx, uy-vy), true + + } + return math.Inf(1), true +} + +// String returns a string representation of the grid. +func (l *LimitedVisionGrid) String() string { + b, _ := l.Render(nil) + return string(b) +} + +// Render returns a text representation of the graph +// with the given path included. If the path is not a path +// in the grid Render returns a non-nil error and the +// path up to that point. +func (l *LimitedVisionGrid) Render(path []graph.Node) ([]byte, error) { + rows, cols := l.Grid.Dims() + b := make([]byte, rows*(cols+1)-1) + for r := 0; r < rows; r++ { + for c := 0; c < cols; c++ { + if !l.Known[r*cols+c] { + b[r*(cols+1)+c] = Unknown + } else if l.Grid.open[r*cols+c] { + b[r*(cols+1)+c] = Open + } else { + b[r*(cols+1)+c] = Closed + } + } + if r < rows-1 { + b[r*(cols+1)+cols] = '\n' + } + } + + // We don't use topo.IsPathIn at the outset because we + // want to draw as much as possible before failing. + for i, n := range path { + if !l.Has(n) || (i != 0 && !l.HasEdgeBetween(path[i-1], n)) { + id := n.ID() + if id >= 0 && id < len(l.Grid.open) { + r, c := l.RowCol(n.ID()) + b[r*(cols+1)+c] = '!' + } + return b, errors.New("grid: not a path in graph") + } + r, c := l.RowCol(n.ID()) + switch i { + case len(path) - 1: + b[r*(cols+1)+c] = 'G' + case 0: + b[r*(cols+1)+c] = 'S' + default: + b[r*(cols+1)+c] = 'o' + } + } + return b, nil +} diff --git a/graph/path/internal/limited_test.go b/graph/path/internal/limited_test.go new file mode 100644 index 00000000..aa1815ee --- /dev/null +++ b/graph/path/internal/limited_test.go @@ -0,0 +1,1242 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package internal + +import ( + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +type changes struct { + n graph.Node + + new, old []simple.Edge +} + +var limitedVisionTests = []struct { + g *Grid + radius float64 + diag bool + remember bool + + path []graph.Node + + want []changes +}{ + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + diag: false, + remember: false, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + }, + old: nil, + }, + { + n: node(6), + new: []simple.Edge{ + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + }, + old: nil, + }, + { + n: node(10), + new: []simple.Edge{ + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + }, + old: nil, + }, + { + n: node(14), + new: []simple.Edge{ + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + diag: false, + remember: false, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(4), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(6), + new: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(10), + new: []simple.Edge{ + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(14), + new: []simple.Edge{ + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + diag: false, + remember: true, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.Edge{ + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + }, + }, + { + n: node(6), + new: []simple.Edge{ + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + }, + old: []simple.Edge{ + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(10), + new: []simple.Edge{ + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + }, + old: []simple.Edge{ + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + }, + }, + { + n: node(14), + new: []simple.Edge{ + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + }, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + diag: false, + remember: true, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(4), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.Edge{ + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(6), + new: []simple.Edge{ + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + }, + { + n: node(10), + new: []simple.Edge{ + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + }, + { + n: node(14), + new: nil, + old: []simple.Edge{ + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + diag: true, + remember: false, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(6), + new: []simple.Edge{ + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(10), + new: []simple.Edge{ + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(14), + new: []simple.Edge{ + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + diag: true, + remember: false, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(4), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(6), + new: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(10), + new: []simple.Edge{ + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(14), + new: []simple.Edge{ + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: nil, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1, + diag: true, + remember: true, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(6), + new: []simple.Edge{ + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(10), + new: []simple.Edge{ + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + }, + }, + { + n: node(14), + new: []simple.Edge{ + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + }, + }, + }, + }, + { + g: NewGridFrom( + "*..*", + "**.*", + "**.*", + "**.*", + ), + radius: 1.5, + diag: true, + remember: true, + path: []graph.Node{node(1), node(2), node(6), node(10), node(14)}, + + want: []changes{ + { + n: node(1), + new: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(0), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(4), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(4), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + old: nil, + }, + { + n: node(2), + new: []simple.Edge{ + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + }, + }, + { + n: node(6), + new: []simple.Edge{ + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(1), T: simple.Node(6), W: math.Sqrt2}, + {F: simple.Node(2), T: simple.Node(1), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(2), T: simple.Node(6), W: 1}, + {F: simple.Node(2), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(3), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + }, + }, + { + n: node(10), + new: []simple.Edge{ + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + old: []simple.Edge{ + {F: simple.Node(5), T: simple.Node(0), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(1), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(5), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(1), W: math.Sqrt2}, + {F: simple.Node(6), T: simple.Node(2), W: 1}, + {F: simple.Node(6), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(6), T: simple.Node(10), W: 1}, + {F: simple.Node(6), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(2), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(3), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(7), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + }, + }, + { + n: node(14), + new: nil, + old: []simple.Edge{ + {F: simple.Node(9), T: simple.Node(4), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(9), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(5), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(6), W: 1}, + {F: simple.Node(10), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(10), T: simple.Node(14), W: 1}, + {F: simple.Node(10), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(6), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(7), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(11), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(13), T: simple.Node(14), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(9), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(10), W: 1}, + {F: simple.Node(14), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(13), W: math.Inf(1)}, + {F: simple.Node(14), T: simple.Node(15), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(10), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(11), W: math.Inf(1)}, + {F: simple.Node(15), T: simple.Node(14), W: math.Inf(1)}, + }, + }, + }, + }, +} + +func TestLimitedVisionGrid(t *testing.T) { + for i, test := range limitedVisionTests { + l := &LimitedVisionGrid{ + Grid: test.g, + VisionRadius: test.radius, + Location: test.path[0], + } + if test.remember { + l.Known = make(map[int]bool) + } + l.Grid.AllowDiagonal = test.diag + + x, y := l.XY(test.path[0]) + for _, u := range l.Nodes() { + ux, uy := l.XY(u) + uNear := math.Hypot(x-ux, y-uy) <= test.radius + for _, v := range l.Nodes() { + vx, vy := l.XY(v) + vNear := math.Hypot(x-vx, y-vy) <= test.radius + if u.ID() == v.ID() && l.HasEdgeBetween(u, v) { + t.Errorf("unexpected self edge: %v -- %v", u, v) + } + if !uNear && !vNear && !l.HasEdgeBetween(u, v) && couldConnectIn(l, u, v) { + t.Errorf("unexpected pessimism: no hope in distant edge between %v and %v for test %d", + u, v, i) + } + if (uNear && vNear) && l.HasEdgeBetween(u, v) != l.Grid.HasEdgeBetween(u, v) { + t.Errorf("unrealistic optimism: disagreement about edge between %v and %v for test %d: got:%t want:%t", + u, v, i, l.HasEdgeBetween(u, v), l.Grid.HasEdgeBetween(u, v)) + } + } + } + + var got []changes + for _, n := range test.path { + new, old := l.MoveTo(n) + got = append(got, changes{n: n, new: asConcreteEdges(new, l), old: asConcreteEdges(old, l)}) + } + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected walk for test %d:\ngot: %+v\nwant:%+v", i, got, test.want) + } + } +} + +func asConcreteEdges(changes []graph.Edge, in graph.Weighter) []simple.Edge { + if changes == nil { + return nil + } + we := make([]simple.Edge, len(changes)) + for i, e := range changes { + we[i].F = e.From() + we[i].T = e.To() + w, ok := in.Weight(e.From(), e.To()) + if !ok && !math.IsInf(w, 1) { + panic("unexpected invalid finite weight") + } + we[i].W = w + } + return we +} + +func couldConnectIn(l *LimitedVisionGrid, u, v graph.Node) bool { + if u.ID() == v.ID() { + return false + } + + ur, uc := l.RowCol(u.ID()) + vr, vc := l.RowCol(v.ID()) + if abs(ur-vr) > 1 || abs(uc-vc) > 1 { + return false + } + if (ur != vr || uc != vc) && !l.Grid.AllowDiagonal { + return false + } + + if !l.Known[u.ID()] && !l.Known[v.ID()] { + return true + } + if l.Known[u.ID()] && !l.Grid.HasOpen(u) { + return false + } + if l.Known[v.ID()] && !l.Grid.HasOpen(v) { + return false + } + + return true +} diff --git a/graph/path/internal/testgraphs/shortest.go b/graph/path/internal/testgraphs/shortest.go new file mode 100644 index 00000000..ffc5ad57 --- /dev/null +++ b/graph/path/internal/testgraphs/shortest.go @@ -0,0 +1,654 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testgraphs + +import ( + "fmt" + "math" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +func init() { + for _, test := range ShortestPathTests { + if len(test.WantPaths) != 1 && test.HasUniquePath { + panic(fmt.Sprintf("%q: bad shortest path test: non-unique paths marked unique", test.Name)) + } + } +} + +// ShortestPathTests are graphs used to test the static shortest path routines in path: BellmanFord, +// DijkstraAllPaths, DijkstraFrom, FloydWarshall and Johnson, and the static degenerate case for the +// dynamic shortest path routine in path/dynamic: DStarLite. +var ShortestPathTests = []struct { + Name string + Graph func() graph.EdgeSetter + Edges []simple.Edge + HasNegativeWeight bool + HasNegativeCycle bool + + Query simple.Edge + Weight float64 + WantPaths [][]int + HasUniquePath bool + + NoPathFor simple.Edge +}{ + // Positive weighted graphs. + { + Name: "empty directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: math.Inf(1), + + NoPathFor: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + }, + { + Name: "empty undirected", + Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: math.Inf(1), + + NoPathFor: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + }, + { + Name: "one edge directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: 1, + WantPaths: [][]int{ + {0, 1}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "one edge self directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(0)}, + Weight: 0, + WantPaths: [][]int{ + {0}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "one edge undirected", + Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: 1, + WantPaths: [][]int{ + {0, 1}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "two paths directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(2), W: 2}, + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(2)}, + Weight: 2, + WantPaths: [][]int{ + {0, 1, 2}, + {0, 2}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(1)}, + }, + { + Name: "two paths undirected", + Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(2), W: 2}, + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(2)}, + Weight: 2, + WantPaths: [][]int{ + {0, 1, 2}, + {0, 2}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(4)}, + }, + { + Name: "confounding paths directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->5 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(5), W: 1}, + + // Add direct edge to goal of weight 4 + {F: simple.Node(0), T: simple.Node(5), W: 4}, + + // Add edge to a node that's still optimal + {F: simple.Node(0), T: simple.Node(2), W: 2}, + + // Add edge to 3 that's overpriced + {F: simple.Node(0), T: simple.Node(3), W: 4}, + + // Add very cheap edge to 4 which is a dead end + {F: simple.Node(0), T: simple.Node(4), W: 0.25}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(5)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 5}, + {0, 2, 3, 5}, + {0, 5}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "confounding paths undirected", + Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->5 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(5), W: 1}, + + // Add direct edge to goal of weight 4 + {F: simple.Node(0), T: simple.Node(5), W: 4}, + + // Add edge to a node that's still optimal + {F: simple.Node(0), T: simple.Node(2), W: 2}, + + // Add edge to 3 that's overpriced + {F: simple.Node(0), T: simple.Node(3), W: 4}, + + // Add very cheap edge to 4 which is a dead end + {F: simple.Node(0), T: simple.Node(4), W: 0.25}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(5)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 5}, + {0, 2, 3, 5}, + {0, 5}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(5), T: simple.Node(6)}, + }, + { + Name: "confounding paths directed 2-step", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->5 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(5), W: 1}, + + // Add two step path to goal of weight 4 + {F: simple.Node(0), T: simple.Node(6), W: 2}, + {F: simple.Node(6), T: simple.Node(5), W: 2}, + + // Add edge to a node that's still optimal + {F: simple.Node(0), T: simple.Node(2), W: 2}, + + // Add edge to 3 that's overpriced + {F: simple.Node(0), T: simple.Node(3), W: 4}, + + // Add very cheap edge to 4 which is a dead end + {F: simple.Node(0), T: simple.Node(4), W: 0.25}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(5)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 5}, + {0, 2, 3, 5}, + {0, 6, 5}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "confounding paths undirected 2-step", + Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->5 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(5), W: 1}, + + // Add two step path to goal of weight 4 + {F: simple.Node(0), T: simple.Node(6), W: 2}, + {F: simple.Node(6), T: simple.Node(5), W: 2}, + + // Add edge to a node that's still optimal + {F: simple.Node(0), T: simple.Node(2), W: 2}, + + // Add edge to 3 that's overpriced + {F: simple.Node(0), T: simple.Node(3), W: 4}, + + // Add very cheap edge to 4 which is a dead end + {F: simple.Node(0), T: simple.Node(4), W: 0.25}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(5)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 5}, + {0, 2, 3, 5}, + {0, 6, 5}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(5), T: simple.Node(7)}, + }, + { + Name: "zero-weight cycle directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight cycle^2 directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + // With its own zero-weight cycle. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight cycle^2 confounding directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + // With its own zero-weight cycle. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + // But leading to the target. + {F: simple.Node(5), T: simple.Node(4), W: 3}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 4}, + {0, 1, 5, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight cycle^3 directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + // With its own zero-weight cycle. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + // With its own zero-weight cycle. + {F: simple.Node(6), T: simple.Node(7), W: 0}, + {F: simple.Node(7), T: simple.Node(6), W: 0}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight 3·cycle^2 confounding directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(1), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(1), W: 0}, + // With 3 of its own zero-weight cycles. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(7), W: 0}, + {F: simple.Node(7), T: simple.Node(5), W: 0}, + // Each leading to the target. + {F: simple.Node(5), T: simple.Node(4), W: 3}, + {F: simple.Node(6), T: simple.Node(4), W: 3}, + {F: simple.Node(7), T: simple.Node(4), W: 3}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 4}, + {0, 1, 5, 4}, + {0, 1, 5, 6, 4}, + {0, 1, 5, 7, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight reversed 3·cycle^2 confounding directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + + // Add a zero-weight cycle. + {F: simple.Node(3), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(3), W: 0}, + // With 3 of its own zero-weight cycles. + {F: simple.Node(5), T: simple.Node(6), W: 0}, + {F: simple.Node(6), T: simple.Node(5), W: 0}, + {F: simple.Node(5), T: simple.Node(7), W: 0}, + {F: simple.Node(7), T: simple.Node(5), W: 0}, + // Each leading from the source. + {F: simple.Node(0), T: simple.Node(5), W: 3}, + {F: simple.Node(0), T: simple.Node(6), W: 3}, + {F: simple.Node(0), T: simple.Node(7), W: 3}, + }, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 4}, + {0, 5, 3, 4}, + {0, 6, 5, 3, 4}, + {0, 7, 5, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight |V|·cycle^(n/|V|) directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: func() []simple.Edge { + e := []simple.Edge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + } + next := len(e) + 1 + + // Add n zero-weight cycles. + const n = 100 + for i := 0; i < n; i++ { + e = append(e, + simple.Edge{F: simple.Node(next + i), T: simple.Node(i), W: 0}, + simple.Edge{F: simple.Node(i), T: simple.Node(next + i), W: 0}, + ) + } + return e + }(), + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight n·cycle directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: func() []simple.Edge { + e := []simple.Edge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + } + next := len(e) + 1 + + // Add n zero-weight cycles. + const n = 100 + for i := 0; i < n; i++ { + e = append(e, + simple.Edge{F: simple.Node(next + i), T: simple.Node(1), W: 0}, + simple.Edge{F: simple.Node(1), T: simple.Node(next + i), W: 0}, + ) + } + return e + }(), + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + { + Name: "zero-weight bi-directional tree with single exit directed", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: func() []simple.Edge { + e := []simple.Edge{ + // Add a path from 0->4 of weight 4 + {F: simple.Node(0), T: simple.Node(1), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + {F: simple.Node(2), T: simple.Node(3), W: 1}, + {F: simple.Node(3), T: simple.Node(4), W: 1}, + } + + // Make a bi-directional tree rooted at node 2 with + // a single exit to node 4 and co-equal cost from + // 2 to 4. + const ( + depth = 4 + branching = 4 + ) + + next := len(e) + 1 + src := 2 + var i, last int + for l := 0; l < depth; l++ { + for i = 0; i < branching; i++ { + last = next + i + e = append(e, simple.Edge{F: simple.Node(src), T: simple.Node(last), W: 0}) + e = append(e, simple.Edge{F: simple.Node(last), T: simple.Node(src), W: 0}) + } + src = next + 1 + next += branching + } + e = append(e, simple.Edge{F: simple.Node(last), T: simple.Node(4), W: 2}) + return e + }(), + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(4)}, + Weight: 4, + WantPaths: [][]int{ + {0, 1, 2, 3, 4}, + {0, 1, 2, 6, 10, 14, 20, 4}, + }, + HasUniquePath: false, + + NoPathFor: simple.Edge{F: simple.Node(4), T: simple.Node(5)}, + }, + + // Negative weighted graphs. + { + Name: "one edge directed negative", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: -1}, + }, + HasNegativeWeight: true, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + Weight: -1, + WantPaths: [][]int{ + {0, 1}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "one edge undirected negative", + Graph: func() graph.EdgeSetter { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: -1}, + }, + HasNegativeWeight: true, + HasNegativeCycle: true, + + Query: simple.Edge{F: simple.Node(0), T: simple.Node(1)}, + }, + { + Name: "wp graph negative", // http://en.wikipedia.org/w/index.php?title=Johnson%27s_algorithm&oldid=564595231 + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + {F: simple.Node('w'), T: simple.Node('z'), W: 2}, + {F: simple.Node('x'), T: simple.Node('w'), W: 6}, + {F: simple.Node('x'), T: simple.Node('y'), W: 3}, + {F: simple.Node('y'), T: simple.Node('w'), W: 4}, + {F: simple.Node('y'), T: simple.Node('z'), W: 5}, + {F: simple.Node('z'), T: simple.Node('x'), W: -7}, + {F: simple.Node('z'), T: simple.Node('y'), W: -3}, + }, + HasNegativeWeight: true, + + Query: simple.Edge{F: simple.Node('z'), T: simple.Node('y')}, + Weight: -4, + WantPaths: [][]int{ + {'z', 'x', 'y'}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, + { + Name: "roughgarden negative", + Graph: func() graph.EdgeSetter { return simple.NewDirectedGraph(0, math.Inf(1)) }, + Edges: []simple.Edge{ + {F: simple.Node('a'), T: simple.Node('b'), W: -2}, + {F: simple.Node('b'), T: simple.Node('c'), W: -1}, + {F: simple.Node('c'), T: simple.Node('a'), W: 4}, + {F: simple.Node('c'), T: simple.Node('x'), W: 2}, + {F: simple.Node('c'), T: simple.Node('y'), W: -3}, + {F: simple.Node('z'), T: simple.Node('x'), W: 1}, + {F: simple.Node('z'), T: simple.Node('y'), W: -4}, + }, + HasNegativeWeight: true, + + Query: simple.Edge{F: simple.Node('a'), T: simple.Node('y')}, + Weight: -6, + WantPaths: [][]int{ + {'a', 'b', 'c', 'y'}, + }, + HasUniquePath: true, + + NoPathFor: simple.Edge{F: simple.Node(2), T: simple.Node(3)}, + }, +} diff --git a/graph/path/johnson_apsp.go b/graph/path/johnson_apsp.go new file mode 100644 index 00000000..9eaea09e --- /dev/null +++ b/graph/path/johnson_apsp.go @@ -0,0 +1,138 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +// JohnsonAllPaths returns a shortest-path tree for shortest paths in the graph g. +// If the graph does not implement graph.Weighter, UniformCost is used. +// +// The time complexity of JohnsonAllPaths is O(|V|.|E|+|V|^2.log|V|). +func JohnsonAllPaths(g graph.Graph) (paths AllShortest, ok bool) { + jg := johnsonWeightAdjuster{ + g: g, + from: g.From, + edgeTo: g.Edge, + } + if wg, ok := g.(graph.Weighter); ok { + jg.weight = wg.Weight + } else { + jg.weight = UniformCost(g) + } + + paths = newAllShortest(g.Nodes(), false) + + sign := -1 + for { + // Choose a random node ID until we find + // one that is not in g. + jg.q = sign * rand.Int() + if _, exists := paths.indexOf[jg.q]; !exists { + break + } + sign *= -1 + } + + jg.bellmanFord = true + jg.adjustBy, ok = BellmanFordFrom(johnsonGraphNode(jg.q), jg) + if !ok { + return paths, false + } + + jg.bellmanFord = false + dijkstraAllPaths(jg, paths) + + for i, u := range paths.nodes { + hu := jg.adjustBy.WeightTo(u) + for j, v := range paths.nodes { + if i == j { + continue + } + hv := jg.adjustBy.WeightTo(v) + paths.dist.Set(i, j, paths.dist.At(i, j)-hu+hv) + } + } + + return paths, ok +} + +type johnsonWeightAdjuster struct { + q int + g graph.Graph + + from func(graph.Node) []graph.Node + edgeTo func(graph.Node, graph.Node) graph.Edge + weight Weighting + + bellmanFord bool + adjustBy Shortest +} + +var ( + // johnsonWeightAdjuster has the behaviour + // of a directed graph, but we don't need + // to be explicit with the type since it + // is not exported. + _ graph.Graph = johnsonWeightAdjuster{} + _ graph.Weighter = johnsonWeightAdjuster{} +) + +func (g johnsonWeightAdjuster) Has(n graph.Node) bool { + if g.bellmanFord && n.ID() == g.q { + return true + } + return g.g.Has(n) + +} + +func (g johnsonWeightAdjuster) Nodes() []graph.Node { + if g.bellmanFord { + return append(g.g.Nodes(), johnsonGraphNode(g.q)) + } + return g.g.Nodes() +} + +func (g johnsonWeightAdjuster) From(n graph.Node) []graph.Node { + if g.bellmanFord && n.ID() == g.q { + return g.g.Nodes() + } + return g.from(n) +} + +func (g johnsonWeightAdjuster) Edge(u, v graph.Node) graph.Edge { + if g.bellmanFord && u.ID() == g.q && g.g.Has(v) { + return simple.Edge{F: johnsonGraphNode(g.q), T: v} + } + return g.edgeTo(u, v) +} + +func (g johnsonWeightAdjuster) Weight(x, y graph.Node) (w float64, ok bool) { + if g.bellmanFord { + switch g.q { + case x.ID(): + return 0, true + case y.ID(): + return math.Inf(1), false + default: + return g.weight(x, y) + } + } + w, ok = g.weight(x, y) + return w + g.adjustBy.WeightTo(x) - g.adjustBy.WeightTo(y), ok +} + +func (johnsonWeightAdjuster) HasEdgeBetween(_, _ graph.Node) bool { + panic("path: unintended use of johnsonWeightAdjuster") +} + +type johnsonGraphNode int + +func (n johnsonGraphNode) ID() int { return int(n) } diff --git a/graph/path/johnson_apsp_test.go b/graph/path/johnson_apsp_test.go new file mode 100644 index 00000000..2a3bdee1 --- /dev/null +++ b/graph/path/johnson_apsp_test.go @@ -0,0 +1,102 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/path/internal/testgraphs" +) + +func TestJohnsonAllPaths(t *testing.T) { + for _, test := range testgraphs.ShortestPathTests { + g := test.Graph() + for _, e := range test.Edges { + g.SetEdge(e) + } + + pt, ok := JohnsonAllPaths(g.(graph.Graph)) + if test.HasNegativeCycle { + if ok { + t.Errorf("%q: expected negative cycle", test.Name) + } + continue + } + if !ok { + t.Fatalf("%q: unexpected negative cycle", test.Name) + } + + // Check all random paths returned are OK. + for i := 0; i < 10; i++ { + p, weight, unique := pt.Between(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + if weight := pt.Weight(test.Query.From(), test.Query.To()); weight != test.Weight { + t.Errorf("%q: unexpected weight from Weight: got:%f want:%f", + test.Name, weight, test.Weight) + } + if unique != test.HasUniquePath { + t.Errorf("%q: unexpected number of paths: got: unique=%t want: unique=%t", + test.Name, unique, test.HasUniquePath) + } + + var got []int + for _, n := range p { + got = append(got, n.ID()) + } + ok := len(got) == 0 && len(test.WantPaths) == 0 + for _, sp := range test.WantPaths { + if reflect.DeepEqual(got, sp) { + ok = true + break + } + } + if !ok { + t.Errorf("%q: unexpected shortest path:\ngot: %v\nwant from:%v", + test.Name, p, test.WantPaths) + } + } + + np, weight, unique := pt.Between(test.NoPathFor.From(), test.NoPathFor.To()) + if np != nil || !math.IsInf(weight, 1) || unique != false { + t.Errorf("%q: unexpected path:\ngot: path=%v weight=%f unique=%t\nwant:path= weight=+Inf unique=false", + test.Name, np, weight, unique) + } + + paths, weight := pt.AllBetween(test.Query.From(), test.Query.To()) + if weight != test.Weight { + t.Errorf("%q: unexpected weight from Between: got:%f want:%f", + test.Name, weight, test.Weight) + } + + var got [][]int + if len(paths) != 0 { + got = make([][]int, len(paths)) + } + for i, p := range paths { + for _, v := range p { + got[i] = append(got[i], v.ID()) + } + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.WantPaths) { + t.Errorf("testing %q: unexpected shortest paths:\ngot: %v\nwant:%v", + test.Name, got, test.WantPaths) + } + + nps, weight := pt.AllBetween(test.NoPathFor.From(), test.NoPathFor.To()) + if nps != nil || !math.IsInf(weight, 1) { + t.Errorf("%q: unexpected path:\ngot: paths=%v weight=%f\nwant:path= weight=+Inf", + test.Name, nps, weight) + } + } +} diff --git a/graph/path/shortest.go b/graph/path/shortest.go new file mode 100644 index 00000000..8294abf2 --- /dev/null +++ b/graph/path/shortest.go @@ -0,0 +1,319 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/matrix/mat64" +) + +// Shortest is a shortest-path tree created by the BellmanFordFrom or DijkstraFrom +// single-source shortest path functions. +type Shortest struct { + // from holds the source node given to + // DijkstraFrom. + from graph.Node + + // nodes hold the nodes of the analysed + // graph. + nodes []graph.Node + // indexOf contains a mapping between + // the id-dense representation of the + // graph and the potentially id-sparse + // nodes held in nodes. + indexOf map[int]int + + // dist and next represent the shortest + // paths between nodes. + // + // Indices into dist and next are + // mapped through indexOf. + // + // dist contains the distances + // from the from node for each + // node in the graph. + dist []float64 + // next contains the shortest-path + // tree of the graph. The index is a + // linear mapping of to-dense-id. + next []int +} + +func newShortestFrom(u graph.Node, nodes []graph.Node) Shortest { + indexOf := make(map[int]int, len(nodes)) + uid := u.ID() + for i, n := range nodes { + indexOf[n.ID()] = i + if n.ID() == uid { + u = n + } + } + + p := Shortest{ + from: u, + + nodes: nodes, + indexOf: indexOf, + + dist: make([]float64, len(nodes)), + next: make([]int, len(nodes)), + } + for i := range nodes { + p.dist[i] = math.Inf(1) + p.next[i] = -1 + } + p.dist[indexOf[uid]] = 0 + + return p +} + +func (p Shortest) set(to int, weight float64, mid int) { + p.dist[to] = weight + p.next[to] = mid +} + +// From returns the starting node of the paths held by the Shortest. +func (p Shortest) From() graph.Node { return p.from } + +// WeightTo returns the weight of the minimum path to v. +func (p Shortest) WeightTo(v graph.Node) float64 { + to, toOK := p.indexOf[v.ID()] + if !toOK { + return math.Inf(1) + } + return p.dist[to] +} + +// To returns a shortest path to v and the weight of the path. +func (p Shortest) To(v graph.Node) (path []graph.Node, weight float64) { + to, toOK := p.indexOf[v.ID()] + if !toOK || math.IsInf(p.dist[to], 1) { + return nil, math.Inf(1) + } + from := p.indexOf[p.from.ID()] + path = []graph.Node{p.nodes[to]} + for to != from { + path = append(path, p.nodes[p.next[to]]) + to = p.next[to] + } + reverse(path) + return path, p.dist[p.indexOf[v.ID()]] +} + +// AllShortest is a shortest-path tree created by the DijkstraAllPaths, FloydWarshall +// or JohnsonAllPaths all-pairs shortest paths functions. +type AllShortest struct { + // nodes hold the nodes of the analysed + // graph. + nodes []graph.Node + // indexOf contains a mapping between + // the id-dense representation of the + // graph and the potentially id-sparse + // nodes held in nodes. + indexOf map[int]int + + // dist, next and forward represent + // the shortest paths between nodes. + // + // Indices into dist and next are + // mapped through indexOf. + // + // dist contains the pairwise + // distances between nodes. + dist *mat64.Dense + // next contains the shortest-path + // tree of the graph. The first index + // is a linear mapping of from-dense-id + // and to-dense-id, to-major with a + // stride equal to len(nodes); the + // slice indexed to is the list of + // intermediates leading from the 'from' + // node to the 'to' node represented + // by dense id. + // The interpretation of next is + // dependent on the state of forward. + next [][]int + // forward indicates the direction of + // path reconstruction. Forward + // reconstruction is used for Floyd- + // Warshall and reverse is used for + // Dijkstra. + forward bool +} + +func newAllShortest(nodes []graph.Node, forward bool) AllShortest { + indexOf := make(map[int]int, len(nodes)) + for i, n := range nodes { + indexOf[n.ID()] = i + } + dist := make([]float64, len(nodes)*len(nodes)) + for i := range dist { + dist[i] = math.Inf(1) + } + return AllShortest{ + nodes: nodes, + indexOf: indexOf, + + dist: mat64.NewDense(len(nodes), len(nodes), dist), + next: make([][]int, len(nodes)*len(nodes)), + forward: forward, + } +} + +func (p AllShortest) at(from, to int) (mid []int) { + return p.next[from+to*len(p.nodes)] +} + +func (p AllShortest) set(from, to int, weight float64, mid ...int) { + p.dist.Set(from, to, weight) + p.next[from+to*len(p.nodes)] = append(p.next[from+to*len(p.nodes)][:0], mid...) +} + +func (p AllShortest) add(from, to int, mid ...int) { +loop: // These are likely to be rare, so just loop over collisions. + for _, k := range mid { + for _, v := range p.next[from+to*len(p.nodes)] { + if k == v { + continue loop + } + } + p.next[from+to*len(p.nodes)] = append(p.next[from+to*len(p.nodes)], k) + } +} + +// Weight returns the weight of the minimum path between u and v. +func (p AllShortest) Weight(u, v graph.Node) float64 { + from, fromOK := p.indexOf[u.ID()] + to, toOK := p.indexOf[v.ID()] + if !fromOK || !toOK { + return math.Inf(1) + } + return p.dist.At(from, to) +} + +// Between returns a shortest path from u to v and the weight of the path. If more than +// one shortest path exists between u and v, a randomly chosen path will be returned and +// unique is returned false. If a cycle with zero weight exists in the path, it will not +// be included, but unique will be returned false. +func (p AllShortest) Between(u, v graph.Node) (path []graph.Node, weight float64, unique bool) { + from, fromOK := p.indexOf[u.ID()] + to, toOK := p.indexOf[v.ID()] + if !fromOK || !toOK || len(p.at(from, to)) == 0 { + if u.ID() == v.ID() { + return []graph.Node{p.nodes[from]}, 0, true + } + return nil, math.Inf(1), false + } + + seen := make([]int, len(p.nodes)) + for i := range seen { + seen[i] = -1 + } + var n graph.Node + if p.forward { + n = p.nodes[from] + seen[from] = 0 + } else { + n = p.nodes[to] + seen[to] = 0 + } + + path = []graph.Node{n} + weight = p.dist.At(from, to) + unique = true + + var next int + for from != to { + c := p.at(from, to) + if len(c) != 1 { + unique = false + next = c[rand.Intn(len(c))] + } else { + next = c[0] + } + if seen[next] >= 0 { + path = path[:seen[next]] + } + seen[next] = len(path) + path = append(path, p.nodes[next]) + if p.forward { + from = next + } else { + to = next + } + } + if !p.forward { + reverse(path) + } + + return path, weight, unique +} + +// AllBetween returns all shortest paths from u to v and the weight of the paths. Paths +// containing zero-weight cycles are not returned. +func (p AllShortest) AllBetween(u, v graph.Node) (paths [][]graph.Node, weight float64) { + from, fromOK := p.indexOf[u.ID()] + to, toOK := p.indexOf[v.ID()] + if !fromOK || !toOK || len(p.at(from, to)) == 0 { + if u.ID() == v.ID() { + return [][]graph.Node{{p.nodes[from]}}, 0 + } + return nil, math.Inf(1) + } + + var n graph.Node + if p.forward { + n = u + } else { + n = v + } + seen := make([]bool, len(p.nodes)) + paths = p.allBetween(from, to, seen, []graph.Node{n}, nil) + + return paths, p.dist.At(from, to) +} + +func (p AllShortest) allBetween(from, to int, seen []bool, path []graph.Node, paths [][]graph.Node) [][]graph.Node { + if p.forward { + seen[from] = true + } else { + seen[to] = true + } + if from == to { + if path == nil { + return paths + } + if !p.forward { + reverse(path) + } + return append(paths, path) + } + first := true + for _, n := range p.at(from, to) { + if seen[n] { + continue + } + if first { + path = append([]graph.Node(nil), path...) + first = false + } + if p.forward { + from = n + } else { + to = n + } + paths = p.allBetween(from, to, append([]bool(nil), seen...), append(path, p.nodes[n]), paths) + } + return paths +} + +func reverse(p []graph.Node) { + for i, j := 0, len(p)-1; i < j; i, j = i+1, j-1 { + p[i], p[j] = p[j], p[i] + } +} diff --git a/graph/path/spanning_tree.go b/graph/path/spanning_tree.go new file mode 100644 index 00000000..1ee9666f --- /dev/null +++ b/graph/path/spanning_tree.go @@ -0,0 +1,182 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "container/heap" + "math" + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +// UndirectedWeighter is an undirected graph that returns edge weights. +type UndirectedWeighter interface { + graph.Undirected + graph.Weighter +} + +// Prim generates a minimum spanning tree of g by greedy tree extension, placing +// the result in the destination, dst. If the edge weights of g are distinct +// it will be the unique minimum spanning tree of g. The destination is not cleared +// first. The weight of the minimum spanning tree is returned. If g is not connected, +// a minimum spanning forest will be constructed in dst and the sum of minimum +// spanning tree weights will be returned. +func Prim(dst graph.UndirectedBuilder, g UndirectedWeighter) float64 { + nodes := g.Nodes() + if len(nodes) == 0 { + return 0 + } + + q := &primQueue{ + indexOf: make(map[int]int, len(nodes)-1), + nodes: make([]simple.Edge, 0, len(nodes)-1), + } + for _, u := range nodes[1:] { + heap.Push(q, simple.Edge{F: u, W: math.Inf(1)}) + } + + u := nodes[0] + for _, v := range g.From(u) { + w, ok := g.Weight(u, v) + if !ok { + panic("prim: unexpected invalid weight") + } + q.update(v, u, w) + } + + var w float64 + for q.Len() > 0 { + e := heap.Pop(q).(simple.Edge) + if e.To() != nil && g.HasEdgeBetween(e.From(), e.To()) { + dst.SetEdge(e) + w += e.Weight() + } + + u = e.From() + for _, n := range g.From(u) { + if key, ok := q.key(n); ok { + w, ok := g.Weight(u, n) + if !ok { + panic("prim: unexpected invalid weight") + } + if w < key { + q.update(n, u, w) + } + } + } + } + return w +} + +// primQueue is a Prim's priority queue. The priority queue is a +// queue of edge From nodes keyed on the minimum edge weight to +// a node in the set of nodes already connected to the minimum +// spanning forest. +type primQueue struct { + indexOf map[int]int + nodes []simple.Edge +} + +func (q *primQueue) Less(i, j int) bool { + return q.nodes[i].Weight() < q.nodes[j].Weight() +} + +func (q *primQueue) Swap(i, j int) { + q.indexOf[q.nodes[i].From().ID()] = j + q.indexOf[q.nodes[j].From().ID()] = i + q.nodes[i], q.nodes[j] = q.nodes[j], q.nodes[i] +} + +func (q *primQueue) Len() int { + return len(q.nodes) +} + +func (q *primQueue) Push(x interface{}) { + n := x.(simple.Edge) + q.indexOf[n.From().ID()] = len(q.nodes) + q.nodes = append(q.nodes, n) +} + +func (q *primQueue) Pop() interface{} { + n := q.nodes[len(q.nodes)-1] + q.nodes = q.nodes[:len(q.nodes)-1] + delete(q.indexOf, n.From().ID()) + return n +} + +// key returns the key for the node u and whether the node is +// in the queue. If the node is not in the queue, key is returned +// as +Inf. +func (q *primQueue) key(u graph.Node) (key float64, ok bool) { + i, ok := q.indexOf[u.ID()] + if !ok { + return math.Inf(1), false + } + return q.nodes[i].Weight(), ok +} + +// update updates u's position in the queue with the new closest +// MST-connected neighbour, v, and the key weight between u and v. +func (q *primQueue) update(u, v graph.Node, key float64) { + id := u.ID() + i, ok := q.indexOf[id] + if !ok { + return + } + q.nodes[i].T = v + q.nodes[i].W = key + heap.Fix(q, i) +} + +// UndirectedWeightLister is an undirected graph that returns edge weights and +// the set of edges in the graph. +type UndirectedWeightLister interface { + UndirectedWeighter + Edges() []graph.Edge +} + +// Kruskal generates a minimum spanning tree of g by greedy tree coalescence, placing +// the result in the destination, dst. If the edge weights of g are distinct +// it will be the unique minimum spanning tree of g. The destination is not cleared +// first. The weight of the minimum spanning tree is returned. If g is not connected, +// a minimum spanning forest will be constructed in dst and the sum of minimum +// spanning tree weights will be returned. +func Kruskal(dst graph.UndirectedBuilder, g UndirectedWeightLister) float64 { + edges := g.Edges() + ascend := make([]simple.Edge, 0, len(edges)) + for _, e := range edges { + u := e.From() + v := e.To() + w, ok := g.Weight(u, v) + if !ok { + panic("kruskal: unexpected invalid weight") + } + ascend = append(ascend, simple.Edge{F: u, T: v, W: w}) + } + sort.Sort(byWeight(ascend)) + + ds := newDisjointSet() + for _, node := range g.Nodes() { + ds.makeSet(node.ID()) + } + + var w float64 + for _, e := range ascend { + if s1, s2 := ds.find(e.From().ID()), ds.find(e.To().ID()); s1 != s2 { + ds.union(s1, s2) + dst.SetEdge(e) + w += e.Weight() + } + } + return w +} + +type byWeight []simple.Edge + +func (e byWeight) Len() int { return len(e) } +func (e byWeight) Less(i, j int) bool { return e[i].Weight() < e[j].Weight() } +func (e byWeight) Swap(i, j int) { e[i], e[j] = e[j], e[i] } diff --git a/graph/path/spanning_tree_test.go b/graph/path/spanning_tree_test.go new file mode 100644 index 00000000..7ce542af --- /dev/null +++ b/graph/path/spanning_tree_test.go @@ -0,0 +1,294 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" +) + +func init() { + for _, test := range spanningTreeTests { + var w float64 + for _, e := range test.treeEdges { + w += e.W + } + if w != test.want { + panic(fmt.Sprintf("bad test: %s weight mismatch: %v != %v", test.name, w, test.want)) + } + } +} + +type spanningGraph interface { + graph.UndirectedBuilder + graph.Weighter + Edges() []graph.Edge +} + +var spanningTreeTests = []struct { + name string + graph func() spanningGraph + edges []simple.Edge + want float64 + treeEdges []simple.Edge +}{ + { + name: "Empty", + graph: func() spanningGraph { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + want: 0, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/f/f7/Prim%27s_algorithm.svg + // Modified to make edge weights unique; A--B is increased to 2.5 otherwise + // to prevent the alternative solution being found. + name: "Prim WP figure 1", + graph: func() spanningGraph { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.Edge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 2.5}, + {F: simple.Node('A'), T: simple.Node('D'), W: 1}, + {F: simple.Node('B'), T: simple.Node('D'), W: 2}, + {F: simple.Node('C'), T: simple.Node('D'), W: 3}, + }, + + want: 6, + treeEdges: []simple.Edge{ + {F: simple.Node('A'), T: simple.Node('D'), W: 1}, + {F: simple.Node('B'), T: simple.Node('D'), W: 2}, + {F: simple.Node('C'), T: simple.Node('D'), W: 3}, + }, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/5/5c/MST_kruskal_en.gif + name: "Kruskal WP figure 1", + graph: func() spanningGraph { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.Edge{ + {F: simple.Node('a'), T: simple.Node('b'), W: 3}, + {F: simple.Node('a'), T: simple.Node('e'), W: 1}, + {F: simple.Node('b'), T: simple.Node('c'), W: 5}, + {F: simple.Node('b'), T: simple.Node('e'), W: 4}, + {F: simple.Node('c'), T: simple.Node('d'), W: 2}, + {F: simple.Node('c'), T: simple.Node('e'), W: 6}, + {F: simple.Node('d'), T: simple.Node('e'), W: 7}, + }, + + want: 11, + treeEdges: []simple.Edge{ + {F: simple.Node('a'), T: simple.Node('b'), W: 3}, + {F: simple.Node('a'), T: simple.Node('e'), W: 1}, + {F: simple.Node('b'), T: simple.Node('c'), W: 5}, + {F: simple.Node('c'), T: simple.Node('d'), W: 2}, + }, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/8/87/Kruskal_Algorithm_6.svg + name: "Kruskal WP example", + graph: func() spanningGraph { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.Edge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 7}, + {F: simple.Node('A'), T: simple.Node('D'), W: 5}, + {F: simple.Node('B'), T: simple.Node('C'), W: 8}, + {F: simple.Node('B'), T: simple.Node('D'), W: 9}, + {F: simple.Node('B'), T: simple.Node('E'), W: 7}, + {F: simple.Node('C'), T: simple.Node('E'), W: 5}, + {F: simple.Node('D'), T: simple.Node('E'), W: 15}, + {F: simple.Node('D'), T: simple.Node('F'), W: 6}, + {F: simple.Node('E'), T: simple.Node('F'), W: 8}, + {F: simple.Node('E'), T: simple.Node('G'), W: 9}, + {F: simple.Node('F'), T: simple.Node('G'), W: 11}, + }, + + want: 39, + treeEdges: []simple.Edge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 7}, + {F: simple.Node('A'), T: simple.Node('D'), W: 5}, + {F: simple.Node('B'), T: simple.Node('E'), W: 7}, + {F: simple.Node('C'), T: simple.Node('E'), W: 5}, + {F: simple.Node('D'), T: simple.Node('F'), W: 6}, + {F: simple.Node('E'), T: simple.Node('G'), W: 9}, + }, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/2/2e/Boruvka%27s_algorithm_%28Sollin%27s_algorithm%29_Anim.gif + name: "Borůvka WP example", + graph: func() spanningGraph { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.Edge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 13}, + {F: simple.Node('A'), T: simple.Node('C'), W: 6}, + {F: simple.Node('B'), T: simple.Node('C'), W: 7}, + {F: simple.Node('B'), T: simple.Node('D'), W: 1}, + {F: simple.Node('C'), T: simple.Node('D'), W: 14}, + {F: simple.Node('C'), T: simple.Node('E'), W: 8}, + {F: simple.Node('C'), T: simple.Node('H'), W: 20}, + {F: simple.Node('D'), T: simple.Node('E'), W: 9}, + {F: simple.Node('D'), T: simple.Node('F'), W: 3}, + {F: simple.Node('E'), T: simple.Node('F'), W: 2}, + {F: simple.Node('E'), T: simple.Node('J'), W: 18}, + {F: simple.Node('G'), T: simple.Node('H'), W: 15}, + {F: simple.Node('G'), T: simple.Node('I'), W: 5}, + {F: simple.Node('G'), T: simple.Node('J'), W: 19}, + {F: simple.Node('G'), T: simple.Node('K'), W: 10}, + {F: simple.Node('H'), T: simple.Node('J'), W: 17}, + {F: simple.Node('I'), T: simple.Node('K'), W: 11}, + {F: simple.Node('J'), T: simple.Node('K'), W: 16}, + {F: simple.Node('J'), T: simple.Node('L'), W: 4}, + {F: simple.Node('K'), T: simple.Node('L'), W: 12}, + }, + + want: 83, + treeEdges: []simple.Edge{ + {F: simple.Node('A'), T: simple.Node('C'), W: 6}, + {F: simple.Node('B'), T: simple.Node('C'), W: 7}, + {F: simple.Node('B'), T: simple.Node('D'), W: 1}, + {F: simple.Node('D'), T: simple.Node('F'), W: 3}, + {F: simple.Node('E'), T: simple.Node('F'), W: 2}, + {F: simple.Node('E'), T: simple.Node('J'), W: 18}, + {F: simple.Node('G'), T: simple.Node('H'), W: 15}, + {F: simple.Node('G'), T: simple.Node('I'), W: 5}, + {F: simple.Node('G'), T: simple.Node('K'), W: 10}, + {F: simple.Node('J'), T: simple.Node('L'), W: 4}, + {F: simple.Node('K'), T: simple.Node('L'), W: 12}, + }, + }, + { + // https://upload.wikimedia.org/wikipedia/commons/d/d2/Minimum_spanning_tree.svg + // Nodes labelled row major. + name: "Minimum Spanning Tree WP figure 1", + graph: func() spanningGraph { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(2), W: 4}, + {F: simple.Node(1), T: simple.Node(3), W: 1}, + {F: simple.Node(1), T: simple.Node(4), W: 4}, + {F: simple.Node(2), T: simple.Node(3), W: 5}, + {F: simple.Node(2), T: simple.Node(5), W: 9}, + {F: simple.Node(2), T: simple.Node(6), W: 9}, + {F: simple.Node(2), T: simple.Node(8), W: 7}, + {F: simple.Node(3), T: simple.Node(4), W: 3}, + {F: simple.Node(3), T: simple.Node(8), W: 9}, + {F: simple.Node(4), T: simple.Node(8), W: 10}, + {F: simple.Node(4), T: simple.Node(10), W: 18}, + {F: simple.Node(5), T: simple.Node(6), W: 2}, + {F: simple.Node(5), T: simple.Node(7), W: 4}, + {F: simple.Node(5), T: simple.Node(9), W: 6}, + {F: simple.Node(6), T: simple.Node(7), W: 2}, + {F: simple.Node(6), T: simple.Node(8), W: 8}, + {F: simple.Node(7), T: simple.Node(8), W: 9}, + {F: simple.Node(7), T: simple.Node(9), W: 3}, + {F: simple.Node(7), T: simple.Node(10), W: 9}, + {F: simple.Node(8), T: simple.Node(10), W: 8}, + {F: simple.Node(9), T: simple.Node(10), W: 9}, + }, + + want: 38, + treeEdges: []simple.Edge{ + {F: simple.Node(1), T: simple.Node(2), W: 4}, + {F: simple.Node(1), T: simple.Node(3), W: 1}, + {F: simple.Node(2), T: simple.Node(8), W: 7}, + {F: simple.Node(3), T: simple.Node(4), W: 3}, + {F: simple.Node(5), T: simple.Node(6), W: 2}, + {F: simple.Node(6), T: simple.Node(7), W: 2}, + {F: simple.Node(6), T: simple.Node(8), W: 8}, + {F: simple.Node(7), T: simple.Node(9), W: 3}, + {F: simple.Node(8), T: simple.Node(10), W: 8}, + }, + }, + + { + // https://upload.wikimedia.org/wikipedia/commons/2/2e/Boruvka%27s_algorithm_%28Sollin%27s_algorithm%29_Anim.gif + // but with C--H and E--J cut. + name: "Borůvka WP example cut", + graph: func() spanningGraph { return simple.NewUndirectedGraph(0, math.Inf(1)) }, + edges: []simple.Edge{ + {F: simple.Node('A'), T: simple.Node('B'), W: 13}, + {F: simple.Node('A'), T: simple.Node('C'), W: 6}, + {F: simple.Node('B'), T: simple.Node('C'), W: 7}, + {F: simple.Node('B'), T: simple.Node('D'), W: 1}, + {F: simple.Node('C'), T: simple.Node('D'), W: 14}, + {F: simple.Node('C'), T: simple.Node('E'), W: 8}, + {F: simple.Node('D'), T: simple.Node('E'), W: 9}, + {F: simple.Node('D'), T: simple.Node('F'), W: 3}, + {F: simple.Node('E'), T: simple.Node('F'), W: 2}, + {F: simple.Node('G'), T: simple.Node('H'), W: 15}, + {F: simple.Node('G'), T: simple.Node('I'), W: 5}, + {F: simple.Node('G'), T: simple.Node('J'), W: 19}, + {F: simple.Node('G'), T: simple.Node('K'), W: 10}, + {F: simple.Node('H'), T: simple.Node('J'), W: 17}, + {F: simple.Node('I'), T: simple.Node('K'), W: 11}, + {F: simple.Node('J'), T: simple.Node('K'), W: 16}, + {F: simple.Node('J'), T: simple.Node('L'), W: 4}, + {F: simple.Node('K'), T: simple.Node('L'), W: 12}, + }, + + want: 65, + treeEdges: []simple.Edge{ + {F: simple.Node('A'), T: simple.Node('C'), W: 6}, + {F: simple.Node('B'), T: simple.Node('C'), W: 7}, + {F: simple.Node('B'), T: simple.Node('D'), W: 1}, + {F: simple.Node('D'), T: simple.Node('F'), W: 3}, + {F: simple.Node('E'), T: simple.Node('F'), W: 2}, + {F: simple.Node('G'), T: simple.Node('H'), W: 15}, + {F: simple.Node('G'), T: simple.Node('I'), W: 5}, + {F: simple.Node('G'), T: simple.Node('K'), W: 10}, + {F: simple.Node('J'), T: simple.Node('L'), W: 4}, + {F: simple.Node('K'), T: simple.Node('L'), W: 12}, + }, + }, +} + +func testMinumumSpanning(mst func(dst graph.UndirectedBuilder, g spanningGraph) float64, t *testing.T) { + for _, test := range spanningTreeTests { + g := test.graph() + for _, e := range test.edges { + g.SetEdge(e) + } + + dst := simple.NewUndirectedGraph(0, math.Inf(1)) + w := mst(dst, g) + if w != test.want { + t.Errorf("unexpected minimum spanning tree weight for %q: got: %f want: %f", + test.name, w, test.want) + } + var got float64 + for _, e := range dst.Edges() { + got += e.Weight() + } + if got != test.want { + t.Errorf("unexpected minimum spanning tree edge weight sum for %q: got: %f want: %f", + test.name, got, test.want) + } + + gotEdges := dst.Edges() + if len(gotEdges) != len(test.treeEdges) { + t.Errorf("unexpected number of spanning tree edges for %q: got: %d want: %d", + test.name, len(gotEdges), len(test.treeEdges)) + } + for _, e := range test.treeEdges { + w, ok := dst.Weight(e.From(), e.To()) + if !ok { + t.Errorf("spanning tree edge not found in graph for %q: %+v", + test.name, e) + } + if w != e.Weight() { + t.Errorf("unexpected spanning tree edge weight for %q: got: %f want: %f", + test.name, w, e.Weight()) + } + } + } +} + +func TestKruskal(t *testing.T) { + testMinumumSpanning(func(dst graph.UndirectedBuilder, g spanningGraph) float64 { + return Kruskal(dst, g) + }, t) +} + +func TestPrim(t *testing.T) { + testMinumumSpanning(func(dst graph.UndirectedBuilder, g spanningGraph) float64 { + return Prim(dst, g) + }, t) +} diff --git a/graph/path/weight.go b/graph/path/weight.go new file mode 100644 index 00000000..91b9d321 --- /dev/null +++ b/graph/path/weight.go @@ -0,0 +1,40 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package path + +import ( + "math" + + "gonum.org/v1/gonum/graph" +) + +// Weighting is a mapping between a pair of nodes and a weight. It follows the +// semantics of the Weighter interface. +type Weighting func(x, y graph.Node) (w float64, ok bool) + +// UniformCost returns a Weighting that returns an edge cost of 1 for existing +// edges, zero for node identity and Inf for otherwise absent edges. +func UniformCost(g graph.Graph) Weighting { + return func(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return 0, true + } + if e := g.Edge(x, y); e != nil { + return 1, true + } + return math.Inf(1), false + } +} + +// Heuristic returns an estimate of the cost of travelling between two nodes. +type Heuristic func(x, y graph.Node) float64 + +// HeuristicCoster wraps the HeuristicCost method. A graph implementing the +// interface provides a heuristic between any two given nodes. +type HeuristicCoster interface { + HeuristicCost(x, y graph.Node) float64 +} diff --git a/graph/simple/dense_directed_matrix.go b/graph/simple/dense_directed_matrix.go new file mode 100644 index 00000000..a6d681d3 --- /dev/null +++ b/graph/simple/dense_directed_matrix.go @@ -0,0 +1,265 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package simple + +import ( + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/matrix/mat64" +) + +// DirectedMatrix represents a directed graph using an adjacency +// matrix such that all IDs are in a contiguous block from 0 to n-1. +// Edges are stored implicitly as an edge weight, so edges stored in +// the graph are not recoverable. +type DirectedMatrix struct { + mat *mat64.Dense + nodes []graph.Node + + self float64 + absent float64 +} + +// NewDirectedMatrix creates a directed dense graph with n nodes. +// All edges are initialized with the weight given by init. The self parameter +// specifies the cost of self connection, and absent specifies the weight +// returned for absent edges. +func NewDirectedMatrix(n int, init, self, absent float64) *DirectedMatrix { + mat := make([]float64, n*n) + if init != 0 { + for i := range mat { + mat[i] = init + } + } + for i := 0; i < len(mat); i += n + 1 { + mat[i] = self + } + return &DirectedMatrix{ + mat: mat64.NewDense(n, n, mat), + self: self, + absent: absent, + } +} + +// NewDirectedMatrixFrom creates a directed dense graph with the given nodes. +// The IDs of the nodes must be contiguous from 0 to len(nodes)-1, but may +// be in any order. If IDs are not contiguous NewDirectedMatrixFrom will panic. +// All edges are initialized with the weight given by init. The self parameter +// specifies the cost of self connection, and absent specifies the weight +// returned for absent edges. +func NewDirectedMatrixFrom(nodes []graph.Node, init, self, absent float64) *DirectedMatrix { + sort.Sort(ordered.ByID(nodes)) + for i, n := range nodes { + if i != n.ID() { + panic("simple: non-contiguous node IDs") + } + } + g := NewDirectedMatrix(len(nodes), init, self, absent) + g.nodes = nodes + return g +} + +// Node returns the node in the graph with the given ID. +func (g *DirectedMatrix) Node(id int) graph.Node { + if !g.has(id) { + return nil + } + if g.nodes == nil { + return Node(id) + } + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *DirectedMatrix) Has(n graph.Node) bool { + return g.has(n.ID()) +} + +func (g *DirectedMatrix) has(id int) bool { + r, _ := g.mat.Dims() + return 0 <= id && id < r +} + +// Nodes returns all the nodes in the graph. +func (g *DirectedMatrix) Nodes() []graph.Node { + if g.nodes != nil { + nodes := make([]graph.Node, len(g.nodes)) + copy(nodes, g.nodes) + return nodes + } + r, _ := g.mat.Dims() + nodes := make([]graph.Node, r) + for i := 0; i < r; i++ { + nodes[i] = Node(i) + } + return nodes +} + +// Edges returns all the edges in the graph. +func (g *DirectedMatrix) Edges() []graph.Edge { + var edges []graph.Edge + r, _ := g.mat.Dims() + for i := 0; i < r; i++ { + for j := 0; j < r; j++ { + if i == j { + continue + } + if w := g.mat.At(i, j); !isSame(w, g.absent) { + edges = append(edges, Edge{F: g.Node(i), T: g.Node(j), W: w}) + } + } + } + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *DirectedMatrix) From(n graph.Node) []graph.Node { + id := n.ID() + if !g.has(id) { + return nil + } + var neighbors []graph.Node + _, c := g.mat.Dims() + for j := 0; j < c; j++ { + if j == id { + continue + } + if !isSame(g.mat.At(id, j), g.absent) { + neighbors = append(neighbors, g.Node(j)) + } + } + return neighbors +} + +// To returns all nodes in g that can reach directly to n. +func (g *DirectedMatrix) To(n graph.Node) []graph.Node { + id := n.ID() + if !g.has(id) { + return nil + } + var neighbors []graph.Node + r, _ := g.mat.Dims() + for i := 0; i < r; i++ { + if i == id { + continue + } + if !isSame(g.mat.At(i, id), g.absent) { + neighbors = append(neighbors, g.Node(i)) + } + } + return neighbors +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y without +// considering direction. +func (g *DirectedMatrix) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + if !g.has(xid) { + return false + } + yid := y.ID() + if !g.has(yid) { + return false + } + return xid != yid && (!isSame(g.mat.At(xid, yid), g.absent) || !isSame(g.mat.At(yid, xid), g.absent)) +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *DirectedMatrix) Edge(u, v graph.Node) graph.Edge { + if g.HasEdgeFromTo(u, v) { + return Edge{F: g.Node(u.ID()), T: g.Node(v.ID()), W: g.mat.At(u.ID(), v.ID())} + } + return nil +} + +// HasEdgeFromTo returns whether an edge exists in the graph from u to v. +func (g *DirectedMatrix) HasEdgeFromTo(u, v graph.Node) bool { + uid := u.ID() + if !g.has(uid) { + return false + } + vid := v.ID() + if !g.has(vid) { + return false + } + return uid != vid && !isSame(g.mat.At(uid, vid), g.absent) +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node or there is no joining edge between the two nodes the weight +// value returned is either the graph's absent or self value. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *DirectedMatrix) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.self, true + } + if g.has(xid) && g.has(yid) { + return g.mat.At(xid, yid), true + } + return g.absent, false +} + +// SetEdge sets e, an edge from one node to another. If the ends of the edge are not in g +// or the edge is a self loop, SetEdge panics. +func (g *DirectedMatrix) SetEdge(e graph.Edge) { + fid := e.From().ID() + tid := e.To().ID() + if fid == tid { + panic("simple: set illegal edge") + } + g.mat.Set(fid, tid, e.Weight()) +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *DirectedMatrix) RemoveEdge(e graph.Edge) { + fid := e.From().ID() + if !g.has(fid) { + return + } + tid := e.To().ID() + if !g.has(tid) { + return + } + g.mat.Set(fid, tid, g.absent) +} + +// Degree returns the in+out degree of n in g. +func (g *DirectedMatrix) Degree(n graph.Node) int { + id := n.ID() + var deg int + r, c := g.mat.Dims() + for i := 0; i < r; i++ { + if i == id { + continue + } + if !isSame(g.mat.At(id, i), g.absent) { + deg++ + } + } + for i := 0; i < c; i++ { + if i == id { + continue + } + if !isSame(g.mat.At(i, id), g.absent) { + deg++ + } + } + return deg +} + +// Matrix returns the mat64.Matrix representation of the graph. The orientation +// of the matrix is such that the matrix entry at G_{ij} is the weight of the edge +// from node i to node j. +func (g *DirectedMatrix) Matrix() mat64.Matrix { + // Prevent alteration of dimensions of the returned matrix. + m := *g.mat + return &m +} diff --git a/graph/simple/dense_undirected_matrix.go b/graph/simple/dense_undirected_matrix.go new file mode 100644 index 00000000..6ef09ff6 --- /dev/null +++ b/graph/simple/dense_undirected_matrix.go @@ -0,0 +1,224 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package simple + +import ( + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/matrix/mat64" +) + +// UndirectedMatrix represents an undirected graph using an adjacency +// matrix such that all IDs are in a contiguous block from 0 to n-1. +// Edges are stored implicitly as an edge weight, so edges stored in +// the graph are not recoverable. +type UndirectedMatrix struct { + mat *mat64.SymDense + nodes []graph.Node + + self float64 + absent float64 +} + +// NewUndirectedMatrix creates an undirected dense graph with n nodes. +// All edges are initialized with the weight given by init. The self parameter +// specifies the cost of self connection, and absent specifies the weight +// returned for absent edges. +func NewUndirectedMatrix(n int, init, self, absent float64) *UndirectedMatrix { + mat := make([]float64, n*n) + if init != 0 { + for i := range mat { + mat[i] = init + } + } + for i := 0; i < len(mat); i += n + 1 { + mat[i] = self + } + return &UndirectedMatrix{ + mat: mat64.NewSymDense(n, mat), + self: self, + absent: absent, + } +} + +// NewUndirectedMatrixFrom creates an undirected dense graph with the given nodes. +// The IDs of the nodes must be contiguous from 0 to len(nodes)-1, but may +// be in any order. If IDs are not contiguous NewUndirectedMatrixFrom will panic. +// All edges are initialized with the weight given by init. The self parameter +// specifies the cost of self connection, and absent specifies the weight +// returned for absent edges. +func NewUndirectedMatrixFrom(nodes []graph.Node, init, self, absent float64) *UndirectedMatrix { + sort.Sort(ordered.ByID(nodes)) + for i, n := range nodes { + if i != n.ID() { + panic("simple: non-contiguous node IDs") + } + } + g := NewUndirectedMatrix(len(nodes), init, self, absent) + g.nodes = nodes + return g +} + +// Node returns the node in the graph with the given ID. +func (g *UndirectedMatrix) Node(id int) graph.Node { + if !g.has(id) { + return nil + } + if g.nodes == nil { + return Node(id) + } + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *UndirectedMatrix) Has(n graph.Node) bool { + return g.has(n.ID()) +} + +func (g *UndirectedMatrix) has(id int) bool { + r := g.mat.Symmetric() + return 0 <= id && id < r +} + +// Nodes returns all the nodes in the graph. +func (g *UndirectedMatrix) Nodes() []graph.Node { + if g.nodes != nil { + nodes := make([]graph.Node, len(g.nodes)) + copy(nodes, g.nodes) + return nodes + } + r := g.mat.Symmetric() + nodes := make([]graph.Node, r) + for i := 0; i < r; i++ { + nodes[i] = Node(i) + } + return nodes +} + +// Edges returns all the edges in the graph. +func (g *UndirectedMatrix) Edges() []graph.Edge { + var edges []graph.Edge + r, _ := g.mat.Dims() + for i := 0; i < r; i++ { + for j := i + 1; j < r; j++ { + if w := g.mat.At(i, j); !isSame(w, g.absent) { + edges = append(edges, Edge{F: g.Node(i), T: g.Node(j), W: w}) + } + } + } + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *UndirectedMatrix) From(n graph.Node) []graph.Node { + id := n.ID() + if !g.has(id) { + return nil + } + var neighbors []graph.Node + r := g.mat.Symmetric() + for i := 0; i < r; i++ { + if i == id { + continue + } + if !isSame(g.mat.At(id, i), g.absent) { + neighbors = append(neighbors, g.Node(i)) + } + } + return neighbors +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *UndirectedMatrix) HasEdgeBetween(u, v graph.Node) bool { + uid := u.ID() + if !g.has(uid) { + return false + } + vid := v.ID() + if !g.has(vid) { + return false + } + return uid != vid && !isSame(g.mat.At(uid, vid), g.absent) +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *UndirectedMatrix) Edge(u, v graph.Node) graph.Edge { + return g.EdgeBetween(u, v) +} + +// EdgeBetween returns the edge between nodes x and y. +func (g *UndirectedMatrix) EdgeBetween(u, v graph.Node) graph.Edge { + if g.HasEdgeBetween(u, v) { + return Edge{F: g.Node(u.ID()), T: g.Node(v.ID()), W: g.mat.At(u.ID(), v.ID())} + } + return nil +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node or there is no joining edge between the two nodes the weight +// value returned is either the graph's absent or self value. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *UndirectedMatrix) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.self, true + } + if g.has(xid) && g.has(yid) { + return g.mat.At(xid, yid), true + } + return g.absent, false +} + +// SetEdge sets e, an edge from one node to another. If the ends of the edge are not in g +// or the edge is a self loop, SetEdge panics. +func (g *UndirectedMatrix) SetEdge(e graph.Edge) { + fid := e.From().ID() + tid := e.To().ID() + if fid == tid { + panic("simple: set illegal edge") + } + g.mat.SetSym(fid, tid, e.Weight()) +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *UndirectedMatrix) RemoveEdge(e graph.Edge) { + fid := e.From().ID() + if !g.has(fid) { + return + } + tid := e.To().ID() + if !g.has(tid) { + return + } + g.mat.SetSym(fid, tid, g.absent) +} + +// Degree returns the degree of n in g. +func (g *UndirectedMatrix) Degree(n graph.Node) int { + id := n.ID() + var deg int + r := g.mat.Symmetric() + for i := 0; i < r; i++ { + if i == id { + continue + } + if !isSame(g.mat.At(id, i), g.absent) { + deg++ + } + } + return deg +} + +// Matrix returns the mat64.Matrix representation of the graph. +func (g *UndirectedMatrix) Matrix() mat64.Matrix { + // Prevent alteration of dimensions of the returned matrix. + m := *g.mat + return &m +} diff --git a/graph/simple/densegraph_test.go b/graph/simple/densegraph_test.go new file mode 100644 index 00000000..dae71387 --- /dev/null +++ b/graph/simple/densegraph_test.go @@ -0,0 +1,140 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package simple + +import ( + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +var ( + _ graph.Graph = (*UndirectedMatrix)(nil) + _ graph.Directed = (*DirectedMatrix)(nil) +) + +func TestBasicDenseImpassable(t *testing.T) { + dg := NewUndirectedMatrix(5, math.Inf(1), 0, math.Inf(1)) + if dg == nil { + t.Fatal("Directed graph could not be made") + } + + for i := 0; i < 5; i++ { + if !dg.Has(Node(i)) { + t.Errorf("Node that should exist doesn't: %d", i) + } + + if degree := dg.Degree(Node(i)); degree != 0 { + t.Errorf("Node in impassable graph has a neighbor. Node: %d Degree: %d", i, degree) + } + } + + for i := 5; i < 10; i++ { + if dg.Has(Node(i)) { + t.Errorf("Node exists that shouldn't: %d", i) + } + } +} + +func TestBasicDensePassable(t *testing.T) { + dg := NewUndirectedMatrix(5, 1, 0, math.Inf(1)) + if dg == nil { + t.Fatal("Directed graph could not be made") + } + + for i := 0; i < 5; i++ { + if !dg.Has(Node(i)) { + t.Errorf("Node that should exist doesn't: %d", i) + } + + if degree := dg.Degree(Node(i)); degree != 4 { + t.Errorf("Node in passable graph missing neighbors. Node: %d Degree: %d", i, degree) + } + } + + for i := 5; i < 10; i++ { + if dg.Has(Node(i)) { + t.Errorf("Node exists that shouldn't: %d", i) + } + } +} + +func TestDirectedDenseAddRemove(t *testing.T) { + dg := NewDirectedMatrix(10, math.Inf(1), 0, math.Inf(1)) + dg.SetEdge(Edge{F: Node(0), T: Node(2), W: 1}) + + if neighbors := dg.From(Node(0)); len(neighbors) != 1 || neighbors[0].ID() != 2 || + dg.Edge(Node(0), Node(2)) == nil { + t.Errorf("Adding edge didn't create successor") + } + + dg.RemoveEdge(Edge{F: Node(0), T: Node(2)}) + + if neighbors := dg.From(Node(0)); len(neighbors) != 0 || dg.Edge(Node(0), Node(2)) != nil { + t.Errorf("Removing edge didn't properly remove successor") + } + + if neighbors := dg.To(Node(2)); len(neighbors) != 0 || dg.Edge(Node(0), Node(2)) != nil { + t.Errorf("Removing directed edge wrongly kept predecessor") + } + + dg.SetEdge(Edge{F: Node(0), T: Node(2), W: 2}) + // I figure we've torture tested From/To at this point + // so we'll just use the bool functions now + if dg.Edge(Node(0), Node(2)) == nil { + t.Fatal("Adding directed edge didn't change successor back") + } + c1, _ := dg.Weight(Node(2), Node(0)) + c2, _ := dg.Weight(Node(0), Node(2)) + if c1 == c2 { + t.Error("Adding directed edge affected cost in undirected manner") + } +} + +func TestUndirectedDenseAddRemove(t *testing.T) { + dg := NewUndirectedMatrix(10, math.Inf(1), 0, math.Inf(1)) + dg.SetEdge(Edge{F: Node(0), T: Node(2)}) + + if neighbors := dg.From(Node(0)); len(neighbors) != 1 || neighbors[0].ID() != 2 || + dg.EdgeBetween(Node(0), Node(2)) == nil { + t.Errorf("Couldn't add neighbor") + } + + if neighbors := dg.From(Node(2)); len(neighbors) != 1 || neighbors[0].ID() != 0 || + dg.EdgeBetween(Node(2), Node(0)) == nil { + t.Errorf("Adding an undirected neighbor didn't add it reciprocally") + } +} + +func TestDenseLists(t *testing.T) { + dg := NewDirectedMatrix(15, 1, 0, math.Inf(1)) + nodes := dg.Nodes() + + if len(nodes) != 15 { + t.Fatalf("Wrong number of nodes") + } + + sort.Sort(ordered.ByID(nodes)) + + for i, node := range dg.Nodes() { + if i != node.ID() { + t.Errorf("Node list doesn't return properly id'd nodes") + } + } + + edges := dg.Edges() + if len(edges) != 15*14 { + t.Errorf("Improper number of edges for passable dense graph") + } + + dg.RemoveEdge(Edge{F: Node(12), T: Node(11)}) + edges = dg.Edges() + if len(edges) != (15*14)-1 { + t.Errorf("Removing edge didn't affect edge listing properly") + } +} diff --git a/graph/simple/directed.go b/graph/simple/directed.go new file mode 100644 index 00000000..e5ef4fe3 --- /dev/null +++ b/graph/simple/directed.go @@ -0,0 +1,280 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package simple + +import ( + "fmt" + + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/graph" +) + +// DirectedGraph implements a generalized directed graph. +type DirectedGraph struct { + nodes map[int]graph.Node + from map[int]map[int]graph.Edge + to map[int]map[int]graph.Edge + + self, absent float64 + + freeIDs intsets.Sparse + usedIDs intsets.Sparse +} + +// NewDirectedGraph returns a DirectedGraph with the specified self and absent +// edge weight values. +func NewDirectedGraph(self, absent float64) *DirectedGraph { + return &DirectedGraph{ + nodes: make(map[int]graph.Node), + from: make(map[int]map[int]graph.Edge), + to: make(map[int]map[int]graph.Edge), + + self: self, + absent: absent, + } +} + +// NewNodeID returns a new unique ID for a node to be added to g. The returned ID does +// not become a valid ID in g until it is added to g. +func (g *DirectedGraph) NewNodeID() int { + if len(g.nodes) == 0 { + return 0 + } + if len(g.nodes) == maxInt { + panic(fmt.Sprintf("simple: cannot allocate node: no slot")) + } + + var id int + if g.freeIDs.Len() != 0 && g.freeIDs.TakeMin(&id) { + return id + } + if id = g.usedIDs.Max(); id < maxInt { + return id + 1 + } + for id = 0; id < maxInt; id++ { + if !g.usedIDs.Has(id) { + return id + } + } + panic("unreachable") +} + +// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. +func (g *DirectedGraph) AddNode(n graph.Node) { + if _, exists := g.nodes[n.ID()]; exists { + panic(fmt.Sprintf("simple: node ID collision: %d", n.ID())) + } + g.nodes[n.ID()] = n + g.from[n.ID()] = make(map[int]graph.Edge) + g.to[n.ID()] = make(map[int]graph.Edge) + + g.freeIDs.Remove(n.ID()) + g.usedIDs.Insert(n.ID()) +} + +// RemoveNode removes n from the graph, as well as any edges attached to it. If the node +// is not in the graph it is a no-op. +func (g *DirectedGraph) RemoveNode(n graph.Node) { + if _, ok := g.nodes[n.ID()]; !ok { + return + } + delete(g.nodes, n.ID()) + + for from := range g.from[n.ID()] { + delete(g.to[from], n.ID()) + } + delete(g.from, n.ID()) + + for to := range g.to[n.ID()] { + delete(g.from[to], n.ID()) + } + delete(g.to, n.ID()) + + g.freeIDs.Insert(n.ID()) + g.usedIDs.Remove(n.ID()) +} + +// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added. +// It will panic if the IDs of the e.From and e.To are equal. +func (g *DirectedGraph) SetEdge(e graph.Edge) { + var ( + from = e.From() + fid = from.ID() + to = e.To() + tid = to.ID() + ) + + if fid == tid { + panic("simple: adding self edge") + } + + if !g.Has(from) { + g.AddNode(from) + } + if !g.Has(to) { + g.AddNode(to) + } + + g.from[fid][tid] = e + g.to[tid][fid] = e +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *DirectedGraph) RemoveEdge(e graph.Edge) { + from, to := e.From(), e.To() + if _, ok := g.nodes[from.ID()]; !ok { + return + } + if _, ok := g.nodes[to.ID()]; !ok { + return + } + + delete(g.from[from.ID()], to.ID()) + delete(g.to[to.ID()], from.ID()) +} + +// Node returns the node in the graph with the given ID. +func (g *DirectedGraph) Node(id int) graph.Node { + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *DirectedGraph) Has(n graph.Node) bool { + _, ok := g.nodes[n.ID()] + + return ok +} + +// Nodes returns all the nodes in the graph. +func (g *DirectedGraph) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.from)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + + return nodes +} + +// Edges returns all the edges in the graph. +func (g *DirectedGraph) Edges() []graph.Edge { + var edges []graph.Edge + for _, u := range g.nodes { + for _, e := range g.from[u.ID()] { + edges = append(edges, e) + } + } + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *DirectedGraph) From(n graph.Node) []graph.Node { + if _, ok := g.from[n.ID()]; !ok { + return nil + } + + from := make([]graph.Node, len(g.from[n.ID()])) + i := 0 + for id := range g.from[n.ID()] { + from[i] = g.nodes[id] + i++ + } + + return from +} + +// To returns all nodes in g that can reach directly to n. +func (g *DirectedGraph) To(n graph.Node) []graph.Node { + if _, ok := g.from[n.ID()]; !ok { + return nil + } + + to := make([]graph.Node, len(g.to[n.ID()])) + i := 0 + for id := range g.to[n.ID()] { + to[i] = g.nodes[id] + i++ + } + + return to +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y without +// considering direction. +func (g *DirectedGraph) HasEdgeBetween(x, y graph.Node) bool { + xid := x.ID() + yid := y.ID() + if _, ok := g.nodes[xid]; !ok { + return false + } + if _, ok := g.nodes[yid]; !ok { + return false + } + if _, ok := g.from[xid][yid]; ok { + return true + } + _, ok := g.from[yid][xid] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *DirectedGraph) Edge(u, v graph.Node) graph.Edge { + if _, ok := g.nodes[u.ID()]; !ok { + return nil + } + if _, ok := g.nodes[v.ID()]; !ok { + return nil + } + edge, ok := g.from[u.ID()][v.ID()] + if !ok { + return nil + } + return edge +} + +// HasEdgeFromTo returns whether an edge exists in the graph from u to v. +func (g *DirectedGraph) HasEdgeFromTo(u, v graph.Node) bool { + if _, ok := g.nodes[u.ID()]; !ok { + return false + } + if _, ok := g.nodes[v.ID()]; !ok { + return false + } + if _, ok := g.from[u.ID()][v.ID()]; !ok { + return false + } + return true +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node or there is no joining edge between the two nodes the weight +// value returned is either the graph's absent or self value. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *DirectedGraph) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.self, true + } + if to, ok := g.from[xid]; ok { + if e, ok := to[yid]; ok { + return e.Weight(), true + } + } + return g.absent, false +} + +// Degree returns the in+out degree of n in g. +func (g *DirectedGraph) Degree(n graph.Node) int { + if _, ok := g.nodes[n.ID()]; !ok { + return 0 + } + + return len(g.from[n.ID()]) + len(g.to[n.ID()]) +} diff --git a/graph/simple/directed_test.go b/graph/simple/directed_test.go new file mode 100644 index 00000000..d7c722e2 --- /dev/null +++ b/graph/simple/directed_test.go @@ -0,0 +1,63 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package simple + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" +) + +var _ graph.Graph = &DirectedGraph{} +var _ graph.Directed = &DirectedGraph{} +var _ graph.Directed = &DirectedGraph{} + +// Tests Issue #27 +func TestEdgeOvercounting(t *testing.T) { + g := generateDummyGraph() + + if neigh := g.From(Node(Node(2))); len(neigh) != 2 { + t.Errorf("Node 2 has incorrect number of neighbors got neighbors %v (count %d), expected 2 neighbors {0,1}", neigh, len(neigh)) + } +} + +func generateDummyGraph() *DirectedGraph { + nodes := [4]struct{ srcID, targetID int }{ + {2, 1}, + {1, 0}, + {2, 0}, + {0, 2}, + } + + g := NewDirectedGraph(0, math.Inf(1)) + + for _, n := range nodes { + g.SetEdge(Edge{F: Node(n.srcID), T: Node(n.targetID), W: 1}) + } + + return g +} + +// Test for issue #123 https://github.com/gonum/graph/issues/123 +func TestIssue123DirectedGraph(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("unexpected panic: %v", r) + } + }() + g := NewDirectedGraph(0, math.Inf(1)) + + n0 := Node(g.NewNodeID()) + g.AddNode(n0) + + n1 := Node(g.NewNodeID()) + g.AddNode(n1) + + g.RemoveNode(n0) + + n2 := Node(g.NewNodeID()) + g.AddNode(n2) +} diff --git a/graph/simple/simple.go b/graph/simple/simple.go new file mode 100644 index 00000000..d081d75e --- /dev/null +++ b/graph/simple/simple.go @@ -0,0 +1,45 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package simple provides a suite of simple graph implementations satisfying +// the gonum/graph interfaces. +package simple + +import ( + "math" + + "gonum.org/v1/gonum/graph" +) + +// Node is a simple graph node. +type Node int + +// ID returns the ID number of the node. +func (n Node) ID() int { + return int(n) +} + +// Edge is a simple graph edge. +type Edge struct { + F, T graph.Node + W float64 +} + +// From returns the from-node of the edge. +func (e Edge) From() graph.Node { return e.F } + +// To returns the to-node of the edge. +func (e Edge) To() graph.Node { return e.T } + +// Weight returns the weight of the edge. +func (e Edge) Weight() float64 { return e.W } + +// maxInt is the maximum value of the machine-dependent int type. +const maxInt int = int(^uint(0) >> 1) + +// isSame returns whether two float64 values are the same where NaN values +// are equalable. +func isSame(a, b float64) bool { + return a == b || (math.IsNaN(a) && math.IsNaN(b)) +} diff --git a/graph/simple/undirected.go b/graph/simple/undirected.go new file mode 100644 index 00000000..05d44080 --- /dev/null +++ b/graph/simple/undirected.go @@ -0,0 +1,241 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package simple + +import ( + "fmt" + + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/graph" +) + +// UndirectedGraph implements a generalized undirected graph. +type UndirectedGraph struct { + nodes map[int]graph.Node + edges map[int]map[int]graph.Edge + + self, absent float64 + + freeIDs intsets.Sparse + usedIDs intsets.Sparse +} + +// NewUndirectedGraph returns an UndirectedGraph with the specified self and absent +// edge weight values. +func NewUndirectedGraph(self, absent float64) *UndirectedGraph { + return &UndirectedGraph{ + nodes: make(map[int]graph.Node), + edges: make(map[int]map[int]graph.Edge), + + self: self, + absent: absent, + } +} + +// NewNodeID returns a new unique ID for a node to be added to g. The returned ID does +// not become a valid ID in g until it is added to g. +func (g *UndirectedGraph) NewNodeID() int { + if len(g.nodes) == 0 { + return 0 + } + if len(g.nodes) == maxInt { + panic(fmt.Sprintf("simple: cannot allocate node: no slot")) + } + + var id int + if g.freeIDs.Len() != 0 && g.freeIDs.TakeMin(&id) { + return id + } + if id = g.usedIDs.Max(); id < maxInt { + return id + 1 + } + for id = 0; id < maxInt; id++ { + if !g.usedIDs.Has(id) { + return id + } + } + panic("unreachable") +} + +// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. +func (g *UndirectedGraph) AddNode(n graph.Node) { + if _, exists := g.nodes[n.ID()]; exists { + panic(fmt.Sprintf("simple: node ID collision: %d", n.ID())) + } + g.nodes[n.ID()] = n + g.edges[n.ID()] = make(map[int]graph.Edge) + + g.freeIDs.Remove(n.ID()) + g.usedIDs.Insert(n.ID()) +} + +// RemoveNode removes n from the graph, as well as any edges attached to it. If the node +// is not in the graph it is a no-op. +func (g *UndirectedGraph) RemoveNode(n graph.Node) { + if _, ok := g.nodes[n.ID()]; !ok { + return + } + delete(g.nodes, n.ID()) + + for from := range g.edges[n.ID()] { + delete(g.edges[from], n.ID()) + } + delete(g.edges, n.ID()) + + g.freeIDs.Insert(n.ID()) + g.usedIDs.Remove(n.ID()) + +} + +// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added. +// It will panic if the IDs of the e.From and e.To are equal. +func (g *UndirectedGraph) SetEdge(e graph.Edge) { + var ( + from = e.From() + fid = from.ID() + to = e.To() + tid = to.ID() + ) + + if fid == tid { + panic("simple: adding self edge") + } + + if !g.Has(from) { + g.AddNode(from) + } + if !g.Has(to) { + g.AddNode(to) + } + + g.edges[fid][tid] = e + g.edges[tid][fid] = e +} + +// RemoveEdge removes e from the graph, leaving the terminal nodes. If the edge does not exist +// it is a no-op. +func (g *UndirectedGraph) RemoveEdge(e graph.Edge) { + from, to := e.From(), e.To() + if _, ok := g.nodes[from.ID()]; !ok { + return + } + if _, ok := g.nodes[to.ID()]; !ok { + return + } + + delete(g.edges[from.ID()], to.ID()) + delete(g.edges[to.ID()], from.ID()) +} + +// Node returns the node in the graph with the given ID. +func (g *UndirectedGraph) Node(id int) graph.Node { + return g.nodes[id] +} + +// Has returns whether the node exists within the graph. +func (g *UndirectedGraph) Has(n graph.Node) bool { + _, ok := g.nodes[n.ID()] + return ok +} + +// Nodes returns all the nodes in the graph. +func (g *UndirectedGraph) Nodes() []graph.Node { + nodes := make([]graph.Node, len(g.nodes)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + + return nodes +} + +// Edges returns all the edges in the graph. +func (g *UndirectedGraph) Edges() []graph.Edge { + var edges []graph.Edge + + seen := make(map[[2]int]struct{}) + for _, u := range g.edges { + for _, e := range u { + uid := e.From().ID() + vid := e.To().ID() + if _, ok := seen[[2]int{uid, vid}]; ok { + continue + } + seen[[2]int{uid, vid}] = struct{}{} + seen[[2]int{vid, uid}] = struct{}{} + edges = append(edges, e) + } + } + + return edges +} + +// From returns all nodes in g that can be reached directly from n. +func (g *UndirectedGraph) From(n graph.Node) []graph.Node { + if !g.Has(n) { + return nil + } + + nodes := make([]graph.Node, len(g.edges[n.ID()])) + i := 0 + for from := range g.edges[n.ID()] { + nodes[i] = g.nodes[from] + i++ + } + + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *UndirectedGraph) HasEdgeBetween(x, y graph.Node) bool { + _, ok := g.edges[x.ID()][y.ID()] + return ok +} + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +func (g *UndirectedGraph) Edge(u, v graph.Node) graph.Edge { + return g.EdgeBetween(u, v) +} + +// EdgeBetween returns the edge between nodes x and y. +func (g *UndirectedGraph) EdgeBetween(x, y graph.Node) graph.Edge { + // We don't need to check if neigh exists because + // it's implicit in the edges access. + if !g.Has(x) { + return nil + } + + return g.edges[x.ID()][y.ID()] +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node or there is no joining edge between the two nodes the weight +// value returned is either the graph's absent or self value. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g *UndirectedGraph) Weight(x, y graph.Node) (w float64, ok bool) { + xid := x.ID() + yid := y.ID() + if xid == yid { + return g.self, true + } + if n, ok := g.edges[xid]; ok { + if e, ok := n[yid]; ok { + return e.Weight(), true + } + } + return g.absent, false +} + +// Degree returns the degree of n in g. +func (g *UndirectedGraph) Degree(n graph.Node) int { + if _, ok := g.nodes[n.ID()]; !ok { + return 0 + } + + return len(g.edges[n.ID()]) +} diff --git a/graph/simple/undirected_test.go b/graph/simple/undirected_test.go new file mode 100644 index 00000000..fa9e4be9 --- /dev/null +++ b/graph/simple/undirected_test.go @@ -0,0 +1,63 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package simple + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" +) + +var _ graph.Graph = (*UndirectedGraph)(nil) + +func TestAssertMutableNotDirected(t *testing.T) { + var g graph.UndirectedBuilder = NewUndirectedGraph(0, math.Inf(1)) + if _, ok := g.(graph.Directed); ok { + t.Fatal("Graph is directed, but a MutableGraph cannot safely be directed!") + } +} + +func TestMaxID(t *testing.T) { + g := NewUndirectedGraph(0, math.Inf(1)) + nodes := make(map[graph.Node]struct{}) + for i := Node(0); i < 3; i++ { + g.AddNode(i) + nodes[i] = struct{}{} + } + g.RemoveNode(Node(0)) + delete(nodes, Node(0)) + g.RemoveNode(Node(2)) + delete(nodes, Node(2)) + n := Node(g.NewNodeID()) + g.AddNode(n) + if !g.Has(n) { + t.Error("added node does not exist in graph") + } + if _, exists := nodes[n]; exists { + t.Errorf("Created already existing node id: %v", n.ID()) + } +} + +// Test for issue #123 https://github.com/gonum/graph/issues/123 +func TestIssue123UndirectedGraph(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Errorf("unexpected panic: %v", r) + } + }() + g := NewUndirectedGraph(0, math.Inf(1)) + + n0 := Node(g.NewNodeID()) + g.AddNode(n0) + + n1 := Node(g.NewNodeID()) + g.AddNode(n1) + + g.RemoveNode(n0) + + n2 := Node(g.NewNodeID()) + g.AddNode(n2) +} diff --git a/graph/topo/bench_test.go b/graph/topo/bench_test.go new file mode 100644 index 00000000..fb23f46f --- /dev/null +++ b/graph/topo/bench_test.go @@ -0,0 +1,58 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package topo + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/graphs/gen" + "gonum.org/v1/gonum/graph/simple" +) + +var ( + gnpDirected_10_tenth = gnpDirected(10, 0.1) + gnpDirected_100_tenth = gnpDirected(100, 0.1) + gnpDirected_1000_tenth = gnpDirected(1000, 0.1) + gnpDirected_10_half = gnpDirected(10, 0.5) + gnpDirected_100_half = gnpDirected(100, 0.5) + gnpDirected_1000_half = gnpDirected(1000, 0.5) +) + +func gnpDirected(n int, p float64) graph.Directed { + g := simple.NewDirectedGraph(0, math.Inf(1)) + gen.Gnp(g, n, p, nil) + return g +} + +func benchmarkTarjanSCC(b *testing.B, g graph.Directed) { + var sccs [][]graph.Node + for i := 0; i < b.N; i++ { + sccs = TarjanSCC(g) + } + if len(sccs) == 0 { + b.Fatal("unexpected number zero-sized SCC set") + } +} + +func BenchmarkTarjanSCCGnp_10_tenth(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_10_tenth) +} +func BenchmarkTarjanSCCGnp_100_tenth(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_100_tenth) +} +func BenchmarkTarjanSCCGnp_1000_tenth(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_1000_tenth) +} +func BenchmarkTarjanSCCGnp_10_half(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_10_half) +} +func BenchmarkTarjanSCCGnp_100_half(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_100_half) +} +func BenchmarkTarjanSCCGnp_1000_half(b *testing.B) { + benchmarkTarjanSCC(b, gnpDirected_1000_half) +} diff --git a/graph/topo/bron_kerbosch.go b/graph/topo/bron_kerbosch.go new file mode 100644 index 00000000..b5491413 --- /dev/null +++ b/graph/topo/bron_kerbosch.go @@ -0,0 +1,225 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package topo + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/set" +) + +// VertexOrdering returns the vertex ordering and the k-cores of +// the undirected graph g. +func VertexOrdering(g graph.Undirected) (order []graph.Node, cores [][]graph.Node) { + nodes := g.Nodes() + + // The algorithm used here is essentially as described at + // http://en.wikipedia.org/w/index.php?title=Degeneracy_%28graph_theory%29&oldid=640308710 + + // Initialize an output list L. + var l []graph.Node + + // Compute a number d_v for each vertex v in G, + // the number of neighbors of v that are not already in L. + // Initially, these numbers are just the degrees of the vertices. + dv := make(map[int]int, len(nodes)) + var ( + maxDegree int + neighbours = make(map[int][]graph.Node) + ) + for _, n := range nodes { + adj := g.From(n) + neighbours[n.ID()] = adj + dv[n.ID()] = len(adj) + if len(adj) > maxDegree { + maxDegree = len(adj) + } + } + + // Initialize an array D such that D[i] contains a list of the + // vertices v that are not already in L for which d_v = i. + d := make([][]graph.Node, maxDegree+1) + for _, n := range nodes { + deg := dv[n.ID()] + d[deg] = append(d[deg], n) + } + + // Initialize k to 0. + k := 0 + // Repeat n times: + s := []int{0} + for range nodes { + // Scan the array cells D[0], D[1], ... until + // finding an i for which D[i] is nonempty. + var ( + i int + di []graph.Node + ) + for i, di = range d { + if len(di) != 0 { + break + } + } + + // Set k to max(k,i). + if i > k { + k = i + s = append(s, make([]int, k-len(s)+1)...) + } + + // Select a vertex v from D[i]. Add v to the + // beginning of L and remove it from D[i]. + var v graph.Node + v, d[i] = di[len(di)-1], di[:len(di)-1] + l = append(l, v) + s[k]++ + delete(dv, v.ID()) + + // For each neighbor w of v not already in L, + // subtract one from d_w and move w to the + // cell of D corresponding to the new value of d_w. + for _, w := range neighbours[v.ID()] { + dw, ok := dv[w.ID()] + if !ok { + continue + } + for i, n := range d[dw] { + if n.ID() == w.ID() { + d[dw][i], d[dw] = d[dw][len(d[dw])-1], d[dw][:len(d[dw])-1] + dw-- + d[dw] = append(d[dw], w) + break + } + } + dv[w.ID()] = dw + } + } + + for i, j := 0, len(l)-1; i < j; i, j = i+1, j-1 { + l[i], l[j] = l[j], l[i] + } + cores = make([][]graph.Node, len(s)) + offset := len(l) + for i, n := range s { + cores[i] = l[offset-n : offset] + offset -= n + } + return l, cores +} + +// BronKerbosch returns the set of maximal cliques of the undirected graph g. +func BronKerbosch(g graph.Undirected) [][]graph.Node { + nodes := g.Nodes() + + // The algorithm used here is essentially BronKerbosch3 as described at + // http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858 + + p := make(set.Nodes, len(nodes)) + for _, n := range nodes { + p.Add(n) + } + x := make(set.Nodes) + var bk bronKerbosch + order, _ := VertexOrdering(g) + for _, v := range order { + neighbours := g.From(v) + nv := make(set.Nodes, len(neighbours)) + for _, n := range neighbours { + nv.Add(n) + } + bk.maximalCliquePivot(g, []graph.Node{v}, make(set.Nodes).Intersect(p, nv), make(set.Nodes).Intersect(x, nv)) + p.Remove(v) + x.Add(v) + } + return bk +} + +type bronKerbosch [][]graph.Node + +func (bk *bronKerbosch) maximalCliquePivot(g graph.Undirected, r []graph.Node, p, x set.Nodes) { + if len(p) == 0 && len(x) == 0 { + *bk = append(*bk, r) + return + } + + neighbours := bk.choosePivotFrom(g, p, x) + nu := make(set.Nodes, len(neighbours)) + for _, n := range neighbours { + nu.Add(n) + } + for _, v := range p { + if nu.Has(v) { + continue + } + neighbours := g.From(v) + nv := make(set.Nodes, len(neighbours)) + for _, n := range neighbours { + nv.Add(n) + } + + var found bool + for _, n := range r { + if n.ID() == v.ID() { + found = true + break + } + } + var sr []graph.Node + if !found { + sr = append(r[:len(r):len(r)], v) + } + + bk.maximalCliquePivot(g, sr, make(set.Nodes).Intersect(p, nv), make(set.Nodes).Intersect(x, nv)) + p.Remove(v) + x.Add(v) + } +} + +func (*bronKerbosch) choosePivotFrom(g graph.Undirected, p, x set.Nodes) (neighbors []graph.Node) { + // TODO(kortschak): Investigate the impact of pivot choice that maximises + // |p ⋂ neighbours(u)| as a function of input size. Until then, leave as + // compile time option. + if !tomitaTanakaTakahashi { + for _, n := range p { + return g.From(n) + } + for _, n := range x { + return g.From(n) + } + panic("bronKerbosch: empty set") + } + + var ( + max = -1 + pivot graph.Node + ) + maxNeighbors := func(s set.Nodes) { + outer: + for _, u := range s { + nb := g.From(u) + c := len(nb) + if c <= max { + continue + } + for n := range nb { + if _, ok := p[n]; ok { + continue + } + c-- + if c <= max { + continue outer + } + } + max = c + pivot = u + neighbors = nb + } + } + maxNeighbors(p) + maxNeighbors(x) + if pivot == nil { + panic("bronKerbosch: empty set") + } + return neighbors +} diff --git a/graph/topo/bron_kerbosch_test.go b/graph/topo/bron_kerbosch_test.go new file mode 100644 index 00000000..a83b8db8 --- /dev/null +++ b/graph/topo/bron_kerbosch_test.go @@ -0,0 +1,164 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package topo + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var vOrderTests = []struct { + g []intset + wantCore [][]int + wantK int +}{ + { + g: []intset{ + 0: linksTo(1, 2, 4, 6), + 1: linksTo(2, 4, 6), + 2: linksTo(3, 6), + 3: linksTo(4, 5), + 4: linksTo(6), + 5: nil, + 6: nil, + }, + wantCore: [][]int{ + {}, + {5}, + {3}, + {0, 1, 2, 4, 6}, + }, + wantK: 3, + }, + { + g: batageljZaversnikGraph, + wantCore: [][]int{ + {0}, + {5, 9, 10, 16}, + {1, 2, 3, 4, 11, 12, 13, 15}, + {6, 7, 8, 14, 17, 18, 19, 20}, + }, + wantK: 3, + }, +} + +func TestVertexOrdering(t *testing.T) { + for i, test := range vOrderTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + order, core := VertexOrdering(g) + if len(core)-1 != test.wantK { + t.Errorf("unexpected value of k for test %d: got: %d want: %d", i, len(core)-1, test.wantK) + } + var offset int + for k, want := range test.wantCore { + sort.Ints(want) + got := make([]int, len(want)) + for j, n := range order[len(order)-len(want)-offset : len(order)-offset] { + got[j] = n.ID() + } + sort.Ints(got) + if !reflect.DeepEqual(got, want) { + t.Errorf("unexpected %d-core for test %d:\ngot: %v\nwant:%v", got, test.wantCore) + } + + for j, n := range core[k] { + got[j] = n.ID() + } + sort.Ints(got) + if !reflect.DeepEqual(got, want) { + t.Errorf("unexpected %d-core for test %d:\ngot: %v\nwant:%v", got, test.wantCore) + } + offset += len(want) + } + } +} + +var bronKerboschTests = []struct { + g []intset + want [][]int +}{ + { + // This is the example given in the Bron-Kerbosch article on wikipedia (renumbered). + // http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858 + g: []intset{ + 0: linksTo(1, 4), + 1: linksTo(2, 4), + 2: linksTo(3), + 3: linksTo(4, 5), + 4: nil, + 5: nil, + }, + want: [][]int{ + {0, 1, 4}, + {1, 2}, + {2, 3}, + {3, 4}, + {3, 5}, + }, + }, + { + g: batageljZaversnikGraph, + want: [][]int{ + {0}, + {1, 2}, + {1, 3}, + {2, 4}, + {3, 4}, + {4, 5}, + {6, 7, 8, 14}, + {7, 11, 12}, + {9, 11}, + {10, 11}, + {12, 18}, + {13, 14, 15}, + {14, 15, 17}, + {15, 16}, + {17, 18, 19, 20}, + }, + }, +} + +func TestBronKerbosch(t *testing.T) { + for i, test := range bronKerboschTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + cliques := BronKerbosch(g) + got := make([][]int, len(cliques)) + for j, c := range cliques { + ids := make([]int, len(c)) + for k, n := range c { + ids[k] = n.ID() + } + sort.Ints(ids) + got[j] = ids + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected cliques for test %d:\ngot: %v\nwant:%v", i, got, test.want) + } + } +} diff --git a/graph/topo/common_test.go b/graph/topo/common_test.go new file mode 100644 index 00000000..5d21786c --- /dev/null +++ b/graph/topo/common_test.go @@ -0,0 +1,47 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package topo + +// batageljZaversnikGraph is the example graph from +// figure 1 of http://arxiv.org/abs/cs/0310049v1 +var batageljZaversnikGraph = []intset{ + 0: nil, + + 1: linksTo(2, 3), + 2: linksTo(4), + 3: linksTo(4), + 4: linksTo(5), + 5: nil, + + 6: linksTo(7, 8, 14), + 7: linksTo(8, 11, 12, 14), + 8: linksTo(14), + 9: linksTo(11), + 10: linksTo(11), + 11: linksTo(12), + 12: linksTo(18), + 13: linksTo(14, 15), + 14: linksTo(15, 17), + 15: linksTo(16, 17), + 16: nil, + 17: linksTo(18, 19, 20), + 18: linksTo(19, 20), + 19: linksTo(20), + 20: nil, +} + +// intset is an integer set. +type intset map[int]struct{} + +func linksTo(i ...int) intset { + if len(i) == 0 { + return nil + } + s := make(intset) + for _, v := range i { + s[v] = struct{}{} + } + return s +} diff --git a/graph/topo/johnson_cycles.go b/graph/topo/johnson_cycles.go new file mode 100644 index 00000000..e84e203e --- /dev/null +++ b/graph/topo/johnson_cycles.go @@ -0,0 +1,280 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package topo + +import ( + "sort" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/internal/set" +) + +// johnson implements Johnson's "Finding all the elementary +// circuits of a directed graph" algorithm. SIAM J. Comput. 4(1):1975. +// +// Comments in the johnson methods are kept in sync with the comments +// and labels from the paper. +type johnson struct { + adjacent johnsonGraph // SCC adjacency list. + b []set.Ints // Johnson's "B-list". + blocked []bool + s int + + stack []graph.Node + + result [][]graph.Node +} + +// CyclesIn returns the set of elementary cycles in the graph g. +func CyclesIn(g graph.Directed) [][]graph.Node { + jg := johnsonGraphFrom(g) + j := johnson{ + adjacent: jg, + b: make([]set.Ints, len(jg.orig)), + blocked: make([]bool, len(jg.orig)), + } + + // len(j.nodes) is the order of g. + for j.s < len(j.adjacent.orig)-1 { + // We use the previous SCC adjacency to reduce the work needed. + sccs := TarjanSCC(j.adjacent.subgraph(j.s)) + // A_k = adjacency structure of strong component K with least + // vertex in subgraph of G induced by {s, s+1, ... ,n}. + j.adjacent = j.adjacent.sccSubGraph(sccs, 2) // Only allow SCCs with >= 2 vertices. + if j.adjacent.order() == 0 { + break + } + + // s = least vertex in V_k + if s := j.adjacent.leastVertexIndex(); s < j.s { + j.s = s + } + for i, v := range j.adjacent.orig { + if !j.adjacent.nodes.Has(v.ID()) { + continue + } + if len(j.adjacent.succ[v.ID()]) > 0 { + j.blocked[i] = false + j.b[i] = make(set.Ints) + } + } + //L3: + _ = j.circuit(j.s) + j.s++ + } + + return j.result +} + +// circuit is the CIRCUIT sub-procedure in the paper. +func (j *johnson) circuit(v int) bool { + f := false + n := j.adjacent.orig[v] + j.stack = append(j.stack, n) + j.blocked[v] = true + + //L1: + for w := range j.adjacent.succ[n.ID()] { + w = j.adjacent.indexOf(w) + if w == j.s { + // Output circuit composed of stack followed by s. + r := make([]graph.Node, len(j.stack)+1) + copy(r, j.stack) + r[len(r)-1] = j.adjacent.orig[j.s] + j.result = append(j.result, r) + f = true + } else if !j.blocked[w] { + if j.circuit(w) { + f = true + } + } + } + + //L2: + if f { + j.unblock(v) + } else { + for w := range j.adjacent.succ[n.ID()] { + j.b[j.adjacent.indexOf(w)].Add(v) + } + } + j.stack = j.stack[:len(j.stack)-1] + + return f +} + +// unblock is the UNBLOCK sub-procedure in the paper. +func (j *johnson) unblock(u int) { + j.blocked[u] = false + for w := range j.b[u] { + j.b[u].Remove(w) + if j.blocked[w] { + j.unblock(w) + } + } +} + +// johnsonGraph is an edge list representation of a graph with helpers +// necessary for Johnson's algorithm +type johnsonGraph struct { + // Keep the original graph nodes and a + // look-up to into the non-sparse + // collection of potentially sparse IDs. + orig []graph.Node + index map[int]int + + nodes set.Ints + succ map[int]set.Ints +} + +// johnsonGraphFrom returns a deep copy of the graph g. +func johnsonGraphFrom(g graph.Directed) johnsonGraph { + nodes := g.Nodes() + sort.Sort(ordered.ByID(nodes)) + c := johnsonGraph{ + orig: nodes, + index: make(map[int]int, len(nodes)), + + nodes: make(set.Ints, len(nodes)), + succ: make(map[int]set.Ints), + } + for i, u := range nodes { + c.index[u.ID()] = i + for _, v := range g.From(u) { + if c.succ[u.ID()] == nil { + c.succ[u.ID()] = make(set.Ints) + c.nodes.Add(u.ID()) + } + c.nodes.Add(v.ID()) + c.succ[u.ID()].Add(v.ID()) + } + } + return c +} + +// order returns the order of the graph. +func (g johnsonGraph) order() int { return g.nodes.Count() } + +// indexOf returns the index of the retained node for the given node ID. +func (g johnsonGraph) indexOf(id int) int { + return g.index[id] +} + +// leastVertexIndex returns the index into orig of the least vertex. +func (g johnsonGraph) leastVertexIndex() int { + for _, v := range g.orig { + if g.nodes.Has(v.ID()) { + return g.indexOf(v.ID()) + } + } + panic("johnsonCycles: empty set") +} + +// subgraph returns a subgraph of g induced by {s, s+1, ... , n}. The +// subgraph is destructively generated in g. +func (g johnsonGraph) subgraph(s int) johnsonGraph { + sn := g.orig[s].ID() + for u, e := range g.succ { + if u < sn { + g.nodes.Remove(u) + delete(g.succ, u) + continue + } + for v := range e { + if v < sn { + g.succ[u].Remove(v) + } + } + } + return g +} + +// sccSubGraph returns the graph of the tarjan's strongly connected +// components with each SCC containing at least min vertices. +// sccSubGraph returns nil if there is no SCC with at least min +// members. +func (g johnsonGraph) sccSubGraph(sccs [][]graph.Node, min int) johnsonGraph { + if len(g.nodes) == 0 { + g.nodes = nil + g.succ = nil + return g + } + sub := johnsonGraph{ + orig: g.orig, + index: g.index, + nodes: make(set.Ints), + succ: make(map[int]set.Ints), + } + + var n int + for _, scc := range sccs { + if len(scc) < min { + continue + } + n++ + for _, u := range scc { + for _, v := range scc { + if _, ok := g.succ[u.ID()][v.ID()]; ok { + if sub.succ[u.ID()] == nil { + sub.succ[u.ID()] = make(set.Ints) + sub.nodes.Add(u.ID()) + } + sub.nodes.Add(v.ID()) + sub.succ[u.ID()].Add(v.ID()) + } + } + } + } + if n == 0 { + g.nodes = nil + g.succ = nil + return g + } + + return sub +} + +// Nodes is required to satisfy Tarjan. +func (g johnsonGraph) Nodes() []graph.Node { + n := make([]graph.Node, 0, len(g.nodes)) + for id := range g.nodes { + n = append(n, johnsonGraphNode(id)) + } + return n +} + +// Successors is required to satisfy Tarjan. +func (g johnsonGraph) From(n graph.Node) []graph.Node { + adj := g.succ[n.ID()] + if len(adj) == 0 { + return nil + } + succ := make([]graph.Node, 0, len(adj)) + for n := range adj { + succ = append(succ, johnsonGraphNode(n)) + } + return succ +} + +func (johnsonGraph) Has(graph.Node) bool { + panic("topo: unintended use of johnsonGraph") +} +func (johnsonGraph) HasEdgeBetween(_, _ graph.Node) bool { + panic("topo: unintended use of johnsonGraph") +} +func (johnsonGraph) Edge(_, _ graph.Node) graph.Edge { + panic("topo: unintended use of johnsonGraph") +} +func (johnsonGraph) HasEdgeFromTo(_, _ graph.Node) bool { + panic("topo: unintended use of johnsonGraph") +} +func (johnsonGraph) To(graph.Node) []graph.Node { + panic("topo: unintended use of johnsonGraph") +} + +type johnsonGraphNode int + +func (n johnsonGraphNode) ID() int { return int(n) } diff --git a/graph/topo/johnson_cycles_test.go b/graph/topo/johnson_cycles_test.go new file mode 100644 index 00000000..533926c7 --- /dev/null +++ b/graph/topo/johnson_cycles_test.go @@ -0,0 +1,119 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package topo + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var cyclesInTests = []struct { + g []intset + sccs [][]int + want [][]int +}{ + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 7), + 2: linksTo(3, 6), + 3: linksTo(4), + 4: linksTo(2, 5), + 6: linksTo(3, 5), + 7: linksTo(0, 6), + }, + want: [][]int{ + {0, 1, 7, 0}, + {2, 3, 4, 2}, + {2, 6, 3, 4, 2}, + }, + }, + { + g: []intset{ + 0: linksTo(1, 2, 3), + 1: linksTo(2), + 2: linksTo(3), + 3: linksTo(1), + }, + want: [][]int{ + {1, 2, 3, 1}, + }, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(0, 2), + 2: linksTo(1), + }, + want: [][]int{ + {0, 1, 0}, + {1, 2, 1}, + }, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3), + 2: linksTo(4, 5), + 3: linksTo(4, 5), + 4: linksTo(6), + 5: nil, + 6: nil, + }, + want: nil, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3, 4), + 2: linksTo(0, 3), + 3: linksTo(4), + 4: linksTo(3), + }, + want: [][]int{ + {0, 1, 2, 0}, + {3, 4, 3}, + }, + }, +} + +func TestCyclesIn(t *testing.T) { + for i, test := range cyclesInTests { + g := simple.NewDirectedGraph(0, math.Inf(1)) + g.AddNode(simple.Node(-10)) // Make sure we test graphs with sparse IDs. + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + cycles := CyclesIn(g) + var got [][]int + if cycles != nil { + got = make([][]int, len(cycles)) + } + // johnson.circuit does range iteration over maps, + // so sort to ensure consistent ordering. + for j, c := range cycles { + ids := make([]int, len(c)) + for k, n := range c { + ids[k] = n.ID() + } + got[j] = ids + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected johnson result for %d:\n\tgot:%#v\n\twant:%#v", i, got, test.want) + } + } +} diff --git a/graph/topo/non_tomita_choice.go b/graph/topo/non_tomita_choice.go new file mode 100644 index 00000000..de09ebd8 --- /dev/null +++ b/graph/topo/non_tomita_choice.go @@ -0,0 +1,9 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !tomita + +package topo + +const tomitaTanakaTakahashi = false diff --git a/graph/topo/tarjan.go b/graph/topo/tarjan.go new file mode 100644 index 00000000..e5b4d953 --- /dev/null +++ b/graph/topo/tarjan.go @@ -0,0 +1,204 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package topo + +import ( + "fmt" + "sort" + + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" +) + +// Unorderable is an error containing sets of unorderable graph.Nodes. +type Unorderable [][]graph.Node + +// Error satisfies the error interface. +func (e Unorderable) Error() string { + const maxNodes = 10 + var n int + for _, c := range e { + n += len(c) + } + if n > maxNodes { + // Don't return errors that are too long. + return fmt.Sprintf("topo: no topological ordering: %d nodes in %d cyclic components", n, len(e)) + } + return fmt.Sprintf("topo: no topological ordering: cyclic components: %v", [][]graph.Node(e)) +} + +func lexical(nodes []graph.Node) { sort.Sort(ordered.ByID(nodes)) } + +// Sort performs a topological sort of the directed graph g returning the 'from' to 'to' +// sort order. If a topological ordering is not possible, an Unorderable error is returned +// listing cyclic components in g with each cyclic component's members sorted by ID. When +// an Unorderable error is returned, each cyclic component's topological position within +// the sorted nodes is marked with a nil graph.Node. +func Sort(g graph.Directed) (sorted []graph.Node, err error) { + sccs := TarjanSCC(g) + return sortedFrom(sccs, lexical) +} + +// SortStabilized performs a topological sort of the directed graph g returning the 'from' +// to 'to' sort order, or the order defined by the in place order sort function where there +// is no unambiguous topological ordering. If a topological ordering is not possible, an +// Unorderable error is returned listing cyclic components in g with each cyclic component's +// members sorted by the provided order function. If order is nil, nodes are ordered lexically +// by node ID. When an Unorderable error is returned, each cyclic component's topological +// position within the sorted nodes is marked with a nil graph.Node. +func SortStabilized(g graph.Directed, order func([]graph.Node)) (sorted []graph.Node, err error) { + if order == nil { + order = lexical + } + sccs := tarjanSCCstabilized(g, order) + return sortedFrom(sccs, order) +} + +func sortedFrom(sccs [][]graph.Node, order func([]graph.Node)) ([]graph.Node, error) { + sorted := make([]graph.Node, 0, len(sccs)) + var sc Unorderable + for _, s := range sccs { + if len(s) != 1 { + order(s) + sc = append(sc, s) + sorted = append(sorted, nil) + continue + } + sorted = append(sorted, s[0]) + } + var err error + if sc != nil { + for i, j := 0, len(sc)-1; i < j; i, j = i+1, j-1 { + sc[i], sc[j] = sc[j], sc[i] + } + err = sc + } + reverse(sorted) + return sorted, err +} + +func reverse(p []graph.Node) { + for i, j := 0, len(p)-1; i < j; i, j = i+1, j-1 { + p[i], p[j] = p[j], p[i] + } +} + +// TarjanSCC returns the strongly connected components of the graph g using Tarjan's algorithm. +// +// A strongly connected component of a graph is a set of vertices where it's possible to reach any +// vertex in the set from any other (meaning there's a cycle between them.) +// +// Generally speaking, a directed graph where the number of strongly connected components is equal +// to the number of nodes is acyclic, unless you count reflexive edges as a cycle (which requires +// only a little extra testing.) +// +func TarjanSCC(g graph.Directed) [][]graph.Node { + return tarjanSCCstabilized(g, nil) +} + +func tarjanSCCstabilized(g graph.Directed, order func([]graph.Node)) [][]graph.Node { + nodes := g.Nodes() + var succ func(graph.Node) []graph.Node + if order == nil { + succ = g.From + } else { + order(nodes) + reverse(nodes) + + succ = func(n graph.Node) []graph.Node { + to := g.From(n) + order(to) + reverse(to) + return to + } + } + + t := tarjan{ + succ: succ, + + indexTable: make(map[int]int, len(nodes)), + lowLink: make(map[int]int, len(nodes)), + onStack: &intsets.Sparse{}, + } + for _, v := range nodes { + if t.indexTable[v.ID()] == 0 { + t.strongconnect(v) + } + } + return t.sccs +} + +// tarjan implements Tarjan's strongly connected component finding +// algorithm. The implementation is from the pseudocode at +// +// http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm?oldid=642744644 +// +type tarjan struct { + succ func(graph.Node) []graph.Node + + index int + indexTable map[int]int + lowLink map[int]int + onStack *intsets.Sparse + + stack []graph.Node + + sccs [][]graph.Node +} + +// strongconnect is the strongconnect function described in the +// wikipedia article. +func (t *tarjan) strongconnect(v graph.Node) { + vID := v.ID() + + // Set the depth index for v to the smallest unused index. + t.index++ + t.indexTable[vID] = t.index + t.lowLink[vID] = t.index + t.stack = append(t.stack, v) + t.onStack.Insert(vID) + + // Consider successors of v. + for _, w := range t.succ(v) { + wID := w.ID() + if t.indexTable[wID] == 0 { + // Successor w has not yet been visited; recur on it. + t.strongconnect(w) + t.lowLink[vID] = min(t.lowLink[vID], t.lowLink[wID]) + } else if t.onStack.Has(wID) { + // Successor w is in stack s and hence in the current SCC. + t.lowLink[vID] = min(t.lowLink[vID], t.indexTable[wID]) + } + } + + // If v is a root node, pop the stack and generate an SCC. + if t.lowLink[vID] == t.indexTable[vID] { + // Start a new strongly connected component. + var ( + scc []graph.Node + w graph.Node + ) + for { + w, t.stack = t.stack[len(t.stack)-1], t.stack[:len(t.stack)-1] + t.onStack.Remove(w.ID()) + // Add w to current strongly connected component. + scc = append(scc, w) + if w.ID() == vID { + break + } + } + // Output the current strongly connected component. + t.sccs = append(t.sccs, scc) + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/graph/topo/tarjan_test.go b/graph/topo/tarjan_test.go new file mode 100644 index 00000000..086dcdfc --- /dev/null +++ b/graph/topo/tarjan_test.go @@ -0,0 +1,309 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package topo + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +type interval struct{ start, end int } + +var tarjanTests = []struct { + g []intset + + ambiguousOrder []interval + want [][]int + + sortedLength int + unorderableLength int + sortable bool +}{ + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 7), + 2: linksTo(3, 6), + 3: linksTo(4), + 4: linksTo(2, 5), + 6: linksTo(3, 5), + 7: linksTo(0, 6), + }, + + want: [][]int{ + {5}, + {2, 3, 4, 6}, + {0, 1, 7}, + }, + + sortedLength: 1, + unorderableLength: 2, + sortable: false, + }, + { + g: []intset{ + 0: linksTo(1, 2, 3), + 1: linksTo(2), + 2: linksTo(3), + 3: linksTo(1), + }, + + want: [][]int{ + {1, 2, 3}, + {0}, + }, + + sortedLength: 1, + unorderableLength: 1, + sortable: false, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(0, 2), + 2: linksTo(1), + }, + + want: [][]int{ + {0, 1, 2}, + }, + + sortedLength: 0, + unorderableLength: 1, + sortable: false, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3), + 2: linksTo(4, 5), + 3: linksTo(4, 5), + 4: linksTo(6), + 5: nil, + 6: nil, + }, + + // Node pairs (2, 3) and (4, 5) are not + // relatively orderable within each pair. + ambiguousOrder: []interval{ + {0, 3}, // This includes node 6 since it only needs to be before 4 in topo sort. + {3, 5}, + }, + want: [][]int{ + {6}, {5}, {4}, {3}, {2}, {1}, {0}, + }, + + sortedLength: 7, + sortable: true, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3, 4), + 2: linksTo(0, 3), + 3: linksTo(4), + 4: linksTo(3), + }, + + // SCCs are not relatively ordable. + ambiguousOrder: []interval{ + {0, 2}, + }, + want: [][]int{ + {0, 1, 2}, + {3, 4}, + }, + + sortedLength: 0, + unorderableLength: 2, + sortable: false, + }, +} + +func TestSort(t *testing.T) { + for i, test := range tarjanTests { + g := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + sorted, err := Sort(g) + var gotSortedLen int + for _, n := range sorted { + if n != nil { + gotSortedLen++ + } + } + if gotSortedLen != test.sortedLength { + t.Errorf("unexpected number of sortable nodes for test %d: got:%d want:%d", i, gotSortedLen, test.sortedLength) + } + if err == nil != test.sortable { + t.Errorf("unexpected sortability for test %d: got error: %v want: nil-error=%t", i, err, test.sortable) + } + if err != nil && len(err.(Unorderable)) != test.unorderableLength { + t.Errorf("unexpected number of unorderable nodes for test %d: got:%d want:%d", i, len(err.(Unorderable)), test.unorderableLength) + } + } +} + +func TestTarjanSCC(t *testing.T) { + for i, test := range tarjanTests { + g := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + gotSCCs := TarjanSCC(g) + // tarjan.strongconnect does range iteration over maps, + // so sort SCC members to ensure consistent ordering. + gotIDs := make([][]int, len(gotSCCs)) + for i, scc := range gotSCCs { + gotIDs[i] = make([]int, len(scc)) + for j, id := range scc { + gotIDs[i][j] = id.ID() + } + sort.Ints(gotIDs[i]) + } + for _, iv := range test.ambiguousOrder { + sort.Sort(ordered.BySliceValues(test.want[iv.start:iv.end])) + sort.Sort(ordered.BySliceValues(gotIDs[iv.start:iv.end])) + } + if !reflect.DeepEqual(gotIDs, test.want) { + t.Errorf("unexpected Tarjan scc result for %d:\n\tgot:%v\n\twant:%v", i, gotIDs, test.want) + } + } +} + +var stabilizedSortTests = []struct { + g []intset + + want []graph.Node + err error +}{ + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 7), + 2: linksTo(3, 6), + 3: linksTo(4), + 4: linksTo(2, 5), + 6: linksTo(3, 5), + 7: linksTo(0, 6), + }, + + want: []graph.Node{nil, nil, simple.Node(5)}, + err: Unorderable{ + {simple.Node(0), simple.Node(1), simple.Node(7)}, + {simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(6)}, + }, + }, + { + g: []intset{ + 0: linksTo(1, 2, 3), + 1: linksTo(2), + 2: linksTo(3), + 3: linksTo(1), + }, + + want: []graph.Node{simple.Node(0), nil}, + err: Unorderable{ + {simple.Node(1), simple.Node(2), simple.Node(3)}, + }, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(0, 2), + 2: linksTo(1), + }, + + want: []graph.Node{nil}, + err: Unorderable{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + }, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3), + 2: linksTo(4, 5), + 3: linksTo(4, 5), + 4: linksTo(6), + 5: nil, + 6: nil, + }, + + want: []graph.Node{simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(6)}, + err: nil, + }, + { + g: []intset{ + 0: linksTo(1), + 1: linksTo(2, 3, 4), + 2: linksTo(0, 3), + 3: linksTo(4), + 4: linksTo(3), + }, + + want: []graph.Node{nil, nil}, + err: Unorderable{ + {simple.Node(0), simple.Node(1), simple.Node(2)}, + {simple.Node(3), simple.Node(4)}, + }, + }, + { + g: []intset{ + 0: linksTo(1, 2, 3, 4, 5, 6), + 1: linksTo(7), + 2: linksTo(7), + 3: linksTo(7), + 4: linksTo(7), + 5: linksTo(7), + 6: linksTo(7), + 7: nil, + }, + + want: []graph.Node{simple.Node(0), simple.Node(1), simple.Node(2), simple.Node(3), simple.Node(4), simple.Node(5), simple.Node(6), simple.Node(7)}, + err: nil, + }, +} + +func TestSortStabilized(t *testing.T) { + for i, test := range stabilizedSortTests { + g := simple.NewDirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + got, err := SortStabilized(g, nil) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected sort result for test %d: got:%d want:%d", i, got, test.want) + } + if !reflect.DeepEqual(err, test.err) { + t.Errorf("unexpected sort error for test %d: got:%v want:%v", i, err, test.want) + } + } +} diff --git a/graph/topo/tomita_choice.go b/graph/topo/tomita_choice.go new file mode 100644 index 00000000..d4eca625 --- /dev/null +++ b/graph/topo/tomita_choice.go @@ -0,0 +1,9 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build tomita + +package topo + +const tomitaTanakaTakahashi = true diff --git a/graph/topo/topo.go b/graph/topo/topo.go new file mode 100644 index 00000000..4f1d4eed --- /dev/null +++ b/graph/topo/topo.go @@ -0,0 +1,69 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package topo provides graph topology analysis functions. +package topo + +import ( + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/traverse" +) + +// IsPathIn returns whether path is a path in g. +// +// As special cases, IsPathIn returns true for a zero length path or for +// a path of length 1 when the node in path exists in the graph. +func IsPathIn(g graph.Graph, path []graph.Node) bool { + switch len(path) { + case 0: + return true + case 1: + return g.Has(path[0]) + default: + var canReach func(u, v graph.Node) bool + switch g := g.(type) { + case graph.Directed: + canReach = g.HasEdgeFromTo + default: + canReach = g.HasEdgeBetween + } + + for i, u := range path[:len(path)-1] { + if !canReach(u, path[i+1]) { + return false + } + } + return true + } +} + +// PathExistsIn returns whether there is a path in g starting at from extending +// to to. +// +// PathExistsIn exists as a helper function. If many tests for path existence +// are being performed, other approaches will be more efficient. +func PathExistsIn(g graph.Graph, from, to graph.Node) bool { + var t traverse.BreadthFirst + return t.Walk(g, from, func(n graph.Node, _ int) bool { return n.ID() == to.ID() }) != nil +} + +// ConnectedComponents returns the connected components of the undirected graph g. +func ConnectedComponents(g graph.Undirected) [][]graph.Node { + var ( + w traverse.DepthFirst + c []graph.Node + cc [][]graph.Node + ) + during := func(n graph.Node) { + c = append(c, n) + } + after := func() { + cc = append(cc, []graph.Node(nil)) + cc[len(cc)-1] = append(cc[len(cc)-1], c...) + c = c[:0] + } + w.WalkAll(g, nil, after, during) + + return cc +} diff --git a/graph/topo/topo_test.go b/graph/topo/topo_test.go new file mode 100644 index 00000000..f4707ce7 --- /dev/null +++ b/graph/topo/topo_test.go @@ -0,0 +1,176 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package topo + +import ( + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +func TestIsPath(t *testing.T) { + dg := simple.NewDirectedGraph(0, math.Inf(1)) + if !IsPathIn(dg, nil) { + t.Error("IsPath returns false on nil path") + } + p := []graph.Node{simple.Node(0)} + if IsPathIn(dg, p) { + t.Error("IsPath returns true on nonexistant node") + } + dg.AddNode(p[0]) + if !IsPathIn(dg, p) { + t.Error("IsPath returns false on single-length path with existing node") + } + p = append(p, simple.Node(1)) + dg.AddNode(p[1]) + if IsPathIn(dg, p) { + t.Error("IsPath returns true on bad path of length 2") + } + dg.SetEdge(simple.Edge{F: p[0], T: p[1], W: 1}) + if !IsPathIn(dg, p) { + t.Error("IsPath returns false on correct path of length 2") + } + p[0], p[1] = p[1], p[0] + if IsPathIn(dg, p) { + t.Error("IsPath erroneously returns true for a reverse path") + } + p = []graph.Node{p[1], p[0], simple.Node(2)} + dg.SetEdge(simple.Edge{F: p[1], T: p[2], W: 1}) + if !IsPathIn(dg, p) { + t.Error("IsPath does not find a correct path for path > 2 nodes") + } + ug := simple.NewUndirectedGraph(0, math.Inf(1)) + ug.SetEdge(simple.Edge{F: p[1], T: p[0], W: 1}) + ug.SetEdge(simple.Edge{F: p[1], T: p[2], W: 1}) + if !IsPathIn(dg, p) { + t.Error("IsPath does not correctly account for undirected behavior") + } +} + +var pathExistsInUndirectedTests = []struct { + g []intset + from, to int + want bool +}{ + {g: batageljZaversnikGraph, from: 0, to: 0, want: true}, + {g: batageljZaversnikGraph, from: 0, to: 1, want: false}, + {g: batageljZaversnikGraph, from: 1, to: 2, want: true}, + {g: batageljZaversnikGraph, from: 2, to: 1, want: true}, + {g: batageljZaversnikGraph, from: 2, to: 12, want: false}, + {g: batageljZaversnikGraph, from: 20, to: 6, want: true}, +} + +func TestPathExistsInUndirected(t *testing.T) { + for i, test := range pathExistsInUndirectedTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + + for u, e := range test.g { + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + if !g.Has(simple.Node(v)) { + g.AddNode(simple.Node(v)) + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + got := PathExistsIn(g, simple.Node(test.from), simple.Node(test.to)) + if got != test.want { + t.Errorf("unexpected result for path existance in test %d: got:%t want %t", i, got, test.want) + } + } +} + +var pathExistsInDirectedTests = []struct { + g []intset + from, to int + want bool +}{ + // The graph definition is such that from node IDs are + // less than to node IDs. + {g: batageljZaversnikGraph, from: 0, to: 0, want: true}, + {g: batageljZaversnikGraph, from: 0, to: 1, want: false}, + {g: batageljZaversnikGraph, from: 1, to: 2, want: true}, + {g: batageljZaversnikGraph, from: 2, to: 1, want: false}, + {g: batageljZaversnikGraph, from: 2, to: 12, want: false}, + {g: batageljZaversnikGraph, from: 20, to: 6, want: false}, + {g: batageljZaversnikGraph, from: 6, to: 20, want: true}, +} + +func TestPathExistsInDirected(t *testing.T) { + for i, test := range pathExistsInDirectedTests { + g := simple.NewDirectedGraph(0, math.Inf(1)) + + for u, e := range test.g { + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + if !g.Has(simple.Node(v)) { + g.AddNode(simple.Node(v)) + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + + got := PathExistsIn(g, simple.Node(test.from), simple.Node(test.to)) + if got != test.want { + t.Errorf("unexpected result for path existance in test %d: got:%t want %t", i, got, test.want) + } + } +} + +var connectedComponentTests = []struct { + g []intset + want [][]int +}{ + { + g: batageljZaversnikGraph, + want: [][]int{ + {0}, + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, + }, + }, +} + +func TestConnectedComponents(t *testing.T) { + for i, test := range connectedComponentTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + + for u, e := range test.g { + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + if !g.Has(simple.Node(v)) { + g.AddNode(simple.Node(v)) + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + cc := ConnectedComponents(g) + got := make([][]int, len(cc)) + for j, c := range cc { + ids := make([]int, len(c)) + for k, n := range c { + ids[k] = n.ID() + } + sort.Ints(ids) + got[j] = ids + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected connected components for test %d %T:\ngot: %v\nwant:%v", i, g, got, test.want) + } + } +} diff --git a/graph/traverse/traverse.go b/graph/traverse/traverse.go new file mode 100644 index 00000000..715d881e --- /dev/null +++ b/graph/traverse/traverse.go @@ -0,0 +1,186 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package traverse provides basic graph traversal primitives. +package traverse + +import ( + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/internal/linear" +) + +// BreadthFirst implements stateful breadth-first graph traversal. +type BreadthFirst struct { + EdgeFilter func(graph.Edge) bool + Visit func(u, v graph.Node) + queue linear.NodeQueue + visited *intsets.Sparse +} + +// Walk performs a breadth-first traversal of the graph g starting from the given node, +// depending on the the EdgeFilter field and the until parameter if they are non-nil. The +// traversal follows edges for which EdgeFilter(edge) is true and returns the first node +// for which until(node, depth) is true. During the traversal, if the Visit field is +// non-nil, it is called with the nodes joined by each followed edge. +func (b *BreadthFirst) Walk(g graph.Graph, from graph.Node, until func(n graph.Node, d int) bool) graph.Node { + if b.visited == nil { + b.visited = &intsets.Sparse{} + } + b.queue.Enqueue(from) + b.visited.Insert(from.ID()) + + var ( + depth int + children int + untilNext = 1 + ) + for b.queue.Len() > 0 { + t := b.queue.Dequeue() + if until != nil && until(t, depth) { + return t + } + for _, n := range g.From(t) { + if b.EdgeFilter != nil && !b.EdgeFilter(g.Edge(t, n)) { + continue + } + if b.visited.Has(n.ID()) { + continue + } + if b.Visit != nil { + b.Visit(t, n) + } + b.visited.Insert(n.ID()) + children++ + b.queue.Enqueue(n) + } + if untilNext--; untilNext == 0 { + depth++ + untilNext = children + children = 0 + } + } + + return nil +} + +// WalkAll calls Walk for each unvisited node of the graph g using edges independent +// of their direction. The functions before and after are called prior to commencing +// and after completing each walk if they are non-nil respectively. The function +// during is called on each node as it is traversed. +func (b *BreadthFirst) WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) { + b.Reset() + for _, from := range g.Nodes() { + if b.Visited(from) { + continue + } + if before != nil { + before() + } + b.Walk(g, from, func(n graph.Node, _ int) bool { + if during != nil { + during(n) + } + return false + }) + if after != nil { + after() + } + } +} + +// Visited returned whether the node n was visited during a traverse. +func (b *BreadthFirst) Visited(n graph.Node) bool { + return b.visited != nil && b.visited.Has(n.ID()) +} + +// Reset resets the state of the traverser for reuse. +func (b *BreadthFirst) Reset() { + b.queue.Reset() + if b.visited != nil { + b.visited.Clear() + } +} + +// DepthFirst implements stateful depth-first graph traversal. +type DepthFirst struct { + EdgeFilter func(graph.Edge) bool + Visit func(u, v graph.Node) + stack linear.NodeStack + visited *intsets.Sparse +} + +// Walk performs a depth-first traversal of the graph g starting from the given node, +// depending on the the EdgeFilter field and the until parameter if they are non-nil. The +// traversal follows edges for which EdgeFilter(edge) is true and returns the first node +// for which until(node) is true. During the traversal, if the Visit field is non-nil, it +// is called with the nodes joined by each followed edge. +func (d *DepthFirst) Walk(g graph.Graph, from graph.Node, until func(graph.Node) bool) graph.Node { + if d.visited == nil { + d.visited = &intsets.Sparse{} + } + d.stack.Push(from) + d.visited.Insert(from.ID()) + + for d.stack.Len() > 0 { + t := d.stack.Pop() + if until != nil && until(t) { + return t + } + for _, n := range g.From(t) { + if d.EdgeFilter != nil && !d.EdgeFilter(g.Edge(t, n)) { + continue + } + if d.visited.Has(n.ID()) { + continue + } + if d.Visit != nil { + d.Visit(t, n) + } + d.visited.Insert(n.ID()) + d.stack.Push(n) + } + } + + return nil +} + +// WalkAll calls Walk for each unvisited node of the graph g using edges independent +// of their direction. The functions before and after are called prior to commencing +// and after completing each walk if they are non-nil respectively. The function +// during is called on each node as it is traversed. +func (d *DepthFirst) WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) { + d.Reset() + for _, from := range g.Nodes() { + if d.Visited(from) { + continue + } + if before != nil { + before() + } + d.Walk(g, from, func(n graph.Node) bool { + if during != nil { + during(n) + } + return false + }) + if after != nil { + after() + } + } +} + +// Visited returned whether the node n was visited during a traverse. +func (d *DepthFirst) Visited(n graph.Node) bool { + return d.visited != nil && d.visited.Has(n.ID()) +} + +// Reset resets the state of the traverser for reuse. +func (d *DepthFirst) Reset() { + d.stack = d.stack[:0] + if d.visited != nil { + d.visited.Clear() + } +} diff --git a/graph/traverse/traverse_test.go b/graph/traverse/traverse_test.go new file mode 100644 index 00000000..b611c463 --- /dev/null +++ b/graph/traverse/traverse_test.go @@ -0,0 +1,434 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package traverse + +import ( + "fmt" + "math" + "reflect" + "sort" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/graphs/gen" + "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/simple" +) + +var ( + // batageljZaversnikGraph is the example graph from + // figure 1 of http://arxiv.org/abs/cs/0310049v1 + batageljZaversnikGraph = []set{ + 0: nil, + + 1: linksTo(2, 3), + 2: linksTo(4), + 3: linksTo(4), + 4: linksTo(5), + 5: nil, + + 6: linksTo(7, 8, 14), + 7: linksTo(8, 11, 12, 14), + 8: linksTo(14), + 9: linksTo(11), + 10: linksTo(11), + 11: linksTo(12), + 12: linksTo(18), + 13: linksTo(14, 15), + 14: linksTo(15, 17), + 15: linksTo(16, 17), + 16: nil, + 17: linksTo(18, 19, 20), + 18: linksTo(19, 20), + 19: linksTo(20), + 20: nil, + } + + // wpBronKerboschGraph is the example given in the Bron-Kerbosch article on wikipedia (renumbered). + // http://en.wikipedia.org/w/index.php?title=Bron%E2%80%93Kerbosch_algorithm&oldid=656805858 + wpBronKerboschGraph = []set{ + 0: linksTo(1, 4), + 1: linksTo(2, 4), + 2: linksTo(3), + 3: linksTo(4, 5), + 4: nil, + 5: nil, + } +) + +var breadthFirstTests = []struct { + g []set + from graph.Node + edge func(graph.Edge) bool + until func(graph.Node, int) bool + final map[graph.Node]bool + want [][]int +}{ + { + g: wpBronKerboschGraph, + from: simple.Node(1), + final: map[graph.Node]bool{nil: true}, + want: [][]int{ + {1}, + {0, 2, 4}, + {3}, + {5}, + }, + }, + { + g: wpBronKerboschGraph, + edge: func(e graph.Edge) bool { + // Do not traverse an edge between 3 and 5. + return (e.From().ID() != 3 || e.To().ID() != 5) && (e.From().ID() != 5 || e.To().ID() != 3) + }, + from: simple.Node(1), + final: map[graph.Node]bool{nil: true}, + want: [][]int{ + {1}, + {0, 2, 4}, + {3}, + }, + }, + { + g: wpBronKerboschGraph, + from: simple.Node(1), + until: func(n graph.Node, _ int) bool { return n == simple.Node(3) }, + final: map[graph.Node]bool{simple.Node(3): true}, + want: [][]int{ + {1}, + {0, 2, 4}, + }, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(13), + final: map[graph.Node]bool{nil: true}, + want: [][]int{ + {13}, + {14, 15}, + {6, 7, 8, 16, 17}, + {11, 12, 18, 19, 20}, + {9, 10}, + }, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(13), + until: func(_ graph.Node, d int) bool { return d > 2 }, + final: map[graph.Node]bool{ + simple.Node(11): true, + simple.Node(12): true, + simple.Node(18): true, + simple.Node(19): true, + simple.Node(20): true, + }, + want: [][]int{ + {13}, + {14, 15}, + {6, 7, 8, 16, 17}, + }, + }, +} + +func TestBreadthFirst(t *testing.T) { + for i, test := range breadthFirstTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + w := BreadthFirst{ + EdgeFilter: test.edge, + } + var got [][]int + final := w.Walk(g, test.from, func(n graph.Node, d int) bool { + if test.until != nil && test.until(n, d) { + return true + } + if d >= len(got) { + got = append(got, []int(nil)) + } + got[d] = append(got[d], n.ID()) + return false + }) + if !test.final[final] { + t.Errorf("unexepected final node for test %d:\ngot: %v\nwant: %v", i, final, test.final) + } + for _, l := range got { + sort.Ints(l) + } + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexepected BFS level structure for test %d:\ngot: %v\nwant: %v", i, got, test.want) + } + } +} + +var depthFirstTests = []struct { + g []set + from graph.Node + edge func(graph.Edge) bool + until func(graph.Node) bool + final map[graph.Node]bool + want []int +}{ + { + g: wpBronKerboschGraph, + from: simple.Node(1), + final: map[graph.Node]bool{nil: true}, + want: []int{0, 1, 2, 3, 4, 5}, + }, + { + g: wpBronKerboschGraph, + edge: func(e graph.Edge) bool { + // Do not traverse an edge between 3 and 5. + return (e.From().ID() != 3 || e.To().ID() != 5) && (e.From().ID() != 5 || e.To().ID() != 3) + }, + from: simple.Node(1), + final: map[graph.Node]bool{nil: true}, + want: []int{0, 1, 2, 3, 4}, + }, + { + g: wpBronKerboschGraph, + from: simple.Node(1), + until: func(n graph.Node) bool { return n == simple.Node(3) }, + final: map[graph.Node]bool{simple.Node(3): true}, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(0), + final: map[graph.Node]bool{nil: true}, + want: []int{0}, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(3), + final: map[graph.Node]bool{nil: true}, + want: []int{1, 2, 3, 4, 5}, + }, + { + g: batageljZaversnikGraph, + from: simple.Node(13), + final: map[graph.Node]bool{nil: true}, + want: []int{6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, + }, +} + +func TestDepthFirst(t *testing.T) { + for i, test := range depthFirstTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + for u, e := range test.g { + // Add nodes that are not defined by an edge. + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + w := DepthFirst{ + EdgeFilter: test.edge, + } + var got []int + final := w.Walk(g, test.from, func(n graph.Node) bool { + if test.until != nil && test.until(n) { + return true + } + got = append(got, n.ID()) + return false + }) + if !test.final[final] { + t.Errorf("unexepected final node for test %d:\ngot: %v\nwant: %v", i, final, test.final) + } + sort.Ints(got) + if test.want != nil && !reflect.DeepEqual(got, test.want) { + t.Errorf("unexepected DFS traversed nodes for test %d:\ngot: %v\nwant: %v", i, got, test.want) + } + } +} + +var walkAllTests = []struct { + g []set + edge func(graph.Edge) bool + want [][]int +}{ + { + g: batageljZaversnikGraph, + want: [][]int{ + {0}, + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, + }, + }, + { + g: batageljZaversnikGraph, + edge: func(e graph.Edge) bool { + // Do not traverse an edge between 3 and 5. + return (e.From().ID() != 4 || e.To().ID() != 5) && (e.From().ID() != 5 || e.To().ID() != 4) + }, + want: [][]int{ + {0}, + {1, 2, 3, 4}, + {5}, + {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, + }, + }, +} + +func TestWalkAll(t *testing.T) { + for i, test := range walkAllTests { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + + for u, e := range test.g { + if !g.Has(simple.Node(u)) { + g.AddNode(simple.Node(u)) + } + for v := range e { + if !g.Has(simple.Node(v)) { + g.AddNode(simple.Node(v)) + } + g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) + } + } + type walker interface { + WalkAll(g graph.Undirected, before, after func(), during func(graph.Node)) + } + for _, w := range []walker{ + &BreadthFirst{}, + &DepthFirst{}, + } { + var ( + c []graph.Node + cc [][]graph.Node + ) + switch w := w.(type) { + case *BreadthFirst: + w.EdgeFilter = test.edge + case *DepthFirst: + w.EdgeFilter = test.edge + default: + panic(fmt.Sprintf("bad walker type: %T", w)) + } + during := func(n graph.Node) { + c = append(c, n) + } + after := func() { + cc = append(cc, []graph.Node(nil)) + cc[len(cc)-1] = append(cc[len(cc)-1], c...) + c = c[:0] + } + w.WalkAll(g, nil, after, during) + + got := make([][]int, len(cc)) + for j, c := range cc { + ids := make([]int, len(c)) + for k, n := range c { + ids[k] = n.ID() + } + sort.Ints(ids) + got[j] = ids + } + sort.Sort(ordered.BySliceValues(got)) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("unexpected connected components for test %d using %T:\ngot: %v\nwant:%v", i, w, got, test.want) + } + } + } +} + +// set is an integer set. +type set map[int]struct{} + +func linksTo(i ...int) set { + if len(i) == 0 { + return nil + } + s := make(set) + for _, v := range i { + s[v] = struct{}{} + } + return s +} + +var ( + gnpUndirected_10_tenth = gnpUndirected(10, 0.1) + gnpUndirected_100_tenth = gnpUndirected(100, 0.1) + gnpUndirected_1000_tenth = gnpUndirected(1000, 0.1) + gnpUndirected_10_half = gnpUndirected(10, 0.5) + gnpUndirected_100_half = gnpUndirected(100, 0.5) + gnpUndirected_1000_half = gnpUndirected(1000, 0.5) +) + +func gnpUndirected(n int, p float64) graph.Undirected { + g := simple.NewUndirectedGraph(0, math.Inf(1)) + gen.Gnp(g, n, p, nil) + return g +} + +func benchmarkWalkAllBreadthFirst(b *testing.B, g graph.Undirected) { + n := len(g.Nodes()) + b.ResetTimer() + var bft BreadthFirst + for i := 0; i < b.N; i++ { + bft.WalkAll(g, nil, nil, nil) + } + if bft.visited.Len() != n { + b.Fatalf("unexpected number of nodes visited: want: %d got %d", n, bft.visited.Len()) + } +} + +func BenchmarkWalkAllBreadthFirstGnp_10_tenth(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_10_tenth) +} +func BenchmarkWalkAllBreadthFirstGnp_100_tenth(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_100_tenth) +} +func BenchmarkWalkAllBreadthFirstGnp_1000_tenth(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_1000_tenth) +} +func BenchmarkWalkAllBreadthFirstGnp_10_half(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_10_half) +} +func BenchmarkWalkAllBreadthFirstGnp_100_half(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_100_half) +} +func BenchmarkWalkAllBreadthFirstGnp_1000_half(b *testing.B) { + benchmarkWalkAllBreadthFirst(b, gnpUndirected_1000_half) +} + +func benchmarkWalkAllDepthFirst(b *testing.B, g graph.Undirected) { + n := len(g.Nodes()) + b.ResetTimer() + var dft DepthFirst + for i := 0; i < b.N; i++ { + dft.WalkAll(g, nil, nil, nil) + } + if dft.visited.Len() != n { + b.Fatalf("unexpected number of nodes visited: want: %d got %d", n, dft.visited.Len()) + } +} + +func BenchmarkWalkAllDepthFirstGnp_10_tenth(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_10_tenth) +} +func BenchmarkWalkAllDepthFirstGnp_100_tenth(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_100_tenth) +} +func BenchmarkWalkAllDepthFirstGnp_1000_tenth(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_1000_tenth) +} +func BenchmarkWalkAllDepthFirstGnp_10_half(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_10_half) +} +func BenchmarkWalkAllDepthFirstGnp_100_half(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_100_half) +} +func BenchmarkWalkAllDepthFirstGnp_1000_half(b *testing.B) { + benchmarkWalkAllDepthFirst(b, gnpUndirected_1000_half) +} diff --git a/graph/undirect.go b/graph/undirect.go new file mode 100644 index 00000000..3dd3dfb3 --- /dev/null +++ b/graph/undirect.go @@ -0,0 +1,185 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package graph + +import ( + "golang.org/x/tools/container/intsets" +) + +// Undirect converts a directed graph to an undirected graph, resolving +// edge weight conflicts. +type Undirect struct { + G Directed + + // Absent is the value used to + // represent absent edge weights + // passed to Merge if the reverse + // edge is present. + Absent float64 + + // Merge defines how discordant edge + // weights in G are resolved. A merge + // is performed if at least one edge + // exists between the nodes being + // considered. The edges corresponding + // to the two weights are also passed, + // in the same order. + // The order of weight parameters + // passed to Merge is not defined, so + // the function should be commutative. + // If Merge is nil, the arithmetic + // mean is used to merge weights. + Merge func(x, y float64, xe, ye Edge) float64 +} + +var ( + _ Undirected = Undirect{} + _ Weighter = Undirect{} +) + +// Has returns whether the node exists within the graph. +func (g Undirect) Has(n Node) bool { return g.G.Has(n) } + +// Nodes returns all the nodes in the graph. +func (g Undirect) Nodes() []Node { return g.G.Nodes() } + +// From returns all nodes in g that can be reached directly from u. +func (g Undirect) From(u Node) []Node { + var ( + nodes []Node + seen intsets.Sparse + ) + for _, n := range g.G.From(u) { + seen.Insert(n.ID()) + nodes = append(nodes, n) + } + for _, n := range g.G.To(u) { + id := n.ID() + if seen.Has(id) { + continue + } + seen.Insert(id) + nodes = append(nodes, n) + } + return nodes +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g Undirect) HasEdgeBetween(x, y Node) bool { return g.G.HasEdgeBetween(x, y) } + +// Edge returns the edge from u to v if such an edge exists and nil otherwise. +// The node v must be directly reachable from u as defined by the From method. +// If an edge exists, the Edge returned is an EdgePair. The weight of +// the edge is determined by applying the Merge func to the weights of the +// edges between u and v. +func (g Undirect) Edge(u, v Node) Edge { return g.EdgeBetween(u, v) } + +// EdgeBetween returns the edge between nodes x and y. If an edge exists, the +// Edge returned is an EdgePair. The weight of the edge is determined by +// applying the Merge func to the weights of edges between x and y. +func (g Undirect) EdgeBetween(x, y Node) Edge { + fe := g.G.Edge(x, y) + re := g.G.Edge(y, x) + if fe == nil && re == nil { + return nil + } + + var f, r float64 + if wg, ok := g.G.(Weighter); ok { + f, ok = wg.Weight(x, y) + if !ok { + f = g.Absent + } + r, ok = wg.Weight(y, x) + if !ok { + r = g.Absent + } + } else { + f = g.Absent + if fe != nil { + f = fe.Weight() + } + r = g.Absent + if re != nil { + r = re.Weight() + } + } + + var w float64 + if g.Merge == nil { + w = (f + r) / 2 + } else { + w = g.Merge(f, r, fe, re) + } + return EdgePair{E: [2]Edge{fe, re}, W: w} +} + +// Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. +// If x and y are the same node the internal node weight is returned. If there is no joining +// edge between the two nodes the weight value returned is zero. Weight returns true if an edge +// exists between x and y or if x and y have the same ID, false otherwise. +func (g Undirect) Weight(x, y Node) (w float64, ok bool) { + fe := g.G.Edge(x, y) + re := g.G.Edge(y, x) + + var f, r float64 + if wg, wOk := g.G.(Weighter); wOk { + var fOk, rOK bool + f, fOk = wg.Weight(x, y) + if !fOk { + f = g.Absent + } + r, rOK = wg.Weight(y, x) + if !rOK { + r = g.Absent + } + ok = fOk || rOK + } else { + f = g.Absent + if fe != nil { + f = fe.Weight() + ok = true + } + r = g.Absent + if re != nil { + r = re.Weight() + ok = true + } + } + + if g.Merge == nil { + return (f + r) / 2, ok + } + return g.Merge(f, r, fe, re), ok +} + +// EdgePair is an opposed pair of directed edges. +type EdgePair struct { + E [2]Edge + W float64 +} + +// From returns the from node of the first non-nil edge, or nil. +func (e EdgePair) From() Node { + if e.E[0] != nil { + return e.E[0].From() + } else if e.E[1] != nil { + return e.E[1].From() + } + return nil +} + +// To returns the to node of the first non-nil edge, or nil. +func (e EdgePair) To() Node { + if e.E[0] != nil { + return e.E[0].To() + } else if e.E[1] != nil { + return e.E[1].To() + } + return nil +} + +// Weight returns the merged edge weights of the two edges. +func (e EdgePair) Weight() float64 { return e.W } diff --git a/graph/undirect_test.go b/graph/undirect_test.go new file mode 100644 index 00000000..56acfa65 --- /dev/null +++ b/graph/undirect_test.go @@ -0,0 +1,126 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package graph_test + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/graph" + "gonum.org/v1/gonum/graph/simple" + "gonum.org/v1/gonum/matrix/mat64" +) + +var directedGraphs = []struct { + g func() graph.DirectedBuilder + edges []simple.Edge + absent float64 + merge func(x, y float64, xe, ye graph.Edge) float64 + + want mat64.Matrix +}{ + { + g: func() graph.DirectedBuilder { return simple.NewDirectedGraph(0, 0) }, + edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + want: mat64.NewSymDense(3, []float64{ + 0, (1. + 2.) / 2., 0, + (1. + 2.) / 2., 0, 1. / 2., + 0, 1. / 2., 0, + }), + }, + { + g: func() graph.DirectedBuilder { return simple.NewDirectedGraph(0, 0) }, + edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + absent: 1, + merge: func(x, y float64, _, _ graph.Edge) float64 { return math.Sqrt(x * y) }, + want: mat64.NewSymDense(3, []float64{ + 0, math.Sqrt(1 * 2), 0, + math.Sqrt(1 * 2), 0, math.Sqrt(1 * 1), + 0, math.Sqrt(1 * 1), 0, + }), + }, + { + g: func() graph.DirectedBuilder { return simple.NewDirectedGraph(0, 0) }, + edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + merge: func(x, y float64, _, _ graph.Edge) float64 { return math.Min(x, y) }, + want: mat64.NewSymDense(3, []float64{ + 0, math.Min(1, 2), 0, + math.Min(1, 2), 0, math.Min(1, 0), + 0, math.Min(1, 0), 0, + }), + }, + { + g: func() graph.DirectedBuilder { return simple.NewDirectedGraph(0, 0) }, + edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + merge: func(x, y float64, xe, ye graph.Edge) float64 { + if xe == nil { + return y + } + if ye == nil { + return x + } + return math.Min(x, y) + }, + want: mat64.NewSymDense(3, []float64{ + 0, math.Min(1, 2), 0, + math.Min(1, 2), 0, 1, + 0, 1, 0, + }), + }, + { + g: func() graph.DirectedBuilder { return simple.NewDirectedGraph(0, 0) }, + edges: []simple.Edge{ + {F: simple.Node(0), T: simple.Node(1), W: 2}, + {F: simple.Node(1), T: simple.Node(0), W: 1}, + {F: simple.Node(1), T: simple.Node(2), W: 1}, + }, + merge: func(x, y float64, _, _ graph.Edge) float64 { return math.Max(x, y) }, + want: mat64.NewSymDense(3, []float64{ + 0, math.Max(1, 2), 0, + math.Max(1, 2), 0, math.Max(1, 0), + 0, math.Max(1, 0), 0, + }), + }, +} + +func TestUndirect(t *testing.T) { + for _, test := range directedGraphs { + g := test.g() + for _, e := range test.edges { + g.SetEdge(e) + } + + src := graph.Undirect{G: g, Absent: test.absent, Merge: test.merge} + dst := simple.NewUndirectedMatrixFrom(src.Nodes(), 0, 0, 0) + for _, u := range src.Nodes() { + for _, v := range src.From(u) { + dst.SetEdge(src.Edge(u, v)) + } + } + + if !mat64.Equal(dst.Matrix(), test.want) { + t.Errorf("unexpected result:\ngot:\n%.4v\nwant:\n%.4v", + mat64.Formatted(dst.Matrix()), + mat64.Formatted(test.want), + ) + } + } +} diff --git a/integrate/README.md b/integrate/README.md new file mode 100644 index 00000000..5da1f320 --- /dev/null +++ b/integrate/README.md @@ -0,0 +1,13 @@ +# Gonum integrate [![Build Status](https://travis-ci.org/gonum/integrate.svg?branch=master)](https://travis-ci.org/gonum/integrate) [![Coverage Status](https://coveralls.io/repos/gonum/integrate/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/integrate?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/integrate?status.svg)](https://godoc.org/github.com/gonum/integrate) + +Package integrate provides numerical evaluation of definite integrals of single-variable functions for the Go programming language. + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see https://github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/integrate/doc.go b/integrate/doc.go new file mode 100644 index 00000000..cd65327e --- /dev/null +++ b/integrate/doc.go @@ -0,0 +1,7 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package integrate provides functions to compute an integral given a +// specific list of evaluations. +package integrate // "github.com/gonum/integrate" diff --git a/integrate/quad/example_test.go b/integrate/quad/example_test.go new file mode 100644 index 00000000..32a4886a --- /dev/null +++ b/integrate/quad/example_test.go @@ -0,0 +1,47 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package quad_test + +import ( + "fmt" + "math" + "runtime" + + "gonum.org/v1/gonum/integrate/quad" + "gonum.org/v1/gonum/stat/distuv" +) + +func Example() { + fmt.Println("Evaluate the expected value of x^2 + 3 under a Weibull distribution") + f := func(x float64) float64 { + d := distuv.Weibull{Lambda: 1, K: 1.5} + return (x*x + 3) * d.Prob(x) + } + ev := quad.Fixed(f, 0, math.Inf(1), 10, nil, 0) + fmt.Printf("EV with 10 points = %0.6v\n", ev) + + ev = quad.Fixed(f, 0, math.Inf(1), 30, nil, 0) + fmt.Printf("EV with 30 points = %0.6v\n", ev) + + ev = quad.Fixed(f, 0, math.Inf(1), 100, nil, 0) + fmt.Printf("EV with 100 points = %0.6v\n", ev) + + ev = quad.Fixed(f, 0, math.Inf(1), 10000, nil, 0) + fmt.Printf("EV with 10000 points = %0.6v\n\n", ev) + + fmt.Println("Estimate using parallel evaluations of f.") + concurrent := runtime.GOMAXPROCS(0) + ev = quad.Fixed(f, 0, math.Inf(1), 100, nil, concurrent) + fmt.Printf("EV = %0.6v\n", ev) + // Output: + // Evaluate the expected value of x^2 + 3 under a Weibull distribution + // EV with 10 points = 4.20175 + // EV with 30 points = 4.19066 + // EV with 100 points = 4.19064 + // EV with 10000 points = 4.19064 + // + // Estimate using parallel evaluations of f. + // EV = 4.19064 +} diff --git a/integrate/quad/hermite.go b/integrate/quad/hermite.go new file mode 100644 index 00000000..d2755f0e --- /dev/null +++ b/integrate/quad/hermite.go @@ -0,0 +1,314 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package quad + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mathext" +) + +// Hermite generates sample locations and weights for performing quadrature with +// with a squared-exponential weight +// int_-inf^inf e^(-x^2) f(x) dx . +type Hermite struct{} + +func (h Hermite) FixedLocations(x, weight []float64, min, max float64) { + // TODO(btracey): Implement the case where x > 20, x < 200 so that we don't + // need to store all of that data. + + // Algorithm adapted from Chebfun http://www.chebfun.org/. + // + // References: + // Algorithm: + // G. H. Golub and J. A. Welsch, "Calculation of Gauss quadrature rules", + // Math. Comp. 23:221-230, 1969. + // A. Glaser, X. Liu and V. Rokhlin, "A fast algorithm for the + // calculation of the roots of special functions", SIAM Journal + // on Scientific Computing", 29(4):1420-1438:, 2007. + // A. Townsend, T. Trogdon, and S.Olver, Fast computation of Gauss quadrature + // nodes and weights on the whole real line, IMA J. Numer. Anal., 36: 337–358, + // 2016. http://arxiv.org/abs/1410.5286 + + if len(x) != len(weight) { + panic("hermite: slice length mismatch") + } + if min >= max { + panic("hermite: min >= max") + } + if !math.IsInf(min, -1) || !math.IsInf(max, 1) { + panic("hermite: non-infinite bound") + } + h.locations(x, weight) +} + +func (h Hermite) locations(x, weights []float64) { + n := len(x) + switch { + case 0 < n && n <= 200: + copy(x, xCacheHermite[n-1]) + copy(weights, wCacheHermite[n-1]) + case n > 200: + h.locationsAsy(x, weights) + } +} + +// Algorithm adapted from Chebfun http://www.chebfun.org/. Specific code +// https://github.com/chebfun/chebfun/blob/development/hermpts.m. + +// Original Copyright Notice: + +/* +Copyright (c) 2015, The Chancellor, Masters and Scholars of the University +of Oxford, and the Chebfun Developers. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the University of Oxford nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// locationAsy returns the node locations and weights of a Hermite quadrature rule +// with len(x) points. +func (h Hermite) locationsAsy(x, w []float64) { + // A. Townsend, T. Trogdon, and S.Olver, Fast computation of Gauss quadrature + // nodes and weights the whole real line, IMA J. Numer. Anal., + // 36: 337–358, 2016. http://arxiv.org/abs/1410.5286 + + // Find the positive locations and weights. + n := len(x) + l := n / 2 + xa := x[l:] + wa := w[l:] + for i := range xa { + xa[i], wa[i] = h.locationsAsy0(i, n) + } + // Flip around zero -- copy the negative x locations with the corresponding + // weights. + if n%2 == 0 { + l-- + } + for i, v := range xa { + x[l-i] = -v + } + for i, v := range wa { + w[l-i] = v + } + sumW := floats.Sum(w) + c := math.SqrtPi / sumW + floats.Scale(c, w) +} + +// locationsAsy0 returns the location and weight for location i in an n-point +// quadrature rule. The rule is symmetric, so i should be <= n/2 + n%2. +func (h Hermite) locationsAsy0(i, n int) (x, w float64) { + const convTol = 1e-16 + const convIter = 20 + theta0 := h.hermiteInitialGuess(i, n) + t0 := theta0 / math.Sqrt(2*float64(n)+1) + theta0 = math.Acos(t0) + sqrt2np1 := math.Sqrt(2*float64(n) + 1) + var vali, dvali float64 + for k := 0; k < convIter; k++ { + vali, dvali = h.hermpolyAsyAiry(i, n, theta0) + dt := -vali / (math.Sqrt2 * sqrt2np1 * dvali * math.Sin(theta0)) + theta0 -= dt + if math.Abs(theta0) < convTol { + break + } + } + x = sqrt2np1 * math.Cos(theta0) + ders := x*vali + math.Sqrt2*dvali + w = math.Exp(-x*x) / (ders * ders) + return x, w +} + +// hermpolyAsyAiry evaluates the Hermite polynomials using the Airy asymptotic +// formula in theta-space. +func (h Hermite) hermpolyAsyAiry(i, n int, t float64) (valVec, dvalVec float64) { + musq := 2*float64(n) + 1 + cosT := math.Cos(t) + sinT := math.Sin(t) + sin2T := 2 * cosT * sinT + eta := 0.5*t - 0.25*sin2T + chi := -math.Pow(3*eta/2, 2.0/3) + phi := math.Pow(-chi/(sinT*sinT), 1.0/4) + cnst := 2 * math.SqrtPi * math.Pow(musq, 1.0/6) * phi + airy0 := real(mathext.AiryAi(complex(math.Pow(musq, 2.0/3)*chi, 0))) + airy1 := real(mathext.AiryAiDeriv(complex(math.Pow(musq, 2.0/3)*chi, 0))) + + // Terms in 12.10.43: + const ( + a1 = 15.0 / 144 + b1 = -7.0 / 5 * a1 + a2 = 5.0 * 7 * 9 * 11.0 / 2.0 / 144.0 / 144.0 + b2 = -13.0 / 11 * a2 + a3 = 7.0 * 9 * 11 * 13 * 15 * 17 / 6.0 / 144.0 / 144.0 / 144.0 + b3 = -19.0 / 17 * a3 + ) + + // Pre-compute terms. + cos2T := cosT * cosT + cos3T := cos2T * cosT + cos4T := cos3T * cosT + cos5T := cos4T * cosT + cos7T := cos5T * cos2T + cos9T := cos7T * cos2T + + chi2 := chi * chi + chi3 := chi2 * chi + chi4 := chi3 * chi + chi5 := chi4 * chi + + phi6 := math.Pow(phi, 6) + phi12 := phi6 * phi6 + phi18 := phi12 * phi6 + + // u polynomials in 12.10.9. + u1 := (cos3T - 6*cosT) / 24.0 + u2 := (-9*cos4T + 249*cos2T + 145) / 1152.0 + u3 := (-4042*cos9T + 18189*cos7T - 28287*cos5T - 151995*cos3T - 259290*cosT) / 414720.0 + + val := airy0 + B0 := -(phi6*u1 + a1) / chi2 + val += B0 * airy1 / math.Pow(musq, 4.0/3) + A1 := (phi12*u2 + b1*phi6*u1 + b2) / chi3 + val += A1 * airy0 / (musq * musq) + B1 := -(phi18*u3 + a1*phi12*u2 + a2*phi6*u1 + a3) / chi5 + val += B1 * airy1 / math.Pow(musq, 4.0/3+2) + val *= cnst + + // Derivative. + eta = 0.5*t - 0.25*sin2T + chi = -math.Pow(3*eta/2, 2.0/3) + phi = math.Pow(-chi/(sinT*sinT), 1.0/4) + cnst = math.Sqrt2 * math.SqrtPi * math.Pow(musq, 1.0/3) / phi + + // v polynomials in 12.10.10. + v1 := (cos3T + 6*cosT) / 24 + v2 := (15*cos4T - 327*cos2T - 143) / 1152 + v3 := (259290*cosT + 238425*cos3T - 36387*cos5T + 18189*cos7T - 4042*cos9T) / 414720 + + C0 := -(phi6*v1 + b1) / chi + dval := C0 * airy0 / math.Pow(musq, 2.0/3) + dval += airy1 + C1 := -(phi18*v3 + b1*phi12*v2 + b2*phi6*v1 + b3) / chi4 + dval += C1 * airy0 / math.Pow(musq, 2.0/3+2) + D1 := (phi12*v2 + a1*phi6*v1 + a2) / chi3 + dval += D1 * airy1 / (musq * musq) + dval *= cnst + return val, dval +} + +// hermiteInitialGuess returns the initial guess for node i in an n-point Hermite +// quadrature rule. The rule is symmetric, so i should be <= n/2 + n%2. +func (h Hermite) hermiteInitialGuess(i, n int) float64 { + // There are two different formulas for the initial guesses of the hermite + // quadrature locations. The first uses the Gatteschi formula and is good + // near x = sqrt(n+0.5) + // [1] L. Gatteschi, Asymptotics and bounds for the zeros of Laguerre + // polynomials: a survey, J. Comput. Appl. Math., 144 (2002), pp. 7-27. + // The second is the Tricomi initial guesses, good near x = 0. This is + // equation 2.1 in [1] and is originally from + // [2] F. G. Tricomi, Sugli zeri delle funzioni di cui si conosce una + // rappresentazione asintotica, Ann. Mat. Pura Appl. 26 (1947), pp. 283-300. + + // If the number of points is odd, there is a quadrature point at 1, which + // has an initial guess of 0. + if n%2 == 1 { + if i == 0 { + return 0 + } + i-- + } + + m := n / 2 + a := -0.5 + if n%2 == 1 { + a = 0.5 + } + nu := 4*float64(m) + 2*a + 2 + + // Find the split between Gatteschi guesses and Tricomi guesses. + p := 0.4985 + math.SmallestNonzeroFloat64 + pidx := int(math.Floor(p * float64(n))) + + // Use the Tricomi initial guesses in the first half where x is nearer to zero. + // Note: zeros of besselj(+/-.5,x) are integer and half-integer multiples of pi. + if i < pidx { + rhs := math.Pi * (4*float64(m) - 4*(float64(i)+1) + 3) / nu + tnk := math.Pi / 2 + for k := 0; k < 7; k++ { + val := tnk - math.Sin(tnk) - rhs + dval := 1 - math.Cos(tnk) + dTnk := val / dval + tnk -= dTnk + if math.Abs(dTnk) < 1e-14 { + break + } + } + vc := math.Cos(tnk / 2) + t := vc * vc + return math.Sqrt(nu*t - (5.0/(4.0*(1-t)*(1-t))-1.0/(1-t)-1+3*a*a)/3/nu) + } + + // Use Gatteschi guesses in the second half where x is nearer to sqrt(n+0.5) + i = i + 1 - m + var ar float64 + if i < len(airyRtsExact) { + ar = airyRtsExact[i] + } else { + t := 3.0 / 8 * math.Pi * (4*(float64(i)+1) - 1) + ar = math.Pow(t, 2.0/3) * (1 + + 5.0/48*math.Pow(t, -2) - + 5.0/36*math.Pow(t, -4) + + 77125.0/82944*math.Pow(t, -6) - + 108056875.0/6967296*math.Pow(t, -8) + + 162375596875.0/334430208*math.Pow(t, -10)) + } + r := nu + math.Pow(2, 2.0/3)*ar*math.Pow(nu, 1.0/3) + + 0.2*math.Pow(2, 4.0/3)*ar*ar*math.Pow(nu, -1.0/3) + + (11.0/35-a*a-12.0/175*ar*ar*ar)/nu + + (16.0/1575*ar+92.0/7875*math.Pow(ar, 4))*math.Pow(2, 2.0/3)*math.Pow(nu, -5.0/3) - + (15152.0/3031875*math.Pow(ar, 5)+1088.0/121275*ar*ar)*math.Pow(2, 1.0/3)*math.Pow(nu, -7.0/3) + if r < 0 { + ar = 0 + } else { + ar = math.Sqrt(r) + } + return ar +} + +// airyRtsExact are the first airy roots. +var airyRtsExact = []float64{ + -2.338107410459762, + -4.087949444130970, + -5.520559828095555, + -6.786708090071765, + -7.944133587120863, + -9.022650853340979, + -10.040174341558084, + -11.008524303733260, + -11.936015563236262, + -12.828776752865757, +} diff --git a/integrate/quad/hermite_data.go b/integrate/quad/hermite_data.go new file mode 100644 index 00000000..c50c8dbb --- /dev/null +++ b/integrate/quad/hermite_data.go @@ -0,0 +1,413 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package quad + +// xCache computed from Chebfun. +var xCacheHermite = [][]float64{ + {0.0000000000000000e+00}, + {-7.0710678118654757e-01, 7.0710678118654757e-01}, + {-1.2247448713915887e+00, 0.0000000000000000e+00, 1.2247448713915887e+00}, + {-1.6506801238857842e+00, -5.2464762327529035e-01, 5.2464762327529035e-01, 1.6506801238857842e+00}, + {-2.0201828704560856e+00, -9.5857246461381873e-01, 0.0000000000000000e+00, 9.5857246461381873e-01, 2.0201828704560856e+00}, + {-2.3506049736744914e+00, -1.3358490740136970e+00, -4.3607741192761657e-01, 4.3607741192761657e-01, 1.3358490740136970e+00, 2.3506049736744914e+00}, + {-2.6519613568352316e+00, -1.6735516287674714e+00, -8.1628788285896481e-01, 0.0000000000000000e+00, 8.1628788285896481e-01, 1.6735516287674714e+00, 2.6519613568352316e+00}, + {-2.9306374202572436e+00, -1.9816567566958443e+00, -1.1571937124467804e+00, -3.8118699020732216e-01, 3.8118699020732216e-01, 1.1571937124467804e+00, 1.9816567566958443e+00, 2.9306374202572436e+00}, + {-3.1909932017815295e+00, -2.2665805845318427e+00, -1.4685532892166682e+00, -7.2355101875283767e-01, 0.0000000000000000e+00, 7.2355101875283767e-01, 1.4685532892166682e+00, 2.2665805845318427e+00, 3.1909932017815295e+00}, + {-3.4361591188377378e+00, -2.5327316742327901e+00, -1.7566836492998816e+00, -1.0366108297895138e+00, -3.4290132722370481e-01, 3.4290132722370481e-01, 1.0366108297895138e+00, 1.7566836492998816e+00, 2.5327316742327901e+00, 3.4361591188377378e+00}, + {-3.6684708465595812e+00, -2.7832900997816514e+00, -2.0259480158257550e+00, -1.3265570844949326e+00, -6.5680956688209979e-01, 0.0000000000000000e+00, 6.5680956688209979e-01, 1.3265570844949326e+00, 2.0259480158257550e+00, 2.7832900997816514e+00, 3.6684708465595812e+00}, + {-3.8897248978697814e+00, -3.0206370251208896e+00, -2.2795070805010593e+00, -1.5976826351526043e+00, -9.4778839124016367e-01, -3.1424037625435908e-01, 3.1424037625435908e-01, 9.4778839124016367e-01, 1.5976826351526043e+00, 2.2795070805010593e+00, 3.0206370251208896e+00, 3.8897248978697814e+00}, + {-4.1013375961786389e+00, -3.2466089783724090e+00, -2.5197356856782389e+00, -1.8531076516015121e+00, -1.2200550365907483e+00, -6.0576387917106034e-01, 0.0000000000000000e+00, 6.0576387917106034e-01, 1.2200550365907483e+00, 1.8531076516015121e+00, 2.5197356856782389e+00, 3.2466089783724090e+00, 4.1013375961786389e+00}, + {-4.3044485704736335e+00, -3.4626569336022701e+00, -2.7484707249854017e+00, -2.0951832585077166e+00, -1.4766827311411406e+00, -8.7871378732939931e-01, -2.9174551067256199e-01, 2.9174551067256199e-01, 8.7871378732939931e-01, 1.4766827311411406e+00, 2.0951832585077166e+00, 2.7484707249854017e+00, 3.4626569336022701e+00, 4.3044485704736335e+00}, + {-4.4999907073093910e+00, -3.6699503734044541e+00, -2.9671669279056028e+00, -2.3257324861738580e+00, -1.7199925751864888e+00, -1.1361155852109204e+00, -5.6506958325557588e-01, 0.0000000000000000e+00, 5.6506958325557588e-01, 1.1361155852109204e+00, 1.7199925751864888e+00, 2.3257324861738580e+00, 2.9671669279056028e+00, 3.6699503734044541e+00, 4.4999907073093910e+00}, + {-4.6887389393058223e+00, -3.8694479048601238e+00, -3.1769991619799529e+00, -2.5462021578474796e+00, -1.9517879909162528e+00, -1.3802585391988815e+00, -8.2295144914465546e-01, -2.7348104613815244e-01, 2.7348104613815244e-01, 8.2295144914465546e-01, 1.3802585391988815e+00, 1.9517879909162528e+00, 2.5462021578474796e+00, 3.1769991619799529e+00, 3.8694479048601238e+00, 4.6887389393058223e+00}, + {-4.8713451936744061e+00, -4.0619466758754772e+00, -3.3789320911414946e+00, -2.7577629157038897e+00, -2.1735028266666214e+00, -1.6129243142212311e+00, -1.0676487257434508e+00, -5.3163300134265479e-01, 0.0000000000000000e+00, 5.3163300134265479e-01, 1.0676487257434508e+00, 1.6129243142212311e+00, 2.1735028266666214e+00, 2.7577629157038897e+00, 3.3789320911414946e+00, 4.0619466758754772e+00, 4.8713451936744061e+00}, + {-5.0483640088744668e+00, -4.2481178735681260e+00, -3.5737690684862655e+00, -2.9613775055316052e+00, -2.3862990891666858e+00, -1.8355316042616294e+00, -1.3009208583896172e+00, -7.7668291926741173e-01, -2.5826775051909689e-01, 2.5826775051909689e-01, 7.7668291926741173e-01, 1.3009208583896172e+00, 1.8355316042616294e+00, 2.3862990891666858e+00, 2.9613775055316052e+00, 3.5737690684862655e+00, 4.2481178735681260e+00, 5.0483640088744668e+00}, + {-5.2202716905374844e+00, -4.4285328066037799e+00, -3.7621873519640201e+00, -3.1578488183476034e+00, -2.5911337897945423e+00, -2.0492317098506181e+00, -1.5241706193935327e+00, -1.0103683871343114e+00, -5.0352016342388828e-01, 0.0000000000000000e+00, 5.0352016342388828e-01, 1.0103683871343114e+00, 1.5241706193935327e+00, 2.0492317098506181e+00, 2.5911337897945423e+00, 3.1578488183476034e+00, 3.7621873519640201e+00, 4.4285328066037799e+00, 5.2202716905374844e+00}, + {-5.3874808900112319e+00, -4.6036824495507451e+00, -3.9447640401156265e+00, -3.3478545673832172e+00, -2.7888060584281313e+00, -2.2549740020892761e+00, -1.7385377121165857e+00, -1.2340762153953231e+00, -7.3747372854539406e-01, -2.4534070830090132e-01, 2.4534070830090132e-01, 7.3747372854539406e-01, 1.2340762153953231e+00, 1.7385377121165857e+00, 2.2549740020892761e+00, 2.7888060584281313e+00, 3.3478545673832172e+00, 3.9447640401156265e+00, 4.6036824495507451e+00, 5.3874808900112319e+00}, + {-5.5503518732646775e+00, -4.7739923434112193e+00, -4.1219955474918395e+00, -3.5319728771376777e+00, -2.9799912077045980e+00, -2.4535521245128376e+00, -1.9449629491862539e+00, -1.4489342506507319e+00, -9.6149963441836894e-01, -4.7945070707910747e-01, -0.0000000000000000e+00, 4.7945070707910747e-01, 9.6149963441836894e-01, 1.4489342506507319e+00, 1.9449629491862539e+00, 2.4535521245128376e+00, 2.9799912077045980e+00, 3.5319728771376777e+00, 4.1219955474918395e+00, 4.7739923434112193e+00, 5.5503518732646775e+00}, + {-5.7092013532052626e+00, -4.9398341310601763e+00, -4.2943124805931614e+00, -3.7107015328778048e+00, -3.1652659092021374e+00, -2.6456374410581724e+00, -2.1442335927985341e+00, -1.6558743732864223e+00, -1.1767139584812445e+00, -7.0368609717000696e-01, -2.3417913993099065e-01, 2.3417913993099065e-01, 7.0368609717000696e-01, 1.1767139584812445e+00, 1.6558743732864223e+00, 2.1442335927985341e+00, 2.6456374410581724e+00, 3.1652659092021374e+00, 3.7107015328778048e+00, 4.2943124805931614e+00, 4.9398341310601763e+00, 5.7092013532052626e+00}, + {-5.8643094989845714e+00, -5.1015346104766763e+00, -4.4620911737400064e+00, -3.8844727081061015e+00, -3.3451271599412244e+00, -2.8318037871261570e+00, -2.3370162114744559e+00, -1.8556770376713707e+00, -1.3840395856824952e+00, -9.1915146544256365e-01, -4.5853835006810478e-01, -0.0000000000000000e+00, 4.5853835006810478e-01, 9.1915146544256365e-01, 1.3840395856824952e+00, 1.8556770376713707e+00, 2.3370162114744559e+00, 2.8318037871261570e+00, 3.3451271599412244e+00, 3.8844727081061015e+00, 4.4620911737400064e+00, 5.1015346104766763e+00, 5.8643094989845714e+00}, + {-6.0159255614257390e+00, -5.2593829276680442e+00, -4.6256627564237878e+00, -4.0536644024481490e+00, -3.5200068130345241e+00, -3.0125461375655647e+00, -2.5238810170114268e+00, -2.0490035736616985e+00, -1.5842500109616942e+00, -1.1267608176112451e+00, -6.7417110703721217e-01, -2.2441454747251557e-01, 2.2441454747251557e-01, 6.7417110703721217e-01, 1.1267608176112451e+00, 1.5842500109616942e+00, 2.0490035736616985e+00, 2.5238810170114268e+00, 3.0125461375655647e+00, 3.5200068130345241e+00, 4.0536644024481490e+00, 4.6256627564237878e+00, 5.2593829276680442e+00, 6.0159255614257390e+00}, + {-6.1642724340524513e+00, -5.4136363552800333e+00, -4.7853203673522238e+00, -4.2186094443865612e+00, -3.6902828769983551e+00, -3.1882949244251044e+00, -2.7053202371730256e+00, -2.2364201302672808e+00, -1.7780011243371474e+00, -1.3272807020730839e+00, -8.8198275621382138e-01, -4.4014729864530827e-01, -0.0000000000000000e+00, 4.4014729864530827e-01, 8.8198275621382138e-01, 1.3272807020730839e+00, 1.7780011243371474e+00, 2.2364201302672808e+00, 2.7053202371730256e+00, 3.1882949244251044e+00, 3.6902828769983551e+00, 4.2186094443865612e+00, 4.7853203673522238e+00, 5.4136363552800333e+00, 6.1642724340524513e+00}, + {-6.3095503856256920e+00, -5.5645249819501030e+00, -4.9413249572413793e+00, -4.3796026629833040e+00, -3.8562884199091489e+00, -3.3594271823508297e+00, -2.8817622195430865e+00, -2.4184157647737790e+00, -1.9658547856411364e+00, -1.5213615166519212e+00, -1.0827330110778832e+00, -6.4809521399344827e-01, -2.1577785624346338e-01, 2.1577785624346338e-01, 6.4809521399344827e-01, 1.0827330110778832e+00, 1.5213615166519212e+00, 1.9658547856411364e+00, 2.4184157647737790e+00, 2.8817622195430865e+00, 3.3594271823508297e+00, 3.8562884199091489e+00, 4.3796026629833040e+00, 4.9413249572413793e+00, 5.5645249819501030e+00, 6.3095503856256920e+00}, + {-6.4519401407534707e+00, -5.7122555528165355e+00, -5.0939100031131836e+00, -4.5369066633724415e+00, -4.0183186704087381e+00, -3.5262753401343527e+00, -3.0535824198222552e+00, -2.5954163389108178e+00, -2.1482966453616275e+00, -1.7095607392603374e+00, -1.2770668173398578e+00, -8.4901134206010298e-01, -4.2380790054385303e-01, -0.0000000000000000e+00, 4.2380790054385303e-01, 8.4901134206010298e-01, 1.2770668173398578e+00, 1.7095607392603374e+00, 2.1482966453616275e+00, 2.5954163389108178e+00, 3.0535824198222552e+00, 3.5262753401343527e+00, 4.0183186704087381e+00, 4.5369066633724415e+00, 5.0939100031131836e+00, 5.7122555528165355e+00, 6.4519401407534707e+00}, + {-6.5916054423677419e+00, -5.8570146413828503e+00, -5.2432853732029354e+00, -4.6907565239431177e+00, -4.1766367421292676e+00, -3.6891342384616794e+00, -3.2211120765614556e+00, -2.7677953529135935e+00, -2.3257498426564407e+00, -1.8923604968376853e+00, -1.4655372634574091e+00, -1.0435352737542081e+00, -6.2483671950520925e-01, -2.0806738269073688e-01, 2.0806738269073688e-01, 6.2483671950520925e-01, 1.0435352737542081e+00, 1.4655372634574091e+00, 1.8923604968376853e+00, 2.3257498426564407e+00, 2.7677953529135935e+00, 3.2211120765614556e+00, 3.6891342384616794e+00, 4.1766367421292676e+00, 4.6907565239431177e+00, 5.2432853732029354e+00, 5.8570146413828503e+00, 6.5916054423677419e+00}, + {-6.7286951986088495e+00, -5.9989712894638192e+00, -5.3896405219667507e+00, -4.8413636510591642e+00, -4.3314782938191501e+00, -3.8482667922136202e+00, -3.3846451410922138e+00, -2.9358825042901264e+00, -2.4985856910194042e+00, -2.0701810760534278e+00, -1.6486229138923163e+00, -1.2322157550847530e+00, -8.1949868127091163e-01, -4.0916463639492873e-01, -0.0000000000000000e+00, 4.0916463639492873e-01, 8.1949868127091163e-01, 1.2322157550847530e+00, 1.6486229138923163e+00, 2.0701810760534278e+00, 2.4985856910194042e+00, 2.9358825042901264e+00, 3.3846451410922138e+00, 3.8482667922136202e+00, 4.3314782938191501e+00, 4.8413636510591642e+00, 5.3896405219667507e+00, 5.9989712894638192e+00, 6.7286951986088495e+00}, + {-6.8633452935298900e+00, -6.1382792201239331e+00, -5.5331471515674950e+00, -4.9889189685899442e+00, -4.4830553570925176e+00, -4.0039086038612286e+00, -3.5444438731553496e+00, -3.0999705295864417e+00, -2.6671321245356170e+00, -2.2433914677615041e+00, -1.8267411436036880e+00, -1.4155278001981884e+00, -1.0083382710467235e+00, -6.0392105862555223e-01, -2.0112857654887151e-01, 2.0112857654887151e-01, 6.0392105862555223e-01, 1.0083382710467235e+00, 1.4155278001981884e+00, 1.8267411436036880e+00, 2.2433914677615041e+00, 2.6671321245356170e+00, 3.0999705295864417e+00, 3.5444438731553496e+00, 4.0039086038612286e+00, 4.4830553570925176e+00, 4.9889189685899442e+00, 5.5331471515674950e+00, 6.1382792201239331e+00, 6.8633452935298900e+00}, + {-6.9956801237185395e+00, -6.2750787049428602e+00, -5.6739614446185875e+00, -5.1335955771123798e+00, -4.6315595063128594e+00, -4.1562717558181452e+00, -3.7007434032314697e+00, -3.2603207323135406e+00, -2.8316804533902054e+00, -2.4123177054804201e+00, -2.0002585489356388e+00, -1.5938858604721398e+00, -1.1918269983500462e+00, -7.9287697691530890e-01, -3.9594273647142297e-01, -0.0000000000000000e+00, 3.9594273647142297e-01, 7.9287697691530890e-01, 1.1918269983500462e+00, 1.5938858604721398e+00, 2.0002585489356388e+00, 2.4123177054804201e+00, 2.8316804533902054e+00, 3.2603207323135406e+00, 3.7007434032314697e+00, 4.1562717558181452e+00, 4.6315595063128594e+00, 5.1335955771123798e+00, 5.6739614446185875e+00, 6.2750787049428602e+00, 6.9956801237185395e+00}, + {-7.1258139098307272e+00, -6.4094981492696599e+00, -5.8122259495159128e+00, -5.2755509865158796e+00, -4.7771645035025960e+00, -4.3055479533511987e+00, -3.8537554854714444e+00, -3.4171674928185705e+00, -2.9924908250023741e+00, -2.5772495377323170e+00, -2.1694991836061122e+00, -1.7676541094632017e+00, -1.3703764109528718e+00, -9.7650046358968279e-01, -5.8497876543593241e-01, -1.9484074156939934e-01, 1.9484074156939934e-01, 5.8497876543593241e-01, 9.7650046358968279e-01, 1.3703764109528718e+00, 1.7676541094632017e+00, 2.1694991836061122e+00, 2.5772495377323170e+00, 2.9924908250023741e+00, 3.4171674928185705e+00, 3.8537554854714444e+00, 4.3055479533511987e+00, 4.7771645035025960e+00, 5.2755509865158796e+00, 5.8122259495159128e+00, 6.4094981492696599e+00, 7.1258139098307272e+00}, + {-7.2538518220151991e+00, -6.5416554457380762e+00, -5.9480711820871450e+00, -5.4149290026141923e+00, -4.9200285205950083e+00, -4.4519111488328269e+00, -4.0036716099569309e+00, -3.5707219802327179e+00, -3.1497966817038248e+00, -2.7384458243513548e+00, -2.3347511515295150e+00, -1.9371545818222065e+00, -1.5443482612431219e+00, -1.1552002041267895e+00, -7.6870137975886854e-01, -3.8392601450840907e-01, -0.0000000000000000e+00, 3.8392601450840907e-01, 7.6870137975886854e-01, 1.1552002041267895e+00, 1.5443482612431219e+00, 1.9371545818222065e+00, 2.3347511515295150e+00, 2.7384458243513548e+00, 3.1497966817038248e+00, 3.5707219802327179e+00, 4.0036716099569309e+00, 4.4519111488328269e+00, 4.9200285205950083e+00, 5.4149290026141923e+00, 5.9480711820871450e+00, 6.5416554457380762e+00, 7.2538518220151991e+00}, + {-7.3798909504812453e+00, -6.6716591360701694e+00, -6.0816169939363158e+00, -5.5518613309887774e+00, -5.0602960186057615e+00, -4.5955197481081704e+00, -4.1506656029707809e+00, -3.7211752324761531e+00, -3.3038084315644154e+00, -2.8961389431744311e+00, -2.4962719408165470e+00, -2.1026736904673324e+00, -1.7140625533873379e+00, -1.3293355518847858e+00, -9.4751645803344731e-01, -5.6771726855487448e-01, -1.8910806052714246e-01, 1.8910806052714246e-01, 5.6771726855487448e-01, 9.4751645803344731e-01, 1.3293355518847858e+00, 1.7140625533873379e+00, 2.1026736904673324e+00, 2.4962719408165470e+00, 2.8961389431744311e+00, 3.3038084315644154e+00, 3.7211752324761531e+00, 4.1506656029707809e+00, 4.5955197481081704e+00, 5.0602960186057615e+00, 5.5518613309887774e+00, 6.0816169939363158e+00, 6.6716591360701694e+00, 7.3798909504812453e+00}, + {-7.5040211464489355e+00, -6.7996094132841307e+00, -6.2129737476337166e+00, -5.6864689480904413e+00, -5.1980993461977523e+00, -4.7365184774132105e+00, -4.2948958144927625e+00, -3.8687007309691541e+00, -3.4547164957519905e+00, -3.0505384204304464e+00, -2.6542927811971722e+00, -2.2644675010425686e+00, -1.8798039887309170e+00, -1.4992244886117301e+00, -1.1217809907203027e+00, -7.4661763987986696e-01, -3.7294171704961682e-01, -0.0000000000000000e+00, 3.7294171704961682e-01, 7.4661763987986696e-01, 1.1217809907203027e+00, 1.4992244886117301e+00, 1.8798039887309170e+00, 2.2644675010425686e+00, 2.6542927811971722e+00, 3.0505384204304464e+00, 3.4547164957519905e+00, 3.8687007309691541e+00, 4.2948958144927625e+00, 4.7365184774132105e+00, 5.1980993461977523e+00, 5.6864689480904413e+00, 6.2129737476337166e+00, 6.7996094132841307e+00, 7.5040211464489355e+00}, + {-7.6263257540038927e+00, -6.9255989902599406e+00, -6.3422433309944113e+00, -5.8188632795055772e+00, -5.3335601071130636e+00, -4.8750399724670830e+00, -4.4365069701928563e+00, -4.0134565677494702e+00, -3.6026938571484757e+00, -3.2018339457881582e+00, -2.8090222351311036e+00, -2.4227660420535617e+00, -2.0418271835544202e+00, -1.6651500018434142e+00, -1.2918109588209239e+00, -9.2098180157075304e-01, -5.5190143329042274e-01, -1.8385336710581282e-01, 1.8385336710581282e-01, 5.5190143329042274e-01, 9.2098180157075304e-01, 1.2918109588209239e+00, 1.6651500018434142e+00, 2.0418271835544202e+00, 2.4227660420535617e+00, 2.8090222351311036e+00, 3.2018339457881582e+00, 3.6026938571484757e+00, 4.0134565677494702e+00, 4.4365069701928563e+00, 4.8750399724670830e+00, 5.3335601071130636e+00, 5.8188632795055772e+00, 6.3422433309944113e+00, 6.9255989902599406e+00, 7.6263257540038927e+00}, + {-7.7468822496494552e+00, -7.0497138557782293e+00, -6.4695200365240302e+00, -5.9491472174619711e+00, -5.4667903359685601e+00, -5.0112061385730726e+00, -4.5756317486673579e+00, -4.1555872811264782e+00, -3.7478982064754800e+00, -3.3501978949725357e+00, -2.9606491813032889e+00, -2.5777768581132716e+00, -2.2003609340092520e+00, -1.8273652487636047e+00, -1.4578876468742090e+00, -1.0911237649759331e+00, -7.2633961660512014e-01, -3.6284990505065795e-01, -0.0000000000000000e+00, 3.6284990505065795e-01, 7.2633961660512014e-01, 1.0911237649759331e+00, 1.4578876468742090e+00, 1.8273652487636047e+00, 2.2003609340092520e+00, 2.5777768581132716e+00, 2.9606491813032889e+00, 3.3501978949725357e+00, 3.7478982064754800e+00, 4.1555872811264782e+00, 4.5756317486673579e+00, 5.0112061385730726e+00, 5.4667903359685601e+00, 5.9491472174619711e+00, 6.4695200365240302e+00, 7.0497138557782293e+00, 7.7468822496494552e+00}, + {-7.8657628033800400e+00, -7.1720339353200302e+00, -6.5948913272654934e+00, -6.0774160035375608e+00, -5.5978935141846780e+00, -5.1451293207408231e+00, -4.7123921320848874e+00, -4.2952254197496051e+00, -3.8904737609633409e+00, -3.4957874548356260e+00, -3.1093453117179419e+00, -2.7296879628883253e+00, -2.3556117330355080e+00, -1.9860977780390656e+00, -1.6202627556330140e+00, -1.2573231317007134e+00, -8.9656834619313597e-01, -5.3733981087098337e-01, -1.7901372329587750e-01, 1.7901372329587750e-01, 5.3733981087098337e-01, 8.9656834619313597e-01, 1.2573231317007134e+00, 1.6202627556330140e+00, 1.9860977780390656e+00, 2.3556117330355080e+00, 2.7296879628883253e+00, 3.1093453117179419e+00, 3.4957874548356260e+00, 3.8904737609633409e+00, 4.2952254197496051e+00, 4.7123921320848874e+00, 5.1451293207408231e+00, 5.5978935141846780e+00, 6.0774160035375608e+00, 6.5948913272654934e+00, 7.1720339353200302e+00, 7.8657628033800400e+00}, + {-7.9830347727197806e+00, -7.2926336708657198e+00, -6.7184385064440910e+00, -6.2037579977281085e+00, -5.7269654517821049e+00, -5.2769133152304262e+00, -4.8469005687435258e+00, -4.4324928825930368e+00, -4.0305528146024674e+00, -3.6387464248745358e+00, -3.2552672359922297e+00, -2.8786703113749548e+00, -2.5077666938913192e+00, -2.1415530119868800e+00, -1.7791625828543136e+00, -1.4198301576857355e+00, -1.0628655672811786e+00, -7.0763327334857218e-01, -3.5353584699632934e-01, -0.0000000000000000e+00, 3.5353584699632934e-01, 7.0763327334857218e-01, 1.0628655672811786e+00, 1.4198301576857355e+00, 1.7791625828543136e+00, 2.1415530119868800e+00, 2.5077666938913192e+00, 2.8786703113749548e+00, 3.2552672359922297e+00, 3.6387464248745358e+00, 4.0305528146024674e+00, 4.4324928825930368e+00, 4.8469005687435258e+00, 5.2769133152304262e+00, 5.7269654517821049e+00, 6.2037579977281085e+00, 6.7184385064440910e+00, 7.2926336708657198e+00, 7.9830347727197806e+00}, + {-8.0987611392508505e+00, -7.4115825314854691e+00, -6.8402373052493548e+00, -6.3282553512200810e+00, -5.8540950560303990e+00, -5.4066542479701267e+00, -4.9792609785452555e+00, -4.5675020728443938e+00, -4.1682570668324992e+00, -3.7792067534352229e+00, -3.3985582658596281e+00, -3.0248798839012840e+00, -2.6569959984428957e+00, -2.2939171418750832e+00, -1.9347914722822956e+00, -1.5788698949316138e+00, -1.2254801090462888e+00, -8.7400661235708799e-01, -5.2387471383227713e-01, -1.7453721459758240e-01, 1.7453721459758240e-01, 5.2387471383227713e-01, 8.7400661235708799e-01, 1.2254801090462888e+00, 1.5788698949316138e+00, 1.9347914722822956e+00, 2.2939171418750832e+00, 2.6569959984428957e+00, 3.0248798839012840e+00, 3.3985582658596281e+00, 3.7792067534352229e+00, 4.1682570668324992e+00, 4.5675020728443938e+00, 4.9792609785452555e+00, 5.4066542479701267e+00, 5.8540950560303990e+00, 6.3282553512200810e+00, 6.8402373052493548e+00, 7.4115825314854691e+00, 8.0987611392508505e+00}, + {-8.2130008955982792e+00, -7.5289454645396203e+00, -6.9603584006367480e+00, -6.4509845971747524e+00, -5.9793650041651327e+00, -5.5344413406134461e+00, -5.1095696265331334e+00, -4.7003568963041156e+00, -4.3036987671546498e+00, -3.9172898548377817e+00, -3.5393499373637116e+00, -3.1684594539419857e+00, -2.8034549614843187e+00, -2.4433595531234111e+00, -2.0873346819187244e+00, -1.7346456088220295e+00, -1.3846357891600325e+00, -1.0367072529242058e+00, -6.9030505233020811e-01, -3.4490446301543276e-01, -0.0000000000000000e+00, 3.4490446301543276e-01, 6.9030505233020811e-01, 1.0367072529242058e+00, 1.3846357891600325e+00, 1.7346456088220295e+00, 2.0873346819187244e+00, 2.4433595531234111e+00, 2.8034549614843187e+00, 3.1684594539419857e+00, 3.5393499373637116e+00, 3.9172898548377817e+00, 4.3036987671546498e+00, 4.7003568963041156e+00, 5.1095696265331334e+00, 5.5344413406134461e+00, 5.9793650041651327e+00, 6.4509845971747524e+00, 6.9603584006367480e+00, 7.5289454645396203e+00, 8.2130008955982792e+00}, + {-8.3258093895669294e+00, -7.6447832957047419e+00, -7.0788678730491084e+00, -6.5720171713874747e+00, -6.1028523343815264e+00, -5.6603575812830567e+00, -5.2379158850176495e+00, -4.8311536291282762e+00, -4.4369817058810304e+00, -4.0531077444247670e+00, -3.6777633163885568e+00, -3.3095400965109221e+00, -2.9472857823054786e+00, -2.5900348706171261e+00, -2.2369607870543176e+00, -1.8873416205434848e+00, -1.5405348009155460e+00, -1.1959577943778097e+00, -8.5307290916055367e-01, -5.1137491831546933e-01, -1.7038058556181696e-01, 1.7038058556181696e-01, 5.1137491831546933e-01, 8.5307290916055367e-01, 1.1959577943778097e+00, 1.5405348009155460e+00, 1.8873416205434848e+00, 2.2369607870543176e+00, 2.5900348706171261e+00, 2.9472857823054786e+00, 3.3095400965109221e+00, 3.6777633163885568e+00, 4.0531077444247670e+00, 4.4369817058810304e+00, 4.8311536291282762e+00, 5.2379158850176495e+00, 5.6603575812830567e+00, 6.1028523343815264e+00, 6.5720171713874747e+00, 7.0788678730491084e+00, 7.6447832957047419e+00, 8.3258093895669294e+00}, + {-8.4372386310833765e+00, -7.7591530847325343e+00, -7.1958276123464335e+00, -6.6914198727121068e+00, -6.2246289668942199e+00, -5.7844803140775571e+00, -5.3643829011515560e+00, -4.9599816751949550e+00, -4.5682020755441552e+00, -4.1867640213660025e+00, -3.8139101240654272e+00, -3.4482424822200026e+00, -3.0886190396004185e+00, -2.7340846945379047e+00, -2.3838237072843595e+00, -2.0371256888641933e+00, -1.6933605309399098e+00, -1.3519593686708704e+00, -1.0123996845633196e+00, -6.7419327674231389e-01, -3.3687619662553298e-01, -0.0000000000000000e+00, 3.3687619662553298e-01, 6.7419327674231389e-01, 1.0123996845633196e+00, 1.3519593686708704e+00, 1.6933605309399098e+00, 2.0371256888641933e+00, 2.3838237072843595e+00, 2.7340846945379047e+00, 3.0886190396004185e+00, 3.4482424822200026e+00, 3.8139101240654272e+00, 4.1867640213660025e+00, 4.5682020755441552e+00, 4.9599816751949550e+00, 5.3643829011515560e+00, 5.7844803140775571e+00, 6.2246289668942199e+00, 6.6914198727121068e+00, 7.1958276123464335e+00, 7.7591530847325343e+00, 8.4372386310833765e+00}, + {-8.5473375667355391e+00, -7.8721084427748513e+00, -7.3112956789163306e+00, -6.8092552715358323e+00, -6.3447621648968919e+00, -5.9068817590275451e+00, -5.4890481838807421e+00, -5.0869242297582531e+00, -4.6974492230014393e+00, -4.3183547234421118e+00, -3.9478937115246548e+00, -3.5846779931052279e+00, -3.2275749742774260e+00, -2.8756390821704421e+00, -2.5280644271476649e+00, -2.1841510195665261e+00, -1.8432799206176103e+00, -1.5048944344828714e+00, -1.1684854631902055e+00, -8.3357976100207332e-01, -4.9973020830067427e-01, -1.6650746707363237e-01, 1.6650746707363237e-01, 4.9973020830067427e-01, 8.3357976100207332e-01, 1.1684854631902055e+00, 1.5048944344828714e+00, 1.8432799206176103e+00, 2.1841510195665261e+00, 2.5280644271476649e+00, 2.8756390821704421e+00, 3.2275749742774260e+00, 3.5846779931052279e+00, 3.9478937115246548e+00, 4.3183547234421118e+00, 4.6974492230014393e+00, 5.0869242297582531e+00, 5.4890481838807421e+00, 5.9068817590275451e+00, 6.3447621648968919e+00, 6.8092552715358323e+00, 7.3112956789163306e+00, 7.8721084427748513e+00, 8.5473375667355391e+00}, + {-8.6561523259903268e+00, -7.9836998162220016e+00, -7.4253266258561936e+00, -6.9255820732775950e+00, -6.4633149436642530e+00, -6.0276294722536941e+00, -5.6119841218396642e+00, -5.2120588631620075e+00, -4.8248063087032573e+00, -4.4479690736019313e+00, -4.0798099079253927e+00, -3.7189496893415628e+00, -3.3642645958565400e+00, -3.0148178197492252e+00, -2.6698124652513462e+00, -2.3285579714531894e+00, -1.9904454586466382e+00, -1.6549291191547923e+00, -1.3215117856392311e+00, -9.8973342486571125e-01, -6.5916168887413507e-01, -3.2938389969666915e-01, -0.0000000000000000e+00, 3.2938389969666915e-01, 6.5916168887413507e-01, 9.8973342486571125e-01, 1.3215117856392311e+00, 1.6549291191547923e+00, 1.9904454586466382e+00, 2.3285579714531894e+00, 2.6698124652513462e+00, 3.0148178197492252e+00, 3.3642645958565400e+00, 3.7189496893415628e+00, 4.0798099079253927e+00, 4.4479690736019313e+00, 4.8248063087032573e+00, 5.2120588631620075e+00, 5.6119841218396642e+00, 6.0276294722536941e+00, 6.4633149436642530e+00, 6.9255820732775950e+00, 7.4253266258561936e+00, 7.9836998162220016e+00, 8.6561523259903268e+00}, + {-8.7637264425763934e+00, -8.0939747412671181e+00, -7.5379717872258256e+00, -7.0404554428052171e+00, -6.5803464347374083e+00, -6.1467867545054018e+00, -5.7332584418499435e+00, -5.3354580360572301e+00, -4.9503508867398853e+00, -4.5756901345704328e+00, -4.2097477613269749e+00, -3.8511531505025514e+00, -3.4987906412463645e+00, -3.1517315196384712e+00, -2.8091871354772668e+00, -2.4704755132281426e+00, -2.1349968729707256e+00, -1.8022151950574945e+00, -1.4716439717320722e+00, -1.1428349031264304e+00, -8.1536867934468149e-01, -4.8884723585117468e-01, -1.6288702795526222e-01, 1.6288702795526222e-01, 4.8884723585117468e-01, 8.1536867934468149e-01, 1.1428349031264304e+00, 1.4716439717320722e+00, 1.8022151950574945e+00, 2.1349968729707256e+00, 2.4704755132281426e+00, 2.8091871354772668e+00, 3.1517315196384712e+00, 3.4987906412463645e+00, 3.8511531505025514e+00, 4.2097477613269749e+00, 4.5756901345704328e+00, 4.9503508867398853e+00, 5.3354580360572301e+00, 5.7332584418499435e+00, 6.1467867545054018e+00, 6.5803464347374083e+00, 7.0404554428052171e+00, 7.5379717872258256e+00, 8.0939747412671181e+00, 8.7637264425763934e+00}, + {-8.8701010540232534e+00, -8.2029780727977943e+00, -7.6492795366289874e+00, -7.1539272947757162e+00, -6.6959122110632512e+00, -6.2644130149704740e+00, -5.8529346161254212e+00, -5.4571895556816514e+00, -5.0741554169850653e+00, -4.7015953849679351e+00, -4.3377901884924199e+00, -3.9813772107064693e+00, -3.6312484092926161e+00, -3.2864825713246675e+00, -2.9462986351921705e+00, -2.6100224744061520e+00, -2.2770625758595000e+00, -1.9468917579991860e+00, -1.6190330813590508e+00, -1.2930487170109526e+00, -9.6853092273781483e-01, -6.4509452302768844e-01, -3.2237044915615060e-01, -0.0000000000000000e+00, 3.2237044915615060e-01, 6.4509452302768844e-01, 9.6853092273781483e-01, 1.2930487170109526e+00, 1.6190330813590508e+00, 1.9468917579991860e+00, 2.2770625758595000e+00, 2.6100224744061520e+00, 2.9462986351921705e+00, 3.2864825713246675e+00, 3.6312484092926161e+00, 3.9813772107064693e+00, 4.3377901884924199e+00, 4.7015953849679351e+00, 5.0741554169850653e+00, 5.4571895556816514e+00, 5.8529346161254212e+00, 6.2644130149704740e+00, 6.6959122110632512e+00, 7.1539272947757162e+00, 7.6492795366289874e+00, 8.2029780727977943e+00, 8.8701010540232534e+00}, + {-8.9753150819316865e+00, -8.3107521907047843e+00, -7.7592955197657743e+00, -7.2660465541643502e+00, -6.8100645780741411e+00, -6.3805640961864096e+00, -5.9710722250135460e+00, -5.5773169812237278e+00, -5.1962877187923642e+00, -4.8257572281332095e+00, -4.4640145469344583e+00, -4.1097046035605898e+00, -3.7617264902283578e+00, -3.4191659693638847e+00, -3.0812489886451053e+00, -2.7473086248223830e+00, -2.4167609048732164e+00, -2.0890866609442762e+00, -1.7638175798953000e+00, -1.4405252201375651e+00, -1.1188121524021566e+00, -7.9830462777856215e-01, -4.7864633759449599e-01, -1.5949293584886245e-01, 1.5949293584886245e-01, 4.7864633759449599e-01, 7.9830462777856215e-01, 1.1188121524021566e+00, 1.4405252201375651e+00, 1.7638175798953000e+00, 2.0890866609442762e+00, 2.4167609048732164e+00, 2.7473086248223830e+00, 3.0812489886451053e+00, 3.4191659693638847e+00, 3.7617264902283578e+00, 4.1097046035605898e+00, 4.4640145469344583e+00, 4.8257572281332095e+00, 5.1962877187923642e+00, 5.5773169812237278e+00, 5.9710722250135460e+00, 6.3805640961864096e+00, 6.8100645780741411e+00, 7.2660465541643502e+00, 7.7592955197657743e+00, 8.3107521907047843e+00, 8.9753150819316865e+00}, + {-9.0794053951994336e+00, -8.4173371862679787e+00, -7.8680628640816641e+00, -7.3768593906319282e+00, -6.9228528349597616e+00, -6.4952925650076585e+00, -6.0877272810547556e+00, -5.6958999850352088e+00, -5.3168113741835157e+00, -4.9482434430048912e+00, -4.5884931402744824e+00, -4.2362125300687872e+00, -3.8903074057661615e+00, -3.5498700372120946e+00, -3.2141328684568560e+00, -2.8824356106455995e+00, -2.5542011939519624e+00, -2.2289177453859468e+00, -1.9061247609883607e+00, -1.5854022514550468e+00, -1.2663620236873581e+00, -9.4864050761025742e-01, -6.3189269951096161e-01, -3.1578690052375491e-01, -0.0000000000000000e+00, 3.1578690052375491e-01, 6.3189269951096161e-01, 9.4864050761025742e-01, 1.2663620236873581e+00, 1.5854022514550468e+00, 1.9061247609883607e+00, 2.2289177453859468e+00, 2.5542011939519624e+00, 2.8824356106455995e+00, 3.2141328684568560e+00, 3.5498700372120946e+00, 3.8903074057661615e+00, 4.2362125300687872e+00, 4.5884931402744824e+00, 4.9482434430048912e+00, 5.3168113741835157e+00, 5.6958999850352088e+00, 6.0877272810547556e+00, 6.4952925650076585e+00, 6.9228528349597616e+00, 7.3768593906319282e+00, 7.8680628640816641e+00, 8.4173371862679787e+00, 9.0794053951994336e+00}, + {-9.1824069581293166e+00, -8.5227710309178022e+00, -7.9756223682056362e+00, -7.4864094298641941e+00, -7.0343235097706103e+00, -6.6086479738553576e+00, -6.2029525192746719e+00, -5.8129946754204047e+00, -5.4357860872249475e+00, -5.0691175849172350e+00, -4.7112936661690421e+00, -4.3609731604545781e+00, -4.0170681728581341e+00, -3.6786770625152689e+00, -3.3450383139378910e+00, -3.0154977695745222e+00, -2.6894847022677451e+00, -2.3664939042986637e+00, -2.0460719686864088e+00, -1.7278065475158983e+00, -1.4113177548982998e+00, -1.0962511289576817e+00, -7.8227172955460689e-01, -4.6905905667823600e-01, -1.5630254688946871e-01, 1.5630254688946871e-01, 4.6905905667823600e-01, 7.8227172955460689e-01, 1.0962511289576817e+00, 1.4113177548982998e+00, 1.7278065475158983e+00, 2.0460719686864088e+00, 2.3664939042986637e+00, 2.6894847022677451e+00, 3.0154977695745222e+00, 3.3450383139378910e+00, 3.6786770625152689e+00, 4.0170681728581341e+00, 4.3609731604545781e+00, 4.7112936661690421e+00, 5.0691175849172350e+00, 5.4357860872249475e+00, 5.8129946754204047e+00, 6.2029525192746719e+00, 6.6086479738553576e+00, 7.0343235097706103e+00, 7.4864094298641941e+00, 7.9756223682056362e+00, 8.5227710309178022e+00, 9.1824069581293166e+00}, + {-9.2843529650947954e+00, -8.6270897293636839e+00, -8.0820126735040123e+00, -7.5947379445835947e+00, -7.1445205714796174e+00, -6.7206770958687514e+00, -6.3167976579034049e+00, -5.9286538858731372e+00, -5.5532680052649175e+00, -5.1884393429381372e+00, -4.8324796145780748e+00, -4.4840540790573504e+00, -4.1420808019620621e+00, -3.8056638567519334e+00, -3.4740473616558587e+00, -3.1465828437716956e+00, -2.8227054233054294e+00, -2.5019160040577368e+00, -2.1837676525361926e+00, -1.8678549556995603e+00, -1.5538055294554218e+00, -1.2412730966236114e+00, -9.2993171560017596e-01, -6.1947084974715272e-01, -3.0959104093724038e-01, -0.0000000000000000e+00, 3.0959104093724038e-01, 6.1947084974715272e-01, 9.2993171560017596e-01, 1.2412730966236114e+00, 1.5538055294554218e+00, 1.8678549556995603e+00, 2.1837676525361926e+00, 2.5019160040577368e+00, 2.8227054233054294e+00, 3.1465828437716956e+00, 3.4740473616558587e+00, 3.8056638567519334e+00, 4.1420808019620621e+00, 4.4840540790573504e+00, 4.8324796145780748e+00, 5.1884393429381372e+00, 5.5532680052649175e+00, 5.9286538858731372e+00, 6.3167976579034049e+00, 6.7206770958687514e+00, 7.1445205714796174e+00, 7.5947379445835947e+00, 8.0820126735040123e+00, 8.6270897293636839e+00, 9.2843529650947954e+00}, + {-9.3852749632231376e+00, -8.7303274588209110e+00, -8.1872704197671577e+00, -7.7018840275679166e+00, -7.2534856216969716e+00, -6.8314241370686029e+00, -6.4293096331149808e+00, -6.0429274349196920e+00, -5.6693100068563673e+00, -5.3062648593656414e+00, -4.9521106229353720e+00, -4.6055186799962122e+00, -4.2654127388779193e+00, -3.9309022499573141e+00, -3.6012366010181420e+00, -3.2757726058076915e+00, -2.9539507925538842e+00, -2.6352776875892849e+00, -2.3193122827994568e+00, -2.0056554817328660e+00, -1.6939417005414366e+00, -1.3838320462108629e+00, -1.0750086571198576e+00, -7.6716990012409136e-01, -4.6002619243746073e-01, -1.5329626692045756e-01, 1.5329626692045756e-01, 4.6002619243746073e-01, 7.6716990012409136e-01, 1.0750086571198576e+00, 1.3838320462108629e+00, 1.6939417005414366e+00, 2.0056554817328660e+00, 2.3193122827994568e+00, 2.6352776875892849e+00, 2.9539507925538842e+00, 3.2757726058076915e+00, 3.6012366010181420e+00, 3.9309022499573141e+00, 4.2654127388779193e+00, 4.6055186799962122e+00, 4.9521106229353720e+00, 5.3062648593656414e+00, 5.6693100068563673e+00, 6.0429274349196920e+00, 6.4293096331149808e+00, 6.8314241370686029e+00, 7.2534856216969716e+00, 7.7018840275679166e+00, 8.1872704197671577e+00, 8.7303274588209110e+00, 9.3852749632231376e+00}, + {-9.4852029643727302e+00, -8.8325166958454133e+00, -8.2914303867830093e+00, -7.8078847487003955e+00, -7.3612580683690458e+00, -6.9409309282147520e+00, -6.5405328108757619e+00, -6.1558623601311924e+00, -5.7839619604859447e+00, -5.4226470161614522e+00, -5.0702427937817154e+00, -4.7254265200961152e+00, -4.3871272577720717e+00, -4.0544595295034727e+00, -3.7266776654942122e+00, -3.4031434102599176e+00, -3.0833023089391358e+00, -2.7666660769675384e+00, -2.4527991478588032e+00, -2.1413081984302371e+00, -1.8318338313140423e+00, -1.5240438405087577e+00, -1.2176276482547366e+00, -9.1229161088998856e-01, -6.0775496588729694e-01, -3.0374624334991529e-01, -0.0000000000000000e+00, 3.0374624334991529e-01, 6.0775496588729694e-01, 9.1229161088998856e-01, 1.2176276482547366e+00, 1.5240438405087577e+00, 1.8318338313140423e+00, 2.1413081984302371e+00, 2.4527991478588032e+00, 2.7666660769675384e+00, 3.0833023089391358e+00, 3.4031434102599176e+00, 3.7266776654942122e+00, 4.0544595295034727e+00, 4.3871272577720717e+00, 4.7254265200961152e+00, 5.0702427937817154e+00, 5.4226470161614522e+00, 5.7839619604859447e+00, 6.1558623601311924e+00, 6.5405328108757619e+00, 6.9409309282147520e+00, 7.3612580683690458e+00, 7.8078847487003955e+00, 8.2914303867830093e+00, 8.8325166958454133e+00, 9.4852029643727302e+00}, + {-9.5841655475234688e+00, -8.9336883320961924e+00, -8.3945256233272012e+00, -7.9127752978124946e+00, -7.4678752834836200e+00, -7.0492370986783772e+00, -6.6505091785664918e+00, -6.2675031293697510e+00, -5.8972709576411209e+00, -5.5376356924033008e+00, -5.1869289795928895e+00, -4.8438336345819870e+00, -4.5072838118199003e+00, -4.1763988304784849e+00, -3.8504376683661063e+00, -3.5287666814910854e+00, -3.2108360825282936e+00, -2.8961623904571474e+00, -2.5843150518736273e+00, -2.2749060375416974e+00, -1.9675815973920669e+00, -1.6620156026589967e+00, -1.3579040662442226e+00, -1.0549605418738988e+00, -7.5291217747488703e-01, -4.5149624980624264e-01, -1.5045704292086298e-01, 1.5045704292086298e-01, 4.5149624980624264e-01, 7.5291217747488703e-01, 1.0549605418738988e+00, 1.3579040662442226e+00, 1.6620156026589967e+00, 1.9675815973920669e+00, 2.2749060375416974e+00, 2.5843150518736273e+00, 2.8961623904571474e+00, 3.2108360825282936e+00, 3.5287666814910854e+00, 3.8504376683661063e+00, 4.1763988304784849e+00, 4.5072838118199003e+00, 4.8438336345819870e+00, 5.1869289795928895e+00, 5.5376356924033008e+00, 5.8972709576411209e+00, 6.2675031293697510e+00, 6.6505091785664918e+00, 7.0492370986783772e+00, 7.4678752834836200e+00, 7.9127752978124946e+00, 8.3945256233272012e+00, 8.9336883320961924e+00, 9.5841655475234688e+00}, + {-9.6821899525637249e+00, -9.0338717801824053e+00, -8.4965875649075624e+00, -8.0165891148558295e+00, -7.5733727465411995e+00, -7.1563802343429099e+00, -6.7592785186840851e+00, -6.3778918319127680e+00, -6.0092815232536667e+00, -5.6512779962558639e+00, -5.3022190388457897e+00, -4.9607928202275557e+00, -4.6259383469194120e+00, -4.2967794840336984e+00, -3.9725795904787460e+00, -3.6527093464132974e+00, -3.3366233189341656e+00, -3.0238424864191802e+00, -2.7139409275560999e+00, -2.4065354826206522e+00, -2.1012775733291407e+00, -1.7978466126036980e+00, -1.4959445977962444e+00, -1.1952915904152335e+00, -8.9562186046229086e-01, -5.9668052547571682e-01, -2.9822055049276669e-01, -0.0000000000000000e+00, 2.9822055049276669e-01, 5.9668052547571682e-01, 8.9562186046229086e-01, 1.1952915904152335e+00, 1.4959445977962444e+00, 1.7978466126036980e+00, 2.1012775733291407e+00, 2.4065354826206522e+00, 2.7139409275560999e+00, 3.0238424864191802e+00, 3.3366233189341656e+00, 3.6527093464132974e+00, 3.9725795904787460e+00, 4.2967794840336984e+00, 4.6259383469194120e+00, 4.9607928202275557e+00, 5.3022190388457897e+00, 5.6512779962558639e+00, 6.0092815232536667e+00, 6.3778918319127680e+00, 6.7592785186840851e+00, 7.1563802343429099e+00, 7.5733727465411995e+00, 8.0165891148558295e+00, 8.4965875649075624e+00, 9.0338717801824053e+00, 9.6821899525637249e+00}, + {-9.7793021663403099e+00, -9.1330950706121001e+00, -8.5976461414362131e+00, -8.1193580087474686e+00, -7.6777841753281493e+00, -7.2623960212867891e+00, -6.8668785666252870e+00, -6.4870683517446244e+00, -6.1200358061419919e+00, -5.7636184744715768e+00, -5.4161600667900469e+00, -5.0763538899639924e+00, -4.7431435831181288e+00, -4.4156573291002159e+00, -4.0931626262997982e+00, -3.7750342196411242e+00, -3.4607307491477983e+00, -3.1497773444199684e+00, -2.8417523763809922e+00, -2.5362771776597737e+00, -2.2330079208452407e+00, -1.9316290883640068e+00, -1.6318481297059444e+00, -1.3333910111792098e+00, -1.0359984385570031e+00, -7.3942258523430104e-01, -4.4342419505035346e-01, -1.4776995439420115e-01, 1.4776995439420115e-01, 4.4342419505035346e-01, 7.3942258523430104e-01, 1.0359984385570031e+00, 1.3333910111792098e+00, 1.6318481297059444e+00, 1.9316290883640068e+00, 2.2330079208452407e+00, 2.5362771776597737e+00, 2.8417523763809922e+00, 3.1497773444199684e+00, 3.4607307491477983e+00, 3.7750342196411242e+00, 4.0931626262997982e+00, 4.4156573291002159e+00, 4.7431435831181288e+00, 5.0763538899639924e+00, 5.4161600667900469e+00, 5.7636184744715768e+00, 6.1200358061419919e+00, 6.4870683517446244e+00, 6.8668785666252870e+00, 7.2623960212867891e+00, 7.6777841753281493e+00, 8.1193580087474686e+00, 8.5976461414362131e+00, 9.1330950706121001e+00, 9.7793021663403099e+00}, + {-9.8755270017367671e+00, -9.2313849407386552e+00, -8.6977298758606238e+00, -8.2211122660677169e+00, -7.7811416453357003e+00, -7.3673183767785728e+00, -6.9733451542956244e+00, -6.5950705250038864e+00, -6.2295737517233460e+00, -5.8746993020212539e+00, -5.5287966039093659e+00, -5.1905639023838361e+00, -4.8589492677211483e+00, -4.5330849920738157e+00, -4.2122424936406224e+00, -3.8958003472863840e+00, -3.5832210121368786e+00, -3.2740334921948340e+00, -2.9678201464818930e+00, -2.6642064637087906e+00, -2.3628529934485321e+00, -2.0634488697846303e+00, -1.7657065251132762e+00, -1.4693573011471874e+00, -1.1741477394031905e+00, -8.7983638589173074e-01, -5.8619098157190686e-01, -2.9298593604778866e-01, -0.0000000000000000e+00, 2.9298593604778866e-01, 5.8619098157190686e-01, 8.7983638589173074e-01, 1.1741477394031905e+00, 1.4693573011471874e+00, 1.7657065251132762e+00, 2.0634488697846303e+00, 2.3628529934485321e+00, 2.6642064637087906e+00, 2.9678201464818930e+00, 3.2740334921948340e+00, 3.5832210121368786e+00, 3.8958003472863840e+00, 4.2122424936406224e+00, 4.5330849920738157e+00, 4.8589492677211483e+00, 5.1905639023838361e+00, 5.5287966039093659e+00, 5.8746993020212539e+00, 6.2295737517233460e+00, 6.5950705250038864e+00, 6.9733451542956244e+00, 7.3673183767785728e+00, 7.7811416453357003e+00, 8.2211122660677169e+00, 8.6977298758606238e+00, 9.2313849407386552e+00, 9.8755270017367671e+00}, + {-9.9708881704574601e+00, -9.3287669164964395e+00, -8.7968659746627651e+00, -8.3218807506473613e+00, -7.8834756990041477e+00, -7.4711795689242475e+00, -7.0787123410660744e+00, -6.7019342833176401e+00, -6.3379332589686221e+00, -5.9845604541065045e+00, -5.6401708246496867e+00, -5.3034673690975112e+00, -4.9734024034844930e+00, -4.6491121384000209e+00, -4.3298717115959429e+00, -4.0150633146984989e+00, -3.7041529964080997e+00, -3.3966733857420293e+00, -3.0922105568140124e+00, -2.7903938536440540e+00, -2.4908878695658663e+00, -2.1933860192661303e+00, -1.8976053029060733e+00, -1.6032819710214761e+00, -1.3101678741366003e+00, -1.0180273335786967e+00, -7.2663440704649163e-01, -4.3577044873391346e-01, -1.4522188229810670e-01, 1.4522188229810670e-01, 4.3577044873391346e-01, 7.2663440704649163e-01, 1.0180273335786967e+00, 1.3101678741366003e+00, 1.6032819710214761e+00, 1.8976053029060733e+00, 2.1933860192661303e+00, 2.4908878695658663e+00, 2.7903938536440540e+00, 3.0922105568140124e+00, 3.3966733857420293e+00, 3.7041529964080997e+00, 4.0150633146984989e+00, 4.3298717115959429e+00, 4.6491121384000209e+00, 4.9734024034844930e+00, 5.3034673690975112e+00, 5.6401708246496867e+00, 5.9845604541065045e+00, 6.3379332589686221e+00, 6.7019342833176401e+00, 7.0787123410660744e+00, 7.4711795689242475e+00, 7.8834756990041477e+00, 8.3218807506473613e+00, 8.7968659746627651e+00, 9.3287669164964395e+00, 9.9708881704574601e+00}, + {-1.0065408350118513e+01, -9.4252653876263999e+00, -8.8950804110294346e+00, -8.4216909949586132e+00, -7.9848154458297120e+00, -7.5740103261427940e+00, -7.1830125334106762e+00, -6.8076937845356600e+00, -6.4451503233185363e+00, -6.0932398625106678e+00, -5.7503227086468636e+00, -5.4151064424967945e+00, -5.0865474548246592e+00, -4.7637856994329741e+00, -4.4460998505989417e+00, -4.1328755226679874e+00, -3.8235821457915500e+00, -3.5177557486926583e+00, -3.2149858747990203e+00, -2.9149054536014392e+00, -2.6171828242728932e+00, -2.3215153515122373e+00, -2.0276242346848043e+00, -1.7352502204281328e+00, -1.4441500040985724e+00, -1.1540931580511036e+00, -8.6485946196705754e-01, -5.7623653694114951e-01, -2.8801770388153508e-01, -0.0000000000000000e+00, 2.8801770388153508e-01, 5.7623653694114951e-01, 8.6485946196705754e-01, 1.1540931580511036e+00, 1.4441500040985724e+00, 1.7352502204281328e+00, 2.0276242346848043e+00, 2.3215153515122373e+00, 2.6171828242728932e+00, 2.9149054536014392e+00, 3.2149858747990203e+00, 3.5177557486926583e+00, 3.8235821457915500e+00, 4.1328755226679874e+00, 4.4460998505989417e+00, 4.7637856994329741e+00, 5.0865474548246592e+00, 5.4151064424967945e+00, 5.7503227086468636e+00, 6.0932398625106678e+00, 6.4451503233185363e+00, 6.8076937845356600e+00, 7.1830125334106762e+00, 7.5740103261427940e+00, 7.9848154458297120e+00, 8.4216909949586132e+00, 8.8950804110294346e+00, 9.4252653876263999e+00, 1.0065408350118513e+01}, + {-1.0159109246180085e+01, -9.5209036770133171e+00, -8.9923980014049434e+00, -8.5205692841176308e+00, -8.0851886542490199e+00, -7.6758399375048869e+00, -7.2862765943955985e+00, -6.9123815321893174e+00, -6.5512591670629208e+00, -6.2007735579934371e+00, -5.8592901963942339e+00, -5.5255210861386832e+00, -5.1984265345762939e+00, -4.8771500774731509e+00, -4.5609737579358356e+00, -4.2492864359560061e+00, -3.9415607339261842e+00, -3.6373358761707317e+00, -3.3362046535475867e+00, -3.0378033382307490e+00, -2.7418037480696915e+00, -2.4479069023076856e+00, -2.1558378712292110e+00, -1.8653415312330315e+00, -1.5761790119750203e+00, -1.2881246748688935e+00, -1.0009634995607180e+00, -7.1448878167257845e-01, -4.2850006422062747e-01, -1.4280123870343886e-01, 1.4280123870343886e-01, 4.2850006422062747e-01, 7.1448878167257845e-01, 1.0009634995607180e+00, 1.2881246748688935e+00, 1.5761790119750203e+00, 1.8653415312330315e+00, 2.1558378712292110e+00, 2.4479069023076856e+00, 2.7418037480696915e+00, 3.0378033382307490e+00, 3.3362046535475867e+00, 3.6373358761707317e+00, 3.9415607339261842e+00, 4.2492864359560061e+00, 4.5609737579358356e+00, 4.8771500774731509e+00, 5.1984265345762939e+00, 5.5255210861386832e+00, 5.8592901963942339e+00, 6.2007735579934371e+00, 6.5512591670629208e+00, 6.9123815321893174e+00, 7.2862765943955985e+00, 7.6758399375048869e+00, 8.0851886542490199e+00, 8.5205692841176308e+00, 8.9923980014049434e+00, 9.5209036770133171e+00, 1.0159109246180085e+01}, + {-1.0252011649196143e+01, -9.6157041046875609e+00, -9.0888424760573390e+00, -8.6185407332142496e+00, -8.1846218361099510e+00, -7.7766963448476236e+00, -7.3885339440499829e+00, -7.0160284848388690e+00, -6.6562923584988729e+00, -6.3071958002194259e+00, -5.9671093310413950e+00, -5.6347492296736759e+00, -5.3090795734924505e+00, -4.9892473314939929e+00, -4.6745377615999182e+00, -4.3643428074654231e+00, -4.0581381112767332e+00, -3.7554659075853780e+00, -3.4559220338316390e+00, -3.1591458858192856e+00, -2.8648125198053043e+00, -2.5726263447097191e+00, -2.2823160084101848e+00, -1.9936301908281084e+00, -1.7063340915790624e+00, -1.4202064526026656e+00, -1.1350369935815596e+00, -8.5062416477081448e-01, -5.6677314117022048e-01, -2.8329399584293824e-01, -0.0000000000000000e+00, 2.8329399584293824e-01, 5.6677314117022048e-01, 8.5062416477081448e-01, 1.1350369935815596e+00, 1.4202064526026656e+00, 1.7063340915790624e+00, 1.9936301908281084e+00, 2.2823160084101848e+00, 2.5726263447097191e+00, 2.8648125198053043e+00, 3.1591458858192856e+00, 3.4559220338316390e+00, 3.7554659075853780e+00, 4.0581381112767332e+00, 4.3643428074654231e+00, 4.6745377615999182e+00, 4.9892473314939929e+00, 5.3090795734924505e+00, 5.6347492296736759e+00, 5.9671093310413950e+00, 6.3071958002194259e+00, 6.6562923584988729e+00, 7.0160284848388690e+00, 7.3885339440499829e+00, 7.7766963448476236e+00, 8.1846218361099510e+00, 8.6185407332142496e+00, 9.0888424760573390e+00, 9.6157041046875609e+00, 1.0252011649196143e+01}, + {-1.0344135487806895e+01, -9.7096880469839437e+00, -9.1844365442194498e+00, -8.7156293586041365e+00, -8.2831403244454158e+00, -7.8766062274725090e+00, -7.4898126515277026e+00, -7.1186641563335851e+00, -6.7602809210235622e+00, -6.4125391965266108e+00, -6.0738143878025932e+00, -5.7428269099958227e+00, -5.4185444743952305e+00, -5.1001173457332412e+00, -4.7868338549738239e+00, -4.4780888809091079e+00, -4.1733609279699495e+00, -3.8721950721542884e+00, -3.5741900152128512e+00, -3.2789880784162539e+00, -2.9862673397528621e+00, -2.6957353597041749e+00, -2.4071241008699498e+00, -2.1201857552620891e+00, -1.8346892680544815e+00, -1.5504173991942523e+00, -1.2671642017112603e+00, -9.8473282246759541e-01, -7.0293355055041085e-01, -4.2158205259642756e-01, -1.4049774444160384e-01, 1.4049774444160384e-01, 4.2158205259642756e-01, 7.0293355055041085e-01, 9.8473282246759541e-01, 1.2671642017112603e+00, 1.5504173991942523e+00, 1.8346892680544815e+00, 2.1201857552620891e+00, 2.4071241008699498e+00, 2.6957353597041749e+00, 2.9862673397528621e+00, 3.2789880784162539e+00, 3.5741900152128512e+00, 3.8721950721542884e+00, 4.1733609279699495e+00, 4.4780888809091079e+00, 4.7868338549738239e+00, 5.1001173457332412e+00, 5.4185444743952305e+00, 5.7428269099958227e+00, 6.0738143878025932e+00, 6.4125391965266108e+00, 6.7602809210235622e+00, 7.1186641563335851e+00, 7.4898126515277026e+00, 7.8766062274725090e+00, 8.2831403244454158e+00, 8.7156293586041365e+00, 9.1844365442194498e+00, 9.7096880469839437e+00, 1.0344135487806895e+01}, + {-1.0435499877854168e+01, -9.8028759912974959e+00, -9.2792019543050390e+00, -8.8118581437284540e+00, -8.3807683451863202e+00, -7.9755950801420372e+00, -7.5901395198641071e+00, -7.2203167078889665e+00, -6.8632544331795353e+00, -6.5168348106821155e+00, -6.1794379922705955e+00, -5.8497884000810672e+00, -5.5268572526403030e+00, -5.2097979830408345e+00, -4.8979018644975740e+00, -4.5905665744435185e+00, -4.2872733352824408e+00, -3.9875699104197153e+00, -3.6910577000963465e+00, -3.3973817713303909e+00, -3.1062230279282566e+00, -2.8172919672837975e+00, -2.5303236304712007e+00, -2.2450734604812066e+00, -1.9613138583081484e+00, -1.6788312791720135e+00, -1.3974237486049623e+00, -1.1168987050996462e+00, -8.3707109558947612e-01, -5.5776166427908214e-01, -2.7879538567115225e-01, -0.0000000000000000e+00, 2.7879538567115225e-01, 5.5776166427908214e-01, 8.3707109558947612e-01, 1.1168987050996462e+00, 1.3974237486049623e+00, 1.6788312791720135e+00, 1.9613138583081484e+00, 2.2450734604812066e+00, 2.5303236304712007e+00, 2.8172919672837975e+00, 3.1062230279282566e+00, 3.3973817713303909e+00, 3.6910577000963465e+00, 3.9875699104197153e+00, 4.2872733352824408e+00, 4.5905665744435185e+00, 4.8979018644975740e+00, 5.2097979830408345e+00, 5.5268572526403030e+00, 5.8497884000810672e+00, 6.1794379922705955e+00, 6.5168348106821155e+00, 6.8632544331795353e+00, 7.2203167078889665e+00, 7.5901395198641071e+00, 7.9755950801420372e+00, 8.3807683451863202e+00, 8.8118581437284540e+00, 9.2792019543050390e+00, 9.8028759912974959e+00, 1.0435499877854168e+01}, + {-1.0526123167960545e+01, -9.8952875868295376e+00, -9.3731595496467204e+00, -8.9072490999647691e+00, -8.4775290833798636e+00, -8.0736872850102248e+00, -7.6895401640404968e+00, -7.3210130327809484e+00, -6.9652411205511076e+00, -6.6201122626360274e+00, -6.2840112287748280e+00, -5.9556663267994852e+00, -5.6340521643499724e+00, -5.3183252246332708e+00, -5.0077796021987675e+00, -4.7018156474074990e+00, -4.3999171682281375e+00, -4.1016344745666560e+00, -3.8065715139453600e+00, -3.5143759357409059e+00, -3.2247312919920357e+00, -2.9373508230046212e+00, -2.6519724354306349e+00, -2.3683545886324011e+00, -2.0862728798817618e+00, -1.8055171714655447e+00, -1.5258891402098638e+00, -1.2472001569431179e+00, -9.6926942307117792e-01, -6.9192230581004455e-01, -4.1498882412107863e-01, -1.3830224498700971e-01, 1.3830224498700971e-01, 4.1498882412107863e-01, 6.9192230581004455e-01, 9.6926942307117792e-01, 1.2472001569431179e+00, 1.5258891402098638e+00, 1.8055171714655447e+00, 2.0862728798817618e+00, 2.3683545886324011e+00, 2.6519724354306349e+00, 2.9373508230046212e+00, 3.2247312919920357e+00, 3.5143759357409059e+00, 3.8065715139453600e+00, 4.1016344745666560e+00, 4.3999171682281375e+00, 4.7018156474074990e+00, 5.0077796021987675e+00, 5.3183252246332708e+00, 5.6340521643499724e+00, 5.9556663267994852e+00, 6.2840112287748280e+00, 6.6201122626360274e+00, 6.9652411205511076e+00, 7.3210130327809484e+00, 7.6895401640404968e+00, 8.0736872850102248e+00, 8.4775290833798636e+00, 8.9072490999647691e+00, 9.3731595496467204e+00, 9.8952875868295376e+00, 1.0526123167960545e+01}, + {-1.0616022981878281e+01, -9.9869416916766838e+00, -9.4663293201553849e+00, -9.0018233229591331e+00, -8.5734447444179089e+00, -8.1709061780525847e+00, -7.7880390829895703e+00, -7.4207788343663230e+00, -7.0662679403068926e+00, -6.7223998201657338e+00, -6.3875637397870904e+00, -6.0604917788315049e+00, -5.7401618236902250e+00, -5.4257332976973487e+00, -5.1165030047214124e+00, -4.8118738520274640e+00, -4.5113321113682128e+00, -4.2144305099719546e+00, -3.9207754044447234e+00, -3.6300168776328952e+00, -3.3418409684468302e+00, -3.0559634843286707e+00, -2.7721250051570916e+00, -2.4900867953039354e+00, -2.2096274151691842e+00, -1.9305398759772254e+00, -1.6526292190403253e+00, -1.3757104277236682e+00, -1.0996066000569449e+00, -8.2414732440241278e-01, -5.4916721122159917e-01, -2.7450454175394473e-01, -0.0000000000000000e+00, 2.7450454175394473e-01, 5.4916721122159917e-01, 8.2414732440241278e-01, 1.0996066000569449e+00, 1.3757104277236682e+00, 1.6526292190403253e+00, 1.9305398759772254e+00, 2.2096274151691842e+00, 2.4900867953039354e+00, 2.7721250051570916e+00, 3.0559634843286707e+00, 3.3418409684468302e+00, 3.6300168776328952e+00, 3.9207754044447234e+00, 4.2144305099719546e+00, 4.5113321113682128e+00, 4.8118738520274640e+00, 5.1165030047214124e+00, 5.4257332976973487e+00, 5.7401618236902250e+00, 6.0604917788315049e+00, 6.3875637397870904e+00, 6.7223998201657338e+00, 7.0662679403068926e+00, 7.4207788343663230e+00, 7.7880390829895703e+00, 8.1709061780525847e+00, 8.5734447444179089e+00, 9.0018233229591331e+00, 9.4663293201553849e+00, 9.9869416916766838e+00, 1.0616022981878281e+01}, + {-1.0705216257883158e+01, -1.0077856416579301e+01, -9.5587304502592971e+00, -9.0956010448419295e+00, -8.6685366107264805e+00, -8.2672741104998497e+00, -7.8856597261055059e+00, -7.5196386980596541e+00, -7.1663606590936650e+00, -6.8237244832006141e+00, -6.4901238172609474e+00, -6.1642944056838216e+00, -5.8452173103130356e+00, -5.5320547921086867e+00, -5.2241062602848638e+00, -4.9207770717124939e+00, -4.6215558496899147e+00, -4.3259976200905568e+00, -4.0337110220232306e+00, -3.7443484358240933e+00, -3.4575982403178411e+00, -3.1731786504386261e+00, -2.8908327450724003e+00, -2.6103244026894505e+00, -2.3314349368154352e+00, -2.0539602757725310e+00, -1.7777085685161123e+00, -1.5024981254275005e+00, -1.2281556226723449e+00, -9.5451451326831394e-01, -6.8141359873982055e-01, -4.0869572314721075e-01, -1.3620655703952730e-01, 1.3620655703952730e-01, 4.0869572314721075e-01, 6.8141359873982055e-01, 9.5451451326831394e-01, 1.2281556226723449e+00, 1.5024981254275005e+00, 1.7777085685161123e+00, 2.0539602757725310e+00, 2.3314349368154352e+00, 2.6103244026894505e+00, 2.8908327450724003e+00, 3.1731786504386261e+00, 3.4575982403178411e+00, 3.7443484358240933e+00, 4.0337110220232306e+00, 4.3259976200905568e+00, 4.6215558496899147e+00, 4.9207770717124939e+00, 5.2241062602848638e+00, 5.5320547921086867e+00, 5.8452173103130356e+00, 6.1642944056838216e+00, 6.4901238172609474e+00, 6.8237244832006141e+00, 7.1663606590936650e+00, 7.5196386980596541e+00, 7.8856597261055059e+00, 8.2672741104998497e+00, 8.6685366107264805e+00, 9.0956010448419295e+00, 9.5587304502592971e+00, 1.0077856416579301e+01, 1.0705216257883158e+01}, + {-1.0793719285461286e+01, -1.0168049165614175e+01, -9.6503813634446356e+00, -9.1886016826884820e+00, -8.7628250943199557e+00, -8.3628125057261151e+00, -7.9824245547615575e+00, -7.6176161578278192e+00, -7.2655439249081999e+00, -6.9241120615277021e+00, -6.5917184866891132e+00, -6.2671025086846086e+00, -5.9492482679521004e+00, -5.6373207673775578e+00, -5.3306219248283462e+00, -5.0285594473595783e+00, -4.7306242061652037e+00, -4.4363734165111914e+00, -4.1454178838251625e+00, -3.8574121614750752e+00, -3.5720468340630473e+00, -3.2890423786892447e+00, -3.0081442150749433e+00, -2.7291186629245998e+00, -2.4517495992505411e+00, -2.1758356606878357e+00, -1.9011878731830645e+00, -1.6276276184711236e+00, -1.3549848665269235e+00, -1.0830966177633830e+00, -8.1180550955890352e-01, -5.4095854971511481e-01, -2.7040594535031914e-01, -0.0000000000000000e+00, 2.7040594535031914e-01, 5.4095854971511481e-01, 8.1180550955890352e-01, 1.0830966177633830e+00, 1.3549848665269235e+00, 1.6276276184711236e+00, 1.9011878731830645e+00, 2.1758356606878357e+00, 2.4517495992505411e+00, 2.7291186629245998e+00, 3.0081442150749433e+00, 3.2890423786892447e+00, 3.5720468340630473e+00, 3.8574121614750752e+00, 4.1454178838251625e+00, 4.4363734165111914e+00, 4.7306242061652037e+00, 5.0285594473595783e+00, 5.3306219248283462e+00, 5.6373207673775578e+00, 5.9492482679521004e+00, 6.2671025086846086e+00, 6.5917184866891132e+00, 6.9241120615277021e+00, 7.2655439249081999e+00, 7.6176161578278192e+00, 7.9824245547615575e+00, 8.3628125057261151e+00, 8.7628250943199557e+00, 9.1886016826884820e+00, 9.6503813634446356e+00, 1.0168049165614175e+01, 1.0793719285461286e+01}, + {-1.0881547739512506e+01, -1.0257536674087854e+01, -9.7412997636867704e+00, -9.2808438835486236e+00, -8.8563297855819929e+00, -8.4575419119948716e+00, -8.0783550992846092e+00, -7.7147337577029216e+00, -7.3638413335052801e+00, -7.0235872465011688e+00, -6.6923735845747432e+00, -6.3689431247367301e+00, -6.0522829950450374e+00, -5.7415608508027303e+00, -5.4360810284450567e+00, -5.1352534929147948e+00, -4.8385712673985131e+00, -4.5455936557800598e+00, -4.2559335229494488e+00, -3.9692474811577245e+00, -3.6852281980879265e+00, -3.4035982804227491e+00, -3.1241053447888532e+00, -2.8465179952316144e+00, -2.5706225005795180e+00, -2.2962200172773377e+00, -2.0231242405790431e+00, -1.7511593940081669e+00, -1.4801584867781896e+00, -1.2099617834856000e+00, -9.4041544125892573e-01, -6.7137027764848267e-01, -4.0268063855845554e-01, -1.3420333993493833e-01, 1.3420333993493833e-01, 4.0268063855845554e-01, 6.7137027764848267e-01, 9.4041544125892573e-01, 1.2099617834856000e+00, 1.4801584867781896e+00, 1.7511593940081669e+00, 2.0231242405790431e+00, 2.2962200172773377e+00, 2.5706225005795180e+00, 2.8465179952316144e+00, 3.1241053447888532e+00, 3.4035982804227491e+00, 3.6852281980879265e+00, 3.9692474811577245e+00, 4.2559335229494488e+00, 4.5455936557800598e+00, 4.8385712673985131e+00, 5.1352534929147948e+00, 5.4360810284450567e+00, 5.7415608508027303e+00, 6.0522829950450374e+00, 6.3689431247367301e+00, 6.6923735845747432e+00, 7.0235872465011688e+00, 7.3638413335052801e+00, 7.7147337577029216e+00, 8.0783550992846092e+00, 8.4575419119948716e+00, 8.8563297855819929e+00, 9.2808438835486236e+00, 9.7412997636867704e+00, 1.0257536674087854e+01, 1.0881547739512506e+01}, + {-1.0968716712272720e+01, -1.0346335043862190e+01, -9.8315026740330858e+00, -9.3723455663368824e+00, -8.9490694985983303e+00, -8.5514820514248040e+00, -8.1734720117891584e+00, -7.8110131087611858e+00, -7.4612754898399762e+00, -7.1221736773103954e+00, -6.7921138299353210e+00, -6.4698421035199560e+00, -6.1543485281550758e+00, -5.8448033276997977e+00, -5.5405131730790877e+00, -5.2408902012860343e+00, -4.9454294985999852e+00, -4.6536923643912962e+00, -4.3652936245432166e+00, -4.0798918452871904e+00, -3.7971816649246475e+00, -3.5168876985063164e+00, -3.2387596283073630e+00, -2.9625681999937008e+00, -2.6881019184401618e+00, -2.4151642892936240e+00, -2.1435714896364328e+00, -1.8731503781015579e+00, -1.6037367745786486e+00, -1.3351739542940309e+00, -1.0673113119622561e+00, -8.0000315987311321e-01, -5.3310762988307847e-01, -2.6648565380755118e-01, -0.0000000000000000e+00, 2.6648565380755118e-01, 5.3310762988307847e-01, 8.0000315987311321e-01, 1.0673113119622561e+00, 1.3351739542940309e+00, 1.6037367745786486e+00, 1.8731503781015579e+00, 2.1435714896364328e+00, 2.4151642892936240e+00, 2.6881019184401618e+00, 2.9625681999937008e+00, 3.2387596283073630e+00, 3.5168876985063164e+00, 3.7971816649246475e+00, 4.0798918452871904e+00, 4.3652936245432166e+00, 4.6536923643912962e+00, 4.9454294985999852e+00, 5.2408902012860343e+00, 5.5405131730790877e+00, 5.8448033276997977e+00, 6.1543485281550758e+00, 6.4698421035199560e+00, 6.7921138299353210e+00, 7.1221736773103954e+00, 7.4612754898399762e+00, 7.8110131087611858e+00, 8.1734720117891584e+00, 8.5514820514248040e+00, 8.9490694985983303e+00, 9.3723455663368824e+00, 9.8315026740330858e+00, 1.0346335043862190e+01, 1.0968716712272720e+01}, + {-1.1055240743138121e+01, -1.0434459776321237e+01, -9.9210064725726337e+00, -9.4631239608462057e+00, -9.0410623133341144e+00, -8.6446518655005491e+00, -8.2677951152318059e+00, -7.9064749419687779e+00, -7.5578680649896128e+00, -7.2198940023018814e+00, -6.8909628903904032e+00, -6.5698241787566660e+00, -6.2554707188783159e+00, -5.9470752244713703e+00, -5.6439466223452381e+00, -5.3454991415732502e+00, -5.0512298489716008e+00, -4.7607019531713526e+00, -4.4735321501381859e+00, -4.1893808634925733e+00, -3.9079445988680890e+00, -3.6289498686372541e+00, -3.3521483007723556e+00, -3.0773126524497552e+00, -2.8042335229302870e+00, -2.5327166122907285e+00, -2.2625804097899467e+00, -1.9936542226231451e+00, -1.7257764756009522e+00, -1.4587932269483976e+00, -1.1925568563654070e+00, -9.2692488970661657e-01, -6.6175893081256654e-01, -3.9692367564298847e-01, -1.3228598727031571e-01, 1.3228598727031571e-01, 3.9692367564298847e-01, 6.6175893081256654e-01, 9.2692488970661657e-01, 1.1925568563654070e+00, 1.4587932269483976e+00, 1.7257764756009522e+00, 1.9936542226231451e+00, 2.2625804097899467e+00, 2.5327166122907285e+00, 2.8042335229302870e+00, 3.0773126524497552e+00, 3.3521483007723556e+00, 3.6289498686372541e+00, 3.9079445988680890e+00, 4.1893808634925733e+00, 4.4735321501381859e+00, 4.7607019531713526e+00, 5.0512298489716008e+00, 5.3454991415732502e+00, 5.6439466223452381e+00, 5.9470752244713703e+00, 6.2554707188783159e+00, 6.5698241787566660e+00, 6.8909628903904032e+00, 7.2198940023018814e+00, 7.5578680649896128e+00, 7.9064749419687779e+00, 8.2677951152318059e+00, 8.6446518655005491e+00, 9.0410623133341144e+00, 9.4631239608462057e+00, 9.9210064725726337e+00, 1.0434459776321237e+01, 1.1055240743138121e+01}, + {-1.1141133846557336e+01, -1.0521925803168939e+01, -1.0009826926005323e+01, -9.5531956441224679e+00, -9.1323256149194787e+00, -8.7370695574210657e+00, -8.3613434490107519e+00, -8.0011391572542987e+00, -7.6536398489544064e+00, -7.3167699357978755e+00, -6.9889434433253230e+00, -6.6689130340885914e+00, -6.3556743048467315e+00, -6.0484023852002728e+00, -5.7464083842334572e+00, -5.4491085484699262e+00, -5.1560018484650616e+00, -4.8666533221367576e+00, -4.5806814514481742e+00, -4.2977484283048772e+00, -4.0175525306328757e+00, -3.7398220661958628e+00, -3.4643104988218911e+00, -3.1907924783359922e+00, -2.9190605692775651e+00, -2.6489225254318436e+00, -2.3801989943566357e+00, -2.1127215630246923e+00, -1.8463310754751214e+00, -1.5808761680325296e+00, -1.3162119786216788e+00, -1.0521989949595671e+00, -7.8870201263520334e-01, -5.2558917877833533e-01, -2.6273110051935877e-01, -0.0000000000000000e+00, 2.6273110051935877e-01, 5.2558917877833533e-01, 7.8870201263520334e-01, 1.0521989949595671e+00, 1.3162119786216788e+00, 1.5808761680325296e+00, 1.8463310754751214e+00, 2.1127215630246923e+00, 2.3801989943566357e+00, 2.6489225254318436e+00, 2.9190605692775651e+00, 3.1907924783359922e+00, 3.4643104988218911e+00, 3.7398220661958628e+00, 4.0175525306328757e+00, 4.2977484283048772e+00, 4.5806814514481742e+00, 4.8666533221367576e+00, 5.1560018484650616e+00, 5.4491085484699262e+00, 5.7464083842334572e+00, 6.0484023852002728e+00, 6.3556743048467315e+00, 6.6689130340885914e+00, 6.9889434433253230e+00, 7.3167699357978755e+00, 7.6536398489544064e+00, 8.0011391572542987e+00, 8.3613434490107519e+00, 8.7370695574210657e+00, 9.1323256149194787e+00, 9.5531956441224679e+00, 1.0009826926005323e+01, 1.0521925803168939e+01, 1.1141133846557336e+01}, + {-1.1226409538142136e+01, -1.0608747515229252e+01, -1.0097979221003259e+01, -9.6425765744143064e+00, -9.2228761302815698e+00, -8.8287526315494791e+00, -8.4541353114024211e+00, -8.0950248691313433e+00, -7.7486107996948919e+00, -7.4128223108085409e+00, -7.0860772325710890e+00, -6.7671313640535109e+00, -6.4549829753707284e+00, -6.1488095423716089e+00, -5.8479242873741697e+00, -5.5517454045920136e+00, -5.2597736967589261e+00, -4.9715759567771789e+00, -4.6867723746994256e+00, -4.4050268283718435e+00, -4.1260392804003079e+00, -3.8495397401994360e+00, -3.5752834066737424e+00, -3.3030467134928974e+00, -3.0326240725636300e+00, -2.7638251631581228e+00, -2.4964726512514903e+00, -2.2304002505260021e+00, -1.9654510562578547e+00, -1.7014760979685193e+00, -1.4383330677067736e+00, -1.1758851891099782e+00, -9.1400019866369742e-01, -6.5254941532698807e-01, -3.9140687826621273e-01, -1.3044853509282020e-01, 1.3044853509282020e-01, 3.9140687826621273e-01, 6.5254941532698807e-01, 9.1400019866369742e-01, 1.1758851891099782e+00, 1.4383330677067736e+00, 1.7014760979685193e+00, 1.9654510562578547e+00, 2.2304002505260021e+00, 2.4964726512514903e+00, 2.7638251631581228e+00, 3.0326240725636300e+00, 3.3030467134928974e+00, 3.5752834066737424e+00, 3.8495397401994360e+00, 4.1260392804003079e+00, 4.4050268283718435e+00, 4.6867723746994256e+00, 4.9715759567771789e+00, 5.2597736967589261e+00, 5.5517454045920136e+00, 5.8479242873741697e+00, 6.1488095423716089e+00, 6.4549829753707284e+00, 6.7671313640535109e+00, 7.0860772325710890e+00, 7.4128223108085409e+00, 7.7486107996948919e+00, 8.0950248691313433e+00, 8.4541353114024211e+00, 8.8287526315494791e+00, 9.2228761302815698e+00, 9.6425765744143064e+00, 1.0097979221003259e+01, 1.0608747515229252e+01, 1.1226409538142136e+01}, + {-1.1311080859133723e+01, -1.0694938789404631e+01, -1.0185477993538820e+01, -9.7312821228925461e+00, -9.3127299623383131e+00, -8.9197179302027116e+00, -8.5461882990986897e+00, -8.1881504491623041e+00, -7.8428000887281044e+00, -7.5080711279939001e+00, -7.1823851209949314e+00, -6.8645009305993021e+00, -6.5534194322069030e+00, -6.2483203822637563e+00, -5.9485190514660768e+00, -5.6534355164057573e+00, -5.3625723452058249e+00, -5.0754980166052253e+00, -4.7918343564389145e+00, -4.5112468522638922e+00, -4.2334370704564908e+00, -3.9581366357170062e+00, -3.6851023893880592e+00, -3.4141124491940373e+00, -3.1449629665080243e+00, -2.8774654290158654e+00, -2.6114443936789562e+00, -2.3467355617654575e+00, -2.0831841274592904e+00, -1.8206433462185645e+00, -1.5589732800480507e+00, -1.2980396851534748e+00, -1.0377130137484731e+00, -7.7786750657853077e-01, -5.1838035636125168e-01, -2.5913092507112634e-01, -0.0000000000000000e+00, 2.5913092507112634e-01, 5.1838035636125168e-01, 7.7786750657853077e-01, 1.0377130137484731e+00, 1.2980396851534748e+00, 1.5589732800480507e+00, 1.8206433462185645e+00, 2.0831841274592904e+00, 2.3467355617654575e+00, 2.6114443936789562e+00, 2.8774654290158654e+00, 3.1449629665080243e+00, 3.4141124491940373e+00, 3.6851023893880592e+00, 3.9581366357170062e+00, 4.2334370704564908e+00, 4.5112468522638922e+00, 4.7918343564389145e+00, 5.0754980166052253e+00, 5.3625723452058249e+00, 5.6534355164057573e+00, 5.9485190514660768e+00, 6.2483203822637563e+00, 6.5534194322069030e+00, 6.8645009305993021e+00, 7.1823851209949314e+00, 7.5080711279939001e+00, 7.8428000887281044e+00, 8.1881504491623041e+00, 8.5461882990986897e+00, 8.9197179302027116e+00, 9.3127299623383131e+00, 9.7312821228925461e+00, 1.0185477993538820e+01, 1.0694938789404631e+01, 1.1311080859133723e+01}, + {-1.1395160399349303e+01, -1.0780513013934538e+01, -1.0272337356338001e+01, -9.8193271033153593e+00, -9.4019026219489774e+00, -9.0099816679963673e+00, -8.6375193440825591e+00, -8.2805335655260475e+00, -7.9362261435724362e+00, -7.6025356011958438e+00, -7.2778871393556734e+00, -6.9610426155273659e+00, -6.6510054458855254e+00, -6.3469576054906103e+00, -6.0482163524027337e+00, -5.7542035843517603e+00, -5.4644235724164387e+00, -5.1784464167185336e+00, -4.8958955116562031e+00, -4.6164378838097413e+00, -4.3397766284785542e+00, -4.0656449059380266e+00, -3.7938011146597774e+00, -3.5240249647298416e+00, -3.2561142480573673e+00, -2.9898821536352491e+00, -2.7251550130837989e+00, -2.4617703885377660e+00, -2.1995754346550642e+00, -1.9384254811801831e+00, -1.6781827934921525e+00, -1.4187154768845949e+00, -1.1598964966533338e+00, -9.0160279089609208e-01, -6.4371445661134197e-01, -3.8611399247334727e-01, -1.2868558374092035e-01, 1.2868558374092035e-01, 3.8611399247334727e-01, 6.4371445661134197e-01, 9.0160279089609208e-01, 1.1598964966533338e+00, 1.4187154768845949e+00, 1.6781827934921525e+00, 1.9384254811801831e+00, 2.1995754346550642e+00, 2.4617703885377660e+00, 2.7251550130837989e+00, 2.9898821536352491e+00, 3.2561142480573673e+00, 3.5240249647298416e+00, 3.7938011146597774e+00, 4.0656449059380266e+00, 4.3397766284785542e+00, 4.6164378838097413e+00, 4.8958955116562031e+00, 5.1784464167185336e+00, 5.4644235724164387e+00, 5.7542035843517603e+00, 6.0482163524027337e+00, 6.3469576054906103e+00, 6.6510054458855254e+00, 6.9610426155273659e+00, 7.2778871393556734e+00, 7.6025356011958438e+00, 7.9362261435724362e+00, 8.2805335655260475e+00, 8.6375193440825591e+00, 9.0099816679963673e+00, 9.4019026219489774e+00, 9.8193271033153593e+00, 1.0272337356338001e+01, 1.0780513013934538e+01, 1.1395160399349303e+01}, + {-1.1478660318722643e+01, -1.0865483112083050e+01, -1.0358570924603207e+01, -9.9067257997991209e+00, -9.4904090577984004e+00, -9.0995594639401105e+00, -8.7281447480576215e+00, -8.3721912199266999e+00, -8.0289066873027544e+00, -7.6962341998287283e+00, -7.3726025317424613e+00, -7.0567764692174766e+00, -6.7477619079872566e+00, -6.4447429831267424e+00, -6.1470388825769424e+00, -5.8540732676978866e+00, -5.5653520540734327e+00, -5.2804469030361734e+00, -4.9989827149592099e+00, -4.7206279897915646e+00, -4.4450872824012313e+00, -4.1720952149448500e+00, -3.9014116643261456e+00, -3.6328178485882909e+00, -3.3661131093032384e+00, -3.1011122385952579e+00, -2.8376432363425028e+00, -2.5755454098889712e+00, -2.3146677482934548e+00, -2.0548675177858016e+00, -1.7960090360977110e+00, -1.5379625916624640e+00, -1.2806034800245349e+00, -1.0238111346569745e+00, -7.6746833310481610e-01, -5.1146046221189689e-01, -2.5567482833134803e-01, -0.0000000000000000e+00, 2.5567482833134803e-01, 5.1146046221189689e-01, 7.6746833310481610e-01, 1.0238111346569745e+00, 1.2806034800245349e+00, 1.5379625916624640e+00, 1.7960090360977110e+00, 2.0548675177858016e+00, 2.3146677482934548e+00, 2.5755454098889712e+00, 2.8376432363425028e+00, 3.1011122385952579e+00, 3.3661131093032384e+00, 3.6328178485882909e+00, 3.9014116643261456e+00, 4.1720952149448500e+00, 4.4450872824012313e+00, 4.7206279897915646e+00, 4.9989827149592099e+00, 5.2804469030361734e+00, 5.5653520540734327e+00, 5.8540732676978866e+00, 6.1470388825769424e+00, 6.4447429831267424e+00, 6.7477619079872566e+00, 7.0567764692174766e+00, 7.3726025317424613e+00, 7.6962341998287283e+00, 8.0289066873027544e+00, 8.3721912199266999e+00, 8.7281447480576215e+00, 9.0995594639401105e+00, 9.4904090577984004e+00, 9.9067257997991209e+00, 1.0358570924603207e+01, 1.0865483112083050e+01, 1.1478660318722643e+01}, + {-1.1561592367542413e+01, -1.0949861564373141e+01, -1.0444191840136728e+01, -9.9934919928404522e+00, -9.5782636843755515e+00, -9.1884663714605921e+00, -8.8180802146261925e+00, -8.4631397820581817e+00, -8.1208587754520742e+00, -7.7891846883888824e+00, -7.4665497978837827e+00, -7.1517217559506374e+00, -6.8437088797189292e+00, -6.5416974088024276e+00, -6.2450084067917304e+00, -5.9530672445968058e+00, -5.6653814275042969e+00, -5.3815241217984982e+00, -5.1011216754614015e+00, -4.8238440007350292e+00, -4.5493970476880525e+00, -4.2775168321151087e+00, -4.0079646366324129e+00, -3.7405231094103377e+00, -3.4749930580623096e+00, -3.2111907876889831e+00, -2.9489458689195023e+00, -2.6880992485383528e+00, -2.4285016349547641e+00, -2.1700121054020434e+00, -1.9124968927478689e+00, -1.6558283181292228e+00, -1.3998838419857680e+00, -1.1445452109440197e+00, -8.8969768175512143e-01, -6.3522930636766928e-01, -3.8103026441027604e-01, -1.2699223100184112e-01, 1.2699223100184112e-01, 3.8103026441027604e-01, 6.3522930636766928e-01, 8.8969768175512143e-01, 1.1445452109440197e+00, 1.3998838419857680e+00, 1.6558283181292228e+00, 1.9124968927478689e+00, 2.1700121054020434e+00, 2.4285016349547641e+00, 2.6880992485383528e+00, 2.9489458689195023e+00, 3.2111907876889831e+00, 3.4749930580623096e+00, 3.7405231094103377e+00, 4.0079646366324129e+00, 4.2775168321151087e+00, 4.5493970476880525e+00, 4.8238440007350292e+00, 5.1011216754614015e+00, 5.3815241217984982e+00, 5.6653814275042969e+00, 5.9530672445968058e+00, 6.2450084067917304e+00, 6.5416974088024276e+00, 6.8437088797189292e+00, 7.1517217559506374e+00, 7.4665497978837827e+00, 7.7891846883888824e+00, 8.1208587754520742e+00, 8.4631397820581817e+00, 8.8180802146261925e+00, 9.1884663714605921e+00, 9.5782636843755515e+00, 9.9934919928404522e+00, 1.0444191840136728e+01, 1.0949861564373141e+01, 1.1561592367542413e+01}, + {-1.1643967905483196e+01, -1.1033660429475029e+01, -1.0529212793984577e+01, -1.0079638983721908e+01, -9.6654804081925363e+00, -9.2767169065128172e+00, -8.9073408793931357e+00, -8.5533950218190302e+00, -8.2120988304736517e+00, -7.8814041633182299e+00, -7.5597467325857197e+00, -7.2458969961152926e+00, -6.9388656371030670e+00, -6.6378409471161133e+00, -6.3421458141623201e+00, -6.0512072677740329e+00, -5.7645343514856853e+00, -5.4817016838558219e+00, -5.2023370059655702e+00, -4.9261115854472983e+00, -4.6527327077376199e+00, -4.3819377189728366e+00, -4.1134892401757890e+00, -3.8471712777564733e+00, -3.5827860282892376e+00, -3.3201512269147213e+00, -3.0590979254933970e+00, -2.7994686133415088e+00, -2.5411156130214039e+00, -2.2838996982733861e+00, -2.0276888921639609e+00, -1.7723574118602183e+00, -1.5177847328096994e+00, -1.2638547500001409e+00, -1.0104550177477929e+00, -7.5747605237336058e-01, -5.0481068435860232e-01, -2.5235344827118406e-01, -0.0000000000000000e+00, 2.5235344827118406e-01, 5.0481068435860232e-01, 7.5747605237336058e-01, 1.0104550177477929e+00, 1.2638547500001409e+00, 1.5177847328096994e+00, 1.7723574118602183e+00, 2.0276888921639609e+00, 2.2838996982733861e+00, 2.5411156130214039e+00, 2.7994686133415088e+00, 3.0590979254933970e+00, 3.3201512269147213e+00, 3.5827860282892376e+00, 3.8471712777564733e+00, 4.1134892401757890e+00, 4.3819377189728366e+00, 4.6527327077376199e+00, 4.9261115854472983e+00, 5.2023370059655702e+00, 5.4817016838558219e+00, 5.7645343514856853e+00, 6.0512072677740329e+00, 6.3421458141623201e+00, 6.6378409471161133e+00, 6.9388656371030670e+00, 7.2458969961152926e+00, 7.5597467325857197e+00, 7.8814041633182299e+00, 8.2120988304736517e+00, 8.5533950218190302e+00, 8.9073408793931357e+00, 9.2767169065128172e+00, 9.6654804081925363e+00, 1.0079638983721908e+01, 1.0529212793984577e+01, 1.1033660429475029e+01, 1.1643967905483196e+01}, + {-1.1725797919515925e+01, -1.1116891363846698e+01, -1.0613646047709890e+01, -1.0165179617422121e+01, -9.7520726523771355e+00, -9.3643250739262687e+00, -8.9959413381560331e+00, -8.6429721394539492e+00, -8.3026426739573083e+00, -7.9729090874349415e+00, -7.6522104625334553e+00, -7.3393200055543293e+00, -7.0332507130647253e+00, -6.7331928786770474e+00, -6.4384711663544172e+00, -6.1485142162283823e+00, -5.8628325617022545e+00, -5.5810022242153172e+00, -5.3026522869660511e+00, -5.0274553198842957e+00, -4.7551198880737857e+00, -4.4853846092140870e+00, -4.2180133803413131e+00, -3.9527914995987943e+00, -3.6895224813523542e+00, -3.4280254143563189e+00, -3.1681327493707792e+00, -2.9096884292910694e+00, -2.6525462944632925e+00, -2.3965687104578790e+00, -2.1416253765529731e+00, -1.8875922815137989e+00, -1.6343507796298868e+00, -1.3817867648795250e+00, -1.1297899248837724e+00, -8.7825305924819486e-01, -6.2707144915742807e-01, -3.7614226682388563e-01, -1.2536401469850444e-01, 1.2536401469850444e-01, 3.7614226682388563e-01, 6.2707144915742807e-01, 8.7825305924819486e-01, 1.1297899248837724e+00, 1.3817867648795250e+00, 1.6343507796298868e+00, 1.8875922815137989e+00, 2.1416253765529731e+00, 2.3965687104578790e+00, 2.6525462944632925e+00, 2.9096884292910694e+00, 3.1681327493707792e+00, 3.4280254143563189e+00, 3.6895224813523542e+00, 3.9527914995987943e+00, 4.2180133803413131e+00, 4.4853846092140870e+00, 4.7551198880737857e+00, 5.0274553198842957e+00, 5.3026522869660511e+00, 5.5810022242153172e+00, 5.8628325617022545e+00, 6.1485142162283823e+00, 6.4384711663544172e+00, 6.7331928786770474e+00, 7.0332507130647253e+00, 7.3393200055543293e+00, 7.6522104625334553e+00, 7.9729090874349415e+00, 8.3026426739573083e+00, 8.6429721394539492e+00, 8.9959413381560331e+00, 9.3643250739262687e+00, 9.7520726523771355e+00, 1.0165179617422121e+01, 1.0613646047709890e+01, 1.1116891363846698e+01, 1.1725797919515925e+01}, + {-1.1807093040777294e+01, -1.1199565640216381e+01, -1.0697503453395814e+01, -1.0250126304140645e+01, -9.8380533797602858e+00, -9.4513043921191180e+00, -9.0838956733280174e+00, -8.7318857937825296e+00, -8.3925055567758680e+00, -8.0637153221240894e+00, -7.7439574806678753e+00, -7.4320079322856305e+00, -7.1268819366716176e+00, -6.8277717420599027e+00, -6.5340037424695643e+00, -6.2450081432878877e+00, -5.9602969222394462e+00, -5.6794474572664067e+00, -5.4020901259356995e+00, -5.1278987508656595e+00, -4.8565831248972122e+00, -4.5878830825516648e+00, -4.3215637389507622e+00, -4.0574116223471224e+00, -3.7952314990808915e+00, -3.5348437409765978e+00, -3.2760821218442313e+00, -3.0187919563650998e+00, -2.7628285142266278e+00, -2.5080556569501704e+00, -2.2543446558260460e+00, -2.0015731577016731e+00, -1.7496242717478425e+00, -1.4983857552446240e+00, -1.2477492802359769e+00, -9.9760976585826833e-01, -7.4786476344152575e-01, -4.9841388325234109e-01, -2.4915825309625725e-01, -0.0000000000000000e+00, 2.4915825309625725e-01, 4.9841388325234109e-01, 7.4786476344152575e-01, 9.9760976585826833e-01, 1.2477492802359769e+00, 1.4983857552446240e+00, 1.7496242717478425e+00, 2.0015731577016731e+00, 2.2543446558260460e+00, 2.5080556569501704e+00, 2.7628285142266278e+00, 3.0187919563650998e+00, 3.2760821218442313e+00, 3.5348437409765978e+00, 3.7952314990808915e+00, 4.0574116223471224e+00, 4.3215637389507622e+00, 4.5878830825516648e+00, 4.8565831248972122e+00, 5.1278987508656595e+00, 5.4020901259356995e+00, 5.6794474572664067e+00, 5.9602969222394462e+00, 6.2450081432878877e+00, 6.5340037424695643e+00, 6.8277717420599027e+00, 7.1268819366716176e+00, 7.4320079322856305e+00, 7.7439574806678753e+00, 8.0637153221240894e+00, 8.3925055567758680e+00, 8.7318857937825296e+00, 9.0838956733280174e+00, 9.4513043921191180e+00, 9.8380533797602858e+00, 1.0250126304140645e+01, 1.0697503453395814e+01, 1.1199565640216381e+01, 1.1807093040777294e+01}, + {-1.1887863560471148e+01, -1.1281694164989270e+01, -1.0780796472469154e+01, -1.0334491039538371e+01, -9.9234351145692425e+00, -9.5376679163020608e+00, -9.1712174787264829e+00, -8.8201501286610533e+00, -8.4817021873215737e+00, -8.1538381574634560e+00, -7.8350036783292891e+00, -7.5239772908068669e+00, -7.2197764697589237e+00, -6.9215953729258182e+00, -6.6287620808575998e+00, -6.3407083213299842e+00, -6.0569474734510278e+00, -5.7770582280615690e+00, -5.5006722123151564e+00, -5.2274644551006757e+00, -4.9571459285134285e+00, -4.6894576329528137e+00, -4.4241658477651837e+00, -4.1610582741258364e+00, -3.8999408693873892e+00, -3.6406352232272088e+00, -3.3829763625124016e+00, -3.1268108983731295e+00, -2.8719954485287333e+00, -2.6183952824717842e+00, -2.3658831480742251e+00, -2.1143382465070100e+00, -1.8636453287449284e+00, -1.6136938918510606e+00, -1.3643774570540068e+00, -1.1155929146033490e+00, -8.6723992270397532e-01, -6.1922034962756711e-01, -3.7143774948304431e-01, -1.2379686317313206e-01, 1.2379686317313206e-01, 3.7143774948304431e-01, 6.1922034962756711e-01, 8.6723992270397532e-01, 1.1155929146033490e+00, 1.3643774570540068e+00, 1.6136938918510606e+00, 1.8636453287449284e+00, 2.1143382465070100e+00, 2.3658831480742251e+00, 2.6183952824717842e+00, 2.8719954485287333e+00, 3.1268108983731295e+00, 3.3829763625124016e+00, 3.6406352232272088e+00, 3.8999408693873892e+00, 4.1610582741258364e+00, 4.4241658477651837e+00, 4.6894576329528137e+00, 4.9571459285134285e+00, 5.2274644551006757e+00, 5.5006722123151564e+00, 5.7770582280615690e+00, 6.0569474734510278e+00, 6.3407083213299842e+00, 6.6287620808575998e+00, 6.9215953729258182e+00, 7.2197764697589237e+00, 7.5239772908068669e+00, 7.8350036783292891e+00, 8.1538381574634560e+00, 8.4817021873215737e+00, 8.8201501286610533e+00, 9.1712174787264829e+00, 9.5376679163020608e+00, 9.9234351145692425e+00, 1.0334491039538371e+01, 1.0780796472469154e+01, 1.1281694164989270e+01, 1.1887863560471148e+01}, + {-1.1968119444868723e+01, -1.1363287494653905e+01, -1.0863536193428574e+01, -1.0418285423785731e+01, -1.0008229962827862e+01, -9.6234282602828909e+00, -9.2579198828492224e+00, -8.9077787978104048e+00, -8.5702467579780226e+00, -8.2432923404437446e+00, -7.9253643753426406e+00, -7.6152439941755770e+00, -7.3119508411483105e+00, -7.0146809405398773e+00, -6.7227640181091326e+00, -6.4356332834442265e+00, -6.1528034765082218e+00, -5.8738545599912273e+00, -5.5984193685789059e+00, -5.3261740939400637e+00, -5.0568308420977290e+00, -4.7901317317816865e+00, -4.5258441564113081e+00, -4.2637569369381021e+00, -4.0036771651776295e+00, -3.7454275882737633e+00, -3.4888444214602070e+00, -3.2337755028119282e+00, -2.9800787232025514e+00, -2.7276206792242430e+00, -2.4762755077735275e+00, -2.2259238693277426e+00, -1.9764520533164986e+00, -1.7277511839192137e+00, -1.4797165084468731e+00, -1.2322467534512360e+00, -9.8524353603723147e-01, -7.3861081967444187e-01, -4.9225440521533759e-01, -2.4608144890838049e-01, -0.0000000000000000e+00, 2.4608144890838049e-01, 4.9225440521533759e-01, 7.3861081967444187e-01, 9.8524353603723147e-01, 1.2322467534512360e+00, 1.4797165084468731e+00, 1.7277511839192137e+00, 1.9764520533164986e+00, 2.2259238693277426e+00, 2.4762755077735275e+00, 2.7276206792242430e+00, 2.9800787232025514e+00, 3.2337755028119282e+00, 3.4888444214602070e+00, 3.7454275882737633e+00, 4.0036771651776295e+00, 4.2637569369381021e+00, 4.5258441564113081e+00, 4.7901317317816865e+00, 5.0568308420977290e+00, 5.3261740939400637e+00, 5.5984193685789059e+00, 5.8738545599912273e+00, 6.1528034765082218e+00, 6.4356332834442265e+00, 6.7227640181091326e+00, 7.0146809405398773e+00, 7.3119508411483105e+00, 7.6152439941755770e+00, 7.9253643753426406e+00, 8.2432923404437446e+00, 8.5702467579780226e+00, 8.9077787978104048e+00, 9.2579198828492224e+00, 9.6234282602828909e+00, 1.0008229962827862e+01, 1.0418285423785731e+01, 1.0863536193428574e+01, 1.1363287494653905e+01, 1.1968119444868723e+01}, + {-1.2047870349469452e+01, -1.1444355851257512e+01, -1.0945733348554121e+01, -1.0501520679503271e+01, -1.0092449631556644e+01, -9.7085976169732788e+00, -9.3440155707490522e+00, -8.9947849881314195e+00, -8.6581529699601738e+00, -8.3320921014281222e+00, -8.0150543482026926e+00, -7.7058233840379780e+00, -7.4034209786511349e+00, -7.1070449818933454e+00, -6.8160267254566378e+00, -6.5298008622888712e+00, -6.2478834549069706e+00, -5.9698556991575886e+00, -5.6953515977146445e+00, -5.4240484642257165e+00, -5.1556594962091573e+00, -4.8899278863041147e+00, -4.6266220952405250e+00, -4.3655320142842475e+00, -4.1064658171809416e+00, -3.8492473525444271e+00, -3.5937139640934332e+00, -3.3397146526239907e+00, -3.0871085130972600e+00, -2.8357633947424321e+00, -2.5855547430080739e+00, -2.3363645905095152e+00, -2.0880806704972801e+00, -1.8405956313004481e+00, -1.5938063340319311e+00, -1.3476132188376881e+00, -1.1019197273183625e+00, -8.5663177059026308e-01, -6.1165723388752291e-01, -3.6690550971654429e-01, -1.2228705241518351e-01, 1.2228705241518351e-01, 3.6690550971654429e-01, 6.1165723388752291e-01, 8.5663177059026308e-01, 1.1019197273183625e+00, 1.3476132188376881e+00, 1.5938063340319311e+00, 1.8405956313004481e+00, 2.0880806704972801e+00, 2.3363645905095152e+00, 2.5855547430080739e+00, 2.8357633947424321e+00, 3.0871085130972600e+00, 3.3397146526239907e+00, 3.5937139640934332e+00, 3.8492473525444271e+00, 4.1064658171809416e+00, 4.3655320142842475e+00, 4.6266220952405250e+00, 4.8899278863041147e+00, 5.1556594962091573e+00, 5.4240484642257165e+00, 5.6953515977146445e+00, 5.9698556991575886e+00, 6.2478834549069706e+00, 6.5298008622888712e+00, 6.8160267254566378e+00, 7.1070449818933454e+00, 7.4034209786511349e+00, 7.7058233840379780e+00, 8.0150543482026926e+00, 8.3320921014281222e+00, 8.6581529699601738e+00, 8.9947849881314195e+00, 9.3440155707490522e+00, 9.7085976169732788e+00, 1.0092449631556644e+01, 1.0501520679503271e+01, 1.0945733348554121e+01, 1.1444355851257512e+01, 1.2047870349469452e+01}, + {-1.2127125632378913e+01, -1.1524909137013976e+01, -1.1027398329668573e+01, -1.0584207668672128e+01, -1.0176105446857637e+01, -9.7931877776907488e+00, -9.4295168046084115e+00, -9.0811814416185097e+00, -8.7454340566434574e+00, -8.4202511789832108e+00, -8.1040878565034831e+00, -7.7957302587642490e+00, -7.4942022390283798e+00, -7.1987034336195581e+00, -6.9085667427912707e+00, -6.6232282263685835e+00, -6.3422052331830958e+00, -6.0650801557222689e+00, -5.7914881274189227e+00, -5.5211075455728480e+00, -5.2536526594233770e+00, -4.9888676939643233e+00, -4.7265221335751297e+00, -4.4664068937399284e+00, -4.2083311812642945e+00, -3.9521198942311013e+00, -3.6976114493318364e+00, -3.4446559506485350e+00, -3.1931136334230796e+00, -2.9428535308492294e+00, -2.6937523228426583e+00, -2.4456933340503899e+00, -2.1985656547350549e+00, -1.9522633630987765e+00, -1.7066848314488341e+00, -1.4617321016098621e+00, -1.2173103173449662e+00, -9.7332720340140344e-01, -7.2969258225037825e-01, -4.8631792072343311e-01, -2.4311589961848629e-01, -0.0000000000000000e+00, 2.4311589961848629e-01, 4.8631792072343311e-01, 7.2969258225037825e-01, 9.7332720340140344e-01, 1.2173103173449662e+00, 1.4617321016098621e+00, 1.7066848314488341e+00, 1.9522633630987765e+00, 2.1985656547350549e+00, 2.4456933340503899e+00, 2.6937523228426583e+00, 2.9428535308492294e+00, 3.1931136334230796e+00, 3.4446559506485350e+00, 3.6976114493318364e+00, 3.9521198942311013e+00, 4.2083311812642945e+00, 4.4664068937399284e+00, 4.7265221335751297e+00, 4.9888676939643233e+00, 5.2536526594233770e+00, 5.5211075455728480e+00, 5.7914881274189227e+00, 6.0650801557222689e+00, 6.3422052331830958e+00, 6.6232282263685835e+00, 6.9085667427912707e+00, 7.1987034336195581e+00, 7.4942022390283798e+00, 7.7957302587642490e+00, 8.1040878565034831e+00, 8.4202511789832108e+00, 8.7454340566434574e+00, 9.0811814416185097e+00, 9.4295168046084115e+00, 9.7931877776907488e+00, 1.0176105446857637e+01, 1.0584207668672128e+01, 1.1027398329668573e+01, 1.1524909137013976e+01, 1.2127125632378913e+01}, + {-1.2205894366956139e+01, -1.1604956948103077e+01, -1.1108541203015454e+01, -1.0666356908585685e+01, -1.0259208370962089e+01, -9.8772101503410621e+00, -9.5144354431069669e+00, -9.1669804759729860e+00, -8.8321028054925428e+00, -8.5077828432020937e+00, -8.1924786677436181e+00, -7.8849788998338592e+00, -7.5843094360641796e+00, -7.2896716618750510e+00, -7.0004000104832143e+00, -6.7159319139391096e+00, -6.4357859730612450e+00, -6.1595457424759266e+00, -5.8868474512821898e+00, -5.6173705443855964e+00, -5.3508302854168104e+00, -5.0869718928011789e+00, -4.8255658337490095e+00, -4.5664040049460510e+00, -4.3092966007328037e+00, -4.0540695203033383e+00, -3.8005622017862843e+00, -3.5486257974651720e+00, -3.2981216238257258e+00, -3.0489198345947157e+00, -2.8008982758405363e+00, -2.5539414905028606e+00, -2.3079398460883205e+00, -2.0627887641978626e+00, -1.8183880343913310e+00, -1.5746411979031998e+00, -1.3314549890897636e+00, -1.0887388243534069e+00, -8.4640432975900237e-01, -6.0436489970992124e-01, -3.6253527994578344e-01, -1.2083116880501313e-01, 1.2083116880501313e-01, 3.6253527994578344e-01, 6.0436489970992124e-01, 8.4640432975900237e-01, 1.0887388243534069e+00, 1.3314549890897636e+00, 1.5746411979031998e+00, 1.8183880343913310e+00, 2.0627887641978626e+00, 2.3079398460883205e+00, 2.5539414905028606e+00, 2.8008982758405363e+00, 3.0489198345947157e+00, 3.2981216238257258e+00, 3.5486257974651720e+00, 3.8005622017862843e+00, 4.0540695203033383e+00, 4.3092966007328037e+00, 4.5664040049460510e+00, 4.8255658337490095e+00, 5.0869718928011789e+00, 5.3508302854168104e+00, 5.6173705443855964e+00, 5.8868474512821898e+00, 6.1595457424759266e+00, 6.4357859730612450e+00, 6.7159319139391096e+00, 7.0004000104832143e+00, 7.2896716618750510e+00, 7.5843094360641796e+00, 7.8849788998338592e+00, 8.1924786677436181e+00, 8.5077828432020937e+00, 8.8321028054925428e+00, 9.1669804759729860e+00, 9.5144354431069669e+00, 9.8772101503410621e+00, 1.0259208370962089e+01, 1.0666356908585685e+01, 1.1108541203015454e+01, 1.1604956948103077e+01, 1.2205894366956139e+01}, + {-1.2284185353778504e+01, -1.1684508587714936e+01, -1.1189171723313381e+01, -1.0747978586907845e+01, -1.0341769018312585e+01, -9.9606757765591638e+00, -9.5987829596674032e+00, -9.2521940040089010e+00, -8.9181715786909077e+00, -8.5946999176295051e+00, -8.2802400806274559e+00, -7.9735830966018995e+00, -7.6737568668958440e+00, -7.3799644903419361e+00, -7.0915418991761436e+00, -6.8079278647256025e+00, -6.5286422072422212e+00, -6.2532696108544226e+00, -5.9814473672099631e+00, -5.7128559348775809e+00, -5.4472115568012640e+00, -5.1842604083343016e+00, -4.9237739013081612e+00, -4.6655448734152234e+00, -4.4093844640660000e+00, -4.1551195285347458e+00, -3.9025904784769208e+00, -3.6516494632523195e+00, -3.4021588258868611e+00, -3.1539897819612150e+00, -2.9070212806051177e+00, -2.6611390150638674e+00, -2.4162345566678476e+00, -2.1722045909628105e+00, -1.9289502385999013e+00, -1.6863764465968691e+00, -1.4443914379551996e+00, -1.2029062094928866e+00, -9.6183406923470449e-01, -7.2109020587034223e-01, -4.8059128370529336e-01, -2.4025505723472676e-01, -0.0000000000000000e+00, 2.4025505723472676e-01, 4.8059128370529336e-01, 7.2109020587034223e-01, 9.6183406923470449e-01, 1.2029062094928866e+00, 1.4443914379551996e+00, 1.6863764465968691e+00, 1.9289502385999013e+00, 2.1722045909628105e+00, 2.4162345566678476e+00, 2.6611390150638674e+00, 2.9070212806051177e+00, 3.1539897819612150e+00, 3.4021588258868611e+00, 3.6516494632523195e+00, 3.9025904784769208e+00, 4.1551195285347458e+00, 4.4093844640660000e+00, 4.6655448734152234e+00, 4.9237739013081612e+00, 5.1842604083343016e+00, 5.4472115568012640e+00, 5.7128559348775809e+00, 5.9814473672099631e+00, 6.2532696108544226e+00, 6.5286422072422212e+00, 6.8079278647256025e+00, 7.0915418991761436e+00, 7.3799644903419361e+00, 7.6737568668958440e+00, 7.9735830966018995e+00, 8.2802400806274559e+00, 8.5946999176295051e+00, 8.9181715786909077e+00, 9.2521940040089010e+00, 9.5987829596674032e+00, 9.9606757765591638e+00, 1.0341769018312585e+01, 1.0747978586907845e+01, 1.1189171723313381e+01, 1.1684508587714936e+01, 1.2284185353778504e+01}, + {-1.2362007131968511e+01, -1.1763573078389516e+01, -1.1269299347041693e+01, -1.0829082575898250e+01, -1.0423797670745445e+01, -1.0043595347880535e+01, -9.6825704596576454e+00, -9.3368335519365662e+00, -9.0036523325638047e+00, -8.6810147998900291e+00, -8.3673849469719066e+00, -8.0615561695659022e+00, -7.7625583367306144e+00, -7.4695962264936551e+00, -7.1820072377109705e+00, -6.8992314496242599e+00, -6.6207898710143054e+00, -6.3462682846048741e+00, -6.0753050133032716e+00, -5.8075814973426141e+00, -5.5428149259789015e+00, -5.2807523972174923e+00, -5.0211662316993868e+00, -4.7638501705179523e+00, -4.5086162584922675e+00, -4.2552922649886131e+00, -4.0037195305892794e+00, -3.7537511542142386e+00, -3.5052504546692158e+00, -3.2580896550268070e+00, -3.0121487491227401e+00, -2.7673145177270055e+00, -2.5234796683078762e+00, -2.2805420772311842e+00, -2.0384041170786049e+00, -1.7969720547840342e+00, -1.5561555086656726e+00, -1.3158669543141910e+00, -1.0760212707898533e+00, -8.3653531976321294e-01, -5.9732755116498426e-01, -3.5831762963623587e-01, -1.1942607662410318e-01, 1.1942607662410318e-01, 3.5831762963623587e-01, 5.9732755116498426e-01, 8.3653531976321294e-01, 1.0760212707898533e+00, 1.3158669543141910e+00, 1.5561555086656726e+00, 1.7969720547840342e+00, 2.0384041170786049e+00, 2.2805420772311842e+00, 2.5234796683078762e+00, 2.7673145177270055e+00, 3.0121487491227401e+00, 3.2580896550268070e+00, 3.5052504546692158e+00, 3.7537511542142386e+00, 4.0037195305892794e+00, 4.2552922649886131e+00, 4.5086162584922675e+00, 4.7638501705179523e+00, 5.0211662316993868e+00, 5.2807523972174923e+00, 5.5428149259789015e+00, 5.8075814973426141e+00, 6.0753050133032716e+00, 6.3462682846048741e+00, 6.6207898710143054e+00, 6.8992314496242599e+00, 7.1820072377109705e+00, 7.4695962264936551e+00, 7.7625583367306144e+00, 8.0615561695659022e+00, 8.3673849469719066e+00, 8.6810147998900291e+00, 9.0036523325638047e+00, 9.3368335519365662e+00, 9.6825704596576454e+00, 1.0043595347880535e+01, 1.0423797670745445e+01, 1.0829082575898250e+01, 1.1269299347041693e+01, 1.1763573078389516e+01, 1.2362007131968511e+01}, + {-1.2439367989923680e+01, -1.1842159173697059e+01, -1.1348933245008068e+01, -1.0909678445859965e+01, -1.0505304291834085e+01, -1.0125979221008995e+01, -9.7658086966213720e+00, -9.4209102766018642e+00, -9.0885566358796162e+00, -8.7667394811116139e+00, -8.4539256923192720e+00, -8.1489109922424241e+00, -7.8507271820680931e+00, -7.5585806862536904e+00, -7.2718103393202060e+00, -6.9898574985414994e+00, -6.7122443318572111e+00, -6.4385576912861495e+00, -6.1684369014005451e+00, -5.9015643538974087e+00, -5.6376581532613121e+00, -5.3764662879277241e+00, -5.1177619537428889e+00, -4.8613397599750519e+00, -4.6070126197625800e+00, -4.3546091773629314e+00, -4.1039716607125998e+00, -3.8549540740709145e+00, -3.6074206648573135e+00, -3.3612446132027243e+00, -3.1163069035955786e+00, -2.8724953462701670e+00, -2.6297037223368069e+00, -2.3878310315742213e+00, -2.1467808256453083e+00, -1.9064606125144659e+00, -1.6667813202271460e+00, -1.4276568101012006e+00, -1.1890034308805355e+00, -9.5073960659419110e-01, -7.1278545180861597e-01, -4.7506240870319627e-01, -2.3749290097360490e-01, -0.0000000000000000e+00, 2.3749290097360490e-01, 4.7506240870319627e-01, 7.1278545180861597e-01, 9.5073960659419110e-01, 1.1890034308805355e+00, 1.4276568101012006e+00, 1.6667813202271460e+00, 1.9064606125144659e+00, 2.1467808256453083e+00, 2.3878310315742213e+00, 2.6297037223368069e+00, 2.8724953462701670e+00, 3.1163069035955786e+00, 3.3612446132027243e+00, 3.6074206648573135e+00, 3.8549540740709145e+00, 4.1039716607125998e+00, 4.3546091773629314e+00, 4.6070126197625800e+00, 4.8613397599750519e+00, 5.1177619537428889e+00, 5.3764662879277241e+00, 5.6376581532613121e+00, 5.9015643538974087e+00, 6.1684369014005451e+00, 6.4385576912861495e+00, 6.7122443318572111e+00, 6.9898574985414994e+00, 7.2718103393202060e+00, 7.5585806862536904e+00, 7.8507271820680931e+00, 8.1489109922424241e+00, 8.4539256923192720e+00, 8.7667394811116139e+00, 9.0885566358796162e+00, 9.4209102766018642e+00, 9.7658086966213720e+00, 1.0125979221008995e+01, 1.0505304291834085e+01, 1.0909678445859965e+01, 1.1348933245008068e+01, 1.1842159173697059e+01, 1.2439367989923680e+01}, + {-1.2516275975487387e+01, -1.1920275369301974e+01, -1.1428082314244874e+01, -1.0989775477860821e+01, -1.0586298540449153e+01, -1.0207837432241758e+01, -9.8485080876029141e+00, -9.5044349817531568e+00, -9.1728956871075304e+00, -8.8518855642291054e+00, -8.5398743353481130e+00, -8.2356600117533336e+00, -7.9382762925370942e+00, -7.6469312171655428e+00, -7.3609650262218116e+00, -7.0798203265112649e+00, -6.8030204171920579e+00, -6.5301531917714213e+00, -6.2608589484644162e+00, -5.9948210018972574e+00, -5.7317583424731948e+00, -5.4714198187320084e+00, -5.2135794701554339e+00, -4.9580327411502472e+00, -4.7045933784481448e+00, -4.4530908645538636e+00, -4.2033682759582804e+00, -3.9552804810525908e+00, -3.7086926119853119e+00, -3.4634787590926437e+00, -3.2195208473769141e+00, -2.9767076627641722e+00, -2.7349340022167890e+00, -2.4940999266938628e+00, -2.2541100997915855e+00, -2.0148731979134999e+00, -1.7763013802059482e+00, -1.5383098083876734e+00, -1.3008162081103343e+00, -1.0637404646882309e+00, -8.2700424699148045e-01, -5.9053065405312266e-01, -3.5424387953214642e-01, -1.1806888962751633e-01, 1.1806888962751633e-01, 3.5424387953214642e-01, 5.9053065405312266e-01, 8.2700424699148045e-01, 1.0637404646882309e+00, 1.3008162081103343e+00, 1.5383098083876734e+00, 1.7763013802059482e+00, 2.0148731979134999e+00, 2.2541100997915855e+00, 2.4940999266938628e+00, 2.7349340022167890e+00, 2.9767076627641722e+00, 3.2195208473769141e+00, 3.4634787590926437e+00, 3.7086926119853119e+00, 3.9552804810525908e+00, 4.2033682759582804e+00, 4.4530908645538636e+00, 4.7045933784481448e+00, 4.9580327411502472e+00, 5.2135794701554339e+00, 5.4714198187320084e+00, 5.7317583424731948e+00, 5.9948210018972574e+00, 6.2608589484644162e+00, 6.5301531917714213e+00, 6.8030204171920579e+00, 7.0798203265112649e+00, 7.3609650262218116e+00, 7.6469312171655428e+00, 7.9382762925370942e+00, 8.2356600117533336e+00, 8.5398743353481130e+00, 8.8518855642291054e+00, 9.1728956871075304e+00, 9.5044349817531568e+00, 9.8485080876029141e+00, 1.0207837432241758e+01, 1.0586298540449153e+01, 1.0989775477860821e+01, 1.1428082314244874e+01, 1.1920275369301974e+01, 1.2516275975487387e+01}, + {-1.2592738905595901e+01, -1.1997929913449418e+01, -1.1506755189277548e+01, -1.1069382675775751e+01, -1.0666789783587026e+01, -1.0289179711107796e+01, -9.9306787276273880e+00, -9.5874181334018580e+00, -9.2566803307032135e+00, -8.9364642812455379e+00, -8.6252425061665043e+00, -8.3218152682134434e+00, -8.0252181314463780e+00, -7.7346607201821760e+00, -7.4494846527302592e+00, -7.1691337582185994e+00, -6.8931324404171299e+00, -6.6210696079053228e+00, -6.3525865059800601e+00, -6.0873673452070678e+00, -5.8251319742404801e+00, -5.5656300731513921e+00, -5.3086364953650067e+00, -5.0539474894081309e+00, -4.8013776030542550e+00, -4.5507571227604720e+00, -4.3019299373155544e+00, -4.0547517407947415e+00, -3.8090885091914664e+00, -3.5648151994628399e+00, -3.3218146305539729e+00, -3.0799765142115443e+00, -2.8391966097343762e+00, -2.5993759817212956e+00, -2.3604203437138307e+00, -2.1222394736491395e+00, -1.8847466894257894e+00, -1.6478583747824140e+00, -1.4114935472024899e+00, -1.1755734607673940e+00, -9.4002123784514680e-01, -7.0476152427011995e-01, -4.6972016327466942e-01, -2.3482388390393241e-01, -0.0000000000000000e+00, 2.3482388390393241e-01, 4.6972016327466942e-01, 7.0476152427011995e-01, 9.4002123784514680e-01, 1.1755734607673940e+00, 1.4114935472024899e+00, 1.6478583747824140e+00, 1.8847466894257894e+00, 2.1222394736491395e+00, 2.3604203437138307e+00, 2.5993759817212956e+00, 2.8391966097343762e+00, 3.0799765142115443e+00, 3.3218146305539729e+00, 3.5648151994628399e+00, 3.8090885091914664e+00, 4.0547517407947415e+00, 4.3019299373155544e+00, 4.5507571227604720e+00, 4.8013776030542550e+00, 5.0539474894081309e+00, 5.3086364953650067e+00, 5.5656300731513921e+00, 5.8251319742404801e+00, 6.0873673452070678e+00, 6.3525865059800601e+00, 6.6210696079053228e+00, 6.8931324404171299e+00, 7.1691337582185994e+00, 7.4494846527302592e+00, 7.7346607201821760e+00, 8.0252181314463780e+00, 8.3218152682134434e+00, 8.6252425061665043e+00, 8.9364642812455379e+00, 9.2566803307032135e+00, 9.5874181334018580e+00, 9.9306787276273880e+00, 1.0289179711107796e+01, 1.0666789783587026e+01, 1.1069382675775751e+01, 1.1506755189277548e+01, 1.1997929913449418e+01, 1.2592738905595901e+01}, + {-1.2668764375434174e+01, -1.2075130816910921e+01, -1.1584960252804917e+01, -1.1148508777693781e+01, -1.0746787108514194e+01, -1.0370015493271170e+01, -1.0012330403392184e+01, -9.6698698743374543e+00, -9.3399210724883908e+00, -9.0204865095226339e+00, -8.7100414635651475e+00, -8.4073884130034546e+00, -8.1115647551404777e+00, -7.8217816701739293e+00, -7.5373821269924042e+00, -7.2578111510465870e+00, -6.9825942253568725e+00, -6.7113212484546603e+00, -6.4436343875167896e+00, -6.1792187234934586e+00, -5.9177949371442047e+00, -5.6591135131207473e+00, -5.4029500908349490e+00, -5.1491016937770269e+00, -4.8973836402140369e+00, -4.6476269884213890e+00, -4.3996764055654278e+00, -4.1533883754886318e+00, -3.9086296798928606e+00, -3.6652761017603779e+00, -3.4232113106647768e+00, -3.1823258978578806e+00, -2.9425165353484215e+00, -2.7036852380958849e+00, -2.4657387122776617e+00, -2.2285877756048471e+00, -1.9921468380503871e+00, -1.7563334332534348e+00, -1.5210677923813427e+00, -1.2862724534455954e+00, -1.0518719000409926e+00, -8.1779222425489551e-01, -5.8396080911088377e-01, -3.5030602639582364e-01, -1.1675694609164179e-01, 1.1675694609164179e-01, 3.5030602639582364e-01, 5.8396080911088377e-01, 8.1779222425489551e-01, 1.0518719000409926e+00, 1.2862724534455954e+00, 1.5210677923813427e+00, 1.7563334332534348e+00, 1.9921468380503871e+00, 2.2285877756048471e+00, 2.4657387122776617e+00, 2.7036852380958849e+00, 2.9425165353484215e+00, 3.1823258978578806e+00, 3.4232113106647768e+00, 3.6652761017603779e+00, 3.9086296798928606e+00, 4.1533883754886318e+00, 4.3996764055654278e+00, 4.6476269884213890e+00, 4.8973836402140369e+00, 5.1491016937770269e+00, 5.4029500908349490e+00, 5.6591135131207473e+00, 5.9177949371442047e+00, 6.1792187234934586e+00, 6.4436343875167896e+00, 6.7113212484546603e+00, 6.9825942253568725e+00, 7.2578111510465870e+00, 7.5373821269924042e+00, 7.8217816701739293e+00, 8.1115647551404777e+00, 8.4073884130034546e+00, 8.7100414635651475e+00, 9.0204865095226339e+00, 9.3399210724883908e+00, 9.6698698743374543e+00, 1.0012330403392184e+01, 1.0370015493271170e+01, 1.0746787108514194e+01, 1.1148508777693781e+01, 1.1584960252804917e+01, 1.2075130816910921e+01, 1.2668764375434174e+01}, + {-1.2744359767130547e+01, -1.2151885862422731e+01, -1.1662705645828531e+01, -1.1227162266730099e+01, -1.0826299334271541e+01, -1.0450353932747101e+01, -1.0093472606221523e+01, -9.7518000378530658e+00, -9.4226280941850682e+00, -9.1039627871662461e+00, -8.7942821113015697e+00, -8.4923907260054339e+00, -8.1973278312442819e+00, -7.9083061352456419e+00, -7.6246699314466770e+00, -7.3458654167536865e+00, -7.0714191292405717e+00, -6.8009219334794446e+00, -6.5340168945910211e+00, -6.2703899396887248e+00, -6.0097625569049269e+00, -5.7518860100246414e+00, -5.4965366980951300e+00, -5.2435123921335229e+00, -4.9926291522002995e+00, -4.7437187782456505e+00, -4.4966266840419751e+00, -4.2512101096067996e+00, -4.0073366067337117e+00, -3.7648827465709873e+00, -3.5237330089839838e+00, -3.2837788216598618e+00, -3.0449177232349895e+00, -2.8070526296277643e+00, -2.5700911865913141e+00, -2.3339451945166196e+00, -2.0985300939053997e+00, -1.8637645018342535e+00, -1.6295697912525116e+00, -1.3958697061759588e+00, -1.1625900068179993e+00, -9.2965813948535503e-01, -6.9700292669283159e-01, -4.6455427344836053e-01, -2.3224288604634152e-01, -0.0000000000000000e+00, 2.3224288604634152e-01, 4.6455427344836053e-01, 6.9700292669283159e-01, 9.2965813948535503e-01, 1.1625900068179993e+00, 1.3958697061759588e+00, 1.6295697912525116e+00, 1.8637645018342535e+00, 2.0985300939053997e+00, 2.3339451945166196e+00, 2.5700911865913141e+00, 2.8070526296277643e+00, 3.0449177232349895e+00, 3.2837788216598618e+00, 3.5237330089839838e+00, 3.7648827465709873e+00, 4.0073366067337117e+00, 4.2512101096067996e+00, 4.4966266840419751e+00, 4.7437187782456505e+00, 4.9926291522002995e+00, 5.2435123921335229e+00, 5.4965366980951300e+00, 5.7518860100246414e+00, 6.0097625569049269e+00, 6.2703899396887248e+00, 6.5340168945910211e+00, 6.8009219334794446e+00, 7.0714191292405717e+00, 7.3458654167536865e+00, 7.6246699314466770e+00, 7.9083061352456419e+00, 8.1973278312442819e+00, 8.4923907260054339e+00, 8.7942821113015697e+00, 9.1039627871662461e+00, 9.4226280941850682e+00, 9.7518000378530658e+00, 1.0093472606221523e+01, 1.0450353932747101e+01, 1.0826299334271541e+01, 1.1227162266730099e+01, 1.1662705645828531e+01, 1.2151885862422731e+01, 1.2744359767130547e+01}, + {-1.2819532258018480e+01, -1.2228202613648115e+01, -1.1739999277265277e+01, -1.1305351381280618e+01, -1.0905335022579179e+01, -1.0530203913474873e+01, -1.0174114544331893e+01, -9.8332181607332707e+00, -9.5048112671603402e+00, -9.1869033275673413e+00, -8.8779750134809063e+00, -8.5768331318717053e+00, -8.2825186558731350e+00, -7.9942457949462566e+00, -7.7113601420959172e+00, -7.4333090418794825e+00, -7.1596200643171857e+00, -6.8898850172400419e+00, -6.6237478409567272e+00, -6.3608952857640544e+00, -6.1010496237476017e+00, -5.8439628737731484e+00, -5.5894121696594157e+00, -5.3371960041051256e+00, -5.0871311519710600e+00, -4.8390501265746098e+00, -4.5927990585018197e+00, -4.3482359124910070e+00, -4.1052289771248800e+00, -3.8636555763680760e+00, -3.6234009627673571e+00, -3.3843573603426855e+00, -3.1464231315109763e+00, -2.9095020472812747e+00, -2.6735026437884462e+00, -2.4383376512469250e+00, -2.2039234837948438e+00, -1.9701797806022634e+00, -1.7370289901408089e+00, -1.5043959907356530e+00, -1.2722077415053921e+00, -1.0403929585875988e+00, -8.0888181218354049e-01, -5.7760564046232032e-01, -3.4649667676368101e-01, -1.1548778684603313e-01, 1.1548778684603313e-01, 3.4649667676368101e-01, 5.7760564046232032e-01, 8.0888181218354049e-01, 1.0403929585875988e+00, 1.2722077415053921e+00, 1.5043959907356530e+00, 1.7370289901408089e+00, 1.9701797806022634e+00, 2.2039234837948438e+00, 2.4383376512469250e+00, 2.6735026437884462e+00, 2.9095020472812747e+00, 3.1464231315109763e+00, 3.3843573603426855e+00, 3.6234009627673571e+00, 3.8636555763680760e+00, 4.1052289771248800e+00, 4.3482359124910070e+00, 4.5927990585018197e+00, 4.8390501265746098e+00, 5.0871311519710600e+00, 5.3371960041051256e+00, 5.5894121696594157e+00, 5.8439628737731484e+00, 6.1010496237476017e+00, 6.3608952857640544e+00, 6.6237478409567272e+00, 6.8898850172400419e+00, 7.1596200643171857e+00, 7.4333090418794825e+00, 7.7113601420959172e+00, 7.9942457949462566e+00, 8.2825186558731350e+00, 8.5768331318717053e+00, 8.8779750134809063e+00, 9.1869033275673413e+00, 9.5048112671603402e+00, 9.8332181607332707e+00, 1.0174114544331893e+01, 1.0530203913474873e+01, 1.0905335022579179e+01, 1.1305351381280618e+01, 1.1739999277265277e+01, 1.2228202613648115e+01, 1.2819532258018480e+01}, + {-1.2894288828491323e+01, -1.2304088423692580e+01, -1.1816848833075053e+01, -1.1383084124753704e+01, -1.0983902488179488e+01, -1.0609574060288383e+01, -1.0254265154452550e+01, -9.9141334955519440e+00, -9.5864801654334606e+00, -9.2693180331543115e+00, -8.9611304090936645e+00, -8.6607262153924776e+00, -8.3671481698791865e+00, -8.0796119574473497e+00, -7.7974644466766474e+00, -7.5201541069686444e+00, -7.2472095182038041e+00, -6.9782234097463292e+00, -6.7128405754384817e+00, -6.4507485669373850e+00, -6.1916704180836000e+00, -5.9353588800666905e+00, -5.6815917979923949e+00, -5.4301683618693133e+00, -5.1809060359441155e+00, -4.9336380202893313e+00, -4.6882111343374202e+00, -4.4444840380621056e+00, -4.2023257256606739e+00, -3.9616142408689083e+00, -3.7222355738045620e+00, -3.4840827074346534e+00, -3.2470547880671274e+00, -3.0110563991586603e+00, -2.7759969215550591e+00, -2.5417899662931847e+00, -2.3083528684815695e+00, -2.0756062326810416e+00, -1.8434735217321803e+00, -1.6118806822031735e+00, -1.3807558006205385e+00, -1.1500287854429532e+00, -9.1963107038107428e-01, -6.8949533518145145e-01, -4.5955524040186729e-01, -2.2974517302503578e-01, -0.0000000000000000e+00, 2.2974517302503578e-01, 4.5955524040186729e-01, 6.8949533518145145e-01, 9.1963107038107428e-01, 1.1500287854429532e+00, 1.3807558006205385e+00, 1.6118806822031735e+00, 1.8434735217321803e+00, 2.0756062326810416e+00, 2.3083528684815695e+00, 2.5417899662931847e+00, 2.7759969215550591e+00, 3.0110563991586603e+00, 3.2470547880671274e+00, 3.4840827074346534e+00, 3.7222355738045620e+00, 3.9616142408689083e+00, 4.2023257256606739e+00, 4.4444840380621056e+00, 4.6882111343374202e+00, 4.9336380202893313e+00, 5.1809060359441155e+00, 5.4301683618693133e+00, 5.6815917979923949e+00, 5.9353588800666905e+00, 6.1916704180836000e+00, 6.4507485669373850e+00, 6.7128405754384817e+00, 6.9782234097463292e+00, 7.2472095182038041e+00, 7.5201541069686444e+00, 7.7974644466766474e+00, 8.0796119574473497e+00, 8.3671481698791865e+00, 8.6607262153924776e+00, 8.9611304090936645e+00, 9.2693180331543115e+00, 9.5864801654334606e+00, 9.9141334955519440e+00, 1.0254265154452550e+01, 1.0609574060288383e+01, 1.0983902488179488e+01, 1.1383084124753704e+01, 1.1816848833075053e+01, 1.2304088423692580e+01, 1.2894288828491323e+01}, + {-1.2968636269474320e+01, -1.2379550443198964e+01, -1.1893261784933093e+01, -1.1460368274811241e+01, -1.1062009808653285e+01, -1.0688472749322155e+01, -1.0333933112841928e+01, -9.9945550223243256e+00, -9.6676440779928683e+00, -9.3512165084081822e+00, -9.0437582257661120e+00, -8.7440802360223131e+00, -8.4512269741988870e+00, -8.1644155757609358e+00, -7.8829941618009407e+00, -7.6064123046955778e+00, -7.3341995730571172e+00, -7.0659495970458304e+00, -6.8013080034124762e+00, -6.5399631244304128e+00, -6.2816387346344911e+00, -6.0260882959858302e+00, -5.7730903426736297e+00, -5.5224447390110498e+00, -5.2739696146779718e+00, -5.0274988314577831e+00, -4.7828798713474461e+00, -4.5399720618862149e+00, -4.2986450736710040e+00, -4.0587776392825550e+00, -3.8202564535947250e+00, -3.5829752236268817e+00, -3.3468338423962911e+00, -3.1117376661126466e+00, -2.8775968778776946e+00, -2.6443259240630739e+00, -2.4118430119268002e+00, -2.1800696589332400e+00, -1.9489302857683151e+00, -1.7183518462708216e+00, -1.4882634884931585e+00, -1.2585962419071162e+00, -1.0292827264188049e+00, -8.0025687937913981e-01, -5.7145369719413508e-01, -3.4280898846921665e-01, -1.1425913587653955e-01, 1.1425913587653955e-01, 3.4280898846921665e-01, 5.7145369719413508e-01, 8.0025687937913981e-01, 1.0292827264188049e+00, 1.2585962419071162e+00, 1.4882634884931585e+00, 1.7183518462708216e+00, 1.9489302857683151e+00, 2.1800696589332400e+00, 2.4118430119268002e+00, 2.6443259240630739e+00, 2.8775968778776946e+00, 3.1117376661126466e+00, 3.3468338423962911e+00, 3.5829752236268817e+00, 3.8202564535947250e+00, 4.0587776392825550e+00, 4.2986450736710040e+00, 4.5399720618862149e+00, 4.7828798713474461e+00, 5.0274988314577831e+00, 5.2739696146779718e+00, 5.5224447390110498e+00, 5.7730903426736297e+00, 6.0260882959858302e+00, 6.2816387346344911e+00, 6.5399631244304128e+00, 6.8013080034124762e+00, 7.0659495970458304e+00, 7.3341995730571172e+00, 7.6064123046955778e+00, 7.8829941618009407e+00, 8.1644155757609358e+00, 8.4512269741988870e+00, 8.7440802360223131e+00, 9.0437582257661120e+00, 9.3512165084081822e+00, 9.6676440779928683e+00, 9.9945550223243256e+00, 1.0333933112841928e+01, 1.0688472749322155e+01, 1.1062009808653285e+01, 1.1460368274811241e+01, 1.1893261784933093e+01, 1.2379550443198964e+01, 1.2968636269474320e+01}, + {-1.3042581189536424e+01, -1.2454595628047418e+01, -1.1969245398474266e+01, -1.1537211392148828e+01, -1.1139664833741461e+01, -1.0766908117887827e+01, -1.0413126845737839e+01, -1.0074491459554146e+01, -9.7483120204672815e+00, -9.4326080721882803e+00, -9.1258680927746667e+00, -8.8269051416209461e+00, -8.5347653443616345e+00, -8.2486672630612325e+00, -7.9679602491408312e+00, -7.6920949569654464e+00, -7.4206019236498832e+00, -7.1530756603397334e+00, -6.8891626070319019e+00, -6.6285518568795139e+00, -6.3709679051115460e+00, -6.1161649040299730e+00, -5.8639220558946130e+00, -5.6140398775862348e+00, -5.3663371416203249e+00, -5.1206483478982010e+00, -4.8768216162575175e+00, -4.6347169158093715e+00, -4.3942045661421210e+00, -4.1551639597063925e+00, -3.9174824654279452e+00, -3.6810544817710307e+00, -3.4457806137632216e+00, -3.2115669533719382e+00, -2.9783244464395575e+00, -2.7459683323916124e+00, -2.5144176453186349e+00, -2.2835947669364720e+00, -2.0534250234577174e+00, -1.8238363196378788e+00, -1.5947588042551295e+00, -1.3661245620886429e+00, -1.1378673281137517e+00, -9.0992222016050861e-01, -6.8222548670729899e-01, -4.5471426681985894e-01, -2.2732635951125563e-01, -0.0000000000000000e+00, 2.2732635951125563e-01, 4.5471426681985894e-01, 6.8222548670729899e-01, 9.0992222016050861e-01, 1.1378673281137517e+00, 1.3661245620886429e+00, 1.5947588042551295e+00, 1.8238363196378788e+00, 2.0534250234577174e+00, 2.2835947669364720e+00, 2.5144176453186349e+00, 2.7459683323916124e+00, 2.9783244464395575e+00, 3.2115669533719382e+00, 3.4457806137632216e+00, 3.6810544817710307e+00, 3.9174824654279452e+00, 4.1551639597063925e+00, 4.3942045661421210e+00, 4.6347169158093715e+00, 4.8768216162575175e+00, 5.1206483478982010e+00, 5.3663371416203249e+00, 5.6140398775862348e+00, 5.8639220558946130e+00, 6.1161649040299730e+00, 6.3709679051115460e+00, 6.6285518568795139e+00, 6.8891626070319019e+00, 7.1530756603397334e+00, 7.4206019236498832e+00, 7.6920949569654464e+00, 7.9679602491408312e+00, 8.2486672630612325e+00, 8.5347653443616345e+00, 8.8269051416209461e+00, 9.1258680927746667e+00, 9.4326080721882803e+00, 9.7483120204672815e+00, 1.0074491459554146e+01, 1.0413126845737839e+01, 1.0766908117887827e+01, 1.1139664833741461e+01, 1.1537211392148828e+01, 1.1969245398474266e+01, 1.2454595628047418e+01, 1.3042581189536424e+01}, + {-1.3116130021662876e+01, -1.2529230746683540e+01, -1.2044806741134924e+01, -1.1613620828842913e+01, -1.1216875194202160e+01, -1.0844888073853586e+01, -1.0491854539276538e+01, -1.0153951274713688e+01, -9.8284927461917118e+00, -9.5135017694124251e+00, -9.2074693533717600e+00, -8.9092105814595968e+00, -8.6177732442147459e+00, -8.3323773071700593e+00, -8.0523733307197105e+00, -7.7772130310612386e+00, -7.5064278944277563e+00, -7.2396132940083531e+00, -6.9764164642851814e+00, -6.7165272404965179e+00, -6.4596708195551207e+00, -6.2056020247183090e+00, -5.9541007064117260e+00, -5.7049680135255354e+00, -5.4580233400707856e+00, -5.2131018018189597e+00, -4.9700521331667717e+00, -4.7287349203529301e+00, -4.4890211062169945e+00, -4.2507907159031859e+00, -4.0139317636282685e+00, -3.7783393087968626e+00, -3.5439146360273117e+00, -3.3105645385243054e+00, -3.0782006880468189e+00, -2.8467390777247825e+00, -2.6160995263623885e+00, -2.3862052347697795e+00, -2.1569823861931283e+00, -1.9283597841455022e+00, -1.7002685219383502e+00, -1.4726416790227095e+00, -1.2454140399065079e+00, -1.0185218319476799e+00, -7.9190247875401665e-01, -5.6549436626674887e-01, -3.3923661887888523e-01, -1.1306888315145193e-01, 1.1306888315145193e-01, 3.3923661887888523e-01, 5.6549436626674887e-01, 7.9190247875401665e-01, 1.0185218319476799e+00, 1.2454140399065079e+00, 1.4726416790227095e+00, 1.7002685219383502e+00, 1.9283597841455022e+00, 2.1569823861931283e+00, 2.3862052347697795e+00, 2.6160995263623885e+00, 2.8467390777247825e+00, 3.0782006880468189e+00, 3.3105645385243054e+00, 3.5439146360273117e+00, 3.7783393087968626e+00, 4.0139317636282685e+00, 4.2507907159031859e+00, 4.4890211062169945e+00, 4.7287349203529301e+00, 4.9700521331667717e+00, 5.2131018018189597e+00, 5.4580233400707856e+00, 5.7049680135255354e+00, 5.9541007064117260e+00, 6.2056020247183090e+00, 6.4596708195551207e+00, 6.7165272404965179e+00, 6.9764164642851814e+00, 7.2396132940083531e+00, 7.5064278944277563e+00, 7.7772130310612386e+00, 8.0523733307197105e+00, 8.3323773071700593e+00, 8.6177732442147459e+00, 8.9092105814595968e+00, 9.2074693533717600e+00, 9.5135017694124251e+00, 9.8284927461917118e+00, 1.0153951274713688e+01, 1.0491854539276538e+01, 1.0844888073853586e+01, 1.1216875194202160e+01, 1.1613620828842913e+01, 1.2044806741134924e+01, 1.2529230746683540e+01, 1.3116130021662876e+01}, + {-1.3189289029708117e+01, -1.2603462387096409e+01, -1.2119952689615966e+01, -1.1689603736290559e+01, -1.1293648310231410e+01, -1.0922420304556775e+01, -1.0570124148913189e+01, -1.0232942694191875e+01, -9.9081947567061555e+00, -9.5939063821323529e+00, -9.2885710764670684e+00, -8.9910059185401376e+00, -8.7002603389157791e+00, -8.4155556842608696e+00, -8.1362437033700719e+00, -7.8617771549009925e+00, -7.5916884556157704e+00, -7.3255738226210259e+00, -7.0630812669681537e+00, -6.8039013480672903e+00, -6.5477599464293741e+00, -6.2944125378566032e+00, -6.0436396020679171e+00, -5.7952429005012469e+00, -5.5490424284915560e+00, -5.3048738966808706e+00, -5.0625866320797561e+00, -4.8220418150442850e+00, -4.5831109874666334e+00, -4.3456747816687633e+00, -4.1096218301890062e+00, -3.8748478248038931e+00, -3.6412546993987251e+00, -3.4087499161671784e+00, -3.1772458384281856e+00, -2.9466591763501873e+00, -2.7169104942556110e+00, -2.4879237700815029e+00, -2.2596259991006340e+00, -2.0319468352407690e+00, -1.8048182643389761e+00, -1.5781743044796297e+00, -1.3519507292254074e+00, -1.1260848100881036e+00, -9.0051507502248329e-01, -6.7518108007869271e-01, -4.5002319163025301e-01, -2.2498237681566594e-01, -0.0000000000000000e+00, 2.2498237681566594e-01, 4.5002319163025301e-01, 6.7518108007869271e-01, 9.0051507502248329e-01, 1.1260848100881036e+00, 1.3519507292254074e+00, 1.5781743044796297e+00, 1.8048182643389761e+00, 2.0319468352407690e+00, 2.2596259991006340e+00, 2.4879237700815029e+00, 2.7169104942556110e+00, 2.9466591763501873e+00, 3.1772458384281856e+00, 3.4087499161671784e+00, 3.6412546993987251e+00, 3.8748478248038931e+00, 4.1096218301890062e+00, 4.3456747816687633e+00, 4.5831109874666334e+00, 4.8220418150442850e+00, 5.0625866320797561e+00, 5.3048738966808706e+00, 5.5490424284915560e+00, 5.7952429005012469e+00, 6.0436396020679171e+00, 6.2944125378566032e+00, 6.5477599464293741e+00, 6.8039013480672903e+00, 7.0630812669681537e+00, 7.3255738226210259e+00, 7.5916884556157704e+00, 7.8617771549009925e+00, 8.1362437033700719e+00, 8.4155556842608696e+00, 8.7002603389157791e+00, 8.9910059185401376e+00, 9.2885710764670684e+00, 9.5939063821323529e+00, 9.9081947567061555e+00, 1.0232942694191875e+01, 1.0570124148913189e+01, 1.0922420304556775e+01, 1.1293648310231410e+01, 1.1689603736290559e+01, 1.2119952689615966e+01, 1.2603462387096409e+01, 1.3189289029708117e+01}, + {-1.3262064314547260e+01, -1.2677296963466635e+01, -1.2194689936989255e+01, -1.1765167072765909e+01, -1.1369991399473138e+01, -1.0999512285277628e+01, -1.0647943408373985e+01, -1.0311473712742933e+01, -9.9874263117220838e+00, -9.6738304400421331e+00, -9.3691820677047506e+00, -9.0723002412708205e+00, -8.7822360072393444e+00, -8.4982120718321887e+00, -8.2195813524123764e+00, -7.9457976314642735e+00, -7.6763942384382915e+00, -7.4109682169993913e+00, -7.1491683376448565e+00, -6.8906858668688686e+00, -6.6352473515597925e+00, -6.3826089025647779e+00, -6.1325516109861775e+00, -5.8848778323693072e+00, -5.6394081442881152e+00, -5.3959788324149320e+00, -5.1544397956688064e+00, -4.9146527868415708e+00, -4.6764899241060425e+00, -4.4398324229806452e+00, -4.2045695090093798e+00, -3.9705974795569130e+00, -3.7378188893809927e+00, -3.5061418395049322e+00, -3.2754793527162449e+00, -3.0457488220163000e+00, -2.8168715207266257e+00, -2.5887721648595683e+00, -2.3613785198892869e+00, -2.1346210452930161e+00, -1.9084325712330619e+00, -1.6827480025638228e+00, -1.4575040460115227e+00, -1.2326389569154106e+00, -1.0080923023599291e+00, -7.8380473788493388e-01, -5.5971779524889242e-01, -3.3577367894853466e-01, -1.1191506937570589e-01, 1.1191506937570589e-01, 3.3577367894853466e-01, 5.5971779524889242e-01, 7.8380473788493388e-01, 1.0080923023599291e+00, 1.2326389569154106e+00, 1.4575040460115227e+00, 1.6827480025638228e+00, 1.9084325712330619e+00, 2.1346210452930161e+00, 2.3613785198892869e+00, 2.5887721648595683e+00, 2.8168715207266257e+00, 3.0457488220163000e+00, 3.2754793527162449e+00, 3.5061418395049322e+00, 3.7378188893809927e+00, 3.9705974795569130e+00, 4.2045695090093798e+00, 4.4398324229806452e+00, 4.6764899241060425e+00, 4.9146527868415708e+00, 5.1544397956688064e+00, 5.3959788324149320e+00, 5.6394081442881152e+00, 5.8848778323693072e+00, 6.1325516109861775e+00, 6.3826089025647779e+00, 6.6352473515597925e+00, 6.8906858668688686e+00, 7.1491683376448565e+00, 7.4109682169993913e+00, 7.6763942384382915e+00, 7.9457976314642735e+00, 8.2195813524123764e+00, 8.4982120718321887e+00, 8.7822360072393444e+00, 9.0723002412708205e+00, 9.3691820677047506e+00, 9.6738304400421331e+00, 9.9874263117220838e+00, 1.0311473712742933e+01, 1.0647943408373985e+01, 1.0999512285277628e+01, 1.1369991399473138e+01, 1.1765167072765909e+01, 1.2194689936989255e+01, 1.2677296963466635e+01, 1.3262064314547260e+01}, + {-1.3334461819943153e+01, -1.2750740722503373e+01, -1.2269024999467902e+01, -1.1840317610615624e+01, -1.1445911484642805e+01, -1.1076171287300262e+01, -1.0725319838167971e+01, -1.0389552102465858e+01, -1.0066195438589224e+01, -9.7532822304545537e+00, -9.4493108799743251e+00, -9.1531023745391185e+00, -8.8637093532419815e+00, -8.5803558609974342e+00, -8.3023959646056102e+00, -8.0292844524423987e+00, -7.7605555495112331e+00, -7.4958071093975249e+00, -7.2346886456654547e+00, -6.9768921155793651e+00, -6.7221447159938794e+00, -6.4702031761523404e+00, -6.2208491815292408e+00, -5.9738856642890008e+00, -5.7291337661713966e+00, -5.4864303291169465e+00, -5.2456258043992712e+00, -5.0065824967968044e+00, -4.7691730793126910e+00, -4.5332793281004458e+00, -4.2987910379219327e+00, -4.0656050865933535e+00, -3.8336246231287601e+00, -3.6027583591447181e+00, -3.3729199468884627e+00, -3.1440274302474247e+00, -2.9160027574766345e+00, -2.6887713462813925e+00, -2.4622616934204693e+00, -2.2364050222293588e+00, -2.0111349624646375e+00, -1.7863872576859270e+00, -1.5620994960576213e+00, -1.3382108609965631e+00, -1.1146618985362737e+00, -8.9139429864040043e-01, -6.6835068799126329e-01, -4.4547443201433412e-01, -2.2270944408436802e-01, -0.0000000000000000e+00, 2.2270944408436802e-01, 4.4547443201433412e-01, 6.6835068799126329e-01, 8.9139429864040043e-01, 1.1146618985362737e+00, 1.3382108609965631e+00, 1.5620994960576213e+00, 1.7863872576859270e+00, 2.0111349624646375e+00, 2.2364050222293588e+00, 2.4622616934204693e+00, 2.6887713462813925e+00, 2.9160027574766345e+00, 3.1440274302474247e+00, 3.3729199468884627e+00, 3.6027583591447181e+00, 3.8336246231287601e+00, 4.0656050865933535e+00, 4.2987910379219327e+00, 4.5332793281004458e+00, 4.7691730793126910e+00, 5.0065824967968044e+00, 5.2456258043992712e+00, 5.4864303291169465e+00, 5.7291337661713966e+00, 5.9738856642890008e+00, 6.2208491815292408e+00, 6.4702031761523404e+00, 6.7221447159938794e+00, 6.9768921155793651e+00, 7.2346886456654547e+00, 7.4958071093975249e+00, 7.7605555495112331e+00, 8.0292844524423987e+00, 8.3023959646056102e+00, 8.5803558609974342e+00, 8.8637093532419815e+00, 9.1531023745391185e+00, 9.4493108799743251e+00, 9.7532822304545537e+00, 1.0066195438589224e+01, 1.0389552102465858e+01, 1.0725319838167971e+01, 1.1076171287300262e+01, 1.1445911484642805e+01, 1.1840317610615624e+01, 1.2269024999467902e+01, 1.2750740722503373e+01, 1.3334461819943153e+01}, + {-1.3406487338144908e+01, -1.2823799749487808e+01, -1.2342964222859672e+01, -1.1915061943114164e+01, -1.1521415400787030e+01, -1.1152404385585125e+01, -1.0802260753684713e+01, -1.0467185421342810e+01, -1.0144509941292846e+01, -9.8322698077779673e+00, -9.5289658233901147e+00, -9.2334208902191612e+00, -8.9446892173254735e+00, -8.6619961681345181e+00, -8.3846969404162657e+00, -8.1122473111627915e+00, -7.8441823844608196e+00, -7.5801008078574874e+00, -7.3196528223045343e+00, -7.0625310602488653e+00, -6.8084633528587952e+00, -6.5572070319215392e+00, -6.3085443611121343e+00, -6.0622788326143020e+00, -5.8182321352035169e+00, -5.5762416493299236e+00, -5.3361583601383602e+00, -5.0978451050891360e+00, -4.8611750917912095e+00, -4.6260306357871555e+00, -4.3923020786826834e+00, -4.1598868551310302e+00, -3.9286886834276706e+00, -3.6986168593184914e+00, -3.4695856364185889e+00, -3.2415136796310131e+00, -3.0143235803311552e+00, -2.7879414239819891e+00, -2.5622964023726080e+00, -2.3373204639068783e+00, -2.1129479963711879e+00, -1.8891155374270083e+00, -1.6657615087415094e+00, -1.4428259702159327e+00, -1.2202503912189531e+00, -9.9797743609810530e-01, -7.7595076154014564e-01, -5.5411482359161690e-01, -3.3241469234223181e-01, -1.1079587242243949e-01, 1.1079587242243949e-01, 3.3241469234223181e-01, 5.5411482359161690e-01, 7.7595076154014564e-01, 9.9797743609810530e-01, 1.2202503912189531e+00, 1.4428259702159327e+00, 1.6657615087415094e+00, 1.8891155374270083e+00, 2.1129479963711879e+00, 2.3373204639068783e+00, 2.5622964023726080e+00, 2.7879414239819891e+00, 3.0143235803311552e+00, 3.2415136796310131e+00, 3.4695856364185889e+00, 3.6986168593184914e+00, 3.9286886834276706e+00, 4.1598868551310302e+00, 4.3923020786826834e+00, 4.6260306357871555e+00, 4.8611750917912095e+00, 5.0978451050891360e+00, 5.3361583601383602e+00, 5.5762416493299236e+00, 5.8182321352035169e+00, 6.0622788326143020e+00, 6.3085443611121343e+00, 6.5572070319215392e+00, 6.8084633528587952e+00, 7.0625310602488653e+00, 7.3196528223045343e+00, 7.5801008078574874e+00, 7.8441823844608196e+00, 8.1122473111627915e+00, 8.3846969404162657e+00, 8.6619961681345181e+00, 8.9446892173254735e+00, 9.2334208902191612e+00, 9.5289658233901147e+00, 9.8322698077779673e+00, 1.0144509941292846e+01, 1.0467185421342810e+01, 1.0802260753684713e+01, 1.1152404385585125e+01, 1.1521415400787030e+01, 1.1915061943114164e+01, 1.2342964222859672e+01, 1.2823799749487808e+01, 1.3406487338144908e+01}, + {-1.3478146515232797e+01, -1.2896479974039561e+01, -1.2416513788721415e+01, -1.1989406490998284e+01, -1.1596509802200323e+01, -1.1228218466075560e+01, -1.0878773272902121e+01, -1.0544381021362536e+01, -1.0222377409009630e+01, -9.9108010025237636e+00, -9.6081549747716188e+00, -9.3132641171485986e+00, -9.0251841867360021e+00, -8.7431418459354120e+00, -8.4664934056489916e+00, -8.1946956148339627e+00, -7.9272844408189824e+00, -7.6638593097942502e+00, -7.4040711750779735e+00, -7.1476133293942068e+00, -6.8942142232839023e+00, -6.6436317759717189e+00, -6.3956488139470400e+00, -6.1500693736430252e+00, -5.9067156746204947e+00, -5.6654256190158065e+00, -5.4260507083580034e+00, -5.1884542945483902e+00, -4.9525101007153634e+00, -4.7181009617643239e+00, -4.4851177450803661e+00, -4.2534584199474237e+00, -4.0230272504840583e+00, -3.7937340917372753e+00, -3.5654937723650511e+00, -3.3382255503269591e+00, -3.1118526303762444e+00, -2.8863017340447339e+00, -2.6615027143383925e+00, -2.4373882085955381e+00, -2.2138933239623526e+00, -1.9909553507579980e+00, -1.7685134996706828e+00, -1.5465086592745161e+00, -1.3248831708071216e+00, -1.1035806175170297e+00, -8.8254562619156474e-01, -6.6172367872096116e-01, -4.4106093175132588e-01, -2.2050404263430215e-01, -0.0000000000000000e+00, 2.2050404263430215e-01, 4.4106093175132588e-01, 6.6172367872096116e-01, 8.8254562619156474e-01, 1.1035806175170297e+00, 1.3248831708071216e+00, 1.5465086592745161e+00, 1.7685134996706828e+00, 1.9909553507579980e+00, 2.2138933239623526e+00, 2.4373882085955381e+00, 2.6615027143383925e+00, 2.8863017340447339e+00, 3.1118526303762444e+00, 3.3382255503269591e+00, 3.5654937723650511e+00, 3.7937340917372753e+00, 4.0230272504840583e+00, 4.2534584199474237e+00, 4.4851177450803661e+00, 4.7181009617643239e+00, 4.9525101007153634e+00, 5.1884542945483902e+00, 5.4260507083580034e+00, 5.6654256190158065e+00, 5.9067156746204947e+00, 6.1500693736430252e+00, 6.3956488139470400e+00, 6.6436317759717189e+00, 6.8942142232839023e+00, 7.1476133293942068e+00, 7.4040711750779735e+00, 7.6638593097942502e+00, 7.9272844408189824e+00, 8.1946956148339627e+00, 8.4664934056489916e+00, 8.7431418459354120e+00, 9.0251841867360021e+00, 9.3132641171485986e+00, 9.6081549747716188e+00, 9.9108010025237636e+00, 1.0222377409009630e+01, 1.0544381021362536e+01, 1.0878773272902121e+01, 1.1228218466075560e+01, 1.1596509802200323e+01, 1.1989406490998284e+01, 1.2416513788721415e+01, 1.2896479974039561e+01, 1.3478146515232797e+01}, + {-1.3549444856223355e+01, -1.2968787175621387e+01, -1.2489679720231214e+01, -1.2063357508698903e+01, -1.1671201169018351e+01, -1.1303620232659483e+01, -1.0954864323727046e+01, -1.0621146056253156e+01, -1.0299805224248269e+01, -9.9888834298724642e+00, -9.6868861866549612e+00, -9.3926401506071997e+00, -9.1052026055338082e+00, -8.8238014938930043e+00, -8.5477942224789647e+00, -8.2766384961541863e+00, -8.0098711302417200e+00, -7.7470923148599020e+00, -7.4879537012921364e+00, -7.2321492282755919e+00, -6.9794079514507139e+00, -6.7294883630724422e+00, -6.4821738377935736e+00, -6.2372689413028590e+00, -5.9945964085177108e+00, -5.7539946473095069e+00, -5.5153156590327264e+00, -5.2784232927787453e+00, -5.0431917691668700e+00, -4.8095044235715418e+00, -4.5772526293071110e+00, -4.3463348693861139e+00, -4.1166559316947993e+00, -3.8881262072644476e+00, -3.6606610751014688e+00, -3.4341803600244734e+00, -3.2086078523280142e+00, -2.9838708799890519e+00, -2.7598999256576846e+00, -2.5366282819075883e+00, -2.3139917392243752e+00, -2.0919283020285095e+00, -1.8703779286996216e+00, -1.6492822921192409e+00, -1.4285845577012724e+00, -1.2082291762513240e+00, -9.8816168930097070e-01, -7.6832854481204382e-01, -5.4867692134760149e-01, -3.2915455896704260e-01, -1.0970959522807897e-01, 1.0970959522807897e-01, 3.2915455896704260e-01, 5.4867692134760149e-01, 7.6832854481204382e-01, 9.8816168930097070e-01, 1.2082291762513240e+00, 1.4285845577012724e+00, 1.6492822921192409e+00, 1.8703779286996216e+00, 2.0919283020285095e+00, 2.3139917392243752e+00, 2.5366282819075883e+00, 2.7598999256576846e+00, 2.9838708799890519e+00, 3.2086078523280142e+00, 3.4341803600244734e+00, 3.6606610751014688e+00, 3.8881262072644476e+00, 4.1166559316947993e+00, 4.3463348693861139e+00, 4.5772526293071110e+00, 4.8095044235715418e+00, 5.0431917691668700e+00, 5.2784232927787453e+00, 5.5153156590327264e+00, 5.7539946473095069e+00, 5.9945964085177108e+00, 6.2372689413028590e+00, 6.4821738377935736e+00, 6.7294883630724422e+00, 6.9794079514507139e+00, 7.2321492282755919e+00, 7.4879537012921364e+00, 7.7470923148599020e+00, 8.0098711302417200e+00, 8.2766384961541863e+00, 8.5477942224789647e+00, 8.8238014938930043e+00, 9.1052026055338082e+00, 9.3926401506071997e+00, 9.6868861866549612e+00, 9.9888834298724642e+00, 1.0299805224248269e+01, 1.0621146056253156e+01, 1.0954864323727046e+01, 1.1303620232659483e+01, 1.1671201169018351e+01, 1.2063357508698903e+01, 1.2489679720231214e+01, 1.2968787175621387e+01, 1.3549444856223355e+01}, + {-1.3620387729947742e+01, -1.3040726988796493e+01, -1.2562467887793943e+01, -1.2136921090287251e+01, -1.1745495813506075e+01, -1.1378616213805854e+01, -1.1030540650989794e+01, -1.0697487488847003e+01, -1.0376800570599057e+01, -1.0066524497824579e+01, -9.7651670958633421e+00, -9.4715568613271639e+00, -9.1847525840655759e+00, -8.9039834682597192e+00, -8.6286079999230569e+00, -8.3580848243237309e+00, -8.0919515900932844e+00, -7.8298092371332197e+00, -7.5713101008750368e+00, -7.3161487524084921e+00, -7.0640548388279587e+00, -6.8147874116676039e+00, -6.5681303797817083e+00, -6.3238888238470219e+00, -6.0818859794767741e+00, -5.8419607451405371e+00, -5.6039656063250805e+00, -5.3677648929830539e+00, -5.1332333061803963e+00, -4.9002546639192408e+00, -4.6687208267203344e+00, -4.4385307716320357e+00, -4.2095897895522105e+00, -3.9818087855776474e+00, -3.7551036658752275e+00, -3.5293947975507334e+00, -3.3046065303600929e+00, -3.0806667710024973e+00, -2.8575066022592246e+00, -2.6350599404753994e+00, -2.4132632258847226e+00, -2.1920551410961067e+00, -1.9713763537322730e+00, -1.7511692797619354e+00, -1.5313778645213059e+00, -1.3119473787947484e+00, -1.0928242276321787e+00, -8.7395576983320977e-01, -6.5529014623361903e-01, -4.3677611509527065e-01, -2.1836289303147782e-01, -0.0000000000000000e+00, 2.1836289303147782e-01, 4.3677611509527065e-01, 6.5529014623361903e-01, 8.7395576983320977e-01, 1.0928242276321787e+00, 1.3119473787947484e+00, 1.5313778645213059e+00, 1.7511692797619354e+00, 1.9713763537322730e+00, 2.1920551410961067e+00, 2.4132632258847226e+00, 2.6350599404753994e+00, 2.8575066022592246e+00, 3.0806667710024973e+00, 3.3046065303600929e+00, 3.5293947975507334e+00, 3.7551036658752275e+00, 3.9818087855776474e+00, 4.2095897895522105e+00, 4.4385307716320357e+00, 4.6687208267203344e+00, 4.9002546639192408e+00, 5.1332333061803963e+00, 5.3677648929830539e+00, 5.6039656063250805e+00, 5.8419607451405371e+00, 6.0818859794767741e+00, 6.3238888238470219e+00, 6.5681303797817083e+00, 6.8147874116676039e+00, 7.0640548388279587e+00, 7.3161487524084921e+00, 7.5713101008750368e+00, 7.8298092371332197e+00, 8.0919515900932844e+00, 8.3580848243237309e+00, 8.6286079999230569e+00, 8.9039834682597192e+00, 9.1847525840655759e+00, 9.4715568613271639e+00, 9.7651670958633421e+00, 1.0066524497824579e+01, 1.0376800570599057e+01, 1.0697487488847003e+01, 1.1030540650989794e+01, 1.1378616213805854e+01, 1.1745495813506075e+01, 1.2136921090287251e+01, 1.2562467887793943e+01, 1.3040726988796493e+01, 1.3620387729947742e+01}, + {-1.3690980373715535e+01, -1.3112304908251922e+01, -1.2634884014394832e+01, -1.2210103175151124e+01, -1.1819399886057777e+01, -1.1453212768894272e+01, -1.1105808823112232e+01, -1.0773412098098593e+01, -1.0453370440115185e+01, -1.0143731414960465e+01, -9.8430051316625278e+00, -9.5500219040630885e+00, -9.2638420079694495e+00, -8.9836958915100507e+00, -8.7089431037842626e+00, -8.4390432154976232e+00, -8.1735346944358760e+00, -7.9120192166772831e+00, -7.6541497885353431e+00, -7.3996216003602537e+00, -7.1481648776449447e+00, -6.8995392180679298e+00, -6.6535290513692580e+00, -6.4099399596264091e+00, -6.1685956652061904e+00, -5.9293355428005707e+00, -5.6920125471434968e+00, -5.4564914735798906e+00, -5.2226474874947222e+00, -4.9903648726555803e+00, -4.7595359591142765e+00, -4.5300601993847316e+00, -4.3018433678250396e+00, -4.0747968629734785e+00, -3.8488370963629586e+00, -3.6238849543164635e+00, -3.3998653215923187e+00, -3.1767066576408891e+00, -2.9543406177575795e+00, -2.7327017126497148e+00, -2.5117270009375883e+00, -2.2913558099291085e+00, -2.0715294806793496e+00, -1.8521911338989445e+00, -1.6332854537309136e+00, -1.4147584867915231e+00, -1.1965574541809449e+00, -9.7863057442477308e-01, -7.6092689551645798e-01, -5.4339613440036172e-01, -3.2598852237076159e-01, -1.0865465496797615e-01, 1.0865465496797615e-01, 3.2598852237076159e-01, 5.4339613440036172e-01, 7.6092689551645798e-01, 9.7863057442477308e-01, 1.1965574541809449e+00, 1.4147584867915231e+00, 1.6332854537309136e+00, 1.8521911338989445e+00, 2.0715294806793496e+00, 2.2913558099291085e+00, 2.5117270009375883e+00, 2.7327017126497148e+00, 2.9543406177575795e+00, 3.1767066576408891e+00, 3.3998653215923187e+00, 3.6238849543164635e+00, 3.8488370963629586e+00, 4.0747968629734785e+00, 4.3018433678250396e+00, 4.5300601993847316e+00, 4.7595359591142765e+00, 4.9903648726555803e+00, 5.2226474874947222e+00, 5.4564914735798906e+00, 5.6920125471434968e+00, 5.9293355428005707e+00, 6.1685956652061904e+00, 6.4099399596264091e+00, 6.6535290513692580e+00, 6.8995392180679298e+00, 7.1481648776449447e+00, 7.3996216003602537e+00, 7.6541497885353431e+00, 7.9120192166772831e+00, 8.1735346944358760e+00, 8.4390432154976232e+00, 8.7089431037842626e+00, 8.9836958915100507e+00, 9.2638420079694495e+00, 9.5500219040630885e+00, 9.8430051316625278e+00, 1.0143731414960465e+01, 1.0453370440115185e+01, 1.0773412098098593e+01, 1.1105808823112232e+01, 1.1453212768894272e+01, 1.1819399886057777e+01, 1.2210103175151124e+01, 1.2634884014394832e+01, 1.3112304908251922e+01, 1.3690980373715535e+01}, + {-1.3761227897775342e+01, -1.3183526293600599e+01, -1.2706933680714704e+01, -1.2282909553416038e+01, -1.1892919380924928e+01, -1.1527416094254811e+01, -1.1180675238467860e+01, -1.0848926485775479e+01, -1.0529521640346799e+01, -1.0220511197831829e+01, -9.9204075235256379e+00, -9.6280427257475036e+00, -9.3424785467404909e+00, -9.0629466613367704e+00, -8.7888076661013130e+00, -8.5195220427131719e+00, -8.2546290644616640e+00, -7.9937311305046359e+00, -7.7364819052916909e+00, -7.4825771858770791e+00, -7.2317477636524030e+00, -6.9837537698848138e+00, -6.7383801424910441e+00, -6.4954329519998799e+00, -6.2547363942623555e+00, -6.0161303065289111e+00, -5.7794680986505123e+00, -5.5446150166977928e+00, -5.3114466751017559e+00, -5.0798478074449882e+00, -4.8497111966094790e+00, -4.6209367530474879e+00, -4.3934307161440911e+00, -4.1671049584554103e+00, -3.9418763763764075e+00, -3.7176663537665213e+00, -3.4944002874250444e+00, -3.2720071651989722e+00, -3.0504191890280565e+00, -2.8295714364637563e+00, -2.6094015552011851e+00, -2.3898494859824693e+00, -2.1708572099022447e+00, -1.9523685166996116e+00, -1.7343287910777165e+00, -1.5166848144697649e+00, -1.2993845799825059e+00, -1.0823771185059250e+00, -8.6561233418988326e-01, -6.4904084766152925e-01, -4.3261384549707677e-01, -2.1628293457217421e-01, -0.0000000000000000e+00, 2.1628293457217421e-01, 4.3261384549707677e-01, 6.4904084766152925e-01, 8.6561233418988326e-01, 1.0823771185059250e+00, 1.2993845799825059e+00, 1.5166848144697649e+00, 1.7343287910777165e+00, 1.9523685166996116e+00, 2.1708572099022447e+00, 2.3898494859824693e+00, 2.6094015552011851e+00, 2.8295714364637563e+00, 3.0504191890280565e+00, 3.2720071651989722e+00, 3.4944002874250444e+00, 3.7176663537665213e+00, 3.9418763763764075e+00, 4.1671049584554103e+00, 4.3934307161440911e+00, 4.6209367530474879e+00, 4.8497111966094790e+00, 5.0798478074449882e+00, 5.3114466751017559e+00, 5.5446150166977928e+00, 5.7794680986505123e+00, 6.0161303065289111e+00, 6.2547363942623555e+00, 6.4954329519998799e+00, 6.7383801424910441e+00, 6.9837537698848138e+00, 7.2317477636524030e+00, 7.4825771858770791e+00, 7.7364819052916909e+00, 7.9937311305046359e+00, 8.2546290644616640e+00, 8.5195220427131719e+00, 8.7888076661013130e+00, 9.0629466613367704e+00, 9.3424785467404909e+00, 9.6280427257475036e+00, 9.9204075235256379e+00, 1.0220511197831829e+01, 1.0529521640346799e+01, 1.0848926485775479e+01, 1.1180675238467860e+01, 1.1527416094254811e+01, 1.1892919380924928e+01, 1.2282909553416038e+01, 1.2706933680714704e+01, 1.3183526293600599e+01, 1.3761227897775342e+01}, + {-1.3831135289582965e+01, -1.3254396373973801e+01, -1.2778622330019754e+01, -1.2355345871125120e+01, -1.1966060141686793e+01, -1.1601232228934139e+01, -1.1255146131451047e+01, -1.0924037082840369e+01, -1.0605260801047601e+01, -1.0296870678005966e+01, -9.9973813085297891e+00, -9.7056265732561915e+00, -9.4206696618824566e+00, -9.1417434592085591e+00, -8.8682095941331820e+00, -8.5995294453241531e+00, -8.3352430784012270e+00, -8.0749536029866285e+00, -7.8183153294116643e+00, -7.5650246493836404e+00, -7.3148129082162541e+00, -7.0674407587544215e+00, -6.8226936349524259e+00, -6.5803780834395011e+00, -6.3403187609122504e+00, -6.1023559541821202e+00, -5.8663435147929848e+00, -5.6321471256242530e+00, -5.3996428356774224e+00, -5.1687158132495581e+00, -4.9392592782592839e+00, -4.7111735825401517e+00, -4.4843654131098756e+00, -4.2587470982328570e+00, -4.0342359998584794e+00, -3.8107539789883282e+00, -3.5882269228863879e+00, -3.3665843249351557e+00, -3.1457589094612213e+00, -2.9256862950849976e+00, -2.7063046911512725e+00, -2.4875546226165683e+00, -2.2693786794419482e+00, -2.0517212870941761e+00, -1.8345284952160181e+00, -1.6177477819054702e+00, -1.4013278713576325e+00, -1.1852185628827800e+00, -9.6937056952866862e-01, -7.5373536471122926e-01, -5.3826503540107018e-01, -3.2291214052800010e-01, -1.0762957335551564e-01, 1.0762957335551564e-01, 3.2291214052800010e-01, 5.3826503540107018e-01, 7.5373536471122926e-01, 9.6937056952866862e-01, 1.1852185628827800e+00, 1.4013278713576325e+00, 1.6177477819054702e+00, 1.8345284952160181e+00, 2.0517212870941761e+00, 2.2693786794419482e+00, 2.4875546226165683e+00, 2.7063046911512725e+00, 2.9256862950849976e+00, 3.1457589094612213e+00, 3.3665843249351557e+00, 3.5882269228863879e+00, 3.8107539789883282e+00, 4.0342359998584794e+00, 4.2587470982328570e+00, 4.4843654131098756e+00, 4.7111735825401517e+00, 4.9392592782592839e+00, 5.1687158132495581e+00, 5.3996428356774224e+00, 5.6321471256242530e+00, 5.8663435147929848e+00, 6.1023559541821202e+00, 6.3403187609122504e+00, 6.5803780834395011e+00, 6.8226936349524259e+00, 7.0674407587544215e+00, 7.3148129082162541e+00, 7.5650246493836404e+00, 7.8183153294116643e+00, 8.0749536029866285e+00, 8.3352430784012270e+00, 8.5995294453241531e+00, 8.8682095941331820e+00, 9.1417434592085591e+00, 9.4206696618824566e+00, 9.7056265732561915e+00, 9.9973813085297891e+00, 1.0296870678005966e+01, 1.0605260801047601e+01, 1.0924037082840369e+01, 1.1255146131451047e+01, 1.1601232228934139e+01, 1.1966060141686793e+01, 1.2355345871125120e+01, 1.2778622330019754e+01, 1.3254396373973801e+01, 1.3831135289582965e+01}, + {-1.3900707417887173e+01, -1.3324920252415142e+01, -1.2849955272837832e+01, -1.2427417635190753e+01, -1.2038827866477725e+01, -1.1674667060202870e+01, -1.1329227578271460e+01, -1.0998750155541702e+01, -1.0680594380572309e+01, -1.0372816508782414e+01, -1.0073933338405658e+01, -9.7827805008057851e+00, -9.4984226146699928e+00, -9.2200937585148388e+00, -8.9471565789061032e+00, -8.6790733379711611e+00, -8.4153848809401453e+00, -8.1556950157409371e+00, -7.8996586867968652e+00, -7.6469728688944967e+00, -7.3973694497863685e+00, -7.1506095923972852e+00, -6.9064792151159047e+00, -6.6647853288831929e+00, -6.4253530391943388e+00, -6.1880230700488541e+00, -5.9526497019202820e+00, -5.7190990412807672e+00, -5.4872475579716511e+00, -5.2569808406969596e+00, -5.0281925314641187e+00, -4.8007834078342349e+00, -4.5746605880295625e+00, -4.3497368387482860e+00, -4.1259299692968714e+00, -3.9031622986173096e+00, -3.6813601841446331e+00, -3.4604536033170050e+00, -3.2403757800798094e+00, -3.0210628499554302e+00, -2.8024535582518539e+00, -2.5844889868023952e+00, -2.3671123053017529e+00, -2.1502685438583309e+00, -1.9339043838414955e+00, -1.7179679644825636e+00, -1.5024087030036999e+00, -1.2871771263105225e+00, -1.0722247125008730e+00, -8.5750374062088575e-01, -6.4296714724579429e-01, -4.2856838858126434e-01, -2.1426130687493608e-01, -0.0000000000000000e+00, 2.1426130687493608e-01, 4.2856838858126434e-01, 6.4296714724579429e-01, 8.5750374062088575e-01, 1.0722247125008730e+00, 1.2871771263105225e+00, 1.5024087030036999e+00, 1.7179679644825636e+00, 1.9339043838414955e+00, 2.1502685438583309e+00, 2.3671123053017529e+00, 2.5844889868023952e+00, 2.8024535582518539e+00, 3.0210628499554302e+00, 3.2403757800798094e+00, 3.4604536033170050e+00, 3.6813601841446331e+00, 3.9031622986173096e+00, 4.1259299692968714e+00, 4.3497368387482860e+00, 4.5746605880295625e+00, 4.8007834078342349e+00, 5.0281925314641187e+00, 5.2569808406969596e+00, 5.4872475579716511e+00, 5.7190990412807672e+00, 5.9526497019202820e+00, 6.1880230700488541e+00, 6.4253530391943388e+00, 6.6647853288831929e+00, 6.9064792151159047e+00, 7.1506095923972852e+00, 7.3973694497863685e+00, 7.6469728688944967e+00, 7.8996586867968652e+00, 8.1556950157409371e+00, 8.4153848809401453e+00, 8.6790733379711611e+00, 8.9471565789061032e+00, 9.2200937585148388e+00, 9.4984226146699928e+00, 9.7827805008057851e+00, 1.0073933338405658e+01, 1.0372816508782414e+01, 1.0680594380572309e+01, 1.0998750155541702e+01, 1.1329227578271460e+01, 1.1674667060202870e+01, 1.2038827866477725e+01, 1.2427417635190753e+01, 1.2849955272837832e+01, 1.3324920252415142e+01, 1.3900707417887173e+01}, + {-1.3969949036642459e+01, -1.3395102910086411e+01, -1.2920937691432538e+01, -1.2499130218130038e+01, -1.2111228112984248e+01, -1.1747726328818176e+01, -1.1402925502488745e+01, -1.1073071811228770e+01, -1.0755528671982248e+01, -1.0448355171600436e+01, -1.0150070286259611e+01, -9.8595113770046634e+00, -9.5757444735437325e+00, -9.2980048323218245e+00, -9.0256561033487941e+00, -8.7581614191156962e+00, -8.4950623921731907e+00, -8.2359635170287859e+00, -7.9805203608479554e+00, -7.7284304703735840e+00, -7.4794262647792982e+00, -7.2332694060552951e+00, -6.9897462859257979e+00, -6.7486643683832410e+00, -6.5098491962299123e+00, -6.2731419188661652e+00, -6.0383972335511160e+00, -5.8054816577895725e+00, -5.5742720692284102e+00, -5.3446544634117208e+00, -5.1165228902768884e+00, -4.8897785383006882e+00, -4.6643289413814166e+00, -4.4400872883391642e+00, -4.2169718186716345e+00, -3.9949052911662122e+00, -3.7738145143243407e+00, -3.5536299294390266e+00, -3.3342852386840143e+00, -3.1157170718023619e+00, -2.8978646859830590e+00, -2.6806696943332091e+00, -2.4640758190263061e+00, -2.2480286657622290e+00, -2.0324755166339639e+00, -1.8173651388771286e+00, -1.6026476072949805e+00, -1.3882741384147259e+00, -1.1741969346494687e+00, -9.6036903692102105e-01, -7.4674418434770939e-01, -5.3327667972273107e-01, -3.1992125960608508e-01, -1.0663296792943616e-01, 1.0663296792943616e-01, 3.1992125960608508e-01, 5.3327667972273107e-01, 7.4674418434770939e-01, 9.6036903692102105e-01, 1.1741969346494687e+00, 1.3882741384147259e+00, 1.6026476072949805e+00, 1.8173651388771286e+00, 2.0324755166339639e+00, 2.2480286657622290e+00, 2.4640758190263061e+00, 2.6806696943332091e+00, 2.8978646859830590e+00, 3.1157170718023619e+00, 3.3342852386840143e+00, 3.5536299294390266e+00, 3.7738145143243407e+00, 3.9949052911662122e+00, 4.2169718186716345e+00, 4.4400872883391642e+00, 4.6643289413814166e+00, 4.8897785383006882e+00, 5.1165228902768884e+00, 5.3446544634117208e+00, 5.5742720692284102e+00, 5.8054816577895725e+00, 6.0383972335511160e+00, 6.2731419188661652e+00, 6.5098491962299123e+00, 6.7486643683832410e+00, 6.9897462859257979e+00, 7.2332694060552951e+00, 7.4794262647792982e+00, 7.7284304703735840e+00, 7.9805203608479554e+00, 8.2359635170287859e+00, 8.4950623921731907e+00, 8.7581614191156962e+00, 9.0256561033487941e+00, 9.2980048323218245e+00, 9.5757444735437325e+00, 9.8595113770046634e+00, 1.0150070286259611e+01, 1.0448355171600436e+01, 1.0755528671982248e+01, 1.1073071811228770e+01, 1.1402925502488745e+01, 1.1747726328818176e+01, 1.2111228112984248e+01, 1.2499130218130038e+01, 1.2920937691432538e+01, 1.3395102910086411e+01, 1.3969949036642459e+01}, + {-1.4038864788757728e+01, -1.3464949210295044e+01, -1.2991574644085651e+01, -1.2570488862595592e+01, -1.2183266303224141e+01, -1.1820415634054809e+01, -1.1476245680301457e+01, -1.1147008003906418e+01, -1.0830069808875091e+01, -1.0523492982154455e+01, -1.0225798652986768e+01, -9.9358258915767603e+00, -9.6526421211592019e+00, -9.3754837607621955e+00, -9.1037154500398181e+00, -8.8368011791635279e+00, -8.5742833161234948e+00, -8.3157670306912532e+00, -8.0609085018410500e+00, -7.8094058375754942e+00, -7.5609919779111072e+00, -7.3154290733448306e+00, -7.0725039783127066e+00, -6.8320245990954787e+00, -6.5938169048330693e+00, -6.3577224590892367e+00, -6.1235963643451115e+00, -5.8913055371925065e+00, -5.6607272507011190e+00, -5.4317478943805018e+00, -5.2042619126759186e+00, -4.9781708909532618e+00, -4.7533827640966910e+00, -4.5298111276324908e+00, -4.3073746350430024e+00, -4.0859964678941409e+00, -3.8656038677524993e+00, -3.6461277207507310e+00, -3.4275021871760831e+00, -3.2096643696850733e+00, -2.9925540147475451e+00, -2.7761132427418982e+00, -2.5602863027962388e+00, -2.3450193490255717e+00, -2.1302602352750175e+00, -1.9159583258608970e+00, -1.7020643201191179e+00, -1.4885300888347839e+00, -1.2753085208470012e+00, -1.0623533783056693e+00, -8.4961915920820152e-01, -6.3706096596817285e-01, -4.2463437886846966e-01, -2.1229533333143397e-01, -0.0000000000000000e+00, 2.1229533333143397e-01, 4.2463437886846966e-01, 6.3706096596817285e-01, 8.4961915920820152e-01, 1.0623533783056693e+00, 1.2753085208470012e+00, 1.4885300888347839e+00, 1.7020643201191179e+00, 1.9159583258608970e+00, 2.1302602352750175e+00, 2.3450193490255717e+00, 2.5602863027962388e+00, 2.7761132427418982e+00, 2.9925540147475451e+00, 3.2096643696850733e+00, 3.4275021871760831e+00, 3.6461277207507310e+00, 3.8656038677524993e+00, 4.0859964678941409e+00, 4.3073746350430024e+00, 4.5298111276324908e+00, 4.7533827640966910e+00, 4.9781708909532618e+00, 5.2042619126759186e+00, 5.4317478943805018e+00, 5.6607272507011190e+00, 5.8913055371925065e+00, 6.1235963643451115e+00, 6.3577224590892367e+00, 6.5938169048330693e+00, 6.8320245990954787e+00, 7.0725039783127066e+00, 7.3154290733448306e+00, 7.5609919779111072e+00, 7.8094058375754942e+00, 8.0609085018410500e+00, 8.3157670306912532e+00, 8.5742833161234948e+00, 8.8368011791635279e+00, 9.1037154500398181e+00, 9.3754837607621955e+00, 9.6526421211592019e+00, 9.9358258915767603e+00, 1.0225798652986768e+01, 1.0523492982154455e+01, 1.0830069808875091e+01, 1.1147008003906418e+01, 1.1476245680301457e+01, 1.1820415634054809e+01, 1.2183266303224141e+01, 1.2570488862595592e+01, 1.2991574644085651e+01, 1.3464949210295044e+01, 1.4038864788757728e+01}, + {-1.4107459209689143e+01, -1.3534463902352346e+01, -1.3061871069197858e+01, -1.2641498685712268e+01, -1.2254947728119026e+01, -1.1892740438516830e+01, -1.1549193745603484e+01, -1.1220564539543394e+01, -1.0904223770953831e+01, -1.0598236096233554e+01, -1.0301124773392132e+01, -1.0011730561776583e+01, -9.7291222611091452e+00, -9.4525374380792577e+00, -9.1813417085894020e+00, -8.9149999082012474e+00, -8.6530551488522143e+00, -8.3951132646519024e+00, -8.1408310358446965e+00, -7.8899071213998058e+00, -7.6420749720138357e+00, -7.3970972165620390e+00, -7.1547611620163289e+00, -6.9148751466506351e+00, -6.6772655554639746e+00, -6.4417743554625506e+00, -6.2082570433307618e+00, -5.9765809233777674e+00, -5.7466236523236125e+00, -5.5182720014163928e+00, -5.2914207968757996e+00, -5.0659720076635653e+00, -4.8418339557415173e+00, -4.6189206287614857e+00, -4.3971510788768189e+00, -4.1764488943211937e+00, -3.9567417327500811e+00, -3.7379609072207938e+00, -3.5200410172016268e+00, -3.3029196182276346e+00, -3.0865369248200669e+00, -2.8708355421046665e+00, -2.6557602222368328e+00, -2.4412576422971846e+00, -2.2272762007812905e+00, -2.0137658301898180e+00, -1.8006778235437944e+00, -1.5879646729152568e+00, -1.3755799182849759e+00, -1.1634780052233955e+00, -9.5161415004400396e-01, -7.3994421120471532e-01, -5.2842456583606134e-01, -3.1701199035803573e-01, -1.0566354421255454e-01, 1.0566354421255454e-01, 3.1701199035803573e-01, 5.2842456583606134e-01, 7.3994421120471532e-01, 9.5161415004400396e-01, 1.1634780052233955e+00, 1.3755799182849759e+00, 1.5879646729152568e+00, 1.8006778235437944e+00, 2.0137658301898180e+00, 2.2272762007812905e+00, 2.4412576422971846e+00, 2.6557602222368328e+00, 2.8708355421046665e+00, 3.0865369248200669e+00, 3.3029196182276346e+00, 3.5200410172016268e+00, 3.7379609072207938e+00, 3.9567417327500811e+00, 4.1764488943211937e+00, 4.3971510788768189e+00, 4.6189206287614857e+00, 4.8418339557415173e+00, 5.0659720076635653e+00, 5.2914207968757996e+00, 5.5182720014163928e+00, 5.7466236523236125e+00, 5.9765809233777674e+00, 6.2082570433307618e+00, 6.4417743554625506e+00, 6.6772655554639746e+00, 6.9148751466506351e+00, 7.1547611620163289e+00, 7.3970972165620390e+00, 7.6420749720138357e+00, 7.8899071213998058e+00, 8.1408310358446965e+00, 8.3951132646519024e+00, 8.6530551488522143e+00, 8.9149999082012474e+00, 9.1813417085894020e+00, 9.4525374380792577e+00, 9.7291222611091452e+00, 1.0011730561776583e+01, 1.0301124773392132e+01, 1.0598236096233554e+01, 1.0904223770953831e+01, 1.1220564539543394e+01, 1.1549193745603484e+01, 1.1892740438516830e+01, 1.2254947728119026e+01, 1.2641498685712268e+01, 1.3061871069197858e+01, 1.3534463902352346e+01, 1.4107459209689143e+01}, + {-1.4175736730885069e+01, -1.3603651625271072e+01, -1.3131831789217085e+01, -1.2712164683229908e+01, -1.2326277551871243e+01, -1.1964706072741592e+01, -1.1621775194820279e+01, -1.1293747081147552e+01, -1.0977996389349029e+01, -1.0672590515300062e+01, -1.0376054822035842e+01, -1.0087231738512564e+01, -9.8051914243374672e+00, -9.5291725793451221e+00, -9.2585417826765291e+00, -8.9927647033681737e+00, -8.7313851861824325e+00, -8.4740097190111463e+00, -8.2202956732045873e+00, -7.9699422487875475e+00, -7.7226833973667368e+00, -7.4782822164736231e+00, -7.2365264558624682e+00, -6.9972248759462685e+00, -6.7602042675666434e+00, -6.5253069909368815e+00, -6.2923889264375843e+00, -6.0613177552660416e+00, -5.8319715065921489e+00, -5.6042373217821275e+00, -5.3780103967408355e+00, -5.1531930714178591e+00, -4.9296940416745816e+00, -4.7074276734866194e+00, -4.4863134031967471e+00, -4.2662752104856114e+00, -4.0472411530744239e+00, -3.8291429540521795e+00, -3.6119156342329615e+00, -3.3954971831747680e+00, -3.1798282634899460e+00, -2.9648519438950705e+00, -2.7505134571206762e+00, -2.5367599793568107e+00, -2.3235404283709329e+00, -2.1108052778175836e+00, -1.8985063855784825e+00, -1.6865968342381339e+00, -1.4750307820226600e+00, -1.2637633227153910e+00, -1.0527503532175146e+00, -8.4194844755040910e-01, -6.3131473620181966e-01, -4.2080678980376768e-01, -2.1038250619832910e-01, -0.0000000000000000e+00, 2.1038250619832910e-01, 4.2080678980376768e-01, 6.3131473620181966e-01, 8.4194844755040910e-01, 1.0527503532175146e+00, 1.2637633227153910e+00, 1.4750307820226600e+00, 1.6865968342381339e+00, 1.8985063855784825e+00, 2.1108052778175836e+00, 2.3235404283709329e+00, 2.5367599793568107e+00, 2.7505134571206762e+00, 2.9648519438950705e+00, 3.1798282634899460e+00, 3.3954971831747680e+00, 3.6119156342329615e+00, 3.8291429540521795e+00, 4.0472411530744239e+00, 4.2662752104856114e+00, 4.4863134031967471e+00, 4.7074276734866194e+00, 4.9296940416745816e+00, 5.1531930714178591e+00, 5.3780103967408355e+00, 5.6042373217821275e+00, 5.8319715065921489e+00, 6.0613177552660416e+00, 6.2923889264375843e+00, 6.5253069909368815e+00, 6.7602042675666434e+00, 6.9972248759462685e+00, 7.2365264558624682e+00, 7.4782822164736231e+00, 7.7226833973667368e+00, 7.9699422487875475e+00, 8.2202956732045873e+00, 8.4740097190111463e+00, 8.7313851861824325e+00, 8.9927647033681737e+00, 9.2585417826765291e+00, 9.5291725793451221e+00, 9.8051914243374672e+00, 1.0087231738512564e+01, 1.0376054822035842e+01, 1.0672590515300062e+01, 1.0977996389349029e+01, 1.1293747081147552e+01, 1.1621775194820279e+01, 1.1964706072741592e+01, 1.2326277551871243e+01, 1.2712164683229908e+01, 1.3131831789217085e+01, 1.3603651625271072e+01, 1.4175736730885069e+01}, + {-1.4243701683090396e+01, -1.3672516911310485e+01, -1.3201461514403192e+01, -1.2782491733501539e+01, -1.2397260816155137e+01, -1.2036317739606817e+01, -1.1693995391536458e+01, -1.1366561153620273e+01, -1.1051393351707578e+01, -1.0746562091821255e+01, -1.0450594818817532e+01, -1.0162335612194752e+01, -9.8808559752619285e+00, -9.6053957268710537e+00, -9.3353223967607271e+00, -9.0701024758844149e+00, -8.8092805310594660e+00, -8.5524636937560086e+00, -8.2993099166213113e+00, -8.0495189311868405e+00, -7.8028251805712348e+00, -7.5589922216241447e+00, -7.3178082375274442e+00, -7.0790824013949303e+00, -6.8426419003295491e+00, -6.6083294779732258e+00, -6.3760013883766673e+00, -6.1455256793035486e+00, -5.9167807417097054e+00, -5.6896540760274723e+00, -5.4640412363607487e+00, -5.2398449216799987e+00, -5.0169741892502993e+00, -4.7953437702964461e+00, -4.5748734716450743e+00, -4.3554876500322477e+00, -4.1371147481089601e+00, -3.9196868830532363e+00, -3.7031394802088755e+00, -3.4874109453955420e+00, -3.2724423705327612e+00, -3.0581772680375412e+00, -2.8445613301276866e+00, -2.6315422097183796e+00, -2.4190693200603040e+00, -2.2070936506509247e+00, -1.9955675972702900e+00, -1.7844448042599628e+00, -1.5736800173872914e+00, -1.3632289458242499e+00, -1.1530481319262951e+00, -9.4309482762671593e-01, -7.3332687636947402e-01, -5.2370259959160714e-01, -3.1418068683720984e-01, -1.0472008864073033e-01, 1.0472008864073033e-01, 3.1418068683720984e-01, 5.2370259959160714e-01, 7.3332687636947402e-01, 9.4309482762671593e-01, 1.1530481319262951e+00, 1.3632289458242499e+00, 1.5736800173872914e+00, 1.7844448042599628e+00, 1.9955675972702900e+00, 2.2070936506509247e+00, 2.4190693200603040e+00, 2.6315422097183796e+00, 2.8445613301276866e+00, 3.0581772680375412e+00, 3.2724423705327612e+00, 3.4874109453955420e+00, 3.7031394802088755e+00, 3.9196868830532363e+00, 4.1371147481089601e+00, 4.3554876500322477e+00, 4.5748734716450743e+00, 4.7953437702964461e+00, 5.0169741892502993e+00, 5.2398449216799987e+00, 5.4640412363607487e+00, 5.6896540760274723e+00, 5.9167807417097054e+00, 6.1455256793035486e+00, 6.3760013883766673e+00, 6.6083294779732258e+00, 6.8426419003295491e+00, 7.0790824013949303e+00, 7.3178082375274442e+00, 7.5589922216241447e+00, 7.8028251805712348e+00, 8.0495189311868405e+00, 8.2993099166213113e+00, 8.5524636937560086e+00, 8.8092805310594660e+00, 9.0701024758844149e+00, 9.3353223967607271e+00, 9.6053957268710537e+00, 9.8808559752619285e+00, 1.0162335612194752e+01, 1.0450594818817532e+01, 1.0746562091821255e+01, 1.1051393351707578e+01, 1.1366561153620273e+01, 1.1693995391536458e+01, 1.2036317739606817e+01, 1.2397260816155137e+01, 1.2782491733501539e+01, 1.3201461514403192e+01, 1.3672516911310485e+01, 1.4243701683090396e+01}, + {-1.4311358299517268e+01, -1.3741064189376445e+01, -1.3270764846437274e+01, -1.2852484601295865e+01, -1.2467902444132251e+01, -1.2107580518550922e+01, -1.1765859570925668e+01, -1.1439012148401694e+01, -1.1124420207060311e+01, -1.0820156534367447e+01, -1.0524750634313888e+01, -1.0237048218321810e+01, -9.9561221176215060e+00, -9.6812132563270588e+00, -9.4116901024866948e+00, -9.1470199577543809e+00, -8.8867481005681856e+00, -8.6304822961073278e+00, -8.3778810688446761e+00, -8.1286446726129125e+00, -7.8825080329965438e+00, -7.6392351571886659e+00, -7.3986146528207790e+00, -7.1604560966616368e+00, -6.9245870629045054e+00, -6.6908506692717395e+00, -6.4591035339104934e+00, -6.2292140613060107e+00, -6.0010609940399187e+00, -5.7745321810917920e+00, -5.5495235238436296e+00, -5.3259380689199052e+00, -5.1036852231316345e+00, -4.8826800705576368e+00, -4.6628427755272810e+00, -4.4440980582138394e+00, -4.2263747318887201e+00, -4.0096052927608685e+00, -3.7937255548353970e+00, -3.5786743234488534e+00, -3.3643931021355877e+00, -3.1508258282961985e+00, -2.9379186338110879e+00, -2.7256196272975335e+00, -2.5138786951694905e+00, -2.3026473190429599e+00, -2.0918784073499572e+00, -1.8815261392920377e+00, -1.6715458194887483e+00, -1.4618937418644296e+00, -1.2525270614742765e+00, -1.0434036731020315e+00, -8.3448209557097697e-01, -6.2572136079995633e-01, -4.1708090670945613e-01, -2.0852047314122538e-01, -0.0000000000000000e+00, 2.0852047314122538e-01, 4.1708090670945613e-01, 6.2572136079995633e-01, 8.3448209557097697e-01, 1.0434036731020315e+00, 1.2525270614742765e+00, 1.4618937418644296e+00, 1.6715458194887483e+00, 1.8815261392920377e+00, 2.0918784073499572e+00, 2.3026473190429599e+00, 2.5138786951694905e+00, 2.7256196272975335e+00, 2.9379186338110879e+00, 3.1508258282961985e+00, 3.3643931021355877e+00, 3.5786743234488534e+00, 3.7937255548353970e+00, 4.0096052927608685e+00, 4.2263747318887201e+00, 4.4440980582138394e+00, 4.6628427755272810e+00, 4.8826800705576368e+00, 5.1036852231316345e+00, 5.3259380689199052e+00, 5.5495235238436296e+00, 5.7745321810917920e+00, 6.0010609940399187e+00, 6.2292140613060107e+00, 6.4591035339104934e+00, 6.6908506692717395e+00, 6.9245870629045054e+00, 7.1604560966616368e+00, 7.3986146528207790e+00, 7.6392351571886659e+00, 7.8825080329965438e+00, 8.1286446726129125e+00, 8.3778810688446761e+00, 8.6304822961073278e+00, 8.8867481005681856e+00, 9.1470199577543809e+00, 9.4116901024866948e+00, 9.6812132563270588e+00, 9.9561221176215060e+00, 1.0237048218321810e+01, 1.0524750634313888e+01, 1.0820156534367447e+01, 1.1124420207060311e+01, 1.1439012148401694e+01, 1.1765859570925668e+01, 1.2107580518550922e+01, 1.2467902444132251e+01, 1.2852484601295865e+01, 1.3270764846437274e+01, 1.3741064189376445e+01, 1.4311358299517268e+01}, + {-1.4378710718888687e+01, -1.3809297788283777e+01, -1.3339746281883333e+01, -1.2922147941452449e+01, -1.2538207244299381e+01, -1.2178499369616199e+01, -1.1837372843992933e+01, -1.1511105327917651e+01, -1.1197082370480098e+01, -1.0893379412488740e+01, -1.0598527994882549e+01, -1.0311375442821380e+01, -1.0030995900063404e+01, -9.7566313825866331e+00, -9.4876512847987584e+00, -9.2235237081638886e+00, -8.9637946326267190e+00, -8.7080724475249998e+00, -8.4560162400066048e+00, -8.2073267773259264e+00, -7.9617394588210120e+00, -7.7190187333975366e+00, -7.4789536245148378e+00, -7.2413541039213873e+00, -7.0060481241167620e+00, -6.7728791679610003e+00, -6.5417042085499943e+00, -6.3123919976942711e+00, -6.0848216199144423e+00, -5.8588812627189206e+00, -5.6344671643769209e+00, -5.4114827083623283e+00, -5.1898376397716799e+00, -4.9694473837781068e+00, -4.7502324499094550e+00, -4.5321179088799042e+00, -4.3150329310427544e+00, -4.0989103774038682e+00, -3.8836864356433058e+00, -3.6693002948148599e+00, -3.4556938533892665e+00, -3.2428114561228023e+00, -3.0305996559046307e+00, -2.8190069972914444e+00, -2.6079838188988345e+00, -2.3974820722025694e+00, -2.1874551546235876e+00, -1.9778577550389427e+00, -1.7686457100860522e+00, -1.5597758698165716e+00, -1.3512059714147289e+00, -1.1428945198277283e+00, -9.3480067426661317e-01, -7.2688413962779108e-01, -5.1910506196077233e-01, -3.1142392716846806e-01, -1.0380146217422165e-01, 1.0380146217422165e-01, 3.1142392716846806e-01, 5.1910506196077233e-01, 7.2688413962779108e-01, 9.3480067426661317e-01, 1.1428945198277283e+00, 1.3512059714147289e+00, 1.5597758698165716e+00, 1.7686457100860522e+00, 1.9778577550389427e+00, 2.1874551546235876e+00, 2.3974820722025694e+00, 2.6079838188988345e+00, 2.8190069972914444e+00, 3.0305996559046307e+00, 3.2428114561228023e+00, 3.4556938533892665e+00, 3.6693002948148599e+00, 3.8836864356433058e+00, 4.0989103774038682e+00, 4.3150329310427544e+00, 4.5321179088799042e+00, 4.7502324499094550e+00, 4.9694473837781068e+00, 5.1898376397716799e+00, 5.4114827083623283e+00, 5.6344671643769209e+00, 5.8588812627189206e+00, 6.0848216199144423e+00, 6.3123919976942711e+00, 6.5417042085499943e+00, 6.7728791679610003e+00, 7.0060481241167620e+00, 7.2413541039213873e+00, 7.4789536245148378e+00, 7.7190187333975366e+00, 7.9617394588210120e+00, 8.2073267773259264e+00, 8.4560162400066048e+00, 8.7080724475249998e+00, 8.9637946326267190e+00, 9.2235237081638886e+00, 9.4876512847987584e+00, 9.7566313825866331e+00, 1.0030995900063404e+01, 1.0311375442821380e+01, 1.0598527994882549e+01, 1.0893379412488740e+01, 1.1197082370480098e+01, 1.1511105327917651e+01, 1.1837372843992933e+01, 1.2178499369616199e+01, 1.2538207244299381e+01, 1.2922147941452449e+01, 1.3339746281883333e+01, 1.3809297788283777e+01, 1.4378710718888687e+01}, + {-1.4445762988361196e+01, -1.3877221939887596e+01, -1.3408410215509624e+01, -1.2991486302387372e+01, -1.2608179914177892e+01, -1.2249079137323781e+01, -1.1908540201639026e+01, -1.1582845829838529e+01, -1.1269385127541279e+01, -1.0966236161382101e+01, -1.0671932487544689e+01, -1.0385323027156920e+01, -1.0105483221483672e+01, -9.8316561653115180e+00, -9.5632121677809998e+00, -9.2996201195877468e+00, -9.0404266923744707e+00, -8.7852408903904529e+00, -8.5337223546130900e+00, -8.2855723571485260e+00, -8.0405267626925543e+00, -7.7983504535582933e+00, -7.5588328607481419e+00, -7.3217843426652625e+00, -7.0870332216969052e+00, -6.8544233372804051e+00, -6.6238120087139674e+00, -6.3950683261592980e+00, -6.1680717068342963e+00, -5.9427106672279626e+00, -5.7188817726033569e+00, -5.4964887330064514e+00, -5.2754416211185129e+00, -5.0556561920420737e+00, -4.8370532888321796e+00, -4.6195583205220858e+00, -4.4031008017280051e+00, -4.1876139447872083e+00, -3.9730342968900869e+00, -3.7593014158877045e+00, -3.5463575794514748e+00, -3.3341475230768891e+00, -3.1226182030944165e+00, -2.9117185814056987e+00, -2.7013994291239474e+00, -2.4916131466813880e+00, -2.2823135982874576e+00, -2.0734559588903583e+00, -1.8649965720202712e+00, -1.6568928170822563e+00, -1.4491029848262951e+00, -1.2415861598558324e+00, -1.0343021091482230e+00, -8.2721117565385283e-01, -6.2027417611781133e-01, -4.1345230233083557e-01, -2.0670702506645103e-01, -0.0000000000000000e+00, 2.0670702506645103e-01, 4.1345230233083557e-01, 6.2027417611781133e-01, 8.2721117565385283e-01, 1.0343021091482230e+00, 1.2415861598558324e+00, 1.4491029848262951e+00, 1.6568928170822563e+00, 1.8649965720202712e+00, 2.0734559588903583e+00, 2.2823135982874576e+00, 2.4916131466813880e+00, 2.7013994291239474e+00, 2.9117185814056987e+00, 3.1226182030944165e+00, 3.3341475230768891e+00, 3.5463575794514748e+00, 3.7593014158877045e+00, 3.9730342968900869e+00, 4.1876139447872083e+00, 4.4031008017280051e+00, 4.6195583205220858e+00, 4.8370532888321796e+00, 5.0556561920420737e+00, 5.2754416211185129e+00, 5.4964887330064514e+00, 5.7188817726033569e+00, 5.9427106672279626e+00, 6.1680717068342963e+00, 6.3950683261592980e+00, 6.6238120087139674e+00, 6.8544233372804051e+00, 7.0870332216969052e+00, 7.3217843426652625e+00, 7.5588328607481419e+00, 7.7983504535582933e+00, 8.0405267626925543e+00, 8.2855723571485260e+00, 8.5337223546130900e+00, 8.7852408903904529e+00, 9.0404266923744707e+00, 9.2996201195877468e+00, 9.5632121677809998e+00, 9.8316561653115180e+00, 1.0105483221483672e+01, 1.0385323027156920e+01, 1.0671932487544689e+01, 1.0966236161382101e+01, 1.1269385127541279e+01, 1.1582845829838529e+01, 1.1908540201639026e+01, 1.2249079137323781e+01, 1.2608179914177892e+01, 1.2991486302387372e+01, 1.3408410215509624e+01, 1.3877221939887596e+01, 1.4445762988361196e+01}, + {-1.4512519066332473e+01, -1.3944840782089997e+01, -1.3476760943476538e+01, -1.3060504129456817e+01, -1.2677825043852227e+01, -1.2319324554388889e+01, -1.1979366518555956e+01, -1.1654238671159664e+01, -1.1341333638590701e+01, -1.1038732086359635e+01, -1.0744969564657922e+01, -1.0458896573213373e+01, -1.0179589836134598e+01, -9.9062935142905033e+00, -9.6383788202379357e+00, -9.3753154236236274e+00, -9.1166506782713626e+00, -8.8619941943843266e+00, -8.6110061582143160e+00, -8.3633883384434800e+00, -8.1188770570299589e+00, -7.8772376216979518e+00, -7.6382598630271916e+00, -7.4017545180817317e+00, -7.1675502710629999e+00, -6.9354913097861042e+00, -6.7054352913834911e+00, -6.4772516357915970e+00, -6.2508200841027559e+00, -6.0260294726803698e+00, -5.8027766843552886e+00, -5.5809657459630806e+00, -5.3605070475936927e+00, -5.1413166636713479e+00, -4.9233157596994808e+00, -4.7064300714392884e+00, -4.4905894456231428e+00, -4.2757274331715260e+00, -4.0617809273868284e+00, -3.8486898408169177e+00, -3.6363968154755777e+00, -3.4248469619214639e+00, -3.2139876233679749e+00, -3.0037681615511667e+00, -2.7941397615435219e+00, -2.5850552530853812e+00, -2.3764689463269284e+00, -2.1683364801428588e+00, -1.9606146814080672e+00, -1.7532614338130410e+00, -1.5462355549578937e+00, -1.3394966805987920e+00, -1.1330051550337377e+00, -9.2672192670934395e-01, -7.2060844820888659e-01, -5.1462657984655003e-01, -3.0873849614504811e-01, -1.0290659451494534e-01, 1.0290659451494534e-01, 3.0873849614504811e-01, 5.1462657984655003e-01, 7.2060844820888659e-01, 9.2672192670934395e-01, 1.1330051550337377e+00, 1.3394966805987920e+00, 1.5462355549578937e+00, 1.7532614338130410e+00, 1.9606146814080672e+00, 2.1683364801428588e+00, 2.3764689463269284e+00, 2.5850552530853812e+00, 2.7941397615435219e+00, 3.0037681615511667e+00, 3.2139876233679749e+00, 3.4248469619214639e+00, 3.6363968154755777e+00, 3.8486898408169177e+00, 4.0617809273868284e+00, 4.2757274331715260e+00, 4.4905894456231428e+00, 4.7064300714392884e+00, 4.9233157596994808e+00, 5.1413166636713479e+00, 5.3605070475936927e+00, 5.5809657459630806e+00, 5.8027766843552886e+00, 6.0260294726803698e+00, 6.2508200841027559e+00, 6.4772516357915970e+00, 6.7054352913834911e+00, 6.9354913097861042e+00, 7.1675502710629999e+00, 7.4017545180817317e+00, 7.6382598630271916e+00, 7.8772376216979518e+00, 8.1188770570299589e+00, 8.3633883384434800e+00, 8.6110061582143160e+00, 8.8619941943843266e+00, 9.1166506782713626e+00, 9.3753154236236274e+00, 9.6383788202379357e+00, 9.9062935142905033e+00, 1.0179589836134598e+01, 1.0458896573213373e+01, 1.0744969564657922e+01, 1.1038732086359635e+01, 1.1341333638590701e+01, 1.1654238671159664e+01, 1.1979366518555956e+01, 1.2319324554388889e+01, 1.2677825043852227e+01, 1.3060504129456817e+01, 1.3476760943476538e+01, 1.3944840782089997e+01, 1.4512519066332473e+01}, + {-1.4578982825139288e+01, -1.4012158361728110e+01, -1.3544802666397535e+01, -1.3129205768185479e+01, -1.2747147119365039e+01, -1.2389240245284292e+01, -1.2049856556961975e+01, -1.1725288752112307e+01, -1.1412932942839976e+01, -1.1110872367128264e+01, -1.0817644548390337e+01, -1.0532101547973223e+01, -1.0253321358511124e+01, -9.9805491945452847e+00, -9.7131571610296650e+00, -9.4506156965670485e+00, -9.1924728279240568e+00, -8.9383387625761230e+00, -8.6878742237708870e+00, -8.4407814687705134e+00, -8.1967972689854154e+00, -7.9556873498473575e+00, -7.7172419338499774e+00, -7.4812721290378645e+00, -7.2476069736794351e+00, -7.0160909961088489e+00, -6.7865821832816833e+00, -6.5589502767074928e+00, -6.3330753329246656e+00, -6.1088464994807214e+00, -5.8861609677875624e+00, -5.6649230721526251e+00, -5.4450435103908958e+00, -5.2264386661630065e+00, -5.0090300168969302e+00, -4.7927436140809663e+00, -4.5775096250454670e+00, -4.3632619272160529e+00, -4.1499377473239889e+00, -3.9374773392776570e+00, -3.7258236953922830e+00, -3.5149222864888690e+00, -3.3047208270435604e+00, -3.0951690621230776e+00, -2.8862185733023908e+00, -2.6778226011448112e+00, -2.4699358821459070e+00, -2.2625144983121754e+00, -2.0555157377720055e+00, -1.8488979650073754e+00, -1.6426204994556326e+00, -1.4366435013663816e+00, -1.2309278639126584e+00, -1.0254351106514223e+00, -8.2012729750837221e-01, -6.1496691852828633e-01, -4.0991681468614050e-01, -2.0494008509748737e-01, -0.0000000000000000e+00, 2.0494008509748737e-01, 4.0991681468614050e-01, 6.1496691852828633e-01, 8.2012729750837221e-01, 1.0254351106514223e+00, 1.2309278639126584e+00, 1.4366435013663816e+00, 1.6426204994556326e+00, 1.8488979650073754e+00, 2.0555157377720055e+00, 2.2625144983121754e+00, 2.4699358821459070e+00, 2.6778226011448112e+00, 2.8862185733023908e+00, 3.0951690621230776e+00, 3.3047208270435604e+00, 3.5149222864888690e+00, 3.7258236953922830e+00, 3.9374773392776570e+00, 4.1499377473239889e+00, 4.3632619272160529e+00, 4.5775096250454670e+00, 4.7927436140809663e+00, 5.0090300168969302e+00, 5.2264386661630065e+00, 5.4450435103908958e+00, 5.6649230721526251e+00, 5.8861609677875624e+00, 6.1088464994807214e+00, 6.3330753329246656e+00, 6.5589502767074928e+00, 6.7865821832816833e+00, 7.0160909961088489e+00, 7.2476069736794351e+00, 7.4812721290378645e+00, 7.7172419338499774e+00, 7.9556873498473575e+00, 8.1967972689854154e+00, 8.4407814687705134e+00, 8.6878742237708870e+00, 8.9383387625761230e+00, 9.1924728279240568e+00, 9.4506156965670485e+00, 9.7131571610296650e+00, 9.9805491945452847e+00, 1.0253321358511124e+01, 1.0532101547973223e+01, 1.0817644548390337e+01, 1.1110872367128264e+01, 1.1412932942839976e+01, 1.1725288752112307e+01, 1.2049856556961975e+01, 1.2389240245284292e+01, 1.2747147119365039e+01, 1.3129205768185479e+01, 1.3544802666397535e+01, 1.4012158361728110e+01, 1.4578982825139288e+01}, + {-1.4645158053651027e+01, -1.4079178637349177e+01, -1.3612539492279215e+01, -1.3197595467366467e+01, -1.2816150525975972e+01, -1.2458830729659516e+01, -1.2120014970184142e+01, -1.1796000859913661e+01, -1.1484187962287965e+01, -1.1182662061890452e+01, -1.0889962635005938e+01, -1.0604943287993811e+01, -1.0326683268027864e+01, -1.0054428831215711e+01, -9.7875529641744929e+00, -9.5255268647413445e+00, -9.2678992236538775e+00, -9.0142808372415573e+00, -8.7643329577328277e+00, -8.5177583232401322e+00, -8.2742941470872093e+00, -8.0337065649878543e+00, -7.7957861839727647e+00, -7.5603444756835589e+00, -7.3272108250171302e+00, -7.0962300932900497e+00, -6.8672605896069676e+00, -6.6401723692025154e+00, -6.4148457960045002e+00, -6.1911703204459041e+00, -5.9690434339462293e+00, -5.7483697694039071e+00, -5.5290603231377613e+00, -5.3110317784497383e+00, -5.0942059146888043e+00, -4.8785090886224198e+00, -4.6638717772489988e+00, -4.4502281730478108e+00, -4.2375158241640083e+00, -4.0256753132434273e+00, -3.8146499696239737e+00, -3.6043856104035212e+00, -3.3948303065739314e+00, -3.1859341709648956e+00, -2.9776491652016608e+00, -2.7699289232646307e+00, -2.5627285895601974e+00, -2.3560046696818464e+00, -2.1497148922675668e+00, -1.9438180805509269e+00, -1.7382740323646890e+00, -1.5330434074921915e+00, -1.3280876213767709e+00, -1.1233687442963156e+00, -9.1884940519120828e-01, -7.1449269940145821e-01, -5.1026209962444491e-01, -3.0612136944972701e-01, -1.0203447886287802e-01, 1.0203447886287802e-01, 3.0612136944972701e-01, 5.1026209962444491e-01, 7.1449269940145821e-01, 9.1884940519120828e-01, 1.1233687442963156e+00, 1.3280876213767709e+00, 1.5330434074921915e+00, 1.7382740323646890e+00, 1.9438180805509269e+00, 2.1497148922675668e+00, 2.3560046696818464e+00, 2.5627285895601974e+00, 2.7699289232646307e+00, 2.9776491652016608e+00, 3.1859341709648956e+00, 3.3948303065739314e+00, 3.6043856104035212e+00, 3.8146499696239737e+00, 4.0256753132434273e+00, 4.2375158241640083e+00, 4.4502281730478108e+00, 4.6638717772489988e+00, 4.8785090886224198e+00, 5.0942059146888043e+00, 5.3110317784497383e+00, 5.5290603231377613e+00, 5.7483697694039071e+00, 5.9690434339462293e+00, 6.1911703204459041e+00, 6.4148457960045002e+00, 6.6401723692025154e+00, 6.8672605896069676e+00, 7.0962300932900497e+00, 7.3272108250171302e+00, 7.5603444756835589e+00, 7.7957861839727647e+00, 8.0337065649878543e+00, 8.2742941470872093e+00, 8.5177583232401322e+00, 8.7643329577328277e+00, 9.0142808372415573e+00, 9.2678992236538775e+00, 9.5255268647413445e+00, 9.7875529641744929e+00, 1.0054428831215711e+01, 1.0326683268027864e+01, 1.0604943287993811e+01, 1.0889962635005938e+01, 1.1182662061890452e+01, 1.1484187962287965e+01, 1.1796000859913661e+01, 1.2120014970184142e+01, 1.2458830729659516e+01, 1.2816150525975972e+01, 1.3197595467366467e+01, 1.3612539492279215e+01, 1.4079178637349177e+01, 1.4645158053651027e+01}, + {-1.4711048459763671e+01, -1.4145905481877998e+01, -1.3679975439346320e+01, -1.3265677382038762e+01, -1.2884839551290751e+01, -1.2528100425622796e+01, -1.2189846306095971e+01, -1.1866379672363987e+01, -1.1555103505482034e+01, -1.1254106111274996e+01, -1.0961928898971054e+01, -1.0677427003696076e+01, -1.0399680913497548e+01, -1.0127937914235881e+01, -9.8615718637313439e+00, -9.6000547095956161e+00, -9.3429357978203189e+00, -9.0898265054222858e+00, -8.8403886058470427e+00, -8.5943253105810840e+00, -8.3513742675803542e+00, -8.1113020156791773e+00, -7.8738995393403330e+00, -7.6389786667002593e+00, -7.4063691221380390e+00, -7.1759160927206223e+00, -6.9474782023460993e+00, -6.7209258124599129e+00, -6.4961395866732436e+00, -6.2730092703749003e+00, -6.0514326468076227e+00, -5.8313146389908859e+00, -5.6125665329607717e+00, -5.3951053025257689e+00, -5.1788530194404441e+00, -4.9637363358218023e+00, -4.7496860279573854e+00, -4.5366365925149861e+00, -4.3245258876633645e+00, -4.1132948128290048e+00, -3.9028870218050722e+00, -3.6932486647410911e+00, -3.4843281552109961e+00, -3.2760759591109072e+00, -3.0684444025981263e+00, -2.8613874966667088e+00, -2.6548607762763461e+00, -2.4488211522211656e+00, -2.2432267741522884e+00, -2.0380369033597177e+00, -1.8332117940811192e+00, -1.6287125822420414e+00, -1.4245011806478818e+00, -1.2205401797456257e+00, -1.0167927531555376e+00, -8.1322256724173581e-01, -6.0979369404756556e-01, -4.0647052696828645e-01, -2.0321769857092067e-01, -0.0000000000000000e+00, 2.0321769857092067e-01, 4.0647052696828645e-01, 6.0979369404756556e-01, 8.1322256724173581e-01, 1.0167927531555376e+00, 1.2205401797456257e+00, 1.4245011806478818e+00, 1.6287125822420414e+00, 1.8332117940811192e+00, 2.0380369033597177e+00, 2.2432267741522884e+00, 2.4488211522211656e+00, 2.6548607762763461e+00, 2.8613874966667088e+00, 3.0684444025981263e+00, 3.2760759591109072e+00, 3.4843281552109961e+00, 3.6932486647410911e+00, 3.9028870218050722e+00, 4.1132948128290048e+00, 4.3245258876633645e+00, 4.5366365925149861e+00, 4.7496860279573854e+00, 4.9637363358218023e+00, 5.1788530194404441e+00, 5.3951053025257689e+00, 5.6125665329607717e+00, 5.8313146389908859e+00, 6.0514326468076227e+00, 6.2730092703749003e+00, 6.4961395866732436e+00, 6.7209258124599129e+00, 6.9474782023460993e+00, 7.1759160927206223e+00, 7.4063691221380390e+00, 7.6389786667002593e+00, 7.8738995393403330e+00, 8.1113020156791773e+00, 8.3513742675803542e+00, 8.5943253105810840e+00, 8.8403886058470427e+00, 9.0898265054222858e+00, 9.3429357978203189e+00, 9.6000547095956161e+00, 9.8615718637313439e+00, 1.0127937914235881e+01, 1.0399680913497548e+01, 1.0677427003696076e+01, 1.0961928898971054e+01, 1.1254106111274996e+01, 1.1555103505482034e+01, 1.1866379672363987e+01, 1.2189846306095971e+01, 1.2528100425622796e+01, 1.2884839551290751e+01, 1.3265677382038762e+01, 1.3679975439346320e+01, 1.4145905481877998e+01, 1.4711048459763671e+01}, + {-1.4776657672798869e+01, -1.4212342685181815e+01, -1.3747114438757134e+01, -1.3333455576348189e+01, -1.2953218388266750e+01, -1.2597053652892484e+01, -1.2259355010417195e+01, -1.1936429761298314e+01, -1.1625684271126064e+01, -1.1325209342106415e+01, -1.1033548296890791e+01, -1.0749557783474378e+01, -1.0472319517421079e+01, -1.0201081802811933e+01, -9.9352193584733488e+00, -9.6742048725828571e+00, -9.4175883379130294e+00, -9.1649817042418142e+00, -8.9160472587078665e+00, -8.6704886789370494e+00, -8.4280440404817565e+00, -8.1884802783862387e+00, -7.9515887476984757e+00, -7.7171816262142663e+00, -7.4850889709254078e+00, -7.2551562877054536e+00, -7.0272425081913878e+00, -6.8012182928404501e+00, -6.5769645975720454e+00, -6.3543714551491233e+00, -6.1333369328198826e+00, -5.9137662356417078e+00, -5.6955709309901366e+00, -5.4786682744780215e+00, -5.2629806212085075e+00, -5.0484349092048060e+00, -4.8349622041811422e+00, -4.6224972966778903e+00, -4.4109783440817232e+00, -4.2003465512658975e+00, -3.9905458845758908e+00, -3.7815228146971922e+00, -3.5732260846105883e+00, -3.3656064993935964e+00, -3.1586167350865688e+00, -2.9522111642257620e+00, -2.7463456959669994e+00, -2.5409776289935784e+00, -2.3360655156294796e+00, -2.1315690357710211e+00, -1.9274488794124773e+00, -1.7236666366787170e+00, -1.5201846943942978e+00, -1.3169661383169375e+00, -1.1139746602463279e+00, -9.1117446928904511e-01, -7.0853020661847821e-01, -5.0600686311669596e-01, -3.0356969932406813e-01, -1.0118416715318335e-01, 1.0118416715318335e-01, 3.0356969932406813e-01, 5.0600686311669596e-01, 7.0853020661847821e-01, 9.1117446928904511e-01, 1.1139746602463279e+00, 1.3169661383169375e+00, 1.5201846943942978e+00, 1.7236666366787170e+00, 1.9274488794124773e+00, 2.1315690357710211e+00, 2.3360655156294796e+00, 2.5409776289935784e+00, 2.7463456959669994e+00, 2.9522111642257620e+00, 3.1586167350865688e+00, 3.3656064993935964e+00, 3.5732260846105883e+00, 3.7815228146971922e+00, 3.9905458845758908e+00, 4.2003465512658975e+00, 4.4109783440817232e+00, 4.6224972966778903e+00, 4.8349622041811422e+00, 5.0484349092048060e+00, 5.2629806212085075e+00, 5.4786682744780215e+00, 5.6955709309901366e+00, 5.9137662356417078e+00, 6.1333369328198826e+00, 6.3543714551491233e+00, 6.5769645975720454e+00, 6.8012182928404501e+00, 7.0272425081913878e+00, 7.2551562877054536e+00, 7.4850889709254078e+00, 7.7171816262142663e+00, 7.9515887476984757e+00, 8.1884802783862387e+00, 8.4280440404817565e+00, 8.6704886789370494e+00, 8.9160472587078665e+00, 9.1649817042418142e+00, 9.4175883379130294e+00, 9.6742048725828571e+00, 9.9352193584733488e+00, 1.0201081802811933e+01, 1.0472319517421079e+01, 1.0749557783474378e+01, 1.1033548296890791e+01, 1.1325209342106415e+01, 1.1625684271126064e+01, 1.1936429761298314e+01, 1.2259355010417195e+01, 1.2597053652892484e+01, 1.2953218388266750e+01, 1.3333455576348189e+01, 1.3747114438757134e+01, 1.4212342685181815e+01, 1.4776657672798869e+01}, + {-1.4841989245812462e+01, -1.4278493956537387e+01, -1.3813960337214354e+01, -1.3400934026297357e+01, -1.3021291138101008e+01, -1.2665694635824183e+01, -1.2328545429882384e+01, -1.2006155595899877e+01, -1.1695934851542777e+01, -1.1395976471020912e+01, -1.1104825671283981e+01, -1.0821340597636343e+01, -1.0544604180098764e+01, -1.0273865729711682e+01, -1.0008500816363464e+01, -9.7479828598297100e+00, -9.4918624914245004e+00, -9.2397522259904878e+00, -8.9913148570644346e+00, -8.7462545214071792e+00, -8.5043097153654035e+00, -8.2652477635213177e+00, -8.0288603849063733e+00, -7.7949601003933706e+00, -7.5633772929797445e+00, -7.3339577806748517e+00, -7.1065607960848611e+00, -6.8810572917778128e+00, -6.6573285089186554e+00, -6.4352647603911377e+00, -6.2147643899767431e+00, -5.9957328770520153e+00, -5.7780820623389184e+00, -5.5617294749593142e+00, -5.3465977447386317e+00, -5.1326140866195260e+00, -4.9197098463649933e+00, -4.7078200985868248e+00, -4.4968832896314073e+00, -4.2868409190677941e+00, -4.0776372545120747e+00, -3.8692190753327944e+00, -3.6615354414501788e+00, -3.4545374839947667e+00, -3.2481782150506633e+00, -3.0424123540922232e+00, -2.8371961690442937e+00, -2.6324873301662031e+00, -2.4282447751872818e+00, -2.2244285843140195e+00, -2.0209998638917077e+00, -1.8179206376413908e+00, -1.6151537445099000e+00, -1.4126627422698670e+00, -1.2104118160904516e+00, -1.0083656913702024e+00, -8.0648955018269064e-01, -6.0474895073475177e-01, -4.0310974927746679e-01, -2.0153802394231832e-01, -0.0000000000000000e+00, 2.0153802394231832e-01, 4.0310974927746679e-01, 6.0474895073475177e-01, 8.0648955018269064e-01, 1.0083656913702024e+00, 1.2104118160904516e+00, 1.4126627422698670e+00, 1.6151537445099000e+00, 1.8179206376413908e+00, 2.0209998638917077e+00, 2.2244285843140195e+00, 2.4282447751872818e+00, 2.6324873301662031e+00, 2.8371961690442937e+00, 3.0424123540922232e+00, 3.2481782150506633e+00, 3.4545374839947667e+00, 3.6615354414501788e+00, 3.8692190753327944e+00, 4.0776372545120747e+00, 4.2868409190677941e+00, 4.4968832896314073e+00, 4.7078200985868248e+00, 4.9197098463649933e+00, 5.1326140866195260e+00, 5.3465977447386317e+00, 5.5617294749593142e+00, 5.7780820623389184e+00, 5.9957328770520153e+00, 6.2147643899767431e+00, 6.4352647603911377e+00, 6.6573285089186554e+00, 6.8810572917778128e+00, 7.1065607960848611e+00, 7.3339577806748517e+00, 7.5633772929797445e+00, 7.7949601003933706e+00, 8.0288603849063733e+00, 8.2652477635213177e+00, 8.5043097153654035e+00, 8.7462545214071792e+00, 8.9913148570644346e+00, 9.2397522259904878e+00, 9.4918624914245004e+00, 9.7479828598297100e+00, 1.0008500816363464e+01, 1.0273865729711682e+01, 1.0544604180098764e+01, 1.0821340597636343e+01, 1.1104825671283981e+01, 1.1395976471020912e+01, 1.1695934851542777e+01, 1.2006155595899877e+01, 1.2328545429882384e+01, 1.2665694635824183e+01, 1.3021291138101008e+01, 1.3400934026297357e+01, 1.3813960337214354e+01, 1.4278493956537387e+01, 1.4841989245812462e+01}, + {-1.4907046657816622e+01, -1.4344362927004781e+01, -1.3880516899476401e+01, -1.3468116622389784e+01, -1.3089061813006204e+01, -1.2734027506319505e+01, -1.2397421815284703e+01, -1.2075561545881943e+01, -1.1765859735997486e+01, -1.1466412107936478e+01, -1.1175765754204676e+01, -1.0892780302181299e+01, -1.0616539883571752e+01, -1.0346294805375646e+01, -1.0081421478842227e+01, -9.8213940466086171e+00, -9.5657637705148062e+00, -9.3141437229916662e+00, -9.0661971968977273e+00, -8.8216287813440992e+00, -8.5801773868921547e+00, -8.3416107212171422e+00, -8.1057208609652847e+00, -7.8723206637443432e+00, -7.6412408321991903e+00, -7.4123274900628546e+00, -7.1854401644106494e+00, -6.9604500933022759e+00, -6.7372387963808658e+00, -6.5156968597076492e+00, -6.2957228964512764e+00, -6.0772226529322166e+00, -5.8601082355882221e+00, -5.6442974391377119e+00, -5.4297131599071493e+00, -5.2162828812008781e+00, -5.0039382199076590e+00, -4.7926145253924428e+00, -4.5822505232162971e+00, -4.3727879974390058e+00, -4.1641715062468725e+00, -3.9563481264582303e+00, -3.7492672231264832e+00, -3.5428802410129703e+00, -3.3371405151612126e+00, -3.1320030981875178e+00, -2.9274246022241841e+00, -2.7233630537216094e+00, -2.5197777595433375e+00, -2.3166291829805914e+00, -2.1138788284758951e+00, -1.9114891339837408e+00, -1.7094233700136701e+00, -1.5076455445008548e+00, -1.3061203127337706e+00, -1.1048128916400251e+00, -9.0368897779154544e-01, -7.0271466854059361e-01, -5.0185638573956481e-01, -3.0108080153124556e-01, -1.0035476572283220e-01, 1.0035476572283220e-01, 3.0108080153124556e-01, 5.0185638573956481e-01, 7.0271466854059361e-01, 9.0368897779154544e-01, 1.1048128916400251e+00, 1.3061203127337706e+00, 1.5076455445008548e+00, 1.7094233700136701e+00, 1.9114891339837408e+00, 2.1138788284758951e+00, 2.3166291829805914e+00, 2.5197777595433375e+00, 2.7233630537216094e+00, 2.9274246022241841e+00, 3.1320030981875178e+00, 3.3371405151612126e+00, 3.5428802410129703e+00, 3.7492672231264832e+00, 3.9563481264582303e+00, 4.1641715062468725e+00, 4.3727879974390058e+00, 4.5822505232162971e+00, 4.7926145253924428e+00, 5.0039382199076590e+00, 5.2162828812008781e+00, 5.4297131599071493e+00, 5.6442974391377119e+00, 5.8601082355882221e+00, 6.0772226529322166e+00, 6.2957228964512764e+00, 6.5156968597076492e+00, 6.7372387963808658e+00, 6.9604500933022759e+00, 7.1854401644106494e+00, 7.4123274900628546e+00, 7.6412408321991903e+00, 7.8723206637443432e+00, 8.1057208609652847e+00, 8.3416107212171422e+00, 8.5801773868921547e+00, 8.8216287813440992e+00, 9.0661971968977273e+00, 9.3141437229916662e+00, 9.5657637705148062e+00, 9.8213940466086171e+00, 1.0081421478842227e+01, 1.0346294805375646e+01, 1.0616539883571752e+01, 1.0892780302181299e+01, 1.1175765754204676e+01, 1.1466412107936478e+01, 1.1765859735997486e+01, 1.2075561545881943e+01, 1.2397421815284703e+01, 1.2734027506319505e+01, 1.3089061813006204e+01, 1.3468116622389784e+01, 1.3880516899476401e+01, 1.4344362927004781e+01, 1.4907046657816622e+01}, + {-1.4971833315919479e+01, -1.4409953151712163e+01, -1.3946787810773682e+01, -1.3535007172173161e+01, -1.3156534338879860e+01, -1.2802056306622088e+01, -1.2465988324400744e+01, -1.2144651884544359e+01, -1.1835463313889939e+01, -1.1536520759384242e+01, -1.1246373170717687e+01, -1.0963881642425228e+01, -1.0688131495402112e+01, -1.0418374021858449e+01, -1.0153986464937166e+01, -9.8944436816224322e+00, -9.6392975564791730e+00, -9.3881617122605014e+00, -9.1406999342794091e+00, -8.8966172574222746e+00, -8.6556530000977201e+00, -8.4175752468453187e+00, -8.1821764257789713e+00, -7.9492697251276718e+00, -7.7186861610617425e+00, -7.4902721568710229e+00, -7.2638875278553732e+00, -7.0394037912138101e+00, -6.8167027385795480e+00, -6.5956752225409012e+00, -6.3762201188154259e+00, -6.1582434336162883e+00, -5.9416575318080138e+00, -5.7263804661537199e+00, -5.5123353916408391e+00, -5.2994500517810534e+00, -5.0876563260932981e+00, -4.8768898298307777e+00, -4.6670895585055892e+00, -4.4581975709748294e+00, -4.2501587058390200e+00, -4.0429203267128022e+00, -3.8364320925946052e+00, -3.6306457501139446e+00, -3.4255149448939752e+00, -3.2209950496501372e+00, -3.0170430069668734e+00, -2.8136171849644747e+00, -2.6106772442959039e+00, -2.4081840151061349e+00, -2.2060993827498390e+00, -2.0043861812019168e+00, -1.8030080932132322e+00, -1.6019295563640745e+00, -1.4011156742530042e+00, -1.2005321321308888e+00, -1.0001451163508825e+00, -7.9992123705629015e-01, -5.9982745357081801e-01, -3.9983100199064880e-01, -1.9989932450580150e-01, -0.0000000000000000e+00, 1.9989932450580150e-01, 3.9983100199064880e-01, 5.9982745357081801e-01, 7.9992123705629015e-01, 1.0001451163508825e+00, 1.2005321321308888e+00, 1.4011156742530042e+00, 1.6019295563640745e+00, 1.8030080932132322e+00, 2.0043861812019168e+00, 2.2060993827498390e+00, 2.4081840151061349e+00, 2.6106772442959039e+00, 2.8136171849644747e+00, 3.0170430069668734e+00, 3.2209950496501372e+00, 3.4255149448939752e+00, 3.6306457501139446e+00, 3.8364320925946052e+00, 4.0429203267128022e+00, 4.2501587058390200e+00, 4.4581975709748294e+00, 4.6670895585055892e+00, 4.8768898298307777e+00, 5.0876563260932981e+00, 5.2994500517810534e+00, 5.5123353916408391e+00, 5.7263804661537199e+00, 5.9416575318080138e+00, 6.1582434336162883e+00, 6.3762201188154259e+00, 6.5956752225409012e+00, 6.8167027385795480e+00, 7.0394037912138101e+00, 7.2638875278553732e+00, 7.4902721568710229e+00, 7.7186861610617425e+00, 7.9492697251276718e+00, 8.1821764257789713e+00, 8.4175752468453187e+00, 8.6556530000977201e+00, 8.8966172574222746e+00, 9.1406999342794091e+00, 9.3881617122605014e+00, 9.6392975564791730e+00, 9.8944436816224322e+00, 1.0153986464937166e+01, 1.0418374021858449e+01, 1.0688131495402112e+01, 1.0963881642425228e+01, 1.1246373170717687e+01, 1.1536520759384242e+01, 1.1835463313889939e+01, 1.2144651884544359e+01, 1.2465988324400744e+01, 1.2802056306622088e+01, 1.3156534338879860e+01, 1.3535007172173161e+01, 1.3946787810773682e+01, 1.4409953151712163e+01, 1.4971833315919479e+01}, + {-1.5036352557386012e+01, -1.4475268112055591e+01, -1.4012776679134205e+01, -1.3601609402686369e+01, -1.3223712557871778e+01, -1.2869784992006130e+01, -1.2534249024802044e+01, -1.2213430791710801e+01, -1.1904749877820654e+01, -1.1606306831707778e+01, -1.1316652442235313e+01, -1.1034649256479808e+01, -1.0759383772299557e+01, -1.0490108256609062e+01, -1.0226200775202839e+01, -9.9671368911110161e+00, -9.7124691040283810e+00, -9.4618115799659321e+00, -9.2148285900237301e+00, -8.9712256084886892e+00, -8.7307423554516284e+00, -8.4931472862936879e+00, -8.2582331746602566e+00, -8.0258135335048770e+00, -7.7957196866256542e+00, -7.5677983509350675e+00, -7.3419096239550905e+00, -7.1179252959243602e+00, -6.8957274242423345e+00, -6.6752071216509830e+00, -6.4562635198693066e+00, -6.2388028782578386e+00, -6.0227378131410365e+00, -5.8079866281147483e+00, -5.5944727293462684e+00, -5.3821241127798674e+00, -5.1708729124709514e+00, -4.9606550011220074e+00, -4.7514096353844053e+00, -4.5430791396990857e+00, -4.3356086234350091e+00, -4.1289457268926073e+00, -3.9230403924055310e+00, -3.7178446573254824e+00, -3.5133124661335695e+00, -3.3093994993045657e+00, -3.1060630168714907e+00, -2.9032617149079720e+00, -2.7009555933736791e+00, -2.4991058339609178e+00, -2.2976746867440045e+00, -2.0966253645719419e+00, -1.8959219442631448e+00, -1.6955292737615766e+00, -1.4954128844992702e+00, -1.2955389082829973e+00, -1.0958739980844798e+00, -8.9638525216554721e-01, -6.9704014101314027e-01, -4.9780643659506446e-01, -2.9865214347665664e-01, -9.9545431361682174e-02, 9.9545431361682174e-02, 2.9865214347665664e-01, 4.9780643659506446e-01, 6.9704014101314027e-01, 8.9638525216554721e-01, 1.0958739980844798e+00, 1.2955389082829973e+00, 1.4954128844992702e+00, 1.6955292737615766e+00, 1.8959219442631448e+00, 2.0966253645719419e+00, 2.2976746867440045e+00, 2.4991058339609178e+00, 2.7009555933736791e+00, 2.9032617149079720e+00, 3.1060630168714907e+00, 3.3093994993045657e+00, 3.5133124661335695e+00, 3.7178446573254824e+00, 3.9230403924055310e+00, 4.1289457268926073e+00, 4.3356086234350091e+00, 4.5430791396990857e+00, 4.7514096353844053e+00, 4.9606550011220074e+00, 5.1708729124709514e+00, 5.3821241127798674e+00, 5.5944727293462684e+00, 5.8079866281147483e+00, 6.0227378131410365e+00, 6.2388028782578386e+00, 6.4562635198693066e+00, 6.6752071216509830e+00, 6.8957274242423345e+00, 7.1179252959243602e+00, 7.3419096239550905e+00, 7.5677983509350675e+00, 7.7957196866256542e+00, 8.0258135335048770e+00, 8.2582331746602566e+00, 8.4931472862936879e+00, 8.7307423554516284e+00, 8.9712256084886892e+00, 9.2148285900237301e+00, 9.4618115799659321e+00, 9.7124691040283810e+00, 9.9671368911110161e+00, 1.0226200775202839e+01, 1.0490108256609062e+01, 1.0759383772299557e+01, 1.1034649256479808e+01, 1.1316652442235313e+01, 1.1606306831707778e+01, 1.1904749877820654e+01, 1.2213430791710801e+01, 1.2534249024802044e+01, 1.2869784992006130e+01, 1.3223712557871778e+01, 1.3601609402686369e+01, 1.4012776679134205e+01, 1.4475268112055591e+01, 1.5036352557386012e+01}, + {-1.5100607651623633e+01, -1.4540311217817694e+01, -1.4078487037622645e+01, -1.3667926962814708e+01, -1.3290600230854309e+01, -1.2937217433362431e+01, -1.2602207896558657e+01, -1.2281902356552338e+01, -1.1973723626537621e+01, -1.1675774634136665e+01, -1.1386607989721913e+01, -1.1105087678592627e+01, -1.0830301363602338e+01, -1.0561502276097833e+01, -1.0298069295499928e+01, -1.0039478682788769e+01, -9.7852835453915379e+00, -9.5350985857059971e+00, -9.2885885541431801e+00, -9.0454593582072000e+00, -8.8054511136991565e+00, -8.5683326410153491e+00, -8.3338970535972763e+00, -8.1019581834327870e+00, -7.8723476562632699e+00, -7.6449124769105978e+00, -7.4195130193460823e+00, -7.1960213409877323e+00, -6.9743197590276207e+00, -6.7542996402499806e+00, -6.5358603661027201e+00, -6.3189084426373174e+00, -6.1033567309754471e+00, -5.8891237786542385e+00, -5.6761332358780425e+00, -5.4643133436064266e+00, -5.2535964827157065e+00, -5.0439187753191463e+00, -4.8352197308201870e+00, -4.6274419304806678e+00, -4.4205307452707974e+00, -4.2144340825751483e+00, -4.0091021579943744e+00, -3.8044872890333408e+00, -3.6005437079246576e+00, -3.3972273912192827e+00, -3.1944959040967831e+00, -2.9923082576177755e+00, -2.7906247773689459e+00, -2.5894069821439305e+00, -2.3886174714670143e+00, -2.1882198209057537e+00, -1.9881784842371524e+00, -1.7884587016329878e+00, -1.5890264131159799e+00, -1.3898481766117783e+00, -1.1908910899840175e+00, -9.9212271649240336e-01, -7.9351101315811157e-01, -5.9502426155773702e-01, -3.9663100059735329e-01, -1.9829996084264417e-01, -0.0000000000000000e+00, 1.9829996084264417e-01, 3.9663100059735329e-01, 5.9502426155773702e-01, 7.9351101315811157e-01, 9.9212271649240336e-01, 1.1908910899840175e+00, 1.3898481766117783e+00, 1.5890264131159799e+00, 1.7884587016329878e+00, 1.9881784842371524e+00, 2.1882198209057537e+00, 2.3886174714670143e+00, 2.5894069821439305e+00, 2.7906247773689459e+00, 2.9923082576177755e+00, 3.1944959040967831e+00, 3.3972273912192827e+00, 3.6005437079246576e+00, 3.8044872890333408e+00, 4.0091021579943744e+00, 4.2144340825751483e+00, 4.4205307452707974e+00, 4.6274419304806678e+00, 4.8352197308201870e+00, 5.0439187753191463e+00, 5.2535964827157065e+00, 5.4643133436064266e+00, 5.6761332358780425e+00, 5.8891237786542385e+00, 6.1033567309754471e+00, 6.3189084426373174e+00, 6.5358603661027201e+00, 6.7542996402499806e+00, 6.9743197590276207e+00, 7.1960213409877323e+00, 7.4195130193460823e+00, 7.6449124769105978e+00, 7.8723476562632699e+00, 8.1019581834327870e+00, 8.3338970535972763e+00, 8.5683326410153491e+00, 8.8054511136991565e+00, 9.0454593582072000e+00, 9.2885885541431801e+00, 9.5350985857059971e+00, 9.7852835453915379e+00, 1.0039478682788769e+01, 1.0298069295499928e+01, 1.0561502276097833e+01, 1.0830301363602338e+01, 1.1105087678592627e+01, 1.1386607989721913e+01, 1.1675774634136665e+01, 1.1973723626537621e+01, 1.2281902356552338e+01, 1.2602207896558657e+01, 1.2937217433362431e+01, 1.3290600230854309e+01, 1.3667926962814708e+01, 1.4078487037622645e+01, 1.4540311217817694e+01, 1.5100607651623633e+01}, + {-1.5164601802095889e+01, -1.4605085809208793e+01, -1.4143922346496764e+01, -1.3733963425557441e+01, -1.3357201039800040e+01, -1.3004357419686706e+01, -1.2669868834839699e+01, -1.2350070580302615e+01, -1.2042388667769094e+01, -1.1744928381740326e+01, -1.1456244136772701e+01, -1.1175201342355262e+01, -1.0900888814619361e+01, -1.0632560739297817e+01, -1.0369596800621338e+01, -1.0111473949621464e+01, -9.8577458942500833e+00, -9.6080278666058625e+00, -9.3619850901178872e+00, -9.1193238995071209e+00, -8.8797848004974700e+00, -8.6431369728612566e+00, -8.4091738642920379e+00, -8.1777096203182182e+00, -7.9485761631426497e+00, -7.7216207799931862e+00, -7.4967041157356897e+00, -7.2736984893343362e+00, -7.0524864720372555e+00, -6.8329596788076081e+00, -6.6150177348097277e+00, -6.3985673866027142e+00, -6.1835217337299566e+00, -5.9697995610809267e+00, -5.7573247560732410e+00, -5.5460257976013150e+00, -5.3358353060028794e+00, -5.1266896451402619e+00, -4.9185285691809160e+00, -4.7112949078678819e+00, -4.5049342850546665e+00, -4.2993948660856276e+00, -4.0946271302677770e+00, -3.8905836652304053e+00, -3.6872189804268034e+00, -3.4844893374148405e+00, -3.2823525948738599e+00, -3.0807680665852137e+00, -2.8796963908316315e+00, -2.6790994098635554e+00, -2.4789400582443553e+00, -2.2791822590257231e+00, -2.0797908268232597e+00, -1.8807313769636194e+00, -1.6819702399610155e+00, -1.4834743806546613e+00, -1.2852113214015310e+00, -1.0871490687721614e+00, -8.8925604324227414e-01, -6.9150101141075326e-01, -4.9385302030582290e-01, -2.9628133336672019e-01, -9.8755367708345074e-02, 9.8755367708345074e-02, 2.9628133336672019e-01, 4.9385302030582290e-01, 6.9150101141075326e-01, 8.8925604324227414e-01, 1.0871490687721614e+00, 1.2852113214015310e+00, 1.4834743806546613e+00, 1.6819702399610155e+00, 1.8807313769636194e+00, 2.0797908268232597e+00, 2.2791822590257231e+00, 2.4789400582443553e+00, 2.6790994098635554e+00, 2.8796963908316315e+00, 3.0807680665852137e+00, 3.2823525948738599e+00, 3.4844893374148405e+00, 3.6872189804268034e+00, 3.8905836652304053e+00, 4.0946271302677770e+00, 4.2993948660856276e+00, 4.5049342850546665e+00, 4.7112949078678819e+00, 4.9185285691809160e+00, 5.1266896451402619e+00, 5.3358353060028794e+00, 5.5460257976013150e+00, 5.7573247560732410e+00, 5.9697995610809267e+00, 6.1835217337299566e+00, 6.3985673866027142e+00, 6.6150177348097277e+00, 6.8329596788076081e+00, 7.0524864720372555e+00, 7.2736984893343362e+00, 7.4967041157356897e+00, 7.7216207799931862e+00, 7.9485761631426497e+00, 8.1777096203182182e+00, 8.4091738642920379e+00, 8.6431369728612566e+00, 8.8797848004974700e+00, 9.1193238995071209e+00, 9.3619850901178872e+00, 9.6080278666058625e+00, 9.8577458942500833e+00, 1.0111473949621464e+01, 1.0369596800621338e+01, 1.0632560739297817e+01, 1.0900888814619361e+01, 1.1175201342355262e+01, 1.1456244136772701e+01, 1.1744928381740326e+01, 1.2042388667769094e+01, 1.2350070580302615e+01, 1.2669868834839699e+01, 1.3004357419686706e+01, 1.3357201039800040e+01, 1.3733963425557441e+01, 1.4143922346496764e+01, 1.4605085809208793e+01, 1.5164601802095889e+01}, + {-1.5228338148167351e+01, -1.4669595158833971e+01, -1.4209085995284871e+01, -1.3799722290211674e+01, -1.3423518590070948e+01, -1.3071208660474600e+01, -1.2737235652415684e+01, -1.2417939378869717e+01, -1.2110749020947747e+01, -1.1813772198267726e+01, -1.1525565112572695e+01, -1.1244994583785543e+01, -1.0971150569840248e+01, -1.0703288201027481e+01, -1.0440787957772772e+01, -1.0183127473450343e+01, -9.9298610495114250e+00, -9.6806044412474730e+00, -9.4350233389881648e+00, -9.1928244988460293e+00, -8.9537488108565402e+00, -8.7175658087076293e+00, -8.4840692689832480e+00, -8.2530736454457152e+00, -8.0244111514703373e+00, -7.7979293513870109e+00, -7.5734891556083452e+00, -7.3509631392269048e+00, -7.1302341220350698e+00, -6.9111939615465703e+00, -6.6937425208758290e+00, -6.4777867811645358e+00, -6.2632400742737344e+00, -6.0500214161419841e+00, -5.8380549248774187e+00, -5.6272693105464811e+00, -5.4175974259243240e+00, -5.2089758693153980e+00, -5.0013446320386352e+00, -4.7946467843764919e+00, -4.5888281947698371e+00, -4.3838372778464736e+00, -4.1796247675352030e+00, -3.9761435120673356e+00, -3.7733482881250526e+00, -3.5711956317782176e+00, -3.3696436841717392e+00, -3.1686520501953628e+00, -2.9681816685955908e+00, -2.7681946921824054e+00, -2.5686543769473498e+00, -2.3695249790490402e+00, -2.1707716587411507e+00, -1.9723603904195017e+00, -1.7742578780516791e+00, -1.5764314753267801e+00, -1.3788491099261777e+00, -1.1814792113700685e+00, -9.8429064194027271e-01, -7.8725263021825032e-01, -5.9033470680942102e-01, -3.9350664185130130e-01, -1.9673838392423251e-01, -0.0000000000000000e+00, 1.9673838392423251e-01, 3.9350664185130130e-01, 5.9033470680942102e-01, 7.8725263021825032e-01, 9.8429064194027271e-01, 1.1814792113700685e+00, 1.3788491099261777e+00, 1.5764314753267801e+00, 1.7742578780516791e+00, 1.9723603904195017e+00, 2.1707716587411507e+00, 2.3695249790490402e+00, 2.5686543769473498e+00, 2.7681946921824054e+00, 2.9681816685955908e+00, 3.1686520501953628e+00, 3.3696436841717392e+00, 3.5711956317782176e+00, 3.7733482881250526e+00, 3.9761435120673356e+00, 4.1796247675352030e+00, 4.3838372778464736e+00, 4.5888281947698371e+00, 4.7946467843764919e+00, 5.0013446320386352e+00, 5.2089758693153980e+00, 5.4175974259243240e+00, 5.6272693105464811e+00, 5.8380549248774187e+00, 6.0500214161419841e+00, 6.2632400742737344e+00, 6.4777867811645358e+00, 6.6937425208758290e+00, 6.9111939615465703e+00, 7.1302341220350698e+00, 7.3509631392269048e+00, 7.5734891556083452e+00, 7.7979293513870109e+00, 8.0244111514703373e+00, 8.2530736454457152e+00, 8.4840692689832480e+00, 8.7175658087076293e+00, 8.9537488108565402e+00, 9.1928244988460293e+00, 9.4350233389881648e+00, 9.6806044412474730e+00, 9.9298610495114250e+00, 1.0183127473450343e+01, 1.0440787957772772e+01, 1.0703288201027481e+01, 1.0971150569840248e+01, 1.1244994583785543e+01, 1.1525565112572695e+01, 1.1813772198267726e+01, 1.2110749020947747e+01, 1.2417939378869717e+01, 1.2737235652415684e+01, 1.3071208660474600e+01, 1.3423518590070948e+01, 1.3799722290211674e+01, 1.4209085995284871e+01, 1.4669595158833971e+01, 1.5228338148167351e+01}, + {-1.5291819766882741e+01, -1.4733842473589300e+01, -1.4273981304787835e+01, -1.3865206984476242e+01, -1.3489556412623140e+01, -1.3137774788027649e+01, -1.2804312082067129e+01, -1.2485512585349447e+01, -1.2178808619831244e+01, -1.1882310118878310e+01, -1.1594575054741449e+01, -1.1314471644289977e+01, -1.1041090976019634e+01, -1.0773689115161440e+01, -1.0511647329914869e+01, -1.0254443928470931e+01, -1.0001633798930122e+01, -9.7528332134391675e+00, -9.5077083232790560e+00, -9.2659663002961761e+00, -9.0273484133947868e+00, -8.7916245448886858e+00, -8.5585887950645070e+00, -8.3280559207901454e+00, -8.0998584215078964e+00, -7.8738441335354343e+00, -7.6498742276810061e+00, -7.4278215299523005e+00, -7.2075691033873337e+00, -6.9890090426447742e+00, -6.7720414432559277e+00, -6.5565735152644828e+00, -6.3425188170017792e+00, -6.1297965894221624e+00, -5.9183311750858119e+00, -5.7080515087680856e+00, -5.4988906689739094e+00, -5.2907854814771786e+00, -5.0836761674893394e+00, -4.8775060302648141e+00, -4.6722211749326386e+00, -4.4677702571485822e+00, -4.2641042568255187e+00, -4.0611762737492727e+00, -3.8589413423442820e+00, -3.6573562632353078e+00, -3.4563794495717373e+00, -3.2559707863506588e+00, -3.0560915012026797e+00, -2.8567040452974051e+00, -2.6577719831894839e+00, -2.4592598905657392e+00, -2.2611332589730622e+00, -2.0633584067085660e+00, -1.8659023951405984e+00, -1.6687329498037236e+00, -1.4718183856744860e+00, -1.2751275360891583e+00, -1.0786296848109087e+00, -8.8229450079298133e-01, -6.8609197521733478e-01, -4.8999236041545891e-01, -2.9396611030029574e-01, -9.7983821955818992e-02, 9.7983821955818992e-02, 2.9396611030029574e-01, 4.8999236041545891e-01, 6.8609197521733478e-01, 8.8229450079298133e-01, 1.0786296848109087e+00, 1.2751275360891583e+00, 1.4718183856744860e+00, 1.6687329498037236e+00, 1.8659023951405984e+00, 2.0633584067085660e+00, 2.2611332589730622e+00, 2.4592598905657392e+00, 2.6577719831894839e+00, 2.8567040452974051e+00, 3.0560915012026797e+00, 3.2559707863506588e+00, 3.4563794495717373e+00, 3.6573562632353078e+00, 3.8589413423442820e+00, 4.0611762737492727e+00, 4.2641042568255187e+00, 4.4677702571485822e+00, 4.6722211749326386e+00, 4.8775060302648141e+00, 5.0836761674893394e+00, 5.2907854814771786e+00, 5.4988906689739094e+00, 5.7080515087680856e+00, 5.9183311750858119e+00, 6.1297965894221624e+00, 6.3425188170017792e+00, 6.5565735152644828e+00, 6.7720414432559277e+00, 6.9890090426447742e+00, 7.2075691033873337e+00, 7.4278215299523005e+00, 7.6498742276810061e+00, 7.8738441335354343e+00, 8.0998584215078964e+00, 8.3280559207901454e+00, 8.5585887950645070e+00, 8.7916245448886858e+00, 9.0273484133947868e+00, 9.2659663002961761e+00, 9.5077083232790560e+00, 9.7528332134391675e+00, 1.0001633798930122e+01, 1.0254443928470931e+01, 1.0511647329914869e+01, 1.0773689115161440e+01, 1.1041090976019634e+01, 1.1314471644289977e+01, 1.1594575054741449e+01, 1.1882310118878310e+01, 1.2178808619831244e+01, 1.2485512585349447e+01, 1.2804312082067129e+01, 1.3137774788027649e+01, 1.3489556412623140e+01, 1.3865206984476242e+01, 1.4273981304787835e+01, 1.4733842473589300e+01, 1.5291819766882741e+01}, + {-1.5355049674683126e+01, -1.4797830896490307e+01, -1.4338611529008967e+01, -1.3930420866479178e+01, -1.3555317966130856e+01, -1.3204059359674192e+01, -1.2871101778903627e+01, -1.2552793952444540e+01, -1.2246571315023999e+01, -1.1950546092769182e+01, -1.1663278012068952e+01, -1.1383636673511937e+01, -1.1110714285141645e+01, -1.0843767837715543e+01, -1.0582179378973514e+01, -1.0325427884573593e+01, -1.0073068822584037e+01, -9.8247189758331519e+00, -9.5800449507652310e+00, -9.3387543294632973e+00, -9.1005887544187765e+00, -8.8653184514446028e+00, -8.6327378395084349e+00, -8.4026619736253494e+00, -8.1749236343739895e+00, -7.9493709251260496e+00, -7.7258652721212853e+00, -7.5042797472635216e+00, -7.2844976517401534e+00, -7.0664113121603904e+00, -6.8499210511601492e+00, -6.6349343022359886e+00, -6.4213648445851028e+00, -6.2091321383995863e+00, -5.9981607447217984e+00, -5.7883798168558824e+00, -5.5797226526273649e+00, -5.3721262986220681e+00, -5.1655311990180879e+00, -4.9598808828268046e+00, -4.7551216843394561e+00, -4.5512024923799270e+00, -4.3480745246271999e+00, -4.1456911238198586e+00, -3.9440075731117403e+00, -3.7429809282294269e+00, -3.5425698644023571e+00, -3.3427345363058465e+00, -3.1434364494849998e+00, -2.9446383419204585e+00, -2.7463040745609382e+00, -2.5483985297872240e+00, -2.3508875168916132e+00, -2.1537376837587945e+00, -1.9569164340215148e+00, -1.7603918490392145e+00, -1.5641326141118630e+00, -1.3681079483960505e+00, -1.1722875380371232e+00, -9.7664147207086760e-01, -7.8114018068176028e-01, -5.8575437543280562e-01, -3.9045499110504589e-01, -1.9521312880340755e-01, -0.0000000000000000e+00, 1.9521312880340755e-01, 3.9045499110504589e-01, 5.8575437543280562e-01, 7.8114018068176028e-01, 9.7664147207086760e-01, 1.1722875380371232e+00, 1.3681079483960505e+00, 1.5641326141118630e+00, 1.7603918490392145e+00, 1.9569164340215148e+00, 2.1537376837587945e+00, 2.3508875168916132e+00, 2.5483985297872240e+00, 2.7463040745609382e+00, 2.9446383419204585e+00, 3.1434364494849998e+00, 3.3427345363058465e+00, 3.5425698644023571e+00, 3.7429809282294269e+00, 3.9440075731117403e+00, 4.1456911238198586e+00, 4.3480745246271999e+00, 4.5512024923799270e+00, 4.7551216843394561e+00, 4.9598808828268046e+00, 5.1655311990180879e+00, 5.3721262986220681e+00, 5.5797226526273649e+00, 5.7883798168558824e+00, 5.9981607447217984e+00, 6.2091321383995863e+00, 6.4213648445851028e+00, 6.6349343022359886e+00, 6.8499210511601492e+00, 7.0664113121603904e+00, 7.2844976517401534e+00, 7.5042797472635216e+00, 7.7258652721212853e+00, 7.9493709251260496e+00, 8.1749236343739895e+00, 8.4026619736253494e+00, 8.6327378395084349e+00, 8.8653184514446028e+00, 9.1005887544187765e+00, 9.3387543294632973e+00, 9.5800449507652310e+00, 9.8247189758331519e+00, 1.0073068822584037e+01, 1.0325427884573593e+01, 1.0582179378973514e+01, 1.0843767837715543e+01, 1.1110714285141645e+01, 1.1383636673511937e+01, 1.1663278012068952e+01, 1.1950546092769182e+01, 1.2246571315023999e+01, 1.2552793952444540e+01, 1.2871101778903627e+01, 1.3204059359674192e+01, 1.3555317966130856e+01, 1.3930420866479178e+01, 1.4338611529008967e+01, 1.4797830896490307e+01, 1.5355049674683126e+01}, + {-1.5418030829061875e+01, -1.4861563508435680e+01, -1.4402979857014893e+01, -1.3995367226732167e+01, -1.3620806639033354e+01, -1.3270065859909028e+01, -1.2937608322597471e+01, -1.2619787154794016e+01, -1.2314040876404606e+01, -1.2018483985703304e+01, -1.1731677947147649e+01, -1.1452493732070961e+01, -1.1180024657270208e+01, -1.0913528629812234e+01, -1.0652388468924656e+01, -1.0396083810552501e+01, -1.0144170696212489e+01, -9.8962664133982265e+00, -9.6520380180840490e+00, -9.4111934972461668e+00, -9.1734748618357518e+00, -8.9386526761940264e+00, -8.7065216731065060e+00, -8.4768972009392183e+00, -8.2496123166430966e+00, -8.0245153858819371e+00, -7.8014680855407574e+00, -7.5803437285851887e+00, -7.3610258494479153e+00, -7.1434070016947420e+00, -6.9273877299634155e+00, -6.7128756859735788e+00, -6.4997848644138259e+00, -6.2880349391774812e+00, -6.0775506840731746e+00, -5.8682614650210780e+00, -5.6601007930399492e+00, -5.4530059291673494e+00, -5.2469175339362204e+00, -5.0417793552319132e+00, -4.8375379493332744e+00, -4.6341424307446326e+00, -4.4315442470876985e+00, -4.2296969758707617e+00, -4.0285561404088908e+00, -3.8280790425501139e+00, -3.6282246101824178e+00, -3.4289532577657682e+00, -3.2302267583609394e+00, -3.0320081258198956e+00, -2.8342615059664689e+00, -2.6369520757359015e+00, -2.4400459493612159e+00, -2.2435100907965948e+00, -2.0473122316554950e+00, -1.8514207940163270e+00, -1.6558048175129170e+00, -1.4604338901821434e+00, -1.2652780825883267e+00, -1.0703078847841583e+00, -8.7549414570205153e-01, -6.8080801459844631e-01, -4.8622088419741660e-01, -2.9170433519935240e-01, -9.7230081835906187e-02, 9.7230081835906187e-02, 2.9170433519935240e-01, 4.8622088419741660e-01, 6.8080801459844631e-01, 8.7549414570205153e-01, 1.0703078847841583e+00, 1.2652780825883267e+00, 1.4604338901821434e+00, 1.6558048175129170e+00, 1.8514207940163270e+00, 2.0473122316554950e+00, 2.2435100907965948e+00, 2.4400459493612159e+00, 2.6369520757359015e+00, 2.8342615059664689e+00, 3.0320081258198956e+00, 3.2302267583609394e+00, 3.4289532577657682e+00, 3.6282246101824178e+00, 3.8280790425501139e+00, 4.0285561404088908e+00, 4.2296969758707617e+00, 4.4315442470876985e+00, 4.6341424307446326e+00, 4.8375379493332744e+00, 5.0417793552319132e+00, 5.2469175339362204e+00, 5.4530059291673494e+00, 5.6601007930399492e+00, 5.8682614650210780e+00, 6.0775506840731746e+00, 6.2880349391774812e+00, 6.4997848644138259e+00, 6.7128756859735788e+00, 6.9273877299634155e+00, 7.1434070016947420e+00, 7.3610258494479153e+00, 7.5803437285851887e+00, 7.8014680855407574e+00, 8.0245153858819371e+00, 8.2496123166430966e+00, 8.4768972009392183e+00, 8.7065216731065060e+00, 8.9386526761940264e+00, 9.1734748618357518e+00, 9.4111934972461668e+00, 9.6520380180840490e+00, 9.8962664133982265e+00, 1.0144170696212489e+01, 1.0396083810552501e+01, 1.0652388468924656e+01, 1.0913528629812234e+01, 1.1180024657270208e+01, 1.1452493732070961e+01, 1.1731677947147649e+01, 1.2018483985703304e+01, 1.2314040876404606e+01, 1.2619787154794016e+01, 1.2937608322597471e+01, 1.3270065859909028e+01, 1.3620806639033354e+01, 1.3995367226732167e+01, 1.4402979857014893e+01, 1.4861563508435680e+01, 1.5418030829061875e+01}, + {-1.5480766130162912e+01, -1.4925043329908892e+01, -1.4467089414730456e+01, -1.4060049290015051e+01, -1.3686025751508065e+01, -1.3335797702455430e+01, -1.3003835219535608e+01, -1.2686495791216792e+01, -1.2381220995463224e+01, -1.2086127582443233e+01, -1.1799778738905447e+01, -1.1521046794198202e+01, -1.1249026163290472e+01, -1.0982975660531801e+01, -1.0722278868759513e+01, -1.0466416077189237e+01, -1.0214943894423017e+01, -9.9674801067548007e+00, -9.7236922142042346e+00, -9.4832886034446808e+00, -9.2460116489073236e+00, -9.0116322486398488e+00, -8.7799454445339524e+00, -8.5507668736650881e+00, -8.3239298647512676e+00, -8.0992830411501870e+00, -7.8766883257751701e+00, -7.6560192679949264e+00, -7.4371596307659544e+00, -7.2200021898070377e+00, -7.0044477068537327e+00, -6.7904040468269269e+00, -6.5777854147500525e+00, -6.3665116929098069e+00, -6.1565078624054426e+00, -5.9477034961131627e+00, -5.7400323123838195e+00, -5.5334317806272333e+00, -5.3278427714156580e+00, -5.1232092449384545e+00, -4.9194779726184912e+00, -4.7165982875032402e+00, -4.5145218597049430e+00, -4.3132024937121241e+00, -4.1125959448506144e+00, -3.9126597525531843e+00, -3.7133530884165373e+00, -3.5146366172935721e+00, -3.3164723698963634e+00, -3.1188236255781381e+00, -2.9216548041266144e+00, -2.7249313655408702e+00, -2.5286197168834539e+00, -2.3326871254017765e+00, -2.1371016372005704e+00, -1.9418320008225314e+00, -1.7468475951589244e+00, -1.5521183611674445e+00, -1.3576147369221905e+00, -1.1633075955612597e+00, -9.6916818573207730e-01, -7.7516807416380029e-01, -5.8127909002062172e-01, -3.8747327070995596e-01, -1.9372280883577261e-01, -0.0000000000000000e+00, 1.9372280883577261e-01, 3.8747327070995596e-01, 5.8127909002062172e-01, 7.7516807416380029e-01, 9.6916818573207730e-01, 1.1633075955612597e+00, 1.3576147369221905e+00, 1.5521183611674445e+00, 1.7468475951589244e+00, 1.9418320008225314e+00, 2.1371016372005704e+00, 2.3326871254017765e+00, 2.5286197168834539e+00, 2.7249313655408702e+00, 2.9216548041266144e+00, 3.1188236255781381e+00, 3.3164723698963634e+00, 3.5146366172935721e+00, 3.7133530884165373e+00, 3.9126597525531843e+00, 4.1125959448506144e+00, 4.3132024937121241e+00, 4.5145218597049430e+00, 4.7165982875032402e+00, 4.9194779726184912e+00, 5.1232092449384545e+00, 5.3278427714156580e+00, 5.5334317806272333e+00, 5.7400323123838195e+00, 5.9477034961131627e+00, 6.1565078624054426e+00, 6.3665116929098069e+00, 6.5777854147500525e+00, 6.7904040468269269e+00, 7.0044477068537327e+00, 7.2200021898070377e+00, 7.4371596307659544e+00, 7.6560192679949264e+00, 7.8766883257751701e+00, 8.0992830411501870e+00, 8.3239298647512676e+00, 8.5507668736650881e+00, 8.7799454445339524e+00, 9.0116322486398488e+00, 9.2460116489073236e+00, 9.4832886034446808e+00, 9.7236922142042346e+00, 9.9674801067548007e+00, 1.0214943894423017e+01, 1.0466416077189237e+01, 1.0722278868759513e+01, 1.0982975660531801e+01, 1.1249026163290472e+01, 1.1521046794198202e+01, 1.1799778738905447e+01, 1.2086127582443233e+01, 1.2381220995463224e+01, 1.2686495791216792e+01, 1.3003835219535608e+01, 1.3335797702455430e+01, 1.3686025751508065e+01, 1.4060049290015051e+01, 1.4467089414730456e+01, 1.4925043329908892e+01, 1.5480766130162912e+01}, + {-1.5543258422323774e+01, -1.4988273322620483e+01, -1.4530943266670407e+01, -1.4124470217193569e+01, -1.3750978557373212e+01, -1.3401258232252896e+01, -1.3069785904893536e+01, -1.2752923386873304e+01, -1.2448115287552957e+01, -1.2153480589094658e+01, -1.1867584185044096e+01, -1.1589299750272769e+01, -1.1317722787546410e+01, -1.1052113009654860e+01, -1.0791854755335825e+01, -1.0536428960217005e+01, -1.0285392793773033e+01, -1.0038364535378761e+01, -9.7950121237570809e+00, -9.5550443402238834e+00, -9.3182039178520490e+00, -9.0842620837165757e+00, -8.8530141842483925e+00, -8.6242761407386386e+00, -8.3978815492187184e+00, -8.1736792862980483e+00, -7.9515315164625289e+00, -7.7313120209923101e+00, -7.5129047868198517e+00, -7.2962028071941081e+00, -7.0811070562331242e+00, -6.8675256072344579e+00, -6.6553728706063735e+00, -6.4445689319376820e+00, -6.2350389743700507e+00, -6.0267127723148342e+00, -5.8195242458455034e+00, -5.6134110669298432e+00, -5.4083143101435791e+00, -5.2041781417053947e+00, -5.0009495416506535e+00, -4.7985780547627241e+00, -4.5970155665415948e+00, -4.3962161010367922e+00, -4.1961356378270693e+00, -3.9967319458099735e+00, -3.7979644317837824e+00, -3.5997940020732910e+00, -3.4021829356783408e+00, -3.2050947676167678e+00, -3.0084941812975128e+00, -2.8123469088994537e+00, -2.6166196388511782e+00, -2.4212799296093106e+00, -2.2262961290209549e+00, -2.0316372986313107e+00, -1.8372731423624578e+00, -1.6431739390450815e+00, -1.4493104783328268e+00, -1.2556539995700138e+00, -1.0621761332184900e+00, -8.6884884447915023e-01, -6.7564437876870465e-01, -4.8253520873311562e-01, -2.8949398249614278e-01, -9.6493472854955881e-02, 9.6493472854955881e-02, 2.8949398249614278e-01, 4.8253520873311562e-01, 6.7564437876870465e-01, 8.6884884447915023e-01, 1.0621761332184900e+00, 1.2556539995700138e+00, 1.4493104783328268e+00, 1.6431739390450815e+00, 1.8372731423624578e+00, 2.0316372986313107e+00, 2.2262961290209549e+00, 2.4212799296093106e+00, 2.6166196388511782e+00, 2.8123469088994537e+00, 3.0084941812975128e+00, 3.2050947676167678e+00, 3.4021829356783408e+00, 3.5997940020732910e+00, 3.7979644317837824e+00, 3.9967319458099735e+00, 4.1961356378270693e+00, 4.3962161010367922e+00, 4.5970155665415948e+00, 4.7985780547627241e+00, 5.0009495416506535e+00, 5.2041781417053947e+00, 5.4083143101435791e+00, 5.6134110669298432e+00, 5.8195242458455034e+00, 6.0267127723148342e+00, 6.2350389743700507e+00, 6.4445689319376820e+00, 6.6553728706063735e+00, 6.8675256072344579e+00, 7.0811070562331242e+00, 7.2962028071941081e+00, 7.5129047868198517e+00, 7.7313120209923101e+00, 7.9515315164625289e+00, 8.1736792862980483e+00, 8.3978815492187184e+00, 8.6242761407386386e+00, 8.8530141842483925e+00, 9.0842620837165757e+00, 9.3182039178520490e+00, 9.5550443402238834e+00, 9.7950121237570809e+00, 1.0038364535378761e+01, 1.0285392793773033e+01, 1.0536428960217005e+01, 1.0791854755335825e+01, 1.1052113009654860e+01, 1.1317722787546410e+01, 1.1589299750272769e+01, 1.1867584185044096e+01, 1.2153480589094658e+01, 1.2448115287552957e+01, 1.2752923386873304e+01, 1.3069785904893536e+01, 1.3401258232252896e+01, 1.3750978557373212e+01, 1.4124470217193569e+01, 1.4530943266670407e+01, 1.4988273322620483e+01, 1.5543258422323774e+01}, + {-1.5605510495565703e+01, -1.5051256391093448e+01, -1.4594544417610667e+01, -1.4188633106973045e+01, -1.3815668245922964e+01, -1.3466450727373902e+01, -1.3135463744634585e+01, -1.2819073395348772e+01, -1.2514727294059055e+01, -1.2220546635363748e+01, -1.1935098004387349e+01, -1.1657256409263454e+01, -1.1386118430379335e+01, -1.1120944670301025e+01, -1.0861120216120376e+01, -1.0606126643170979e+01, -1.0355521675732227e+01, -1.0108924080680463e+01, -9.8660022302368411e+00, -9.6264652954408270e+00, -9.3900563633043106e+00, -9.1565469853869601e+00, -8.9257328082304568e+00, -8.6974300329890397e+00, -8.4714725186984587e+00, -8.2477093909264614e+00, -8.0260030514294165e+00, -7.8062275090663409e+00, -7.5882669703629624e+00, -7.3720146416474837e+00, -7.1573717048843459e+00, -6.9442464371104355e+00, -6.7325534493647661e+00, -6.5222130256523068e+00, -6.3131505461243611e+00, -6.1052959815328816e+00, -5.8985834483025466e+00, -5.6929508153954593e+00, -5.4883393556191784e+00, -5.2846934352257779e+00, -5.0819602366259380e+00, -4.8800895098428096e+00, -4.6790333489905045e+00, -4.4787459906088296e+00, -4.2791836311409464e+00, -4.0803042612209337e+00, -3.8820675147573152e+00, -3.6844345310674940e+00, -3.4873678285452550e+00, -3.2908311885362425e+00, -3.0947895482603323e+00, -2.8992089017596818e+00, -2.7040562079709125e+00, -2.5092993051224148e+00, -2.3149068307458065e+00, -2.1208481466662792e+00, -1.9270932684016822e+00, -1.7336127984562590e+00, -1.5403778630431328e+00, -1.3473600518110582e+00, -1.1545313601863669e+00, -9.6186413397127435e-01, -7.6933101586525243e-01, -5.7690489359762542e-01, -3.8455884937721463e-01, -1.9226611037913860e-01, -0.0000000000000000e+00, 1.9226611037913860e-01, 3.8455884937721463e-01, 5.7690489359762542e-01, 7.6933101586525243e-01, 9.6186413397127435e-01, 1.1545313601863669e+00, 1.3473600518110582e+00, 1.5403778630431328e+00, 1.7336127984562590e+00, 1.9270932684016822e+00, 2.1208481466662792e+00, 2.3149068307458065e+00, 2.5092993051224148e+00, 2.7040562079709125e+00, 2.8992089017596818e+00, 3.0947895482603323e+00, 3.2908311885362425e+00, 3.4873678285452550e+00, 3.6844345310674940e+00, 3.8820675147573152e+00, 4.0803042612209337e+00, 4.2791836311409464e+00, 4.4787459906088296e+00, 4.6790333489905045e+00, 4.8800895098428096e+00, 5.0819602366259380e+00, 5.2846934352257779e+00, 5.4883393556191784e+00, 5.6929508153954593e+00, 5.8985834483025466e+00, 6.1052959815328816e+00, 6.3131505461243611e+00, 6.5222130256523068e+00, 6.7325534493647661e+00, 6.9442464371104355e+00, 7.1573717048843459e+00, 7.3720146416474837e+00, 7.5882669703629624e+00, 7.8062275090663409e+00, 8.0260030514294165e+00, 8.2477093909264614e+00, 8.4714725186984587e+00, 8.6974300329890397e+00, 8.9257328082304568e+00, 9.1565469853869601e+00, 9.3900563633043106e+00, 9.6264652954408270e+00, 9.8660022302368411e+00, 1.0108924080680463e+01, 1.0355521675732227e+01, 1.0606126643170979e+01, 1.0861120216120376e+01, 1.1120944670301025e+01, 1.1386118430379335e+01, 1.1657256409263454e+01, 1.1935098004387349e+01, 1.2220546635363748e+01, 1.2514727294059055e+01, 1.2819073395348772e+01, 1.3135463744634585e+01, 1.3466450727373902e+01, 1.3815668245922964e+01, 1.4188633106973045e+01, 1.4594544417610667e+01, 1.5051256391093448e+01, 1.5605510495565703e+01}, + {-1.5667525087033042e+01, -1.5113995384194148e+01, -1.4657895814201638e+01, -1.4252540997590891e+01, -1.3880097943698006e+01, -1.3531378400872688e+01, -1.3200872037437804e+01, -1.2884949200661589e+01, -1.2581060484489544e+01, -1.2287329276732219e+01, -1.2002323839142806e+01, -1.1724920501080165e+01, -1.1454216910571811e+01, -1.1189474551468571e+01, -1.0930079251827893e+01, -1.0675513220130126e+01, -1.0425334729531320e+01, -1.0179163028964693e+01, -9.9366669190764370e+00, -9.6975559558409401e+00, -9.4615735756363968e+00, -9.2284916500953180e+00, -8.9981061215741249e+00, -8.7702334668725097e+00, -8.5447078038596302e+00, -8.3213785029101519e+00, -8.1001081988952368e+00, -7.8807711240717229e+00, -7.6632517003331104e+00, -7.4474433427993905e+00, -7.2332474369156490e+00, -7.0205724589985739e+00, -6.8093332161497848e+00, -6.5994501860991619e+00, -6.3908489411790317e+00, -6.1834596435017497e+00, -5.9772166006971021e+00, -5.7720578733949548e+00, -5.5679249271127809e+00, -5.3647623224033971e+00, -5.1625174380934791e+00, -4.9611402232433406e+00, -4.7605829741178525e+00, -4.5608001330046735e+00, -4.3617481061705252e+00, -4.1633850986262280e+00, -3.9656709636900676e+00, -3.7685670656076877e+00, -3.5720361537138379e+00, -3.3760422468139430e+00, -3.1805505266274205e+00, -2.9855272392745684e+00, -2.7909396039085173e+00, -2.5967557276963822e+00, -2.4029445264418832e+00, -2.2094756502175628e+00, -2.0163194134400269e+00, -1.8234467288779213e+00, -1.6308290451307998e+00, -1.4384382871587706e+00, -1.2462467994785644e+00, -1.0542272916723083e+00, -8.6235278588129705e-01, -6.7059656597901129e-01, -4.7893212813590247e-01, -2.8733313250340886e-01, -9.5773355756546857e-02, 9.5773355756546857e-02, 2.8733313250340886e-01, 4.7893212813590247e-01, 6.7059656597901129e-01, 8.6235278588129705e-01, 1.0542272916723083e+00, 1.2462467994785644e+00, 1.4384382871587706e+00, 1.6308290451307998e+00, 1.8234467288779213e+00, 2.0163194134400269e+00, 2.2094756502175628e+00, 2.4029445264418832e+00, 2.5967557276963822e+00, 2.7909396039085173e+00, 2.9855272392745684e+00, 3.1805505266274205e+00, 3.3760422468139430e+00, 3.5720361537138379e+00, 3.7685670656076877e+00, 3.9656709636900676e+00, 4.1633850986262280e+00, 4.3617481061705252e+00, 4.5608001330046735e+00, 4.7605829741178525e+00, 4.9611402232433406e+00, 5.1625174380934791e+00, 5.3647623224033971e+00, 5.5679249271127809e+00, 5.7720578733949548e+00, 5.9772166006971021e+00, 6.1834596435017497e+00, 6.3908489411790317e+00, 6.5994501860991619e+00, 6.8093332161497848e+00, 7.0205724589985739e+00, 7.2332474369156490e+00, 7.4474433427993905e+00, 7.6632517003331104e+00, 7.8807711240717229e+00, 8.1001081988952368e+00, 8.3213785029101519e+00, 8.5447078038596302e+00, 8.7702334668725097e+00, 8.9981061215741249e+00, 9.2284916500953180e+00, 9.4615735756363968e+00, 9.6975559558409401e+00, 9.9366669190764370e+00, 1.0179163028964693e+01, 1.0425334729531320e+01, 1.0675513220130126e+01, 1.0930079251827893e+01, 1.1189474551468571e+01, 1.1454216910571811e+01, 1.1724920501080165e+01, 1.2002323839142806e+01, 1.2287329276732219e+01, 1.2581060484489544e+01, 1.2884949200661589e+01, 1.3200872037437804e+01, 1.3531378400872688e+01, 1.3880097943698006e+01, 1.4252540997590891e+01, 1.4657895814201638e+01, 1.5113995384194148e+01, 1.5667525087033042e+01}, + {-1.5729304882383959e+01, -1.5176493096610994e+01, -1.4721000346526051e+01, -1.4316196868450396e+01, -1.3944270716194302e+01, -1.3596044402569063e+01, -1.3266014016557564e+01, -1.2950554119200040e+01, -1.2647118258490758e+01, -1.2353831996553668e+01, -1.2069265257081389e+01, -1.1792295678839055e+01, -1.1522021967701262e+01, -1.1257706480479557e+01, -1.0998735778960949e+01, -1.0744592698355470e+01, -1.0494836054902457e+01, -1.0249085574277188e+01, -1.0007010480604432e+01, -9.7683207101299594e+00, -9.5327600441503151e+00, -9.3001006700843707e+00, -9.0701388219340853e+00, -8.8426912480559938e+00, -8.6175923211137029e+00, -8.3946916522729023e+00, -8.1738521055035420e+00, -7.9549481324236444e+00, -7.7378643662186803e+00, -7.5224944266685263e+00, -7.3087398984951246e+00, -7.0965094530044173e+00, -6.8857180889690319e+00, -6.6762864733372753e+00, -6.4681403659874999e+00, -6.2612101156154036e+00, -6.0554302161231597e+00, -5.8507389147062092e+00, -5.6470778643062038e+00, -5.4443918142929100e+00, -5.2426283342121209e+00, -5.0417375662357022e+00, -4.8416720026085907e+00, -4.6423862849333188e+00, -4.4438370225867869e+00, -4.2459826279436079e+00, -4.0487831663989748e+00, -3.8522002194524045e+00, -3.6561967593406961e+00, -3.4607370339009882e+00, -3.2657864605087177e+00, -3.0713115280751384e+00, -2.8772797062087854e+00, -2.6836593607479262e+00, -2.4904196749593304e+00, -2.2975305757745934e+00, -2.1049626645007851e+00, -1.9126871514986146e+00, -1.7206757943700177e+00, -1.5289008392390442e+00, -1.3373349647460135e+00, -1.1459512284058875e+00, -9.5472301500823675e-01, -7.6362398675858623e-01, -5.7262803487972669e-01, -3.8170923240711668e-01, -1.9084178792504236e-01, -0.0000000000000000e+00, 1.9084178792504236e-01, 3.8170923240711668e-01, 5.7262803487972669e-01, 7.6362398675858623e-01, 9.5472301500823675e-01, 1.1459512284058875e+00, 1.3373349647460135e+00, 1.5289008392390442e+00, 1.7206757943700177e+00, 1.9126871514986146e+00, 2.1049626645007851e+00, 2.2975305757745934e+00, 2.4904196749593304e+00, 2.6836593607479262e+00, 2.8772797062087854e+00, 3.0713115280751384e+00, 3.2657864605087177e+00, 3.4607370339009882e+00, 3.6561967593406961e+00, 3.8522002194524045e+00, 4.0487831663989748e+00, 4.2459826279436079e+00, 4.4438370225867869e+00, 4.6423862849333188e+00, 4.8416720026085907e+00, 5.0417375662357022e+00, 5.2426283342121209e+00, 5.4443918142929100e+00, 5.6470778643062038e+00, 5.8507389147062092e+00, 6.0554302161231597e+00, 6.2612101156154036e+00, 6.4681403659874999e+00, 6.6762864733372753e+00, 6.8857180889690319e+00, 7.0965094530044173e+00, 7.3087398984951246e+00, 7.5224944266685263e+00, 7.7378643662186803e+00, 7.9549481324236444e+00, 8.1738521055035420e+00, 8.3946916522729023e+00, 8.6175923211137029e+00, 8.8426912480559938e+00, 9.0701388219340853e+00, 9.3001006700843707e+00, 9.5327600441503151e+00, 9.7683207101299594e+00, 1.0007010480604432e+01, 1.0249085574277188e+01, 1.0494836054902457e+01, 1.0744592698355470e+01, 1.0998735778960949e+01, 1.1257706480479557e+01, 1.1522021967701262e+01, 1.1792295678839055e+01, 1.2069265257081389e+01, 1.2353831996553668e+01, 1.2647118258490758e+01, 1.2950554119200040e+01, 1.3266014016557564e+01, 1.3596044402569063e+01, 1.3944270716194302e+01, 1.4316196868450396e+01, 1.4721000346526051e+01, 1.5176493096610994e+01, 1.5729304882383959e+01}, + {-1.5790852517134587e+01, -1.5238752270283085e+01, -1.4783860849603613e+01, -1.4379603641698345e+01, -1.4008189569512616e+01, -1.3660451820769911e+01, -1.3330892851617801e+01, -1.3015891401590464e+01, -1.2712903947791023e+01, -1.2420058208074661e+01, -1.2135925753638015e+01, -1.1859385521045176e+01, -1.1589537264407285e+01, -1.1325644205334678e+01, -1.1067093632255466e+01, -1.0813369000829548e+01, -1.0564029664716180e+01, -1.0318695821142974e+01, -1.0077037112888743e+01, -9.8387638519273803e+00, -9.6036201601455531e+00, -9.3713785365821725e+00, -9.1418355028369902e+00, -8.9148080748582679e+00, -8.6901308761912386e+00, -8.4676537549061486e+00, -8.2472398001890390e+00, -8.0287636791201553e+00, -7.8121102322437741e+00, -7.5971732800158449e+00, -7.3838546023854859e+00, -7.1720630615179752e+00, -6.9617138436331016e+00, -6.7527278005665341e+00, -6.5450308752913493e+00, -6.3385535985021413e+00, -6.1332306456429340e+00, -5.9290004455850367e+00, -5.7258048336320568e+00, -5.5235887427222501e+00, -5.3222999276716845e+00, -5.1218887180998118e+00, -4.9223077963371686e+00, -4.7235119971600676e+00, -4.5254581266508760e+00, -4.3281047978617426e+00, -4.1314122812779592e+00, -3.9353423683453870e+00, -3.7398582465531405e+00, -3.5449243847552383e+00, -3.3505064275787246e+00, -3.1565710979056170e+00, -2.9630861065357892e+00, -2.7700200682405702e+00, -2.5773424235052076e+00, -2.3850233653343853e+00, -2.1930337705606084e+00, -2.0013451351519014e+00, -1.8099295130641593e+00, -1.6187594582257014e+00, -1.4278079692779639e+00, -1.2370484367275345e+00, -1.0464545921915449e+00, -8.5600045944125114e-01, -6.6566030696788747e-01, -4.7540860181095812e-01, -2.8521996440226244e-01, -9.5069124189415724e-02, 9.5069124189415724e-02, 2.8521996440226244e-01, 4.7540860181095812e-01, 6.6566030696788747e-01, 8.5600045944125114e-01, 1.0464545921915449e+00, 1.2370484367275345e+00, 1.4278079692779639e+00, 1.6187594582257014e+00, 1.8099295130641593e+00, 2.0013451351519014e+00, 2.1930337705606084e+00, 2.3850233653343853e+00, 2.5773424235052076e+00, 2.7700200682405702e+00, 2.9630861065357892e+00, 3.1565710979056170e+00, 3.3505064275787246e+00, 3.5449243847552383e+00, 3.7398582465531405e+00, 3.9353423683453870e+00, 4.1314122812779592e+00, 4.3281047978617426e+00, 4.5254581266508760e+00, 4.7235119971600676e+00, 4.9223077963371686e+00, 5.1218887180998118e+00, 5.3222999276716845e+00, 5.5235887427222501e+00, 5.7258048336320568e+00, 5.9290004455850367e+00, 6.1332306456429340e+00, 6.3385535985021413e+00, 6.5450308752913493e+00, 6.7527278005665341e+00, 6.9617138436331016e+00, 7.1720630615179752e+00, 7.3838546023854859e+00, 7.5971732800158449e+00, 7.8121102322437741e+00, 8.0287636791201553e+00, 8.2472398001890390e+00, 8.4676537549061486e+00, 8.6901308761912386e+00, 8.9148080748582679e+00, 9.1418355028369902e+00, 9.3713785365821725e+00, 9.6036201601455531e+00, 9.8387638519273803e+00, 1.0077037112888743e+01, 1.0318695821142974e+01, 1.0564029664716180e+01, 1.0813369000829548e+01, 1.1067093632255466e+01, 1.1325644205334678e+01, 1.1589537264407285e+01, 1.1859385521045176e+01, 1.2135925753638015e+01, 1.2420058208074661e+01, 1.2712903947791023e+01, 1.3015891401590464e+01, 1.3330892851617801e+01, 1.3660451820769911e+01, 1.4008189569512616e+01, 1.4379603641698345e+01, 1.4783860849603613e+01, 1.5238752270283085e+01, 1.5790852517134587e+01}, + {-1.5852170577958367e+01, -1.5300775595780827e+01, -1.4846480104844703e+01, -1.4442764183748782e+01, -1.4071857451951351e+01, -1.3724603683931077e+01, -1.3395511650343654e+01, -1.3080964234499790e+01, -1.2778420818075578e+01, -1.2486011256383852e+01, -1.2202308753936913e+01, -1.1926193533696322e+01, -1.1656766388576511e+01, -1.1393291396981837e+01, -1.1135156567035956e+01, -1.0881845968701494e+01, -1.0632919487519736e+01, -1.0387997787201458e+01, -1.0146750924472403e+01, -9.9088895826069283e+00, -9.6741582198685645e+00, -9.4423296428652392e+00, -9.2132006568631315e+00, -8.9865885415552977e+00, -8.7623281675764328e+00, -8.5402696161385645e+00, -8.3202761978883633e+00, -8.1022227916007061e+00, -7.8859944413814738e+00, -7.6714851645199493e+00, -7.4585969322894226e+00, -7.2472387937374041e+00, -7.0373261184664502e+00, -6.8287799390351633e+00, -6.6215263772344395e+00, -6.4154961413560549e+00, -6.2106240838470441e+00, -6.0068488105662023e+00, -5.8041123343284946e+00, -5.6023597666149243e+00, -5.4015390422975438e+00, -5.2016006730266913e+00, -5.0024975255849276e+00, -4.8041846220567344e+00, -4.6066189591163766e+00, -4.4097593441152032e+00, -4.2135662459677485e+00, -4.0180016591039696e+00, -3.8230289789816339e+00, -3.6286128878452084e+00, -3.4347192495813528e+00, -3.2413150126609418e+00, -3.0483681202772592e+00, -2.8558474268927547e+00, -2.6637226204951387e+00, -2.4719641499397405e+00, -2.2805431568207979e+00, -2.0894314113711125e+00, -1.8986012519385917e+00, -1.7080255276306118e+00, -1.5176775437537562e+00, -1.3275310097080575e+00, -1.1375599890219745e+00, -9.4773885123753698e-01, -7.5804222537475319e-01, -5.6844495472091694e-01, -3.7892205270411800e-01, -1.8944865962132065e-01, -0.0000000000000000e+00, 1.8944865962132065e-01, 3.7892205270411800e-01, 5.6844495472091694e-01, 7.5804222537475319e-01, 9.4773885123753698e-01, 1.1375599890219745e+00, 1.3275310097080575e+00, 1.5176775437537562e+00, 1.7080255276306118e+00, 1.8986012519385917e+00, 2.0894314113711125e+00, 2.2805431568207979e+00, 2.4719641499397405e+00, 2.6637226204951387e+00, 2.8558474268927547e+00, 3.0483681202772592e+00, 3.2413150126609418e+00, 3.4347192495813528e+00, 3.6286128878452084e+00, 3.8230289789816339e+00, 4.0180016591039696e+00, 4.2135662459677485e+00, 4.4097593441152032e+00, 4.6066189591163766e+00, 4.8041846220567344e+00, 5.0024975255849276e+00, 5.2016006730266913e+00, 5.4015390422975438e+00, 5.6023597666149243e+00, 5.8041123343284946e+00, 6.0068488105662023e+00, 6.2106240838470441e+00, 6.4154961413560549e+00, 6.6215263772344395e+00, 6.8287799390351633e+00, 7.0373261184664502e+00, 7.2472387937374041e+00, 7.4585969322894226e+00, 7.6714851645199493e+00, 7.8859944413814738e+00, 8.1022227916007061e+00, 8.3202761978883633e+00, 8.5402696161385645e+00, 8.7623281675764328e+00, 8.9865885415552977e+00, 9.2132006568631315e+00, 9.4423296428652392e+00, 9.6741582198685645e+00, 9.9088895826069283e+00, 1.0146750924472403e+01, 1.0387997787201458e+01, 1.0632919487519736e+01, 1.0881845968701494e+01, 1.1135156567035956e+01, 1.1393291396981837e+01, 1.1656766388576511e+01, 1.1926193533696322e+01, 1.2202308753936913e+01, 1.2486011256383852e+01, 1.2778420818075578e+01, 1.3080964234499790e+01, 1.3395511650343654e+01, 1.3724603683931077e+01, 1.4071857451951351e+01, 1.4442764183748782e+01, 1.4846480104844703e+01, 1.5300775595780827e+01, 1.5852170577958367e+01}, + {-1.5913261603942480e+01, -1.5362565713640512e+01, -1.4908860841455180e+01, -1.4505681306755122e+01, -1.4135277255544954e+01, -1.3788502962262141e+01, -1.3459873460233181e+01, -1.3145775742375259e+01, -1.2843672070795714e+01, -1.2551694420292197e+01, -1.2268417614744900e+01, -1.1992723152311497e+01, -1.1723712855448614e+01, -1.1460651651502332e+01, -1.1202928261484638e+01, -1.0950027363642045e+01, -1.0701509369981165e+01, -1.0456995405743042e+01, -1.0216155937006269e+01, -9.9787020140292348e+00, -9.7443784273495506e+00, -9.5129582872037410e+00, -9.2842386787046287e+00, -9.0580371415563476e+00, -8.8341887898063280e+00, -8.6125439341638330e+00, -8.3929661031022729e+00, -8.1753303834489426e+00, -7.9595220192037859e+00, -7.7454352207811352e+00, -7.5329721470151476e+00, -7.3220420300038924e+00, -7.1125604188199452e+00, -6.9044485227388090e+00, -6.6976326382579296e+00, -6.4920436470380141e+00, -6.2876165741721222e+00, -6.0842901980089970e+00, -5.8820067042248958e+00, -5.6807113780286782e+00, -5.4803523293560428e+00, -5.2808802467053466e+00, -5.0822481759241382e+00, -4.8844113207996323e+00, -4.6873268627591953e+00, -4.4909537973654823e+00, -4.2952527856086178e+00, -4.1001860182656378e+00, -3.9057170918238593e+00, -3.7118108946570874e+00, -3.5184335023072513e+00, -3.3255520808638139e+00, -3.1331347975530193e+00, -2.9411507377518000e+00, -2.7495698277296028e+00, -2.5583627624976102e+00, -2.3675009382106698e+00, -2.1769563886241587e+00, -1.9867017251572272e+00, -1.7967100801564784e+00, -1.6069550529909824e+00, -1.4174106586413215e+00, -1.2280512784727862e+00, -1.0388516129063341e+00, -8.4978663572097946e-01, -6.6083154973822611e-01, -4.7196174365329491e-01, -2.8315274978949312e-01, -9.4380202561292328e-02, 9.4380202561292328e-02, 2.8315274978949312e-01, 4.7196174365329491e-01, 6.6083154973822611e-01, 8.4978663572097946e-01, 1.0388516129063341e+00, 1.2280512784727862e+00, 1.4174106586413215e+00, 1.6069550529909824e+00, 1.7967100801564784e+00, 1.9867017251572272e+00, 2.1769563886241587e+00, 2.3675009382106698e+00, 2.5583627624976102e+00, 2.7495698277296028e+00, 2.9411507377518000e+00, 3.1331347975530193e+00, 3.3255520808638139e+00, 3.5184335023072513e+00, 3.7118108946570874e+00, 3.9057170918238593e+00, 4.1001860182656378e+00, 4.2952527856086178e+00, 4.4909537973654823e+00, 4.6873268627591953e+00, 4.8844113207996323e+00, 5.0822481759241382e+00, 5.2808802467053466e+00, 5.4803523293560428e+00, 5.6807113780286782e+00, 5.8820067042248958e+00, 6.0842901980089970e+00, 6.2876165741721222e+00, 6.4920436470380141e+00, 6.6976326382579296e+00, 6.9044485227388090e+00, 7.1125604188199452e+00, 7.3220420300038924e+00, 7.5329721470151476e+00, 7.7454352207811352e+00, 7.9595220192037859e+00, 8.1753303834489426e+00, 8.3929661031022729e+00, 8.6125439341638330e+00, 8.8341887898063280e+00, 9.0580371415563476e+00, 9.2842386787046287e+00, 9.5129582872037410e+00, 9.7443784273495506e+00, 9.9787020140292348e+00, 1.0216155937006269e+01, 1.0456995405743042e+01, 1.0701509369981165e+01, 1.0950027363642045e+01, 1.1202928261484638e+01, 1.1460651651502332e+01, 1.1723712855448614e+01, 1.1992723152311497e+01, 1.2268417614744900e+01, 1.2551694420292197e+01, 1.2843672070795714e+01, 1.3145775742375259e+01, 1.3459873460233181e+01, 1.3788502962262141e+01, 1.4135277255544954e+01, 1.4505681306755122e+01, 1.4908860841455180e+01, 1.5362565713640512e+01, 1.5913261603942480e+01}, + {-1.5974128087803059e+01, -1.5424125215654696e+01, -1.4971005737794270e+01, -1.4568357770032772e+01, -1.4198451817550286e+01, -1.3852152569276431e+01, -1.3523981270171619e+01, -1.3210328989123949e+01, -1.2908660844914866e+01, -1.2617110914147242e+01, -1.2334255626355663e+01, -1.2058977743887230e+01, -1.1790380109646946e+01, -1.1527728492218195e+01, -1.1270412318828130e+01, -1.1017916870112439e+01, -1.0769803079243415e+01, -1.0525692528151630e+01, -1.0285256087783404e+01, -1.0048205171171734e+01, -9.8142848971316887e+00, -9.5832686756941996e+00, -9.3549538681059694e+00, -9.1291582704569425e+00, -8.9057172366410864e+00, -8.6844813033334454e+00, -8.4653142133164536e+00, -8.2480912579473227e+00, -8.0326978775762718e+00, -7.8190284721625867e+00, -7.6069853844711011e+00, -7.3964780259572480e+00, -7.1874221213951852e+00, -6.9797390529218948e+00, -6.7733552877875338e+00, -6.5682018769582182e+00, -6.3642140139886543e+00, -6.1613306454010424e+00, -5.9594941252729363e+00, -5.7586499079259337e+00, -5.5587462735771860e+00, -5.3597340826114390e+00, -5.1615665547873322e+00, -4.9641990702352388e+00, -4.7675889895563337e+00, -4.5716954907107725e+00, -4.3764794207003801e+00, -4.1819031603187895e+00, -3.9879305004682921e+00, -3.7945265287347798e+00, -3.6016575250757095e+00, -3.4092908656157688e+00, -3.2173949336645937e+00, -3.0259390371736554e+00, -2.8348933319378968e+00, -2.6442287499240060e+00, -2.4539169321730845e+00, -2.2639301657825421e+00, -2.0742413245213673e+00, -1.8848238126757204e+00, -1.6956515117588089e+00, -1.5066987297510446e+00, -1.3179401525641421e+00, -1.1293507974466097e+00, -9.4090596806846227e-01, -7.5258121104029896e-01, -5.6435227363645946e-01, -3.7619506250401802e-01, -1.8808560314914807e-01, -0.0000000000000000e+00, 1.8808560314914807e-01, 3.7619506250401802e-01, 5.6435227363645946e-01, 7.5258121104029896e-01, 9.4090596806846227e-01, 1.1293507974466097e+00, 1.3179401525641421e+00, 1.5066987297510446e+00, 1.6956515117588089e+00, 1.8848238126757204e+00, 2.0742413245213673e+00, 2.2639301657825421e+00, 2.4539169321730845e+00, 2.6442287499240060e+00, 2.8348933319378968e+00, 3.0259390371736554e+00, 3.2173949336645937e+00, 3.4092908656157688e+00, 3.6016575250757095e+00, 3.7945265287347798e+00, 3.9879305004682921e+00, 4.1819031603187895e+00, 4.3764794207003801e+00, 4.5716954907107725e+00, 4.7675889895563337e+00, 4.9641990702352388e+00, 5.1615665547873322e+00, 5.3597340826114390e+00, 5.5587462735771860e+00, 5.7586499079259337e+00, 5.9594941252729363e+00, 6.1613306454010424e+00, 6.3642140139886543e+00, 6.5682018769582182e+00, 6.7733552877875338e+00, 6.9797390529218948e+00, 7.1874221213951852e+00, 7.3964780259572480e+00, 7.6069853844711011e+00, 7.8190284721625867e+00, 8.0326978775762718e+00, 8.2480912579473227e+00, 8.4653142133164536e+00, 8.6844813033334454e+00, 8.9057172366410864e+00, 9.1291582704569425e+00, 9.3549538681059694e+00, 9.5832686756941996e+00, 9.8142848971316887e+00, 1.0048205171171734e+01, 1.0285256087783404e+01, 1.0525692528151630e+01, 1.0769803079243415e+01, 1.1017916870112439e+01, 1.1270412318828130e+01, 1.1527728492218195e+01, 1.1790380109646946e+01, 1.2058977743887230e+01, 1.2334255626355663e+01, 1.2617110914147242e+01, 1.2908660844914866e+01, 1.3210328989123949e+01, 1.3523981270171619e+01, 1.3852152569276431e+01, 1.4198451817550286e+01, 1.4568357770032772e+01, 1.4971005737794270e+01, 1.5424125215654696e+01, 1.5974128087803059e+01}, + {-1.6034772477060816e+01, -1.5485456646120181e+01, -1.5032917422687504e+01, -1.4630796281434252e+01, -1.4261383921882931e+01, -1.3915555363288536e+01, -1.3587838011990620e+01, -1.3274626979734647e+01, -1.2973390218594389e+01, -1.2682263889584272e+01, -1.2399826014408026e+01, -1.2124960608784908e+01, -1.1856771527137033e+01, -1.1594525371724179e+01, -1.1337612269445431e+01, -1.1085518097551031e+01, -1.0837804305192460e+01, -1.0594092926257336e+01, -1.0354055232179574e+01, -1.0117402994660386e+01, -9.8838816568977812e+00, -9.6532649249849332e+00, -9.4253504326923299e+00, -9.1999562289744645e+00, -8.9769179041114668e+00, -8.7560862173209468e+00, -8.5373251222877080e+00, -8.3205101114907762e+00, -8.1055268182049698e+00, -7.8922698284767430e+00, -7.6806416654983130e+00, -7.4705519165212015e+00, -7.2619164783901100e+00, -7.0546569023913719e+00, -6.8486998227236997e+00, -6.6439764557516492e+00, -6.4404221594710993e+00, -6.2379760444330401e+00, -6.0365806288366217e+00, -5.8361815316904240e+00, -5.6367271989099255e+00, -5.4381686580140975e+00, -5.2404592977393536e+00, -5.0435546694321367e+00, -4.8474123075333448e+00, -4.6519915668456937e+00, -4.4572534745922692e+00, -4.2631605955419172e+00, -4.0696769087032161e+00, -3.8767676942807565e+00, -3.6843994297509557e+00, -3.4925396940542712e+00, -3.3011570790203533e+00, -3.1102211072454056e+00, -2.9197021557295608e+00, -2.7295713846583514e+00, -2.5398006707783964e+00, -2.3503625448744949e+00, -2.1612301329048256e+00, -1.9723771003938499e+00, -1.7837775997197194e+00, -1.5954062199652144e+00, -1.4072379390291252e+00, -1.2192480777190431e+00, -1.0314122555671925e+00, -8.4370634812858625e-01, -6.5610644553571928e-01, -4.6858881209649367e-01, -2.8112984673230629e-01, -9.3706044061378571e-02, 9.3706044061378571e-02, 2.8112984673230629e-01, 4.6858881209649367e-01, 6.5610644553571928e-01, 8.4370634812858625e-01, 1.0314122555671925e+00, 1.2192480777190431e+00, 1.4072379390291252e+00, 1.5954062199652144e+00, 1.7837775997197194e+00, 1.9723771003938499e+00, 2.1612301329048256e+00, 2.3503625448744949e+00, 2.5398006707783964e+00, 2.7295713846583514e+00, 2.9197021557295608e+00, 3.1102211072454056e+00, 3.3011570790203533e+00, 3.4925396940542712e+00, 3.6843994297509557e+00, 3.8767676942807565e+00, 4.0696769087032161e+00, 4.2631605955419172e+00, 4.4572534745922692e+00, 4.6519915668456937e+00, 4.8474123075333448e+00, 5.0435546694321367e+00, 5.2404592977393536e+00, 5.4381686580140975e+00, 5.6367271989099255e+00, 5.8361815316904240e+00, 6.0365806288366217e+00, 6.2379760444330401e+00, 6.4404221594710993e+00, 6.6439764557516492e+00, 6.8486998227236997e+00, 7.0546569023913719e+00, 7.2619164783901100e+00, 7.4705519165212015e+00, 7.6806416654983130e+00, 7.8922698284767430e+00, 8.1055268182049698e+00, 8.3205101114907762e+00, 8.5373251222877080e+00, 8.7560862173209468e+00, 8.9769179041114668e+00, 9.1999562289744645e+00, 9.4253504326923299e+00, 9.6532649249849332e+00, 9.8838816568977812e+00, 1.0117402994660386e+01, 1.0354055232179574e+01, 1.0594092926257336e+01, 1.0837804305192460e+01, 1.1085518097551031e+01, 1.1337612269445431e+01, 1.1594525371724179e+01, 1.1856771527137033e+01, 1.2124960608784908e+01, 1.2399826014408026e+01, 1.2682263889584272e+01, 1.2973390218594389e+01, 1.3274626979734647e+01, 1.3587838011990620e+01, 1.3915555363288536e+01, 1.4261383921882931e+01, 1.4630796281434252e+01, 1.5032917422687504e+01, 1.5485456646120181e+01, 1.6034772477060816e+01}, + {-1.6095197175178654e+01, -1.5546562503045239e+01, -1.5094598476696428e+01, -1.4692999498678725e+01, -1.4324076300505626e+01, -1.3978714148861499e+01, -1.3651446561974707e+01, -1.3338672661844436e+01, -1.3037863210821454e+01, -1.2747156437216972e+01, -1.2465131941640982e+01, -1.2190674982552025e+01, -1.1922890417116040e+01, -1.1661045673847648e+01, -1.1404531572900545e+01, -1.1152834582481235e+01, -1.0905516662643253e+01, -1.0662200294603309e+01, -1.0422557146004042e+01, -1.0186299343207718e+01, -9.9531726499989794e+00, -9.7229510648991155e+00, -9.4954324906908987e+00, -9.2704352257718199e+00, -9.0477950934492313e+00, -8.8273630721636813e+00, -8.6090033232019607e+00, -8.3925915368661208e+00, -8.1780135360427444e+00, -7.9651640895243876e+00, -7.7539458975483946e+00, -7.5442687197268468e+00, -7.3360486214748111e+00, -7.1292073196522763e+00, -6.9236716117447346e+00, -6.7193728757570428e+00, -6.5162466302615387e+00, -6.3142321458564812e+00, -6.1132721007540169e+00, -5.9133122744035465e+00, -5.7143012740244483e+00, -5.5161902897161745e+00, -5.3189328744684259e+00, -5.1224847459365774e+00, -4.9268036072990391e+00, -4.7318489848907346e+00, -4.5375820806238156e+00, -4.3439656374738016e+00, -4.1509638165353397e+00, -3.9585420843435810e+00, -3.7666671093205584e+00, -3.5753066663455639e+00, -3.3844295485681095e+00, -3.1940054856848250e+00, -3.0040050679901400e+00, -2.8143996755869578e+00, -2.6251614122095890e+00, -2.4362630431683869e+00, -2.2476779369751214e+00, -2.0593800102511661e+00, -1.8713436755579074e+00, -1.6835437918212028e+00, -1.4959556170497912e+00, -1.3085547630718375e+00, -1.1213171520347327e+00, -9.3421897443120272e-01, -7.4723664843005233e-01, -5.6034678030272367e-01, -3.7352612574750421e-01, -1.8675155192184525e-01, -0.0000000000000000e+00, 1.8675155192184525e-01, 3.7352612574750421e-01, 5.6034678030272367e-01, 7.4723664843005233e-01, 9.3421897443120272e-01, 1.1213171520347327e+00, 1.3085547630718375e+00, 1.4959556170497912e+00, 1.6835437918212028e+00, 1.8713436755579074e+00, 2.0593800102511661e+00, 2.2476779369751214e+00, 2.4362630431683869e+00, 2.6251614122095890e+00, 2.8143996755869578e+00, 3.0040050679901400e+00, 3.1940054856848250e+00, 3.3844295485681095e+00, 3.5753066663455639e+00, 3.7666671093205584e+00, 3.9585420843435810e+00, 4.1509638165353397e+00, 4.3439656374738016e+00, 4.5375820806238156e+00, 4.7318489848907346e+00, 4.9268036072990391e+00, 5.1224847459365774e+00, 5.3189328744684259e+00, 5.5161902897161745e+00, 5.7143012740244483e+00, 5.9133122744035465e+00, 6.1132721007540169e+00, 6.3142321458564812e+00, 6.5162466302615387e+00, 6.7193728757570428e+00, 6.9236716117447346e+00, 7.1292073196522763e+00, 7.3360486214748111e+00, 7.5442687197268468e+00, 7.7539458975483946e+00, 7.9651640895243876e+00, 8.1780135360427444e+00, 8.3925915368661208e+00, 8.6090033232019607e+00, 8.8273630721636813e+00, 9.0477950934492313e+00, 9.2704352257718199e+00, 9.4954324906908987e+00, 9.7229510648991155e+00, 9.9531726499989794e+00, 1.0186299343207718e+01, 1.0422557146004042e+01, 1.0662200294603309e+01, 1.0905516662643253e+01, 1.1152834582481235e+01, 1.1404531572900545e+01, 1.1661045673847648e+01, 1.1922890417116040e+01, 1.2190674982552025e+01, 1.2465131941640982e+01, 1.2747156437216972e+01, 1.3037863210821454e+01, 1.3338672661844436e+01, 1.3651446561974707e+01, 1.3978714148861499e+01, 1.4324076300505626e+01, 1.4692999498678725e+01, 1.5094598476696428e+01, 1.5546562503045239e+01, 1.6095197175178654e+01}, + {-1.6155404542662776e+01, -1.5607445239317764e+01, -1.5156051433346871e+01, -1.4754970030637802e+01, -1.4386531634770627e+01, -1.4041631678205716e+01, -1.3714809742317117e+01, -1.3402468927252324e+01, -1.3102082782981558e+01, -1.2811791588270133e+01, -1.2530176509588186e+01, -1.2256124037680147e+01, -1.1988740023836153e+01, -1.1727292715539413e+01, -1.1471173619903071e+01, -1.1219869790544209e+01, -1.0972943693447091e+01, -1.0730018252630529e+01, -1.0490765527764685e+01, -1.0254897995961329e+01, -1.0022161737889968e+01, -9.7923310409601427e+00, -9.5652040735500723e+00, -9.3405993801743854e+00, -9.1183530139059350e+00, -8.8983161691878188e+00, -8.6803532117101110e+00, -8.4643400264036650e+00, -8.2501626225617972e+00, -8.0377159484935703e+00, -7.8269028782146863e+00, -7.6176333403821728e+00, -7.4098235656060059e+00, -7.2033954328740331e+00, -6.9982758994323033e+00, -6.7943965013094090e+00, -6.5916929139374751e+00, -6.3901045641355303e+00, -6.1895742861825749e+00, -5.9900480158931027e+00, -5.7914745175749145e+00, -5.5938051395422690e+00, -5.3969935945114758e+00, -5.2009957617479348e+00, -5.0057695082847111e+00, -4.8112745269098740e+00, -4.6174721889364516e+00, -4.4243254100357463e+00, -4.2317985276405068e+00, -4.0398571886161809e+00, -3.8484682460617101e+00, -3.6575996642408795e+00, -3.4672204307647947e+00, -3.2773004752487735e+00, -3.0878105937554641e+00, -2.8987223784123866e+00, -2.7100081516581653e+00, -2.5216409046290269e+00, -2.3335942392467470e+00, -2.1458423136124405e+00, -1.9583597903480086e+00, -1.7711217875596625e+00, -1.5841038321261636e+00, -1.3972818150389417e+00, -1.2106319485423875e+00, -1.0241307248408380e+00, -8.3775487615432709e-01, -6.5148133591837221e-01, -4.6528720093408932e-01, -2.7914969428399067e-01, -9.3046128836030015e-02, 9.3046128836030015e-02, 2.7914969428399067e-01, 4.6528720093408932e-01, 6.5148133591837221e-01, 8.3775487615432709e-01, 1.0241307248408380e+00, 1.2106319485423875e+00, 1.3972818150389417e+00, 1.5841038321261636e+00, 1.7711217875596625e+00, 1.9583597903480086e+00, 2.1458423136124405e+00, 2.3335942392467470e+00, 2.5216409046290269e+00, 2.7100081516581653e+00, 2.8987223784123866e+00, 3.0878105937554641e+00, 3.2773004752487735e+00, 3.4672204307647947e+00, 3.6575996642408795e+00, 3.8484682460617101e+00, 4.0398571886161809e+00, 4.2317985276405068e+00, 4.4243254100357463e+00, 4.6174721889364516e+00, 4.8112745269098740e+00, 5.0057695082847111e+00, 5.2009957617479348e+00, 5.3969935945114758e+00, 5.5938051395422690e+00, 5.7914745175749145e+00, 5.9900480158931027e+00, 6.1895742861825749e+00, 6.3901045641355303e+00, 6.5916929139374751e+00, 6.7943965013094090e+00, 6.9982758994323033e+00, 7.2033954328740331e+00, 7.4098235656060059e+00, 7.6176333403821728e+00, 7.8269028782146863e+00, 8.0377159484935703e+00, 8.2501626225617972e+00, 8.4643400264036650e+00, 8.6803532117101110e+00, 8.8983161691878188e+00, 9.1183530139059350e+00, 9.3405993801743854e+00, 9.5652040735500723e+00, 9.7923310409601427e+00, 1.0022161737889968e+01, 1.0254897995961329e+01, 1.0490765527764685e+01, 1.0730018252630529e+01, 1.0972943693447091e+01, 1.1219869790544209e+01, 1.1471173619903071e+01, 1.1727292715539413e+01, 1.1988740023836153e+01, 1.2256124037680147e+01, 1.2530176509588186e+01, 1.2811791588270133e+01, 1.3102082782981558e+01, 1.3402468927252324e+01, 1.3714809742317117e+01, 1.4041631678205716e+01, 1.4386531634770627e+01, 1.4754970030637802e+01, 1.5156051433346871e+01, 1.5607445239317764e+01, 1.6155404542662776e+01}, + {-1.6215396898128663e+01, -1.5668107263835802e+01, -1.5217278780317361e+01, -1.4816710438579342e+01, -1.4448752556717958e+01, -1.4104310652531494e+01, -1.3777930322527094e+01, -1.3466018613382040e+01, -1.3166051840377859e+01, -1.2876172316156813e+01, -1.2594962760214381e+01, -1.2321310885302282e+01, -1.2054323528364668e+01, -1.1793269748698537e+01, -1.1537541734199792e+01, -1.1286627118459547e+01, -1.1040088868523824e+01, -1.0797550346784112e+01, -1.0558684000851162e+01, -1.0323202654766870e+01, -1.0090852702474850e+01, -9.8614087168236804e+00, -9.6346691284611641e+00, -9.4104527247850562e+00, -9.1885957854652229e+00, -8.9689497178220225e+00, -8.7513790888474610e+00, -8.5357599750069966e+00, -8.3219785688987216e+00, -8.1099299952250909e+00, -7.8995172986236630e+00, -7.6906505735952022e+00, -7.4832462126880364e+00, -7.2772262536958907e+00, -7.0725178102281943e+00, -6.8690525728554430e+00, -6.6667663702937121e+00, -6.4655987819036467e+00, -6.2654927942392939e+00, -6.0663944955663265e+00, -5.8682528032352996e+00, -5.6710192195879507e+00, -5.4746476127280044e+00, -5.2790940190292117e+00, -5.0843164647041039e+00, -4.8902748041336244e+00, -4.6969305729742112e+00, -4.5042468543255083e+00, -4.3121881564674842e+00, -4.1207203008672968e+00, -3.9298103193193850e+00, -3.7394263592217327e+00, -3.5495375961107607e+00, -3.3601141526799938e+00, -3.1711270235961577e+00, -2.9825480055027773e+00, -2.7943496316674543e+00, -2.6065051107863355e+00, -2.4189882695090272e+00, -2.2317734982904458e+00, -2.0448357002136932e+00, -1.8581502424607397e+00, -1.6716929101361060e+00, -1.4854398621734262e+00, -1.2993675890761167e+00, -1.1134528722618340e+00, -9.2767274479622841e-01, -7.4200445331498865e-01, -5.5642542094454162e-01, -3.7091321104119962e-01, -1.8544549157619233e-01, -0.0000000000000000e+00, 1.8544549157619233e-01, 3.7091321104119962e-01, 5.5642542094454162e-01, 7.4200445331498865e-01, 9.2767274479622841e-01, 1.1134528722618340e+00, 1.2993675890761167e+00, 1.4854398621734262e+00, 1.6716929101361060e+00, 1.8581502424607397e+00, 2.0448357002136932e+00, 2.2317734982904458e+00, 2.4189882695090272e+00, 2.6065051107863355e+00, 2.7943496316674543e+00, 2.9825480055027773e+00, 3.1711270235961577e+00, 3.3601141526799938e+00, 3.5495375961107607e+00, 3.7394263592217327e+00, 3.9298103193193850e+00, 4.1207203008672968e+00, 4.3121881564674842e+00, 4.5042468543255083e+00, 4.6969305729742112e+00, 4.8902748041336244e+00, 5.0843164647041039e+00, 5.2790940190292117e+00, 5.4746476127280044e+00, 5.6710192195879507e+00, 5.8682528032352996e+00, 6.0663944955663265e+00, 6.2654927942392939e+00, 6.4655987819036467e+00, 6.6667663702937121e+00, 6.8690525728554430e+00, 7.0725178102281943e+00, 7.2772262536958907e+00, 7.4832462126880364e+00, 7.6906505735952022e+00, 7.8995172986236630e+00, 8.1099299952250909e+00, 8.3219785688987216e+00, 8.5357599750069966e+00, 8.7513790888474610e+00, 8.9689497178220225e+00, 9.1885957854652229e+00, 9.4104527247850562e+00, 9.6346691284611641e+00, 9.8614087168236804e+00, 1.0090852702474850e+01, 1.0323202654766870e+01, 1.0558684000851162e+01, 1.0797550346784112e+01, 1.1040088868523824e+01, 1.1286627118459547e+01, 1.1537541734199792e+01, 1.1793269748698537e+01, 1.2054323528364668e+01, 1.2321310885302282e+01, 1.2594962760214381e+01, 1.2876172316156813e+01, 1.3166051840377859e+01, 1.3466018613382040e+01, 1.3777930322527094e+01, 1.4104310652531494e+01, 1.4448752556717958e+01, 1.4816710438579342e+01, 1.5217278780317361e+01, 1.5668107263835802e+01, 1.6215396898128663e+01}, + {-1.6275176519333314e+01, -1.5728550942602004e+01, -1.5278282960589307e+01, -1.4878223237370916e+01, -1.4510741650331246e+01, -1.4166753723357122e+01, -1.3840811020790602e+01, -1.3529324504696065e+01, -1.3229773233699543e+01, -1.2940301538002238e+01, -1.2659493677496206e+01, -1.2386238576832154e+01, -1.2119644050283457e+01, -1.1858979961933818e+01, -1.1603639174400232e+01, -1.1353109895917042e+01, -1.1106955589822139e+01, -1.0864800052544570e+01, -1.0626316115639773e+01, -1.0391216946349248e+01, -1.0159249248367633e+01, -9.9301878766205718e+00, -9.7038315207870216e+00, -9.4799992080020576e+00, -9.2585274414535341e+00, -9.0392678383049354e+00, -8.8220851638421109e+00, -8.6068556830666605e+00, -8.3934657688780785e+00, -8.1818107193508762e+00, -7.9717937466932813e+00, -7.7633251081577797e+00, -7.5563213550879356e+00, -7.3507046808793666e+00, -7.1464023522306821e+00, -6.9433462109007360e+00, -6.7414722354477217e+00, -6.5407201542348838e+00, -6.3410331024462083e+00, -6.1423573170383490e+00, -5.9446418645201566e+00, -5.7478383972427567e+00, -5.5519009345358734e+00, -5.3567856655668686e+00, -5.1624507712492340e+00, -4.9688562629036443e+00, -4.7759638356907441e+00, -4.5837367351012581e+00, -4.3921396350144111e+00, -4.2011385260270222e+00, -4.0107006129187415e+00, -3.8207942202581950e+00, -3.6313887052743148e+00, -3.4424543772197556e+00, -3.2539624225418282e+00, -3.0658848352527657e+00, -2.8781943519573039e+00, -2.6908643910529264e+00, -2.5038689956679221e+00, -2.3171827799457509e+00, -2.1307808783218642e+00, -1.9446388974719979e+00, -1.7587328706394580e+00, -1.5730392140737939e+00, -1.3875346853347825e+00, -1.2021963432343084e+00, -1.0170015092047828e+00, -8.3192772989651476e-01, -6.4695274081809961e-01, -4.6205443084366904e-01, -2.7721080741886533e-01, -9.2399962303806829e-02, 9.2399962303806829e-02, 2.7721080741886533e-01, 4.6205443084366904e-01, 6.4695274081809961e-01, 8.3192772989651476e-01, 1.0170015092047828e+00, 1.2021963432343084e+00, 1.3875346853347825e+00, 1.5730392140737939e+00, 1.7587328706394580e+00, 1.9446388974719979e+00, 2.1307808783218642e+00, 2.3171827799457509e+00, 2.5038689956679221e+00, 2.6908643910529264e+00, 2.8781943519573039e+00, 3.0658848352527657e+00, 3.2539624225418282e+00, 3.4424543772197556e+00, 3.6313887052743148e+00, 3.8207942202581950e+00, 4.0107006129187415e+00, 4.2011385260270222e+00, 4.3921396350144111e+00, 4.5837367351012581e+00, 4.7759638356907441e+00, 4.9688562629036443e+00, 5.1624507712492340e+00, 5.3567856655668686e+00, 5.5519009345358734e+00, 5.7478383972427567e+00, 5.9446418645201566e+00, 6.1423573170383490e+00, 6.3410331024462083e+00, 6.5407201542348838e+00, 6.7414722354477217e+00, 6.9433462109007360e+00, 7.1464023522306821e+00, 7.3507046808793666e+00, 7.5563213550879356e+00, 7.7633251081577797e+00, 7.9717937466932813e+00, 8.1818107193508762e+00, 8.3934657688780785e+00, 8.6068556830666605e+00, 8.8220851638421109e+00, 9.0392678383049354e+00, 9.2585274414535341e+00, 9.4799992080020576e+00, 9.7038315207870216e+00, 9.9301878766205718e+00, 1.0159249248367633e+01, 1.0391216946349248e+01, 1.0626316115639773e+01, 1.0864800052544570e+01, 1.1106955589822139e+01, 1.1353109895917042e+01, 1.1603639174400232e+01, 1.1858979961933818e+01, 1.2119644050283457e+01, 1.2386238576832154e+01, 1.2659493677496206e+01, 1.2940301538002238e+01, 1.3229773233699543e+01, 1.3529324504696065e+01, 1.3840811020790602e+01, 1.4166753723357122e+01, 1.4510741650331246e+01, 1.4878223237370916e+01, 1.5278282960589307e+01, 1.5728550942602004e+01, 1.6275176519333314e+01}, + {-1.6334745644175054e+01, -1.5788778599783345e+01, -1.5339066373560392e+01, -1.4939510896644496e+01, -1.4572501452752805e+01, -1.4228963493774261e+01, -1.3903454505286284e+01, -1.3592389334062910e+01, -1.3293249760441302e+01, -1.3004182116116599e+01, -1.2723772188949674e+01, -1.2450910105547806e+01, -1.2184704649330305e+01, -1.1924426482264677e+01, -1.1669469135738963e+01, -1.1419321387402469e+01, -1.1173547192211004e+01, -1.0931770776387262e+01, -1.0693665351523348e+01, -1.0458944424415622e+01, -1.0227355005071125e+01, -9.9986722272145627e+00, -9.7726950364017036e+00, -9.5492426964438799e+00, -9.3281519310537870e+00, -9.1092745642913098e+00, -8.8924755568174323e+00, -8.6776313592631116e+00, -8.4646285219201989e+00, -8.2533625133112452e+00, -8.0437367102645929e+00, -7.8356615297967140e+00, -7.6290536790115411e+00, -7.4238355038151660e+00, -7.2199344208383769e+00, -7.0172824197970574e+00, -6.8158156257772653e+00, -6.6154739127391755e+00, -6.4162005609911104e+00, -6.2179419525665987e+00, -6.0206472994014675e+00, -5.8242683999987914e+00, -5.6287594209215639e+00, -5.4340766999932706e+00, -5.2401785685362707e+00, -5.0470251903539998e+00, -4.8545784154787137e+00, -4.6628016469727172e+00, -4.4716597192961824e+00, -4.2811187869459504e+00, -4.0911462222326103e+00, -3.9017105212024688e+00, -3.7127812168303533e+00, -3.5243287987118928e+00, -3.3363246385723251e+00, -3.1487409209853521e+00, -2.9615505787617051e+00, -2.7747272325244832e+00, -2.5882451340382215e+00, -2.4020791129020052e+00, -2.2162045262547485e+00, -2.0305972111736730e+00, -1.8452334394757037e+00, -1.6600898746564745e+00, -1.4751435307233549e+00, -1.2903717326977489e+00, -1.1057520785781945e+00, -9.2126240256979075e-01, -7.3688073939740739e-01, -5.5258528953022001e-01, -3.6835438515345242e-01, -1.8416645673001250e-01, -0.0000000000000000e+00, 1.8416645673001250e-01, 3.6835438515345242e-01, 5.5258528953022001e-01, 7.3688073939740739e-01, 9.2126240256979075e-01, 1.1057520785781945e+00, 1.2903717326977489e+00, 1.4751435307233549e+00, 1.6600898746564745e+00, 1.8452334394757037e+00, 2.0305972111736730e+00, 2.2162045262547485e+00, 2.4020791129020052e+00, 2.5882451340382215e+00, 2.7747272325244832e+00, 2.9615505787617051e+00, 3.1487409209853521e+00, 3.3363246385723251e+00, 3.5243287987118928e+00, 3.7127812168303533e+00, 3.9017105212024688e+00, 4.0911462222326103e+00, 4.2811187869459504e+00, 4.4716597192961824e+00, 4.6628016469727172e+00, 4.8545784154787137e+00, 5.0470251903539998e+00, 5.2401785685362707e+00, 5.4340766999932706e+00, 5.6287594209215639e+00, 5.8242683999987914e+00, 6.0206472994014675e+00, 6.2179419525665987e+00, 6.4162005609911104e+00, 6.6154739127391755e+00, 6.8158156257772653e+00, 7.0172824197970574e+00, 7.2199344208383769e+00, 7.4238355038151660e+00, 7.6290536790115411e+00, 7.8356615297967140e+00, 8.0437367102645929e+00, 8.2533625133112452e+00, 8.4646285219201989e+00, 8.6776313592631116e+00, 8.8924755568174323e+00, 9.1092745642913098e+00, 9.3281519310537870e+00, 9.5492426964438799e+00, 9.7726950364017036e+00, 9.9986722272145627e+00, 1.0227355005071125e+01, 1.0458944424415622e+01, 1.0693665351523348e+01, 1.0931770776387262e+01, 1.1173547192211004e+01, 1.1419321387402469e+01, 1.1669469135738963e+01, 1.1924426482264677e+01, 1.2184704649330305e+01, 1.2450910105547806e+01, 1.2723772188949674e+01, 1.3004182116116599e+01, 1.3293249760441302e+01, 1.3592389334062910e+01, 1.3903454505286284e+01, 1.4228963493774261e+01, 1.4572501452752805e+01, 1.4939510896644496e+01, 1.5339066373560392e+01, 1.5788778599783345e+01, 1.6334745644175054e+01}, + {-1.6394106471662131e+01, -1.5848792518737463e+01, -1.5399631376122628e+01, -1.5000575841923927e+01, -1.4634034455459645e+01, -1.4290942519672281e+01, -1.3965863395458523e+01, -1.3655215784079445e+01, -1.3356484166275854e+01, -1.3067816859418864e+01, -1.2787801167106462e+01, -1.2515328408121787e+01, -1.2249508326984577e+01, -1.1989612376763933e+01, -1.1735034751777302e+01, -1.1485264793960161e+01, -1.1239866945305195e+01, -1.0998465857673063e+01, -1.0760735118869476e+01, -1.0526388571683613e+01, -1.0295173529077774e+01, -1.0066865400378582e+01, -9.8412633839451633e+00, -9.6181869772854895e+00, -9.3974731217264083e+00, -9.1789738453613765e+00, -8.9625543013934692e+00, -8.7480911232640413e+00, -8.5354710358385653e+00, -8.3245896752567052e+00, -8.1153505801125796e+00, -7.9076643242985316e+00, -7.7014477677473518e+00, -7.4966234058915848e+00, -7.2931188022489746e+00, -7.0908660913775821e+00, -6.8898015416986063e+00, -6.6898651694904157e+00, -6.4910003968128018e+00, -6.2931537473009849e+00, -6.0962745747319902e+00, -5.9003148200559909e+00, -5.7052287932366612e+00, -5.5109729767842897e+00, -5.3175058483147666e+00, -5.1247877198432272e+00, -4.9327805918366323e+00, -4.7414480203154818e+00, -4.5507549955198634e+00, -4.3606678308461584e+00, -4.1711540609235342e+00, -3.9821823478385219e+00, -3.7937223946353149e+00, -3.6057448653220203e+00, -3.4182213107015205e+00, -3.2311240994220300e+00, -3.0444263537086158e+00, -2.8581018892943821e+00, -2.6721251591199171e+00, -2.4864712004130762e+00, -2.3011155847990197e+00, -2.1160343711234311e+00, -1.9312040607006651e+00, -1.7466015547236411e+00, -1.5622041135941906e+00, -1.3779893179515634e+00, -1.1939350311932622e+00, -1.0100193632965979e+00, -8.2622063576151961e-01, -6.4251734750563116e-01, -4.5888814155095509e-01, -2.7531177234913912e-01, -9.1767073597484664e-02, 9.1767073597484664e-02, 2.7531177234913912e-01, 4.5888814155095509e-01, 6.4251734750563116e-01, 8.2622063576151961e-01, 1.0100193632965979e+00, 1.1939350311932622e+00, 1.3779893179515634e+00, 1.5622041135941906e+00, 1.7466015547236411e+00, 1.9312040607006651e+00, 2.1160343711234311e+00, 2.3011155847990197e+00, 2.4864712004130762e+00, 2.6721251591199171e+00, 2.8581018892943821e+00, 3.0444263537086158e+00, 3.2311240994220300e+00, 3.4182213107015205e+00, 3.6057448653220203e+00, 3.7937223946353149e+00, 3.9821823478385219e+00, 4.1711540609235342e+00, 4.3606678308461584e+00, 4.5507549955198634e+00, 4.7414480203154818e+00, 4.9327805918366323e+00, 5.1247877198432272e+00, 5.3175058483147666e+00, 5.5109729767842897e+00, 5.7052287932366612e+00, 5.9003148200559909e+00, 6.0962745747319902e+00, 6.2931537473009849e+00, 6.4910003968128018e+00, 6.6898651694904157e+00, 6.8898015416986063e+00, 7.0908660913775821e+00, 7.2931188022489746e+00, 7.4966234058915848e+00, 7.7014477677473518e+00, 7.9076643242985316e+00, 8.1153505801125796e+00, 8.3245896752567052e+00, 8.5354710358385653e+00, 8.7480911232640413e+00, 8.9625543013934692e+00, 9.1789738453613765e+00, 9.3974731217264083e+00, 9.6181869772854895e+00, 9.8412633839451633e+00, 1.0066865400378582e+01, 1.0295173529077774e+01, 1.0526388571683613e+01, 1.0760735118869476e+01, 1.0998465857673063e+01, 1.1239866945305195e+01, 1.1485264793960161e+01, 1.1735034751777302e+01, 1.1989612376763933e+01, 1.2249508326984577e+01, 1.2515328408121787e+01, 1.2787801167106462e+01, 1.3067816859418864e+01, 1.3356484166275854e+01, 1.3655215784079445e+01, 1.3965863395458523e+01, 1.4290942519672281e+01, 1.4634034455459645e+01, 1.5000575841923927e+01, 1.5399631376122628e+01, 1.5848792518737463e+01, 1.6394106471662131e+01}, + {-1.6453261162851238e+01, -1.5908594943006905e+01, -1.5459980283706434e+01, -1.5061420455716602e+01, -1.4695343105401838e+01, -1.4352693310923225e+01, -1.4028040263249208e+01, -1.3717806488350135e+01, -1.3419479146381439e+01, -1.3131208524813520e+01, -1.2851583430941135e+01, -1.2579496366100177e+01, -1.2314058027999442e+01, -1.2054540654144855e+01, -1.1800339096046955e+01, -1.1550943254895040e+01, -1.1305918055227691e+01, -1.1064888570473238e+01, -1.0827528760910019e+01, -1.0593552801837916e+01, -1.0362708305895856e+01, -1.0134770954893138e+01, -9.9095401969966606e+00, -9.6868357605097319e+00, -9.4664948015418702e+00, -9.2483695494377951e+00, -9.0323253471918115e+00, -8.8182390083208837e+00, -8.6059974295318415e+00, -8.3954964118396482e+00, -8.1866396528418637e+00, -7.9793378805138149e+00, -7.7735081047843622e+00, -7.5690729677310218e+00, -7.3659601768199030e+00, -7.1641020084474496e+00, -6.9634348712930993e+00, -6.7638989207955804e+00, -6.5654377175196297e+00, -6.3679979233591490e+00, -6.1715290304849564e+00, -5.9759831187344989e+00, -5.7813146377916294e+00, -5.5874802110437694e+00, -5.3944384584526848e+00, -5.2021498361504346e+00, -5.0105764907872219e+00, -4.8196821269235706e+00, -4.6294318859840997e+00, -4.4397922354810584e+00, -4.2507308673785191e+00, -4.0622166046072063e+00, -3.8742193148591682e+00, -3.6867098308940789e+00, -3.4996598766773372e+00, -3.3130419987465562e+00, -3.1268295022692216e+00, -2.9409963913117498e+00, -2.7555173128901118e+00, -2.5703675044157226e+00, -2.3855227441881959e+00, -2.2009593046196674e+00, -2.0166539079042916e+00, -1.8325836838717240e+00, -1.6487261297853975e+00, -1.4650590718655645e+00, -1.2815606283337120e+00, -1.0982091737893589e+00, -9.1498330474263811e-01, -7.3186180613665275e-01, -5.4882361870252716e-01, -3.6584780699750397e-01, -1.8291352798246857e-01, -0.0000000000000000e+00, 1.8291352798246857e-01, 3.6584780699750397e-01, 5.4882361870252716e-01, 7.3186180613665275e-01, 9.1498330474263811e-01, 1.0982091737893589e+00, 1.2815606283337120e+00, 1.4650590718655645e+00, 1.6487261297853975e+00, 1.8325836838717240e+00, 2.0166539079042916e+00, 2.2009593046196674e+00, 2.3855227441881959e+00, 2.5703675044157226e+00, 2.7555173128901118e+00, 2.9409963913117498e+00, 3.1268295022692216e+00, 3.3130419987465562e+00, 3.4996598766773372e+00, 3.6867098308940789e+00, 3.8742193148591682e+00, 4.0622166046072063e+00, 4.2507308673785191e+00, 4.4397922354810584e+00, 4.6294318859840997e+00, 4.8196821269235706e+00, 5.0105764907872219e+00, 5.2021498361504346e+00, 5.3944384584526848e+00, 5.5874802110437694e+00, 5.7813146377916294e+00, 5.9759831187344989e+00, 6.1715290304849564e+00, 6.3679979233591490e+00, 6.5654377175196297e+00, 6.7638989207955804e+00, 6.9634348712930993e+00, 7.1641020084474496e+00, 7.3659601768199030e+00, 7.5690729677310218e+00, 7.7735081047843622e+00, 7.9793378805138149e+00, 8.1866396528418637e+00, 8.3954964118396482e+00, 8.6059974295318415e+00, 8.8182390083208837e+00, 9.0323253471918115e+00, 9.2483695494377951e+00, 9.4664948015418702e+00, 9.6868357605097319e+00, 9.9095401969966606e+00, 1.0134770954893138e+01, 1.0362708305895856e+01, 1.0593552801837916e+01, 1.0827528760910019e+01, 1.1064888570473238e+01, 1.1305918055227691e+01, 1.1550943254895040e+01, 1.1800339096046955e+01, 1.2054540654144855e+01, 1.2314058027999442e+01, 1.2579496366100177e+01, 1.2851583430941135e+01, 1.3131208524813520e+01, 1.3419479146381439e+01, 1.3717806488350135e+01, 1.4028040263249208e+01, 1.4352693310923225e+01, 1.4695343105401838e+01, 1.5061420455716602e+01, 1.5459980283706434e+01, 1.5908594943006905e+01, 1.6453261162851238e+01}, + {-1.6512211841757207e+01, -1.5968188077282482e+01, -1.5520115371292015e+01, -1.5122047078570679e+01, -1.4756429806104775e+01, -1.4414218332528858e+01, -1.4089987634289908e+01, -1.3780164032724846e+01, -1.3482237346726031e+01, -1.3194359818522189e+01, -1.2915121747251227e+01, -1.2643416807332409e+01, -1.2378356641882881e+01, -1.2119214266294843e+01, -1.1865385183637930e+01, -1.1616359849416588e+01, -1.1371703666311570e+01, -1.1131042125331231e+01, -1.0894049555564962e+01, -1.0660440461418377e+01, -1.0429962752004187e+01, -1.0202392378570206e+01, -9.9775290361704698e+00, -9.7551926810776539e+00, -9.5352206814286085e+00, -9.3174654651143189e+00, -9.1017925622483045e+00, -8.8880789637690558e+00, -8.6762117355753663e+00, -8.4660868409009815e+00, -8.2576081336726084e+00, -8.0506864932467330e+00, -7.8452390768098423e+00, -7.6411886703008571e+00, -7.4384631222974562e+00, -7.2369948481366277e+00, -7.0367203937895502e+00, -6.8375800508126918e+00, -6.6395175151495431e+00, -6.4424795837354694e+00, -6.2464158838193349e+00, -6.0512786307039113e+00, -5.8570224102572590e+00, -5.6636039830858733e+00, -5.4709821077089327e+00, -5.2791173804478735e+00, -5.0879720900604992e+00, -4.8975100854141935e+00, -4.7076966547174930e+00, -4.5184984150200371e+00, -4.3298832108534802e+00, -4.1418200210249481e+00, -3.9542788726937901e+00, -3.7672307619648824e+00, -3.5806475803201039e+00, -3.3945020462860152e+00, -3.2087676418019360e+00, -3.0234185528101056e+00, -2.8384296136395832e+00, -2.6537762547990797e+00, -2.4694344538319206e+00, -2.2853806889194859e+00, -2.1015918949484664e+00, -1.9180454217825835e+00, -1.7347189945015418e+00, -1.5515906753892701e+00, -1.3686388274702970e+00, -1.1858420794076876e+00, -1.0031792915885485e+00, -8.2062952323391314e-01, -6.3817200037899757e-01, -4.5578608457752007e-01, -2.7345124219010619e-01, -9.1147014121871414e-02, 9.1147014121871414e-02, 2.7345124219010619e-01, 4.5578608457752007e-01, 6.3817200037899757e-01, 8.2062952323391314e-01, 1.0031792915885485e+00, 1.1858420794076876e+00, 1.3686388274702970e+00, 1.5515906753892701e+00, 1.7347189945015418e+00, 1.9180454217825835e+00, 2.1015918949484664e+00, 2.2853806889194859e+00, 2.4694344538319206e+00, 2.6537762547990797e+00, 2.8384296136395832e+00, 3.0234185528101056e+00, 3.2087676418019360e+00, 3.3945020462860152e+00, 3.5806475803201039e+00, 3.7672307619648824e+00, 3.9542788726937901e+00, 4.1418200210249481e+00, 4.3298832108534802e+00, 4.5184984150200371e+00, 4.7076966547174930e+00, 4.8975100854141935e+00, 5.0879720900604992e+00, 5.2791173804478735e+00, 5.4709821077089327e+00, 5.6636039830858733e+00, 5.8570224102572590e+00, 6.0512786307039113e+00, 6.2464158838193349e+00, 6.4424795837354694e+00, 6.6395175151495431e+00, 6.8375800508126918e+00, 7.0367203937895502e+00, 7.2369948481366277e+00, 7.4384631222974562e+00, 7.6411886703008571e+00, 7.8452390768098423e+00, 8.0506864932467330e+00, 8.2576081336726084e+00, 8.4660868409009815e+00, 8.6762117355753663e+00, 8.8880789637690558e+00, 9.1017925622483045e+00, 9.3174654651143189e+00, 9.5352206814286085e+00, 9.7551926810776539e+00, 9.9775290361704698e+00, 1.0202392378570206e+01, 1.0429962752004187e+01, 1.0660440461418377e+01, 1.0894049555564962e+01, 1.1131042125331231e+01, 1.1371703666311570e+01, 1.1616359849416588e+01, 1.1865385183637930e+01, 1.2119214266294843e+01, 1.2378356641882881e+01, 1.2643416807332409e+01, 1.2915121747251227e+01, 1.3194359818522189e+01, 1.3482237346726031e+01, 1.3780164032724846e+01, 1.4089987634289908e+01, 1.4414218332528858e+01, 1.4756429806104775e+01, 1.5122047078570679e+01, 1.5520115371292015e+01, 1.5968188077282482e+01, 1.6512211841757207e+01}, + {-1.6570960596234816e+01, -1.6027574088336884e+01, -1.5580038874389315e+01, -1.5182458010099252e+01, -1.4817296918736639e+01, -1.4475520005731354e+01, -1.4151707989055947e+01, -1.3842290956496822e+01, -1.3544761365310002e+01, -1.3257273397371849e+01, -1.2978418831992128e+01, -1.2707092507353986e+01, -1.2442407004329516e+01, -1.2183636109757821e+01, -1.1930175972733117e+01, -1.1681517598227204e+01, -1.1437226862743914e+01, -1.1196929670964046e+01, -1.0960300717203255e+01, -1.0727054831642461e+01, -1.0496940216738453e+01, -1.0269733090205794e+01, -1.0045233391137220e+01, -9.8232613010212955e+00, -9.6036543973400637e+00, -9.3862653039000534e+00, -9.1709597353376804e+00, -8.9576148574362815e+00, -8.7461179027166409e+00, -8.5363649940564841e+00, -8.3282601391216602e+00, -8.1217143660350786e+00, -7.9166449765926146e+00, -7.7129748979045933e+00, -7.5106321169206671e+00, -7.3095491851216430e+00, -7.1096627829092727e+00, -6.9109133350249667e+00, -6.7132446697794288e+00, -6.5166037160520816e+00, -6.3209402329793747e+00, -6.1262065680386195e+00, -5.9323574398835213e+00, -5.7393497428256754e+00, -5.5471423703043676e+00, -5.3556960550616148e+00, -5.1649732240539885e+00, -4.9749378663979575e+00, -4.7855554128699298e+00, -4.5967926256728040e+00, -4.4086174973432648e+00, -4.2209991578129564e+00, -4.0339077887557737e+00, -3.8473145444559340e+00, -3.6611914785198536e+00, -3.4755114758312047e+00, -3.2902481892147279e+00, -3.1053759803318370e+00, -2.9208698643810656e+00, -2.7367054582199937e+00, -2.5528589315633066e+00, -2.3693069609448871e+00, -2.1860266861608908e+00, -2.0029956689361597e+00, -1.8201918535785517e+00, -1.6375935294051731e+00, -1.4551792947414237e+00, -1.2729280223085093e+00, -1.0908188258278129e+00, -9.0883102768153856e-01, -7.2694412747841530e-01, -5.4513777138121788e-01, -3.6339172205944553e-01, -1.8168582913588810e-01, -0.0000000000000000e+00, 1.8168582913588810e-01, 3.6339172205944553e-01, 5.4513777138121788e-01, 7.2694412747841530e-01, 9.0883102768153856e-01, 1.0908188258278129e+00, 1.2729280223085093e+00, 1.4551792947414237e+00, 1.6375935294051731e+00, 1.8201918535785517e+00, 2.0029956689361597e+00, 2.1860266861608908e+00, 2.3693069609448871e+00, 2.5528589315633066e+00, 2.7367054582199937e+00, 2.9208698643810656e+00, 3.1053759803318370e+00, 3.2902481892147279e+00, 3.4755114758312047e+00, 3.6611914785198536e+00, 3.8473145444559340e+00, 4.0339077887557737e+00, 4.2209991578129564e+00, 4.4086174973432648e+00, 4.5967926256728040e+00, 4.7855554128699298e+00, 4.9749378663979575e+00, 5.1649732240539885e+00, 5.3556960550616148e+00, 5.5471423703043676e+00, 5.7393497428256754e+00, 5.9323574398835213e+00, 6.1262065680386195e+00, 6.3209402329793747e+00, 6.5166037160520816e+00, 6.7132446697794288e+00, 6.9109133350249667e+00, 7.1096627829092727e+00, 7.3095491851216430e+00, 7.5106321169206671e+00, 7.7129748979045933e+00, 7.9166449765926146e+00, 8.1217143660350786e+00, 8.3282601391216602e+00, 8.5363649940564841e+00, 8.7461179027166409e+00, 8.9576148574362815e+00, 9.1709597353376804e+00, 9.3862653039000534e+00, 9.6036543973400637e+00, 9.8232613010212955e+00, 1.0045233391137220e+01, 1.0269733090205794e+01, 1.0496940216738453e+01, 1.0727054831642461e+01, 1.0960300717203255e+01, 1.1196929670964046e+01, 1.1437226862743914e+01, 1.1681517598227204e+01, 1.1930175972733117e+01, 1.2183636109757821e+01, 1.2442407004329516e+01, 1.2707092507353986e+01, 1.2978418831992128e+01, 1.3257273397371849e+01, 1.3544761365310002e+01, 1.3842290956496822e+01, 1.4151707989055947e+01, 1.4475520005731354e+01, 1.4817296918736639e+01, 1.5182458010099252e+01, 1.5580038874389315e+01, 1.6027574088336884e+01, 1.6570960596234816e+01}, + {-1.6629509478833860e+01, -1.6086755105929722e+01, -1.5639752989987683e+01, -1.5242655509972604e+01, -1.4877946763142496e+01, -1.4536600709088953e+01, -1.4213203763983850e+01, -1.3904189753562465e+01, -1.3607053753368865e+01, -1.3319951870041416e+01, -1.3041477351568494e+01, -1.2770526190723876e+01, -1.2506211898605262e+01, -1.2247809027167504e+01, -1.1994714366091593e+01, -1.1746419465057167e+01, -1.1502490670154140e+01, -1.1262554295905716e+01, -1.1026285398343321e+01, -1.0793399130164836e+01, -1.0563643984112028e+01, -1.0336796441464246e+01, -1.0112656682574075e+01, -9.8910451114622759e+00, -9.6717995123443519e+00, -9.4547727023830390e+00, -9.2398305782140078e+00, -9.0268504779630501e+00, -8.8157197982791242e+00, -8.6063348191874436e+00, -8.3985996995836860e+00, -8.1924256138258222e+00, -7.9877300057571530e+00, -7.7844359410588435e+00, -7.5824715424057798e+00, -7.3817694947224117e+00, -7.1822666100804051e+00, -6.9839034435780709e+00, -6.7866239529910715e+00, -6.5903751961596155e+00, -6.3951070610365948e+00, -6.2007720241079047e+00, -6.0073249335450427e+00, -5.8147228139876921e+00, -5.6229246903015975e+00, -5.4318914280313058e+00, -5.2415855885816516e+00, -5.0519712974268067e+00, -4.8630141238699967e+00, -4.6746809710674029e+00, -4.4869399751921195e+00, -4.2997604127527840e+00, -4.1131126152005661e+00, -3.9269678900605394e+00, -3.7412984479117779e+00, -3.5560773346168779e+00, -3.3712783682677476e+00, -3.1868760803720186e+00, -3.0028456608544345e+00, -2.8191629064911972e+00, -2.6358041724333074e+00, -2.4527463265082488e+00, -2.2699667060184630e+00, -2.0874430767805627e+00, -1.9051535941715365e+00, -1.7230767659677173e+00, -1.5411914167793415e+00, -1.3594766538983880e+00, -1.1779118343903046e+00, -9.9647653327140173e-01, -8.1515051262328730e-01, -6.3391369150388599e-01, -4.5274611652143021e-01, -2.7162793294346238e-01, -9.0539356217393022e-02, 9.0539356217393022e-02, 2.7162793294346238e-01, 4.5274611652143021e-01, 6.3391369150388599e-01, 8.1515051262328730e-01, 9.9647653327140173e-01, 1.1779118343903046e+00, 1.3594766538983880e+00, 1.5411914167793415e+00, 1.7230767659677173e+00, 1.9051535941715365e+00, 2.0874430767805627e+00, 2.2699667060184630e+00, 2.4527463265082488e+00, 2.6358041724333074e+00, 2.8191629064911972e+00, 3.0028456608544345e+00, 3.1868760803720186e+00, 3.3712783682677476e+00, 3.5560773346168779e+00, 3.7412984479117779e+00, 3.9269678900605394e+00, 4.1131126152005661e+00, 4.2997604127527840e+00, 4.4869399751921195e+00, 4.6746809710674029e+00, 4.8630141238699967e+00, 5.0519712974268067e+00, 5.2415855885816516e+00, 5.4318914280313058e+00, 5.6229246903015975e+00, 5.8147228139876921e+00, 6.0073249335450427e+00, 6.2007720241079047e+00, 6.3951070610365948e+00, 6.5903751961596155e+00, 6.7866239529910715e+00, 6.9839034435780709e+00, 7.1822666100804051e+00, 7.3817694947224117e+00, 7.5824715424057798e+00, 7.7844359410588435e+00, 7.9877300057571530e+00, 8.1924256138258222e+00, 8.3985996995836860e+00, 8.6063348191874436e+00, 8.8157197982791242e+00, 9.0268504779630501e+00, 9.2398305782140078e+00, 9.4547727023830390e+00, 9.6717995123443519e+00, 9.8910451114622759e+00, 1.0112656682574075e+01, 1.0336796441464246e+01, 1.0563643984112028e+01, 1.0793399130164836e+01, 1.1026285398343321e+01, 1.1262554295905716e+01, 1.1502490670154140e+01, 1.1746419465057167e+01, 1.1994714366091593e+01, 1.2247809027167504e+01, 1.2506211898605262e+01, 1.2770526190723876e+01, 1.3041477351568494e+01, 1.3319951870041416e+01, 1.3607053753368865e+01, 1.3904189753562465e+01, 1.4213203763983850e+01, 1.4536600709088953e+01, 1.4877946763142496e+01, 1.5242655509972604e+01, 1.5639752989987683e+01, 1.6086755105929722e+01, 1.6629509478833860e+01}, + {-1.6687860507628386e+01, -1.6145733223684985e+01, -1.5699259877476434e+01, -1.5302641798879872e+01, -1.4938381618846188e+01, -1.4597462779517947e+01, -1.4274477352553639e+01, -1.3965862873544308e+01, -1.3669117016537621e+01, -1.3382397798268309e+01, -1.3104299924083964e+01, -1.2833720532318454e+01, -1.2569774056886668e+01, -1.2311735808633442e+01, -1.2059003212482786e+01, -1.1811068358148432e+01, -1.1567498057148995e+01, -1.1327919030095220e+01, -1.1092006691295751e+01, -1.0859476512776732e+01, -1.0630077274574017e+01, -1.0403585718697158e+01, -1.0179802264046788e+01, -9.9585475345593846e+00, -9.7396595186399217e+00, -9.5229912243166375e+00, -9.3084087277706491e+00, -9.0957895370391153e+00, -8.8850212104784116e+00, -8.6760001828398110e+00, -8.4686307618168346e+00, -8.2628242655509627e+00, -8.0584982774535074e+00, -7.8555759992614407e+00, -7.6539856868168998e+00, -7.4536601558800220e+00, -7.2545363475276838e+00, -7.0565549444870097e+00, -6.8596600312005922e+00, -6.6637987915949521e+00, -6.4689212394819462e+00, -6.2749799773089512e+00, -6.0819299796217976e+00, -5.8897283981415303e+00, -5.6983343858032613e+00, -5.5077089374792596e+00, -5.3178147454224645e+00, -5.1286160677313077e+00, -4.9400786083607757e+00, -4.7521694073949581e+00, -4.5648567404584961e+00, -4.3781100262830321e+00, -4.1918997415637014e+00, -4.0061973423430199e+00, -3.8209751912478049e+00, -3.6362064899810247e+00, -3.4518652165367119e+00, -3.2679260666634748e+00, -3.0843643991522391e+00, -2.9011561845674412e+00, -2.7182779570790365e+00, -2.5357067690860005e+00, -2.3534201483511836e+00, -2.1713960573929474e+00, -1.9896128549013927e+00, -1.8080492589666075e+00, -1.6266843119235277e+00, -1.4454973466329897e+00, -1.2644679540316108e+00, -1.0835759517944645e+00, -9.0280135396429395e-01, -7.2212434140935688e-01, -5.4152523297908439e-01, -3.6098445723261258e-01, -1.8048252462003789e-01, -0.0000000000000000e+00, 1.8048252462003789e-01, 3.6098445723261258e-01, 5.4152523297908439e-01, 7.2212434140935688e-01, 9.0280135396429395e-01, 1.0835759517944645e+00, 1.2644679540316108e+00, 1.4454973466329897e+00, 1.6266843119235277e+00, 1.8080492589666075e+00, 1.9896128549013927e+00, 2.1713960573929474e+00, 2.3534201483511836e+00, 2.5357067690860005e+00, 2.7182779570790365e+00, 2.9011561845674412e+00, 3.0843643991522391e+00, 3.2679260666634748e+00, 3.4518652165367119e+00, 3.6362064899810247e+00, 3.8209751912478049e+00, 4.0061973423430199e+00, 4.1918997415637014e+00, 4.3781100262830321e+00, 4.5648567404584961e+00, 4.7521694073949581e+00, 4.9400786083607757e+00, 5.1286160677313077e+00, 5.3178147454224645e+00, 5.5077089374792596e+00, 5.6983343858032613e+00, 5.8897283981415303e+00, 6.0819299796217976e+00, 6.2749799773089512e+00, 6.4689212394819462e+00, 6.6637987915949521e+00, 6.8596600312005922e+00, 7.0565549444870097e+00, 7.2545363475276838e+00, 7.4536601558800220e+00, 7.6539856868168998e+00, 7.8555759992614407e+00, 8.0584982774535074e+00, 8.2628242655509627e+00, 8.4686307618168346e+00, 8.6760001828398110e+00, 8.8850212104784116e+00, 9.0957895370391153e+00, 9.3084087277706491e+00, 9.5229912243166375e+00, 9.7396595186399217e+00, 9.9585475345593846e+00, 1.0179802264046788e+01, 1.0403585718697158e+01, 1.0630077274574017e+01, 1.0859476512776732e+01, 1.1092006691295751e+01, 1.1327919030095220e+01, 1.1567498057148995e+01, 1.1811068358148432e+01, 1.2059003212482786e+01, 1.2311735808633442e+01, 1.2569774056886668e+01, 1.2833720532318454e+01, 1.3104299924083964e+01, 1.3382397798268309e+01, 1.3669117016537621e+01, 1.3965862873544308e+01, 1.4274477352553639e+01, 1.4597462779517947e+01, 1.4938381618846188e+01, 1.5302641798879872e+01, 1.5699259877476434e+01, 1.6145733223684985e+01, 1.6687860507628386e+01}, + {-1.6746015667021069e+01, -1.6204510499941978e+01, -1.5758561659537367e+01, -1.5362419059461168e+01, -1.4998603726021303e+01, -1.4658108513302281e+01, -1.4335531106337195e+01, -1.4027312722878635e+01, -1.3730953615978237e+01, -1.3444613698016527e+01, -1.3166889120550762e+01, -1.2896678158583638e+01, -1.2633096161556749e+01, -1.2375419193081754e+01, -1.2123045308073459e+01, -1.1875467131689264e+01, -1.1632251936796413e+01, -1.1393026846411182e+01, -1.1157467629750515e+01, -1.0925290075047540e+01, -1.0696243246707187e+01, -1.0470104144699656e+01, -1.0246673423826493e+01, -1.0025771925388167e+01, -9.8072378395003508e+00, -9.5909243626320890e+00, -9.3766977481232310e+00, -9.1644356715597066e+00, -8.9540258506546646e+00, -8.7453648725360029e+00, -8.5383571913371981e+00, -8.3329142666081459e+00, -8.1289538189277764e+00, -7.9263991836556649e+00, -7.7251787473280729e+00, -7.5252254540210100e+00, -7.3264763712435084e+00, -7.1288723067188302e+00, -6.9323574688579237e+00, -6.7368791649028887e+00, -6.5423875316754021e+00, -6.3488352946504518e+00, -6.1561775517231760e+00, -5.9643715785732399e+00, -5.7733766529779098e+00, -5.5831538957985396e+00, -5.3936661266788803e+00, -5.2048777327581446e+00, -5.0167545489255820e+00, -4.8292637483334380e+00, -4.6423737420472682e+00, -4.4560540868511129e+00, -4.2702754003439098e+00, -4.0850092825657862e+00, -3.9002282434810596e+00, -3.7159056357210827e+00, -3.5320155920561942e+00, -3.3485329671235227e+00, -3.1654332829874168e+00, -2.9826926781529521e+00, -2.8002878596910716e+00, -2.6181960581673263e+00, -2.4363949850953830e+00, -2.2548627926621019e+00, -2.0735780354934534e+00, -1.8925196342502328e+00, -1.7116668408598084e+00, -1.5309992052052144e+00, -1.3504965431061176e+00, -1.1701389054376192e+00, -9.8990654824282009e-01, -8.0977990370358899e-01, -6.2973955184126684e-01, -4.4976619282513375e-01, -2.6984061977151302e-01, -8.9943691920400901e-02, 8.9943691920400901e-02, 2.6984061977151302e-01, 4.4976619282513375e-01, 6.2973955184126684e-01, 8.0977990370358899e-01, 9.8990654824282009e-01, 1.1701389054376192e+00, 1.3504965431061176e+00, 1.5309992052052144e+00, 1.7116668408598084e+00, 1.8925196342502328e+00, 2.0735780354934534e+00, 2.2548627926621019e+00, 2.4363949850953830e+00, 2.6181960581673263e+00, 2.8002878596910716e+00, 2.9826926781529521e+00, 3.1654332829874168e+00, 3.3485329671235227e+00, 3.5320155920561942e+00, 3.7159056357210827e+00, 3.9002282434810596e+00, 4.0850092825657862e+00, 4.2702754003439098e+00, 4.4560540868511129e+00, 4.6423737420472682e+00, 4.8292637483334380e+00, 5.0167545489255820e+00, 5.2048777327581446e+00, 5.3936661266788803e+00, 5.5831538957985396e+00, 5.7733766529779098e+00, 5.9643715785732399e+00, 6.1561775517231760e+00, 6.3488352946504518e+00, 6.5423875316754021e+00, 6.7368791649028887e+00, 6.9323574688579237e+00, 7.1288723067188302e+00, 7.3264763712435084e+00, 7.5252254540210100e+00, 7.7251787473280729e+00, 7.9263991836556649e+00, 8.1289538189277764e+00, 8.3329142666081459e+00, 8.5383571913371981e+00, 8.7453648725360029e+00, 8.9540258506546646e+00, 9.1644356715597066e+00, 9.3766977481232310e+00, 9.5909243626320890e+00, 9.8072378395003508e+00, 1.0025771925388167e+01, 1.0246673423826493e+01, 1.0470104144699656e+01, 1.0696243246707187e+01, 1.0925290075047540e+01, 1.1157467629750515e+01, 1.1393026846411182e+01, 1.1632251936796413e+01, 1.1875467131689264e+01, 1.2123045308073459e+01, 1.2375419193081754e+01, 1.2633096161556749e+01, 1.2896678158583638e+01, 1.3166889120550762e+01, 1.3444613698016527e+01, 1.3730953615978237e+01, 1.4027312722878635e+01, 1.4335531106337195e+01, 1.4658108513302281e+01, 1.4998603726021303e+01, 1.5362419059461168e+01, 1.5758561659537367e+01, 1.6204510499941978e+01, 1.6746015667021069e+01}, + {-1.6803976908523694e+01, -1.6263088958580713e+01, -1.5817660423010251e+01, -1.5421989437211316e+01, -1.5058615286432362e+01, -1.4718540167071973e+01, -1.4396367336014109e+01, -1.4088541665869107e+01, -1.3792565969471646e+01, -1.3506602040607744e+01, -1.3229247466060766e+01, -1.2959401648746917e+01, -1.2696180846459008e+01, -1.2438861869552357e+01, -1.2186843397769389e+01, -1.1939618587201746e+01, -1.1696755168060276e+01, -1.1457880662155430e+01, -1.1222671190311015e+01, -1.0990842853911044e+01, -1.0762144998868230e+01, -1.0536354880406639e+01, -1.0313273386643994e+01, -1.0092721573755421e+01, -9.8745378311513203e+00, -9.6585755413803565e+00, -9.4447011326189330e+00, -9.2327924457049324e+00, -9.0227373554249493e+00, -8.8144325990031405e+00, -8.6077827747261111e+00, -8.4026994812503251e+00, -8.1991005739976206e+00, -7.9969095195952864e+00, -7.7960548328817607e+00, -7.5964695838133709e+00, -7.3980909638458217e+00, -7.2008599031569602e+00, -7.0047207315224398e+00, -6.8096208768281805e+00, -6.6155105961598455e+00, -6.4223427351940696e+00, -6.2300725122630887e+00, -6.0386573240004857e+00, -5.8480565699220763e+00, -5.6582314936691613e+00, -5.4691450389548066e+00, -5.2807617185180318e+00, -5.0930474946144608e+00, -4.9059696697619373e+00, -4.7194967866215638e+00, -4.5335985360330326e+00, -4.3482456723419469e+00, -4.1634099352589846e+00, -3.9790639775789276e+00, -3.7951812981638180e+00, -3.6117361796606513e+00, -3.4287036304814422e+00, -3.2460593306235781e+00, -3.0637795809520179e+00, -2.8818412556030690e+00, -2.7002217572028795e+00, -2.5188989746230557e+00, -2.3378512430214919e+00, -2.1570573059390363e+00, -1.9764962792423748e+00, -1.7961476167208907e+00, -1.6159910771604287e+00, -1.4360066927302104e+00, -1.2561747385307371e+00, -1.0764757031605943e+00, -8.9689026016876394e-01, -7.1739924026651414e-01, -5.3798360417923241e-01, -3.5862441602383283e-01, -1.7930281710163956e-01, -0.0000000000000000e+00, 1.7930281710163956e-01, 3.5862441602383283e-01, 5.3798360417923241e-01, 7.1739924026651414e-01, 8.9689026016876394e-01, 1.0764757031605943e+00, 1.2561747385307371e+00, 1.4360066927302104e+00, 1.6159910771604287e+00, 1.7961476167208907e+00, 1.9764962792423748e+00, 2.1570573059390363e+00, 2.3378512430214919e+00, 2.5188989746230557e+00, 2.7002217572028795e+00, 2.8818412556030690e+00, 3.0637795809520179e+00, 3.2460593306235781e+00, 3.4287036304814422e+00, 3.6117361796606513e+00, 3.7951812981638180e+00, 3.9790639775789276e+00, 4.1634099352589846e+00, 4.3482456723419469e+00, 4.5335985360330326e+00, 4.7194967866215638e+00, 4.9059696697619373e+00, 5.0930474946144608e+00, 5.2807617185180318e+00, 5.4691450389548066e+00, 5.6582314936691613e+00, 5.8480565699220763e+00, 6.0386573240004857e+00, 6.2300725122630887e+00, 6.4223427351940696e+00, 6.6155105961598455e+00, 6.8096208768281805e+00, 7.0047207315224398e+00, 7.2008599031569602e+00, 7.3980909638458217e+00, 7.5964695838133709e+00, 7.7960548328817607e+00, 7.9969095195952864e+00, 8.1991005739976206e+00, 8.4026994812503251e+00, 8.6077827747261111e+00, 8.8144325990031405e+00, 9.0227373554249493e+00, 9.2327924457049324e+00, 9.4447011326189330e+00, 9.6585755413803565e+00, 9.8745378311513203e+00, 1.0092721573755421e+01, 1.0313273386643994e+01, 1.0536354880406639e+01, 1.0762144998868230e+01, 1.0990842853911044e+01, 1.1222671190311015e+01, 1.1457880662155430e+01, 1.1696755168060276e+01, 1.1939618587201746e+01, 1.2186843397769389e+01, 1.2438861869552357e+01, 1.2696180846459008e+01, 1.2959401648746917e+01, 1.3229247466060766e+01, 1.3506602040607744e+01, 1.3792565969471646e+01, 1.4088541665869107e+01, 1.4396367336014109e+01, 1.4718540167071973e+01, 1.5058615286432362e+01, 1.5421989437211316e+01, 1.5817660423010251e+01, 1.6263088958580713e+01, 1.6803976908523694e+01}, + {-1.6861746151514453e+01, -1.6321470589822656e+01, -1.5876558219732326e+01, -1.5481355041356229e+01, -1.5118418464347313e+01, -1.4778759958751550e+01, -1.4456988312356128e+01, -1.4149552025707647e+01, -1.3853956452475600e+01, -1.3568365253816872e+01, -1.3291377440919536e+01, -1.3021893535990777e+01, -1.2759030698111300e+01, -1.2502066478454370e+01, -1.2250400176513523e+01, -1.2003525474883981e+01, -1.1761010557188053e+01, -1.1522483340487554e+01, -1.1287620293977072e+01, -1.1056137829198551e+01, -1.0827785570772761e+01, -1.0602341026531503e+01, -1.0379605315384135e+01, -1.0159399705951289e+01, -9.9415627845826098e+00, -9.7259481176063289e+00, -9.5124223057752690e+00, -9.3008633529456954e+00, -9.0911592887589681e+00, -8.8832069983214303e+00, -8.6769112218541409e+00, -8.4721836948885070e+00, -8.2689424054370715e+00, -8.0671109491149302e+00, -7.8666179667484384e+00, -7.6673966518192671e+00, -7.4693843173280303e+00, -7.2725220134526776e+00, -7.0767541888205505e+00, -6.8820283893841117e+00, -6.6882949898457129e+00, -6.4955069533605654e+00, -6.3036196158933109e+00, -6.1125904921391818e+00, -5.9223791003665953e+00, -5.7329468039109130e+00, -5.5442566673621716e+00, -5.3562733257536657e+00, -5.1689628652816504e+00, -4.9822927142762881e+00, -4.7962315433057050e+00, -4.6107491734334216e+00, -4.4258164917680798e+00, -4.2414053735465238e+00, -4.0574886100793801e+00, -3.8740398419645214e+00, -3.6910334970398750e+00, -3.5084447326044930e+00, -3.3262493814868481e+00, -3.1444239015829951e+00, -2.9629453285254086e+00, -2.7817912311767614e+00, -2.6009396696722078e+00, -2.4203691557594618e+00, -2.2400586152085502e+00, -2.0599873520829730e+00, -1.8801350146814075e+00, -1.7004815629744074e+00, -1.5210072373739318e+00, -1.3416925286852595e+00, -1.1625181491010375e+00, -9.8346500410607329e-01, -8.0451416516907071e-01, -6.2564684310401653e-01, -4.4684436198936728e-01, -2.6808813353769451e-01, -8.9359631812036308e-02, 8.9359631812036308e-02, 2.6808813353769451e-01, 4.4684436198936728e-01, 6.2564684310401653e-01, 8.0451416516907071e-01, 9.8346500410607329e-01, 1.1625181491010375e+00, 1.3416925286852595e+00, 1.5210072373739318e+00, 1.7004815629744074e+00, 1.8801350146814075e+00, 2.0599873520829730e+00, 2.2400586152085502e+00, 2.4203691557594618e+00, 2.6009396696722078e+00, 2.7817912311767614e+00, 2.9629453285254086e+00, 3.1444239015829951e+00, 3.3262493814868481e+00, 3.5084447326044930e+00, 3.6910334970398750e+00, 3.8740398419645214e+00, 4.0574886100793801e+00, 4.2414053735465238e+00, 4.4258164917680798e+00, 4.6107491734334216e+00, 4.7962315433057050e+00, 4.9822927142762881e+00, 5.1689628652816504e+00, 5.3562733257536657e+00, 5.5442566673621716e+00, 5.7329468039109130e+00, 5.9223791003665953e+00, 6.1125904921391818e+00, 6.3036196158933109e+00, 6.4955069533605654e+00, 6.6882949898457129e+00, 6.8820283893841117e+00, 7.0767541888205505e+00, 7.2725220134526776e+00, 7.4693843173280303e+00, 7.6673966518192671e+00, 7.8666179667484384e+00, 8.0671109491149302e+00, 8.2689424054370715e+00, 8.4721836948885070e+00, 8.6769112218541409e+00, 8.8832069983214303e+00, 9.0911592887589681e+00, 9.3008633529456954e+00, 9.5124223057752690e+00, 9.7259481176063289e+00, 9.9415627845826098e+00, 1.0159399705951289e+01, 1.0379605315384135e+01, 1.0602341026531503e+01, 1.0827785570772761e+01, 1.1056137829198551e+01, 1.1287620293977072e+01, 1.1522483340487554e+01, 1.1761010557188053e+01, 1.2003525474883981e+01, 1.2250400176513523e+01, 1.2502066478454370e+01, 1.2759030698111300e+01, 1.3021893535990777e+01, 1.3291377440919536e+01, 1.3568365253816872e+01, 1.3853956452475600e+01, 1.4149552025707647e+01, 1.4456988312356128e+01, 1.4778759958751550e+01, 1.5118418464347313e+01, 1.5481355041356229e+01, 1.5876558219732326e+01, 1.6321470589822656e+01, 1.6861746151514453e+01}, + {-1.6919325283973091e+01, -1.6379657351007765e+01, -1.5935257067352701e+01, -1.5540517945702927e+01, -1.5178015387422422e+01, -1.4838770068479555e+01, -1.4517396267181470e+01, -1.4210346085463854e+01, -1.3915127399149720e+01, -1.3629905722933353e+01, -1.3353281481744700e+01, -1.3084156308589026e+01, -1.2821648256881092e+01, -1.2565035612781342e+01, -1.2313718290542331e+01, -1.2067190494908804e+01, -1.1825020859053186e+01, -1.1586837691812352e+01, -1.1352317807578974e+01, -1.1121177925121051e+01, -1.0893167945027271e+01, -1.0668065625149652e+01, -1.0445672312722746e+01, -1.0225809486441577e+01, -1.0008315927297842e+01, -9.7930453831581623e+00, -9.5798646251513500e+00, -9.3686518179792717e+00, -9.1592951439814989e+00, -8.9516916339961323e+00, -8.7457461680254056e+00, -8.5413706163114078e+00, -8.3384830972746489e+00, -8.1370073333099651e+00, -7.9368720889917341e+00, -7.7380106790491130e+00, -7.5403605357059194e+00, -7.3438628267689321e+00, -7.1484621172907721e+00, -6.9541060688033616e+00, -6.7607451710725037e+00, -6.5683325021070607e+00, -6.3768235128018915e+00, -6.1861758331287540e+00, -5.9963490972348117e+00, -5.8073047851809010e+00, -5.6190060793645857e+00, -5.4314177339367200e+00, -5.2445059557435734e+00, -5.0582382955161487e+00, -4.8725835481900202e+00, -4.6875116613772301e+00, -4.5029936511304234e+00, -4.3190015242413970e+00, -4.1355082064043351e+00, -3.9524874756501580e+00, -3.7699139005244779e+00, -3.5877627825391012e+00, -3.4060101024770435e+00, -3.2246324701747149e+00, -3.0436070774431303e+00, -2.8629116538234336e+00, -2.6825244249014188e+00, -2.5024240729314422e+00, -2.3225896995428044e+00, -2.1430007903215516e+00, -1.9636371810781683e+00, -1.7844790256269836e+00, -1.6055067649166126e+00, -1.4267010973625776e+00, -1.2480429502435568e+00, -1.0695134520316971e+00, -8.9109390553517087e-01, -7.1276576173782080e-01, -5.3451059422635872e-01, -3.5631007410029453e-01, -1.7814594526358507e-01, -0.0000000000000000e+00, 1.7814594526358507e-01, 3.5631007410029453e-01, 5.3451059422635872e-01, 7.1276576173782080e-01, 8.9109390553517087e-01, 1.0695134520316971e+00, 1.2480429502435568e+00, 1.4267010973625776e+00, 1.6055067649166126e+00, 1.7844790256269836e+00, 1.9636371810781683e+00, 2.1430007903215516e+00, 2.3225896995428044e+00, 2.5024240729314422e+00, 2.6825244249014188e+00, 2.8629116538234336e+00, 3.0436070774431303e+00, 3.2246324701747149e+00, 3.4060101024770435e+00, 3.5877627825391012e+00, 3.7699139005244779e+00, 3.9524874756501580e+00, 4.1355082064043351e+00, 4.3190015242413970e+00, 4.5029936511304234e+00, 4.6875116613772301e+00, 4.8725835481900202e+00, 5.0582382955161487e+00, 5.2445059557435734e+00, 5.4314177339367200e+00, 5.6190060793645857e+00, 5.8073047851809010e+00, 5.9963490972348117e+00, 6.1861758331287540e+00, 6.3768235128018915e+00, 6.5683325021070607e+00, 6.7607451710725037e+00, 6.9541060688033616e+00, 7.1484621172907721e+00, 7.3438628267689321e+00, 7.5403605357059194e+00, 7.7380106790491130e+00, 7.9368720889917341e+00, 8.1370073333099651e+00, 8.3384830972746489e+00, 8.5413706163114078e+00, 8.7457461680254056e+00, 8.9516916339961323e+00, 9.1592951439814989e+00, 9.3686518179792717e+00, 9.5798646251513500e+00, 9.7930453831581623e+00, 1.0008315927297842e+01, 1.0225809486441577e+01, 1.0445672312722746e+01, 1.0668065625149652e+01, 1.0893167945027271e+01, 1.1121177925121051e+01, 1.1352317807578974e+01, 1.1586837691812352e+01, 1.1825020859053186e+01, 1.2067190494908804e+01, 1.2313718290542331e+01, 1.2565035612781342e+01, 1.2821648256881092e+01, 1.3084156308589026e+01, 1.3353281481744700e+01, 1.3629905722933353e+01, 1.3915127399149720e+01, 1.4210346085463854e+01, 1.4517396267181470e+01, 1.4838770068479555e+01, 1.5178015387422422e+01, 1.5540517945702927e+01, 1.5935257067352701e+01, 1.6379657351007765e+01, 1.6919325283973091e+01}, + {-1.6976716163194499e+01, -1.6437651167348605e+01, -1.5993758950122626e+01, -1.5599480189464179e+01, -1.5237408147560531e+01, -1.4898572639500255e+01, -1.4577593394280033e+01, -1.4270926089044083e+01, -1.3976081103348914e+01, -1.3691225791789593e+01, -1.3414961982530070e+01, -1.3146192411007465e+01, -1.2884036018123565e+01, -1.2627771819287853e+01, -1.2376800338602001e+01, -1.2130616298680719e+01, -1.1888788778454018e+01, -1.1650946475122105e+01, -1.1416766545164455e+01, -1.1185966011702471e+01, -1.0958295048610227e+01, -1.0733531661229089e+01, -1.0511477422708499e+01, -1.0291954019502739e+01, -1.0074800425004574e+01, -9.8598705664345285e+00, -9.6470313831544541e+00, -9.4361611985975138e+00, -9.2271483457046273e+00, -9.0198899989563817e+00, -8.8142911760456872e+00, -8.6102638798256326e+00, -8.4077263570086043e+00, -8.2066024546299392e+00, -8.0068210588433661e+00, -7.8083156034214856e+00, -7.6110236375661993e+00, -7.4148864444214286e+00, -7.2198487031214214e+00, -7.0258581883766524e+00, -6.8328655025529308e+00, -6.6408238359815064e+00, -6.4496887518830528e+00, -6.2594179928228799e+00, -6.0699713060598244e+00, -5.8813102855233703e+00, -5.6933982284661457e+00, -5.5062000051024196e+00, -5.3196819397663528e+00, -5.1338117023131167e+00, -4.9485582086476523e+00, -4.7638915294038444e+00, -4.5797828059155004e+00, -4.3962041727224284e+00, -4.2131286859429329e+00, -4.0305302569201968e+00, -3.8483835906160127e+00, -3.6666641282827874e+00, -3.4853479939947509e+00, -3.3044119446629794e+00, -3.1238333231970716e+00, -2.9435900145097715e+00, -2.7636604040902180e+00, -2.5840233388973028e+00, -2.4046580903472949e+00, -2.2255443191898578e+00, -2.0466620420841379e+00, -1.8679915997020398e+00, -1.6895136261993984e+00, -1.5112090199076367e+00, -1.3330589151089478e+00, -1.1550446547671134e+00, -9.7714776409397042e-01, -7.9934992483832146e-01, -6.2163295018989517e-01, -4.4397876019583243e-01, -2.6636935759120106e-01, -8.8786803948269877e-02, 8.8786803948269877e-02, 2.6636935759120106e-01, 4.4397876019583243e-01, 6.2163295018989517e-01, 7.9934992483832146e-01, 9.7714776409397042e-01, 1.1550446547671134e+00, 1.3330589151089478e+00, 1.5112090199076367e+00, 1.6895136261993984e+00, 1.8679915997020398e+00, 2.0466620420841379e+00, 2.2255443191898578e+00, 2.4046580903472949e+00, 2.5840233388973028e+00, 2.7636604040902180e+00, 2.9435900145097715e+00, 3.1238333231970716e+00, 3.3044119446629794e+00, 3.4853479939947509e+00, 3.6666641282827874e+00, 3.8483835906160127e+00, 4.0305302569201968e+00, 4.2131286859429329e+00, 4.3962041727224284e+00, 4.5797828059155004e+00, 4.7638915294038444e+00, 4.9485582086476523e+00, 5.1338117023131167e+00, 5.3196819397663528e+00, 5.5062000051024196e+00, 5.6933982284661457e+00, 5.8813102855233703e+00, 6.0699713060598244e+00, 6.2594179928228799e+00, 6.4496887518830528e+00, 6.6408238359815064e+00, 6.8328655025529308e+00, 7.0258581883766524e+00, 7.2198487031214214e+00, 7.4148864444214286e+00, 7.6110236375661993e+00, 7.8083156034214856e+00, 8.0068210588433661e+00, 8.2066024546299392e+00, 8.4077263570086043e+00, 8.6102638798256326e+00, 8.8142911760456872e+00, 9.0198899989563817e+00, 9.2271483457046273e+00, 9.4361611985975138e+00, 9.6470313831544541e+00, 9.8598705664345285e+00, 1.0074800425004574e+01, 1.0291954019502739e+01, 1.0511477422708499e+01, 1.0733531661229089e+01, 1.0958295048610227e+01, 1.1185966011702471e+01, 1.1416766545164455e+01, 1.1650946475122105e+01, 1.1888788778454018e+01, 1.2130616298680719e+01, 1.2376800338602001e+01, 1.2627771819287853e+01, 1.2884036018123565e+01, 1.3146192411007465e+01, 1.3414961982530070e+01, 1.3691225791789593e+01, 1.3976081103348914e+01, 1.4270926089044083e+01, 1.4577593394280033e+01, 1.4898572639500255e+01, 1.5237408147560531e+01, 1.5599480189464179e+01, 1.5993758950122626e+01, 1.6437651167348605e+01, 1.6976716163194499e+01}, + {-1.7033920616481659e+01, -1.6495453932662432e+01, -1.6052065819662449e+01, -1.5658243778058655e+01, -1.5296598801743723e+01, -1.4958169779028550e+01, -1.4637581850310665e+01, -1.4331294242121345e+01, -1.4036819819586414e+01, -1.3752327763757672e+01, -1.3476421295676769e+01, -1.3208004244970210e+01, -1.2946196433284063e+01, -1.2690277599628986e+01, -1.2439648873125966e+01, -1.2193805490052643e+01, -1.1952316971370964e+01, -1.1714812399295406e+01, -1.1480969269340585e+01, -1.1250504906165974e+01, -1.1023169754304320e+01, -1.0798742064110225e+01, -1.0577023632291938e+01, -1.0357836350801911e+01, -1.0141019383247183e+01, -9.9264268340723447e+00, -9.7139258087846567e+00, -9.5033947874905458e+00, -9.2947222516928303e+00, -9.0878055174840568e+00, -8.8825497382175893e+00, -8.6788670473198550e+00, -8.4766758177429260e+00, -8.2759000190893772e+00, -8.0764686569918620e+00, -7.8783152821330633e+00, -7.6813775585211594e+00, -7.4855968824216461e+00, -7.2909180447858821e+00, -7.0972889311843357e+00, -6.9046602542051492e+00, -6.7129853140601305e+00, -6.5222197837846556e+00, -6.3323215159520476e+00, -6.1432503682675650e+00, -5.9549680457789771e+00, -5.7674379577529349e+00, -5.5806250875296657e+00, -5.3944958738913487e+00, -5.2090181026688498e+00, -5.0241608074728896e+00, -4.8398941785737106e+00, -4.6561894790717648e+00, -4.4730189676038190e+00, -4.2903558269168203e+00, -4.1081740977179662e+00, -3.9264486172753981e+00, -3.7451549623013909e+00, -3.5642693956998519e+00, -3.3837688168037010e+00, -3.2036307147658607e+00, -3.0238331248011101e+00, -2.8443545870054412e+00, -2.6651741075053921e+00, -2.4862711217125546e+00, -2.3076254594784578e+00, -2.1292173119626474e+00, -1.9510272000422848e+00, -1.7730359441052344e+00, -1.5952246350806079e+00, -1.4175746065712449e+00, -1.2400674079618077e+00, -1.0626847783841744e+00, -8.8540862142874210e-01, -7.0822098049619520e-01, -5.3110401468933777e-01, -3.5403997514879265e-01, -1.7701118173979521e-01, -0.0000000000000000e+00, 1.7701118173979521e-01, 3.5403997514879265e-01, 5.3110401468933777e-01, 7.0822098049619520e-01, 8.8540862142874210e-01, 1.0626847783841744e+00, 1.2400674079618077e+00, 1.4175746065712449e+00, 1.5952246350806079e+00, 1.7730359441052344e+00, 1.9510272000422848e+00, 2.1292173119626474e+00, 2.3076254594784578e+00, 2.4862711217125546e+00, 2.6651741075053921e+00, 2.8443545870054412e+00, 3.0238331248011101e+00, 3.2036307147658607e+00, 3.3837688168037010e+00, 3.5642693956998519e+00, 3.7451549623013909e+00, 3.9264486172753981e+00, 4.1081740977179662e+00, 4.2903558269168203e+00, 4.4730189676038190e+00, 4.6561894790717648e+00, 4.8398941785737106e+00, 5.0241608074728896e+00, 5.2090181026688498e+00, 5.3944958738913487e+00, 5.5806250875296657e+00, 5.7674379577529349e+00, 5.9549680457789771e+00, 6.1432503682675650e+00, 6.3323215159520476e+00, 6.5222197837846556e+00, 6.7129853140601305e+00, 6.9046602542051492e+00, 7.0972889311843357e+00, 7.2909180447858821e+00, 7.4855968824216461e+00, 7.6813775585211594e+00, 7.8783152821330633e+00, 8.0764686569918620e+00, 8.2759000190893772e+00, 8.4766758177429260e+00, 8.6788670473198550e+00, 8.8825497382175893e+00, 9.0878055174840568e+00, 9.2947222516928303e+00, 9.5033947874905458e+00, 9.7139258087846567e+00, 9.9264268340723447e+00, 1.0141019383247183e+01, 1.0357836350801911e+01, 1.0577023632291938e+01, 1.0798742064110225e+01, 1.1023169754304320e+01, 1.1250504906165974e+01, 1.1480969269340585e+01, 1.1714812399295406e+01, 1.1952316971370964e+01, 1.2193805490052643e+01, 1.2439648873125966e+01, 1.2690277599628986e+01, 1.2946196433284063e+01, 1.3208004244970210e+01, 1.3476421295676769e+01, 1.3752327763757672e+01, 1.4036819819586414e+01, 1.4331294242121345e+01, 1.4637581850310665e+01, 1.4958169779028550e+01, 1.5296598801743723e+01, 1.5658243778058655e+01, 1.6052065819662449e+01, 1.6495453932662432e+01, 1.7033920616481659e+01}, + {-1.7090940441818589e+01, -1.6553067510081998e+01, -1.6110179595706111e+01, -1.5716810683887498e+01, -1.5355589372841228e+01, -1.5017563559089020e+01, -1.4697363755671436e+01, -1.4391452713037102e+01, -1.4097345763967498e+01, -1.3813213902715583e+01, -1.3537661732992635e+01, -1.3269594170493015e+01, -1.3008131910966144e+01, -1.2752555411464087e+01, -1.2502266401375357e+01, -1.2256760626504082e+01, -1.2015608046183521e+01, -1.1778438124354272e+01, -1.1544928692572215e+01, -1.1314797374275166e+01, -1.1087794882081830e+01, -1.0863699708936927e+01, -1.0642313872803815e+01, -1.0423459468924202e+01, -1.0206975848984905e+01, -9.9927172925773995e+00, -9.7805510693200404e+00, -9.5703558139886304e+00, -9.3620201546636572e+00, -9.1554415470755703e+00, -8.9505252782658893e+00, -8.7471836102562435e+00, -8.5453350402475099e+00, -8.3449036583995202e+00, -8.1458185877888383e+00, -7.9480134939425788e+00, -7.7514261535735791e+00, -7.5559980739261903e+00, -7.3616741555800598e+00, -7.1684023927258176e+00, -6.9761336058782426e+00, -6.7848212027732666e+00, -6.5944209638389415e+00, -6.4048908491640280e+00, -6.2161908243320640e+00, -6.0282827028602410e+00, -5.8411300032943645e+00, -5.6546978192742712e+00, -5.4689527011066783e+00, -5.2838625475716334e+00, -5.0993965068499545e+00, -4.9155248855969580e+00, -4.7322190653061282e+00, -4.5494514252081650e+00, -4.3671952710387769e+00, -4.1854247690845812e+00, -4.0041148849824761e+00, -3.8232413268052290e+00, -3.6427804920159894e+00, -3.4627094179181652e+00, -3.2830057352652728e+00, -3.1036476247289064e+00, -2.9246137759523689e+00, -2.7458833489433849e+00, -2.5674359375820566e+00, -2.3892515350402799e+00, -2.2113105009265008e+00, -2.0335935299852599e+00, -1.8560816221946776e+00, -1.6787560541171089e+00, -1.5015983513687976e+00, -1.3245902620836472e+00, -1.1477137312543411e+00, -9.7095087584109574e-01, -7.9428396054439432e-01, -6.1769537414325426e-01, -4.4116760630493546e-01, -2.6468322477561551e-01, -8.8224852864438347e-02, 8.8224852864438347e-02, 2.6468322477561551e-01, 4.4116760630493546e-01, 6.1769537414325426e-01, 7.9428396054439432e-01, 9.7095087584109574e-01, 1.1477137312543411e+00, 1.3245902620836472e+00, 1.5015983513687976e+00, 1.6787560541171089e+00, 1.8560816221946776e+00, 2.0335935299852599e+00, 2.2113105009265008e+00, 2.3892515350402799e+00, 2.5674359375820566e+00, 2.7458833489433849e+00, 2.9246137759523689e+00, 3.1036476247289064e+00, 3.2830057352652728e+00, 3.4627094179181652e+00, 3.6427804920159894e+00, 3.8232413268052290e+00, 4.0041148849824761e+00, 4.1854247690845812e+00, 4.3671952710387769e+00, 4.5494514252081650e+00, 4.7322190653061282e+00, 4.9155248855969580e+00, 5.0993965068499545e+00, 5.2838625475716334e+00, 5.4689527011066783e+00, 5.6546978192742712e+00, 5.8411300032943645e+00, 6.0282827028602410e+00, 6.2161908243320640e+00, 6.4048908491640280e+00, 6.5944209638389415e+00, 6.7848212027732666e+00, 6.9761336058782426e+00, 7.1684023927258176e+00, 7.3616741555800598e+00, 7.5559980739261903e+00, 7.7514261535735791e+00, 7.9480134939425788e+00, 8.1458185877888383e+00, 8.3449036583995202e+00, 8.5453350402475099e+00, 8.7471836102562435e+00, 8.9505252782658893e+00, 9.1554415470755703e+00, 9.3620201546636572e+00, 9.5703558139886304e+00, 9.7805510693200404e+00, 9.9927172925773995e+00, 1.0206975848984905e+01, 1.0423459468924202e+01, 1.0642313872803815e+01, 1.0863699708936927e+01, 1.1087794882081830e+01, 1.1314797374275166e+01, 1.1544928692572215e+01, 1.1778438124354272e+01, 1.2015608046183521e+01, 1.2256760626504082e+01, 1.2502266401375357e+01, 1.2752555411464087e+01, 1.3008131910966144e+01, 1.3269594170493015e+01, 1.3537661732992635e+01, 1.3813213902715583e+01, 1.4097345763967498e+01, 1.4391452713037102e+01, 1.4697363755671436e+01, 1.5017563559089020e+01, 1.5355589372841228e+01, 1.5716810683887498e+01, 1.6110179595706111e+01, 1.6553067510081998e+01, 1.7090940441818589e+01}, + {-1.7147777408524032e+01, -1.6610493732745791e+01, -1.6168102166823996e+01, -1.5775182847088153e+01, -1.5414381850393539e+01, -1.5076756017330117e+01, -1.4756941195343936e+01, -1.4451403633675961e+01, -1.4157661115094985e+01, -1.3873886433984071e+01, -1.3598685566661047e+01, -1.3330964506884797e+01, -1.3069844817966612e+01, -1.2814607669526135e+01, -1.2564655386543684e+01, -1.2319484220282153e+01, -1.2078664564848737e+01, -1.1841826262681151e+01, -1.1608647478438799e+01, -1.1378846131631990e+01, -1.1152173200444981e+01, -1.0928407418040756e+01, -1.0707351021384738e+01, -1.0488826306849386e+01, -1.0272672812117237e+01, -1.0058744989900266e+01, -9.8469102719449655e+00, -9.6370474457447699e+00, -9.4290452840267438e+00, -9.2228013802394901e+00, -9.0182211531960341e+00, -8.8152169915922389e+00, -8.6137075149457782e+00, -8.4136169320244640e+00, -8.2148744813764658e+00, -8.0174139413725705e+00, -7.8211731993958935e+00, -7.6260938715966651e+00, -7.4321209660664360e+00, -7.2392025834514619e+00, -7.0472896499758120e+00, -6.8563356786247329e+00, -6.6662965548819884e+00, -6.4771303439479562e+00, -6.2887971168089667e+00, -6.1012587928995696e+00, -5.9144789974110621e+00, -5.7284229315624149e+00, -5.5430572543722416e+00, -5.3583499746593573e+00, -5.1742703521606801e+00, -4.9907888067929420e+00, -4.8078768352029666e+00, -4.6255069338529911e+00, -4.4436525279753418e+00, -4.2622879058067751e+00, -4.0813881575787159e+00, -3.9009291187969852e+00, -3.7208873173946002e+00, -3.5412399243848873e+00, -3.3619647076803778e+00, -3.1830399887764611e+00, -3.0044446020282125e+00, -2.8261578562746821e+00, -2.6481594985877317e+00, -2.4704296799425793e+00, -2.2929489226249280e+00, -2.1156980892051682e+00, -1.9386583529239170e+00, -1.7618111693452876e+00, -1.5851382491449768e+00, -1.4086215319096145e+00, -1.2322431608320461e+00, -1.0559854581943640e+00, -8.7983090153669952e-01, -7.0376210041511855e-01, -5.2776177365646371e-01, -3.5181272702177707e-01, -1.7589783119299077e-01, -0.0000000000000000e+00, 1.7589783119299077e-01, 3.5181272702177707e-01, 5.2776177365646371e-01, 7.0376210041511855e-01, 8.7983090153669952e-01, 1.0559854581943640e+00, 1.2322431608320461e+00, 1.4086215319096145e+00, 1.5851382491449768e+00, 1.7618111693452876e+00, 1.9386583529239170e+00, 2.1156980892051682e+00, 2.2929489226249280e+00, 2.4704296799425793e+00, 2.6481594985877317e+00, 2.8261578562746821e+00, 3.0044446020282125e+00, 3.1830399887764611e+00, 3.3619647076803778e+00, 3.5412399243848873e+00, 3.7208873173946002e+00, 3.9009291187969852e+00, 4.0813881575787159e+00, 4.2622879058067751e+00, 4.4436525279753418e+00, 4.6255069338529911e+00, 4.8078768352029666e+00, 4.9907888067929420e+00, 5.1742703521606801e+00, 5.3583499746593573e+00, 5.5430572543722416e+00, 5.7284229315624149e+00, 5.9144789974110621e+00, 6.1012587928995696e+00, 6.2887971168089667e+00, 6.4771303439479562e+00, 6.6662965548819884e+00, 6.8563356786247329e+00, 7.0472896499758120e+00, 7.2392025834514619e+00, 7.4321209660664360e+00, 7.6260938715966651e+00, 7.8211731993958935e+00, 8.0174139413725705e+00, 8.2148744813764658e+00, 8.4136169320244640e+00, 8.6137075149457782e+00, 8.8152169915922389e+00, 9.0182211531960341e+00, 9.2228013802394901e+00, 9.4290452840267438e+00, 9.6370474457447699e+00, 9.8469102719449655e+00, 1.0058744989900266e+01, 1.0272672812117237e+01, 1.0488826306849386e+01, 1.0707351021384738e+01, 1.0928407418040756e+01, 1.1152173200444981e+01, 1.1378846131631990e+01, 1.1608647478438799e+01, 1.1841826262681151e+01, 1.2078664564848737e+01, 1.2319484220282153e+01, 1.2564655386543684e+01, 1.2814607669526135e+01, 1.3069844817966612e+01, 1.3330964506884797e+01, 1.3598685566661047e+01, 1.3873886433984071e+01, 1.4157661115094985e+01, 1.4451403633675961e+01, 1.4756941195343936e+01, 1.5076756017330117e+01, 1.5414381850393539e+01, 1.5775182847088153e+01, 1.6168102166823996e+01, 1.6610493732745791e+01, 1.7147777408524032e+01}, + {-1.7204433257886514e+01, -1.6667734404468501e+01, -1.6225835391124875e+01, -1.5833362176266244e+01, -1.5472978191373558e+01, -1.5135749157814335e+01, -1.4816316219712570e+01, -1.4511149100314286e+01, -1.4217768014947598e+01, -1.3934347545235219e+01, -1.3659495030180320e+01, -1.3392117533718560e+01, -1.3131337480278725e+01, -1.2876436746658081e+01, -1.2626818248827179e+01, -1.2381978739506893e+01, -1.2141489044042531e+01, -1.1904979380197393e+01, -1.1672128242851137e+01, -1.1442653844932979e+01, -1.1216307427723020e+01, -1.0992867962280265e+01, -1.0772137902368133e+01, -1.0553939743380022e+01, -1.0338113206958853e+01, -1.0124512916959700e+01, -9.9130064653237309e+00, -9.7034727903605109e+00, -9.4958008075637199e+00, -9.2898882462326107e+00, -9.0856406550885644e+00, -8.8829705476356562e+00, -8.6817966638328432e+00, -8.4820433291649113e+00, -8.2836398957394959e+00, -8.0865202528325053e+00, -7.8906223965273750e+00, -7.6958880498740347e+00, -7.5022623264288848e+00, -7.3096934312013273e+00, -7.1181323939823153e+00, -6.9275328308096045e+00, -6.7378507299670023e+00, -6.5490442594474336e+00, -6.3610735932529767e+00, -6.1739007542758424e+00, -5.9874894718156684e+00, -5.8018050520510185e+00, -5.6168142600053486e+00, -5.4324852117363971e+00, -5.2487872756390139e+00, -5.0656909818891060e+00, -4.8831679391745020e+00, -4.7011907579602283e+00, -4.5197329796234431e+00, -4.3387690108692292e+00, -4.1582740629043391e+00, -3.9782240949032923e+00, -3.7985957613512462e+00, -3.6193663628916424e+00, -3.4405138003449269e+00, -3.2620165315981051e+00, -3.0838535310943649e+00, -2.9060042516778903e+00, -2.7284485885718048e+00, -2.5511668452873062e+00, -2.3741397012797925e+00, -2.1973481811834414e+00, -2.0207736254695439e+00, -1.8443976623860776e+00, -1.6682021810467551e+00, -1.4921693055472409e+00, -1.3162813699945290e+00, -1.1405208943427161e+00, -9.6487056093471757e-01, -7.8931319165491054e-01, -6.1383172560234123e-01, -4.3840919719805421e-01, -2.6302871464332994e-01, -8.7673438648223800e-02, 8.7673438648223800e-02, 2.6302871464332994e-01, 4.3840919719805421e-01, 6.1383172560234123e-01, 7.8931319165491054e-01, 9.6487056093471757e-01, 1.1405208943427161e+00, 1.3162813699945290e+00, 1.4921693055472409e+00, 1.6682021810467551e+00, 1.8443976623860776e+00, 2.0207736254695439e+00, 2.1973481811834414e+00, 2.3741397012797925e+00, 2.5511668452873062e+00, 2.7284485885718048e+00, 2.9060042516778903e+00, 3.0838535310943649e+00, 3.2620165315981051e+00, 3.4405138003449269e+00, 3.6193663628916424e+00, 3.7985957613512462e+00, 3.9782240949032923e+00, 4.1582740629043391e+00, 4.3387690108692292e+00, 4.5197329796234431e+00, 4.7011907579602283e+00, 4.8831679391745020e+00, 5.0656909818891060e+00, 5.2487872756390139e+00, 5.4324852117363971e+00, 5.6168142600053486e+00, 5.8018050520510185e+00, 5.9874894718156684e+00, 6.1739007542758424e+00, 6.3610735932529767e+00, 6.5490442594474336e+00, 6.7378507299670023e+00, 6.9275328308096045e+00, 7.1181323939823153e+00, 7.3096934312013273e+00, 7.5022623264288848e+00, 7.6958880498740347e+00, 7.8906223965273750e+00, 8.0865202528325053e+00, 8.2836398957394959e+00, 8.4820433291649113e+00, 8.6817966638328432e+00, 8.8829705476356562e+00, 9.0856406550885644e+00, 9.2898882462326107e+00, 9.4958008075637199e+00, 9.7034727903605109e+00, 9.9130064653237309e+00, 1.0124512916959700e+01, 1.0338113206958853e+01, 1.0553939743380022e+01, 1.0772137902368133e+01, 1.0992867962280265e+01, 1.1216307427723020e+01, 1.1442653844932979e+01, 1.1672128242851137e+01, 1.1904979380197393e+01, 1.2141489044042531e+01, 1.2381978739506893e+01, 1.2626818248827179e+01, 1.2876436746658081e+01, 1.3131337480278725e+01, 1.3392117533718560e+01, 1.3659495030180320e+01, 1.3934347545235219e+01, 1.4217768014947598e+01, 1.4511149100314286e+01, 1.4816316219712570e+01, 1.5135749157814335e+01, 1.5472978191373558e+01, 1.5833362176266244e+01, 1.6225835391124875e+01, 1.6667734404468501e+01, 1.7204433257886514e+01}, + {-1.7260909703781458e+01, -1.6724791300392337e+01, -1.6283381096937688e+01, -1.5891350549206285e+01, -1.5531380320925585e+01, -1.5194544951785256e+01, -1.4875490845359661e+01, -1.4570691174443654e+01, -1.4277668569732091e+01, -1.3994599387373768e+01, -1.3720092319274791e+01, -1.3453055491772846e+01, -1.3192612184064762e+01, -1.2938044974817329e+01, -1.2688757366462070e+01, -1.2444246609242258e+01, -1.2204083956265350e+01, -1.1967899997504619e+01, -1.1735373555229600e+01, -1.1506223133185523e+01, -1.1280200233327742e+01, -1.1057084062337088e+01, -1.0836677288618299e+01, -1.0618802604522946e+01, -1.0403299913666036e+01, -1.0190024009115621e+01, -9.9788426411218261e+00, -9.7696348969572284e+00, -9.5622898330514161e+00, -9.3567053127370503e+00, -9.1527870128321815e+00, -8.9504475698358625e+00, -8.7496058423271297e+00, -8.5501862706726577e+00, -8.3521183186851253e+00, -8.1553359846666886e+00, -7.9597773714928959e+00, -7.7653843071712023e+00, -7.5721020087422000e+00, -7.3798787835549238e+00, -7.1886657628964983e+00, -6.9984166637349920e+00, -6.8090875749762771e+00, -6.6206367651677347e+00, -6.4330245090246105e+00, -6.2462129305252470e+00, -6.0601658606325453e+00, -5.8748487079613687e+00, -5.6902283409336283e+00, -5.5062729801514685e+00, -5.3229520998798137e+00, -5.1402363376670781e+00, -4.9580974112509208e+00, -4.7765080419975057e+00, -4.5954418842104330e+00, -4.4148734597213917e+00, -4.2347780972404623e+00, -4.0551318760012771e+00, -3.8759115732862068e+00, -3.6970946154603719e+00, -3.5186590321815130e+00, -3.3405834134862555e+00, -3.1628468694827729e+00, -2.9854289924057533e+00, -2.8083098208124282e+00, -2.6314698057185479e+00, -2.4548897784909895e+00, -2.2785509203293697e+00, -2.1024347331829158e+00, -1.9265230119611116e+00, -1.7507978179074160e+00, -1.5752414530149108e+00, -1.3998364353710842e+00, -1.2245654753263127e+00, -1.0494114523869875e+00, -8.7435739273980528e-01, -6.9938644731849353e-01, -5.2448187032830795e-01, -3.4962699814701426e-01, -1.7480522852383426e-01, -0.0000000000000000e+00, 1.7480522852383426e-01, 3.4962699814701426e-01, 5.2448187032830795e-01, 6.9938644731849353e-01, 8.7435739273980528e-01, 1.0494114523869875e+00, 1.2245654753263127e+00, 1.3998364353710842e+00, 1.5752414530149108e+00, 1.7507978179074160e+00, 1.9265230119611116e+00, 2.1024347331829158e+00, 2.2785509203293697e+00, 2.4548897784909895e+00, 2.6314698057185479e+00, 2.8083098208124282e+00, 2.9854289924057533e+00, 3.1628468694827729e+00, 3.3405834134862555e+00, 3.5186590321815130e+00, 3.6970946154603719e+00, 3.8759115732862068e+00, 4.0551318760012771e+00, 4.2347780972404623e+00, 4.4148734597213917e+00, 4.5954418842104330e+00, 4.7765080419975057e+00, 4.9580974112509208e+00, 5.1402363376670781e+00, 5.3229520998798137e+00, 5.5062729801514685e+00, 5.6902283409336283e+00, 5.8748487079613687e+00, 6.0601658606325453e+00, 6.2462129305252470e+00, 6.4330245090246105e+00, 6.6206367651677347e+00, 6.8090875749762771e+00, 6.9984166637349920e+00, 7.1886657628964983e+00, 7.3798787835549238e+00, 7.5721020087422000e+00, 7.7653843071712023e+00, 7.9597773714928959e+00, 8.1553359846666886e+00, 8.3521183186851253e+00, 8.5501862706726577e+00, 8.7496058423271297e+00, 8.9504475698358625e+00, 9.1527870128321815e+00, 9.3567053127370503e+00, 9.5622898330514161e+00, 9.7696348969572284e+00, 9.9788426411218261e+00, 1.0190024009115621e+01, 1.0403299913666036e+01, 1.0618802604522946e+01, 1.0836677288618299e+01, 1.1057084062337088e+01, 1.1280200233327742e+01, 1.1506223133185523e+01, 1.1735373555229600e+01, 1.1967899997504619e+01, 1.2204083956265350e+01, 1.2444246609242258e+01, 1.2688757366462070e+01, 1.2938044974817329e+01, 1.3192612184064762e+01, 1.3453055491772846e+01, 1.3720092319274791e+01, 1.3994599387373768e+01, 1.4277668569732091e+01, 1.4570691174443654e+01, 1.4875490845359661e+01, 1.5194544951785256e+01, 1.5531380320925585e+01, 1.5891350549206285e+01, 1.6283381096937688e+01, 1.6724791300392337e+01, 1.7260909703781458e+01}, + {-1.7317208433270949e+01, -1.6781666167619914e+01, -1.6340741083473855e+01, -1.5949149813561979e+01, -1.5589590133082927e+01, -1.5253145338412237e+01, -1.4934467055837311e+01, -1.4630031883570041e+01, -1.4337364850710150e+01, -1.4054644075392147e+01, -1.3780479592778537e+01, -1.3513780583944808e+01, -1.3253671176599115e+01, -1.2999434646049597e+01, -1.2750475076730016e+01, -1.2506290212533999e+01, -1.2266451730913499e+01, -1.2030590590990464e+01, -1.1798385939645330e+01, -1.1569556568885659e+01, -1.1343854238969067e+01, -1.1121058389970566e+01, -1.0900971902825360e+01, -1.0683417664825948e+01, -1.0468235759616565e+01, -1.0255281147593752e+01, -1.0044421735476904e+01, -9.8355367576951434e+00, -9.6285154098307064e+00, -9.4232556874808058e+00, -9.2196633937979797e+00, -9.0176512865137788e+00, -8.8171383410582820e+00, -8.6180491108986974e+00, -8.4203131697537437e+00, -8.2238646231301775e+00, -8.0286416788466841e+00, -7.8345862679873983e+00, -7.6416437091600784e+00, -7.4497624100959028e+00, -7.2588936015760819e+00, -7.0689910994481711e+00, -6.8800110911364190e+00, -6.6919119435819789e+00, -6.5046540299913760e+00, -6.3181995731417278e+00, -6.1325125033020340e+00, -5.9475583290919758e+00, -5.7633040198215193e+00, -5.5797178980431177e+00, -5.3967695412089913e+00, -5.2144296914634500e+00, -5.0326701727181335e+00, -4.8514638142596134e+00, -4.6707843802263858e+00, -4.4906065043681664e+00, -4.3109056295662098e+00, -4.1316579516506131e+00, -3.9528403671005403e+00, -3.7744304242568925e+00, -3.5964062777151744e+00, -3.4187466455998319e+00, -3.2414307694507918e+00, -3.0644383764788512e+00, -2.8877496439694483e+00, -2.7113451656344782e+00, -2.5352059197296661e+00, -2.3593132387707172e+00, -2.1836487806954117e+00, -2.0081945013310838e+00, -1.8329326280378133e+00, -1.6578456344072345e+00, -1.4829162159053173e+00, -1.3081272663548922e+00, -1.1334618551601847e+00, -9.5890320518127026e-01, -7.8443467117124477e-01, -6.1003971869307638e-01, -4.3570190343662574e-01, -2.6140485085923082e-01, -8.7132236075583736e-02, 8.7132236075583736e-02, 2.6140485085923082e-01, 4.3570190343662574e-01, 6.1003971869307638e-01, 7.8443467117124477e-01, 9.5890320518127026e-01, 1.1334618551601847e+00, 1.3081272663548922e+00, 1.4829162159053173e+00, 1.6578456344072345e+00, 1.8329326280378133e+00, 2.0081945013310838e+00, 2.1836487806954117e+00, 2.3593132387707172e+00, 2.5352059197296661e+00, 2.7113451656344782e+00, 2.8877496439694483e+00, 3.0644383764788512e+00, 3.2414307694507918e+00, 3.4187466455998319e+00, 3.5964062777151744e+00, 3.7744304242568925e+00, 3.9528403671005403e+00, 4.1316579516506131e+00, 4.3109056295662098e+00, 4.4906065043681664e+00, 4.6707843802263858e+00, 4.8514638142596134e+00, 5.0326701727181335e+00, 5.2144296914634500e+00, 5.3967695412089913e+00, 5.5797178980431177e+00, 5.7633040198215193e+00, 5.9475583290919758e+00, 6.1325125033020340e+00, 6.3181995731417278e+00, 6.5046540299913760e+00, 6.6919119435819789e+00, 6.8800110911364190e+00, 7.0689910994481711e+00, 7.2588936015760819e+00, 7.4497624100959028e+00, 7.6416437091600784e+00, 7.8345862679873983e+00, 8.0286416788466841e+00, 8.2238646231301775e+00, 8.4203131697537437e+00, 8.6180491108986974e+00, 8.8171383410582820e+00, 9.0176512865137788e+00, 9.2196633937979797e+00, 9.4232556874808058e+00, 9.6285154098307064e+00, 9.8355367576951434e+00, 1.0044421735476904e+01, 1.0255281147593752e+01, 1.0468235759616565e+01, 1.0683417664825948e+01, 1.0900971902825360e+01, 1.1121058389970566e+01, 1.1343854238969067e+01, 1.1569556568885659e+01, 1.1798385939645330e+01, 1.2030590590990464e+01, 1.2266451730913499e+01, 1.2506290212533999e+01, 1.2750475076730016e+01, 1.2999434646049597e+01, 1.3253671176599115e+01, 1.3513780583944808e+01, 1.3780479592778537e+01, 1.4054644075392147e+01, 1.4337364850710150e+01, 1.4630031883570041e+01, 1.4934467055837311e+01, 1.5253145338412237e+01, 1.5589590133082927e+01, 1.5949149813561979e+01, 1.6340741083473855e+01, 1.6781666167619914e+01, 1.7317208433270949e+01}, + {-1.7373331107186754e+01, -1.6838360725829279e+01, -1.6397917121470808e+01, -1.6006761787526802e+01, -1.5647609491464893e+01, -1.5311552225513632e+01, -1.4993246802416799e+01, -1.4689173221989655e+01, -1.4396858895000966e+01, -1.4114483689200235e+01, -1.3840658973492838e+01, -1.3574294976135944e+01, -1.3314516667182943e+01, -1.3060608013433232e+01, -1.2811973676932878e+01, -1.2568111891415747e+01, -1.2328594755317379e+01, -1.2093053593899976e+01, -1.1861167875925814e+01, -1.1632656679158853e+01, -1.1407272019832192e+01, -1.1184793569232429e+01, -1.0965024418758787e+01, -1.0747787648671435e+01, -1.0532923520744902e+01, -1.0320287160863774e+01, -1.0109746630421466e+01, -9.9011813092421690e+00, -9.6944805303231938e+00, -9.4895424198040619e+00, -9.2862729054572402e+00, -9.0845848645331397e+00, -8.8843973875939959e+00, -8.6856351394777924e+00, -8.4882278020634931e+00, -8.2921095862957674e+00, -8.0972188031442496e+00, -7.9034974849477484e+00, -7.7108910500251024e+00, -7.5193480045954200e+00, -7.3288196769976075e+00, -7.1392599799761927e+00, -6.9506251974411839e+00, -6.7628737926408222e+00, -6.5759662351281483e+00, -6.3898648442721324e+00, -6.2045336473746264e+00, -6.0199382507162937e+00, -5.8360457220763333e+00, -5.6528244834591428e+00, -5.4702442129216378e+00, -5.2882757545322603e+00, -5.1068910356106052e+00, -4.9260629904980000e+00, -4.7457654901969706e+00, -4.5659732772932937e+00, -4.3866619056401390e+00, -4.2078076843410157e+00, -4.0293876256181580e+00, -3.8513793961965916e+00, -3.6737612718723360e+00, -3.4965120949666812e+00, -3.3196112343979944e+00, -3.1430385481283984e+00, -2.9667743477655746e+00, -2.7907993651201082e+00, -2.6150947205366424e+00, -2.4396418928328796e+00, -2.2644226906944231e+00, -2.0894192253858019e+00, -1.9146138846489213e+00, -1.7399893076698572e+00, -1.5655283610033905e+00, -1.3912141153521926e+00, -1.2170298231041317e+00, -1.0429588965369114e+00, -8.6898488660423323e-01, -6.9509146222196017e-01, -5.2126238997639096e-01, -3.4748151417981160e-01, -1.7373273720096005e-01, -0.0000000000000000e+00, 1.7373273720096005e-01, 3.4748151417981160e-01, 5.2126238997639096e-01, 6.9509146222196017e-01, 8.6898488660423323e-01, 1.0429588965369114e+00, 1.2170298231041317e+00, 1.3912141153521926e+00, 1.5655283610033905e+00, 1.7399893076698572e+00, 1.9146138846489213e+00, 2.0894192253858019e+00, 2.2644226906944231e+00, 2.4396418928328796e+00, 2.6150947205366424e+00, 2.7907993651201082e+00, 2.9667743477655746e+00, 3.1430385481283984e+00, 3.3196112343979944e+00, 3.4965120949666812e+00, 3.6737612718723360e+00, 3.8513793961965916e+00, 4.0293876256181580e+00, 4.2078076843410157e+00, 4.3866619056401390e+00, 4.5659732772932937e+00, 4.7457654901969706e+00, 4.9260629904980000e+00, 5.1068910356106052e+00, 5.2882757545322603e+00, 5.4702442129216378e+00, 5.6528244834591428e+00, 5.8360457220763333e+00, 6.0199382507162937e+00, 6.2045336473746264e+00, 6.3898648442721324e+00, 6.5759662351281483e+00, 6.7628737926408222e+00, 6.9506251974411839e+00, 7.1392599799761927e+00, 7.3288196769976075e+00, 7.5193480045954200e+00, 7.7108910500251024e+00, 7.9034974849477484e+00, 8.0972188031442496e+00, 8.2921095862957674e+00, 8.4882278020634931e+00, 8.6856351394777924e+00, 8.8843973875939959e+00, 9.0845848645331397e+00, 9.2862729054572402e+00, 9.4895424198040619e+00, 9.6944805303231938e+00, 9.9011813092421690e+00, 1.0109746630421466e+01, 1.0320287160863774e+01, 1.0532923520744902e+01, 1.0747787648671435e+01, 1.0965024418758787e+01, 1.1184793569232429e+01, 1.1407272019832192e+01, 1.1632656679158853e+01, 1.1861167875925814e+01, 1.2093053593899976e+01, 1.2328594755317379e+01, 1.2568111891415747e+01, 1.2811973676932878e+01, 1.3060608013433232e+01, 1.3314516667182943e+01, 1.3574294976135944e+01, 1.3840658973492838e+01, 1.4114483689200235e+01, 1.4396858895000966e+01, 1.4689173221989655e+01, 1.4993246802416799e+01, 1.5311552225513632e+01, 1.5647609491464893e+01, 1.6006761787526802e+01, 1.6397917121470808e+01, 1.6838360725829279e+01, 1.7373331107186754e+01}, + {-1.7429279360697116e+01, -1.6894876667871738e+01, -1.6454910953817389e+01, -1.6064188260485547e+01, -1.5705440229953897e+01, -1.5369767490259161e+01, -1.5051832004816319e+01, -1.4748117151542182e+01, -1.4456152706360307e+01, -1.4174120274430678e+01, -1.3900632549018214e+01, -1.3634600798111430e+01, -1.3375150828031479e+01, -1.3121567291995134e+01, -1.2873255425338009e+01, -1.2629713947884454e+01, -1.2390515375747968e+01, -1.2155291397374004e+01, -1.1923721800726158e+01, -1.1695525946865237e+01, -1.1470456105717808e+01, -1.1248292177643179e+01, -1.1028837462481100e+01, -1.0811915231528733e+01, -1.0597365922834403e+01, -1.0385044825972880e+01, -1.0174820155259216e+01, -9.9665714341945719e+00, -9.7601881314978272e+00, -9.5555685021734451e+00, -9.3526185969451436e+00, -9.1512514109155187e+00, -8.9513861481082948e+00, -8.7529475830520980e+00, -8.5558655040914431e+00, -8.3600742258949641e+00, -8.1655121608455978e+00, -7.9721214407712111e+00, -7.7798475819041020e+00, -7.5886391871177059e+00, -7.3984476804351802e+00, -7.2092270695808969e+00, -7.0209337329860251e+00, -6.8335262281900011e+00, -6.6469651190213561e+00, -6.4612128193108518e+00, -6.2762334512001194e+00, -6.0919927163706555e+00, -5.9084577787394661e+00, -5.7255971573558835e+00, -5.5433806283944191e+00, -5.3617791352758264e+00, -5.1807647060662454e+00, -5.0003103774057065e+00, -4.8203901243047591e+00, -4.6409787952237167e+00, -4.4620520519147870e+00, -4.2835863135645020e+00, -4.1055587048237943e+00, -3.9279470073566172e+00, -3.7507296145762479e+00, -3.5738854892718694e+00, -3.3973941238575383e+00, -3.2212355030015671e+00, -3.0453900684172543e+00, -2.8698386856160685e+00, -2.6945626124422972e+00, -2.5195434692239367e+00, -2.3447632103886216e+00, -2.1702040974057377e+00, -1.9958486729268685e+00, -1.8216797360063830e+00, -1.6476803182925728e+00, -1.4738336610872771e+00, -1.3001231931786021e+00, -1.1265325093571319e+00, -9.5304534953113307e-01, -7.7964557836059989e-01, -6.0631716533377134e-01, -4.3304416521289407e-01, -2.5981069877863450e-01, -8.6600933804640304e-02, 8.6600933804640304e-02, 2.5981069877863450e-01, 4.3304416521289407e-01, 6.0631716533377134e-01, 7.7964557836059989e-01, 9.5304534953113307e-01, 1.1265325093571319e+00, 1.3001231931786021e+00, 1.4738336610872771e+00, 1.6476803182925728e+00, 1.8216797360063830e+00, 1.9958486729268685e+00, 2.1702040974057377e+00, 2.3447632103886216e+00, 2.5195434692239367e+00, 2.6945626124422972e+00, 2.8698386856160685e+00, 3.0453900684172543e+00, 3.2212355030015671e+00, 3.3973941238575383e+00, 3.5738854892718694e+00, 3.7507296145762479e+00, 3.9279470073566172e+00, 4.1055587048237943e+00, 4.2835863135645020e+00, 4.4620520519147870e+00, 4.6409787952237167e+00, 4.8203901243047591e+00, 5.0003103774057065e+00, 5.1807647060662454e+00, 5.3617791352758264e+00, 5.5433806283944191e+00, 5.7255971573558835e+00, 5.9084577787394661e+00, 6.0919927163706555e+00, 6.2762334512001194e+00, 6.4612128193108518e+00, 6.6469651190213561e+00, 6.8335262281900011e+00, 7.0209337329860251e+00, 7.2092270695808969e+00, 7.3984476804351802e+00, 7.5886391871177059e+00, 7.7798475819041020e+00, 7.9721214407712111e+00, 8.1655121608455978e+00, 8.3600742258949641e+00, 8.5558655040914431e+00, 8.7529475830520980e+00, 8.9513861481082948e+00, 9.1512514109155187e+00, 9.3526185969451436e+00, 9.5555685021734451e+00, 9.7601881314978272e+00, 9.9665714341945719e+00, 1.0174820155259216e+01, 1.0385044825972880e+01, 1.0597365922834403e+01, 1.0811915231528733e+01, 1.1028837462481100e+01, 1.1248292177643179e+01, 1.1470456105717808e+01, 1.1695525946865237e+01, 1.1923721800726158e+01, 1.2155291397374004e+01, 1.2390515375747968e+01, 1.2629713947884454e+01, 1.2873255425338009e+01, 1.3121567291995134e+01, 1.3375150828031479e+01, 1.3634600798111430e+01, 1.3900632549018214e+01, 1.4174120274430678e+01, 1.4456152706360307e+01, 1.4748117151542182e+01, 1.5051832004816319e+01, 1.5369767490259161e+01, 1.5705440229953897e+01, 1.6064188260485547e+01, 1.6454910953817389e+01, 1.6894876667871738e+01, 1.7429279360697116e+01}, + {-1.7485054803857970e+01, -1.6951215660353082e+01, -1.6511724296161706e+01, -1.6121430993647511e+01, -1.5763084153353320e+01, -1.5427792979852288e+01, -1.5110224551907818e+01, -1.4806865602342286e+01, -1.4515248255936989e+01, -1.4233555843220696e+01, -1.3960402372562056e+01, -1.3694700144334103e+01, -1.3435575795134914e+01, -1.3182314659599264e+01, -1.2934322542095073e+01, -1.2691098644846306e+01, -1.2452215898392630e+01, -1.2217306351455802e+01, -1.1986050108567399e+01, -1.1758166811670554e+01, -1.1533408982146776e+01, -1.1311556747331544e+01, -1.1092413613523263e+01, -1.0875803041166620e+01, -1.0661565642768281e+01, -1.0449556869836458e+01, -1.0239645087896863e+01, -1.0031709962451384e+01, -9.8256410962894503e+00, -9.6213368716463528e+00, -9.4187034605725390e+00, -9.2176539744013386e+00, -9.0181077289936873e+00, -8.8199896069364012e+00, -8.6232295013939773e+00, -8.4277618290957275e+00, -8.2335251021525675e+00, -8.0404615501699581e+00, -7.8485167855520830e+00, -7.6576395060512166e+00, -7.4677812295616199e+00, -7.2788960569330223e+00, -7.0909404592182668e+00, -6.9038730862998348e+00, -6.7176545942812487e+00, -6.5322474893984905e+00, -6.3476159865165220e+00, -6.1637258805374548e+00, -5.9805444292681393e+00, -5.7980402464829925e+00, -5.6161832040781530e+00, -5.4349443423501533e+00, -5.2542957875499878e+00, -5.0742106759647410e+00, -4.8946630838663463e+00, -4.7156279627427748e+00, -4.5370810792926148e+00, -4.3589989597211884e+00, -4.1813588379261919e+00, -4.0041386072044292e+00, -3.8273167751493955e+00, -3.6508724214429682e+00, -3.4747851582739164e+00, -3.2990350931419172e+00, -3.1236027938286419e+00, -2.9484692553376957e+00, -2.7736158686231027e+00, -2.5990243909418167e+00, -2.4246769176797933e+00, -2.2505558555135576e+00, -2.0766438967802112e+00, -1.9029239949385686e+00, -1.7293793410127316e+00, -1.5559933409170248e+00, -1.3827495935679281e+00, -1.2096318696945301e+00, -1.0366240912641824e+00, -8.6371031144450516e-01, -6.9087469502674481e-01, -5.1810149923876170e-01, -3.4537505487866837e-01, -1.7267974770236652e-01, -0.0000000000000000e+00, 1.7267974770236652e-01, 3.4537505487866837e-01, 5.1810149923876170e-01, 6.9087469502674481e-01, 8.6371031144450516e-01, 1.0366240912641824e+00, 1.2096318696945301e+00, 1.3827495935679281e+00, 1.5559933409170248e+00, 1.7293793410127316e+00, 1.9029239949385686e+00, 2.0766438967802112e+00, 2.2505558555135576e+00, 2.4246769176797933e+00, 2.5990243909418167e+00, 2.7736158686231027e+00, 2.9484692553376957e+00, 3.1236027938286419e+00, 3.2990350931419172e+00, 3.4747851582739164e+00, 3.6508724214429682e+00, 3.8273167751493955e+00, 4.0041386072044292e+00, 4.1813588379261919e+00, 4.3589989597211884e+00, 4.5370810792926148e+00, 4.7156279627427748e+00, 4.8946630838663463e+00, 5.0742106759647410e+00, 5.2542957875499878e+00, 5.4349443423501533e+00, 5.6161832040781530e+00, 5.7980402464829925e+00, 5.9805444292681393e+00, 6.1637258805374548e+00, 6.3476159865165220e+00, 6.5322474893984905e+00, 6.7176545942812487e+00, 6.9038730862998348e+00, 7.0909404592182668e+00, 7.2788960569330223e+00, 7.4677812295616199e+00, 7.6576395060512166e+00, 7.8485167855520830e+00, 8.0404615501699581e+00, 8.2335251021525675e+00, 8.4277618290957275e+00, 8.6232295013939773e+00, 8.8199896069364012e+00, 9.0181077289936873e+00, 9.2176539744013386e+00, 9.4187034605725390e+00, 9.6213368716463528e+00, 9.8256410962894503e+00, 1.0031709962451384e+01, 1.0239645087896863e+01, 1.0449556869836458e+01, 1.0661565642768281e+01, 1.0875803041166620e+01, 1.1092413613523263e+01, 1.1311556747331544e+01, 1.1533408982146776e+01, 1.1758166811670554e+01, 1.1986050108567399e+01, 1.2217306351455802e+01, 1.2452215898392630e+01, 1.2691098644846306e+01, 1.2934322542095073e+01, 1.3182314659599264e+01, 1.3435575795134914e+01, 1.3694700144334103e+01, 1.3960402372562056e+01, 1.4233555843220696e+01, 1.4515248255936989e+01, 1.4806865602342286e+01, 1.5110224551907818e+01, 1.5427792979852288e+01, 1.5763084153353320e+01, 1.6121430993647511e+01, 1.6511724296161706e+01, 1.6951215660353082e+01, 1.7485054803857970e+01}, + {-1.7540659022148994e+01, -1.7007379344198675e+01, -1.6568358837502078e+01, -1.6178491720661924e+01, -1.5820543038026845e+01, -1.5485630512193200e+01, -1.5168426302403656e+01, -1.4865420473490115e+01, -1.4574147483007465e+01, -1.4292792374971157e+01, -1.4019970463722631e+01, -1.3754595074773901e+01, -1.3495793669093878e+01, -1.3242852257808744e+01, -1.2995177210125478e+01, -1.2752268207034200e+01, -1.2513698590301434e+01, -1.2279100766067012e+01, -1.2048155152843032e+01, -1.1820581671084192e+01, -1.1596133091430600e+01, -1.1374589766138451e+01, -1.1155755406023257e+01, -1.0939453658827642e+01, -1.0725525309740862e+01, -1.0513825970487574e+01, -1.0304224156133158e+01, -1.0096599672544393e+01, -9.8908422549712061e+00, -9.6868504112873062e+00, -9.4845304332878886e+00, -9.2837955469590963e+00, -9.0845651784194441e+00, -8.8867643167273460e+00, -8.6903229582689274e+00, -8.4951756202195732e+00, -8.3012609127831123e+00, -8.1085211616830808e+00, -7.9169020738077709e+00, -7.7263524400685295e+00, -7.5368238704753843e+00, -7.3482705572089442e+00, -7.1606490621065957e+00, -6.9739181255105622e+00, -6.7880384938663552e+00, -6.6029727638288866e+00, -6.4186852409432520e+00, -6.2351418112283552e+00, -6.0523098242126343e+00, -5.8701579861589899e+00, -5.6886562623761669e+00, -5.5077757876508500e+00, -5.3274887839522851e+00, -5.1477684846624596e+00, -4.9685890646722539e+00, -4.7899255757595700e+00, -4.6117538867311527e+00, -4.4340506278668892e+00, -4.2567931392552376e+00, -4.0799594226519913e+00, -3.9035280965327215e+00, -3.7274783540427840e+00, -3.5517899235782049e+00, -3.3764430317567267e+00, -3.2014183685612045e+00, -3.0266970544577654e+00, -2.8522606093090528e+00, -2.6780909229187282e+00, -2.5041702270574335e+00, -2.3304810688329010e+00, -2.1570062852778933e+00, -1.9837289790394881e+00, -1.8106324950618549e+00, -1.6377003981623639e+00, -1.4649164514076216e+00, -1.2922645952019900e+00, -1.1197289270063837e+00, -9.4729368160967065e-01, -7.7494321187896786e-01, -6.0266196991848653e-01, -4.3043448856942984e-01, -2.5824536318581770e-01, -8.6079233622990678e-02, 8.6079233622990678e-02, 2.5824536318581770e-01, 4.3043448856942984e-01, 6.0266196991848653e-01, 7.7494321187896786e-01, 9.4729368160967065e-01, 1.1197289270063837e+00, 1.2922645952019900e+00, 1.4649164514076216e+00, 1.6377003981623639e+00, 1.8106324950618549e+00, 1.9837289790394881e+00, 2.1570062852778933e+00, 2.3304810688329010e+00, 2.5041702270574335e+00, 2.6780909229187282e+00, 2.8522606093090528e+00, 3.0266970544577654e+00, 3.2014183685612045e+00, 3.3764430317567267e+00, 3.5517899235782049e+00, 3.7274783540427840e+00, 3.9035280965327215e+00, 4.0799594226519913e+00, 4.2567931392552376e+00, 4.4340506278668892e+00, 4.6117538867311527e+00, 4.7899255757595700e+00, 4.9685890646722539e+00, 5.1477684846624596e+00, 5.3274887839522851e+00, 5.5077757876508500e+00, 5.6886562623761669e+00, 5.8701579861589899e+00, 6.0523098242126343e+00, 6.2351418112283552e+00, 6.4186852409432520e+00, 6.6029727638288866e+00, 6.7880384938663552e+00, 6.9739181255105622e+00, 7.1606490621065957e+00, 7.3482705572089442e+00, 7.5368238704753843e+00, 7.7263524400685295e+00, 7.9169020738077709e+00, 8.1085211616830808e+00, 8.3012609127831123e+00, 8.4951756202195732e+00, 8.6903229582689274e+00, 8.8867643167273460e+00, 9.0845651784194441e+00, 9.2837955469590963e+00, 9.4845304332878886e+00, 9.6868504112873062e+00, 9.8908422549712061e+00, 1.0096599672544393e+01, 1.0304224156133158e+01, 1.0513825970487574e+01, 1.0725525309740862e+01, 1.0939453658827642e+01, 1.1155755406023257e+01, 1.1374589766138451e+01, 1.1596133091430600e+01, 1.1820581671084192e+01, 1.2048155152843032e+01, 1.2279100766067012e+01, 1.2513698590301434e+01, 1.2752268207034200e+01, 1.2995177210125478e+01, 1.3242852257808744e+01, 1.3495793669093878e+01, 1.3754595074773901e+01, 1.4019970463722631e+01, 1.4292792374971157e+01, 1.4574147483007465e+01, 1.4865420473490115e+01, 1.5168426302403656e+01, 1.5485630512193200e+01, 1.5820543038026845e+01, 1.6178491720661924e+01, 1.6568358837502078e+01, 1.7007379344198675e+01, 1.7540659022148994e+01}, + {-1.7596093576995067e+01, -1.7063369335203092e+01, -1.6624816240761632e+01, -1.6235372148216229e+01, -1.5877818632519856e+01, -1.5543281876523103e+01, -1.5226439085523806e+01, -1.4923783633761518e+01, -1.4632852295689380e+01, -1.4351831817083784e+01, -1.4079338809250348e+01, -1.3814287615693701e+01, -1.3555806515930390e+01, -1.3303182192722531e+01, -1.3055821575985398e+01, -1.2813224821897842e+01, -1.2574965680305057e+01, -1.2340676911954159e+01, -1.2110039246794949e+01, -1.1882772881465453e+01, -1.1658630833708994e+01, -1.1437393678686862e+01, -1.1218865329829219e+01, -1.1002869620365653e+01, -1.0789247506430682e+01, -1.0577854758286833e+01, -1.0368560038906804e+01, -1.0161243292925425e+01, -9.9557943864826086e+00, -9.7521119515382608e+00, -9.5501023980913669e+00, -9.3496790652448780e+00, -9.1507614878382224e+00, -8.9532747598589513e+00, -8.7571489793618653e+00, -8.5623187624005972e+00, -8.3687228156851035e+00, -8.1763035594473781e+00, -7.9850067934236462e+00, -7.7947814000180404e+00, -7.6055790796564340e+00, -7.4173541141133637e+00, -7.2300631542333695e+00, -7.0436650289972214e+00, -6.8581205733240118e+00, -6.6733924723685520e+00, -6.4894451203829293e+00, -6.3062444924720467e+00, -6.1237580277938539e+00, -5.9419545229426243e+00, -5.7608040344137255e+00, -5.5802777891851223e+00, -5.4003481025684028e+00, -5.2209883025831942e+00, -5.0421726601961838e+00, -4.8638763248414749e+00, -4.6860752647046970e+00, -4.5087462113102941e+00, -4.3318666080012935e+00, -4.1554145619443341e+00, -3.9793687993309228e+00, -3.8037086234793556e+00, -3.6284138755712148e+00, -3.4534648977822986e+00, -3.2788424985907505e+00, -3.1045279200654083e+00, -2.9305028069552952e+00, -2.7567491774170563e+00, -2.5832493952312059e+00, -2.4099861433705372e+00, -2.2369423987951111e+00, -2.0641014083580762e+00, -1.8914466657152740e+00, -1.7189618891393004e+00, -1.5466310001455315e+00, -1.3744381028436181e+00, -1.2023674639332740e+00, -1.0304034932677821e+00, -8.5853072491269411e-01, -6.8673379863064854e-01, -5.1499744172618944e-01, -3.4330645118694048e-01, -1.7164567605949776e-01, -0.0000000000000000e+00, 1.7164567605949776e-01, 3.4330645118694048e-01, 5.1499744172618944e-01, 6.8673379863064854e-01, 8.5853072491269411e-01, 1.0304034932677821e+00, 1.2023674639332740e+00, 1.3744381028436181e+00, 1.5466310001455315e+00, 1.7189618891393004e+00, 1.8914466657152740e+00, 2.0641014083580762e+00, 2.2369423987951111e+00, 2.4099861433705372e+00, 2.5832493952312059e+00, 2.7567491774170563e+00, 2.9305028069552952e+00, 3.1045279200654083e+00, 3.2788424985907505e+00, 3.4534648977822986e+00, 3.6284138755712148e+00, 3.8037086234793556e+00, 3.9793687993309228e+00, 4.1554145619443341e+00, 4.3318666080012935e+00, 4.5087462113102941e+00, 4.6860752647046970e+00, 4.8638763248414749e+00, 5.0421726601961838e+00, 5.2209883025831942e+00, 5.4003481025684028e+00, 5.5802777891851223e+00, 5.7608040344137255e+00, 5.9419545229426243e+00, 6.1237580277938539e+00, 6.3062444924720467e+00, 6.4894451203829293e+00, 6.6733924723685520e+00, 6.8581205733240118e+00, 7.0436650289972214e+00, 7.2300631542333695e+00, 7.4173541141133637e+00, 7.6055790796564340e+00, 7.7947814000180404e+00, 7.9850067934236462e+00, 8.1763035594473781e+00, 8.3687228156851035e+00, 8.5623187624005972e+00, 8.7571489793618653e+00, 8.9532747598589513e+00, 9.1507614878382224e+00, 9.3496790652448780e+00, 9.5501023980913669e+00, 9.7521119515382608e+00, 9.9557943864826086e+00, 1.0161243292925425e+01, 1.0368560038906804e+01, 1.0577854758286833e+01, 1.0789247506430682e+01, 1.1002869620365653e+01, 1.1218865329829219e+01, 1.1437393678686862e+01, 1.1658630833708994e+01, 1.1882772881465453e+01, 1.2110039246794949e+01, 1.2340676911954159e+01, 1.2574965680305057e+01, 1.2813224821897842e+01, 1.3055821575985398e+01, 1.3303182192722531e+01, 1.3555806515930390e+01, 1.3814287615693701e+01, 1.4079338809250348e+01, 1.4351831817083784e+01, 1.4632852295689380e+01, 1.4923783633761518e+01, 1.5226439085523806e+01, 1.5543281876523103e+01, 1.5877818632519856e+01, 1.6235372148216229e+01, 1.6624816240761632e+01, 1.7063369335203092e+01, 1.7596093576995067e+01}, + {-1.7651360006273592e+01, -1.7119187224564673e+01, -1.6681098143347068e+01, -1.6292073956617820e+01, -1.5934912658163535e+01, -1.5600748834050473e+01, -1.5284264701644213e+01, -1.4981956922278711e+01, -1.4691364571634727e+01, -1.4410676085677181e+01, -1.4138509363787067e+01, -1.3873779760412367e+01, -1.3615616367875141e+01, -1.3363306535787522e+01, -1.3116257750703349e+01, -1.2873970640467419e+01, -1.2636019359905287e+01, -1.2402037021606754e+01, -1.2171704664459938e+01, -1.1944742758999288e+01, -1.1720904567955738e+01, -1.1499970887418726e+01, -1.1281745831568482e+01, -1.1066053417347991e+01, -1.0852734770136896e+01, -1.0641645817094179e+01, -1.0432655367504838e+01, -1.0225643503212597e+01, -1.0020500219714993e+01, -9.8171242715446922e+00, -9.6154221854030180e+00, -9.4153074120141333e+00, -9.2166995934430851e+00, -9.0195239271065724e+00, -8.8237106112187824e+00, -8.6291943591887517e+00, -8.4359139726921839e+00, -8.2438119649078239e+00, -8.0528342268332285e+00, -7.8629297307503139e+00, -7.6740502658540599e+00, -7.4861502018311290e+00, -7.2991862768130868e+00, -7.1131174066575413e+00, -6.9279045129506267e+00, -6.7435103674923891e+00, -6.5598994513357987e+00, -6.3770378267108159e+00, -6.1948930203856341e+00, -6.0134339172047717e+00, -5.8326306627035311e+00, -5.6524545738351115e+00, -5.4728780569640936e+00, -5.2938745323809906e+00, -5.1154183646798366e+00, -4.9374847984163193e+00, -4.7600498985294708e+00, -4.5830904950670517e+00, -4.4065841318044781e+00, -4.2305090183906966e+00, -4.0548439856925214e+00, -3.8795684440424409e+00, -3.7046623441243547e+00, -3.5301061402576419e+00, -3.3558807558629016e+00, -3.1819675509129310e+00, -3.0083482911904582e+00, -2.8350051191900167e+00, -2.6619205265154431e+00, -2.4890773276369966e+00, -2.3164586348831824e+00, -2.1440478345522327e+00, -1.9718285640369488e+00, -1.7997846898643619e+00, -1.6279002865585475e+00, -1.4561596162410049e+00, -1.2845471088883613e+00, -1.1130473431718593e+00, -9.4164502780718806e-01, -7.7032498334676469e-01, -5.9907212434961710e-01, -4.2787144186658727e-01, -2.5670798618070745e-01, -8.5566849744303619e-02, 8.5566849744303619e-02, 2.5670798618070745e-01, 4.2787144186658727e-01, 5.9907212434961710e-01, 7.7032498334676469e-01, 9.4164502780718806e-01, 1.1130473431718593e+00, 1.2845471088883613e+00, 1.4561596162410049e+00, 1.6279002865585475e+00, 1.7997846898643619e+00, 1.9718285640369488e+00, 2.1440478345522327e+00, 2.3164586348831824e+00, 2.4890773276369966e+00, 2.6619205265154431e+00, 2.8350051191900167e+00, 3.0083482911904582e+00, 3.1819675509129310e+00, 3.3558807558629016e+00, 3.5301061402576419e+00, 3.7046623441243547e+00, 3.8795684440424409e+00, 4.0548439856925214e+00, 4.2305090183906966e+00, 4.4065841318044781e+00, 4.5830904950670517e+00, 4.7600498985294708e+00, 4.9374847984163193e+00, 5.1154183646798366e+00, 5.2938745323809906e+00, 5.4728780569640936e+00, 5.6524545738351115e+00, 5.8326306627035311e+00, 6.0134339172047717e+00, 6.1948930203856341e+00, 6.3770378267108159e+00, 6.5598994513357987e+00, 6.7435103674923891e+00, 6.9279045129506267e+00, 7.1131174066575413e+00, 7.2991862768130868e+00, 7.4861502018311290e+00, 7.6740502658540599e+00, 7.8629297307503139e+00, 8.0528342268332285e+00, 8.2438119649078239e+00, 8.4359139726921839e+00, 8.6291943591887517e+00, 8.8237106112187824e+00, 9.0195239271065724e+00, 9.2166995934430851e+00, 9.4153074120141333e+00, 9.6154221854030180e+00, 9.8171242715446922e+00, 1.0020500219714993e+01, 1.0225643503212597e+01, 1.0432655367504838e+01, 1.0641645817094179e+01, 1.0852734770136896e+01, 1.1066053417347991e+01, 1.1281745831568482e+01, 1.1499970887418726e+01, 1.1720904567955738e+01, 1.1944742758999288e+01, 1.2171704664459938e+01, 1.2402037021606754e+01, 1.2636019359905287e+01, 1.2873970640467419e+01, 1.3116257750703349e+01, 1.3363306535787522e+01, 1.3615616367875141e+01, 1.3873779760412367e+01, 1.4138509363787067e+01, 1.4410676085677181e+01, 1.4691364571634727e+01, 1.4981956922278711e+01, 1.5284264701644213e+01, 1.5600748834050473e+01, 1.5934912658163535e+01, 1.6292073956617820e+01, 1.6681098143347068e+01, 1.7119187224564673e+01, 1.7651360006273592e+01}, + {-1.7706459824808160e+01, -1.7174834579405605e+01, -1.6737206157692185e+01, -1.6348598800359760e+01, -1.5991826809662236e+01, -1.5658033118559841e+01, -1.5341904922927041e+01, -1.5039942149162044e+01, -1.4749686158703426e+01, -1.4469327066282485e+01, -1.4197484050584235e+01, -1.3933073470045795e+01, -1.3675225224131985e+01, -1.3423227324587016e+01, -1.3176487810593191e+01, -1.2934507778191829e+01, -1.2696861784139129e+01, -1.2463183290148008e+01, -1.2233153641587771e+01, -1.2006493580642585e+01, -1.1782956612954054e+01, -1.1562323753600294e+01, -1.1344399315683788e+01, -1.1129007498123606e+01, -1.0915989593880358e+01, -1.0705201685404040e+01, -1.0496512726733012e+01, -1.0289802935397134e+01, -1.0084962434756044e+01, -9.8818901004391417e+00, -9.6804925743867667e+00, -9.4806834174876062e+00, -9.2823823775768961e+00, -9.0855147540413785e+00, -8.8900108437873531e+00, -8.6958054560996842e+00, -8.5028374861240277e+00, -8.3110495384702450e+00, -8.1203875938581902e+00, -7.9308007128818385e+00, -7.7422407719095485e+00, -7.5546622269112049e+00, -7.3680219016401658e+00, -7.1822787971261874e+00, -6.9973939198751642e+00, -6.8133301265393582e+00, -6.6300519831306728e+00, -6.4475256371099929e+00, -6.2657187009061461e+00, -6.0846001456053820e+00, -5.9041402037120223e+00, -5.7243102800175727e+00, -5.5450828697328980e+00, -5.3664314831390003e+00, -5.1883305760991361e+00, -5.0107554858504457e+00, -4.8336823715588126e+00, -4.6570881591776718e+00, -4.4809504902012192e+00, -4.3052476739459955e+00, -4.1299586430328983e+00, -3.9550629117751774e+00, -3.7805405372073957e+00, -3.6063720825162893e+00, -3.4325385826573980e+00, -3.2590215119615689e+00, -3.0858027535533901e+00, -2.9128645704195151e+00, -2.7401895779789363e+00, -2.5677607180197990e+00, -2.3955612338784800e+00, -2.2235746467465418e+00, -2.0517847329999523e+00, -1.8801755024527722e+00, -1.7087311774444227e+00, -1.5374361726757684e+00, -1.3662750757146653e+00, -1.1952326280963763e+00, -1.0242937069484293e+00, -8.5344330707311145e-01, -6.8266652342392853e-01, -5.1194853391500583e-01, -3.4127458250465148e-01, -1.7062996249611376e-01, -0.0000000000000000e+00, 1.7062996249611376e-01, 3.4127458250465148e-01, 5.1194853391500583e-01, 6.8266652342392853e-01, 8.5344330707311145e-01, 1.0242937069484293e+00, 1.1952326280963763e+00, 1.3662750757146653e+00, 1.5374361726757684e+00, 1.7087311774444227e+00, 1.8801755024527722e+00, 2.0517847329999523e+00, 2.2235746467465418e+00, 2.3955612338784800e+00, 2.5677607180197990e+00, 2.7401895779789363e+00, 2.9128645704195151e+00, 3.0858027535533901e+00, 3.2590215119615689e+00, 3.4325385826573980e+00, 3.6063720825162893e+00, 3.7805405372073957e+00, 3.9550629117751774e+00, 4.1299586430328983e+00, 4.3052476739459955e+00, 4.4809504902012192e+00, 4.6570881591776718e+00, 4.8336823715588126e+00, 5.0107554858504457e+00, 5.1883305760991361e+00, 5.3664314831390003e+00, 5.5450828697328980e+00, 5.7243102800175727e+00, 5.9041402037120223e+00, 6.0846001456053820e+00, 6.2657187009061461e+00, 6.4475256371099929e+00, 6.6300519831306728e+00, 6.8133301265393582e+00, 6.9973939198751642e+00, 7.1822787971261874e+00, 7.3680219016401658e+00, 7.5546622269112049e+00, 7.7422407719095485e+00, 7.9308007128818385e+00, 8.1203875938581902e+00, 8.3110495384702450e+00, 8.5028374861240277e+00, 8.6958054560996842e+00, 8.8900108437873531e+00, 9.0855147540413785e+00, 9.2823823775768961e+00, 9.4806834174876062e+00, 9.6804925743867667e+00, 9.8818901004391417e+00, 1.0084962434756044e+01, 1.0289802935397134e+01, 1.0496512726733012e+01, 1.0705201685404040e+01, 1.0915989593880358e+01, 1.1129007498123606e+01, 1.1344399315683788e+01, 1.1562323753600294e+01, 1.1782956612954054e+01, 1.2006493580642585e+01, 1.2233153641587771e+01, 1.2463183290148008e+01, 1.2696861784139129e+01, 1.2934507778191829e+01, 1.3176487810593191e+01, 1.3423227324587016e+01, 1.3675225224131985e+01, 1.3933073470045795e+01, 1.4197484050584235e+01, 1.4469327066282485e+01, 1.4749686158703426e+01, 1.5039942149162044e+01, 1.5341904922927041e+01, 1.5658033118559841e+01, 1.5991826809662236e+01, 1.6348598800359760e+01, 1.6737206157692185e+01, 1.7174834579405605e+01, 1.7706459824808160e+01}, + {-1.7761394524848996e+01, -1.7230312943277969e+01, -1.6793141871786613e+01, -1.6404948308671031e+01, -1.6048562755664683e+01, -1.5715136437003761e+01, -1.5399361493933315e+01, -1.5097741096163510e+01, -1.4807818875617881e+01, -1.4527786614519313e+01, -1.4256264762200541e+01, -1.3992170674226745e+01, -1.3734635051620387e+01, -1.3482946563606328e+01, -1.3236513798043475e+01, -1.2994838315752334e+01, -1.2757495072417459e+01, -1.2524117876199165e+01, -1.2294388376531968e+01, -1.2068027585042133e+01, -1.1844789248242524e+01, -1.1624454598296943e+01, -1.1406828145437910e+01, -1.1191734268858408e+01, -1.0979014427470727e+01, -1.0768524857445218e+01, -1.0560134656049588e+01, -1.0353724175012228e+01, -1.0149183664094940e+01, -9.9464121185839414e+00, -9.7453162942320208e+00, -9.5458098606732449e+00, -9.3478126700959958e+00, -9.1512501224373288e+00, -8.9560526118688415e+00, -8.7621550421132515e+00, -8.5694964003332892e+00, -8.3780193810985182e+00, -8.1876700533578219e+00, -7.9983975644987861e+00, -7.8101538765164022e+00, -7.6228935300856273e+00, -7.4365734329690358e+00, -7.2511526697184987e+00, -7.0665923300691791e+00, -6.8828553537915784e+00, -6.6999063900760145e+00, -6.5177116697841271e+00, -6.3362388891223835e+00, -6.1554571034797059e+00, -5.9753366303309603e+00, -5.7958489602446139e+00, -5.6169666751500360e+00, -5.4386633731207876e+00, -5.2609135990173996e+00, -5.0836927804084810e+00, -4.9069771682545298e+00, -4.7307437818957530e+00, -4.5549703579349439e+00, -4.3796353026499011e+00, -4.2047176476080219e+00, -4.0301970081890968e+00, -3.8560535447518163e+00, -3.6822679262054381e+00, -3.5088212957709741e+00, -3.3356952387365157e+00, -3.1628717520292895e+00, -2.9903332154429094e+00, -2.8180623643724516e+00, -2.6460422639225052e+00, -2.4742562842645146e+00, -2.3026880771296399e+00, -2.1313215533321839e+00, -1.9601408612264668e+00, -1.7891303660069930e+00, -1.6182746297679145e+00, -1.4475583922432660e+00, -1.2769665521542517e+00, -1.1064841490940971e+00, -9.3609634588467550e-01, -7.6578841134230902e-01, -5.9554570339290602e-01, -4.2535365247890039e-01, -2.5519774520239308e-01, -8.5063508150433453e-02, 8.5063508150433453e-02, 2.5519774520239308e-01, 4.2535365247890039e-01, 5.9554570339290602e-01, 7.6578841134230902e-01, 9.3609634588467550e-01, 1.1064841490940971e+00, 1.2769665521542517e+00, 1.4475583922432660e+00, 1.6182746297679145e+00, 1.7891303660069930e+00, 1.9601408612264668e+00, 2.1313215533321839e+00, 2.3026880771296399e+00, 2.4742562842645146e+00, 2.6460422639225052e+00, 2.8180623643724516e+00, 2.9903332154429094e+00, 3.1628717520292895e+00, 3.3356952387365157e+00, 3.5088212957709741e+00, 3.6822679262054381e+00, 3.8560535447518163e+00, 4.0301970081890968e+00, 4.2047176476080219e+00, 4.3796353026499011e+00, 4.5549703579349439e+00, 4.7307437818957530e+00, 4.9069771682545298e+00, 5.0836927804084810e+00, 5.2609135990173996e+00, 5.4386633731207876e+00, 5.6169666751500360e+00, 5.7958489602446139e+00, 5.9753366303309603e+00, 6.1554571034797059e+00, 6.3362388891223835e+00, 6.5177116697841271e+00, 6.6999063900760145e+00, 6.8828553537915784e+00, 7.0665923300691791e+00, 7.2511526697184987e+00, 7.4365734329690358e+00, 7.6228935300856273e+00, 7.8101538765164022e+00, 7.9983975644987861e+00, 8.1876700533578219e+00, 8.3780193810985182e+00, 8.5694964003332892e+00, 8.7621550421132515e+00, 8.9560526118688415e+00, 9.1512501224373288e+00, 9.3478126700959958e+00, 9.5458098606732449e+00, 9.7453162942320208e+00, 9.9464121185839414e+00, 1.0149183664094940e+01, 1.0353724175012228e+01, 1.0560134656049588e+01, 1.0768524857445218e+01, 1.0979014427470727e+01, 1.1191734268858408e+01, 1.1406828145437910e+01, 1.1624454598296943e+01, 1.1844789248242524e+01, 1.2068027585042133e+01, 1.2294388376531968e+01, 1.2524117876199165e+01, 1.2757495072417459e+01, 1.2994838315752334e+01, 1.3236513798043475e+01, 1.3482946563606328e+01, 1.3734635051620387e+01, 1.3992170674226745e+01, 1.4256264762200541e+01, 1.4527786614519313e+01, 1.4807818875617881e+01, 1.5097741096163510e+01, 1.5399361493933315e+01, 1.5715136437003761e+01, 1.6048562755664683e+01, 1.6404948308671031e+01, 1.6793141871786613e+01, 1.7230312943277969e+01, 1.7761394524848996e+01}, + {-1.7816165576540595e+01, -1.7285623836656182e+01, -1.6848906849690259e+01, -1.6461124086051807e+01, -1.6105122139319558e+01, -1.5772060470078458e+01, -1.5456636132218662e+01, -1.5155355517282629e+01, -1.4865764512599243e+01, -1.4586056556752672e+01, -1.4314853361179868e+01, -1.4051073271804183e+01, -1.3793847785696649e+01, -1.3542466224976369e+01, -1.3296337722283933e+01, -1.3054964299852571e+01, -1.2817921309339152e+01, -1.2584842902718409e+01, -1.2355411031114167e+01, -1.2129346973425209e+01, -1.1906404715032753e+01, -1.1686365703318645e+01, -1.1469034643887829e+01, -1.1254236094539081e+01, -1.1041811678540856e+01, -1.0831617784246889e+01, -1.0623523650663971e+01, -1.0417409762265434e+01, -1.0213166493789654e+01, -1.0010692958774635e+01, -9.8098960253945080e+00, -9.6106894706457702e+00, -9.4129932496899222e+00, -9.2167328616325275e+00, -9.0218387965226103e+00, -8.8282460511228340e+00, -8.6358937032013543e+00, -8.4447245358586134e+00, -8.2546847048231751e+00, -8.0657234428032414e+00, -7.8777927959207110e+00, -7.6908473880261887e+00, -7.5048442093293950e+00, -7.3197424263067070e+00, -7.1355032102865055e+00, -6.9520895824801361e+00, -6.7694662735346460e+00, -6.5875995959434990e+00, -6.4064573278715784e+00, -6.2260086071378540e+00, -6.0462238342585293e+00, -5.8670745835899512e+00, -5.6885335217276216e+00, -5.5105743324184848e+00, -5.3331716473306852e+00, -5.1563009821003343e+00, -4.9799386771402681e+00, -4.8040618427527138e+00, -4.6286483081374303e+00, -4.4536765739303981e+00, -4.2791257679461268e+00, -4.1049756038301792e+00, -3.9312063423578660e+00, -3.7577987551410561e+00, -3.5847340905279546e+00, -3.4119940415009409e+00, -3.2395607153955579e+00, -3.0674166052796257e+00, -2.8955445628456173e+00, -2.7239277726819950e+00, -2.5525497278003657e+00, -2.3813942063052753e+00, -2.2104452491022966e+00, -2.0396871385479329e+00, -1.8691043779518630e+00, -1.6986816718482496e+00, -1.5284039069583553e+00, -1.3582561337715613e+00, -1.1882235486761765e+00, -1.0182914765751778e+00, -8.4844535392529652e-01, -6.7867071214067709e-01, -5.0895316130475177e-01, -3.3927837413597878e-01, -1.6963207015474091e-01, -0.0000000000000000e+00, 1.6963207015474091e-01, 3.3927837413597878e-01, 5.0895316130475177e-01, 6.7867071214067709e-01, 8.4844535392529652e-01, 1.0182914765751778e+00, 1.1882235486761765e+00, 1.3582561337715613e+00, 1.5284039069583553e+00, 1.6986816718482496e+00, 1.8691043779518630e+00, 2.0396871385479329e+00, 2.2104452491022966e+00, 2.3813942063052753e+00, 2.5525497278003657e+00, 2.7239277726819950e+00, 2.8955445628456173e+00, 3.0674166052796257e+00, 3.2395607153955579e+00, 3.4119940415009409e+00, 3.5847340905279546e+00, 3.7577987551410561e+00, 3.9312063423578660e+00, 4.1049756038301792e+00, 4.2791257679461268e+00, 4.4536765739303981e+00, 4.6286483081374303e+00, 4.8040618427527138e+00, 4.9799386771402681e+00, 5.1563009821003343e+00, 5.3331716473306852e+00, 5.5105743324184848e+00, 5.6885335217276216e+00, 5.8670745835899512e+00, 6.0462238342585293e+00, 6.2260086071378540e+00, 6.4064573278715784e+00, 6.5875995959434990e+00, 6.7694662735346460e+00, 6.9520895824801361e+00, 7.1355032102865055e+00, 7.3197424263067070e+00, 7.5048442093293950e+00, 7.6908473880261887e+00, 7.8777927959207110e+00, 8.0657234428032414e+00, 8.2546847048231751e+00, 8.4447245358586134e+00, 8.6358937032013543e+00, 8.8282460511228340e+00, 9.0218387965226103e+00, 9.2167328616325275e+00, 9.4129932496899222e+00, 9.6106894706457702e+00, 9.8098960253945080e+00, 1.0010692958774635e+01, 1.0213166493789654e+01, 1.0417409762265434e+01, 1.0623523650663971e+01, 1.0831617784246889e+01, 1.1041811678540856e+01, 1.1254236094539081e+01, 1.1469034643887829e+01, 1.1686365703318645e+01, 1.1906404715032753e+01, 1.2129346973425209e+01, 1.2355411031114167e+01, 1.2584842902718409e+01, 1.2817921309339152e+01, 1.3054964299852571e+01, 1.3296337722283933e+01, 1.3542466224976369e+01, 1.3793847785696649e+01, 1.4051073271804183e+01, 1.4314853361179868e+01, 1.4586056556752672e+01, 1.4865764512599243e+01, 1.5155355517282629e+01, 1.5456636132218662e+01, 1.5772060470078458e+01, 1.6105122139319558e+01, 1.6461124086051807e+01, 1.6848906849690259e+01, 1.7285623836656182e+01, 1.7816165576540595e+01}, + {-1.7870774428377043e+01, -1.7340768757416335e+01, -1.6904502632033939e+01, -1.6517127712794291e+01, -1.6161506578815988e+01, -1.5828806872783744e+01, -1.5513730528912630e+01, -1.5212787139365300e+01, -1.4923524831985965e+01, -1.4644138690731507e+01, -1.4373251680710139e+01, -1.4109783131522859e+01, -1.3852865330854605e+01, -1.3601788249195971e+01, -1.3355961560129954e+01, -1.3114887743985697e+01, -1.2878142545481497e+01, -1.2645360457815213e+01, -1.2416223731463095e+01, -1.2190453910463864e+01, -1.1967805217099682e+01, -1.1748059312137153e+01, -1.1531021094829603e+01, -1.1316515299946504e+01, -1.1104383713549687e+01, -1.0894482874671912e+01, -1.0686682162601475e+01, -1.0480862193135913e+01, -1.0276913464597831e+01, -1.0074735207405618e+01, -9.8742344007979135e+00, -9.6753249277855886e+00, -9.4779268451589243e+00, -9.2819657498467407e+00, -9.0873722264251189e+00, -8.8940813633373228e+00, -8.7020323275849982e+00, -8.5111679894115486e+00, -8.3214345899181446e+00, -8.1327814457042589e+00, -7.9451606855641499e+00, -7.7585270150414196e+00, -7.5728375052793471e+00, -7.3880514031314979e+00, -7.2041299599356252e+00, -7.0210362767207544e+00, -6.8387351639253717e+00, -6.6571930139644744e+00, -6.4763776852031878e+00, -6.2962583960814955e+00, -6.1168056282939949e+00, -5.9379910380649177e+00, -5.7597873746756241e+00, -5.5821684055025109e+00, -5.4051088469102604e+00, -5.2285843004206338e+00, -5.0525711936423852e+00, -4.8770467255047967e+00, -4.7019888153869536e+00, -4.5273760557783174e+00, -4.3531876681442050e+00, -4.1794034617032088e+00, -4.0060037948530276e+00, -3.8329695390070744e+00, -3.6602820446272100e+00, -3.4879231092581433e+00, -3.3158749473870577e+00, -3.1441201619679244e+00, -2.9726417174641275e+00, -2.8014229142755962e+00, -2.6304473644278392e+00, -2.4596989684102435e+00, -2.2891618930598643e+00, -2.1188205503948270e+00, -1.9486595773085056e+00, -1.7786638160418760e+00, -1.6088182953569903e+00, -1.4391082123394401e+00, -1.2695189147619996e+00, -1.1000358839454638e+00, -9.3064471805601867e-01, -7.6133111578138291e-01, -5.9208086033042751e-01, -4.2287980370308703e-01, -2.5371385117911249e-01, -8.4568945975610571e-02, 8.4568945975610571e-02, 2.5371385117911249e-01, 4.2287980370308703e-01, 5.9208086033042751e-01, 7.6133111578138291e-01, 9.3064471805601867e-01, 1.1000358839454638e+00, 1.2695189147619996e+00, 1.4391082123394401e+00, 1.6088182953569903e+00, 1.7786638160418760e+00, 1.9486595773085056e+00, 2.1188205503948270e+00, 2.2891618930598643e+00, 2.4596989684102435e+00, 2.6304473644278392e+00, 2.8014229142755962e+00, 2.9726417174641275e+00, 3.1441201619679244e+00, 3.3158749473870577e+00, 3.4879231092581433e+00, 3.6602820446272100e+00, 3.8329695390070744e+00, 4.0060037948530276e+00, 4.1794034617032088e+00, 4.3531876681442050e+00, 4.5273760557783174e+00, 4.7019888153869536e+00, 4.8770467255047967e+00, 5.0525711936423852e+00, 5.2285843004206338e+00, 5.4051088469102604e+00, 5.5821684055025109e+00, 5.7597873746756241e+00, 5.9379910380649177e+00, 6.1168056282939949e+00, 6.2962583960814955e+00, 6.4763776852031878e+00, 6.6571930139644744e+00, 6.8387351639253717e+00, 7.0210362767207544e+00, 7.2041299599356252e+00, 7.3880514031314979e+00, 7.5728375052793471e+00, 7.7585270150414196e+00, 7.9451606855641499e+00, 8.1327814457042589e+00, 8.3214345899181446e+00, 8.5111679894115486e+00, 8.7020323275849982e+00, 8.8940813633373228e+00, 9.0873722264251189e+00, 9.2819657498467407e+00, 9.4779268451589243e+00, 9.6753249277855886e+00, 9.8742344007979135e+00, 1.0074735207405618e+01, 1.0276913464597831e+01, 1.0480862193135913e+01, 1.0686682162601475e+01, 1.0894482874671912e+01, 1.1104383713549687e+01, 1.1316515299946504e+01, 1.1531021094829603e+01, 1.1748059312137153e+01, 1.1967805217099682e+01, 1.2190453910463864e+01, 1.2416223731463095e+01, 1.2645360457815213e+01, 1.2878142545481497e+01, 1.3114887743985697e+01, 1.3355961560129954e+01, 1.3601788249195971e+01, 1.3852865330854605e+01, 1.4109783131522859e+01, 1.4373251680710139e+01, 1.4644138690731507e+01, 1.4923524831985965e+01, 1.5212787139365300e+01, 1.5513730528912630e+01, 1.5828806872783744e+01, 1.6161506578815988e+01, 1.6517127712794291e+01, 1.6904502632033939e+01, 1.7340768757416335e+01, 1.7870774428377043e+01}, + {-1.7925222507645273e+01, -1.7395749181302794e+01, -1.6959930736506667e+01, -1.6572960745489535e+01, -1.6217717667909398e+01, -1.5885377274967727e+01, -1.5570646349282180e+01, -1.5270037662686175e+01, -1.4981101568835271e+01, -1.4702034786209495e+01, -1.4431461525263758e+01, -1.4168302092683751e+01, -1.3911689561406538e+01, -1.3660914545833675e+01, -1.3415387256705733e+01, -1.3174610629179487e+01, -1.2938160798167818e+01, -1.2705672595541055e+01, -1.2476828568829013e+01, -1.2251350525113802e+01, -1.2028992921645616e+01, -1.1809537630775932e+01, -1.1592789743714977e+01, -1.1378574170599888e+01, -1.1166732858754798e+01, -1.0957122496418719e+01, -1.0749612601735487e+01, -1.0544083920437931e+01, -1.0340427073072608e+01, -1.0138541405599460e+01, -9.9383340069978168e+00, -9.7397188649785829e+00, -9.5426161366508815e+00, -9.3469515154567748e+00, -9.1526556791851785e+00, -8.9596638066377352e+00, -8.7679151527158581e+00, -8.5773526734573888e+00, -8.3879226939696405e+00, -8.1995746133560008e+00, -8.0122606416719417e+00, -7.8259355647163380e+00, -7.6405565330989909e+00, -7.4560828725515957e+00, -7.2724759128875176e+00, -7.0896988333823048e+00, -6.9077165226546269e+00, -6.7264954513869304e+00, -6.5460035564448802e+00, -6.3662101351413103e+00, -6.1870857485496860e+00, -6.0086021329082362e+00, -5.8307321182728238e+00, -5.6534495536772900e+00, -5.4767292381468682e+00, -5.3005468569855445e+00, -5.1248789228235241e+00, -4.9497027209678768e+00, -4.7749962586489980e+00, -4.6007382177989511e+00, -4.4269079110357756e+00, -4.2534852405612638e+00, -4.0804506597091201e+00, -3.9077851369063397e+00, -3.7354701218335649e+00, -3.5634875135904314e+00, -3.3918196306899016e+00, -3.2204491827214987e+00, -3.0493592435375283e+00, -2.8785332258289715e+00, -2.7079548569689353e+00, -2.5376081560115265e+00, -2.3674774117429300e+00, -2.1975471616893691e+00, -2.0278021719937014e+00, -1.8582274180786869e+00, -1.6888080660205369e+00, -1.5195294545613143e+00, -1.3503770776931412e+00, -1.1813365677510279e+00, -1.0123936789545276e+00, -8.4353427134138192e-01, -6.7474429503886002e-01, -5.0600977482067722e-01, -3.3731679489919819e-01, -1.6865148390411927e-01, -0.0000000000000000e+00, 1.6865148390411927e-01, 3.3731679489919819e-01, 5.0600977482067722e-01, 6.7474429503886002e-01, 8.4353427134138192e-01, 1.0123936789545276e+00, 1.1813365677510279e+00, 1.3503770776931412e+00, 1.5195294545613143e+00, 1.6888080660205369e+00, 1.8582274180786869e+00, 2.0278021719937014e+00, 2.1975471616893691e+00, 2.3674774117429300e+00, 2.5376081560115265e+00, 2.7079548569689353e+00, 2.8785332258289715e+00, 3.0493592435375283e+00, 3.2204491827214987e+00, 3.3918196306899016e+00, 3.5634875135904314e+00, 3.7354701218335649e+00, 3.9077851369063397e+00, 4.0804506597091201e+00, 4.2534852405612638e+00, 4.4269079110357756e+00, 4.6007382177989511e+00, 4.7749962586489980e+00, 4.9497027209678768e+00, 5.1248789228235241e+00, 5.3005468569855445e+00, 5.4767292381468682e+00, 5.6534495536772900e+00, 5.8307321182728238e+00, 6.0086021329082362e+00, 6.1870857485496860e+00, 6.3662101351413103e+00, 6.5460035564448802e+00, 6.7264954513869304e+00, 6.9077165226546269e+00, 7.0896988333823048e+00, 7.2724759128875176e+00, 7.4560828725515957e+00, 7.6405565330989909e+00, 7.8259355647163380e+00, 8.0122606416719417e+00, 8.1995746133560008e+00, 8.3879226939696405e+00, 8.5773526734573888e+00, 8.7679151527158581e+00, 8.9596638066377352e+00, 9.1526556791851785e+00, 9.3469515154567748e+00, 9.5426161366508815e+00, 9.7397188649785829e+00, 9.9383340069978168e+00, 1.0138541405599460e+01, 1.0340427073072608e+01, 1.0544083920437931e+01, 1.0749612601735487e+01, 1.0957122496418719e+01, 1.1166732858754798e+01, 1.1378574170599888e+01, 1.1592789743714977e+01, 1.1809537630775932e+01, 1.2028992921645616e+01, 1.2251350525113802e+01, 1.2476828568829013e+01, 1.2705672595541055e+01, 1.2938160798167818e+01, 1.3174610629179487e+01, 1.3415387256705733e+01, 1.3660914545833675e+01, 1.3911689561406538e+01, 1.4168302092683751e+01, 1.4431461525263758e+01, 1.4702034786209495e+01, 1.4981101568835271e+01, 1.5270037662686175e+01, 1.5570646349282180e+01, 1.5885377274967727e+01, 1.6217717667909398e+01, 1.6572960745489535e+01, 1.6959930736506667e+01, 1.7395749181302794e+01, 1.7925222507645273e+01}, + {-1.7979511220856821e+01, -1.7450566562382527e+01, -1.7015192658329994e+01, -1.6628624717520726e+01, -1.6273756976433262e+01, -1.5941773281856777e+01, -1.5627385233279865e+01, -1.5327108761515133e+01, -1.5038496431508072e+01, -1.4759746585548676e+01, -1.4489484671220278e+01, -1.4226631965786098e+01, -1.3970322322144929e+01, -1.3719846994209712e+01, -1.3474616726146943e+01, -1.3234134904720168e+01, -1.2997978052213019e+01, -1.2765781336657277e+01, -1.2537227600374516e+01, -1.2312038911428751e+01, -1.2089969960138866e+01, -1.1870802828673778e+01, -1.1654342798540783e+01, -1.1440414953672729e+01, -1.1228861401155735e+01, -1.1019538976992907e+01, -1.0812317336788272e+01, -1.0607077354851786e+01, -1.0403709772624749e+01, -1.0202114050301228e+01, -1.0002197385309380e+01, -9.8038738687782931e+00, -9.6070637568592137e+00, -9.4116928382313976e+00, -9.2176918826171956e+00, -9.0249961578901878e+00, -8.8335450055546225e+00, -8.6432814661321498e+00, -8.4541519474088638e+00, -8.2661059296450645e+00, -8.0790957027880133e+00, -7.8930761314972990e+00, -7.7080044444269156e+00, -7.5238400447339577e+00, -7.3405443392217018e+00, -7.1580805838909543e+00, -6.9764137439811300e+00, -6.7955103668419072e+00, -6.6153384661958059e+00, -6.4358674165386551e+00, -6.2570678565839728e+00, -6.0789116007933410e+00, -5.9013715581517205e+00, -5.7244216574471602e+00, -5.5480367784012250e+00, -5.3721926880716282e+00, -5.1968659820138337e+00, -5.0220340297452291e+00, -4.8476749241050427e+00, -4.6737674341465381e+00, -4.5002909612360460e+00, -4.3272254980667917e+00, -4.1545515903248518e+00, -3.9822503007705263e+00, -3.8103031755212977e+00, -3.6386922123428187e+00, -3.4673998307723486e+00, -3.2964088439149859e+00, -3.1257024317672348e+00, -2.9552641159350221e+00, -2.7850777356245309e+00, -2.6151274247942147e+00, -2.4453975903652418e+00, -2.2758728913956188e+00, -2.1065382191302762e+00, -1.9373786778457494e+00, -1.7683795664136901e+00, -1.5995263605124337e+00, -1.4308046954202789e+00, -1.2622003493280531e+00, -1.0936992271119663e+00, -9.2528734451076988e-01, -7.5695081265386188e-01, -5.8867582288920217e-01, -4.2044863186181980e-01, -2.5225554679525719e-01, -8.4082910929564950e-02, 8.4082910929564950e-02, 2.5225554679525719e-01, 4.2044863186181980e-01, 5.8867582288920217e-01, 7.5695081265386188e-01, 9.2528734451076988e-01, 1.0936992271119663e+00, 1.2622003493280531e+00, 1.4308046954202789e+00, 1.5995263605124337e+00, 1.7683795664136901e+00, 1.9373786778457494e+00, 2.1065382191302762e+00, 2.2758728913956188e+00, 2.4453975903652418e+00, 2.6151274247942147e+00, 2.7850777356245309e+00, 2.9552641159350221e+00, 3.1257024317672348e+00, 3.2964088439149859e+00, 3.4673998307723486e+00, 3.6386922123428187e+00, 3.8103031755212977e+00, 3.9822503007705263e+00, 4.1545515903248518e+00, 4.3272254980667917e+00, 4.5002909612360460e+00, 4.6737674341465381e+00, 4.8476749241050427e+00, 5.0220340297452291e+00, 5.1968659820138337e+00, 5.3721926880716282e+00, 5.5480367784012250e+00, 5.7244216574471602e+00, 5.9013715581517205e+00, 6.0789116007933410e+00, 6.2570678565839728e+00, 6.4358674165386551e+00, 6.6153384661958059e+00, 6.7955103668419072e+00, 6.9764137439811300e+00, 7.1580805838909543e+00, 7.3405443392217018e+00, 7.5238400447339577e+00, 7.7080044444269156e+00, 7.8930761314972990e+00, 8.0790957027880133e+00, 8.2661059296450645e+00, 8.4541519474088638e+00, 8.6432814661321498e+00, 8.8335450055546225e+00, 9.0249961578901878e+00, 9.2176918826171956e+00, 9.4116928382313976e+00, 9.6070637568592137e+00, 9.8038738687782931e+00, 1.0002197385309380e+01, 1.0202114050301228e+01, 1.0403709772624749e+01, 1.0607077354851786e+01, 1.0812317336788272e+01, 1.1019538976992907e+01, 1.1228861401155735e+01, 1.1440414953672729e+01, 1.1654342798540783e+01, 1.1870802828673778e+01, 1.2089969960138866e+01, 1.2312038911428751e+01, 1.2537227600374516e+01, 1.2765781336657277e+01, 1.2997978052213019e+01, 1.3234134904720168e+01, 1.3474616726146943e+01, 1.3719846994209712e+01, 1.3970322322144929e+01, 1.4226631965786098e+01, 1.4489484671220278e+01, 1.4759746585548676e+01, 1.5038496431508072e+01, 1.5327108761515133e+01, 1.5627385233279865e+01, 1.5941773281856777e+01, 1.6273756976433262e+01, 1.6628624717520726e+01, 1.7015192658329994e+01, 1.7450566562382527e+01, 1.7979511220856821e+01}, + {-1.8033641954168267e+01, -1.7505222333487513e+01, -1.7070289870719815e+01, -1.6684121139543407e+01, -1.6329626050797177e+01, -1.5997996474571265e+01, -1.5683948796077209e+01, -1.5384002084668344e+01, -1.5095711102237930e+01, -1.4817275804306519e+01, -1.4547322867471838e+01, -1.4284774533151579e+01, -1.4028765428985777e+01, -1.3778587444058825e+01, -1.3533651852283532e+01, -1.3293462488855706e+01, -1.3057596260647884e+01, -1.2825688669380938e+01, -1.2597422849942523e+01, -1.2372521129351217e+01, -1.2150738429127935e+01, -1.1931857039523125e+01, -1.1715682430712077e+01, -1.1502039858881551e+01, -1.1290771589409180e+01, -1.1081734604649661e+01, -1.0874798696301507e+01, -1.0669844865923427e+01, -1.0466763974552268e+01, -1.0265455595339178e+01, -1.0065827032900119e+01, -9.8677924805319144e+00, -9.6712722921832484e+00, -9.4761923505272865e+00, -9.2824835159740040e+00, -9.0900811442169349e+00, -8.8989246621016740e+00, -8.7089571933595398e+00, -8.5201252271656553e+00, -8.3323783236290581e+00, -8.1456688512594901e+00, -7.9599517522241854e+00, -7.7751843318419356e+00, -7.5913260692870139e+00, -7.4083384469130396e+00, -7.2261847959726726e+00, -7.0448301568163600e+00, -6.8642411519124229e+00, -6.6843858702502548e+00, -6.5052337618746865e+00, -6.3267555414586063e+00, -6.1489230999568738e+00, -5.9717094235012285e+00, -5.7950885187964847e+00, -5.6190353443649403e+00, -5.4435257470611598e+00, -5.2685364033444513e+00, -5.0940447648531757e+00, -4.9200290078745663e+00, -4.7464679863470698e+00, -4.5733411880702048e+00, -4.4006286938303605e+00, -4.2283111391802617e+00, -4.0563696786358214e+00, -3.8847859520769483e+00, -3.7135420531591667e+00, -3.5426204995608663e+00, -3.3720042049069567e+00, -3.2016764522238601e+00, -3.0316208687934161e+00, -2.8618214022844848e+00, -2.6922622980510740e+00, -2.5229280774947309e+00, -2.3538035173969201e+00, -2.1848736301342204e+00, -2.0161236446955049e+00, -1.8475389884259239e+00, -1.6791052694275435e+00, -1.5108082595509420e+00, -1.3426338779160372e+00, -1.1745681749038943e+00, -1.0065973165643360e+00, -8.3870756938683533e-01, -6.7088528538449332e-01, -5.0311688744285843e-01, -3.3538885488700437e-01, -1.6768770922162865e-01, -0.0000000000000000e+00, 1.6768770922162865e-01, 3.3538885488700437e-01, 5.0311688744285843e-01, 6.7088528538449332e-01, 8.3870756938683533e-01, 1.0065973165643360e+00, 1.1745681749038943e+00, 1.3426338779160372e+00, 1.5108082595509420e+00, 1.6791052694275435e+00, 1.8475389884259239e+00, 2.0161236446955049e+00, 2.1848736301342204e+00, 2.3538035173969201e+00, 2.5229280774947309e+00, 2.6922622980510740e+00, 2.8618214022844848e+00, 3.0316208687934161e+00, 3.2016764522238601e+00, 3.3720042049069567e+00, 3.5426204995608663e+00, 3.7135420531591667e+00, 3.8847859520769483e+00, 4.0563696786358214e+00, 4.2283111391802617e+00, 4.4006286938303605e+00, 4.5733411880702048e+00, 4.7464679863470698e+00, 4.9200290078745663e+00, 5.0940447648531757e+00, 5.2685364033444513e+00, 5.4435257470611598e+00, 5.6190353443649403e+00, 5.7950885187964847e+00, 5.9717094235012285e+00, 6.1489230999568738e+00, 6.3267555414586063e+00, 6.5052337618746865e+00, 6.6843858702502548e+00, 6.8642411519124229e+00, 7.0448301568163600e+00, 7.2261847959726726e+00, 7.4083384469130396e+00, 7.5913260692870139e+00, 7.7751843318419356e+00, 7.9599517522241854e+00, 8.1456688512594901e+00, 8.3323783236290581e+00, 8.5201252271656553e+00, 8.7089571933595398e+00, 8.8989246621016740e+00, 9.0900811442169349e+00, 9.2824835159740040e+00, 9.4761923505272865e+00, 9.6712722921832484e+00, 9.8677924805319144e+00, 1.0065827032900119e+01, 1.0265455595339178e+01, 1.0466763974552268e+01, 1.0669844865923427e+01, 1.0874798696301507e+01, 1.1081734604649661e+01, 1.1290771589409180e+01, 1.1502039858881551e+01, 1.1715682430712077e+01, 1.1931857039523125e+01, 1.2150738429127935e+01, 1.2372521129351217e+01, 1.2597422849942523e+01, 1.2825688669380938e+01, 1.3057596260647884e+01, 1.3293462488855706e+01, 1.3533651852283532e+01, 1.3778587444058825e+01, 1.4028765428985777e+01, 1.4284774533151579e+01, 1.4547322867471838e+01, 1.4817275804306519e+01, 1.5095711102237930e+01, 1.5384002084668344e+01, 1.5683948796077209e+01, 1.5997996474571265e+01, 1.6329626050797177e+01, 1.6684121139543407e+01, 1.7070289870719815e+01, 1.7505222333487513e+01, 1.8033641954168267e+01}, + {-1.8087616073790890e+01, -1.7559717906645613e+01, -1.7125223825336107e+01, -1.6739451499952981e+01, -1.6385326414471709e+01, -1.6054048410627541e+01, -1.5740338628583727e+01, -1.5440719256044483e+01, -1.5152747237684542e+01, -1.4874624131806939e+01, -1.4604977836012001e+01, -1.4342731549531273e+01, -1.4087020669594040e+01, -1.3837137716174603e+01, -1.3592494489303405e+01, -1.3352595269479263e+01, -1.3117017345422802e+01, -1.2885396550109379e+01, -1.2657416308802228e+01, -1.2432799205480446e+01, -1.2211300391032086e+01, -1.1992702362083911e+01, -1.1776810775879971e+01, -1.1563451059348457e+01, -1.1352465634716971e+01, -1.1143711629308052e+01, -1.0937058969577729e+01, -1.0732388783033896e+01, -1.0529592049038808e+01, -1.0328568452453034e+01, -1.0129225403849107e+01, -9.9314771974714695e+00, -9.7352442838524844e+00, -9.5404526384475599e+00, -9.3470332111408592e+00, -9.1549214442271172e+00, -8.9640568486659262e+00, -8.7743826301592698e+00, -8.5858453580177638e+00, -8.3983946709283614e+00, -8.2119830146725530e+00, -8.0265654076120381e+00, -7.8420992303922956e+00, -7.6585440368392881e+00, -7.4758613834617105e+00, -7.2940146753366397e+00, -7.1129690264635128e+00, -6.9326911329302607e+00, -6.7531491574546436e+00, -6.5743126240500311e+00, -6.3961523217237177e+00, -6.2186402162517354e+00, -6.0417493691907094e+00, -5.8654538633877182e+00, -5.6897287343358398e+00, -5.5145499067980914e+00, -5.3398941361876862e+00, -5.1657389542492513e+00, -4.9920626186351811e+00, -4.8188440660145870e+00, -4.6460628683903158e+00, -4.4736991923328295e+00, -4.3017337608691273e+00, -4.1301478177908013e+00, -3.9589230941681977e+00, -3.7880417768779360e+00, -3.6174864789689782e+00, -3.4472402117084235e+00, -3.2772863581623723e+00, -3.1076086481798137e+00, -2.9381911346587741e+00, -2.7690181709839532e+00, -2.6000743895340599e+00, -2.4313446811650303e+00, -2.2628141755824469e+00, -2.0944682225228455e+00, -1.9262923736692732e+00, -1.7582723652315242e+00, -1.5903941011259675e+00, -1.4226436366938928e+00, -1.2550071629008195e+00, -1.0874709909623226e+00, -9.2002153734466763e-01, -7.5264530909089167e-01, -5.8532888942501560e-01, -4.1805892358878166e-01, -2.5082210486674750e-01, -8.3605160756706529e-02, 8.3605160756706529e-02, 2.5082210486674750e-01, 4.1805892358878166e-01, 5.8532888942501560e-01, 7.5264530909089167e-01, 9.2002153734466763e-01, 1.0874709909623226e+00, 1.2550071629008195e+00, 1.4226436366938928e+00, 1.5903941011259675e+00, 1.7582723652315242e+00, 1.9262923736692732e+00, 2.0944682225228455e+00, 2.2628141755824469e+00, 2.4313446811650303e+00, 2.6000743895340599e+00, 2.7690181709839532e+00, 2.9381911346587741e+00, 3.1076086481798137e+00, 3.2772863581623723e+00, 3.4472402117084235e+00, 3.6174864789689782e+00, 3.7880417768779360e+00, 3.9589230941681977e+00, 4.1301478177908013e+00, 4.3017337608691273e+00, 4.4736991923328295e+00, 4.6460628683903158e+00, 4.8188440660145870e+00, 4.9920626186351811e+00, 5.1657389542492513e+00, 5.3398941361876862e+00, 5.5145499067980914e+00, 5.6897287343358398e+00, 5.8654538633877182e+00, 6.0417493691907094e+00, 6.2186402162517354e+00, 6.3961523217237177e+00, 6.5743126240500311e+00, 6.7531491574546436e+00, 6.9326911329302607e+00, 7.1129690264635128e+00, 7.2940146753366397e+00, 7.4758613834617105e+00, 7.6585440368392881e+00, 7.8420992303922956e+00, 8.0265654076120381e+00, 8.2119830146725530e+00, 8.3983946709283614e+00, 8.5858453580177638e+00, 8.7743826301592698e+00, 8.9640568486659262e+00, 9.1549214442271172e+00, 9.3470332111408592e+00, 9.5404526384475599e+00, 9.7352442838524844e+00, 9.9314771974714695e+00, 1.0129225403849107e+01, 1.0328568452453034e+01, 1.0529592049038808e+01, 1.0732388783033896e+01, 1.0937058969577729e+01, 1.1143711629308052e+01, 1.1352465634716971e+01, 1.1563451059348457e+01, 1.1776810775879971e+01, 1.1992702362083911e+01, 1.2211300391032086e+01, 1.2432799205480446e+01, 1.2657416308802228e+01, 1.2885396550109379e+01, 1.3117017345422802e+01, 1.3352595269479263e+01, 1.3592494489303405e+01, 1.3837137716174603e+01, 1.4087020669594040e+01, 1.4342731549531273e+01, 1.4604977836012001e+01, 1.4874624131806939e+01, 1.5152747237684542e+01, 1.5440719256044483e+01, 1.5740338628583727e+01, 1.6054048410627541e+01, 1.6385326414471709e+01, 1.6739451499952981e+01, 1.7125223825336107e+01, 1.7559717906645613e+01, 1.8087616073790890e+01}, + {-1.8141434926389717e+01, -1.7614054673500309e+01, -1.7179995952720883e+01, -1.6794617265339959e+01, -1.6440859568460443e+01, -1.6109930624426557e+01, -1.5796556297952138e+01, -1.5497261875146510e+01, -1.5209606469472327e+01, -1.4931793231695860e+01, -1.4662451272508532e+01, -1.4400504742695974e+01, -1.4145089803991842e+01, -1.3895499603035967e+01, -1.3651146462397561e+01, -1.3411535104793492e+01, -1.3176243198091708e+01, -1.2944906904124267e+01, -1.2717209936373832e+01, -1.2492875133818373e+01, -1.2271657874909140e+01, -1.2053340860973840e+01, -1.1837729934755059e+01, -1.1624650692438404e+01, -1.1413945711687965e+01, -1.1205472263438262e+01, -1.0999100407593694e+01, -1.0794711396339702e+01, -1.0592196326121911e+01, -1.0391454992291058e+01, -1.0192394910173833e+01, -9.9949304737714737e+00, -9.7989822290161133e+00, -9.6044762429642674e+00, -9.4113435537920687e+00, -9.2195196892087417e+00, -9.0289442430934326e+00, -8.8395605019136383e+00, -8.6513151138967856e+00, -8.4641577950728877e+00, -8.2780410672415687e+00, -8.0929200236841812e+00, -7.9087521190744416e+00, -7.7254969805656009e+00, -7.5431162374687224e+00, -7.3615733673019719e+00, -7.1808335562975261e+00, -7.0008635727114159e+00, -6.8216316515006419e+00, -6.6431073891179739e+00, -6.4652616473335298e+00, -6.2880664651279838e+00, -6.1114949778187784e+00, -5.9355213426810298e+00, -5.7601206704114505e+00, -5.5852689618586204e+00, -5.4109430495080577e+00, -5.2371205432672880e+00, -5.0637797801455120e+00, -4.8908997774658411e+00, -4.7184601892859508e+00, -4.5464412657363820e+00, -4.3748238150150680e+00, -4.2035891678025479e+00, -4.0327191438852346e+00, -3.8621960207943373e+00, -3.6920025042860427e+00, -3.5221217005044698e+00, -3.3525370896831359e+00, -3.1832325012532876e+00, -3.0141920902387014e+00, -2.8454003148266174e+00, -2.6768419150134308e+00, -2.5085018922317608e+00, -2.3403654898726809e+00, -2.1724181746232882e+00, -2.0046456185454748e+00, -1.8370336818268698e+00, -1.6695683961394456e+00, -1.5022359485453094e+00, -1.3350226658927800e+00, -1.1679149996489939e+00, -1.0008995111180643e+00, -8.3396285699622974e-01, -6.6709177521751994e-01, -5.0027307104524965e-01, -3.3349360336615247e-01, -1.6674027114518436e-01, -0.0000000000000000e+00, 1.6674027114518436e-01, 3.3349360336615247e-01, 5.0027307104524965e-01, 6.6709177521751994e-01, 8.3396285699622974e-01, 1.0008995111180643e+00, 1.1679149996489939e+00, 1.3350226658927800e+00, 1.5022359485453094e+00, 1.6695683961394456e+00, 1.8370336818268698e+00, 2.0046456185454748e+00, 2.1724181746232882e+00, 2.3403654898726809e+00, 2.5085018922317608e+00, 2.6768419150134308e+00, 2.8454003148266174e+00, 3.0141920902387014e+00, 3.1832325012532876e+00, 3.3525370896831359e+00, 3.5221217005044698e+00, 3.6920025042860427e+00, 3.8621960207943373e+00, 4.0327191438852346e+00, 4.2035891678025479e+00, 4.3748238150150680e+00, 4.5464412657363820e+00, 4.7184601892859508e+00, 4.8908997774658411e+00, 5.0637797801455120e+00, 5.2371205432672880e+00, 5.4109430495080577e+00, 5.5852689618586204e+00, 5.7601206704114505e+00, 5.9355213426810298e+00, 6.1114949778187784e+00, 6.2880664651279838e+00, 6.4652616473335298e+00, 6.6431073891179739e+00, 6.8216316515006419e+00, 7.0008635727114159e+00, 7.1808335562975261e+00, 7.3615733673019719e+00, 7.5431162374687224e+00, 7.7254969805656009e+00, 7.9087521190744416e+00, 8.0929200236841812e+00, 8.2780410672415687e+00, 8.4641577950728877e+00, 8.6513151138967856e+00, 8.8395605019136383e+00, 9.0289442430934326e+00, 9.2195196892087417e+00, 9.4113435537920687e+00, 9.6044762429642674e+00, 9.7989822290161133e+00, 9.9949304737714737e+00, 1.0192394910173833e+01, 1.0391454992291058e+01, 1.0592196326121911e+01, 1.0794711396339702e+01, 1.0999100407593694e+01, 1.1205472263438262e+01, 1.1413945711687965e+01, 1.1624650692438404e+01, 1.1837729934755059e+01, 1.2053340860973840e+01, 1.2271657874909140e+01, 1.2492875133818373e+01, 1.2717209936373832e+01, 1.2944906904124267e+01, 1.3176243198091708e+01, 1.3411535104793492e+01, 1.3651146462397561e+01, 1.3895499603035967e+01, 1.4145089803991842e+01, 1.4400504742695974e+01, 1.4662451272508532e+01, 1.4931793231695860e+01, 1.5209606469472327e+01, 1.5497261875146510e+01, 1.5796556297952138e+01, 1.6109930624426557e+01, 1.6440859568460443e+01, 1.6794617265339959e+01, 1.7179995952720883e+01, 1.7614054673500309e+01, 1.8141434926389717e+01}, + {-1.8195099839472430e+01, -1.7668234005719587e+01, -1.7234607662724841e+01, -1.6849619880933339e+01, -1.6496226991759631e+01, -1.6165644627729627e+01, -1.5852603348070128e+01, -1.5553631517589562e+01, -1.5266290404714507e+01, -1.4988784742481727e+01, -1.4719744846860621e+01, -1.4458095814010402e+01, -1.4202974565149994e+01, -1.3953674869416368e+01, -1.3709609568387386e+01, -1.3470283823956324e+01, -1.3235275680476827e+01, -1.3004221626275813e+01, -1.2776805660932723e+01, -1.2552750876494338e+01, -1.2331812877201305e+01, -1.2113774567435913e+01, -1.1898441973897304e+01, -1.1685640860572095e+01, -1.1475213959174649e+01, -1.1267018682922650e+01, -1.1060925223886697e+01, -1.0856814957685176e+01, -1.0654579096632252e+01, -1.0454117545377073e+01, -1.0255337922825921e+01, -1.0058154721574315e+01, -9.8624885817991093e+00, -9.6682656610062114e+00, -9.4754170845116796e+00, -9.2838784642833954e+00, -9.0935894759573372e+00, -8.9044934855939797e+00, -8.7165372191524781e+00, -8.5296704688056462e+00, -8.3438458311533719e+00, -8.1590184731587261e+00, -7.9751459222633976e+00, -7.7921878776629914e+00, -7.6101060401591205e+00, -7.4288639583701048e+00, -7.2484268893885622e+00, -7.0687616722327293e+00, -6.8898366126570973e+00, -6.7116213780739269e+00, -6.5340869014957565e+00, -6.3572052935446060e+00, -6.1809497616900950e+00, -6.0052945359788579e+00, -5.8302148006042280e+00, -5.6556866307401252e+00, -5.4816869341281516e+00, -5.3081933969635617e+00, -5.1351844336752253e+00, -4.9626391402379442e+00, -4.7905372506934265e+00, -4.6188590965895351e+00, -4.4475855690767556e+00, -4.2766980834267416e+00, -4.1061785457606526e+00, -3.9360093217952534e+00, -3.7661732074327352e+00, -3.5966534010361229e+00, -3.4274334772463870e+00, -3.2584973622099573e+00, -3.0898293100966461e+00, -2.9214138807980121e+00, -2.7532359187051947e+00, -2.5852805324732593e+00, -2.4175330756862730e+00, -2.2499791283437252e+00, -2.0826044790946652e+00, -1.9153951081510019e+00, -1.7483371708160103e+00, -1.5814169815681258e+00, -1.4146209986437335e+00, -1.2479358090658317e+00, -1.0813481140682928e+00, -9.1484471486787966e-01, -7.4841249873834059e-01, -5.8203842534274008e-01, -4.1570951328174155e-01, -2.4941282681685847e-01, -8.3135462728728945e-02, 8.3135462728728945e-02, 2.4941282681685847e-01, 4.1570951328174155e-01, 5.8203842534274008e-01, 7.4841249873834059e-01, 9.1484471486787966e-01, 1.0813481140682928e+00, 1.2479358090658317e+00, 1.4146209986437335e+00, 1.5814169815681258e+00, 1.7483371708160103e+00, 1.9153951081510019e+00, 2.0826044790946652e+00, 2.2499791283437252e+00, 2.4175330756862730e+00, 2.5852805324732593e+00, 2.7532359187051947e+00, 2.9214138807980121e+00, 3.0898293100966461e+00, 3.2584973622099573e+00, 3.4274334772463870e+00, 3.5966534010361229e+00, 3.7661732074327352e+00, 3.9360093217952534e+00, 4.1061785457606526e+00, 4.2766980834267416e+00, 4.4475855690767556e+00, 4.6188590965895351e+00, 4.7905372506934265e+00, 4.9626391402379442e+00, 5.1351844336752253e+00, 5.3081933969635617e+00, 5.4816869341281516e+00, 5.6556866307401252e+00, 5.8302148006042280e+00, 6.0052945359788579e+00, 6.1809497616900950e+00, 6.3572052935446060e+00, 6.5340869014957565e+00, 6.7116213780739269e+00, 6.8898366126570973e+00, 7.0687616722327293e+00, 7.2484268893885622e+00, 7.4288639583701048e+00, 7.6101060401591205e+00, 7.7921878776629914e+00, 7.9751459222633976e+00, 8.1590184731587261e+00, 8.3438458311533719e+00, 8.5296704688056462e+00, 8.7165372191524781e+00, 8.9044934855939797e+00, 9.0935894759573372e+00, 9.2838784642833954e+00, 9.4754170845116796e+00, 9.6682656610062114e+00, 9.8624885817991093e+00, 1.0058154721574315e+01, 1.0255337922825921e+01, 1.0454117545377073e+01, 1.0654579096632252e+01, 1.0856814957685176e+01, 1.1060925223886697e+01, 1.1267018682922650e+01, 1.1475213959174649e+01, 1.1685640860572095e+01, 1.1898441973897304e+01, 1.2113774567435913e+01, 1.2331812877201305e+01, 1.2552750876494338e+01, 1.2776805660932723e+01, 1.3004221626275813e+01, 1.3235275680476827e+01, 1.3470283823956324e+01, 1.3709609568387386e+01, 1.3953674869416368e+01, 1.4202974565149994e+01, 1.4458095814010402e+01, 1.4719744846860621e+01, 1.4988784742481727e+01, 1.5266290404714507e+01, 1.5553631517589562e+01, 1.5852603348070128e+01, 1.6165644627729627e+01, 1.6496226991759631e+01, 1.6849619880933339e+01, 1.7234607662724841e+01, 1.7668234005719587e+01, 1.8195099839472430e+01}, + {-1.8248612121768343e+01, -1.7722257255394386e+01, -1.7289060344922966e+01, -1.6904460771032490e+01, -1.6551430141805881e+01, -1.6221191910121661e+01, -1.5908481300039147e+01, -1.5609829735595335e+01, -1.5322800626523263e+01, -1.5045600278061576e+01, -1.4776860203741105e+01, -1.4515506438991860e+01, -1.4260676659563400e+01, -1.4011665252976300e+01, -1.3767885576334674e+01, -1.3528843227708883e+01, -1.3294116625314924e+01, -1.3063342581647838e+01, -1.2836205380293851e+01, -1.2612428364469304e+01, -1.2391767362459763e+01, -1.2174005480084015e+01, -1.1958948926483190e+01, -1.1746423632015365e+01, -1.1536272481085435e+01, -1.1328353027891652e+01, -1.1122535595414808e+01, -1.0918701681487823e+01, -1.0716742613104932e+01, -1.0516558403048526e+01, -1.0318056772656865e+01, -1.0121152311984588e+01, -9.9257657543260880e+00, -9.7318233465134139e+00, -9.5392562998795718e+00, -9.3480003095250854e+00, -9.1579951317106332e+00, -8.9691842109485744e+00, -8.7815143497770496e+00, -8.5949354153447821e+00, -8.4094000778684173e+00, -8.2248635767903480e+00, -8.0412835110966494e+00, -7.8586196507783281e+00, -7.6768337668550366e+00, -7.4958894777450231e+00, -7.3157521100712737e+00, -7.1363885722521356e+00, -6.9577672394433048e+00, -6.7798578485838581e+00, -6.6026314024574280e+00, -6.4260600818151339e+00, -6.2501171647232399e+00, -6.0747769523986586e+00, -5.9000147008819077e+00, -5.7258065579720290e+00, -5.5521295049130304e+00, -5.3789613023779728e+00, -5.2062804403463288e+00, -5.0340660915133606e+00, -4.8622980679082559e+00, -4.6909567804310086e+00, -4.5200232010473753e+00, -4.3494788274071139e+00, -4.1793056496735739e+00, -4.0094861193729656e+00, -3.8400031200895830e+00, -3.6708399398492308e+00, -3.5019802450472732e+00, -3.3334080557903905e+00, -3.1651077225323845e+00, -2.9970639038944427e+00, -2.8292615455692673e+00, -2.6616858602164983e+00, -2.4943223082640649e+00, -2.3271565795365086e+00, -2.1601745756370865e+00, -1.9933623930155944e+00, -1.8267063066584319e+00, -1.6601927543415429e+00, -1.4938083213904756e+00, -1.3275397258950710e+00, -1.1613738043291120e+00, -9.9529749752779750e-01, -8.2929783697808435e-01, -6.6336193137884258e-01, -4.9747695342938458e-01, -3.3163012680628950e-01, -1.6580871328955671e-01, -0.0000000000000000e+00, 1.6580871328955671e-01, 3.3163012680628950e-01, 4.9747695342938458e-01, 6.6336193137884258e-01, 8.2929783697808435e-01, 9.9529749752779750e-01, 1.1613738043291120e+00, 1.3275397258950710e+00, 1.4938083213904756e+00, 1.6601927543415429e+00, 1.8267063066584319e+00, 1.9933623930155944e+00, 2.1601745756370865e+00, 2.3271565795365086e+00, 2.4943223082640649e+00, 2.6616858602164983e+00, 2.8292615455692673e+00, 2.9970639038944427e+00, 3.1651077225323845e+00, 3.3334080557903905e+00, 3.5019802450472732e+00, 3.6708399398492308e+00, 3.8400031200895830e+00, 4.0094861193729656e+00, 4.1793056496735739e+00, 4.3494788274071139e+00, 4.5200232010473753e+00, 4.6909567804310086e+00, 4.8622980679082559e+00, 5.0340660915133606e+00, 5.2062804403463288e+00, 5.3789613023779728e+00, 5.5521295049130304e+00, 5.7258065579720290e+00, 5.9000147008819077e+00, 6.0747769523986586e+00, 6.2501171647232399e+00, 6.4260600818151339e+00, 6.6026314024574280e+00, 6.7798578485838581e+00, 6.9577672394433048e+00, 7.1363885722521356e+00, 7.3157521100712737e+00, 7.4958894777450231e+00, 7.6768337668550366e+00, 7.8586196507783281e+00, 8.0412835110966494e+00, 8.2248635767903480e+00, 8.4094000778684173e+00, 8.5949354153447821e+00, 8.7815143497770496e+00, 8.9691842109485744e+00, 9.1579951317106332e+00, 9.3480003095250854e+00, 9.5392562998795718e+00, 9.7318233465134139e+00, 9.9257657543260880e+00, 1.0121152311984588e+01, 1.0318056772656865e+01, 1.0516558403048526e+01, 1.0716742613104932e+01, 1.0918701681487823e+01, 1.1122535595414808e+01, 1.1328353027891652e+01, 1.1536272481085435e+01, 1.1746423632015365e+01, 1.1958948926483190e+01, 1.2174005480084015e+01, 1.2391767362459763e+01, 1.2612428364469304e+01, 1.2836205380293851e+01, 1.3063342581647838e+01, 1.3294116625314924e+01, 1.3528843227708883e+01, 1.3767885576334674e+01, 1.4011665252976300e+01, 1.4260676659563400e+01, 1.4515506438991860e+01, 1.4776860203741105e+01, 1.5045600278061576e+01, 1.5322800626523263e+01, 1.5609829735595335e+01, 1.5908481300039147e+01, 1.6221191910121661e+01, 1.6551430141805881e+01, 1.6904460771032490e+01, 1.7289060344922966e+01, 1.7722257255394386e+01, 1.8248612121768343e+01}, + {-1.8301973063597831e+01, -1.7776125755426882e+01, -1.7343355369019513e+01, -1.6959141339427859e+01, -1.6606470454912181e+01, -1.6276573939462359e+01, -1.5964191652640661e+01, -1.5665858058473457e+01, -1.5379138694506308e+01, -1.5102241428233055e+01, -1.4833798963124122e+01, -1.4572738267853815e+01, -1.4318197767810874e+01, -1.4069472464839684e+01, -1.3825976228134913e+01, -1.3587215088986124e+01, -1.3352767836885693e+01, -1.3122271606204340e+01, -1.2895410962476978e+01, -1.2671909498220252e+01, -1.2451523264048797e+01, -1.2234035565627281e+01, -1.2019252793050947e+01, -1.1807001041645883e+01, -1.1597123347173454e+01, -1.1389477403535365e+01, -1.1183933663391947e+01, -1.0980373745597644e+01, -1.0778689090663802e+01, -1.0578779818366641e+01, -1.0380553751354837e+01, -1.0183925576033463e+01, -9.9888161177141903e+00, -9.7951517114594342e+00, -9.6028636535242580e+00, -9.4118877210445753e+00, -9.2221637498031388e+00, -9.0336352616534104e+00, -8.8462491345909715e+00, -8.6599553096056603e+00, -8.4747065293805139e+00, -8.2904581046690247e+00, -8.1071677048133868e+00, -7.9247951693895704e+00, -7.7433023384005537e+00, -7.5626528988034316e+00, -7.3828122454620404e+00, -7.2037473548748121e+00, -7.0254266702460146e+00, -6.8478199966541871e+00, -6.6708984052298304e+00, -6.4946341453898597e+00, -6.3190005642925637e+00, -6.1439720327768708e+00, -5.9695238771362042e+00, -5.7956323161519689e+00, -5.6222744028767648e+00, -5.4494279707139679e+00, -5.2770715833897031e+00, -5.1051844884564179e+00, -4.9337465740051734e+00, -4.7627383282970204e+00, -4.5921408020531498e+00, -4.4219355731693852e+00, -4.2521047136434067e+00, -4.0826307585233783e+00, -3.9134966767045909e+00, -3.7446858434166801e+00, -3.5761820142581890e+00, -3.4079693006478804e+00, -3.2400321465734825e+00, -3.0723553065286380e+00, -2.9049238245378035e+00, -2.7377230141769160e+00, -2.5707384395048281e+00, -2.4039558968269845e+00, -2.2373613972185420e+00, -2.0709411497393346e+00, -1.9046815452776742e+00, -1.7385691409641026e+00, -1.5725906450998823e+00, -1.4067329025482804e+00, -1.2409828805395797e+00, -1.0753276548433179e+00, -9.0975439626347543e-01, -7.4425035741428780e-01, -5.7880285973602430e-01, -4.1339928071149723e-01, -2.4802704124523722e-01, -8.2673593168222662e-02, 8.2673593168222662e-02, 2.4802704124523722e-01, 4.1339928071149723e-01, 5.7880285973602430e-01, 7.4425035741428780e-01, 9.0975439626347543e-01, 1.0753276548433179e+00, 1.2409828805395797e+00, 1.4067329025482804e+00, 1.5725906450998823e+00, 1.7385691409641026e+00, 1.9046815452776742e+00, 2.0709411497393346e+00, 2.2373613972185420e+00, 2.4039558968269845e+00, 2.5707384395048281e+00, 2.7377230141769160e+00, 2.9049238245378035e+00, 3.0723553065286380e+00, 3.2400321465734825e+00, 3.4079693006478804e+00, 3.5761820142581890e+00, 3.7446858434166801e+00, 3.9134966767045909e+00, 4.0826307585233783e+00, 4.2521047136434067e+00, 4.4219355731693852e+00, 4.5921408020531498e+00, 4.7627383282970204e+00, 4.9337465740051734e+00, 5.1051844884564179e+00, 5.2770715833897031e+00, 5.4494279707139679e+00, 5.6222744028767648e+00, 5.7956323161519689e+00, 5.9695238771362042e+00, 6.1439720327768708e+00, 6.3190005642925637e+00, 6.4946341453898597e+00, 6.6708984052298304e+00, 6.8478199966541871e+00, 7.0254266702460146e+00, 7.2037473548748121e+00, 7.3828122454620404e+00, 7.5626528988034316e+00, 7.7433023384005537e+00, 7.9247951693895704e+00, 8.1071677048133868e+00, 8.2904581046690247e+00, 8.4747065293805139e+00, 8.6599553096056603e+00, 8.8462491345909715e+00, 9.0336352616534104e+00, 9.2221637498031388e+00, 9.4118877210445753e+00, 9.6028636535242580e+00, 9.7951517114594342e+00, 9.9888161177141903e+00, 1.0183925576033463e+01, 1.0380553751354837e+01, 1.0578779818366641e+01, 1.0778689090663802e+01, 1.0980373745597644e+01, 1.1183933663391947e+01, 1.1389477403535365e+01, 1.1597123347173454e+01, 1.1807001041645883e+01, 1.2019252793050947e+01, 1.2234035565627281e+01, 1.2451523264048797e+01, 1.2671909498220252e+01, 1.2895410962476978e+01, 1.3122271606204340e+01, 1.3352767836885693e+01, 1.3587215088986124e+01, 1.3825976228134913e+01, 1.4069472464839684e+01, 1.4318197767810874e+01, 1.4572738267853815e+01, 1.4833798963124122e+01, 1.5102241428233055e+01, 1.5379138694506308e+01, 1.5665858058473457e+01, 1.5964191652640661e+01, 1.6276573939462359e+01, 1.6606470454912181e+01, 1.6959141339427859e+01, 1.7343355369019513e+01, 1.7776125755426882e+01, 1.8301973063597831e+01}, + {-1.8355183937232482e+01, -1.7829840819908938e+01, -1.7397494085242659e+01, -1.7013662969810934e+01, -1.6661349346692710e+01, -1.6331792162325648e+01, -1.6019735882790211e+01, -1.5721717993090206e+01, -1.5435306145250426e+01, -1.5158709759192869e+01, -1.4890562720798751e+01, -1.4629792926034948e+01, -1.4375539545099908e+01, -1.4127098190154650e+01, -1.3883883239094454e+01, -1.3645401153510734e+01, -1.3411231091622829e+01, -1.3181010507418183e+01, -1.2954424246353401e+01, -1.2731196148405482e+01, -1.2511082484830109e+01, -1.2293866759574003e+01, -1.2079355542224606e+01, -1.1867375091697919e+01, -1.1657768593802700e+01, -1.1450393880891689e+01, -1.1245121534098722e+01, -1.1041833292131351e+01, -1.0840420707879813e+01, -1.0640784006999668e+01, -1.0442831112353673e+01, -1.0246476805614231e+01, -1.0051642003036079e+01, -9.8582531268427509e+00, -9.6662415571436178e+00, -9.4755431520404851e+00, -9.2860978257640348e+00, -9.0978491764272782e+00, -8.9107441563917540e+00, -8.7247327793845830e+00, -8.5397678594367203e+00, -8.3558047774774487e+00, -8.1728012720508225e+00, -7.9907172511424713e+00, -7.8095146225403225e+00, -7.6291571405168730e+00, -7.4496102669262783e+00, -7.2708410450674368e+00, -7.0928179848824850e+00, -6.9155109582455818e+00, -6.7388911032550611e+00, -6.5629307365772949e+00, -6.3876032730067926e+00, -6.2128831515070333e+00, -6.0387457670829185e+00, -5.8651674079104827e+00, -5.6921251972144509e+00, -5.5195970394407690e+00, -5.3475615703205710e+00, -5.1759981104652155e+00, -5.0048866221698640e+00, -4.8342076691363776e+00, -4.6639423788555394e+00, -4.4940724074145217e+00, -4.3245799065183155e+00, -4.1554474925341225e+00, -3.9866582173856151e+00, -3.8181955411399695e+00, -3.6500433061447404e+00, -3.4821857125843008e+00, -3.3146072953368710e+00, -3.1472929020232101e+00, -2.9802276721470844e+00, -2.8133970172356633e+00, -2.6467866018952186e+00, -2.4803823257039688e+00, -2.3141703058696805e+00, -2.1481368605848363e+00, -1.9822684930168015e+00, -1.8165518758745727e+00, -1.6509738364973834e+00, -1.4855213424137426e+00, -1.3201814873224036e+00, -1.1549414774493456e+00, -9.8978861823713149e-01, -8.2471030132498657e-01, -6.5969399177967603e-01, -4.9472721553871407e-01, -3.2979754702868869e-01, -1.6489259692248556e-01, -0.0000000000000000e+00, 1.6489259692248556e-01, 3.2979754702868869e-01, 4.9472721553871407e-01, 6.5969399177967603e-01, 8.2471030132498657e-01, 9.8978861823713149e-01, 1.1549414774493456e+00, 1.3201814873224036e+00, 1.4855213424137426e+00, 1.6509738364973834e+00, 1.8165518758745727e+00, 1.9822684930168015e+00, 2.1481368605848363e+00, 2.3141703058696805e+00, 2.4803823257039688e+00, 2.6467866018952186e+00, 2.8133970172356633e+00, 2.9802276721470844e+00, 3.1472929020232101e+00, 3.3146072953368710e+00, 3.4821857125843008e+00, 3.6500433061447404e+00, 3.8181955411399695e+00, 3.9866582173856151e+00, 4.1554474925341225e+00, 4.3245799065183155e+00, 4.4940724074145217e+00, 4.6639423788555394e+00, 4.8342076691363776e+00, 5.0048866221698640e+00, 5.1759981104652155e+00, 5.3475615703205710e+00, 5.5195970394407690e+00, 5.6921251972144509e+00, 5.8651674079104827e+00, 6.0387457670829185e+00, 6.2128831515070333e+00, 6.3876032730067926e+00, 6.5629307365772949e+00, 6.7388911032550611e+00, 6.9155109582455818e+00, 7.0928179848824850e+00, 7.2708410450674368e+00, 7.4496102669262783e+00, 7.6291571405168730e+00, 7.8095146225403225e+00, 7.9907172511424713e+00, 8.1728012720508225e+00, 8.3558047774774487e+00, 8.5397678594367203e+00, 8.7247327793845830e+00, 8.9107441563917540e+00, 9.0978491764272782e+00, 9.2860978257640348e+00, 9.4755431520404851e+00, 9.6662415571436178e+00, 9.8582531268427509e+00, 1.0051642003036079e+01, 1.0246476805614231e+01, 1.0442831112353673e+01, 1.0640784006999668e+01, 1.0840420707879813e+01, 1.1041833292131351e+01, 1.1245121534098722e+01, 1.1450393880891689e+01, 1.1657768593802700e+01, 1.1867375091697919e+01, 1.2079355542224606e+01, 1.2293866759574003e+01, 1.2511082484830109e+01, 1.2731196148405482e+01, 1.2954424246353401e+01, 1.3181010507418183e+01, 1.3411231091622829e+01, 1.3645401153510734e+01, 1.3883883239094454e+01, 1.4127098190154650e+01, 1.4375539545099908e+01, 1.4629792926034948e+01, 1.4890562720798751e+01, 1.5158709759192869e+01, 1.5435306145250426e+01, 1.5721717993090206e+01, 1.6019735882790211e+01, 1.6331792162325648e+01, 1.6661349346692710e+01, 1.7013662969810934e+01, 1.7397494085242659e+01, 1.7829840819908938e+01, 1.8355183937232482e+01}, + {-1.8408245997246180e+01, -1.7883403744491030e+01, -1.7451477824729114e+01, -1.7068027026173699e+01, -1.6716068212476749e+01, -1.6386848004427836e+01, -1.6075115445979726e+01, -1.5777411024325023e+01, -1.5491304492792262e+01, -1.5215006814022102e+01, -1.4947153048869007e+01, -1.4686672014714095e+01, -1.4432703621796808e+01, -1.4184544088639219e+01, -1.3941608298492062e+01, -1.3703403140370927e+01, -1.3469508138708429e+01, -1.3239561064882505e+01, -1.3013247042274847e+01, -1.2790290156511402e+01, -1.2570446897828043e+01, -1.2353500966915787e+01, -1.2139259111417608e+01, -1.1927547752486015e+01, -1.1718210224692305e+01, -1.1511104497611852e+01, -1.1306101279669830e+01, -1.1103082428282363e+01, -1.0901939607604296e+01, -1.0702573148080202e+01, -1.0504891071714988e+01, -1.0308808254390055e+01, -1.0114245702254145e+01, -9.9211299236483459e+00, -9.7293923814947600e+00, -9.5389690138184235e+00, -9.3497998122512573e+00, -9.1618284501124911e+00, -8.9750019530671192e+00, -8.7892704065055494e+00, -8.6045866947189253e+00, -8.4209062677087161e+00, -8.2381869320992998e+00, -8.0563886631444781e+00, -7.8754734352537348e+00, -7.6954050688277018e+00, -7.5161490914978035e+00, -7.3376726121226348e+00, -7.1599442061117617e+00, -6.9829338108329129e+00, -6.8066126300166054e+00, -6.6309530462073942e+00, -6.4559285404270428e+00, -6.2815136183148121e+00, -6.1076837420963281e+00, -5.9344152678072613e+00, -5.7616853872629088e+00, -5.5894720743212600e+00, -5.4177540350364595e+00, -5.2465106613426817e+00, -5.0757219879463076e+00, -4.9053686521374775e+00, -4.7354318562614344e+00, -4.5658933326158548e+00, -4.3967353105632334e+00, -4.2279404856676086e+00, -4.0594919906828633e+00, -3.8913733682357932e+00, -3.7235685450613194e+00, -3.5560618076598769e+00, -3.3888377792582984e+00, -3.2218813979656056e+00, -3.0551778960241212e+00, -2.8887127800643957e+00, -2.7224718122796761e+00, -2.5564409924420968e+00, -2.3906065406885992e+00, -2.2249548810097695e+00, -2.0594726253794451e+00, -1.8941465584671033e+00, -1.7289636228787715e+00, -1.5639109048755229e+00, -1.3989756205215691e+00, -1.2341451022165917e+00, -1.0694067855692595e+00, -9.0474819657091143e-01, -7.4015693903015356e-01, -5.7562068223063112e-01, -4.1112714877553319e-01, -2.4666410258345153e-01, -8.2219337001082138e-02, 8.2219337001082138e-02, 2.4666410258345153e-01, 4.1112714877553319e-01, 5.7562068223063112e-01, 7.4015693903015356e-01, 9.0474819657091143e-01, 1.0694067855692595e+00, 1.2341451022165917e+00, 1.3989756205215691e+00, 1.5639109048755229e+00, 1.7289636228787715e+00, 1.8941465584671033e+00, 2.0594726253794451e+00, 2.2249548810097695e+00, 2.3906065406885992e+00, 2.5564409924420968e+00, 2.7224718122796761e+00, 2.8887127800643957e+00, 3.0551778960241212e+00, 3.2218813979656056e+00, 3.3888377792582984e+00, 3.5560618076598769e+00, 3.7235685450613194e+00, 3.8913733682357932e+00, 4.0594919906828633e+00, 4.2279404856676086e+00, 4.3967353105632334e+00, 4.5658933326158548e+00, 4.7354318562614344e+00, 4.9053686521374775e+00, 5.0757219879463076e+00, 5.2465106613426817e+00, 5.4177540350364595e+00, 5.5894720743212600e+00, 5.7616853872629088e+00, 5.9344152678072613e+00, 6.1076837420963281e+00, 6.2815136183148121e+00, 6.4559285404270428e+00, 6.6309530462073942e+00, 6.8066126300166054e+00, 6.9829338108329129e+00, 7.1599442061117617e+00, 7.3376726121226348e+00, 7.5161490914978035e+00, 7.6954050688277018e+00, 7.8754734352537348e+00, 8.0563886631444781e+00, 8.2381869320992998e+00, 8.4209062677087161e+00, 8.6045866947189253e+00, 8.7892704065055494e+00, 8.9750019530671192e+00, 9.1618284501124911e+00, 9.3497998122512573e+00, 9.5389690138184235e+00, 9.7293923814947600e+00, 9.9211299236483459e+00, 1.0114245702254145e+01, 1.0308808254390055e+01, 1.0504891071714988e+01, 1.0702573148080202e+01, 1.0901939607604296e+01, 1.1103082428282363e+01, 1.1306101279669830e+01, 1.1511104497611852e+01, 1.1718210224692305e+01, 1.1927547752486015e+01, 1.2139259111417608e+01, 1.2353500966915787e+01, 1.2570446897828043e+01, 1.2790290156511402e+01, 1.3013247042274847e+01, 1.3239561064882505e+01, 1.3469508138708429e+01, 1.3703403140370927e+01, 1.3941608298492062e+01, 1.4184544088639219e+01, 1.4432703621796808e+01, 1.4686672014714095e+01, 1.4947153048869007e+01, 1.5215006814022102e+01, 1.5491304492792262e+01, 1.5777411024325023e+01, 1.6075115445979726e+01, 1.6386848004427836e+01, 1.6716068212476749e+01, 1.7068027026173699e+01, 1.7451477824729114e+01, 1.7883403744491030e+01, 1.8408245997246180e+01}, + {-1.8461160480857558e+01, -1.7936815806741905e+01, -1.7505307899899091e+01, -1.7122234853198016e+01, -1.6770628427712005e+01, -1.6441742871044735e+01, -1.6130331776708392e+01, -1.5832938615515195e+01, -1.5547135229076916e+01, -1.5271134113158810e+01, -1.5003571496240674e+01, -1.4743377111311560e+01, -1.4489691603942756e+01, -1.4241811795112390e+01, -1.3999153070125370e+01, -1.3761222742582584e+01, -1.3527600700651213e+01, -1.3297925030905425e+01, -1.3071881132685062e+01, -1.2849193335481473e+01, -1.2629618346876333e+01, -1.2412940062792593e+01, -1.2198965407516690e+01, -1.1987520963108198e+01, -1.1778450211639703e+01, -1.1571611258704099e+01, -1.1366874938858906e+01, -1.1164123227107424e+01, -1.0963247897778071e+01, -1.0764149385037474e+01, -1.0566735808984420e+01, -1.0370922138674908e+01, -1.0176629469126997e+01, -9.9837843937805424e+00, -9.7923184573541491e+00, -9.6021676767792830e+00, -9.4132721200689708e+00, -9.2255755347225286e+00, -9.0390250186738808e+00, -8.8535707279314924e+00, -8.6691656159885877e+00, -8.4857652008457727e+00, -8.3033273561177268e+00, -8.1218121232175022e+00, -7.9411815420463903e+00, -7.7613994979807179e+00, -7.5824315832521663e+00, -7.4042449710755918e+00, -7.2268083010962609e+00, -7.0500915749135666e+00, -6.8740660605962152e+00, -6.6987042052389292e+00, -6.5239795547267194e+00, -6.3498666799725676e+00, -6.1763411089806590e+00, -6.0033792641618602e+00, -5.8309584043931153e+00, -5.6590565713687386e+00, -5.4876525398409859e+00, -5.3167257713902920e+00, -5.1462563714034442e+00, -4.9762250489711075e+00, -4.8066130794454613e+00, -4.6374022694244390e+00, -4.4685749239519819e+00, -4.3001138157438552e+00, -4.1320021562665863e+00, -3.9642235685129914e+00, -3.7967620613319606e+00, -3.6296020051828295e+00, -3.4627281091959579e+00, -3.2961253994312023e+00, -3.1297791982350316e+00, -2.9636751046050795e+00, -2.7977989754781833e+00, -2.6321369078644477e+00, -2.4666752217556631e+00, -2.3014004437416671e+00, -2.1362992912728620e+00, -1.9713586575113293e+00, -1.8065655967166996e+00, -1.6419073101163049e+00, -1.4773711322121057e+00, -1.3129445174795540e+00, -1.1486150274158851e+00, -9.8437031789740859e-01, -8.2019812680717263e-01, -6.5608626189593511e-01, -4.9202258884072003e-01, -3.2799501946636006e-01, -1.6399150009634114e-01, -0.0000000000000000e+00, 1.6399150009634114e-01, 3.2799501946636006e-01, 4.9202258884072003e-01, 6.5608626189593511e-01, 8.2019812680717263e-01, 9.8437031789740859e-01, 1.1486150274158851e+00, 1.3129445174795540e+00, 1.4773711322121057e+00, 1.6419073101163049e+00, 1.8065655967166996e+00, 1.9713586575113293e+00, 2.1362992912728620e+00, 2.3014004437416671e+00, 2.4666752217556631e+00, 2.6321369078644477e+00, 2.7977989754781833e+00, 2.9636751046050795e+00, 3.1297791982350316e+00, 3.2961253994312023e+00, 3.4627281091959579e+00, 3.6296020051828295e+00, 3.7967620613319606e+00, 3.9642235685129914e+00, 4.1320021562665863e+00, 4.3001138157438552e+00, 4.4685749239519819e+00, 4.6374022694244390e+00, 4.8066130794454613e+00, 4.9762250489711075e+00, 5.1462563714034442e+00, 5.3167257713902920e+00, 5.4876525398409859e+00, 5.6590565713687386e+00, 5.8309584043931153e+00, 6.0033792641618602e+00, 6.1763411089806590e+00, 6.3498666799725676e+00, 6.5239795547267194e+00, 6.6987042052389292e+00, 6.8740660605962152e+00, 7.0500915749135666e+00, 7.2268083010962609e+00, 7.4042449710755918e+00, 7.5824315832521663e+00, 7.7613994979807179e+00, 7.9411815420463903e+00, 8.1218121232175022e+00, 8.3033273561177268e+00, 8.4857652008457727e+00, 8.6691656159885877e+00, 8.8535707279314924e+00, 9.0390250186738808e+00, 9.2255755347225286e+00, 9.4132721200689708e+00, 9.6021676767792830e+00, 9.7923184573541491e+00, 9.9837843937805424e+00, 1.0176629469126997e+01, 1.0370922138674908e+01, 1.0566735808984420e+01, 1.0764149385037474e+01, 1.0963247897778071e+01, 1.1164123227107424e+01, 1.1366874938858906e+01, 1.1571611258704099e+01, 1.1778450211639703e+01, 1.1987520963108198e+01, 1.2198965407516690e+01, 1.2412940062792593e+01, 1.2629618346876333e+01, 1.2849193335481473e+01, 1.3071881132685062e+01, 1.3297925030905425e+01, 1.3527600700651213e+01, 1.3761222742582584e+01, 1.3999153070125370e+01, 1.4241811795112390e+01, 1.4489691603942756e+01, 1.4743377111311560e+01, 1.5003571496240674e+01, 1.5271134113158810e+01, 1.5547135229076916e+01, 1.5832938615515195e+01, 1.6130331776708392e+01, 1.6441742871044735e+01, 1.6770628427712005e+01, 1.7122234853198016e+01, 1.7505307899899091e+01, 1.7936815806741905e+01, 1.8461160480857558e+01}, + {-1.8513928608263910e+01, -1.7990078266499342e+01, -1.7558985604821832e+01, -1.7176287776635139e+01, -1.6825031348357740e+01, -1.6496478147418177e+01, -1.6185386288902521e+01, -1.5888302208889046e+01, -1.5602799824404595e+01, -1.5327093154858311e+01, -1.5059819589095412e+01, -1.4799909769977225e+01, -1.4546505073756210e+01, -1.4298902920011114e+01, -1.4056519192842705e+01, -1.3818861627636300e+01, -1.3585510473849133e+01, -1.3356104131088610e+01, -1.3130328272714728e+01, -1.2907907470327904e+01, -1.2688598647247023e+01, -1.2472185893139361e+01, -1.2258476307546671e+01, -1.2047296632129509e+01, -1.1838490495223393e+01, -1.1631916137256281e+01, -1.1427444517781534e+01, -1.1224957728290695e+01, -1.1024347652217228e+01, -1.0825514826405534e+01, -1.0628367468022887e+01, -1.0432820638288694e+01, -1.0238795520089184e+01, -1.0046218790968188e+01, -9.8550220764490426e+00, -9.6651414713778827e+00, -9.4765171191542965e+00, -9.2890928404578474e+00, -9.1028158044838392e+00, -8.9176362368413074e+00, -8.7335071591960247e+00, -8.5503841565041103e+00, -8.3682251683108984e+00, -8.1869903011111198e+00, -8.0066416592005272e+00, -7.8271431918122021e+00, -7.6484605546357463e+00, -7.4705609840747460e+00, -7.2934131828156445e+00, -7.1169872154661693e+00, -6.9412544131792480e+00, -6.7661872863133015e+00, -6.5917594442957039e+00, -6.4179455219559527e+00, -6.2447211116812200e+00, -6.0720627008216166e+00, -5.8999476138372433e+00, -5.7283539587355410e+00, -5.5572605773966774e+00, -5.3866469994277919e+00, -5.2164933992246887e+00, -5.0467805559527736e+00, -4.8774898161882945e+00, -4.7086030589866992e+00, -4.5401026631678034e+00, -4.3719714766276327e+00, -4.2041927875047698e+00, -4.0367502970449332e+00, -3.8696280940217886e+00, -3.7028106305845436e+00, -3.5362826994142633e+00, -3.3700294120808700e+00, -3.2040361785018661e+00, -3.0382886874118746e+00, -2.8727728877593544e+00, -2.7074749709533479e+00, -2.5423813538889330e+00, -2.3774786626852964e+00, -2.2127537170750284e+00, -2.0481935153874455e+00, -1.8837852200725123e+00, -1.7195161437153161e+00, -1.5553737354940405e+00, -1.3913455680370777e+00, -1.2274193246372884e+00, -1.0635827867835286e+00, -8.9982382197139399e-01, -7.3613037175675000e-01, -5.7249044001699179e-01, -4.0889208138615224e-01, -2.4532338983095259e-01, -8.1772487335672980e-02, 8.1772487335672980e-02, 2.4532338983095259e-01, 4.0889208138615224e-01, 5.7249044001699179e-01, 7.3613037175675000e-01, 8.9982382197139399e-01, 1.0635827867835286e+00, 1.2274193246372884e+00, 1.3913455680370777e+00, 1.5553737354940405e+00, 1.7195161437153161e+00, 1.8837852200725123e+00, 2.0481935153874455e+00, 2.2127537170750284e+00, 2.3774786626852964e+00, 2.5423813538889330e+00, 2.7074749709533479e+00, 2.8727728877593544e+00, 3.0382886874118746e+00, 3.2040361785018661e+00, 3.3700294120808700e+00, 3.5362826994142633e+00, 3.7028106305845436e+00, 3.8696280940217886e+00, 4.0367502970449332e+00, 4.2041927875047698e+00, 4.3719714766276327e+00, 4.5401026631678034e+00, 4.7086030589866992e+00, 4.8774898161882945e+00, 5.0467805559527736e+00, 5.2164933992246887e+00, 5.3866469994277919e+00, 5.5572605773966774e+00, 5.7283539587355410e+00, 5.8999476138372433e+00, 6.0720627008216166e+00, 6.2447211116812200e+00, 6.4179455219559527e+00, 6.5917594442957039e+00, 6.7661872863133015e+00, 6.9412544131792480e+00, 7.1169872154661693e+00, 7.2934131828156445e+00, 7.4705609840747460e+00, 7.6484605546357463e+00, 7.8271431918122021e+00, 8.0066416592005272e+00, 8.1869903011111198e+00, 8.3682251683108984e+00, 8.5503841565041103e+00, 8.7335071591960247e+00, 8.9176362368413074e+00, 9.1028158044838392e+00, 9.2890928404578474e+00, 9.4765171191542965e+00, 9.6651414713778827e+00, 9.8550220764490426e+00, 1.0046218790968188e+01, 1.0238795520089184e+01, 1.0432820638288694e+01, 1.0628367468022887e+01, 1.0825514826405534e+01, 1.1024347652217228e+01, 1.1224957728290695e+01, 1.1427444517781534e+01, 1.1631916137256281e+01, 1.1838490495223393e+01, 1.2047296632129509e+01, 1.2258476307546671e+01, 1.2472185893139361e+01, 1.2688598647247023e+01, 1.2907907470327904e+01, 1.3130328272714728e+01, 1.3356104131088610e+01, 1.3585510473849133e+01, 1.3818861627636300e+01, 1.4056519192842705e+01, 1.4298902920011114e+01, 1.4546505073756210e+01, 1.4799909769977225e+01, 1.5059819589095412e+01, 1.5327093154858311e+01, 1.5602799824404595e+01, 1.5888302208889046e+01, 1.6185386288902521e+01, 1.6496478147418177e+01, 1.6825031348357740e+01, 1.7176287776635139e+01, 1.7558985604821832e+01, 1.7990078266499342e+01, 1.8513928608263910e+01}, + {-1.8566551582966934e+01, -1.8043192366212146e+01, -1.7612512215572043e+01, -1.7230187103675732e+01, -1.6879278311267964e+01, -1.6551055199152213e+01, -1.6240280376324659e+01, -1.5943503225988053e+01, -1.5658299727865778e+01, -1.5382885415641553e+01, -1.5115898831352473e+01, -1.4856271522065896e+01, -1.4603145590122086e+01, -1.4355819049893570e+01, -1.4113708281060786e+01, -1.3876321438029819e+01, -1.3643239129136898e+01, -1.3414100064890203e+01, -1.3188590190760220e+01, -1.2966434318726625e+01, -1.2747389586262109e+01, -1.2531240275314762e+01, -1.2317793659316827e+01, -1.2106876638246456e+01, -1.1898332985486029e+01, -1.1692021075138110e+01, -1.1487811990637235e+01, -1.1285587938886058e+01, -1.1085240911376399e+01, -1.0886671546608126e+01, -1.0689788157813780e+01, -1.0494505897387436e+01, -1.0300746035105149e+01, -1.0108435331643134e+01, -9.9175054923613413e+00, -9.7278926890529842e+00, -9.5395371395344313e+00, -9.3523827366910055e+00, -9.1663767199978832e+00, -8.9814693836739572e+00, -8.7976138165555611e+00, -8.6147656695390857e+00, -8.4328829470701354e+00, -8.2519258196777496e+00, -8.0718564549859924e+00, -7.8926388649980117e+00, -7.7142387677523603e+00, -7.5366234617083592e+00, -7.3597617114348806e+00, -7.1836236433617389e+00, -7.0081806505105702e+00, -6.8334053052569255e+00, -6.6592712792911071e+00, -6.4857532700449330e+00, -6.3128269329377309e+00, -6.1404688188693868e+00, -5.9686563164530524e+00, -5.7973675985364332e+00, -5.6265815726098278e+00, -5.4562778347421155e+00, -5.2864366267236216e+00, -5.1170387961280301e+00, -4.9480657590346588e+00, -4.7794994651782767e+00, -4.6113223653163988e+00, -4.4435173806242290e+00, -4.2760678739453368e+00, -4.1089576227421016e+00, -3.9421707936041384e+00, -3.7756919181855801e+00, -3.6095058704533836e+00, -3.4435978451389198e+00, -3.2779533372941430e+00, -3.1125581228617367e+00, -2.9473982401758851e+00, -2.7824599723168095e+00, -2.6177298302480856e+00, -2.4531945366709622e+00, -2.2888410105346408e+00, -2.1246563521456703e+00, -1.9606278288234207e+00, -1.7967428610519807e+00, -1.6329890090818511e+00, -1.4693539599375276e+00, -1.3058255147894620e+00, -1.1423915766510224e+00, -9.7904013836295944e-01, -8.1575927082952060e-01, -6.5253711147178228e-01, -4.8936185286498823e-01, -3.2622173152770212e-01, -1.6310501683142664e-01, -0.0000000000000000e+00, 1.6310501683142664e-01, 3.2622173152770212e-01, 4.8936185286498823e-01, 6.5253711147178228e-01, 8.1575927082952060e-01, 9.7904013836295944e-01, 1.1423915766510224e+00, 1.3058255147894620e+00, 1.4693539599375276e+00, 1.6329890090818511e+00, 1.7967428610519807e+00, 1.9606278288234207e+00, 2.1246563521456703e+00, 2.2888410105346408e+00, 2.4531945366709622e+00, 2.6177298302480856e+00, 2.7824599723168095e+00, 2.9473982401758851e+00, 3.1125581228617367e+00, 3.2779533372941430e+00, 3.4435978451389198e+00, 3.6095058704533836e+00, 3.7756919181855801e+00, 3.9421707936041384e+00, 4.1089576227421016e+00, 4.2760678739453368e+00, 4.4435173806242290e+00, 4.6113223653163988e+00, 4.7794994651782767e+00, 4.9480657590346588e+00, 5.1170387961280301e+00, 5.2864366267236216e+00, 5.4562778347421155e+00, 5.6265815726098278e+00, 5.7973675985364332e+00, 5.9686563164530524e+00, 6.1404688188693868e+00, 6.3128269329377309e+00, 6.4857532700449330e+00, 6.6592712792911071e+00, 6.8334053052569255e+00, 7.0081806505105702e+00, 7.1836236433617389e+00, 7.3597617114348806e+00, 7.5366234617083592e+00, 7.7142387677523603e+00, 7.8926388649980117e+00, 8.0718564549859924e+00, 8.2519258196777496e+00, 8.4328829470701354e+00, 8.6147656695390857e+00, 8.7976138165555611e+00, 8.9814693836739572e+00, 9.1663767199978832e+00, 9.3523827366910055e+00, 9.5395371395344313e+00, 9.7278926890529842e+00, 9.9175054923613413e+00, 1.0108435331643134e+01, 1.0300746035105149e+01, 1.0494505897387436e+01, 1.0689788157813780e+01, 1.0886671546608126e+01, 1.1085240911376399e+01, 1.1285587938886058e+01, 1.1487811990637235e+01, 1.1692021075138110e+01, 1.1898332985486029e+01, 1.2106876638246456e+01, 1.2317793659316827e+01, 1.2531240275314762e+01, 1.2747389586262109e+01, 1.2966434318726625e+01, 1.3188590190760220e+01, 1.3414100064890203e+01, 1.3643239129136898e+01, 1.3876321438029819e+01, 1.4113708281060786e+01, 1.4355819049893570e+01, 1.4603145590122086e+01, 1.4856271522065896e+01, 1.5115898831352473e+01, 1.5382885415641553e+01, 1.5658299727865778e+01, 1.5943503225988053e+01, 1.6240280376324659e+01, 1.6551055199152213e+01, 1.6879278311267964e+01, 1.7230187103675732e+01, 1.7612512215572043e+01, 1.8043192366212146e+01, 1.8566551582966934e+01}, + {-1.8619030592090468e+01, -1.8096159331273782e+01, -1.7665888990577489e+01, -1.7283934123310647e+01, -1.6933370634565016e+01, -1.6605475372599290e+01, -1.6295015412972358e+01, -1.5998543068078176e+01, -1.5713636367765231e+01, -1.5438512350731910e+01, -1.5171810705118517e+01, -1.4912463876600265e+01, -1.4659614689068135e+01, -1.4412561747929246e+01, -1.4170721925268760e+01, -1.3933603791786325e+01, -1.3700788312318828e+01, -1.3471914506172659e+01, -1.3246668589046763e+01, -1.3024775611596180e+01, -1.2805992923888546e+01, -1.2590104998712771e+01, -1.2376919282049462e+01, -1.2166262830933078e+01, -1.1957979562598471e+01, -1.1751927983683725e+01, -1.1547979300411118e+01, -1.1346015834038415e+01, -1.1145929683090303e+01, -1.0947621586721102e+01, -1.0750999953246895e+01, -1.0555980025269434e+01, -1.0362483158498314e+01, -1.0170436195792986e+01, -9.9797709214047838e+00, -9.7904235831297708e+00, -9.6023344722552224e+00, -9.4154475529222363e+00, -9.2297101339294976e+00, -9.0450725771408784e+00, -8.8614880375878489e+00, -8.6789122311192006e+00, -8.4973032260786319e+00, -8.3166212560112189e+00, -8.1368285508332487e+00, -7.9578891842622976e+00, -7.7797689356090070e+00, -7.6024351642886749e+00, -7.4258566956282692e+00, -7.2500037167290969e+00, -7.0748476813029546e+00, -6.9003612225343067e+00, -6.7265180731367256e+00, -6.5532929918714933e+00, -6.3806616958821749e+00, -6.2086007982735998e+00, -6.0370877504282516e+00, -5.8661007886095131e+00, -5.6956188844502709e+00, -5.5256216989684903e+00, -5.3560895397890276e+00, -5.1870033212841671e+00, -5.0183445273745217e+00, -4.8500951767577565e+00, -4.6822377903553614e+00, -4.5147553607879187e+00, -4.3476313237072048e+00, -4.1808495308294304e+00, -4.0143942245280941e+00, -3.8482500138575717e+00, -3.6824018518898707e+00, -3.5168350142570763e+00, -3.3515350788010423e+00, -3.1864879062399973e+00, -3.0216796217689894e+00, -2.8570965975176055e+00, -2.6927254357942609e+00, -2.5285529530516158e+00, -2.3645661645123681e+00, -2.2007522693989476e+00, -2.0370986367144122e+00, -1.8735927915252717e+00, -1.7102224017000158e+00, -1.5469752650598505e+00, -1.3838392969005895e+00, -1.2208025178467894e+00, -1.0578530420011503e+00, -8.9497906535386207e-01, -7.3216885441804769e-01, -5.6941073505871143e-01, -4.0669308148366978e-01, -2.4400430536582823e-01, -8.1332845066888051e-02, 8.1332845066888051e-02, 2.4400430536582823e-01, 4.0669308148366978e-01, 5.6941073505871143e-01, 7.3216885441804769e-01, 8.9497906535386207e-01, 1.0578530420011503e+00, 1.2208025178467894e+00, 1.3838392969005895e+00, 1.5469752650598505e+00, 1.7102224017000158e+00, 1.8735927915252717e+00, 2.0370986367144122e+00, 2.2007522693989476e+00, 2.3645661645123681e+00, 2.5285529530516158e+00, 2.6927254357942609e+00, 2.8570965975176055e+00, 3.0216796217689894e+00, 3.1864879062399973e+00, 3.3515350788010423e+00, 3.5168350142570763e+00, 3.6824018518898707e+00, 3.8482500138575717e+00, 4.0143942245280941e+00, 4.1808495308294304e+00, 4.3476313237072048e+00, 4.5147553607879187e+00, 4.6822377903553614e+00, 4.8500951767577565e+00, 5.0183445273745217e+00, 5.1870033212841671e+00, 5.3560895397890276e+00, 5.5256216989684903e+00, 5.6956188844502709e+00, 5.8661007886095131e+00, 6.0370877504282516e+00, 6.2086007982735998e+00, 6.3806616958821749e+00, 6.5532929918714933e+00, 6.7265180731367256e+00, 6.9003612225343067e+00, 7.0748476813029546e+00, 7.2500037167290969e+00, 7.4258566956282692e+00, 7.6024351642886749e+00, 7.7797689356090070e+00, 7.9578891842622976e+00, 8.1368285508332487e+00, 8.3166212560112189e+00, 8.4973032260786319e+00, 8.6789122311192006e+00, 8.8614880375878489e+00, 9.0450725771408784e+00, 9.2297101339294976e+00, 9.4154475529222363e+00, 9.6023344722552224e+00, 9.7904235831297708e+00, 9.9797709214047838e+00, 1.0170436195792986e+01, 1.0362483158498314e+01, 1.0555980025269434e+01, 1.0750999953246895e+01, 1.0947621586721102e+01, 1.1145929683090303e+01, 1.1346015834038415e+01, 1.1547979300411118e+01, 1.1751927983683725e+01, 1.1957979562598471e+01, 1.2166262830933078e+01, 1.2376919282049462e+01, 1.2590104998712771e+01, 1.2805992923888546e+01, 1.3024775611596180e+01, 1.3246668589046763e+01, 1.3471914506172659e+01, 1.3700788312318828e+01, 1.3933603791786325e+01, 1.4170721925268760e+01, 1.4412561747929246e+01, 1.4659614689068135e+01, 1.4912463876600265e+01, 1.5171810705118517e+01, 1.5438512350731910e+01, 1.5713636367765231e+01, 1.5998543068078176e+01, 1.6295015412972358e+01, 1.6605475372599290e+01, 1.6933370634565016e+01, 1.7283934123310647e+01, 1.7665888990577489e+01, 1.8096159331273782e+01, 1.8619030592090468e+01}, + {-1.8671366806690571e+01, -1.8148980370347783e+01, -1.7719117170958008e+01, -1.7337530106682756e+01, -1.6987309618003824e+01, -1.6659739995236801e+01, -1.6349592753466883e+01, -1.6053423116550778e+01, -1.5768811152035209e+01, -1.5493975394480826e+01, -1.5227556671125813e+01, -1.4968488320721917e+01, -1.4715913884228952e+01, -1.4469132554376165e+01, -1.4227561692518973e+01, -1.3990710282959036e+01, -1.3758159644687614e+01, -1.3529549103735965e+01, -1.3304565144176481e+01, -1.3082933053660961e+01, -1.2864410393317099e+01, -1.2648781825357542e+01, -1.2435854966991251e+01, -1.2225457031069224e+01, -1.2017432077505465e+01, -1.1811638744355296e+01, -1.1607948359555895e+01, -1.1406243357684700e+01, -1.1206415943294315e+01, -1.1008366955213159e+01, -1.0812004895879960e+01, -1.0617245097158223e+01, -1.0424008999756163e+01, -1.0232223527789033e+01, -1.0041820543476462e+01, -9.8527363696957284e+00, -9.6649113702822387e+00, -9.4782895797065567e+00, -9.2928183751587881e+00, -9.1084481852078358e+00, -8.9251322301305365e+00, -8.7428262897666009e+00, -8.5614884953828341e+00, -8.3810791425501474e+00, -8.2015605224698938e+00, -8.0228967695483639e+00, -7.8450537233223443e+00, -7.6679988030953385e+00, -7.4917008938611840e+00, -7.3161302422763823e+00, -7.1412583615998901e+00, -6.9670579446537078e+00, -6.7935027839732776e+00, -6.6205676984161617e+00, -6.4482284655834805e+00, -6.2764617594829843e+00, -6.1052450929273041e+00, -5.9345567642172057e+00, -5.7643758077087970e+00, -5.5946819479066203e+00, -5.4254555567622882e+00, -5.2566776138914113e+00, -5.0883296694508156e+00, -4.9203938094437563e+00, -4.7528526232436477e+00, -4.5856891731470037e+00, -4.4188869657842096e+00, -4.2524299252326587e+00, -4.0863023676909851e+00, -3.9204889775857690e+00, -3.7549747849933839e+00, -3.5897451442697546e+00, -3.4247857137898574e+00, -3.2600824367068570e+00, -3.0956215226480941e+00, -2.9313894302716164e+00, -2.7673728506128410e+00, -2.6035586911561817e+00, -2.4399340605712174e+00, -2.2764862540572279e+00, -2.1132027392437367e+00, -1.9500711425981514e+00, -1.7870792362946351e+00, -1.6242149255011178e+00, -1.4614662360438109e+00, -1.2988213024107587e+00, -1.1362683560579210e+00, -9.7379571398297626e-01, -8.1139176753353270e-01, -6.4904497141773709e-01, -4.8674383288637452e-01, -3.2447690105649102e-01, -1.6223275634733261e-01, -0.0000000000000000e+00, 1.6223275634733261e-01, 3.2447690105649102e-01, 4.8674383288637452e-01, 6.4904497141773709e-01, 8.1139176753353270e-01, 9.7379571398297626e-01, 1.1362683560579210e+00, 1.2988213024107587e+00, 1.4614662360438109e+00, 1.6242149255011178e+00, 1.7870792362946351e+00, 1.9500711425981514e+00, 2.1132027392437367e+00, 2.2764862540572279e+00, 2.4399340605712174e+00, 2.6035586911561817e+00, 2.7673728506128410e+00, 2.9313894302716164e+00, 3.0956215226480941e+00, 3.2600824367068570e+00, 3.4247857137898574e+00, 3.5897451442697546e+00, 3.7549747849933839e+00, 3.9204889775857690e+00, 4.0863023676909851e+00, 4.2524299252326587e+00, 4.4188869657842096e+00, 4.5856891731470037e+00, 4.7528526232436477e+00, 4.9203938094437563e+00, 5.0883296694508156e+00, 5.2566776138914113e+00, 5.4254555567622882e+00, 5.5946819479066203e+00, 5.7643758077087970e+00, 5.9345567642172057e+00, 6.1052450929273041e+00, 6.2764617594829843e+00, 6.4482284655834805e+00, 6.6205676984161617e+00, 6.7935027839732776e+00, 6.9670579446537078e+00, 7.1412583615998901e+00, 7.3161302422763823e+00, 7.4917008938611840e+00, 7.6679988030953385e+00, 7.8450537233223443e+00, 8.0228967695483639e+00, 8.2015605224698938e+00, 8.3810791425501474e+00, 8.5614884953828341e+00, 8.7428262897666009e+00, 8.9251322301305365e+00, 9.1084481852078358e+00, 9.2928183751587881e+00, 9.4782895797065567e+00, 9.6649113702822387e+00, 9.8527363696957284e+00, 1.0041820543476462e+01, 1.0232223527789033e+01, 1.0424008999756163e+01, 1.0617245097158223e+01, 1.0812004895879960e+01, 1.1008366955213159e+01, 1.1206415943294315e+01, 1.1406243357684700e+01, 1.1607948359555895e+01, 1.1811638744355296e+01, 1.2017432077505465e+01, 1.2225457031069224e+01, 1.2435854966991251e+01, 1.2648781825357542e+01, 1.2864410393317099e+01, 1.3082933053660961e+01, 1.3304565144176481e+01, 1.3529549103735965e+01, 1.3758159644687614e+01, 1.3990710282959036e+01, 1.4227561692518973e+01, 1.4469132554376165e+01, 1.4715913884228952e+01, 1.4968488320721917e+01, 1.5227556671125813e+01, 1.5493975394480826e+01, 1.5768811152035209e+01, 1.6053423116550778e+01, 1.6349592753466883e+01, 1.6659739995236801e+01, 1.6987309618003824e+01, 1.7337530106682756e+01, 1.7719117170958008e+01, 1.8148980370347783e+01, 1.8671366806690571e+01}, + {-1.8723561382058008e+01, -1.8201656675685278e+01, -1.7772197980856198e+01, -1.7390976307430105e+01, -1.7041096543327139e+01, -1.6713850376034177e+01, -1.6404013733432148e+01, -1.6108144733313441e+01, -1.5823825468638194e+01, -1.5549275960782586e+01, -1.5283138169159214e+01, -1.5024346320130698e+01, -1.4772044667297957e+01, -1.4525532987045759e+01, -1.4284229126904924e+01, -1.4047642482122557e+01, -1.3815354723529373e+01, -1.3587005481836711e+01, -1.3362281507661821e+01, -1.3140908323999378e+01, -1.2922643701525621e+01, -1.2707272490482195e+01, -1.2494602478007950e+01, -1.2284461031551617e+01, -1.2076692352553557e+01, -1.1871155209388238e+01, -1.1667721050654935e+01, -1.1466272423235269e+01, -1.1266701636724759e+01, -1.1068909628665612e+01, -1.0872804994678496e+01, -1.0678303154963148e+01, -1.0485325634312177e+01, -1.0293799437190248e+01, -1.0103656502883585e+01, -9.9148332284509078e+00, -9.7272700493753241e+00, -9.5409110695534167e+00, -9.3557037336580802e+00, -9.1715985360473766e+00, -8.9885487613184782e+00, -8.8065102523660030e+00, -8.6254412024311282e+00, -8.4453019681474064e+00, -8.2660549010220361e+00, -8.0876641951531028e+00, -7.9100957492873887e+00, -7.7333170415796193e+00, -7.5572970156311445e+00, -7.3820059765703627e+00, -7.2074154960945611e+00, -7.0334983255273515e+00, -6.8602283160613764e+00, -6.6875803454554488e+00, -6.5155302505411381e+00, -6.3440547649682282e+00, -6.1731314616830320e+00, -6.0027386996898384e+00, -5.8328555746948121e+00, -5.6634618732746507e+00, -5.4945380302499895e+00, -5.3260650889766197e+00, -5.1580246642968088e+00, -4.9903989079186992e+00, -4.8231704760145977e+00, -4.6563224988490806e+00, -4.4898385522658026e+00, -4.3237026308777766e+00, -4.1578991228200994e+00, -3.9924127859367369e+00, -3.8272287252842805e+00, -3.6623323718456740e+00, -3.4977094623559837e+00, -3.3333460201503651e+00, -3.1692283369516736e+00, -3.0053429555216815e+00, -2.8416766531057553e+00, -2.6782164256060947e+00, -2.5149494724234098e+00, -2.3518631819111540e+00, -2.1889451173902774e+00, -2.0261830036759103e+00, -1.8635647140704730e+00, -1.7010782577804868e+00, -1.5387117677168360e+00, -1.3764534886404416e+00, -1.2142917656172734e+00, -1.0522150327483684e+00, -8.9021180214204398e-01, -7.2827065309683536e-01, -5.6638022146482336e-01, -4.0452918916600705e-01, -2.4270627382517243e-01, -8.0900218503372048e-02, 8.0900218503372048e-02, 2.4270627382517243e-01, 4.0452918916600705e-01, 5.6638022146482336e-01, 7.2827065309683536e-01, 8.9021180214204398e-01, 1.0522150327483684e+00, 1.2142917656172734e+00, 1.3764534886404416e+00, 1.5387117677168360e+00, 1.7010782577804868e+00, 1.8635647140704730e+00, 2.0261830036759103e+00, 2.1889451173902774e+00, 2.3518631819111540e+00, 2.5149494724234098e+00, 2.6782164256060947e+00, 2.8416766531057553e+00, 3.0053429555216815e+00, 3.1692283369516736e+00, 3.3333460201503651e+00, 3.4977094623559837e+00, 3.6623323718456740e+00, 3.8272287252842805e+00, 3.9924127859367369e+00, 4.1578991228200994e+00, 4.3237026308777766e+00, 4.4898385522658026e+00, 4.6563224988490806e+00, 4.8231704760145977e+00, 4.9903989079186992e+00, 5.1580246642968088e+00, 5.3260650889766197e+00, 5.4945380302499895e+00, 5.6634618732746507e+00, 5.8328555746948121e+00, 6.0027386996898384e+00, 6.1731314616830320e+00, 6.3440547649682282e+00, 6.5155302505411381e+00, 6.6875803454554488e+00, 6.8602283160613764e+00, 7.0334983255273515e+00, 7.2074154960945611e+00, 7.3820059765703627e+00, 7.5572970156311445e+00, 7.7333170415796193e+00, 7.9100957492873887e+00, 8.0876641951531028e+00, 8.2660549010220361e+00, 8.4453019681474064e+00, 8.6254412024311282e+00, 8.8065102523660030e+00, 8.9885487613184782e+00, 9.1715985360473766e+00, 9.3557037336580802e+00, 9.5409110695534167e+00, 9.7272700493753241e+00, 9.9148332284509078e+00, 1.0103656502883585e+01, 1.0293799437190248e+01, 1.0485325634312177e+01, 1.0678303154963148e+01, 1.0872804994678496e+01, 1.1068909628665612e+01, 1.1266701636724759e+01, 1.1466272423235269e+01, 1.1667721050654935e+01, 1.1871155209388238e+01, 1.2076692352553557e+01, 1.2284461031551617e+01, 1.2494602478007950e+01, 1.2707272490482195e+01, 1.2922643701525621e+01, 1.3140908323999378e+01, 1.3362281507661821e+01, 1.3587005481836711e+01, 1.3815354723529373e+01, 1.4047642482122557e+01, 1.4284229126904924e+01, 1.4525532987045759e+01, 1.4772044667297957e+01, 1.5024346320130698e+01, 1.5283138169159214e+01, 1.5549275960782586e+01, 1.5823825468638194e+01, 1.6108144733313441e+01, 1.6404013733432148e+01, 1.6713850376034177e+01, 1.7041096543327139e+01, 1.7390976307430105e+01, 1.7772197980856198e+01, 1.8201656675685278e+01, 1.8723561382058008e+01}, + {-1.8775615458013544e+01, -1.8254189423434781e+01, -1.7825132627760091e+01, -1.7444273962020645e+01, -1.7094732674611997e+01, -1.6767807805810907e+01, -1.6458279669864240e+01, -1.6162709261170946e+01, -1.5878680685959477e+01, -1.5604415443478599e+01, -1.5338556618472303e+01, -1.5080039319512867e+01, -1.4828008508467775e+01, -1.4581764541755678e+01, -1.4340725750026818e+01, -1.4104401936851414e+01, -1.3872375122615423e+01, -1.3644285240693469e+01, -1.3419819306444866e+01, -1.3198703076577427e+01, -1.2980694529827234e+01, -1.2765578703092004e+01, -1.2553163552163017e+01, -1.2343276597888334e+01, -1.2135762182101830e+01, -1.1930479202418702e+01, -1.1727299227066995e+01, -1.1526104914236369e+01, -1.1326788677599657e+01, -1.1129251552471963e+01, -1.0933402226734774e+01, -1.0739156208018326e+01, -1.0546435104305445e+01, -1.0355165999524157e+01, -1.0165280909146327e+01, -9.9767163035334772e+00, -9.7894126889375794e+00, -9.6033142377998999e+00, -9.4183684613901413e+00, -9.2345259189629125e+00, -9.0517399585345863e+00, -8.8699664851432551e+00, -8.6891637530810133e+00, -8.5092921791069820e+00, -8.3303141740818543e+00, -8.1521939908263850e+00, -7.9748975863098721e+00, -7.7983924965309503e+00, -7.6226477226697984e+00, -7.4476336272751640e+00, -7.2733218394067363e+00, -7.0996851677878805e+00, -6.9266975211391140e+00, -6.7543338349621100e+00, -6.5825700041298303e+00, -6.4113828207126948e+00, -6.2407499165352709e+00, -6.0706497100141474e+00, -5.9010613568767107e+00, -5.7319647044035085e+00, -5.5633402488744599e+00, -5.3951690959323528e+00, -5.2274329236061510e+00, -5.0601139477624058e+00, -4.8931948897757946e+00, -4.7266589462300219e+00, -4.5604897604781494e+00, -4.3946713959074097e+00, -4.2291883107676789e+00, -4.0640253344354704e+00, -3.8991676449965649e+00, -3.7346007480405388e+00, -3.5703104565694619e+00, -3.4062828719311762e+00, -3.2425043656948236e+00, -3.0789615623928461e+00, -2.9156413230595541e+00, -2.7525307295016344e+00, -2.5896170692407368e+00, -2.4268878210725524e+00, -2.2643306411906372e+00, -2.1019333498267070e+00, -1.9396839183622288e+00, -1.7775704568689277e+00, -1.6155812020383324e+00, -1.4537045054627018e+00, -1.2919288222316836e+00, -1.1302426998108011e+00, -9.6863476716944097e-01, -8.0709372412735814e-01, -6.4560833088991310e-01, -4.8416739774326256e-01, -3.2275977488157320e-01, -1.6137434233903589e-01, -0.0000000000000000e+00, 1.6137434233903589e-01, 3.2275977488157320e-01, 4.8416739774326256e-01, 6.4560833088991310e-01, 8.0709372412735814e-01, 9.6863476716944097e-01, 1.1302426998108011e+00, 1.2919288222316836e+00, 1.4537045054627018e+00, 1.6155812020383324e+00, 1.7775704568689277e+00, 1.9396839183622288e+00, 2.1019333498267070e+00, 2.2643306411906372e+00, 2.4268878210725524e+00, 2.5896170692407368e+00, 2.7525307295016344e+00, 2.9156413230595541e+00, 3.0789615623928461e+00, 3.2425043656948236e+00, 3.4062828719311762e+00, 3.5703104565694619e+00, 3.7346007480405388e+00, 3.8991676449965649e+00, 4.0640253344354704e+00, 4.2291883107676789e+00, 4.3946713959074097e+00, 4.5604897604781494e+00, 4.7266589462300219e+00, 4.8931948897757946e+00, 5.0601139477624058e+00, 5.2274329236061510e+00, 5.3951690959323528e+00, 5.5633402488744599e+00, 5.7319647044035085e+00, 5.9010613568767107e+00, 6.0706497100141474e+00, 6.2407499165352709e+00, 6.4113828207126948e+00, 6.5825700041298303e+00, 6.7543338349621100e+00, 6.9266975211391140e+00, 7.0996851677878805e+00, 7.2733218394067363e+00, 7.4476336272751640e+00, 7.6226477226697984e+00, 7.7983924965309503e+00, 7.9748975863098721e+00, 8.1521939908263850e+00, 8.3303141740818543e+00, 8.5092921791069820e+00, 8.6891637530810133e+00, 8.8699664851432551e+00, 9.0517399585345863e+00, 9.2345259189629125e+00, 9.4183684613901413e+00, 9.6033142377998999e+00, 9.7894126889375794e+00, 9.9767163035334772e+00, 1.0165280909146327e+01, 1.0355165999524157e+01, 1.0546435104305445e+01, 1.0739156208018326e+01, 1.0933402226734774e+01, 1.1129251552471963e+01, 1.1326788677599657e+01, 1.1526104914236369e+01, 1.1727299227066995e+01, 1.1930479202418702e+01, 1.2135762182101830e+01, 1.2343276597888334e+01, 1.2553163552163017e+01, 1.2765578703092004e+01, 1.2980694529827234e+01, 1.3198703076577427e+01, 1.3419819306444866e+01, 1.3644285240693469e+01, 1.3872375122615423e+01, 1.4104401936851414e+01, 1.4340725750026818e+01, 1.4581764541755678e+01, 1.4828008508467775e+01, 1.5080039319512867e+01, 1.5338556618472303e+01, 1.5604415443478599e+01, 1.5878680685959477e+01, 1.6162709261170946e+01, 1.6458279669864240e+01, 1.6767807805810907e+01, 1.7094732674611997e+01, 1.7444273962020645e+01, 1.7825132627760091e+01, 1.8254189423434781e+01, 1.8775615458013544e+01}, + {-1.8827530159196098e+01, -1.8306579773944520e+01, -1.7877922302817918e+01, -1.7497424290078804e+01, -1.7148219258607661e+01, -1.6821613557585714e+01, -1.6512391861491736e+01, -1.6217118024196811e+01, -1.5933378153189908e+01, -1.5659395216751500e+01, -1.5393813418192966e+01, -1.5135568742958350e+01, -1.4883806856859362e+01, -1.4637828692771006e+01, -1.4397053061445078e+01, -1.4160990172186152e+01, -1.3929222392681286e+01, -1.3701389956978932e+01, -1.3477180143402940e+01, -1.3256318940768097e+01, -1.3038564534403923e+01, -1.2823702146512529e+01, -1.2611539900280661e+01, -1.2401905468777167e+01, -1.2194643333116042e+01, -1.1989612519093924e+01, -1.1786684713553210e+01, -1.1585742685014308e+01, -1.1386678950280542e+01, -1.1189394641517911e+01, -1.0993798537966583e+01, -1.0799806233800744e+01, -1.0607339419318674e+01, -1.0416325257045436e+01, -1.0226695837777637e+01, -1.0038387704321417e+01, -9.8513414328396713e+00, -9.6655012634583866e+00, -9.4808147731799934e+00, -9.2972325852854905e+00, -9.1147081103323924e+00, -8.9331973146145547e+00, -8.7526585125759730e+00, -8.5730521801893929e+00, -8.3943407867426210e+00, -8.2164886428367048e+00, -8.0394617627036364e+00, -7.8632277392072103e+00, -7.6877556301072998e+00, -7.5130158543520213e+00, -7.3389800973191823e+00, -7.1656212240628339e+00, -6.9929131997360230e+00, -6.8208310164601347e+00, -6.6493506259970188e+00, -6.4784488776542828e+00, -6.3081034609187254e+00, -6.1382928523689460e+00, -5.9689962664672880e+00, -5.8001936098740767e+00, -5.6318654389648133e+00, -5.4639929202639941e+00, -5.2965577935384172e+00, -5.1295423373184992e+00, -4.9629293366389069e+00, -4.7967020528099553e+00, -4.6308441950490966e+00, -4.4653398938177720e+00, -4.3001736757230296e+00, -4.1353304398559789e+00, -3.9707954354504480e+00, -3.8065542407552790e+00, -3.6425927430227989e+00, -3.4788971195240692e+00, -3.3154538195088263e+00, -3.1522495470345691e+00, -2.9892712445951148e+00, -2.8265060774842699e+00, -2.6639414188349808e+00, -2.5015648352786735e+00, -2.3393640731732996e+00, -2.1773270453521110e+00, -2.0154418183483078e+00, -1.8536966000534938e+00, -1.6920797277704067e+00, -1.5305796566226446e+00, -1.3691849482861076e+00, -1.2078842600086817e+00, -1.0466663338862598e+00, -8.8551998636459661e-01, -7.2443409793770541e-01, -5.6339760301455488e-01, -4.0239947992671032e-01, -2.4142874105030510e-01, -8.0474423016328678e-02, 8.0474423016328678e-02, 2.4142874105030510e-01, 4.0239947992671032e-01, 5.6339760301455488e-01, 7.2443409793770541e-01, 8.8551998636459661e-01, 1.0466663338862598e+00, 1.2078842600086817e+00, 1.3691849482861076e+00, 1.5305796566226446e+00, 1.6920797277704067e+00, 1.8536966000534938e+00, 2.0154418183483078e+00, 2.1773270453521110e+00, 2.3393640731732996e+00, 2.5015648352786735e+00, 2.6639414188349808e+00, 2.8265060774842699e+00, 2.9892712445951148e+00, 3.1522495470345691e+00, 3.3154538195088263e+00, 3.4788971195240692e+00, 3.6425927430227989e+00, 3.8065542407552790e+00, 3.9707954354504480e+00, 4.1353304398559789e+00, 4.3001736757230296e+00, 4.4653398938177720e+00, 4.6308441950490966e+00, 4.7967020528099553e+00, 4.9629293366389069e+00, 5.1295423373184992e+00, 5.2965577935384172e+00, 5.4639929202639941e+00, 5.6318654389648133e+00, 5.8001936098740767e+00, 5.9689962664672880e+00, 6.1382928523689460e+00, 6.3081034609187254e+00, 6.4784488776542828e+00, 6.6493506259970188e+00, 6.8208310164601347e+00, 6.9929131997360230e+00, 7.1656212240628339e+00, 7.3389800973191823e+00, 7.5130158543520213e+00, 7.6877556301072998e+00, 7.8632277392072103e+00, 8.0394617627036364e+00, 8.2164886428367048e+00, 8.3943407867426210e+00, 8.5730521801893929e+00, 8.7526585125759730e+00, 8.9331973146145547e+00, 9.1147081103323924e+00, 9.2972325852854905e+00, 9.4808147731799934e+00, 9.6655012634583866e+00, 9.8513414328396713e+00, 1.0038387704321417e+01, 1.0226695837777637e+01, 1.0416325257045436e+01, 1.0607339419318674e+01, 1.0799806233800744e+01, 1.0993798537966583e+01, 1.1189394641517911e+01, 1.1386678950280542e+01, 1.1585742685014308e+01, 1.1786684713553210e+01, 1.1989612519093924e+01, 1.2194643333116042e+01, 1.2401905468777167e+01, 1.2611539900280661e+01, 1.2823702146512529e+01, 1.3038564534403923e+01, 1.3256318940768097e+01, 1.3477180143402940e+01, 1.3701389956978932e+01, 1.3929222392681286e+01, 1.4160990172186152e+01, 1.4397053061445078e+01, 1.4637828692771006e+01, 1.4883806856859362e+01, 1.5135568742958350e+01, 1.5393813418192966e+01, 1.5659395216751500e+01, 1.5933378153189908e+01, 1.6217118024196811e+01, 1.6512391861491736e+01, 1.6821613557585714e+01, 1.7148219258607661e+01, 1.7497424290078804e+01, 1.7877922302817918e+01, 1.8306579773944520e+01, 1.8827530159196098e+01}, + {-1.8879306595344101e+01, -1.8358828872057543e+01, -1.7930568181145354e+01, -1.7550428494704086e+01, -1.7201557525065336e+01, -1.6875268886917173e+01, -1.6566351589127169e+01, -1.6271372328095570e+01, -1.5987919200699100e+01, -1.5714216635509363e+01, -1.5448909947718773e+01, -1.5190935994367434e+01, -1.4939441140940190e+01, -1.4693726893234164e+01, -1.4453212539122219e+01, -1.4217408691087410e+01, -1.3985898061893202e+01, -1.3758321184299211e+01, -1.3534365597840969e+01, -1.3313757521857125e+01, -1.3096255346825995e+01, -1.2881644478923162e+01, -1.2669733207493820e+01, -1.2460349356668459e+01, -1.2253337545746717e+01, -1.2048556927665979e+01, -1.1845879306886999e+01, -1.1645187561301928e+01, -1.1446374309916036e+01, -1.1249340780842516e+01, -1.1053995843796514e+01, -1.0860255178628208e+01, -1.0668040557095399e+01, -1.0477279219472964e+01, -1.0287903331040779e+01, -1.0099849506211216e+01, -9.9130583902203586e+00, -9.7274742900396252e+00, -9.5430448475612568e+00, -9.3597207492442038e+00, -9.1774554673313418e+00, -8.9962050285074913e+00, -8.8159278064930948e+00, -8.6365843355868694e+00, -8.4581371426023590e+00, -8.2805505950043532e+00, -8.1037907633543647e+00, -7.9278252964301190e+00, -7.7526233076005129e+00, -7.5781552712214886e+00, -7.4043929279751541e+00, -7.2313091982087343e+00, -7.0588781024451404e+00, -6.8870746883362148e+00, -6.7158749634153345e+00, -6.5452558330803203e+00, -6.3751950433020319e+00, -6.2056711276101213e+00, -6.0366633579564608e+00, -5.8681516990995659e+00, -5.7001167661909662e+00, -5.5325397852775344e+00, -5.3654025564628540e+00, -5.1986874194964612e+00, -5.0323772215824860e+00, -4.8664552872193818e+00, -4.7009053899003126e+00, -4.5357117255196737e+00, -4.3708588873453733e+00, -4.2063318424291563e+00, -4.0421159093385528e+00, -3.8781967371040955e+00, -3.7145602852845432e+00, -3.5511928050609516e+00, -3.3880808212776983e+00, -3.2252111153551550e+00, -3.0625707090045471e+00, -2.9001468486808863e+00, -2.7379269907145933e+00, -2.5758987870667562e+00, -2.4140500716568205e+00, -2.2523688472150090e+00, -2.0908432726148978e+00, -1.9294616506444018e+00, -1.7682124161759520e+00, -1.6070841246989318e+00, -1.4460654411794531e+00, -1.2851451292143858e+00, -1.1243120404481430e+00, -9.6355510422216051e-01, -8.0286331742823902e-01, -6.4222573453801035e-01, -4.8163145778170013e-01, -3.2106962745015089e-01, -1.6052941229469772e-01, -0.0000000000000000e+00, 1.6052941229469772e-01, 3.2106962745015089e-01, 4.8163145778170013e-01, 6.4222573453801035e-01, 8.0286331742823902e-01, 9.6355510422216051e-01, 1.1243120404481430e+00, 1.2851451292143858e+00, 1.4460654411794531e+00, 1.6070841246989318e+00, 1.7682124161759520e+00, 1.9294616506444018e+00, 2.0908432726148978e+00, 2.2523688472150090e+00, 2.4140500716568205e+00, 2.5758987870667562e+00, 2.7379269907145933e+00, 2.9001468486808863e+00, 3.0625707090045471e+00, 3.2252111153551550e+00, 3.3880808212776983e+00, 3.5511928050609516e+00, 3.7145602852845432e+00, 3.8781967371040955e+00, 4.0421159093385528e+00, 4.2063318424291563e+00, 4.3708588873453733e+00, 4.5357117255196737e+00, 4.7009053899003126e+00, 4.8664552872193818e+00, 5.0323772215824860e+00, 5.1986874194964612e+00, 5.3654025564628540e+00, 5.5325397852775344e+00, 5.7001167661909662e+00, 5.8681516990995659e+00, 6.0366633579564608e+00, 6.2056711276101213e+00, 6.3751950433020319e+00, 6.5452558330803203e+00, 6.7158749634153345e+00, 6.8870746883362148e+00, 7.0588781024451404e+00, 7.2313091982087343e+00, 7.4043929279751541e+00, 7.5781552712214886e+00, 7.7526233076005129e+00, 7.9278252964301190e+00, 8.1037907633543647e+00, 8.2805505950043532e+00, 8.4581371426023590e+00, 8.6365843355868694e+00, 8.8159278064930948e+00, 8.9962050285074913e+00, 9.1774554673313418e+00, 9.3597207492442038e+00, 9.5430448475612568e+00, 9.7274742900396252e+00, 9.9130583902203586e+00, 1.0099849506211216e+01, 1.0287903331040779e+01, 1.0477279219472964e+01, 1.0668040557095399e+01, 1.0860255178628208e+01, 1.1053995843796514e+01, 1.1249340780842516e+01, 1.1446374309916036e+01, 1.1645187561301928e+01, 1.1845879306886999e+01, 1.2048556927665979e+01, 1.2253337545746717e+01, 1.2460349356668459e+01, 1.2669733207493820e+01, 1.2881644478923162e+01, 1.3096255346825995e+01, 1.3313757521857125e+01, 1.3534365597840969e+01, 1.3758321184299211e+01, 1.3985898061893202e+01, 1.4217408691087410e+01, 1.4453212539122219e+01, 1.4693726893234164e+01, 1.4939441140940190e+01, 1.5190935994367434e+01, 1.5448909947718773e+01, 1.5714216635509363e+01, 1.5987919200699100e+01, 1.6271372328095570e+01, 1.6566351589127169e+01, 1.6875268886917173e+01, 1.7201557525065336e+01, 1.7550428494704086e+01, 1.7930568181145354e+01, 1.8358828872057543e+01, 1.8879306595344101e+01}, + {-1.8930945861570141e+01, -1.8410937847399730e+01, -1.7983071422125320e+01, -1.7603287762782053e+01, -1.7254748687059873e+01, -1.6928775032235986e+01, -1.6620160116009828e+01, -1.6325473460556140e+01, -1.6042305140399389e+01, -1.5768881035760351e+01, -1.5503847567102451e+01, -1.5246142457847222e+01, -1.4994912768931876e+01, -1.4749460575583919e+01, -1.4509205639853443e+01, -1.4273658974878348e+01, -1.4042403636302666e+01, -1.3815080453660714e+01, -1.3591377225971019e+01, -1.3371020401535507e+01, -1.3153768574557885e+01, -1.2939407333876543e+01, -1.2727745133777605e+01, -1.2518609948312903e+01, -1.2311846533891678e+01, -1.2107314169569506e+01, -1.1904884776447382e+01, -1.1704441340847984e+01, -1.1505876583067728e+01, -1.1309091826281094e+01, -1.1113996029812375e+01, -1.0920504958337819e+01, -1.0728540464237067e+01, -1.0538029864706095e+01, -1.0348905398685391e+01, -1.0161103751374336e+01, -9.9745656362640407e+00, -9.7892354263520396e+00, -9.6050608275979510e+00, -9.4219925888112019e+00, -9.2399842430857984e+00, -9.0589918766548454e+00, -8.8789739216625421e+00, -8.6998909698693474e+00, -8.5217056047373152e+00, -8.3443822497033171e+00, -8.1678870307509044e+00, -7.9921876516470487e+00, -7.8172532804264092e+00, -7.6430544458895735e+00, -7.4695629430384693e+00, -7.2967517465063425e+00, -7.1245949311547765e+00, -6.9530675991094046e+00, -6.7821458125915717e+00, -6.6118065319773942e+00, -6.4420275585800111e+00, -6.2727874817069420e+00, -6.1040656295934008e+00, -5.9358420238552689e+00, -5.7680973371429536e+00, -5.6008128537104387e+00, -5.4339704326429148e+00, -5.2675524735120289e+00, -5.1015418842505529e+00, -4.9359220510583919e+00, -4.7706768101697055e+00, -4.6057904213268381e+00, -4.4412475428209168e+00, -4.2770332079715754e+00, -4.1131328029295950e+00, -3.9495320456963339e+00, -3.7862169662628560e+00, -3.6231738877798154e+00, -3.4603894086764226e+00, -3.2978503856533741e+00, -3.1355439174805326e+00, -2.9734573295354325e+00, -2.8115781590234925e+00, -2.6498941408250944e+00, -2.4883931939185926e+00, -2.3270634083318020e+00, -2.1658930325776748e+00, -2.0048704615326960e+00, -1.8439842247190983e+00, -1.6832229749542722e+00, -1.5225754773327997e+00, -1.3620305985083838e+00, -1.2015772962445594e+00, -1.0412046092045326e+00, -8.8090164695175288e-01, -7.2065758013394154e-01, -5.6046163082425071e-01, -4.0030306299404111e-01, -2.4017117309244904e-01, -8.0055280708449292e-02, 8.0055280708449292e-02, 2.4017117309244904e-01, 4.0030306299404111e-01, 5.6046163082425071e-01, 7.2065758013394154e-01, 8.8090164695175288e-01, 1.0412046092045326e+00, 1.2015772962445594e+00, 1.3620305985083838e+00, 1.5225754773327997e+00, 1.6832229749542722e+00, 1.8439842247190983e+00, 2.0048704615326960e+00, 2.1658930325776748e+00, 2.3270634083318020e+00, 2.4883931939185926e+00, 2.6498941408250944e+00, 2.8115781590234925e+00, 2.9734573295354325e+00, 3.1355439174805326e+00, 3.2978503856533741e+00, 3.4603894086764226e+00, 3.6231738877798154e+00, 3.7862169662628560e+00, 3.9495320456963339e+00, 4.1131328029295950e+00, 4.2770332079715754e+00, 4.4412475428209168e+00, 4.6057904213268381e+00, 4.7706768101697055e+00, 4.9359220510583919e+00, 5.1015418842505529e+00, 5.2675524735120289e+00, 5.4339704326429148e+00, 5.6008128537104387e+00, 5.7680973371429536e+00, 5.9358420238552689e+00, 6.1040656295934008e+00, 6.2727874817069420e+00, 6.4420275585800111e+00, 6.6118065319773942e+00, 6.7821458125915717e+00, 6.9530675991094046e+00, 7.1245949311547765e+00, 7.2967517465063425e+00, 7.4695629430384693e+00, 7.6430544458895735e+00, 7.8172532804264092e+00, 7.9921876516470487e+00, 8.1678870307509044e+00, 8.3443822497033171e+00, 8.5217056047373152e+00, 8.6998909698693474e+00, 8.8789739216625421e+00, 9.0589918766548454e+00, 9.2399842430857984e+00, 9.4219925888112019e+00, 9.6050608275979510e+00, 9.7892354263520396e+00, 9.9745656362640407e+00, 1.0161103751374336e+01, 1.0348905398685391e+01, 1.0538029864706095e+01, 1.0728540464237067e+01, 1.0920504958337819e+01, 1.1113996029812375e+01, 1.1309091826281094e+01, 1.1505876583067728e+01, 1.1704441340847984e+01, 1.1904884776447382e+01, 1.2107314169569506e+01, 1.2311846533891678e+01, 1.2518609948312903e+01, 1.2727745133777605e+01, 1.2939407333876543e+01, 1.3153768574557885e+01, 1.3371020401535507e+01, 1.3591377225971019e+01, 1.3815080453660714e+01, 1.4042403636302666e+01, 1.4273658974878348e+01, 1.4509205639853443e+01, 1.4749460575583919e+01, 1.4994912768931876e+01, 1.5246142457847222e+01, 1.5503847567102451e+01, 1.5768881035760351e+01, 1.6042305140399389e+01, 1.6325473460556140e+01, 1.6620160116009828e+01, 1.6928775032235986e+01, 1.7254748687059873e+01, 1.7603287762782053e+01, 1.7983071422125320e+01, 1.8410937847399730e+01, 1.8930945861570141e+01}, + {-1.8982449038629166e+01, -1.8462907814661030e+01, -1.8035433169700678e+01, -1.7656003265287762e+01, -1.7307793941303686e+01, -1.6982133215169227e+01, -1.6673818688140226e+01, -1.6379422691596499e+01, -1.6096537266100814e+01, -1.5823389734978102e+01, -1.5558627617427760e+01, -1.5301189498098173e+01, -1.5050223129207568e+01, -1.4805031151963790e+01, -1.4565033799686276e+01, -1.4329742483675762e+01, -1.4098740600289259e+01, -1.3871669273924994e+01, -1.3648216561379414e+01, -1.3428109138379162e+01, -1.3211105801450707e+01, -1.2996992320804354e+01, -1.2785577314468604e+01, -1.2576688905294764e+01, -1.2370171985743601e+01, -1.2165885959983921e+01, -1.1963702864796298e+01, -1.1763505794009992e+01, -1.1565187568319024e+01, -1.1368649605090505e+01, -1.1173800952409410e+01, -1.0980557458945643e+01, -1.0788841056880692e+01, -1.0598579139520853e+01, -1.0409704018662802e+01, -1.0222152449492267e+01, -1.0035865212956141e+01, -9.8507867472781321e+00, -9.6668648216825712e+00, -9.4840502465221892e+00, -9.3022966149286930e+00, -9.1215600718621754e+00, -8.9417991070598717e+00, -8.7629743689023787e+00, -8.5850484966463263e+00, -8.4079859688330369e+00, -8.2317529659853896e+00, -8.0563172459604981e+00, -7.8816480305419629e+00, -7.7077159020391406e+00, -7.5344927088175595e+00, -7.3619514788185860e+00, -7.1900663402415486e+00, -7.0188124486605776e+00, -6.8481659199339457e+00, -6.6781037683378583e+00, -6.5086038494209282e+00, -6.3396448071316529e+00, -6.1712060248201084e+00, -6.0032675797578730e+00, -5.8358102008577646e+00, -5.6688152293079357e+00, -5.5022645818639999e+00, -5.3361407165684911e+00, -5.1704266006896686e+00, -5.0051056806918259e+00, -4.8401618540670963e+00, -4.6755794428746595e+00, -4.5113431688473895e+00, -4.3474381299386442e+00, -4.1838497781931396e+00, -4.0205638988360004e+00, -3.8575665904830925e+00, -3.6948442463838789e+00, -3.5323835366153280e+00, -3.3701713911519686e+00, -3.2081949837430650e+00, -3.0464417165332232e+00, -2.8848992053675047e+00, -2.7235552657264601e+00, -2.5623978992403580e+00, -2.4014152807354292e+00, -2.2405957457680694e+00, -2.0799277786058252e+00, -1.9194000006165373e+00, -1.7590011590293138e+00, -1.5987201160331019e+00, -1.4385458381804410e+00, -1.2784673860656646e+00, -1.1184739042482656e+00, -9.5855461139344544e-01, -7.9869879060299465e-01, -6.3889577991065161e-01, -4.7913496291691687e-01, -3.1940575953902500e-01, -1.5969761685235179e-01, -0.0000000000000000e+00, 1.5969761685235179e-01, 3.1940575953902500e-01, 4.7913496291691687e-01, 6.3889577991065161e-01, 7.9869879060299465e-01, 9.5855461139344544e-01, 1.1184739042482656e+00, 1.2784673860656646e+00, 1.4385458381804410e+00, 1.5987201160331019e+00, 1.7590011590293138e+00, 1.9194000006165373e+00, 2.0799277786058252e+00, 2.2405957457680694e+00, 2.4014152807354292e+00, 2.5623978992403580e+00, 2.7235552657264601e+00, 2.8848992053675047e+00, 3.0464417165332232e+00, 3.2081949837430650e+00, 3.3701713911519686e+00, 3.5323835366153280e+00, 3.6948442463838789e+00, 3.8575665904830925e+00, 4.0205638988360004e+00, 4.1838497781931396e+00, 4.3474381299386442e+00, 4.5113431688473895e+00, 4.6755794428746595e+00, 4.8401618540670963e+00, 5.0051056806918259e+00, 5.1704266006896686e+00, 5.3361407165684911e+00, 5.5022645818639999e+00, 5.6688152293079357e+00, 5.8358102008577646e+00, 6.0032675797578730e+00, 6.1712060248201084e+00, 6.3396448071316529e+00, 6.5086038494209282e+00, 6.6781037683378583e+00, 6.8481659199339457e+00, 7.0188124486605776e+00, 7.1900663402415486e+00, 7.3619514788185860e+00, 7.5344927088175595e+00, 7.7077159020391406e+00, 7.8816480305419629e+00, 8.0563172459604981e+00, 8.2317529659853896e+00, 8.4079859688330369e+00, 8.5850484966463263e+00, 8.7629743689023787e+00, 8.9417991070598717e+00, 9.1215600718621754e+00, 9.3022966149286930e+00, 9.4840502465221892e+00, 9.6668648216825712e+00, 9.8507867472781321e+00, 1.0035865212956141e+01, 1.0222152449492267e+01, 1.0409704018662802e+01, 1.0598579139520853e+01, 1.0788841056880692e+01, 1.0980557458945643e+01, 1.1173800952409410e+01, 1.1368649605090505e+01, 1.1565187568319024e+01, 1.1763505794009992e+01, 1.1963702864796298e+01, 1.2165885959983921e+01, 1.2370171985743601e+01, 1.2576688905294764e+01, 1.2785577314468604e+01, 1.2996992320804354e+01, 1.3211105801450707e+01, 1.3428109138379162e+01, 1.3648216561379414e+01, 1.3871669273924994e+01, 1.4098740600289259e+01, 1.4329742483675762e+01, 1.4565033799686276e+01, 1.4805031151963790e+01, 1.5050223129207568e+01, 1.5301189498098173e+01, 1.5558627617427760e+01, 1.5823389734978102e+01, 1.6096537266100814e+01, 1.6379422691596499e+01, 1.6673818688140226e+01, 1.6982133215169227e+01, 1.7307793941303686e+01, 1.7656003265287762e+01, 1.8035433169700678e+01, 1.8462907814661030e+01, 1.8982449038629166e+01}, + {-1.9033817193180372e+01, -1.8514739873870020e+01, -1.8087654552659949e+01, -1.7708576157582009e+01, -1.7360694468453165e+01, -1.7035344640856714e+01, -1.6727328534606457e+01, -1.6433221273899989e+01, -1.6150616853857390e+01, -1.5877744032458063e+01, -1.5613251421176075e+01, -1.5356078460791041e+01, -1.5105373590679383e+01, -1.4860440014620181e+01, -1.4620698434329638e+01, -1.4385660656810286e+01, -1.4154910416992225e+01, -1.3928089132251925e+01, -1.3704885115481808e+01, -1.3485025268316207e+01, -1.3268268588222005e+01, -1.3054401025509831e+01, -1.2843231360770561e+01, -1.2634587864551046e+01, -1.2428315564322974e+01, -1.2224273988380631e+01, -1.2022335288240422e+01, -1.1822382664331087e+01, -1.1624309036867450e+01, -1.1428015916557383e+01, -1.1233412439414929e+01, -1.1040414537288214e+01, -1.0848944221357737e+01, -1.0658928960246737e+01, -1.0470301137821307e+01, -1.0282997578470843e+01, -1.0096959129817110e+01, -9.9121302945287511e+00, -9.7284589043113154e+00, -9.5458958302732722e+00, -9.3643947247907189e+00, -9.1839117907500878e+00, -9.0044055746721732e+00, -8.8258367807379408e+00, -8.6481681031671602e+00, -8.4713640747611425e+00, -8.2953909297232951e+00, -8.1202164791264426e+00, -7.9458099976117715e+00, -7.7721421200878789e+00, -7.5991847473548857e+00, -7.4269109597125382e+00, -7.2552949377261493e+00, -7.0843118894232422e+00, -6.9139379832792587e+00, -6.7441502864247154e+00, -6.5749267075705307e+00, -6.4062459442041968e+00, -6.2380874336583796e+00, -6.0704313076963157e+00, -5.9032583502958440e+00, -5.7365499583469575e+00, -5.5702881050067488e+00, -5.4044553054813402e+00, -5.2390345850270315e+00, -5.0740094489830243e+00, -4.9093638546659628e+00, -4.7450821849723575e+00, -4.5811492235491675e+00, -4.4175501314054006e+00, -4.2542704248488947e+00, -4.0912959546425300e+00, -3.9286128862831946e+00, -3.7662076813149068e+00, -3.6040670795948389e+00, -3.4421780824374997e+00, -3.2805279365682800e+00, -3.1191041188228450e+00, -2.9578943215336770e+00, -2.7968864385493881e+00, -2.6360685518363063e+00, -2.4754289186153811e+00, -2.3149559589906059e+00, -2.1546382440280341e+00, -1.9944644842470249e+00, -1.8344235184876900e+00, -1.6745043031205911e+00, -1.5146959015666042e+00, -1.3549874740965486e+00, -1.1953682678816466e+00, -1.0358276072672234e+00, -8.7635488424319652e-01, -7.1693954908593016e-01, -5.5757110114689967e-01, -3.9823907976435802e-01, -2.3893305527481104e-01, -7.9642620101614783e-02, 7.9642620101614783e-02, 2.3893305527481104e-01, 3.9823907976435802e-01, 5.5757110114689967e-01, 7.1693954908593016e-01, 8.7635488424319652e-01, 1.0358276072672234e+00, 1.1953682678816466e+00, 1.3549874740965486e+00, 1.5146959015666042e+00, 1.6745043031205911e+00, 1.8344235184876900e+00, 1.9944644842470249e+00, 2.1546382440280341e+00, 2.3149559589906059e+00, 2.4754289186153811e+00, 2.6360685518363063e+00, 2.7968864385493881e+00, 2.9578943215336770e+00, 3.1191041188228450e+00, 3.2805279365682800e+00, 3.4421780824374997e+00, 3.6040670795948389e+00, 3.7662076813149068e+00, 3.9286128862831946e+00, 4.0912959546425300e+00, 4.2542704248488947e+00, 4.4175501314054006e+00, 4.5811492235491675e+00, 4.7450821849723575e+00, 4.9093638546659628e+00, 5.0740094489830243e+00, 5.2390345850270315e+00, 5.4044553054813402e+00, 5.5702881050067488e+00, 5.7365499583469575e+00, 5.9032583502958440e+00, 6.0704313076963157e+00, 6.2380874336583796e+00, 6.4062459442041968e+00, 6.5749267075705307e+00, 6.7441502864247154e+00, 6.9139379832792587e+00, 7.0843118894232422e+00, 7.2552949377261493e+00, 7.4269109597125382e+00, 7.5991847473548857e+00, 7.7721421200878789e+00, 7.9458099976117715e+00, 8.1202164791264426e+00, 8.2953909297232951e+00, 8.4713640747611425e+00, 8.6481681031671602e+00, 8.8258367807379408e+00, 9.0044055746721732e+00, 9.1839117907500878e+00, 9.3643947247907189e+00, 9.5458958302732722e+00, 9.7284589043113154e+00, 9.9121302945287511e+00, 1.0096959129817110e+01, 1.0282997578470843e+01, 1.0470301137821307e+01, 1.0658928960246737e+01, 1.0848944221357737e+01, 1.1040414537288214e+01, 1.1233412439414929e+01, 1.1428015916557383e+01, 1.1624309036867450e+01, 1.1822382664331087e+01, 1.2022335288240422e+01, 1.2224273988380631e+01, 1.2428315564322974e+01, 1.2634587864551046e+01, 1.2843231360770561e+01, 1.3054401025509831e+01, 1.3268268588222005e+01, 1.3485025268316207e+01, 1.3704885115481808e+01, 1.3928089132251925e+01, 1.4154910416992225e+01, 1.4385660656810286e+01, 1.4620698434329638e+01, 1.4860440014620181e+01, 1.5105373590679383e+01, 1.5356078460791041e+01, 1.5613251421176075e+01, 1.5877744032458063e+01, 1.6150616853857390e+01, 1.6433221273899989e+01, 1.6727328534606457e+01, 1.7035344640856714e+01, 1.7360694468453165e+01, 1.7708576157582009e+01, 1.8087654552659949e+01, 1.8514739873870020e+01, 1.9033817193180372e+01}, + {-1.9085051378043033e+01, -1.8566435110662020e+01, -1.8139736684916269e+01, -1.7761007579700482e+01, -1.7413451433407719e+01, -1.7088410498259837e+01, -1.6780690867902603e+01, -1.6486870443143417e+01, -1.6204545162304957e+01, -1.5931945209665145e+01, -1.5667720282583909e+01, -1.5410810672934431e+01, -1.5160365503176191e+01, -1.4915688536290588e+01, -1.4676200939552615e+01, -1.4441414913235960e+01, -1.4210914528731067e+01, -1.3984341494531598e+01, -1.3761384377966619e+01, -1.3541770305082187e+01, -1.3325258472923085e+01, -1.3111635010647520e+01, -1.2900708860246835e+01, -1.2692308438876983e+01, -1.2486278907997042e+01, -1.2282479919055724e+01, -1.2080783737378024e+01, -1.1881073669101410e+01, -1.1683242733101009e+01, -1.1487192532589896e+01, -1.1292832290695909e+01, -1.1100078021646450e+01, -1.0908851814834854e+01, -1.0719081213424776e+01, -1.0530698672582092e+01, -1.0343641085134585e+01, -1.0157849364615741e+01, -9.9732680773760247e+00, -9.7898451168372347e+00, -9.6075314140949892e+00, -9.4262806799959176e+00, -9.2460491745721143e+00, -9.0667955003389675e+00, -8.8884804164791387e+00, -8.7110666713658151e+00, -8.5345188512382073e+00, -8.3588032431445285e+00, -8.1838877105226704e+00, -8.0097415800046274e+00, -7.8363355382140769e+00, -7.6636415374829738e+00, -7.4916327095468409e+00, -7.3202832863932787e+00, -7.1495685275371788e+00, -6.9794646530814948e+00, -6.8099487819964919e+00, -6.6409988751145752e+00, -6.4725936823937991e+00, -6.3047126940519806e+00, -6.1373360952161162e+00, -5.9704447237692317e+00, -5.8040200311098342e+00, -5.6380440455680922e+00, -5.4724993382485847e+00, -5.3073689910920496e+00, -5.1426365669687621e+00, -4.9782860816339154e+00, -4.8143019773913309e+00, -4.6506690983259311e+00, -4.4873726669780289e+00, -4.3243982623437809e+00, -4.1617317990962412e+00, -3.9993595079305000e+00, -3.8372679169445236e+00, -3.6754438339745814e+00, -3.5138743298107440e+00, -3.3525467222238068e+00, -3.1914485607403469e+00, -3.0305676121073946e+00, -2.8698918463925485e+00, -2.7094094236692574e+00, -2.5491086812405244e+00, -2.3889781213574715e+00, -2.2290063993920741e+00, -2.0691823124259607e+00, -1.9094947882195137e+00, -1.7499328745276050e+00, -1.5904857287301759e+00, -1.4311426077475764e+00, -1.2718928582120677e+00, -1.1127259068682478e+00, -9.5363125117633152e-01, -7.9459845009326358e-01, -6.3561711500753826e-01, -4.7667690080438158e-01, -3.1776749703859319e-01, -1.5887861919288843e-01, -0.0000000000000000e+00, 1.5887861919288843e-01, 3.1776749703859319e-01, 4.7667690080438158e-01, 6.3561711500753826e-01, 7.9459845009326358e-01, 9.5363125117633152e-01, 1.1127259068682478e+00, 1.2718928582120677e+00, 1.4311426077475764e+00, 1.5904857287301759e+00, 1.7499328745276050e+00, 1.9094947882195137e+00, 2.0691823124259607e+00, 2.2290063993920741e+00, 2.3889781213574715e+00, 2.5491086812405244e+00, 2.7094094236692574e+00, 2.8698918463925485e+00, 3.0305676121073946e+00, 3.1914485607403469e+00, 3.3525467222238068e+00, 3.5138743298107440e+00, 3.6754438339745814e+00, 3.8372679169445236e+00, 3.9993595079305000e+00, 4.1617317990962412e+00, 4.3243982623437809e+00, 4.4873726669780289e+00, 4.6506690983259311e+00, 4.8143019773913309e+00, 4.9782860816339154e+00, 5.1426365669687621e+00, 5.3073689910920496e+00, 5.4724993382485847e+00, 5.6380440455680922e+00, 5.8040200311098342e+00, 5.9704447237692317e+00, 6.1373360952161162e+00, 6.3047126940519806e+00, 6.4725936823937991e+00, 6.6409988751145752e+00, 6.8099487819964919e+00, 6.9794646530814948e+00, 7.1495685275371788e+00, 7.3202832863932787e+00, 7.4916327095468409e+00, 7.6636415374829738e+00, 7.8363355382140769e+00, 8.0097415800046274e+00, 8.1838877105226704e+00, 8.3588032431445285e+00, 8.5345188512382073e+00, 8.7110666713658151e+00, 8.8884804164791387e+00, 9.0667955003389675e+00, 9.2460491745721143e+00, 9.4262806799959176e+00, 9.6075314140949892e+00, 9.7898451168372347e+00, 9.9732680773760247e+00, 1.0157849364615741e+01, 1.0343641085134585e+01, 1.0530698672582092e+01, 1.0719081213424776e+01, 1.0908851814834854e+01, 1.1100078021646450e+01, 1.1292832290695909e+01, 1.1487192532589896e+01, 1.1683242733101009e+01, 1.1881073669101410e+01, 1.2080783737378024e+01, 1.2282479919055724e+01, 1.2486278907997042e+01, 1.2692308438876983e+01, 1.2900708860246835e+01, 1.3111635010647520e+01, 1.3325258472923085e+01, 1.3541770305082187e+01, 1.3761384377966619e+01, 1.3984341494531598e+01, 1.4210914528731067e+01, 1.4441414913235960e+01, 1.4676200939552615e+01, 1.4915688536290588e+01, 1.5160365503176191e+01, 1.5410810672934431e+01, 1.5667720282583909e+01, 1.5931945209665145e+01, 1.6204545162304957e+01, 1.6486870443143417e+01, 1.6780690867902603e+01, 1.7088410498259837e+01, 1.7413451433407719e+01, 1.7761007579700482e+01, 1.8139736684916269e+01, 1.8566435110662020e+01, 1.9085051378043033e+01}, + {-1.9136152632446343e+01, -1.8617994596540964e+01, -1.8191680665779813e+01, -1.7813298656636132e+01, -1.7466065985601755e+01, -1.7141331960462935e+01, -1.6833906884239585e+01, -1.6540371418317267e+01, -1.6258323432990789e+01, -1.5985994530572864e+01, -1.5722035487991715e+01, -1.5465387443233377e+01, -1.5215200197812091e+01, -1.4970778070582133e+01, -1.4731542691573273e+01, -1.4497006651929539e+01, -1.4266754357415572e+01, -1.4040427805805265e+01, -1.3817715817227148e+01, -1.3598345740663659e+01, -1.3382076971394328e+01, -1.3168695816190608e+01, -1.2958011377300066e+01, -1.2749852217418379e+01, -1.2544063630985093e+01, -1.2340505391648597e+01, -1.2139049877631299e+01, -1.1939580499904540e+01, -1.1741990375159112e+01, -1.1546181198293549e+01, -1.1352062278750141e+01, -1.1159549712352600e+01, -1.0968565665937081e+01, -1.0779037756447492e+01, -1.0590898509596441e+01, -1.0404084885901707e+01, -1.0218537864062538e+01, -1.0034202073365652e+01, -9.8510254682020655e+00, -9.6689590389043136e+00, -9.4879565540345112e+00, -9.3079743300090456e+00, -9.1289710245687488e+00, -8.9509074511196953e+00, -8.7737464113997543e+00, -8.5974525442855416e+00, -8.4219921888566009e+00, -8.2473332600882276e+00, -8.0734451357601422e+00, -7.9002985533514174e+00, -7.7278655158483680e+00, -7.5561192055258362e+00, -7.3850339048770719e+00, -7.2145849239662976e+00, -7.0447485335633226e+00, -6.8755019034936238e+00, -6.7068230457014044e+00, -6.5386907615791259e+00, -6.3710845931658042e+00, -6.2039847778590458e+00, -6.0373722063233055e+00, -5.8712283833097523e+00, -5.7055353911321696e+00, -5.5402758555689235e+00, -5.3754329139836932e+00, -5.2109901854777609e+00, -5.0469317429044782e+00, -4.8832420865923929e+00, -4.7199061196376721e+00, -4.5569091246390609e+00, -4.3942367417598831e+00, -4.2318749480117184e+00, -4.0698100376633946e+00, -3.9080286036870948e+00, -3.7465175201606447e+00, -3.5852639255516232e+00, -3.4242552068148551e+00, -3.2634789842401504e+00, -3.1029230969919848e+00, -2.9425755892871246e+00, -2.7824246971601365e+00, -2.6224588357702330e+00, -2.4626665872061215e+00, -2.3030366887483824e+00, -2.1435580215515251e+00, -1.9842195997101939e+00, -1.8250105596761317e+00, -1.6659201499943919e+00, -1.5069377213289974e+00, -1.3480527167497827e+00, -1.1892546622534923e+00, -1.0305331574934382e+00, -8.7187786669305845e-01, -7.1327850971966389e-01, -5.5472485329544763e-01, -3.9620670232352440e-01, -2.3771389130732343e-01, -7.9236275842124657e-02, 7.9236275842124657e-02, 2.3771389130732343e-01, 3.9620670232352440e-01, 5.5472485329544763e-01, 7.1327850971966389e-01, 8.7187786669305845e-01, 1.0305331574934382e+00, 1.1892546622534923e+00, 1.3480527167497827e+00, 1.5069377213289974e+00, 1.6659201499943919e+00, 1.8250105596761317e+00, 1.9842195997101939e+00, 2.1435580215515251e+00, 2.3030366887483824e+00, 2.4626665872061215e+00, 2.6224588357702330e+00, 2.7824246971601365e+00, 2.9425755892871246e+00, 3.1029230969919848e+00, 3.2634789842401504e+00, 3.4242552068148551e+00, 3.5852639255516232e+00, 3.7465175201606447e+00, 3.9080286036870948e+00, 4.0698100376633946e+00, 4.2318749480117184e+00, 4.3942367417598831e+00, 4.5569091246390609e+00, 4.7199061196376721e+00, 4.8832420865923929e+00, 5.0469317429044782e+00, 5.2109901854777609e+00, 5.3754329139836932e+00, 5.5402758555689235e+00, 5.7055353911321696e+00, 5.8712283833097523e+00, 6.0373722063233055e+00, 6.2039847778590458e+00, 6.3710845931658042e+00, 6.5386907615791259e+00, 6.7068230457014044e+00, 6.8755019034936238e+00, 7.0447485335633226e+00, 7.2145849239662976e+00, 7.3850339048770719e+00, 7.5561192055258362e+00, 7.7278655158483680e+00, 7.9002985533514174e+00, 8.0734451357601422e+00, 8.2473332600882276e+00, 8.4219921888566009e+00, 8.5974525442855416e+00, 8.7737464113997543e+00, 8.9509074511196953e+00, 9.1289710245687488e+00, 9.3079743300090456e+00, 9.4879565540345112e+00, 9.6689590389043136e+00, 9.8510254682020655e+00, 1.0034202073365652e+01, 1.0218537864062538e+01, 1.0404084885901707e+01, 1.0590898509596441e+01, 1.0779037756447492e+01, 1.0968565665937081e+01, 1.1159549712352600e+01, 1.1352062278750141e+01, 1.1546181198293549e+01, 1.1741990375159112e+01, 1.1939580499904540e+01, 1.2139049877631299e+01, 1.2340505391648597e+01, 1.2544063630985093e+01, 1.2749852217418379e+01, 1.2958011377300066e+01, 1.3168695816190608e+01, 1.3382076971394328e+01, 1.3598345740663659e+01, 1.3817715817227148e+01, 1.4040427805805265e+01, 1.4266754357415572e+01, 1.4497006651929539e+01, 1.4731542691573273e+01, 1.4970778070582133e+01, 1.5215200197812091e+01, 1.5465387443233377e+01, 1.5722035487991715e+01, 1.5985994530572864e+01, 1.6258323432990789e+01, 1.6540371418317267e+01, 1.6833906884239585e+01, 1.7141331960462935e+01, 1.7466065985601755e+01, 1.7813298656636132e+01, 1.8191680665779813e+01, 1.8617994596540964e+01, 1.9136152632446343e+01}, + {-1.9187121982273521e+01, -1.8669419389135154e+01, -1.8243487580223828e+01, -1.7865450498614848e+01, -1.7518539259289700e+01, -1.7194110184967560e+01, -1.6886977763848531e+01, -1.6593725402038196e+01, -1.6311952890695306e+01, -1.6039893241994275e+01, -1.5776198306184138e+01, -1.5519810062439074e+01, -1.5269878987345788e+01, -1.5025709952340740e+01, -1.4786725047437830e+01, -1.4552437252279828e+01, -1.4322431304945502e+01, -1.4096349490675653e+01, -1.3873880880782780e+01, -1.3654753045730484e+01, -1.3438725577708846e+01, -1.3225584959886243e+01, -1.3015140453639436e+01, -1.2807220766151111e+01, -1.2601671323850574e+01, -1.2398352021647000e+01, -1.2197135349764665e+01, -1.1997904823149442e+01, -1.1800553655478529e+01, -1.1604983632531599e+01, -1.1411104149281471e+01, -1.1218831382380758e+01, -1.1028087575354093e+01, -1.0838800418181339e+01, -1.0650902506384885e+01, -1.0464330867440474e+01, -1.0279026544483804e+01, -1.0094934229009290e+01, -9.9120019356474849e+00, -9.7301807132353808e+00, -9.5494243873137332e+00, -9.3696893299405168e+00, -9.1909342533320295e+00, -9.0131200243591802e+00, -8.8362094973560179e+00, -8.6601673630569582e+00, -8.4849600117808954e+00, -8.3105554092350147e+00, -8.1369229835265475e+00, -7.9640335221538869e+00, -7.7918590779046193e+00, -7.6203728827216537e+00, -7.4495492687133176e+00, -7.2793635955820948e+00, -7.1097921838319138e+00, -6.9408122531878398e+00, -6.7724018657261427e+00, -6.6045398732686005e+00, -6.4372058686436739e+00, -6.2703801404598503e+00, -6.1040436310739281e+00, -5.9381778974699042e+00, -5.7727650747931136e+00, -5.6077878423099152e+00, -5.4432293915858283e+00, -5.2790733966951038e+00, -5.1153039862925711e+00, -4.9519057173944132e+00, -4.7888635507286939e+00, -4.6261628275290461e+00, -4.4637892476562113e+00, -4.3017288489422221e+00, -4.1399679876610396e+00, -3.9784933200376109e+00, -3.8172917847145760e+00, -3.6563505861024530e+00, -3.4956571785450063e+00, -3.3351992512368578e+00, -3.1749647138352097e+00, -3.0149416827118620e+00, -2.8551184677956569e+00, -2.6954835599590137e+00, -2.5360256189054007e+00, -2.3767334615175160e+00, -2.2175960506285199e+00, -2.0586024841810624e+00, -1.8997419847409271e+00, -1.7410038893340725e+00, -1.5823776395775344e+00, -1.4238527720762202e+00, -1.2654189090589871e+00, -1.1070657492286282e+00, -9.4878305880147162e-01, -7.9056066271324643e-01, -6.3238843596870120e-01, -4.7425629511315831e-01, -3.1615418980479731e-01, -1.5807209446693934e-01, -0.0000000000000000e+00, 1.5807209446693934e-01, 3.1615418980479731e-01, 4.7425629511315831e-01, 6.3238843596870120e-01, 7.9056066271324643e-01, 9.4878305880147162e-01, 1.1070657492286282e+00, 1.2654189090589871e+00, 1.4238527720762202e+00, 1.5823776395775344e+00, 1.7410038893340725e+00, 1.8997419847409271e+00, 2.0586024841810624e+00, 2.2175960506285199e+00, 2.3767334615175160e+00, 2.5360256189054007e+00, 2.6954835599590137e+00, 2.8551184677956569e+00, 3.0149416827118620e+00, 3.1749647138352097e+00, 3.3351992512368578e+00, 3.4956571785450063e+00, 3.6563505861024530e+00, 3.8172917847145760e+00, 3.9784933200376109e+00, 4.1399679876610396e+00, 4.3017288489422221e+00, 4.4637892476562113e+00, 4.6261628275290461e+00, 4.7888635507286939e+00, 4.9519057173944132e+00, 5.1153039862925711e+00, 5.2790733966951038e+00, 5.4432293915858283e+00, 5.6077878423099152e+00, 5.7727650747931136e+00, 5.9381778974699042e+00, 6.1040436310739281e+00, 6.2703801404598503e+00, 6.4372058686436739e+00, 6.6045398732686005e+00, 6.7724018657261427e+00, 6.9408122531878398e+00, 7.1097921838319138e+00, 7.2793635955820948e+00, 7.4495492687133176e+00, 7.6203728827216537e+00, 7.7918590779046193e+00, 7.9640335221538869e+00, 8.1369229835265475e+00, 8.3105554092350147e+00, 8.4849600117808954e+00, 8.6601673630569582e+00, 8.8362094973560179e+00, 9.0131200243591802e+00, 9.1909342533320295e+00, 9.3696893299405168e+00, 9.5494243873137332e+00, 9.7301807132353808e+00, 9.9120019356474849e+00, 1.0094934229009290e+01, 1.0279026544483804e+01, 1.0464330867440474e+01, 1.0650902506384885e+01, 1.0838800418181339e+01, 1.1028087575354093e+01, 1.1218831382380758e+01, 1.1411104149281471e+01, 1.1604983632531599e+01, 1.1800553655478529e+01, 1.1997904823149442e+01, 1.2197135349764665e+01, 1.2398352021647000e+01, 1.2601671323850574e+01, 1.2807220766151111e+01, 1.3015140453639436e+01, 1.3225584959886243e+01, 1.3438725577708846e+01, 1.3654753045730484e+01, 1.3873880880782780e+01, 1.4096349490675653e+01, 1.4322431304945502e+01, 1.4552437252279828e+01, 1.4786725047437830e+01, 1.5025709952340740e+01, 1.5269878987345788e+01, 1.5519810062439074e+01, 1.5776198306184138e+01, 1.6039893241994275e+01, 1.6311952890695306e+01, 1.6593725402038196e+01, 1.6886977763848531e+01, 1.7194110184967560e+01, 1.7518539259289700e+01, 1.7865450498614848e+01, 1.8243487580223828e+01, 1.8669419389135154e+01, 1.9187121982273521e+01}, + {-1.9237960440300323e+01, -1.8720710532447114e+01, -1.8295158499144485e+01, -1.7917464201364730e+01, -1.7570872373824393e+01, -1.7246746313979781e+01, -1.6939904671276931e+01, -1.6646933580854089e+01, -1.6365434743746000e+01, -1.6093642573904912e+01, -1.5830209988722080e+01, -1.5574079803690140e+01, -1.5324403166531194e+01, -1.5080485498011255e+01, -1.4841749345390438e+01, -1.4607708074467340e+01, -1.4377946753600369e+01, -1.4152107953707038e+01, -1.3929880995689542e+01, -1.3710993670057162e+01, -1.3495205764604879e+01, -1.3282303937699215e+01, -1.3072097608735946e+01, -1.2864415628348308e+01, -1.2659103553980440e+01, -1.2456021400878894e+01, -1.2255041770389502e+01, -1.2056048280588383e+01, -1.1858934241324912e+01, -1.1663601528470521e+01, -1.1469959621759649e+01, -1.1277924777921493e+01, -1.1087419316430047e+01, -1.0898370999572231e+01, -1.0710712491958864e+01, -1.0524380887307489e+01, -1.0339317292477098e+01, -1.0155466460457681e+01, -9.9727764654064881e+00, -9.7911984139496884e+00, -9.6106861878874543e+00, -9.4311962141946886e+00, -9.2526872588317186e+00, -9.0751202413947372e+00, -8.8984580680650804e+00, -8.7226654806754844e+00, -8.5477089200129779e+00, -8.3735564017325164e+00, -8.2001774034706933e+00, -8.0275427619319260e+00, -7.8556245788755001e+00, -7.6843961350654411e+00, -7.5138318113597080e+00, -7.3439070162139659e+00, -7.1745981189604136e+00, -7.0058823882959311e+00, -6.8377379354779668e+00, -6.6701436617824124e+00, -6.5030792098264039e+00, -6.3365249184017198e+00, -6.1704617805017721e+00, -6.0048714042581519e+00, -5.8397359765316308e+00, -5.6750382289281065e+00, -5.5107614060326373e+00, -5.3468892356747437e+00, -5.1834059010560054e+00, -5.0202960145867985e+00, -4.8575445932931558e+00, -4.6951370356673570e+00, -4.5330590998470743e+00, -4.3712968830180499e+00, -4.2098368019442765e+00, -4.0486655745377966e+00, -3.8877702023875300e+00, -3.7271379541730876e+00, -3.5667563498954848e+00, -3.4066131458619480e+00, -3.2466963203668557e+00, -3.0869940600152046e+00, -2.9274947466388688e+00, -2.7681869447595400e+00, -2.6090593895553744e+00, -2.4501009752913179e+00, -2.2913007441756847e+00, -2.1326478756079257e+00, -1.9741316757846794e+00, -1.8157415676330977e+00, -1.6574670810421992e+00, -1.4992978433645401e+00, -1.3412235701618946e+00, -1.1832340561698793e+00, -1.0253191664575543e+00, -8.6746882775900824e-01, -7.0967301995478616e-01, -5.5192176768174561e-01, -3.9420513205055796e-01, -2.3651320245058799e-01, -7.8836088422303746e-02, 7.8836088422303746e-02, 2.3651320245058799e-01, 3.9420513205055796e-01, 5.5192176768174561e-01, 7.0967301995478616e-01, 8.6746882775900824e-01, 1.0253191664575543e+00, 1.1832340561698793e+00, 1.3412235701618946e+00, 1.4992978433645401e+00, 1.6574670810421992e+00, 1.8157415676330977e+00, 1.9741316757846794e+00, 2.1326478756079257e+00, 2.2913007441756847e+00, 2.4501009752913179e+00, 2.6090593895553744e+00, 2.7681869447595400e+00, 2.9274947466388688e+00, 3.0869940600152046e+00, 3.2466963203668557e+00, 3.4066131458619480e+00, 3.5667563498954848e+00, 3.7271379541730876e+00, 3.8877702023875300e+00, 4.0486655745377966e+00, 4.2098368019442765e+00, 4.3712968830180499e+00, 4.5330590998470743e+00, 4.6951370356673570e+00, 4.8575445932931558e+00, 5.0202960145867985e+00, 5.1834059010560054e+00, 5.3468892356747437e+00, 5.5107614060326373e+00, 5.6750382289281065e+00, 5.8397359765316308e+00, 6.0048714042581519e+00, 6.1704617805017721e+00, 6.3365249184017198e+00, 6.5030792098264039e+00, 6.6701436617824124e+00, 6.8377379354779668e+00, 7.0058823882959311e+00, 7.1745981189604136e+00, 7.3439070162139659e+00, 7.5138318113597080e+00, 7.6843961350654411e+00, 7.8556245788755001e+00, 8.0275427619319260e+00, 8.2001774034706933e+00, 8.3735564017325164e+00, 8.5477089200129779e+00, 8.7226654806754844e+00, 8.8984580680650804e+00, 9.0751202413947372e+00, 9.2526872588317186e+00, 9.4311962141946886e+00, 9.6106861878874543e+00, 9.7911984139496884e+00, 9.9727764654064881e+00, 1.0155466460457681e+01, 1.0339317292477098e+01, 1.0524380887307489e+01, 1.0710712491958864e+01, 1.0898370999572231e+01, 1.1087419316430047e+01, 1.1277924777921493e+01, 1.1469959621759649e+01, 1.1663601528470521e+01, 1.1858934241324912e+01, 1.2056048280588383e+01, 1.2255041770389502e+01, 1.2456021400878894e+01, 1.2659103553980440e+01, 1.2864415628348308e+01, 1.3072097608735946e+01, 1.3282303937699215e+01, 1.3495205764604879e+01, 1.3710993670057162e+01, 1.3929880995689542e+01, 1.4152107953707038e+01, 1.4377946753600369e+01, 1.4607708074467340e+01, 1.4841749345390438e+01, 1.5080485498011255e+01, 1.5324403166531194e+01, 1.5574079803690140e+01, 1.5830209988722080e+01, 1.6093642573904912e+01, 1.6365434743746000e+01, 1.6646933580854089e+01, 1.6939904671276931e+01, 1.7246746313979781e+01, 1.7570872373824393e+01, 1.7917464201364730e+01, 1.8295158499144485e+01, 1.8720710532447114e+01, 1.9237960440300323e+01}, + {-1.9288669006428073e+01, -1.8771869057097732e+01, -1.8346694479614712e+01, -1.7969340846379055e+01, -1.7623066433928877e+01, -1.7299241474690692e+01, -1.6992688755677822e+01, -1.6699997125541856e+01, -1.6418770184323929e+01, -1.6147243739757997e+01, -1.5884071770266710e+01, -1.5628197922845580e+01, -1.5378774012459481e+01, -1.5135106005988732e+01, -1.4896616905233879e+01, -1.4662820459834590e+01, -1.4433302066419493e+01, -1.4207704579815282e+01, -1.3985717568940393e+01, -1.3767069042933601e+01, -1.3551518983907220e+01, -1.3338854224244356e+01, -1.3128884340266051e+01, -1.2921438325035480e+01, -1.2716361866052114e+01, -1.2513515097991551e+01, -1.2312770732455700e+01, -1.2114012489821327e+01, -1.1917133775310306e+01, -1.1722036554111044e+01, -1.1528630389965276e+01, -1.1336831618941112e+01, -1.1146562635737574e+01, -1.0957751274234692e+01, -1.0770330267425512e+01, -1.0584236774568581e+01, -1.0399411965548676e+01, -1.0215800654155213e+01, -1.0033350973375560e+01, -9.8520140869264541e+00, -9.6717439321652883e+00, -9.4924969902767238e+00, -9.3142320802515925e+00, -9.1369101736902376e+00, -8.9604942278913082e+00, -8.7849490350458534e+00, -8.6102410856578757e+00, -8.4363384445666423e+00, -8.2632106381612598e+00, -8.0908285515608398e+00, -7.9191643346894995e+00, -7.7481913163088629e+00, -7.5778839251852919e+00, -7.4082176176676109e+00, -7.2391688110363521e+00, -7.0707148220592551e+00, -6.9028338102518392e+00, -6.7355047253976705e+00, -6.5687072589316280e+00, -6.4024217988321039e+00, -6.2366293877054586e+00, -6.0713116837789416e+00, -5.9064509245471877e+00, -5.7420298928430569e+00, -5.5780318851261201e+00, -5.4144406818022057e+00, -5.2512405194051937e+00, -5.0884160644880927e+00, -4.9259523890845678e+00, -4.7638349476146598e+00, -4.6020495551197111e+00, -4.4405823667216309e+00, -4.2794198582106002e+00, -4.1185488076735286e+00, -3.9579562780827859e+00, -3.7976296007713630e+00, -3.6375563597264895e+00, -3.4777243766391046e+00, -3.3181216966513536e+00, -3.1587365747486800e+00, -2.9995574627469606e+00, -2.8405729968287345e+00, -2.6817719855857511e+00, -2.5231433985279939e+00, -2.3646763550219534e+00, -2.2063601136233109e+00, -2.0481840617713236e+00, -1.8901377058141628e+00, -1.7322106613361827e+00, -1.5743926437596774e+00, -1.4166734591950965e+00, -1.2590429955149371e+00, -1.1014912136276596e+00, -9.4400813892896185e-01, -7.8658385290862076e-01, -6.2920848489186076e-01, -4.7187220389486334e-01, -3.1456521057457892e-01, -1.5727772925344838e-01, -0.0000000000000000e+00, 1.5727772925344838e-01, 3.1456521057457892e-01, 4.7187220389486334e-01, 6.2920848489186076e-01, 7.8658385290862076e-01, 9.4400813892896185e-01, 1.1014912136276596e+00, 1.2590429955149371e+00, 1.4166734591950965e+00, 1.5743926437596774e+00, 1.7322106613361827e+00, 1.8901377058141628e+00, 2.0481840617713236e+00, 2.2063601136233109e+00, 2.3646763550219534e+00, 2.5231433985279939e+00, 2.6817719855857511e+00, 2.8405729968287345e+00, 2.9995574627469606e+00, 3.1587365747486800e+00, 3.3181216966513536e+00, 3.4777243766391046e+00, 3.6375563597264895e+00, 3.7976296007713630e+00, 3.9579562780827859e+00, 4.1185488076735286e+00, 4.2794198582106002e+00, 4.4405823667216309e+00, 4.6020495551197111e+00, 4.7638349476146598e+00, 4.9259523890845678e+00, 5.0884160644880927e+00, 5.2512405194051937e+00, 5.4144406818022057e+00, 5.5780318851261201e+00, 5.7420298928430569e+00, 5.9064509245471877e+00, 6.0713116837789416e+00, 6.2366293877054586e+00, 6.4024217988321039e+00, 6.5687072589316280e+00, 6.7355047253976705e+00, 6.9028338102518392e+00, 7.0707148220592551e+00, 7.2391688110363521e+00, 7.4082176176676109e+00, 7.5778839251852919e+00, 7.7481913163088629e+00, 7.9191643346894995e+00, 8.0908285515608398e+00, 8.2632106381612598e+00, 8.4363384445666423e+00, 8.6102410856578757e+00, 8.7849490350458534e+00, 8.9604942278913082e+00, 9.1369101736902376e+00, 9.3142320802515925e+00, 9.4924969902767238e+00, 9.6717439321652883e+00, 9.8520140869264541e+00, 1.0033350973375560e+01, 1.0215800654155213e+01, 1.0399411965548676e+01, 1.0584236774568581e+01, 1.0770330267425512e+01, 1.0957751274234692e+01, 1.1146562635737574e+01, 1.1336831618941112e+01, 1.1528630389965276e+01, 1.1722036554111044e+01, 1.1917133775310306e+01, 1.2114012489821327e+01, 1.2312770732455700e+01, 1.2513515097991551e+01, 1.2716361866052114e+01, 1.2921438325035480e+01, 1.3128884340266051e+01, 1.3338854224244356e+01, 1.3551518983907220e+01, 1.3767069042933601e+01, 1.3985717568940393e+01, 1.4207704579815282e+01, 1.4433302066419493e+01, 1.4662820459834590e+01, 1.4896616905233879e+01, 1.5135106005988732e+01, 1.5378774012459481e+01, 1.5628197922845580e+01, 1.5884071770266710e+01, 1.6147243739757997e+01, 1.6418770184323929e+01, 1.6699997125541856e+01, 1.6992688755677822e+01, 1.7299241474690692e+01, 1.7623066433928877e+01, 1.7969340846379055e+01, 1.8346694479614712e+01, 1.8771869057097732e+01, 1.9288669006428073e+01}, + {-1.9339248667911409e+01, -1.8822895980564734e+01, -1.8398096565132178e+01, -1.8021081501173168e+01, -1.7675122529961925e+01, -1.7351596779550405e+01, -1.7045331151092153e+01, -1.6752917191398179e+01, -1.6471960388762881e+01, -1.6200697936792103e+01, -1.5937784868895722e+01, -1.5682165658809755e+01, -1.5432992784892868e+01, -1.5189572756961194e+01, -1.4951329028681464e+01, -1.4717775731247299e+01, -1.4488498587572698e+01, -1.4263140734648266e+01, -1.4041391987855551e+01, -1.3822980573565543e+01, -1.3607666666938064e+01, -1.3395237273208020e+01, -1.3185502124544024e+01, -1.2978290355434069e+01, -1.2773447782488505e+01, -1.2570834658918320e+01, -1.2370323805730495e+01, -1.2171799044787127e+01, -1.1975153875897130e+01, -1.1780290352805242e+01, -1.1587118122520339e+01, -1.1395553599726039e+01, -1.1205519253636435e+01, -1.1016942989025184e+01, -1.0829757606576079e+01, -1.0643900330402785e+01, -1.0459312392733535e+01, -1.0275938667476471e+01, -1.0093727345768286e+01, -9.9126296477337945e+00, -9.7325995656019266e+00, -9.5535936340768206e+00, -9.3755707244836426e+00, -9.1984918597235552e+00, -9.0223200475008358e+00, -8.8470201296436706e+00, -8.6725586456412369e+00, -8.4989037087736055e+00, -8.3260248934261227e+00, -8.1538931323624819e+00, -7.9824806228866425e+00, -7.8117607409569434e+00, -7.6417079624302628e+00, -7.4722977907127222e+00, -7.3035066901782200e+00, -7.1353120247902524e+00, -6.9676920014260446e+00, -6.8006256174581203e+00, -6.6340926121968646e+00, -6.4680734218403675e+00, -6.3025491376151397e+00, -6.1375014668241503e+00, -5.9729126965475468e+00, -5.8087656597670589e+00, -5.6450437037075716e+00, -5.4817306602094709e+00, -5.3188108179631426e+00, -5.1562688964529020e+00, -4.9940900214715160e+00, -4.8322597020794342e+00, -4.6707638088937005e+00, -4.5095885536020024e+00, -4.3487204696060182e+00, -4.1881463937064671e+00, -4.0278534487497097e+00, -3.8678290271620543e+00, -3.7080607753039518e+00, -3.5485365785817580e+00, -3.3892445472592136e+00, -3.2301730029155085e+00, -3.0713104655004981e+00, -2.9126456409412849e+00, -2.7541674092575419e+00, -2.5958648131459636e+00, -2.4377270469968155e+00, -2.2797434463078550e+00, -2.1219034774632650e+00, -1.9641967278469044e+00, -1.8066128962612460e+00, -1.6491417836246915e+00, -1.4917732839215128e+00, -1.3344973753799896e+00, -1.1773041118552243e+00, -1.0201836143944896e+00, -8.6312606296338723e-01, -7.0612168831240074e-01, -5.4916076396359503e-01, -3.9223359829815591e-01, -2.3533052672581237e-01, -7.8441903917412792e-02, 7.8441903917412792e-02, 2.3533052672581237e-01, 3.9223359829815591e-01, 5.4916076396359503e-01, 7.0612168831240074e-01, 8.6312606296338723e-01, 1.0201836143944896e+00, 1.1773041118552243e+00, 1.3344973753799896e+00, 1.4917732839215128e+00, 1.6491417836246915e+00, 1.8066128962612460e+00, 1.9641967278469044e+00, 2.1219034774632650e+00, 2.2797434463078550e+00, 2.4377270469968155e+00, 2.5958648131459636e+00, 2.7541674092575419e+00, 2.9126456409412849e+00, 3.0713104655004981e+00, 3.2301730029155085e+00, 3.3892445472592136e+00, 3.5485365785817580e+00, 3.7080607753039518e+00, 3.8678290271620543e+00, 4.0278534487497097e+00, 4.1881463937064671e+00, 4.3487204696060182e+00, 4.5095885536020024e+00, 4.6707638088937005e+00, 4.8322597020794342e+00, 4.9940900214715160e+00, 5.1562688964529020e+00, 5.3188108179631426e+00, 5.4817306602094709e+00, 5.6450437037075716e+00, 5.8087656597670589e+00, 5.9729126965475468e+00, 6.1375014668241503e+00, 6.3025491376151397e+00, 6.4680734218403675e+00, 6.6340926121968646e+00, 6.8006256174581203e+00, 6.9676920014260446e+00, 7.1353120247902524e+00, 7.3035066901782200e+00, 7.4722977907127222e+00, 7.6417079624302628e+00, 7.8117607409569434e+00, 7.9824806228866425e+00, 8.1538931323624819e+00, 8.3260248934261227e+00, 8.4989037087736055e+00, 8.6725586456412369e+00, 8.8470201296436706e+00, 9.0223200475008358e+00, 9.1984918597235552e+00, 9.3755707244836426e+00, 9.5535936340768206e+00, 9.7325995656019266e+00, 9.9126296477337945e+00, 1.0093727345768286e+01, 1.0275938667476471e+01, 1.0459312392733535e+01, 1.0643900330402785e+01, 1.0829757606576079e+01, 1.1016942989025184e+01, 1.1205519253636435e+01, 1.1395553599726039e+01, 1.1587118122520339e+01, 1.1780290352805242e+01, 1.1975153875897130e+01, 1.2171799044787127e+01, 1.2370323805730495e+01, 1.2570834658918320e+01, 1.2773447782488505e+01, 1.2978290355434069e+01, 1.3185502124544024e+01, 1.3395237273208020e+01, 1.3607666666938064e+01, 1.3822980573565543e+01, 1.4041391987855551e+01, 1.4263140734648266e+01, 1.4488498587572698e+01, 1.4717775731247299e+01, 1.4951329028681464e+01, 1.5189572756961194e+01, 1.5432992784892868e+01, 1.5682165658809755e+01, 1.5937784868895722e+01, 1.6200697936792103e+01, 1.6471960388762881e+01, 1.6752917191398179e+01, 1.7045331151092153e+01, 1.7351596779550405e+01, 1.7675122529961925e+01, 1.8021081501173168e+01, 1.8398096565132178e+01, 1.8822895980564734e+01, 1.9339248667911409e+01}, +} + +// wCache computed from Chebfun. +var wCacheHermite = [][]float64{ + {1.7724538509055159e+00}, + {8.8622692545275794e-01, 8.8622692545275794e-01}, + {2.9540897515091952e-01, 1.1816359006036770e+00, 2.9540897515091952e-01}, + {8.1312835447245130e-02, 8.0491409000551273e-01, 8.0491409000551273e-01, 8.1312835447245130e-02}, + {1.9953242059045879e-02, 3.9361932315224107e-01, 9.4530872048294201e-01, 3.9361932315224107e-01, 1.9953242059045879e-02}, + {4.5300099055088682e-03, 1.5706732032285645e-01, 7.2462959522439263e-01, 7.2462959522439263e-01, 1.5706732032285645e-01, 4.5300099055088682e-03}, + {9.7178124509951806e-04, 5.4515582819127072e-02, 4.2560725261012772e-01, 8.1026461755680723e-01, 4.2560725261012772e-01, 5.4515582819127072e-02, 9.7178124509951806e-04}, + {1.9960407221136889e-04, 1.7077983007413408e-02, 2.0780232581489197e-01, 6.6114701255824115e-01, 6.6114701255824115e-01, 2.0780232581489197e-01, 1.7077983007413408e-02, 1.9960407221136889e-04}, + {3.9606977263264351e-05, 4.9436242755369481e-03, 8.8474527394376584e-02, 4.3265155900255570e-01, 7.2023521560605097e-01, 4.3265155900255570e-01, 8.8474527394376584e-02, 4.9436242755369481e-03, 3.9606977263264351e-05}, + {7.6404328552325936e-06, 1.3436457467812385e-03, 3.3874394455481120e-02, 2.4013861108231432e-01, 6.1086263373532612e-01, 6.1086263373532612e-01, 2.4013861108231432e-01, 3.3874394455481120e-02, 1.3436457467812385e-03, 7.6404328552325936e-06}, + {1.4395603937142598e-06, 3.4681946632334550e-04, 1.1911395444911524e-02, 1.1722787516770818e-01, 4.2935975235612489e-01, 6.5475928691459262e-01, 4.2935975235612489e-01, 1.1722787516770818e-01, 1.1911395444911524e-02, 3.4681946632334550e-04, 1.4395603937142598e-06}, + {2.6585516843563055e-07, 8.5736870435878019e-05, 3.9053905846290599e-03, 5.1607985615883964e-02, 2.6049231026416109e-01, 5.7013523626247942e-01, 5.7013523626247942e-01, 2.6049231026416109e-01, 5.1607985615883964e-02, 3.9053905846290599e-03, 8.5736870435878019e-05, 2.6585516843563055e-07}, + {4.8257318500731284e-08, 2.0430360402707074e-05, 1.2074599927193832e-03, 2.0862775296169932e-02, 1.4032332068702327e-01, 4.2161629689854296e-01, 6.0439318792116203e-01, 4.2161629689854296e-01, 1.4032332068702327e-01, 2.0862775296169932e-02, 1.2074599927193832e-03, 2.0430360402707074e-05, 4.8257318500731284e-08}, + {8.6285911681251554e-09, 4.7164843550189453e-06, 3.5509261355192302e-04, 7.8500547264579047e-03, 6.8505534223465281e-02, 2.7310560906424641e-01, 5.3640590971209023e-01, 5.3640590971209023e-01, 2.7310560906424641e-01, 6.8505534223465281e-02, 7.8500547264579047e-03, 3.5509261355192302e-04, 4.7164843550189453e-06, 8.6285911681251554e-09}, + {1.5224758042535219e-09, 1.0591155477110612e-06, 1.0000444123249973e-04, 2.7780688429127598e-03, 3.0780033872546117e-02, 1.5848891579593580e-01, 4.1202868749889832e-01, 5.6410030872641814e-01, 4.1202868749889832e-01, 1.5848891579593580e-01, 3.0780033872546117e-02, 2.7780688429127598e-03, 1.0000444123249973e-04, 1.0591155477110612e-06, 1.5224758042535219e-09}, + {2.6548074740111957e-10, 2.3209808448652080e-07, 2.7118600925378922e-05, 9.3228400862418201e-04, 1.2880311535509982e-02, 8.3810041398985943e-02, 2.8064745852853384e-01, 5.0792947901661334e-01, 5.0792947901661334e-01, 2.8064745852853384e-01, 8.3810041398985943e-02, 1.2880311535509982e-02, 9.3228400862418201e-04, 2.7118600925378922e-05, 2.3209808448652080e-07, 2.6548074740111957e-10}, + {4.5805789307986523e-11, 4.9770789816307401e-08, 7.1122891400212805e-06, 2.9864328669775215e-04, 5.0673499576275429e-03, 4.0920034149756306e-02, 1.7264829767009740e-01, 4.0182646947041184e-01, 5.3091793762486328e-01, 4.0182646947041184e-01, 1.7264829767009740e-01, 4.0920034149756306e-02, 5.0673499576275429e-03, 2.9864328669775215e-04, 7.1122891400212805e-06, 4.9770789816307401e-08, 4.5805789307986523e-11}, + {7.8281997721158175e-12, 1.0467205795791975e-08, 1.8106544810934246e-06, 9.1811268679294544e-05, 1.8885226302684155e-03, 1.8640042387544645e-02, 9.7301747641315411e-02, 2.8480728566997937e-01, 4.8349569472545578e-01, 4.8349569472545578e-01, 2.8480728566997937e-01, 9.7301747641315411e-02, 1.8640042387544645e-02, 1.8885226302684155e-03, 9.1811268679294544e-05, 1.8106544810934246e-06, 1.0467205795791975e-08, 7.8281997721158175e-12}, + {1.3262970944985103e-12, 2.1630510098635541e-09, 4.4882431472231438e-07, 2.7209197763161644e-05, 6.7087752140718431e-04, 7.9888667777229892e-03, 5.0810386909052110e-02, 1.8363270130699696e-01, 3.9160898861302956e-01, 5.0297488827618764e-01, 3.9160898861302956e-01, 1.8363270130699696e-01, 5.0810386909052110e-02, 7.9888667777229892e-03, 6.7087752140718431e-04, 2.7209197763161644e-05, 4.4882431472231438e-07, 2.1630510098635541e-09, 1.3262970944985103e-12}, + {2.2293936455341389e-13, 4.3993409922731442e-10, 1.0860693707692744e-07, 7.8025564785320785e-06, 2.2833863601635308e-04, 3.2437733422378532e-03, 2.4810520887463654e-02, 1.0901720602002316e-01, 2.8667550536283426e-01, 4.6224366960061009e-01, 4.6224366960061009e-01, 2.8667550536283426e-01, 1.0901720602002316e-01, 2.4810520887463654e-02, 3.2437733422378532e-03, 2.2833863601635308e-04, 7.8025564785320785e-06, 1.0860693707692744e-07, 4.3993409922731442e-10, 2.2293936455341389e-13}, + {3.7203650688184023e-14, 8.8186112420499177e-11, 2.5712301800593246e-08, 2.1718848980566754e-06, 7.4783988673100723e-05, 1.2549820417264148e-03, 1.1414065837434373e-02, 6.0179646658912296e-02, 1.9212032406699767e-01, 3.8166907361350205e-01, 4.7902370312017756e-01, 3.8166907361350205e-01, 1.9212032406699767e-01, 6.0179646658912296e-02, 1.1414065837434373e-02, 1.2549820417264148e-03, 7.4783988673100723e-05, 2.1718848980566754e-06, 2.5712301800593246e-08, 8.8186112420499177e-11, 3.7203650688184023e-14}, + {6.1671834244041516e-15, 1.7443390075479748e-11, 5.9669909860596536e-09, 5.8842875633009930e-07, 2.3655128552510423e-05, 4.6488505088425271e-04, 4.9783993350516510e-03, 3.1140370884423854e-02, 1.1910236095878249e-01, 2.8697143324690705e-01, 4.4354522643495936e-01, 4.4354522643495936e-01, 2.8697143324690705e-01, 1.1910236095878249e-01, 3.1140370884423854e-02, 4.9783993350516510e-03, 4.6488505088425271e-04, 2.3655128552510423e-05, 5.8842875633009930e-07, 5.9669909860596536e-09, 1.7443390075479748e-11, 6.1671834244041516e-15}, + {1.0160384616453285e-15, 3.4083140980305419e-12, 1.3596296504028875e-09, 1.5553393291457709e-07, 7.2492959180022684e-06, 1.6556169914187465e-04, 2.0695678749606356e-03, 1.5207084004484164e-02, 6.8890289429087329e-02, 1.9864489857802253e-01, 3.7214382487756476e-01, 4.5819658559321297e-01, 3.7214382487756476e-01, 1.9864489857802253e-01, 6.8890289429087329e-02, 1.5207084004484164e-02, 2.0695678749606356e-03, 1.6556169914187465e-04, 7.2492959180022684e-06, 1.5553393291457709e-07, 1.3596296504028875e-09, 3.4083140980305419e-12, 1.0160384616453285e-15}, + {1.6643684964891445e-16, 6.5846202430781003e-13, 3.0462542699875441e-10, 4.0189711749414533e-08, 2.1582457049023422e-06, 5.6886916364043827e-05, 8.2369248268841886e-04, 7.0483558100726791e-03, 3.7445470503230750e-02, 1.2773962178455914e-01, 2.8617953534644303e-01, 4.2693116386869923e-01, 4.2693116386869923e-01, 2.8617953534644303e-01, 1.2773962178455914e-01, 3.7445470503230750e-02, 7.0483558100726791e-03, 8.2369248268841886e-04, 5.6886916364043827e-05, 2.1582457049023422e-06, 4.0189711749414533e-08, 3.0462542699875441e-10, 6.5846202430781003e-13, 1.6643684964891445e-16}, + {2.7119235127587269e-17, 1.2588149877465385e-13, 6.7196384177062396e-11, 1.0170382503018480e-08, 6.2570324996911171e-07, 1.8915972957340510e-05, 3.1508363874548464e-04, 3.1157087201256362e-03, 1.9243098965408916e-02, 7.6888995175808827e-02, 2.0362113667812395e-01, 3.6308898927589056e-01, 4.3986872216948475e-01, 3.6308898927589056e-01, 2.0362113667812395e-01, 7.6888995175808827e-02, 1.9243098965408916e-02, 3.1157087201256362e-03, 3.1508363874548464e-04, 1.8915972957340510e-05, 6.2570324996911171e-07, 1.0170382503018480e-08, 6.7196384177062396e-11, 1.2588149877465385e-13, 2.7119235127587269e-17}, + {4.3969160947540168e-18, 2.3831486593721262e-14, 1.4609999339816088e-11, 2.5244940344905425e-09, 1.7701063373973562e-07, 6.1032917173960523e-06, 1.1622970160311058e-04, 1.3190647223238600e-03, 9.3979012911595897e-03, 4.3598227217250818e-02, 1.3511332791178782e-01, 2.8463224117678448e-01, 4.1204365059036946e-01, 4.1204365059036946e-01, 2.8463224117678448e-01, 1.3511332791178782e-01, 4.3598227217250818e-02, 9.3979012911595897e-03, 1.3190647223238600e-03, 1.1622970160311058e-04, 6.1032917173960523e-06, 1.7701063373973562e-07, 2.5244940344905425e-09, 1.4609999339816088e-11, 2.3831486593721262e-14, 4.3969160947540168e-18}, + {7.0957792932592773e-19, 4.4707724573930981e-15, 3.1341176136230566e-12, 6.1550315782317765e-10, 4.8954004096995851e-08, 1.9152809005953010e-06, 4.1467580043841186e-05, 5.3676961568811289e-04, 4.3812798357925394e-03, 2.3415933625341907e-02, 8.4173081084051971e-02, 2.0737048075100944e-01, 3.5451730409975396e-01, 4.2357728801505945e-01, 3.5451730409975396e-01, 2.0737048075100944e-01, 8.4173081084051971e-02, 2.3415933625341907e-02, 4.3812798357925394e-03, 5.3676961568811289e-04, 4.1467580043841186e-05, 1.9152809005953010e-06, 4.8954004096995851e-08, 6.1550315782317765e-10, 3.1341176136230566e-12, 4.4707724573930981e-15, 7.0957792932592773e-19}, + {1.1401393479036859e-19, 8.3159379512068002e-16, 6.6394367149096827e-13, 1.4758531682776914e-10, 1.3256825015417164e-08, 5.8577197209929782e-07, 1.4345504229714394e-05, 2.1061810002403312e-04, 1.9573312944089908e-03, 1.1968423214354838e-02, 4.9514889289898188e-02, 1.4139460978695487e-01, 2.8256139125938867e-01, 3.9860471782645146e-01, 3.9860471782645146e-01, 2.8256139125938867e-01, 1.4139460978695487e-01, 4.9514889289898188e-02, 1.1968423214354838e-02, 1.9573312944089908e-03, 2.1061810002403312e-04, 1.4345504229714394e-05, 5.8577197209929782e-07, 1.3256825015417164e-08, 1.4758531682776914e-10, 6.6394367149096827e-13, 8.3159379512068002e-16, 1.1401393479036859e-19}, + {1.8244608516739659e-20, 1.5345004446053123e-16, 1.3901072714496111e-13, 3.4841301613084286e-11, 3.5203123276007155e-09, 1.7492291299499463e-07, 4.8230734976477891e-06, 7.9909203545218356e-05, 8.4079250614026418e-04, 5.8455035452715061e-03, 2.7639655592023655e-02, 9.0768842215578197e-02, 2.1014269444921063e-01, 3.4641893907167015e-01, 4.0897117463522970e-01, 3.4641893907167015e-01, 2.1014269444921063e-01, 9.0768842215578197e-02, 2.7639655592023655e-02, 5.8455035452715061e-03, 8.4079250614026418e-04, 7.9909203545218356e-05, 4.8230734976477891e-06, 1.7492291299499463e-07, 3.5203123276007155e-09, 3.4841301613084286e-11, 1.3901072714496111e-13, 1.5345004446053123e-16, 1.8244608516739659e-20}, + {2.9082547001312504e-21, 2.8103336027509541e-17, 2.8786070805487377e-14, 8.1061862974630246e-12, 9.1785804243785856e-10, 5.1085224507759746e-08, 1.5790948873247135e-06, 2.9387252289229863e-05, 3.4831012431868588e-04, 2.7379224730676621e-03, 1.4703829704826692e-02, 5.5144176870234256e-02, 1.4673584754089000e-01, 2.8013093083921248e-01, 3.8639488954181417e-01, 3.8639488954181417e-01, 2.8013093083921248e-01, 1.4673584754089000e-01, 5.5144176870234256e-02, 1.4703829704826692e-02, 2.7379224730676621e-03, 3.4831012431868588e-04, 2.9387252289229863e-05, 1.5790948873247135e-06, 5.1085224507759746e-08, 9.1785804243785856e-10, 8.1061862974630246e-12, 2.8786070805487377e-14, 2.8103336027509541e-17, 2.9082547001312504e-21}, + {4.6189683913871598e-22, 5.1106090079270951e-18, 5.8995564987539112e-15, 1.8603735214521663e-12, 2.3524920032086692e-10, 1.4611988344910622e-08, 5.0437125589397732e-07, 1.0498602757675620e-05, 1.3952090395047032e-04, 1.2336833073068893e-03, 7.4827999140352043e-03, 3.1847230731300323e-02, 9.6717948160870412e-02, 2.1213278866876470e-01, 3.3877265789410776e-01, 3.9577855609860946e-01, 3.3877265789410776e-01, 2.1213278866876470e-01, 9.6717948160870412e-02, 3.1847230731300323e-02, 7.4827999140352043e-03, 1.2336833073068893e-03, 1.3952090395047032e-04, 1.0498602757675620e-05, 5.0437125589397732e-07, 1.4611988344910622e-08, 2.3524920032086692e-10, 1.8603735214521663e-12, 5.8995564987539112e-15, 5.1106090079270951e-18, 4.6189683913871598e-22}, + {7.3106764273841909e-23, 9.2317365365181365e-19, 1.1973440170928574e-15, 4.2150102113264756e-13, 5.9332914633966556e-11, 4.0988321647708776e-09, 1.5741677925455937e-07, 3.6505851295623875e-06, 5.4165840618199778e-05, 5.3626836552797335e-04, 3.6548903266544271e-03, 1.7553428831573435e-02, 6.0458130955912612e-02, 1.5126973407664251e-01, 2.7745814230252980e-01, 3.7523835259280258e-01, 3.7523835259280258e-01, 2.7745814230252980e-01, 1.5126973407664251e-01, 6.0458130955912612e-02, 1.7553428831573435e-02, 3.6548903266544271e-03, 5.3626836552797335e-04, 5.4165840618199778e-05, 3.6505851295623875e-06, 1.5741677925455937e-07, 4.0988321647708776e-09, 5.9332914633966556e-11, 4.2150102113264756e-13, 1.1973440170928574e-15, 9.2317365365181365e-19, 7.3106764273841909e-23}, + {1.1533162176980265e-23, 1.6570947415336692e-19, 2.4077856795579959e-16, 9.4348141590150248e-14, 1.4739809370924901e-11, 1.1289222471083366e-09, 4.8077456763232087e-08, 1.2376933672012150e-06, 2.0423684051423809e-05, 2.2544277059632773e-04, 1.7184546377609299e-03, 9.2656899706852411e-03, 3.5987982318576993e-02, 1.0206907999554145e-01, 2.1349393115029186e-01, 3.3155200075074132e-01, 3.8378526651986389e-01, 3.3155200075074132e-01, 2.1349393115029186e-01, 1.0206907999554145e-01, 3.5987982318576993e-02, 9.2656899706852411e-03, 1.7184546377609299e-03, 2.2544277059632773e-04, 2.0423684051423809e-05, 1.2376933672012150e-06, 4.8077456763232087e-08, 1.1289222471083366e-09, 1.4739809370924901e-11, 9.4348141590150248e-14, 2.4077856795579959e-16, 1.6570947415336692e-19, 1.1533162176980265e-23}, + {1.8138001119597749e-24, 2.9567089223605576e-20, 4.7999019978948293e-17, 2.0878403731160143e-14, 3.6098817474860888e-12, 3.0562520419155053e-10, 1.4387732912539959e-08, 4.0979740352245880e-07, 7.4934487833022770e-06, 9.1861189828724009e-05, 7.7981759962319987e-04, 4.6984636292665893e-03, 2.0473151727019457e-02, 6.5445134108752731e-02, 1.5511041662330927e-01, 2.7462771563513722e-01, 3.6499244699664513e-01, 3.6499244699664513e-01, 2.7462771563513722e-01, 1.5511041662330927e-01, 6.5445134108752731e-02, 2.0473151727019457e-02, 4.6984636292665893e-03, 7.7981759962319987e-04, 9.1861189828724009e-05, 7.4934487833022770e-06, 4.0979740352245880e-07, 1.4387732912539959e-08, 3.0562520419155053e-10, 3.6098817474860888e-12, 2.0878403731160143e-14, 4.7999019978948293e-17, 2.9567089223605576e-20, 1.8138001119597749e-24}, + {2.8441134634327172e-25, 5.2456527291743166e-21, 9.4898848794730163e-18, 4.5704441904182093e-15, 8.7225260125370039e-13, 8.1406956866777238e-11, 4.2239761300094312e-09, 1.3269405173066746e-07, 2.6798156546135386e-06, 3.6352769174157649e-05, 3.4234009319960727e-04, 2.2950283295840954e-03, 1.1166806590265730e-02, 4.0024775133100314e-02, 1.0687290695546242e-01, 2.1434719059607343e-01, 3.2472872157456961e-01, 3.7281997319072468e-01, 3.2472872157456961e-01, 2.1434719059607343e-01, 1.0687290695546242e-01, 4.0024775133100314e-02, 1.1166806590265730e-02, 2.2950283295840954e-03, 3.4234009319960727e-04, 3.6352769174157649e-05, 2.6798156546135386e-06, 1.3269405173066746e-07, 4.2239761300094312e-09, 8.1406956866777238e-11, 8.7225260125370039e-13, 4.5704441904182093e-15, 9.4898848794730163e-18, 5.2456527291743166e-21, 2.8441134634327172e-25}, + {4.4471534175756294e-26, 9.2564030835581952e-22, 1.8615979878080060e-18, 9.9029016869062119e-16, 2.0809126742868747e-13, 2.1353541817845700e-11, 1.2178678209557312e-09, 4.2074913231090725e-08, 9.3555700897732196e-07, 1.3997029220328986e-05, 1.4569615962636070e-04, 1.0825347566868020e-03, 5.8564259865595538e-03, 2.3425767509731743e-02, 7.0104750105177666e-02, 1.5835545375116650e-01, 2.7170124700952736e-01, 3.5554007427370893e-01, 3.5554007427370893e-01, 2.7170124700952736e-01, 1.5835545375116650e-01, 7.0104750105177666e-02, 2.3425767509731743e-02, 5.8564259865595538e-03, 1.0825347566868020e-03, 1.4569615962636070e-04, 1.3997029220328986e-05, 9.3555700897732196e-07, 4.2074913231090725e-08, 1.2178678209557312e-09, 2.1353541817845700e-11, 2.0809126742868747e-13, 9.9029016869062119e-16, 1.8615979878080060e-18, 9.2564030835581952e-22, 4.4471534175756294e-26}, + {6.9350835444886530e-27, 1.6249853271916221e-22, 3.6247269512444368e-19, 2.1248851941314958e-16, 4.9047393641852124e-14, 5.5203972646374721e-12, 3.4519062272121333e-10, 1.3079698821802362e-08, 3.1928854810032377e-07, 5.2521435771200543e-06, 6.0226951652674167e-05, 4.9417150121469438e-04, 2.9608001846029054e-03, 1.3160179977211566e-02, 4.3931362299539353e-02, 1.1117916510719518e-01, 2.1478887596478388e-01, 3.1827467975443136e-01, 3.6274375769908357e-01, 3.1827467975443136e-01, 2.1478887596478388e-01, 1.1117916510719518e-01, 4.3931362299539353e-02, 1.3160179977211566e-02, 2.9608001846029054e-03, 4.9417150121469438e-04, 6.0226951652674167e-05, 5.2521435771200543e-06, 3.1928854810032377e-07, 1.3079698821802362e-08, 3.4519062272121333e-10, 5.5203972646374721e-12, 4.9047393641852124e-14, 2.1248851941314958e-16, 3.6247269512444368e-19, 1.6249853271916221e-22, 6.9350835444886530e-27}, + {1.0787188820741241e-27, 2.8387387532094075e-23, 7.0078433305584917e-20, 4.5173712236048158e-17, 1.1428616750256895e-14, 1.4076333438452520e-12, 9.6270292926054501e-11, 3.9906528856889178e-09, 1.0665865704409148e-07, 1.9234656867323990e-06, 2.4223415120935207e-05, 2.1875759533939115e-04, 1.4463071215627061e-03, 7.1152368261340193e-03, 2.6380533520486894e-02, 7.4443983368238764e-02, 1.6108797149548099e-01, 2.6872376002892800e-01, 3.4678411786878038e-01, 3.4678411786878038e-01, 2.6872376002892800e-01, 1.6108797149548099e-01, 7.4443983368238764e-02, 2.6380533520486894e-02, 7.1152368261340193e-03, 1.4463071215627061e-03, 2.1875759533939115e-04, 2.4223415120935207e-05, 1.9234656867323990e-06, 1.0665865704409148e-07, 3.9906528856889178e-09, 9.6270292926054501e-11, 1.4076333438452520e-12, 1.1428616750256895e-14, 4.5173712236048158e-17, 7.0078433305584917e-20, 2.8387387532094075e-23, 1.0787188820741241e-27}, + {1.6737892441539538e-28, 4.9359073375904207e-24, 1.3457268201343837e-20, 9.5193204821162674e-18, 2.6340961107224671e-15, 3.5426508019791487e-13, 2.6440048769930072e-11, 1.1961664237667613e-09, 3.4915088439108438e-08, 6.8844204093401453e-07, 9.4942995361418356e-06, 9.4077279467672325e-05, 6.8405759521855724e-04, 3.7112302317141572e-03, 1.5221980837289402e-02, 4.7690071331635359e-02, 1.1503504579976950e-01, 2.1489607677746486e-01, 3.1216284886717011e-01, 3.5344263570679940e-01, 3.1216284886717011e-01, 2.1489607677746486e-01, 1.1503504579976950e-01, 4.7690071331635359e-02, 1.5221980837289402e-02, 3.7112302317141572e-03, 6.8405759521855724e-04, 9.4077279467672325e-05, 9.4942995361418356e-06, 6.8844204093401453e-07, 3.4915088439108438e-08, 1.1961664237667613e-09, 2.6440048769930072e-11, 3.5426508019791487e-13, 2.6340961107224671e-15, 9.5193204821162674e-18, 1.3457268201343837e-20, 4.9359073375904207e-24, 1.6737892441539538e-28}, + {2.5910437138470431e-29, 8.5440569637751720e-25, 2.5675933654117104e-21, 1.9891810121165382e-18, 6.0083587894908697e-16, 8.8057076452162173e-14, 7.1565280526903396e-12, 3.5256207913654460e-10, 1.1212360832275973e-08, 2.4111441636705294e-07, 3.6315761506930362e-06, 3.9369339810924932e-05, 3.1385359454133192e-04, 1.8714968295979542e-03, 8.4608880082581352e-03, 2.9312565536172355e-02, 7.8474605865404390e-02, 1.6337873271327136e-01, 2.6572825187737692e-01, 3.3864327742558936e-01, 3.3864327742558936e-01, 2.6572825187737692e-01, 1.6337873271327136e-01, 7.8474605865404390e-02, 2.9312565536172355e-02, 8.4608880082581352e-03, 1.8714968295979542e-03, 3.1385359454133192e-04, 3.9369339810924932e-05, 3.6315761506930362e-06, 2.4111441636705294e-07, 1.1212360832275973e-08, 3.5256207913654460e-10, 7.1565280526903396e-12, 8.8057076452162173e-14, 6.0083587894908697e-16, 1.9891810121165382e-18, 2.5675933654117104e-21, 8.5440569637751720e-25, 2.5910437138470431e-29}, + {4.0019596605455888e-30, 1.4726537286520423e-25, 4.8687379360130589e-22, 4.1234085375315004e-19, 1.3569875295861202e-16, 2.1629872471750215e-14, 1.9103833646809321e-12, 1.0226798927782354e-10, 3.5356816483807076e-09, 8.2726584187498191e-08, 1.3573781404870848e-06, 1.6055965736677200e-05, 1.3993025659674152e-04, 9.1423425632870857e-04, 4.5403929873032720e-03, 1.7330881362116784e-02, 5.1289872397094663e-02, 1.1848439124684401e-01, 2.1473086449008444e-01, 3.0636781693785120e-01, 3.4482208361638955e-01, 3.0636781693785120e-01, 2.1473086449008444e-01, 1.1848439124684401e-01, 5.1289872397094663e-02, 1.7330881362116784e-02, 4.5403929873032720e-03, 9.1423425632870857e-04, 1.3993025659674152e-04, 1.6055965736677200e-05, 1.3573781404870848e-06, 8.2726584187498191e-08, 3.5356816483807076e-09, 1.0226798927782354e-10, 1.9103833646809321e-12, 2.1629872471750215e-14, 1.3569875295861202e-16, 4.1234085375315004e-19, 4.8687379360130589e-22, 1.4726537286520423e-25, 4.0019596605455888e-30}, + {6.1678589258109773e-31, 2.5278698640534739e-26, 9.1778906956924963e-23, 8.4821520800863616e-20, 3.0358903478107461e-17, 5.2533377155686787e-15, 5.0327055821840466e-13, 2.9217288372333376e-11, 1.0958052288078504e-09, 2.7834715265490800e-08, 4.9636593935798231e-07, 6.3902459677354328e-06, 6.0719621077883790e-05, 4.3341227172125611e-04, 2.3571613945963252e-03, 9.8795240531885219e-03, 3.2202101288907867e-02, 8.2211269303293782e-02, 1.6528800127466756e-01, 2.6273890678229461e-01, 3.3104891389085667e-01, 3.3104891389085667e-01, 2.6273890678229461e-01, 1.6528800127466756e-01, 8.2211269303293782e-02, 3.2202101288907867e-02, 9.8795240531885219e-03, 2.3571613945963252e-03, 4.3341227172125611e-04, 6.0719621077883790e-05, 6.3902459677354328e-06, 4.9636593935798231e-07, 2.7834715265490800e-08, 1.0958052288078504e-09, 2.9217288372333376e-11, 5.0327055821840466e-13, 5.2533377155686787e-15, 3.0358903478107461e-17, 8.4821520800863616e-20, 9.1778906956924963e-23, 2.5278698640534739e-26, 6.1678589258109773e-31}, + {9.4863063307486296e-32, 4.3221460599337345e-27, 1.7203368260282161e-23, 1.7320753790913467e-20, 6.7308117032428195e-18, 1.2622032209758195e-15, 1.3092104166584946e-13, 8.2271061208164963e-12, 3.3407179153175535e-10, 9.1931960675404414e-09, 1.7777830445479720e-07, 2.4851377424115403e-06, 2.5680573077056677e-05, 1.9972435671322962e-04, 1.1860700927674253e-03, 5.4414552932418097e-03, 1.9468160151101737e-02, 5.4724809081874805e-02, 1.2156737988638795e-01, 2.1434349700188368e-01, 3.0086599386765978e-01, 3.3680296539275278e-01, 3.0086599386765978e-01, 2.1434349700188368e-01, 1.2156737988638795e-01, 5.4724809081874805e-02, 1.9468160151101737e-02, 5.4414552932418097e-03, 1.1860700927674253e-03, 1.9972435671322962e-04, 2.5680573077056677e-05, 2.4851377424115403e-06, 1.7777830445479720e-07, 9.1931960675404414e-09, 3.3407179153175535e-10, 8.2271061208164963e-12, 1.3092104166584946e-13, 1.2622032209758195e-15, 6.7308117032428195e-18, 1.7320753790913467e-20, 1.7203368260282161e-23, 4.3221460599337345e-27, 9.4863063307486296e-32}, + {1.4561153081762322e-32, 7.3621261042968285e-28, 3.2072216919050275e-24, 3.5121449558365656e-21, 1.4794099758171669e-18, 3.0015214029808191e-16, 3.3650356127923192e-14, 2.2848078971220373e-12, 1.0026000778909185e-10, 2.9831210190396358e-09, 6.2427245062815072e-08, 9.4545385422855902e-07, 1.0600171772517656e-05, 8.9597973640616782e-05, 5.7942043271566558e-04, 2.9012937752966299e-03, 1.1357866939069948e-02, 3.5033757109687119e-02, 8.5670187300246295e-02, 1.6686716582564590e-01, 2.5977339611588807e-01, 3.2394262884199604e-01, 3.2394262884199604e-01, 2.5977339611588807e-01, 1.6686716582564590e-01, 8.5670187300246295e-02, 3.5033757109687119e-02, 1.1357866939069948e-02, 2.9012937752966299e-03, 5.7942043271566558e-04, 8.9597973640616782e-05, 1.0600171772517656e-05, 9.4545385422855902e-07, 6.2427245062815072e-08, 2.9831210190396358e-09, 1.0026000778909185e-10, 2.2848078971220373e-12, 3.3650356127923192e-14, 3.0015214029808191e-16, 1.4794099758171669e-18, 3.5121449558365656e-21, 3.2072216919050275e-24, 7.3621261042968285e-28, 1.4561153081762322e-32}, + {2.2308126593779868e-33, 1.2494829120559801e-28, 5.9481747159233458e-25, 7.0737246502696336e-22, 3.2248298707326610e-19, 7.0674619157542681e-17, 8.5500874663703821e-15, 6.2620383158353876e-13, 2.9642049893157670e-11, 9.5182669412336419e-10, 2.1512839074194501e-08, 3.5225192415065300e-07, 4.2754558863972689e-06, 3.9183295448819551e-05, 2.7524242709953090e-04, 1.5001278829297612e-03, 6.4070706562040147e-03, 2.1617644433765643e-02, 5.7992746631628803e-02, 1.2432050192893590e-01, 2.1377487850201790e-01, 2.9563565196662861e-01, 3.2931845505069163e-01, 2.9563565196662861e-01, 2.1377487850201790e-01, 1.2432050192893590e-01, 5.7992746631628803e-02, 2.1617644433765643e-02, 6.4070706562040147e-03, 1.5001278829297612e-03, 2.7524242709953090e-04, 3.9183295448819551e-05, 4.2754558863972689e-06, 3.5225192415065300e-07, 2.1512839074194501e-08, 9.5182669412336419e-10, 2.9642049893157670e-11, 6.2620383158353876e-13, 8.5500874663703821e-15, 7.0674619157542681e-17, 3.2248298707326610e-19, 7.0737246502696336e-22, 5.9481747159233458e-25, 1.2494829120559801e-28, 2.2308126593779868e-33}, + {3.4113792299096508e-34, 2.1132014962696289e-29, 1.0976558019968051e-25, 1.4155042016755176e-22, 6.9737995966949200e-20, 1.6484447389507407e-17, 2.1486472823678717e-15, 1.6947076167749986e-13, 8.6391402914483532e-12, 2.9885455879923381e-10, 7.2816347565639946e-09, 1.2865324130563406e-07, 1.6869468397355139e-06, 1.6725935920653945e-05, 1.2731983755106949e-04, 7.5339673454313967e-04, 3.5010578505227864e-03, 1.2883487559777229e-02, 3.7795830992247079e-02, 8.8868227566005320e-02, 1.6816012736212269e-01, 2.5684454350651975e-01, 3.1727438491816684e-01, 3.1727438491816684e-01, 2.5684454350651975e-01, 1.6816012736212269e-01, 8.8868227566005320e-02, 3.7795830992247079e-02, 1.2883487559777229e-02, 3.5010578505227864e-03, 7.5339673454313967e-04, 1.2731983755106949e-04, 1.6725935920653945e-05, 1.6869468397355139e-06, 1.2865324130563406e-07, 7.2816347565639946e-09, 2.9885455879923381e-10, 8.6391402914483532e-12, 1.6947076167749986e-13, 2.1486472823678717e-15, 1.6484447389507407e-17, 6.9737995966949200e-20, 1.4155042016755176e-22, 1.0976558019968051e-25, 2.1132014962696289e-29, 3.4113792299096508e-34}, + {5.2074550840354642e-35, 3.5619817807815819e-30, 2.0158558166547157e-26, 2.8149547423920401e-23, 1.4966299166256593e-20, 3.8101463479230325e-18, 5.3428423961486667e-16, 4.5312676467479057e-14, 2.4836135431247532e-12, 9.2402978883643831e-11, 2.4228134937243909e-09, 4.6104364856635215e-08, 6.5181055230401887e-07, 6.9771079617906096e-06, 5.7425938238321535e-05, 3.6806169587486260e-04, 1.8562527788732503e-03, 7.4296915378901547e-03, 2.3765555762406108e-02, 6.1094386221801737e-02, 1.2677670015500209e-01, 2.1305846026514422e-01, 2.9065687385124467e-01, 3.2231167941131522e-01, 2.9065687385124467e-01, 2.1305846026514422e-01, 1.2677670015500209e-01, 6.1094386221801737e-02, 2.3765555762406108e-02, 7.4296915378901547e-03, 1.8562527788732503e-03, 3.6806169587486260e-04, 5.7425938238321535e-05, 6.9771079617906096e-06, 6.5181055230401887e-07, 4.6104364856635215e-08, 2.4228134937243909e-09, 9.2402978883643831e-11, 2.4836135431247532e-12, 4.5312676467479057e-14, 5.3428423961486667e-16, 3.8101463479230325e-18, 1.4966299166256593e-20, 2.8149547423920401e-23, 2.0158558166547157e-26, 3.5619817807815819e-30, 5.2074550840354642e-35}, + {7.9355514607740056e-36, 5.9846126933135906e-31, 3.6850360801506979e-27, 5.5645774689023294e-24, 3.1883873235051506e-21, 8.7301596011867662e-19, 1.3151596226583889e-16, 1.1975898654791956e-14, 7.0469325815459271e-13, 2.8152965378381835e-11, 7.9304674951654092e-10, 1.6225141358957786e-08, 2.4686589936697532e-07, 2.8472586917348417e-06, 2.5285990277484952e-05, 1.7515043180117349e-04, 9.5639231981941610e-04, 4.1530049119775534e-03, 1.4444961574981133e-02, 4.0479676984603939e-02, 9.1822297079285201e-02, 1.6920447194564109e-01, 2.5396154266475901e-01, 3.1100103037796278e-01, 3.1100103037796278e-01, 2.5396154266475901e-01, 1.6920447194564109e-01, 9.1822297079285201e-02, 4.0479676984603939e-02, 1.4444961574981133e-02, 4.1530049119775534e-03, 9.5639231981941610e-04, 1.7515043180117349e-04, 2.5285990277484952e-05, 2.8472586917348417e-06, 2.4686589936697532e-07, 1.6225141358957786e-08, 7.9304674951654092e-10, 2.8152965378381835e-11, 7.0469325815459271e-13, 1.1975898654791956e-14, 1.3151596226583889e-16, 8.7301596011867662e-19, 3.1883873235051506e-21, 5.5645774689023294e-24, 3.6850360801506979e-27, 5.9846126933135906e-31, 7.9355514607740056e-36}, + {1.2072872864975299e-36, 1.0023613427435658e-31, 6.7063563353463921e-28, 1.0936809436127891e-24, 6.7446743456588804e-22, 1.9836416602794039e-19, 3.2059589524003601e-17, 3.1301391441242865e-15, 1.9744849360632020e-13, 8.4575241714312574e-12, 2.5554702439987741e-10, 5.6118428733874883e-09, 9.1729613211703643e-08, 1.1378411996774051e-06, 1.0881805485674181e-05, 8.1291046453153734e-05, 4.7952088600477827e-04, 2.2536737753387727e-03, 8.5018075629547680e-03, 2.5900304438342722e-02, 6.4032496212210105e-02, 1.2896559830848855e-01, 2.1222171925816707e-01, 2.8591145169466448e-01, 3.1573389003557428e-01, 2.8591145169466448e-01, 2.1222171925816707e-01, 1.2896559830848855e-01, 6.4032496212210105e-02, 2.5900304438342722e-02, 8.5018075629547680e-03, 2.2536737753387727e-03, 4.7952088600477827e-04, 8.1291046453153734e-05, 1.0881805485674181e-05, 1.1378411996774051e-06, 9.1729613211703643e-08, 5.6118428733874883e-09, 2.5554702439987741e-10, 8.4575241714312574e-12, 1.9744849360632020e-13, 3.1301391441242865e-15, 3.2059589524003601e-17, 1.9836416602794039e-19, 6.7446743456588804e-22, 1.0936809436127891e-24, 6.7063563353463921e-28, 1.0023613427435658e-31, 1.2072872864975299e-36}, + {1.8337940485734247e-37, 1.6738016679078003e-32, 1.2152441234045103e-28, 2.1376583083600910e-25, 1.4170935995734126e-22, 4.4709843654079433e-20, 7.7423829570434533e-18, 8.0942618934651918e-16, 5.4659440318156410e-14, 2.5066555238996801e-12, 8.1118773649302876e-11, 1.9090405438119032e-09, 3.3467934040214541e-08, 4.4570299668178385e-07, 4.5816827079555368e-06, 3.6840190537807232e-05, 2.3426989210925618e-04, 1.1890117817496457e-03, 4.8532638261719538e-03, 1.6031941068412211e-02, 4.3079159156765599e-02, 9.4548935477086246e-02, 1.7003245567716402e-01, 2.5113085633200216e-01, 3.0508512920439906e-01, 3.0508512920439906e-01, 2.5113085633200216e-01, 1.7003245567716402e-01, 9.4548935477086246e-02, 4.3079159156765599e-02, 1.6031941068412211e-02, 4.8532638261719538e-03, 1.1890117817496457e-03, 2.3426989210925618e-04, 3.6840190537807232e-05, 4.5816827079555368e-06, 4.4570299668178385e-07, 3.3467934040214541e-08, 1.9090405438119032e-09, 8.1118773649302876e-11, 2.5066555238996801e-12, 5.4659440318156410e-14, 8.0942618934651918e-16, 7.7423829570434533e-18, 4.4709843654079433e-20, 1.4170935995734126e-22, 2.1376583083600910e-25, 1.2152441234045103e-28, 1.6738016679078003e-32, 1.8337940485734247e-37}, + {2.7811222326645344e-38, 2.7868913296983680e-33, 2.1929968310380126e-29, 4.1558650081686601e-26, 2.9579544865762534e-23, 9.9993599745434670e-21, 1.8530303241143367e-18, 2.0717064275729557e-16, 1.4956863300607063e-14, 7.3335422940638437e-13, 2.5381498317560184e-11, 6.3917274853532610e-10, 1.1999326533873204e-08, 1.7127604128737511e-07, 1.8891833940946794e-06, 1.6319954290330701e-05, 1.1165708931911324e-04, 6.1070259874041984e-04, 2.6911086058640649e-03, 9.6161203333211508e-03, 2.8012262602063957e-02, 6.6811317318844293e-02, 1.3091376937688559e-01, 2.1128731588244376e-01, 2.8138276384359967e-01, 3.0954302944664125e-01, 2.8138276384359967e-01, 2.1128731588244376e-01, 1.3091376937688559e-01, 6.6811317318844293e-02, 2.8012262602063957e-02, 9.6161203333211508e-03, 2.6911086058640649e-03, 6.1070259874041984e-04, 1.1165708931911324e-04, 1.6319954290330701e-05, 1.8891833940946794e-06, 1.7127604128737511e-07, 1.1999326533873204e-08, 6.3917274853532610e-10, 2.5381498317560184e-11, 7.3335422940638437e-13, 1.4956863300607063e-14, 2.0717064275729557e-16, 1.8530303241143367e-18, 9.9993599745434670e-21, 2.9579544865762534e-23, 4.1558650081686601e-26, 2.1929968310380126e-29, 2.7868913296983680e-33, 2.7811222326645344e-38}, + {4.2115420614105446e-39, 4.6271645012802355e-34, 3.9415951369162550e-30, 8.0378813038410338e-27, 6.1353803600426939e-24, 2.2196939309444735e-21, 4.3966970036273617e-19, 5.2503117409060339e-17, 4.0473768240447191e-15, 2.1189539626185899e-13, 7.8326447571213533e-12, 2.1076390184671402e-10, 4.2306685774284424e-09, 6.4623052172886120e-08, 7.6355680403038401e-07, 7.0741004987582161e-06, 5.1975998082926043e-05, 3.0574624681119092e-04, 1.4514479978625793e-03, 5.5977022679341544e-03, 1.7635166965733341e-02, 4.5590184103438805e-02, 9.7064055572858784e-02, 1.7067182934440731e-01, 2.4835688537420786e-01, 2.9949402485158516e-01, 2.9949402485158516e-01, 2.4835688537420786e-01, 1.7067182934440731e-01, 9.7064055572858784e-02, 4.5590184103438805e-02, 1.7635166965733341e-02, 5.5977022679341544e-03, 1.4514479978625793e-03, 3.0574624681119092e-04, 5.1975998082926043e-05, 7.0741004987582161e-06, 7.6355680403038401e-07, 6.4623052172886120e-08, 4.2306685774284424e-09, 2.1076390184671402e-10, 7.8326447571213533e-12, 2.1189539626185899e-13, 4.0473768240447191e-15, 5.2503117409060339e-17, 4.3966970036273617e-19, 2.2196939309444735e-21, 6.1353803600426939e-24, 8.0378813038410338e-27, 3.9415951369162550e-30, 4.6271645012802355e-34, 4.2115420614105446e-39}, + {6.3684623301529066e-40, 7.6617679179706699e-35, 7.0570663748570958e-31, 1.5468771288046908e-27, 1.2648661239395541e-24, 4.8919455331107564e-22, 1.0345305017520525e-19, 1.3179732316466649e-17, 1.0835445640249948e-15, 6.0495805864229647e-14, 2.3852254108327101e-12, 6.8487736158296791e-11, 1.4678463337326563e-09, 2.3957838556591937e-08, 3.0275650879319551e-07, 3.0032131335980235e-06, 2.3654729185615187e-05, 1.4937604708377004e-04, 7.6242846753152228e-04, 3.1668653729621131e-03, 1.0765666029311394e-02, 3.0093535038790555e-02, 6.9436105549292540e-02, 1.3264501499247186e-01, 2.1027400626010295e-01, 2.7705564403537380e-01, 3.0370259492878027e-01, 2.7705564403537380e-01, 2.1027400626010295e-01, 1.3264501499247186e-01, 6.9436105549292540e-02, 3.0093535038790555e-02, 1.0765666029311394e-02, 3.1668653729621131e-03, 7.6242846753152228e-04, 1.4937604708377004e-04, 2.3654729185615187e-05, 3.0032131335980235e-06, 3.0275650879319551e-07, 2.3957838556591937e-08, 1.4678463337326563e-09, 6.8487736158296791e-11, 2.3852254108327101e-12, 6.0495805864229647e-14, 1.0835445640249948e-15, 1.3179732316466649e-17, 1.0345305017520525e-19, 4.8919455331107564e-22, 1.2648661239395541e-24, 1.5468771288046908e-27, 7.0570663748570958e-31, 7.6617679179706699e-35, 6.3684623301529066e-40}, + {9.6165697698301258e-41, 1.2653200760168758e-35, 1.2587808691128722e-31, 2.9626275871495710e-28, 2.5923371557456032e-25, 1.0706490586422193e-22, 2.4146919999727056e-20, 3.2782519697898691e-18, 2.8709892632049820e-16, 1.7073406733468467e-14, 7.1713449978551876e-13, 2.1943984676811026e-11, 5.0147398704735039e-10, 8.7334448358337394e-09, 1.1786188465819090e-07, 1.2498100284112936e-06, 1.0535444441825744e-05, 7.1294347272485073e-05, 3.9051617266315898e-04, 1.7435254219654911e-03, 6.3820594170464536e-03, 1.9246441370539501e-02, 4.8010306161295493e-02, 9.9382787160472649e-02, 1.7114652799601413e-01, 2.4564247050424473e-01, 2.9419908452729160e-01, 2.9419908452729160e-01, 2.4564247050424473e-01, 1.7114652799601413e-01, 9.9382787160472649e-02, 4.8010306161295493e-02, 1.9246441370539501e-02, 6.3820594170464536e-03, 1.7435254219654911e-03, 3.9051617266315898e-04, 7.1294347272485073e-05, 1.0535444441825744e-05, 1.2498100284112936e-06, 1.1786188465819090e-07, 8.7334448358337394e-09, 5.0147398704735039e-10, 2.1943984676811026e-11, 7.1713449978551876e-13, 1.7073406733468467e-14, 2.8709892632049820e-16, 3.2782519697898691e-18, 2.4146919999727056e-20, 1.0706490586422193e-22, 2.5923371557456032e-25, 2.9626275871495710e-28, 1.2587808691128722e-31, 1.2653200760168758e-35, 9.6165697698301258e-41}, + {1.4501627690036662e-41, 2.0843249634724133e-36, 2.2371881417054147e-32, 5.6477366517509067e-29, 5.2828491369827090e-26, 2.3275184070080019e-23, 5.5924703344128403e-21, 8.0822735455939761e-19, 7.5316452507313807e-17, 4.7652984604189149e-15, 2.1297535284773726e-13, 6.9364439628016448e-12, 1.6879993347401012e-10, 3.1324958261028878e-09, 4.5081881972300138e-08, 5.1027034733995817e-07, 4.5962183144073910e-06, 3.3274977701846682e-05, 1.9525422369452320e-04, 9.3526439804451304e-04, 3.6789367196008232e-03, 1.1943896271882769e-02, 3.2137739232619873e-02, 7.1912783366758826e-02, 1.3418063914176925e-01, 2.0919736551904625e-01, 2.7291625193942631e-01, 2.9818072956643887e-01, 2.7291625193942631e-01, 2.0919736551904625e-01, 1.3418063914176925e-01, 7.1912783366758826e-02, 3.2137739232619873e-02, 1.1943896271882769e-02, 3.6789367196008232e-03, 9.3526439804451304e-04, 1.9525422369452320e-04, 3.3274977701846682e-05, 4.5962183144073910e-06, 5.1027034733995817e-07, 4.5081881972300138e-08, 3.1324958261028878e-09, 1.6879993347401012e-10, 6.9364439628016448e-12, 2.1297535284773726e-13, 4.7652984604189149e-15, 7.5316452507313807e-17, 8.0822735455939761e-19, 5.5924703344128403e-21, 2.3275184070080019e-23, 5.2828491369827090e-26, 5.6477366517509067e-29, 2.2371881417054147e-32, 2.0843249634724133e-36, 1.4501627690036662e-41}, + {2.1839473796203715e-42, 3.4249840843882790e-37, 3.9621540898960065e-33, 1.0717993883210793e-29, 1.0706713589643687e-26, 5.0270999187295385e-24, 1.2855363897049299e-21, 1.9756668115390835e-19, 1.9569261785647621e-17, 1.3158561251396991e-15, 6.2504456297525029e-14, 2.1641925885012134e-12, 5.6013978504685036e-11, 1.1062006976882208e-09, 1.6954324255991913e-08, 2.0454464536460739e-07, 1.9657534004009810e-06, 1.5201081492284489e-05, 9.5395991047773378e-05, 4.8937293565704996e-04, 2.0647475636031381e-03, 7.2020522320410518e-03, 2.0858574140157814e-02, 5.0338397424815960e-02, 1.0151939271798682e-01, 1.7147724762127156e-01, 2.4298927099272355e-01, 2.8917508433514816e-01, 2.8917508433514816e-01, 2.4298927099272355e-01, 1.7147724762127156e-01, 1.0151939271798682e-01, 5.0338397424815960e-02, 2.0858574140157814e-02, 7.2020522320410518e-03, 2.0647475636031381e-03, 4.8937293565704996e-04, 9.5395991047773378e-05, 1.5201081492284489e-05, 1.9657534004009810e-06, 2.0454464536460739e-07, 1.6954324255991913e-08, 1.1062006976882208e-09, 5.6013978504685036e-11, 2.1641925885012134e-12, 6.2504456297525029e-14, 1.3158561251396991e-15, 1.9569261785647621e-17, 1.9756668115390835e-19, 1.2855363897049299e-21, 5.0270999187295385e-24, 1.0706713589643687e-26, 1.0717993883210793e-29, 3.9621540898960065e-33, 3.4249840843882790e-37, 2.1839473796203715e-42}, + {3.2848343922234264e-43, 5.6145192176094857e-38, 6.9933335612180924e-34, 2.0251468211785233e-30, 2.1584037474070782e-27, 1.0789794198158127e-24, 2.9336812927661561e-22, 4.7897086011228863e-20, 5.0376705984946099e-18, 3.5961584198415702e-16, 1.8135512160129682e-14, 6.6680503871104131e-13, 1.8333727853050702e-11, 3.8483200507286178e-10, 6.2732332422802088e-09, 8.0560041690845556e-08, 8.2486418628805857e-07, 6.8030638512964077e-06, 4.5587459694050582e-05, 2.5003668451320217e-04, 1.1295333257645079e-03, 4.2250842236442390e-03, 1.3144726459581649e-02, 3.4139801128400288e-02, 7.4247675370613914e-02, 1.3553970687329148e-01, 2.0807036460654699e-01, 2.6895194980711801e-01, 2.9294948869685189e-01, 2.6895194980711801e-01, 2.0807036460654699e-01, 1.3553970687329148e-01, 7.4247675370613914e-02, 3.4139801128400288e-02, 1.3144726459581649e-02, 4.2250842236442390e-03, 1.1295333257645079e-03, 2.5003668451320217e-04, 4.5587459694050582e-05, 6.8030638512964077e-06, 8.2486418628805857e-07, 8.0560041690845556e-08, 6.2732332422802088e-09, 3.8483200507286178e-10, 1.8333727853050702e-11, 6.6680503871104131e-13, 1.8135512160129682e-14, 3.5961584198415702e-16, 5.0376705984946099e-18, 4.7897086011228863e-20, 2.9336812927661561e-22, 1.0789794198158127e-24, 2.1584037474070782e-27, 2.0251468211785233e-30, 6.9933335612180924e-34, 5.6145192176094857e-38, 3.2848343922234264e-43}, + {4.9345427975166703e-44, 9.1824526100660134e-39, 1.2302868650409080e-34, 3.8103303738430430e-31, 4.3288355988163862e-28, 2.3018029777481733e-25, 6.6480276615029978e-23, 1.1519651049881098e-20, 1.2852645022546249e-18, 9.7305218355116897e-17, 5.2042716465726346e-15, 2.0297402247949017e-13, 5.9217773854289703e-12, 1.3196011058824996e-10, 2.2850766766300011e-09, 3.1195246571716635e-08, 3.3984745324530809e-07, 2.9851306091787731e-06, 2.1327339454200749e-05, 1.2486893055641099e-04, 6.0296061313673489e-04, 2.4143454547297083e-03, 8.0534582747568747e-03, 2.2465314158278335e-02, 5.2574374089316610e-02, 1.0348723259331935e-01, 1.7168192789310016e-01, 2.4039805219536928e-01, 2.8439970531426456e-01, 2.8439970531426456e-01, 2.4039805219536928e-01, 1.7168192789310016e-01, 1.0348723259331935e-01, 5.2574374089316610e-02, 2.2465314158278335e-02, 8.0534582747568747e-03, 2.4143454547297083e-03, 6.0296061313673489e-04, 1.2486893055641099e-04, 2.1327339454200749e-05, 2.9851306091787731e-06, 3.3984745324530809e-07, 3.1195246571716635e-08, 2.2850766766300011e-09, 1.3196011058824996e-10, 5.9217773854289703e-12, 2.0297402247949017e-13, 5.2042716465726346e-15, 9.7305218355116897e-17, 1.2852645022546249e-18, 1.1519651049881098e-20, 6.6480276615029978e-23, 2.3018029777481733e-25, 4.3288355988163862e-28, 3.8103303738430430e-31, 1.2302868650409080e-34, 9.1824526100660134e-39, 4.9345427975166703e-44}, + {7.4038563068673450e-45, 1.4983962534795572e-39, 2.1574506027269642e-35, 7.1398344998607888e-32, 8.6385560494218303e-29, 4.8816444464632883e-26, 1.4963121942445614e-23, 2.7492726789010400e-21, 3.2508143970587746e-19, 2.6076354448061946e-17, 1.4776310161414783e-15, 6.1066717751743867e-14, 1.8884472351365658e-12, 4.4624672633249920e-11, 8.1989628692240572e-10, 1.1884210228039399e-08, 1.3757431403862670e-07, 1.2852403270784334e-06, 9.7761956199732341e-06, 6.1008880084875632e-05, 3.1439538907451493e-04, 1.3453332060777454e-03, 4.8029120328152543e-03, 1.4362559357587188e-02, 3.6095769719147547e-02, 7.6447309674074940e-02, 1.3673928335964028e-01, 2.0690383287647826e-01, 2.6515118763397444e-01, 2.8798424312571891e-01, 2.6515118763397444e-01, 2.0690383287647826e-01, 1.3673928335964028e-01, 7.6447309674074940e-02, 3.6095769719147547e-02, 1.4362559357587188e-02, 4.8029120328152543e-03, 1.3453332060777454e-03, 3.1439538907451493e-04, 6.1008880084875632e-05, 9.7761956199732341e-06, 1.2852403270784334e-06, 1.3757431403862670e-07, 1.1884210228039399e-08, 8.1989628692240572e-10, 4.4624672633249920e-11, 1.8884472351365658e-12, 6.1066717751743867e-14, 1.4776310161414783e-15, 2.6076354448061946e-17, 3.2508143970587746e-19, 2.7492726789010400e-21, 1.4963121942445614e-23, 4.8816444464632883e-26, 8.6385560494218303e-29, 7.1398344998607888e-32, 2.1574506027269642e-35, 1.4983962534795572e-39, 7.4038563068673450e-45}, + {1.1095872479683389e-45, 2.4397475881451687e-40, 3.7716267271207567e-36, 1.3325596117642357e-32, 1.7155731476717639e-29, 1.0294059971650915e-26, 3.3457569557525580e-24, 6.5125672574964802e-22, 8.1536404730238284e-20, 6.9232479095776861e-18, 4.1524441096940554e-16, 1.8166245762596555e-14, 5.9484305160561044e-13, 1.4889573490628030e-11, 2.8993590128077474e-10, 4.4568227752259551e-09, 5.4755546192766962e-08, 5.4335161342049202e-07, 4.3942869362670327e-06, 2.9187419041555301e-05, 1.6027733468184521e-04, 7.3177355696550823e-04, 2.7913248289530633e-03, 8.9321783603078207e-03, 2.4061272766109355e-02, 5.4718970932182816e-02, 1.0529876369778575e-01, 1.7177615691888495e-01, 2.3786890495865878e-01, 2.7985311752282899e-01, 2.7985311752282899e-01, 2.3786890495865878e-01, 1.7177615691888495e-01, 1.0529876369778575e-01, 5.4718970932182816e-02, 2.4061272766109355e-02, 8.9321783603078207e-03, 2.7913248289530633e-03, 7.3177355696550823e-04, 1.6027733468184521e-04, 2.9187419041555301e-05, 4.3942869362670327e-06, 5.4335161342049202e-07, 5.4755546192766962e-08, 4.4568227752259551e-09, 2.8993590128077474e-10, 1.4889573490628030e-11, 5.9484305160561044e-13, 1.8166245762596555e-14, 4.1524441096940554e-16, 6.9232479095776861e-18, 8.1536404730238284e-20, 6.5125672574964802e-22, 3.3457569557525580e-24, 1.0294059971650915e-26, 1.7155731476717639e-29, 1.3325596117642357e-32, 3.7716267271207567e-36, 2.4397475881451687e-40, 1.1095872479683389e-45}, + {1.6610070486206728e-46, 3.9640620009950677e-41, 6.5736876067220763e-37, 2.4774746124224036e-33, 3.3910839755167296e-30, 2.1587655850502334e-27, 7.4335800238463694e-25, 1.5315980968945761e-22, 2.0285571447032586e-20, 1.8216160573946239e-18, 1.1553699025986796e-16, 5.3454835391987630e-15, 1.8515162945489592e-13, 4.9041814317738659e-12, 1.0110041892763622e-10, 1.6462612023799091e-09, 2.1440032177267756e-08, 2.2570860520414515e-07, 1.9382734960996544e-06, 1.3684069297535329e-05, 7.9958097609494878e-05, 3.8892085371592777e-04, 1.5825583090958971e-03, 5.4099296624677247e-03, 1.5592290312662006e-02, 3.8002651439240136e-02, 7.8518270158397185e-02, 1.3779465152760539e-01, 2.0570683105394089e-01, 2.6150339781427412e-01, 2.8326318995972372e-01, 2.6150339781427412e-01, 2.0570683105394089e-01, 1.3779465152760539e-01, 7.8518270158397185e-02, 3.8002651439240136e-02, 1.5592290312662006e-02, 5.4099296624677247e-03, 1.5825583090958971e-03, 3.8892085371592777e-04, 7.9958097609494878e-05, 1.3684069297535329e-05, 1.9382734960996544e-06, 2.2570860520414515e-07, 2.1440032177267756e-08, 1.6462612023799091e-09, 1.0110041892763622e-10, 4.9041814317738659e-12, 1.8515162945489592e-13, 5.3454835391987630e-15, 1.1553699025986796e-16, 1.8216160573946239e-18, 2.0285571447032586e-20, 1.5315980968945761e-22, 7.4335800238463694e-25, 2.1587655850502334e-27, 3.3910839755167296e-30, 2.4774746124224036e-33, 6.5736876067220763e-37, 3.9640620009950677e-41, 1.6610070486206728e-46}, + {2.4837138180536654e-47, 6.4274569671736483e-42, 1.1424028966725505e-37, 4.5888574043976661e-34, 6.6725110959391675e-31, 4.5029239074522869e-28, 1.6414116353925588e-25, 3.5767852999576706e-23, 5.0073739324943669e-21, 4.7513038441234886e-19, 3.1838887747718650e-17, 1.5564176512276732e-15, 5.6970949884188746e-14, 1.5952148801760892e-12, 3.4779437587729222e-11, 5.9926928642653631e-10, 8.2638647618516911e-09, 9.2185737335790556e-08, 8.3956368818335782e-07, 6.2919256841286273e-06, 3.9066932688710276e-05, 2.0215217999457319e-04, 8.7616004129601344e-04, 3.1945104951283309e-03, 9.8342822671495106e-03, 2.5641844544669879e-02, 5.6773556441129344e-02, 1.0696556035928920e-01, 1.7177351127893237e-01, 2.3540141376649018e-01, 2.7551763457131306e-01, 2.7551763457131306e-01, 2.3540141376649018e-01, 1.7177351127893237e-01, 1.0696556035928920e-01, 5.6773556441129344e-02, 2.5641844544669879e-02, 9.8342822671495106e-03, 3.1945104951283309e-03, 8.7616004129601344e-04, 2.0215217999457319e-04, 3.9066932688710276e-05, 6.2919256841286273e-06, 8.3956368818335782e-07, 9.2185737335790556e-08, 8.2638647618516911e-09, 5.9926928642653631e-10, 3.4779437587729222e-11, 1.5952148801760892e-12, 5.6970949884188746e-14, 1.5564176512276732e-15, 3.1838887747718650e-17, 4.7513038441234886e-19, 5.0073739324943669e-21, 3.5767852999576706e-23, 1.6414116353925588e-25, 4.5029239074522869e-28, 6.6725110959391675e-31, 4.5888574043976661e-34, 1.1424028966725505e-37, 6.4274569671736483e-42, 2.4837138180536654e-47}, + {3.7099206361930349e-48, 1.0400778615224128e-42, 1.9796804708319897e-38, 8.4687478191905945e-35, 1.3071305930820806e-31, 9.3437837175659029e-29, 3.6027426635285024e-26, 8.2963863116210883e-24, 1.2266629909143781e-21, 1.2288435628835336e-19, 8.6925536958459408e-18, 4.4857058689315790e-16, 1.7335817955789140e-14, 5.1265062385198317e-13, 1.1808921844569749e-11, 2.1508698297874976e-10, 3.1371929535383148e-09, 3.7041625984897139e-08, 3.5734732949990906e-07, 2.8393114498469317e-06, 1.8709113003788699e-05, 1.0284880800685653e-04, 4.7411702610320811e-04, 1.8409222622442125e-03, 6.0436044551375788e-03, 1.6829299199652096e-02, 3.9858264027817066e-02, 8.0467087994200825e-02, 1.3871950817658463e-01, 2.0448695346897386e-01, 2.5799889943138321e-01, 2.7876694884925185e-01, 2.5799889943138321e-01, 2.0448695346897386e-01, 1.3871950817658463e-01, 8.0467087994200825e-02, 3.9858264027817066e-02, 1.6829299199652096e-02, 6.0436044551375788e-03, 1.8409222622442125e-03, 4.7411702610320811e-04, 1.0284880800685653e-04, 1.8709113003788699e-05, 2.8393114498469317e-06, 3.5734732949990906e-07, 3.7041625984897139e-08, 3.1371929535383148e-09, 2.1508698297874976e-10, 1.1808921844569749e-11, 5.1265062385198317e-13, 1.7335817955789140e-14, 4.4857058689315790e-16, 8.6925536958459408e-18, 1.2288435628835336e-19, 1.2266629909143781e-21, 8.2963863116210883e-24, 3.6027426635285024e-26, 9.3437837175659029e-29, 1.3071305930820806e-31, 8.4687478191905945e-35, 1.9796804708319897e-38, 1.0400778615224128e-42, 3.7099206361930349e-48}, + {5.5357065358570184e-49, 1.6797479901081275e-43, 3.4211380112558623e-39, 1.5573906246297621e-35, 2.5496608991129390e-32, 1.9291035954649827e-29, 7.8617977889259561e-27, 1.9117068833006383e-24, 2.9828627842798555e-22, 3.1522545665038165e-20, 2.3518847106758435e-18, 1.2800933913224359e-16, 5.2186237265908379e-15, 1.6283407307097284e-13, 3.9591777669477542e-12, 7.6152172501454727e-11, 1.1736167423215493e-09, 1.4651253164761138e-08, 1.4955329367272515e-07, 1.2583402510311900e-06, 8.7884992308503793e-06, 5.1259291357862856e-05, 2.5098369851306242e-04, 1.0363290995075809e-03, 3.6225869785344623e-03, 1.0756040509879146e-02, 2.7203128953688913e-02, 5.8739981964099283e-02, 1.0849834930618682e-01, 1.7168584234908363e-01, 2.3299478606267793e-01, 2.7137742494130401e-01, 2.7137742494130401e-01, 2.3299478606267793e-01, 1.7168584234908363e-01, 1.0849834930618682e-01, 5.8739981964099283e-02, 2.7203128953688913e-02, 1.0756040509879146e-02, 3.6225869785344623e-03, 1.0363290995075809e-03, 2.5098369851306242e-04, 5.1259291357862856e-05, 8.7884992308503793e-06, 1.2583402510311900e-06, 1.4955329367272515e-07, 1.4651253164761138e-08, 1.1736167423215493e-09, 7.6152172501454727e-11, 3.9591777669477542e-12, 1.6283407307097284e-13, 5.2186237265908379e-15, 1.2800933913224359e-16, 2.3518847106758435e-18, 3.1522545665038165e-20, 2.9828627842798555e-22, 1.9117068833006383e-24, 7.8617977889259561e-27, 1.9291035954649827e-29, 2.5496608991129390e-32, 1.5573906246297621e-35, 3.4211380112558623e-39, 1.6797479901081275e-43, 5.5357065358570184e-49}, + {8.2516107962538437e-50, 2.7076758452831307e-44, 5.8962844659788279e-40, 2.8541849032786616e-36, 4.9525862550205175e-33, 3.9632869870747322e-30, 1.7059115810757949e-27, 4.3769741948718935e-25, 7.2016107891350715e-23, 8.0222187354240242e-21, 6.3078910455861518e-19, 3.6181996190429121e-17, 1.5546635722380968e-15, 5.1139174817165822e-14, 1.3112516106390246e-12, 2.6608653477929730e-11, 4.3286561534485417e-10, 5.7075829327787572e-09, 6.1577962214505752e-08, 5.4804560350180002e-07, 4.0522493910237441e-06, 2.5045342890495838e-05, 1.3008291629845118e-04, 5.7039896752377221e-04, 2.1199816320368434e-03, 6.7014045380057391e-03, 1.8069433112703592e-02, 4.1661108762478506e-02, 8.2300163369735294e-02, 1.3952613948284390e-01, 2.0325057415444170e-01, 2.5462881185279007e-01, 2.7447822655926341e-01, 2.5462881185279007e-01, 2.0325057415444170e-01, 1.3952613948284390e-01, 8.2300163369735294e-02, 4.1661108762478506e-02, 1.8069433112703592e-02, 6.7014045380057391e-03, 2.1199816320368434e-03, 5.7039896752377221e-04, 1.3008291629845118e-04, 2.5045342890495838e-05, 4.0522493910237441e-06, 5.4804560350180002e-07, 6.1577962214505752e-08, 5.7075829327787572e-09, 4.3286561534485417e-10, 2.6608653477929730e-11, 1.3112516106390246e-12, 5.1139174817165822e-14, 1.5546635722380968e-15, 3.6181996190429121e-17, 6.3078910455861518e-19, 8.0222187354240242e-21, 7.2016107891350715e-23, 4.3769741948718935e-25, 1.7059115810757949e-27, 3.9632869870747322e-30, 4.9525862550205175e-33, 2.8541849032786616e-36, 5.8962844659788279e-40, 2.7076758452831307e-44, 8.2516107962538437e-50}, + {1.2287768797135238e-50, 4.3565748909654033e-45, 1.0135609150438053e-40, 5.2133092407201474e-37, 9.5811571508986169e-34, 8.1036840367508257e-31, 3.6813492354788247e-28, 9.9592645616067056e-26, 1.7266548206330479e-23, 2.0259038600763283e-21, 1.6775151863814584e-19, 1.0132362352411122e-17, 4.5848634437116816e-16, 1.5885532676287405e-14, 4.2916420558156765e-13, 9.1795670585092616e-12, 1.5747988216738595e-10, 2.1910095676436381e-09, 2.4958591861839229e-08, 2.3470996573719479e-07, 1.8351979221091958e-06, 1.2005278344250187e-05, 6.6061130219886947e-05, 3.0721561121964142e-04, 1.2123596600232957e-03, 4.0741349478589858e-03, 1.1693944851274627e-02, 2.8741855098732765e-02, 6.0620459149597836e-02, 1.0990705313380535e-01, 1.7152351798443127e-01, 2.3064795199119065e-01, 2.6741826939146512e-01, 2.6741826939146512e-01, 2.3064795199119065e-01, 1.7152351798443127e-01, 1.0990705313380535e-01, 6.0620459149597836e-02, 2.8741855098732765e-02, 1.1693944851274627e-02, 4.0741349478589858e-03, 1.2123596600232957e-03, 3.0721561121964142e-04, 6.6061130219886947e-05, 1.2005278344250187e-05, 1.8351979221091958e-06, 2.3470996573719479e-07, 2.4958591861839229e-08, 2.1910095676436381e-09, 1.5747988216738595e-10, 9.1795670585092616e-12, 4.2916420558156765e-13, 1.5885532676287405e-14, 4.5848634437116816e-16, 1.0132362352411122e-17, 1.6775151863814584e-19, 2.0259038600763283e-21, 1.7266548206330479e-23, 9.9592645616067056e-26, 3.6813492354788247e-28, 8.1036840367508257e-31, 9.5811571508986169e-34, 5.2133092407201474e-37, 1.0135609150438053e-40, 4.3565748909654033e-45, 1.2287768797135238e-50}, + {1.8280449098224982e-51, 6.9969776104465074e-46, 1.7378601313821812e-41, 9.4914073654790101e-38, 1.8462398438517290e-34, 1.6492772853150654e-31, 7.9020561032723045e-29, 2.2524636987884908e-26, 4.1119507972824725e-24, 5.0779932729853307e-22, 4.4245805201641825e-20, 2.8120140377689001e-18, 1.3389362360428643e-16, 4.8824398317753951e-15, 1.3886060911907966e-13, 3.1279303248480510e-12, 5.6537332414960619e-11, 8.2920364429410743e-10, 9.9634336551576826e-09, 9.8898818048931736e-08, 8.1685444112022656e-07, 5.6493811974978918e-06, 3.2895750894750603e-05, 1.6204473635815332e-04, 6.7809290318947399e-04, 2.4191591440605796e-03, 7.3808332831545517e-03, 1.9308982903048826e-02, 4.3410259562275427e-02, 8.4023710374037747e-02, 1.4022557730554358e-01, 2.0200304815121278e-01, 2.5138497704677004e-01, 2.7038153661061759e-01, 2.5138497704677004e-01, 2.0200304815121278e-01, 1.4022557730554358e-01, 8.4023710374037747e-02, 4.3410259562275427e-02, 1.9308982903048826e-02, 7.3808332831545517e-03, 2.4191591440605796e-03, 6.7809290318947399e-04, 1.6204473635815332e-04, 3.2895750894750603e-05, 5.6493811974978918e-06, 8.1685444112022656e-07, 9.8898818048931736e-08, 9.9634336551576826e-09, 8.2920364429410743e-10, 5.6537332414960619e-11, 3.1279303248480510e-12, 1.3886060911907966e-13, 4.8824398317753951e-15, 1.3389362360428643e-16, 2.8120140377689001e-18, 4.4245805201641825e-20, 5.0779932729853307e-22, 4.1119507972824725e-24, 2.2524636987884908e-26, 7.9020561032723045e-29, 1.6492772853150654e-31, 1.8462398438517290e-34, 9.4914073654790101e-38, 1.7378601313821812e-41, 6.9969776104465074e-46, 1.8280449098224982e-51}, + {2.7170067116730165e-52, 1.1217925177026293e-46, 2.9723642655668546e-42, 1.7225457466828413e-38, 3.5439568636689488e-35, 3.3415178524750795e-32, 1.6874060730443393e-29, 5.0645263679858964e-27, 9.7283658177698223e-25, 1.2635945997114491e-22, 1.1577247535043669e-20, 7.7362132775431355e-19, 3.8731516902515290e-17, 1.4852494321530914e-15, 4.4433093884802028e-14, 1.0531630647084200e-12, 2.0038587880644725e-11, 3.0952986928769617e-10, 3.9193048318854111e-09, 4.1023319776043747e-08, 3.5754993018691617e-07, 2.6114965376035973e-06, 1.6073154232928773e-05, 8.3767928571091071e-05, 3.7124104714178821e-04, 1.4042112162131032e-03, 4.5476632686124660e-03, 1.2644719871722365e-02, 3.0255311010248965e-02, 6.2417460794691487e-02, 1.1120083831262205e-01, 1.7129562704597320e-01, 2.2835964147332644e-01, 2.6362735600964210e-01, 2.6362735600964210e-01, 2.2835964147332644e-01, 1.7129562704597320e-01, 1.1120083831262205e-01, 6.2417460794691487e-02, 3.0255311010248965e-02, 1.2644719871722365e-02, 4.5476632686124660e-03, 1.4042112162131032e-03, 3.7124104714178821e-04, 8.3767928571091071e-05, 1.6073154232928773e-05, 2.6114965376035973e-06, 3.5754993018691617e-07, 4.1023319776043747e-08, 3.9193048318854111e-09, 3.0952986928769617e-10, 2.0038587880644725e-11, 1.0531630647084200e-12, 4.4433093884802028e-14, 1.4852494321530914e-15, 3.8731516902515290e-17, 7.7362132775431355e-19, 1.1577247535043669e-20, 1.2635945997114491e-22, 9.7283658177698223e-25, 5.0645263679858964e-27, 1.6874060730443393e-29, 3.3415178524750795e-32, 3.5439568636689488e-35, 1.7225457466828413e-38, 2.9723642655668546e-42, 1.1217925177026293e-46, 2.7170067116730165e-52}, + {4.0345457983197185e-53, 1.7954384298058220e-47, 5.0715303590978945e-43, 3.1165183087668226e-39, 6.7773962594083074e-36, 6.7403932258482419e-33, 3.5851439372856567e-30, 1.1322450883416873e-27, 2.2869723112554000e-25, 3.1221586704548222e-23, 3.0058381695419005e-21, 2.1103468793130292e-19, 1.1100994988590987e-17, 4.4732478501982463e-16, 1.4065409569369246e-14, 3.5050786947688594e-13, 7.0144682351913210e-12, 1.1401392553489413e-10, 1.5199381740983112e-09, 1.6759992864221019e-08, 1.5399292502874990e-07, 1.1865872353918687e-06, 7.7110412769679424e-06, 4.2469576433922949e-05, 1.9909609055329152e-04, 7.9743820114063489e-04, 2.7377658998792736e-03, 8.0794563303749761e-03, 2.0544655922552182e-02, 4.5105267291699995e-02, 8.5643719556781017e-02, 1.4082773794401451e-01, 2.0074887688731419e-01, 2.4825988992112150e-01, 2.6646296361626087e-01, 2.4825988992112150e-01, 2.0074887688731419e-01, 1.4082773794401451e-01, 8.5643719556781017e-02, 4.5105267291699995e-02, 2.0544655922552182e-02, 8.0794563303749761e-03, 2.7377658998792736e-03, 7.9743820114063489e-04, 1.9909609055329152e-04, 4.2469576433922949e-05, 7.7110412769679424e-06, 1.1865872353918687e-06, 1.5399292502874990e-07, 1.6759992864221019e-08, 1.5199381740983112e-09, 1.1401392553489413e-10, 7.0144682351913210e-12, 3.5050786947688594e-13, 1.4065409569369246e-14, 4.4732478501982463e-16, 1.1100994988590987e-17, 2.1103468793130292e-19, 3.0058381695419005e-21, 3.1221586704548222e-23, 2.2869723112554000e-25, 1.1322450883416873e-27, 3.5851439372856567e-30, 6.7403932258482419e-33, 6.7773962594083074e-36, 3.1165183087668226e-39, 5.0715303590978945e-43, 1.7954384298058220e-47, 4.0345457983197185e-53}, + {5.9856092466933942e-54, 2.8688168912332612e-48, 8.6328113687066931e-44, 5.6216222243961033e-40, 1.2913788025337670e-36, 1.3538428107777088e-33, 7.5798318604310986e-31, 2.5172693785018537e-28, 5.3430216209626571e-26, 7.6615923972613038e-24, 7.7454736745174986e-22, 5.7095124323046545e-20, 3.1533210598724162e-18, 1.3342434681247850e-16, 4.4061175397950322e-15, 1.1534952560183679e-13, 2.4259623022354819e-12, 4.1457910332486197e-11, 5.8137344484280929e-10, 6.7473312881324816e-09, 6.5292934189484169e-08, 5.3024856335051780e-07, 3.6344904047182492e-06, 2.1131233267306212e-05, 1.0466994285006789e-04, 4.4339999663332603e-04, 1.6117353953558448e-03, 5.0416367476379337e-03, 1.3605327560618538e-02, 3.1741278190050709e-02, 6.4133640985369098e-02, 1.1238816501981971e-01, 1.7101015293603891e-01, 2.2612844383734518e-01, 2.5999310620316046e-01, 2.5999310620316046e-01, 2.2612844383734518e-01, 1.7101015293603891e-01, 1.1238816501981971e-01, 6.4133640985369098e-02, 3.1741278190050709e-02, 1.3605327560618538e-02, 5.0416367476379337e-03, 1.6117353953558448e-03, 4.4339999663332603e-04, 1.0466994285006789e-04, 2.1131233267306212e-05, 3.6344904047182492e-06, 5.3024856335051780e-07, 6.5292934189484169e-08, 6.7473312881324816e-09, 5.8137344484280929e-10, 4.1457910332486197e-11, 2.4259623022354819e-12, 1.1534952560183679e-13, 4.4061175397950322e-15, 1.3342434681247850e-16, 3.1533210598724162e-18, 5.7095124323046545e-20, 7.7454736745174986e-22, 7.6615923972613038e-24, 5.3430216209626571e-26, 2.5172693785018537e-28, 7.5798318604310986e-31, 1.3538428107777088e-33, 1.2913788025337670e-36, 5.6216222243961033e-40, 8.6328113687066931e-44, 2.8688168912332612e-48, 5.9856092466933942e-54}, + {8.8724008630942898e-55, 4.5764336789075590e-49, 1.4661118038718265e-44, 1.0110662325251453e-40, 2.4518913381167023e-37, 2.7079520650401302e-34, 1.5949041770861358e-31, 5.5663539164360154e-29, 1.2407683405472676e-26, 1.8675901831656063e-24, 1.9812686302523555e-22, 1.5323733317270031e-20, 8.8796168315044913e-19, 3.9423704233496054e-17, 1.3663145902821194e-15, 3.7548696680658361e-14, 8.2926419028182389e-13, 1.4887527478920644e-11, 2.1942330999743630e-10, 2.6779761171072075e-09, 2.7267833016134243e-08, 2.3316541347245123e-07, 1.6840172739131284e-06, 1.0325059077129107e-05, 5.3979561403797981e-05, 2.4157232920980263e-04, 9.2859086457657155e-04, 3.0750221611855083e-03, 8.7949222136699829e-03, 2.1773546737772456e-02, 4.6746077576099838e-02, 8.7165933915876653e-02, 1.4134154505606342e-01, 1.9949184460058894e-01, 2.4524663594920437e-01, 2.6270996412870795e-01, 2.4524663594920437e-01, 1.9949184460058894e-01, 1.4134154505606342e-01, 8.7165933915876653e-02, 4.6746077576099838e-02, 2.1773546737772456e-02, 8.7949222136699829e-03, 3.0750221611855083e-03, 9.2859086457657155e-04, 2.4157232920980263e-04, 5.3979561403797981e-05, 1.0325059077129107e-05, 1.6840172739131284e-06, 2.3316541347245123e-07, 2.7267833016134243e-08, 2.6779761171072075e-09, 2.1942330999743630e-10, 1.4887527478920644e-11, 8.2926419028182389e-13, 3.7548696680658361e-14, 1.3663145902821194e-15, 3.9423704233496054e-17, 8.8796168315044913e-19, 1.5323733317270031e-20, 1.9812686302523555e-22, 1.8675901831656063e-24, 1.2407683405472676e-26, 5.5663539164360154e-29, 1.5949041770861358e-31, 2.7079520650401302e-34, 2.4518913381167023e-37, 1.0110662325251453e-40, 1.4661118038718265e-44, 4.5764336789075590e-49, 8.8724008630942898e-55}, + {1.3140200635759138e-55, 7.2888760600699374e-50, 2.4843223778452137e-45, 1.8132393982490279e-41, 4.6392142210443241e-38, 5.3944805170903356e-35, 3.3402996562304201e-32, 1.2244058147622891e-29, 2.8644542990100537e-27, 4.5229388132654362e-25, 5.0319775906458023e-23, 4.0808135693241622e-21, 2.4793963766166604e-19, 1.1542667556483506e-17, 4.1953024073558444e-16, 1.2094094650388391e-14, 2.8026693289669983e-13, 5.2816149659273362e-12, 8.1749589868013172e-11, 1.0483088420892190e-09, 1.1221758911496157e-08, 1.0094315168892042e-07, 7.6747273751899334e-07, 4.9572490208738044e-06, 2.7325285268221331e-05, 1.2904853700328517e-04, 5.2397811821303173e-04, 1.8346879155592502e-03, 5.5544997811365557e-03, 1.4572966566065007e-02, 3.3197971745097789e-02, 6.5771771087721614e-02, 1.1347683695023611e-01, 1.7067412122709255e-01, 2.2395285395671372e-01, 2.5650502626034899e-01, 2.5650502626034899e-01, 2.2395285395671372e-01, 1.7067412122709255e-01, 1.1347683695023611e-01, 6.5771771087721614e-02, 3.3197971745097789e-02, 1.4572966566065007e-02, 5.5544997811365557e-03, 1.8346879155592502e-03, 5.2397811821303173e-04, 1.2904853700328517e-04, 2.7325285268221331e-05, 4.9572490208738044e-06, 7.6747273751899334e-07, 1.0094315168892042e-07, 1.1221758911496157e-08, 1.0483088420892190e-09, 8.1749589868013172e-11, 5.2816149659273362e-12, 2.8026693289669983e-13, 1.2094094650388391e-14, 4.1953024073558444e-16, 1.1542667556483506e-17, 2.4793963766166604e-19, 4.0808135693241622e-21, 5.0319775906458023e-23, 4.5229388132654362e-25, 2.8644542990100537e-27, 1.2244058147622891e-29, 3.3402996562304201e-32, 5.3944805170903356e-35, 4.6392142210443241e-38, 1.8132393982490279e-41, 2.4843223778452137e-45, 7.2888760600699374e-50, 1.3140200635759138e-55}, + {1.9444622230234342e-56, 1.1590959320007943e-50, 4.2004740254236363e-46, 3.2427888315124139e-42, 8.7482381269078278e-39, 1.0703814562172511e-35, 6.9640785632250250e-33, 2.6794918791965289e-30, 6.5751748013020018e-28, 1.0884570120961755e-25, 1.2691625603633038e-23, 1.0785433636173751e-21, 6.8663309606135431e-20, 3.3495959873429566e-18, 1.2758954586949696e-16, 3.8555242748433330e-15, 9.3683796134838034e-14, 1.8518064702871477e-12, 3.0076840393622017e-11, 4.0491316393465588e-10, 4.5529601729418187e-09, 4.3045713494096147e-08, 3.4420843484101099e-07, 2.3399997161498497e-06, 1.3586053874631190e-05, 6.7639272623934896e-05, 2.8977924888595573e-04, 1.0716281610696826e-03, 3.4300764387647066e-03, 9.5249775695009746e-03, 2.2993107110436964e-02, 4.8332960504809425e-02, 8.8595835021937436e-02, 1.4177503840549346e-01, 1.9823513131250983e-01, 2.4233883536068279e-01, 2.5911119749680783e-01, 2.4233883536068279e-01, 1.9823513131250983e-01, 1.4177503840549346e-01, 8.8595835021937436e-02, 4.8332960504809425e-02, 2.2993107110436964e-02, 9.5249775695009746e-03, 3.4300764387647066e-03, 1.0716281610696826e-03, 2.8977924888595573e-04, 6.7639272623934896e-05, 1.3586053874631190e-05, 2.3399997161498497e-06, 3.4420843484101099e-07, 4.3045713494096147e-08, 4.5529601729418187e-09, 4.0491316393465588e-10, 3.0076840393622017e-11, 1.8518064702871477e-12, 9.3683796134838034e-14, 3.8555242748433330e-15, 1.2758954586949696e-16, 3.3495959873429566e-18, 6.8663309606135431e-20, 1.0785433636173751e-21, 1.2691625603633038e-23, 1.0884570120961755e-25, 6.5751748013020018e-28, 2.6794918791965289e-30, 6.9640785632250250e-33, 1.0703814562172511e-35, 8.7482381269078278e-39, 3.2427888315124139e-42, 4.2004740254236363e-46, 1.1590959320007943e-50, 1.9444622230234342e-56}, + {2.8750275727924455e-57, 1.8404303463880958e-51, 7.0869721836637015e-47, 5.7836152624626662e-43, 1.6442414677949876e-39, 2.1156822123723002e-36, 1.4455024437001548e-33, 5.8345675304162565e-31, 1.5008973228057372e-28, 2.6033049503053747e-26, 3.1794998286708481e-24, 2.8296018603048517e-22, 1.8863727782270500e-20, 9.6365678168475681e-19, 3.8443430855465295e-17, 1.2168900581339222e-15, 3.0981886195643928e-14, 6.4188571380482567e-13, 1.0931590521335809e-11, 1.5438256127811863e-10, 1.8219509376836273e-09, 1.8089441547445238e-08, 1.5199860776329110e-07, 1.0865550828327965e-06, 6.6384540614267379e-06, 3.4806103755504017e-05, 1.5717296348585755e-04, 6.1320670594855193e-04, 2.0727405318696742e-03, 6.0846962089377739e-03, 1.5545067446090813e-02, 3.4623986133714632e-02, 6.7334688728284187e-02, 1.1447404988622129e-01, 1.7029372558220210e-01, 2.2183130791546488e-01, 2.5315358016164968e-01, 2.5315358016164968e-01, 2.2183130791546488e-01, 1.7029372558220210e-01, 1.1447404988622129e-01, 6.7334688728284187e-02, 3.4623986133714632e-02, 1.5545067446090813e-02, 6.0846962089377739e-03, 2.0727405318696742e-03, 6.1320670594855193e-04, 1.5717296348585755e-04, 3.4806103755504017e-05, 6.6384540614267379e-06, 1.0865550828327965e-06, 1.5199860776329110e-07, 1.8089441547445238e-08, 1.8219509376836273e-09, 1.5438256127811863e-10, 1.0931590521335809e-11, 6.4188571380482567e-13, 3.0981886195643928e-14, 1.2168900581339222e-15, 3.8443430855465295e-17, 9.6365678168475681e-19, 1.8863727782270500e-20, 2.8296018603048517e-22, 3.1794998286708481e-24, 2.6033049503053747e-26, 1.5008973228057372e-28, 5.8345675304162565e-31, 1.4455024437001548e-33, 2.1156822123723002e-36, 1.6442414677949876e-39, 5.7836152624626662e-43, 7.0869721836637015e-47, 1.8404303463880958e-51, 2.8750275727924455e-57}, + {4.2475403944235563e-58, 2.9179360026092975e-52, 1.1932102199256711e-47, 1.0287869477179010e-43, 3.0804483195558287e-40, 4.1660662393372492e-37, 2.9874354212480538e-34, 1.2642951712027768e-31, 3.4074887052468082e-29, 6.1891475308279466e-27, 7.9129760878551264e-25, 7.3704570195170156e-23, 5.1421792395941592e-21, 2.7491455795179009e-19, 1.1478770068871720e-17, 3.8036255791351365e-16, 1.0139883410013013e-14, 2.2003659842875677e-13, 3.9263803072919160e-12, 5.8125114501326569e-11, 7.1939577649798698e-10, 7.4947098368604126e-09, 6.6118669991811844e-08, 4.9655916977568413e-07, 3.1895150634568674e-06, 1.7594600636505465e-05, 8.3660559585237938e-05, 3.4399085887424382e-04, 1.2265540580803703e-03, 3.8020227522452721e-03, 1.0267477817470316e-02, 2.4201116175054306e-02, 4.9866450712457495e-02, 8.9938636734284719e-02, 1.4213547000895149e-01, 1.9698140672796691e-01, 2.3953059321276829e-01, 2.5565638153018372e-01, 2.3953059321276829e-01, 1.9698140672796691e-01, 1.4213547000895149e-01, 8.9938636734284719e-02, 4.9866450712457495e-02, 2.4201116175054306e-02, 1.0267477817470316e-02, 3.8020227522452721e-03, 1.2265540580803703e-03, 3.4399085887424382e-04, 8.3660559585237938e-05, 1.7594600636505465e-05, 3.1895150634568674e-06, 4.9655916977568413e-07, 6.6118669991811844e-08, 7.4947098368604126e-09, 7.1939577649798698e-10, 5.8125114501326569e-11, 3.9263803072919160e-12, 2.2003659842875677e-13, 1.0139883410013013e-14, 3.8036255791351365e-16, 1.1478770068871720e-17, 2.7491455795179009e-19, 5.1421792395941592e-21, 7.3704570195170156e-23, 7.9129760878551264e-25, 6.1891475308279466e-27, 3.4074887052468082e-29, 1.2642951712027768e-31, 2.9874354212480538e-34, 4.1660662393372492e-37, 3.0804483195558287e-40, 1.0287869477179010e-43, 1.1932102199256711e-47, 2.9179360026092975e-52, 4.2475403944235563e-58}, + {6.2703784480694208e-59, 4.6195869591589206e-53, 2.0048780070281735e-48, 1.8252564480138844e-44, 5.7530583850395732e-41, 8.1734457929853433e-38, 6.1482072743115000e-35, 2.7266171296454801e-32, 7.6951427469170207e-30, 1.4628329302419815e-27, 1.9567429736662381e-25, 1.9064520843927174e-23, 1.3911463582850983e-21, 7.7788589853855015e-20, 3.3973551764091287e-18, 1.1777094633733961e-16, 3.2852244087268414e-15, 7.4617858659486148e-14, 1.3941377125806722e-12, 2.1618054623290873e-11, 2.8038686778996357e-10, 3.0626832246516170e-09, 2.8344707359971740e-08, 2.2345250981121576e-07, 1.5076264668245447e-06, 8.7420837008076225e-06, 4.3727831577546010e-05, 1.8929762178671690e-04, 7.1126362441827832e-04, 2.3254926708230895e-03, 6.6306857259903285e-03, 1.6519285009994170e-02, 3.6018246356681126e-02, 6.8825257394126579e-02, 1.1538643824874496e-01, 1.6987443543948361e-01, 2.1976221051624720e-01, 2.4993008013933904e-01, 2.4993008013933904e-01, 2.1976221051624720e-01, 1.6987443543948361e-01, 1.1538643824874496e-01, 6.8825257394126579e-02, 3.6018246356681126e-02, 1.6519285009994170e-02, 6.6306857259903285e-03, 2.3254926708230895e-03, 7.1126362441827832e-04, 1.8929762178671690e-04, 4.3727831577546010e-05, 8.7420837008076225e-06, 1.5076264668245447e-06, 2.2345250981121576e-07, 2.8344707359971740e-08, 3.0626832246516170e-09, 2.8038686778996357e-10, 2.1618054623290873e-11, 1.3941377125806722e-12, 7.4617858659486148e-14, 3.2852244087268414e-15, 1.1777094633733961e-16, 3.3973551764091287e-18, 7.7788589853855015e-20, 1.3911463582850983e-21, 1.9064520843927174e-23, 1.9567429736662381e-25, 1.4628329302419815e-27, 7.6951427469170207e-30, 2.7266171296454801e-32, 6.1482072743115000e-35, 8.1734457929853433e-38, 5.7530583850395732e-41, 1.8252564480138844e-44, 2.0048780070281735e-48, 4.6195869591589206e-53, 6.2703784480694208e-59}, + {9.2494982219878178e-60, 7.3032412797370021e-54, 3.3619702764053515e-49, 3.2301359968277160e-45, 1.0711545066976377e-41, 1.5978109726748470e-38, 1.2601224816663446e-35, 5.8531004842511326e-33, 1.7288387765755684e-30, 3.4377966700873511e-28, 4.8085158087733593e-26, 4.8977600911363362e-24, 3.7358525784193159e-22, 2.1835856119475800e-20, 9.9692083309512582e-19, 3.6131260931106432e-17, 1.0539595203667931e-15, 2.5039803161790368e-14, 4.8951189293680036e-13, 7.9452485251106098e-12, 1.0791168663568375e-10, 1.2349280054594245e-09, 1.1980389793173491e-08, 9.9059473817560524e-08, 7.0144004582899757e-07, 4.2716344520701190e-06, 2.2456298833005965e-05, 1.0225119927510267e-04, 4.0444792546155510e-04, 1.3933051824601373e-03, 4.1899160223157692e-03, 1.1020394106207396e-02, 2.5395651463267135e-02, 5.1347296466210786e-02, 9.1199284542961764e-02, 1.4242938912607919e-01, 1.9573290855318265e-01, 2.3681645470932214e-01, 2.5233616878303844e-01, 2.3681645470932214e-01, 1.9573290855318265e-01, 1.4242938912607919e-01, 9.1199284542961764e-02, 5.1347296466210786e-02, 2.5395651463267135e-02, 1.1020394106207396e-02, 4.1899160223157692e-03, 1.3933051824601373e-03, 4.0444792546155510e-04, 1.0225119927510267e-04, 2.2456298833005965e-05, 4.2716344520701190e-06, 7.0144004582899757e-07, 9.9059473817560524e-08, 1.1980389793173491e-08, 1.2349280054594245e-09, 1.0791168663568375e-10, 7.9452485251106098e-12, 4.8951189293680036e-13, 2.5039803161790368e-14, 1.0539595203667931e-15, 3.6131260931106432e-17, 9.9692083309512582e-19, 2.1835856119475800e-20, 3.7358525784193159e-22, 4.8977600911363362e-24, 4.8085158087733593e-26, 3.4377966700873511e-28, 1.7288387765755684e-30, 5.8531004842511326e-33, 1.2601224816663446e-35, 1.5978109726748470e-38, 1.0711545066976377e-41, 3.2301359968277160e-45, 3.3619702764053515e-49, 7.3032412797370021e-54, 9.2494982219878178e-60}, + {1.3633833300020003e-60, 1.1529935596394474e-54, 5.6267053619996539e-50, 5.7021852730627675e-46, 1.9884044482437607e-42, 3.1126000220972273e-39, 2.5723712996578709e-36, 1.2507839519363874e-33, 3.8645811266244288e-31, 8.0343028910788638e-29, 1.1744629608333255e-26, 1.2499248537371909e-24, 9.9604705585733289e-23, 6.0820538195831629e-21, 2.9010288549385599e-19, 1.0985973435650033e-17, 3.3490712214349002e-16, 8.3173189675616162e-15, 1.7001957813551391e-13, 2.8865604962002583e-12, 4.1025651516570179e-11, 4.9151895982232822e-10, 4.9945929385487262e-09, 4.3280820924798808e-08, 3.2138167253993492e-07, 2.0537028582318748e-06, 1.1336998395832870e-05, 5.4246298804851998e-05, 2.2565979982055683e-04, 8.1827502694065590e-04, 2.5924825356809312e-03, 7.1909572204228826e-03, 1.7493488621590211e-02, 3.7379964305875417e-02, 7.0246334697072893e-02, 1.1622011916471321e-01, 1.6942108833811217e-01, 2.1774395641632643e-01, 2.4682659213344721e-01, 2.4682659213344721e-01, 2.1774395641632643e-01, 1.6942108833811217e-01, 1.1622011916471321e-01, 7.0246334697072893e-02, 3.7379964305875417e-02, 1.7493488621590211e-02, 7.1909572204228826e-03, 2.5924825356809312e-03, 8.1827502694065590e-04, 2.2565979982055683e-04, 5.4246298804851998e-05, 1.1336998395832870e-05, 2.0537028582318748e-06, 3.2138167253993492e-07, 4.3280820924798808e-08, 4.9945929385487262e-09, 4.9151895982232822e-10, 4.1025651516570179e-11, 2.8865604962002583e-12, 1.7001957813551391e-13, 8.3173189675616162e-15, 3.3490712214349002e-16, 1.0985973435650033e-17, 2.9010288549385599e-19, 6.0820538195831629e-21, 9.9604705585733289e-23, 1.2499248537371909e-24, 1.1744629608333255e-26, 8.0343028910788638e-29, 3.8645811266244288e-31, 1.2507839519363874e-33, 2.5723712996578709e-36, 3.1126000220972273e-39, 1.9884044482437607e-42, 5.7021852730627675e-46, 5.6267053619996539e-50, 1.1529935596394474e-54, 1.3633833300020003e-60}, + {2.0081683556012850e-61, 1.8178162551753148e-55, 9.3991295413480502e-51, 1.0041756149620635e-46, 3.6803258437880526e-43, 6.0427427569366402e-40, 5.2306055163095921e-37, 2.6610906118130193e-34, 8.5963278572927171e-32, 1.8674862726204788e-29, 2.8515675215544967e-27, 3.1692521338966959e-25, 2.6370712657175804e-23, 1.6812873372296920e-21, 8.3735311688359131e-20, 3.3113569430928055e-18, 1.0543294854998749e-16, 2.7353878696405856e-15, 5.8430667493651178e-14, 1.0369888470878425e-12, 1.5412284525394938e-11, 1.9317783962508064e-10, 2.0546146868576734e-09, 1.8645196384240901e-08, 1.4507140693109981e-07, 9.7197681673778427e-07, 5.6294099461087388e-06, 2.8280775482696968e-05, 1.2361276486093516e-04, 4.7135721157038344e-04, 1.5717570688376730e-03, 4.5927856260634522e-03, 1.1781817217642985e-02, 2.6575061210558436e-02, 5.2776416531222697e-02, 9.2382459021801644e-02, 1.4266271740044509e-01, 1.9449150803253865e-01, 2.3419136519193123e-01, 2.4914204006426580e-01, 2.3419136519193123e-01, 1.9449150803253865e-01, 1.4266271740044509e-01, 9.2382459021801644e-02, 5.2776416531222697e-02, 2.6575061210558436e-02, 1.1781817217642985e-02, 4.5927856260634522e-03, 1.5717570688376730e-03, 4.7135721157038344e-04, 1.2361276486093516e-04, 2.8280775482696968e-05, 5.6294099461087388e-06, 9.7197681673778427e-07, 1.4507140693109981e-07, 1.8645196384240901e-08, 2.0546146868576734e-09, 1.9317783962508064e-10, 1.5412284525394938e-11, 1.0369888470878425e-12, 5.8430667493651178e-14, 2.7353878696405856e-15, 1.0543294854998749e-16, 3.3113569430928055e-18, 8.3735311688359131e-20, 1.6812873372296920e-21, 2.6370712657175804e-23, 3.1692521338966959e-25, 2.8515675215544967e-27, 1.8674862726204788e-29, 8.5963278572927171e-32, 2.6610906118130193e-34, 5.2306055163095921e-37, 6.0427427569366402e-40, 3.6803258437880526e-43, 1.0041756149620635e-46, 9.3991295413480502e-51, 1.8178162551753148e-55, 2.0081683556012850e-61}, + {2.9557746032980847e-62, 2.8621845857326094e-56, 1.5671564937749406e-51, 1.7642057043388989e-47, 6.7924330161546228e-44, 1.1692076998197370e-40, 1.0595146928277511e-37, 5.6371927794771982e-35, 1.9029906100319421e-32, 4.3178173430220290e-30, 6.8834570436337191e-28, 7.9851871981733358e-26, 6.9341198195289992e-24, 4.6134710745539610e-22, 2.3978402756179082e-20, 9.8965289896201795e-19, 3.2891620143645649e-17, 8.9094610406663587e-16, 1.9875208346984979e-14, 3.6848498201591518e-13, 5.7232797185020048e-12, 7.4997199146582833e-11, 8.3430559260867452e-10, 7.9229232891502669e-09, 6.4544629501196559e-08, 4.5305355658612973e-07, 2.7507246274012478e-06, 1.4496444191129691e-05, 6.6517412418153150e-05, 2.6647788669335111e-04, 9.3431768696117658e-04, 2.8731975330897244e-03, 7.7640394053996482e-03, 1.8465751154427907e-02, 3.8708599914838084e-02, 7.1600747691843394e-02, 1.1698073380429937e-01, 1.6893796927590174e-01, 2.1577494627433041e-01, 2.4383585380721171e-01, 2.4383585380721171e-01, 2.1577494627433041e-01, 1.6893796927590174e-01, 1.1698073380429937e-01, 7.1600747691843394e-02, 3.8708599914838084e-02, 1.8465751154427907e-02, 7.7640394053996482e-03, 2.8731975330897244e-03, 9.3431768696117658e-04, 2.6647788669335111e-04, 6.6517412418153150e-05, 1.4496444191129691e-05, 2.7507246274012478e-06, 4.5305355658612973e-07, 6.4544629501196559e-08, 7.9229232891502669e-09, 8.3430559260867452e-10, 7.4997199146582833e-11, 5.7232797185020048e-12, 3.6848498201591518e-13, 1.9875208346984979e-14, 8.9094610406663587e-16, 3.2891620143645649e-17, 9.8965289896201795e-19, 2.3978402756179082e-20, 4.6134710745539610e-22, 6.9341198195289992e-24, 7.9851871981733358e-26, 6.8834570436337191e-28, 4.3178173430220290e-30, 1.9029906100319421e-32, 5.6371927794771982e-35, 1.0595146928277511e-37, 1.1692076998197370e-40, 6.7924330161546228e-44, 1.7642057043388989e-47, 1.5671564937749406e-51, 2.8621845857326094e-56, 2.9557746032980847e-62}, + {4.3474845662635656e-63, 4.5007211282481250e-57, 2.6082298377217237e-52, 3.0923065202135848e-48, 1.2501139575481106e-44, 2.2549072526181938e-41, 2.1381421402290456e-38, 1.1891459359657575e-35, 4.1929734266120318e-33, 9.9316879214599191e-31, 1.6522218331862429e-28, 1.9995631822582135e-26, 1.8111771920709664e-24, 1.2568606780858601e-22, 6.8135449122040696e-21, 2.9333425183931587e-19, 1.0170733571061197e-17, 2.8746837567251872e-16, 6.6931269313103119e-15, 1.2955204220510481e-13, 2.1014796586114549e-12, 2.8770619925838150e-11, 3.3453423873608581e-10, 3.3221419859886598e-09, 2.8316197051829986e-08, 2.0807020978532919e-07, 1.3232911149144323e-06, 7.3096953196703488e-06, 3.5180651840387621e-05, 1.4793874164100584e-04, 5.4489132381766836e-04, 1.7617305058156662e-03, 5.0096471937478518e-03, 1.2549959027149010e-02, 2.7737938219946516e-02, 5.4154863728585530e-02, 9.3492582227695284e-02, 1.4284081532237788e-01, 1.9325876496080116e-01, 2.3165063428423818e-01, 2.4606621240915144e-01, 2.3165063428423818e-01, 1.9325876496080116e-01, 1.4284081532237788e-01, 9.3492582227695284e-02, 5.4154863728585530e-02, 2.7737938219946516e-02, 1.2549959027149010e-02, 5.0096471937478518e-03, 1.7617305058156662e-03, 5.4489132381766836e-04, 1.4793874164100584e-04, 3.5180651840387621e-05, 7.3096953196703488e-06, 1.3232911149144323e-06, 2.0807020978532919e-07, 2.8316197051829986e-08, 3.3221419859886598e-09, 3.3453423873608581e-10, 2.8770619925838150e-11, 2.1014796586114549e-12, 1.2955204220510481e-13, 6.6931269313103119e-15, 2.8746837567251872e-16, 1.0170733571061197e-17, 2.9333425183931587e-19, 6.8135449122040696e-21, 1.2568606780858601e-22, 1.8111771920709664e-24, 1.9995631822582135e-26, 1.6522218331862429e-28, 9.9316879214599191e-31, 4.1929734266120318e-33, 1.1891459359657575e-35, 2.1381421402290456e-38, 2.2549072526181938e-41, 1.2501139575481106e-44, 3.0923065202135848e-48, 2.6082298377217237e-52, 4.5007211282481250e-57, 4.3474845662635656e-63}, + {6.3900846179356680e-64, 7.0683040654635165e-58, 4.3331628156671634e-53, 5.4079341607686490e-49, 2.2944871434121997e-45, 4.3348761233697938e-42, 4.2990971075609177e-39, 2.4981476114804934e-36, 9.1963660505689469e-34, 2.2729303616459228e-31, 3.9439087540838148e-29, 4.9770348134757658e-27, 4.7000291498915663e-25, 3.4001352768447133e-23, 1.9215431432889354e-21, 8.6245303609378974e-20, 3.1179884254074804e-18, 9.1905096520186247e-17, 2.2320593837338383e-15, 4.5078424718756776e-14, 7.6319902510210860e-13, 1.0909613183044814e-11, 1.3250311215425566e-10, 1.3750709116496800e-09, 1.2253983047111421e-08, 9.4193245001969527e-08, 6.2702226836829128e-07, 3.6275480887435970e-06, 1.8297490531324017e-05, 8.0695629747031377e-05, 3.1195003282250721e-04, 1.0594217898549964e-03, 3.1670839271362595e-03, 8.3485090964466376e-03, 1.9434337138642246e-02, 4.0003826723007251e-02, 7.2891273924741068e-02, 1.1767348589341342e-01, 1.6842887908813681e-01, 2.1385359898330383e-01, 2.4095120319809515e-01, 2.4095120319809515e-01, 2.1385359898330383e-01, 1.6842887908813681e-01, 1.1767348589341342e-01, 7.2891273924741068e-02, 4.0003826723007251e-02, 1.9434337138642246e-02, 8.3485090964466376e-03, 3.1670839271362595e-03, 1.0594217898549964e-03, 3.1195003282250721e-04, 8.0695629747031377e-05, 1.8297490531324017e-05, 3.6275480887435970e-06, 6.2702226836829128e-07, 9.4193245001969527e-08, 1.2253983047111421e-08, 1.3750709116496800e-09, 1.3250311215425566e-10, 1.0909613183044814e-11, 7.6319902510210860e-13, 4.5078424718756776e-14, 2.2320593837338383e-15, 9.1905096520186247e-17, 3.1179884254074804e-18, 8.6245303609378974e-20, 1.9215431432889354e-21, 3.4001352768447133e-23, 4.7000291498915663e-25, 4.9770348134757658e-27, 3.9439087540838148e-29, 2.2729303616459228e-31, 9.1963660505689469e-34, 2.4981476114804934e-36, 4.2990971075609177e-39, 4.3348761233697938e-42, 2.2944871434121997e-45, 5.4079341607686490e-49, 4.3331628156671634e-53, 7.0683040654635165e-58, 6.3900846179356680e-64}, + {9.3860543034002427e-65, 1.1086857074759456e-58, 7.1863132033979924e-54, 9.4366281490374702e-50, 4.2000954414179859e-46, 8.3074192361133957e-43, 8.6131947009295395e-40, 5.2269922366851146e-37, 2.0080025620200044e-34, 5.1761145427794598e-32, 9.3634938532685839e-30, 1.2315531785339706e-27, 1.2119297214386231e-25, 9.1354157424215784e-24, 5.3793647773372928e-22, 2.5158646274622071e-20, 9.4786222458398701e-19, 2.9120616998176371e-17, 7.3730974398680154e-16, 1.5527783781178122e-14, 2.7422533133249144e-13, 4.0903372275217891e-12, 5.1859074150534959e-11, 5.6202961151004291e-10, 5.2329996549801057e-09, 4.2048817138133669e-08, 2.9276307349429699e-07, 1.7725651070157471e-06, 9.3629045679147633e-06, 4.3270500380986358e-05, 1.7541290219541701e-04, 6.2518907824834233e-04, 1.9629978285824797e-03, 5.4395127563656737e-03, 1.3323152028369395e-02, 2.8883095437764291e-02, 5.5483794234023616e-02, 9.4533826153130718e-02, 1.4296854105472981e-01, 1.9203597399663150e-01, 2.2918990372570339e-01, 2.4310155924759538e-01, 2.2918990372570339e-01, 1.9203597399663150e-01, 1.4296854105472981e-01, 9.4533826153130718e-02, 5.5483794234023616e-02, 2.8883095437764291e-02, 1.3323152028369395e-02, 5.4395127563656737e-03, 1.9629978285824797e-03, 6.2518907824834233e-04, 1.7541290219541701e-04, 4.3270500380986358e-05, 9.3629045679147633e-06, 1.7725651070157471e-06, 2.9276307349429699e-07, 4.2048817138133669e-08, 5.2329996549801057e-09, 5.6202961151004291e-10, 5.1859074150534959e-11, 4.0903372275217891e-12, 2.7422533133249144e-13, 1.5527783781178122e-14, 7.3730974398680154e-16, 2.9120616998176371e-17, 9.4786222458398701e-19, 2.5158646274622071e-20, 5.3793647773372928e-22, 9.1354157424215784e-24, 1.2119297214386231e-25, 1.2315531785339706e-27, 9.3634938532685839e-30, 5.1761145427794598e-32, 2.0080025620200044e-34, 5.2269922366851146e-37, 8.6131947009295395e-40, 8.3074192361133957e-43, 4.2000954414179859e-46, 9.4366281490374702e-50, 7.1863132033979924e-54, 1.1086857074759456e-58, 9.3860543034002427e-65}, + {1.3777591125358009e-65, 1.7368921661372738e-59, 1.1897755678170730e-54, 1.6430818957997274e-50, 7.6682284731962107e-47, 1.5871807417910754e-43, 1.7196165366502119e-40, 1.0893693911932259e-37, 4.3652562606795252e-35, 1.1730726684546622e-32, 2.2113391943206024e-30, 3.0299940661257904e-28, 3.1056775475544893e-26, 2.4381144772606556e-24, 1.4951761449964922e-22, 7.2828478980006098e-21, 2.8579464976920660e-19, 9.1468094747747248e-18, 2.4130464210357486e-16, 5.2963672903976192e-15, 9.7511119835367196e-14, 1.5167942114683800e-12, 2.0061976506906991e-11, 2.2691700569827051e-10, 2.2060316533485200e-09, 1.8517359090727501e-08, 1.3475150826592070e-07, 8.5321092475315403e-07, 4.7158906386790063e-06, 2.2820419642920848e-05, 9.6932540256516268e-05, 3.6225322463531061e-04, 1.1935740511675038e-03, 3.4735556703184827e-03, 8.9429974621500780e-03, 2.0397690515966099e-02, 4.1265501456996284e-02, 7.4120627126827321e-02, 1.1830317740926892e-01, 1.6789719350811264e-01, 2.1197836082996782e-01, 2.3816651641238701e-01, 2.3816651641238701e-01, 2.1197836082996782e-01, 1.6789719350811264e-01, 1.1830317740926892e-01, 7.4120627126827321e-02, 4.1265501456996284e-02, 2.0397690515966099e-02, 8.9429974621500780e-03, 3.4735556703184827e-03, 1.1935740511675038e-03, 3.6225322463531061e-04, 9.6932540256516268e-05, 2.2820419642920848e-05, 4.7158906386790063e-06, 8.5321092475315403e-07, 1.3475150826592070e-07, 1.8517359090727501e-08, 2.2060316533485200e-09, 2.2691700569827051e-10, 2.0061976506906991e-11, 1.5167942114683800e-12, 9.7511119835367196e-14, 5.2963672903976192e-15, 2.4130464210357486e-16, 9.1468094747747248e-18, 2.8579464976920660e-19, 7.2828478980006098e-21, 1.4951761449964922e-22, 2.4381144772606556e-24, 3.1056775475544893e-26, 3.0299940661257904e-28, 2.2113391943206024e-30, 1.1730726684546622e-32, 4.3652562606795252e-35, 1.0893693911932259e-37, 1.7196165366502119e-40, 1.5871807417910754e-43, 7.6682284731962107e-47, 1.6430818957997274e-50, 1.1897755678170730e-54, 1.7368921661372738e-59, 1.3777591125358009e-65}, + {2.0210775781982523e-66, 2.7178104548553350e-60, 1.9665137729345701e-55, 2.8548162606098395e-51, 1.3964239783926081e-47, 3.0233321269411514e-44, 3.4214653414754691e-41, 2.2616501773134073e-38, 9.4491938966483701e-36, 2.6460383187052969e-33, 5.1955440071780227e-31, 7.4129920915228913e-29, 7.9104233673873923e-27, 6.4645977792616403e-25, 4.1267488231576369e-23, 2.0924604014548367e-21, 8.5484498659455372e-20, 2.8486537373202696e-18, 7.8262318929365957e-17, 1.7892942386135024e-15, 3.4323564970059177e-14, 5.5646126660265747e-13, 7.6736928514695270e-12, 9.0529279992180488e-11, 9.1835433159763121e-10, 8.0473976876877841e-09, 6.1165350599767583e-08, 4.0472265409701691e-07, 2.3390768958015489e-06, 1.1842716592385991e-05, 5.2665815424842040e-05, 2.0620794316657292e-04, 7.1235629871549161e-04, 2.1752890413369533e-03, 5.8813993717320096e-03, 1.4099847351552907e-02, 3.0009543309201085e-02, 5.6764441788522510e-02, 9.5510122550246740e-02, 1.4305030254196435e-01, 1.9082420376099704e-01, 2.2680511848210408e-01, 2.4024154090350588e-01, 2.2680511848210408e-01, 1.9082420376099704e-01, 1.4305030254196435e-01, 9.5510122550246740e-02, 5.6764441788522510e-02, 3.0009543309201085e-02, 1.4099847351552907e-02, 5.8813993717320096e-03, 2.1752890413369533e-03, 7.1235629871549161e-04, 2.0620794316657292e-04, 5.2665815424842040e-05, 1.1842716592385991e-05, 2.3390768958015489e-06, 4.0472265409701691e-07, 6.1165350599767583e-08, 8.0473976876877841e-09, 9.1835433159763121e-10, 9.0529279992180488e-11, 7.6736928514695270e-12, 5.5646126660265747e-13, 3.4323564970059177e-14, 1.7892942386135024e-15, 7.8262318929365957e-17, 2.8486537373202696e-18, 8.5484498659455372e-20, 2.0924604014548367e-21, 4.1267488231576369e-23, 6.4645977792616403e-25, 7.9104233673873923e-27, 7.4129920915228913e-29, 5.1955440071780227e-31, 2.6460383187052969e-33, 9.4491938966483701e-36, 2.2616501773134073e-38, 3.4214653414754691e-41, 3.0233321269411514e-44, 1.3964239783926081e-47, 2.8548162606098395e-51, 1.9665137729345701e-55, 2.7178104548553350e-60, 2.0210775781982523e-66}, + {2.9629045151469795e-67, 4.2477382853725514e-61, 3.2450153429194443e-56, 4.9498576868697659e-52, 2.5365833564005594e-48, 5.7421164166187080e-45, 6.7848084979774069e-42, 4.6777688454197694e-39, 2.0368541188744583e-36, 5.9410439274149082e-34, 1.2145487671367711e-31, 1.8036964134319502e-29, 2.0029387907481775e-27, 1.7031624106751895e-25, 1.1312252871807839e-23, 5.9680464287706203e-22, 2.5370441167173625e-20, 8.7983250076979868e-19, 2.5159793892190254e-17, 5.9885746170489713e-16, 1.1962793877597350e-14, 2.0202353514446467e-13, 2.9029728072990475e-12, 3.5699318546714651e-11, 3.7765043235634349e-10, 3.4525199163835126e-09, 2.7390187380396967e-08, 1.8926893464082190e-07, 1.1429783024859512e-06, 6.0502321414091725e-06, 2.8148083952665619e-05, 1.1537557343902387e-04, 4.1754273548549582e-04, 1.3367210462102556e-03, 3.7920023944900709e-03, 9.5461945478795308e-03, 2.1354422319535372e-02, 4.2493637239894133e-02, 7.5291446661321912e-02, 1.1887424153508566e-01, 1.6734591429857545e-01, 2.1014771223832399e-01, 2.3547615304001107e-01, 2.3547615304001107e-01, 2.1014771223832399e-01, 1.6734591429857545e-01, 1.1887424153508566e-01, 7.5291446661321912e-02, 4.2493637239894133e-02, 2.1354422319535372e-02, 9.5461945478795308e-03, 3.7920023944900709e-03, 1.3367210462102556e-03, 4.1754273548549582e-04, 1.1537557343902387e-04, 2.8148083952665619e-05, 6.0502321414091725e-06, 1.1429783024859512e-06, 1.8926893464082190e-07, 2.7390187380396967e-08, 3.4525199163835126e-09, 3.7765043235634349e-10, 3.5699318546714651e-11, 2.9029728072990475e-12, 2.0202353514446467e-13, 1.1962793877597350e-14, 5.9885746170489713e-16, 2.5159793892190254e-17, 8.7983250076979868e-19, 2.5370441167173625e-20, 5.9680464287706203e-22, 1.1312252871807839e-23, 1.7031624106751895e-25, 2.0029387907481775e-27, 1.8036964134319502e-29, 1.2145487671367711e-31, 5.9410439274149082e-34, 2.0368541188744583e-36, 4.6777688454197694e-39, 6.7848084979774069e-42, 5.7421164166187080e-45, 2.5365833564005594e-48, 4.9498576868697659e-52, 3.2450153429194443e-56, 4.2477382853725514e-61, 2.9629045151469795e-67}, + {4.3409286059314790e-68, 6.6312997992786490e-62, 5.3461191685641914e-57, 8.5648796438497824e-53, 4.5963493020491623e-49, 1.0874550734954457e-45, 1.3410304270363433e-42, 9.6394008578235831e-40, 4.3726474538903734e-37, 1.3279095802116780e-34, 2.8252406271755742e-32, 4.3652040547608271e-30, 5.0421784821017282e-28, 4.4592405404333692e-26, 3.0802364578690691e-24, 1.6900522980387141e-22, 7.4723281435460732e-21, 2.6954831586023608e-19, 8.0190167662890588e-18, 1.9861050466676079e-16, 4.1293419627929950e-15, 7.2600749267287114e-14, 1.0864518129258071e-12, 1.3919025655825987e-11, 1.5345768250281952e-10, 1.4627430245954727e-09, 1.2104826477830397e-08, 8.7294781098733113e-08, 5.5045426913594814e-07, 3.0442062696033981e-06, 1.4805735210956500e-05, 6.3482017172793501e-05, 2.4048437850905004e-04, 8.0646696699679095e-04, 2.3982976827574042e-03, 6.3343363657207474e-03, 1.4878611633370075e-02, 3.1116468918540825e-02, 5.7998096102851303e-02, 9.6425173608541109e-02, 1.4309010371318212e-01, 1.8962432993080802e-01, 2.2449250076685384e-01, 2.3748014388162669e-01, 2.2449250076685384e-01, 1.8962432993080802e-01, 1.4309010371318212e-01, 9.6425173608541109e-02, 5.7998096102851303e-02, 3.1116468918540825e-02, 1.4878611633370075e-02, 6.3343363657207474e-03, 2.3982976827574042e-03, 8.0646696699679095e-04, 2.4048437850905004e-04, 6.3482017172793501e-05, 1.4805735210956500e-05, 3.0442062696033981e-06, 5.5045426913594814e-07, 8.7294781098733113e-08, 1.2104826477830397e-08, 1.4627430245954727e-09, 1.5345768250281952e-10, 1.3919025655825987e-11, 1.0864518129258071e-12, 7.2600749267287114e-14, 4.1293419627929950e-15, 1.9861050466676079e-16, 8.0190167662890588e-18, 2.6954831586023608e-19, 7.4723281435460732e-21, 1.6900522980387141e-22, 3.0802364578690691e-24, 4.4592405404333692e-26, 5.0421784821017282e-28, 4.3652040547608271e-30, 2.8252406271755742e-32, 1.3279095802116780e-34, 4.3726474538903734e-37, 9.6394008578235831e-40, 1.3410304270363433e-42, 1.0874550734954457e-45, 4.5963493020491623e-49, 8.5648796438497824e-53, 5.3461191685641914e-57, 6.6312997992786490e-62, 4.3409286059314790e-68}, + {6.3559888804815291e-69, 1.0340740401651512e-62, 8.7937979910383930e-58, 1.4790458246095511e-53, 8.3086543388025186e-50, 2.0536646110581859e-46, 2.6420736294829820e-43, 1.9792151722732658e-40, 9.3494545988123451e-38, 2.9549868117171349e-35, 6.5403217012580441e-33, 1.0509161650154305e-30, 1.2621393343519558e-28, 1.1604245678013870e-26, 8.3325690961981494e-25, 4.7526132981917159e-23, 2.1844800072999790e-21, 8.1927992139953961e-20, 2.5344499212676499e-18, 6.5284978547093747e-17, 1.4120140414140493e-15, 2.5832194339375668e-14, 4.0236781196418743e-13, 5.3673492268073417e-12, 6.1636566122784830e-11, 6.1219783545440359e-10, 5.2813629715600939e-09, 3.9723156884506070e-08, 2.6137484697367874e-07, 1.5091682442228327e-06, 7.6676762452478550e-06, 3.4365246906918278e-05, 1.3616684443587397e-04, 4.7795191142819410e-04, 1.4887726540954260e-03, 4.1217965699966519e-03, 1.0156852342094170e-02, 2.2303298514796874e-02, 4.3688380057289714e-02, 7.6406289996198792e-02, 1.1939077299329898e-01, 1.6677771361921795e-01, 2.0836017261496417e-01, 2.3287490818454673e-01, 2.3287490818454673e-01, 2.0836017261496417e-01, 1.6677771361921795e-01, 1.1939077299329898e-01, 7.6406289996198792e-02, 4.3688380057289714e-02, 2.2303298514796874e-02, 1.0156852342094170e-02, 4.1217965699966519e-03, 1.4887726540954260e-03, 4.7795191142819410e-04, 1.3616684443587397e-04, 3.4365246906918278e-05, 7.6676762452478550e-06, 1.5091682442228327e-06, 2.6137484697367874e-07, 3.9723156884506070e-08, 5.2813629715600939e-09, 6.1219783545440359e-10, 6.1636566122784830e-11, 5.3673492268073417e-12, 4.0236781196418743e-13, 2.5832194339375668e-14, 1.4120140414140493e-15, 6.5284978547093747e-17, 2.5344499212676499e-18, 8.1927992139953961e-20, 2.1844800072999790e-21, 4.7526132981917159e-23, 8.3325690961981494e-25, 1.1604245678013870e-26, 1.2621393343519558e-28, 1.0509161650154305e-30, 6.5403217012580441e-33, 2.9549868117171349e-35, 9.3494545988123451e-38, 1.9792151722732658e-40, 2.6420736294829820e-43, 2.0536646110581859e-46, 8.3086543388025186e-50, 1.4790458246095511e-53, 8.7937979910383930e-58, 1.0340740401651512e-62, 6.3559888804815291e-69}, + {9.3008818390890492e-70, 1.6107424492415425e-63, 1.4442544724939497e-58, 2.5491245644508241e-54, 1.4983841626026885e-50, 3.8676878782479128e-47, 5.1890175350658309e-44, 4.0494895783343356e-41, 1.9912326515858821e-38, 6.5473365822875601e-36, 1.5069227943967880e-33, 2.5171173318424500e-31, 3.1418754018247846e-29, 3.0018077177700208e-27, 2.2397389074987337e-25, 1.3273883998725675e-23, 6.3398444713628853e-22, 2.4709662681137447e-20, 7.9447537335212530e-19, 2.1273958174343124e-17, 4.7841544346425597e-16, 9.1026391570176184e-15, 1.4750035153523922e-13, 2.0475389185298693e-12, 2.4477459246779186e-11, 2.5318768471063941e-10, 2.2756270244146732e-09, 1.7840153336747013e-08, 1.2241314031279016e-07, 7.3745467763804806e-07, 3.9114112665063118e-06, 1.8311113911126260e-05, 7.5833505293245319e-05, 2.7838967822704579e-04, 9.0756465037858196e-04, 2.6316863728237144e-03, 6.7973713273565750e-03, 1.5658123034423620e-02, 3.2203216875107243e-02, 5.9186084836389256e-02, 9.7282463095519897e-02, 1.4309158549116330e-01, 1.8843706331894564e-01, 2.2224852664936542e-01, 2.3481182765823758e-01, 2.2224852664936542e-01, 1.8843706331894564e-01, 1.4309158549116330e-01, 9.7282463095519897e-02, 5.9186084836389256e-02, 3.2203216875107243e-02, 1.5658123034423620e-02, 6.7973713273565750e-03, 2.6316863728237144e-03, 9.0756465037858196e-04, 2.7838967822704579e-04, 7.5833505293245319e-05, 1.8311113911126260e-05, 3.9114112665063118e-06, 7.3745467763804806e-07, 1.2241314031279016e-07, 1.7840153336747013e-08, 2.2756270244146732e-09, 2.5318768471063941e-10, 2.4477459246779186e-11, 2.0475389185298693e-12, 1.4750035153523922e-13, 9.1026391570176184e-15, 4.7841544346425597e-16, 2.1273958174343124e-17, 7.9447537335212530e-19, 2.4709662681137447e-20, 6.3398444713628853e-22, 1.3273883998725675e-23, 2.2397389074987337e-25, 3.0018077177700208e-27, 3.1418754018247846e-29, 2.5171173318424500e-31, 1.5069227943967880e-33, 6.5473365822875601e-36, 1.9912326515858821e-38, 4.0494895783343356e-41, 5.1890175350658309e-44, 3.8676878782479128e-47, 1.4983841626026885e-50, 2.5491245644508241e-54, 1.4442544724939497e-58, 1.6107424492415425e-63, 9.3008818390890492e-70}, + {1.3602242492354518e-70, 2.5062893896000025e-64, 2.3683907001837810e-59, 4.3849662998245842e-55, 2.6959438737993594e-51, 7.2644220875022382e-48, 1.0159844536444225e-44, 8.2566412936940675e-42, 4.2246144598021515e-39, 1.4445590039286314e-36, 3.4560072588078828e-34, 5.9987185516144465e-32, 7.7788491872908368e-30, 7.7199678213751262e-28, 5.9827510138490597e-26, 3.6826729053156295e-24, 1.8269179382831153e-22, 7.3963423583597857e-21, 2.4705505922880106e-19, 6.8737797990960140e-18, 1.6064742942702627e-16, 3.1773129599637848e-15, 5.3533724861984214e-14, 7.7293031086018118e-13, 9.6137828691596686e-12, 1.0350233726240316e-10, 9.6863849248805751e-10, 7.9104166149104796e-09, 5.6567852900930044e-08, 3.5533045829496680e-07, 1.9661408494659142e-06, 9.6077760741794566e-06, 4.1557921102543606e-05, 1.5944214368480690e-04, 5.4359224952962480e-04, 1.6496055361812409e-03, 4.4622998595035017e-03, 1.0773786624642434e-02, 2.3243228173755130e-02, 4.4849988132390606e-02, 7.7467627605512762e-02, 1.1985655590239072e-01, 1.6619497260995916e-01, 2.0661430370392464e-01, 2.3035797018194470e-01, 2.3035797018194470e-01, 2.0661430370392464e-01, 1.6619497260995916e-01, 1.1985655590239072e-01, 7.7467627605512762e-02, 4.4849988132390606e-02, 2.3243228173755130e-02, 1.0773786624642434e-02, 4.4622998595035017e-03, 1.6496055361812409e-03, 5.4359224952962480e-04, 1.5944214368480690e-04, 4.1557921102543606e-05, 9.6077760741794566e-06, 1.9661408494659142e-06, 3.5533045829496680e-07, 5.6567852900930044e-08, 7.9104166149104796e-09, 9.6863849248805751e-10, 1.0350233726240316e-10, 9.6137828691596686e-12, 7.7293031086018118e-13, 5.3533724861984214e-14, 3.1773129599637848e-15, 1.6064742942702627e-16, 6.8737797990960140e-18, 2.4705505922880106e-19, 7.3963423583597857e-21, 1.8269179382831153e-22, 3.6826729053156295e-24, 5.9827510138490597e-26, 7.7199678213751262e-28, 7.7788491872908368e-30, 5.9987185516144465e-32, 3.4560072588078828e-34, 1.4445590039286314e-36, 4.2246144598021515e-39, 8.2566412936940675e-42, 1.0159844536444225e-44, 7.2644220875022382e-48, 2.6959438737993594e-51, 4.3849662998245842e-55, 2.3683907001837810e-59, 2.5062893896000025e-64, 1.3602242492354518e-70}, + {1.9881401943823065e-71, 3.8956133082883524e-65, 3.8780907613890165e-60, 7.5287596024697438e-56, 4.8396443307633869e-52, 1.3608233728823463e-48, 1.9832504849666674e-45, 1.6777720088426207e-42, 8.9292665279968075e-40, 3.1739897948436054e-37, 7.8902747437194502e-35, 1.4225885948951900e-32, 1.9157413956045486e-30, 1.9741018729702676e-28, 1.5883597138828314e-26, 1.0150605078465530e-24, 5.2280336522983695e-23, 2.1976422794092572e-21, 7.6226000038011678e-20, 2.2026235762112506e-18, 5.3473142908729109e-17, 1.0988447789132501e-15, 1.9241100890740006e-14, 2.8879825636852583e-13, 3.7354214836948911e-12, 4.1834945759406555e-11, 4.0743696574618951e-10, 3.4640710439123456e-09, 2.5801094931709852e-08, 1.6888360171753998e-07, 9.7426112561417961e-07, 4.9661767693609960e-06, 2.2420154669404182e-05, 8.9832774694917811e-05, 3.2005763736769638e-04, 1.0156641399211783e-03, 2.8750919999992967e-03, 7.2695749936617917e-03, 1.6437166647437267e-02, 3.3269271876221002e-02, 6.0329758617287225e-02, 9.8085267668094472e-02, 1.4305806223178333e-01, 1.8726297375534309e-01, 2.2006990496442211e-01, 2.3223147790375134e-01, 2.2006990496442211e-01, 1.8726297375534309e-01, 1.4305806223178333e-01, 9.8085267668094472e-02, 6.0329758617287225e-02, 3.3269271876221002e-02, 1.6437166647437267e-02, 7.2695749936617917e-03, 2.8750919999992967e-03, 1.0156641399211783e-03, 3.2005763736769638e-04, 8.9832774694917811e-05, 2.2420154669404182e-05, 4.9661767693609960e-06, 9.7426112561417961e-07, 1.6888360171753998e-07, 2.5801094931709852e-08, 3.4640710439123456e-09, 4.0743696574618951e-10, 4.1834945759406555e-11, 3.7354214836948911e-12, 2.8879825636852583e-13, 1.9241100890740006e-14, 1.0988447789132501e-15, 5.3473142908729109e-17, 2.2026235762112506e-18, 7.6226000038011678e-20, 2.1976422794092572e-21, 5.2280336522983695e-23, 1.0150605078465530e-24, 1.5883597138828314e-26, 1.9741018729702676e-28, 1.9157413956045486e-30, 1.4225885948951900e-32, 7.8902747437194502e-35, 3.1739897948436054e-37, 8.9292665279968075e-40, 1.6777720088426207e-42, 1.9832504849666674e-45, 1.3608233728823463e-48, 4.8396443307633869e-52, 7.5287596024697438e-56, 3.8780907613890165e-60, 3.8956133082883524e-65, 1.9881401943823065e-71}, + {2.9042780793285192e-72, 6.0487911085991875e-66, 6.3408840552698421e-61, 1.2902630736739495e-56, 8.6686227081665284e-53, 2.5425883339495936e-49, 3.8599589978240019e-46, 3.3979613434850632e-43, 1.8803612804682350e-40, 6.9456401083003465e-38, 1.7934288277345599e-35, 3.3574581848271432e-33, 4.6935588729781351e-31, 5.0199340944280284e-29, 4.1917802591871942e-27, 2.7800091791127284e-25, 1.4859465721519723e-23, 6.4827357579899811e-22, 2.3339160328683892e-20, 7.0010683610304173e-19, 1.7647313333962599e-17, 3.7660828360044482e-16, 6.8501492079314778e-15, 1.0683188551398555e-13, 1.4362003723050719e-12, 1.6723593784919510e-11, 1.6940433392992703e-10, 1.4986355561051177e-09, 1.1619214278627516e-08, 7.9204993538763526e-08, 4.7607676418369897e-07, 2.5297850142327841e-06, 1.1912329247318932e-05, 4.9812715968551620e-05, 1.8533007239769129e-04, 6.1455372697219728e-04, 1.8190665842030779e-03, 4.8128687057527163e-03, 1.1395877807434502e-02, 2.4173252104118973e-02, 4.5978813889354229e-02, 7.8477839811903538e-02, 1.2027508931592504e-01, 1.6559981501591434e-01, 2.0490871177338488e-01, 2.2792088322788109e-01, 2.2792088322788109e-01, 2.0490871177338488e-01, 1.6559981501591434e-01, 1.2027508931592504e-01, 7.8477839811903538e-02, 4.5978813889354229e-02, 2.4173252104118973e-02, 1.1395877807434502e-02, 4.8128687057527163e-03, 1.8190665842030779e-03, 6.1455372697219728e-04, 1.8533007239769129e-04, 4.9812715968551620e-05, 1.1912329247318932e-05, 2.5297850142327841e-06, 4.7607676418369897e-07, 7.9204993538763526e-08, 1.1619214278627516e-08, 1.4986355561051177e-09, 1.6940433392992703e-10, 1.6723593784919510e-11, 1.4362003723050719e-12, 1.0683188551398555e-13, 6.8501492079314778e-15, 3.7660828360044482e-16, 1.7647313333962599e-17, 7.0010683610304173e-19, 2.3339160328683892e-20, 6.4827357579899811e-22, 1.4859465721519723e-23, 2.7800091791127284e-25, 4.1917802591871942e-27, 5.0199340944280284e-29, 4.6935588729781351e-31, 3.3574581848271432e-33, 1.7934288277345599e-35, 6.9456401083003465e-38, 1.8803612804682350e-40, 3.3979613434850632e-43, 3.8599589978240019e-46, 2.5425883339495936e-49, 8.6686227081665284e-53, 1.2902630736739495e-56, 6.3408840552698421e-61, 6.0487911085991875e-66, 2.9042780793285192e-72}, + {4.2402214052951246e-73, 9.3824834253827312e-67, 1.0352869434490524e-61, 2.2072219195734482e-57, 1.5493136809731731e-53, 4.7385536981365373e-50, 7.4907905142626159e-47, 6.8594377885386513e-44, 3.9454427601608861e-41, 1.5138792655234332e-38, 4.0587293642249081e-36, 7.8867039514681461e-34, 1.1440858552314813e-31, 1.2695564683626133e-29, 1.0997785424357608e-27, 7.5663389636387123e-26, 4.1954427268621758e-24, 1.8988470634740822e-22, 7.0927393378883720e-21, 2.2077343775414074e-19, 5.7754643743238307e-18, 1.2794126341282052e-16, 2.4162049041525693e-15, 3.9134647294064509e-14, 5.4654903154799270e-13, 6.6135809154494093e-12, 6.9642829049519196e-11, 6.4070330827294555e-10, 5.1680095336388813e-09, 3.6666857282366239e-08, 2.2949550926387024e-07, 1.2704896429597333e-06, 6.2359369667152816e-06, 2.7195889773576724e-05, 1.0558960284417518e-04, 3.6560795714255136e-04, 1.1307532404246092e-03, 3.1281305245610394e-03, 7.7500451541012766e-03, 1.7214629493700298e-02, 3.4314242859408567e-02, 6.1430478646654310e-02, 9.8836668138780004e-02, 1.4299255414069270e-01, 1.8610251044108347e-01, 2.1795355826999802e-01, 2.2973436523811983e-01, 2.1795355826999802e-01, 1.8610251044108347e-01, 1.4299255414069270e-01, 9.8836668138780004e-02, 6.1430478646654310e-02, 3.4314242859408567e-02, 1.7214629493700298e-02, 7.7500451541012766e-03, 3.1281305245610394e-03, 1.1307532404246092e-03, 3.6560795714255136e-04, 1.0558960284417518e-04, 2.7195889773576724e-05, 6.2359369667152816e-06, 1.2704896429597333e-06, 2.2949550926387024e-07, 3.6666857282366239e-08, 5.1680095336388813e-09, 6.4070330827294555e-10, 6.9642829049519196e-11, 6.6135809154494093e-12, 5.4654903154799270e-13, 3.9134647294064509e-14, 2.4162049041525693e-15, 1.2794126341282052e-16, 5.7754643743238307e-18, 2.2077343775414074e-19, 7.0927393378883720e-21, 1.8988470634740822e-22, 4.1954427268621758e-24, 7.5663389636387123e-26, 1.0997785424357608e-27, 1.2695564683626133e-29, 1.1440858552314813e-31, 7.8867039514681461e-34, 4.0587293642249081e-36, 1.5138792655234332e-38, 3.9454427601608861e-41, 6.8594377885386513e-44, 7.4907905142626159e-47, 4.7385536981365373e-50, 1.5493136809731731e-53, 2.2072219195734482e-57, 1.0352869434490524e-61, 9.3824834253827312e-67, 4.2402214052951246e-73}, + {6.1873167292600330e-74, 1.4538901947049863e-67, 1.6879603995600424e-62, 3.7691324369200321e-58, 2.7631164912569130e-54, 8.8091139694466722e-51, 1.4495623366344723e-47, 1.3802919462863240e-44, 8.2491698349502409e-42, 3.2868281039958480e-39, 9.1463558192668670e-37, 1.8440635697521863e-34, 2.7749265480534503e-32, 3.1936039953280896e-30, 2.8689474946571079e-28, 2.0467667970915599e-26, 1.1768586219954579e-24, 5.5235547418541776e-23, 2.1397391826730893e-21, 6.9081875027574077e-20, 1.8747446593629021e-18, 4.3090894092529427e-17, 8.4454653993109795e-16, 1.4199548095965024e-14, 2.0591425994119171e-13, 2.5880423909347226e-12, 2.8316127909785268e-11, 2.7076622359247714e-10, 2.2709635043178179e-09, 1.6760660123885240e-08, 1.0917307724251056e-07, 6.2927723529831787e-07, 3.2175123782368650e-06, 1.4625147457368242e-05, 5.9216205461426278e-05, 2.1395132199714689e-04, 6.9090534092963924e-04, 1.9969762869401319e-03, 5.1728592008298650e-03, 1.2022070950665343e-02, 2.5092532015162070e-02, 4.7075288211797156e-02, 7.9439215172105435e-02, 1.2064961060726002e-01, 1.6499413655200360e-01, 2.0324204888941669e-01, 2.2555951425452636e-01, 2.2555951425452636e-01, 2.0324204888941669e-01, 1.6499413655200360e-01, 1.2064961060726002e-01, 7.9439215172105435e-02, 4.7075288211797156e-02, 2.5092532015162070e-02, 1.2022070950665343e-02, 5.1728592008298650e-03, 1.9969762869401319e-03, 6.9090534092963924e-04, 2.1395132199714689e-04, 5.9216205461426278e-05, 1.4625147457368242e-05, 3.2175123782368650e-06, 6.2927723529831787e-07, 1.0917307724251056e-07, 1.6760660123885240e-08, 2.2709635043178179e-09, 2.7076622359247714e-10, 2.8316127909785268e-11, 2.5880423909347226e-12, 2.0591425994119171e-13, 1.4199548095965024e-14, 8.4454653993109795e-16, 4.3090894092529427e-17, 1.8747446593629021e-18, 6.9081875027574077e-20, 2.1397391826730893e-21, 5.5235547418541776e-23, 1.1768586219954579e-24, 2.0467667970915599e-26, 2.8689474946571079e-28, 3.1936039953280896e-30, 2.7749265480534503e-32, 1.8440635697521863e-34, 9.1463558192668670e-37, 3.2868281039958480e-39, 8.2491698349502409e-42, 1.3802919462863240e-44, 1.4495623366344723e-47, 8.8091139694466722e-51, 2.7631164912569130e-54, 3.7691324369200321e-58, 1.6879603995600424e-62, 1.4538901947049863e-67, 6.1873167292600330e-74}, + {9.0236831042710006e-75, 2.2507013266634397e-68, 2.7483088481763178e-63, 6.4250837772781210e-59, 4.9175305451785707e-55, 1.6336381889925197e-51, 2.7972683193869001e-48, 2.7688066162395138e-45, 1.7187588390664908e-42, 7.1089100355543671e-40, 2.0525562261562526e-37, 4.2923202100065188e-35, 6.6976892723501377e-33, 7.9915865248767542e-31, 7.4422174735850754e-29, 5.5036367600342068e-27, 3.2802180350829561e-25, 1.5959112775571386e-23, 6.4090652642750824e-22, 2.1453091893671746e-20, 6.0370235645633800e-19, 1.4391241588665120e-17, 2.9258946262067771e-16, 5.1042859875473367e-15, 7.6822356519145676e-14, 1.0023990331996466e-12, 1.1389647007504889e-11, 1.1314327929338598e-10, 9.8619913092006371e-10, 7.5672777489105014e-09, 5.1267694307391355e-08, 3.0750156860401326e-07, 1.6368618884967503e-06, 7.7499739996840847e-06, 3.2702654980222023e-05, 1.2321031502033358e-04, 4.1514601828721595e-04, 1.2527946608682095e-03, 3.3904013872216063e-03, 8.2379096963313674e-03, 1.7989495266934163e-02, 3.5337848644927512e-02, 6.2489606495141174e-02, 9.9539560539641095e-02, 1.4289781614596173e-01, 1.8495601933162914e-01, 2.1589660563060412e-01, 2.2731610876192898e-01, 2.1589660563060412e-01, 1.8495601933162914e-01, 1.4289781614596173e-01, 9.9539560539641095e-02, 6.2489606495141174e-02, 3.5337848644927512e-02, 1.7989495266934163e-02, 8.2379096963313674e-03, 3.3904013872216063e-03, 1.2527946608682095e-03, 4.1514601828721595e-04, 1.2321031502033358e-04, 3.2702654980222023e-05, 7.7499739996840847e-06, 1.6368618884967503e-06, 3.0750156860401326e-07, 5.1267694307391355e-08, 7.5672777489105014e-09, 9.8619913092006371e-10, 1.1314327929338598e-10, 1.1389647007504889e-11, 1.0023990331996466e-12, 7.6822356519145676e-14, 5.1042859875473367e-15, 2.9258946262067771e-16, 1.4391241588665120e-17, 6.0370235645633800e-19, 2.1453091893671746e-20, 6.4090652642750824e-22, 1.5959112775571386e-23, 3.2802180350829561e-25, 5.5036367600342068e-27, 7.4422174735850754e-29, 7.9915865248767542e-31, 6.6976892723501377e-33, 4.2923202100065188e-35, 2.0525562261562526e-37, 7.1089100355543671e-40, 1.7187588390664908e-42, 2.7688066162395138e-45, 2.7972683193869001e-48, 1.6336381889925197e-51, 4.9175305451785707e-55, 6.4250837772781210e-59, 2.7483088481763178e-63, 2.2507013266634397e-68, 9.0236831042710006e-75}, + {1.3153371477011018e-75, 3.4808413877180985e-69, 4.4687024216810169e-64, 1.0933824737518103e-59, 8.7337328359193298e-56, 3.0222939315022155e-52, 5.3832225069701608e-49, 5.5370648197825761e-46, 3.5689385617810602e-43, 1.5317989647111863e-40, 4.5874016658583215e-38, 9.9468000592214207e-36, 1.6088732079384737e-33, 1.9895468942695488e-31, 1.9199707067949033e-29, 1.4712415549741861e-27, 9.0859656470487372e-26, 4.5806010985499422e-24, 1.9062601886875492e-22, 6.6129511764811165e-21, 1.9288793268371580e-19, 4.7668311711866824e-18, 1.0049051491574811e-16, 1.8181691304932292e-15, 2.8387673951693530e-14, 3.8436817248766534e-13, 4.5333033745839362e-12, 4.6760103859850812e-11, 4.2335937835110236e-10, 3.3755847311277282e-09, 2.3773662147574315e-08, 1.4829694050050112e-07, 8.2135445478328264e-07, 4.0482331787772522e-06, 1.7791805918220274e-05, 6.9854324445415533e-05, 2.4541809273052672e-04, 7.7269582168165273e-04, 2.1831319760967165e-03, 5.5416312894389780e-03, 1.2651375112800185e-02, 2.6000340271244451e-02, 4.8139906731089997e-02, 8.0353950080642028e-02, 1.2098311686251535e-01, 1.6437963059849708e-01, 2.0161301347923419e-01, 2.2327002349753469e-01, 2.2327002349753469e-01, 2.0161301347923419e-01, 1.6437963059849708e-01, 1.2098311686251535e-01, 8.0353950080642028e-02, 4.8139906731089997e-02, 2.6000340271244451e-02, 1.2651375112800185e-02, 5.5416312894389780e-03, 2.1831319760967165e-03, 7.7269582168165273e-04, 2.4541809273052672e-04, 6.9854324445415533e-05, 1.7791805918220274e-05, 4.0482331787772522e-06, 8.2135445478328264e-07, 1.4829694050050112e-07, 2.3773662147574315e-08, 3.3755847311277282e-09, 4.2335937835110236e-10, 4.6760103859850812e-11, 4.5333033745839362e-12, 3.8436817248766534e-13, 2.8387673951693530e-14, 1.8181691304932292e-15, 1.0049051491574811e-16, 4.7668311711866824e-18, 1.9288793268371580e-19, 6.6129511764811165e-21, 1.9062601886875492e-22, 4.5806010985499422e-24, 9.0859656470487372e-26, 1.4712415549741861e-27, 1.9199707067949033e-29, 1.9895468942695488e-31, 1.6088732079384737e-33, 9.9468000592214207e-36, 4.5874016658583215e-38, 1.5317989647111863e-40, 3.5689385617810602e-43, 5.5370648197825761e-46, 5.3832225069701608e-49, 3.0222939315022155e-52, 8.7337328359193298e-56, 1.0933824737518103e-59, 4.4687024216810169e-64, 3.4808413877180985e-69, 1.3153371477011018e-75}, + {1.9163113126364858e-76, 5.3782147987051925e-70, 7.2563879227687952e-65, 1.8575257861979059e-60, 1.5480113585024239e-56, 5.5781996438680938e-53, 1.0331986095466757e-49, 1.1039698088171895e-46, 7.3860282667906572e-44, 3.2885519707581838e-41, 1.0211695752712912e-38, 2.2950262940501390e-36, 3.8466556677503065e-34, 4.9282126606183490e-32, 4.9266058774066898e-30, 3.9104187247799965e-28, 2.5014139383687256e-26, 1.3062311410367629e-24, 5.6310279110780034e-23, 2.0237140711644305e-21, 6.1159230112779824e-20, 1.5662392354042098e-18, 3.4222031640236014e-17, 6.4188994417848841e-16, 1.0392178377829332e-14, 1.4594559933116930e-13, 1.7858814626910534e-12, 1.9118156866346926e-11, 1.7970567599571068e-10, 1.4881403983681883e-09, 1.0889411432936255e-08, 7.0605103886976605e-08, 4.0665248009122635e-07, 2.0852201445349388e-06, 9.5392954689367993e-06, 3.9005661581998708e-05, 1.4279713128781597e-04, 4.6876282593032669e-04, 1.3817279615374414e-03, 3.6614915226082989e-03, 8.7323289056329013e-03, 1.8760838951499537e-02, 3.6339904964249992e-02, 6.3508495757082825e-02, 1.0019666687230201e-01, 1.4277636364566415e-01, 1.8382375801093334e-01, 2.1389634702935822e-01, 2.2497264372314615e-01, 2.1389634702935822e-01, 1.8382375801093334e-01, 1.4277636364566415e-01, 1.0019666687230201e-01, 6.3508495757082825e-02, 3.6339904964249992e-02, 1.8760838951499537e-02, 8.7323289056329013e-03, 3.6614915226082989e-03, 1.3817279615374414e-03, 4.6876282593032669e-04, 1.4279713128781597e-04, 3.9005661581998708e-05, 9.5392954689367993e-06, 2.0852201445349388e-06, 4.0665248009122635e-07, 7.0605103886976605e-08, 1.0889411432936255e-08, 1.4881403983681883e-09, 1.7970567599571068e-10, 1.9118156866346926e-11, 1.7858814626910534e-12, 1.4594559933116930e-13, 1.0392178377829332e-14, 6.4188994417848841e-16, 3.4222031640236014e-17, 1.5662392354042098e-18, 6.1159230112779824e-20, 2.0237140711644305e-21, 5.6310279110780034e-23, 1.3062311410367629e-24, 2.5014139383687256e-26, 3.9104187247799965e-28, 4.9266058774066898e-30, 4.9282126606183490e-32, 3.8466556677503065e-34, 2.2950262940501390e-36, 1.0211695752712912e-38, 3.2885519707581838e-41, 7.3860282667906572e-44, 1.1039698088171895e-46, 1.0331986095466757e-49, 5.5781996438680938e-53, 1.5480113585024239e-56, 1.8575257861979059e-60, 7.2563879227687952e-65, 5.3782147987051925e-70, 1.9163113126364858e-76}, + {2.7904525118679737e-77, 8.3020782212471425e-71, 1.1767736856636937e-65, 3.1505048454950654e-61, 2.7383297861245024e-57, 1.0271804264134620e-53, 1.9777901946758928e-50, 2.1945724897613748e-47, 1.5235549200899557e-44, 7.0346474438870195e-42, 2.2642373940609524e-39, 5.2728051887223330e-37, 9.1548141716730934e-35, 1.2147369169275739e-32, 1.2575027798926635e-30, 1.0335182999889521e-28, 6.8454256421150675e-27, 3.7013456293648089e-25, 1.6522412624655730e-23, 6.1491894101104838e-22, 1.9247067870562822e-20, 5.1057396537975428e-19, 1.1557955215269003e-17, 2.2464616952811288e-16, 3.7697131696054083e-15, 5.4886703549372233e-14, 6.9650658814205409e-13, 7.7347769030963229e-12, 7.5445969018975008e-11, 6.4855152005816811e-10, 4.9282840753506927e-09, 3.3196572232173258e-08, 1.9871572271899896e-07, 1.0595200143943266e-06, 5.0423148877264742e-06, 2.1459377904439359e-05, 8.1811800690556602e-05, 2.7983364446273394e-04, 8.5995448443042602e-04, 2.3773109222215024e-03, 5.9185523609855805e-03, 1.3282862169963864e-02, 2.6896050260216100e-02, 4.9173217905643024e-02, 8.1224149327040002e-02, 1.2127838443962285e-01, 1.6375781072963536e-01, 2.0002035034474053e-01, 2.2104883827723254e-01, 2.2104883827723254e-01, 2.0002035034474053e-01, 1.6375781072963536e-01, 1.2127838443962285e-01, 8.1224149327040002e-02, 4.9173217905643024e-02, 2.6896050260216100e-02, 1.3282862169963864e-02, 5.9185523609855805e-03, 2.3773109222215024e-03, 8.5995448443042602e-04, 2.7983364446273394e-04, 8.1811800690556602e-05, 2.1459377904439359e-05, 5.0423148877264742e-06, 1.0595200143943266e-06, 1.9871572271899896e-07, 3.3196572232173258e-08, 4.9282840753506927e-09, 6.4855152005816811e-10, 7.5445969018975008e-11, 7.7347769030963229e-12, 6.9650658814205409e-13, 5.4886703549372233e-14, 3.7697131696054083e-15, 2.2464616952811288e-16, 1.1557955215269003e-17, 5.1057396537975428e-19, 1.9247067870562822e-20, 6.1491894101104838e-22, 1.6522412624655730e-23, 3.7013456293648089e-25, 6.8454256421150675e-27, 1.0335182999889521e-28, 1.2575027798926635e-30, 1.2147369169275739e-32, 9.1548141716730934e-35, 5.2728051887223330e-37, 2.2642373940609524e-39, 7.0346474438870195e-42, 1.5235549200899557e-44, 2.1945724897613748e-47, 1.9777901946758928e-50, 1.0271804264134620e-53, 2.7383297861245024e-57, 3.1505048454950654e-61, 1.1767736856636937e-65, 8.3020782212471425e-71, 2.7904525118679737e-77}, + {4.0613138578260408e-78, 1.2803753168202646e-71, 1.9059379634157273e-66, 5.3348322229477923e-62, 4.8344851717020582e-58, 1.8871785659984032e-54, 3.7761789448607101e-51, 4.3499235924727088e-48, 3.1326162048099509e-45, 1.4994923130410846e-42, 5.0011700959096005e-40, 1.2063719426097628e-37, 2.1689987827926264e-35, 2.9797144315839396e-33, 3.1931805290733206e-31, 2.7165497805935431e-29, 1.8623802130980743e-27, 1.0423117478273709e-25, 4.8161473163605573e-24, 1.8555204994489541e-22, 6.0128622969968872e-21, 1.6515980171005252e-19, 3.8719360930637078e-18, 7.7952821069111630e-17, 1.3552585228326797e-15, 2.0448819688025393e-14, 2.6898645575023506e-13, 3.0973073233390342e-12, 3.1335844312742886e-11, 2.7949011969950757e-10, 2.2044098210910168e-09, 1.5418168139637173e-08, 9.5872357774191023e-08, 5.3122836336339743e-07, 2.6285303500427774e-06, 1.1636493707975660e-05, 4.6170574104968263e-05, 1.6444759671629532e-04, 5.2653510513586970e-04, 1.5174715210062894e-03, 3.9409789851024037e-03, 9.2324971205438137e-03, 1.9527821414966836e-02, 3.7320312768871315e-02, 6.4488485276268173e-02, 1.0081054546716739e-01, 1.4263049549711082e-01, 1.8270590844100287e-01, 2.1195024923496616e-01, 2.2270019277644792e-01, 2.1195024923496616e-01, 1.8270590844100287e-01, 1.4263049549711082e-01, 1.0081054546716739e-01, 6.4488485276268173e-02, 3.7320312768871315e-02, 1.9527821414966836e-02, 9.2324971205438137e-03, 3.9409789851024037e-03, 1.5174715210062894e-03, 5.2653510513586970e-04, 1.6444759671629532e-04, 4.6170574104968263e-05, 1.1636493707975660e-05, 2.6285303500427774e-06, 5.3122836336339743e-07, 9.5872357774191023e-08, 1.5418168139637173e-08, 2.2044098210910168e-09, 2.7949011969950757e-10, 3.1335844312742886e-11, 3.0973073233390342e-12, 2.6898645575023506e-13, 2.0448819688025393e-14, 1.3552585228326797e-15, 7.7952821069111630e-17, 3.8719360930637078e-18, 1.6515980171005252e-19, 6.0128622969968872e-21, 1.8555204994489541e-22, 4.8161473163605573e-24, 1.0423117478273709e-25, 1.8623802130980743e-27, 2.7165497805935431e-29, 3.1931805290733206e-31, 2.9797144315839396e-33, 2.1689987827926264e-35, 1.2063719426097628e-37, 5.0011700959096005e-40, 1.4994923130410846e-42, 3.1326162048099509e-45, 4.3499235924727088e-48, 3.7761789448607101e-51, 1.8871785659984032e-54, 4.8344851717020582e-58, 5.3348322229477923e-62, 1.9059379634157273e-66, 1.2803753168202646e-71, 4.0613138578260408e-78}, + {5.9080678650312624e-79, 1.9728605748792453e-72, 3.0830289900033436e-67, 9.0192223036937046e-63, 8.5188830817618133e-59, 3.4594779364755318e-55, 7.1915294634635365e-52, 8.5975639548257647e-49, 6.4207252053484628e-46, 3.1852178778360094e-43, 1.1004706827142279e-40, 2.7487848843571218e-38, 5.1162326043852910e-36, 7.2745725968876294e-34, 8.0674342787094055e-32, 7.1018122263849361e-30, 5.0377911662132328e-28, 2.9173500726293596e-26, 1.3948415260687786e-24, 5.5610269616591533e-23, 1.8649976751302685e-21, 5.3023161831319081e-20, 1.2868329211211647e-18, 2.6824921647604057e-17, 4.8298353217030778e-16, 7.5488968779152708e-15, 1.0288749373509957e-13, 1.2278785144101270e-12, 1.2879038257315668e-11, 1.1913006349290762e-10, 9.7479212538717177e-10, 7.0758572838895756e-09, 4.5681275084849536e-08, 2.6290974837537234e-07, 1.3517971591103712e-06, 6.2215248177778678e-06, 2.5676159384549134e-05, 9.5171627785509925e-05, 3.1729197104330006e-04, 9.5269218854862072e-04, 2.5792732600590893e-03, 6.3030002856080628e-03, 1.3915665220231790e-02, 2.7779127385933564e-02, 5.0175812677428613e-02, 8.2051827391224449e-02, 1.2153798684410418e-01, 1.6313003050278282e-01, 1.9846285025418653e-01, 2.1889262958743932e-01, 2.1889262958743932e-01, 1.9846285025418653e-01, 1.6313003050278282e-01, 1.2153798684410418e-01, 8.2051827391224449e-02, 5.0175812677428613e-02, 2.7779127385933564e-02, 1.3915665220231790e-02, 6.3030002856080628e-03, 2.5792732600590893e-03, 9.5269218854862072e-04, 3.1729197104330006e-04, 9.5171627785509925e-05, 2.5676159384549134e-05, 6.2215248177778678e-06, 1.3517971591103712e-06, 2.6290974837537234e-07, 4.5681275084849536e-08, 7.0758572838895756e-09, 9.7479212538717177e-10, 1.1913006349290762e-10, 1.2879038257315668e-11, 1.2278785144101270e-12, 1.0288749373509957e-13, 7.5488968779152708e-15, 4.8298353217030778e-16, 2.6824921647604057e-17, 1.2868329211211647e-18, 5.3023161831319081e-20, 1.8649976751302685e-21, 5.5610269616591533e-23, 1.3948415260687786e-24, 2.9173500726293596e-26, 5.0377911662132328e-28, 7.1018122263849361e-30, 8.0674342787094055e-32, 7.2745725968876294e-34, 5.1162326043852910e-36, 2.7487848843571218e-38, 1.1004706827142279e-40, 3.1852178778360094e-43, 6.4207252053484628e-46, 8.5975639548257647e-49, 7.1915294634635365e-52, 3.4594779364755318e-55, 8.5188830817618133e-59, 9.0192223036937046e-63, 3.0830289900033436e-67, 1.9728605748792453e-72, 5.9080678650312624e-79}, + {8.5904309894818364e-80, 3.0371816846686698e-73, 4.9809124279561082e-68, 1.5224294774877133e-63, 1.4982961830544962e-59, 6.3278572616256388e-56, 1.3661743924144741e-52, 1.6945475116309319e-49, 1.3119398711365523e-46, 6.7430272036894988e-44, 2.4125325785224105e-41, 6.2381218594744620e-39, 1.2015973481338649e-36, 1.7677477939830743e-34, 2.0280915379277212e-32, 1.8467949790116279e-30, 1.3550808933459723e-28, 8.1168066229507355e-27, 4.0142573977672800e-25, 1.6555633107937502e-23, 5.7440707561477782e-22, 1.6897039658922656e-20, 4.2436086794049572e-19, 9.1557867438886624e-18, 1.7065546359370669e-16, 2.7618433228960722e-15, 3.8986379094133088e-14, 4.8201156943039955e-13, 5.2391878407492571e-12, 5.0236198872007664e-11, 4.2625383198445261e-10, 3.2096074629923419e-09, 2.1502703382505708e-08, 1.2847504869574726e-07, 6.8606640833299067e-07, 3.2808733242412502e-06, 1.4075589850899586e-05, 5.4263099453546539e-05, 1.8825409449540776e-04, 5.8852552673756763e-04, 1.6599244925103198e-03, 4.2284362004214454e-03, 9.7376438372710882e-03, 2.0289684052787870e-02, 3.8279047715437671e-02, 6.5430893699439191e-02, 1.0138360090162955e-01, 1.4246231456883673e-01, 1.8160258790817957e-01, 2.1005593297000114e-01, 2.2049524037272045e-01, 2.1005593297000114e-01, 1.8160258790817957e-01, 1.4246231456883673e-01, 1.0138360090162955e-01, 6.5430893699439191e-02, 3.8279047715437671e-02, 2.0289684052787870e-02, 9.7376438372710882e-03, 4.2284362004214454e-03, 1.6599244925103198e-03, 5.8852552673756763e-04, 1.8825409449540776e-04, 5.4263099453546539e-05, 1.4075589850899586e-05, 3.2808733242412502e-06, 6.8606640833299067e-07, 1.2847504869574726e-07, 2.1502703382505708e-08, 3.2096074629923419e-09, 4.2625383198445261e-10, 5.0236198872007664e-11, 5.2391878407492571e-12, 4.8201156943039955e-13, 3.8986379094133088e-14, 2.7618433228960722e-15, 1.7065546359370669e-16, 9.1557867438886624e-18, 4.2436086794049572e-19, 1.6897039658922656e-20, 5.7440707561477782e-22, 1.6555633107937502e-23, 4.0142573977672800e-25, 8.1168066229507355e-27, 1.3550808933459723e-28, 1.8467949790116279e-30, 2.0280915379277212e-32, 1.7677477939830743e-34, 1.2015973481338649e-36, 6.2381218594744620e-39, 2.4125325785224105e-41, 6.7430272036894988e-44, 1.3119398711365523e-46, 1.6945475116309319e-49, 1.3661743924144741e-52, 6.3278572616256388e-56, 1.4982961830544962e-59, 1.5224294774877133e-63, 4.9809124279561082e-68, 3.0371816846686698e-73, 8.5904309894818364e-80}, + {1.2484709934169793e-80, 4.6716134267455262e-74, 8.0373302337190505e-69, 2.5658825214250866e-64, 2.6303256479665557e-60, 1.1549629962198519e-56, 2.5889667003232748e-53, 3.3307225187898004e-50, 2.6725211308631837e-47, 1.4227172891228852e-44, 5.2696956176078606e-42, 1.4101103127648418e-39, 2.8100935042395224e-37, 4.2761357132188511e-35, 5.0736585413756089e-33, 4.7776103023740991e-31, 3.6248608340202214e-29, 2.2451158851842135e-27, 1.1481416337131872e-25, 4.8966201179064703e-24, 1.7569837815084929e-22, 5.3457088341630912e-21, 1.3887935290404047e-19, 3.1001141967930157e-18, 5.9794936879871788e-17, 1.0016087747850758e-15, 1.4637583603666311e-14, 1.8740601774404304e-13, 2.1099943426302045e-12, 2.0963143669741310e-11, 1.8436168972317116e-10, 1.4393514257953216e-09, 1.0001836240436016e-08, 6.2007747893151711e-08, 3.4372586316527799e-07, 1.7070358456037084e-06, 7.6089581259975007e-06, 3.0491388427439179e-05, 1.1001458276280751e-04, 3.5787758856259302e-04, 1.0509023763580526e-03, 2.7887647298672400e-03, 6.6943659482095498e-03, 1.4548976670515633e-02, 2.8649120680685196e-02, 5.1148315515202297e-02, 8.2838910302204208e-02, 1.2176431106358794e-01, 1.6249750087283824e-01, 1.9693934921359804e-01, 2.1679829114353039e-01, 2.1679829114353039e-01, 1.9693934921359804e-01, 1.6249750087283824e-01, 1.2176431106358794e-01, 8.2838910302204208e-02, 5.1148315515202297e-02, 2.8649120680685196e-02, 1.4548976670515633e-02, 6.6943659482095498e-03, 2.7887647298672400e-03, 1.0509023763580526e-03, 3.5787758856259302e-04, 1.1001458276280751e-04, 3.0491388427439179e-05, 7.6089581259975007e-06, 1.7070358456037084e-06, 3.4372586316527799e-07, 6.2007747893151711e-08, 1.0001836240436016e-08, 1.4393514257953216e-09, 1.8436168972317116e-10, 2.0963143669741310e-11, 2.1099943426302045e-12, 1.8740601774404304e-13, 1.4637583603666311e-14, 1.0016087747850758e-15, 5.9794936879871788e-17, 3.1001141967930157e-18, 1.3887935290404047e-19, 5.3457088341630912e-21, 1.7569837815084929e-22, 4.8966201179064703e-24, 1.1481416337131872e-25, 2.2451158851842135e-27, 3.6248608340202214e-29, 4.7776103023740991e-31, 5.0736585413756089e-33, 4.2761357132188511e-35, 2.8100935042395224e-37, 1.4101103127648418e-39, 5.2696956176078606e-42, 1.4227172891228852e-44, 2.6725211308631837e-47, 3.3307225187898004e-50, 2.5889667003232748e-53, 1.1549629962198519e-56, 2.6303256479665557e-60, 2.5658825214250866e-64, 8.0373302337190505e-69, 4.6716134267455262e-74, 1.2484709934169793e-80}, + {1.8135909934565948e-81, 7.1794482518779405e-75, 1.2953741930788741e-69, 4.3179663130756179e-65, 4.6092689309993016e-61, 2.1035897073764635e-57, 4.8944169739176386e-54, 6.5290610509647759e-51, 5.4278702104818919e-48, 2.9919651066058538e-45, 1.1469498354442222e-42, 3.1751925459280292e-40, 6.5444038132328712e-38, 1.0297652702618718e-35, 1.2632131984833186e-33, 1.2296697906080111e-31, 9.6441699135755975e-30, 6.1744578340056585e-28, 3.2639881507273933e-26, 1.4390083206149803e-24, 5.3380455822882838e-23, 1.6792427517695717e-21, 4.5112507797362053e-20, 1.0414929706906582e-18, 2.0779783402868767e-17, 3.6013157967372950e-16, 5.4464951383584157e-15, 7.2181098533397167e-14, 8.4145383929577368e-13, 8.6584557144940455e-12, 7.8890516800983647e-11, 6.3831524130277722e-10, 4.5984942968861874e-09, 2.9567316716160832e-08, 1.7005133441347446e-07, 8.7658428229201604e-07, 4.0574245645905015e-06, 1.6891865749199694e-05, 6.3348592408607267e-05, 2.1430344005210969e-04, 6.5478304395432502e-04, 1.8089687249743006e-03, 4.5234328605134695e-03, 1.0247034345774014e-02, 2.1045743544451385e-02, 3.9216150726808105e-02, 6.6337015149646864e-02, 1.0191809344727074e-01, 1.4227374613665661e-01, 1.8051385843527265e-01, 2.0821116124461711e-01, 2.1835450988366478e-01, 2.0821116124461711e-01, 1.8051385843527265e-01, 1.4227374613665661e-01, 1.0191809344727074e-01, 6.6337015149646864e-02, 3.9216150726808105e-02, 2.1045743544451385e-02, 1.0247034345774014e-02, 4.5234328605134695e-03, 1.8089687249743006e-03, 6.5478304395432502e-04, 2.1430344005210969e-04, 6.3348592408607267e-05, 1.6891865749199694e-05, 4.0574245645905015e-06, 8.7658428229201604e-07, 1.7005133441347446e-07, 2.9567316716160832e-08, 4.5984942968861874e-09, 6.3831524130277722e-10, 7.8890516800983647e-11, 8.6584557144940455e-12, 8.4145383929577368e-13, 7.2181098533397167e-14, 5.4464951383584157e-15, 3.6013157967372950e-16, 2.0779783402868767e-17, 1.0414929706906582e-18, 4.5112507797362053e-20, 1.6792427517695717e-21, 5.3380455822882838e-23, 1.4390083206149803e-24, 3.2639881507273933e-26, 6.1744578340056585e-28, 9.6441699135755975e-30, 1.2296697906080111e-31, 1.2632131984833186e-33, 1.0297652702618718e-35, 6.5444038132328712e-38, 3.1751925459280292e-40, 1.1469498354442222e-42, 2.9919651066058538e-45, 5.4278702104818919e-48, 6.5290610509647759e-51, 4.8944169739176386e-54, 2.1035897073764635e-57, 4.6092689309993016e-61, 4.3179663130756179e-65, 1.2953741930788741e-69, 7.1794482518779405e-75, 1.8135909934565948e-81}, + {2.6333035610382397e-82, 1.1024259296315383e-75, 2.0852967445741233e-70, 7.2556400241843898e-66, 8.0626671773555472e-62, 3.8234147683158063e-58, 9.2309809923115915e-55, 1.2764717039702522e-51, 1.0991625015027042e-48, 6.2718288470036324e-46, 2.4875851238977396e-43, 7.1225496037923785e-41, 1.5178899706379763e-38, 2.4689751624056617e-36, 3.1303492079755755e-34, 3.1491543092696820e-32, 2.5522940793940470e-30, 1.6885482670813982e-28, 9.2239272353929576e-27, 4.2024365472164892e-25, 1.6110964547970300e-23, 5.2383797573874037e-22, 1.4547178325694397e-20, 3.4721710760327322e-19, 7.1634722023972862e-18, 1.2840032078315100e-16, 2.0088075710888178e-15, 2.7546357750311648e-14, 3.3235533916670117e-13, 3.5405078866592410e-12, 3.3406627081403544e-11, 2.8000417787301215e-10, 2.0903260822482034e-09, 1.3932720755460754e-08, 8.3098897726797486e-08, 4.4440079875949290e-07, 2.1349200492771325e-06, 9.2289528191432300e-06, 3.5954963665620299e-05, 1.2641879089097217e-04, 4.0166542717281779e-04, 1.1545621668817155e-03, 3.0055192270927668e-03, 7.0920553324460628e-03, 1.5182046088138676e-02, 2.9505655023499801e-02, 5.2091376675144491e-02, 8.3587237918301055e-02, 1.2195957249370640e-01, 1.6186130554382056e-01, 1.9544872749879730e-01, 2.1476292059027455e-01, 2.1476292059027455e-01, 1.9544872749879730e-01, 1.6186130554382056e-01, 1.2195957249370640e-01, 8.3587237918301055e-02, 5.2091376675144491e-02, 2.9505655023499801e-02, 1.5182046088138676e-02, 7.0920553324460628e-03, 3.0055192270927668e-03, 1.1545621668817155e-03, 4.0166542717281779e-04, 1.2641879089097217e-04, 3.5954963665620299e-05, 9.2289528191432300e-06, 2.1349200492771325e-06, 4.4440079875949290e-07, 8.3098897726797486e-08, 1.3932720755460754e-08, 2.0903260822482034e-09, 2.8000417787301215e-10, 3.3406627081403544e-11, 3.5405078866592410e-12, 3.3235533916670117e-13, 2.7546357750311648e-14, 2.0088075710888178e-15, 1.2840032078315100e-16, 7.1634722023972862e-18, 3.4721710760327322e-19, 1.4547178325694397e-20, 5.2383797573874037e-22, 1.6110964547970300e-23, 4.2024365472164892e-25, 9.2239272353929576e-27, 1.6885482670813982e-28, 2.5522940793940470e-30, 3.1491543092696820e-32, 3.1303492079755755e-34, 2.4689751624056617e-36, 1.5178899706379763e-38, 7.1225496037923785e-41, 2.4875851238977396e-43, 6.2718288470036324e-46, 1.0991625015027042e-48, 1.2764717039702522e-51, 9.2309809923115915e-55, 3.8234147683158063e-58, 8.0626671773555472e-62, 7.2556400241843898e-66, 2.0852967445741233e-70, 1.1024259296315383e-75, 2.6333035610382397e-82}, + {3.8217861138085193e-83, 1.6914062097101716e-76, 3.3530353599320843e-71, 1.2174103962049957e-66, 1.4078704255855603e-62, 6.9351300068921097e-59, 1.7369401373650657e-55, 2.4890859009540812e-52, 2.2194272123488213e-49, 1.3105586296104345e-46, 5.3766702664810952e-44, 1.5917657474423608e-41, 3.5064188455904165e-39, 5.8941611353204651e-37, 7.7216030296457281e-35, 8.0254188497506414e-33, 6.7194313102734894e-31, 4.5922904136653062e-29, 2.5914755539513213e-27, 1.2197280334801351e-25, 4.8310543796668917e-24, 1.6229893391874090e-22, 4.6574324658183078e-21, 1.1488922069252337e-19, 2.4500971300072567e-18, 4.5403372361053743e-17, 7.3453513452694623e-16, 1.0418125668654998e-14, 1.3004299981305270e-13, 1.4335908364459435e-12, 1.4002082648585132e-11, 1.2152299982982779e-10, 9.3968905695997315e-10, 6.4898261604097228e-09, 4.0121667112572270e-08, 2.2249156377389857e-07, 1.1087989233089753e-06, 4.9744232013977632e-06, 2.0121686738026826e-05, 7.3491681493347192e-05, 2.4267655305986469e-04, 7.2534332143885018e-04, 1.9644706290361147e-03, 4.8255384821498035e-03, 1.0759969971184533e-02, 2.1795386765479520e-02, 4.0131719533568026e-02, 6.7208115842432761e-02, 1.0241614803131452e-01, 1.4206655437043109e-01, 1.7943973488563147e-01, 2.0641382873539532e-01, 2.1627494312286819e-01, 2.0641382873539532e-01, 1.7943973488563147e-01, 1.4206655437043109e-01, 1.0241614803131452e-01, 6.7208115842432761e-02, 4.0131719533568026e-02, 2.1795386765479520e-02, 1.0759969971184533e-02, 4.8255384821498035e-03, 1.9644706290361147e-03, 7.2534332143885018e-04, 2.4267655305986469e-04, 7.3491681493347192e-05, 2.0121686738026826e-05, 4.9744232013977632e-06, 1.1087989233089753e-06, 2.2249156377389857e-07, 4.0121667112572270e-08, 6.4898261604097228e-09, 9.3968905695997315e-10, 1.2152299982982779e-10, 1.4002082648585132e-11, 1.4335908364459435e-12, 1.3004299981305270e-13, 1.0418125668654998e-14, 7.3453513452694623e-16, 4.5403372361053743e-17, 2.4500971300072567e-18, 1.1488922069252337e-19, 4.6574324658183078e-21, 1.6229893391874090e-22, 4.8310543796668917e-24, 1.2197280334801351e-25, 2.5914755539513213e-27, 4.5922904136653062e-29, 6.7194313102734894e-31, 8.0254188497506414e-33, 7.7216030296457281e-35, 5.8941611353204651e-37, 3.5064188455904165e-39, 1.5917657474423608e-41, 5.3766702664810952e-44, 1.3105586296104345e-46, 2.2194272123488213e-49, 2.4890859009540812e-52, 1.7369401373650657e-55, 6.9351300068921097e-59, 1.4078704255855603e-62, 1.2174103962049957e-66, 3.3530353599320843e-71, 1.6914062097101716e-76, 3.8217861138085193e-83}, + {5.5441992722068482e-84, 2.5929395481292082e-77, 5.3853541853574509e-72, 2.0397343220146265e-67, 2.4541249535874453e-63, 1.2554100822781216e-59, 3.2608376921091931e-56, 4.8412365544964550e-53, 4.4687726007935870e-50, 2.7300300393618730e-47, 1.1581833176995228e-44, 3.5442966005156755e-42, 8.0681149793680242e-40, 1.4011614007496688e-37, 1.8960834059704929e-35, 2.0353977109818878e-33, 1.7599996574525402e-31, 1.2422004027168656e-29, 7.2392001895975213e-28, 3.5188457649983255e-26, 1.4394549700596331e-24, 4.9949088636257322e-23, 1.4806823585568918e-21, 3.7736012205435806e-20, 8.3155142767475590e-19, 1.5925756694175446e-17, 2.6632797443869722e-16, 3.9055385475699820e-15, 5.0416061378516563e-14, 5.7492300646009343e-13, 5.8103188163962404e-12, 5.2193608370012943e-11, 4.1786070059665728e-10, 2.9889202437814213e-09, 1.9144674266312151e-08, 1.1003547442210821e-07, 5.6858218763614167e-07, 2.6459673129317030e-06, 1.1106993480718368e-05, 4.2117165655971054e-05, 1.4445933891050312e-04, 4.4872081587300148e-04, 1.2636334832367285e-03, 3.2292611575356744e-03, 7.4954912038533066e-03, 1.5814177885623497e-02, 3.0348423943327270e-02, 5.3005665528953826e-02, 8.4298566514348958e-02, 1.2212582857840716e-01, 1.6122241452497918e-01, 1.9398990851223818e-01, 2.1278380261127008e-01, 2.1278380261127008e-01, 1.9398990851223818e-01, 1.6122241452497918e-01, 1.2212582857840716e-01, 8.4298566514348958e-02, 5.3005665528953826e-02, 3.0348423943327270e-02, 1.5814177885623497e-02, 7.4954912038533066e-03, 3.2292611575356744e-03, 1.2636334832367285e-03, 4.4872081587300148e-04, 1.4445933891050312e-04, 4.2117165655971054e-05, 1.1106993480718368e-05, 2.6459673129317030e-06, 5.6858218763614167e-07, 1.1003547442210821e-07, 1.9144674266312151e-08, 2.9889202437814213e-09, 4.1786070059665728e-10, 5.2193608370012943e-11, 5.8103188163962404e-12, 5.7492300646009343e-13, 5.0416061378516563e-14, 3.9055385475699820e-15, 2.6632797443869722e-16, 1.5925756694175446e-17, 8.3155142767475590e-19, 3.7736012205435806e-20, 1.4806823585568918e-21, 4.9949088636257322e-23, 1.4394549700596331e-24, 3.5188457649983255e-26, 7.2392001895975213e-28, 1.2422004027168656e-29, 1.7599996574525402e-31, 2.0353977109818878e-33, 1.8960834059704929e-35, 1.4011614007496688e-37, 8.0681149793680242e-40, 3.5442966005156755e-42, 1.1581833176995228e-44, 2.7300300393618730e-47, 4.4687726007935870e-50, 4.8412365544964550e-53, 3.2608376921091931e-56, 1.2554100822781216e-59, 2.4541249535874453e-63, 2.0397343220146265e-67, 5.3853541853574509e-72, 2.5929395481292082e-77, 5.5441992722068482e-84}, + {8.0393570948066263e-85, 3.9718103441759187e-78, 8.6398120096864360e-73, 3.4126815525065270e-68, 4.2706414980124341e-64, 2.2680834264069969e-60, 6.1079802227760500e-57, 9.3924613692270336e-54, 8.9727413440350903e-51, 5.6695759907967620e-48, 2.4865399657656492e-45, 7.8635083915713631e-43, 1.8492505278934263e-40, 3.3170216420826621e-38, 4.6353055637591542e-36, 5.1377976964188761e-34, 4.5868230110636832e-32, 3.3422916829863083e-30, 2.0109122099933846e-28, 1.0091662170872907e-26, 4.2622901606926843e-25, 1.5271754441949008e-23, 4.6750298903216843e-22, 1.2305362144434042e-20, 2.8009656241231101e-19, 5.5420769366655970e-18, 9.5769111189688996e-17, 1.4514991221804437e-15, 1.9370075854564139e-14, 2.2840535977994185e-13, 2.3875175115445612e-12, 2.2189005868460593e-11, 1.8384761407124325e-10, 1.3614036372254147e-09, 9.0305672540467943e-09, 5.3771344014689486e-08, 2.8795698296534307e-07, 1.3893404522738127e-06, 6.0491308542217258e-06, 2.3802318133010187e-05, 8.4755918374596230e-05, 2.7344820329821672e-04, 8.0022923976588462e-04, 2.1262829728506513e-03, 5.1343246513282466e-03, 1.1275787985601648e-02, 2.2538065887400437e-02, 4.1025901106205930e-02, 6.8045431494172207e-02, 1.0287976270898229e-01, 1.4184235712795296e-01, 1.7838019194959490e-01, 2.0466195210272575e-01, 2.1425368197218711e-01, 2.0466195210272575e-01, 1.7838019194959490e-01, 1.4184235712795296e-01, 1.0287976270898229e-01, 6.8045431494172207e-02, 4.1025901106205930e-02, 2.2538065887400437e-02, 1.1275787985601648e-02, 5.1343246513282466e-03, 2.1262829728506513e-03, 8.0022923976588462e-04, 2.7344820329821672e-04, 8.4755918374596230e-05, 2.3802318133010187e-05, 6.0491308542217258e-06, 1.3893404522738127e-06, 2.8795698296534307e-07, 5.3771344014689486e-08, 9.0305672540467943e-09, 1.3614036372254147e-09, 1.8384761407124325e-10, 2.2189005868460593e-11, 2.3875175115445612e-12, 2.2840535977994185e-13, 1.9370075854564139e-14, 1.4514991221804437e-15, 9.5769111189688996e-17, 5.5420769366655970e-18, 2.8009656241231101e-19, 1.2305362144434042e-20, 4.6750298903216843e-22, 1.5271754441949008e-23, 4.2622901606926843e-25, 1.0091662170872907e-26, 2.0109122099933846e-28, 3.3422916829863083e-30, 4.5868230110636832e-32, 5.1377976964188761e-34, 4.6353055637591542e-36, 3.3170216420826621e-38, 1.8492505278934263e-40, 7.8635083915713631e-43, 2.4865399657656492e-45, 5.6695759907967620e-48, 8.9727413440350903e-51, 9.3924613692270336e-54, 6.1079802227760500e-57, 2.2680834264069969e-60, 4.2706414980124341e-64, 3.4126815525065270e-68, 8.6398120096864360e-73, 3.9718103441759187e-78, 8.0393570948066263e-85}, + {1.1652438369940990e-85, 6.0791348825232945e-79, 1.3845734727539209e-73, 5.7018195541180805e-69, 7.4193203262024338e-65, 4.0896774498494807e-61, 1.1415803801508950e-57, 1.8177229307902597e-54, 1.7966861107994258e-51, 1.1738936354016808e-48, 5.3209955905676318e-46, 1.7384628972964638e-43, 4.2224503669018324e-41, 7.8205013430131660e-39, 1.1282489276123687e-36, 1.2908866148089198e-34, 1.1895168657985647e-32, 8.9460231384332668e-31, 5.5552056820850460e-29, 2.8773904696541066e-27, 1.2543771045577858e-25, 4.6393197457827112e-24, 1.4661278293822309e-22, 3.9843331940864138e-21, 9.3649180986702086e-20, 1.9137000334222806e-18, 3.4159437284687078e-17, 5.3490074750121478e-16, 7.3765684098315642e-15, 8.9908236810354557e-14, 9.7167575155334535e-13, 9.3392850013870488e-12, 8.0050126851044650e-11, 6.1341491782010079e-10, 4.2120058561600563e-09, 2.5970629339726590e-08, 1.4407085283844865e-07, 7.2034690286882965e-07, 3.2515206739898432e-06, 1.3269605500302639e-05, 4.9028384509802042e-05, 1.6420793698012457e-04, 4.9909954967131240e-04, 1.3780641953787555e-03, 3.4597075988944920e-03, 7.9041144380998778e-03, 1.6444728895483641e-02, 3.1177182981317560e-02, 5.3891864826823496e-02, 8.4974571583542949e-02, 1.2226499127815092e-01, 1.6058169612107806e-01, 1.9256185751562635e-01, 2.1085839371676188e-01, 2.1085839371676188e-01, 1.9256185751562635e-01, 1.6058169612107806e-01, 1.2226499127815092e-01, 8.4974571583542949e-02, 5.3891864826823496e-02, 3.1177182981317560e-02, 1.6444728895483641e-02, 7.9041144380998778e-03, 3.4597075988944920e-03, 1.3780641953787555e-03, 4.9909954967131240e-04, 1.6420793698012457e-04, 4.9028384509802042e-05, 1.3269605500302639e-05, 3.2515206739898432e-06, 7.2034690286882965e-07, 1.4407085283844865e-07, 2.5970629339726590e-08, 4.2120058561600563e-09, 6.1341491782010079e-10, 8.0050126851044650e-11, 9.3392850013870488e-12, 9.7167575155334535e-13, 8.9908236810354557e-14, 7.3765684098315642e-15, 5.3490074750121478e-16, 3.4159437284687078e-17, 1.9137000334222806e-18, 9.3649180986702086e-20, 3.9843331940864138e-21, 1.4661278293822309e-22, 4.6393197457827112e-24, 1.2543771045577858e-25, 2.8773904696541066e-27, 5.5552056820850460e-29, 8.9460231384332668e-31, 1.1895168657985647e-32, 1.2908866148089198e-34, 1.1282489276123687e-36, 7.8205013430131660e-39, 4.2224503669018324e-41, 1.7384628972964638e-43, 5.3209955905676318e-46, 1.1738936354016808e-48, 1.7966861107994258e-51, 1.8177229307902597e-54, 1.1415803801508950e-57, 4.0896774498494807e-61, 7.4193203262024338e-65, 5.7018195541180805e-69, 1.3845734727539209e-73, 6.0791348825232945e-79, 1.1652438369940990e-85}, + {1.6882167305707454e-86, 9.2973163909464803e-80, 2.2164453269063499e-74, 9.5134149540243336e-70, 1.2868308966878782e-65, 7.3601988558208524e-62, 2.1289805828564999e-58, 3.5092885496818465e-55, 3.5879758763817130e-52, 2.4233946264708683e-49, 1.1349953099138248e-46, 3.8300452415564833e-44, 9.6052219657335494e-42, 1.8364466079421476e-39, 2.7344551836642605e-37, 3.2286335472886435e-35, 3.0699209573361954e-33, 2.3822649787982913e-31, 1.5263559111336781e-29, 8.1574699196788167e-28, 3.6694695554120368e-26, 1.4004790074896691e-24, 4.5675182897648129e-23, 1.2811473098169559e-21, 3.1084252235905216e-20, 6.5579821121285801e-19, 1.2087664560459120e-17, 1.9548969486564158e-16, 2.7849389834496225e-15, 3.5072844186621564e-14, 3.9175124016391924e-13, 3.8925586774167020e-12, 3.4501563168365539e-11, 2.7347438232977245e-10, 1.9430095134453053e-09, 1.2400464068693708e-08, 7.1228670517261927e-08, 3.6889724023685680e-07, 1.7254610364884881e-06, 7.2997812630457740e-06, 2.7971738168589429e-05, 9.7203453180453000e-05, 3.0668682564469456e-04, 8.7945145983116615e-04, 2.2942465962944290e-03, 5.4493669764638540e-03, 1.1793861247331682e-02, 2.3273293687959880e-02, 4.1898884894253120e-02, 6.8850165394430590e-02, 1.0331081665178690e-01, 1.4160263924602950e-01, 1.7733517017411166e-01, 2.0295366115211383e-01, 2.1228805186235042e-01, 2.0295366115211383e-01, 1.7733517017411166e-01, 1.4160263924602950e-01, 1.0331081665178690e-01, 6.8850165394430590e-02, 4.1898884894253120e-02, 2.3273293687959880e-02, 1.1793861247331682e-02, 5.4493669764638540e-03, 2.2942465962944290e-03, 8.7945145983116615e-04, 3.0668682564469456e-04, 9.7203453180453000e-05, 2.7971738168589429e-05, 7.2997812630457740e-06, 1.7254610364884881e-06, 3.6889724023685680e-07, 7.1228670517261927e-08, 1.2400464068693708e-08, 1.9430095134453053e-09, 2.7347438232977245e-10, 3.4501563168365539e-11, 3.8925586774167020e-12, 3.9175124016391924e-13, 3.5072844186621564e-14, 2.7849389834496225e-15, 1.9548969486564158e-16, 1.2087664560459120e-17, 6.5579821121285801e-19, 3.1084252235905216e-20, 1.2811473098169559e-21, 4.5675182897648129e-23, 1.4004790074896691e-24, 3.6694695554120368e-26, 8.1574699196788167e-28, 1.5263559111336781e-29, 2.3822649787982913e-31, 3.0699209573361954e-33, 3.2286335472886435e-35, 2.7344551836642605e-37, 1.8364466079421476e-39, 9.6052219657335494e-42, 3.8300452415564833e-44, 1.1349953099138248e-46, 2.4233946264708683e-49, 3.5879758763817130e-52, 3.5092885496818465e-55, 2.1289805828564999e-58, 7.3601988558208524e-62, 1.2868308966878782e-65, 9.5134149540243336e-70, 2.2164453269063499e-74, 9.2973163909464803e-80, 1.6882167305707454e-86}, + {2.4448842535551943e-87, 1.4208271558885895e-80, 3.5443349838315051e-75, 1.5851638341206613e-70, 2.2283154783345243e-66, 1.3221294591344122e-62, 3.9619475088358356e-59, 6.7588233504303362e-56, 7.1462236088717712e-53, 4.9883667718148639e-50, 2.4133632044032138e-47, 8.4092583458821788e-45, 2.1769699583039015e-42, 4.2954616661119346e-40, 6.5994654800159303e-38, 8.0390389893761170e-36, 7.8853213936624651e-34, 6.3119668181308563e-32, 4.1716030615092882e-30, 2.2997378701939073e-28, 1.0671290531221681e-26, 4.2015271606281150e-25, 1.4137224274155160e-23, 4.0914965094167889e-22, 1.0244196283925887e-20, 2.2306211570300883e-19, 4.2441255956981095e-18, 7.0866359430444936e-17, 1.0425344386668410e-15, 1.3561256356020877e-14, 1.5649369927618164e-13, 1.6069042876497942e-12, 1.4722456305780643e-11, 1.2066201440627706e-10, 8.8669552925941743e-10, 5.8549609302492589e-09, 3.4807738736531026e-08, 1.8664547970988355e-07, 9.0421645542748592e-07, 3.9637332341743650e-06, 1.5744241598181718e-05, 5.6738856687547051e-05, 1.8573262875095809e-04, 5.5284802877925447e-04, 1.4977892627292288e-03, 3.6965702725171162e-03, 8.3173850369341346e-03, 1.7073105881727814e-02, 3.1991743583371472e-02, 5.4750665778331979e-02, 8.5616850779843184e-02, 1.2237883847025718e-01, 1.5993992755454783e-01, 1.9116358027866243e-01, 2.0898430851629271e-01, 2.0898430851629271e-01, 1.9116358027866243e-01, 1.5993992755454783e-01, 1.2237883847025718e-01, 8.5616850779843184e-02, 5.4750665778331979e-02, 3.1991743583371472e-02, 1.7073105881727814e-02, 8.3173850369341346e-03, 3.6965702725171162e-03, 1.4977892627292288e-03, 5.5284802877925447e-04, 1.8573262875095809e-04, 5.6738856687547051e-05, 1.5744241598181718e-05, 3.9637332341743650e-06, 9.0421645542748592e-07, 1.8664547970988355e-07, 3.4807738736531026e-08, 5.8549609302492589e-09, 8.8669552925941743e-10, 1.2066201440627706e-10, 1.4722456305780643e-11, 1.6069042876497942e-12, 1.5649369927618164e-13, 1.3561256356020877e-14, 1.0425344386668410e-15, 7.0866359430444936e-17, 4.2441255956981095e-18, 2.2306211570300883e-19, 1.0244196283925887e-20, 4.0914965094167889e-22, 1.4137224274155160e-23, 4.2015271606281150e-25, 1.0671290531221681e-26, 2.2997378701939073e-28, 4.1716030615092882e-30, 6.3119668181308563e-32, 7.8853213936624651e-34, 8.0390389893761170e-36, 6.5994654800159303e-38, 4.2954616661119346e-40, 2.1769699583039015e-42, 8.4092583458821788e-45, 2.4133632044032138e-47, 4.9883667718148639e-50, 7.1462236088717712e-53, 6.7588233504303362e-56, 3.9619475088358356e-59, 1.3221294591344122e-62, 2.2283154783345243e-66, 1.5851638341206613e-70, 3.5443349838315051e-75, 1.4208271558885895e-80, 2.4448842535551943e-87}, + {3.5392388249213494e-88, 2.1696906628474067e-81, 5.6618251917679648e-76, 2.6377634936769698e-71, 3.8524845909450548e-67, 2.3705848077171715e-63, 7.3575399530382127e-60, 1.2986758900322505e-56, 1.4196212763395569e-53, 1.0238881258836751e-50, 5.1156622686963731e-48, 1.8401448448645002e-45, 4.9161713392811270e-43, 1.0008264983378071e-40, 1.5861732912787765e-38, 1.9928674928468924e-36, 2.0159688321556722e-34, 1.6641520867485548e-32, 1.1341833636634616e-30, 6.4478013617261386e-29, 3.0854328584335985e-27, 1.2528407416044293e-25, 4.3478662125855451e-24, 1.2979585113660281e-22, 3.3525506308968111e-21, 7.5318707919556725e-20, 1.4788148820660904e-18, 2.5485379935372649e-17, 3.8703599993584500e-16, 5.1983189715882119e-15, 6.1952864130014014e-14, 6.5714753453597697e-13, 6.2212201579575959e-12, 5.2699881035078001e-11, 4.0039253602146504e-10, 2.7342851107604089e-09, 1.6816952694545013e-08, 9.3323608375261539e-08, 4.6806643299789927e-07, 2.1250386338304275e-06, 8.7455216612331247e-06, 3.2668449881324752e-05, 1.1089473739894331e-04, 3.4245439902397305e-04, 9.6300903314221480e-04, 2.4681920354686017e-03, 5.7702467735466509e-03, 1.2313597617381173e-02, 2.4000639085914963e-02, 4.2750896794915914e-02, 6.9623487033404263e-02, 1.0371107766286002e-01, 1.4134876449586573e-01, 1.7630458117164949e-01, 2.0128719075538343e-01, 2.1037554689061755e-01, 2.0128719075538343e-01, 1.7630458117164949e-01, 1.4134876449586573e-01, 1.0371107766286002e-01, 6.9623487033404263e-02, 4.2750896794915914e-02, 2.4000639085914963e-02, 1.2313597617381173e-02, 5.7702467735466509e-03, 2.4681920354686017e-03, 9.6300903314221480e-04, 3.4245439902397305e-04, 1.1089473739894331e-04, 3.2668449881324752e-05, 8.7455216612331247e-06, 2.1250386338304275e-06, 4.6806643299789927e-07, 9.3323608375261539e-08, 1.6816952694545013e-08, 2.7342851107604089e-09, 4.0039253602146504e-10, 5.2699881035078001e-11, 6.2212201579575959e-12, 6.5714753453597697e-13, 6.1952864130014014e-14, 5.1983189715882119e-15, 3.8703599993584500e-16, 2.5485379935372649e-17, 1.4788148820660904e-18, 7.5318707919556725e-20, 3.3525506308968111e-21, 1.2979585113660281e-22, 4.3478662125855451e-24, 1.2528407416044293e-25, 3.0854328584335985e-27, 6.4478013617261386e-29, 1.1341833636634616e-30, 1.6641520867485548e-32, 2.0159688321556722e-34, 1.9928674928468924e-36, 1.5861732912787765e-38, 1.0008264983378071e-40, 4.9161713392811270e-43, 1.8401448448645002e-45, 5.1156622686963731e-48, 1.0238881258836751e-50, 1.4196212763395569e-53, 1.2986758900322505e-56, 7.3575399530382127e-60, 2.3705848077171715e-63, 3.8524845909450548e-67, 2.6377634936769698e-71, 5.6618251917679648e-76, 2.1696906628474067e-81, 3.5392388249213494e-88}, + {5.1213633747657793e-89, 3.3107952448155878e-82, 9.0350209598558634e-77, 4.3835962164609016e-72, 6.6500528211701889e-68, 4.2427446781122925e-64, 1.3635093884813276e-60, 2.4895722182831332e-57, 2.8129093907478575e-54, 2.0956899110692340e-51, 1.0810706995222149e-48, 4.0133902027335798e-46, 1.1062614025677837e-43, 2.3230252252301317e-41, 3.7968846438904689e-39, 4.9189778171570439e-37, 5.1304565438169636e-35, 4.3662939232282773e-33, 3.0678714585911782e-31, 1.7980362370024124e-29, 8.8704657684441925e-28, 3.7135654602235681e-26, 1.3288244259482261e-24, 4.0906197763453875e-23, 1.0896574554298035e-21, 2.5250019651414982e-20, 5.1142598161040868e-19, 9.0937679770517361e-18, 1.4251779817419312e-16, 1.9757601287853092e-15, 2.4309836206138916e-14, 2.6627832873106297e-13, 2.6038192973897978e-12, 2.2788951363311533e-11, 1.7893870863289438e-10, 1.2632724994941663e-09, 8.0347791732044002e-09, 4.6125099246668157e-08, 2.3940078640211405e-07, 1.1251692413517793e-06, 4.7955457442441056e-06, 1.8559162409889888e-05, 6.5298413383660050e-05, 2.0909754829024987e-04, 6.1000345990479894e-04, 1.6227318637929411e-03, 3.9395573314086755e-03, 8.7347828708895063e-03, 1.7698763026162554e-02, 3.2791967492410569e-02, 5.5582763848207158e-02, 8.6226926941764842e-02, 1.2246902437683259e-01, 1.5929780439003277e-01, 1.8979412167575810e-01, 2.0715930730796278e-01, 2.0715930730796278e-01, 1.8979412167575810e-01, 1.5929780439003277e-01, 1.2246902437683259e-01, 8.6226926941764842e-02, 5.5582763848207158e-02, 3.2791967492410569e-02, 1.7698763026162554e-02, 8.7347828708895063e-03, 3.9395573314086755e-03, 1.6227318637929411e-03, 6.1000345990479894e-04, 2.0909754829024987e-04, 6.5298413383660050e-05, 1.8559162409889888e-05, 4.7955457442441056e-06, 1.1251692413517793e-06, 2.3940078640211405e-07, 4.6125099246668157e-08, 8.0347791732044002e-09, 1.2632724994941663e-09, 1.7893870863289438e-10, 2.2788951363311533e-11, 2.6038192973897978e-12, 2.6627832873106297e-13, 2.4309836206138916e-14, 1.9757601287853092e-15, 1.4251779817419312e-16, 9.0937679770517361e-18, 5.1142598161040868e-19, 2.5250019651414982e-20, 1.0896574554298035e-21, 4.0906197763453875e-23, 1.3288244259482261e-24, 3.7135654602235681e-26, 8.8704657684441925e-28, 1.7980362370024124e-29, 3.0678714585911782e-31, 4.3662939232282773e-33, 5.1304565438169636e-35, 4.9189778171570439e-37, 3.7968846438904689e-39, 2.3230252252301317e-41, 1.1062614025677837e-43, 4.0133902027335798e-46, 1.0810706995222149e-48, 2.0956899110692340e-51, 2.8129093907478575e-54, 2.4895722182831332e-57, 1.3635093884813276e-60, 4.2427446781122925e-64, 6.6500528211701889e-68, 4.3835962164609016e-72, 9.0350209598558634e-77, 3.3107952448155878e-82, 5.1213633747657793e-89}, + {7.4077801156809802e-90, 5.0483520825696067e-83, 1.4403225795247276e-77, 7.2755698062212851e-73, 1.1461458182067259e-68, 7.5798509757209669e-65, 2.5217356180713449e-61, 4.7616681817655899e-58, 5.5596107723280791e-55, 4.2776169290546349e-52, 2.2777250019423805e-49, 8.7248851122544073e-47, 2.4806792113142151e-44, 5.3718421575826214e-42, 9.0525141699026487e-40, 1.2089985963915576e-37, 1.2997822407575913e-35, 1.1401487006660065e-33, 8.2566517430946983e-32, 4.9874725361855554e-30, 2.5360177279806859e-28, 1.0943086662261828e-26, 4.0363441926925487e-25, 1.2809131432068308e-23, 3.5178503719335083e-22, 8.4054498872392565e-21, 1.7557265568072654e-19, 3.2200557928719378e-18, 5.2060944517170957e-17, 7.4470753817100703e-16, 9.4565868275202180e-15, 1.0692722214257240e-13, 1.0796165415752499e-12, 9.7589319582302090e-12, 7.9162851028857836e-11, 5.7753749442476326e-10, 3.7971425911450754e-09, 2.2540365079384215e-08, 1.2101463098116854e-07, 5.8853747125042215e-07, 2.5965756360441134e-06, 1.0406346919868978e-05, 3.7931294208686378e-05, 1.2588825538260341e-04, 3.8080638386839771e-04, 1.0508900454889139e-03, 2.6479410521627993e-03, 6.0965525061442453e-03, 1.2834439196438882e-02, 2.4719722908456396e-02, 4.3582193779905874e-02, 7.0366531191907819e-02, 1.0408220923468044e-01, 1.4108198634981012e-01, 1.7528831212387214e-01, 1.9966087345702854e-01, 2.0851381638716077e-01, 1.9966087345702854e-01, 1.7528831212387214e-01, 1.4108198634981012e-01, 1.0408220923468044e-01, 7.0366531191907819e-02, 4.3582193779905874e-02, 2.4719722908456396e-02, 1.2834439196438882e-02, 6.0965525061442453e-03, 2.6479410521627993e-03, 1.0508900454889139e-03, 3.8080638386839771e-04, 1.2588825538260341e-04, 3.7931294208686378e-05, 1.0406346919868978e-05, 2.5965756360441134e-06, 5.8853747125042215e-07, 1.2101463098116854e-07, 2.2540365079384215e-08, 3.7971425911450754e-09, 5.7753749442476326e-10, 7.9162851028857836e-11, 9.7589319582302090e-12, 1.0796165415752499e-12, 1.0692722214257240e-13, 9.4565868275202180e-15, 7.4470753817100703e-16, 5.2060944517170957e-17, 3.2200557928719378e-18, 1.7557265568072654e-19, 8.4054498872392565e-21, 3.5178503719335083e-22, 1.2809131432068308e-23, 4.0363441926925487e-25, 1.0943086662261828e-26, 2.5360177279806859e-28, 4.9874725361855554e-30, 8.2566517430946983e-32, 1.1401487006660065e-33, 1.2997822407575913e-35, 1.2089985963915576e-37, 9.0525141699026487e-40, 5.3718421575826214e-42, 2.4806792113142151e-44, 8.7248851122544073e-47, 2.2777250019423805e-49, 4.2776169290546349e-52, 5.5596107723280791e-55, 4.7616681817655899e-58, 2.5217356180713449e-61, 7.5798509757209669e-65, 1.1461458182067259e-68, 7.2755698062212851e-73, 1.4403225795247276e-77, 5.0483520825696067e-83, 7.4077801156809802e-90}, + {1.0710750710094196e-90, 7.6922700260785516e-84, 2.2937970374962485e-78, 1.2060181138762046e-73, 1.9724028846801179e-69, 1.3517892214658933e-65, 4.6544766331713673e-62, 9.0869836287455904e-59, 1.0961147706353286e-55, 8.7075616610856478e-53, 4.7848109229537450e-50, 1.8906897473607166e-47, 5.5435860303288234e-45, 1.2376390647546546e-42, 2.1498363403641766e-40, 2.9591207501866347e-38, 3.2783946198859832e-36, 2.9632924702764426e-34, 2.2111690104503776e-32, 1.3762537782433349e-30, 7.2106896606964717e-29, 3.2061793655442875e-27, 1.2186704300488311e-25, 3.9856906328389221e-24, 1.1282136742777468e-22, 2.7788009433178836e-21, 5.9840605797879746e-20, 1.1316516319423812e-18, 1.8868897366381483e-17, 2.7841156852775031e-16, 3.6474708837523359e-15, 4.2559572408720686e-14, 4.4353966285433845e-13, 4.1393133324428903e-12, 3.4675788374516700e-11, 2.6132836673568577e-10, 1.7753911292124313e-09, 1.0893439091005499e-08, 6.0471668709771245e-08, 3.0419237917584698e-07, 1.3886494911822552e-06, 5.7606576662754425e-06, 2.1743312833175104e-05, 7.4756242475529144e-05, 2.3436272202084139e-04, 6.7059411024834642e-04, 1.7528045021959946e-03, 4.1883749721869905e-03, 9.1558081843385875e-03, 1.8321199420242032e-02, 3.3577761609077682e-02, 5.6388855176296548e-02, 8.6806251150572486e-02, 1.2253708910746171e-01, 1.5865594890874077e-01, 1.8845256425575369e-01, 2.0538128483764440e-01, 2.0538128483764440e-01, 1.8845256425575369e-01, 1.5865594890874077e-01, 1.2253708910746171e-01, 8.6806251150572486e-02, 5.6388855176296548e-02, 3.3577761609077682e-02, 1.8321199420242032e-02, 9.1558081843385875e-03, 4.1883749721869905e-03, 1.7528045021959946e-03, 6.7059411024834642e-04, 2.3436272202084139e-04, 7.4756242475529144e-05, 2.1743312833175104e-05, 5.7606576662754425e-06, 1.3886494911822552e-06, 3.0419237917584698e-07, 6.0471668709771245e-08, 1.0893439091005499e-08, 1.7753911292124313e-09, 2.6132836673568577e-10, 3.4675788374516700e-11, 4.1393133324428903e-12, 4.4353966285433845e-13, 4.2559572408720686e-14, 3.6474708837523359e-15, 2.7841156852775031e-16, 1.8868897366381483e-17, 1.1316516319423812e-18, 5.9840605797879746e-20, 2.7788009433178836e-21, 1.1282136742777468e-22, 3.9856906328389221e-24, 1.2186704300488311e-25, 3.2061793655442875e-27, 7.2106896606964717e-29, 1.3762537782433349e-30, 2.2111690104503776e-32, 2.9632924702764426e-34, 3.2783946198859832e-36, 2.9591207501866347e-38, 2.1498363403641766e-40, 1.2376390647546546e-42, 5.5435860303288234e-45, 1.8906897473607166e-47, 4.7848109229537450e-50, 8.7075616610856478e-53, 1.0961147706353286e-55, 9.0869836287455904e-59, 4.6544766331713673e-62, 1.3517892214658933e-65, 1.9724028846801179e-69, 1.2060181138762046e-73, 2.2937970374962485e-78, 7.6922700260785516e-84, 1.0710750710094196e-90}, + {1.5480449561254974e-91, 1.1712554562855694e-84, 3.6493992259071536e-79, 1.9966381452254604e-74, 3.3892412733092808e-70, 2.4065988574277261e-66, 8.5740429722944209e-63, 1.7303021840396506e-59, 2.1557967924444521e-56, 1.7677871947095523e-53, 1.0022253044363931e-50, 4.0842818848410062e-48, 1.2346472555075369e-45, 2.8411408701159342e-43, 5.0858613958959180e-41, 7.2130038186701857e-39, 8.2330481300630906e-37, 7.6663204905842568e-35, 5.8928891499709780e-33, 3.7782612371775474e-31, 2.0392097722330042e-29, 9.3406997569354054e-28, 3.6577061009128777e-26, 1.2325099622415151e-24, 3.5948795028461328e-23, 9.1244425221919135e-22, 2.0251548550899527e-20, 3.9477817506225531e-19, 6.7863601469508643e-18, 1.0325389659471167e-16, 1.3951643164647175e-15, 1.6793350772844097e-14, 1.8058345392733700e-13, 1.7393402348430495e-12, 1.5041987406688428e-11, 1.1705945482958366e-10, 8.2144797343634809e-10, 5.2077334277669068e-09, 2.9879393170121428e-08, 1.5539942997674910e-07, 7.3371456445731177e-07, 3.1491925110163785e-06, 1.2303027527173753e-05, 4.3799266325778880e-05, 1.4224028492262314e-04, 4.2179171252798944e-04, 1.1430722829481254e-03, 2.8333080652480614e-03, 6.4278810024544141e-03, 1.3355861419689084e-02, 2.5430213894352387e-02, 4.4393059115154253e-02, 7.1080397415348953e-02, 1.0442577716745464e-01, 1.4080345768904715e-01, 1.7428622967828752e-01, 1.9807313269914872e-01, 2.0670065276640287e-01, 1.9807313269914872e-01, 1.7428622967828752e-01, 1.4080345768904715e-01, 1.0442577716745464e-01, 7.1080397415348953e-02, 4.4393059115154253e-02, 2.5430213894352387e-02, 1.3355861419689084e-02, 6.4278810024544141e-03, 2.8333080652480614e-03, 1.1430722829481254e-03, 4.2179171252798944e-04, 1.4224028492262314e-04, 4.3799266325778880e-05, 1.2303027527173753e-05, 3.1491925110163785e-06, 7.3371456445731177e-07, 1.5539942997674910e-07, 2.9879393170121428e-08, 5.2077334277669068e-09, 8.2144797343634809e-10, 1.1705945482958366e-10, 1.5041987406688428e-11, 1.7393402348430495e-12, 1.8058345392733700e-13, 1.6793350772844097e-14, 1.3951643164647175e-15, 1.0325389659471167e-16, 6.7863601469508643e-18, 3.9477817506225531e-19, 2.0251548550899527e-20, 9.1244425221919135e-22, 3.5948795028461328e-23, 1.2325099622415151e-24, 3.6577061009128777e-26, 9.3406997569354054e-28, 2.0392097722330042e-29, 3.7782612371775474e-31, 5.8928891499709780e-33, 7.6663204905842568e-35, 8.2330481300630906e-37, 7.2130038186701857e-39, 5.0858613958959180e-41, 2.8411408701159342e-43, 1.2346472555075369e-45, 4.0842818848410062e-48, 1.0022253044363931e-50, 1.7677871947095523e-53, 2.1557967924444521e-56, 1.7303021840396506e-59, 8.5740429722944209e-63, 2.4065988574277261e-66, 3.3892412733092808e-70, 1.9966381452254604e-74, 3.6493992259071536e-79, 1.1712554562855694e-84, 1.5480449561254974e-91}, + {2.2365648981246453e-92, 1.7821550800540237e-85, 5.8004986924644819e-80, 3.3015035960765624e-75, 5.8152759548633637e-71, 4.2771691981814217e-67, 1.5763666548556604e-63, 3.2876134769273718e-60, 4.2297673811987948e-57, 3.5794857851611975e-54, 2.0932606053442080e-51, 8.7956536234027020e-49, 2.7406328866050857e-46, 6.4989825715662458e-44, 1.1986003025152256e-41, 1.7511205172582050e-39, 2.0587364582129049e-37, 1.9743896190133811e-35, 1.5630006293499951e-33, 1.0320466636328443e-31, 5.7365178511704523e-30, 2.7061869712127610e-28, 1.0914439534101697e-26, 3.7881611827990218e-25, 1.1381700734483244e-23, 2.9761942889320718e-22, 6.8061278108013458e-21, 1.3672374402361970e-19, 2.4223988311307281e-18, 3.7993465086131341e-17, 5.2930247423722938e-16, 6.5702357143564891e-15, 7.2875563565483730e-14, 7.2418684802603713e-13, 6.4631097928536238e-12, 5.1919141781420298e-11, 3.7618946881237821e-10, 2.4632483182140787e-09, 1.4601515540917063e-08, 7.8484291703314789e-08, 3.8310233242483633e-07, 1.7005728326428347e-06, 6.8734922472265778e-06, 2.5326195751014174e-05, 8.5160665584721077e-05, 2.6158391341408045e-04, 7.3463960542667715e-04, 1.8879100806443562e-03, 4.4427288798279318e-03, 9.5799818951133077e-03, 1.8939956587000626e-02, 3.4349073289602634e-02, 5.7169633542064863e-02, 8.7356205785880797e-02, 1.2258446739609345e-01, 1.5801491756025524e-01, 1.8713802680418945e-01, 2.0364826010006534e-01, 2.0364826010006534e-01, 1.8713802680418945e-01, 1.5801491756025524e-01, 1.2258446739609345e-01, 8.7356205785880797e-02, 5.7169633542064863e-02, 3.4349073289602634e-02, 1.8939956587000626e-02, 9.5799818951133077e-03, 4.4427288798279318e-03, 1.8879100806443562e-03, 7.3463960542667715e-04, 2.6158391341408045e-04, 8.5160665584721077e-05, 2.5326195751014174e-05, 6.8734922472265778e-06, 1.7005728326428347e-06, 3.8310233242483633e-07, 7.8484291703314789e-08, 1.4601515540917063e-08, 2.4632483182140787e-09, 3.7618946881237821e-10, 5.1919141781420298e-11, 6.4631097928536238e-12, 7.2418684802603713e-13, 7.2875563565483730e-14, 6.5702357143564891e-15, 5.2930247423722938e-16, 3.7993465086131341e-17, 2.4223988311307281e-18, 1.3672374402361970e-19, 6.8061278108013458e-21, 2.9761942889320718e-22, 1.1381700734483244e-23, 3.7881611827990218e-25, 1.0914439534101697e-26, 2.7061869712127610e-28, 5.7365178511704523e-30, 1.0320466636328443e-31, 1.5630006293499951e-33, 1.9743896190133811e-35, 2.0587364582129049e-37, 1.7511205172582050e-39, 1.1986003025152256e-41, 6.4989825715662458e-44, 2.7406328866050857e-46, 8.7956536234027020e-49, 2.0932606053442080e-51, 3.5794857851611975e-54, 4.2297673811987948e-57, 3.2876134769273718e-60, 1.5763666548556604e-63, 4.2771691981814217e-67, 5.8152759548633637e-71, 3.3015035960765624e-75, 5.8004986924644819e-80, 1.7821550800540237e-85, 2.2365648981246453e-92}, + {3.2301009543101099e-93, 2.7098206745663592e-86, 9.2107100141581600e-81, 5.4525421540759655e-76, 9.9634282798974572e-72, 7.5888934406190700e-68, 2.8926678180441972e-64, 6.2331956354059190e-61, 8.2793896913033925e-58, 7.2291385544928827e-55, 4.3597174343439006e-52, 1.8884218782951360e-49, 6.0637045694189279e-47, 1.4814159278355307e-44, 2.8142461042205111e-42, 4.2343947760097721e-40, 5.1264009327908215e-38, 5.0622696862483853e-36, 4.1261954854591773e-34, 2.8051622162519962e-32, 1.6053724151348174e-30, 7.7976718238941548e-29, 3.2382364130273421e-27, 1.1573493767550765e-25, 3.5810407352214098e-24, 9.6443805701337253e-23, 2.2718330011553644e-21, 4.7015694865721316e-20, 8.5828869554158906e-19, 1.3872615165495405e-17, 1.9920232649990639e-16, 2.5491665563098012e-15, 2.9155331883629833e-14, 2.9881593623355600e-13, 2.7511620846328702e-12, 2.2805223736764051e-11, 1.7055424914056455e-10, 1.1530186653890739e-09, 7.0587498965529012e-09, 3.9196764143747362e-08, 1.9772532357280954e-07, 9.0734367403526114e-07, 3.7926166158590859e-06, 1.4457032475544561e-05, 5.0311336988073622e-05, 1.6000468687262702e-04, 4.6545282707817341e-04, 1.2395239105761761e-03, 3.0241014828653783e-03, 6.7638384706753211e-03, 1.3877372041544333e-02, 2.6131824932046500e-02, 4.5183798113816530e-02, 7.1766149805041285e-02, 1.0474325576824089e-01, 1.4051423956652490e-01, 1.7329818332155345e-01, 1.9652247660560301e-01, 2.0493398052053613e-01, 1.9652247660560301e-01, 1.7329818332155345e-01, 1.4051423956652490e-01, 1.0474325576824089e-01, 7.1766149805041285e-02, 4.5183798113816530e-02, 2.6131824932046500e-02, 1.3877372041544333e-02, 6.7638384706753211e-03, 3.0241014828653783e-03, 1.2395239105761761e-03, 4.6545282707817341e-04, 1.6000468687262702e-04, 5.0311336988073622e-05, 1.4457032475544561e-05, 3.7926166158590859e-06, 9.0734367403526114e-07, 1.9772532357280954e-07, 3.9196764143747362e-08, 7.0587498965529012e-09, 1.1530186653890739e-09, 1.7055424914056455e-10, 2.2805223736764051e-11, 2.7511620846328702e-12, 2.9881593623355600e-13, 2.9155331883629833e-14, 2.5491665563098012e-15, 1.9920232649990639e-16, 1.3872615165495405e-17, 8.5828869554158906e-19, 4.7015694865721316e-20, 2.2718330011553644e-21, 9.6443805701337253e-23, 3.5810407352214098e-24, 1.1573493767550765e-25, 3.2382364130273421e-27, 7.7976718238941548e-29, 1.6053724151348174e-30, 2.8051622162519962e-32, 4.1261954854591773e-34, 5.0622696862483853e-36, 5.1264009327908215e-38, 4.2343947760097721e-40, 2.8142461042205111e-42, 1.4814159278355307e-44, 6.0637045694189279e-47, 1.8884218782951360e-49, 4.3597174343439006e-52, 7.2291385544928827e-55, 8.2793896913033925e-58, 6.2331956354059190e-61, 2.8926678180441972e-64, 7.5888934406190700e-68, 9.9634282798974572e-72, 5.4525421540759655e-76, 9.2107100141581600e-81, 2.7098206745663592e-86, 3.2301009543101099e-93}, + {4.6632605618348153e-94, 4.1175713624143213e-87, 1.4612038470881841e-81, 8.9943320432041730e-77, 1.7046189545614933e-72, 1.3442523656293476e-68, 5.2981258920312120e-65, 1.1793052736766146e-61, 1.6168482075284075e-58, 1.4562812961539782e-55, 9.0550269871980438e-53, 4.0423080380262144e-50, 1.3372947653240557e-47, 3.3652104040755819e-45, 6.5834566491742290e-43, 1.0199300069374435e-40, 1.2712364015219454e-38, 1.2922794919134986e-36, 1.0842626381128112e-34, 7.5875981466261195e-33, 4.4697458344428785e-31, 2.2348156961076159e-29, 9.5537375722030760e-28, 3.5151519348961093e-26, 1.1197954114046576e-24, 3.1052469143218520e-23, 7.5325222776132763e-22, 1.6054837533511592e-20, 3.0189715471734914e-19, 5.0270892648593941e-18, 7.4380949511123831e-17, 9.8097342377809155e-16, 1.1565317290963977e-14, 1.2221338000525176e-13, 1.1603996128858022e-12, 9.9222265232533288e-12, 7.6565621148965857e-11, 5.3422379271962827e-10, 3.3764133497574799e-09, 1.9362011885244885e-08, 1.0089574633621321e-07, 4.7845042712908339e-07, 2.0673284334051564e-06, 8.1491561908568428e-06, 2.9337744635072858e-05, 9.6558931405380603e-05, 2.9081250785794189e-04, 8.0215126322350460e-04, 2.0279429361286859e-03, 4.7023255147965815e-03, 1.0006845717689308e-02, 1.9554616052364186e-02, 3.5105886050128668e-02, 5.7925787803644498e-02, 8.7878107549790321e-02, 1.2261249660444425e-01, 1.5737520760258733e-01, 1.8584966291329158e-01, 2.0195836706954076e-01, 2.0195836706954076e-01, 1.8584966291329158e-01, 1.5737520760258733e-01, 1.2261249660444425e-01, 8.7878107549790321e-02, 5.7925787803644498e-02, 3.5105886050128668e-02, 1.9554616052364186e-02, 1.0006845717689308e-02, 4.7023255147965815e-03, 2.0279429361286859e-03, 8.0215126322350460e-04, 2.9081250785794189e-04, 9.6558931405380603e-05, 2.9337744635072858e-05, 8.1491561908568428e-06, 2.0673284334051564e-06, 4.7845042712908339e-07, 1.0089574633621321e-07, 1.9362011885244885e-08, 3.3764133497574799e-09, 5.3422379271962827e-10, 7.6565621148965857e-11, 9.9222265232533288e-12, 1.1603996128858022e-12, 1.2221338000525176e-13, 1.1565317290963977e-14, 9.8097342377809155e-16, 7.4380949511123831e-17, 5.0270892648593941e-18, 3.0189715471734914e-19, 1.6054837533511592e-20, 7.5325222776132763e-22, 3.1052469143218520e-23, 1.1197954114046576e-24, 3.5151519348961093e-26, 9.5537375722030760e-28, 2.2348156961076159e-29, 4.4697458344428785e-31, 7.5875981466261195e-33, 1.0842626381128112e-34, 1.2922794919134986e-36, 1.2712364015219454e-38, 1.0199300069374435e-40, 6.5834566491742290e-43, 3.3652104040755819e-45, 1.3372947653240557e-47, 4.0423080380262144e-50, 9.0550269871980438e-53, 1.4562812961539782e-55, 1.6168482075284075e-58, 1.1793052736766146e-61, 5.2981258920312120e-65, 1.3442523656293476e-68, 1.7046189545614933e-72, 8.9943320432041730e-77, 1.4612038470881841e-81, 4.1175713624143213e-87, 4.6632605618348153e-94}, + {6.7298368161176175e-95, 6.2524679295400819e-88, 2.3159244482213129e-82, 1.4819345628019795e-77, 2.9122929849292479e-73, 2.3772467547464570e-69, 9.6859162631794203e-66, 2.2265944526096699e-62, 3.1502482452041196e-59, 2.9262669926463904e-56, 1.8755830649756743e-53, 8.6273958082206037e-51, 2.9399528685004811e-48, 7.6185958106575033e-46, 1.5345315352659727e-43, 2.4472631035773749e-41, 3.1395792592468297e-39, 3.2847155364958309e-37, 2.8362637361915701e-35, 2.0425551530268673e-33, 1.2382461823632275e-31, 6.3712964630586884e-30, 2.8030942195831802e-28, 1.0614795301061955e-26, 3.4805041051243282e-25, 9.9351833121692472e-24, 2.4810981347002888e-22, 5.4448704650642035e-21, 1.0543376862850843e-19, 1.8081886383358570e-18, 2.7559344338025971e-17, 3.7447612695692442e-16, 4.5495653050067822e-15, 4.9552804559564594e-14, 4.8505588604403995e-13, 4.2769240959330674e-12, 3.4041116737305440e-11, 2.4505079134311513e-10, 1.5983528945271918e-09, 9.4619152361816427e-09, 5.0915075227638090e-08, 2.4939923966935258e-07, 1.1135208095853982e-06, 4.5371664146194656e-06, 1.6890448115948282e-05, 5.7506280394736890e-05, 1.7923272339346707e-04, 5.1182575908404512e-04, 1.3402041554580024e-03, 3.2201249358166924e-03, 7.1040413328426078e-03, 1.4398510037728523e-02, 2.6824309528990144e-02, 4.5954734368354178e-02, 7.2424817070363218e-02, 1.0503603365193327e-01, 1.4021530912606431e-01, 1.7232400830089628e-01, 1.9500749227238295e-01, 2.0321184623044758e-01, 1.9500749227238295e-01, 1.7232400830089628e-01, 1.4021530912606431e-01, 1.0503603365193327e-01, 7.2424817070363218e-02, 4.5954734368354178e-02, 2.6824309528990144e-02, 1.4398510037728523e-02, 7.1040413328426078e-03, 3.2201249358166924e-03, 1.3402041554580024e-03, 5.1182575908404512e-04, 1.7923272339346707e-04, 5.7506280394736890e-05, 1.6890448115948282e-05, 4.5371664146194656e-06, 1.1135208095853982e-06, 2.4939923966935258e-07, 5.0915075227638090e-08, 9.4619152361816427e-09, 1.5983528945271918e-09, 2.4505079134311513e-10, 3.4041116737305440e-11, 4.2769240959330674e-12, 4.8505588604403995e-13, 4.9552804559564594e-14, 4.5495653050067822e-15, 3.7447612695692442e-16, 2.7559344338025971e-17, 1.8081886383358570e-18, 1.0543376862850843e-19, 5.4448704650642035e-21, 2.4810981347002888e-22, 9.9351833121692472e-24, 3.4805041051243282e-25, 1.0614795301061955e-26, 2.8030942195831802e-28, 6.3712964630586884e-30, 1.2382461823632275e-31, 2.0425551530268673e-33, 2.8362637361915701e-35, 3.2847155364958309e-37, 3.1395792592468297e-39, 2.4472631035773749e-41, 1.5345315352659727e-43, 7.6185958106575033e-46, 2.9399528685004811e-48, 8.6273958082206037e-51, 1.8755830649756743e-53, 2.9262669926463904e-56, 3.1502482452041196e-59, 2.2265944526096699e-62, 9.6859162631794203e-66, 2.3772467547464570e-69, 2.9122929849292479e-73, 1.4819345628019795e-77, 2.3159244482213129e-82, 6.2524679295400819e-88, 6.7298368161176175e-95}, + {9.7087403173561320e-96, 9.4880223969421335e-89, 3.6672428899258345e-83, 2.4388595277598848e-78, 4.9686800178709975e-74, 4.1972934212808472e-70, 1.7675264508544507e-66, 4.1953576796012743e-63, 6.1240687137526128e-60, 5.8655575443381544e-57, 3.8745058915294428e-54, 1.8359883902918249e-51, 6.4431660432386704e-49, 1.7190498209667764e-46, 3.5641227393846403e-44, 5.8499085615955162e-42, 7.7228330960795927e-40, 8.3138040908205878e-38, 7.3861592386371398e-36, 5.4726905931533611e-34, 3.4133817510443908e-32, 1.8070157219004075e-30, 8.1797979499699255e-29, 3.1872062136052619e-27, 1.0753877987999934e-25, 3.1590858369572161e-24, 8.1196497360506958e-23, 1.8341746417696775e-21, 3.6563781425498920e-20, 6.4565140315879466e-19, 1.0133911369582986e-17, 1.4182835695860085e-16, 1.7750978597330652e-15, 1.9921528797000957e-14, 2.0097524571107850e-13, 1.8267486127018911e-12, 1.4991784686824891e-11, 1.1130625000696823e-10, 7.4897520452156729e-10, 4.5753933756254367e-09, 2.5414386492665182e-08, 1.2854272339650551e-07, 5.9280419576037410e-07, 2.4957777427586521e-06, 9.6033945516455336e-06, 3.3808196410240332e-05, 1.0899702609675318e-04, 3.2209543490435076e-04, 8.7313245576434379e-04, 2.1727898312954579e-03, 4.9668732525919509e-03, 1.0435962135902662e-02, 2.0164796980741757e-02, 3.5848215647758121e-02, 5.8657999750043426e-02, 8.8373210437321048e-02, 1.2262242405763166e-01, 1.5673726302678062e-01, 1.8458665957131964e-01, 2.0030984626187961e-01, 2.0030984626187961e-01, 1.8458665957131964e-01, 1.5673726302678062e-01, 1.2262242405763166e-01, 8.8373210437321048e-02, 5.8657999750043426e-02, 3.5848215647758121e-02, 2.0164796980741757e-02, 1.0435962135902662e-02, 4.9668732525919509e-03, 2.1727898312954579e-03, 8.7313245576434379e-04, 3.2209543490435076e-04, 1.0899702609675318e-04, 3.3808196410240332e-05, 9.6033945516455336e-06, 2.4957777427586521e-06, 5.9280419576037410e-07, 1.2854272339650551e-07, 2.5414386492665182e-08, 4.5753933756254367e-09, 7.4897520452156729e-10, 1.1130625000696823e-10, 1.4991784686824891e-11, 1.8267486127018911e-12, 2.0097524571107850e-13, 1.9921528797000957e-14, 1.7750978597330652e-15, 1.4182835695860085e-16, 1.0133911369582986e-17, 6.4565140315879466e-19, 3.6563781425498920e-20, 1.8341746417696775e-21, 8.1196497360506958e-23, 3.1590858369572161e-24, 1.0753877987999934e-25, 3.1872062136052619e-27, 8.1797979499699255e-29, 1.8070157219004075e-30, 3.4133817510443908e-32, 5.4726905931533611e-34, 7.3861592386371398e-36, 8.3138040908205878e-38, 7.7228330960795927e-40, 5.8499085615955162e-42, 3.5641227393846403e-44, 1.7190498209667764e-46, 6.4431660432386704e-49, 1.8359883902918249e-51, 3.8745058915294428e-54, 5.8655575443381544e-57, 6.1240687137526128e-60, 4.1953576796012743e-63, 1.7675264508544507e-66, 4.1972934212808472e-70, 4.9686800178709975e-74, 2.4388595277598848e-78, 3.6672428899258345e-83, 9.4880223969421335e-89, 9.7087403173561320e-96}, + {1.4001253071178789e-96, 1.4388577548096490e-89, 5.8017947700800046e-84, 4.0091236159545663e-79, 8.4655265882771739e-75, 7.3990554223004025e-71, 3.2196574821489126e-67, 7.8890210982671253e-64, 1.1878725902550843e-60, 1.1728639625604033e-57, 7.9826611475407281e-55, 3.8960048884898755e-52, 1.4077485752140258e-49, 3.8661220025482209e-47, 8.2491446524855651e-45, 1.3931625443392332e-42, 1.8922123418053773e-40, 2.0955223902923607e-38, 1.9150597358365338e-36, 1.4595508732329443e-34, 9.3637976764322119e-33, 5.0989613303209105e-31, 2.3742569610821154e-29, 9.5165969692199733e-28, 3.3033284608828233e-26, 9.9838789745986388e-25, 2.6403982498871405e-23, 6.1378568842560367e-22, 1.2592940912286238e-20, 2.2889503956241953e-19, 3.6986721862085567e-18, 5.3301125275267336e-17, 6.8703687643915730e-16, 7.9423755813393362e-15, 8.2552749332412685e-14, 7.7326044861505372e-13, 6.5412509847214547e-12, 5.0072069799282932e-11, 3.4747667141215967e-10, 2.1897184637878725e-09, 1.2550651872012550e-08, 6.5522732997355584e-08, 3.1199715417437437e-07, 1.3566980827714974e-06, 5.3937313862223019e-06, 1.9625894008346668e-05, 6.5422509840297027e-05, 1.9997290405207970e-04, 5.6094024606844449e-04, 1.4450639870005968e-03, 3.4211784137958604e-03, 7.4481168960531027e-03, 1.4918844448036933e-02, 2.7507458506267436e-02, 4.6706206412519734e-02, 7.3057392793912337e-02, 1.0530541916565815e-01, 1.3990756676688021e-01, 1.7136352815479530e-01, 1.9352684051681762e-01, 2.0153240948474130e-01, 1.9352684051681762e-01, 1.7136352815479530e-01, 1.3990756676688021e-01, 1.0530541916565815e-01, 7.3057392793912337e-02, 4.6706206412519734e-02, 2.7507458506267436e-02, 1.4918844448036933e-02, 7.4481168960531027e-03, 3.4211784137958604e-03, 1.4450639870005968e-03, 5.6094024606844449e-04, 1.9997290405207970e-04, 6.5422509840297027e-05, 1.9625894008346668e-05, 5.3937313862223019e-06, 1.3566980827714974e-06, 3.1199715417437437e-07, 6.5522732997355584e-08, 1.2550651872012550e-08, 2.1897184637878725e-09, 3.4747667141215967e-10, 5.0072069799282932e-11, 6.5412509847214547e-12, 7.7326044861505372e-13, 8.2552749332412685e-14, 7.9423755813393362e-15, 6.8703687643915730e-16, 5.3301125275267336e-17, 3.6986721862085567e-18, 2.2889503956241953e-19, 1.2592940912286238e-20, 6.1378568842560367e-22, 2.6403982498871405e-23, 9.9838789745986388e-25, 3.3033284608828233e-26, 9.5165969692199733e-28, 2.3742569610821154e-29, 5.0989613303209105e-31, 9.3637976764322119e-33, 1.4595508732329443e-34, 1.9150597358365338e-36, 2.0955223902923607e-38, 1.8922123418053773e-40, 1.3931625443392332e-42, 8.2491446524855651e-45, 3.8661220025482209e-47, 1.4077485752140258e-49, 3.8960048884898755e-52, 7.9826611475407281e-55, 1.1728639625604033e-57, 1.1878725902550843e-60, 7.8890210982671253e-64, 3.2196574821489126e-67, 7.3990554223004025e-71, 8.4655265882771739e-75, 4.0091236159545663e-79, 5.8017947700800046e-84, 1.4388577548096490e-89, 1.4001253071178789e-96}, + {2.0184534275095049e-97, 2.1806296158265287e-90, 9.1706055028522197e-85, 6.5830036453656527e-80, 1.4403978976524620e-75, 1.3022823162971665e-71, 5.8544142858486073e-68, 1.4805274033207088e-64, 2.2990511219174665e-61, 2.3396177274687451e-58, 1.6403928051497794e-55, 8.2441788250067191e-53, 3.0664667336421114e-50, 8.6667923231989335e-48, 1.9026918231732264e-45, 3.3057067086043009e-43, 4.6182598989607685e-41, 5.2602254003426042e-39, 4.9438860107310490e-37, 3.8749094400485918e-35, 2.5564844139368277e-33, 1.4316070974387265e-31, 6.8553849798952103e-30, 2.8259664729965746e-28, 1.0088930738432750e-26, 3.1364243262134751e-25, 8.5327296120897214e-24, 2.0406372113926846e-22, 4.3078486936244584e-21, 8.0577481866273284e-20, 1.3400866628758495e-18, 1.9879461273563199e-17, 2.6381930823541892e-16, 3.1406382865933653e-15, 3.3622360761898003e-14, 3.2444814316722348e-13, 2.8281489919728500e-12, 2.2313290142958860e-11, 1.5963585528134907e-10, 1.0373981456665397e-09, 6.1333415530709063e-09, 3.3038743448338228e-08, 1.6237364967913452e-07, 7.2898765543366947e-07, 2.9932498983591025e-06, 1.1252541495603299e-05, 3.8767965827716168e-05, 1.2251950121646584e-04, 3.5547512496610876e-04, 9.4757899341760905e-04, 2.3223308982827312e-03, 5.2360833859067743e-03, 1.0866914248342787e-02, 2.0770153886127483e-02, 3.6576106509803016e-02, 5.9366942312670930e-02, 8.8842708636295842e-02, 1.2261541377174207e-01, 1.5610147984994696e-01, 1.8334823578007414e-01, 1.9870103704081624e-01, 1.9870103704081624e-01, 1.8334823578007414e-01, 1.5610147984994696e-01, 1.2261541377174207e-01, 8.8842708636295842e-02, 5.9366942312670930e-02, 3.6576106509803016e-02, 2.0770153886127483e-02, 1.0866914248342787e-02, 5.2360833859067743e-03, 2.3223308982827312e-03, 9.4757899341760905e-04, 3.5547512496610876e-04, 1.2251950121646584e-04, 3.8767965827716168e-05, 1.1252541495603299e-05, 2.9932498983591025e-06, 7.2898765543366947e-07, 1.6237364967913452e-07, 3.3038743448338228e-08, 6.1333415530709063e-09, 1.0373981456665397e-09, 1.5963585528134907e-10, 2.2313290142958860e-11, 2.8281489919728500e-12, 3.2444814316722348e-13, 3.3622360761898003e-14, 3.1406382865933653e-15, 2.6381930823541892e-16, 1.9879461273563199e-17, 1.3400866628758495e-18, 8.0577481866273284e-20, 4.3078486936244584e-21, 2.0406372113926846e-22, 8.5327296120897214e-24, 3.1364243262134751e-25, 1.0088930738432750e-26, 2.8259664729965746e-28, 6.8553849798952103e-30, 1.4316070974387265e-31, 2.5564844139368277e-33, 3.8749094400485918e-35, 4.9438860107310490e-37, 5.2602254003426042e-39, 4.6182598989607685e-41, 3.3057067086043009e-43, 1.9026918231732264e-45, 8.6667923231989335e-48, 3.0664667336421114e-50, 8.2441788250067191e-53, 1.6403928051497794e-55, 2.3396177274687451e-58, 2.2990511219174665e-61, 1.4805274033207088e-64, 5.8544142858486073e-68, 1.3022823162971665e-71, 1.4403978976524620e-75, 6.5830036453656527e-80, 9.1706055028522197e-85, 2.1806296158265287e-90, 2.0184534275095049e-97}, + {2.9088440757674062e-98, 3.3027195553941757e-91, 1.4482784276490109e-85, 1.0797361898132115e-80, 2.4475687753038470e-76, 2.2885780042663531e-72, 1.0626701542492299e-68, 2.7730751722659017e-65, 4.4400764524986828e-62, 4.6560392499732150e-59, 3.3622797072552750e-56, 1.7396913258105826e-53, 6.6597646076210362e-51, 1.9366833085713306e-48, 4.3737554297590874e-46, 7.8155861441480535e-44, 1.1228680356492188e-41, 1.3151165218678305e-39, 1.2708875196505519e-37, 1.0241410150378061e-35, 6.9469156975836022e-34, 3.9996687161846431e-32, 1.9692128985290527e-30, 8.3465290951830949e-29, 3.0639885163656867e-27, 9.7951708742326283e-26, 2.7405597239380626e-24, 6.7411887298015296e-23, 1.4638683297363268e-21, 2.8169790254203712e-20, 4.8205257099851608e-19, 7.3591325007878809e-18, 1.0052255425278666e-16, 1.2319403285686423e-15, 1.3580008734485746e-14, 1.3496086984992707e-13, 1.2118575324056077e-12, 9.8514672314148016e-12, 7.2637761188053839e-11, 4.8661361388782973e-10, 2.9666085963352118e-09, 1.6482913905846427e-08, 8.3579939555984911e-08, 3.8727287415554441e-07, 1.6416874675897103e-06, 6.3737479499140128e-06, 2.2686436750985634e-05, 7.4097922186640899e-05, 2.2227085873416057e-04, 6.1281987967776825e-04, 1.5540467884754450e-03, 3.6270593070595858e-03, 7.7957038787030220e-03, 1.5437973179493971e-02, 2.8181096910943754e-02, 4.7438564768728979e-02, 7.3664835869183778e-02, 1.0555264545810959e-01, 1.3959184263252383e-01, 1.7041655690534233e-01, 1.9207925104318502e-01, 1.9989393461088162e-01, 1.9207925104318502e-01, 1.7041655690534233e-01, 1.3959184263252383e-01, 1.0555264545810959e-01, 7.3664835869183778e-02, 4.7438564768728979e-02, 2.8181096910943754e-02, 1.5437973179493971e-02, 7.7957038787030220e-03, 3.6270593070595858e-03, 1.5540467884754450e-03, 6.1281987967776825e-04, 2.2227085873416057e-04, 7.4097922186640899e-05, 2.2686436750985634e-05, 6.3737479499140128e-06, 1.6416874675897103e-06, 3.8727287415554441e-07, 8.3579939555984911e-08, 1.6482913905846427e-08, 2.9666085963352118e-09, 4.8661361388782973e-10, 7.2637761188053839e-11, 9.8514672314148016e-12, 1.2118575324056077e-12, 1.3496086984992707e-13, 1.3580008734485746e-14, 1.2319403285686423e-15, 1.0052255425278666e-16, 7.3591325007878809e-18, 4.8205257099851608e-19, 2.8169790254203712e-20, 1.4638683297363268e-21, 6.7411887298015296e-23, 2.7405597239380626e-24, 9.7951708742326283e-26, 3.0639885163656867e-27, 8.3465290951830949e-29, 1.9692128985290527e-30, 3.9996687161846431e-32, 6.9469156975836022e-34, 1.0241410150378061e-35, 1.2708875196505519e-37, 1.3151165218678305e-39, 1.1228680356492188e-41, 7.8155861441480535e-44, 4.3737554297590874e-46, 1.9366833085713306e-48, 6.6597646076210362e-51, 1.7396913258105826e-53, 3.3622797072552750e-56, 4.6560392499732150e-59, 4.4400764524986828e-62, 2.7730751722659017e-65, 1.0626701542492299e-68, 2.2885780042663531e-72, 2.4475687753038470e-76, 1.0797361898132115e-80, 1.4482784276490109e-85, 3.3027195553941757e-91, 2.9088440757674062e-98}, + {4.1905794490628812e-99, 4.9990906972957580e-92, 2.2852295477811565e-86, 1.7690369566797577e-81, 4.1535499466158161e-77, 4.0157584892449402e-73, 1.9255984704437394e-69, 5.1840723409278860e-66, 8.5567547361303599e-63, 9.2443848020406234e-60, 6.8742017262988808e-57, 3.6611032011247543e-54, 1.4421371050636836e-51, 4.3141707603430363e-49, 1.0020507711410342e-46, 1.8412712525866596e-44, 2.7198617815524323e-42, 3.2749113002444449e-40, 3.2533264664077919e-38, 2.6949141835666013e-36, 1.8790207698162015e-34, 1.1120314056802636e-32, 5.6279071396682005e-31, 2.4520940513432773e-29, 9.2537661461189014e-28, 3.0414019572106789e-26, 8.7492009712123219e-25, 2.2129732702532020e-23, 4.9419868423536690e-22, 9.7813379414413797e-21, 1.7218091698469169e-19, 2.7043296085128987e-18, 3.8011128040478799e-17, 4.7943347392243567e-16, 5.4401721259012553e-15, 5.5664982903187763e-14, 5.1473099468312146e-13, 4.3100503800704298e-12, 3.2741601230785952e-11, 2.2604055819337785e-10, 1.4204990214913607e-09, 8.1379035349171669e-09, 4.2560154044109738e-08, 2.0345626953177357e-07, 8.9008863258739004e-07, 3.5675339063854564e-06, 1.3113467580430861e-05, 4.4247522456022853e-05, 1.3716931938884588e-04, 3.9098949747131122e-04, 1.0254795244170039e-03, 2.4764405325003970e-03, 5.5096709995779728e-03, 1.1299305506959472e-02, 2.1370374426895520e-02, 3.7289628484137964e-02, 6.0053278089003327e-02, 8.9287739344200062e-02, 1.2259255262751995e-01, 1.5546821084992313e-01, 1.8213364120711689e-01, 1.9713037059257607e-01, 1.9713037059257607e-01, 1.8213364120711689e-01, 1.5546821084992313e-01, 1.2259255262751995e-01, 8.9287739344200062e-02, 6.0053278089003327e-02, 3.7289628484137964e-02, 2.1370374426895520e-02, 1.1299305506959472e-02, 5.5096709995779728e-03, 2.4764405325003970e-03, 1.0254795244170039e-03, 3.9098949747131122e-04, 1.3716931938884588e-04, 4.4247522456022853e-05, 1.3113467580430861e-05, 3.5675339063854564e-06, 8.9008863258739004e-07, 2.0345626953177357e-07, 4.2560154044109738e-08, 8.1379035349171669e-09, 1.4204990214913607e-09, 2.2604055819337785e-10, 3.2741601230785952e-11, 4.3100503800704298e-12, 5.1473099468312146e-13, 5.5664982903187763e-14, 5.4401721259012553e-15, 4.7943347392243567e-16, 3.8011128040478799e-17, 2.7043296085128987e-18, 1.7218091698469169e-19, 9.7813379414413797e-21, 4.9419868423536690e-22, 2.2129732702532020e-23, 8.7492009712123219e-25, 3.0414019572106789e-26, 9.2537661461189014e-28, 2.4520940513432773e-29, 5.6279071396682005e-31, 1.1120314056802636e-32, 1.8790207698162015e-34, 2.6949141835666013e-36, 3.2533264664077919e-38, 3.2749113002444449e-40, 2.7198617815524323e-42, 1.8412712525866596e-44, 1.0020507711410342e-46, 4.3141707603430363e-49, 1.4421371050636836e-51, 3.6611032011247543e-54, 6.8742017262988808e-57, 9.2443848020406234e-60, 8.5567547361303599e-63, 5.1840723409278860e-66, 1.9255984704437394e-69, 4.0157584892449402e-73, 4.1535499466158161e-77, 1.7690369566797577e-81, 2.2852295477811565e-86, 4.9990906972957580e-92, 4.1905794490628812e-99}, + {6.0350604964534262e-100, 7.5621198682031623e-93, 3.6027698446759891e-87, 2.8952659291406100e-82, 7.0395367135995835e-78, 7.0359072121742493e-74, 3.4833403833073089e-70, 9.6729013253984892e-67, 1.6455761362144333e-63, 1.8312341591411876e-60, 1.4019398864694188e-57, 7.6839475145600301e-55, 3.1138694261390015e-52, 9.5806542034971832e-50, 2.2882121049633724e-47, 4.3227155768633621e-45, 6.5638401618338331e-43, 8.1233879274180601e-41, 8.2938969771250512e-39, 7.0606944403026099e-37, 5.0593403396440372e-35, 3.0770662798790086e-33, 1.6004068212453668e-31, 7.1663558200524862e-30, 2.7795790004930404e-28, 9.3899224442264679e-27, 2.7766379169834465e-25, 7.2198960174204195e-24, 1.6577060031062816e-22, 3.3737146353721905e-21, 6.1074208727145320e-20, 9.8664119741289685e-19, 1.4266141735959953e-17, 1.8513770722928222e-16, 2.1618705462400890e-15, 2.2768505441090677e-14, 2.1674951892336612e-13, 1.8688765345567561e-12, 1.4622404081860438e-11, 1.0399946851470756e-10, 6.7347582712586187e-10, 3.9769084715886220e-09, 2.1444167115213114e-08, 1.0572466663977363e-07, 4.7716606625319424e-07, 1.9736622489528508e-06, 7.4891717673847164e-06, 2.6095502713919602e-05, 8.3569751965942746e-05, 2.4616923611611111e-04, 6.6748228082773623e-04, 1.6670890148279265e-03, 3.8375633568742918e-03, 8.1464528080591927e-03, 1.5955521786480558e-02, 2.8845081137418717e-02, 4.8152169340609514e-02, 7.4248071076568556e-02, 1.0577887521500248e-01, 1.3926890249425167e-01, 1.6948290095730328e-01, 1.9066351798670744e-01, 1.9829478313399460e-01, 1.9066351798670744e-01, 1.6948290095730328e-01, 1.3926890249425167e-01, 1.0577887521500248e-01, 7.4248071076568556e-02, 4.8152169340609514e-02, 2.8845081137418717e-02, 1.5955521786480558e-02, 8.1464528080591927e-03, 3.8375633568742918e-03, 1.6670890148279265e-03, 6.6748228082773623e-04, 2.4616923611611111e-04, 8.3569751965942746e-05, 2.6095502713919602e-05, 7.4891717673847164e-06, 1.9736622489528508e-06, 4.7716606625319424e-07, 1.0572466663977363e-07, 2.1444167115213114e-08, 3.9769084715886220e-09, 6.7347582712586187e-10, 1.0399946851470756e-10, 1.4622404081860438e-11, 1.8688765345567561e-12, 2.1674951892336612e-13, 2.2768505441090677e-14, 2.1618705462400890e-15, 1.8513770722928222e-16, 1.4266141735959953e-17, 9.8664119741289685e-19, 6.1074208727145320e-20, 3.3737146353721905e-21, 1.6577060031062816e-22, 7.2198960174204195e-24, 2.7766379169834465e-25, 9.3899224442264679e-27, 2.7795790004930404e-28, 7.1663558200524862e-30, 1.6004068212453668e-31, 3.0770662798790086e-33, 5.0593403396440372e-35, 7.0606944403026099e-37, 8.2938969771250512e-39, 8.1233879274180601e-41, 6.5638401618338331e-43, 4.3227155768633621e-45, 2.2882121049633724e-47, 9.5806542034971832e-50, 3.1138694261390015e-52, 7.6839475145600301e-55, 1.4019398864694188e-57, 1.8312341591411876e-60, 1.6455761362144333e-63, 9.6729013253984892e-67, 3.4833403833073089e-70, 7.0359072121742493e-74, 7.0395367135995835e-78, 2.8952659291406100e-82, 3.6027698446759891e-87, 7.5621198682031623e-93, 6.0350604964534262e-100}, + {8.6885048841104336e-101, 1.1432282229672125e-93, 5.6751482819801390e-88, 4.7334609039691596e-83, 1.1915620124280458e-78, 1.2309273526337388e-74, 6.2907076772692688e-71, 1.8014846076367508e-67, 3.1581319803836728e-64, 3.6193344722347900e-61, 2.8521414298372380e-58, 1.6084468211903416e-55, 6.7043872367938317e-53, 2.1211541634033625e-50, 5.2082971293259102e-48, 1.0113496653683935e-45, 1.5782902465389378e-43, 2.0072591434893221e-41, 2.1058526230258254e-39, 1.8420302384806772e-37, 1.3561579038335388e-35, 8.4745466577882083e-34, 4.5287460314884707e-32, 2.0836578377129600e-30, 8.3043823092881025e-29, 2.8828182366037129e-27, 8.7606149843747518e-26, 2.3412386562212859e-24, 5.5254399484537480e-23, 1.1560142775887639e-21, 2.1516151218938123e-20, 3.5742061956149856e-19, 5.3150514071326065e-18, 7.0949360015714532e-17, 8.5234045323955501e-16, 9.2369780981720531e-15, 9.0500846874230352e-14, 8.0327883964150772e-13, 6.4713186612400961e-12, 4.7401870432354588e-11, 3.1621598261836951e-10, 1.9240529197354846e-09, 1.0693195796935537e-08, 5.4353072977389075e-08, 2.5298490233788676e-07, 1.0794646043238905e-06, 4.2268677400739964e-06, 1.5203524203072556e-05, 5.0277271260002348e-05, 1.5298771765756425e-04, 4.2867197747952282e-04, 1.1068159448702048e-03, 2.6349882348356921e-03, 5.7873557283189625e-03, 1.1732759367031630e-02, 2.1965177289949588e-02, 3.7988873885061170e-02, 6.0717658137057637e-02, 8.9709385493087268e-02, 1.2255485603934885e-01, 1.5483776980551858e-01, 1.8094215487742904e-01, 1.9559636350108756e-01, 1.9559636350108756e-01, 1.8094215487742904e-01, 1.5483776980551858e-01, 1.2255485603934885e-01, 8.9709385493087268e-02, 6.0717658137057637e-02, 3.7988873885061170e-02, 2.1965177289949588e-02, 1.1732759367031630e-02, 5.7873557283189625e-03, 2.6349882348356921e-03, 1.1068159448702048e-03, 4.2867197747952282e-04, 1.5298771765756425e-04, 5.0277271260002348e-05, 1.5203524203072556e-05, 4.2268677400739964e-06, 1.0794646043238905e-06, 2.5298490233788676e-07, 5.4353072977389075e-08, 1.0693195796935537e-08, 1.9240529197354846e-09, 3.1621598261836951e-10, 4.7401870432354588e-11, 6.4713186612400961e-12, 8.0327883964150772e-13, 9.0500846874230352e-14, 9.2369780981720531e-15, 8.5234045323955501e-16, 7.0949360015714532e-17, 5.3150514071326065e-18, 3.5742061956149856e-19, 2.1516151218938123e-20, 1.1560142775887639e-21, 5.5254399484537480e-23, 2.3412386562212859e-24, 8.7606149843747518e-26, 2.8828182366037129e-27, 8.3043823092881025e-29, 2.0836578377129600e-30, 4.5287460314884707e-32, 8.4745466577882083e-34, 1.3561579038335388e-35, 1.8420302384806772e-37, 2.1058526230258254e-39, 2.0072591434893221e-41, 1.5782902465389378e-43, 1.0113496653683935e-45, 5.2082971293259102e-48, 2.1211541634033625e-50, 6.7043872367938317e-53, 1.6084468211903416e-55, 2.8521414298372380e-58, 3.6193344722347900e-61, 3.1581319803836728e-64, 1.8014846076367508e-67, 6.2907076772692688e-71, 1.2309273526337388e-74, 1.1915620124280458e-78, 4.7334609039691596e-83, 5.6751482819801390e-88, 1.1432282229672125e-93, 8.6885048841104336e-101}, + {1.2504497509175530e-101, 1.7272798059471284e-94, 8.9321681572258524e-89, 7.7306185241136030e-84, 2.0143957652711162e-79, 2.1503714733677984e-75, 1.1341924208630308e-71, 3.3489139011900278e-68, 6.0486548964206330e-65, 7.1375092946576251e-62, 5.7884563375067011e-59, 3.3581166223962448e-56, 1.4394641949298623e-53, 4.6821808383361703e-51, 1.1817054440721172e-48, 2.3581659156082481e-46, 3.7814427940915093e-44, 4.9411031115925398e-42, 5.3255303775590573e-40, 4.7854390680281889e-38, 3.6191883446065631e-36, 2.3232083386416384e-34, 1.2753331411048401e-32, 6.0277753850946330e-31, 2.4679773241853991e-29, 8.8019567691972675e-28, 2.7482489212126092e-26, 7.5468218903320873e-25, 1.8303134636337642e-23, 3.9355990860983814e-22, 7.5293161638815711e-21, 1.2857997786762843e-19, 1.9659326888507207e-18, 2.6986511907298130e-17, 3.3344414303302576e-16, 3.7173303125266623e-15, 3.7473954472956373e-14, 3.4230094493503872e-13, 2.8385303725081926e-12, 2.1406920290521382e-11, 1.4706331273477511e-10, 9.2173940967721533e-10, 5.2781663937137130e-09, 2.7650497045037171e-08, 1.3267855842580783e-07, 5.8380944276295039e-07, 2.3581561724849069e-06, 8.7524468034552877e-06, 2.9876790536001972e-05, 9.3874435720364848e-05, 2.7170762628015821e-04, 7.2493929742724068e-04, 1.7841208326818967e-03, 4.0524855186172149e-03, 8.5000263041808636e-03, 1.6471142241660967e-02, 2.9499296248305443e-02, 4.8847387114452009e-02, 7.4807989768816377e-02, 1.0598520508123921e-01, 1.3893945309094766e-01, 1.6856236074260383e-01, 1.8927849580179334e-01, 1.9673340688884505e-01, 1.8927849580179334e-01, 1.6856236074260383e-01, 1.3893945309094766e-01, 1.0598520508123921e-01, 7.4807989768816377e-02, 4.8847387114452009e-02, 2.9499296248305443e-02, 1.6471142241660967e-02, 8.5000263041808636e-03, 4.0524855186172149e-03, 1.7841208326818967e-03, 7.2493929742724068e-04, 2.7170762628015821e-04, 9.3874435720364848e-05, 2.9876790536001972e-05, 8.7524468034552877e-06, 2.3581561724849069e-06, 5.8380944276295039e-07, 1.3267855842580783e-07, 2.7650497045037171e-08, 5.2781663937137130e-09, 9.2173940967721533e-10, 1.4706331273477511e-10, 2.1406920290521382e-11, 2.8385303725081926e-12, 3.4230094493503872e-13, 3.7473954472956373e-14, 3.7173303125266623e-15, 3.3344414303302576e-16, 2.6986511907298130e-17, 1.9659326888507207e-18, 1.2857997786762843e-19, 7.5293161638815711e-21, 3.9355990860983814e-22, 1.8303134636337642e-23, 7.5468218903320873e-25, 2.7482489212126092e-26, 8.8019567691972675e-28, 2.4679773241853991e-29, 6.0277753850946330e-31, 1.2753331411048401e-32, 2.3232083386416384e-34, 3.6191883446065631e-36, 4.7854390680281889e-38, 5.3255303775590573e-40, 4.9411031115925398e-42, 3.7814427940915093e-44, 2.3581659156082481e-46, 1.1817054440721172e-48, 4.6821808383361703e-51, 1.4394641949298623e-53, 3.3581166223962448e-56, 5.7884563375067011e-59, 7.1375092946576251e-62, 6.0486548964206330e-65, 3.3489139011900278e-68, 1.1341924208630308e-71, 2.1503714733677984e-75, 2.0143957652711162e-79, 7.7306185241136030e-84, 8.9321681572258524e-89, 1.7272798059471284e-94, 1.2504497509175530e-101}, + {1.7990659801093241e-102, 2.6081724024084728e-95, 1.4046897713151180e-89, 1.2612494833385409e-84, 3.4012300869368197e-80, 3.7512158688048432e-76, 2.0415857972441075e-72, 6.2142441618306433e-69, 1.1561551640964042e-65, 1.4044672577405165e-62, 1.1719785012130235e-59, 6.9930729240520693e-57, 3.0820773833392742e-54, 1.0304862520557101e-51, 2.6727437517360924e-49, 5.4802170289787664e-47, 9.0280401387865924e-45, 1.2117795341306277e-42, 1.3414974817643660e-40, 1.2380855579763670e-38, 9.6167080679676503e-37, 6.3399135263665769e-35, 3.5743788958794533e-33, 1.7351030202821157e-31, 7.2965450067684075e-30, 2.6729236200580738e-28, 8.5728304837693986e-27, 2.4184034596476935e-25, 6.0259840320064904e-24, 1.3313678590335932e-22, 2.6174575839348305e-21, 4.5940076773297253e-20, 7.2201073169282769e-19, 1.0189332304232922e-17, 1.2945481593393717e-16, 1.4842238375138792e-15, 1.5390497303535517e-14, 1.4463473211904274e-13, 1.2342144866005691e-12, 9.5803165087358731e-12, 6.7757804877745394e-11, 4.3731866598484108e-10, 2.5793972294264184e-09, 1.3921907152935201e-08, 6.8845811221543303e-08, 3.1228729861789030e-07, 1.3007470032382014e-06, 4.9799245325909927e-06, 1.7540485848093888e-05, 5.6887437600402582e-05, 1.7001408826280900e-04, 4.6855153780841227e-04, 1.1915638144571682e-03, 2.7978394016057863e-03, 6.0688624069258814e-03, 1.2166918864469335e-02, 2.2554310167824408e-02, 3.8673954810636818e-02, 6.1360721004490068e-02, 9.0108678376448870e-02, 1.2250327316413555e-01, 1.5421043529835440e-01, 1.7977308390779931e-01, 1.9409761186408808e-01, 1.9409761186408808e-01, 1.7977308390779931e-01, 1.5421043529835440e-01, 1.2250327316413555e-01, 9.0108678376448870e-02, 6.1360721004490068e-02, 3.8673954810636818e-02, 2.2554310167824408e-02, 1.2166918864469335e-02, 6.0688624069258814e-03, 2.7978394016057863e-03, 1.1915638144571682e-03, 4.6855153780841227e-04, 1.7001408826280900e-04, 5.6887437600402582e-05, 1.7540485848093888e-05, 4.9799245325909927e-06, 1.3007470032382014e-06, 3.1228729861789030e-07, 6.8845811221543303e-08, 1.3921907152935201e-08, 2.5793972294264184e-09, 4.3731866598484108e-10, 6.7757804877745394e-11, 9.5803165087358731e-12, 1.2342144866005691e-12, 1.4463473211904274e-13, 1.5390497303535517e-14, 1.4842238375138792e-15, 1.2945481593393717e-16, 1.0189332304232922e-17, 7.2201073169282769e-19, 4.5940076773297253e-20, 2.6174575839348305e-21, 1.3313678590335932e-22, 6.0259840320064904e-24, 2.4184034596476935e-25, 8.5728304837693986e-27, 2.6729236200580738e-28, 7.2965450067684075e-30, 1.7351030202821157e-31, 3.5743788958794533e-33, 6.3399135263665769e-35, 9.6167080679676503e-37, 1.2380855579763670e-38, 1.3414974817643660e-40, 1.2117795341306277e-42, 9.0280401387865924e-45, 5.4802170289787664e-47, 2.6727437517360924e-49, 1.0304862520557101e-51, 3.0820773833392742e-54, 6.9930729240520693e-57, 1.1719785012130235e-59, 1.4044672577405165e-62, 1.1561551640964042e-65, 6.2142441618306433e-69, 2.0415857972441075e-72, 3.7512158688048432e-76, 3.4012300869368197e-80, 1.2612494833385409e-84, 1.4046897713151180e-89, 2.6081724024084728e-95, 1.7990659801093241e-102}, + {2.5875539364524082e-103, 3.9360184590802221e-96, 2.2072552957748285e-90, 2.0556308729779607e-85, 5.7358476340730861e-81, 6.5345649901409931e-77, 3.6690360645455800e-73, 1.1510510197511481e-69, 2.2055377414515242e-66, 2.7576366331120112e-63, 2.3673174707161052e-60, 1.4525786040323095e-57, 6.5811912152939833e-55, 2.2613773295130902e-52, 6.0264301132977530e-50, 1.2693840763809051e-47, 2.1479177879979361e-45, 2.9609218353788539e-43, 3.3661609053282785e-41, 3.1901478352848241e-39, 2.5443979671277979e-37, 1.7223946532210455e-35, 9.9710553873521448e-34, 4.9700994335207590e-32, 2.1462063060723877e-30, 8.0737792155578718e-29, 2.6593692402816157e-27, 7.7051505318327598e-26, 1.9720496638158951e-24, 4.4757971347544071e-23, 9.0403370335874384e-22, 1.6303640703529370e-20, 2.6332049182645191e-19, 3.8194419802784429e-18, 4.9883327330781313e-17, 5.8802277275507751e-16, 6.2702394771473180e-15, 6.0607257135908391e-14, 5.3204907075388442e-13, 4.2495506587750072e-12, 3.0933020393247358e-11, 2.0552435298786022e-10, 1.2482251818681576e-09, 6.9389671445373625e-09, 3.5351823460523453e-08, 1.6525270457753961e-07, 7.0953503060139187e-07, 2.8010603367707380e-06, 1.0176471541446871e-05, 3.4054184172402124e-05, 1.0504748699764762e-04, 2.9892250594151955e-04, 7.8519722061027154e-04, 1.9050667392793649e-03, 4.2716207417923171e-03, 8.8560992639436561e-03, 1.6984511709158091e-02, 3.0143653484891619e-02, 4.9524590136894565e-02, 7.5345450641660414e-02, 1.0617266978963312e-01, 1.3860414698078849e-01, 1.6765473214361890e-01, 1.8792309546385810e-01, 1.9520834171916421e-01, 1.8792309546385810e-01, 1.6765473214361890e-01, 1.3860414698078849e-01, 1.0617266978963312e-01, 7.5345450641660414e-02, 4.9524590136894565e-02, 3.0143653484891619e-02, 1.6984511709158091e-02, 8.8560992639436561e-03, 4.2716207417923171e-03, 1.9050667392793649e-03, 7.8519722061027154e-04, 2.9892250594151955e-04, 1.0504748699764762e-04, 3.4054184172402124e-05, 1.0176471541446871e-05, 2.8010603367707380e-06, 7.0953503060139187e-07, 1.6525270457753961e-07, 3.5351823460523453e-08, 6.9389671445373625e-09, 1.2482251818681576e-09, 2.0552435298786022e-10, 3.0933020393247358e-11, 4.2495506587750072e-12, 5.3204907075388442e-13, 6.0607257135908391e-14, 6.2702394771473180e-15, 5.8802277275507751e-16, 4.9883327330781313e-17, 3.8194419802784429e-18, 2.6332049182645191e-19, 1.6303640703529370e-20, 9.0403370335874384e-22, 4.4757971347544071e-23, 1.9720496638158951e-24, 7.7051505318327598e-26, 2.6593692402816157e-27, 8.0737792155578718e-29, 2.1462063060723877e-30, 4.9700994335207590e-32, 9.9710553873521448e-34, 1.7223946532210455e-35, 2.5443979671277979e-37, 3.1901478352848241e-39, 3.3661609053282785e-41, 2.9609218353788539e-43, 2.1479177879979361e-45, 1.2693840763809051e-47, 6.0264301132977530e-50, 2.2613773295130902e-52, 6.5811912152939833e-55, 1.4525786040323095e-57, 2.3673174707161052e-60, 2.7576366331120112e-63, 2.2055377414515242e-66, 1.1510510197511481e-69, 3.6690360645455800e-73, 6.5345649901409931e-77, 5.7358476340730861e-81, 2.0556308729779607e-85, 2.2072552957748285e-90, 3.9360184590802221e-96, 2.5875539364524082e-103}, + {3.7204460108518457e-104, 5.9364731594787663e-97, 3.4655965116643281e-91, 3.3469757581791224e-86, 9.6613261772636215e-82, 1.1367258528662723e-77, 6.5833865033387550e-74, 2.1283034461639501e-70, 4.1991937638649886e-67, 5.4030149717578019e-64, 4.7707625290237234e-61, 3.0097211186016156e-58, 1.4015247946309535e-55, 4.9483338463613849e-53, 1.3546817753059001e-50, 2.9307665929739616e-48, 5.0927511908300209e-46, 7.2087130229885203e-44, 8.4144007328158726e-42, 8.1870801342500945e-40, 6.7037119216509246e-38, 4.6587143166611642e-36, 2.7687058280430152e-34, 1.4168038025321554e-32, 6.2811433857681812e-31, 2.4259782593432643e-29, 8.2046076950332880e-28, 2.4409654886964413e-26, 6.4156025663739209e-25, 1.4954510277528916e-23, 3.1025363444064255e-22, 5.7477855676921120e-21, 9.5376732466503112e-20, 1.4215508257408722e-18, 1.9080516525917262e-17, 2.3119223992445814e-16, 2.5344536275316043e-15, 2.5189945152766989e-14, 2.2742721378405763e-13, 1.8685821935956322e-12, 1.3994739517759176e-11, 9.5692629429270517e-11, 5.9825297159286590e-10, 3.4243028086561824e-09, 1.7967512803433057e-08, 8.6525026250843954e-08, 3.8283102346903316e-07, 1.5578439536677208e-06, 5.8357960655860304e-06, 2.0142490747188856e-05, 6.4107957353545819e-05, 1.8828587640798520e-04, 5.1065276380199355e-04, 1.2796927737216395e-03, 2.9648560622765260e-03, 6.3539216222626869e-03, 1.2601446134450314e-02, 2.3137547830647125e-02, 3.9345000709058629e-02, 6.1983091960651798e-02, 9.0486600174251544e-02, 1.2243869169055180e-01, 1.5358645412541436e-01, 1.7862576228606980e-01, 1.9263278589714239e-01, 1.9263278589714239e-01, 1.7862576228606980e-01, 1.5358645412541436e-01, 1.2243869169055180e-01, 9.0486600174251544e-02, 6.1983091960651798e-02, 3.9345000709058629e-02, 2.3137547830647125e-02, 1.2601446134450314e-02, 6.3539216222626869e-03, 2.9648560622765260e-03, 1.2796927737216395e-03, 5.1065276380199355e-04, 1.8828587640798520e-04, 6.4107957353545819e-05, 2.0142490747188856e-05, 5.8357960655860304e-06, 1.5578439536677208e-06, 3.8283102346903316e-07, 8.6525026250843954e-08, 1.7967512803433057e-08, 3.4243028086561824e-09, 5.9825297159286590e-10, 9.5692629429270517e-11, 1.3994739517759176e-11, 1.8685821935956322e-12, 2.2742721378405763e-13, 2.5189945152766989e-14, 2.5344536275316043e-15, 2.3119223992445814e-16, 1.9080516525917262e-17, 1.4215508257408722e-18, 9.5376732466503112e-20, 5.7477855676921120e-21, 3.1025363444064255e-22, 1.4954510277528916e-23, 6.4156025663739209e-25, 2.4409654886964413e-26, 8.2046076950332880e-28, 2.4259782593432643e-29, 6.2811433857681812e-31, 1.4168038025321554e-32, 2.7687058280430152e-34, 4.6587143166611642e-36, 6.7037119216509246e-38, 8.1870801342500945e-40, 8.4144007328158726e-42, 7.2087130229885203e-44, 5.0927511908300209e-46, 2.9307665929739616e-48, 1.3546817753059001e-50, 4.9483338463613849e-53, 1.4015247946309535e-55, 3.0097211186016156e-58, 4.7707625290237234e-61, 5.4030149717578019e-64, 4.1991937638649886e-67, 2.1283034461639501e-70, 6.5833865033387550e-74, 1.1367258528662723e-77, 9.6613261772636215e-82, 3.3469757581791224e-86, 3.4655965116643281e-91, 5.9364731594787663e-97, 3.7204460108518457e-104}, + {5.3476826111026365e-105, 8.9485710679509321e-98, 5.4370243471100807e-92, 5.4441378603550616e-87, 1.6254006780310087e-82, 1.9746831356131776e-78, 1.1794217215696164e-74, 3.9284007348254153e-71, 7.9796183204186807e-68, 1.0563843092209409e-64, 9.5924087114315112e-62, 6.2207574186530967e-59, 2.9767954168841160e-56, 1.0797369730934170e-53, 3.0360436451965334e-51, 6.7450137912280108e-49, 1.2034270735300903e-46, 1.7487964745761127e-44, 2.0954606929273772e-42, 2.0928182450743565e-40, 1.7589155981687000e-38, 1.2546216106083190e-36, 7.6531182757967849e-35, 4.0196809205772165e-33, 1.8291657781800354e-31, 7.2519108515928950e-30, 2.5176731485459177e-28, 7.6897052483356061e-27, 2.0750476694679341e-25, 4.9664572942742541e-24, 1.0580876836793333e-22, 2.0131999550178635e-21, 3.4313613065500532e-20, 5.2539364144662411e-19, 7.2456324501572317e-18, 9.0217967422636200e-17, 1.0165109952415262e-15, 1.0385841011593362e-14, 9.6411044899350535e-14, 8.1461816331285264e-13, 6.2756146921948126e-12, 4.4148505508362490e-11, 2.8403341656010478e-10, 1.6734368028761769e-09, 9.0404035956869064e-09, 4.4835197499650446e-08, 2.0435322677073055e-07, 8.5687946165889204e-07, 3.3086178947400949e-06, 1.1774562755908359e-05, 3.8651667203812415e-05, 1.1712338225370822e-04, 3.2784720468186990e-04, 8.4825701574449603e-04, 2.0298461578116241e-03, 4.4947646714684642e-03, 9.2143589576985860e-03, 1.7495331329372001e-02, 3.0778087957022211e-02, 5.0184153739443245e-02, 7.5861280569172768e-02, 1.0634224601517195e-01, 1.3826358695373833e-01, 1.6675980772407939e-01, 1.8659628095711822e-01, 1.9371820170604062e-01, 1.8659628095711822e-01, 1.6675980772407939e-01, 1.3826358695373833e-01, 1.0634224601517195e-01, 7.5861280569172768e-02, 5.0184153739443245e-02, 3.0778087957022211e-02, 1.7495331329372001e-02, 9.2143589576985860e-03, 4.4947646714684642e-03, 2.0298461578116241e-03, 8.4825701574449603e-04, 3.2784720468186990e-04, 1.1712338225370822e-04, 3.8651667203812415e-05, 1.1774562755908359e-05, 3.3086178947400949e-06, 8.5687946165889204e-07, 2.0435322677073055e-07, 4.4835197499650446e-08, 9.0404035956869064e-09, 1.6734368028761769e-09, 2.8403341656010478e-10, 4.4148505508362490e-11, 6.2756146921948126e-12, 8.1461816331285264e-13, 9.6411044899350535e-14, 1.0385841011593362e-14, 1.0165109952415262e-15, 9.0217967422636200e-17, 7.2456324501572317e-18, 5.2539364144662411e-19, 3.4313613065500532e-20, 2.0131999550178635e-21, 1.0580876836793333e-22, 4.9664572942742541e-24, 2.0750476694679341e-25, 7.6897052483356061e-27, 2.5176731485459177e-28, 7.2519108515928950e-30, 1.8291657781800354e-31, 4.0196809205772165e-33, 7.6531182757967849e-35, 1.2546216106083190e-36, 1.7589155981687000e-38, 2.0928182450743565e-40, 2.0954606929273772e-42, 1.7487964745761127e-44, 1.2034270735300903e-46, 6.7450137912280108e-49, 3.0360436451965334e-51, 1.0797369730934170e-53, 2.9767954168841160e-56, 6.2207574186530967e-59, 9.5924087114315112e-62, 1.0563843092209409e-64, 7.9796183204186807e-68, 3.9284007348254153e-71, 1.1794217215696164e-74, 1.9746831356131776e-78, 1.6254006780310087e-82, 5.4441378603550616e-87, 5.4370243471100807e-92, 8.9485710679509321e-98, 5.3476826111026365e-105}, + {7.6842766516367719e-106, 1.3481426814084330e-98, 8.5232824201455338e-93, 8.8466828631703380e-88, 2.7313386049487823e-83, 3.4257032455364114e-79, 2.1096988030040495e-75, 7.2385503439630423e-72, 1.5134726683009566e-68, 2.0611376551597914e-65, 1.9243761113547505e-62, 1.2826427266230406e-59, 6.3061655444515630e-57, 2.3494568244414183e-54, 6.7840814198640183e-52, 1.5474546466895863e-49, 2.8342684935250220e-47, 4.2276037377430170e-45, 5.1990976532787586e-43, 5.3289760352121873e-41, 4.5962221753185640e-39, 3.3643504079348503e-37, 2.1059885157863759e-35, 1.1351213650894055e-33, 5.3008778122412928e-32, 2.1567929048213211e-30, 7.6849291812936124e-29, 2.4091492702687982e-27, 6.6731359742375955e-26, 1.6395930158211436e-24, 3.5862705417926132e-23, 7.0063164858326786e-22, 1.2263229445163221e-20, 1.9284904334361852e-19, 2.7319104369658748e-18, 3.4946872798000184e-17, 4.0459872349113726e-16, 4.2484216574797647e-15, 4.0538431929767204e-14, 3.5215468617192942e-13, 2.7897431630242835e-12, 2.0185811443148509e-11, 1.3360415395259884e-10, 8.0999556201008525e-10, 4.5039223844610038e-09, 2.2996588427898263e-08, 1.0794018969942840e-07, 4.6622930297370394e-07, 1.8549414274389103e-06, 6.8039737747046242e-06, 2.3027980530130599e-05, 7.1968372723672767e-05, 2.0783849443716974e-04, 5.5499593798384811e-04, 1.3711669594184176e-03, 3.1358975655376973e-03, 6.6422701758844281e-03, 1.3036021883614270e-02, 2.3714690293508239e-02, 4.0002156173129341e-02, 6.2585382403901088e-02, 9.0844086374182967e-02, 1.2236194224535350e-01, 1.5296604436543901e-01, 1.7749954969646717e-01, 1.9120062497846860e-01, 1.9120062497846860e-01, 1.7749954969646717e-01, 1.5296604436543901e-01, 1.2236194224535350e-01, 9.0844086374182967e-02, 6.2585382403901088e-02, 4.0002156173129341e-02, 2.3714690293508239e-02, 1.3036021883614270e-02, 6.6422701758844281e-03, 3.1358975655376973e-03, 1.3711669594184176e-03, 5.5499593798384811e-04, 2.0783849443716974e-04, 7.1968372723672767e-05, 2.3027980530130599e-05, 6.8039737747046242e-06, 1.8549414274389103e-06, 4.6622930297370394e-07, 1.0794018969942840e-07, 2.2996588427898263e-08, 4.5039223844610038e-09, 8.0999556201008525e-10, 1.3360415395259884e-10, 2.0185811443148509e-11, 2.7897431630242835e-12, 3.5215468617192942e-13, 4.0538431929767204e-14, 4.2484216574797647e-15, 4.0459872349113726e-16, 3.4946872798000184e-17, 2.7319104369658748e-18, 1.9284904334361852e-19, 1.2263229445163221e-20, 7.0063164858326786e-22, 3.5862705417926132e-23, 1.6395930158211436e-24, 6.6731359742375955e-26, 2.4091492702687982e-27, 7.6849291812936124e-29, 2.1567929048213211e-30, 5.3008778122412928e-32, 1.1351213650894055e-33, 2.1059885157863759e-35, 3.3643504079348503e-37, 4.5962221753185640e-39, 5.3289760352121873e-41, 5.1990976532787586e-43, 4.2276037377430170e-45, 2.8342684935250220e-47, 1.5474546466895863e-49, 6.7840814198640183e-52, 2.3494568244414183e-54, 6.3061655444515630e-57, 1.2826427266230406e-59, 1.9243761113547505e-62, 2.0611376551597914e-65, 1.5134726683009566e-68, 7.2385503439630423e-72, 2.1096988030040495e-75, 3.4257032455364114e-79, 2.7313386049487823e-83, 8.8466828631703380e-88, 8.5232824201455338e-93, 1.3481426814084330e-98, 7.6842766516367719e-106}, + {1.1038467599988350e-106, 2.0299162819709644e-99, 1.3351165545454540e-93, 1.4361908901012819e-88, 4.5844662610976337e-84, 5.9349976525016213e-80, 3.7680124485137400e-76, 1.3315304198313815e-72, 2.8651973069480425e-69, 4.0133192434618745e-66, 3.8520167842143179e-63, 2.6383248122689808e-60, 1.3324956798179218e-57, 5.0982905111217610e-55, 1.5114881547668727e-52, 3.5392080595751209e-50, 6.6532981134843764e-48, 1.0184623032786348e-45, 1.2852633429954566e-43, 1.3517324859318610e-41, 1.1962163965744953e-39, 8.9837835745312106e-38, 5.7697747333366196e-36, 3.1907496278196311e-34, 1.5288163843577720e-32, 6.3824723629696159e-31, 2.3335393536670584e-29, 7.5069091034254989e-28, 2.1339408990452690e-26, 5.3812272933845995e-25, 1.2081587782243251e-23, 2.4230032186653206e-22, 4.3541619756512954e-21, 7.0308758150274706e-20, 1.0228495371481795e-18, 1.3439170617083339e-17, 1.5983699268748500e-16, 1.7244201781932836e-15, 1.6909213145415565e-14, 1.5097790665682497e-13, 1.2295731019067163e-12, 9.1482393782595353e-12, 6.2274132191241200e-11, 3.8838846452764459e-10, 2.2221554698762070e-09, 1.1677641217752186e-08, 5.6428156340858430e-08, 2.5098662449728381e-07, 1.0285882365095455e-06, 3.8874166532037593e-06, 1.3560417245137210e-05, 4.3693239040909913e-05, 1.3013545776424483e-04, 3.5851189054336881e-04, 9.1411456482270634e-04, 2.1583740072268734e-03, 4.7217142757868197e-03, 9.5745050499428906e-03, 1.8003325023065602e-02, 3.1402556502212124e-02, 5.0826454983412143e-02, 7.6356275486723038e-02, 1.0649485597288683e-01, 1.3791833004859055e-01, 1.6587737779249406e-01, 1.8529706602349078e-01, 1.9226167387366441e-01, 1.8529706602349078e-01, 1.6587737779249406e-01, 1.3791833004859055e-01, 1.0649485597288683e-01, 7.6356275486723038e-02, 5.0826454983412143e-02, 3.1402556502212124e-02, 1.8003325023065602e-02, 9.5745050499428906e-03, 4.7217142757868197e-03, 2.1583740072268734e-03, 9.1411456482270634e-04, 3.5851189054336881e-04, 1.3013545776424483e-04, 4.3693239040909913e-05, 1.3560417245137210e-05, 3.8874166532037593e-06, 1.0285882365095455e-06, 2.5098662449728381e-07, 5.6428156340858430e-08, 1.1677641217752186e-08, 2.2221554698762070e-09, 3.8838846452764459e-10, 6.2274132191241200e-11, 9.1482393782595353e-12, 1.2295731019067163e-12, 1.5097790665682497e-13, 1.6909213145415565e-14, 1.7244201781932836e-15, 1.5983699268748500e-16, 1.3439170617083339e-17, 1.0228495371481795e-18, 7.0308758150274706e-20, 4.3541619756512954e-21, 2.4230032186653206e-22, 1.2081587782243251e-23, 5.3812272933845995e-25, 2.1339408990452690e-26, 7.5069091034254989e-28, 2.3335393536670584e-29, 6.3824723629696159e-31, 1.5288163843577720e-32, 3.1907496278196311e-34, 5.7697747333366196e-36, 8.9837835745312106e-38, 1.1962163965744953e-39, 1.3517324859318610e-41, 1.2852633429954566e-43, 1.0184623032786348e-45, 6.6532981134843764e-48, 3.5392080595751209e-50, 1.5114881547668727e-52, 5.0982905111217610e-55, 1.3324956798179218e-57, 2.6383248122689808e-60, 3.8520167842143179e-63, 4.0133192434618745e-66, 2.8651973069480425e-69, 1.3315304198313815e-72, 3.7680124485137400e-76, 5.9349976525016213e-80, 4.5844662610976337e-84, 1.4361908901012819e-88, 1.3351165545454540e-93, 2.0299162819709644e-99, 1.1038467599988350e-106}, + {1.5852022154122762e-107, 3.0548054158892936e-100, 2.0897891620152027e-94, 2.3293228753706694e-89, 7.6861123200181953e-85, 1.0268748980780725e-80, 6.7197562830108496e-77, 2.4452549463378667e-73, 5.4141833815112683e-70, 7.7987351892856256e-67, 7.6937052841722558e-64, 5.4140880882527221e-61, 2.8084445413684342e-58, 1.1033315179441334e-55, 3.3578943438527196e-53, 8.0698691825802516e-51, 1.5567833435482675e-48, 2.4451923543925048e-46, 3.1658838545522830e-44, 3.4158346081733210e-42, 3.1009657171113824e-40, 2.3889887847651522e-38, 1.5738945493185839e-36, 8.9283867523289446e-35, 4.3884114191019410e-33, 1.8794344951812523e-31, 7.0495273821073143e-30, 2.3266903412110293e-28, 6.7861521642478146e-27, 1.7559922329924036e-25, 4.0458189399870260e-24, 8.3276681875539800e-23, 1.5360712580259943e-21, 2.5462929950511611e-20, 3.8033125448314512e-19, 5.1314188262140908e-18, 6.2679375130394878e-17, 6.9461573699177854e-16, 6.9976953274028973e-15, 6.4202984348233192e-14, 5.3739121421360399e-13, 4.1101386023109489e-12, 2.8767484176405797e-11, 1.8451534167067902e-10, 1.0859592046532814e-09, 5.8718148797495608e-09, 2.9201210196159125e-08, 1.3370799258052363e-07, 5.6424627677752911e-07, 2.1965028260725411e-06, 7.8943275081059988e-06, 2.6215639412143949e-05, 8.0497734201318759e-05, 2.2870525172954362e-04, 6.0159714197281571e-04, 1.4659454148941060e-03, 3.3108212147861167e-03, 6.9336514656727563e-03, 1.3470344826444706e-02, 2.4285561078700165e-02, 4.0645578943455961e-02, 6.3168189419948478e-02, 9.1182028088582376e-02, 1.2227380245007502e-01, 1.5234939813711931e-01, 1.7639383039152406e-01, 1.8979993309264909e-01, 1.8979993309264909e-01, 1.7639383039152406e-01, 1.5234939813711931e-01, 1.2227380245007502e-01, 9.1182028088582376e-02, 6.3168189419948478e-02, 4.0645578943455961e-02, 2.4285561078700165e-02, 1.3470344826444706e-02, 6.9336514656727563e-03, 3.3108212147861167e-03, 1.4659454148941060e-03, 6.0159714197281571e-04, 2.2870525172954362e-04, 8.0497734201318759e-05, 2.6215639412143949e-05, 7.8943275081059988e-06, 2.1965028260725411e-06, 5.6424627677752911e-07, 1.3370799258052363e-07, 2.9201210196159125e-08, 5.8718148797495608e-09, 1.0859592046532814e-09, 1.8451534167067902e-10, 2.8767484176405797e-11, 4.1101386023109489e-12, 5.3739121421360399e-13, 6.4202984348233192e-14, 6.9976953274028973e-15, 6.9461573699177854e-16, 6.2679375130394878e-17, 5.1314188262140908e-18, 3.8033125448314512e-19, 2.5462929950511611e-20, 1.5360712580259943e-21, 8.3276681875539800e-23, 4.0458189399870260e-24, 1.7559922329924036e-25, 6.7861521642478146e-27, 2.3266903412110293e-28, 7.0495273821073143e-30, 1.8794344951812523e-31, 4.3884114191019410e-33, 8.9283867523289446e-35, 1.5738945493185839e-36, 2.3889887847651522e-38, 3.1009657171113824e-40, 3.4158346081733210e-42, 3.1658838545522830e-44, 2.4451923543925048e-46, 1.5567833435482675e-48, 8.0698691825802516e-51, 3.3578943438527196e-53, 1.1033315179441334e-55, 2.8084445413684342e-58, 5.4140880882527221e-61, 7.6937052841722558e-64, 7.7987351892856256e-67, 5.4141833815112683e-70, 2.4452549463378667e-73, 6.7197562830108496e-77, 1.0268748980780725e-80, 7.6861123200181953e-85, 2.3293228753706694e-89, 2.0897891620152027e-94, 3.0548054158892936e-100, 1.5852022154122762e-107}, + {2.2757903447048717e-108, 4.5946784737513260e-101, 3.2685938252533535e-95, 3.7743169785683037e-90, 1.2871697383667851e-85, 1.7743864842451219e-81, 1.1966100169534770e-77, 4.4831207104684604e-74, 1.0212230702897007e-70, 1.5124472591580667e-67, 1.5333631698716670e-64, 1.1084367892237507e-61, 5.9044668946443965e-59, 2.3813770140907575e-56, 7.4386721348341212e-54, 1.8345006104189449e-51, 3.6310691969704462e-49, 5.8508598523019220e-47, 7.7706802795811407e-45, 8.5997500074472335e-43, 8.0073315846684445e-41, 6.3269186795493014e-39, 4.2749818807535224e-37, 2.4872103396508171e-35, 1.2538186619197742e-33, 5.5075144968159152e-32, 2.1188905321706446e-30, 7.1735092247885270e-29, 2.1463025081080465e-27, 5.6976909711813352e-26, 1.3468870756541617e-24, 2.8447276912580344e-23, 5.3848024996122255e-22, 9.1613793530553680e-21, 1.4046424779365027e-19, 1.9456017248888693e-18, 2.4401660157799310e-17, 2.7770723790106855e-16, 2.8735526657240152e-15, 2.7084363045358423e-14, 2.3293514464982674e-13, 1.8309133143528682e-12, 1.3172552368556761e-11, 8.6866283016645484e-11, 5.2575217351973056e-10, 2.9240918874514531e-09, 1.4961568756142573e-08, 7.0502109098437831e-08, 3.0626482923803324e-07, 1.2276189268114097e-06, 4.5443796787236290e-06, 1.5548071919772645e-05, 4.9202833580003181e-05, 1.4411581751672914e-04, 3.9094357332687408e-04, 9.8276091717415027e-04, 2.2905612451458858e-03, 4.9522684042317359e-03, 9.9362495542868867e-03, 1.8508238320820009e-02, 3.2017035703904927e-02, 5.1451871301553709e-02, 7.6831201307210703e-02, 1.0663137077642493e-01, 1.3756889121351917e-01, 1.6500723131965989e-01, 1.8402451115016699e-01, 1.9083751332645207e-01, 1.8402451115016699e-01, 1.6500723131965989e-01, 1.3756889121351917e-01, 1.0663137077642493e-01, 7.6831201307210703e-02, 5.1451871301553709e-02, 3.2017035703904927e-02, 1.8508238320820009e-02, 9.9362495542868867e-03, 4.9522684042317359e-03, 2.2905612451458858e-03, 9.8276091717415027e-04, 3.9094357332687408e-04, 1.4411581751672914e-04, 4.9202833580003181e-05, 1.5548071919772645e-05, 4.5443796787236290e-06, 1.2276189268114097e-06, 3.0626482923803324e-07, 7.0502109098437831e-08, 1.4961568756142573e-08, 2.9240918874514531e-09, 5.2575217351973056e-10, 8.6866283016645484e-11, 1.3172552368556761e-11, 1.8309133143528682e-12, 2.3293514464982674e-13, 2.7084363045358423e-14, 2.8735526657240152e-15, 2.7770723790106855e-16, 2.4401660157799310e-17, 1.9456017248888693e-18, 1.4046424779365027e-19, 9.1613793530553680e-21, 5.3848024996122255e-22, 2.8447276912580344e-23, 1.3468870756541617e-24, 5.6976909711813352e-26, 2.1463025081080465e-27, 7.1735092247885270e-29, 2.1188905321706446e-30, 5.5075144968159152e-32, 1.2538186619197742e-33, 2.4872103396508171e-35, 4.2749818807535224e-37, 6.3269186795493014e-39, 8.0073315846684445e-41, 8.5997500074472335e-43, 7.7706802795811407e-45, 5.8508598523019220e-47, 3.6310691969704462e-49, 1.8345006104189449e-51, 7.4386721348341212e-54, 2.3813770140907575e-56, 5.9044668946443965e-59, 1.1084367892237507e-61, 1.5333631698716670e-64, 1.5124472591580667e-67, 1.0212230702897007e-70, 4.4831207104684604e-74, 1.1966100169534770e-77, 1.7743864842451219e-81, 1.2871697383667851e-85, 3.7743169785683037e-90, 3.2685938252533535e-95, 4.5946784737513260e-101, 2.2757903447048717e-108}, + {3.2662778348790219e-109, 6.9071006009219448e-102, 5.1085629363787234e-96, 6.1100313027084669e-91, 2.1531900867437274e-86, 3.0621042209000059e-82, 2.1277376772398947e-78, 8.2059605065764682e-75, 1.9227730563170089e-71, 2.9274096096614171e-68, 3.0495045268798647e-65, 2.2641169845080718e-62, 1.2382980686348502e-59, 5.1263348642622049e-57, 1.6432629457353511e-54, 4.1579427709675079e-52, 8.4425869514003785e-50, 1.3953581486228228e-47, 1.9006681419175218e-45, 2.1571532321739302e-43, 2.0597137897723631e-41, 1.6688589526897371e-39, 1.1562775861404743e-37, 6.8982672254135044e-36, 3.5658879405329104e-34, 1.6062235506206207e-32, 6.3371488059404152e-31, 2.2002659780562692e-29, 6.7518197536098842e-28, 1.8384352926742758e-26, 4.4579796693281321e-25, 9.6593405936315995e-24, 1.8759587883105718e-22, 3.2750072247643929e-21, 5.1531219168800766e-20, 7.3260730719021186e-19, 9.4321973070076218e-18, 1.1021086847913827e-16, 1.1710396791414340e-15, 1.1336050130083279e-14, 1.0014937399406310e-13, 8.0878754293572482e-13, 5.9796723109076469e-12, 4.0531324359847441e-11, 2.5220174708373236e-10, 1.4423973477091834e-09, 7.5910433713044797e-09, 3.6801425167297173e-08, 1.6451664884983423e-07, 6.7880160807256645e-07, 2.5872670138074200e-06, 9.1170822839813128e-06, 2.9724333423383228e-05, 8.9724509010453385e-05, 2.5091729952798149e-04, 6.5046837318858926e-04, 1.5639824929501397e-03, 3.4894828544320858e-03, 7.2278157943492030e-03, 1.3904131095041473e-02, 2.4850005571417737e-02, 4.1275438102408031e-02, 6.3732095470061270e-02, 9.1501274267677846e-02, 1.2217500065832824e-01, 1.5173668408251911e-01, 1.7530801211052990e-01, 1.8842957463583779e-01, 1.8842957463583779e-01, 1.7530801211052990e-01, 1.5173668408251911e-01, 1.2217500065832824e-01, 9.1501274267677846e-02, 6.3732095470061270e-02, 4.1275438102408031e-02, 2.4850005571417737e-02, 1.3904131095041473e-02, 7.2278157943492030e-03, 3.4894828544320858e-03, 1.5639824929501397e-03, 6.5046837318858926e-04, 2.5091729952798149e-04, 8.9724509010453385e-05, 2.9724333423383228e-05, 9.1170822839813128e-06, 2.5872670138074200e-06, 6.7880160807256645e-07, 1.6451664884983423e-07, 3.6801425167297173e-08, 7.5910433713044797e-09, 1.4423973477091834e-09, 2.5220174708373236e-10, 4.0531324359847441e-11, 5.9796723109076469e-12, 8.0878754293572482e-13, 1.0014937399406310e-13, 1.1336050130083279e-14, 1.1710396791414340e-15, 1.1021086847913827e-16, 9.4321973070076218e-18, 7.3260730719021186e-19, 5.1531219168800766e-20, 3.2750072247643929e-21, 1.8759587883105718e-22, 9.6593405936315995e-24, 4.4579796693281321e-25, 1.8384352926742758e-26, 6.7518197536098842e-28, 2.2002659780562692e-29, 6.3371488059404152e-31, 1.6062235506206207e-32, 3.5658879405329104e-34, 6.8982672254135044e-36, 1.1562775861404743e-37, 1.6688589526897371e-39, 2.0597137897723631e-41, 2.1571532321739302e-43, 1.9006681419175218e-45, 1.3953581486228228e-47, 8.4425869514003785e-50, 4.1579427709675079e-52, 1.6432629457353511e-54, 5.1263348642622049e-57, 1.2382980686348502e-59, 2.2641169845080718e-62, 3.0495045268798647e-65, 2.9274096096614171e-68, 1.9227730563170089e-71, 8.2059605065764682e-75, 2.1277376772398947e-78, 3.0621042209000059e-82, 2.1531900867437274e-86, 6.1100313027084669e-91, 5.1085629363787234e-96, 6.9071006009219448e-102, 3.2662778348790219e-109}, + {4.6865023080529104e-110, 1.0377874004830612e-102, 7.9784749096307812e-97, 9.8821174227967692e-92, 3.5979287498244655e-87, 5.2776428357398472e-83, 3.7779666227111211e-79, 1.4996171154683470e-75, 3.6138115204304974e-72, 5.6551650475163530e-69, 6.0520249291763858e-66, 4.6142654439156290e-63, 2.5906808193011388e-60, 1.1006724998865391e-57, 3.6200846949796910e-55, 9.3965049756134747e-53, 1.9569075431422824e-50, 3.3168917267338703e-48, 4.6329566465533973e-46, 5.3914438385767737e-44, 5.2781068509974114e-42, 4.3845152623372787e-40, 3.1144817985274696e-38, 1.9049498787300406e-36, 1.0095682854224567e-34, 4.6623959142602483e-33, 1.8860299651335772e-31, 6.7143368715209606e-30, 2.1127537039024262e-28, 5.8994042231272372e-27, 1.4671212494779564e-25, 3.2605011152464131e-24, 6.4955255161731863e-23, 1.1633403477038459e-21, 1.8781142293296228e-20, 2.7399173517222677e-19, 3.6203893599581944e-18, 4.3421867882952047e-17, 4.7366003944880216e-16, 4.7080515903807368e-15, 4.2715858467937535e-14, 3.5433804833163948e-13, 2.6914605808295047e-12, 1.8746383733203776e-11, 1.1989016690827638e-10, 7.0489725875624514e-10, 3.8145955545353021e-09, 1.9020527069551235e-08, 8.7475726975743740e-08, 3.7140992001185702e-07, 1.4571432947497977e-06, 5.2867540339888927e-06, 1.7751862632560425e-05, 5.5204240789547246e-05, 1.5909525194144218e-04, 4.2516612395155680e-04, 1.0541825457525329e-03, 2.4263153829887293e-03, 5.1862282813377051e-03, 1.0299316731984193e-02, 1.9009837222668049e-02, 3.2621520059018146e-02, 5.2060779315091815e-02, 7.7286794858634558e-02, 1.0675261357345991e-01, 1.3721574664493244e-01, 1.6414915672894112e-01, 1.8277772077559612e-01, 1.8944453877662401e-01, 1.8277772077559612e-01, 1.6414915672894112e-01, 1.3721574664493244e-01, 1.0675261357345991e-01, 7.7286794858634558e-02, 5.2060779315091815e-02, 3.2621520059018146e-02, 1.9009837222668049e-02, 1.0299316731984193e-02, 5.1862282813377051e-03, 2.4263153829887293e-03, 1.0541825457525329e-03, 4.2516612395155680e-04, 1.5909525194144218e-04, 5.5204240789547246e-05, 1.7751862632560425e-05, 5.2867540339888927e-06, 1.4571432947497977e-06, 3.7140992001185702e-07, 8.7475726975743740e-08, 1.9020527069551235e-08, 3.8145955545353021e-09, 7.0489725875624514e-10, 1.1989016690827638e-10, 1.8746383733203776e-11, 2.6914605808295047e-12, 3.5433804833163948e-13, 4.2715858467937535e-14, 4.7080515903807368e-15, 4.7366003944880216e-16, 4.3421867882952047e-17, 3.6203893599581944e-18, 2.7399173517222677e-19, 1.8781142293296228e-20, 1.1633403477038459e-21, 6.4955255161731863e-23, 3.2605011152464131e-24, 1.4671212494779564e-25, 5.8994042231272372e-27, 2.1127537039024262e-28, 6.7143368715209606e-30, 1.8860299651335772e-31, 4.6623959142602483e-33, 1.0095682854224567e-34, 1.9049498787300406e-36, 3.1144817985274696e-38, 4.3845152623372787e-40, 5.2781068509974114e-42, 5.3914438385767737e-44, 4.6329566465533973e-46, 3.3168917267338703e-48, 1.9569075431422824e-50, 9.3965049756134747e-53, 3.6200846949796910e-55, 1.1006724998865391e-57, 2.5906808193011388e-60, 4.6142654439156290e-63, 6.0520249291763858e-66, 5.6551650475163530e-69, 3.6138115204304974e-72, 1.4996171154683470e-75, 3.7779666227111211e-79, 5.2776428357398472e-83, 3.5979287498244655e-87, 9.8821174227967692e-92, 7.9784749096307812e-97, 1.0377874004830612e-102, 4.6865023080529104e-110}, + {6.7223469064836171e-111, 1.5584604318709814e-103, 1.2451690475064742e-97, 1.5968463027613036e-92, 6.0055451530824495e-88, 9.0848000543271587e-84, 6.6985500695669678e-80, 2.7361658102621640e-76, 6.7802095889475983e-73, 1.0903770909317098e-69, 1.1985921850382964e-66, 9.3828601952142795e-64, 5.4070585225542087e-61, 2.3572025385780174e-58, 7.9532902157128368e-56, 2.1173804777066541e-53, 4.5220720973223149e-51, 7.8591635665593126e-49, 1.1254750686853198e-46, 1.3427041430602204e-44, 1.3474889050314146e-42, 1.1474212047422846e-40, 8.3547107388260308e-39, 5.2380609435106477e-37, 2.8455586990614318e-35, 1.3470860626931207e-33, 5.5860425698193572e-32, 2.0386781124262974e-30, 6.5767258559351848e-29, 1.8828451569167714e-27, 4.8012341582972026e-26, 1.0941854437188646e-24, 2.2355486477720061e-23, 4.1066490153458769e-22, 6.8008865930090286e-21, 1.0178867789337611e-19, 1.3800519281469149e-18, 1.6985968059071478e-17, 1.9017680123139647e-16, 1.9404932122013048e-15, 1.8076531130346059e-14, 1.5398466784483034e-13, 1.2013344715990716e-12, 8.5959906732140100e-12, 5.6487797699597178e-11, 3.4133713929443775e-10, 1.8988505331522261e-09, 9.7353434088062900e-09, 4.6047775382709491e-08, 2.0113005931537178e-07, 8.1197441052941798e-07, 3.0322448415500775e-06, 1.0482793298607957e-05, 3.3573050144199230e-05, 9.9676496285740638e-05, 2.7450358985306201e-04, 7.0161767403489428e-04, 1.6652282490644866e-03, 3.6717374087279781e-03, 7.5245206122160650e-03, 1.4337113630217399e-02, 2.5407889466847185e-02, 4.1891912442268933e-02, 6.4277668190634463e-02, 9.1802633810630571e-02, 1.2206621940114575e-01, 1.5112804960523191e-01, 1.7424152504403007e-01, 1.8708847054904945e-01, 1.8708847054904945e-01, 1.7424152504403007e-01, 1.5112804960523191e-01, 1.2206621940114575e-01, 9.1802633810630571e-02, 6.4277668190634463e-02, 4.1891912442268933e-02, 2.5407889466847185e-02, 1.4337113630217399e-02, 7.5245206122160650e-03, 3.6717374087279781e-03, 1.6652282490644866e-03, 7.0161767403489428e-04, 2.7450358985306201e-04, 9.9676496285740638e-05, 3.3573050144199230e-05, 1.0482793298607957e-05, 3.0322448415500775e-06, 8.1197441052941798e-07, 2.0113005931537178e-07, 4.6047775382709491e-08, 9.7353434088062900e-09, 1.8988505331522261e-09, 3.4133713929443775e-10, 5.6487797699597178e-11, 8.5959906732140100e-12, 1.2013344715990716e-12, 1.5398466784483034e-13, 1.8076531130346059e-14, 1.9404932122013048e-15, 1.9017680123139647e-16, 1.6985968059071478e-17, 1.3800519281469149e-18, 1.0178867789337611e-19, 6.8008865930090286e-21, 4.1066490153458769e-22, 2.2355486477720061e-23, 1.0941854437188646e-24, 4.8012341582972026e-26, 1.8828451569167714e-27, 6.5767258559351848e-29, 2.0386781124262974e-30, 5.5860425698193572e-32, 1.3470860626931207e-33, 2.8455586990614318e-35, 5.2380609435106477e-37, 8.3547107388260308e-39, 1.1474212047422846e-40, 1.3474889050314146e-42, 1.3427041430602204e-44, 1.1254750686853198e-46, 7.8591635665593126e-49, 4.5220720973223149e-51, 2.1173804777066541e-53, 7.9532902157128368e-56, 2.3572025385780174e-58, 5.4070585225542087e-61, 9.3828601952142795e-64, 1.1985921850382964e-66, 1.0903770909317098e-69, 6.7802095889475983e-73, 2.7361658102621640e-76, 6.6985500695669678e-80, 9.0848000543271587e-84, 6.0055451530824495e-88, 1.5968463027613036e-92, 1.2451690475064742e-97, 1.5584604318709814e-103, 6.7223469064836171e-111}, + {9.6398630558977581e-112, 2.3391641752283700e-104, 1.9419047430148712e-98, 2.5780282869707508e-93, 1.0013546946979084e-88, 1.5618992863642802e-84, 1.1860256149765069e-80, 4.9845319901386102e-77, 1.2699036539452659e-73, 2.0984019099670130e-70, 2.3689362034001624e-67, 1.9037493843202249e-64, 1.1258502033609599e-61, 5.0354502440866812e-59, 1.7426389319046294e-56, 4.7576590995159999e-54, 1.0418263136743596e-51, 1.8562658771588515e-49, 2.7249577678833700e-47, 3.3321800978024594e-45, 3.4274481444478336e-43, 2.9912154191216358e-41, 2.2321555171303588e-39, 1.4342596614707723e-37, 7.9853025164866527e-36, 3.8743074669761106e-34, 1.6466139693318358e-32, 6.1594817750585881e-31, 2.0367481580156025e-29, 5.9772735819833118e-28, 1.5625565508848433e-26, 3.6509499167114885e-25, 7.6484446772058021e-24, 1.4407768646001281e-22, 2.4470614433838565e-21, 3.7566695291667047e-20, 5.2249355965739373e-19, 6.5981079437776417e-18, 7.5804607661939761e-17, 7.9383130347919212e-16, 7.5907028620400909e-15, 6.6385260183760165e-14, 5.3182112719426004e-13, 3.9083095195736355e-12, 2.6383151459347353e-11, 1.6380456665860958e-10, 9.3648087516475362e-10, 4.9354207551905105e-09, 2.4002106969319454e-08, 1.0781831043581527e-07, 4.4775845772911881e-07, 1.7205483203483572e-06, 6.1220977817639379e-06, 2.0186382119025494e-05, 6.1721031633452369e-05, 1.7510316724439029e-04, 4.6120030826672870e-04, 1.1283616065624156e-03, 2.5655409728187234e-03, 5.4233979404253157e-03, 1.0663442942343464e-02, 1.9507907091601058e-02, 3.3216020285214413e-02, 5.2653553807060320e-02, 7.7723764833089265e-02, 1.0685936247311774e-01, 1.3685933683570478e-01, 1.6330294257556086e-01, 1.8155584069555794e-01, 1.8808162842571305e-01, 1.8155584069555794e-01, 1.6330294257556086e-01, 1.3685933683570478e-01, 1.0685936247311774e-01, 7.7723764833089265e-02, 5.2653553807060320e-02, 3.3216020285214413e-02, 1.9507907091601058e-02, 1.0663442942343464e-02, 5.4233979404253157e-03, 2.5655409728187234e-03, 1.1283616065624156e-03, 4.6120030826672870e-04, 1.7510316724439029e-04, 6.1721031633452369e-05, 2.0186382119025494e-05, 6.1220977817639379e-06, 1.7205483203483572e-06, 4.4775845772911881e-07, 1.0781831043581527e-07, 2.4002106969319454e-08, 4.9354207551905105e-09, 9.3648087516475362e-10, 1.6380456665860958e-10, 2.6383151459347353e-11, 3.9083095195736355e-12, 5.3182112719426004e-13, 6.6385260183760165e-14, 7.5907028620400909e-15, 7.9383130347919212e-16, 7.5804607661939761e-17, 6.5981079437776417e-18, 5.2249355965739373e-19, 3.7566695291667047e-20, 2.4470614433838565e-21, 1.4407768646001281e-22, 7.6484446772058021e-24, 3.6509499167114885e-25, 1.5625565508848433e-26, 5.9772735819833118e-28, 2.0367481580156025e-29, 6.1594817750585881e-31, 1.6466139693318358e-32, 3.8743074669761106e-34, 7.9853025164866527e-36, 1.4342596614707723e-37, 2.2321555171303588e-39, 2.9912154191216358e-41, 3.4274481444478336e-43, 3.3321800978024594e-45, 2.7249577678833700e-47, 1.8562658771588515e-49, 1.0418263136743596e-51, 4.7576590995159999e-54, 1.7426389319046294e-56, 5.0354502440866812e-59, 1.1258502033609599e-61, 1.9037493843202249e-64, 2.3689362034001624e-67, 2.0984019099670130e-70, 1.2699036539452659e-73, 4.9845319901386102e-77, 1.1860256149765069e-80, 1.5618992863642802e-84, 1.0013546946979084e-88, 2.5780282869707508e-93, 1.9419047430148712e-98, 2.3391641752283700e-104, 9.6398630558977581e-112}, + {1.3819748652176074e-112, 3.5091818441132373e-105, 3.0263733342631031e-99, 4.1584216000446123e-94, 1.6678802978259982e-89, 2.6820059816501053e-85, 2.0970348613054561e-81, 9.0664032095201726e-78, 2.3744232682771987e-74, 4.0308051146214329e-71, 4.6725947222676983e-68, 3.8542403780632908e-65, 2.3387627697862867e-62, 1.0729932979377662e-59, 3.8081687860913558e-57, 1.0660224990923822e-54, 2.3931046396310541e-52, 4.3706076964057967e-50, 6.5758217028615195e-48, 8.2408262629145279e-46, 8.6863577038588966e-44, 7.7681876124982396e-42, 5.9400458445057631e-40, 3.9109426504580767e-38, 2.2311802993712928e-36, 1.1092621876592673e-34, 4.8310493095269011e-33, 1.8519160989732117e-31, 6.2757371777744156e-30, 1.8875929093999227e-28, 5.0576726716251256e-27, 1.2113423787195963e-25, 2.6014811007021294e-24, 5.0242965481154138e-23, 8.7498945768853231e-22, 1.3775031653677140e-20, 1.9649805509896429e-19, 2.5453305256296733e-18, 3.0000691187992888e-17, 3.2236051617172698e-16, 3.1633284490034087e-15, 2.8395986506952882e-14, 2.3353492711597277e-13, 1.7622103628998908e-12, 1.2216962997815707e-11, 7.7914682997538544e-11, 4.5765854976073951e-10, 2.4786353105487376e-09, 1.2390357485809571e-08, 5.7223858055497259e-08, 2.4439179961675454e-07, 9.6600646013167157e-07, 3.5367142158469601e-06, 1.2002319438047467e-05, 3.7780839366269368e-05, 1.1038074912944360e-04, 2.9949084760834345e-04, 7.5504927141389195e-04, 1.7696288232331070e-03, 3.8574393750280067e-03, 7.8235307009575233e-03, 1.4769041560724656e-02, 2.5959097306055404e-02, 4.2495188992312062e-02, 6.4805460287971808e-02, 9.2086877576565612e-02, 1.2194809856528342e-01, 1.5052362288934179e-01, 1.7319382084353874e-01, 1.8577559474964558e-01, 1.8577559474964558e-01, 1.7319382084353874e-01, 1.5052362288934179e-01, 1.2194809856528342e-01, 9.2086877576565612e-02, 6.4805460287971808e-02, 4.2495188992312062e-02, 2.5959097306055404e-02, 1.4769041560724656e-02, 7.8235307009575233e-03, 3.8574393750280067e-03, 1.7696288232331070e-03, 7.5504927141389195e-04, 2.9949084760834345e-04, 1.1038074912944360e-04, 3.7780839366269368e-05, 1.2002319438047467e-05, 3.5367142158469601e-06, 9.6600646013167157e-07, 2.4439179961675454e-07, 5.7223858055497259e-08, 1.2390357485809571e-08, 2.4786353105487376e-09, 4.5765854976073951e-10, 7.7914682997538544e-11, 1.2216962997815707e-11, 1.7622103628998908e-12, 2.3353492711597277e-13, 2.8395986506952882e-14, 3.1633284490034087e-15, 3.2236051617172698e-16, 3.0000691187992888e-17, 2.5453305256296733e-18, 1.9649805509896429e-19, 1.3775031653677140e-20, 8.7498945768853231e-22, 5.0242965481154138e-23, 2.6014811007021294e-24, 1.2113423787195963e-25, 5.0576726716251256e-27, 1.8875929093999227e-28, 6.2757371777744156e-30, 1.8519160989732117e-31, 4.8310493095269011e-33, 1.1092621876592673e-34, 2.2311802993712928e-36, 3.9109426504580767e-38, 5.9400458445057631e-40, 7.7681876124982396e-42, 8.6863577038588966e-44, 8.2408262629145279e-46, 6.5758217028615195e-48, 4.3706076964057967e-50, 2.3931046396310541e-52, 1.0660224990923822e-54, 3.8081687860913558e-57, 1.0729932979377662e-59, 2.3387627697862867e-62, 3.8542403780632908e-65, 4.6725947222676983e-68, 4.0308051146214329e-71, 2.3744232682771987e-74, 9.0664032095201726e-78, 2.0970348613054561e-81, 2.6820059816501053e-85, 1.6678802978259982e-89, 4.1584216000446123e-94, 3.0263733342631031e-99, 3.5091818441132373e-105, 1.3819748652176074e-112}, + {1.9806611743021416e-113, 5.2617952692292333e-106, 4.7131990325935266e-100, 6.7017830703194019e-95, 2.7751659416516980e-90, 4.5998341384092458e-86, 3.7027394072850406e-82, 1.6465801492558192e-78, 4.4321525706156201e-75, 7.7285235953959866e-72, 9.1980779235827154e-69, 7.7863635474467061e-66, 4.8472018976182706e-63, 2.2808008160100623e-60, 8.3001996570148669e-58, 2.3819600570060440e-55, 5.4809275321322830e-53, 1.0258876994968507e-50, 1.5817079781846762e-48, 2.0310845466149993e-46, 2.1935503204230003e-44, 2.0098426331457899e-42, 1.5745331638769155e-40, 1.0620797611432563e-38, 6.2076082159887624e-37, 3.1618692048946272e-35, 1.4108563317113768e-33, 5.5412911024876112e-32, 1.9240852596678829e-30, 5.9301271167711558e-29, 1.6282950449666844e-27, 3.9967858207858083e-26, 8.7976197776883766e-25, 1.7416595619626179e-23, 3.1094324529576228e-22, 5.0189377569399244e-21, 7.3412947992638873e-20, 9.7524056424221390e-19, 1.1789993455088293e-17, 1.2995830094215584e-16, 1.3084437330245737e-15, 1.2052816831862512e-14, 1.0173726615206055e-13, 7.8806482946078899e-13, 5.6095283428337204e-12, 3.6739040139866195e-11, 2.2165913480620041e-10, 1.2333492148378478e-09, 6.3355479710981103e-09, 3.0075005874343488e-08, 1.3205310627276386e-07, 5.3676540058539977e-07, 2.0214361392302868e-06, 7.0582654033955854e-06, 2.2866437400066508e-05, 6.8776486666748005e-05, 1.9216752502494505e-04, 4.9906383375612176e-04, 1.2052761990741546e-03, 2.7081400657517538e-03, 5.6635846018365278e-03, 1.1028376452466447e-02, 2.0002251583713944e-02, 3.3800561758698749e-02, 5.3230566834836512e-02, 7.8142792739003333e-02, 1.0695235327964076e-01, 1.3650006936059866e-01, 1.6246837812900003e-01, 1.8035805565273866e-01, 1.8674771616737459e-01, 1.8035805565273866e-01, 1.6246837812900003e-01, 1.3650006936059866e-01, 1.0695235327964076e-01, 7.8142792739003333e-02, 5.3230566834836512e-02, 3.3800561758698749e-02, 2.0002251583713944e-02, 1.1028376452466447e-02, 5.6635846018365278e-03, 2.7081400657517538e-03, 1.2052761990741546e-03, 4.9906383375612176e-04, 1.9216752502494505e-04, 6.8776486666748005e-05, 2.2866437400066508e-05, 7.0582654033955854e-06, 2.0214361392302868e-06, 5.3676540058539977e-07, 1.3205310627276386e-07, 3.0075005874343488e-08, 6.3355479710981103e-09, 1.2333492148378478e-09, 2.2165913480620041e-10, 3.6739040139866195e-11, 5.6095283428337204e-12, 7.8806482946078899e-13, 1.0173726615206055e-13, 1.2052816831862512e-14, 1.3084437330245737e-15, 1.2995830094215584e-16, 1.1789993455088293e-17, 9.7524056424221390e-19, 7.3412947992638873e-20, 5.0189377569399244e-21, 3.1094324529576228e-22, 1.7416595619626179e-23, 8.7976197776883766e-25, 3.9967858207858083e-26, 1.6282950449666844e-27, 5.9301271167711558e-29, 1.9240852596678829e-30, 5.5412911024876112e-32, 1.4108563317113768e-33, 3.1618692048946272e-35, 6.2076082159887624e-37, 1.0620797611432563e-38, 1.5745331638769155e-40, 2.0098426331457899e-42, 2.1935503204230003e-44, 2.0310845466149993e-46, 1.5817079781846762e-48, 1.0258876994968507e-50, 5.4809275321322830e-53, 2.3819600570060440e-55, 8.3001996570148669e-58, 2.2808008160100623e-60, 4.8472018976182706e-63, 7.7863635474467061e-66, 9.1980779235827154e-69, 7.7285235953959866e-72, 4.4321525706156201e-75, 1.6465801492558192e-78, 3.7027394072850406e-82, 4.5998341384092458e-86, 2.7751659416516980e-90, 6.7017830703194019e-95, 4.7131990325935266e-100, 5.2617952692292333e-106, 1.9806611743021416e-113}, + {2.8379348362554196e-114, 7.8858321167381958e-107, 7.3351907294176643e-101, 1.0791401722330717e-95, 4.6128120689561502e-91, 7.8796483529297319e-87, 6.5291103196563761e-83, 2.9859071017101074e-79, 8.2594238150373050e-76, 1.4791530184295327e-72, 1.8070968918430098e-69, 1.5696742395566467e-66, 1.0023248619238131e-63, 4.8364134393087594e-61, 1.8044278404363096e-58, 5.3077896463877236e-56, 1.2516691340073944e-53, 2.4006692740362835e-51, 3.7923450617699092e-49, 4.9890808610628276e-47, 5.5197834921993867e-45, 5.1808064286331934e-43, 4.1575196368970433e-41, 2.8726311560209485e-39, 1.7198340431536187e-37, 8.9732693547519472e-36, 4.1015179356507749e-34, 1.6502257188992863e-32, 5.8701285325766118e-31, 1.8535450041434515e-29, 5.2145562564115323e-28, 1.3115164390064590e-26, 2.9583134344508206e-25, 6.0020532911752611e-24, 1.0982988908956421e-22, 1.8172013379429154e-21, 2.7250115798124682e-20, 3.7116593876307894e-19, 4.6014038935013638e-18, 5.2019302408782819e-17, 5.3723712748625257e-16, 5.0771526984812688e-15, 4.3975029340499356e-14, 3.4959048726655372e-13, 2.5543256450392521e-12, 1.7175688761100677e-11, 1.0641335972971535e-10, 6.0815188314211019e-10, 3.2093758879421831e-09, 1.5654930566151192e-08, 7.0648903615829459e-08, 2.9522889815634413e-07, 1.1433046682221214e-06, 4.1062137791532273e-06, 1.3686795544658825e-05, 4.2366755055396916e-05, 1.2186350361528871e-04, 3.2590355495495157e-04, 8.1076372459361551e-04, 1.8771268090367514e-03, 4.0464432735401257e-03, 8.1246183048277309e-03, 1.5199679576417248e-02, 2.6503531097710236e-02, 4.3085461690763743e-02, 6.5316009514185674e-02, 9.2354740298272661e-02, 1.2182123832712786e-01, 1.4992351472225099e-01, 1.7216437167539980e-01, 1.8448997083421120e-01, 1.8448997083421120e-01, 1.7216437167539980e-01, 1.4992351472225099e-01, 1.2182123832712786e-01, 9.2354740298272661e-02, 6.5316009514185674e-02, 4.3085461690763743e-02, 2.6503531097710236e-02, 1.5199679576417248e-02, 8.1246183048277309e-03, 4.0464432735401257e-03, 1.8771268090367514e-03, 8.1076372459361551e-04, 3.2590355495495157e-04, 1.2186350361528871e-04, 4.2366755055396916e-05, 1.3686795544658825e-05, 4.1062137791532273e-06, 1.1433046682221214e-06, 2.9522889815634413e-07, 7.0648903615829459e-08, 1.5654930566151192e-08, 3.2093758879421831e-09, 6.0815188314211019e-10, 1.0641335972971535e-10, 1.7175688761100677e-11, 2.5543256450392521e-12, 3.4959048726655372e-13, 4.3975029340499356e-14, 5.0771526984812688e-15, 5.3723712748625257e-16, 5.2019302408782819e-17, 4.6014038935013638e-18, 3.7116593876307894e-19, 2.7250115798124682e-20, 1.8172013379429154e-21, 1.0982988908956421e-22, 6.0020532911752611e-24, 2.9583134344508206e-25, 1.3115164390064590e-26, 5.2145562564115323e-28, 1.8535450041434515e-29, 5.8701285325766118e-31, 1.6502257188992863e-32, 4.1015179356507749e-34, 8.9732693547519472e-36, 1.7198340431536187e-37, 2.8726311560209485e-39, 4.1575196368970433e-41, 5.1808064286331934e-43, 5.5197834921993867e-45, 4.9890808610628276e-47, 3.7923450617699092e-49, 2.4006692740362835e-51, 1.2516691340073944e-53, 5.3077896463877236e-56, 1.8044278404363096e-58, 4.8364134393087594e-61, 1.0023248619238131e-63, 1.5696742395566467e-66, 1.8070968918430098e-69, 1.4791530184295327e-72, 8.2594238150373050e-76, 2.9859071017101074e-79, 6.5291103196563761e-83, 7.8796483529297319e-87, 4.6128120689561502e-91, 1.0791401722330717e-95, 7.3351907294176643e-101, 7.8858321167381958e-107, 2.8379348362554196e-114}, + {4.0651653045385065e-115, 1.1812699945481087e-107, 1.1408091037467098e-101, 1.7361831916251206e-96, 7.6595061701919539e-92, 1.3482180200386414e-87, 1.1497555722475321e-83, 5.4065905193630812e-80, 1.5366409186618650e-76, 2.8258657002435720e-73, 3.5434157687072630e-70, 3.1577316852342737e-67, 2.0680029879339054e-64, 1.0231020536481417e-61, 3.9127659587819162e-59, 1.1795593319147925e-56, 2.8502626581292134e-54, 5.6008912228881934e-52, 9.0638661704615042e-50, 1.2214291755276681e-47, 1.3841464531877442e-45, 1.3306007915064349e-43, 1.0936052280580312e-41, 7.7388088770231391e-40, 4.7451186753733802e-38, 2.5356047070173512e-36, 1.1870121009809329e-34, 4.8915667031805749e-33, 1.7822371990214424e-31, 5.7644513660319519e-30, 1.6612582615477246e-28, 4.2804618347791540e-27, 9.8922322140449142e-26, 2.0564738212957134e-24, 3.8562115828650105e-23, 6.5389458924467930e-22, 1.0050517825377878e-20, 1.4033245536407663e-19, 1.7836445099325982e-18, 2.0676254282785005e-17, 2.1899168813282935e-16, 2.1227770911527276e-15, 1.8861860904057362e-14, 1.5385347856793465e-13, 1.1536439246054796e-12, 7.9623160515403962e-12, 5.0644993569234348e-11, 2.9720520664121096e-10, 1.6108731738857700e-09, 8.0720587699486656e-09, 3.7430932220185756e-08, 1.6076054796089227e-07, 6.4000756781336375e-07, 2.3636229043243477e-06, 8.1033917859954005e-06, 2.5807006976135383e-05, 7.6393528572820399e-05, 2.1031479179566012e-04, 5.3877140763670364e-04, 1.2849006257472789e-03, 2.8540126420656033e-03, 5.9065989999834033e-03, 1.1393877212953164e-02, 2.0492691616955331e-02, 3.4375183073736520e-02, 5.3792186966533914e-02, 7.8544533849893697e-02, 1.0703228204562122e-01, 1.3613832142377319e-01, 1.6164525387078738e-01, 1.7918358709477061e-01, 1.8544178808228795e-01, 1.7918358709477061e-01, 1.6164525387078738e-01, 1.3613832142377319e-01, 1.0703228204562122e-01, 7.8544533849893697e-02, 5.3792186966533914e-02, 3.4375183073736520e-02, 2.0492691616955331e-02, 1.1393877212953164e-02, 5.9065989999834033e-03, 2.8540126420656033e-03, 1.2849006257472789e-03, 5.3877140763670364e-04, 2.1031479179566012e-04, 7.6393528572820399e-05, 2.5807006976135383e-05, 8.1033917859954005e-06, 2.3636229043243477e-06, 6.4000756781336375e-07, 1.6076054796089227e-07, 3.7430932220185756e-08, 8.0720587699486656e-09, 1.6108731738857700e-09, 2.9720520664121096e-10, 5.0644993569234348e-11, 7.9623160515403962e-12, 1.1536439246054796e-12, 1.5385347856793465e-13, 1.8861860904057362e-14, 2.1227770911527276e-15, 2.1899168813282935e-16, 2.0676254282785005e-17, 1.7836445099325982e-18, 1.4033245536407663e-19, 1.0050517825377878e-20, 6.5389458924467930e-22, 3.8562115828650105e-23, 2.0564738212957134e-24, 9.8922322140449142e-26, 4.2804618347791540e-27, 1.6612582615477246e-28, 5.7644513660319519e-30, 1.7822371990214424e-31, 4.8915667031805749e-33, 1.1870121009809329e-34, 2.5356047070173512e-36, 4.7451186753733802e-38, 7.7388088770231391e-40, 1.0936052280580312e-41, 1.3306007915064349e-43, 1.3841464531877442e-45, 1.2214291755276681e-47, 9.0638661704615042e-50, 5.6008912228881934e-52, 2.8502626581292134e-54, 1.1795593319147925e-56, 3.9127659587819162e-59, 1.0231020536481417e-61, 2.0680029879339054e-64, 3.1577316852342737e-67, 3.5434157687072630e-70, 2.8258657002435720e-73, 1.5366409186618650e-76, 5.4065905193630812e-80, 1.1497555722475321e-83, 1.3482180200386414e-87, 7.6595061701919539e-92, 1.7361831916251206e-96, 1.1408091037467098e-101, 1.1812699945481087e-107, 4.0651653045385065e-115}, + {5.8215540266145185e-116, 1.7686479321265132e-108, 1.7730623068856681e-102, 2.7909232189455364e-97, 1.2705722231489315e-92, 2.3041370774073117e-88, 2.0220172247445533e-84, 9.7753535494291230e-81, 2.8542469937135876e-77, 5.3891664187060082e-74, 6.9347342664174447e-71, 6.3393303649456501e-68, 4.2572743226051364e-65, 2.1591730776951801e-62, 8.4632278622572117e-60, 2.6143765867593842e-57, 6.4722677680216748e-55, 1.3028416632725528e-52, 2.1595419825453231e-50, 2.9805109745607960e-48, 3.4589808905752308e-46, 3.4051398010375247e-44, 2.8658496493850430e-42, 2.0766525261834300e-40, 1.3038602059242759e-38, 7.1344872719593792e-37, 3.4201248592076866e-35, 1.4432903376167608e-33, 5.3852783517497647e-32, 1.7838570362707828e-30, 5.2653274547677795e-29, 1.3896193908215000e-27, 3.2896623243386845e-26, 7.0060070837042623e-25, 1.3459870964148325e-23, 2.3386559482775554e-22, 3.6836215601895347e-21, 5.2713950568645777e-20, 6.8677255495973648e-19, 8.1615638298029365e-18, 8.8631701623207850e-17, 8.8103300045560730e-16, 8.0291277303592449e-15, 6.7183131113433536e-14, 5.1685673461842002e-13, 3.6606905840155156e-12, 2.3898379902347417e-11, 1.4397371489675669e-10, 8.0125910717950545e-10, 4.1235783120777111e-09, 1.9642460747885040e-08, 8.6680352990322611e-08, 3.5465537239549829e-07, 1.3464428002356888e-06, 4.7465352780258519e-06, 1.5547603684619328e-05, 4.7349798947666790e-05, 1.3415011473384580e-04, 3.5376394702118597e-04, 8.6875807961727194e-04, 1.9876616088445901e-03, 4.2386040557315851e-03, 8.4275632150598145e-03, 1.5628807300276451e-02, 2.7041109022394049e-02, 4.3662930188759774e-02, 6.5809838711917215e-02, 9.2606922401635969e-02, 1.2168620186278144e-01, 1.4932782014181728e-01, 1.7115266931753381e-01, 1.8323066902877375e-01, 1.8323066902877375e-01, 1.7115266931753381e-01, 1.4932782014181728e-01, 1.2168620186278144e-01, 9.2606922401635969e-02, 6.5809838711917215e-02, 4.3662930188759774e-02, 2.7041109022394049e-02, 1.5628807300276451e-02, 8.4275632150598145e-03, 4.2386040557315851e-03, 1.9876616088445901e-03, 8.6875807961727194e-04, 3.5376394702118597e-04, 1.3415011473384580e-04, 4.7349798947666790e-05, 1.5547603684619328e-05, 4.7465352780258519e-06, 1.3464428002356888e-06, 3.5465537239549829e-07, 8.6680352990322611e-08, 1.9642460747885040e-08, 4.1235783120777111e-09, 8.0125910717950545e-10, 1.4397371489675669e-10, 2.3898379902347417e-11, 3.6606905840155156e-12, 5.1685673461842002e-13, 6.7183131113433536e-14, 8.0291277303592449e-15, 8.8103300045560730e-16, 8.8631701623207850e-17, 8.1615638298029365e-18, 6.8677255495973648e-19, 5.2713950568645777e-20, 3.6836215601895347e-21, 2.3386559482775554e-22, 1.3459870964148325e-23, 7.0060070837042623e-25, 3.2896623243386845e-26, 1.3896193908215000e-27, 5.2653274547677795e-29, 1.7838570362707828e-30, 5.3852783517497647e-32, 1.4432903376167608e-33, 3.4201248592076866e-35, 7.1344872719593792e-37, 1.3038602059242759e-38, 2.0766525261834300e-40, 2.8658496493850430e-42, 3.4051398010375247e-44, 3.4589808905752308e-46, 2.9805109745607960e-48, 2.1595419825453231e-50, 1.3028416632725528e-52, 6.4722677680216748e-55, 2.6143765867593842e-57, 8.4632278622572117e-60, 2.1591730776951801e-62, 4.2572743226051364e-65, 6.3393303649456501e-68, 6.9347342664174447e-71, 5.3891664187060082e-74, 2.8542469937135876e-77, 9.7753535494291230e-81, 2.0220172247445533e-84, 2.3041370774073117e-88, 1.2705722231489315e-92, 2.7909232189455364e-97, 1.7730623068856681e-102, 1.7686479321265132e-108, 5.8215540266145185e-116}, + {8.3346219931731252e-117, 2.6468336179684675e-109, 2.7538984203799183e-103, 4.4826957080916534e-98, 2.1055559670183425e-93, 3.9333042153463284e-89, 3.5513952096001502e-85, 1.7648636462384819e-81, 5.2931716200065506e-78, 1.0259659682881671e-74, 1.3546124768341285e-71, 1.2700634063455813e-68, 8.7450484044987438e-66, 4.5461329246587614e-63, 1.8260394178147789e-60, 5.7792816013390868e-58, 1.4656166079834788e-55, 3.0217106412347761e-53, 5.1294451668154943e-51, 7.2494810877533628e-49, 8.6147071643386152e-47, 8.6832052790729524e-45, 7.4822992810294955e-43, 5.5510153038363309e-41, 3.5683132140145833e-39, 1.9990336800405551e-37, 9.8114235481332920e-36, 4.2392471038699379e-34, 1.6195898700068922e-32, 5.4933861932302487e-31, 1.6604056318842839e-29, 4.4876913417614677e-28, 1.0880533660044361e-26, 2.3734409390889848e-25, 4.6708788240159748e-24, 8.3141586271431848e-23, 1.3417423881673005e-21, 1.9674928839115667e-20, 2.6269310713002712e-19, 3.1997441855901569e-18, 3.5620366003569210e-17, 3.6302240823037884e-16, 3.3924183801506980e-15, 2.9112006503092275e-14, 2.2973505987627707e-13, 1.6693328537504025e-12, 1.1182840247910251e-11, 6.9144057864820654e-11, 3.9502105053420148e-10, 2.0873156939372195e-09, 1.0211061576622443e-08, 4.6286545842406255e-08, 1.9458139349161944e-07, 7.5918662435991949e-07, 2.7511365949804849e-06, 9.2658749369498393e-06, 2.9023198119388909e-05, 8.4594658849625380e-05, 2.2956989796967087e-04, 5.8033480492528523e-04, 1.3672056490331354e-03, 3.0030570133818706e-03, 6.1522556633449429e-03, 1.1759716605478240e-02, 2.0979064379787655e-02, 3.4939934715514299e-02, 5.4338778627529040e-02, 7.8929618144152600e-02, 1.0709980745724954e-01, 1.3577444219071524e-01, 1.6083336191837752e-01, 1.7803169108709616e-01, 1.8416287919896177e-01, 1.7803169108709616e-01, 1.6083336191837752e-01, 1.3577444219071524e-01, 1.0709980745724954e-01, 7.8929618144152600e-02, 5.4338778627529040e-02, 3.4939934715514299e-02, 2.0979064379787655e-02, 1.1759716605478240e-02, 6.1522556633449429e-03, 3.0030570133818706e-03, 1.3672056490331354e-03, 5.8033480492528523e-04, 2.2956989796967087e-04, 8.4594658849625380e-05, 2.9023198119388909e-05, 9.2658749369498393e-06, 2.7511365949804849e-06, 7.5918662435991949e-07, 1.9458139349161944e-07, 4.6286545842406255e-08, 1.0211061576622443e-08, 2.0873156939372195e-09, 3.9502105053420148e-10, 6.9144057864820654e-11, 1.1182840247910251e-11, 1.6693328537504025e-12, 2.2973505987627707e-13, 2.9112006503092275e-14, 3.3924183801506980e-15, 3.6302240823037884e-16, 3.5620366003569210e-17, 3.1997441855901569e-18, 2.6269310713002712e-19, 1.9674928839115667e-20, 1.3417423881673005e-21, 8.3141586271431848e-23, 4.6708788240159748e-24, 2.3734409390889848e-25, 1.0880533660044361e-26, 4.4876913417614677e-28, 1.6604056318842839e-29, 5.4933861932302487e-31, 1.6195898700068922e-32, 4.2392471038699379e-34, 9.8114235481332920e-36, 1.9990336800405551e-37, 3.5683132140145833e-39, 5.5510153038363309e-41, 7.4822992810294955e-43, 8.6832052790729524e-45, 8.6147071643386152e-47, 7.2494810877533628e-49, 5.1294451668154943e-51, 3.0217106412347761e-53, 1.4656166079834788e-55, 5.7792816013390868e-58, 1.8260394178147789e-60, 4.5461329246587614e-63, 8.7450484044987438e-66, 1.2700634063455813e-68, 1.3546124768341285e-71, 1.0259659682881671e-74, 5.2931716200065506e-78, 1.7648636462384819e-81, 3.5513952096001502e-85, 3.9333042153463284e-89, 2.1055559670183425e-93, 4.4826957080916534e-98, 2.7538984203799183e-103, 2.6468336179684675e-109, 8.3346219931731252e-117}, + {1.1929450990497388e-117, 3.9591990974598804e-110, 4.2745275541790886e-104, 7.1940582732963705e-99, 3.4858463341267156e-94, 6.7067764488470954e-90, 6.2295239916515678e-86, 3.1817588164569700e-82, 9.8006355361055656e-79, 1.9498222863573950e-75, 2.6411200905371024e-72, 2.5394077671157272e-69, 1.7924826309087973e-66, 9.5498361457830398e-64, 3.9302490205746199e-61, 1.2742413782141750e-58, 3.3097280501169341e-56, 6.9880745770528625e-54, 1.2146673922184433e-51, 1.7576627452371236e-49, 2.1383500879761454e-47, 2.2064997583491492e-45, 1.9463790072121561e-43, 1.4781646220486795e-41, 9.7267315160133413e-40, 5.5780033470752983e-38, 2.8025392714968451e-36, 1.2395973767055291e-34, 4.8482501635459064e-33, 1.6835590125100971e-31, 5.2099674531110126e-30, 1.4417990594032542e-28, 3.5795224098780112e-27, 7.9961758900246410e-26, 1.6116510554151974e-24, 2.9383411496603336e-23, 4.8574792709615864e-22, 7.2973076814277955e-21, 9.9829502923346154e-20, 1.2460703643781112e-18, 1.4216815546927034e-17, 1.4851721687462022e-16, 1.4228468795430129e-15, 1.2519744100239038e-14, 1.0132054243548976e-13, 7.5515422033135666e-13, 5.1897461393175068e-12, 3.2925485308161026e-11, 1.9304840630938534e-10, 1.0471078941135214e-09, 5.2592465173501358e-09, 2.4482298403820274e-08, 1.0571641536621842e-07, 4.2377549476354214e-07, 1.5781624324532756e-06, 5.4637147044287493e-06, 1.7596343655070067e-05, 5.2748866067347142e-05, 1.4726499921039843e-04, 3.8309201801330436e-04, 9.2902602860733265e-04, 2.1011697743361312e-03, 4.4337774736073364e-03, 8.7321528128579372e-03, 1.6056218663448245e-02, 2.7571764216085648e-02, 4.4227798774476149e-02, 6.6287455917162549e-02, 9.2844091734104794e-02, 1.2154351785304160e-01, 1.4873661992593393e-01, 1.7015822429768401e-01, 1.8199680336473223e-01, 1.8199680336473223e-01, 1.7015822429768401e-01, 1.4873661992593393e-01, 1.2154351785304160e-01, 9.2844091734104794e-02, 6.6287455917162549e-02, 4.4227798774476149e-02, 2.7571764216085648e-02, 1.6056218663448245e-02, 8.7321528128579372e-03, 4.4337774736073364e-03, 2.1011697743361312e-03, 9.2902602860733265e-04, 3.8309201801330436e-04, 1.4726499921039843e-04, 5.2748866067347142e-05, 1.7596343655070067e-05, 5.4637147044287493e-06, 1.5781624324532756e-06, 4.2377549476354214e-07, 1.0571641536621842e-07, 2.4482298403820274e-08, 5.2592465173501358e-09, 1.0471078941135214e-09, 1.9304840630938534e-10, 3.2925485308161026e-11, 5.1897461393175068e-12, 7.5515422033135666e-13, 1.0132054243548976e-13, 1.2519744100239038e-14, 1.4228468795430129e-15, 1.4851721687462022e-16, 1.4216815546927034e-17, 1.2460703643781112e-18, 9.9829502923346154e-20, 7.2973076814277955e-21, 4.8574792709615864e-22, 2.9383411496603336e-23, 1.6116510554151974e-24, 7.9961758900246410e-26, 3.5795224098780112e-27, 1.4417990594032542e-28, 5.2099674531110126e-30, 1.6835590125100971e-31, 4.8482501635459064e-33, 1.2395973767055291e-34, 2.8025392714968451e-36, 5.5780033470752983e-38, 9.7267315160133413e-40, 1.4781646220486795e-41, 1.9463790072121561e-43, 2.2064997583491492e-45, 2.1383500879761454e-47, 1.7576627452371236e-49, 1.2146673922184433e-51, 6.9880745770528625e-54, 3.3097280501169341e-56, 1.2742413782141750e-58, 3.9302490205746199e-61, 9.5498361457830398e-64, 1.7924826309087973e-66, 2.5394077671157272e-69, 2.6411200905371024e-72, 1.9498222863573950e-75, 9.8006355361055656e-79, 3.1817588164569700e-82, 6.2295239916515678e-86, 6.7067764488470954e-90, 3.4858463341267156e-94, 7.1940582732963705e-99, 4.2745275541790886e-104, 3.9591990974598804e-110, 1.1929450990497388e-117}, + {1.7070406181366590e-118, 5.9195113844414591e-111, 6.6305252022274385e-105, 1.1536024679706741e-99, 5.7653910975637400e-95, 1.1423077010030593e-90, 1.0913377348991997e-86, 5.7280704066660911e-83, 1.8118187632234171e-79, 3.6992788142779886e-76, 5.1399529790115008e-73, 5.0672863794680850e-70, 3.6662464654865143e-67, 2.0015272638354942e-64, 8.4387742209978957e-62, 2.8023099391369100e-59, 7.4539706347406648e-57, 1.6114689883841890e-54, 2.8677408135139503e-52, 4.2481015098521193e-50, 5.2903245181279725e-48, 5.5876178971908134e-46, 5.0448907217391667e-44, 3.9213661446271294e-42, 2.6409880203075402e-40, 1.5501131114814050e-38, 7.9712569158416828e-37, 3.6087469701637568e-35, 1.4446952835847923e-33, 5.1351616577255980e-32, 1.6267414726790182e-30, 4.6086441078964235e-29, 1.1714111882873408e-27, 2.6792736258069186e-26, 5.5296079664300731e-25, 1.0324183959837516e-23, 1.7479927721363103e-22, 2.6897676451867309e-21, 3.7695192606286801e-20, 4.8205800888162673e-19, 5.6356840948811206e-18, 6.0335058787737898e-17, 5.9246665636288388e-16, 5.3441830122937569e-15, 4.4343905593075405e-14, 3.3891924837505246e-13, 2.3889528428660744e-12, 1.5547996800001229e-11, 9.3534621545646173e-11, 5.2065241132424465e-10, 2.6842310976125569e-09, 1.2828665113850952e-08, 5.6885421998531753e-08, 2.3421973604647242e-07, 8.9613156437377830e-07, 3.1882138059205163e-06, 1.0554357586582146e-05, 3.2530204545596872e-05, 9.3401898795249160e-05, 2.4995620584101932e-04, 6.2376294512410423e-04, 1.4521587444586976e-03, 3.1551701974875863e-03, 6.4003731513496125e-03, 1.2125677167472506e-02, 2.1461222380505476e-02, 3.5494877838398289e-02, 5.4870701544829148e-02, 7.9298651231443446e-02, 1.0715555306319222e-01, 1.3540875492462576e-01, 1.6003249638444184e-01, 1.7690165636825916e-01, 1.8291007049692826e-01, 1.7690165636825916e-01, 1.6003249638444184e-01, 1.3540875492462576e-01, 1.0715555306319222e-01, 7.9298651231443446e-02, 5.4870701544829148e-02, 3.5494877838398289e-02, 2.1461222380505476e-02, 1.2125677167472506e-02, 6.4003731513496125e-03, 3.1551701974875863e-03, 1.4521587444586976e-03, 6.2376294512410423e-04, 2.4995620584101932e-04, 9.3401898795249160e-05, 3.2530204545596872e-05, 1.0554357586582146e-05, 3.1882138059205163e-06, 8.9613156437377830e-07, 2.3421973604647242e-07, 5.6885421998531753e-08, 1.2828665113850952e-08, 2.6842310976125569e-09, 5.2065241132424465e-10, 9.3534621545646173e-11, 1.5547996800001229e-11, 2.3889528428660744e-12, 3.3891924837505246e-13, 4.4343905593075405e-14, 5.3441830122937569e-15, 5.9246665636288388e-16, 6.0335058787737898e-17, 5.6356840948811206e-18, 4.8205800888162673e-19, 3.7695192606286801e-20, 2.6897676451867309e-21, 1.7479927721363103e-22, 1.0324183959837516e-23, 5.5296079664300731e-25, 2.6792736258069186e-26, 1.1714111882873408e-27, 4.6086441078964235e-29, 1.6267414726790182e-30, 5.1351616577255980e-32, 1.4446952835847923e-33, 3.6087469701637568e-35, 7.9712569158416828e-37, 1.5501131114814050e-38, 2.6409880203075402e-40, 3.9213661446271294e-42, 5.0448907217391667e-44, 5.5876178971908134e-46, 5.2903245181279725e-48, 4.2481015098521193e-50, 2.8677408135139503e-52, 1.6114689883841890e-54, 7.4539706347406648e-57, 2.8023099391369100e-59, 8.4387742209978957e-62, 2.0015272638354942e-64, 3.6662464654865143e-67, 5.0672863794680850e-70, 5.1399529790115008e-73, 3.6992788142779886e-76, 1.8118187632234171e-79, 5.7280704066660911e-83, 1.0913377348991997e-86, 1.1423077010030593e-90, 5.7653910975637400e-95, 1.1536024679706741e-99, 6.6305252022274385e-105, 5.9195113844414591e-111, 1.7070406181366590e-118}, + {2.4420658728359029e-119, 8.8463582669186499e-112, 1.0278520435124409e-105, 1.8483749220636043e-100, 9.5264999562099965e-96, 1.9434401044261462e-91, 1.9094951070499896e-87, 1.0297738588062730e-83, 3.3443041190506409e-80, 7.0066129472632568e-77, 9.9847674734222346e-74, 1.0091718959432019e-70, 7.4829681064377069e-68, 4.1855384000761587e-65, 1.8075959008515128e-62, 6.1472579038779528e-60, 1.6742548573659892e-57, 3.7056307854458431e-55, 6.7504839696392484e-53, 1.0235353311199910e-50, 1.3045775870281223e-48, 1.4101600092151863e-46, 1.3029538434289154e-44, 1.0364256329737640e-42, 7.1430632340356861e-41, 4.2904029597408759e-39, 2.2577848908542067e-37, 1.0460259894518416e-35, 4.2855476518701719e-34, 1.5590004744721381e-32, 5.0546933927274757e-31, 1.4657489608244835e-29, 3.8136046756805110e-28, 8.9292832689033937e-27, 1.8867047659679220e-25, 3.6067468226756066e-24, 6.2530721763179845e-23, 9.8539255836953708e-22, 1.4143965820612745e-20, 1.8527994733871280e-19, 2.2190951508494865e-18, 2.4342129329346826e-17, 2.4494846944487187e-16, 2.2645381737872469e-15, 1.9261422339406544e-14, 1.5093097961491213e-13, 1.0909182729913857e-12, 7.2818111329385306e-12, 4.4936440478669596e-11, 2.5663720011644112e-10, 1.3577644240845783e-09, 6.6605391288638309e-09, 3.0321186483039541e-08, 1.2819858780710668e-07, 5.0378676249733306e-07, 1.8413731465659074e-06, 6.2640223021607951e-06, 1.9844802959774770e-05, 5.8582692413005888e-05, 1.6123158507144338e-04, 4.1390553680515079e-04, 9.9155807247580142e-04, 2.2175853317597280e-03, 4.6318204121044990e-03, 9.0381820758826531e-03, 1.6481721286763326e-02, 2.8095443629279886e-02, 4.4780275406602559e-02, 6.6749354510874270e-02, 9.3066885205695463e-02, 1.2139368280029710e-01, 1.4814998194065979e-01, 1.6918056507168472e-01, 1.8078752906102052e-01, 1.8078752906102052e-01, 1.6918056507168472e-01, 1.4814998194065979e-01, 1.2139368280029710e-01, 9.3066885205695463e-02, 6.6749354510874270e-02, 4.4780275406602559e-02, 2.8095443629279886e-02, 1.6481721286763326e-02, 9.0381820758826531e-03, 4.6318204121044990e-03, 2.2175853317597280e-03, 9.9155807247580142e-04, 4.1390553680515079e-04, 1.6123158507144338e-04, 5.8582692413005888e-05, 1.9844802959774770e-05, 6.2640223021607951e-06, 1.8413731465659074e-06, 5.0378676249733306e-07, 1.2819858780710668e-07, 3.0321186483039541e-08, 6.6605391288638309e-09, 1.3577644240845783e-09, 2.5663720011644112e-10, 4.4936440478669596e-11, 7.2818111329385306e-12, 1.0909182729913857e-12, 1.5093097961491213e-13, 1.9261422339406544e-14, 2.2645381737872469e-15, 2.4494846944487187e-16, 2.4342129329346826e-17, 2.2190951508494865e-18, 1.8527994733871280e-19, 1.4143965820612745e-20, 9.8539255836953708e-22, 6.2530721763179845e-23, 3.6067468226756066e-24, 1.8867047659679220e-25, 8.9292832689033937e-27, 3.8136046756805110e-28, 1.4657489608244835e-29, 5.0546933927274757e-31, 1.5590004744721381e-32, 4.2855476518701719e-34, 1.0460259894518416e-35, 2.2577848908542067e-37, 4.2904029597408759e-39, 7.1430632340356861e-41, 1.0364256329737640e-42, 1.3029538434289154e-44, 1.4101600092151863e-46, 1.3045775870281223e-48, 1.0235353311199910e-50, 6.7504839696392484e-53, 3.7056307854458431e-55, 1.6742548573659892e-57, 6.1472579038779528e-60, 1.8075959008515128e-62, 4.1855384000761587e-65, 7.4829681064377069e-68, 1.0091718959432019e-70, 9.9847674734222346e-74, 7.0066129472632568e-77, 3.3443041190506409e-80, 1.0297738588062730e-83, 1.9094951070499896e-87, 1.9434401044261462e-91, 9.5264999562099965e-96, 1.8483749220636043e-100, 1.0278520435124409e-105, 8.8463582669186499e-112, 2.4420658728359029e-119}, + {3.4927077138614495e-120, 1.3214344265685972e-112, 1.5923529644019419e-106, 2.9592365392916602e-101, 1.5726312834383212e-96, 3.3028107528503361e-92, 3.3368715475506461e-88, 1.8487368270391726e-84, 6.1636129673212566e-81, 1.3248817176167857e-77, 1.9361289427704634e-74, 2.0059128285660820e-71, 1.5241335107478225e-68, 8.7332836494574003e-66, 3.8627717414010648e-63, 1.3451211690839924e-60, 3.7506692343030420e-58, 8.4975513070583486e-56, 1.5843787624675853e-53, 2.4585380900294205e-51, 3.2067130430374953e-49, 3.5468958347722111e-47, 3.3533561409072355e-45, 2.7292702435888796e-43, 1.9246140375840066e-41, 1.1827867549833032e-39, 6.3685955808210726e-38, 3.0190103270136603e-36, 1.2656167558393507e-34, 4.7112145637232019e-33, 1.5631232313432506e-31, 4.6386822641081590e-30, 1.2351960569462707e-28, 2.9601529366809405e-27, 6.4022761029959671e-26, 1.2529044419038621e-24, 2.2238719447561208e-23, 3.5882695810709981e-22, 5.2741804743987912e-21, 7.0757399180811555e-20, 8.6802800075429983e-19, 9.7541289549630027e-18, 1.0056284258182538e-16, 9.5266259491509481e-16, 8.3044572801891268e-15, 6.6701332750751410e-14, 4.9425874408492004e-13, 3.3828553008734636e-12, 2.1409348303068694e-11, 1.2542010220460425e-10, 6.8076912279459116e-10, 3.4268964379715692e-09, 1.6011995715635929e-08, 6.9500026302554605e-08, 2.8044586426011501e-07, 1.0528006766858483e-06, 3.6792955563634022e-06, 1.1977707839841136e-05, 3.6343264722217326e-05, 1.0283673489115176e-04, 2.7149548605395329e-04, 6.6906197625873226e-04, 1.5397243486054463e-03, 3.3102482665201089e-03, 6.6507742518744171e-03, 1.2491552298533356e-02, 2.1939032537498546e-02, 3.6040083142086628e-02, 5.5388310278285176e-02, 7.9652215262150924e-02, 1.0720010935792797e-01, 1.3504155894527325e-01, 1.5924245367972575e-01, 1.7579280253635429e-01, 1.8168248613117691e-01, 1.7579280253635429e-01, 1.5924245367972575e-01, 1.3504155894527325e-01, 1.0720010935792797e-01, 7.9652215262150924e-02, 5.5388310278285176e-02, 3.6040083142086628e-02, 2.1939032537498546e-02, 1.2491552298533356e-02, 6.6507742518744171e-03, 3.3102482665201089e-03, 1.5397243486054463e-03, 6.6906197625873226e-04, 2.7149548605395329e-04, 1.0283673489115176e-04, 3.6343264722217326e-05, 1.1977707839841136e-05, 3.6792955563634022e-06, 1.0528006766858483e-06, 2.8044586426011501e-07, 6.9500026302554605e-08, 1.6011995715635929e-08, 3.4268964379715692e-09, 6.8076912279459116e-10, 1.2542010220460425e-10, 2.1409348303068694e-11, 3.3828553008734636e-12, 4.9425874408492004e-13, 6.6701332750751410e-14, 8.3044572801891268e-15, 9.5266259491509481e-16, 1.0056284258182538e-16, 9.7541289549630027e-18, 8.6802800075429983e-19, 7.0757399180811555e-20, 5.2741804743987912e-21, 3.5882695810709981e-22, 2.2238719447561208e-23, 1.2529044419038621e-24, 6.4022761029959671e-26, 2.9601529366809405e-27, 1.2351960569462707e-28, 4.6386822641081590e-30, 1.5631232313432506e-31, 4.7112145637232019e-33, 1.2656167558393507e-34, 3.0190103270136603e-36, 6.3685955808210726e-38, 1.1827867549833032e-39, 1.9246140375840066e-41, 2.7292702435888796e-43, 3.3533561409072355e-45, 3.5468958347722111e-47, 3.2067130430374953e-49, 2.4585380900294205e-51, 1.5843787624675853e-53, 8.4975513070583486e-56, 3.7506692343030420e-58, 1.3451211690839924e-60, 3.8627717414010648e-63, 8.7332836494574003e-66, 1.5241335107478225e-68, 2.0059128285660820e-71, 1.9361289427704634e-74, 1.3248817176167857e-77, 6.1636129673212566e-81, 1.8487368270391726e-84, 3.3368715475506461e-88, 3.3028107528503361e-92, 1.5726312834383212e-96, 2.9592365392916602e-101, 1.5923529644019419e-106, 1.3214344265685972e-112, 3.4927077138614495e-120}, + {4.9941282442606218e-121, 1.9730195235183967e-113, 2.4653426103610859e-107, 4.7340081105291807e-102, 2.5936668261705122e-97, 5.6069447675960520e-93, 5.8240937771374570e-89, 3.3144783626996768e-85, 1.1342570222437056e-81, 2.5011096149430186e-78, 3.7476379174495528e-75, 3.9794814788876447e-72, 3.0979908735545725e-69, 1.8182439901095753e-66, 8.2354102738652040e-64, 2.9360923690156291e-61, 8.3803809757287599e-59, 1.9432660775004502e-56, 3.7079038793856585e-54, 5.8875467910577051e-52, 7.8572573935602256e-50, 8.8917221680510199e-48, 8.6005009516161168e-46, 7.1611639319733097e-44, 5.1661373788013124e-42, 3.2479669251550536e-40, 1.7890987177636214e-38, 8.6765699223362474e-37, 3.7212625316226216e-35, 1.4172340427766930e-33, 4.8110787981190828e-32, 1.4608586938294995e-30, 3.9805330733973355e-29, 9.7620761562971344e-28, 2.1608244949042565e-26, 4.3281046749583524e-25, 7.8636681438025253e-24, 1.2989130984240299e-22, 1.9546850118180088e-21, 2.6851626691585123e-20, 3.3733593511587544e-19, 3.8824303202657657e-18, 4.1001349905289425e-17, 3.9793051828221563e-16, 3.5542824359476288e-15, 2.9256051436471688e-14, 2.2220151125790449e-13, 1.5590549255574669e-12, 1.0116812009960419e-11, 6.0778437594159535e-11, 3.3838207012562939e-10, 1.7475098827142176e-09, 8.3784654573163473e-09, 3.7324734098992270e-08, 1.5461411843105312e-07, 5.9598254897039207e-07, 2.1391519688131322e-06, 7.1539515355890577e-06, 2.2304926470707147e-05, 6.4869805018180065e-05, 1.7607226778935711e-04, 4.4622007110453903e-04, 1.0563416857043819e-03, 2.3368400915518292e-03, 4.8325911868397145e-03, 9.3454535527143379e-03, 1.6905135871613127e-02, 2.8612106958160764e-02, 4.5320570847252710e-02, 6.7196013411209815e-02, 9.3275910346104995e-02, 1.2123716317285059e-01, 1.4756796236123393e-01, 1.6821923724022270e-01, 1.7960204009494329e-01, 1.7960204009494329e-01, 1.6821923724022270e-01, 1.4756796236123393e-01, 1.2123716317285059e-01, 9.3275910346104995e-02, 6.7196013411209815e-02, 4.5320570847252710e-02, 2.8612106958160764e-02, 1.6905135871613127e-02, 9.3454535527143379e-03, 4.8325911868397145e-03, 2.3368400915518292e-03, 1.0563416857043819e-03, 4.4622007110453903e-04, 1.7607226778935711e-04, 6.4869805018180065e-05, 2.2304926470707147e-05, 7.1539515355890577e-06, 2.1391519688131322e-06, 5.9598254897039207e-07, 1.5461411843105312e-07, 3.7324734098992270e-08, 8.3784654573163473e-09, 1.7475098827142176e-09, 3.3838207012562939e-10, 6.0778437594159535e-11, 1.0116812009960419e-11, 1.5590549255574669e-12, 2.2220151125790449e-13, 2.9256051436471688e-14, 3.5542824359476288e-15, 3.9793051828221563e-16, 4.1001349905289425e-17, 3.8824303202657657e-18, 3.3733593511587544e-19, 2.6851626691585123e-20, 1.9546850118180088e-21, 1.2989130984240299e-22, 7.8636681438025253e-24, 4.3281046749583524e-25, 2.1608244949042565e-26, 9.7620761562971344e-28, 3.9805330733973355e-29, 1.4608586938294995e-30, 4.8110787981190828e-32, 1.4172340427766930e-33, 3.7212625316226216e-35, 8.6765699223362474e-37, 1.7890987177636214e-38, 3.2479669251550536e-40, 5.1661373788013124e-42, 7.1611639319733097e-44, 8.6005009516161168e-46, 8.8917221680510199e-48, 7.8572573935602256e-50, 5.8875467910577051e-52, 3.7079038793856585e-54, 1.9432660775004502e-56, 8.3803809757287599e-59, 2.9360923690156291e-61, 8.2354102738652040e-64, 1.8182439901095753e-66, 3.0979908735545725e-69, 3.9794814788876447e-72, 3.7476379174495528e-75, 2.5011096149430186e-78, 1.1342570222437056e-81, 3.3144783626996768e-85, 5.8240937771374570e-89, 5.6069447675960520e-93, 2.5936668261705122e-97, 4.7340081105291807e-102, 2.4653426103610859e-107, 1.9730195235183967e-113, 4.9941282442606218e-121}, + {7.1392222017713907e-122, 2.9445845110667619e-114, 3.8145868837135596e-108, 7.5673169898909099e-103, 4.2736593644380303e-98, 9.5083335143727237e-94, 1.0152930470452851e-89, 5.9342954899998552e-86, 2.0842120266141319e-82, 4.7139344340961388e-79, 7.2413131304484502e-76, 7.8798610228883591e-73, 6.2842892805603737e-70, 3.7773465198180638e-67, 1.7517513408453002e-64, 6.3932209199477197e-62, 1.8676726441679446e-59, 4.4319273103122463e-57, 8.6528507374176976e-55, 1.4056977850593077e-52, 1.9192002948401386e-50, 2.2217716370141584e-48, 2.1982691386986115e-46, 1.8722764372760468e-44, 1.3815703248778117e-42, 8.8845643289761640e-41, 5.0058533566520875e-39, 2.4832338706643681e-37, 1.0894227474485724e-35, 4.2442335712525587e-34, 1.4739090369348960e-32, 4.5785676785685073e-31, 1.2763864929327656e-29, 3.2028196423033392e-28, 7.2542458795704827e-27, 1.4869262820581125e-25, 2.7648741131715751e-24, 4.6744604380487021e-23, 7.2007069149677438e-22, 1.0126623472614820e-20, 1.3025790505179032e-19, 1.5351372541981349e-18, 1.6603563330241997e-17, 1.6505566788948694e-16, 1.5102835946897961e-15, 1.2737138463928603e-14, 9.9133825544714478e-14, 7.1289732797212971e-13, 4.7421458438831827e-12, 2.9209512270101235e-11, 1.6676562560887225e-10, 8.8333847125166249e-10, 4.3447745740955300e-09, 1.9860254178505552e-08, 8.4433687619112637e-08, 3.3409895046160263e-07, 1.2312829806627210e-06, 4.2290221665164350e-06, 1.3544999036061644e-05, 4.0477621043373221e-05, 1.1292006863438276e-04, 2.9420790203745482e-04, 7.1623536508659178e-04, 1.6298641009901027e-03, 3.4681866693627482e-03, 6.9032861428781267e-03, 1.2857145952636101e-02, 2.2412375310366960e-02, 3.6575629838591243e-02, 5.5891953828813568e-02, 7.9990869817108165e-02, 1.0723403572962083e-01, 1.3467313142650547e-01, 1.5846303276659124e-01, 1.7470447835636663e-01, 1.8047929085878514e-01, 1.7470447835636663e-01, 1.5846303276659124e-01, 1.3467313142650547e-01, 1.0723403572962083e-01, 7.9990869817108165e-02, 5.5891953828813568e-02, 3.6575629838591243e-02, 2.2412375310366960e-02, 1.2857145952636101e-02, 6.9032861428781267e-03, 3.4681866693627482e-03, 1.6298641009901027e-03, 7.1623536508659178e-04, 2.9420790203745482e-04, 1.1292006863438276e-04, 4.0477621043373221e-05, 1.3544999036061644e-05, 4.2290221665164350e-06, 1.2312829806627210e-06, 3.3409895046160263e-07, 8.4433687619112637e-08, 1.9860254178505552e-08, 4.3447745740955300e-09, 8.8333847125166249e-10, 1.6676562560887225e-10, 2.9209512270101235e-11, 4.7421458438831827e-12, 7.1289732797212971e-13, 9.9133825544714478e-14, 1.2737138463928603e-14, 1.5102835946897961e-15, 1.6505566788948694e-16, 1.6603563330241997e-17, 1.5351372541981349e-18, 1.3025790505179032e-19, 1.0126623472614820e-20, 7.2007069149677438e-22, 4.6744604380487021e-23, 2.7648741131715751e-24, 1.4869262820581125e-25, 7.2542458795704827e-27, 3.2028196423033392e-28, 1.2763864929327656e-29, 4.5785676785685073e-31, 1.4739090369348960e-32, 4.2442335712525587e-34, 1.0894227474485724e-35, 2.4832338706643681e-37, 5.0058533566520875e-39, 8.8845643289761640e-41, 1.3815703248778117e-42, 1.8722764372760468e-44, 2.1982691386986115e-46, 2.2217716370141584e-48, 1.9192002948401386e-50, 1.4056977850593077e-52, 8.6528507374176976e-55, 4.4319273103122463e-57, 1.8676726441679446e-59, 6.3932209199477197e-62, 1.7517513408453002e-64, 3.7773465198180638e-67, 6.2842892805603737e-70, 7.8798610228883591e-73, 7.2413131304484502e-76, 4.7139344340961388e-79, 2.0842120266141319e-82, 5.9342954899998552e-86, 1.0152930470452851e-89, 9.5083335143727237e-94, 4.2736593644380303e-98, 7.5673169898909099e-103, 3.8145868837135596e-108, 2.9445845110667619e-114, 7.1392222017713907e-122}, + {1.0203215419405115e-122, 4.3926409088220260e-115, 5.8986558173681245e-109, 1.2087105293093391e-103, 7.0353980850250737e-99, 1.6107326288260005e-94, 1.7678067289525790e-90, 1.0610697100358954e-86, 3.8241442068780522e-83, 8.8702923923721366e-80, 1.3967624162820115e-76, 1.5573928888055416e-73, 1.2722188115916827e-70, 7.8305641247237068e-68, 3.7176883954596755e-65, 1.3887513560879043e-62, 4.1517737028880682e-60, 1.0080675510766497e-57, 2.0135706193376487e-55, 3.3463102229914590e-53, 4.6733192109921242e-51, 5.5335945022909141e-49, 5.5997707655432161e-47, 4.8778201649868724e-45, 3.6811705155316592e-43, 2.4210413787496984e-41, 1.3950773628177882e-39, 7.0777866064732306e-38, 3.1757468989046869e-36, 1.2654132053176338e-34, 4.4947480753641788e-33, 1.4281952005441561e-31, 4.0727582182469552e-30, 1.0454808582283026e-28, 2.4226185736538330e-27, 5.0807355599009919e-26, 9.6670785467690252e-25, 1.6725361565602745e-23, 2.6368638947823986e-22, 3.7957111549106315e-21, 4.9980289800251531e-20, 6.0306098179642906e-19, 6.6786804983364280e-18, 6.7991402460144679e-17, 6.3720317811650348e-16, 5.5049284400726915e-15, 4.3896449685818035e-14, 3.2346882306340970e-13, 2.2052168865195276e-12, 1.3923473891503035e-11, 8.1499619365601122e-11, 4.4267370542157585e-10, 2.2331409933577818e-09, 1.0471618689062924e-08, 4.5678915072122709e-08, 1.8549839541616252e-07, 7.0175441742037147e-07, 2.4747420668926454e-06, 8.1402071214919003e-06, 2.4988785980142873e-05, 7.1628474554958981e-05, 1.9180837279585649e-04, 4.8004901932197877e-04, 1.1233614820028411e-03, 2.4588639421196687e-03, 5.0359498094177816e-03, 9.6537773093780983e-03, 1.7326295602536231e-02, 2.9121725644242560e-02, 4.5848897885251948e-02, 6.7627897299374851e-02, 9.3471746781564918e-02, 1.2107439739077461e-01, 1.4699060677873937e-01, 1.6727380280253201e-01, 1.7843956694581845e-01, 1.7843956694581845e-01, 1.6727380280253201e-01, 1.4699060677873937e-01, 1.2107439739077461e-01, 9.3471746781564918e-02, 6.7627897299374851e-02, 4.5848897885251948e-02, 2.9121725644242560e-02, 1.7326295602536231e-02, 9.6537773093780983e-03, 5.0359498094177816e-03, 2.4588639421196687e-03, 1.1233614820028411e-03, 4.8004901932197877e-04, 1.9180837279585649e-04, 7.1628474554958981e-05, 2.4988785980142873e-05, 8.1402071214919003e-06, 2.4747420668926454e-06, 7.0175441742037147e-07, 1.8549839541616252e-07, 4.5678915072122709e-08, 1.0471618689062924e-08, 2.2331409933577818e-09, 4.4267370542157585e-10, 8.1499619365601122e-11, 1.3923473891503035e-11, 2.2052168865195276e-12, 3.2346882306340970e-13, 4.3896449685818035e-14, 5.5049284400726915e-15, 6.3720317811650348e-16, 6.7991402460144679e-17, 6.6786804983364280e-18, 6.0306098179642906e-19, 4.9980289800251531e-20, 3.7957111549106315e-21, 2.6368638947823986e-22, 1.6725361565602745e-23, 9.6670785467690252e-25, 5.0807355599009919e-26, 2.4226185736538330e-27, 1.0454808582283026e-28, 4.0727582182469552e-30, 1.4281952005441561e-31, 4.4947480753641788e-33, 1.2654132053176338e-34, 3.1757468989046869e-36, 7.0777866064732306e-38, 1.3950773628177882e-39, 2.4210413787496984e-41, 3.6811705155316592e-43, 4.8778201649868724e-45, 5.5997707655432161e-47, 5.5335945022909141e-49, 4.6733192109921242e-51, 3.3463102229914590e-53, 2.0135706193376487e-55, 1.0080675510766497e-57, 4.1517737028880682e-60, 1.3887513560879043e-62, 3.7176883954596755e-65, 7.8305641247237068e-68, 1.2722188115916827e-70, 1.5573928888055416e-73, 1.3967624162820115e-76, 8.8702923923721366e-80, 3.8241442068780522e-83, 1.0610697100358954e-86, 1.7678067289525790e-90, 1.6107326288260005e-94, 7.0353980850250737e-99, 1.2087105293093391e-103, 5.8986558173681245e-109, 4.3926409088220260e-115, 1.0203215419405115e-122}, + {1.4578716888574380e-123, 6.5499584195542182e-116, 9.1158441302395916e-110, 1.9291851130201365e-104, 1.1571376888010415e-99, 2.7257668732866951e-95, 3.0744291780743119e-91, 1.8947250431186403e-87, 7.0064183028413687e-84, 1.6664955389849393e-80, 2.6895662316444978e-77, 3.0723812680200150e-74, 2.5704405332276809e-71, 1.6198772061572697e-68, 7.8722498229365745e-66, 3.0095177392268181e-63, 9.2061099904566106e-61, 2.2868504296047653e-58, 4.6726874994563693e-56, 7.9427931843455534e-54, 1.1344972574084324e-51, 1.3738127684763008e-49, 1.4217090927665081e-47, 1.2663997582044745e-45, 9.7729455955061106e-44, 6.5725138972034875e-42, 3.8727324373725659e-40, 2.0091450762048232e-38, 9.2185663859103873e-37, 3.7563551936945986e-35, 1.3644995796552897e-33, 4.4341465741479497e-32, 1.2932715429724819e-30, 3.3956536214966241e-29, 8.0487680064663208e-28, 1.7268001245109222e-26, 3.3613905413108243e-25, 5.9504202589874584e-24, 9.5995603721747768e-23, 1.4141461815469168e-21, 1.9058394524305284e-20, 2.3538938440623925e-19, 2.6687563232163005e-18, 2.7817760484437033e-17, 2.6696608032295694e-16, 2.3621238776008329e-15, 1.9293848215014542e-14, 1.4565613270987712e-13, 1.0174797099588637e-12, 6.5837630407380247e-12, 3.9501281887181556e-11, 2.1996223199610065e-10, 1.1378158851290800e-09, 5.4720083734809282e-09, 2.4485807329829557e-08, 1.0202255589712521e-07, 3.9608954710479925e-07, 1.4337991258427923e-06, 4.8422272544211524e-06, 1.5265488972373680e-05, 4.4948480076886716e-05, 1.2367217082799177e-04, 3.1811200186972611e-04, 7.6528399238001590e-04, 1.7225370790285232e-03, 3.6288805291928589e-03, 7.1577405214717574e-03, 1.3222272319718250e-02, 2.2881143871485050e-02, 3.7101604703410701e-02, 5.6381975314828768e-02, 8.0315152775434245e-02, 1.0725786228191081e-01, 1.3430372904700771e-01, 1.5769403536946561e-01, 1.7363606017905039e-01, 1.7929968765055787e-01, 1.7363606017905039e-01, 1.5769403536946561e-01, 1.3430372904700771e-01, 1.0725786228191081e-01, 8.0315152775434245e-02, 5.6381975314828768e-02, 3.7101604703410701e-02, 2.2881143871485050e-02, 1.3222272319718250e-02, 7.1577405214717574e-03, 3.6288805291928589e-03, 1.7225370790285232e-03, 7.6528399238001590e-04, 3.1811200186972611e-04, 1.2367217082799177e-04, 4.4948480076886716e-05, 1.5265488972373680e-05, 4.8422272544211524e-06, 1.4337991258427923e-06, 3.9608954710479925e-07, 1.0202255589712521e-07, 2.4485807329829557e-08, 5.4720083734809282e-09, 1.1378158851290800e-09, 2.1996223199610065e-10, 3.9501281887181556e-11, 6.5837630407380247e-12, 1.0174797099588637e-12, 1.4565613270987712e-13, 1.9293848215014542e-14, 2.3621238776008329e-15, 2.6696608032295694e-16, 2.7817760484437033e-17, 2.6687563232163005e-18, 2.3538938440623925e-19, 1.9058394524305284e-20, 1.4141461815469168e-21, 9.5995603721747768e-23, 5.9504202589874584e-24, 3.3613905413108243e-25, 1.7268001245109222e-26, 8.0487680064663208e-28, 3.3956536214966241e-29, 1.2932715429724819e-30, 4.4341465741479497e-32, 1.3644995796552897e-33, 3.7563551936945986e-35, 9.2185663859103873e-37, 2.0091450762048232e-38, 3.8727324373725659e-40, 6.5725138972034875e-42, 9.7729455955061106e-44, 1.2663997582044745e-45, 1.4217090927665081e-47, 1.3738127684763008e-49, 1.1344972574084324e-51, 7.9427931843455534e-54, 4.6726874994563693e-56, 2.2868504296047653e-58, 9.2061099904566106e-61, 3.0095177392268181e-63, 7.8722498229365745e-66, 1.6198772061572697e-68, 2.5704405332276809e-71, 3.0723812680200150e-74, 2.6895662316444978e-77, 1.6664955389849393e-80, 7.0064183028413687e-84, 1.8947250431186403e-87, 3.0744291780743119e-91, 2.7257668732866951e-95, 1.1571376888010415e-99, 1.9291851130201365e-104, 9.1158441302395916e-110, 6.5499584195542182e-116, 1.4578716888574380e-123}, + {2.0825660478904760e-124, 9.7625806330567035e-117, 1.4079328290981535e-110, 3.0768081483238432e-105, 1.9014873630323964e-100, 4.6079244634146070e-96, 5.3405557808694215e-92, 3.3789567793532434e-88, 1.2818424753415062e-84, 3.1260093916222602e-81, 5.1701750558611924e-78, 6.0500487002887184e-75, 5.1832685019930213e-72, 3.3439902942647502e-69, 1.6632668027272507e-66, 6.5065315377220389e-64, 2.0362992343457651e-61, 5.1742950935108869e-59, 1.0813687999683845e-56, 1.8798749780879993e-54, 2.7458133331828386e-52, 3.3999899766205468e-50, 3.5976656083923711e-48, 3.2766076271604045e-46, 2.5853058405449532e-44, 1.7776460048844266e-42, 1.0709222498944708e-40, 5.6804446369555694e-39, 2.6648525467274738e-37, 1.1102669670225965e-35, 4.1238340545301011e-34, 1.3703279298000201e-32, 4.0870885738671846e-31, 1.0974483844909332e-29, 2.6604572771951219e-28, 5.8380527272929378e-27, 1.1624651194307257e-25, 2.1051475426760218e-24, 3.4745776974200654e-23, 5.2372761374065798e-22, 7.2227982269547378e-21, 9.1298647949536611e-20, 1.0594921794825161e-18, 1.1305197522298609e-17, 1.1108048214201895e-16, 1.0064014746615927e-15, 8.4185702868695228e-15, 6.5097729971311742e-14, 4.6585402153758067e-13, 3.0885703725214258e-12, 1.8990163158421596e-11, 1.0838710379194289e-10, 5.7477002127859619e-10, 2.8342947222693205e-09, 1.3006943860141712e-08, 5.5591582741553296e-08, 2.2143724484223221e-07, 8.2259408138485364e-07, 2.8515507236878458e-06, 9.2296922270054013e-06, 2.7908549833980887e-05, 7.8876670613220481e-05, 2.0846012412302649e-04, 5.1540364930051158e-04, 1.1925993797900470e-03, 2.5835851277422653e-03, 5.2417582224628060e-03, 9.9629708516368199e-03, 1.7745045563417383e-02, 2.9624281938924940e-02, 4.6365470641524055e-02, 6.8045456872924986e-02, 9.3654947635056565e-02, 1.2090579766618584e-01, 1.4641795120378570e-01, 1.6634383944546130e-01, 1.7729937449709982e-01, 1.7729937449709982e-01, 1.6634383944546130e-01, 1.4641795120378570e-01, 1.2090579766618584e-01, 9.3654947635056565e-02, 6.8045456872924986e-02, 4.6365470641524055e-02, 2.9624281938924940e-02, 1.7745045563417383e-02, 9.9629708516368199e-03, 5.2417582224628060e-03, 2.5835851277422653e-03, 1.1925993797900470e-03, 5.1540364930051158e-04, 2.0846012412302649e-04, 7.8876670613220481e-05, 2.7908549833980887e-05, 9.2296922270054013e-06, 2.8515507236878458e-06, 8.2259408138485364e-07, 2.2143724484223221e-07, 5.5591582741553296e-08, 1.3006943860141712e-08, 2.8342947222693205e-09, 5.7477002127859619e-10, 1.0838710379194289e-10, 1.8990163158421596e-11, 3.0885703725214258e-12, 4.6585402153758067e-13, 6.5097729971311742e-14, 8.4185702868695228e-15, 1.0064014746615927e-15, 1.1108048214201895e-16, 1.1305197522298609e-17, 1.0594921794825161e-18, 9.1298647949536611e-20, 7.2227982269547378e-21, 5.2372761374065798e-22, 3.4745776974200654e-23, 2.1051475426760218e-24, 1.1624651194307257e-25, 5.8380527272929378e-27, 2.6604572771951219e-28, 1.0974483844909332e-29, 4.0870885738671846e-31, 1.3703279298000201e-32, 4.1238340545301011e-34, 1.1102669670225965e-35, 2.6648525467274738e-37, 5.6804446369555694e-39, 1.0709222498944708e-40, 1.7776460048844266e-42, 2.5853058405449532e-44, 3.2766076271604045e-46, 3.5976656083923711e-48, 3.3999899766205468e-50, 2.7458133331828386e-52, 1.8798749780879993e-54, 1.0813687999683845e-56, 5.1742950935108869e-59, 2.0362992343457651e-61, 6.5065315377220389e-64, 1.6632668027272507e-66, 3.3439902942647502e-69, 5.1832685019930213e-72, 6.0500487002887184e-75, 5.1701750558611924e-78, 3.1260093916222602e-81, 1.2818424753415062e-84, 3.3789567793532434e-88, 5.3405557808694215e-92, 4.6079244634146070e-96, 1.9014873630323964e-100, 3.0768081483238432e-105, 1.4079328290981535e-110, 9.7625806330567035e-117, 2.0825660478904760e-124}, + {2.9742440544925765e-125, 1.4544742104415291e-117, 2.1732568643306002e-111, 4.9034921609592363e-106, 3.1218947762576099e-101, 7.7817715084363300e-97, 9.2663025096531715e-93, 6.0181049060844634e-89, 2.3418402716705127e-85, 5.8546944803309517e-82, 9.9220223776303372e-79, 1.1892107956658327e-75, 1.0431826368600407e-72, 6.8889436382474771e-70, 3.5064990884120332e-67, 1.4034428812712122e-64, 4.4930692768932806e-62, 1.1677337858216425e-59, 2.4957603118464674e-57, 4.4365856613493741e-55, 6.6258941032515879e-53, 8.3883165922512944e-51, 9.0744120512086595e-49, 8.4490059406933366e-47, 6.8149889325650219e-45, 4.7903177946790465e-43, 2.9501316492565748e-41, 1.5996806743635201e-39, 7.6718304654322104e-38, 3.2676791768964119e-36, 1.2408362449919783e-34, 4.2155847725706856e-33, 1.2855517878737815e-31, 3.5296150194332557e-30, 8.7497557637466758e-29, 1.9635223775022683e-27, 3.9986259229284162e-26, 7.4065187877720327e-25, 1.2504748686909515e-23, 1.9282493305400296e-22, 2.7207846792186873e-21, 3.5191108460642354e-20, 4.1792457685713468e-19, 4.5641951147736119e-18, 4.5905709762107554e-17, 4.2579719891425731e-16, 3.6469920289222789e-15, 2.8879673414801644e-14, 2.1167713706852141e-13, 1.4376384719405419e-12, 9.0565354971087218e-12, 5.2969771654748994e-11, 2.8789912587990587e-10, 1.4553534068219742e-09, 6.8479451315824872e-09, 3.0015309064632456e-08, 1.2263753200782247e-07, 4.6740187357094381e-07, 1.6627017535681513e-06, 5.5239309109102710e-06, 1.7148598641483128e-05, 4.9770974063404784e-05, 1.3511264030161956e-04, 3.4322471703307256e-04, 8.1620625227316382e-04, 1.8177000254213835e-03, 3.7922249171946417e-03, 7.4139737035166485e-03, 1.3586755499761058e-02, 2.3345243317359717e-02, 3.7618101204680170e-02, 5.6858711709023881e-02, 8.0625581158863605e-02, 1.0727209153833471e-01, 1.3393358950744624e-01, 1.5693526614765907e-01, 1.7258695046281516e-01, 1.7814291547216715e-01, 1.7258695046281516e-01, 1.5693526614765907e-01, 1.3393358950744624e-01, 1.0727209153833471e-01, 8.0625581158863605e-02, 5.6858711709023881e-02, 3.7618101204680170e-02, 2.3345243317359717e-02, 1.3586755499761058e-02, 7.4139737035166485e-03, 3.7922249171946417e-03, 1.8177000254213835e-03, 8.1620625227316382e-04, 3.4322471703307256e-04, 1.3511264030161956e-04, 4.9770974063404784e-05, 1.7148598641483128e-05, 5.5239309109102710e-06, 1.6627017535681513e-06, 4.6740187357094381e-07, 1.2263753200782247e-07, 3.0015309064632456e-08, 6.8479451315824872e-09, 1.4553534068219742e-09, 2.8789912587990587e-10, 5.2969771654748994e-11, 9.0565354971087218e-12, 1.4376384719405419e-12, 2.1167713706852141e-13, 2.8879673414801644e-14, 3.6469920289222789e-15, 4.2579719891425731e-16, 4.5905709762107554e-17, 4.5641951147736119e-18, 4.1792457685713468e-19, 3.5191108460642354e-20, 2.7207846792186873e-21, 1.9282493305400296e-22, 1.2504748686909515e-23, 7.4065187877720327e-25, 3.9986259229284162e-26, 1.9635223775022683e-27, 8.7497557637466758e-29, 3.5296150194332557e-30, 1.2855517878737815e-31, 4.2155847725706856e-33, 1.2408362449919783e-34, 3.2676791768964119e-36, 7.6718304654322104e-38, 1.5996806743635201e-39, 2.9501316492565748e-41, 4.7903177946790465e-43, 6.8149889325650219e-45, 8.4490059406933366e-47, 9.0744120512086595e-49, 8.3883165922512944e-51, 6.6258941032515879e-53, 4.4365856613493741e-55, 2.4957603118464674e-57, 1.1677337858216425e-59, 4.4930692768932806e-62, 1.4034428812712122e-64, 3.5064990884120332e-67, 6.8889436382474771e-70, 1.0431826368600407e-72, 1.1892107956658327e-75, 9.9220223776303372e-79, 5.8546944803309517e-82, 2.3418402716705127e-85, 6.0181049060844634e-89, 9.2663025096531715e-93, 7.7817715084363300e-97, 3.1218947762576099e-101, 4.9034921609592363e-106, 2.1732568643306002e-111, 1.4544742104415291e-117, 2.9742440544925765e-125}, + {4.2467223153569913e-126, 2.1660313165253327e-118, 3.3526412389934468e-112, 7.8089506311734750e-107, 5.1211062371557049e-102, 1.3128438701986923e-97, 1.6059434510399780e-93, 1.0704932710164072e-89, 4.2723909537910979e-86, 1.0948479687576274e-82, 1.9009714466058216e-79, 2.3333732870895970e-76, 2.0954987289754821e-73, 1.4163011238027347e-70, 7.3764205708401192e-68, 3.0202620912677113e-65, 9.8899383346021114e-63, 2.6286294129074487e-60, 5.7447123101943819e-58, 1.0441146661857655e-55, 1.5941894796140349e-53, 2.0631744724119192e-51, 2.2815057723526744e-49, 2.1713655679015281e-47, 1.7902127496153674e-45, 1.2862015727088547e-43, 8.0963481474532886e-42, 4.4873140335977730e-40, 2.1997031006119584e-38, 9.5769420875142906e-37, 3.7173934630972095e-35, 1.2910298923887236e-33, 4.0247941719917949e-32, 1.1297479501227750e-30, 2.8633730681601511e-29, 6.5701662464695220e-28, 1.3681807173905664e-26, 2.5916454156396681e-25, 4.4751190749666469e-24, 7.0583497822483184e-23, 1.0188011695097018e-21, 1.3481278810188344e-20, 1.6381331947152628e-19, 1.8307185107770479e-18, 1.8844546640240470e-17, 1.7891286411123497e-16, 1.5687514682212088e-15, 1.2719076381502738e-14, 9.5465675547568851e-14, 6.6405134257786806e-13, 4.2851307836098596e-12, 2.5677582201989908e-11, 1.4301024597508902e-10, 7.4092720692344339e-10, 3.5737970851749710e-09, 1.6060537813990750e-08, 6.7293992111962037e-08, 2.6306912128825106e-07, 9.6009499955544809e-07, 3.2731466120984474e-06, 1.0429494937549579e-05, 3.1076452822469759e-05, 8.6632019755194801e-05, 2.2604661890533189e-04, 5.5229314310309603e-04, 1.2640347665701273e-03, 2.7109305106750477e-03, 5.4498805064709423e-03, 1.0272859026411405e-02, 1.8161242168807858e-02, 3.0119768029475406e-02, 4.6870503949025956e-02, 6.8449129121212759e-02, 9.3826040853472042e-02, 1.2073175170965833e-01, 1.4585002297738520e-01, 1.6542893986636190e-01, 1.7618076008397315e-01, 1.7618076008397315e-01, 1.6542893986636190e-01, 1.4585002297738520e-01, 1.2073175170965833e-01, 9.3826040853472042e-02, 6.8449129121212759e-02, 4.6870503949025956e-02, 3.0119768029475406e-02, 1.8161242168807858e-02, 1.0272859026411405e-02, 5.4498805064709423e-03, 2.7109305106750477e-03, 1.2640347665701273e-03, 5.5229314310309603e-04, 2.2604661890533189e-04, 8.6632019755194801e-05, 3.1076452822469759e-05, 1.0429494937549579e-05, 3.2731466120984474e-06, 9.6009499955544809e-07, 2.6306912128825106e-07, 6.7293992111962037e-08, 1.6060537813990750e-08, 3.5737970851749710e-09, 7.4092720692344339e-10, 1.4301024597508902e-10, 2.5677582201989908e-11, 4.2851307836098596e-12, 6.6405134257786806e-13, 9.5465675547568851e-14, 1.2719076381502738e-14, 1.5687514682212088e-15, 1.7891286411123497e-16, 1.8844546640240470e-17, 1.8307185107770479e-18, 1.6381331947152628e-19, 1.3481278810188344e-20, 1.0188011695097018e-21, 7.0583497822483184e-23, 4.4751190749666469e-24, 2.5916454156396681e-25, 1.3681807173905664e-26, 6.5701662464695220e-28, 2.8633730681601511e-29, 1.1297479501227750e-30, 4.0247941719917949e-32, 1.2910298923887236e-33, 3.7173934630972095e-35, 9.5769420875142906e-37, 2.1997031006119584e-38, 4.4873140335977730e-40, 8.0963481474532886e-42, 1.2862015727088547e-43, 1.7902127496153674e-45, 2.1713655679015281e-47, 2.2815057723526744e-49, 2.0631744724119192e-51, 1.5941894796140349e-53, 1.0441146661857655e-55, 5.7447123101943819e-58, 2.6286294129074487e-60, 9.8899383346021114e-63, 3.0202620912677113e-65, 7.3764205708401192e-68, 1.4163011238027347e-70, 2.0954987289754821e-73, 2.3333732870895970e-76, 1.9009714466058216e-79, 1.0948479687576274e-82, 4.2723909537910979e-86, 1.0704932710164072e-89, 1.6059434510399780e-93, 1.3128438701986923e-97, 5.1211062371557049e-102, 7.8089506311734750e-107, 3.3526412389934468e-112, 2.1660313165253327e-118, 4.2467223153569913e-126}, + {6.0622191716662980e-127, 3.2243541187800939e-119, 5.1690742816237208e-113, 1.2426977160105404e-107, 8.3933287533777738e-103, 2.2126569238728289e-98, 2.7801189404282378e-94, 1.9017852686354782e-90, 7.7836404960844694e-87, 2.0443095742420186e-83, 3.6361329490246816e-80, 4.5702928776404487e-77, 4.2014053957085256e-74, 2.9059246516402931e-71, 1.5484204394570369e-68, 6.4850166385488236e-66, 2.1717290123179292e-63, 5.9022979463583546e-61, 1.3188160319392796e-58, 2.4504276066974761e-56, 3.8244861009984640e-54, 5.0591506359259702e-52, 5.7180427835175108e-50, 5.5619189779622956e-48, 4.6865094097082296e-46, 3.4411166261243821e-44, 2.2137173158797545e-42, 1.2539021346574782e-40, 6.2819019919798964e-39, 2.7952039819044771e-37, 1.1089145782361913e-35, 3.9362772026982286e-34, 1.2543049763002862e-32, 3.5989403271252947e-31, 9.3246229360624703e-30, 2.1873567871874991e-28, 4.6570323992852519e-27, 9.0198508148124766e-26, 1.5926655666987673e-24, 2.5689779244357800e-23, 3.7925166697437060e-22, 5.1332963733171119e-21, 6.3810270087780860e-20, 7.2960970893548457e-19, 7.6848696141461809e-18, 7.4667368566800348e-17, 6.7010236404093807e-16, 5.5616305380816712e-15, 4.2738351786402332e-14, 3.0441295544509839e-13, 2.0118060311112926e-12, 1.2348350013212526e-11, 7.0457887005315459e-11, 3.7404445985544352e-10, 1.8490262742729560e-09, 8.5176899942265963e-09, 3.6590845237002989e-08, 1.4668615688059134e-07, 5.4909587760916178e-07, 1.9204753233550013e-06, 6.2793321142086111e-06, 1.9203890628511156e-05, 5.4960123823238632e-05, 1.4726036700166861e-04, 3.6956136752144001e-04, 8.6899815474605370e-04, 1.9153075674406669e-03, 3.9581151034971717e-03, 7.6718266966305298e-03, 1.3950429172087464e-02, 2.3804589918929770e-02, 3.8125218704480275e-02, 5.7322493628469834e-02, 8.0922651951388633e-02, 1.0727720003748800e-01, 1.3356293292585539e-01, 1.5618653283532280e-01, 1.7155657639082103e-01, 1.7700824722075201e-01, 1.7155657639082103e-01, 1.5618653283532280e-01, 1.3356293292585539e-01, 1.0727720003748800e-01, 8.0922651951388633e-02, 5.7322493628469834e-02, 3.8125218704480275e-02, 2.3804589918929770e-02, 1.3950429172087464e-02, 7.6718266966305298e-03, 3.9581151034971717e-03, 1.9153075674406669e-03, 8.6899815474605370e-04, 3.6956136752144001e-04, 1.4726036700166861e-04, 5.4960123823238632e-05, 1.9203890628511156e-05, 6.2793321142086111e-06, 1.9204753233550013e-06, 5.4909587760916178e-07, 1.4668615688059134e-07, 3.6590845237002989e-08, 8.5176899942265963e-09, 1.8490262742729560e-09, 3.7404445985544352e-10, 7.0457887005315459e-11, 1.2348350013212526e-11, 2.0118060311112926e-12, 3.0441295544509839e-13, 4.2738351786402332e-14, 5.5616305380816712e-15, 6.7010236404093807e-16, 7.4667368566800348e-17, 7.6848696141461809e-18, 7.2960970893548457e-19, 6.3810270087780860e-20, 5.1332963733171119e-21, 3.7925166697437060e-22, 2.5689779244357800e-23, 1.5926655666987673e-24, 9.0198508148124766e-26, 4.6570323992852519e-27, 2.1873567871874991e-28, 9.3246229360624703e-30, 3.5989403271252947e-31, 1.2543049763002862e-32, 3.9362772026982286e-34, 1.1089145782361913e-35, 2.7952039819044771e-37, 6.2819019919798964e-39, 1.2539021346574782e-40, 2.2137173158797545e-42, 3.4411166261243821e-44, 4.6865094097082296e-46, 5.5619189779622956e-48, 5.7180427835175108e-50, 5.0591506359259702e-52, 3.8244861009984640e-54, 2.4504276066974761e-56, 1.3188160319392796e-58, 5.9022979463583546e-61, 2.1717290123179292e-63, 6.4850166385488236e-66, 1.5484204394570369e-68, 2.9059246516402931e-71, 4.2014053957085256e-74, 4.5702928776404487e-77, 3.6361329490246816e-80, 2.0443095742420186e-83, 7.7836404960844694e-87, 1.9017852686354782e-90, 2.7801189404282378e-94, 2.2126569238728289e-98, 8.3933287533777738e-103, 1.2426977160105404e-107, 5.1690742816237208e-113, 3.2243541187800939e-119, 6.0622191716662980e-127}, + {8.6518898286288247e-128, 4.7977981754547922e-120, 7.9650930361988897e-114, 1.9761840987326553e-108, 1.3744652069324438e-103, 3.7255148645554058e-99, 4.8074121331969427e-95, 3.3744153060134342e-91, 1.4161180265335159e-87, 3.8114504571794760e-84, 6.9438585136020447e-81, 8.9360817516471687e-78, 8.4079759000226087e-75, 5.9504405763416772e-72, 3.2435033695316742e-69, 1.3893312175841125e-66, 4.7576408366455308e-64, 1.3220024862368775e-61, 3.0197052622687561e-59, 5.7351470833255443e-57, 9.1486995119191431e-55, 1.2368470663040083e-52, 1.4286078076592960e-50, 1.4200335880405776e-48, 1.2226957787809403e-46, 9.1739205502621965e-45, 6.0306042099204429e-43, 3.4904884601063066e-41, 1.7869095381531890e-39, 8.1249855483381444e-38, 3.2939528684311649e-36, 1.1948989473488384e-34, 3.8912956469188826e-33, 1.1411267330350244e-31, 3.0219294698888464e-30, 7.2459465976943397e-29, 1.5770256477583313e-27, 3.1226061139317796e-26, 5.6372579181684656e-25, 9.2975592528325581e-24, 1.4036014280320261e-22, 1.9429670019227641e-21, 2.4703591186430466e-20, 2.8894203773544814e-19, 3.1135796480328694e-18, 3.0953725694775336e-17, 2.8427562189767261e-16, 2.4147784190996735e-15, 1.8994699453982887e-14, 1.3851048606782092e-13, 9.3729953674226721e-13, 5.8917523372705995e-12, 3.4433525991626855e-11, 1.8726953725774312e-10, 9.4854377303416358e-10, 4.4780357696096071e-09, 1.9718477984120434e-08, 8.1042320257489110e-08, 3.1108717616071734e-07, 1.1159535961120921e-06, 3.7432563998726419e-06, 1.1746874098316171e-05, 3.4504766489542566e-05, 9.4911766414585672e-05, 2.4458580745649063e-04, 5.9072464709476020e-04, 1.3376446613946990e-03, 2.8408258176521148e-03, 5.6601830605110866e-03, 1.0583273905359803e-02, 1.8574752611538813e-02, 3.0608185223036027e-02, 4.7364212800332400e-02, 6.8839337618374755e-02, 9.3985530465238165e-02, 1.2055262431349997e-01, 1.4528684159808489e-01, 1.6452871112826625e-01, 1.7508305167467292e-01, 1.7508305167467292e-01, 1.6452871112826625e-01, 1.4528684159808489e-01, 1.2055262431349997e-01, 9.3985530465238165e-02, 6.8839337618374755e-02, 4.7364212800332400e-02, 3.0608185223036027e-02, 1.8574752611538813e-02, 1.0583273905359803e-02, 5.6601830605110866e-03, 2.8408258176521148e-03, 1.3376446613946990e-03, 5.9072464709476020e-04, 2.4458580745649063e-04, 9.4911766414585672e-05, 3.4504766489542566e-05, 1.1746874098316171e-05, 3.7432563998726419e-06, 1.1159535961120921e-06, 3.1108717616071734e-07, 8.1042320257489110e-08, 1.9718477984120434e-08, 4.4780357696096071e-09, 9.4854377303416358e-10, 1.8726953725774312e-10, 3.4433525991626855e-11, 5.8917523372705995e-12, 9.3729953674226721e-13, 1.3851048606782092e-13, 1.8994699453982887e-14, 2.4147784190996735e-15, 2.8427562189767261e-16, 3.0953725694775336e-17, 3.1135796480328694e-18, 2.8894203773544814e-19, 2.4703591186430466e-20, 1.9429670019227641e-21, 1.4036014280320261e-22, 9.2975592528325581e-24, 5.6372579181684656e-25, 3.1226061139317796e-26, 1.5770256477583313e-27, 7.2459465976943397e-29, 3.0219294698888464e-30, 1.1411267330350244e-31, 3.8912956469188826e-33, 1.1948989473488384e-34, 3.2939528684311649e-36, 8.1249855483381444e-38, 1.7869095381531890e-39, 3.4904884601063066e-41, 6.0306042099204429e-43, 9.1739205502621965e-45, 1.2226957787809403e-46, 1.4200335880405776e-48, 1.4286078076592960e-50, 1.2368470663040083e-52, 9.1486995119191431e-55, 5.7351470833255443e-57, 3.0197052622687561e-59, 1.3220024862368775e-61, 4.7576408366455308e-64, 1.3893312175841125e-66, 3.2435033695316742e-69, 5.9504405763416772e-72, 8.4079759000226087e-75, 8.9360817516471687e-78, 6.9438585136020447e-81, 3.8114504571794760e-84, 1.4161180265335159e-87, 3.3744153060134342e-91, 4.8074121331969427e-95, 3.7255148645554058e-99, 1.3744652069324438e-103, 1.9761840987326553e-108, 7.9650930361988897e-114, 4.7977981754547922e-120, 8.6518898286288247e-128}, + {1.2345052237856376e-128, 7.1361565819334150e-121, 1.2266594150983389e-114, 3.1403768309606574e-109, 2.2488806415651994e-104, 6.2666361422341182e-100, 8.3038517132199445e-96, 5.9799996465821154e-92, 2.5729286682716097e-88, 7.0956475615088519e-85, 1.3239358802678529e-81, 1.7442238644011473e-78, 1.6795285148575302e-75, 1.2160739161745740e-72, 6.7800483155694390e-70, 2.9698887117979696e-67, 1.0398334915263462e-64, 2.9537631885955336e-62, 6.8964075076110458e-60, 1.3386610121664405e-57, 2.1822972256453033e-55, 3.0148592722499396e-53, 3.5582391595026354e-51, 3.6138684655576511e-49, 3.1792871272966973e-47, 2.4372213779029665e-45, 1.6369116080171861e-43, 9.6799943605644117e-42, 5.0631425091072337e-40, 2.3522144528005868e-38, 9.7436152093981038e-37, 3.6115822674301904e-35, 1.2018288490038798e-33, 3.6015212879811887e-32, 9.7468625406557925e-31, 2.3885355396506504e-29, 5.3132702519188496e-28, 1.0753756973350715e-26, 1.9845716557598769e-25, 3.3462806594548906e-24, 5.1650319326919827e-23, 7.3109577835953338e-22, 9.5059376788875581e-21, 1.1371572178214573e-19, 1.2534183670047640e-18, 1.2747621562807485e-17, 1.1978221703435283e-16, 1.0411788127158037e-15, 8.3817954183785831e-15, 6.2561571481732302e-14, 4.3340112417705868e-13, 2.7894047381925510e-12, 1.6694572089431568e-11, 9.2995420785846948e-11, 4.8253510985881196e-10, 2.3340778029825478e-09, 1.0532686874011172e-08, 4.4371096492273068e-08, 1.7461444759106688e-07, 6.4230905783791856e-07, 2.2097354109635801e-06, 7.1138004485475131e-06, 2.1441047304603760e-05, 6.0530803203101914e-05, 1.6013349936228681e-04, 3.9713567276994117e-04, 9.2365343040052964e-04, 2.0153124277213861e-03, 4.1264467864295497e-03, 7.9311452492789869e-03, 1.4313136262234679e-02, 2.4259110409796711e-02, 3.8623061726879737e-02, 5.7773645171755317e-02, 8.1206842893413358e-02, 1.0727363982645181e-01, 1.3319196312197995e-01, 1.5544764635273797e-01, 1.7054438857615731e-01, 1.7589498780426926e-01, 1.7054438857615731e-01, 1.5544764635273797e-01, 1.3319196312197995e-01, 1.0727363982645181e-01, 8.1206842893413358e-02, 5.7773645171755317e-02, 3.8623061726879737e-02, 2.4259110409796711e-02, 1.4313136262234679e-02, 7.9311452492789869e-03, 4.1264467864295497e-03, 2.0153124277213861e-03, 9.2365343040052964e-04, 3.9713567276994117e-04, 1.6013349936228681e-04, 6.0530803203101914e-05, 2.1441047304603760e-05, 7.1138004485475131e-06, 2.2097354109635801e-06, 6.4230905783791856e-07, 1.7461444759106688e-07, 4.4371096492273068e-08, 1.0532686874011172e-08, 2.3340778029825478e-09, 4.8253510985881196e-10, 9.2995420785846948e-11, 1.6694572089431568e-11, 2.7894047381925510e-12, 4.3340112417705868e-13, 6.2561571481732302e-14, 8.3817954183785831e-15, 1.0411788127158037e-15, 1.1978221703435283e-16, 1.2747621562807485e-17, 1.2534183670047640e-18, 1.1371572178214573e-19, 9.5059376788875581e-21, 7.3109577835953338e-22, 5.1650319326919827e-23, 3.3462806594548906e-24, 1.9845716557598769e-25, 1.0753756973350715e-26, 5.3132702519188496e-28, 2.3885355396506504e-29, 9.7468625406557925e-31, 3.6015212879811887e-32, 1.2018288490038798e-33, 3.6115822674301904e-35, 9.7436152093981038e-37, 2.3522144528005868e-38, 5.0631425091072337e-40, 9.6799943605644117e-42, 1.6369116080171861e-43, 2.4372213779029665e-45, 3.1792871272966973e-47, 3.6138684655576511e-49, 3.5582391595026354e-51, 3.0148592722499396e-53, 2.1822972256453033e-55, 1.3386610121664405e-57, 6.8964075076110458e-60, 2.9537631885955336e-62, 1.0398334915263462e-64, 2.9698887117979696e-67, 6.7800483155694390e-70, 1.2160739161745740e-72, 1.6795285148575302e-75, 1.7442238644011473e-78, 1.3239358802678529e-81, 7.0956475615088519e-85, 2.5729286682716097e-88, 5.9799996465821154e-92, 8.3038517132199445e-96, 6.2666361422341182e-100, 2.2488806415651994e-104, 3.1403768309606574e-109, 1.2266594150983389e-114, 7.1361565819334150e-121, 1.2345052237856376e-128}, + {1.7610777213868225e-129, 1.0609912453053086e-121, 1.8880558326632475e-115, 4.9869144791066677e-110, 3.6765138012657772e-105, 1.0530846293412266e-100, 1.4327597465974048e-96, 1.0584620865577655e-92, 4.6684664948676272e-89, 1.3190436630179440e-85, 2.5202632570592097e-82, 3.3987392362121908e-79, 3.3488181154099359e-76, 2.4804288326920011e-73, 1.4143430079239634e-70, 6.3346915410241234e-68, 2.2674306256941818e-65, 6.5836081498721399e-63, 1.5709872468845785e-60, 3.1162632356321267e-58, 5.1910061298697851e-56, 7.3273399650957289e-54, 8.8354796635334199e-52, 9.1677552430019203e-50, 8.2395121572045278e-48, 6.4526516804970545e-46, 4.4272600478065905e-44, 2.6745508857556167e-42, 1.4291089046778579e-40, 6.7826401946708970e-39, 2.8703150932676095e-37, 1.0869482703973487e-35, 3.6955025716069553e-34, 1.1315067191371783e-32, 3.1289601063429292e-31, 7.8353356972027161e-30, 1.7811808982463465e-28, 3.6843324819342597e-27, 6.9494876383385912e-26, 1.1977696964648504e-24, 1.8899444794564548e-23, 2.7350044749786203e-22, 3.6360647433609545e-21, 4.4479270726420680e-20, 5.0139935781581053e-19, 5.2157884028434802e-18, 5.0135017597656447e-17, 4.4585078370462008e-16, 3.6726238537048878e-15, 2.8053332193363147e-14, 1.9891563745557595e-13, 1.3105682814703333e-12, 8.0308637715632703e-12, 4.5809917511320124e-11, 2.4345153103464099e-10, 1.2063179828327093e-09, 5.5773560719102751e-09, 2.4077676519331747e-08, 9.7119175861531978e-08, 3.6624118990378204e-07, 1.2919701008614705e-06, 4.2657607173255093e-06, 1.3189244631563864e-05, 3.8205770006826046e-05, 1.0373273668170783e-04, 2.6409447862081663e-04, 6.3070332659971552e-04, 1.4134038747122414e-03, 2.9731958710714898e-03, 5.8725347587191210e-03, 1.0894054653347555e-02, 1.8985454327504647e-02, 3.1089543185356148e-02, 4.7846811856586229e-02, 6.9216492829879864e-02, 9.4133897771831843e-02, 1.2036875882166113e-01, 1.4472841947349580e-01, 1.6364277404586250e-01, 1.7400560617482017e-01, 1.7400560617482017e-01, 1.6364277404586250e-01, 1.4472841947349580e-01, 1.2036875882166113e-01, 9.4133897771831843e-02, 6.9216492829879864e-02, 4.7846811856586229e-02, 3.1089543185356148e-02, 1.8985454327504647e-02, 1.0894054653347555e-02, 5.8725347587191210e-03, 2.9731958710714898e-03, 1.4134038747122414e-03, 6.3070332659971552e-04, 2.6409447862081663e-04, 1.0373273668170783e-04, 3.8205770006826046e-05, 1.3189244631563864e-05, 4.2657607173255093e-06, 1.2919701008614705e-06, 3.6624118990378204e-07, 9.7119175861531978e-08, 2.4077676519331747e-08, 5.5773560719102751e-09, 1.2063179828327093e-09, 2.4345153103464099e-10, 4.5809917511320124e-11, 8.0308637715632703e-12, 1.3105682814703333e-12, 1.9891563745557595e-13, 2.8053332193363147e-14, 3.6726238537048878e-15, 4.4585078370462008e-16, 5.0135017597656447e-17, 5.2157884028434802e-18, 5.0139935781581053e-19, 4.4479270726420680e-20, 3.6360647433609545e-21, 2.7350044749786203e-22, 1.8899444794564548e-23, 1.1977696964648504e-24, 6.9494876383385912e-26, 3.6843324819342597e-27, 1.7811808982463465e-28, 7.8353356972027161e-30, 3.1289601063429292e-31, 1.1315067191371783e-32, 3.6955025716069553e-34, 1.0869482703973487e-35, 2.8703150932676095e-37, 6.7826401946708970e-39, 1.4291089046778579e-40, 2.6745508857556167e-42, 4.4272600478065905e-44, 6.4526516804970545e-46, 8.2395121572045278e-48, 9.1677552430019203e-50, 8.8354796635334199e-52, 7.3273399650957289e-54, 5.1910061298697851e-56, 3.1162632356321267e-58, 1.5709872468845785e-60, 6.5836081498721399e-63, 2.2674306256941818e-65, 6.3346915410241234e-68, 1.4143430079239634e-70, 2.4804288326920011e-73, 3.3488181154099359e-76, 3.3987392362121908e-79, 2.5202632570592097e-82, 1.3190436630179440e-85, 4.6684664948676272e-89, 1.0584620865577655e-92, 1.4327597465974048e-96, 1.0530846293412266e-100, 3.6765138012657772e-105, 4.9869144791066677e-110, 1.8880558326632475e-115, 1.0609912453053086e-121, 1.7610777213868225e-129}, + {2.5117056700120872e-130, 1.5768344953215994e-122, 2.9044636530400262e-116, 7.9137283674998714e-111, 6.0054708822621273e-106, 1.7679796472043246e-101, 2.4694368635244847e-97, 1.8712284923478763e-93, 8.4595142859097527e-90, 2.4484925972797376e-86, 4.7901098788291739e-83, 6.6115362451933797e-80, 6.6651975922997095e-77, 5.0496259060528478e-74, 2.9443577961646315e-71, 1.3482570840246656e-68, 4.9330325826042063e-66, 1.4638938206976037e-63, 3.5696603658904023e-61, 7.2351735603462302e-59, 1.2313651255661928e-56, 1.7756983991411928e-54, 2.1873288432589287e-52, 2.3183952076674861e-50, 2.1283904185528713e-48, 1.7025628600075561e-46, 1.1931897574643388e-44, 7.3626408195179616e-43, 4.0184547253394729e-41, 1.9480947197049647e-39, 8.4210939788616602e-38, 3.2575341809749061e-36, 1.1313879341749972e-34, 3.5389381244383855e-33, 9.9980778309899927e-32, 2.5579997011243763e-30, 5.9416331503292959e-29, 1.2558645009560268e-27, 2.4207882624773725e-26, 4.2641635772547449e-25, 6.8770962222233684e-24, 1.0173048420715203e-22, 1.3826289575432440e-21, 1.7292550621372860e-20, 1.9932479444365377e-19, 2.1204345027937428e-18, 2.0846204533947437e-17, 1.8963226940193161e-16, 1.5980648038540025e-15, 1.2489882385266198e-14, 9.0627897868794926e-14, 6.1113514542896781e-13, 3.8334734795673616e-12, 2.2387867842316195e-11, 1.2183208011102774e-10, 6.1827585936607041e-10, 2.9281826160122555e-09, 1.2951325071150348e-08, 5.3532512893353530e-08, 2.0690866853712093e-07, 7.4825803592771974e-07, 2.5332274890078433e-06, 8.0328671931181133e-06, 2.3869848947287937e-05, 6.6497705172595715e-05, 1.7374941584438457e-04, 4.2595976788697434e-04, 9.8016363676181151e-04, 2.1176656262735217e-03, 4.2971163011999540e-03, 8.1917798784339399e-03, 1.4674728608435711e-02, 2.4708741311255288e-02, 3.9111739287652818e-02, 5.8212483797557772e-02, 8.1478613249930595e-02, 1.0726183985947185e-01, 1.3282086880025051e-01, 1.5471842089261012e-01, 1.6954985984858575e-01, 1.7480247235206883e-01, 1.6954985984858575e-01, 1.5471842089261012e-01, 1.3282086880025051e-01, 1.0726183985947185e-01, 8.1478613249930595e-02, 5.8212483797557772e-02, 3.9111739287652818e-02, 2.4708741311255288e-02, 1.4674728608435711e-02, 8.1917798784339399e-03, 4.2971163011999540e-03, 2.1176656262735217e-03, 9.8016363676181151e-04, 4.2595976788697434e-04, 1.7374941584438457e-04, 6.6497705172595715e-05, 2.3869848947287937e-05, 8.0328671931181133e-06, 2.5332274890078433e-06, 7.4825803592771974e-07, 2.0690866853712093e-07, 5.3532512893353530e-08, 1.2951325071150348e-08, 2.9281826160122555e-09, 6.1827585936607041e-10, 1.2183208011102774e-10, 2.2387867842316195e-11, 3.8334734795673616e-12, 6.1113514542896781e-13, 9.0627897868794926e-14, 1.2489882385266198e-14, 1.5980648038540025e-15, 1.8963226940193161e-16, 2.0846204533947437e-17, 2.1204345027937428e-18, 1.9932479444365377e-19, 1.7292550621372860e-20, 1.3826289575432440e-21, 1.0173048420715203e-22, 6.8770962222233684e-24, 4.2641635772547449e-25, 2.4207882624773725e-26, 1.2558645009560268e-27, 5.9416331503292959e-29, 2.5579997011243763e-30, 9.9980778309899927e-32, 3.5389381244383855e-33, 1.1313879341749972e-34, 3.2575341809749061e-36, 8.4210939788616602e-38, 1.9480947197049647e-39, 4.0184547253394729e-41, 7.3626408195179616e-43, 1.1931897574643388e-44, 1.7025628600075561e-46, 2.1283904185528713e-48, 2.3183952076674861e-50, 2.1873288432589287e-52, 1.7756983991411928e-54, 1.2313651255661928e-56, 7.2351735603462302e-59, 3.5696603658904023e-61, 1.4638938206976037e-63, 4.9330325826042063e-66, 1.3482570840246656e-68, 2.9443577961646315e-71, 5.0496259060528478e-74, 6.6651975922997095e-77, 6.6115362451933797e-80, 4.7901098788291739e-83, 2.4484925972797376e-86, 8.4595142859097527e-90, 1.8712284923478763e-93, 2.4694368635244847e-97, 1.7679796472043246e-101, 6.0054708822621273e-106, 7.9137283674998714e-111, 2.9044636530400262e-116, 1.5768344953215994e-122, 2.5117056700120872e-130}, + {3.5814970887800193e-131, 2.3425513711144864e-123, 4.4656005878580503e-117, 1.2549679546936818e-111, 9.8017329285864726e-107, 2.9653839872557489e-102, 4.2516584957198355e-98, 3.3041628702723710e-94, 1.5309029297604490e-90, 4.5385580031078324e-87, 9.0901963341946014e-84, 1.2839971949179289e-80, 1.3242215741981033e-77, 1.0260459032147593e-74, 6.1171687686353920e-72, 2.8634705175373264e-69, 1.0708169155525760e-66, 3.2473167974844921e-64, 8.0909309792517176e-62, 1.6754390708913517e-59, 2.9129572580930014e-57, 4.2909222783948995e-55, 5.3988684348783699e-53, 5.8447003073435629e-51, 5.4802004204685326e-49, 4.4772141969183521e-47, 3.2045539320239441e-45, 2.0194963974060789e-43, 1.1256982521722169e-41, 5.5735541782797091e-40, 2.4607034140503088e-38, 9.7221219580876439e-37, 3.4489022958731964e-35, 1.1019416508568278e-33, 3.1800971964673699e-32, 8.3116537305566989e-31, 1.9723475111279380e-29, 4.2593300365187824e-28, 8.3889785533018652e-27, 1.5099943444312937e-25, 2.4887063965856610e-24, 3.7625921372478096e-23, 5.2269932699489526e-22, 6.6828358472667806e-21, 7.8752810946470447e-20, 8.5660876502561181e-19, 8.6117182742222153e-18, 8.0118871420831184e-17, 6.9061126848313650e-16, 5.5217099395406411e-15, 4.0993475210626060e-14, 2.8287311125546069e-13, 1.8159956877481757e-12, 1.0856048964794633e-11, 6.0482344698906487e-11, 3.1429016861706717e-10, 1.5244189642430853e-09, 6.9064794339712537e-09, 2.9246755983618971e-08, 1.1583508882541563e-07, 4.2933935551544649e-07, 1.4900490066410718e-06, 4.8446895241968929e-06, 1.4764162429716271e-05, 4.2191721743284952e-05, 1.1311130499099743e-04, 2.8458825008902025e-04, 6.7223242445783719e-04, 1.4912851650067261e-03, 3.1079648052231286e-03, 6.0868070844442837e-03, 1.1205047384266207e-02, 1.9393234478244935e-02, 3.1563859231069517e-02, 4.8318515012084520e-02, 6.9580992429206442e-02, 9.4271602476518737e-02, 1.2018047849522055e-01, 1.4417476260347803e-01, 1.6277076260081147e-01, 1.7294780784506847e-01, 1.7294780784506847e-01, 1.6277076260081147e-01, 1.4417476260347803e-01, 1.2018047849522055e-01, 9.4271602476518737e-02, 6.9580992429206442e-02, 4.8318515012084520e-02, 3.1563859231069517e-02, 1.9393234478244935e-02, 1.1205047384266207e-02, 6.0868070844442837e-03, 3.1079648052231286e-03, 1.4912851650067261e-03, 6.7223242445783719e-04, 2.8458825008902025e-04, 1.1311130499099743e-04, 4.2191721743284952e-05, 1.4764162429716271e-05, 4.8446895241968929e-06, 1.4900490066410718e-06, 4.2933935551544649e-07, 1.1583508882541563e-07, 2.9246755983618971e-08, 6.9064794339712537e-09, 1.5244189642430853e-09, 3.1429016861706717e-10, 6.0482344698906487e-11, 1.0856048964794633e-11, 1.8159956877481757e-12, 2.8287311125546069e-13, 4.0993475210626060e-14, 5.5217099395406411e-15, 6.9061126848313650e-16, 8.0118871420831184e-17, 8.6117182742222153e-18, 8.5660876502561181e-19, 7.8752810946470447e-20, 6.6828358472667806e-21, 5.2269932699489526e-22, 3.7625921372478096e-23, 2.4887063965856610e-24, 1.5099943444312937e-25, 8.3889785533018652e-27, 4.2593300365187824e-28, 1.9723475111279380e-29, 8.3116537305566989e-31, 3.1800971964673699e-32, 1.1019416508568278e-33, 3.4489022958731964e-35, 9.7221219580876439e-37, 2.4607034140503088e-38, 5.5735541782797091e-40, 1.1256982521722169e-41, 2.0194963974060789e-43, 3.2045539320239441e-45, 4.4772141969183521e-47, 5.4802004204685326e-49, 5.8447003073435629e-51, 5.3988684348783699e-53, 4.2909222783948995e-55, 2.9129572580930014e-57, 1.6754390708913517e-59, 8.0909309792517176e-62, 3.2473167974844921e-64, 1.0708169155525760e-66, 2.8634705175373264e-69, 6.1171687686353920e-72, 1.0260459032147593e-74, 1.3242215741981033e-77, 1.2839971949179289e-80, 9.0901963341946014e-84, 4.5385580031078324e-87, 1.5309029297604490e-90, 3.3041628702723710e-94, 4.2516584957198355e-98, 2.9653839872557489e-102, 9.8017329285864726e-107, 1.2549679546936818e-111, 4.4656005878580503e-117, 2.3425513711144864e-123, 3.5814970887800193e-131}, + {5.1058382388659269e-132, 3.4787452134261360e-124, 6.8621328476606254e-118, 1.9887929527241800e-112, 1.5984806988768767e-107, 4.9691113060541562e-103, 7.3123967185564915e-99, 5.8275341127995904e-95, 2.7668599413210135e-91, 8.4008516795919007e-88, 1.7224108182682644e-84, 2.4894935837631581e-81, 2.6262929329466987e-78, 2.0809367058140554e-75, 1.2683653376027615e-72, 6.0687062439892660e-70, 2.3192577160038707e-67, 7.1865618890614741e-65, 1.8293638224274986e-62, 3.8697820973543049e-60, 6.8723829518191775e-58, 1.0339639913382959e-55, 1.3286530592326351e-53, 1.4689382904493016e-51, 1.4065458992870208e-49, 1.1734649400073276e-47, 8.5768492248869891e-46, 5.5194857702963127e-44, 3.1417689022491827e-42, 1.5884965434373284e-40, 7.1618254982458697e-39, 2.8896676701682861e-37, 1.0469000850542053e-35, 3.4161633966903074e-34, 1.0069252468038614e-32, 2.6880974156578509e-31, 6.5158094363462302e-30, 1.4374174204375062e-28, 2.8922727144899803e-27, 5.3189806528533866e-26, 8.9574942952228153e-25, 1.3838820621840956e-23, 1.9647377828565719e-22, 2.5674274750397857e-21, 3.0926768131345034e-20, 3.4389885933401063e-19, 3.5348317750763591e-18, 3.3627744521880394e-17, 2.9643952991648909e-16, 2.4242278762902340e-15, 1.8410778220221309e-14, 1.2997777867558265e-13, 8.5384118147611980e-13, 5.2237944008745323e-12, 2.9789583264039043e-11, 1.5847474437596250e-10, 7.8704836352169759e-10, 3.6517281221510981e-09, 1.5839569546032163e-08, 6.4270494029387501e-08, 2.4409702642671850e-07, 8.6823986929119786e-07, 2.8938252044645185e-06, 9.0422158488303162e-06, 2.6500151909252169e-05, 7.2875309659252541e-05, 1.8812470050977485e-04, 4.5604422468456632e-04, 1.0385182654144745e-03, 2.2223166735266457e-03, 4.4700208091087738e-03, 8.4535858780912364e-03, 1.5035066629455310e-02, 2.5153428292907908e-02, 3.9591364280961522e-02, 5.8639320239639699e-02, 8.1738404552485058e-02, 1.0724220730838535e-01, 1.3244982464015054e-01, 1.5399867398459949e-01, 1.6857248411687309e-01, 1.7373006454622800e-01, 1.6857248411687309e-01, 1.5399867398459949e-01, 1.3244982464015054e-01, 1.0724220730838535e-01, 8.1738404552485058e-02, 5.8639320239639699e-02, 3.9591364280961522e-02, 2.5153428292907908e-02, 1.5035066629455310e-02, 8.4535858780912364e-03, 4.4700208091087738e-03, 2.2223166735266457e-03, 1.0385182654144745e-03, 4.5604422468456632e-04, 1.8812470050977485e-04, 7.2875309659252541e-05, 2.6500151909252169e-05, 9.0422158488303162e-06, 2.8938252044645185e-06, 8.6823986929119786e-07, 2.4409702642671850e-07, 6.4270494029387501e-08, 1.5839569546032163e-08, 3.6517281221510981e-09, 7.8704836352169759e-10, 1.5847474437596250e-10, 2.9789583264039043e-11, 5.2237944008745323e-12, 8.5384118147611980e-13, 1.2997777867558265e-13, 1.8410778220221309e-14, 2.4242278762902340e-15, 2.9643952991648909e-16, 3.3627744521880394e-17, 3.5348317750763591e-18, 3.4389885933401063e-19, 3.0926768131345034e-20, 2.5674274750397857e-21, 1.9647377828565719e-22, 1.3838820621840956e-23, 8.9574942952228153e-25, 5.3189806528533866e-26, 2.8922727144899803e-27, 1.4374174204375062e-28, 6.5158094363462302e-30, 2.6880974156578509e-31, 1.0069252468038614e-32, 3.4161633966903074e-34, 1.0469000850542053e-35, 2.8896676701682861e-37, 7.1618254982458697e-39, 1.5884965434373284e-40, 3.1417689022491827e-42, 5.5194857702963127e-44, 8.5768492248869891e-46, 1.1734649400073276e-47, 1.4065458992870208e-49, 1.4689382904493016e-51, 1.3286530592326351e-53, 1.0339639913382959e-55, 6.8723829518191775e-58, 3.8697820973543049e-60, 1.8293638224274986e-62, 7.1865618890614741e-65, 2.3192577160038707e-67, 6.0687062439892660e-70, 1.2683653376027615e-72, 2.0809367058140554e-75, 2.6262929329466987e-78, 2.4894935837631581e-81, 1.7224108182682644e-84, 8.4008516795919007e-88, 2.7668599413210135e-91, 5.8275341127995904e-95, 7.3123967185564915e-99, 4.9691113060541562e-103, 1.5984806988768767e-107, 1.9887929527241800e-112, 6.8621328476606254e-118, 3.4787452134261360e-124, 5.1058382388659269e-132}, + {7.2774136808374355e-133, 5.1640253363781065e-125, 1.0539163395229755e-118, 3.1495974864069521e-113, 2.6047400909049849e-108, 8.3190735956096083e-104, 1.2563394260844383e-99, 1.0266029334944310e-95, 4.9942483588606006e-92, 1.5528225080749898e-88, 3.2586916028699435e-85, 4.8189357949651464e-82, 5.1995900683110418e-79, 4.2125456733725475e-76, 2.6247146396219082e-73, 1.2834925357232391e-70, 5.0121772980919659e-68, 1.5867585378958465e-65, 4.1261409970889649e-63, 8.9152934736506373e-61, 1.6170383864591641e-58, 2.4845512749608618e-56, 3.2602867516914131e-54, 3.6806734534292869e-52, 3.5986560950072034e-50, 3.0655422197589668e-48, 2.2877484525825812e-46, 1.5032084002307616e-44, 8.7364621051992394e-43, 4.5101690564191873e-41, 2.0762677615749785e-39, 8.5540504547638604e-38, 3.1645195547118431e-36, 1.0544772050999357e-34, 3.1740376151073218e-33, 8.6536469704170907e-32, 2.1423361912655937e-30, 4.8272033657573108e-29, 9.9214758418835271e-28, 1.8639024742210292e-26, 3.2068221113110570e-25, 5.0619653821736361e-24, 7.3433969692709968e-23, 9.8063138469438635e-22, 1.2072647224673922e-20, 1.3721655943148051e-19, 1.4417902155501092e-18, 1.4022988180739114e-17, 1.2639871956315117e-16, 1.0570613866427036e-15, 8.2106561126223668e-15, 5.9294550957769600e-14, 3.9849788475246675e-13, 2.4946167855672290e-12, 1.4558577681248529e-11, 7.9272325104664409e-11, 4.0303485756427884e-10, 1.9146717079546461e-09, 8.5049436556100333e-09, 3.5346942618254887e-08, 1.3752997102467001e-07, 5.0124990214178011e-07, 1.7121991444326337e-06, 5.4842169146680313e-06, 1.6479308921225968e-05, 4.6474831646589210e-05, 1.2306336370474281e-04, 3.0608156336295680e-04, 7.1531332284984861e-04, 1.5712593917201550e-03, 3.2450562679797843e-03, 6.3028742438160333e-03, 1.1516105006399560e-02, 1.9797989451736150e-02, 3.2031157662458190e-02, 4.8779535009276516e-02, 6.9933221621689870e-02, 9.4399083753525778e-02, 1.1998808778160919e-01, 1.4362587120152381e-01, 1.6191232338499803e-01, 1.7190906682322146e-01, 1.7190906682322146e-01, 1.6191232338499803e-01, 1.4362587120152381e-01, 1.1998808778160919e-01, 9.4399083753525778e-02, 6.9933221621689870e-02, 4.8779535009276516e-02, 3.2031157662458190e-02, 1.9797989451736150e-02, 1.1516105006399560e-02, 6.3028742438160333e-03, 3.2450562679797843e-03, 1.5712593917201550e-03, 7.1531332284984861e-04, 3.0608156336295680e-04, 1.2306336370474281e-04, 4.6474831646589210e-05, 1.6479308921225968e-05, 5.4842169146680313e-06, 1.7121991444326337e-06, 5.0124990214178011e-07, 1.3752997102467001e-07, 3.5346942618254887e-08, 8.5049436556100333e-09, 1.9146717079546461e-09, 4.0303485756427884e-10, 7.9272325104664409e-11, 1.4558577681248529e-11, 2.4946167855672290e-12, 3.9849788475246675e-13, 5.9294550957769600e-14, 8.2106561126223668e-15, 1.0570613866427036e-15, 1.2639871956315117e-16, 1.4022988180739114e-17, 1.4417902155501092e-18, 1.3721655943148051e-19, 1.2072647224673922e-20, 9.8063138469438635e-22, 7.3433969692709968e-23, 5.0619653821736361e-24, 3.2068221113110570e-25, 1.8639024742210292e-26, 9.9214758418835271e-28, 4.8272033657573108e-29, 2.1423361912655937e-30, 8.6536469704170907e-32, 3.1740376151073218e-33, 1.0544772050999357e-34, 3.1645195547118431e-36, 8.5540504547638604e-38, 2.0762677615749785e-39, 4.5101690564191873e-41, 8.7364621051992394e-43, 1.5032084002307616e-44, 2.2877484525825812e-46, 3.0655422197589668e-48, 3.5986560950072034e-50, 3.6806734534292869e-52, 3.2602867516914131e-54, 2.4845512749608618e-56, 1.6170383864591641e-58, 8.9152934736506373e-61, 4.1261409970889649e-63, 1.5867585378958465e-65, 5.0121772980919659e-68, 1.2834925357232391e-70, 2.6247146396219082e-73, 4.2125456733725475e-76, 5.1995900683110418e-79, 4.8189357949651464e-82, 3.2586916028699435e-85, 1.5528225080749898e-88, 4.9942483588606006e-92, 1.0266029334944310e-95, 1.2563394260844383e-99, 8.3190735956096083e-104, 2.6047400909049849e-108, 3.1495974864069521e-113, 1.0539163395229755e-118, 5.1640253363781065e-125, 7.2774136808374355e-133}, + {1.0370401330404128e-133, 7.6628104007938171e-126, 1.6177944458582779e-119, 4.9846209741944082e-114, 4.2410903981966999e-109, 1.3914702767711137e-104, 2.1562790735643016e-100, 1.8064249655941844e-96, 9.0033176079341812e-93, 2.8662892545517945e-89, 6.1560200907369249e-86, 9.3130571849846176e-83, 1.0276539331534194e-79, 8.5120283276029899e-77, 5.4209234698248101e-74, 2.7089105182625548e-71, 1.0808323828410104e-68, 3.4954669585711314e-66, 9.2841597125229309e-64, 2.0487495492161133e-61, 3.7947795686740356e-59, 5.9537760035157825e-57, 7.9771959541897771e-55, 9.1949435242106659e-53, 9.1785078949346243e-51, 7.9824553719798949e-49, 6.0817267689790556e-47, 4.0796548388663509e-45, 2.4206136388252030e-43, 1.2757690988603576e-41, 5.9959663570350600e-40, 2.5220557090360086e-38, 9.5260156082741867e-37, 3.2409917090630152e-35, 9.9611495020508274e-34, 2.7731632192036800e-32, 7.0108006530723495e-31, 1.6132689567876035e-29, 3.3864807517869285e-28, 6.4981402796424245e-27, 1.1420079983768409e-25, 1.8415308229503966e-24, 2.7293664944237734e-23, 3.7240665643118182e-22, 4.6849502295754945e-21, 5.4418440370928148e-20, 5.8442290512558873e-19, 5.8103464142089000e-18, 5.3541848627525126e-17, 4.5782053131046985e-16, 3.6364250808804760e-15, 2.6857950742667181e-14, 1.8463211087063347e-13, 1.1824213225107695e-12, 7.0605885367663953e-12, 3.9342842554083200e-11, 2.0472924906259976e-10, 9.9563021167170463e-10, 4.5281139927096718e-09, 1.9271612548094547e-08, 7.6800568196628212e-08, 2.8675127848315921e-07, 1.0036330972927129e-06, 3.2945281705899829e-06, 1.0147672170741122e-05, 2.9341866948530294e-05, 7.9677853191228106e-05, 2.0327512248096151e-04, 4.8739807702018396e-04, 1.0987048493532403e-03, 2.3292137543048106e-03, 4.6450584683976901e-03, 8.7164233107623907e-03, 1.5394018995268760e-02, 2.5593125567577809e-02, 4.0062052918626051e-02, 5.9054458453798808e-02, 8.1986641314913386e-02, 1.0721512879081883e-01, 1.3207899230191014e-01, 1.5328822654091181e-01, 1.6761177530123578e-01, 1.7267715506412973e-01, 1.6761177530123578e-01, 1.5328822654091181e-01, 1.3207899230191014e-01, 1.0721512879081883e-01, 8.1986641314913386e-02, 5.9054458453798808e-02, 4.0062052918626051e-02, 2.5593125567577809e-02, 1.5394018995268760e-02, 8.7164233107623907e-03, 4.6450584683976901e-03, 2.3292137543048106e-03, 1.0987048493532403e-03, 4.8739807702018396e-04, 2.0327512248096151e-04, 7.9677853191228106e-05, 2.9341866948530294e-05, 1.0147672170741122e-05, 3.2945281705899829e-06, 1.0036330972927129e-06, 2.8675127848315921e-07, 7.6800568196628212e-08, 1.9271612548094547e-08, 4.5281139927096718e-09, 9.9563021167170463e-10, 2.0472924906259976e-10, 3.9342842554083200e-11, 7.0605885367663953e-12, 1.1824213225107695e-12, 1.8463211087063347e-13, 2.6857950742667181e-14, 3.6364250808804760e-15, 4.5782053131046985e-16, 5.3541848627525126e-17, 5.8103464142089000e-18, 5.8442290512558873e-19, 5.4418440370928148e-20, 4.6849502295754945e-21, 3.7240665643118182e-22, 2.7293664944237734e-23, 1.8415308229503966e-24, 1.1420079983768409e-25, 6.4981402796424245e-27, 3.3864807517869285e-28, 1.6132689567876035e-29, 7.0108006530723495e-31, 2.7731632192036800e-32, 9.9611495020508274e-34, 3.2409917090630152e-35, 9.5260156082741867e-37, 2.5220557090360086e-38, 5.9959663570350600e-40, 1.2757690988603576e-41, 2.4206136388252030e-43, 4.0796548388663509e-45, 6.0817267689790556e-47, 7.9824553719798949e-49, 9.1785078949346243e-51, 9.1949435242106659e-53, 7.9771959541897771e-55, 5.9537760035157825e-57, 3.7947795686740356e-59, 2.0487495492161133e-61, 9.2841597125229309e-64, 3.4954669585711314e-66, 1.0808323828410104e-68, 2.7089105182625548e-71, 5.4209234698248101e-74, 8.5120283276029899e-77, 1.0276539331534194e-79, 9.3130571849846176e-83, 6.1560200907369249e-86, 2.8662892545517945e-89, 9.0033176079341812e-93, 1.8064249655941844e-96, 2.1562790735643016e-100, 1.3914702767711137e-104, 4.2410903981966999e-109, 4.9846209741944082e-114, 1.6177944458582779e-119, 7.6628104007938171e-126, 1.0370401330404128e-133}, + {1.4774864044730919e-134, 1.1366413967312580e-126, 2.4820647345980668e-120, 7.8835864352328026e-115, 6.9000209771443205e-110, 2.3253044708336631e-105, 3.6970767260897540e-101, 3.1749907175216285e-97, 1.6210276225797838e-93, 5.2835329659655297e-90, 1.1612190047837748e-86, 1.7969751555347008e-83, 2.0276116391228268e-80, 1.7168527133451101e-77, 1.1174481216103580e-74, 5.7057155838516782e-72, 2.3257094876339456e-69, 7.6827297329990042e-67, 2.0840476902701378e-64, 4.6963320200403117e-62, 8.8821741614196649e-60, 1.4228297251266947e-57, 1.9462991520350709e-55, 2.2902568991273256e-53, 2.3338081888304624e-51, 2.0719270806826472e-49, 1.6113919045974023e-47, 1.1033912986165171e-45, 6.6828682986466127e-44, 3.5953723054115794e-42, 1.7249314720204933e-40, 7.4065841467302406e-39, 2.8558675123113318e-37, 9.9193674854686742e-36, 3.1125293650397015e-34, 8.8470553643068575e-33, 2.2836747845517017e-31, 5.3659089984759047e-30, 1.1502283587852324e-28, 2.2540053407015112e-27, 4.0457517920854419e-26, 6.6636084030909077e-25, 1.0088605806727544e-23, 1.4062620052335121e-22, 1.8074912939358217e-21, 2.1452843610753105e-20, 2.3544032965183590e-19, 2.3923239898564218e-18, 2.2533431601785240e-17, 1.9696954324441430e-16, 1.5995738956856818e-15, 1.2080546491164034e-14, 8.4930831160690606e-14, 5.5633632513833882e-13, 3.3984267451196722e-12, 1.9374997522123724e-11, 1.0317252591614767e-10, 5.1352562907714339e-10, 2.3907560585436029e-09, 1.0417563656335543e-08, 4.2512972951519652e-08, 1.6257453952247463e-07, 5.8290254892118051e-07, 1.9605333794325452e-06, 6.1886554017466215e-06, 1.8342475402473601e-05, 5.1067234537777706e-05, 1.3360429556693264e-04, 3.2858768305186580e-04, 7.5994560780524184e-04, 1.6532956640381497e-03, 3.3843936084184865e-03, 6.5206132604078895e-03, 1.1827087059306185e-02, 2.0199624381625723e-02, 3.2491469153777909e-02, 4.9230083099421298e-02, 7.0273553473008815e-02, 9.4516761260745735e-02, 1.1979187349505478e-01, 1.4308174026017673e-01, 1.6106711507035643e-01, 1.7088881774276651e-01, 1.7088881774276651e-01, 1.6106711507035643e-01, 1.4308174026017673e-01, 1.1979187349505478e-01, 9.4516761260745735e-02, 7.0273553473008815e-02, 4.9230083099421298e-02, 3.2491469153777909e-02, 2.0199624381625723e-02, 1.1827087059306185e-02, 6.5206132604078895e-03, 3.3843936084184865e-03, 1.6532956640381497e-03, 7.5994560780524184e-04, 3.2858768305186580e-04, 1.3360429556693264e-04, 5.1067234537777706e-05, 1.8342475402473601e-05, 6.1886554017466215e-06, 1.9605333794325452e-06, 5.8290254892118051e-07, 1.6257453952247463e-07, 4.2512972951519652e-08, 1.0417563656335543e-08, 2.3907560585436029e-09, 5.1352562907714339e-10, 1.0317252591614767e-10, 1.9374997522123724e-11, 3.3984267451196722e-12, 5.5633632513833882e-13, 8.4930831160690606e-14, 1.2080546491164034e-14, 1.5995738956856818e-15, 1.9696954324441430e-16, 2.2533431601785240e-17, 2.3923239898564218e-18, 2.3544032965183590e-19, 2.1452843610753105e-20, 1.8074912939358217e-21, 1.4062620052335121e-22, 1.0088605806727544e-23, 6.6636084030909077e-25, 4.0457517920854419e-26, 2.2540053407015112e-27, 1.1502283587852324e-28, 5.3659089984759047e-30, 2.2836747845517017e-31, 8.8470553643068575e-33, 3.1125293650397015e-34, 9.9193674854686742e-36, 2.8558675123113318e-37, 7.4065841467302406e-39, 1.7249314720204933e-40, 3.5953723054115794e-42, 6.6828682986466127e-44, 1.1033912986165171e-45, 1.6113919045974023e-47, 2.0719270806826472e-49, 2.3338081888304624e-51, 2.2902568991273256e-53, 1.9462991520350709e-55, 1.4228297251266947e-57, 8.8821741614196649e-60, 4.6963320200403117e-62, 2.0840476902701378e-64, 7.6827297329990042e-67, 2.3257094876339456e-69, 5.7057155838516782e-72, 1.1174481216103580e-74, 1.7168527133451101e-77, 2.0276116391228268e-80, 1.7969751555347008e-83, 1.1612190047837748e-86, 5.2835329659655297e-90, 1.6210276225797838e-93, 3.1749907175216285e-97, 3.6970767260897540e-101, 2.3253044708336631e-105, 6.9000209771443205e-110, 7.8835864352328026e-115, 2.4820647345980668e-120, 1.1366413967312580e-126, 1.4774864044730919e-134}, + {2.1045621159574830e-135, 1.6853736680140806e-127, 3.8060787191717414e-121, 1.2460431717780355e-115, 1.1217254900384875e-110, 3.8823686733906794e-106, 6.3324559268876792e-102, 5.5741078533835752e-98, 2.9150063258205350e-94, 9.7261605479925101e-91, 2.1872204017818973e-87, 3.4618487459964773e-84, 3.9938420292542256e-81, 3.4566329048643892e-78, 2.2990777865226915e-75, 1.1993601521489046e-72, 4.9937669382694245e-70, 1.6848180938195073e-67, 4.6671413158696264e-65, 1.0738850147584223e-62, 2.0736313112573398e-60, 3.3911184321991622e-58, 4.7353070830108189e-56, 5.6878446259603137e-54, 5.9160971507025675e-52, 5.3608992748856614e-50, 4.2554770940703958e-48, 2.9740995846398285e-46, 1.8385123238649587e-44, 1.0095495376276113e-42, 4.9435800520554766e-41, 2.1666198058800618e-39, 8.5272688786829149e-38, 3.0232780766836873e-36, 9.6838410701764544e-35, 2.8099176317436489e-33, 7.4047930191407272e-32, 1.7763620673555590e-30, 3.8878538387006395e-29, 7.7794521016127823e-28, 1.4259174843705503e-26, 2.3985064022625709e-25, 3.7088241471290263e-24, 5.2806166677136793e-23, 6.9334558099800012e-22, 8.4073193071442628e-21, 9.4275495388536763e-20, 9.7888471796527459e-19, 9.4228636835633407e-18, 8.4188202692459649e-17, 6.9888828000995662e-16, 5.3963258195263796e-15, 3.8792170840235010e-14, 2.5986297789613529e-13, 1.6235905955395716e-12, 9.4688541385973895e-12, 5.1587531828242437e-11, 2.6274698033796913e-10, 1.2519243488472937e-09, 5.5840692373466946e-09, 2.3330544086080361e-08, 9.1359564208430839e-08, 3.3548824403388151e-07, 1.1558985161302230e-06, 3.7384592935259604e-06, 1.1355193773739383e-05, 3.2404937824118138e-05, 8.6919300398468442e-05, 2.1921561912382546e-04, 5.2002884998328185e-04, 1.1607090699966350e-03, 2.4383039027033393e-03, 4.8221285878206101e-03, 8.9801569838840641e-03, 1.5751462301844443e-02, 2.6027795319202608e-02, 4.0523924217918790e-02, 5.9458195592787075e-02, 8.2223731723011229e-02, 1.0718097152174927e-01, 1.3170852135471239e-01, 1.5258690288545360e-01, 1.6666726633087006e-01, 1.7164316012362582e-01, 1.6666726633087006e-01, 1.5258690288545360e-01, 1.3170852135471239e-01, 1.0718097152174927e-01, 8.2223731723011229e-02, 5.9458195592787075e-02, 4.0523924217918790e-02, 2.6027795319202608e-02, 1.5751462301844443e-02, 8.9801569838840641e-03, 4.8221285878206101e-03, 2.4383039027033393e-03, 1.1607090699966350e-03, 5.2002884998328185e-04, 2.1921561912382546e-04, 8.6919300398468442e-05, 3.2404937824118138e-05, 1.1355193773739383e-05, 3.7384592935259604e-06, 1.1558985161302230e-06, 3.3548824403388151e-07, 9.1359564208430839e-08, 2.3330544086080361e-08, 5.5840692373466946e-09, 1.2519243488472937e-09, 2.6274698033796913e-10, 5.1587531828242437e-11, 9.4688541385973895e-12, 1.6235905955395716e-12, 2.5986297789613529e-13, 3.8792170840235010e-14, 5.3963258195263796e-15, 6.9888828000995662e-16, 8.4188202692459649e-17, 9.4228636835633407e-18, 9.7888471796527459e-19, 9.4275495388536763e-20, 8.4073193071442628e-21, 6.9334558099800012e-22, 5.2806166677136793e-23, 3.7088241471290263e-24, 2.3985064022625709e-25, 1.4259174843705503e-26, 7.7794521016127823e-28, 3.8878538387006395e-29, 1.7763620673555590e-30, 7.4047930191407272e-32, 2.8099176317436489e-33, 9.6838410701764544e-35, 3.0232780766836873e-36, 8.5272688786829149e-38, 2.1666198058800618e-39, 4.9435800520554766e-41, 1.0095495376276113e-42, 1.8385123238649587e-44, 2.9740995846398285e-46, 4.2554770940703958e-48, 5.3608992748856614e-50, 5.9160971507025675e-52, 5.6878446259603137e-54, 4.7353070830108189e-56, 3.3911184321991622e-58, 2.0736313112573398e-60, 1.0738850147584223e-62, 4.6671413158696264e-65, 1.6848180938195073e-67, 4.9937669382694245e-70, 1.1993601521489046e-72, 2.2990777865226915e-75, 3.4566329048643892e-78, 3.9938420292542256e-81, 3.4618487459964773e-84, 2.1872204017818973e-87, 9.7261605479925101e-91, 2.9150063258205350e-94, 5.5741078533835752e-98, 6.3324559268876792e-102, 3.8823686733906794e-106, 1.1217254900384875e-110, 1.2460431717780355e-115, 3.8060787191717414e-121, 1.6853736680140806e-127, 2.1045621159574830e-135}, + {2.9971690491012730e-136, 2.4980891398206762e-128, 5.8333713614299987e-122, 1.9681709423933214e-116, 1.8221727762675135e-111, 6.4763280099261484e-107, 1.0835544161526790e-102, 9.7751589620462579e-99, 5.2354686514639054e-95, 1.7880404661796150e-91, 4.1137899834361915e-88, 6.6588269447352457e-85, 7.8536797447719853e-82, 6.9470795412027442e-79, 4.7212966724403236e-76, 2.5160708333635340e-73, 1.0700081200070465e-70, 3.6866210764241453e-68, 1.0427591853094809e-65, 2.4496158809944983e-63, 4.8287654459243867e-61, 8.0607602578177551e-59, 1.1488941335553380e-56, 1.4084920383852964e-54, 1.4951953571335084e-52, 1.3827452604659908e-50, 1.1201727218381219e-48, 7.9894861866156147e-47, 5.0402806679659781e-45, 2.8245056542381498e-43, 1.4115238161648369e-41, 6.3134908835445427e-40, 2.5359952829354267e-38, 9.1766156441607901e-37, 3.0000961317861622e-35, 8.8855426938068462e-34, 2.3901684056219713e-32, 5.8532507898005387e-31, 1.3078348727191383e-29, 2.6717694287109624e-28, 5.0001529132188371e-27, 8.5882149512444349e-26, 1.3561502945339099e-24, 1.9719885628376035e-23, 2.6445905466631306e-22, 3.2756544281813711e-21, 3.7524614126630812e-20, 3.9808239456321635e-19, 3.9155933049886526e-18, 3.5751188594220651e-17, 3.0333673764885698e-16, 2.3941367575799993e-15, 1.7594869510962716e-14, 1.2051394761470136e-13, 7.6998498930386894e-13, 4.5928264710545402e-12, 2.5595903423630225e-11, 1.3337516615570700e-10, 6.5027567060176707e-10, 2.9684197043117582e-09, 1.2694911467897228e-08, 5.0894009383117858e-08, 1.9137169385842292e-07, 6.7528978068278956e-07, 2.2372679339319808e-06, 6.9624497238718160e-06, 2.0361547224732169e-05, 5.5980964406792492e-05, 1.4474894898356766e-04, 3.5211870018385556e-04, 8.0612713585123284e-04, 1.7373614851938118e-03, 3.5259000508765289e-03, 6.7399040525805923e-03, 1.2137859543972172e-02, 2.0598052684982535e-02, 3.2944830178350461e-02, 4.9670368744572549e-02, 7.0602349240131604e-02, 9.4625036098936688e-02, 1.1959210591508003e-01, 1.4254236006576013e-01, 1.6023480790396424e-01, 1.6988651844048314e-01, 1.6988651844048314e-01, 1.6023480790396424e-01, 1.4254236006576013e-01, 1.1959210591508003e-01, 9.4625036098936688e-02, 7.0602349240131604e-02, 4.9670368744572549e-02, 3.2944830178350461e-02, 2.0598052684982535e-02, 1.2137859543972172e-02, 6.7399040525805923e-03, 3.5259000508765289e-03, 1.7373614851938118e-03, 8.0612713585123284e-04, 3.5211870018385556e-04, 1.4474894898356766e-04, 5.5980964406792492e-05, 2.0361547224732169e-05, 6.9624497238718160e-06, 2.2372679339319808e-06, 6.7528978068278956e-07, 1.9137169385842292e-07, 5.0894009383117858e-08, 1.2694911467897228e-08, 2.9684197043117582e-09, 6.5027567060176707e-10, 1.3337516615570700e-10, 2.5595903423630225e-11, 4.5928264710545402e-12, 7.6998498930386894e-13, 1.2051394761470136e-13, 1.7594869510962716e-14, 2.3941367575799993e-15, 3.0333673764885698e-16, 3.5751188594220651e-17, 3.9155933049886526e-18, 3.9808239456321635e-19, 3.7524614126630812e-20, 3.2756544281813711e-21, 2.6445905466631306e-22, 1.9719885628376035e-23, 1.3561502945339099e-24, 8.5882149512444349e-26, 5.0001529132188371e-27, 2.6717694287109624e-28, 1.3078348727191383e-29, 5.8532507898005387e-31, 2.3901684056219713e-32, 8.8855426938068462e-34, 3.0000961317861622e-35, 9.1766156441607901e-37, 2.5359952829354267e-38, 6.3134908835445427e-40, 1.4115238161648369e-41, 2.8245056542381498e-43, 5.0402806679659781e-45, 7.9894861866156147e-47, 1.1201727218381219e-48, 1.3827452604659908e-50, 1.4951953571335084e-52, 1.4084920383852964e-54, 1.1488941335553380e-56, 8.0607602578177551e-59, 4.8287654459243867e-61, 2.4496158809944983e-63, 1.0427591853094809e-65, 3.6866210764241453e-68, 1.0700081200070465e-70, 2.5160708333635340e-73, 4.7212966724403236e-76, 6.9470795412027442e-79, 7.8536797447719853e-82, 6.6588269447352457e-85, 4.1137899834361915e-88, 1.7880404661796150e-91, 5.2354686514639054e-95, 9.7751589620462579e-99, 1.0835544161526790e-102, 6.4763280099261484e-107, 1.8221727762675135e-111, 1.9681709423933214e-116, 5.8333713614299987e-122, 2.4980891398206762e-128, 2.9971690491012730e-136}, + {4.2674931553342203e-137, 3.7013509844210040e-129, 8.9359543576021383e-123, 3.1068184196664260e-117, 2.9577586950025811e-112, 1.0793940202510381e-107, 1.8522459789363982e-103, 1.7123515642355668e-99, 9.3917005928096861e-96, 3.2827539517233995e-92, 7.7262644929909970e-89, 1.2788460726412831e-85, 1.5418407850274678e-82, 1.3937615371156682e-79, 9.6774116872500576e-77, 5.2679228724311439e-74, 2.2879261623118261e-71, 8.0492001695776603e-69, 2.3244392181338319e-66, 5.5743129455028007e-64, 1.1216194835766520e-61, 1.9110201175931197e-59, 2.7798349876894280e-57, 3.4779129275742834e-55, 3.7676299883874885e-53, 3.5555263388415704e-51, 2.9391917507565755e-49, 2.1391283000208420e-47, 1.3770363396814081e-45, 7.8742105891358037e-44, 4.0154223770167576e-42, 1.8327311167318893e-40, 7.5123280800309780e-39, 2.7740812006389936e-37, 9.2554744703184908e-36, 2.7976499634157274e-34, 7.6807810254033586e-33, 1.9198421026192681e-31, 4.3786397679911876e-30, 9.1312863995714357e-29, 1.7445924812851179e-27, 3.0593178878006020e-26, 4.9326008142373812e-25, 7.3241393698795336e-24, 1.0030774102469258e-22, 1.2689360428385754e-21, 1.4847983173617774e-20, 1.6090879587826797e-19, 1.6169926387796005e-18, 1.5085327113052835e-17, 1.3079623075775175e-16, 1.0550654299237249e-15, 7.9256160807813284e-15, 5.5495687412198589e-14, 3.6252638108375508e-13, 2.2112377011770522e-12, 1.2603426258460018e-11, 6.7177337738006964e-11, 3.3507655233538448e-10, 1.5650990540810345e-09, 6.8499863308168436e-09, 2.8109038530404097e-08, 1.0820676942101237e-07, 3.9097121047484011e-07, 1.3265796796150300e-06, 4.2288616562734994e-06, 1.2670859378200327e-05, 3.5699320251985919e-05, 9.4613317406319364e-05, 2.3596028278015030e-04, 5.5394259248142631e-04, 1.2245148633746915e-03, 2.5495331679026910e-03, 5.0011317639987000e-03, 9.2446564129297221e-03, 1.6107280751087583e-02, 2.6457407162359760e-02, 4.0977099534106338e-02, 5.9850822005640535e-02, 8.2450068298432835e-02, 1.0714008439362262e-01, 1.3133855013394508e-01, 1.5189453076872492e-01, 1.6573850820195182e-01, 1.7062752012289428e-01, 1.6573850820195182e-01, 1.5189453076872492e-01, 1.3133855013394508e-01, 1.0714008439362262e-01, 8.2450068298432835e-02, 5.9850822005640535e-02, 4.0977099534106338e-02, 2.6457407162359760e-02, 1.6107280751087583e-02, 9.2446564129297221e-03, 5.0011317639987000e-03, 2.5495331679026910e-03, 1.2245148633746915e-03, 5.5394259248142631e-04, 2.3596028278015030e-04, 9.4613317406319364e-05, 3.5699320251985919e-05, 1.2670859378200327e-05, 4.2288616562734994e-06, 1.3265796796150300e-06, 3.9097121047484011e-07, 1.0820676942101237e-07, 2.8109038530404097e-08, 6.8499863308168436e-09, 1.5650990540810345e-09, 3.3507655233538448e-10, 6.7177337738006964e-11, 1.2603426258460018e-11, 2.2112377011770522e-12, 3.6252638108375508e-13, 5.5495687412198589e-14, 7.9256160807813284e-15, 1.0550654299237249e-15, 1.3079623075775175e-16, 1.5085327113052835e-17, 1.6169926387796005e-18, 1.6090879587826797e-19, 1.4847983173617774e-20, 1.2689360428385754e-21, 1.0030774102469258e-22, 7.3241393698795336e-24, 4.9326008142373812e-25, 3.0593178878006020e-26, 1.7445924812851179e-27, 9.1312863995714357e-29, 4.3786397679911876e-30, 1.9198421026192681e-31, 7.6807810254033586e-33, 2.7976499634157274e-34, 9.2554744703184908e-36, 2.7740812006389936e-37, 7.5123280800309780e-39, 1.8327311167318893e-40, 4.0154223770167576e-42, 7.8742105891358037e-44, 1.3770363396814081e-45, 2.1391283000208420e-47, 2.9391917507565755e-49, 3.5555263388415704e-51, 3.7676299883874885e-53, 3.4779129275742834e-55, 2.7798349876894280e-57, 1.9110201175931197e-59, 1.1216194835766520e-61, 5.5743129455028007e-64, 2.3244392181338319e-66, 8.0492001695776603e-69, 2.2879261623118261e-71, 5.2679228724311439e-74, 9.6774116872500576e-77, 1.3937615371156682e-79, 1.5418407850274678e-82, 1.2788460726412831e-85, 7.7262644929909970e-89, 3.2827539517233995e-92, 9.3917005928096861e-96, 1.7123515642355668e-99, 1.8522459789363982e-103, 1.0793940202510381e-107, 2.9577586950025811e-112, 3.1068184196664260e-117, 8.9359543576021383e-123, 3.7013509844210040e-129, 4.2674931553342203e-137}, + {6.0750158130606195e-138, 5.4821992024733287e-130, 1.3681822165982846e-123, 4.9011169950359405e-118, 4.7974396933811439e-113, 1.7974392277078273e-108, 3.1631548152333414e-104, 2.9963165563522804e-100, 1.6827169561417482e-96, 6.0190850814126162e-93, 1.4490438595507066e-89, 2.4523185664718153e-86, 3.0220219471047618e-83, 2.7913874973199548e-80, 1.9799592744971097e-77, 1.1008005267477927e-74, 4.8820589020655159e-72, 1.7536229837285863e-69, 5.1696909850843693e-67, 1.2654633658209892e-64, 2.5987959219621812e-62, 4.5188057419567269e-60, 6.7077790006444227e-58, 8.5635704641083388e-56, 9.4658821709007862e-54, 9.1146156997272630e-52, 7.6876441303763667e-50, 5.7085575439180572e-48, 3.7493520841061347e-46, 2.1874580274727376e-44, 1.1381244408182845e-42, 5.3001743821412355e-41, 2.2167101442428974e-39, 8.3523638615101674e-38, 2.8435471995138850e-36, 8.7709151746020293e-35, 2.4573526663074424e-33, 6.2684680341301147e-32, 1.4591317861612538e-30, 3.1058077266730593e-29, 6.0569508661768345e-28, 1.0842625724312578e-26, 1.7847202502838671e-25, 2.7056507791212747e-24, 3.7836354660151275e-23, 4.8878185643771254e-22, 5.8409861850177518e-21, 6.4652715404585129e-20, 6.6366701688022747e-19, 6.3252994285961157e-18, 5.6034658987730242e-17, 4.6187988803389262e-16, 3.5458950811944735e-15, 2.5377705512106429e-14, 1.6946972716989475e-13, 1.0568382827043380e-12, 6.1595020440963285e-12, 3.3576005591117169e-11, 1.7130382466099029e-10, 8.1856149500888656e-10, 3.6657050674739318e-09, 1.5393813958417279e-08, 6.0654560255829627e-08, 2.2435783940914669e-07, 7.7946793854749263e-07, 2.5447213452537048e-06, 7.8101702177205490e-06, 2.2544487920551540e-05, 6.1227929783044720e-05, 1.5651161607055494e-04, 3.7668553922014524e-04, 8.5385410230442147e-04, 1.8234228920144958e-03, 3.6694988559735154e-03, 6.9606294949961902e-03, 1.2448294747794275e-02, 2.0993195618512490e-02, 3.3391282475767885e-02, 5.0100599356951693e-02, 7.0919958702876942e-02, 9.4724291720265918e-02, 1.1938903980933140e-01, 1.4200771666714165e-01, 1.5941508322714990e-01, 1.6890164874640598e-01, 1.6890164874640598e-01, 1.5941508322714990e-01, 1.4200771666714165e-01, 1.1938903980933140e-01, 9.4724291720265918e-02, 7.0919958702876942e-02, 5.0100599356951693e-02, 3.3391282475767885e-02, 2.0993195618512490e-02, 1.2448294747794275e-02, 6.9606294949961902e-03, 3.6694988559735154e-03, 1.8234228920144958e-03, 8.5385410230442147e-04, 3.7668553922014524e-04, 1.5651161607055494e-04, 6.1227929783044720e-05, 2.2544487920551540e-05, 7.8101702177205490e-06, 2.5447213452537048e-06, 7.7946793854749263e-07, 2.2435783940914669e-07, 6.0654560255829627e-08, 1.5393813958417279e-08, 3.6657050674739318e-09, 8.1856149500888656e-10, 1.7130382466099029e-10, 3.3576005591117169e-11, 6.1595020440963285e-12, 1.0568382827043380e-12, 1.6946972716989475e-13, 2.5377705512106429e-14, 3.5458950811944735e-15, 4.6187988803389262e-16, 5.6034658987730242e-17, 6.3252994285961157e-18, 6.6366701688022747e-19, 6.4652715404585129e-20, 5.8409861850177518e-21, 4.8878185643771254e-22, 3.7836354660151275e-23, 2.7056507791212747e-24, 1.7847202502838671e-25, 1.0842625724312578e-26, 6.0569508661768345e-28, 3.1058077266730593e-29, 1.4591317861612538e-30, 6.2684680341301147e-32, 2.4573526663074424e-33, 8.7709151746020293e-35, 2.8435471995138850e-36, 8.3523638615101674e-38, 2.2167101442428974e-39, 5.3001743821412355e-41, 1.1381244408182845e-42, 2.1874580274727376e-44, 3.7493520841061347e-46, 5.7085575439180572e-48, 7.6876441303763667e-50, 9.1146156997272630e-52, 9.4658821709007862e-54, 8.5635704641083388e-56, 6.7077790006444227e-58, 4.5188057419567269e-60, 2.5987959219621812e-62, 1.2654633658209892e-64, 5.1696909850843693e-67, 1.7536229837285863e-69, 4.8820589020655159e-72, 1.1008005267477927e-74, 1.9799592744971097e-77, 2.7913874973199548e-80, 3.0220219471047618e-83, 2.4523185664718153e-86, 1.4490438595507066e-89, 6.0190850814126162e-93, 1.6827169561417482e-96, 2.9963165563522804e-100, 3.1631548152333414e-104, 1.7974392277078273e-108, 4.7974396933811439e-113, 4.9011169950359405e-118, 1.3681822165982846e-123, 5.4821992024733287e-130, 6.0750158130606195e-138}, + {8.6464098495106045e-139, 8.1169547967150641e-131, 2.0937788694250258e-124, 7.7268624062801043e-119, 7.7755878030242305e-114, 2.9905793066209871e-109, 5.3966031917331080e-105, 5.2373672835160608e-101, 3.0113519152678094e-97, 1.1021983838887256e-93, 2.7138416423119788e-90, 4.6954865769208796e-87, 5.9136418179343394e-84, 5.5809142352163536e-81, 4.0435337904295643e-78, 2.2958300915077279e-75, 1.0396325878228644e-72, 3.8123200620819477e-70, 1.1471867481155006e-67, 2.8660528596806035e-65, 6.0065917977528455e-63, 1.0657711610182893e-60, 1.6142564784909037e-58, 2.1026978884308611e-56, 2.3713251069838819e-54, 2.3294898984397351e-52, 2.0044580918502007e-50, 1.5184626573152095e-48, 1.0174299157427975e-46, 6.0556195147012746e-45, 3.2142710908365357e-43, 1.5270851777984907e-41, 6.5158604619910054e-40, 2.5048070243067333e-38, 8.7004606571271586e-37, 2.7381749245865647e-35, 7.8277738587896100e-34, 2.0375540992709603e-32, 4.8399847326203970e-31, 1.0513633818680897e-29, 2.0926202706959383e-28, 3.8234939104131151e-27, 6.4242027780709820e-26, 9.9421354277925673e-25, 1.4194294864852321e-23, 1.8722162613285435e-22, 2.2845745768934510e-21, 2.5824265914439110e-20, 2.7074430614342264e-19, 2.6357601492491789e-18, 2.3853221384019439e-17, 2.0087998156976881e-16, 1.5758126400353855e-15, 1.1525451076836792e-14, 7.8665152475648879e-14, 5.0146808941799565e-13, 2.9880423319270495e-12, 1.6654840593814865e-11, 8.6899012302376471e-11, 4.2472082249711324e-10, 1.9457386067825712e-09, 8.3602716973645751e-09, 3.3710054470838133e-08, 1.2762506765080952e-07, 4.5391122547936338e-07, 1.5173031250618367e-06, 4.7690949847434419e-06, 1.4100857760918970e-05, 3.9234961307384339e-05, 1.0277324714018339e-04, 2.5352235086933272e-04, 5.8914391280362889e-04, 1.2901045250613646e-03, 2.6628467710093206e-03, 5.1819700035925865e-03, 9.5097957728564348e-03, 1.6461365836824633e-02, 2.6881937632071830e-02, 4.1421702134247403e-02, 6.0232621258249110e-02, 8.2666028537237118e-02, 1.0709279898985245e-01, 1.3096920653341185e-01, 1.5121094137038713e-01, 1.6482506909185640e-01, 1.6962969836778974e-01, 1.6482506909185640e-01, 1.5121094137038713e-01, 1.3096920653341185e-01, 1.0709279898985245e-01, 8.2666028537237118e-02, 6.0232621258249110e-02, 4.1421702134247403e-02, 2.6881937632071830e-02, 1.6461365836824633e-02, 9.5097957728564348e-03, 5.1819700035925865e-03, 2.6628467710093206e-03, 1.2901045250613646e-03, 5.8914391280362889e-04, 2.5352235086933272e-04, 1.0277324714018339e-04, 3.9234961307384339e-05, 1.4100857760918970e-05, 4.7690949847434419e-06, 1.5173031250618367e-06, 4.5391122547936338e-07, 1.2762506765080952e-07, 3.3710054470838133e-08, 8.3602716973645751e-09, 1.9457386067825712e-09, 4.2472082249711324e-10, 8.6899012302376471e-11, 1.6654840593814865e-11, 2.9880423319270495e-12, 5.0146808941799565e-13, 7.8665152475648879e-14, 1.1525451076836792e-14, 1.5758126400353855e-15, 2.0087998156976881e-16, 2.3853221384019439e-17, 2.6357601492491789e-18, 2.7074430614342264e-19, 2.5824265914439110e-20, 2.2845745768934510e-21, 1.8722162613285435e-22, 1.4194294864852321e-23, 9.9421354277925673e-25, 6.4242027780709820e-26, 3.8234939104131151e-27, 2.0926202706959383e-28, 1.0513633818680897e-29, 4.8399847326203970e-31, 2.0375540992709603e-32, 7.8277738587896100e-34, 2.7381749245865647e-35, 8.7004606571271586e-37, 2.5048070243067333e-38, 6.5158604619910054e-40, 1.5270851777984907e-41, 3.2142710908365357e-43, 6.0556195147012746e-45, 1.0174299157427975e-46, 1.5184626573152095e-48, 2.0044580918502007e-50, 2.3294898984397351e-52, 2.3713251069838819e-54, 2.1026978884308611e-56, 1.6142564784909037e-58, 1.0657711610182893e-60, 6.0065917977528455e-63, 2.8660528596806035e-65, 1.1471867481155006e-67, 3.8123200620819477e-70, 1.0396325878228644e-72, 2.2958300915077279e-75, 4.0435337904295643e-78, 5.5809142352163536e-81, 5.9136418179343394e-84, 4.6954865769208796e-87, 2.7138416423119788e-90, 1.1021983838887256e-93, 3.0113519152678094e-97, 5.2373672835160608e-101, 5.3966031917331080e-105, 2.9905793066209871e-109, 7.7755878030242305e-114, 7.7268624062801043e-119, 2.0937788694250258e-124, 8.1169547967150641e-131, 8.6464098495106045e-139}, + {1.2303789814620092e-139, 1.2013699333289992e-131, 3.2026074548384006e-125, 1.2174269794916373e-119, 1.2593229738553804e-114, 4.9714964520806193e-110, 9.1982052962411378e-106, 9.1447911140134055e-102, 5.3827092462530275e-98, 2.0157286790487118e-94, 5.0755707227503414e-91, 8.9771058574961900e-88, 1.1553649373808784e-84, 1.1139151556417037e-81, 8.2429409894791420e-79, 4.7790526311204645e-76, 2.2094400576899919e-73, 8.2703192545553517e-71, 2.5400223834270154e-68, 6.4759951809357819e-66, 1.3849218619189611e-63, 2.5072557278333359e-61, 3.8744806525565368e-59, 5.1487100357555966e-57, 5.9234211353878837e-55, 5.9358962183919884e-53, 5.2102035909462387e-51, 4.0261165631274628e-49, 2.7517389408826910e-47, 1.6706338169898752e-45, 9.0454023907569489e-44, 4.3836632815273276e-42, 1.9080203924026029e-40, 7.4822875434667983e-39, 2.6513404940738975e-37, 8.5126426420369604e-36, 2.4827942651601884e-34, 6.5937510349118087e-33, 1.5981308016388612e-31, 3.5423572866413238e-30, 7.1949797524882649e-29, 1.3416207816913450e-27, 2.3006552131922817e-26, 3.6342070015972533e-25, 5.2963698057770957e-24, 7.1317120414745996e-23, 8.8849961119116762e-22, 1.0255026540751254e-20, 1.0979177006155230e-19, 1.0916029509464340e-18, 1.0090271979231116e-17, 8.6804078056359369e-17, 6.9567797833146074e-16, 5.1989584985238723e-15, 3.6262025536343989e-14, 2.3625593061240154e-13, 1.4389854608144821e-12, 8.1997932243736651e-12, 4.3745620487604465e-11, 2.1864887185791365e-10, 1.0245209689572339e-09, 4.5031898910426613e-09, 1.8577866622072818e-08, 7.1975399855994780e-08, 2.6200414925731448e-07, 8.9655811991941417e-07, 2.8853130691641410e-06, 8.7365058018499081e-06, 2.4899323348910079e-05, 6.6819890242436042e-05, 1.6890601339725517e-04, 4.0229796846567709e-04, 9.0312111074868030e-04, 1.9114445894976445e-03, 3.8151134691487313e-03, 7.1826754657021994e-03, 1.2758271065775782e-02, 2.1384981853074116e-02, 3.3830872556682462e-02, 5.0520980072118506e-02, 7.1226720494510898e-02, 9.4814894788900164e-02, 1.1918291538647637e-01, 1.4147779230279267e-01, 1.5860763301741698e-01, 1.6793370935002905e-01, 1.6793370935002905e-01, 1.5860763301741698e-01, 1.4147779230279267e-01, 1.1918291538647637e-01, 9.4814894788900164e-02, 7.1226720494510898e-02, 5.0520980072118506e-02, 3.3830872556682462e-02, 2.1384981853074116e-02, 1.2758271065775782e-02, 7.1826754657021994e-03, 3.8151134691487313e-03, 1.9114445894976445e-03, 9.0312111074868030e-04, 4.0229796846567709e-04, 1.6890601339725517e-04, 6.6819890242436042e-05, 2.4899323348910079e-05, 8.7365058018499081e-06, 2.8853130691641410e-06, 8.9655811991941417e-07, 2.6200414925731448e-07, 7.1975399855994780e-08, 1.8577866622072818e-08, 4.5031898910426613e-09, 1.0245209689572339e-09, 2.1864887185791365e-10, 4.3745620487604465e-11, 8.1997932243736651e-12, 1.4389854608144821e-12, 2.3625593061240154e-13, 3.6262025536343989e-14, 5.1989584985238723e-15, 6.9567797833146074e-16, 8.6804078056359369e-17, 1.0090271979231116e-17, 1.0916029509464340e-18, 1.0979177006155230e-19, 1.0255026540751254e-20, 8.8849961119116762e-22, 7.1317120414745996e-23, 5.2963698057770957e-24, 3.6342070015972533e-25, 2.3006552131922817e-26, 1.3416207816913450e-27, 7.1949797524882649e-29, 3.5423572866413238e-30, 1.5981308016388612e-31, 6.5937510349118087e-33, 2.4827942651601884e-34, 8.5126426420369604e-36, 2.6513404940738975e-37, 7.4822875434667983e-39, 1.9080203924026029e-40, 4.3836632815273276e-42, 9.0454023907569489e-44, 1.6706338169898752e-45, 2.7517389408826910e-47, 4.0261165631274628e-49, 5.2102035909462387e-51, 5.9358962183919884e-53, 5.9234211353878837e-55, 5.1487100357555966e-57, 3.8744806525565368e-59, 2.5072557278333359e-61, 1.3849218619189611e-63, 6.4759951809357819e-66, 2.5400223834270154e-68, 8.2703192545553517e-71, 2.2094400576899919e-73, 4.7790526311204645e-76, 8.2429409894791420e-79, 1.1139151556417037e-81, 1.1553649373808784e-84, 8.9771058574961900e-88, 5.0755707227503414e-91, 2.0157286790487118e-94, 5.3827092462530275e-98, 9.1447911140134055e-102, 9.1982052962411378e-106, 4.9714964520806193e-110, 1.2593229738553804e-114, 1.2174269794916373e-119, 3.2026074548384006e-125, 1.2013699333289992e-131, 1.2303789814620092e-139}, + {1.7504813313443110e-140, 1.7774902414670824e-132, 4.8962631916290320e-126, 1.9169773412509448e-120, 2.0380950317636651e-115, 8.2575913221058373e-111, 1.5662913179616934e-106, 1.5950515939148060e-102, 9.6102475509992629e-99, 3.6817405361106414e-95, 9.4795771929584613e-92, 1.7137636253252277e-88, 2.2537069207131266e-85, 2.2195670363270061e-82, 1.6773665243938764e-79, 9.9294168393320748e-77, 4.6861855398798507e-74, 1.7903790379405142e-71, 5.6115831515377673e-69, 1.4599152900352242e-66, 3.1854832448751424e-64, 5.8835568128153365e-62, 9.2750122555037185e-60, 1.2572829274411131e-57, 1.4754337744917936e-55, 1.5080977336171035e-53, 1.3501492314506362e-51, 1.0641162728147897e-49, 7.4179019446614824e-48, 4.5933036667242678e-46, 2.5365532103719637e-44, 1.2538070457653651e-42, 5.5662423908008861e-41, 2.2264349328620495e-39, 8.0473188469528885e-38, 2.6355807192340085e-36, 7.8414692242533960e-35, 2.1244914229476255e-33, 5.2531973592621732e-32, 1.1880047374923401e-30, 2.4620531629619134e-29, 4.6845665497518896e-28, 8.1977521328279625e-27, 1.3215706261902287e-25, 1.9657684577473083e-24, 2.7018364834425692e-23, 3.4361611658856167e-22, 4.0489821139593706e-21, 4.4260400812843420e-20, 4.4935788616135659e-19, 4.2418977594565075e-18, 3.7271474634420088e-17, 3.0512318816558229e-16, 2.3295237031463167e-15, 1.6601293173811213e-14, 1.1052712006706022e-13, 6.8801511055288008e-13, 4.0073848073937339e-12, 2.1856088643011424e-11, 1.1169403547356809e-10, 5.3519948055672733e-10, 2.4060047025435626e-09, 1.0153711719361421e-08, 4.0247544813147544e-08, 1.4992205080398724e-07, 5.2506826823537642e-07, 1.7297783253854633e-06, 5.3626317222650889e-06, 1.5651476474775071e-05, 4.3021779350373374e-05, 1.1141208654585957e-04, 2.7191419917337988e-04, 6.2563601676209426e-04, 1.3574588134771591e-03, 2.7781892530593399e-03, 5.3645468312921761e-03, 9.7754538393799058e-03, 1.6813616037549516e-02, 2.7301369702544091e-02, 4.1857856809001823e-02, 6.0603870172343872e-02, 8.2871975523587077e-02, 1.0703943053616907e-01, 1.3060060873789656e-01, 1.5053596929119434e-01, 1.6392653352569631e-01, 1.6864917988011466e-01, 1.6392653352569631e-01, 1.5053596929119434e-01, 1.3060060873789656e-01, 1.0703943053616907e-01, 8.2871975523587077e-02, 6.0603870172343872e-02, 4.1857856809001823e-02, 2.7301369702544091e-02, 1.6813616037549516e-02, 9.7754538393799058e-03, 5.3645468312921761e-03, 2.7781892530593399e-03, 1.3574588134771591e-03, 6.2563601676209426e-04, 2.7191419917337988e-04, 1.1141208654585957e-04, 4.3021779350373374e-05, 1.5651476474775071e-05, 5.3626317222650889e-06, 1.7297783253854633e-06, 5.2506826823537642e-07, 1.4992205080398724e-07, 4.0247544813147544e-08, 1.0153711719361421e-08, 2.4060047025435626e-09, 5.3519948055672733e-10, 1.1169403547356809e-10, 2.1856088643011424e-11, 4.0073848073937339e-12, 6.8801511055288008e-13, 1.1052712006706022e-13, 1.6601293173811213e-14, 2.3295237031463167e-15, 3.0512318816558229e-16, 3.7271474634420088e-17, 4.2418977594565075e-18, 4.4935788616135659e-19, 4.4260400812843420e-20, 4.0489821139593706e-21, 3.4361611658856167e-22, 2.7018364834425692e-23, 1.9657684577473083e-24, 1.3215706261902287e-25, 8.1977521328279625e-27, 4.6845665497518896e-28, 2.4620531629619134e-29, 1.1880047374923401e-30, 5.2531973592621732e-32, 2.1244914229476255e-33, 7.8414692242533960e-35, 2.6355807192340085e-36, 8.0473188469528885e-38, 2.2264349328620495e-39, 5.5662423908008861e-41, 1.2538070457653651e-42, 2.5365532103719637e-44, 4.5933036667242678e-46, 7.4179019446614824e-48, 1.0641162728147897e-49, 1.3501492314506362e-51, 1.5080977336171035e-53, 1.4754337744917936e-55, 1.2572829274411131e-57, 9.2750122555037185e-60, 5.8835568128153365e-62, 3.1854832448751424e-64, 1.4599152900352242e-66, 5.6115831515377673e-69, 1.7903790379405142e-71, 4.6861855398798507e-74, 9.9294168393320748e-77, 1.6773665243938764e-79, 2.2195670363270061e-82, 2.2537069207131266e-85, 1.7137636253252277e-88, 9.4795771929584613e-92, 3.6817405361106414e-95, 9.6102475509992629e-99, 1.5950515939148060e-102, 1.5662913179616934e-106, 8.2575913221058373e-111, 2.0380950317636651e-115, 1.9169773412509448e-120, 4.8962631916290320e-126, 1.7774902414670824e-132, 1.7504813313443110e-140}, + {2.4899600964326729e-141, 2.6289723724457029e-133, 7.4819712112270593e-127, 3.0166712841087998e-121, 3.2960842775717504e-116, 1.3704328437984587e-111, 2.6646059822111242e-107, 2.7792048294771247e-103, 1.7138296773072837e-99, 6.7162796391421331e-96, 1.7680841960979503e-92, 3.2668637275061076e-89, 4.3893173430676675e-86, 4.4153132623096831e-83, 3.4072707861884866e-80, 2.0591798858084703e-77, 9.9197548192127678e-75, 3.8678293788234498e-72, 1.2370523208691571e-69, 3.2836627133699974e-67, 7.3095353354239491e-65, 1.3772094187709065e-62, 2.2145636638702121e-60, 3.0619202170369175e-58, 3.6647661995973869e-56, 3.8203649763779160e-54, 3.4881351774083147e-52, 2.8036775536310555e-50, 1.9931613619579773e-48, 1.2586567146117010e-46, 7.0884044215753474e-45, 3.5732404426806206e-43, 1.6178126120857497e-41, 6.5996510428781978e-40, 2.4328759328467202e-38, 8.1267763573550637e-37, 2.4662127220461684e-35, 6.8155261813509929e-34, 1.7191030917484011e-32, 3.9660195668953352e-31, 8.3853154776461475e-30, 1.6278171201629848e-28, 2.9065390998814081e-27, 4.7813433896247487e-26, 7.2578010107444783e-25, 1.0180797851831930e-23, 1.3215548441960911e-22, 1.5895976396503745e-21, 1.7738996763753002e-20, 1.8387513781865510e-19, 1.7723693479759404e-18, 1.5903120371435548e-17, 1.3296671955521453e-16, 1.0369288823537636e-15, 7.5490426637877302e-15, 5.1350286901144194e-14, 3.2662837995375004e-13, 1.9442795471244843e-12, 1.0838609818985724e-11, 5.6623712315092519e-11, 2.7740673531720516e-10, 1.2752593807305187e-09, 5.5042412134787782e-09, 2.2317961616833082e-08, 8.5054483756057923e-08, 3.0481775749836127e-07, 1.0277468837741270e-06, 3.2615617411254204e-06, 9.7462566160282362e-06, 2.7434125933222057e-05, 7.2768434100256330e-05, 1.8194526534270113e-04, 4.2896461357756435e-04, 9.5392124328337667e-04, 2.0013900802573659e-03, 3.9626676572752555e-03, 7.4059308800968815e-03, 1.3067672819155697e-02, 2.1773347066246198e-02, 3.4263651242794235e-02, 5.0931713552683139e-02, 7.1522962430052642e-02, 9.4897195996236208e-02, 1.1897395918444152e-01, 1.4095256578997853e-01, 1.5781215945203400e-01, 1.6698222073712451e-01, 1.6698222073712451e-01, 1.5781215945203400e-01, 1.4095256578997853e-01, 1.1897395918444152e-01, 9.4897195996236208e-02, 7.1522962430052642e-02, 5.0931713552683139e-02, 3.4263651242794235e-02, 2.1773347066246198e-02, 1.3067672819155697e-02, 7.4059308800968815e-03, 3.9626676572752555e-03, 2.0013900802573659e-03, 9.5392124328337667e-04, 4.2896461357756435e-04, 1.8194526534270113e-04, 7.2768434100256330e-05, 2.7434125933222057e-05, 9.7462566160282362e-06, 3.2615617411254204e-06, 1.0277468837741270e-06, 3.0481775749836127e-07, 8.5054483756057923e-08, 2.2317961616833082e-08, 5.5042412134787782e-09, 1.2752593807305187e-09, 2.7740673531720516e-10, 5.6623712315092519e-11, 1.0838609818985724e-11, 1.9442795471244843e-12, 3.2662837995375004e-13, 5.1350286901144194e-14, 7.5490426637877302e-15, 1.0369288823537636e-15, 1.3296671955521453e-16, 1.5903120371435548e-17, 1.7723693479759404e-18, 1.8387513781865510e-19, 1.7738996763753002e-20, 1.5895976396503745e-21, 1.3215548441960911e-22, 1.0180797851831930e-23, 7.2578010107444783e-25, 4.7813433896247487e-26, 2.9065390998814081e-27, 1.6278171201629848e-28, 8.3853154776461475e-30, 3.9660195668953352e-31, 1.7191030917484011e-32, 6.8155261813509929e-34, 2.4662127220461684e-35, 8.1267763573550637e-37, 2.4328759328467202e-38, 6.5996510428781978e-40, 1.6178126120857497e-41, 3.5732404426806206e-43, 7.0884044215753474e-45, 1.2586567146117010e-46, 1.9931613619579773e-48, 2.8036775536310555e-50, 3.4881351774083147e-52, 3.8203649763779160e-54, 3.6647661995973869e-56, 3.0619202170369175e-58, 2.2145636638702121e-60, 1.3772094187709065e-62, 7.3095353354239491e-65, 3.2836627133699974e-67, 1.2370523208691571e-69, 3.8678293788234498e-72, 9.9197548192127678e-75, 2.0591798858084703e-77, 3.4072707861884866e-80, 4.4153132623096831e-83, 4.3893173430676675e-86, 3.2668637275061076e-89, 1.7680841960979503e-92, 6.7162796391421331e-96, 1.7138296773072837e-99, 2.7792048294771247e-103, 2.6646059822111242e-107, 1.3704328437984587e-111, 3.2960842775717504e-116, 3.0166712841087998e-121, 7.4819712112270593e-127, 2.6289723724457029e-133, 2.4899600964326729e-141}, + {3.5411506471568517e-142, 3.8870007298929211e-134, 1.1427720218874746e-127, 4.7443699591186030e-122, 5.3267445942905176e-117, 2.2724999081578913e-112, 4.5288568274049433e-108, 4.8374430266711206e-104, 3.0528486739600850e-100, 1.2236703652880107e-96, 3.2933121419749483e-93, 6.2184654173606399e-90, 8.5354199357192903e-87, 8.7687858501113383e-84, 6.9091769993084969e-81, 4.2624770595798820e-78, 2.0957319191157142e-75, 8.3387106103658512e-73, 2.7211703761612434e-70, 7.3690229255476969e-68, 1.6733234438392451e-65, 3.2158114928338939e-63, 5.2740829263623727e-61, 7.4369351842678165e-59, 9.0774918435864705e-57, 9.6499842697585386e-55, 8.9847110119503318e-53, 7.3640839458387673e-51, 5.3383547450946618e-49, 3.4375135972727117e-47, 1.9740530949677369e-45, 1.0147285474798106e-43, 4.6848975802870826e-42, 1.9488875555428468e-40, 7.3264228854645894e-39, 2.4958088668373114e-37, 7.7243461606513683e-36, 2.1771495752866995e-34, 5.6010600122601367e-33, 1.3180336788235122e-31, 2.8426307813064235e-30, 5.6294266388452469e-29, 1.0254685909108741e-27, 1.7211387969394399e-26, 2.6657834170950206e-25, 3.8158515821307025e-24, 5.0550170089602786e-23, 6.2057205211001172e-22, 7.0687611828654942e-21, 7.4798012691484967e-20, 7.3607060012414608e-19, 6.7436191474716113e-18, 5.7576889770247240e-17, 4.5856377569387674e-16, 3.4098950541891060e-15, 2.3694365058853221e-14, 1.5398051925046748e-13, 9.3656673457701801e-13, 5.3355866239683074e-12, 2.8490354792258560e-11, 1.4268284555926340e-10, 6.7061742381683788e-10, 2.9598086074993327e-09, 1.2273853303242205e-08, 4.7847173987299635e-08, 1.7543109823449902e-07, 6.0525229343483686e-07, 1.9657973702696829e-06, 6.0130527402628209e-06, 1.7329090398329860e-05, 4.7069644542722322e-05, 1.2054246571768105e-04, 2.9114733811626920e-04, 6.6342074803749660e-04, 1.4265570512383724e-03, 2.8955046143597550e-03, 5.5487673845870103e-03, 1.0041513921437970e-02, 1.7163936516514416e-02, 2.7715692333499325e-02, 4.2285689519455438e-02, 6.0964838880386028e-02, 8.3068258519182064e-02, 1.0698027879398084e-01, 1.3023286590097533e-01, 1.4986945253577164e-01, 1.6304250159157527e-01, 1.6768547028079969e-01, 1.6304250159157527e-01, 1.4986945253577164e-01, 1.3023286590097533e-01, 1.0698027879398084e-01, 8.3068258519182064e-02, 6.0964838880386028e-02, 4.2285689519455438e-02, 2.7715692333499325e-02, 1.7163936516514416e-02, 1.0041513921437970e-02, 5.5487673845870103e-03, 2.8955046143597550e-03, 1.4265570512383724e-03, 6.6342074803749660e-04, 2.9114733811626920e-04, 1.2054246571768105e-04, 4.7069644542722322e-05, 1.7329090398329860e-05, 6.0130527402628209e-06, 1.9657973702696829e-06, 6.0525229343483686e-07, 1.7543109823449902e-07, 4.7847173987299635e-08, 1.2273853303242205e-08, 2.9598086074993327e-09, 6.7061742381683788e-10, 1.4268284555926340e-10, 2.8490354792258560e-11, 5.3355866239683074e-12, 9.3656673457701801e-13, 1.5398051925046748e-13, 2.3694365058853221e-14, 3.4098950541891060e-15, 4.5856377569387674e-16, 5.7576889770247240e-17, 6.7436191474716113e-18, 7.3607060012414608e-19, 7.4798012691484967e-20, 7.0687611828654942e-21, 6.2057205211001172e-22, 5.0550170089602786e-23, 3.8158515821307025e-24, 2.6657834170950206e-25, 1.7211387969394399e-26, 1.0254685909108741e-27, 5.6294266388452469e-29, 2.8426307813064235e-30, 1.3180336788235122e-31, 5.6010600122601367e-33, 2.1771495752866995e-34, 7.7243461606513683e-36, 2.4958088668373114e-37, 7.3264228854645894e-39, 1.9488875555428468e-40, 4.6848975802870826e-42, 1.0147285474798106e-43, 1.9740530949677369e-45, 3.4375135972727117e-47, 5.3383547450946618e-49, 7.3640839458387673e-51, 8.9847110119503318e-53, 9.6499842697585386e-55, 9.0774918435864705e-57, 7.4369351842678165e-59, 5.2740829263623727e-61, 3.2158114928338939e-63, 1.6733234438392451e-65, 7.3690229255476969e-68, 2.7211703761612434e-70, 8.3387106103658512e-73, 2.0957319191157142e-75, 4.2624770595798820e-78, 6.9091769993084969e-81, 8.7687858501113383e-84, 8.5354199357192903e-87, 6.2184654173606399e-90, 3.2933121419749483e-93, 1.2236703652880107e-96, 3.0528486739600850e-100, 4.8374430266711206e-104, 4.5288568274049433e-108, 2.2724999081578913e-112, 5.3267445942905176e-117, 4.7443699591186030e-122, 1.1427720218874746e-127, 3.8870007298929211e-134, 3.5411506471568517e-142}, + {5.0351722883464185e-143, 5.7450587562745078e-135, 1.7446064596498268e-128, 7.4571213334341600e-123, 8.6023715273839571e-118, 3.7652628313310755e-113, 7.6903016009308287e-109, 8.4113401468636500e-105, 5.4319085709594968e-101, 2.2267204629384821e-97, 6.1261103396048387e-94, 1.1819905626126024e-90, 1.6572504238354695e-87, 1.7386395392283553e-84, 1.3986045504550338e-81, 8.8071523423621673e-79, 4.4190897787947332e-76, 1.7941108043227645e-73, 5.9730812278268291e-71, 1.6500317832456593e-68, 3.8217018216862523e-66, 7.4907171097897077e-64, 1.2528614722567282e-61, 1.8015494058808057e-59, 2.2422904341536794e-57, 2.4305731255545130e-55, 2.3074311289682700e-53, 1.9283073358698602e-51, 1.4252524566058730e-49, 9.3573522665893741e-48, 5.4788838446141128e-46, 2.8715169045497604e-44, 1.3517494625509147e-42, 5.7335891630321996e-41, 2.1977946695381225e-39, 7.6344180491439718e-38, 2.4094190488253342e-36, 6.9253812367067252e-35, 1.8169855856152196e-33, 4.3607057687085942e-32, 9.5923503135464682e-31, 1.9376278309334056e-29, 3.6004726047782310e-28, 6.1647472746508888e-27, 9.7413623207618448e-26, 1.4227116244089339e-24, 1.9231607886931175e-23, 2.4093040723082529e-22, 2.8008499497491982e-21, 3.0250061661788475e-20, 3.0387132211276073e-19, 2.8421271873321773e-18, 2.4775756264214477e-17, 2.0149141590187015e-16, 1.5301273364381654e-15, 1.0859626897815736e-14, 7.2089869379341516e-14, 4.4796392616415365e-13, 2.6076028723419556e-12, 1.4228958097317545e-11, 7.2832614256562299e-11, 3.4992319867238825e-10, 1.5789636824184370e-09, 6.6952823181138107e-09, 2.6692828097969734e-08, 1.0010785492509061e-07, 3.5334287745169781e-07, 1.1742867585331092e-06, 3.6760831094679487e-06, 1.0844326360928105e-05, 3.0156999060878010e-05, 7.9084957328144794e-05, 1.9564188997236542e-04, 4.5669297388226392e-04, 1.0062461311647175e-03, 2.0932217887326024e-03, 4.1120856339170011e-03, 7.6302877130003874e-03, 1.3376390072548504e-02, 2.2158233552618596e-02, 3.4689673239772116e-02, 5.1332999819585050e-02, 7.1809001831171768e-02, 9.4971530833224349e-02, 1.1876238489882553e-01, 1.4043201287954626e-01, 1.5702837449220031e-01, 1.6604672219204664e-01, 1.6604672219204664e-01, 1.5702837449220031e-01, 1.4043201287954626e-01, 1.1876238489882553e-01, 9.4971530833224349e-02, 7.1809001831171768e-02, 5.1332999819585050e-02, 3.4689673239772116e-02, 2.2158233552618596e-02, 1.3376390072548504e-02, 7.6302877130003874e-03, 4.1120856339170011e-03, 2.0932217887326024e-03, 1.0062461311647175e-03, 4.5669297388226392e-04, 1.9564188997236542e-04, 7.9084957328144794e-05, 3.0156999060878010e-05, 1.0844326360928105e-05, 3.6760831094679487e-06, 1.1742867585331092e-06, 3.5334287745169781e-07, 1.0010785492509061e-07, 2.6692828097969734e-08, 6.6952823181138107e-09, 1.5789636824184370e-09, 3.4992319867238825e-10, 7.2832614256562299e-11, 1.4228958097317545e-11, 2.6076028723419556e-12, 4.4796392616415365e-13, 7.2089869379341516e-14, 1.0859626897815736e-14, 1.5301273364381654e-15, 2.0149141590187015e-16, 2.4775756264214477e-17, 2.8421271873321773e-18, 3.0387132211276073e-19, 3.0250061661788475e-20, 2.8008499497491982e-21, 2.4093040723082529e-22, 1.9231607886931175e-23, 1.4227116244089339e-24, 9.7413623207618448e-26, 6.1647472746508888e-27, 3.6004726047782310e-28, 1.9376278309334056e-29, 9.5923503135464682e-31, 4.3607057687085942e-32, 1.8169855856152196e-33, 6.9253812367067252e-35, 2.4094190488253342e-36, 7.6344180491439718e-38, 2.1977946695381225e-39, 5.7335891630321996e-41, 1.3517494625509147e-42, 2.8715169045497604e-44, 5.4788838446141128e-46, 9.3573522665893741e-48, 1.4252524566058730e-49, 1.9283073358698602e-51, 2.3074311289682700e-53, 2.4305731255545130e-55, 2.2422904341536794e-57, 1.8015494058808057e-59, 1.2528614722567282e-61, 7.4907171097897077e-64, 3.8217018216862523e-66, 1.6500317832456593e-68, 5.9730812278268291e-71, 1.7941108043227645e-73, 4.4190897787947332e-76, 8.8071523423621673e-79, 1.3986045504550338e-81, 1.7386395392283553e-84, 1.6572504238354695e-87, 1.1819905626126024e-90, 6.1261103396048387e-94, 2.2267204629384821e-97, 5.4319085709594968e-101, 8.4113401468636500e-105, 7.6903016009308287e-109, 3.7652628313310755e-113, 8.6023715273839571e-118, 7.4571213334341600e-123, 1.7446064596498268e-128, 5.7450587562745078e-135, 5.0351722883464185e-143}, + {7.1581854941568756e-144, 8.4884228757564859e-136, 2.6621446843016668e-129, 1.1714088250630149e-123, 1.3882583385637704e-118, 6.2335512554508696e-114, 1.3046719672955675e-109, 1.4610767163662094e-105, 9.6541517663049285e-102, 4.0470443036783296e-98, 1.1380585129708444e-94, 2.2435189643567695e-91, 3.2128730776926215e-88, 3.4417484237908715e-85, 2.8263134922810747e-82, 1.8164480123517544e-79, 9.3003877258546557e-77, 3.8523675927861067e-74, 1.3083561453477787e-71, 3.6865159997894300e-69, 8.7082600252251548e-67, 1.7406436581415539e-64, 2.9687147399709626e-62, 4.3527424404558593e-60, 5.5237929617045550e-58, 6.1047069753060061e-56, 5.9085581038387938e-54, 5.0340269517910206e-52, 3.7932466358096469e-50, 2.5389205160417814e-48, 1.5155318342592620e-46, 8.0977464419800098e-45, 3.8862848936787104e-43, 1.6805797332715199e-41, 6.5678744364293848e-40, 2.3261212178440308e-38, 7.4851978878895327e-37, 2.1937508830604144e-35, 5.8690540840121578e-34, 1.4363784560339465e-32, 3.2222344142269078e-31, 6.6381799678904965e-30, 1.2580944858403407e-28, 2.1972252658847511e-27, 3.5417421260548565e-26, 5.2769903994937601e-25, 7.2776858868650826e-24, 9.3028399771791796e-23, 1.1035696761428192e-21, 1.2163644574829813e-20, 1.2470907989461904e-19, 1.1906056130964038e-18, 1.0595326417660698e-17, 8.7974278780040251e-17, 6.8216435985574468e-16, 4.9441425800883030e-15, 3.3521165632319237e-14, 2.1277112806959519e-13, 1.2653006101080342e-12, 7.0545233223348931e-12, 3.6899828977436854e-11, 1.8119180456089166e-10, 8.3573910554417999e-10, 3.6229939665804831e-09, 1.4769397910223943e-08, 5.6647039057714555e-08, 2.0451241808924649e-07, 6.9532414269249713e-07, 2.2272343809174102e-06, 6.7240427138149140e-06, 1.9140150173987354e-05, 5.1388360015799239e-05, 1.3017662891537081e-04, 3.1123241184750341e-04, 7.0249863037702334e-04, 1.4973772242764213e-03, 3.0147364453737358e-03, 5.7345384962421463e-03, 1.0307863786080675e-02, 1.7512238829626020e-02, 2.8124900042797892e-02, 4.2705327076181680e-02, 6.1315790894116422e-02, 8.3255213529058528e-02, 1.0691562889960281e-01, 1.2986607877253428e-01, 1.4921123248756085e-01, 1.6217258820124303e-01, 1.6673809474249007e-01, 1.6217258820124303e-01, 1.4921123248756085e-01, 1.2986607877253428e-01, 1.0691562889960281e-01, 8.3255213529058528e-02, 6.1315790894116422e-02, 4.2705327076181680e-02, 2.8124900042797892e-02, 1.7512238829626020e-02, 1.0307863786080675e-02, 5.7345384962421463e-03, 3.0147364453737358e-03, 1.4973772242764213e-03, 7.0249863037702334e-04, 3.1123241184750341e-04, 1.3017662891537081e-04, 5.1388360015799239e-05, 1.9140150173987354e-05, 6.7240427138149140e-06, 2.2272343809174102e-06, 6.9532414269249713e-07, 2.0451241808924649e-07, 5.6647039057714555e-08, 1.4769397910223943e-08, 3.6229939665804831e-09, 8.3573910554417999e-10, 1.8119180456089166e-10, 3.6899828977436854e-11, 7.0545233223348931e-12, 1.2653006101080342e-12, 2.1277112806959519e-13, 3.3521165632319237e-14, 4.9441425800883030e-15, 6.8216435985574468e-16, 8.7974278780040251e-17, 1.0595326417660698e-17, 1.1906056130964038e-18, 1.2470907989461904e-19, 1.2163644574829813e-20, 1.1035696761428192e-21, 9.3028399771791796e-23, 7.2776858868650826e-24, 5.2769903994937601e-25, 3.5417421260548565e-26, 2.1972252658847511e-27, 1.2580944858403407e-28, 6.6381799678904965e-30, 3.2222344142269078e-31, 1.4363784560339465e-32, 5.8690540840121578e-34, 2.1937508830604144e-35, 7.4851978878895327e-37, 2.3261212178440308e-38, 6.5678744364293848e-40, 1.6805797332715199e-41, 3.8862848936787104e-43, 8.0977464419800098e-45, 1.5155318342592620e-46, 2.5389205160417814e-48, 3.7932466358096469e-50, 5.0340269517910206e-52, 5.9085581038387938e-54, 6.1047069753060061e-56, 5.5237929617045550e-58, 4.3527424404558593e-60, 2.9687147399709626e-62, 1.7406436581415539e-64, 8.7082600252251548e-67, 3.6865159997894300e-69, 1.3083561453477787e-71, 3.8523675927861067e-74, 9.3003877258546557e-77, 1.8164480123517544e-79, 2.8263134922810747e-82, 3.4417484237908715e-85, 3.2128730776926215e-88, 2.2435189643567695e-91, 1.1380585129708444e-94, 4.0470443036783296e-98, 9.6541517663049285e-102, 1.4610767163662094e-105, 1.3046719672955675e-109, 6.2335512554508696e-114, 1.3882583385637704e-118, 1.1714088250630149e-123, 2.6621446843016668e-129, 8.4884228757564859e-136, 7.1581854941568756e-144}, + {1.0174451907169722e-144, 1.2537577338109092e-136, 4.0603558490313254e-130, 1.8390471781108747e-124, 2.2388300710588648e-119, 1.0311647067706544e-114, 2.2113953581884588e-110, 2.5353839157043305e-106, 1.7139381704010506e-102, 7.3466025769339733e-99, 2.1114364896149106e-95, 4.2524253414775605e-92, 6.2193919080044227e-89, 6.8022938891305936e-86, 5.7017766571657716e-83, 3.7396644213938176e-80, 1.9536604993085239e-77, 8.2555014673420022e-75, 2.8598818663126844e-72, 8.2184808615623598e-70, 1.9797683901166225e-67, 4.0351646934878695e-65, 7.0170567960964978e-63, 1.0489546649192595e-60, 1.3571109461554121e-58, 1.5290034639304410e-56, 1.5086081632928153e-54, 1.3102411068553504e-52, 1.0064229300129089e-50, 6.8667092650473948e-49, 4.1782480984927090e-47, 2.2757544084791531e-45, 1.1133537204234619e-43, 4.9079810854674800e-42, 1.9553490062333371e-40, 7.0599294307578851e-39, 2.3160882385061203e-37, 6.9205465629360576e-36, 1.8877397396823247e-34, 4.7107012996283542e-33, 1.0775571184918142e-31, 2.2637292363656048e-30, 4.3753093336081546e-29, 7.7932715085212503e-28, 1.2812781788064907e-26, 1.9472758171895140e-25, 2.7395824646129918e-24, 3.5726754325441841e-23, 4.3241778048815671e-22, 4.8633316486835449e-21, 5.0883502730989637e-20, 4.9579227287808755e-19, 4.5034462009468205e-18, 3.8170938055666007e-17, 3.0217745531718828e-16, 2.2362025898948135e-15, 1.5482439389379285e-14, 1.0036629079256339e-13, 6.0964973515510935e-13, 3.4723560883860410e-12, 1.8557142556642682e-11, 9.3114559517381624e-11, 4.3894092072618305e-10, 1.9450249932898343e-09, 8.1060721426662619e-09, 3.1789582778002615e-08, 1.1737053608502818e-07, 4.0816183881635333e-07, 1.3374965511498204e-06, 4.1315876560548306e-06, 1.2035714382322826e-05, 3.3076061707490808e-05, 8.5780643722862892e-05, 2.1000778733594350e-04, 4.8548944122296688e-04, 1.0600860254999084e-03, 2.1869011800911028e-03, 4.2632921737953853e-03, 7.8556410099729287e-03, 1.3684318450535705e-02, 2.2539589851423701e-02, 3.5108996740976929e-02, 5.1725036108245200e-02, 7.2085145846744095e-02, 9.5038220322125194e-02, 1.1854839415593066e-01, 1.3991610657942335e-01, 1.5625599948674623e-01, 1.6512677086080088e-01, 1.6512677086080088e-01, 1.5625599948674623e-01, 1.3991610657942335e-01, 1.1854839415593066e-01, 9.5038220322125194e-02, 7.2085145846744095e-02, 5.1725036108245200e-02, 3.5108996740976929e-02, 2.2539589851423701e-02, 1.3684318450535705e-02, 7.8556410099729287e-03, 4.2632921737953853e-03, 2.1869011800911028e-03, 1.0600860254999084e-03, 4.8548944122296688e-04, 2.1000778733594350e-04, 8.5780643722862892e-05, 3.3076061707490808e-05, 1.2035714382322826e-05, 4.1315876560548306e-06, 1.3374965511498204e-06, 4.0816183881635333e-07, 1.1737053608502818e-07, 3.1789582778002615e-08, 8.1060721426662619e-09, 1.9450249932898343e-09, 4.3894092072618305e-10, 9.3114559517381624e-11, 1.8557142556642682e-11, 3.4723560883860410e-12, 6.0964973515510935e-13, 1.0036629079256339e-13, 1.5482439389379285e-14, 2.2362025898948135e-15, 3.0217745531718828e-16, 3.8170938055666007e-17, 4.5034462009468205e-18, 4.9579227287808755e-19, 5.0883502730989637e-20, 4.8633316486835449e-21, 4.3241778048815671e-22, 3.5726754325441841e-23, 2.7395824646129918e-24, 1.9472758171895140e-25, 1.2812781788064907e-26, 7.7932715085212503e-28, 4.3753093336081546e-29, 2.2637292363656048e-30, 1.0775571184918142e-31, 4.7107012996283542e-33, 1.8877397396823247e-34, 6.9205465629360576e-36, 2.3160882385061203e-37, 7.0599294307578851e-39, 1.9553490062333371e-40, 4.9079810854674800e-42, 1.1133537204234619e-43, 2.2757544084791531e-45, 4.1782480984927090e-47, 6.8667092650473948e-49, 1.0064229300129089e-50, 1.3102411068553504e-52, 1.5086081632928153e-54, 1.5290034639304410e-56, 1.3571109461554121e-58, 1.0489546649192595e-60, 7.0170567960964978e-63, 4.0351646934878695e-65, 1.9797683901166225e-67, 8.2184808615623598e-70, 2.8598818663126844e-72, 8.2555014673420022e-75, 1.9536604993085239e-77, 3.7396644213938176e-80, 5.7017766571657716e-83, 6.8022938891305936e-86, 6.2193919080044227e-89, 4.2524253414775605e-92, 2.1114364896149106e-95, 7.3466025769339733e-99, 1.7139381704010506e-102, 2.5353839157043305e-106, 2.2113953581884588e-110, 1.0311647067706544e-114, 2.2388300710588648e-119, 1.8390471781108747e-124, 4.0603558490313254e-130, 1.2537577338109092e-136, 1.0174451907169722e-144}, + {1.4459034710264201e-145, 1.8512101069007797e-137, 6.1900866973604703e-131, 2.8855379169821182e-125, 3.6080591054052492e-120, 1.7044183943684018e-115, 3.7449189704395232e-111, 4.3952304904350605e-107, 3.0394872358078098e-103, 1.3320382883615053e-99, 3.9122879439382170e-96, 8.0489834136101609e-93, 1.2021477111483726e-89, 1.3422872316499288e-86, 1.1483443011896613e-83, 7.6855073087396857e-81, 4.0962408560880496e-78, 1.7656535944547459e-75, 6.2384154226153306e-73, 1.8282206685181686e-70, 4.4907236877039048e-68, 9.3322988518723512e-66, 1.6545283606525458e-63, 2.5213872637605977e-61, 3.3253581541518404e-59, 3.8190282366232640e-57, 3.8408503131563961e-55, 3.4001469878023392e-53, 2.6620432033111890e-51, 1.8512591668862315e-49, 1.1481424339931328e-47, 6.3739969672637270e-46, 3.1784051437766470e-44, 1.4281570152975713e-42, 5.7996825799748193e-41, 2.1345161706875471e-39, 7.1381873166360108e-38, 2.1743217660681791e-36, 6.0463752750772134e-35, 1.5382579845230378e-33, 3.5875473238148687e-32, 7.6845885182041777e-31, 1.5145049680016594e-29, 2.7509103704580098e-28, 4.6123845343733745e-27, 7.1493666161606643e-26, 1.0259279798609206e-24, 1.3647547675188007e-23, 1.6851209810753113e-22, 1.9336042594232875e-21, 2.0642309881609900e-20, 2.0524462477993889e-19, 1.9026226109394554e-18, 1.6459732365754106e-17, 1.3300948716108394e-16, 1.0048759007103044e-15, 7.1035141604691271e-15, 4.7022739273699201e-14, 2.9170375040074331e-13, 1.6970108678299655e-12, 9.2646537879215591e-12, 4.7495690973542646e-11, 2.2878306073735174e-10, 1.0360690148079607e-09, 4.4135301064719171e-09, 1.7694607842914065e-08, 6.6798391472451806e-08, 2.3755404518235753e-07, 7.9619631902655087e-07, 2.5160446644029356e-06, 7.4993851915062359e-06, 2.1091170590509833e-05, 5.5987643740857493e-05, 1.4032641744066531e-04, 3.3217919994016825e-04, 7.4286891131823533e-04, 1.5698960784933606e-03, 3.1358280493826080e-03, 5.9217687653631513e-03, 1.0574395576910816e-02, 1.7858440641500769e-02, 2.8528992504062382e-02, 4.3116896847977884e-02, 6.1656983184778281e-02, 8.3433163844430863e-02, 1.0684575215294285e-01, 1.2950034028006346e-01, 1.4856115387707583e-01, 1.6131642239308974e-01, 1.6580659700649841e-01, 1.6131642239308974e-01, 1.4856115387707583e-01, 1.2950034028006346e-01, 1.0684575215294285e-01, 8.3433163844430863e-02, 6.1656983184778281e-02, 4.3116896847977884e-02, 2.8528992504062382e-02, 1.7858440641500769e-02, 1.0574395576910816e-02, 5.9217687653631513e-03, 3.1358280493826080e-03, 1.5698960784933606e-03, 7.4286891131823533e-04, 3.3217919994016825e-04, 1.4032641744066531e-04, 5.5987643740857493e-05, 2.1091170590509833e-05, 7.4993851915062359e-06, 2.5160446644029356e-06, 7.9619631902655087e-07, 2.3755404518235753e-07, 6.6798391472451806e-08, 1.7694607842914065e-08, 4.4135301064719171e-09, 1.0360690148079607e-09, 2.2878306073735174e-10, 4.7495690973542646e-11, 9.2646537879215591e-12, 1.6970108678299655e-12, 2.9170375040074331e-13, 4.7022739273699201e-14, 7.1035141604691271e-15, 1.0048759007103044e-15, 1.3300948716108394e-16, 1.6459732365754106e-17, 1.9026226109394554e-18, 2.0524462477993889e-19, 2.0642309881609900e-20, 1.9336042594232875e-21, 1.6851209810753113e-22, 1.3647547675188007e-23, 1.0259279798609206e-24, 7.1493666161606643e-26, 4.6123845343733745e-27, 2.7509103704580098e-28, 1.5145049680016594e-29, 7.6845885182041777e-31, 3.5875473238148687e-32, 1.5382579845230378e-33, 6.0463752750772134e-35, 2.1743217660681791e-36, 7.1381873166360108e-38, 2.1345161706875471e-39, 5.7996825799748193e-41, 1.4281570152975713e-42, 3.1784051437766470e-44, 6.3739969672637270e-46, 1.1481424339931328e-47, 1.8512591668862315e-49, 2.6620432033111890e-51, 3.4001469878023392e-53, 3.8408503131563961e-55, 3.8190282366232640e-57, 3.3253581541518404e-59, 2.5213872637605977e-61, 1.6545283606525458e-63, 9.3322988518723512e-66, 4.4907236877039048e-68, 1.8282206685181686e-70, 6.2384154226153306e-73, 1.7656535944547459e-75, 4.0962408560880496e-78, 7.6855073087396857e-81, 1.1483443011896613e-83, 1.3422872316499288e-86, 1.2021477111483726e-89, 8.0489834136101609e-93, 3.9122879439382170e-96, 1.3320382883615053e-99, 3.0394872358078098e-103, 4.3952304904350605e-107, 3.7449189704395232e-111, 1.7044183943684018e-115, 3.6080591054052492e-120, 2.8855379169821182e-125, 6.1900866973604703e-131, 1.8512101069007797e-137, 1.4459034710264201e-145}, + {2.0544167081187589e-146, 2.7324651628287789e-138, 9.4326009424734410e-132, 4.5249380509459828e-126, 5.8107301413051742e-121, 2.8150324044562284e-116, 6.3362635154258981e-112, 7.6118645291179184e-108, 5.3843632439536920e-104, 2.4123127079122074e-100, 7.2398333677694101e-97, 1.5214189335297059e-93, 2.3202235060376314e-90, 2.6445775673882037e-87, 2.3089447193822174e-84, 1.5767056174162126e-81, 8.5727195865402764e-79, 3.7689704357176965e-76, 1.3580443028284028e-73, 4.0582349306406949e-71, 1.0163600799789738e-68, 2.1532917098122703e-66, 3.8916837271887350e-64, 6.0453772000204261e-62, 8.1267907500285513e-60, 9.5128584361969727e-58, 9.7509710005032432e-56, 8.7976987433650472e-54, 7.0198773756157181e-52, 4.9753094376640113e-50, 3.1447462107627518e-48, 1.7792627000157171e-46, 9.0423237558527988e-45, 4.1409133307449204e-43, 1.7138906209368488e-41, 6.4290783512879458e-40, 2.1913996777475932e-38, 6.8039020082108794e-37, 1.9286270378988431e-35, 5.0017461082503641e-34, 1.1891915619808499e-32, 2.5969337466904165e-31, 5.2182308893507914e-30, 9.6642798753295627e-29, 1.6523003694364310e-27, 2.6117599911695471e-26, 3.8222432521976105e-25, 5.1859356642906214e-24, 6.5314813585357555e-23, 7.6453095155047312e-22, 8.3267040963735343e-21, 8.4472663315088944e-20, 7.9904365646153140e-19, 7.0543936381041909e-18, 5.8181634606657441e-17, 4.4867423723460479e-16, 3.2378602233952898e-15, 2.1883227889949076e-14, 1.3861757281246388e-13, 8.2354944810071531e-13, 4.5921996541535561e-12, 2.4048711144413950e-11, 1.1835015186215515e-10, 5.4765134657351679e-10, 2.3841694011026308e-09, 9.7699965359482599e-09, 3.7704288545104245e-08, 1.3709740387891837e-07, 4.6989603841203290e-07, 1.5187614573110066e-06, 4.6308779212753262e-06, 1.3325507543076759e-05, 3.6199433343496547e-05, 9.2866446344988979e-05, 2.2505423008074610e-04, 5.1535932107027135e-04, 1.1154298676886345e-03, 2.2823888738018917e-03, 4.4162127170279562e-03, 8.0818888889421375e-03, 1.3991358954534535e-02, 2.2917370391076095e-02, 3.5521683059969993e-02, 5.2108016747135361e-02, 7.2351691768296089e-02, 9.5097571709914869e-02, 1.1833217723448959e-01, 1.3940481744965749e-01, 1.5549476479437641e-01, 1.6422194087055850e-01, 1.6422194087055850e-01, 1.5549476479437641e-01, 1.3940481744965749e-01, 1.1833217723448959e-01, 9.5097571709914869e-02, 7.2351691768296089e-02, 5.2108016747135361e-02, 3.5521683059969993e-02, 2.2917370391076095e-02, 1.3991358954534535e-02, 8.0818888889421375e-03, 4.4162127170279562e-03, 2.2823888738018917e-03, 1.1154298676886345e-03, 5.1535932107027135e-04, 2.2505423008074610e-04, 9.2866446344988979e-05, 3.6199433343496547e-05, 1.3325507543076759e-05, 4.6308779212753262e-06, 1.5187614573110066e-06, 4.6989603841203290e-07, 1.3709740387891837e-07, 3.7704288545104245e-08, 9.7699965359482599e-09, 2.3841694011026308e-09, 5.4765134657351679e-10, 1.1835015186215515e-10, 2.4048711144413950e-11, 4.5921996541535561e-12, 8.2354944810071531e-13, 1.3861757281246388e-13, 2.1883227889949076e-14, 3.2378602233952898e-15, 4.4867423723460479e-16, 5.8181634606657441e-17, 7.0543936381041909e-18, 7.9904365646153140e-19, 8.4472663315088944e-20, 8.3267040963735343e-21, 7.6453095155047312e-22, 6.5314813585357555e-23, 5.1859356642906214e-24, 3.8222432521976105e-25, 2.6117599911695471e-26, 1.6523003694364310e-27, 9.6642798753295627e-29, 5.2182308893507914e-30, 2.5969337466904165e-31, 1.1891915619808499e-32, 5.0017461082503641e-34, 1.9286270378988431e-35, 6.8039020082108794e-37, 2.1913996777475932e-38, 6.4290783512879458e-40, 1.7138906209368488e-41, 4.1409133307449204e-43, 9.0423237558527988e-45, 1.7792627000157171e-46, 3.1447462107627518e-48, 4.9753094376640113e-50, 7.0198773756157181e-52, 8.7976987433650472e-54, 9.7509710005032432e-56, 9.5128584361969727e-58, 8.1267907500285513e-60, 6.0453772000204261e-62, 3.8916837271887350e-64, 2.1532917098122703e-66, 1.0163600799789738e-68, 4.0582349306406949e-71, 1.3580443028284028e-73, 3.7689704357176965e-76, 8.5727195865402764e-79, 1.5767056174162126e-81, 2.3089447193822174e-84, 2.6445775673882037e-87, 2.3202235060376314e-90, 1.5214189335297059e-93, 7.2398333677694101e-97, 2.4123127079122074e-100, 5.3843632439536920e-104, 7.6118645291179184e-108, 6.3362635154258981e-112, 2.8150324044562284e-116, 5.8107301413051742e-121, 4.5249380509459828e-126, 9.4326009424734410e-132, 2.7324651628287789e-138, 2.0544167081187589e-146}, + {2.9184983704075192e-147, 4.0319183713400766e-139, 1.4367134541050939e-132, 7.0917398018507910e-127, 9.3517988737392972e-122, 4.6457185244440549e-117, 1.0711309190325783e-112, 1.3169706905085093e-108, 9.5280026251390744e-105, 4.3635736981957750e-101, 1.3380638102406329e-97, 2.8718782241763001e-94, 4.4716757994553476e-91, 5.2022930902389893e-88, 4.6349150479031114e-85, 3.2290491038758581e-82, 1.7908398704126536e-79, 8.0297842302329272e-77, 2.9503683873426791e-74, 8.9893224354049310e-72, 2.2951885774902920e-69, 4.9569512961693677e-67, 9.1317952402850698e-65, 1.4458391823512865e-62, 1.9809319471106229e-60, 2.3631742826980710e-58, 2.4686029155016893e-56, 2.2697566491840546e-54, 1.8456028929462080e-52, 1.3329759770755586e-50, 8.5857720828783205e-49, 4.9502403838758848e-47, 2.5636716593985549e-45, 1.1964123882499316e-43, 5.0463692733981642e-42, 1.9291541526211061e-40, 6.7015535541500665e-39, 2.1206217889043141e-37, 6.1266403471398839e-36, 1.6195131761876436e-34, 3.9248683542722297e-33, 8.7371187009076405e-32, 1.7897414312928308e-30, 3.3792749075968173e-29, 5.8905961617051956e-28, 9.4940326558644130e-27, 1.4168234014649860e-25, 1.9603740051045881e-24, 2.5181065241794600e-23, 3.0063944491537587e-22, 3.3400431583218902e-21, 3.4567219838648987e-20, 3.3360382939472660e-19, 3.0052255828362505e-18, 2.5293356487116101e-17, 1.9906862214252033e-16, 1.4663260946610058e-15, 1.0116632951507467e-14, 6.5425658781468336e-14, 3.9689851927958321e-13, 2.2600968959480387e-12, 1.2088512678946103e-11, 6.0769364101383090e-11, 2.8728746426712136e-10, 1.2779384152123448e-09, 5.3517155996766336e-09, 2.1109723472766886e-08, 7.8466356162788103e-08, 2.7497279026009702e-07, 9.0883362098124687e-07, 2.8342636150206807e-06, 8.3429573893995674e-06, 2.3188718962635865e-05, 6.0877111145275987e-05, 1.5100325433613592e-04, 3.5399662151566394e-04, 7.8452960713547043e-04, 1.6440892137594167e-03, 3.2587225571780792e-03, 6.1103686178933300e-03, 1.0841005727093818e-02, 1.8202465449941120e-02, 2.8927974168057351e-02, 4.3520526497899684e-02, 6.1988666273243780e-02, 8.3602420563279559e-02, 1.0677090675896843e-01, 1.2913573606742534e-01, 1.4791906474448899e-01, 1.6047364667465450e-01, 1.6489053845950130e-01, 1.6047364667465450e-01, 1.4791906474448899e-01, 1.2913573606742534e-01, 1.0677090675896843e-01, 8.3602420563279559e-02, 6.1988666273243780e-02, 4.3520526497899684e-02, 2.8927974168057351e-02, 1.8202465449941120e-02, 1.0841005727093818e-02, 6.1103686178933300e-03, 3.2587225571780792e-03, 1.6440892137594167e-03, 7.8452960713547043e-04, 3.5399662151566394e-04, 1.5100325433613592e-04, 6.0877111145275987e-05, 2.3188718962635865e-05, 8.3429573893995674e-06, 2.8342636150206807e-06, 9.0883362098124687e-07, 2.7497279026009702e-07, 7.8466356162788103e-08, 2.1109723472766886e-08, 5.3517155996766336e-09, 1.2779384152123448e-09, 2.8728746426712136e-10, 6.0769364101383090e-11, 1.2088512678946103e-11, 2.2600968959480387e-12, 3.9689851927958321e-13, 6.5425658781468336e-14, 1.0116632951507467e-14, 1.4663260946610058e-15, 1.9906862214252033e-16, 2.5293356487116101e-17, 3.0052255828362505e-18, 3.3360382939472660e-19, 3.4567219838648987e-20, 3.3400431583218902e-21, 3.0063944491537587e-22, 2.5181065241794600e-23, 1.9603740051045881e-24, 1.4168234014649860e-25, 9.4940326558644130e-27, 5.8905961617051956e-28, 3.3792749075968173e-29, 1.7897414312928308e-30, 8.7371187009076405e-32, 3.9248683542722297e-33, 1.6195131761876436e-34, 6.1266403471398839e-36, 2.1206217889043141e-37, 6.7015535541500665e-39, 1.9291541526211061e-40, 5.0463692733981642e-42, 1.1964123882499316e-43, 2.5636716593985549e-45, 4.9502403838758848e-47, 8.5857720828783205e-49, 1.3329759770755586e-50, 1.8456028929462080e-52, 2.2697566491840546e-54, 2.4686029155016893e-56, 2.3631742826980710e-58, 1.9809319471106229e-60, 1.4458391823512865e-62, 9.1317952402850698e-65, 4.9569512961693677e-67, 2.2951885774902920e-69, 8.9893224354049310e-72, 2.9503683873426791e-74, 8.0297842302329272e-77, 1.7908398704126536e-79, 3.2290491038758581e-82, 4.6349150479031114e-85, 5.2022930902389893e-88, 4.4716757994553476e-91, 2.8718782241763001e-94, 1.3380638102406329e-97, 4.3635736981957750e-101, 9.5280026251390744e-105, 1.3169706905085093e-108, 1.0711309190325783e-112, 4.6457185244440549e-117, 9.3517988737392972e-122, 7.0917398018507910e-127, 1.4367134541050939e-132, 4.0319183713400766e-139, 2.9184983704075192e-147}, + {4.1452696623483395e-148, 5.9474161464872244e-140, 2.1873318060197500e-133, 1.1108350634945189e-127, 1.5040760324474137e-122, 7.6610437292542439e-118, 1.8091479691129481e-113, 2.2763600768872421e-109, 1.6842534274181958e-105, 7.8840222434465455e-102, 2.4699093339298307e-98, 5.4137540405290719e-95, 8.6056883186768174e-92, 1.0218043358339510e-88, 9.2888951681828944e-86, 6.6016471696136248e-83, 3.7342898142071596e-80, 1.7074874775824880e-77, 6.3969105456232966e-75, 1.9870439601235429e-72, 5.1717638304628555e-70, 1.1385038568984282e-67, 2.1376722221415430e-65, 3.4493784123174178e-63, 4.8161711078239858e-61, 5.8549015274027961e-59, 6.2323324068554731e-57, 5.8390470979220446e-55, 4.8378847700931107e-53, 3.5603170842517748e-51, 2.3366431061277383e-49, 1.3727341637645679e-47, 7.2439067732577147e-46, 3.4446682433867826e-44, 1.4805046972403839e-42, 5.7672996866961233e-41, 2.0415908964489771e-39, 6.5835338360421613e-38, 1.9383756218147382e-36, 5.2220236908204409e-35, 1.2898503021552704e-33, 2.9266129491084507e-32, 6.1107571504811921e-31, 1.1761496941464036e-29, 2.0900714057742614e-28, 3.4343583117038137e-27, 5.2255927032642325e-26, 7.3725440555518383e-25, 9.6570947115181529e-24, 1.1758429681040065e-22, 1.3323707929307384e-21, 1.4065250811244644e-20, 1.3847330443129062e-19, 1.2726463913998945e-18, 1.0928940877684042e-17, 8.7773275665944823e-17, 6.5982162774306465e-16, 4.6464228722152545e-15, 3.0673938466320995e-14, 1.8997359653204635e-13, 1.1045578960219544e-12, 6.0330789028505752e-12, 3.0975214481618230e-11, 1.4957890384694261e-10, 6.7975116544323199e-10, 2.9085970464514601e-09, 1.1724370655087347e-08, 4.4542518892262074e-08, 1.5956404054013332e-07, 5.3920679976732085e-07, 1.7195329738679880e-06, 5.1768455512555845e-06, 1.4718871925099586e-05, 3.9535219175273295e-05, 1.0035307023681430e-04, 2.4079185627092926e-04, 5.4630685564139225e-04, 1.1722653593393563e-03, 2.3796447518820959e-03, 4.5707734636933712e-03, 8.3089325331250057e-03, 1.4297417780659441e-02, 2.3291535150151157e-02, 3.5927796289914674e-02, 5.2482133056536061e-02, 7.2608927339705281e-02, 9.5149879125439124e-02, 1.1811391373984721e-01, 1.3889811387154746e-01, 1.5474440942350939e-01, 1.6333182250163769e-01, 1.6333182250163769e-01, 1.5474440942350939e-01, 1.3889811387154746e-01, 1.1811391373984721e-01, 9.5149879125439124e-02, 7.2608927339705281e-02, 5.2482133056536061e-02, 3.5927796289914674e-02, 2.3291535150151157e-02, 1.4297417780659441e-02, 8.3089325331250057e-03, 4.5707734636933712e-03, 2.3796447518820959e-03, 1.1722653593393563e-03, 5.4630685564139225e-04, 2.4079185627092926e-04, 1.0035307023681430e-04, 3.9535219175273295e-05, 1.4718871925099586e-05, 5.1768455512555845e-06, 1.7195329738679880e-06, 5.3920679976732085e-07, 1.5956404054013332e-07, 4.4542518892262074e-08, 1.1724370655087347e-08, 2.9085970464514601e-09, 6.7975116544323199e-10, 1.4957890384694261e-10, 3.0975214481618230e-11, 6.0330789028505752e-12, 1.1045578960219544e-12, 1.8997359653204635e-13, 3.0673938466320995e-14, 4.6464228722152545e-15, 6.5982162774306465e-16, 8.7773275665944823e-17, 1.0928940877684042e-17, 1.2726463913998945e-18, 1.3847330443129062e-19, 1.4065250811244644e-20, 1.3323707929307384e-21, 1.1758429681040065e-22, 9.6570947115181529e-24, 7.3725440555518383e-25, 5.2255927032642325e-26, 3.4343583117038137e-27, 2.0900714057742614e-28, 1.1761496941464036e-29, 6.1107571504811921e-31, 2.9266129491084507e-32, 1.2898503021552704e-33, 5.2220236908204409e-35, 1.9383756218147382e-36, 6.5835338360421613e-38, 2.0415908964489771e-39, 5.7672996866961233e-41, 1.4805046972403839e-42, 3.4446682433867826e-44, 7.2439067732577147e-46, 1.3727341637645679e-47, 2.3366431061277383e-49, 3.5603170842517748e-51, 4.8378847700931107e-53, 5.8390470979220446e-55, 6.2323324068554731e-57, 5.8549015274027961e-59, 4.8161711078239858e-61, 3.4493784123174178e-63, 2.1376722221415430e-65, 1.1385038568984282e-67, 5.1717638304628555e-70, 1.9870439601235429e-72, 6.3969105456232966e-75, 1.7074874775824880e-77, 3.7342898142071596e-80, 6.6016471696136248e-83, 9.2888951681828944e-86, 1.0218043358339510e-88, 8.6056883186768174e-92, 5.4137540405290719e-95, 2.4699093339298307e-98, 7.8840222434465455e-102, 1.6842534274181958e-105, 2.2763600768872421e-109, 1.8091479691129481e-113, 7.6610437292542439e-118, 1.5040760324474137e-122, 1.1108350634945189e-127, 2.1873318060197500e-133, 5.9474161464872244e-140, 4.1452696623483395e-148}, + {5.8866637956879832e-149, 8.7701238593349446e-141, 3.3286398376690490e-134, 1.7390228685740816e-128, 2.4174491971248305e-123, 1.2623847464849609e-118, 3.0530327446766110e-114, 3.9308789125198654e-110, 2.9740999490947605e-106, 1.4228368487505154e-102, 4.5535119727458115e-99, 1.0191828364399763e-95, 1.6537960518565174e-92, 2.0039262792917714e-89, 1.8586066284522124e-86, 1.3473832322197353e-83, 7.7728521820677718e-81, 3.6240329528761601e-78, 1.3842194496021173e-75, 4.3831680288373217e-73, 1.1628357927637541e-70, 2.6089921702855559e-68, 4.9923292649319471e-66, 8.2091330064948600e-64, 1.1679600204323236e-61, 1.4467547750792869e-59, 1.5691297806630218e-57, 1.4978576876165396e-55, 1.2644313857762022e-53, 9.4805533849020122e-52, 6.3392777437739552e-50, 3.7943396524379168e-48, 2.0399882317508400e-46, 9.8835394906743943e-45, 4.3280559299142535e-43, 1.7178434457904729e-41, 6.1961228512356421e-40, 2.0359401385923293e-38, 6.1082242612809361e-37, 1.6768933675263854e-35, 4.2210054325158127e-34, 9.7605477823793654e-33, 2.0771142264898199e-31, 4.0748381699253249e-30, 7.3810648870417183e-29, 1.2363547377218958e-27, 1.9178022081467005e-26, 2.7586033246049575e-25, 3.6843129796217172e-24, 4.5743951370215857e-23, 5.2859323137468154e-22, 5.6910915175835955e-21, 5.7148760619818976e-20, 5.3577677281181046e-19, 4.6939007358067331e-18, 3.8463054439056453e-17, 2.9504021972772029e-16, 2.1202927606877813e-15, 1.4286304928072976e-14, 9.0316979019406731e-14, 5.3609851542957339e-13, 2.9897229802024487e-12, 1.5674715085860065e-11, 7.7305137154009676e-11, 3.5884068378224706e-10, 1.5685984370316076e-09, 6.4603917825466764e-09, 2.5081389998281072e-08, 9.1830644706366585e-08, 3.1721513586827257e-07, 1.0342536339020313e-06, 3.1840053712593505e-06, 9.2587247391013518e-06, 2.5439403557345701e-05, 6.6066258510845340e-05, 1.6221813086114782e-04, 3.7669274161032700e-04, 8.2747754872833888e-04, 1.7199311750936504e-03, 3.3833630340537615e-03, 6.3002503573431189e-03, 1.1107594867856934e-02, 1.8544242319012489e-02, 2.9321853906612717e-02, 4.3916343744405027e-02, 6.2311084328469719e-02, 8.3763283089409293e-02, 1.0669133852506041e-01, 1.2877234499448006e-01, 1.4728481639742919e-01, 1.5964391640203837e-01, 1.6398949726573361e-01, 1.5964391640203837e-01, 1.4728481639742919e-01, 1.2877234499448006e-01, 1.0669133852506041e-01, 8.3763283089409293e-02, 6.2311084328469719e-02, 4.3916343744405027e-02, 2.9321853906612717e-02, 1.8544242319012489e-02, 1.1107594867856934e-02, 6.3002503573431189e-03, 3.3833630340537615e-03, 1.7199311750936504e-03, 8.2747754872833888e-04, 3.7669274161032700e-04, 1.6221813086114782e-04, 6.6066258510845340e-05, 2.5439403557345701e-05, 9.2587247391013518e-06, 3.1840053712593505e-06, 1.0342536339020313e-06, 3.1721513586827257e-07, 9.1830644706366585e-08, 2.5081389998281072e-08, 6.4603917825466764e-09, 1.5685984370316076e-09, 3.5884068378224706e-10, 7.7305137154009676e-11, 1.5674715085860065e-11, 2.9897229802024487e-12, 5.3609851542957339e-13, 9.0316979019406731e-14, 1.4286304928072976e-14, 2.1202927606877813e-15, 2.9504021972772029e-16, 3.8463054439056453e-17, 4.6939007358067331e-18, 5.3577677281181046e-19, 5.7148760619818976e-20, 5.6910915175835955e-21, 5.2859323137468154e-22, 4.5743951370215857e-23, 3.6843129796217172e-24, 2.7586033246049575e-25, 1.9178022081467005e-26, 1.2363547377218958e-27, 7.3810648870417183e-29, 4.0748381699253249e-30, 2.0771142264898199e-31, 9.7605477823793654e-33, 4.2210054325158127e-34, 1.6768933675263854e-35, 6.1082242612809361e-37, 2.0359401385923293e-38, 6.1961228512356421e-40, 1.7178434457904729e-41, 4.3280559299142535e-43, 9.8835394906743943e-45, 2.0399882317508400e-46, 3.7943396524379168e-48, 6.3392777437739552e-50, 9.4805533849020122e-52, 1.2644313857762022e-53, 1.4978576876165396e-55, 1.5691297806630218e-57, 1.4467547750792869e-59, 1.1679600204323236e-61, 8.2091330064948600e-64, 4.9923292649319471e-66, 2.6089921702855559e-68, 1.1628357927637541e-70, 4.3831680288373217e-73, 1.3842194496021173e-75, 3.6240329528761601e-78, 7.7728521820677718e-81, 1.3473832322197353e-83, 1.8586066284522124e-86, 2.0039262792917714e-89, 1.6537960518565174e-92, 1.0191828364399763e-95, 4.5535119727458115e-99, 1.4228368487505154e-102, 2.9740999490947605e-106, 3.9308789125198654e-110, 3.0530327446766110e-114, 1.2623847464849609e-118, 2.4174491971248305e-123, 1.7390228685740816e-128, 3.3286398376690490e-134, 8.7701238593349446e-141, 5.8866637956879832e-149}, + {8.3581373975539108e-150, 1.2928412877755577e-141, 5.0632382588324120e-135, 2.7209602221952139e-129, 3.8829389622015062e-124, 2.0785832875875387e-119, 5.1477595408996125e-115, 6.7815072200124497e-111, 5.2462701695642363e-107, 2.5648912231375885e-103, 8.3845258592424195e-100, 1.9161630252069163e-96, 3.1736968736455641e-93, 3.9241298067673186e-90, 3.7129493377218318e-87, 2.7453553081368732e-84, 1.6150344379416257e-81, 7.6774327866656284e-79, 2.9894343828423281e-76, 9.6489070550182607e-74, 2.6089586336270140e-71, 5.9654008943367430e-69, 1.1631966527487701e-66, 1.9489490740739864e-64, 2.8252664298663074e-62, 3.5656104439409607e-60, 3.9399315442250632e-58, 3.8315828065199010e-56, 3.2951200002417535e-54, 2.5169328462380233e-52, 1.7144956007470846e-50, 1.0454204091183458e-48, 5.7258874684495484e-47, 2.8261341310391440e-45, 1.2607977361040919e-43, 5.0982121558902017e-42, 1.8734745650648728e-40, 6.2719136180711063e-39, 1.9172254945419127e-37, 5.3629616050774624e-36, 1.3755486543958331e-34, 3.2412811142581749e-33, 7.0292474203881568e-32, 1.4053678782835759e-30, 2.5945192595304142e-29, 4.4296347519346036e-28, 7.0039976811745699e-27, 1.0270246629696484e-25, 1.3983996188477357e-24, 1.7702189074849013e-23, 2.0857890645994067e-22, 2.2900155277371847e-21, 2.3452218050389733e-20, 2.2425235675550114e-19, 2.0040402270860207e-18, 1.6752540366716003e-17, 1.3110796195605400e-16, 9.6139706301947510e-16, 6.6105224464386113e-15, 4.2652608433469510e-14, 2.5842479214605026e-13, 1.4712572098023350e-12, 7.8755658569412608e-12, 3.9661851656268533e-11, 1.8802196827204209e-10, 8.3950345085448172e-10, 3.5321294226177634e-09, 1.4010751708171831e-08, 5.2419925848831286e-08, 1.8506755890537394e-07, 6.1679613744986908e-07, 1.9413286157507076e-06, 5.7724680860172742e-06, 1.6221044402072930e-05, 4.3091495767535577e-05, 1.0825095642068624e-04, 2.5723066429963950e-04, 5.7833524878596126e-04, 1.2305790314187559e-03, 2.4786280618533298e-03, 4.7269014592664482e-03, 8.5366761761569536e-03, 1.4602406139195508e-02, 2.3662049334306538e-02, 3.6327402988086469e-02, 5.2847573265457019e-02, 7.2857131060649991e-02, 9.5195424202311488e-02, 1.1789377323403843e-01, 1.3839596229316664e-01, 1.5400468068882942e-01, 1.6245602140829696e-01, 1.6245602140829696e-01, 1.5400468068882942e-01, 1.3839596229316664e-01, 1.1789377323403843e-01, 9.5195424202311488e-02, 7.2857131060649991e-02, 5.2847573265457019e-02, 3.6327402988086469e-02, 2.3662049334306538e-02, 1.4602406139195508e-02, 8.5366761761569536e-03, 4.7269014592664482e-03, 2.4786280618533298e-03, 1.2305790314187559e-03, 5.7833524878596126e-04, 2.5723066429963950e-04, 1.0825095642068624e-04, 4.3091495767535577e-05, 1.6221044402072930e-05, 5.7724680860172742e-06, 1.9413286157507076e-06, 6.1679613744986908e-07, 1.8506755890537394e-07, 5.2419925848831286e-08, 1.4010751708171831e-08, 3.5321294226177634e-09, 8.3950345085448172e-10, 1.8802196827204209e-10, 3.9661851656268533e-11, 7.8755658569412608e-12, 1.4712572098023350e-12, 2.5842479214605026e-13, 4.2652608433469510e-14, 6.6105224464386113e-15, 9.6139706301947510e-16, 1.3110796195605400e-16, 1.6752540366716003e-17, 2.0040402270860207e-18, 2.2425235675550114e-19, 2.3452218050389733e-20, 2.2900155277371847e-21, 2.0857890645994067e-22, 1.7702189074849013e-23, 1.3983996188477357e-24, 1.0270246629696484e-25, 7.0039976811745699e-27, 4.4296347519346036e-28, 2.5945192595304142e-29, 1.4053678782835759e-30, 7.0292474203881568e-32, 3.2412811142581749e-33, 1.3755486543958331e-34, 5.3629616050774624e-36, 1.9172254945419127e-37, 6.2719136180711063e-39, 1.8734745650648728e-40, 5.0982121558902017e-42, 1.2607977361040919e-43, 2.8261341310391440e-45, 5.7258874684495484e-47, 1.0454204091183458e-48, 1.7144956007470846e-50, 2.5169328462380233e-52, 3.2951200002417535e-54, 3.8315828065199010e-56, 3.9399315442250632e-58, 3.5656104439409607e-60, 2.8252664298663074e-62, 1.9489490740739864e-64, 1.1631966527487701e-66, 5.9654008943367430e-69, 2.6089586336270140e-71, 9.6489070550182607e-74, 2.9894343828423281e-76, 7.6774327866656284e-79, 1.6150344379416257e-81, 2.7453553081368732e-84, 3.7129493377218318e-87, 3.9241298067673186e-90, 3.1736968736455641e-93, 1.9161630252069163e-96, 8.3845258592424195e-100, 2.5648912231375885e-103, 5.2462701695642363e-107, 6.7815072200124497e-111, 5.1477595408996125e-115, 2.0785832875875387e-119, 3.8829389622015062e-124, 2.7209602221952139e-129, 5.0632382588324120e-135, 1.2928412877755577e-141, 8.3581373975539108e-150}, + {1.1865178694667318e-150, 1.9052328091840223e-142, 7.6984112043987381e-136, 4.2550288152769099e-130, 6.2327840907767578e-125, 3.4199371076928271e-120, 8.6723736530813987e-116, 1.1688387166643387e-111, 9.2447904963657574e-108, 4.6184277629201267e-104, 1.5419925530578493e-100, 3.5978676971165183e-97, 6.0819398055170106e-94, 7.6728915952440279e-91, 7.4056905596969795e-88, 5.5844689207576789e-85, 3.3498078614715179e-82, 1.6234441963286573e-79, 6.4436381052523653e-77, 2.1197593898507255e-74, 5.8410998823252364e-72, 1.3609591582325947e-69, 2.7039668570857215e-67, 4.6159532490505087e-65, 6.8172254689772145e-63, 8.7649300109604261e-61, 9.8662587260951024e-59, 9.7741261753796815e-57, 8.5624277958175666e-55, 6.6621826190749697e-53, 4.6227110569813219e-51, 2.8712161421730314e-49, 1.6018948070503715e-47, 8.0538675955345321e-46, 3.6600273200497822e-44, 1.5076237023555035e-42, 5.6437809696463000e-41, 1.9247883296069542e-39, 5.9942100762419949e-38, 1.7082702187606927e-36, 4.4641638317895058e-35, 1.0718010386176091e-33, 2.3684402708428834e-32, 4.8253003329308802e-31, 9.0781689354637632e-30, 1.5795898083977327e-28, 2.5455821620542874e-27, 3.8046791468512480e-26, 5.2807723431418099e-25, 6.8148555847519964e-24, 8.1865279023956756e-23, 9.1644244237263828e-22, 9.5703407786302617e-21, 9.3325018346830289e-20, 8.5060423271066705e-19, 7.2528021781457044e-18, 5.7903374085298744e-17, 4.3318599899726389e-16, 3.0391558780794568e-15, 2.0010535409370048e-14, 1.2373574238435096e-13, 7.1903669458823460e-13, 3.9291706318326725e-12, 2.0202524727399665e-11, 9.7794253591584735e-11, 4.4592266183083370e-10, 1.9163195825780139e-09, 7.7651658482449274e-09, 2.9683092240535501e-08, 1.0708625929490390e-07, 3.6475807440990068e-07, 1.1735270767794228e-06, 3.5674612381232805e-06, 1.0250735219808427e-05, 2.7849862113005195e-05, 7.1564447183165722e-05, 1.7398159469356308e-04, 4.0027477960329739e-04, 8.7170842819435444e-04, 1.7973955409015775e-03, 3.5096925793779445e-03, 6.4913282065116552e-03, 1.1374067733309335e-02, 1.8883705620831706e-02, 2.9710644677922813e-02, 4.4304476145580723e-02, 6.2624475272894761e-02, 8.3916039610710105e-02, 1.0660728151712012e-01, 1.2841023960066572e-01, 1.4665826336478710e-01, 1.5882689919380447e-01, 1.6310306755078369e-01, 1.5882689919380447e-01, 1.4665826336478710e-01, 1.2841023960066572e-01, 1.0660728151712012e-01, 8.3916039610710105e-02, 6.2624475272894761e-02, 4.4304476145580723e-02, 2.9710644677922813e-02, 1.8883705620831706e-02, 1.1374067733309335e-02, 6.4913282065116552e-03, 3.5096925793779445e-03, 1.7973955409015775e-03, 8.7170842819435444e-04, 4.0027477960329739e-04, 1.7398159469356308e-04, 7.1564447183165722e-05, 2.7849862113005195e-05, 1.0250735219808427e-05, 3.5674612381232805e-06, 1.1735270767794228e-06, 3.6475807440990068e-07, 1.0708625929490390e-07, 2.9683092240535501e-08, 7.7651658482449274e-09, 1.9163195825780139e-09, 4.4592266183083370e-10, 9.7794253591584735e-11, 2.0202524727399665e-11, 3.9291706318326725e-12, 7.1903669458823460e-13, 1.2373574238435096e-13, 2.0010535409370048e-14, 3.0391558780794568e-15, 4.3318599899726389e-16, 5.7903374085298744e-17, 7.2528021781457044e-18, 8.5060423271066705e-19, 9.3325018346830289e-20, 9.5703407786302617e-21, 9.1644244237263828e-22, 8.1865279023956756e-23, 6.8148555847519964e-24, 5.2807723431418099e-25, 3.8046791468512480e-26, 2.5455821620542874e-27, 1.5795898083977327e-28, 9.0781689354637632e-30, 4.8253003329308802e-31, 2.3684402708428834e-32, 1.0718010386176091e-33, 4.4641638317895058e-35, 1.7082702187606927e-36, 5.9942100762419949e-38, 1.9247883296069542e-39, 5.6437809696463000e-41, 1.5076237023555035e-42, 3.6600273200497822e-44, 8.0538675955345321e-46, 1.6018948070503715e-47, 2.8712161421730314e-49, 4.6227110569813219e-51, 6.6621826190749697e-53, 8.5624277958175666e-55, 9.7741261753796815e-57, 9.8662587260951024e-59, 8.7649300109604261e-61, 6.8172254689772145e-63, 4.6159532490505087e-65, 2.7039668570857215e-67, 1.3609591582325947e-69, 5.8410998823252364e-72, 2.1197593898507255e-74, 6.4436381052523653e-77, 1.6234441963286573e-79, 3.3498078614715179e-82, 5.5844689207576789e-85, 7.4056905596969795e-88, 7.6728915952440279e-91, 6.0819398055170106e-94, 3.5978676971165183e-97, 1.5419925530578493e-100, 4.6184277629201267e-104, 9.2447904963657574e-108, 1.1688387166643387e-111, 8.6723736530813987e-116, 3.4199371076928271e-120, 6.2327840907767578e-125, 4.2550288152769099e-130, 7.6984112043987381e-136, 1.9052328091840223e-142, 1.1865178694667318e-150}, + {1.6840859823147192e-151, 2.8068259915465668e-143, 1.1700024361722009e-136, 6.6504100620446623e-131, 9.9982626870689096e-126, 5.6227251746796540e-121, 1.4598025546816272e-116, 2.0126980605111617e-112, 1.6274180017356631e-108, 8.3068317564996415e-105, 2.8324541894274240e-101, 6.7467686874093196e-98, 1.1639059887066096e-94, 1.4980806006797597e-91, 1.4748024918249946e-88, 1.1340919960793407e-85, 6.9358925722736469e-83, 3.4266063564656041e-80, 1.3862443412766689e-77, 4.6475320184424221e-75, 1.3049987561313226e-72, 3.0981254141048187e-70, 6.2713089100746324e-68, 1.0906635714604883e-65, 1.6409070764036964e-63, 2.1490689833897993e-61, 2.4641241627782225e-59, 2.4864657741894790e-57, 2.2186336768274302e-55, 1.7582563693437111e-53, 1.2426111111041695e-51, 7.8609642161410873e-50, 4.4670071717223134e-48, 2.2875134062797375e-46, 1.0588298166277823e-44, 4.4424843586907703e-43, 1.6939665809360599e-41, 5.8848055182020130e-40, 1.8668536705967508e-38, 5.4197686272780061e-37, 1.4428750537835282e-35, 3.5292920298964982e-34, 7.9458957717354865e-33, 1.6494369134608046e-31, 3.1620314656015991e-30, 5.6065555004969651e-29, 9.2077125425461603e-28, 1.4025749559057771e-26, 1.9841800348065493e-25, 2.6100548891439468e-24, 3.1962255598539348e-23, 3.6477448742277230e-22, 3.8838880473136030e-21, 3.8618679709476893e-20, 3.5894545533623586e-19, 3.1214143458455917e-18, 2.5417847367765562e-17, 1.9397457159226965e-16, 1.3883744241015343e-15, 9.3270625462533699e-15, 5.8852482736096351e-14, 3.4902504651461380e-13, 1.9466883562172841e-12, 1.0217552929953939e-11, 5.0496076724281894e-11, 2.3510718451740779e-10, 1.0318035977700679e-09, 4.2703647703012249e-09, 1.6675261164947539e-08, 6.1462809064451552e-08, 2.1392739679622303e-07, 7.0340742267172300e-07, 2.1857314406758851e-06, 6.4208055079598766e-06, 1.7837324122194181e-05, 4.6876297088489141e-05, 1.1657026717177768e-04, 2.7438000977925001e-04, 6.1144669240944507e-04, 1.2903563124214057e-03, 2.5792975144676013e-03, 4.8845246714536682e-03, 8.7650270802736002e-03, 1.4906240076216418e-02, 2.4028883068628805e-02, 3.6720571883816493e-02, 5.3204522444878222e-02, 7.3096572483403829e-02, 9.5234476669428525e-02, 1.1767191582495477e-01, 1.3789832745338026e-01, 1.5327533388369177e-01, 1.6159415788497841e-01, 1.6159415788497841e-01, 1.5327533388369177e-01, 1.3789832745338026e-01, 1.1767191582495477e-01, 9.5234476669428525e-02, 7.3096572483403829e-02, 5.3204522444878222e-02, 3.6720571883816493e-02, 2.4028883068628805e-02, 1.4906240076216418e-02, 8.7650270802736002e-03, 4.8845246714536682e-03, 2.5792975144676013e-03, 1.2903563124214057e-03, 6.1144669240944507e-04, 2.7438000977925001e-04, 1.1657026717177768e-04, 4.6876297088489141e-05, 1.7837324122194181e-05, 6.4208055079598766e-06, 2.1857314406758851e-06, 7.0340742267172300e-07, 2.1392739679622303e-07, 6.1462809064451552e-08, 1.6675261164947539e-08, 4.2703647703012249e-09, 1.0318035977700679e-09, 2.3510718451740779e-10, 5.0496076724281894e-11, 1.0217552929953939e-11, 1.9466883562172841e-12, 3.4902504651461380e-13, 5.8852482736096351e-14, 9.3270625462533699e-15, 1.3883744241015343e-15, 1.9397457159226965e-16, 2.5417847367765562e-17, 3.1214143458455917e-18, 3.5894545533623586e-19, 3.8618679709476893e-20, 3.8838880473136030e-21, 3.6477448742277230e-22, 3.1962255598539348e-23, 2.6100548891439468e-24, 1.9841800348065493e-25, 1.4025749559057771e-26, 9.2077125425461603e-28, 5.6065555004969651e-29, 3.1620314656015991e-30, 1.6494369134608046e-31, 7.9458957717354865e-33, 3.5292920298964982e-34, 1.4428750537835282e-35, 5.4197686272780061e-37, 1.8668536705967508e-38, 5.8848055182020130e-40, 1.6939665809360599e-41, 4.4424843586907703e-43, 1.0588298166277823e-44, 2.2875134062797375e-46, 4.4670071717223134e-48, 7.8609642161410873e-50, 1.2426111111041695e-51, 1.7582563693437111e-53, 2.2186336768274302e-55, 2.4864657741894790e-57, 2.4641241627782225e-59, 2.1490689833897993e-61, 1.6409070764036964e-63, 1.0906635714604883e-65, 6.2713089100746324e-68, 3.0981254141048187e-70, 1.3049987561313226e-72, 4.6475320184424221e-75, 1.3862443412766689e-77, 3.4266063564656041e-80, 6.9358925722736469e-83, 1.1340919960793407e-85, 1.4748024918249946e-88, 1.4980806006797597e-91, 1.1639059887066096e-94, 6.7467686874093196e-98, 2.8324541894274240e-101, 8.3068317564996415e-105, 1.6274180017356631e-108, 2.0126980605111617e-112, 1.4598025546816272e-116, 5.6227251746796540e-121, 9.9982626870689096e-126, 6.6504100620446623e-131, 1.1700024361722009e-136, 2.8068259915465668e-143, 1.6840859823147192e-151}, + {2.3899020087783538e-152, 4.1337932844079439e-144, 1.7774077118017352e-137, 1.0388721680141190e-131, 1.6028413383110423e-126, 9.2375467812799180e-122, 2.4552181378752603e-117, 3.4625987620456931e-113, 2.8619431556076958e-109, 1.4924416386535932e-105, 5.1966730435893490e-102, 1.2635422959480214e-98, 2.2243270327788831e-95, 2.9206395863825604e-92, 2.9324498160004818e-89, 2.2993488113263748e-86, 1.4336286376453945e-83, 7.2194564657826763e-81, 2.9766194663244294e-78, 1.0169377873705381e-75, 2.9095299074235018e-73, 7.0373804171328241e-71, 1.4512217440971957e-68, 2.5709836724164109e-66, 3.9400295587538806e-64, 5.2559492672815257e-62, 6.1380579859214437e-60, 6.3081846096424608e-58, 5.7325826101059963e-56, 4.6268156176755226e-54, 3.3301662675561347e-52, 2.1455339764954737e-50, 1.2416693105547687e-48, 6.4756889941564796e-47, 3.0527217350206308e-45, 1.3044685923509235e-43, 5.0660482804550958e-42, 1.7925263383158762e-40, 5.7919770166825449e-39, 1.7127600543267554e-37, 4.6447431828997982e-36, 1.1573309534274821e-34, 2.6544306695450948e-33, 5.6136594541327730e-32, 1.0964361374105204e-30, 1.9808277135032592e-29, 3.3148509472564812e-28, 5.1455269820153546e-27, 7.4183584908683151e-26, 9.9456309833303069e-25, 1.2413968193571878e-23, 1.4441897483451718e-22, 1.5675836145616411e-21, 1.5891496108132932e-20, 1.5060515461273932e-19, 1.3355156911983980e-18, 1.1090885964042391e-17, 8.6327149787564008e-17, 6.3027647004538790e-16, 4.3195605416094461e-15, 2.7808623921464611e-14, 1.6828396856093499e-13, 9.5787095713446750e-13, 5.1314070230067691e-12, 2.5887038946092999e-11, 1.2305056649947358e-10, 5.5140053605655075e-10, 2.3304976685688244e-09, 9.2946430660480328e-09, 3.4995595911608765e-08, 1.2444418429985038e-07, 4.1810988437722446e-07, 1.3277780039510742e-06, 3.9868978854768734e-06, 1.1323113503918158e-05, 3.0426750494245559e-05, 7.7380888614623922e-05, 1.8630373980043952e-04, 4.2474911952990744e-04, 9.1721684584915764e-04, 1.8764550081725386e-03, 3.6376544190370392e-03, 6.6835183409171238e-03, 1.1640333062329629e-02, 1.9220794786116900e-02, 3.0094363212091947e-02, 4.4685050904584946e-02, 6.2929070893539232e-02, 8.4060967557359437e-02, 1.0651895867711307e-01, 1.2804948653534245e-01, 1.4603926334720602e-01, 1.5802227437713226e-01, 1.6223085863339984e-01, 1.5802227437713226e-01, 1.4603926334720602e-01, 1.2804948653534245e-01, 1.0651895867711307e-01, 8.4060967557359437e-02, 6.2929070893539232e-02, 4.4685050904584946e-02, 3.0094363212091947e-02, 1.9220794786116900e-02, 1.1640333062329629e-02, 6.6835183409171238e-03, 3.6376544190370392e-03, 1.8764550081725386e-03, 9.1721684584915764e-04, 4.2474911952990744e-04, 1.8630373980043952e-04, 7.7380888614623922e-05, 3.0426750494245559e-05, 1.1323113503918158e-05, 3.9868978854768734e-06, 1.3277780039510742e-06, 4.1810988437722446e-07, 1.2444418429985038e-07, 3.4995595911608765e-08, 9.2946430660480328e-09, 2.3304976685688244e-09, 5.5140053605655075e-10, 1.2305056649947358e-10, 2.5887038946092999e-11, 5.1314070230067691e-12, 9.5787095713446750e-13, 1.6828396856093499e-13, 2.7808623921464611e-14, 4.3195605416094461e-15, 6.3027647004538790e-16, 8.6327149787564008e-17, 1.1090885964042391e-17, 1.3355156911983980e-18, 1.5060515461273932e-19, 1.5891496108132932e-20, 1.5675836145616411e-21, 1.4441897483451718e-22, 1.2413968193571878e-23, 9.9456309833303069e-25, 7.4183584908683151e-26, 5.1455269820153546e-27, 3.3148509472564812e-28, 1.9808277135032592e-29, 1.0964361374105204e-30, 5.6136594541327730e-32, 2.6544306695450948e-33, 1.1573309534274821e-34, 4.6447431828997982e-36, 1.7127600543267554e-37, 5.7919770166825449e-39, 1.7925263383158762e-40, 5.0660482804550958e-42, 1.3044685923509235e-43, 3.0527217350206308e-45, 6.4756889941564796e-47, 1.2416693105547687e-48, 2.1455339764954737e-50, 3.3301662675561347e-52, 4.6268156176755226e-54, 5.7325826101059963e-56, 6.3081846096424608e-58, 6.1380579859214437e-60, 5.2559492672815257e-62, 3.9400295587538806e-64, 2.5709836724164109e-66, 1.4512217440971957e-68, 7.0373804171328241e-71, 2.9095299074235018e-73, 1.0169377873705381e-75, 2.9766194663244294e-78, 7.2194564657826763e-81, 1.4336286376453945e-83, 2.2993488113263748e-86, 2.9324498160004818e-89, 2.9206395863825604e-92, 2.2243270327788831e-95, 1.2635422959480214e-98, 5.1966730435893490e-102, 1.4924416386535932e-105, 2.8619431556076958e-109, 3.4625987620456931e-113, 2.4552181378752603e-117, 9.2375467812799180e-122, 1.6028413383110423e-126, 1.0388721680141190e-131, 1.7774077118017352e-137, 4.1337932844079439e-144, 2.3899020087783538e-152}, + {3.3909583926202969e-153, 6.0862398111746403e-145, 2.6990049104808299e-138, 1.6219807504695568e-132, 2.5679266269176032e-127, 1.5165281109964923e-122, 4.1260001698114066e-118, 5.9515348152406019e-114, 5.0279031031404388e-110, 2.6784561524395333e-106, 9.5230206639834012e-103, 2.3633738761330501e-99, 4.2451210579798656e-96, 5.6858261506014681e-93, 5.8218672370402156e-90, 4.6543449390713426e-87, 2.9582182277022238e-84, 1.5183294739007438e-81, 6.3795487359338829e-79, 2.2208089866950920e-76, 6.4735410582641528e-74, 1.5951103254298808e-71, 3.3507196700207861e-69, 6.0464069117443835e-67, 9.4376753651859668e-65, 1.2822191213791653e-62, 1.5249989655376484e-60, 1.5960849625455376e-58, 1.4770796663837213e-56, 1.2140312147914462e-54, 8.8982101270994950e-53, 5.8379315269148491e-51, 3.4404622652833074e-49, 1.8272036259234053e-47, 8.7716947482766774e-46, 3.8170926065847122e-44, 1.5096656333028563e-42, 5.4400265472252386e-41, 1.7901934646856910e-39, 5.3916646781027312e-38, 1.4892193296848201e-36, 3.7795868784349260e-35, 8.8301666493717958e-34, 1.9022911023392480e-32, 3.7850530748490676e-31, 6.9665700818714156e-30, 1.1878115612451122e-28, 1.8786842016880562e-27, 2.7599602414845152e-26, 3.7707755724079553e-25, 4.7967389479007740e-24, 5.6876402480164174e-23, 6.2928558569586138e-22, 6.5032337700285951e-21, 6.2833568961437137e-20, 5.6810615766852734e-19, 4.8108093342629945e-18, 3.8186952800271027e-17, 2.8435455634715359e-16, 1.9878218878928244e-15, 1.3054944744238950e-14, 8.0602086244990039e-14, 4.6813428453581271e-13, 2.5592533379055519e-12, 1.3177335517890257e-11, 6.3937241128218932e-11, 2.9249655637661996e-10, 1.2622501489006109e-09, 5.1408413936157202e-09, 1.9768915482746416e-08, 7.1808683672368473e-08, 2.4648607700088249e-07, 7.9982594734022375e-07, 2.4543893859357136e-06, 7.1249965705005385e-06, 1.9573063938461480e-05, 5.0897601014117974e-05, 1.2532087255275024e-04, 2.9224860429386435e-04, 6.4564239421835911e-04, 1.3515815953737001e-03, 2.6816113762841770e-03, 5.0435720589444479e-03, 8.9938955083231700e-03, 1.5208840297800851e-02, 2.4392011104876491e-02, 3.7107373608297196e-02, 5.3553162455639902e-02, 7.3327512502661077e-02, 9.5267294910895362e-02, 1.1744849271751398e-01, 1.3740517258624155e-01, 1.5255613196758108e-01, 1.6074586617490177e-01, 1.6074586617490177e-01, 1.5255613196758108e-01, 1.3740517258624155e-01, 1.1744849271751398e-01, 9.5267294910895362e-02, 7.3327512502661077e-02, 5.3553162455639902e-02, 3.7107373608297196e-02, 2.4392011104876491e-02, 1.5208840297800851e-02, 8.9938955083231700e-03, 5.0435720589444479e-03, 2.6816113762841770e-03, 1.3515815953737001e-03, 6.4564239421835911e-04, 2.9224860429386435e-04, 1.2532087255275024e-04, 5.0897601014117974e-05, 1.9573063938461480e-05, 7.1249965705005385e-06, 2.4543893859357136e-06, 7.9982594734022375e-07, 2.4648607700088249e-07, 7.1808683672368473e-08, 1.9768915482746416e-08, 5.1408413936157202e-09, 1.2622501489006109e-09, 2.9249655637661996e-10, 6.3937241128218932e-11, 1.3177335517890257e-11, 2.5592533379055519e-12, 4.6813428453581271e-13, 8.0602086244990039e-14, 1.3054944744238950e-14, 1.9878218878928244e-15, 2.8435455634715359e-16, 3.8186952800271027e-17, 4.8108093342629945e-18, 5.6810615766852734e-19, 6.2833568961437137e-20, 6.5032337700285951e-21, 6.2928558569586138e-22, 5.6876402480164174e-23, 4.7967389479007740e-24, 3.7707755724079553e-25, 2.7599602414845152e-26, 1.8786842016880562e-27, 1.1878115612451122e-28, 6.9665700818714156e-30, 3.7850530748490676e-31, 1.9022911023392480e-32, 8.8301666493717958e-34, 3.7795868784349260e-35, 1.4892193296848201e-36, 5.3916646781027312e-38, 1.7901934646856910e-39, 5.4400265472252386e-41, 1.5096656333028563e-42, 3.8170926065847122e-44, 8.7716947482766774e-46, 1.8272036259234053e-47, 3.4404622652833074e-49, 5.8379315269148491e-51, 8.8982101270994950e-53, 1.2140312147914462e-54, 1.4770796663837213e-56, 1.5960849625455376e-58, 1.5249989655376484e-60, 1.2822191213791653e-62, 9.4376753651859668e-65, 6.0464069117443835e-67, 3.3507196700207861e-69, 1.5951103254298808e-71, 6.4735410582641528e-74, 2.2208089866950920e-76, 6.3795487359338829e-79, 1.5183294739007438e-81, 2.9582182277022238e-84, 4.6543449390713426e-87, 5.8218672370402156e-90, 5.6858261506014681e-93, 4.2451210579798656e-96, 2.3633738761330501e-99, 9.5230206639834012e-103, 2.6784561524395333e-106, 5.0279031031404388e-110, 5.9515348152406019e-114, 4.1260001698114066e-118, 1.5165281109964923e-122, 2.5679266269176032e-127, 1.6219807504695568e-132, 2.6990049104808299e-138, 6.0862398111746403e-145, 3.3909583926202969e-153}, + {4.8105196926800447e-154, 8.9581349097014215e-146, 4.0967387783316221e-139, 2.5310532151069106e-133, 4.1115283174204790e-128, 2.4878902559132056e-123, 6.9281121543161367e-119, 1.0220279314543827e-114, 8.8243129868960541e-111, 4.8017711254332563e-107, 1.7430737935309201e-103, 4.4149829449283152e-100, 8.0909195748902241e-97, 1.1053200966532163e-93, 1.1540787556182570e-90, 9.4062445961729118e-88, 6.0938287850722912e-85, 3.1875459729105427e-82, 1.3647333597873649e-79, 4.8404013281274901e-77, 1.4373955207015468e-74, 3.6078416607613653e-72, 7.7193542145188385e-70, 1.4187152411878090e-67, 2.2552327816162141e-65, 3.1202888315880434e-63, 3.7791134625824903e-61, 4.0276289664497742e-59, 3.7954127913999138e-57, 3.1764227614962876e-55, 2.3706043434701509e-53, 1.5836556658561472e-51, 9.5030686706332782e-50, 5.1390369637842554e-48, 2.5120644517965854e-46, 1.1131134062886865e-44, 4.4828688752777018e-43, 1.6449624113929946e-41, 5.5124888578291881e-40, 1.6907462404862362e-38, 4.7559672339276421e-37, 1.2293279880804420e-35, 2.9252024556839558e-34, 6.4187377483908620e-33, 1.3009300303447977e-31, 2.4391335868389452e-30, 4.2366796233867587e-29, 6.8268728000449227e-28, 1.0218585868330291e-26, 1.4225584486944289e-25, 1.8440385833763509e-24, 2.2283071036811595e-23, 2.5127294052122314e-22, 2.6467919286881548e-21, 2.6068354747780742e-20, 2.4028313064323887e-19, 2.0745586965632990e-18, 1.6791123823339180e-17, 1.2750493352152407e-16, 9.0906021055959760e-16, 6.0895673953539301e-15, 3.8353345411384518e-14, 2.2726043918949056e-13, 1.2676970629687990e-12, 6.6608945127799692e-12, 3.2985045445873824e-11, 1.5402785642655144e-10, 6.7857514014962344e-10, 2.8217661921664192e-09, 1.1080667611835489e-08, 4.1107393732952725e-08, 1.4413206230487042e-07, 4.7781084115403341e-07, 1.4981838617872995e-06, 4.4446553339045300e-06, 1.2480054945286184e-05, 3.3176731522024002e-05, 8.3524630257267974e-05, 1.9919419791658306e-04, 4.5012132211052618e-04, 9.6399635747843960e-04, 1.9570814745659979e-03, 3.7671919910449735e-03, 6.8767389146135380e-03, 1.1906303498193138e-02, 1.9555454063496128e-02, 3.0473029715843637e-02, 4.5058194694576482e-02, 6.3225096957716942e-02, 8.4198334040706369e-02, 1.0642658240453728e-01, 1.2769014695749564e-01, 1.4542767716486577e-01, 1.5722973246415300e-01, 1.6137249430200609e-01, 1.5722973246415300e-01, 1.4542767716486577e-01, 1.2769014695749564e-01, 1.0642658240453728e-01, 8.4198334040706369e-02, 6.3225096957716942e-02, 4.5058194694576482e-02, 3.0473029715843637e-02, 1.9555454063496128e-02, 1.1906303498193138e-02, 6.8767389146135380e-03, 3.7671919910449735e-03, 1.9570814745659979e-03, 9.6399635747843960e-04, 4.5012132211052618e-04, 1.9919419791658306e-04, 8.3524630257267974e-05, 3.3176731522024002e-05, 1.2480054945286184e-05, 4.4446553339045300e-06, 1.4981838617872995e-06, 4.7781084115403341e-07, 1.4413206230487042e-07, 4.1107393732952725e-08, 1.1080667611835489e-08, 2.8217661921664192e-09, 6.7857514014962344e-10, 1.5402785642655144e-10, 3.2985045445873824e-11, 6.6608945127799692e-12, 1.2676970629687990e-12, 2.2726043918949056e-13, 3.8353345411384518e-14, 6.0895673953539301e-15, 9.0906021055959760e-16, 1.2750493352152407e-16, 1.6791123823339180e-17, 2.0745586965632990e-18, 2.4028313064323887e-19, 2.6068354747780742e-20, 2.6467919286881548e-21, 2.5127294052122314e-22, 2.2283071036811595e-23, 1.8440385833763509e-24, 1.4225584486944289e-25, 1.0218585868330291e-26, 6.8268728000449227e-28, 4.2366796233867587e-29, 2.4391335868389452e-30, 1.3009300303447977e-31, 6.4187377483908620e-33, 2.9252024556839558e-34, 1.2293279880804420e-35, 4.7559672339276421e-37, 1.6907462404862362e-38, 5.5124888578291881e-40, 1.6449624113929946e-41, 4.4828688752777018e-43, 1.1131134062886865e-44, 2.5120644517965854e-46, 5.1390369637842554e-48, 9.5030686706332782e-50, 1.5836556658561472e-51, 2.3706043434701509e-53, 3.1764227614962876e-55, 3.7954127913999138e-57, 4.0276289664497742e-59, 3.7791134625824903e-61, 3.1202888315880434e-63, 2.2552327816162141e-65, 1.4187152411878090e-67, 7.7193542145188385e-70, 3.6078416607613653e-72, 1.4373955207015468e-74, 4.8404013281274901e-77, 1.3647333597873649e-79, 3.1875459729105427e-82, 6.0938287850722912e-85, 9.4062445961729118e-88, 1.1540787556182570e-90, 1.1053200966532163e-93, 8.0909195748902241e-97, 4.4149829449283152e-100, 1.7430737935309201e-103, 4.8017711254332563e-107, 8.8243129868960541e-111, 1.0220279314543827e-114, 6.9281121543161367e-119, 2.4878902559132056e-123, 4.1115283174204790e-128, 2.5310532151069106e-133, 4.0967387783316221e-139, 8.9581349097014215e-146, 4.8105196926800447e-154}, + {6.8232197942250040e-155, 1.3181218114180107e-146, 6.2157350428501506e-140, 3.9475798303387850e-134, 6.5789265659620338e-129, 4.0785124308845132e-124, 1.1623859612267819e-119, 1.7535057075593614e-115, 1.5472021309193150e-111, 8.5990905704820439e-108, 3.1867892204083499e-104, 8.2372979129162400e-101, 1.5400245034982435e-97, 2.1456921017005163e-94, 2.2843171180826872e-91, 1.8979497846368726e-88, 1.2532102545185035e-85, 6.6801061673807505e-83, 2.9141025510545569e-80, 1.0529633740939257e-77, 3.1851858054210446e-75, 8.1431135103329952e-73, 1.7744839092477200e-70, 3.3212610596524388e-68, 5.3763688423964646e-66, 7.5746019148953009e-64, 9.3412200164700803e-62, 1.0136702052099045e-59, 9.7258603579728974e-58, 8.2874406983788114e-56, 6.2972157268746326e-54, 4.2830642136217272e-52, 2.6167460089856425e-50, 1.4407389710981317e-48, 7.1704184113766286e-47, 3.2349665837355912e-45, 1.3265135880257318e-43, 4.9561856762703143e-42, 1.6911721771605448e-40, 5.2817945954838791e-39, 1.5129382111557171e-37, 3.9824232345150253e-36, 9.6505627399970417e-35, 2.1566756583641779e-33, 4.4519543419059356e-32, 8.5019504368590908e-31, 1.5042535921639604e-29, 2.4692068347694563e-28, 3.7652687650201339e-27, 5.3404226168220292e-26, 7.0535560842160286e-25, 8.6851943617712193e-24, 9.9804891048351136e-23, 1.0714309730247980e-21, 1.0755595219737973e-20, 1.0105554063847399e-19, 8.8944609945993243e-19, 7.3396140181061249e-18, 5.6828205180213369e-17, 4.1316021764480691e-16, 2.8225916935311505e-15, 1.8132136826440378e-14, 1.0959822792780298e-13, 6.2370678258135157e-13, 3.3437645093788376e-12, 1.6897122210470246e-11, 8.0527347789629487e-11, 3.6211627179619072e-10, 1.5372205783801174e-09, 6.1632086713433375e-09, 2.3347964326766498e-08, 8.3606844554454458e-08, 2.8310992931625352e-07, 9.0687938435499206e-07, 2.7490144224436228e-06, 7.8882549269903193e-06, 2.1433661822155404e-05, 5.5163316323048505e-05, 1.3451233819198536e-04, 3.1084451589835123e-04, 6.8092260658474482e-04, 1.4142383035108275e-03, 2.7855275571971620e-03, 5.2039736325766575e-03, 9.2231946903286923e-03, 1.5510131997231313e-02, 2.4751412543080331e-02, 3.7487880444774385e-02, 5.3893671909463224e-02, 7.3550203638163128e-02, 9.5294126497036155e-02, 1.1722364672954393e-01, 1.3691645960749019e-01, 1.5184684526785858e-01, 1.5991079381814263e-01, 1.5991079381814263e-01, 1.5184684526785858e-01, 1.3691645960749019e-01, 1.1722364672954393e-01, 9.5294126497036155e-02, 7.3550203638163128e-02, 5.3893671909463224e-02, 3.7487880444774385e-02, 2.4751412543080331e-02, 1.5510131997231313e-02, 9.2231946903286923e-03, 5.2039736325766575e-03, 2.7855275571971620e-03, 1.4142383035108275e-03, 6.8092260658474482e-04, 3.1084451589835123e-04, 1.3451233819198536e-04, 5.5163316323048505e-05, 2.1433661822155404e-05, 7.8882549269903193e-06, 2.7490144224436228e-06, 9.0687938435499206e-07, 2.8310992931625352e-07, 8.3606844554454458e-08, 2.3347964326766498e-08, 6.1632086713433375e-09, 1.5372205783801174e-09, 3.6211627179619072e-10, 8.0527347789629487e-11, 1.6897122210470246e-11, 3.3437645093788376e-12, 6.2370678258135157e-13, 1.0959822792780298e-13, 1.8132136826440378e-14, 2.8225916935311505e-15, 4.1316021764480691e-16, 5.6828205180213369e-17, 7.3396140181061249e-18, 8.8944609945993243e-19, 1.0105554063847399e-19, 1.0755595219737973e-20, 1.0714309730247980e-21, 9.9804891048351136e-23, 8.6851943617712193e-24, 7.0535560842160286e-25, 5.3404226168220292e-26, 3.7652687650201339e-27, 2.4692068347694563e-28, 1.5042535921639604e-29, 8.5019504368590908e-31, 4.4519543419059356e-32, 2.1566756583641779e-33, 9.6505627399970417e-35, 3.9824232345150253e-36, 1.5129382111557171e-37, 5.2817945954838791e-39, 1.6911721771605448e-40, 4.9561856762703143e-42, 1.3265135880257318e-43, 3.2349665837355912e-45, 7.1704184113766286e-47, 1.4407389710981317e-48, 2.6167460089856425e-50, 4.2830642136217272e-52, 6.2972157268746326e-54, 8.2874406983788114e-56, 9.7258603579728974e-58, 1.0136702052099045e-59, 9.3412200164700803e-62, 7.5746019148953009e-64, 5.3763688423964646e-66, 3.3212610596524388e-68, 1.7744839092477200e-70, 8.1431135103329952e-73, 3.1851858054210446e-75, 1.0529633740939257e-77, 2.9141025510545569e-80, 6.6801061673807505e-83, 1.2532102545185035e-85, 1.8979497846368726e-88, 2.2843171180826872e-91, 2.1456921017005163e-94, 1.5400245034982435e-97, 8.2372979129162400e-101, 3.1867892204083499e-104, 8.5990905704820439e-108, 1.5472021309193150e-111, 1.7535057075593614e-115, 1.1623859612267819e-119, 4.0785124308845132e-124, 6.5789265659620338e-129, 3.9475798303387850e-134, 6.2157350428501506e-140, 1.3181218114180107e-146, 6.8232197942250040e-155}, + {9.6764302762857911e-156, 1.9389386338649253e-147, 9.4268794388387584e-141, 6.1537049528839255e-135, 1.0520595245806230e-129, 6.6813621694344271e-125, 1.9486722540934962e-120, 3.0058398378782854e-116, 2.7101250640991562e-112, 1.5383037549430030e-108, 5.8195869131646608e-105, 1.5349872474118010e-101, 2.9274184968148517e-98, 4.1594648723850271e-95, 4.5147260427833628e-92, 3.8235833994762416e-89, 2.5729913678738507e-86, 1.3975076314494611e-83, 6.2111050589991735e-81, 2.2862048443444402e-78, 7.0441083482496365e-76, 1.8341247494924424e-73, 4.0702482203595230e-71, 7.7576584194845979e-69, 1.2786993882275677e-66, 1.8342905501305085e-64, 2.3031479777875351e-62, 2.5445408528816102e-60, 2.4855538228455434e-58, 2.1561995344944781e-56, 1.6679549705866419e-54, 1.1549259780000125e-52, 7.1833013403181687e-51, 4.0263574453603144e-49, 2.0400456628439797e-47, 9.3700002807816908e-46, 3.9116867251382951e-44, 1.4879647423347193e-42, 5.1693708373553046e-41, 1.6438042759677152e-39, 4.7942896465195374e-38, 1.2849980190682212e-36, 3.1708729314553754e-35, 7.2161081218241727e-34, 1.5169921976469880e-32, 2.9504597948207525e-31, 5.3168727228967571e-30, 8.8896336943576362e-29, 1.3808362593425483e-27, 1.9951324606202683e-26, 2.6846378493690218e-25, 3.3679964757574780e-24, 3.9436002250852672e-23, 4.3140992488603084e-22, 4.4134945997917874e-21, 4.2263869813792336e-20, 3.7916648002202093e-19, 3.1895272336827489e-18, 2.5176935915196902e-17, 1.8663270859468551e-16, 1.3001503435609439e-15, 8.5176175587843442e-15, 5.2510379021912937e-14, 3.0482099219006810e-13, 1.6671499873186635e-12, 8.5956677592000092e-12, 4.1801607084826671e-11, 1.9183890700529380e-10, 8.3123118452689150e-10, 3.4021150696080136e-09, 1.3158571431631216e-08, 4.8115154735048105e-08, 1.6639485157072335e-07, 5.4443385920665998e-07, 1.6859754012772494e-06, 4.9431447402619969e-06, 1.3725819438547434e-05, 3.6106464014912190e-05, 9.0004542316217840e-05, 2.1266213156628891e-04, 4.7639613833099480e-04, 1.0120395216254993e-03, 2.0392461173393923e-03, 3.8982490246164416e-03, 7.0709100790306376e-03, 1.2171895486539193e-02, 1.9887632287530231e-02, 3.0846667595353164e-02, 4.5424033501544080e-02, 6.3512773332392206e-02, 8.4328396273560896e-02, 1.0633035510412364e-01, 1.2733227690715612e-01, 1.4482336870308740e-01, 1.5644897465655389e-01, 1.6052761213288572e-01, 1.5644897465655389e-01, 1.4482336870308740e-01, 1.2733227690715612e-01, 1.0633035510412364e-01, 8.4328396273560896e-02, 6.3512773332392206e-02, 4.5424033501544080e-02, 3.0846667595353164e-02, 1.9887632287530231e-02, 1.2171895486539193e-02, 7.0709100790306376e-03, 3.8982490246164416e-03, 2.0392461173393923e-03, 1.0120395216254993e-03, 4.7639613833099480e-04, 2.1266213156628891e-04, 9.0004542316217840e-05, 3.6106464014912190e-05, 1.3725819438547434e-05, 4.9431447402619969e-06, 1.6859754012772494e-06, 5.4443385920665998e-07, 1.6639485157072335e-07, 4.8115154735048105e-08, 1.3158571431631216e-08, 3.4021150696080136e-09, 8.3123118452689150e-10, 1.9183890700529380e-10, 4.1801607084826671e-11, 8.5956677592000092e-12, 1.6671499873186635e-12, 3.0482099219006810e-13, 5.2510379021912937e-14, 8.5176175587843442e-15, 1.3001503435609439e-15, 1.8663270859468551e-16, 2.5176935915196902e-17, 3.1895272336827489e-18, 3.7916648002202093e-19, 4.2263869813792336e-20, 4.4134945997917874e-21, 4.3140992488603084e-22, 3.9436002250852672e-23, 3.3679964757574780e-24, 2.6846378493690218e-25, 1.9951324606202683e-26, 1.3808362593425483e-27, 8.8896336943576362e-29, 5.3168727228967571e-30, 2.9504597948207525e-31, 1.5169921976469880e-32, 7.2161081218241727e-34, 3.1708729314553754e-35, 1.2849980190682212e-36, 4.7942896465195374e-38, 1.6438042759677152e-39, 5.1693708373553046e-41, 1.4879647423347193e-42, 3.9116867251382951e-44, 9.3700002807816908e-46, 2.0400456628439797e-47, 4.0263574453603144e-49, 7.1833013403181687e-51, 1.1549259780000125e-52, 1.6679549705866419e-54, 2.1561995344944781e-56, 2.4855538228455434e-58, 2.5445408528816102e-60, 2.3031479777875351e-62, 1.8342905501305085e-64, 1.2786993882275677e-66, 7.7576584194845979e-69, 4.0702482203595230e-71, 1.8341247494924424e-73, 7.0441083482496365e-76, 2.2862048443444402e-78, 6.2111050589991735e-81, 1.3975076314494611e-83, 2.5729913678738507e-86, 3.8235833994762416e-89, 4.5147260427833628e-92, 4.1594648723850271e-95, 2.9274184968148517e-98, 1.5349872474118010e-101, 5.8195869131646608e-105, 1.5383037549430030e-108, 2.7101250640991562e-112, 3.0058398378782854e-116, 1.9486722540934962e-120, 6.6813621694344271e-125, 1.0520595245806230e-129, 6.1537049528839255e-135, 9.4268794388387584e-141, 1.9389386338649253e-147, 9.6764302762857911e-156}, + {1.3720504154302014e-156, 2.8513090679363871e-148, 1.4291119261031478e-141, 9.5878345367776407e-136, 1.6813631090843168e-130, 1.0937641473652881e-125, 3.2642500496954800e-121, 5.1480442370317754e-117, 4.7425471562207601e-113, 2.7489983469746781e-109, 1.0615412978825736e-105, 2.8568935742124688e-102, 5.5574407262791218e-99, 8.0520048626328837e-96, 8.9097729474744936e-93, 7.6909567014190078e-90, 5.2740027603411657e-87, 2.9186112720938588e-84, 1.3214406564729561e-81, 4.9544462772840985e-79, 1.5547429149839197e-76, 4.1226034386806711e-74, 9.3161574688297957e-72, 1.8079563460381452e-69, 3.0341692292606370e-67, 4.4312923121519367e-65, 5.6644240327335667e-63, 6.3708774357395162e-61, 6.3351435391240280e-59, 5.5944362188420675e-57, 4.4053385520999193e-55, 3.1050807666511750e-53, 1.9659178072617245e-51, 1.1217013968671671e-49, 5.7853802707668581e-48, 2.7049816006551789e-46, 1.1495533915103732e-44, 4.4515141949278675e-43, 1.5743976688633690e-41, 5.0968507385634822e-40, 1.5134439954515047e-38, 4.1300163134837491e-37, 1.0376574212671890e-35, 2.4044973436406753e-34, 5.1472183288770750e-33, 1.0194603568070278e-31, 1.8709115794220601e-30, 3.1858380070837839e-29, 5.0402581729336372e-28, 7.4179265516977060e-27, 1.0167813330369454e-25, 1.2995016885518635e-24, 1.5502266336408172e-23, 1.7279241662380531e-22, 1.8012995272732974e-21, 1.7578400079602021e-20, 1.6072599968378759e-19, 1.3780640314290736e-18, 1.1088556613183840e-17, 8.3797787500377154e-17, 5.9519054533347666e-16, 3.9759844018964598e-15, 2.4996755476537754e-14, 1.4799417664726766e-13, 8.2563190162426826e-13, 4.3426586703108686e-12, 2.1547012918303077e-11, 1.0090299262094598e-10, 4.4618936758916388e-10, 1.8639520759198730e-09, 7.3594054861502447e-09, 2.7474235203608662e-08, 9.7018924643039030e-08, 3.2418977135736030e-07, 1.0254381425692049e-06, 3.0713815320154091e-06, 8.7138650801478641e-06, 2.3424552293210665e-05, 5.9681270208738333e-05, 1.4415391428196787e-04, 3.3017517124886084e-04, 7.1728665634025713e-04, 1.4783089544886255e-03, 2.8910036930282720e-03, 5.3656605093971325e-03, 9.4528407852602792e-03, 1.5810044685497838e-02, 2.5107070566959051e-02, 3.7862166097742164e-02, 5.4226226141723462e-02, 7.3764890309958767e-02, 9.5315208688082131e-02, 1.1699751277485990e-01, 1.3643214928471140e-01, 1.5114725119507466e-01, 1.5908860103657232e-01, 1.5908860103657232e-01, 1.5114725119507466e-01, 1.3643214928471140e-01, 1.1699751277485990e-01, 9.5315208688082131e-02, 7.3764890309958767e-02, 5.4226226141723462e-02, 3.7862166097742164e-02, 2.5107070566959051e-02, 1.5810044685497838e-02, 9.4528407852602792e-03, 5.3656605093971325e-03, 2.8910036930282720e-03, 1.4783089544886255e-03, 7.1728665634025713e-04, 3.3017517124886084e-04, 1.4415391428196787e-04, 5.9681270208738333e-05, 2.3424552293210665e-05, 8.7138650801478641e-06, 3.0713815320154091e-06, 1.0254381425692049e-06, 3.2418977135736030e-07, 9.7018924643039030e-08, 2.7474235203608662e-08, 7.3594054861502447e-09, 1.8639520759198730e-09, 4.4618936758916388e-10, 1.0090299262094598e-10, 2.1547012918303077e-11, 4.3426586703108686e-12, 8.2563190162426826e-13, 1.4799417664726766e-13, 2.4996755476537754e-14, 3.9759844018964598e-15, 5.9519054533347666e-16, 8.3797787500377154e-17, 1.1088556613183840e-17, 1.3780640314290736e-18, 1.6072599968378759e-19, 1.7578400079602021e-20, 1.8012995272732974e-21, 1.7279241662380531e-22, 1.5502266336408172e-23, 1.2995016885518635e-24, 1.0167813330369454e-25, 7.4179265516977060e-27, 5.0402581729336372e-28, 3.1858380070837839e-29, 1.8709115794220601e-30, 1.0194603568070278e-31, 5.1472183288770750e-33, 2.4044973436406753e-34, 1.0376574212671890e-35, 4.1300163134837491e-37, 1.5134439954515047e-38, 5.0968507385634822e-40, 1.5743976688633690e-41, 4.4515141949278675e-43, 1.1495533915103732e-44, 2.7049816006551789e-46, 5.7853802707668581e-48, 1.1217013968671671e-49, 1.9659178072617245e-51, 3.1050807666511750e-53, 4.4053385520999193e-55, 5.5944362188420675e-57, 6.3351435391240280e-59, 6.3708774357395162e-61, 5.6644240327335667e-63, 4.4312923121519367e-65, 3.0341692292606370e-67, 1.8079563460381452e-69, 9.3161574688297957e-72, 4.1226034386806711e-74, 1.5547429149839197e-76, 4.9544462772840985e-79, 1.3214406564729561e-81, 2.9186112720938588e-84, 5.2740027603411657e-87, 7.6909567014190078e-90, 8.9097729474744936e-93, 8.0520048626328837e-96, 5.5574407262791218e-99, 2.8568935742124688e-102, 1.0615412978825736e-105, 2.7489983469746781e-109, 4.7425471562207601e-113, 5.1480442370317754e-117, 3.2642500496954800e-121, 1.0937641473652881e-125, 1.6813631090843168e-130, 9.5878345367776407e-136, 1.4291119261031478e-141, 2.8513090679363871e-148, 1.3720504154302014e-156}, + {1.9451569748580915e-157, 4.1917692496623074e-149, 2.1656533203264049e-142, 1.4930848367233329e-136, 2.6854744034643652e-131, 1.7892892532014627e-126, 5.4637061901241444e-122, 8.8092712504606827e-118, 8.2912095929290215e-114, 4.9074274510768621e-110, 1.9341588617846345e-106, 5.3107713773093621e-103, 1.0536661811562218e-99, 1.5565848726847315e-96, 1.7557722156935769e-93, 1.5446161289516271e-90, 1.0792867414624379e-87, 6.0849467639302215e-85, 2.8063950432169120e-82, 1.0716703469936493e-79, 3.4248444263060510e-77, 9.2475643800642814e-75, 2.1277914455786410e-72, 4.2042110347158325e-70, 7.1831202945319969e-68, 1.0679652291289812e-65, 1.3896846788334397e-63, 1.5910268843395548e-61, 1.6104220743828299e-59, 1.4475542666378789e-57, 1.1602357060613541e-55, 8.3238465917891379e-54, 5.3641275790400676e-52, 3.1152601083577022e-50, 1.6354424962643853e-48, 7.7832174172965086e-47, 3.3668417110773493e-45, 1.3271170300689291e-43, 4.7778763656316077e-42, 1.5745422805731105e-40, 4.7595446906951574e-39, 1.3222509215279862e-37, 3.3821840940140512e-36, 7.9793659216047449e-35, 1.7391569791608673e-33, 3.5073691468931601e-32, 6.5544111912453122e-31, 1.1365779583643404e-29, 1.8312631014871582e-28, 2.7449324565145490e-27, 3.8322872065908508e-26, 4.9890778549827656e-25, 6.0629582449560457e-24, 6.8848488569478251e-23, 7.3125997647970303e-22, 7.2714081831677253e-21, 6.7751229891684194e-20, 5.9201437592343701e-19, 4.8552433914811921e-18, 3.7401100817855975e-17, 2.7081193971598301e-16, 1.8444288831090382e-15, 1.1823696121971421e-14, 7.1386313730701460e-14, 4.0616946929687980e-13, 2.1791052221508088e-12, 1.1029706356088577e-11, 5.2697432068365651e-11, 2.3777643019834690e-10, 1.0136912013567245e-09, 4.0850156582808148e-09, 1.5567430501187781e-08, 5.6124175036636782e-08, 1.9149546201420412e-07, 6.1858506291091545e-07, 1.8924364481789124e-06, 5.4848459956508166e-06, 1.5064725177098550e-05, 3.9222592074287836e-05, 9.6829305369002766e-05, 2.2671622856088540e-04, 5.0357752441741071e-04, 1.0613379467370166e-03, 2.1229194690909154e-03, 4.0307696130016573e-03, 7.2659539954360898e-03, 1.2437029172215985e-02, 2.0217282655364367e-02, 3.1215303196211058e-02, 4.5782692483561545e-02, 6.3792314106331613e-02, 8.4451401972617260e-02, 1.0623046970193420e-01, 1.2697592765070259e-01, 1.4422620485622731e-01, 1.5567971237666092e-01, 1.5969586284722317e-01, 1.5567971237666092e-01, 1.4422620485622731e-01, 1.2697592765070259e-01, 1.0623046970193420e-01, 8.4451401972617260e-02, 6.3792314106331613e-02, 4.5782692483561545e-02, 3.1215303196211058e-02, 2.0217282655364367e-02, 1.2437029172215985e-02, 7.2659539954360898e-03, 4.0307696130016573e-03, 2.1229194690909154e-03, 1.0613379467370166e-03, 5.0357752441741071e-04, 2.2671622856088540e-04, 9.6829305369002766e-05, 3.9222592074287836e-05, 1.5064725177098550e-05, 5.4848459956508166e-06, 1.8924364481789124e-06, 6.1858506291091545e-07, 1.9149546201420412e-07, 5.6124175036636782e-08, 1.5567430501187781e-08, 4.0850156582808148e-09, 1.0136912013567245e-09, 2.3777643019834690e-10, 5.2697432068365651e-11, 1.1029706356088577e-11, 2.1791052221508088e-12, 4.0616946929687980e-13, 7.1386313730701460e-14, 1.1823696121971421e-14, 1.8444288831090382e-15, 2.7081193971598301e-16, 3.7401100817855975e-17, 4.8552433914811921e-18, 5.9201437592343701e-19, 6.7751229891684194e-20, 7.2714081831677253e-21, 7.3125997647970303e-22, 6.8848488569478251e-23, 6.0629582449560457e-24, 4.9890778549827656e-25, 3.8322872065908508e-26, 2.7449324565145490e-27, 1.8312631014871582e-28, 1.1365779583643404e-29, 6.5544111912453122e-31, 3.5073691468931601e-32, 1.7391569791608673e-33, 7.9793659216047449e-35, 3.3821840940140512e-36, 1.3222509215279862e-37, 4.7595446906951574e-39, 1.5745422805731105e-40, 4.7778763656316077e-42, 1.3271170300689291e-43, 3.3668417110773493e-45, 7.7832174172965086e-47, 1.6354424962643853e-48, 3.1152601083577022e-50, 5.3641275790400676e-52, 8.3238465917891379e-54, 1.1602357060613541e-55, 1.4475542666378789e-57, 1.6104220743828299e-59, 1.5910268843395548e-61, 1.3896846788334397e-63, 1.0679652291289812e-65, 7.1831202945319969e-68, 4.2042110347158325e-70, 2.1277914455786410e-72, 9.2475643800642814e-75, 3.4248444263060510e-77, 1.0716703469936493e-79, 2.8063950432169120e-82, 6.0849467639302215e-85, 1.0792867414624379e-87, 1.5446161289516271e-90, 1.7557722156935769e-93, 1.5565848726847315e-96, 1.0536661811562218e-99, 5.3107713773093621e-103, 1.9341588617846345e-106, 4.9074274510768621e-110, 8.2912095929290215e-114, 8.8092712504606827e-118, 5.4637061901241444e-122, 1.7892892532014627e-126, 2.6854744034643652e-131, 1.4930848367233329e-136, 2.1656533203264049e-142, 4.1917692496623074e-149, 1.9451569748580915e-157}, + {2.7572081394930497e-158, 6.1606195891114038e-150, 3.2804813831912987e-143, 2.3239698294632731e-137, 4.2866809471010448e-132, 2.9250839726119467e-127, 9.1380522604480418e-123, 1.5061298645822260e-118, 1.4481443283610901e-114, 8.7515402609102180e-111, 3.5201601974984495e-107, 9.8605307314410817e-104, 1.9951459370163873e-100, 3.0050341197440912e-97, 3.4549517863933081e-94, 3.0974015995404665e-91, 2.2051316618251230e-88, 1.2664932443877347e-85, 5.9494906351077990e-83, 2.3137758798623088e-80, 7.5297591329388192e-78, 2.0701649292513591e-75, 4.8496085133984147e-73, 9.7550576247941725e-71, 1.6966738887834285e-68, 2.5677846130096429e-66, 3.4010587398231950e-64, 3.9632860731065032e-62, 4.0830488118084828e-60, 3.7353956966630745e-58, 3.0471769779359536e-56, 2.2249520894879323e-54, 1.4592805785267631e-52, 8.6253646389571326e-51, 4.6085517173721152e-49, 2.2322309293391554e-47, 9.8278883256522070e-46, 3.9428752392560041e-44, 1.4448263309190163e-42, 4.8464578191552559e-41, 1.4912109536234187e-39, 4.2170331394849629e-38, 1.0980633083650227e-36, 2.6372704388350129e-35, 5.8519678162563370e-34, 1.2015551933775674e-32, 2.2862239823374585e-31, 4.0367549228098398e-30, 6.6230590346823284e-29, 1.0109795409268771e-27, 1.4374775988383664e-26, 1.9060160602736751e-25, 2.3593174689076554e-24, 2.7291375088225280e-23, 2.9530245244292184e-22, 2.9916750627894004e-21, 2.8402168199630962e-20, 2.5289725099536307e-19, 2.1136880764547752e-18, 1.6594882054957410e-17, 1.2247874128456919e-16, 8.5035945941928308e-16, 5.5576041209463139e-15, 3.4212940713768145e-14, 1.9850553217879612e-13, 1.0861345804029464e-12, 5.6073947890454799e-12, 2.7329486591769151e-11, 1.2580856861713816e-10, 5.4727113377318889e-10, 2.2506273484860213e-09, 8.7538457447490308e-09, 3.2215483374955876e-08, 1.1221944492414074e-07, 3.7014154510322367e-07, 1.1564156154340975e-06, 3.4233275145786425e-06, 9.6051781722267405e-06, 2.5551197899130104e-05, 6.4459196331247565e-05, 1.5425452576992943e-04, 3.5024735925131938e-04, 7.5473297532327498e-04, 1.5437752230132358e-03, 2.9979972233121189e-03, 5.5285649600795095e-03, 9.6827528386239439e-03, 1.6108512025371353e-02, 2.5458972192611309e-02, 3.8230305479849361e-02, 5.4550997194724032e-02, 7.3971809106191291e-02, 9.5330768912038982e-02, 1.1677021831583778e-01, 1.3595220139257186e-01, 1.5045713397116045e-01, 1.5827896015320714e-01, 1.5827896015320714e-01, 1.5045713397116045e-01, 1.3595220139257186e-01, 1.1677021831583778e-01, 9.5330768912038982e-02, 7.3971809106191291e-02, 5.4550997194724032e-02, 3.8230305479849361e-02, 2.5458972192611309e-02, 1.6108512025371353e-02, 9.6827528386239439e-03, 5.5285649600795095e-03, 2.9979972233121189e-03, 1.5437752230132358e-03, 7.5473297532327498e-04, 3.5024735925131938e-04, 1.5425452576992943e-04, 6.4459196331247565e-05, 2.5551197899130104e-05, 9.6051781722267405e-06, 3.4233275145786425e-06, 1.1564156154340975e-06, 3.7014154510322367e-07, 1.1221944492414074e-07, 3.2215483374955876e-08, 8.7538457447490308e-09, 2.2506273484860213e-09, 5.4727113377318889e-10, 1.2580856861713816e-10, 2.7329486591769151e-11, 5.6073947890454799e-12, 1.0861345804029464e-12, 1.9850553217879612e-13, 3.4212940713768145e-14, 5.5576041209463139e-15, 8.5035945941928308e-16, 1.2247874128456919e-16, 1.6594882054957410e-17, 2.1136880764547752e-18, 2.5289725099536307e-19, 2.8402168199630962e-20, 2.9916750627894004e-21, 2.9530245244292184e-22, 2.7291375088225280e-23, 2.3593174689076554e-24, 1.9060160602736751e-25, 1.4374775988383664e-26, 1.0109795409268771e-27, 6.6230590346823284e-29, 4.0367549228098398e-30, 2.2862239823374585e-31, 1.2015551933775674e-32, 5.8519678162563370e-34, 2.6372704388350129e-35, 1.0980633083650227e-36, 4.2170331394849629e-38, 1.4912109536234187e-39, 4.8464578191552559e-41, 1.4448263309190163e-42, 3.9428752392560041e-44, 9.8278883256522070e-46, 2.2322309293391554e-47, 4.6085517173721152e-49, 8.6253646389571326e-51, 1.4592805785267631e-52, 2.2249520894879323e-54, 3.0471769779359536e-56, 3.7353956966630745e-58, 4.0830488118084828e-60, 3.9632860731065032e-62, 3.4010587398231950e-64, 2.5677846130096429e-66, 1.6966738887834285e-68, 9.7550576247941725e-71, 4.8496085133984147e-73, 2.0701649292513591e-75, 7.5297591329388192e-78, 2.3137758798623088e-80, 5.9494906351077990e-83, 1.2664932443877347e-85, 2.2051316618251230e-88, 3.0974015995404665e-91, 3.4549517863933081e-94, 3.0050341197440912e-97, 1.9951459370163873e-100, 9.8605307314410817e-104, 3.5201601974984495e-107, 8.7515402609102180e-111, 1.4481443283610901e-114, 1.5061298645822260e-118, 9.1380522604480418e-123, 2.9250839726119467e-127, 4.2866809471010448e-132, 2.3239698294632731e-137, 3.2804813831912987e-143, 6.1606195891114038e-150, 2.7572081394930497e-158}, + {3.9076471690941080e-159, 9.0516231985655450e-151, 4.9672234319145855e-144, 3.6154341661312203e-138, 6.8385535268994495e-133, 4.7785893786651104e-128, 1.5271628772769884e-123, 2.5728411822428113e-119, 2.5269536248805626e-115, 1.5590872025715406e-111, 6.3995909265162004e-108, 1.8286346030132772e-104, 3.7730702714400253e-101, 5.7934780549600130e-98, 6.7888152108219864e-95, 6.2017960981784824e-92, 4.4982131286438984e-89, 2.6316100628013750e-86, 1.2590645102017268e-83, 4.9863539974326119e-81, 1.6522944213413452e-78, 4.6250118175679923e-76, 1.1030078970560833e-73, 2.2585685158900422e-71, 3.9985750751823772e-69, 6.1594934342804038e-67, 8.3034758916801791e-65, 9.8479077342924136e-63, 1.0325295240318946e-60, 9.6133222464273388e-59, 7.9807919503856858e-57, 5.9302840185272367e-55, 3.9582000609173701e-53, 2.3808961922219179e-51, 1.2945943475503535e-49, 6.3814434194007278e-48, 2.8592815645992017e-46, 1.1674410264648282e-44, 4.3538446893851820e-43, 1.4863772701012763e-41, 4.6548397931087811e-40, 1.3398281145584983e-38, 3.5510998957536425e-37, 8.6816489289737604e-36, 1.9610184560405483e-34, 4.0989946034555524e-33, 7.9401630700838486e-32, 1.4273966207691636e-30, 2.3845069143279796e-29, 3.7062734865446578e-28, 5.3663645149930618e-27, 7.2463592171380759e-26, 9.1353566359276092e-25, 1.0763247315298265e-23, 1.1863095918086436e-22, 1.2243177639523886e-21, 1.1841779286732196e-20, 1.0743199749303155e-19, 9.1494332489911347e-19, 7.3203566611052359e-18, 5.5063768554293231e-17, 3.8967149070515473e-16, 2.5960894208342548e-15, 1.6293142388397836e-14, 9.6386743368990212e-14, 5.3778391218729220e-13, 2.8314924455552075e-12, 1.4075632287720228e-11, 6.6097087557103094e-11, 2.9333592912411779e-10, 1.2308733220895705e-09, 4.8855519350876319e-09, 1.8350327790289198e-08, 6.5248828381395632e-08, 2.1971536691628579e-07, 7.0090428369282574e-07, 2.1189035330905069e-06, 6.0723051489799535e-06, 1.6501142336395539e-05, 4.2531734642799478e-05, 1.0400739885143485e-04, 2.4136469790269507e-04, 5.3166865805501619e-04, 1.1118823380073424e-03, 2.2080714903093502e-03, 4.1646982803793314e-03, 7.4617948415810062e-03, 1.2701628295481309e-02, 2.0544362511894173e-02, 3.1578965559564402e-02, 4.6134295845117745e-02, 6.4063927714297891e-02, 8.4567589743710897e-02, 1.0612711013185427e-01, 1.2662114600203433e-01, 1.4363605547026137e-01, 1.5492166682336009e-01, 1.5887690970441684e-01, 1.5492166682336009e-01, 1.4363605547026137e-01, 1.2662114600203433e-01, 1.0612711013185427e-01, 8.4567589743710897e-02, 6.4063927714297891e-02, 4.6134295845117745e-02, 3.1578965559564402e-02, 2.0544362511894173e-02, 1.2701628295481309e-02, 7.4617948415810062e-03, 4.1646982803793314e-03, 2.2080714903093502e-03, 1.1118823380073424e-03, 5.3166865805501619e-04, 2.4136469790269507e-04, 1.0400739885143485e-04, 4.2531734642799478e-05, 1.6501142336395539e-05, 6.0723051489799535e-06, 2.1189035330905069e-06, 7.0090428369282574e-07, 2.1971536691628579e-07, 6.5248828381395632e-08, 1.8350327790289198e-08, 4.8855519350876319e-09, 1.2308733220895705e-09, 2.9333592912411779e-10, 6.6097087557103094e-11, 1.4075632287720228e-11, 2.8314924455552075e-12, 5.3778391218729220e-13, 9.6386743368990212e-14, 1.6293142388397836e-14, 2.5960894208342548e-15, 3.8967149070515473e-16, 5.5063768554293231e-17, 7.3203566611052359e-18, 9.1494332489911347e-19, 1.0743199749303155e-19, 1.1841779286732196e-20, 1.2243177639523886e-21, 1.1863095918086436e-22, 1.0763247315298265e-23, 9.1353566359276092e-25, 7.2463592171380759e-26, 5.3663645149930618e-27, 3.7062734865446578e-28, 2.3845069143279796e-29, 1.4273966207691636e-30, 7.9401630700838486e-32, 4.0989946034555524e-33, 1.9610184560405483e-34, 8.6816489289737604e-36, 3.5510998957536425e-37, 1.3398281145584983e-38, 4.6548397931087811e-40, 1.4863772701012763e-41, 4.3538446893851820e-43, 1.1674410264648282e-44, 2.8592815645992017e-46, 6.3814434194007278e-48, 1.2945943475503535e-49, 2.3808961922219179e-51, 3.9582000609173701e-53, 5.9302840185272367e-55, 7.9807919503856858e-57, 9.6133222464273388e-59, 1.0325295240318946e-60, 9.8479077342924136e-63, 8.3034758916801791e-65, 6.1594934342804038e-67, 3.9985750751823772e-69, 2.2585685158900422e-71, 1.1030078970560833e-73, 4.6250118175679923e-76, 1.6522944213413452e-78, 4.9863539974326119e-81, 1.2590645102017268e-83, 2.6316100628013750e-86, 4.4982131286438984e-89, 6.2017960981784824e-92, 6.7888152108219864e-95, 5.7934780549600130e-98, 3.7730702714400253e-101, 1.8286346030132772e-104, 6.3995909265162004e-108, 1.5590872025715406e-111, 2.5269536248805626e-115, 2.5728411822428113e-119, 1.5271628772769884e-123, 4.7785893786651104e-128, 6.8385535268994495e-133, 3.6154341661312203e-138, 4.9672234319145855e-144, 9.0516231985655450e-151, 3.9076471690941080e-159}, + {5.5372309477634655e-160, 1.3295499920372636e-151, 7.5182851789608105e-145, 5.6218117631932678e-139, 1.0903164404085858e-133, 7.8013060714659609e-129, 2.5502660858886434e-124, 4.3913191972243959e-120, 4.4053240904063359e-116, 2.7746976743925027e-112, 1.1621599260631149e-108, 3.3872112245822123e-105, 7.1263773535131733e-102, 1.1154449265558409e-98, 1.3320789562852151e-95, 1.2398999039839109e-92, 9.1613585633591115e-90, 5.4590825264344227e-87, 2.6598715295190543e-84, 1.0726407876436278e-81, 3.6188278671651930e-79, 1.0312393292677344e-76, 2.5035350436180196e-74, 5.2179989944251382e-72, 9.4025005576362417e-70, 1.4740979038429450e-67, 2.0223861173713801e-65, 2.4409225876304963e-63, 2.6043821060405426e-61, 2.4675003119821257e-59, 2.0845067543701599e-57, 1.5761631000101791e-55, 1.0705056723174281e-53, 6.5523461103489109e-52, 3.6254089691585309e-50, 1.8184989576075493e-48, 8.2913990414809887e-47, 3.4450097830357403e-45, 1.3074430076121838e-43, 4.5423930481987850e-42, 1.4477028628289723e-40, 4.2408968311262046e-39, 1.1439892419798912e-37, 2.8466218480726145e-36, 6.5448147609160573e-35, 1.3925226088255375e-33, 2.7459089931491756e-32, 5.0252446557042918e-31, 8.5465806757782117e-30, 1.3525065257212417e-28, 1.9939689031724527e-27, 2.7417253568038711e-26, 3.5198681528057952e-25, 4.2235075145104786e-24, 4.7412259196608422e-23, 4.9840723225381343e-22, 4.9106724438195655e-21, 4.5386744987288709e-20, 3.9382188462775671e-19, 3.2106160083645321e-18, 2.4610138689948007e-17, 1.7749316371092158e-16, 1.2052626919006545e-15, 7.7106596673007474e-15, 4.6502415038307999e-14, 2.6453661839732785e-13, 1.4202436007691954e-12, 7.2000553706787476e-12, 3.4484441377850428e-11, 1.5611080651132002e-10, 6.6828734274332115e-10, 2.7064654297770221e-09, 1.0373610614267088e-08, 3.7645745874679117e-08, 1.2939635385192320e-07, 4.2140690642224546e-07, 1.3007683229247929e-06, 3.8067496326313364e-06, 1.0565607635971951e-05, 2.7819080771995885e-05, 6.9504723426630250e-05, 1.6482276370905397e-04, 3.7106723611638040e-04, 7.9325913151483628e-04, 1.6106180017909323e-03, 3.1064654644112318e-03, 5.6926204501420372e-03, 9.9128527364234706e-03, 1.6405471669264392e-02, 2.5807108029946707e-02, 3.8592374515300572e-02, 5.4868153810335302e-02, 7.4171189043357108e-02, 9.5341025218153283e-02, 1.1654188378760408e-01, 1.3547657485442111e-01, 1.4977628436985038e-01, 1.5748155504372183e-01, 1.5748155504372183e-01, 1.4977628436985038e-01, 1.3547657485442111e-01, 1.1654188378760408e-01, 9.5341025218153283e-02, 7.4171189043357108e-02, 5.4868153810335302e-02, 3.8592374515300572e-02, 2.5807108029946707e-02, 1.6405471669264392e-02, 9.9128527364234706e-03, 5.6926204501420372e-03, 3.1064654644112318e-03, 1.6106180017909323e-03, 7.9325913151483628e-04, 3.7106723611638040e-04, 1.6482276370905397e-04, 6.9504723426630250e-05, 2.7819080771995885e-05, 1.0565607635971951e-05, 3.8067496326313364e-06, 1.3007683229247929e-06, 4.2140690642224546e-07, 1.2939635385192320e-07, 3.7645745874679117e-08, 1.0373610614267088e-08, 2.7064654297770221e-09, 6.6828734274332115e-10, 1.5611080651132002e-10, 3.4484441377850428e-11, 7.2000553706787476e-12, 1.4202436007691954e-12, 2.6453661839732785e-13, 4.6502415038307999e-14, 7.7106596673007474e-15, 1.2052626919006545e-15, 1.7749316371092158e-16, 2.4610138689948007e-17, 3.2106160083645321e-18, 3.9382188462775671e-19, 4.5386744987288709e-20, 4.9106724438195655e-21, 4.9840723225381343e-22, 4.7412259196608422e-23, 4.2235075145104786e-24, 3.5198681528057952e-25, 2.7417253568038711e-26, 1.9939689031724527e-27, 1.3525065257212417e-28, 8.5465806757782117e-30, 5.0252446557042918e-31, 2.7459089931491756e-32, 1.3925226088255375e-33, 6.5448147609160573e-35, 2.8466218480726145e-36, 1.1439892419798912e-37, 4.2408968311262046e-39, 1.4477028628289723e-40, 4.5423930481987850e-42, 1.3074430076121838e-43, 3.4450097830357403e-45, 8.2913990414809887e-47, 1.8184989576075493e-48, 3.6254089691585309e-50, 6.5523461103489109e-52, 1.0705056723174281e-53, 1.5761631000101791e-55, 2.0845067543701599e-57, 2.4675003119821257e-59, 2.6043821060405426e-61, 2.4409225876304963e-63, 2.0223861173713801e-65, 1.4740979038429450e-67, 9.4025005576362417e-70, 5.2179989944251382e-72, 2.5035350436180196e-74, 1.0312393292677344e-76, 3.6188278671651930e-79, 1.0726407876436278e-81, 2.6598715295190543e-84, 5.4590825264344227e-87, 9.1613585633591115e-90, 1.2398999039839109e-92, 1.3320789562852151e-95, 1.1154449265558409e-98, 7.1263773535131733e-102, 3.3872112245822123e-105, 1.1621599260631149e-108, 2.7746976743925027e-112, 4.4053240904063359e-116, 4.3913191972243959e-120, 2.5502660858886434e-124, 7.8013060714659609e-129, 1.0903164404085858e-133, 5.6218117631932678e-139, 7.5182851789608105e-145, 1.3295499920372636e-151, 5.5372309477634655e-160}, + {7.8451635230016858e-161, 1.9523607750140259e-152, 1.1375077401246616e-145, 8.7373530318096058e-140, 1.7373540565570015e-134, 1.2727518873570116e-129, 4.2555627733290781e-125, 7.4887926040201802e-121, 7.6728599246194710e-117, 4.9331494690374170e-113, 2.1081805704508371e-109, 6.2668746307989698e-106, 1.3443162713188522e-102, 2.1447717307711369e-99, 2.6100910182768806e-96, 2.4752041309788718e-93, 1.8629470575327606e-90, 1.1305871177614866e-87, 5.6095106427386894e-85, 2.3032570747054949e-82, 7.9109829843002634e-80, 2.2948435687570354e-77, 5.6707499982586783e-75, 1.2029596296647568e-72, 2.2060845936398770e-70, 3.5197550034683429e-68, 4.9140189431762165e-66, 6.0352629400444085e-64, 6.5524291595185267e-62, 6.3168313216462770e-60, 5.4297718879402538e-58, 4.1774383436193032e-56, 2.8868574992210366e-54, 1.7978766039740882e-52, 1.0121575932082767e-50, 5.1657784424151435e-49, 2.3965562741555340e-47, 1.0131990990489010e-45, 3.9127390924870208e-44, 1.3832722270346481e-42, 4.4862136218811265e-41, 1.3373657357984576e-39, 3.6713213079441595e-38, 9.2972768440223579e-37, 2.1755444131733555e-35, 4.7112703089400342e-34, 9.4560355326075165e-33, 1.7615330473782583e-31, 3.0497304146140982e-30, 4.9132641478669298e-29, 7.3745987634168783e-28, 1.0324336757120609e-26, 1.3496248520015288e-25, 1.6490733800656049e-24, 1.8852558386853772e-23, 2.0184180321625388e-22, 2.0255846228536046e-21, 1.9070317011573267e-20, 1.6857232563417842e-19, 1.4001409738252677e-18, 1.0935411714915941e-17, 8.0367861053116616e-17, 5.5616740488492008e-16, 3.6264613629986606e-15, 2.2293626576566599e-14, 1.2928616191624445e-13, 7.0768307534960783e-13, 3.6582348996540792e-12, 1.7867762742843070e-11, 8.2498114987726634e-11, 3.6024058170237729e-10, 1.4883529382284672e-09, 5.8205576663344680e-09, 2.1554622191079048e-08, 7.5613014701765766e-08, 2.5135518772343285e-07, 7.9206548159012504e-07, 2.3667653844440894e-06, 6.7081316695963449e-06, 1.8039486708167727e-05, 4.6040475362243668e-05, 1.1154709040626857e-04, 2.5661526702463013e-04, 5.6067195570805187e-04, 1.1636625437784563e-03, 2.2946716387392549e-03, 4.2999800431004790e-03, 7.6583588130546571e-03, 1.2965620087982580e-02, 2.0868833143304531e-02, 3.1937686193532246e-02, 4.6478966725271985e-02, 6.4327817062627538e-02, 8.4677189450608162e-02, 1.0602045179435517e-01, 1.2626797462143288e-01, 1.4305279328441931e-01, 1.5417456855130846e-01, 1.5807042792926745e-01, 1.5417456855130846e-01, 1.4305279328441931e-01, 1.2626797462143288e-01, 1.0602045179435517e-01, 8.4677189450608162e-02, 6.4327817062627538e-02, 4.6478966725271985e-02, 3.1937686193532246e-02, 2.0868833143304531e-02, 1.2965620087982580e-02, 7.6583588130546571e-03, 4.2999800431004790e-03, 2.2946716387392549e-03, 1.1636625437784563e-03, 5.6067195570805187e-04, 2.5661526702463013e-04, 1.1154709040626857e-04, 4.6040475362243668e-05, 1.8039486708167727e-05, 6.7081316695963449e-06, 2.3667653844440894e-06, 7.9206548159012504e-07, 2.5135518772343285e-07, 7.5613014701765766e-08, 2.1554622191079048e-08, 5.8205576663344680e-09, 1.4883529382284672e-09, 3.6024058170237729e-10, 8.2498114987726634e-11, 1.7867762742843070e-11, 3.6582348996540792e-12, 7.0768307534960783e-13, 1.2928616191624445e-13, 2.2293626576566599e-14, 3.6264613629986606e-15, 5.5616740488492008e-16, 8.0367861053116616e-17, 1.0935411714915941e-17, 1.4001409738252677e-18, 1.6857232563417842e-19, 1.9070317011573267e-20, 2.0255846228536046e-21, 2.0184180321625388e-22, 1.8852558386853772e-23, 1.6490733800656049e-24, 1.3496248520015288e-25, 1.0324336757120609e-26, 7.3745987634168783e-28, 4.9132641478669298e-29, 3.0497304146140982e-30, 1.7615330473782583e-31, 9.4560355326075165e-33, 4.7112703089400342e-34, 2.1755444131733555e-35, 9.2972768440223579e-37, 3.6713213079441595e-38, 1.3373657357984576e-39, 4.4862136218811265e-41, 1.3832722270346481e-42, 3.9127390924870208e-44, 1.0131990990489010e-45, 2.3965562741555340e-47, 5.1657784424151435e-49, 1.0121575932082767e-50, 1.7978766039740882e-52, 2.8868574992210366e-54, 4.1774383436193032e-56, 5.4297718879402538e-58, 6.3168313216462770e-60, 6.5524291595185267e-62, 6.0352629400444085e-64, 4.9140189431762165e-66, 3.5197550034683429e-68, 2.2060845936398770e-70, 1.2029596296647568e-72, 5.6707499982586783e-75, 2.2948435687570354e-77, 7.9109829843002634e-80, 2.3032570747054949e-82, 5.6095106427386894e-85, 1.1305871177614866e-87, 1.8629470575327606e-90, 2.4752041309788718e-93, 2.6100910182768806e-96, 2.1447717307711369e-99, 1.3443162713188522e-102, 6.2668746307989698e-106, 2.1081805704508371e-109, 4.9331494690374170e-113, 7.6728599246194710e-117, 7.4887926040201802e-121, 4.2555627733290781e-125, 1.2727518873570116e-129, 1.7373540565570015e-134, 8.7373530318096058e-140, 1.1375077401246616e-145, 1.9523607750140259e-152, 7.8451635230016858e-161}, + {1.1113325242665607e-161, 2.8661157405088651e-153, 1.7203699801925772e-146, 1.3572912678569801e-140, 2.7667745801693423e-135, 2.0750643806729351e-130, 7.0958232027421688e-126, 1.2760468594731325e-121, 1.3351777371855847e-117, 8.7619375020369923e-114, 3.8201658326880149e-110, 1.1581310985408031e-106, 2.5327817240407812e-103, 4.1185419255140006e-100, 5.1071272449783039e-97, 4.9339716820592914e-94, 3.7824070114676548e-91, 2.3376600104580566e-88, 1.1809947785806983e-85, 4.9369057800338342e-83, 1.7261669173831611e-80, 5.0968500275659627e-78, 1.2818807628470368e-75, 2.7674728413631406e-73, 5.1647694116231104e-71, 8.3851919880334988e-69, 1.1912098546399618e-66, 1.4886103795423663e-64, 1.6443955400649481e-62, 1.6129133242366921e-60, 1.4105633288272223e-58, 1.1041151603377387e-56, 7.7628198468094521e-55, 4.9186136364477312e-53, 2.8172193314312900e-51, 1.4628544044995270e-49, 6.9047962388108693e-48, 2.9700444136624115e-46, 1.1669783057995060e-44, 4.1977240232717920e-43, 1.3852328747381678e-41, 4.2018792516358609e-40, 1.1737667874934990e-38, 3.0248112870289189e-37, 7.2029787582674604e-36, 1.5874640120654814e-34, 3.2427846726141820e-33, 6.1484526840191010e-32, 1.0834946554226288e-30, 1.7768523467499803e-29, 2.7149541158618372e-28, 3.8695229489123667e-27, 5.1500223036312467e-26, 6.4071917092815282e-25, 7.4586793696524265e-24, 8.1320524064342075e-23, 8.3113512372523795e-22, 7.9697999021291434e-21, 7.1759828546746257e-20, 6.0717113565204395e-19, 4.8312403419891758e-18, 3.6176893189785955e-17, 2.5510691957075621e-16, 1.6951627656128116e-15, 1.0621010070430722e-14, 6.2782746989491113e-14, 3.5033054765081019e-13, 1.8463363234967078e-12, 9.1951726021293097e-12, 4.3294831001094053e-11, 1.9281472420443613e-10, 8.1257537810009703e-10, 3.2418174605425769e-09, 1.2248647054749650e-08, 4.3845698417608257e-08, 1.4875155394404803e-07, 4.7845376510326057e-07, 1.4594959469005024e-06, 4.2236041008124797e-06, 1.1598624726140732e-05, 3.0233694291010849e-05, 7.4825364488004140e-05, 1.7586687773524874e-04, 3.9264033171199677e-04, 8.3286186061158249e-04, 1.6788174607182051e-03, 3.2163656781061659e-03, 5.8577616753894349e-03, 1.0143065156003795e-02, 1.6700865101051256e-02, 2.6151472056325592e-02, 3.8948449958622955e-02, 5.5177861430971059e-02, 7.4363251819021731e-02, 9.5346186707308309e-02, 1.1631262299580138e-01, 1.3500522787142605e-01, 1.4910449946872065e-01, 1.5669608061804552e-01, 1.5669608061804552e-01, 1.4910449946872065e-01, 1.3500522787142605e-01, 1.1631262299580138e-01, 9.5346186707308309e-02, 7.4363251819021731e-02, 5.5177861430971059e-02, 3.8948449958622955e-02, 2.6151472056325592e-02, 1.6700865101051256e-02, 1.0143065156003795e-02, 5.8577616753894349e-03, 3.2163656781061659e-03, 1.6788174607182051e-03, 8.3286186061158249e-04, 3.9264033171199677e-04, 1.7586687773524874e-04, 7.4825364488004140e-05, 3.0233694291010849e-05, 1.1598624726140732e-05, 4.2236041008124797e-06, 1.4594959469005024e-06, 4.7845376510326057e-07, 1.4875155394404803e-07, 4.3845698417608257e-08, 1.2248647054749650e-08, 3.2418174605425769e-09, 8.1257537810009703e-10, 1.9281472420443613e-10, 4.3294831001094053e-11, 9.1951726021293097e-12, 1.8463363234967078e-12, 3.5033054765081019e-13, 6.2782746989491113e-14, 1.0621010070430722e-14, 1.6951627656128116e-15, 2.5510691957075621e-16, 3.6176893189785955e-17, 4.8312403419891758e-18, 6.0717113565204395e-19, 7.1759828546746257e-20, 7.9697999021291434e-21, 8.3113512372523795e-22, 8.1320524064342075e-23, 7.4586793696524265e-24, 6.4071917092815282e-25, 5.1500223036312467e-26, 3.8695229489123667e-27, 2.7149541158618372e-28, 1.7768523467499803e-29, 1.0834946554226288e-30, 6.1484526840191010e-32, 3.2427846726141820e-33, 1.5874640120654814e-34, 7.2029787582674604e-36, 3.0248112870289189e-37, 1.1737667874934990e-38, 4.2018792516358609e-40, 1.3852328747381678e-41, 4.1977240232717920e-43, 1.1669783057995060e-44, 2.9700444136624115e-46, 6.9047962388108693e-48, 1.4628544044995270e-49, 2.8172193314312900e-51, 4.9186136364477312e-53, 7.7628198468094521e-55, 1.1041151603377387e-56, 1.4105633288272223e-58, 1.6129133242366921e-60, 1.6443955400649481e-62, 1.4886103795423663e-64, 1.1912098546399618e-66, 8.3851919880334988e-69, 5.1647694116231104e-71, 2.7674728413631406e-73, 1.2818807628470368e-75, 5.0968500275659627e-78, 1.7261669173831611e-80, 4.9369057800338342e-83, 1.1809947785806983e-85, 2.3376600104580566e-88, 3.7824070114676548e-91, 4.9339716820592914e-94, 5.1071272449783039e-97, 4.1185419255140006e-100, 2.5327817240407812e-103, 1.1581310985408031e-106, 3.8201658326880149e-110, 8.7619375020369923e-114, 1.3351777371855847e-117, 1.2760468594731325e-121, 7.0958232027421688e-126, 2.0750643806729351e-130, 2.7667745801693423e-135, 1.3572912678569801e-140, 1.7203699801925772e-146, 2.8661157405088651e-153, 1.1113325242665607e-161}, + {1.5740526693584465e-162, 4.2063621518212007e-154, 2.6008944296538456e-147, 2.1074517218240589e-141, 4.4036325515199439e-136, 3.3809077673415763e-131, 1.1822946408488032e-126, 2.1725144459735252e-122, 2.3212763347728001e-118, 1.5547020684816359e-114, 6.9150182989560957e-111, 2.1377995126059837e-107, 4.7660941708469085e-104, 7.8984266909061953e-101, 9.9792660546750878e-98, 9.8208576850538984e-95, 7.6677750665974574e-92, 4.8256764019125120e-89, 2.4821990706514334e-86, 1.0563282231662235e-83, 3.7595217722773437e-81, 1.1298318188883590e-78, 2.8919012660409682e-76, 6.3534513888384988e-74, 1.2065320173749644e-71, 1.9931390693715852e-69, 2.8809012333842463e-67, 3.6628479225209667e-65, 4.1164923961054212e-63, 4.1077464167348542e-61, 3.6546677508675100e-59, 2.9102221244239064e-57, 2.0815358697976881e-55, 1.3417085980893448e-53, 7.8178603818978630e-52, 4.1297412217775072e-50, 1.9830414431093633e-48, 8.6778002491153641e-47, 3.4688352621558211e-45, 1.2694602644562695e-43, 4.2621053825441441e-42, 1.3153901362816908e-40, 3.7386729623017851e-39, 9.8033645273483504e-38, 2.3754629195463299e-36, 5.3274424573468086e-35, 1.1074717912785746e-33, 2.1369895498120545e-32, 3.8327370697542584e-31, 6.3974120073582433e-30, 9.9497591435745215e-29, 1.4435514631174776e-27, 1.9558597204465646e-26, 2.4773098248022596e-25, 2.9362302035583120e-24, 3.2596930342072210e-23, 3.3925841234631972e-22, 3.3130211274194918e-21, 3.0381735933104597e-20, 2.6183914995557019e-19, 2.1223329298239927e-18, 1.6190413502935239e-17, 1.1632214089861438e-16, 7.8760411702639125e-16, 5.0287848550079939e-15, 3.0295892003599562e-14, 1.7231158339195911e-13, 9.2573881503227024e-13, 4.7003287276740161e-12, 2.2565549953554105e-11, 1.0248110528690129e-10, 4.4046822285487214e-10, 1.7924282778278772e-09, 6.9087593674811365e-09, 2.5232222625609405e-08, 8.7350604983433712e-08, 2.8673524946820525e-07, 8.9277708976484127e-07, 2.6374622880097546e-06, 7.3949955626738131e-06, 1.9684213310007427e-05, 4.9755352753869857e-05, 1.1945642608697544e-04, 2.7247518029396975e-04, 5.9058909090482672e-04, 1.2166676013683477e-03, 2.3826889355841037e-03, 4.4365604655715969e-03, 7.8555741198391739e-03, 1.3228935168893997e-02, 2.1190659578816773e-02, 3.2291498859030154e-02, 4.6816827098479806e-02, 6.4584179655610197e-02, 8.4780422567999614e-02, 1.0591066198925958e-01, 1.2591645229378781e-01, 1.4247629387217531e-01, 1.5343815707202285e-01, 1.5727610417082902e-01, 1.5343815707202285e-01, 1.4247629387217531e-01, 1.2591645229378781e-01, 1.0591066198925958e-01, 8.4780422567999614e-02, 6.4584179655610197e-02, 4.6816827098479806e-02, 3.2291498859030154e-02, 2.1190659578816773e-02, 1.3228935168893997e-02, 7.8555741198391739e-03, 4.4365604655715969e-03, 2.3826889355841037e-03, 1.2166676013683477e-03, 5.9058909090482672e-04, 2.7247518029396975e-04, 1.1945642608697544e-04, 4.9755352753869857e-05, 1.9684213310007427e-05, 7.3949955626738131e-06, 2.6374622880097546e-06, 8.9277708976484127e-07, 2.8673524946820525e-07, 8.7350604983433712e-08, 2.5232222625609405e-08, 6.9087593674811365e-09, 1.7924282778278772e-09, 4.4046822285487214e-10, 1.0248110528690129e-10, 2.2565549953554105e-11, 4.7003287276740161e-12, 9.2573881503227024e-13, 1.7231158339195911e-13, 3.0295892003599562e-14, 5.0287848550079939e-15, 7.8760411702639125e-16, 1.1632214089861438e-16, 1.6190413502935239e-17, 2.1223329298239927e-18, 2.6183914995557019e-19, 3.0381735933104597e-20, 3.3130211274194918e-21, 3.3925841234631972e-22, 3.2596930342072210e-23, 2.9362302035583120e-24, 2.4773098248022596e-25, 1.9558597204465646e-26, 1.4435514631174776e-27, 9.9497591435745215e-29, 6.3974120073582433e-30, 3.8327370697542584e-31, 2.1369895498120545e-32, 1.1074717912785746e-33, 5.3274424573468086e-35, 2.3754629195463299e-36, 9.8033645273483504e-38, 3.7386729623017851e-39, 1.3153901362816908e-40, 4.2621053825441441e-42, 1.2694602644562695e-43, 3.4688352621558211e-45, 8.6778002491153641e-47, 1.9830414431093633e-48, 4.1297412217775072e-50, 7.8178603818978630e-52, 1.3417085980893448e-53, 2.0815358697976881e-55, 2.9102221244239064e-57, 3.6546677508675100e-59, 4.1077464167348542e-61, 4.1164923961054212e-63, 3.6628479225209667e-65, 2.8809012333842463e-67, 1.9931390693715852e-69, 1.2065320173749644e-71, 6.3534513888384988e-74, 2.8919012660409682e-76, 1.1298318188883590e-78, 3.7595217722773437e-81, 1.0563282231662235e-83, 2.4821990706514334e-86, 4.8256764019125120e-89, 7.6677750665974574e-92, 9.8208576850538984e-95, 9.9792660546750878e-98, 7.8984266909061953e-101, 4.7660941708469085e-104, 2.1377995126059837e-107, 6.9150182989560957e-111, 1.5547020684816359e-114, 2.3212763347728001e-118, 2.1725144459735252e-122, 1.1822946408488032e-126, 3.3809077673415763e-131, 4.4036325515199439e-136, 2.1074517218240589e-141, 2.6008944296538456e-147, 4.2063621518212007e-154, 1.5740526693584465e-162}, + {2.2290934963031539e-163, 6.1716304223418473e-155, 3.9305958509063355e-148, 3.2706601334834755e-142, 7.0049069648137550e-137, 5.5049260050287900e-132, 1.9684692530020812e-127, 3.6957545112422320e-123, 4.0320327117616306e-119, 2.7559362749699724e-115, 1.2503894738744883e-111, 3.9416969862084461e-108, 8.9577890237321700e-105, 1.5127860735379895e-101, 1.9472732376896783e-98, 1.9519789398323314e-95, 1.5520652579926001e-92, 9.9458309202670908e-90, 5.2083206235820379e-87, 2.2562215375682347e-84, 8.1731118972592471e-82, 2.4997514837476365e-79, 6.5111285362111366e-77, 1.4555888776738779e-74, 2.8125155025369667e-72, 4.7271089337772468e-70, 6.9513137370020262e-68, 8.9912466505154563e-66, 1.0279594830695334e-63, 1.0434894316959833e-61, 9.4440639857201346e-60, 7.6499247670821092e-58, 5.5658406725957325e-56, 3.6493796373809251e-54, 2.1630323514364711e-52, 1.1622901525905010e-50, 5.6773339224732908e-49, 2.5272570465088243e-47, 1.0276815273410889e-45, 3.8259457909463708e-44, 1.3067728287128299e-42, 4.1029828415971428e-41, 1.1864415902523173e-39, 3.1652198121078916e-38, 7.8035886293155777e-37, 1.7807430428966829e-35, 3.7667945725159055e-34, 7.3963969744653024e-33, 1.3499836949356773e-31, 2.2932424003565328e-30, 3.6300293183361797e-29, 5.3605436078106824e-28, 7.3930155412655720e-27, 9.5323773039462743e-26, 1.1502145928125925e-24, 1.3000662757028629e-23, 1.3776941782313042e-22, 1.3699807056265559e-21, 1.2794012136597428e-20, 1.1229742763811151e-19, 9.2710336687274256e-19, 7.2042972150393114e-18, 5.2729781171856177e-17, 3.6375048889083554e-16, 2.3664867578847666e-15, 1.4528301518132017e-14, 8.4213476872404286e-14, 4.6114644502136799e-13, 2.3867692880717110e-12, 1.1681801468249808e-11, 5.4092941845487156e-11, 2.3708105480750139e-10, 9.8392832670094020e-10, 3.8682673753498617e-09, 1.4411972185221586e-08, 5.0903013962041357e-08, 1.7050141340191249e-07, 5.4177677321026202e-07, 1.6336412605871983e-06, 4.6759044289293238e-06, 1.2707753951032874e-05, 3.2800534876023489e-05, 8.0428506528979537e-05, 1.8739476963256670e-04, 4.1497155710923123e-04, 8.7353709789879039e-04, 1.7483531042542699e-03, 3.3276551358222884e-03, 6.0239245919995622e-03, 1.0373317514267365e-02, 1.6994637482018023e-02, 2.6492061401939205e-02, 3.9298609227795579e-02, 5.5480282208033298e-02, 7.4548212057078664e-02, 9.5346453940664169e-02, 1.1608254348974273e-01, 1.3453811804025481e-01, 1.4844158241213595e-01, 1.5592224232989221e-01, 1.5592224232989221e-01, 1.4844158241213595e-01, 1.3453811804025481e-01, 1.1608254348974273e-01, 9.5346453940664169e-02, 7.4548212057078664e-02, 5.5480282208033298e-02, 3.9298609227795579e-02, 2.6492061401939205e-02, 1.6994637482018023e-02, 1.0373317514267365e-02, 6.0239245919995622e-03, 3.3276551358222884e-03, 1.7483531042542699e-03, 8.7353709789879039e-04, 4.1497155710923123e-04, 1.8739476963256670e-04, 8.0428506528979537e-05, 3.2800534876023489e-05, 1.2707753951032874e-05, 4.6759044289293238e-06, 1.6336412605871983e-06, 5.4177677321026202e-07, 1.7050141340191249e-07, 5.0903013962041357e-08, 1.4411972185221586e-08, 3.8682673753498617e-09, 9.8392832670094020e-10, 2.3708105480750139e-10, 5.4092941845487156e-11, 1.1681801468249808e-11, 2.3867692880717110e-12, 4.6114644502136799e-13, 8.4213476872404286e-14, 1.4528301518132017e-14, 2.3664867578847666e-15, 3.6375048889083554e-16, 5.2729781171856177e-17, 7.2042972150393114e-18, 9.2710336687274256e-19, 1.1229742763811151e-19, 1.2794012136597428e-20, 1.3699807056265559e-21, 1.3776941782313042e-22, 1.3000662757028629e-23, 1.1502145928125925e-24, 9.5323773039462743e-26, 7.3930155412655720e-27, 5.3605436078106824e-28, 3.6300293183361797e-29, 2.2932424003565328e-30, 1.3499836949356773e-31, 7.3963969744653024e-33, 3.7667945725159055e-34, 1.7807430428966829e-35, 7.8035886293155777e-37, 3.1652198121078916e-38, 1.1864415902523173e-39, 4.1029828415971428e-41, 1.3067728287128299e-42, 3.8259457909463708e-44, 1.0276815273410889e-45, 2.5272570465088243e-47, 5.6773339224732908e-49, 1.1622901525905010e-50, 2.1630323514364711e-52, 3.6493796373809251e-54, 5.5658406725957325e-56, 7.6499247670821092e-58, 9.4440639857201346e-60, 1.0434894316959833e-61, 1.0279594830695334e-63, 8.9912466505154563e-66, 6.9513137370020262e-68, 4.7271089337772468e-70, 2.8125155025369667e-72, 1.4555888776738779e-74, 6.5111285362111366e-77, 2.4997514837476365e-79, 8.1731118972592471e-82, 2.2562215375682347e-84, 5.2083206235820379e-87, 9.9458309202670908e-90, 1.5520652579926001e-92, 1.9519789398323314e-95, 1.9472732376896783e-98, 1.5127860735379895e-101, 8.9577890237321700e-105, 3.9416969862084461e-108, 1.2503894738744883e-111, 2.7559362749699724e-115, 4.0320327117616306e-119, 3.6957545112422320e-123, 1.9684692530020812e-127, 5.5049260050287900e-132, 7.0049069648137550e-137, 3.2706601334834755e-142, 3.9305958509063355e-148, 6.1716304223418473e-155, 2.2290934963031539e-163}, +} diff --git a/integrate/quad/hermite_test.go b/integrate/quad/hermite_test.go new file mode 100644 index 00000000..d74b82dc --- /dev/null +++ b/integrate/quad/hermite_test.go @@ -0,0 +1,251 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package quad + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestHermite(t *testing.T) { + for cas, test := range []struct { + n int + f func(float64) float64 + ev float64 + tol float64 + }{ + { + n: 2, + f: func(x float64) float64 { return 1 }, + ev: math.SqrtPi, + tol: 1e-14, + }, + { + n: 4, + f: func(x float64) float64 { return math.Exp(-2 * 0.5 * x) }, + ev: math.SqrtPi * math.Exp(0.25), + tol: 1e-4, + }, + { + n: 9, + f: func(x float64) float64 { return math.Exp(-2 * 0.5 * x) }, + ev: math.SqrtPi * math.Exp(0.25), + tol: 1e-12, + }, + { + n: 10, + f: func(x float64) float64 { return math.Exp(-2 * 0.5 * x) }, + ev: math.SqrtPi * math.Exp(0.25), + tol: 1e-12, + }, + { + n: 15, + f: func(x float64) float64 { return math.Exp(-2 * 2 * x) }, + ev: math.SqrtPi * math.Exp(4), + tol: 1e-4, + }, + { + n: 22, + f: func(x float64) float64 { return math.Exp(-2 * 2 * x) }, + ev: math.SqrtPi * math.Exp(4), + tol: 1e-12, + }, + { + n: 21, + f: func(x float64) float64 { return math.Exp(-2 * 2 * x) }, + ev: math.SqrtPi * math.Exp(4), + tol: 1e-12, + }, + } { + ev := Fixed(test.f, math.Inf(-1), math.Inf(1), test.n, Hermite{}, 0) + if !floats.EqualWithinAbsOrRel(test.ev, ev, test.tol, test.tol) { + t.Errorf("Case %d: expected value mismatch.\nWant %v\ngot %v", cas, test.ev, ev) + } + } +} + +func TestHermiteLocations(t *testing.T) { + // Test the hermite locations and weights against other precomputed table. + // Data from http://dlmf.nist.gov/3.5. + for _, test := range []struct { + n int + x []float64 + w []float64 + }{ + // Evaluated from Chebfun. + { + n: 5, + x: []float64{-0.202018287045609e1, -0.958572464613819, 0, 0.958572464613819, 0.202018287045609e1}, + w: []float64{0.199532420590459e-1, 0.393619323152241, 0.945308720482942, 0.393619323152241, 0.199532420590459e-1}, + }, + { + n: 10, + x: []float64{-0.343615911883773760e1, -0.253273167423278980e1, -0.175668364929988177e1, -0.103661082978951365e1, -0.342901327223704609, 0.342901327223704609, 0.103661082978951365e1, 0.175668364929988177e1, 0.253273167423278980e1, 0.343615911883773760e1}, + w: []float64{0.764043285523262063e-5, 0.134364574678123269e-2, 0.338743944554810631e-1, 0.240138611082314686, 0.610862633735325799, 0.610862633735325799, 0.240138611082314686, 0.338743944554810631e-1, 0.134364574678123269e-2, 0.764043285523262063e-5}, + }, + { + n: 215, + x: []float64{-2.0083110126223993e+01, -1.9573161931385755e+01, -1.9153731166695263e+01, -1.8781558404513735e+01, -1.8440108632764016e+01, -1.8120857960601569e+01, -1.7818692349773503e+01, -1.7530242081974308e+01, -1.7253139752773148e+01, -1.6985642449377284e+01, -1.6726420346886542e+01, -1.6474429782282726e+01, -1.6228832750513551e+01, -1.5988943547145137e+01, -1.5754192102761674e+01, -1.5524098014731747e+01, -1.5298251677453143e+01, -1.5076300264808333e+01, -1.4857937115425768e+01, -1.4642893558208563e+01, -1.4430932522616979e+01, -1.4221843477251845e+01, -1.4015438372554696e+01, -1.3811548353270942e+01, -1.3610021068540190e+01, -1.3410718451340038e+01, -1.3213514870431910e+01, -1.3018295580800100e+01, -1.2824955415404188e+01, -1.2633397673617059e+01, -1.2443533171189967e+01, -1.2255279423804318e+01, -1.2068559941826503e+01, -1.1883303618198463e+01, -1.1699444194777641e+01, -1.1516919795109878e+01, -1.1335672513742256e+01, -1.1155648053883823e+01, -1.0976795406593546e+01, -1.0799066565787168e+01, -1.0622416274262394e+01, -1.0446801796686490e+01, -1.0272182716104577e+01, -1.0098520751035824e+01, -9.9257795906487338e+00, -9.7539247458611111e+00, -9.5829234145081710e+00, -9.4127443589734394e+00, -9.2433577948895387e+00, -9.0747352896969389e+00, -8.9068496700026394e+00, -8.7396749368126798e+00, -8.5731861878255415e+00, -8.4073595460710955e+00, -8.2421720942637187e+00, -8.0776018143113824e+00, -7.9136275314855800e+00, -7.7502288628124383e+00, -7.5873861692931381e+00, -7.4250805116042331e+00, -7.2632936089653120e+00, -7.1020078008938672e+00, -6.9412060115960434e+00, -6.7808717167671544e+00, -6.6209889125982082e+00, -6.4615420868046280e+00, -6.3025161915109100e+00, -6.1438966178406549e+00, -5.9856691720754620e+00, -5.8278200532585673e+00, -5.6703358321303936e+00, -5.5132034312931157e+00, -5.3564101065103049e+00, -5.1999434290559226e+00, -5.0437912690340267e+00, -4.8879417795972326e+00, -4.7323833819978187e+00, -4.5771047514106780e+00, -4.4220948034722349e+00, -4.2673426814837114e+00, -4.1128377442311503e+00, -3.9585695543782120e+00, -3.8045278673909002e+00, -3.6507026209565665e+00, -3.4970839248619634e+00, -3.3436620512978501e+00, -3.1904274255596032e+00, -3.0373706171156218e+00, -2.8844823310168755e+00, -2.7317533996228827e+00, -2.5791747746208049e+00, -2.4267375193157439e+00, -2.2744328011717010e+00, -2.1222518845837395e+00, -1.9701861238629792e+00, -1.8182269564169717e+00, -1.6663658961089640e+00, -1.5145945267802365e+00, -1.3629044959205205e+00, -1.2112875084719879e+00, -1.0597353207530273e+00, -9.0823973448851325e-01, -7.5679259093351370e-01, -6.0538576507805808e-01, -4.5401115992078167e-01, -3.0266070079942864e-01, -1.5132632976672361e-01, 7.9483151672010196e-15, 1.5132632976672361e-01, 3.0266070079942864e-01, 4.5401115992078167e-01, 6.0538576507805808e-01, 7.5679259093351370e-01, 9.0823973448851325e-01, 1.0597353207530273e+00, 1.2112875084719879e+00, 1.3629044959205205e+00, 1.5145945267802365e+00, 1.6663658961089640e+00, 1.8182269564169717e+00, 1.9701861238629792e+00, 2.1222518845837395e+00, 2.2744328011717010e+00, 2.4267375193157439e+00, 2.5791747746208049e+00, 2.7317533996228827e+00, 2.8844823310168755e+00, 3.0373706171156218e+00, 3.1904274255596032e+00, 3.3436620512978501e+00, 3.4970839248619634e+00, 3.6507026209565665e+00, 3.8045278673909002e+00, 3.9585695543782120e+00, 4.1128377442311503e+00, 4.2673426814837114e+00, 4.4220948034722349e+00, 4.5771047514106780e+00, 4.7323833819978187e+00, 4.8879417795972326e+00, 5.0437912690340267e+00, 5.1999434290559226e+00, 5.3564101065103049e+00, 5.5132034312931157e+00, 5.6703358321303936e+00, 5.8278200532585673e+00, 5.9856691720754620e+00, 6.1438966178406549e+00, 6.3025161915109100e+00, 6.4615420868046280e+00, 6.6209889125982082e+00, 6.7808717167671544e+00, 6.9412060115960434e+00, 7.1020078008938672e+00, 7.2632936089653120e+00, 7.4250805116042331e+00, 7.5873861692931381e+00, 7.7502288628124383e+00, 7.9136275314855800e+00, 8.0776018143113824e+00, 8.2421720942637187e+00, 8.4073595460710955e+00, 8.5731861878255415e+00, 8.7396749368126798e+00, 8.9068496700026394e+00, 9.0747352896969389e+00, 9.2433577948895387e+00, 9.4127443589734394e+00, 9.5829234145081710e+00, 9.7539247458611111e+00, 9.9257795906487338e+00, 1.0098520751035824e+01, 1.0272182716104577e+01, 1.0446801796686490e+01, 1.0622416274262394e+01, 1.0799066565787168e+01, 1.0976795406593546e+01, 1.1155648053883823e+01, 1.1335672513742256e+01, 1.1516919795109878e+01, 1.1699444194777641e+01, 1.1883303618198463e+01, 1.2068559941826503e+01, 1.2255279423804318e+01, 1.2443533171189967e+01, 1.2633397673617059e+01, 1.2824955415404188e+01, 1.3018295580800100e+01, 1.3213514870431910e+01, 1.3410718451340038e+01, 1.3610021068540190e+01, 1.3811548353270942e+01, 1.4015438372554696e+01, 1.4221843477251845e+01, 1.4430932522616979e+01, 1.4642893558208563e+01, 1.4857937115425768e+01, 1.5076300264808333e+01, 1.5298251677453143e+01, 1.5524098014731747e+01, 1.5754192102761674e+01, 1.5988943547145137e+01, 1.6228832750513551e+01, 1.6474429782282726e+01, 1.6726420346886542e+01, 1.6985642449377284e+01, 1.7253139752773148e+01, 1.7530242081974308e+01, 1.7818692349773503e+01, 1.8120857960601569e+01, 1.8440108632764016e+01, 1.8781558404513735e+01, 1.9153731166695263e+01, 1.9573161931385755e+01, 2.0083110126223993e+01}, + w: []float64{4.0474005560499094e-176, 1.8797130400856443e-167, 1.8432377040276421e-160, 2.2601442864626069e-154, 6.9363023753259492e-149, 7.6575370428605554e-144, 3.7894855074137878e-139, 9.7310398950542353e-135, 1.4382941114934084e-130, 1.3214094652141891e-126, 8.0053233705919762e-123, 3.3506484324551954e-119, 1.0061133084529732e-115, 2.2355880918528976e-112, 3.7723274691873339e-109, 4.9410774014014167e-106, 5.1189805080467357e-103, 4.2633269887655389e-100, 2.8951564896303124e-97, 1.6231768954981774e-94, 7.5966487579367170e-92, 2.9971587600601123e-89, 1.0056653752640396e-86, 2.8926565116618279e-84, 7.1838069610206879e-82, 1.5504440487214177e-79, 2.9253709118548054e-77, 4.8516529695481360e-75, 7.1080340648382430e-73, 9.2417798747589595e-71, 1.0709039437896534e-68, 1.1102986726619406e-66, 1.0337280935884043e-64, 8.6720569345151135e-63, 6.5759615285599325e-61, 4.5206307708839604e-59, 2.8251413443094276e-57, 1.6091856250751163e-55, 8.3743579179261028e-54, 3.9908716881614503e-52, 1.7453732998154445e-50, 7.0192904730947679e-49, 2.6008368230936308e-47, 8.8947358191690260e-46, 2.8125213532676820e-44, 8.2357837374304705e-43, 2.2368010157343200e-41, 5.6428177886700861e-40, 1.3240736407971940e-38, 2.8936578029605094e-37, 5.8971855560501346e-36, 1.1220768467833071e-34, 1.9956009474900652e-33, 3.3209946083724174e-32, 5.1767166839129889e-31, 7.5658951790722304e-30, 1.0377543674300410e-28, 1.3370496163293642e-27, 1.6195422525877890e-26, 1.8458039741402227e-25, 1.9809275961773415e-24, 2.0034006172471768e-23, 1.9107136033126365e-22, 1.7196934641222891e-21, 1.4615728740382834e-20, 1.1737567188678477e-19, 8.9122322093114715e-19, 6.4017277272147784e-18, 4.3526236743179514e-17, 2.8027154496363443e-16, 1.7100226833829111e-15, 9.8907988394494626e-15, 5.4258798698008971e-14, 2.8243097014577004e-13, 1.3955439320917938e-12, 6.5484943121277863e-12, 2.9192823809511808e-11, 1.2368298646403665e-10, 4.9819378483709125e-10, 1.9084879833147422e-09, 6.9554442384546823e-09, 2.4123461087320678e-08, 7.9645691304111948e-08, 2.5038904484412268e-07, 7.4974774628062337e-07, 2.1388110362272039e-06, 5.8142267442915587e-06, 1.5065139508846480e-05, 3.7214305501073257e-05, 8.7657861198914500e-05, 1.9692436368292282e-04, 4.2200152760283493e-04, 8.6279569789330843e-04, 1.6832545363270029e-03, 3.1340302956109622e-03, 5.5696401904272858e-03, 9.4487851093380676e-03, 1.5303805411902717e-02, 2.3666975130344652e-02, 3.4949960453868167e-02, 4.9288724246681882e-02, 6.6386134961517171e-02, 8.5401153510804823e-02, 1.0493731687783339e-01, 1.2316720474285285e-01, 1.3809371553328023e-01, 1.4790300421921079e-01, 1.5132498974070285e-01, 1.4790300421921079e-01, 1.3809371553328023e-01, 1.2316720474285285e-01, 1.0493731687783339e-01, 8.5401153510804823e-02, 6.6386134961517171e-02, 4.9288724246681882e-02, 3.4949960453868167e-02, 2.3666975130344652e-02, 1.5303805411902717e-02, 9.4487851093380676e-03, 5.5696401904272858e-03, 3.1340302956109622e-03, 1.6832545363270029e-03, 8.6279569789330843e-04, 4.2200152760283493e-04, 1.9692436368292282e-04, 8.7657861198914500e-05, 3.7214305501073257e-05, 1.5065139508846480e-05, 5.8142267442915587e-06, 2.1388110362272039e-06, 7.4974774628062337e-07, 2.5038904484412268e-07, 7.9645691304111948e-08, 2.4123461087320678e-08, 6.9554442384546823e-09, 1.9084879833147422e-09, 4.9819378483709125e-10, 1.2368298646403665e-10, 2.9192823809511808e-11, 6.5484943121277863e-12, 1.3955439320917938e-12, 2.8243097014577004e-13, 5.4258798698008971e-14, 9.8907988394494626e-15, 1.7100226833829111e-15, 2.8027154496363443e-16, 4.3526236743179514e-17, 6.4017277272147784e-18, 8.9122322093114715e-19, 1.1737567188678477e-19, 1.4615728740382834e-20, 1.7196934641222891e-21, 1.9107136033126365e-22, 2.0034006172471768e-23, 1.9809275961773415e-24, 1.8458039741402227e-25, 1.6195422525877890e-26, 1.3370496163293642e-27, 1.0377543674300410e-28, 7.5658951790722304e-30, 5.1767166839129889e-31, 3.3209946083724174e-32, 1.9956009474900652e-33, 1.1220768467833071e-34, 5.8971855560501346e-36, 2.8936578029605094e-37, 1.3240736407971940e-38, 5.6428177886700861e-40, 2.2368010157343200e-41, 8.2357837374304705e-43, 2.8125213532676820e-44, 8.8947358191690260e-46, 2.6008368230936308e-47, 7.0192904730947679e-49, 1.7453732998154445e-50, 3.9908716881614503e-52, 8.3743579179261028e-54, 1.6091856250751163e-55, 2.8251413443094276e-57, 4.5206307708839604e-59, 6.5759615285599325e-61, 8.6720569345151135e-63, 1.0337280935884043e-64, 1.1102986726619406e-66, 1.0709039437896534e-68, 9.2417798747589595e-71, 7.1080340648382430e-73, 4.8516529695481360e-75, 2.9253709118548054e-77, 1.5504440487214177e-79, 7.1838069610206879e-82, 2.8926565116618279e-84, 1.0056653752640396e-86, 2.9971587600601123e-89, 7.5966487579367170e-92, 1.6231768954981774e-94, 2.8951564896303124e-97, 4.2633269887655389e-100, 5.1189805080467357e-103, 4.9410774014014167e-106, 3.7723274691873339e-109, 2.2355880918528976e-112, 1.0061133084529732e-115, 3.3506484324551954e-119, 8.0053233705919762e-123, 1.3214094652141891e-126, 1.4382941114934084e-130, 9.7310398950542353e-135, 3.7894855074137878e-139, 7.6575370428605554e-144, 6.9363023753259492e-149, 2.2601442864626069e-154, 1.8432377040276421e-160, 1.8797130400856443e-167, 4.0474005560499094e-176}, + }, + { + n: 216, + x: []float64{-2.0131752068397390e+01, -1.9622211733828486e+01, -1.9203122650098184e+01, -1.8831257901839155e+01, -1.8490094811217439e+01, -1.8171115805943941e+01, -1.7869210618319627e+01, -1.7581012003064874e+01, -1.7304154286393636e+01, -1.7036895825521608e+01, -1.6777907762072694e+01, -1.6526147190139376e+01, -1.6280776711860355e+01, -1.6041111119395726e+01, -1.5806580756275796e+01, -1.5576705568204593e+01, -1.5351076247103551e+01, -1.5129340223792830e+01, -1.4911191060978103e+01, -1.4696360284715409e+01, -1.4484610999323769e+01, -1.4275732829628778e+01, -1.4069537866591046e+01, -1.3865857382137794e+01, -1.3664539141187824e+01, -1.3465445182689793e+01, -1.3268449972893279e+01, -1.3073438856897617e+01, -1.2880306751340244e+01, -1.2688957033629340e+01, -1.2499300592587632e+01, -1.2311255012587219e+01, -1.2124743868808109e+01, -1.1939696115566026e+01, -1.1756045553033841e+01, -1.1573730360348824e+01, -1.1392692685219812e+01, -1.1212878281848150e+01, -1.1034236190346626e+01, -1.0856718451952171e+01, -1.0680279855235202e+01, -1.0504877709252620e+01, -1.0330471640205081e+01, -1.0157023408668081e+01, -9.9844967448895385e+00, -9.8128572000013108e+00, -9.6420720112891818e+00, -9.4721099799172528e+00, -9.3029413597147883e+00, -9.1345377558145096e+00, -8.9668720320849413e+00, -8.7999182264315081e+00, -8.6336514731539875e+00, -8.4680479316454296e+00, -8.3030847208017082e+00, -8.1387398585838486e+00, -7.9749922062384426e+00, -7.8118214167366684e+00, -7.6492078870405447e+00, -7.4871327138470951e+00, -7.3255776524981444e+00, -7.1645250787759087e+00, -7.0039579533331269e+00, -6.8438597885318986e+00, -6.6842146174875827e+00, -6.5250069651340752e+00, -6.3662218211444577e+00, -6.2078446145563948e+00, -6.0498611899661094e+00, -5.8922577851667635e+00, -5.7350210101185848e+00, -5.5781378271479722e+00, -5.4215955322816969e+00, -5.2653817376305465e+00, -5.1094843547439881e+00, -4.9538915788638089e+00, -4.7985918740108131e+00, -4.6435739588438905e+00, -4.4888267932355790e+00, -4.3343395655126109e+00, -4.1801016803139959e+00, -4.0261027470226392e+00, -3.8723325687298416e+00, -3.7187811316950210e+00, -3.5654385952656149e+00, -3.4122952822245907e+00, -3.2593416695353823e+00, -3.1065683794558021e+00, -2.9539661709946619e+00, -2.8015259316863266e+00, -2.6492386696600243e+00, -2.4970955059821409e+00, -2.3450876672510903e+00, -2.1932064784252856e+00, -2.0414433558661624e+00, -1.8897898005787916e+00, -1.7382373916337388e+00, -1.5867777797546210e+00, -1.4354026810562848e+00, -1.2841038709195900e+00, -1.1328731779888348e+00, -9.8170247827895785e-01, -8.3058368937955573e-01, -6.7950876474356448e-01, -5.2846968804856509e-01, -3.7745846761911317e-01, -2.2646713089859094e-01, -7.5487718959414210e-02, 7.5487718959414210e-02, 2.2646713089859094e-01, 3.7745846761911317e-01, 5.2846968804856509e-01, 6.7950876474356448e-01, 8.3058368937955573e-01, 9.8170247827895785e-01, 1.1328731779888348e+00, 1.2841038709195900e+00, 1.4354026810562848e+00, 1.5867777797546210e+00, 1.7382373916337388e+00, 1.8897898005787916e+00, 2.0414433558661624e+00, 2.1932064784252856e+00, 2.3450876672510903e+00, 2.4970955059821409e+00, 2.6492386696600243e+00, 2.8015259316863266e+00, 2.9539661709946619e+00, 3.1065683794558021e+00, 3.2593416695353823e+00, 3.4122952822245907e+00, 3.5654385952656149e+00, 3.7187811316950210e+00, 3.8723325687298416e+00, 4.0261027470226392e+00, 4.1801016803139959e+00, 4.3343395655126109e+00, 4.4888267932355790e+00, 4.6435739588438905e+00, 4.7985918740108131e+00, 4.9538915788638089e+00, 5.1094843547439881e+00, 5.2653817376305465e+00, 5.4215955322816969e+00, 5.5781378271479722e+00, 5.7350210101185848e+00, 5.8922577851667635e+00, 6.0498611899661094e+00, 6.2078446145563948e+00, 6.3662218211444577e+00, 6.5250069651340752e+00, 6.6842146174875827e+00, 6.8438597885318986e+00, 7.0039579533331269e+00, 7.1645250787759087e+00, 7.3255776524981444e+00, 7.4871327138470951e+00, 7.6492078870405447e+00, 7.8118214167366684e+00, 7.9749922062384426e+00, 8.1387398585838486e+00, 8.3030847208017082e+00, 8.4680479316454296e+00, 8.6336514731539875e+00, 8.7999182264315081e+00, 8.9668720320849413e+00, 9.1345377558145096e+00, 9.3029413597147883e+00, 9.4721099799172528e+00, 9.6420720112891818e+00, 9.8128572000013108e+00, 9.9844967448895385e+00, 1.0157023408668081e+01, 1.0330471640205081e+01, 1.0504877709252620e+01, 1.0680279855235202e+01, 1.0856718451952171e+01, 1.1034236190346626e+01, 1.1212878281848150e+01, 1.1392692685219812e+01, 1.1573730360348824e+01, 1.1756045553033841e+01, 1.1939696115566026e+01, 1.2124743868808109e+01, 1.2311255012587219e+01, 1.2499300592587632e+01, 1.2688957033629340e+01, 1.2880306751340244e+01, 1.3073438856897617e+01, 1.3268449972893279e+01, 1.3465445182689793e+01, 1.3664539141187824e+01, 1.3865857382137794e+01, 1.4069537866591046e+01, 1.4275732829628778e+01, 1.4484610999323769e+01, 1.4696360284715409e+01, 1.4911191060978103e+01, 1.5129340223792830e+01, 1.5351076247103551e+01, 1.5576705568204593e+01, 1.5806580756275796e+01, 1.6041111119395726e+01, 1.6280776711860355e+01, 1.6526147190139376e+01, 1.6777907762072694e+01, 1.7036895825521608e+01, 1.7304154286393636e+01, 1.7581012003064874e+01, 1.7869210618319627e+01, 1.8171115805943941e+01, 1.8490094811217439e+01, 1.8831257901839155e+01, 1.9203122650098184e+01, 1.9622211733828486e+01, 2.0131752068397390e+01}, + w: []float64{5.7186844211118222e-177, 2.7466189949527236e-168, 2.7698274929964049e-161, 3.4828172461418377e-155, 1.0940903755394791e-149, 1.2347606047124676e-144, 6.2404773612052171e-140, 1.6353340891378212e-135, 2.4650950171742754e-131, 2.3085411036710099e-127, 1.4249650100034198e-123, 6.0746030482858092e-120, 1.8572077169453742e-116, 4.2005766103289114e-113, 7.2131362796894811e-110, 9.6125997143450870e-107, 1.0130358260780602e-103, 8.5810245129266594e-101, 5.9257988910096090e-98, 3.3780606107607827e-95, 1.6073077596553874e-92, 6.4463886647737192e-90, 2.1986159587286647e-87, 6.4275556938243753e-85, 1.6222763835321407e-82, 3.5581101139323407e-80, 6.8220148646876484e-78, 1.1496573365594917e-75, 1.7114200608857651e-73, 2.2608688324572314e-71, 2.6617645198762597e-69, 2.8038024736345674e-67, 2.6521234350652613e-65, 2.2603869398967457e-63, 1.7413601437152754e-61, 1.2161701083247541e-59, 7.7214787759599970e-58, 4.4681959655564470e-56, 2.3623580471674404e-54, 1.1437576644069702e-52, 5.0819691921164956e-51, 2.0764486091263794e-49, 7.8168818968667932e-48, 2.7161609526051418e-46, 8.7263192332605962e-45, 2.5963610791198993e-43, 7.1651564650842932e-42, 1.8367370768736730e-40, 4.3795689659428445e-39, 9.7263842188046952e-38, 2.0144288376257676e-36, 3.8953956971431042e-35, 7.0411654624671892e-34, 1.1909731529300876e-32, 1.8870059773886237e-31, 2.8034152482012231e-30, 3.9088957466494064e-29, 5.1199371899987404e-28, 6.3051173258996659e-27, 7.3062988441733997e-26, 7.9729602997232079e-25, 8.1994951837475763e-24, 7.9526775811935095e-23, 7.2794477168595113e-22, 6.2925924422563063e-21, 5.1402243977739270e-20, 3.9702645520078747e-19, 2.9013105636885269e-18, 2.0070043240260125e-17, 1.3149628048888219e-16, 8.1641639956286359e-16, 4.8056898389707300e-15, 2.6831763736632487e-14, 1.4216321504480736e-13, 7.1508314522575616e-13, 3.4161417919950439e-12, 1.5505876032631646e-11, 6.6896188793649314e-11, 2.7441476023994389e-10, 1.0706905991113023e-09, 3.9747846429602356e-09, 1.4044052119190546e-08, 4.7242215798796869e-08, 1.5133894631903387e-07, 4.6181858824280925e-07, 1.3427778873836719e-06, 3.7209613424878082e-06, 9.8293533546629111e-06, 2.4757612288389546e-05, 5.9469805842774389e-05, 1.3626145195379436e-04, 2.9786395909886146e-04, 6.2130683688573309e-04, 1.2368227283931328e-03, 2.3501040099770882e-03, 4.2629032262842719e-03, 7.3827553287034008e-03, 1.2208924001688722e-02, 1.9280976823883154e-02, 2.9081432020399377e-02, 4.1896299298471870e-02, 5.7655710815363609e-02, 7.5795804675644604e-02, 9.5193937891141694e-02, 1.1422353375366404e-01, 1.3094856577352781e-01, 1.4343569727181574e-01, 1.5011822522474477e-01, 1.5011822522474477e-01, 1.4343569727181574e-01, 1.3094856577352781e-01, 1.1422353375366404e-01, 9.5193937891141694e-02, 7.5795804675644604e-02, 5.7655710815363609e-02, 4.1896299298471870e-02, 2.9081432020399377e-02, 1.9280976823883154e-02, 1.2208924001688722e-02, 7.3827553287034008e-03, 4.2629032262842719e-03, 2.3501040099770882e-03, 1.2368227283931328e-03, 6.2130683688573309e-04, 2.9786395909886146e-04, 1.3626145195379436e-04, 5.9469805842774389e-05, 2.4757612288389546e-05, 9.8293533546629111e-06, 3.7209613424878082e-06, 1.3427778873836719e-06, 4.6181858824280925e-07, 1.5133894631903387e-07, 4.7242215798796869e-08, 1.4044052119190546e-08, 3.9747846429602356e-09, 1.0706905991113023e-09, 2.7441476023994389e-10, 6.6896188793649314e-11, 1.5505876032631646e-11, 3.4161417919950439e-12, 7.1508314522575616e-13, 1.4216321504480736e-13, 2.6831763736632487e-14, 4.8056898389707300e-15, 8.1641639956286359e-16, 1.3149628048888219e-16, 2.0070043240260125e-17, 2.9013105636885269e-18, 3.9702645520078747e-19, 5.1402243977739270e-20, 6.2925924422563063e-21, 7.2794477168595113e-22, 7.9526775811935095e-23, 8.1994951837475763e-24, 7.9729602997232079e-25, 7.3062988441733997e-26, 6.3051173258996659e-27, 5.1199371899987404e-28, 3.9088957466494064e-29, 2.8034152482012231e-30, 1.8870059773886237e-31, 1.1909731529300876e-32, 7.0411654624671892e-34, 3.8953956971431042e-35, 2.0144288376257676e-36, 9.7263842188046952e-38, 4.3795689659428445e-39, 1.8367370768736730e-40, 7.1651564650842932e-42, 2.5963610791198993e-43, 8.7263192332605962e-45, 2.7161609526051418e-46, 7.8168818968667932e-48, 2.0764486091263794e-49, 5.0819691921164956e-51, 1.1437576644069702e-52, 2.3623580471674404e-54, 4.4681959655564470e-56, 7.7214787759599970e-58, 1.2161701083247541e-59, 1.7413601437152754e-61, 2.2603869398967457e-63, 2.6521234350652613e-65, 2.8038024736345674e-67, 2.6617645198762597e-69, 2.2608688324572314e-71, 1.7114200608857651e-73, 1.1496573365594917e-75, 6.8220148646876484e-78, 3.5581101139323407e-80, 1.6222763835321407e-82, 6.4275556938243753e-85, 2.1986159587286647e-87, 6.4463886647737192e-90, 1.6073077596553874e-92, 3.3780606107607827e-95, 5.9257988910096090e-98, 8.5810245129266594e-101, 1.0130358260780602e-103, 9.6125997143450870e-107, 7.2131362796894811e-110, 4.2005766103289114e-113, 1.8572077169453742e-116, 6.0746030482858092e-120, 1.4249650100034198e-123, 2.3085411036710099e-127, 2.4650950171742754e-131, 1.6353340891378212e-135, 6.2404773612052171e-140, 1.2347606047124676e-144, 1.0940903755394791e-149, 3.4828172461418377e-155, 2.7698274929964049e-161, 2.7466189949527236e-168, 5.7186844211118222e-177}, + }, + { + n: 217, + x: []float64{-2.0180280152078982e+01, -1.9671145428267970e+01, -1.9252396116029669e+01, -1.8880837640701767e+01, -1.8539959593913657e+01, -1.8221250688860252e+01, -1.7919604408706316e+01, -1.7631655968298805e+01, -1.7355041415469405e+01, -1.7088020370809854e+01, -1.6829264937408070e+01, -1.6577732962488266e+01, -1.6332587652172350e+01, -1.6093144292573264e+01, -1.5858833637952957e+01, -1.5629175980464554e+01, -1.5403762307923412e+01, -1.5182240306661464e+01, -1.4964303762199654e+01, -1.4749684396618285e+01, -1.4538145488075983e+01, -1.4329476816694543e+01, -1.4123490613100632e+01, -1.3920018275613611e+01, -1.3718907684195138e+01, -1.3520020983073742e+01, -1.3323232735334253e+01, -1.3128428375570619e+01, -1.2935502903505391e+01, -1.2744359774012816e+01, -1.2554909948437734e+01, -1.2367071079310476e+01, -1.2180766806106346e+01, -1.1995926144008331e+01, -1.1812482951007951e+01, -1.1630375461345015e+01, -1.1449545875407471e+01, -1.1269939997911081e+01, -1.1091506917547994e+01, -1.0914198722404091e+01, -1.0737970246351363e+01, -1.0562778842365235e+01, -1.0388584179329960e+01, -1.0215348059403579e+01, -1.0043034253437085e+01, -9.8716083522966080e+00, -9.7010376322345699e+00, -9.5312909327068294e+00, -9.3623385452449437e+00, -9.1941521121732386e+00, -9.0267045341142556e+00, -8.8599698853577831e+00, -8.6939233362816957e+00, -8.5285410821102356e+00, -8.3638002773794167e+00, -8.1996789755519419e+00, -8.0361560732874953e+00, -7.8732112589291026e+00, -7.7108249648145373e+00, -7.5489783230637100e+00, -7.3876531245300106e+00, -7.2268317806359086e+00, -7.0664972878418659e+00, -6.9066331945227768e+00, -6.7472235700485381e+00, -6.5882529758852613e+00, -6.4297064385510465e+00, -6.2715694242761426e+00, -6.1138278152311072e+00, -5.9564678871991967e+00, -5.7994762885802258e+00, -5.6428400206233480e+00, -5.4865464187949282e+00, -5.3305831351959538e+00, -5.1749381219506319e+00, -5.0195996154942355e+00, -4.8645561216944264e+00, -4.7097964017452645e+00, -4.5553094587783480e+00, -4.4010845251394572e+00, -4.2471110502834843e+00, -4.0933786892435746e+00, -3.9398772916341032e+00, -3.7865968911497059e+00, -3.6335276955255318e+00, -3.4806600769262501e+00, -3.3279845627335654e+00, -3.1754918267040755e+00, -3.0231726804711898e+00, -2.8710180653663722e+00, -2.7190190445367941e+00, -2.5671667953376018e+00, -2.4154526019785036e+00, -2.2638678484054164e+00, -2.1124040113990956e+00, -1.9610526538735082e+00, -1.8098054183577674e+00, -1.6586540206460576e+00, -1.5075902436008417e+00, -1.3566059310952046e+00, -1.2056929820809235e+00, -1.0548433447690717e+00, -9.0404901091087708e-01, -7.5330201016646747e-01, -6.0259440454997382e-01, -4.5191828293935077e-01, -3.0126575563983427e-01, -1.5062894899007009e-01, 7.9851131193273576e-15, 1.5062894899007009e-01, 3.0126575563983427e-01, 4.5191828293935077e-01, 6.0259440454997382e-01, 7.5330201016646747e-01, 9.0404901091087708e-01, 1.0548433447690717e+00, 1.2056929820809235e+00, 1.3566059310952046e+00, 1.5075902436008417e+00, 1.6586540206460576e+00, 1.8098054183577674e+00, 1.9610526538735082e+00, 2.1124040113990956e+00, 2.2638678484054164e+00, 2.4154526019785036e+00, 2.5671667953376018e+00, 2.7190190445367941e+00, 2.8710180653663722e+00, 3.0231726804711898e+00, 3.1754918267040755e+00, 3.3279845627335654e+00, 3.4806600769262501e+00, 3.6335276955255318e+00, 3.7865968911497059e+00, 3.9398772916341032e+00, 4.0933786892435746e+00, 4.2471110502834843e+00, 4.4010845251394572e+00, 4.5553094587783480e+00, 4.7097964017452645e+00, 4.8645561216944264e+00, 5.0195996154942355e+00, 5.1749381219506319e+00, 5.3305831351959538e+00, 5.4865464187949282e+00, 5.6428400206233480e+00, 5.7994762885802258e+00, 5.9564678871991967e+00, 6.1138278152311072e+00, 6.2715694242761426e+00, 6.4297064385510465e+00, 6.5882529758852613e+00, 6.7472235700485381e+00, 6.9066331945227768e+00, 7.0664972878418659e+00, 7.2268317806359086e+00, 7.3876531245300106e+00, 7.5489783230637100e+00, 7.7108249648145373e+00, 7.8732112589291026e+00, 8.0361560732874953e+00, 8.1996789755519419e+00, 8.3638002773794167e+00, 8.5285410821102356e+00, 8.6939233362816957e+00, 8.8599698853577831e+00, 9.0267045341142556e+00, 9.1941521121732386e+00, 9.3623385452449437e+00, 9.5312909327068294e+00, 9.7010376322345699e+00, 9.8716083522966080e+00, 1.0043034253437085e+01, 1.0215348059403579e+01, 1.0388584179329960e+01, 1.0562778842365235e+01, 1.0737970246351363e+01, 1.0914198722404091e+01, 1.1091506917547994e+01, 1.1269939997911081e+01, 1.1449545875407471e+01, 1.1630375461345015e+01, 1.1812482951007951e+01, 1.1995926144008331e+01, 1.2180766806106346e+01, 1.2367071079310476e+01, 1.2554909948437734e+01, 1.2744359774012816e+01, 1.2935502903505391e+01, 1.3128428375570619e+01, 1.3323232735334253e+01, 1.3520020983073742e+01, 1.3718907684195138e+01, 1.3920018275613611e+01, 1.4123490613100632e+01, 1.4329476816694543e+01, 1.4538145488075983e+01, 1.4749684396618285e+01, 1.4964303762199654e+01, 1.5182240306661464e+01, 1.5403762307923412e+01, 1.5629175980464554e+01, 1.5858833637952957e+01, 1.6093144292573264e+01, 1.6332587652172350e+01, 1.6577732962488266e+01, 1.6829264937408070e+01, 1.7088020370809854e+01, 1.7355041415469405e+01, 1.7631655968298805e+01, 1.7919604408706316e+01, 1.8221250688860252e+01, 1.8539959593913657e+01, 1.8880837640701767e+01, 1.9252396116029669e+01, 1.9671145428267970e+01, 2.0180280152078982e+01}, + w: []float64{8.0790134837724204e-178, 4.0123708332001955e-169, 4.1608342695810454e-162, 5.3647010323313458e-156, 1.7249035730335862e-150, 1.9898962894711550e-145, 1.0270178951244021e-140, 2.7462859803070011e-136, 4.2216443703754674e-132, 4.0296773344706320e-128, 2.5341526783446447e-124, 1.1002243777181162e-120, 3.4246772430261828e-117, 7.8839348684832184e-114, 1.3776135348531781e-110, 1.8677560466742519e-107, 2.0021556471031417e-104, 1.7247770196475562e-101, 1.2111464936797437e-98, 7.0196501028640057e-96, 3.3954234881610162e-93, 1.3842435843570204e-90, 4.7985036069815231e-88, 1.4256947701704702e-85, 3.6567711491235357e-83, 8.1499750643585127e-81, 1.5877740343548737e-78, 2.7187040652791320e-76, 4.1119602314337377e-74, 5.5188731969772834e-72, 6.6010643664052121e-70, 7.0639875689587789e-68, 6.7880577161215916e-66, 5.8772891020073188e-64, 4.5996045356018730e-62, 3.2633290432137694e-60, 2.1047497049395128e-58, 1.2372745780617511e-56, 6.6453150452727337e-55, 3.2684621263244055e-53, 1.4753196845067616e-51, 6.1238771021510087e-50, 2.3420591906941631e-48, 8.2677634302135741e-47, 2.6986236644096577e-45, 8.1576808396884509e-44, 2.2873393442828659e-42, 5.9575720207549899e-41, 1.4433986536815081e-39, 3.2572816931648467e-38, 6.8552334632687487e-37, 1.3471217671214917e-35, 2.4745963539025701e-34, 4.2538970187949130e-33, 6.8502295544213803e-32, 1.0344007225282243e-30, 1.4660497224001333e-29, 1.9519881038552925e-28, 2.4437079996027598e-27, 2.8788818637419581e-26, 3.1940663724110344e-25, 3.3399348780894923e-24, 3.2939758359327470e-23, 3.0661414593245886e-22, 2.6955142404467904e-21, 2.2394681775190790e-20, 1.7594079537257698e-19, 1.3078564789171130e-18, 9.2038260248200122e-18, 6.1351365453804107e-17, 3.8757039748543155e-16, 2.3214598330581677e-15, 1.3190482037051148e-14, 7.1128747627508331e-14, 3.6416855631427732e-13, 1.7709744825377116e-12, 8.1836457113383607e-12, 3.5947660428421198e-11, 1.5015547963310099e-10, 5.9663534866912190e-10, 2.2558892777245505e-09, 8.1190427548544262e-09, 2.7822813440253852e-08, 9.0809483027322313e-08, 2.8236711509871372e-07, 8.3668655155751835e-07, 2.3631134387385760e-06, 6.3632839492173400e-06, 1.6339902252008705e-05, 4.0020290652701539e-05, 9.3510362001206373e-05, 2.0848221478522648e-04, 4.4359250162546185e-04, 9.0090002804434576e-04, 1.7466777765574378e-03, 3.2333646918818863e-03, 5.7155709629331409e-03, 9.6489576482962046e-03, 1.5558416546311961e-02, 2.3963959563684092e-02, 3.5261402555428784e-02, 4.9570551047913969e-02, 6.6582815385485522e-02, 8.5455825791019971e-02, 1.0480572103134121e-01, 1.2283174514792664e-01, 1.3757292020567533e-01, 1.4725235676872742e-01, 1.5062763955757250e-01, 1.4725235676872742e-01, 1.3757292020567533e-01, 1.2283174514792664e-01, 1.0480572103134121e-01, 8.5455825791019971e-02, 6.6582815385485522e-02, 4.9570551047913969e-02, 3.5261402555428784e-02, 2.3963959563684092e-02, 1.5558416546311961e-02, 9.6489576482962046e-03, 5.7155709629331409e-03, 3.2333646918818863e-03, 1.7466777765574378e-03, 9.0090002804434576e-04, 4.4359250162546185e-04, 2.0848221478522648e-04, 9.3510362001206373e-05, 4.0020290652701539e-05, 1.6339902252008705e-05, 6.3632839492173400e-06, 2.3631134387385760e-06, 8.3668655155751835e-07, 2.8236711509871372e-07, 9.0809483027322313e-08, 2.7822813440253852e-08, 8.1190427548544262e-09, 2.2558892777245505e-09, 5.9663534866912190e-10, 1.5015547963310099e-10, 3.5947660428421198e-11, 8.1836457113383607e-12, 1.7709744825377116e-12, 3.6416855631427732e-13, 7.1128747627508331e-14, 1.3190482037051148e-14, 2.3214598330581677e-15, 3.8757039748543155e-16, 6.1351365453804107e-17, 9.2038260248200122e-18, 1.3078564789171130e-18, 1.7594079537257698e-19, 2.2394681775190790e-20, 2.6955142404467904e-21, 3.0661414593245886e-22, 3.2939758359327470e-23, 3.3399348780894923e-24, 3.1940663724110344e-25, 2.8788818637419581e-26, 2.4437079996027598e-27, 1.9519881038552925e-28, 1.4660497224001333e-29, 1.0344007225282243e-30, 6.8502295544213803e-32, 4.2538970187949130e-33, 2.4745963539025701e-34, 1.3471217671214917e-35, 6.8552334632687487e-37, 3.2572816931648467e-38, 1.4433986536815081e-39, 5.9575720207549899e-41, 2.2873393442828659e-42, 8.1576808396884509e-44, 2.6986236644096577e-45, 8.2677634302135741e-47, 2.3420591906941631e-48, 6.1238771021510087e-50, 1.4753196845067616e-51, 3.2684621263244055e-53, 6.6453150452727337e-55, 1.2372745780617511e-56, 2.1047497049395128e-58, 3.2633290432137694e-60, 4.5996045356018730e-62, 5.8772891020073188e-64, 6.7880577161215916e-66, 7.0639875689587789e-68, 6.6010643664052121e-70, 5.5188731969772834e-72, 4.1119602314337377e-74, 2.7187040652791320e-76, 1.5877740343548737e-78, 8.1499750643585127e-81, 3.6567711491235357e-83, 1.4256947701704702e-85, 4.7985036069815231e-88, 1.3842435843570204e-90, 3.3954234881610162e-93, 7.0196501028640057e-96, 1.2111464936797437e-98, 1.7247770196475562e-101, 2.0021556471031417e-104, 1.8677560466742519e-107, 1.3776135348531781e-110, 7.8839348684832184e-114, 3.4246772430261828e-117, 1.1002243777181162e-120, 2.5341526783446447e-124, 4.0296773344706320e-128, 4.2216443703754674e-132, 2.7462859803070011e-136, 1.0270178951244021e-140, 1.9898962894711550e-145, 1.7249035730335862e-150, 5.3647010323313458e-156, 4.1608342695810454e-162, 4.0123708332001955e-169, 8.0790134837724204e-178}, + }, + + { + n: 218, + x: []float64{-2.0228695170577915e+01, -1.9719963830858333e+01, -1.9301552400253843e+01, -1.8930298474919816e+01, -1.8589703851801165e+01, -1.8271263496827501e+01, -1.7969874624529179e+01, -1.7682174897106314e+01, -1.7405802075069708e+01, -1.7139017035820078e+01, -1.6880492838899503e+01, -1.6629188080724916e+01, -1.6384266568226192e+01, -1.6145044078855118e+01, -1.5910951775414047e+01, -1.5681510294638914e+01, -1.5456310918627016e+01, -1.5235001587812036e+01, -1.5017276309282583e+01, -1.4802867000027815e+01, -1.4591537111039028e+01, -1.4383076576817141e+01, -1.4177297766812716e+01, -1.3974032204957940e+01, -1.3773127885530926e+01, -1.3574447057358521e+01, -1.3377864379717227e+01, -1.3183265376084384e+01, -1.2990545128683925e+01, -1.2799607169295788e+01, -1.2610362531246457e+01, -1.2422728934700823e+01, -1.2236630082919943e+01, -1.2051995051456386e+01, -1.1868757755632400e+01, -1.1686856484310367e+01, -1.1506233490083723e+01, -1.1326834627713886e+01, -1.1148609034007171e+01, -1.0971508843435563e+01, -1.0795488934711024e+01, -1.0620506704266159e+01, -1.0446521863206758e+01, -1.0273496254809785e+01, -1.0101393690063306e+01, -9.9301797990985268e+00, -9.7598218966614141e+00, -9.5902888600219054e+00, -9.4215510179308293e+00, -9.2535800494152092e+00, -9.0863488913560904e+00, -8.9198316539249092e+00, -8.7540035430671104e+00, -8.5888407893192067e+00, -8.4243205823293916e+00, -8.2604210105245137e+00, -8.0971210054295799e+00, -7.9344002902008972e+00, -7.7722393319820444e+00, -7.6106192977338623e+00, -7.4495220132267015e+00, -7.2889299249154647e+00, -7.1288260644465895e+00, -6.9691940155714960e+00, -6.8100178832631793e+00, -6.6512822648525844e+00, -6.4929722230189020e+00, -6.3350732604836884e+00, -6.1775712962725331e+00, -6.0204526434206276e+00, -5.8637039880096422e+00, -5.7073123694332661e+00, -5.5512651617979705e+00, -5.3955500563732679e+00, -5.2401550450133421e+00, -5.0850684044781733e+00, -4.9302786815884012e+00, -4.7757746791533817e+00, -4.6215454426166902e+00, -4.4675802473678914e+00, -4.3138685866729931e+00, -4.1604001601800418e+00, -4.0071648629591818e+00, -3.8541527750397258e+00, -3.7013541514093888e+00, -3.5487594124432715e+00, -3.3963591347324886e+00, -3.2441440422843915e+00, -3.0921049980680149e+00, -2.9402329958803848e+00, -2.7885191525106028e+00, -2.6369547001801932e+00, -2.4855309792393636e+00, -2.3342394311001944e+00, -2.1830715913886820e+00, -2.0320190832985223e+00, -1.8810736111306099e+00, -1.7302269540027844e+00, -1.5794709597152470e+00, -1.4287975387577758e+00, -1.2781986584451195e+00, -1.1276663371680935e+00, -9.7719263874768358e-01, -8.2676966688043974e-01, -6.7638955966349490e-01, -5.2604448418800387e-01, -3.7572663118998539e-01, -2.2542820974780486e-01, -7.5141442015907556e-02, 7.5141442015907556e-02, 2.2542820974780486e-01, 3.7572663118998539e-01, 5.2604448418800387e-01, 6.7638955966349490e-01, 8.2676966688043974e-01, 9.7719263874768358e-01, 1.1276663371680935e+00, 1.2781986584451195e+00, 1.4287975387577758e+00, 1.5794709597152470e+00, 1.7302269540027844e+00, 1.8810736111306099e+00, 2.0320190832985223e+00, 2.1830715913886820e+00, 2.3342394311001944e+00, 2.4855309792393636e+00, 2.6369547001801932e+00, 2.7885191525106028e+00, 2.9402329958803848e+00, 3.0921049980680149e+00, 3.2441440422843915e+00, 3.3963591347324886e+00, 3.5487594124432715e+00, 3.7013541514093888e+00, 3.8541527750397258e+00, 4.0071648629591818e+00, 4.1604001601800418e+00, 4.3138685866729931e+00, 4.4675802473678914e+00, 4.6215454426166902e+00, 4.7757746791533817e+00, 4.9302786815884012e+00, 5.0850684044781733e+00, 5.2401550450133421e+00, 5.3955500563732679e+00, 5.5512651617979705e+00, 5.7073123694332661e+00, 5.8637039880096422e+00, 6.0204526434206276e+00, 6.1775712962725331e+00, 6.3350732604836884e+00, 6.4929722230189020e+00, 6.6512822648525844e+00, 6.8100178832631793e+00, 6.9691940155714960e+00, 7.1288260644465895e+00, 7.2889299249154647e+00, 7.4495220132267015e+00, 7.6106192977338623e+00, 7.7722393319820444e+00, 7.9344002902008972e+00, 8.0971210054295799e+00, 8.2604210105245137e+00, 8.4243205823293916e+00, 8.5888407893192067e+00, 8.7540035430671104e+00, 8.9198316539249092e+00, 9.0863488913560904e+00, 9.2535800494152092e+00, 9.4215510179308293e+00, 9.5902888600219054e+00, 9.7598218966614141e+00, 9.9301797990985268e+00, 1.0101393690063306e+01, 1.0273496254809785e+01, 1.0446521863206758e+01, 1.0620506704266159e+01, 1.0795488934711024e+01, 1.0971508843435563e+01, 1.1148609034007171e+01, 1.1326834627713886e+01, 1.1506233490083723e+01, 1.1686856484310367e+01, 1.1868757755632400e+01, 1.2051995051456386e+01, 1.2236630082919943e+01, 1.2422728934700823e+01, 1.2610362531246457e+01, 1.2799607169295788e+01, 1.2990545128683925e+01, 1.3183265376084384e+01, 1.3377864379717227e+01, 1.3574447057358521e+01, 1.3773127885530926e+01, 1.3974032204957940e+01, 1.4177297766812716e+01, 1.4383076576817141e+01, 1.4591537111039028e+01, 1.4802867000027815e+01, 1.5017276309282583e+01, 1.5235001587812036e+01, 1.5456310918627016e+01, 1.5681510294638914e+01, 1.5910951775414047e+01, 1.6145044078855118e+01, 1.6384266568226192e+01, 1.6629188080724916e+01, 1.6880492838899503e+01, 1.7139017035820078e+01, 1.7405802075069708e+01, 1.7682174897106314e+01, 1.7969874624529179e+01, 1.8271263496827501e+01, 1.8589703851801165e+01, 1.8930298474919816e+01, 1.9301552400253843e+01, 1.9719963830858333e+01, 2.0228695170577915e+01}, + w: []float64{1.1412038714903467e-178, 5.8600364276414301e-170, 6.2483530291970031e-163, 8.2600389517381484e-157, 2.7180946943728827e-151, 3.2050447674896954e-146, 1.6891299829881347e-141, 4.6087117363873922e-137, 7.2242769320344098e-133, 7.0281073750791237e-129, 4.5026465211632589e-125, 1.9907761957745900e-121, 6.3085296819235091e-118, 1.4780807064034936e-114, 2.6279883692096037e-111, 3.6246331337631131e-108, 3.9519127727199950e-105, 3.4620642776922925e-102, 2.4718758245223020e-99, 1.4565168188237643e-96, 7.1616419809360768e-94, 2.9675903948483656e-91, 1.0455125036940855e-88, 3.1567897170935801e-86, 8.2277370866559977e-84, 1.8632623782187992e-81, 3.6882177983197069e-79, 6.4162031293430147e-77, 9.8590364210588088e-75, 1.3442782637610740e-72, 1.6333988316711487e-70, 1.7756459769101764e-68, 1.7332892347041021e-66, 1.5244548820160086e-64, 1.2118948225793116e-62, 8.7339153184655864e-61, 5.7220382749093667e-59, 3.4167937984322514e-57, 1.8641137908561576e-55, 9.3133897167275065e-54, 4.2703424814876432e-52, 1.8006175119892686e-50, 6.9955013175656585e-49, 2.5086717527911961e-47, 8.3184624948029151e-46, 2.5546048751257637e-44, 7.2770684318833216e-43, 1.9256515369002052e-41, 4.7401499620934791e-40, 1.0868621062998897e-38, 2.3241907456347607e-37, 4.6409284690005433e-36, 8.6630347696542139e-35, 1.5133539937177412e-33, 2.4766678429636503e-32, 3.8008678166597364e-31, 5.4751646602962371e-30, 7.4097643192715769e-29, 9.4293221065635326e-28, 1.1292370018541933e-26, 1.2736861289852883e-25, 1.3540721404735189e-24, 1.3578087095789605e-23, 1.2851527881373697e-22, 1.1488929806753338e-21, 9.7071144039920359e-21, 7.7562537574525747e-20, 5.8643464026904450e-19, 4.1979458289914584e-18, 2.8466716026161652e-17, 1.8295539696950399e-16, 1.1150004956688747e-15, 6.4466274804790879e-15, 3.5376499268729578e-14, 1.8433622668090456e-13, 9.1243282637242511e-13, 4.2919888935314847e-12, 1.9193290587578772e-11, 8.1626646177788407e-11, 3.3026130822100178e-10, 1.2716614885102940e-09, 4.6613505196508951e-09, 1.6270858113762294e-08, 5.4099533071374670e-08, 1.7138819219313466e-07, 5.1747190361086424e-07, 1.4894285947831174e-06, 4.0877345728852175e-06, 1.0699746166171350e-05, 2.6716804837681635e-05, 6.3650699225936851e-05, 1.4471442394637491e-04, 3.1404212609163355e-04, 6.5058509971884274e-04, 1.2868513657693481e-03, 2.4306591608453860e-03, 4.3848013160776717e-03, 7.5554485133504786e-03, 1.2436693679604333e-02, 1.9558227968032915e-02, 2.9388347600235249e-02, 4.2196739277833864e-02, 5.7899315166709715e-02, 7.5925444911783990e-02, 9.5157950558542009e-02, 1.1399005091049424e-01, 1.3051762867943345e-01, 1.4284462872400217e-01, 1.4943738595687683e-01, 1.4943738595687683e-01, 1.4284462872400217e-01, 1.3051762867943345e-01, 1.1399005091049424e-01, 9.5157950558542009e-02, 7.5925444911783990e-02, 5.7899315166709715e-02, 4.2196739277833864e-02, 2.9388347600235249e-02, 1.9558227968032915e-02, 1.2436693679604333e-02, 7.5554485133504786e-03, 4.3848013160776717e-03, 2.4306591608453860e-03, 1.2868513657693481e-03, 6.5058509971884274e-04, 3.1404212609163355e-04, 1.4471442394637491e-04, 6.3650699225936851e-05, 2.6716804837681635e-05, 1.0699746166171350e-05, 4.0877345728852175e-06, 1.4894285947831174e-06, 5.1747190361086424e-07, 1.7138819219313466e-07, 5.4099533071374670e-08, 1.6270858113762294e-08, 4.6613505196508951e-09, 1.2716614885102940e-09, 3.3026130822100178e-10, 8.1626646177788407e-11, 1.9193290587578772e-11, 4.2919888935314847e-12, 9.1243282637242511e-13, 1.8433622668090456e-13, 3.5376499268729578e-14, 6.4466274804790879e-15, 1.1150004956688747e-15, 1.8295539696950399e-16, 2.8466716026161652e-17, 4.1979458289914584e-18, 5.8643464026904450e-19, 7.7562537574525747e-20, 9.7071144039920359e-21, 1.1488929806753338e-21, 1.2851527881373697e-22, 1.3578087095789605e-23, 1.3540721404735189e-24, 1.2736861289852883e-25, 1.1292370018541933e-26, 9.4293221065635326e-28, 7.4097643192715769e-29, 5.4751646602962371e-30, 3.8008678166597364e-31, 2.4766678429636503e-32, 1.5133539937177412e-33, 8.6630347696542139e-35, 4.6409284690005433e-36, 2.3241907456347607e-37, 1.0868621062998897e-38, 4.7401499620934791e-40, 1.9256515369002052e-41, 7.2770684318833216e-43, 2.5546048751257637e-44, 8.3184624948029151e-46, 2.5086717527911961e-47, 6.9955013175656585e-49, 1.8006175119892686e-50, 4.2703424814876432e-52, 9.3133897167275065e-54, 1.8641137908561576e-55, 3.4167937984322514e-57, 5.7220382749093667e-59, 8.7339153184655864e-61, 1.2118948225793116e-62, 1.5244548820160086e-64, 1.7332892347041021e-66, 1.7756459769101764e-68, 1.6333988316711487e-70, 1.3442782637610740e-72, 9.8590364210588088e-75, 6.4162031293430147e-77, 3.6882177983197069e-79, 1.8632623782187992e-81, 8.2277370866559977e-84, 3.1567897170935801e-86, 1.0455125036940855e-88, 2.9675903948483656e-91, 7.1616419809360768e-94, 1.4565168188237643e-96, 2.4718758245223020e-99, 3.4620642776922925e-102, 3.9519127727199950e-105, 3.6246331337631131e-108, 2.6279883692096037e-111, 1.4780807064034936e-114, 6.3085296819235091e-118, 1.9907761957745900e-121, 4.5026465211632589e-125, 7.0281073750791237e-129, 7.2242769320344098e-133, 4.6087117363873922e-137, 1.6891299829881347e-141, 3.2050447674896954e-146, 2.7180946943728827e-151, 8.2600389517381484e-157, 6.2483530291970031e-163, 5.8600364276414301e-170, 1.1412038714903467e-178}, + }, + { + n: 219, + x: []float64{-2.0276997908046905e+01, -1.9768667748260523e+01, -1.9350592328749663e+01, -1.8979641248255188e+01, -1.8639328445512675e+01, -1.8321155106754730e+01, -1.8020022158568153e+01, -1.7732569697856896e+01, -1.7456437188959409e+01, -1.7189886759582706e+01, -1.6931592420762687e+01, -1.6680513514209245e+01, -1.6435814444517028e+01, -1.6196811477889465e+01, -1.5962936183500821e+01, -1.5733709540823362e+01, -1.5508723124641774e+01, -1.5287625128097030e+01, -1.5070109778611977e+01, -1.4855909186982135e+01, -1.4644786976036578e+01, -1.4436533233749541e+01, -1.4230960467563948e+01, -1.4027900326255610e+01, -1.3827200917702472e+01, -1.3628724594657513e+01, -1.3432346111954516e+01, -1.3237951081351927e+01, -1.3045434667000123e+01, -1.2854700477033081e+01, -1.2665659616227074e+01, -1.2478229871866438e+01, -1.2292335010497055e+01, -1.2107904167551959e+01, -1.1924871315204850e+01, -1.1743174796469416e+01, -1.1562756915679721e+01, -1.1383563577182978e+01, -1.1205543965443459e+01, -1.1028650260865531e+01, -1.0852837386548828e+01, -1.0678062781931233e+01, -1.0504286199887655e+01, -1.0331469524360219e+01, -1.0159576606018058e+01, -9.9885731137985694e+00, -9.8184264004786943e+00, -9.6491053806754916e+00, -9.4805804198871506e+00, -9.3128232333657657e+00, -9.1458067937670240e+00, -8.9795052466532344e+00, -8.8138938330391774e+00, -8.6489488182673355e+00, -8.4846474265831215e+00, -8.3209677808533336e+00, -8.1578888469343305e+00, -7.9953903822513528e+00, -7.8334528881984324e+00, -7.6720575660104693e+00, -7.5111862757957555e+00, -7.3508214984498235e+00, -7.1909463001999656e+00, -7.0315442995549828e+00, -6.8725996364571813e+00, -6.7140969434532645e+00, -6.5560213187184688e+00, -6.3983583007839497e+00, -6.2410938448312283e+00, -6.0842143004302391e+00, -5.9277063906083614e+00, -5.7715571921480873e+00, -5.6157541170197165e+00, -5.4602848948636904e+00, -5.3051375564443513e+00, -5.1503004180034342e+00, -4.9957620664475568e+00, -4.8415113453092564e+00, -4.6875373414259709e+00, -4.5338293722856466e+00, -4.3803769739918419e+00, -4.2271698898044328e+00, -4.0741980592156279e+00, -3.9214516075238026e+00, -3.7689208358703388e+00, -3.6165962117072561e+00, -3.4644683596654966e+00, -3.3125280527959076e+00, -3.1607662041567641e+00, -3.0091738587233952e+00, -2.8577421855969432e+00, -2.7064624704909552e+00, -2.5553261084754681e+00, -2.4043245969596510e+00, -2.2534495288951528e+00, -2.1026925861830650e+00, -1.9520455332686681e+00, -1.8015002109084974e+00, -1.6510485300954487e+00, -1.5006824661279821e+00, -1.3503940528101779e+00, -1.2001753767700742e+00, -1.0500185718839765e+00, -8.9991581379505270e-01, -7.4985931451474896e-01, -5.9984131709602384e-01, -4.4985409036765389e-01, -2.9988992371893503e-01, -1.4994112192465620e-01, 8.0217422708380516e-15, 1.4994112192465620e-01, 2.9988992371893503e-01, 4.4985409036765389e-01, 5.9984131709602384e-01, 7.4985931451474896e-01, 8.9991581379505270e-01, 1.0500185718839765e+00, 1.2001753767700742e+00, 1.3503940528101779e+00, 1.5006824661279821e+00, 1.6510485300954487e+00, 1.8015002109084974e+00, 1.9520455332686681e+00, 2.1026925861830650e+00, 2.2534495288951528e+00, 2.4043245969596510e+00, 2.5553261084754681e+00, 2.7064624704909552e+00, 2.8577421855969432e+00, 3.0091738587233952e+00, 3.1607662041567641e+00, 3.3125280527959076e+00, 3.4644683596654966e+00, 3.6165962117072561e+00, 3.7689208358703388e+00, 3.9214516075238026e+00, 4.0741980592156279e+00, 4.2271698898044328e+00, 4.3803769739918419e+00, 4.5338293722856466e+00, 4.6875373414259709e+00, 4.8415113453092564e+00, 4.9957620664475568e+00, 5.1503004180034342e+00, 5.3051375564443513e+00, 5.4602848948636904e+00, 5.6157541170197165e+00, 5.7715571921480873e+00, 5.9277063906083614e+00, 6.0842143004302391e+00, 6.2410938448312283e+00, 6.3983583007839497e+00, 6.5560213187184688e+00, 6.7140969434532645e+00, 6.8725996364571813e+00, 7.0315442995549828e+00, 7.1909463001999656e+00, 7.3508214984498235e+00, 7.5111862757957555e+00, 7.6720575660104693e+00, 7.8334528881984324e+00, 7.9953903822513528e+00, 8.1578888469343305e+00, 8.3209677808533336e+00, 8.4846474265831215e+00, 8.6489488182673355e+00, 8.8138938330391774e+00, 8.9795052466532344e+00, 9.1458067937670240e+00, 9.3128232333657657e+00, 9.4805804198871506e+00, 9.6491053806754916e+00, 9.8184264004786943e+00, 9.9885731137985694e+00, 1.0159576606018058e+01, 1.0331469524360219e+01, 1.0504286199887655e+01, 1.0678062781931233e+01, 1.0852837386548828e+01, 1.1028650260865531e+01, 1.1205543965443459e+01, 1.1383563577182978e+01, 1.1562756915679721e+01, 1.1743174796469416e+01, 1.1924871315204850e+01, 1.2107904167551959e+01, 1.2292335010497055e+01, 1.2478229871866438e+01, 1.2665659616227074e+01, 1.2854700477033081e+01, 1.3045434667000123e+01, 1.3237951081351927e+01, 1.3432346111954516e+01, 1.3628724594657513e+01, 1.3827200917702472e+01, 1.4027900326255610e+01, 1.4230960467563948e+01, 1.4436533233749541e+01, 1.4644786976036578e+01, 1.4855909186982135e+01, 1.5070109778611977e+01, 1.5287625128097030e+01, 1.5508723124641774e+01, 1.5733709540823362e+01, 1.5962936183500821e+01, 1.6196811477889465e+01, 1.6435814444517028e+01, 1.6680513514209245e+01, 1.6931592420762687e+01, 1.7189886759582706e+01, 1.7456437188959409e+01, 1.7732569697856896e+01, 1.8020022158568153e+01, 1.8321155106754730e+01, 1.8639328445512675e+01, 1.8979641248255188e+01, 1.9350592328749663e+01, 1.9768667748260523e+01, 2.0276997908046905e+01}, + w: []float64{1.6118004761490936e-179, 8.5565157993831952e-171, 9.3801386072360495e-164, 1.2712817065467470e-157, 4.2810879764792902e-152, 5.1593581306426363e-147, 2.7763562197121041e-142, 7.7287684331971630e-138, 1.2353061004428027e-133, 1.2247428452374434e-129, 7.9930519467022852e-126, 3.5986937020445443e-122, 1.1608863141459933e-118, 2.7680773700442792e-115, 5.0074481042562811e-112, 7.0254966797767812e-109, 7.7903695739499256e-106, 6.9398586398625168e-103, 5.0378132240927281e-100, 3.0176790544586562e-97, 1.5082063803644767e-94, 6.3518001539538009e-92, 2.2741855202923794e-89, 6.9776584966048747e-87, 1.8479046829051634e-84, 4.2518674704681371e-82, 8.5507393331426323e-80, 1.5112093165489227e-77, 2.3589639789454550e-75, 3.2673822149378061e-73, 4.0328590535463278e-71, 4.4532356700297110e-69, 4.4154958570004513e-67, 3.9446173154369991e-65, 3.1851636643508064e-63, 2.3315719656364080e-61, 1.5515360955581329e-59, 9.4102483913550526e-58, 5.2146771930312127e-56, 2.6462964683019027e-54, 1.2324622103285675e-52, 5.2785960684684324e-51, 2.0830950016909702e-49, 7.5881492915547110e-48, 2.5559164938518617e-46, 7.9735166177827294e-45, 2.3073707359625722e-43, 6.2027848314701266e-42, 1.5511852212359039e-40, 3.6134675099711877e-39, 7.8508422681776689e-38, 1.5928021832222874e-36, 3.0210523716429586e-35, 5.3626533220153980e-34, 8.9182314112122594e-33, 1.3908724042317442e-31, 2.0361886950192076e-30, 2.8006915544325587e-29, 3.6224809761826824e-28, 4.4096199762595120e-27, 5.0558656605721755e-26, 5.4641111784906703e-25, 5.5704394297442813e-24, 5.3605363007899914e-23, 4.8726597293407410e-22, 4.1864031729275524e-21, 3.4017282707064429e-20, 2.6157557992877646e-19, 1.9044895750724533e-18, 1.3136464708861073e-17, 8.5885898614439566e-17, 5.3250576372585674e-16, 3.1325104388327040e-15, 1.7491400171437906e-14, 9.2749216025525341e-14, 4.6723068181067832e-13, 2.2369795792044991e-12, 1.0182840690359900e-11, 4.4087115371635113e-11, 1.8161128736541464e-10, 7.1204644180465281e-10, 2.6579545759517285e-09, 9.4491700732305002e-09, 3.2001745961210195e-08, 1.0327820095258369e-07, 3.1769761704760471e-07, 9.3174969312259845e-07, 2.6059663547935113e-06, 6.9521878670475772e-06, 1.7695019387908094e-05, 4.2977984770344540e-05, 9.9630005120895210e-05, 2.2047640877838706e-04, 4.6583912781443418e-04, 9.3989854709223869e-04, 1.8111811218635974e-03, 3.3337948402502641e-03, 5.8622951858897081e-03, 9.8491710526776490e-03, 1.5811821288832947e-02, 2.4258117817844916e-02, 3.5568359860607475e-02, 4.9846708381161745e-02, 6.6773674520725357e-02, 8.5505952447471292e-02, 1.0467230074567024e-01, 1.2249815849737687e-01, 1.3705778627617005e-01, 1.4661020932556390e-01, 1.4993984211667696e-01, 1.4661020932556390e-01, 1.3705778627617005e-01, 1.2249815849737687e-01, 1.0467230074567024e-01, 8.5505952447471292e-02, 6.6773674520725357e-02, 4.9846708381161745e-02, 3.5568359860607475e-02, 2.4258117817844916e-02, 1.5811821288832947e-02, 9.8491710526776490e-03, 5.8622951858897081e-03, 3.3337948402502641e-03, 1.8111811218635974e-03, 9.3989854709223869e-04, 4.6583912781443418e-04, 2.2047640877838706e-04, 9.9630005120895210e-05, 4.2977984770344540e-05, 1.7695019387908094e-05, 6.9521878670475772e-06, 2.6059663547935113e-06, 9.3174969312259845e-07, 3.1769761704760471e-07, 1.0327820095258369e-07, 3.2001745961210195e-08, 9.4491700732305002e-09, 2.6579545759517285e-09, 7.1204644180465281e-10, 1.8161128736541464e-10, 4.4087115371635113e-11, 1.0182840690359900e-11, 2.2369795792044991e-12, 4.6723068181067832e-13, 9.2749216025525341e-14, 1.7491400171437906e-14, 3.1325104388327040e-15, 5.3250576372585674e-16, 8.5885898614439566e-17, 1.3136464708861073e-17, 1.9044895750724533e-18, 2.6157557992877646e-19, 3.4017282707064429e-20, 4.1864031729275524e-21, 4.8726597293407410e-22, 5.3605363007899914e-23, 5.5704394297442813e-24, 5.4641111784906703e-25, 5.0558656605721755e-26, 4.4096199762595120e-27, 3.6224809761826824e-28, 2.8006915544325587e-29, 2.0361886950192076e-30, 1.3908724042317442e-31, 8.9182314112122594e-33, 5.3626533220153980e-34, 3.0210523716429586e-35, 1.5928021832222874e-36, 7.8508422681776689e-38, 3.6134675099711877e-39, 1.5511852212359039e-40, 6.2027848314701266e-42, 2.3073707359625722e-43, 7.9735166177827294e-45, 2.5559164938518617e-46, 7.5881492915547110e-48, 2.0830950016909702e-49, 5.2785960684684324e-51, 1.2324622103285675e-52, 2.6462964683019027e-54, 5.2146771930312127e-56, 9.4102483913550526e-58, 1.5515360955581329e-59, 2.3315719656364080e-61, 3.1851636643508064e-63, 3.9446173154369991e-65, 4.4154958570004513e-67, 4.4532356700297110e-69, 4.0328590535463278e-71, 3.2673822149378061e-73, 2.3589639789454550e-75, 1.5112093165489227e-77, 8.5507393331426323e-80, 4.2518674704681371e-82, 1.8479046829051634e-84, 6.9776584966048747e-87, 2.2741855202923794e-89, 6.3518001539538009e-92, 1.5082063803644767e-94, 3.0176790544586562e-97, 5.0378132240927281e-100, 6.9398586398625168e-103, 7.7903695739499256e-106, 7.0254966797767812e-109, 5.0074481042562811e-112, 2.7680773700442792e-115, 1.1608863141459933e-118, 3.5986937020445443e-122, 7.9930519467022852e-126, 1.2247428452374434e-129, 1.2353061004428027e-133, 7.7287684331971630e-138, 2.7763562197121041e-142, 5.1593581306426363e-147, 4.2810879764792902e-152, 1.2712817065467470e-157, 9.3801386072360495e-164, 8.5565157993831952e-171, 1.6118004761490936e-179}, + }, + { + n: 220, + x: []float64{-2.0325189139629405e+01, -1.9817257977795947e+01, -1.9399516717870224e+01, -1.9028866794578029e+01, -1.8688834225534919e+01, -1.8370926385157830e+01, -1.8070047892967271e+01, -1.7782841268044042e+01, -1.7506947669788651e+01, -1.7240630469775191e+01, -1.6982564625621777e+01, -1.6731710220470223e+01, -1.6487232253468321e+01, -1.6248447477010238e+01, -1.6014787864496149e+01, -1.5785774736307584e+01, -1.5560999958339213e+01, -1.5340111975060188e+01, -1.5122805233008011e+01, -1.4908812035694833e+01, -1.4697896176804390e+01, -1.4489847896889446e+01, -1.4284479840564213e+01, -1.4081623780688842e+01, -1.3881127938034011e+01, -1.3682854768615876e+01, -1.3486679122200039e+01, -1.3292486698232523e+01, -1.3100172742223814e+01, -1.2909640938118768e+01, -1.2720802461619986e+01, -1.2533575166624548e+01, -1.2347882882470566e+01, -1.2163654803990811e+01, -1.1980824959739557e+01, -1.1799331746419007e+01, -1.1619117519647554e+01, -1.1440128232906956e+01, -1.1262313117871999e+01, -1.1085624400434606e+01, -1.0910017047638791e+01, -1.0735448541485018e+01, -1.0561878676174262e+01, -1.0389269375869560e+01, -1.0217584530474927e+01, -1.0046789847284987e+01, -9.8768527166552929e+00, -9.7077420900935678e+00, -9.5394283693840993e+00, -9.3718833055374660e+00, -9.2050799065113704e+00, -9.0389923527798217e+00, -8.8735959199405876e+00, -8.7088669076480283e+00, -8.5447825742424133e+00, -8.3813210765192689e+00, -8.2184614141456525e+00, -8.0561833782850805e+00, -7.8944675040409047e+00, -7.7332950263697580e+00, -7.5726478391539116e+00, -7.4125084571532707e+00, -7.2528599805868588e+00, -7.0936860621182607e+00, -6.9349708760424020e+00, -6.7766990894903305e+00, -6.6188558354865279e+00, -6.4614266877089035e+00, -6.3043976368153372e+00, -6.1477550682134519e+00, -5.9914857411611600e+00, -5.8355767690955807e+00, -5.6800156010969900e+00, -5.5247900044023472e+00, -5.3698880478903845e+00, -5.2152980864665599e+00, -5.0610087462822682e+00, -4.9070089107279511e+00, -4.7532877071444766e+00, -4.5998344942017342e+00, -4.4466388498971172e+00, -4.2936905601303739e+00, -4.1409796078143595e+00, -3.9884961624844180e+00, -3.8362305703715940e+00, -3.6841733449075362e+00, -3.5323151576310980e+00, -3.3806468294686467e+00, -3.2291593223621100e+00, -3.0778437312202702e+00, -2.9266912761707076e+00, -2.7756932950907438e+00, -2.6248412363975424e+00, -2.4741266520783536e+00, -2.3235411909430654e+00, -2.1730765920823036e+00, -2.0227246785151167e+00, -1.8724773510110999e+00, -1.7223265820726865e+00, -1.5722644100637477e+00, -1.4222829334715719e+00, -1.2723743052896335e+00, -1.1225307275089995e+00, -9.7274444570696528e-01, -8.2300774372149477e-01, -6.7331293840074014e-01, -5.2365237441695056e-01, -3.7401841913451778e-01, -2.2440345752197671e-01, -7.4799887098051757e-02, 7.4799887098051757e-02, 2.2440345752197671e-01, 3.7401841913451778e-01, 5.2365237441695056e-01, 6.7331293840074014e-01, 8.2300774372149477e-01, 9.7274444570696528e-01, 1.1225307275089995e+00, 1.2723743052896335e+00, 1.4222829334715719e+00, 1.5722644100637477e+00, 1.7223265820726865e+00, 1.8724773510110999e+00, 2.0227246785151167e+00, 2.1730765920823036e+00, 2.3235411909430654e+00, 2.4741266520783536e+00, 2.6248412363975424e+00, 2.7756932950907438e+00, 2.9266912761707076e+00, 3.0778437312202702e+00, 3.2291593223621100e+00, 3.3806468294686467e+00, 3.5323151576310980e+00, 3.6841733449075362e+00, 3.8362305703715940e+00, 3.9884961624844180e+00, 4.1409796078143595e+00, 4.2936905601303739e+00, 4.4466388498971172e+00, 4.5998344942017342e+00, 4.7532877071444766e+00, 4.9070089107279511e+00, 5.0610087462822682e+00, 5.2152980864665599e+00, 5.3698880478903845e+00, 5.5247900044023472e+00, 5.6800156010969900e+00, 5.8355767690955807e+00, 5.9914857411611600e+00, 6.1477550682134519e+00, 6.3043976368153372e+00, 6.4614266877089035e+00, 6.6188558354865279e+00, 6.7766990894903305e+00, 6.9349708760424020e+00, 7.0936860621182607e+00, 7.2528599805868588e+00, 7.4125084571532707e+00, 7.5726478391539116e+00, 7.7332950263697580e+00, 7.8944675040409047e+00, 8.0561833782850805e+00, 8.2184614141456525e+00, 8.3813210765192689e+00, 8.5447825742424133e+00, 8.7088669076480283e+00, 8.8735959199405876e+00, 9.0389923527798217e+00, 9.2050799065113704e+00, 9.3718833055374660e+00, 9.5394283693840993e+00, 9.7077420900935678e+00, 9.8768527166552929e+00, 1.0046789847284987e+01, 1.0217584530474927e+01, 1.0389269375869560e+01, 1.0561878676174262e+01, 1.0735448541485018e+01, 1.0910017047638791e+01, 1.1085624400434606e+01, 1.1262313117871999e+01, 1.1440128232906956e+01, 1.1619117519647554e+01, 1.1799331746419007e+01, 1.1980824959739557e+01, 1.2163654803990811e+01, 1.2347882882470566e+01, 1.2533575166624548e+01, 1.2720802461619986e+01, 1.2909640938118768e+01, 1.3100172742223814e+01, 1.3292486698232523e+01, 1.3486679122200039e+01, 1.3682854768615876e+01, 1.3881127938034011e+01, 1.4081623780688842e+01, 1.4284479840564213e+01, 1.4489847896889446e+01, 1.4697896176804390e+01, 1.4908812035694833e+01, 1.5122805233008011e+01, 1.5340111975060188e+01, 1.5560999958339213e+01, 1.5785774736307584e+01, 1.6014787864496149e+01, 1.6248447477010238e+01, 1.6487232253468321e+01, 1.6731710220470223e+01, 1.6982564625621777e+01, 1.7240630469775191e+01, 1.7506947669788651e+01, 1.7782841268044042e+01, 1.8070047892967271e+01, 1.8370926385157830e+01, 1.8688834225534919e+01, 1.9028866794578029e+01, 1.9399516717870224e+01, 1.9817257977795947e+01, 2.0325189139629405e+01}, + w: []float64{2.2761605731502931e-180, 1.2490844229282551e-171, 1.4077080884426324e-164, 1.9558070725961945e-158, 6.7396164617778564e-153, 8.3007451278928549e-148, 4.5605427168506885e-143, 1.2952107195320918e-138, 2.1106922482765282e-134, 2.1325182525295938e-130, 1.4176541142180510e-126, 6.4990818384221324e-123, 2.1340663816447175e-119, 5.1782994410611593e-116, 9.5303885471678039e-113, 1.3600769560707746e-109, 1.5337501625076215e-106, 1.3892626373123839e-103, 1.0252931948997944e-100, 6.2430026550428978e-98, 3.1713496923820005e-95, 1.3573663268548106e-92, 4.9385791079870452e-90, 1.5396613562557895e-87, 4.1428768007295419e-85, 9.6845718261332366e-83, 1.9785969337019459e-80, 3.5522955000635345e-78, 5.6327088700629997e-76, 7.9248469784581938e-74, 9.9353884108905009e-72, 1.1143371044053519e-69, 1.1222249771693660e-67, 1.0182568638449594e-65, 8.3508496445242703e-64, 6.2085535684767686e-62, 4.1960840622737107e-60, 2.5847807937901128e-58, 1.4547608917709417e-56, 7.4980265458380947e-55, 3.5467498009174184e-53, 1.5428702374218767e-51, 6.1841637682672203e-50, 2.2881100073201874e-48, 7.8282784948541621e-47, 2.4806114249059706e-45, 7.2916745732054914e-44, 1.9911806078855746e-42, 5.0584298583405264e-41, 1.1970700137586669e-39, 2.6422337190194530e-38, 5.4462015155980312e-37, 1.0495069994748297e-35, 1.8928725655710039e-34, 3.1985659419085236e-33, 5.0689745622498271e-32, 7.5410079936029980e-31, 1.0540919389712685e-29, 1.3856239612378123e-28, 1.7143191474654609e-27, 1.9978524188114189e-26, 2.1947842513043781e-25, 2.2745432296820405e-24, 2.2252271383645215e-23, 2.0564749726923156e-22, 1.7964719327802204e-21, 1.4843379300503135e-20, 1.1606915413845120e-19, 8.5944540731309027e-19, 6.0293824390549243e-18, 4.0096487904356170e-17, 2.5289217277543671e-16, 1.5134484435681475e-15, 8.5980922774659504e-15, 4.6390554602844329e-14, 2.3781148094626393e-13, 1.1587426167580950e-12, 5.3685841373417416e-12, 2.3659835874748833e-11, 9.9219381603477156e-11, 3.9606009206879336e-10, 1.5053791970450186e-09, 5.4498580894419877e-09, 1.8797800781026250e-08, 6.1792198822459984e-08, 1.9363392840773747e-07, 5.7857719375034532e-07, 1.6488403637671232e-06, 4.4826356596959815e-06, 1.1628419918195159e-05, 2.8789242845201347e-05, 6.8037279449589797e-05, 1.5351500720814013e-04, 3.3076323494923371e-04, 6.8063888690970183e-04, 1.3378748383672085e-03, 2.5123201954271616e-03, 4.5076732111920138e-03, 7.7285957578851656e-03, 1.2663915587278220e-02, 1.9833481075447929e-02, 2.9691593353631068e-02, 4.2492045448586743e-02, 5.8137078835965875e-02, 7.6049788530935164e-02, 9.5118681388506904e-02, 1.1375654825578213e-01, 1.3009049092173738e-01, 1.4226074789149157e-01, 1.4876572633109977e-01, 1.4876572633109977e-01, 1.4226074789149157e-01, 1.3009049092173738e-01, 1.1375654825578213e-01, 9.5118681388506904e-02, 7.6049788530935164e-02, 5.8137078835965875e-02, 4.2492045448586743e-02, 2.9691593353631068e-02, 1.9833481075447929e-02, 1.2663915587278220e-02, 7.7285957578851656e-03, 4.5076732111920138e-03, 2.5123201954271616e-03, 1.3378748383672085e-03, 6.8063888690970183e-04, 3.3076323494923371e-04, 1.5351500720814013e-04, 6.8037279449589797e-05, 2.8789242845201347e-05, 1.1628419918195159e-05, 4.4826356596959815e-06, 1.6488403637671232e-06, 5.7857719375034532e-07, 1.9363392840773747e-07, 6.1792198822459984e-08, 1.8797800781026250e-08, 5.4498580894419877e-09, 1.5053791970450186e-09, 3.9606009206879336e-10, 9.9219381603477156e-11, 2.3659835874748833e-11, 5.3685841373417416e-12, 1.1587426167580950e-12, 2.3781148094626393e-13, 4.6390554602844329e-14, 8.5980922774659504e-15, 1.5134484435681475e-15, 2.5289217277543671e-16, 4.0096487904356170e-17, 6.0293824390549243e-18, 8.5944540731309027e-19, 1.1606915413845120e-19, 1.4843379300503135e-20, 1.7964719327802204e-21, 2.0564749726923156e-22, 2.2252271383645215e-23, 2.2745432296820405e-24, 2.1947842513043781e-25, 1.9978524188114189e-26, 1.7143191474654609e-27, 1.3856239612378123e-28, 1.0540919389712685e-29, 7.5410079936029980e-31, 5.0689745622498271e-32, 3.1985659419085236e-33, 1.8928725655710039e-34, 1.0495069994748297e-35, 5.4462015155980312e-37, 2.6422337190194530e-38, 1.1970700137586669e-39, 5.0584298583405264e-41, 1.9911806078855746e-42, 7.2916745732054914e-44, 2.4806114249059706e-45, 7.8282784948541621e-47, 2.2881100073201874e-48, 6.1841637682672203e-50, 1.5428702374218767e-51, 3.5467498009174184e-53, 7.4980265458380947e-55, 1.4547608917709417e-56, 2.5847807937901128e-58, 4.1960840622737107e-60, 6.2085535684767686e-62, 8.3508496445242703e-64, 1.0182568638449594e-65, 1.1222249771693660e-67, 1.1143371044053519e-69, 9.9353884108905009e-72, 7.9248469784581938e-74, 5.6327088700629997e-76, 3.5522955000635345e-78, 1.9785969337019459e-80, 9.6845718261332366e-83, 4.1428768007295419e-85, 1.5396613562557895e-87, 4.9385791079870452e-90, 1.3573663268548106e-92, 3.1713496923820005e-95, 6.2430026550428978e-98, 1.0252931948997944e-100, 1.3892626373123839e-103, 1.5337501625076215e-106, 1.3600769560707746e-109, 9.5303885471678039e-113, 5.1782994410611593e-116, 2.1340663816447175e-119, 6.4990818384221324e-123, 1.4176541142180510e-126, 2.1325182525295938e-130, 2.1106922482765282e-134, 1.2952107195320918e-138, 4.5605427168506885e-143, 8.3007451278928549e-148, 6.7396164617778564e-153, 1.9558070725961945e-158, 1.4077080884426324e-164, 1.2490844229282551e-171, 2.2761605731502931e-180}, + }, + } { + h := Hermite{} + x := make([]float64, test.n) + weight := make([]float64, test.n) + h.FixedLocations(x, weight, math.Inf(-1), math.Inf(1)) + if !floats.EqualApprox(x, test.x, 1e-14) { + t.Errorf("n = %v, x mismatch", test.n) + fmt.Println(x) + fmt.Println() + fmt.Println(test.x) + //t.Errorf("x mismatch. \nWant %v\ngot %v", test.x, x) + } + if !floats.EqualApprox(weight, test.w, 1e-14) { + t.Errorf("n = %v, w mismatch", test.n) + //t.Errorf("w mismatch. Want %v, got %v", test.w, weight) + } + } +} + +func TestHermiteInitialGuesses(t *testing.T) { + for _, test := range []struct { + n int + want []float64 + }{ + // Evaluated from Chebfun. + { + n: 215, + want: []float64{0, 0.151326329763712, 0.302660700793398, 0.454011159911720, 0.605385765065948, 0.756792590918330, 0.908239734470234, 1.059735320731617, 1.211287508447394, 1.362904495892717, 1.514594526749157, 1.666365896074552, 1.818226956379164, 1.970186123821706, 2.122251884538916, 2.274432801123240, 2.426737519263548, 2.579174774564779, 2.731753399562905, 2.884482330952826, 3.037370617047366, 3.190427425487010, 3.343662051220745, 3.497083924780193, 3.650702620869949, 3.804527867299248, 3.958569554281313, 4.112837744128784, 4.267342681375636, 4.422094803358200, 4.577104751290402, 4.732383381871004, 4.887941779463563, 5.043791268893151, 5.199943428907478, 5.356410106353889, 5.513203431128299, 5.670335831956713, 5.827820053075521, 5.985669171882509, 6.143896617637219, 6.302516191296349, 6.461542086578262, 6.620988912359293, 6.780871716514890, 6.941206011329554, 7.102007800612191, 7.263293608667420, 7.425080511288993, 7.587386168959320, 7.750228862458692, 7.913627531110426, 8.077601813913194, 8.242172093840729, 8.407359545621334, 8.573186187346858, 8.739674936302684, 8.906849669458699, 9.074735289116129, 9.243357794268617, 9.412744358308792, 9.582923413795772, 9.753924745096450, 9.925779589826769, 10.098520750150884, 10.272182715150265, 10.446801795655594, 10.622416273146731, 10.799066564577450, 10.976795405279171, 11.155648052452676, 11.335672512180423, 11.516919793401330, 11.699444192903831, 11.883303616137852, 12.068559939553955, 12.255279421290370, 12.443533168399910, 12.633397670509774, 12.824955411930718, 13.018295576901773, 13.213514866037960, 13.410718446364541, 13.610021062878001, 13.811548346792373, 14.015438365098394, 14.221843468615116, 14.430932512542578, 14.642893546366283, 14.857937101386424, 15.076300248006383, 15.298251657131900, 15.524097989861344, 15.754192071913305, 15.988943508292977, 16.228832700713156, 16.474429717130270, 16.726420259572109, 16.985642328947012, 17.253139580754688, 17.530241825363181, 17.818691945179868, 18.120857274390474, 18.440107345774539, 18.781555607447057, 19.153723464992801, 19.573128956064245, 20.082675660407357}, + }, + { + n: 216, + want: []float64{7.5487718957947841e-02, 2.2646713089416223e-01, 3.7745846761172613e-01, 5.2846968803819716e-01, 6.7950876473020116e-01, 8.3058368936317251e-01, 9.8170247825952706e-01, 1.1328731779663146e+00, 1.2841038708939367e+00, 1.4354026810274640e+00, 1.5867777797225648e+00, 1.7382373915984026e+00, 1.8897898005400910e+00, 2.0414433558240375e+00, 2.1932064783796412e+00, 2.3450876672018457e+00, 2.4970955059292010e+00, 2.6492386696032790e+00, 2.8015259316256671e+00, 2.9539661709299665e+00, 3.1065683793869288e+00, 3.2593416694621893e+00, 3.4122952821469283e+00, 3.5654385951833136e+00, 3.7187811316079062e+00, 3.8723325686377130e+00, 4.0261027469252912e+00, 4.1801016802112088e+00, 4.3343395654041350e+00, 4.4888267931211692e+00, 4.6435739587232687e+00, 4.7985918738836766e+00, 4.9538915787298405e+00, 5.1094843546028494e+00, 5.2653817374818566e+00, 5.4215955321250595e+00, 5.5781378269829656e+00, 5.7350210099447425e+00, 5.8922577849835758e+00, 6.0498611897730488e+00, 6.2078446143528714e+00, 6.3662218209298418e+00, 6.5250069649076838e+00, 6.6842146172486627e+00, 6.8438597882796577e+00, 7.0039579530666876e+00, 7.1645250784943162e+00, 7.3255776522003675e+00, 7.4871327135320032e+00, 7.6492078867069049e+00, 7.8118214163831334e+00, 7.9749922058635363e+00, 8.1387398581859554e+00, 8.3030847203790454e+00, 8.4680479311960379e+00, 8.6336514726757141e+00, 8.7999182259219690e+00, 8.9668720315415094e+00, 9.1345377552342626e+00, 9.3029413590944845e+00, 9.4721099792532808e+00, 9.6420720105775217e+00, 9.8128571992374614e+00, 9.9844967440684584e+00, 1.0157023407784097e+01, 1.0330471639251822e+01, 1.0504877708222864e+01, 1.0680279854120787e+01, 1.0856718450743809e+01, 1.1034236189033734e+01, 1.1212878280418622e+01, 1.1392692683659751e+01, 1.1573730358642214e+01, 1.1756045551162156e+01, 1.1939696113507749e+01, 1.2124743866538131e+01, 1.2311255010076101e+01, 1.2499300589800702e+01, 1.2688957030525529e+01, 1.2880306747870632e+01, 1.3073438853003600e+01, 1.3268449968504161e+01, 1.3465445177719724e+01, 1.3664539135531767e+01, 1.3865857375666192e+01, 1.4069537859142688e+01, 1.4275732821001174e+01, 1.4484610989259913e+01, 1.4696360272885402e+01, 1.4911191046953165e+01, 1.5129340207007946e+01, 1.5351076226802732e+01, 1.5576705543358910e+01, 1.5806580725457744e+01, 1.6041111080581306e+01, 1.6280776662107755e+01, 1.6526147125048691e+01, 1.6777907674840002e+01, 1.7036895705202610e+01, 1.7304154114531990e+01, 1.7581011746684457e+01, 1.7869210214084568e+01, 1.8171115120332015e+01, 1.8490093525334313e+01, 1.8831255107137672e+01, 1.9203114954794152e+01, 1.9622178785373663e+01, 2.0131752068311702e+01}, + }, + } { + got := make([]float64, test.n/2+test.n%2) + for i := range got { + got[i] = Hermite{}.hermiteInitialGuess(i, test.n) + } + if !floats.EqualApprox(got, test.want, 1e-14) { + t.Errorf("n = %v, hermite initial guesses mismatch", test.n) + } + } +} + +func TestHermiteLocationsAsy0(t *testing.T) { + for _, test := range []struct { + n int + x []float64 + w []float64 + }{ + // Evaluated from Chebfun. + { + n: 215, + x: []float64{-7.9483151672010196e-15, 1.5132632976672361e-01, 3.0266070079942864e-01, 4.5401115992078167e-01, 6.0538576507805808e-01, 7.5679259093351370e-01, 9.0823973448851325e-01, 1.0597353207530273e+00, 1.2112875084719879e+00, 1.3629044959205205e+00, 1.5145945267802365e+00, 1.6663658961089640e+00, 1.8182269564169717e+00, 1.9701861238629792e+00, 2.1222518845837395e+00, 2.2744328011717010e+00, 2.4267375193157439e+00, 2.5791747746208049e+00, 2.7317533996228827e+00, 2.8844823310168755e+00, 3.0373706171156218e+00, 3.1904274255596032e+00, 3.3436620512978501e+00, 3.4970839248619634e+00, 3.6507026209565665e+00, 3.8045278673909002e+00, 3.9585695543782120e+00, 4.1128377442311503e+00, 4.2673426814837114e+00, 4.4220948034722349e+00, 4.5771047514106780e+00, 4.7323833819978187e+00, 4.8879417795972326e+00, 5.0437912690340267e+00, 5.1999434290559226e+00, 5.3564101065103049e+00, 5.5132034312931157e+00, 5.6703358321303936e+00, 5.8278200532585673e+00, 5.9856691720754620e+00, 6.1438966178406549e+00, 6.3025161915109100e+00, 6.4615420868046280e+00, 6.6209889125982082e+00, 6.7808717167671544e+00, 6.9412060115960434e+00, 7.1020078008938672e+00, 7.2632936089653120e+00, 7.4250805116042331e+00, 7.5873861692931381e+00, 7.7502288628124383e+00, 7.9136275314855800e+00, 8.0776018143113824e+00, 8.2421720942637187e+00, 8.4073595460710955e+00, 8.5731861878255415e+00, 8.7396749368126798e+00, 8.9068496700026394e+00, 9.0747352896969389e+00, 9.2433577948895387e+00, 9.4127443589734394e+00, 9.5829234145081710e+00, 9.7539247458611111e+00, 9.9257795906487338e+00, 1.0098520751035824e+01, 1.0272182716104577e+01, 1.0446801796686490e+01, 1.0622416274262394e+01, 1.0799066565787168e+01, 1.0976795406593546e+01, 1.1155648053883823e+01, 1.1335672513742256e+01, 1.1516919795109878e+01, 1.1699444194777641e+01, 1.1883303618198463e+01, 1.2068559941826503e+01, 1.2255279423804318e+01, 1.2443533171189967e+01, 1.2633397673617059e+01, 1.2824955415404188e+01, 1.3018295580800100e+01, 1.3213514870431910e+01, 1.3410718451340038e+01, 1.3610021068540190e+01, 1.3811548353270942e+01, 1.4015438372554696e+01, 1.4221843477251845e+01, 1.4430932522616979e+01, 1.4642893558208563e+01, 1.4857937115425768e+01, 1.5076300264808333e+01, 1.5298251677453143e+01, 1.5524098014731747e+01, 1.5754192102761674e+01, 1.5988943547145137e+01, 1.6228832750513551e+01, 1.6474429782282726e+01, 1.6726420346886542e+01, 1.6985642449377284e+01, 1.7253139752773148e+01, 1.7530242081974308e+01, 1.7818692349773503e+01, 1.8120857960601569e+01, 1.8440108632764016e+01, 1.8781558404513735e+01, 1.9153731166695263e+01, 1.9573161931385755e+01, 2.0083110126223993e+01}, + w: []float64{5.8004562850365771e-04, 5.6692877486338696e-04, 5.2932867305102921e-04, 4.7211368597165944e-04, 4.0223648470876573e-04, 3.2735218319190782e-04, 2.5446548811048362e-04, 1.8892919855999243e-04, 1.3396711152850057e-04, 9.0718165504482523e-05, 5.8661199606591556e-05, 3.6218251240150691e-05, 2.1349054444552587e-05, 1.2013089019084848e-05, 6.4521031002773646e-06, 3.3071925113778075e-06, 1.6175791039359969e-06, 7.5483313427524376e-07, 3.3600239642860852e-07, 1.4264659961771696e-07, 5.7746366478382785e-08, 2.2286582090203475e-08, 8.1983021699506761e-09, 2.8738670556378732e-09, 9.5976924324201262e-10, 3.0529085215378481e-10, 9.2467927287192434e-11, 2.6660996519674056e-11, 7.3154481204350507e-12, 1.9096325566425540e-12, 4.7409073505752031e-13, 1.1189936218333804e-13, 2.5101111888653927e-14, 5.3492761412487281e-15, 1.0825895304391782e-15, 2.0798005039728529e-16, 3.7912539356931888e-17, 6.5547084049896133e-18, 1.0743122119399353e-18, 1.6684093877262400e-19, 2.4538539136228336e-20, 3.4161583900178126e-21, 4.4991409209589655e-22, 5.6023724685401444e-23, 6.5917775903350454e-24, 7.3239791710744789e-25, 7.6792588730186891e-26, 7.5931172671070367e-27, 7.0751732949679160e-28, 6.2078867832748634e-29, 5.1250608797215456e-30, 3.9778286806416675e-31, 2.9000923323091595e-32, 1.9842934651116758e-33, 1.2729744163019100e-34, 7.6493618655638258e-36, 4.3010461850159373e-37, 2.2604572504006732e-38, 1.1091714341886240e-39, 5.0753225126752125e-41, 2.1629552371814077e-42, 8.5739087326714758e-44, 3.1568681170134092e-45, 1.0780709245918455e-46, 3.4094518277810594e-48, 9.9692987408874913e-50, 2.6905726285477170e-51, 6.6902112757430557e-53, 1.5297458011420645e-54, 3.2099851519180199e-56, 6.1681886704578063e-58, 1.0829083084555836e-59, 1.7328083889009238e-61, 2.5206396804555329e-63, 3.3240965181095399e-65, 3.9623955222122382e-67, 4.2558991248868728e-69, 4.1048947183601511e-71, 3.5424776999043975e-73, 2.7245890408644923e-75, 1.8596929038788086e-77, 1.1213274238978696e-79, 5.9430256314002078e-82, 2.7536336403486887e-84, 1.1087876280230634e-86, 3.8548279808836764e-89, 1.1488445098745636e-91, 2.9118805234147757e-94, 6.2218187764965726e-97, 1.1097458975689325e-99, 1.6341809683598844e-102, 1.9621625424695376e-105, 1.8939702898325753e-108, 1.4459753551186440e-111, 8.5692594596311645e-115, 3.8565449589488849e-118, 1.2843410590864927e-121, 3.0685300780965873e-125, 5.0651104293759753e-129, 5.5131423653412833e-133, 3.7300165435945031e-137, 1.4525522232777015e-141, 2.9352196847507026e-146, 2.6587623615117695e-151, 8.6633861029598960e-157, 7.0653364942986233e-163, 7.2051505413036788e-170, 1.5514139491189097e-178}, + }, + { + n: 216, + x: []float64{7.5487718959414210e-02, 2.2646713089859094e-01, 3.7745846761911317e-01, 5.2846968804856509e-01, 6.7950876474356448e-01, 8.3058368937955573e-01, 9.8170247827895785e-01, 1.1328731779888348e+00, 1.2841038709195900e+00, 1.4354026810562848e+00, 1.5867777797546210e+00, 1.7382373916337388e+00, 1.8897898005787916e+00, 2.0414433558661624e+00, 2.1932064784252856e+00, 2.3450876672510903e+00, 2.4970955059821409e+00, 2.6492386696600243e+00, 2.8015259316863266e+00, 2.9539661709946619e+00, 3.1065683794558021e+00, 3.2593416695353823e+00, 3.4122952822245907e+00, 3.5654385952656149e+00, 3.7187811316950210e+00, 3.8723325687298416e+00, 4.0261027470226392e+00, 4.1801016803139959e+00, 4.3343395655126109e+00, 4.4888267932355790e+00, 4.6435739588438905e+00, 4.7985918740108131e+00, 4.9538915788638089e+00, 5.1094843547439881e+00, 5.2653817376305465e+00, 5.4215955322816969e+00, 5.5781378271479722e+00, 5.7350210101185848e+00, 5.8922577851667635e+00, 6.0498611899661094e+00, 6.2078446145563948e+00, 6.3662218211444577e+00, 6.5250069651340752e+00, 6.6842146174875827e+00, 6.8438597885318986e+00, 7.0039579533331269e+00, 7.1645250787759087e+00, 7.3255776524981444e+00, 7.4871327138470951e+00, 7.6492078870405447e+00, 7.8118214167366684e+00, 7.9749922062384426e+00, 8.1387398585838486e+00, 8.3030847208017082e+00, 8.4680479316454296e+00, 8.6336514731539875e+00, 8.7999182264315081e+00, 8.9668720320849413e+00, 9.1345377558145096e+00, 9.3029413597147883e+00, 9.4721099799172528e+00, 9.6420720112891818e+00, 9.8128572000013108e+00, 9.9844967448895385e+00, 1.0157023408668081e+01, 1.0330471640205081e+01, 1.0504877709252620e+01, 1.0680279855235202e+01, 1.0856718451952171e+01, 1.1034236190346626e+01, 1.1212878281848150e+01, 1.1392692685219812e+01, 1.1573730360348824e+01, 1.1756045553033841e+01, 1.1939696115566026e+01, 1.2124743868808109e+01, 1.2311255012587219e+01, 1.2499300592587632e+01, 1.2688957033629340e+01, 1.2880306751340244e+01, 1.3073438856897617e+01, 1.3268449972893279e+01, 1.3465445182689793e+01, 1.3664539141187824e+01, 1.3865857382137794e+01, 1.4069537866591046e+01, 1.4275732829628778e+01, 1.4484610999323769e+01, 1.4696360284715409e+01, 1.4911191060978103e+01, 1.5129340223792830e+01, 1.5351076247103551e+01, 1.5576705568204593e+01, 1.5806580756275796e+01, 1.6041111119395726e+01, 1.6280776711860355e+01, 1.6526147190139376e+01, 1.6777907762072694e+01, 1.7036895825521608e+01, 1.7304154286393636e+01, 1.7581012003064874e+01, 1.7869210618319627e+01, 1.8171115805943941e+01, 1.8490094811217439e+01, 1.8831257901839155e+01, 1.9203122650098184e+01, 1.9622211733828486e+01, 2.0131752068397390e+01}, + w: []float64{5.7408951238509774e-04, 5.4853385977693967e-04, 5.0077995633045094e-04, 4.3681926493182888e-04, 3.6404534695321319e-04, 2.8986205027358900e-04, 2.2048980967270541e-04, 1.6022189177224014e-04, 1.1121464501100074e-04, 7.3735261435177744e-05, 4.6689968632275442e-05, 2.8233496634858870e-05, 1.6302404527221912e-05, 8.9873835313609794e-06, 4.7299184092204348e-06, 2.3760322139117827e-06, 1.1391060264678187e-06, 5.2109775739704647e-07, 2.2742736124678848e-07, 9.4679280581569520e-08, 3.7589897335857270e-08, 1.4229883676778969e-08, 5.1351173480468011e-09, 1.7661093963625318e-09, 5.7875785413194057e-10, 1.8066600901602130e-10, 5.3707955985666741e-11, 1.5200567246892033e-11, 4.0945877360252466e-12, 1.0494304449814065e-12, 2.5582770078364328e-13, 5.9298335011290506e-14, 1.3064177735039720e-14, 2.7346561920969734e-15, 5.4366757055637182e-16, 1.0261135273171614e-16, 1.8378155831501011e-17, 3.1221798154524404e-18, 5.0287455392773255e-19, 7.6752848097550855e-20, 1.1095334788910946e-20, 1.5183281292392555e-21, 1.9657499371912346e-22, 2.4064442018314010e-23, 2.7838422576260478e-24, 3.0413021389695441e-25, 3.1356913424697775e-26, 3.0490587561112177e-27, 2.7941107980138270e-28, 2.4112340295373517e-29, 1.9579916032501855e-30, 1.4948591683644822e-31, 1.0720958700672810e-32, 7.2163812209007653e-34, 4.5545782039839515e-35, 2.6927171840186886e-36, 1.4896964129251313e-37, 7.7036780004272946e-39, 3.7196117693798106e-40, 1.6748563396289038e-41, 7.0241404150854973e-43, 2.7401344340734534e-44, 9.9291319468776600e-46, 3.3371619908503302e-47, 1.0387276524925886e-48, 2.9893704843803614e-50, 7.9408570659652511e-52, 1.9434716944530867e-53, 4.3740144067322860e-55, 9.0342460240718143e-57, 1.7087495134365174e-58, 2.9528859528856670e-60, 4.6509376421165100e-62, 6.6593952486160953e-64, 8.6442830921042970e-66, 1.0142381095581560e-67, 1.0722439547251424e-69, 1.0179251007077803e-71, 8.6461259693742430e-74, 6.5448969088799971e-76, 4.3965762236216239e-78, 2.6089085327841006e-80, 1.3607099985773063e-82, 6.2039892663366641e-85, 2.4580575133840935e-87, 8.4080554628125066e-90, 2.4652597109139967e-92, 6.1467455174872763e-95, 1.2918545805718045e-97, 2.2661732049781124e-100, 3.2815976681148591e-103, 3.8741015126651295e-106, 3.6760977386321105e-109, 2.7584831111443303e-112, 1.6064052012003602e-115, 7.1024252453209961e-119, 2.3230796238780657e-122, 5.4494213912665180e-126, 8.8284366174946482e-130, 9.4271378060446301e-134, 6.2539251873936211e-138, 2.3865140957941506e-142, 4.7220323342515999e-147, 4.1840743138172546e-152, 1.3319161291512504e-157, 1.0592510752538756e-163, 1.0503755670967946e-170, 2.1869674690632971e-179}, + }, + } { + n := test.n + x := make([]float64, n/2+n%2) + w := make([]float64, n/2+n%2) + for i := range x { + x[i], w[i] = Hermite{}.locationsAsy0(i, n) + } + if !floats.EqualApprox(x, test.x, 1e-13) { + t.Errorf("n = %v, x mismatch", n) + fmt.Println(x[107]) + fmt.Println(test.x[107]) + } + if !floats.EqualApprox(w, test.w, 1e-13) { + t.Errorf("n = %v, w mismatch", n) + } + } +} + +func TestHermiteAsyAiry(t *testing.T) { + for _, test := range []struct { + n int + theta []float64 + val []float64 + dval []float64 + }{ + { + n: 215, + theta: []float64{1.5707963267948966e+00, 1.5635071294267224e+00, 1.5562171573546757e+00, 1.5489256352159648e+00, 1.5416317863284521e+00, 1.5343348320272066e+00, 1.5270339909965103e+00, 1.5197284785957685e+00, 1.5124175061777518e+00, 1.5051002803975593e+00, 1.4977760025106577e+00, 1.4904438676582881e+00, 1.4831030641384946e+00, 1.4757527726609410e+00, 1.4683921655836265e+00, 1.4610204061295120e+00, 1.4536366475809854e+00, 1.4462400324499760e+00, 1.4388296916214274e+00, 1.4314047434676882e+00, 1.4239642929312548e+00, 1.4165074305731233e+00, 1.4090332315838545e+00, 1.4015407547542300e+00, 1.3940290414022056e+00, 1.3864971142525955e+00, 1.3789439762656834e+00, 1.3713686094106747e+00, 1.3637699733795743e+00, 1.3561470042367485e+00, 1.3484986129990375e+00, 1.3408236841408716e+00, 1.3331210740183812e+00, 1.3253896092059803e+00, 1.3176280847383373e+00, 1.3098352622500289e+00, 1.3020098680044709e+00, 1.2941505908029671e+00, 1.2862560797638511e+00, 1.2783249419607658e+00, 1.2703557399080556e+00, 1.2623469888800907e+00, 1.2542971540500127e+00, 1.2462046474319508e+00, 1.2380678246090893e+00, 1.2298849812281600e+00, 1.2216543492388388e+00, 1.2133740928542220e+00, 1.2050423042059359e+00, 1.1966569986644591e+00, 1.1882161097919153e+00, 1.1797174838907749e+00, 1.1711588741076131e+00, 1.1625379340461441e+00, 1.1538522108381697e+00, 1.1450991376146524e+00, 1.1362760253118058e+00, 1.1273800537386238e+00, 1.1184082618225748e+00, 1.1093575369389341e+00, 1.1002246032162142e+00, 1.0910060086950395e+00, 1.0816981112001869e+00, 1.0722970627649082e+00, 1.0627987924225111e+00, 1.0531989871517369e+00, 1.0434930707289145e+00, 1.0336761802000907e+00, 1.0237431396389916e+00, 1.0136884308001370e+00, 1.0035061602085740e+00, 9.9319002214595331e-01, 9.8273325689369295e-01, 9.7212860347355579e-01, 9.6136824597870241e-01, 9.5044375240720391e-01, 9.3934600468605900e-01, 9.2806511829511895e-01, 9.1659034955139063e-01, 9.0490998817422319e-01, 8.9301123219309975e-01, 8.8088004154453947e-01, 8.6850096578161351e-01, 8.5585694011780433e-01, 8.4292904244735056e-01, 8.2969620188675874e-01, 8.1613484656631152e-01, 8.0221847457494289e-01, 7.8791712669745728e-01, 7.7319673223616503e-01, 7.5801828879746735e-01, 7.4233682191908168e-01, 7.2610004838413222e-01, 7.0924663405346811e-01, 6.9170388642137270e-01, 6.7338464244284535e-01, 6.5418298314185364e-01, 6.3396819041411068e-01, 6.1257598542667102e-01, 5.8979540387821172e-01, 5.6534835113739590e-01, 5.3885619819698471e-01, 5.0978185232293227e-01, 4.7732127920035572e-01, 4.4017830784988765e-01, 3.9602307074600884e-01, 3.3985069280702440e-01, 2.5624520569356829e-01}, + val: []float64{-2.7524590607067879e-13, -1.2484792737707130e-10, 2.5043777255407545e-10, -3.7621487726711831e-10, 5.0266571286479591e-10, -6.3022107051014496e-10, 7.5847898514904004e-10, -8.8850597267422281e-10, 1.0201287099545048e-09, -1.1532700149758681e-09, 1.2885402426941860e-09, -1.4262514564750722e-09, 1.5667774694950304e-09, -1.7098460348004283e-09, 1.8563663242006209e-09, -2.0060430373954962e-09, 2.1597272205910619e-09, -2.3174687646872261e-09, 2.4795270439737100e-09, -2.6462815453642877e-09, 2.8188431716836157e-09, -2.9962948915230151e-09, 3.1805879826447352e-09, -3.3709772507788239e-09, 3.5681573894354513e-09, -3.7732681484183285e-09, 3.9863813736176932e-09, -4.2080297462347532e-09, 4.4391671460302399e-09, -4.6802436355831232e-09, 4.9322546933533433e-09, -5.1957881449299223e-09, 5.4715433664057677e-09, -5.7608265327475837e-09, 6.0644153161437157e-09, -6.3835515563504339e-09, 6.7192819880764795e-09, -7.0729371214636086e-09, 7.4458702579674617e-09, -7.8396410076078555e-09, 8.2556088536449877e-09, -8.6960989460562939e-09, 9.1626310723815202e-09, -9.6575986146054327e-09, 1.0182896152806950e-08, -1.0741758184989815e-08, 1.1337214303287172e-08, -1.1971481080324528e-08, 1.2648762056240369e-08, -1.3372488830525768e-08, 1.4147041859097387e-08, -1.4977276046958432e-08, 1.5868475891599271e-08, -1.6825823997480545e-08, 1.7856900524878266e-08, -1.8967833880184117e-08, 2.0167708166421882e-08, -2.1465280681285451e-08, 2.2870631970634630e-08, -2.4395881051717265e-08, 2.6054060647767539e-08, -2.7859818527100110e-08, 2.9830454146699167e-08, -3.1984835487787522e-08, 3.4345470368342559e-08, -3.6937900081988413e-08, 3.9790883510012329e-08, -4.2938418365980210e-08, 4.6419377177480922e-08, -5.0279213559974237e-08, 5.4570799296449321e-08, -5.9356303125081130e-08, 6.4708755363671345e-08, -7.0714511032393380e-08, 7.7475892426711618e-08, -8.5115456468135130e-08, 9.3779863576446978e-08, -1.0364644483987255e-07, 1.1493006182865740e-07, -1.2789317815470753e-07, 1.4285900893044798e-07, -1.6022759919461249e-07, 1.8049814080062288e-07, -2.0429953256541455e-07, 2.3243044535889061e-07, -2.6591504027157263e-07, 3.0608147425737922e-07, -3.5467098673335754e-07, 4.1399606056878556e-07, -4.8716979156405424e-07, 5.7844824292016844e-07, -6.9374768843585542e-07, 8.4144962449118331e-07, -1.0336795693201387e-06, 1.2884020459910342e-06, -1.6329629222918408e-06, 2.1103031286712709e-06, -2.7903321871954755e-06, 3.7918023218017778e-06, -5.3269144947324421e-06, 7.7989206456257246e-06, -1.2034979469568085e-05, 1.9905658561076196e-05, -3.6224899321604820e-05, 7.5828952282754516e-05, -1.9870421394114517e-04, 7.9136577883937422e-04, -9.1266148556594703e-03}, + dval: []float64{-2.9359856130945122e+01, 2.9359466144908318e+01, -2.9358296010652477e+01, 2.9356345199427643e+01, -2.9353612829040124e+01, 2.9350097662433203e+01, -2.9345798105693621e+01, 2.9340712205476308e+01, -2.9334837645838910e+01, 2.9328171744474840e+01, -2.9320711448331572e+01, 2.9312453328598885e+01, -2.9303393575049100e+01, 2.9293527989709109e+01, -2.9282851979841201e+01, 2.9271360550207458e+01, -2.9259048294588819e+01, 2.9245909386527540e+01, -2.9231937569258221e+01, 2.9217126144788914e+01, -2.9201467962090302e+01, 2.9184955404346876e+01, -2.9167580375219231e+01, 2.9149334284062498e+01, -2.9130208030040425e+01, 2.9110191985068752e+01, -2.9089275975516287e+01, 2.9067449262584436e+01, -2.9044700521279459e+01, 2.9021017817883425e+01, -2.8996388585821325e+01, 2.8970799599811933e+01, -2.8944236948180023e+01, 2.8916686003195348e+01, -2.8888131389291605e+01, 2.8858556949003951e+01, -2.8827945706448649e+01, 2.8796279828150279e+01, -2.8763540581003511e+01, 2.8729708287134507e+01, -2.8694762275403512e+01, 2.8658680829263385e+01, -2.8621441130659093e+01, 2.8583019199620328e+01, -2.8543389829161509e+01, 2.8502526515061927e+01, -2.8460401380051497e+01, 2.8416985091874277e+01, -2.8372246774642264e+01, 2.8326153912823031e+01, -2.8278672247129006e+01, 2.8229765661486788e+01, -2.8179396060166667e+01, 2.8127523234037287e+01, -2.8074104714780372e+01, 2.8019095615750665e+01, -2.7962448457994284e+01, 2.7904112979739956e+01, -2.7844035927448619e+01, 2.7782160826241125e+01, -2.7718427727214667e+01, 2.7652772928798932e+01, -2.7585128668881747e+01, 2.7515422783940370e+01, -2.7443578330833645e+01, 2.7369513166223737e+01, -2.7293139477783004e+01, 2.7214363260373997e+01, -2.7133083729234610e+01, 2.7049192660814331e+01, -2.6962573650237655e+01, 2.6873101272350414e+01, -2.6780640130847800e+01, 2.6685043776981303e+01, -2.6586153475654008e+01, 2.6483796792158788e+01, -2.6377785967154090e+01, 2.6267916040395331e+01, -2.6153962674834343e+01, 2.6035679621411951e+01, -2.5912795750458177e+01, 2.5785011557068390e+01, -2.5651995023754676e+01, 2.5513376692151432e+01, -2.5368743753874771e+01, 2.5217632914945654e+01, -2.5059521712941240e+01, 2.4893817863127197e+01, -2.4719846067215368e+01, 2.4536831517922174e+01, -2.4343879046260469e+01, 2.4139946442705973e+01, -2.3923809867871942e+01, 2.3694018337866666e+01, -2.3448832829666316e+01, 2.3186143264519330e+01, -2.2903352884396824e+01, 2.2597213200674400e+01, -2.2263581543467414e+01, 2.1897052703993687e+01, -2.1490376258364485e+01, 2.1033488463000687e+01, -2.0511802124454178e+01, 1.9902938182242686e+01, -1.9169784832381577e+01, 1.8243381598901596e+01, -1.6969663168974311e+01, 1.4853826851969115e+01}, + }, + { + n: 215, + theta: []float64{1.5707963267948968e+00, 1.5635071294265777e+00, 1.5562171573543850e+00, 1.5489256352155283e+00, 1.5416317863278686e+00, 1.5343348320264747e+00, 1.5270339909956292e+00, 1.5197284785947358e+00, 1.5124175061765655e+00, 1.5051002803962170e+00, 1.4977760025091569e+00, 1.4904438676566254e+00, 1.4831030641366665e+00, 1.4757527726589439e+00, 1.4683921655814560e+00, 1.4610204061271637e+00, 1.4536366475784539e+00, 1.4462400324472560e+00, 1.4388296916185130e+00, 1.4314047434645731e+00, 1.4239642929279313e+00, 1.4165074305695844e+00, 1.4090332315800913e+00, 1.4015407547502341e+00, 1.3940290413979675e+00, 1.3864971142481046e+00, 1.3789439762609286e+00, 1.3713686094056443e+00, 1.3637699733742550e+00, 1.3561470042311266e+00, 1.3484986129930978e+00, 1.3408236841345980e+00, 1.3331210740117563e+00, 1.3253896091989852e+00, 1.3176280847309516e+00, 1.3098352622422307e+00, 1.3020098679962364e+00, 1.2941505907942705e+00, 1.2862560797546647e+00, 1.2783249419510594e+00, 1.2703557398977969e+00, 1.2623469888692436e+00, 1.2542971540385390e+00, 1.2462046474198085e+00, 1.2380678245962331e+00, 1.2298849812145400e+00, 1.2216543492243996e+00, 1.2133740928389052e+00, 1.2050423041896758e+00, 1.1966569986471847e+00, 1.1882161097735480e+00, 1.1797174838712285e+00, 1.1711588740867924e+00, 1.1625379340239450e+00, 1.1538522108144755e+00, 1.1450991375893356e+00, 1.1362760252847235e+00, 1.1273800537096179e+00, 1.1184082617914692e+00, 1.1093575369055320e+00, 1.1002246031802951e+00, 1.0910060086563567e+00, 1.0816981111584625e+00, 1.0722970627198296e+00, 1.0627987923737243e+00, 1.0531989870988405e+00, 1.0434930706714527e+00, 1.0336761801375436e+00, 1.0237431395707643e+00, 1.0136884307255469e+00, 1.0035061601268345e+00, 9.9319002205615470e-01, 9.8273325679477930e-01, 9.7212860336429585e-01, 9.6136824585765468e-01, 9.5044375227267230e-01, 9.3934600453603823e-01, 9.2806511812722514e-01, 9.1659034936277473e-01, 9.0490998796145916e-01, 8.9301123195204113e-01, 8.8088004127013353e-01, 8.6850096546765831e-01, 8.5585693975662547e-01, 8.4292904202937069e-01, 8.2969620139991496e-01, 8.1613484599525510e-01, 8.0221847389992995e-01, 7.8791712589278218e-01, 7.7319673126791522e-01, 7.5801828762024448e-01, 7.4233682047111893e-01, 7.2610004657985505e-01, 7.0924663177187774e-01, 6.9170388348738876e-01, 6.7338463859636577e-01, 6.5418297798453895e-01, 6.3396818331389482e-01, 6.1257597533770680e-01, 5.8979538898074346e-01, 5.6534832806423485e-01, 5.3885616021897675e-01, 5.0978178458826806e-01, 4.7732114425935024e-01, 4.4017799165717791e-01, 3.9602210904603868e-01, 3.3984592789666196e-01, 2.5616263514373872e-01}, + val: []float64{-2.7524577037687927e-13, -1.3157296144588393e-13, -1.4217705189589319e-13, -9.3051784272423659e-14, 6.2263913433904649e-14, -7.2338165854311426e-14, 1.6489823942055246e-13, 8.2086154015730068e-14, 1.7030857773598118e-13, 1.9200825273544764e-13, 3.4144423192398587e-13, -1.3350292964848512e-13, 7.7406393378692183e-16, 3.0802286839980475e-15, 1.0626665274130983e-13, 9.7508116816654928e-14, -1.2286283979350783e-13, 1.6602061523803380e-13, 1.2145800400612989e-14, -2.0125760394077007e-13, 1.1752853222876857e-13, 1.5246361311903834e-13, -1.7100196342840500e-13, -9.0852635256292980e-14, -7.8101776477326909e-14, -8.6215405399587178e-14, -1.8424041061507494e-13, -1.7748959370373156e-13, 1.6659488983250428e-14, -2.3029664495695825e-14, 4.9882044749360307e-14, -1.6935708059066857e-13, -1.6889419531778083e-14, -1.5488691966202885e-13, 4.7496471682336465e-15, -6.0236075531674274e-14, -4.7790439973748918e-14, 1.0528243973915236e-14, -1.4481370116381506e-13, 4.8870674172048881e-14, 5.9145722182844837e-14, -3.6252017525118028e-14, -1.4799821290649442e-13, 7.8483748114372226e-14, -3.1698431394015554e-14, -2.1250000650523357e-13, -1.2207160366356720e-13, -4.4799710774576449e-14, -6.6076225108040054e-14, 4.9432907671096125e-14, 1.1714372287574581e-13, 7.1071624668919607e-14, -1.4699620399669987e-13, 4.9028118279404591e-14, 5.6995970859340297e-15, 1.8655926516135062e-14, 3.2409175615798361e-14, 7.1510069979380908e-14, -7.2558225742592175e-14, 4.1294505314113302e-14, -1.8304081875904709e-14, 1.3492357431194347e-13, -2.0526864648283952e-13, 1.1949578558177085e-14, 5.3441698191945163e-14, 4.9207462229933007e-14, -1.9962117626180037e-13, 8.2375100050737861e-15, 5.8811770905000782e-14, -3.8856969371752553e-15, 4.8345877891596704e-14, -1.2020353849039574e-13, 1.0795889278969854e-14, 2.7165003590955340e-14, 7.9664181703224841e-15, -3.1357633506603503e-14, 3.0114465704049404e-14, 5.4841545026050259e-14, 8.3356466046602926e-14, 3.4875109219720919e-14, 5.3887688890067731e-14, -8.5090430827758076e-15, 1.4753806570541977e-14, 4.1314792687095403e-15, 2.8114340045724569e-14, -8.9380771455156681e-15, -3.2451925819727029e-14, 5.0739464388639648e-14, 5.2751575373088884e-14, 3.8348847777085630e-14, -3.1825724566756715e-14, 6.6426259272244758e-14, -6.4295491511138863e-14, 8.9401622475124014e-15, 2.5866873030708164e-14, 9.6302605421508054e-14, 4.6623114840341440e-14, -1.7497072577375209e-14, 3.3453526916664849e-14, -5.5592329550244261e-14, 1.4115683421722400e-13, -3.9306913138151204e-13, 1.2007938611150981e-12, -4.7530501604406474e-12, 2.5399685303214922e-11, -2.2827587443604869e-10, 5.3187001008179367e-09, -1.4222383864770318e-06}, + dval: []float64{-2.9359856130945126e+01, 2.9359466144908307e+01, -2.9358296010652474e+01, 2.9356345199427643e+01, -2.9353612829040117e+01, 2.9350097662433203e+01, -2.9345798105693628e+01, 2.9340712205476311e+01, -2.9334837645838906e+01, 2.9328171744474847e+01, -2.9320711448331569e+01, 2.9312453328598881e+01, -2.9303393575049114e+01, 2.9293527989709105e+01, -2.9282851979841208e+01, 2.9271360550207465e+01, -2.9259048294588812e+01, 2.9245909386527540e+01, -2.9231937569258211e+01, 2.9217126144788910e+01, -2.9201467962090309e+01, 2.9184955404346905e+01, -2.9167580375219234e+01, 2.9149334284062515e+01, -2.9130208030040418e+01, 2.9110191985068738e+01, -2.9089275975516284e+01, 2.9067449262584432e+01, -2.9044700521279456e+01, 2.9021017817883422e+01, -2.8996388585821315e+01, 2.8970799599811926e+01, -2.8944236948180027e+01, 2.8916686003195355e+01, -2.8888131389291594e+01, 2.8858556949003940e+01, -2.8827945706448645e+01, 2.8796279828150276e+01, -2.8763540581003515e+01, 2.8729708287134510e+01, -2.8694762275403530e+01, 2.8658680829263389e+01, -2.8621441130659079e+01, 2.8583019199620328e+01, -2.8543389829161509e+01, 2.8502526515061930e+01, -2.8460401380051490e+01, 2.8416985091874288e+01, -2.8372246774642264e+01, 2.8326153912823038e+01, -2.8278672247129016e+01, 2.8229765661486780e+01, -2.8179396060166667e+01, 2.8127523234037294e+01, -2.8074104714780368e+01, 2.8019095615750661e+01, -2.7962448457994284e+01, 2.7904112979739949e+01, -2.7844035927448619e+01, 2.7782160826241114e+01, -2.7718427727214678e+01, 2.7652772928798946e+01, -2.7585128668881751e+01, 2.7515422783940377e+01, -2.7443578330833653e+01, 2.7369513166223744e+01, -2.7293139477783015e+01, 2.7214363260374000e+01, -2.7133083729234624e+01, 2.7049192660814349e+01, -2.6962573650237655e+01, 2.6873101272350418e+01, -2.6780640130847814e+01, 2.6685043776981328e+01, -2.6586153475654026e+01, 2.6483796792158806e+01, -2.6377785967154097e+01, 2.6267916040395356e+01, -2.6153962674834389e+01, 2.6035679621411997e+01, -2.5912795750458240e+01, 2.5785011557068451e+01, -2.5651995023754750e+01, 2.5513376692151542e+01, -2.5368743753874902e+01, 2.5217632914945817e+01, -2.5059521712941454e+01, 2.4893817863127474e+01, -2.4719846067215741e+01, 2.4536831517922678e+01, -2.4343879046261161e+01, 2.4139946442706947e+01, -2.3923809867873366e+01, 2.3694018337868730e+01, -2.3448832829669414e+01, 2.3186143264524166e+01, -2.2903352884404576e+01, 2.2597213200687420e+01, -2.2263581543490410e+01, 2.1897052704036881e+01, -2.1490376258452002e+01, 2.1033488463196051e+01, -2.0511802124949831e+01, 1.9902938183741984e+01, -1.9169784838249630e+01, 1.8243381633602635e+01, -1.6969663610835688e+01, 1.4853865657323199e+01}, + }, + { + n: 215, + theta: []float64{1.5707963267948970e+00, 1.5635071294265774e+00, 1.5562171573543853e+00, 1.5489256352155283e+00, 1.5416317863278686e+00, 1.5343348320264747e+00, 1.5270339909956290e+00, 1.5197284785947358e+00, 1.5124175061765652e+00, 1.5051002803962172e+00, 1.4977760025091564e+00, 1.4904438676566252e+00, 1.4831030641366665e+00, 1.4757527726589439e+00, 1.4683921655814558e+00, 1.4610204061271639e+00, 1.4536366475784541e+00, 1.4462400324472562e+00, 1.4388296916185130e+00, 1.4314047434645729e+00, 1.4239642929279310e+00, 1.4165074305695846e+00, 1.4090332315800915e+00, 1.4015407547502341e+00, 1.3940290413979675e+00, 1.3864971142481046e+00, 1.3789439762609288e+00, 1.3713686094056441e+00, 1.3637699733742550e+00, 1.3561470042311266e+00, 1.3484986129930978e+00, 1.3408236841345977e+00, 1.3331210740117563e+00, 1.3253896091989850e+00, 1.3176280847309516e+00, 1.3098352622422307e+00, 1.3020098679962364e+00, 1.2941505907942705e+00, 1.2862560797546649e+00, 1.2783249419510594e+00, 1.2703557398977969e+00, 1.2623469888692436e+00, 1.2542971540385393e+00, 1.2462046474198085e+00, 1.2380678245962331e+00, 1.2298849812145398e+00, 1.2216543492243999e+00, 1.2133740928389052e+00, 1.2050423041896758e+00, 1.1966569986471847e+00, 1.1882161097735477e+00, 1.1797174838712285e+00, 1.1711588740867926e+00, 1.1625379340239450e+00, 1.1538522108144755e+00, 1.1450991375893356e+00, 1.1362760252847235e+00, 1.1273800537096179e+00, 1.1184082617914692e+00, 1.1093575369055320e+00, 1.1002246031802951e+00, 1.0910060086563569e+00, 1.0816981111584627e+00, 1.0722970627198296e+00, 1.0627987923737243e+00, 1.0531989870988405e+00, 1.0434930706714529e+00, 1.0336761801375436e+00, 1.0237431395707643e+00, 1.0136884307255469e+00, 1.0035061601268345e+00, 9.9319002205615448e-01, 9.8273325679477930e-01, 9.7212860336429585e-01, 9.6136824585765468e-01, 9.5044375227267230e-01, 9.3934600453603823e-01, 9.2806511812722525e-01, 9.1659034936277461e-01, 9.0490998796145927e-01, 8.9301123195204102e-01, 8.8088004127013353e-01, 8.6850096546765831e-01, 8.5585693975662547e-01, 8.4292904202937069e-01, 8.2969620139991496e-01, 8.1613484599525521e-01, 8.0221847389993006e-01, 7.8791712589278207e-01, 7.7319673126791533e-01, 7.5801828762024459e-01, 7.4233682047111904e-01, 7.2610004657985516e-01, 7.0924663177187774e-01, 6.9170388348738865e-01, 6.7338463859636599e-01, 6.5418297798453884e-01, 6.3396818331389482e-01, 6.1257597533770669e-01, 5.8979538898074335e-01, 5.6534832806423441e-01, 5.3885616021897553e-01, 5.0978178458826395e-01, 4.7732114425933253e-01, 4.4017799165707200e-01, 3.9602210904493385e-01, 3.3984592786463697e-01, 2.5616262227240338e-01}, + val: []float64{-4.8194502666337268e-14, -1.8219292956257052e-14, 8.5393034645390052e-14, -9.3051784272423659e-14, 6.2263913433904649e-14, -7.2338165854311426e-14, -6.2580913476718581e-14, 8.2086154015730068e-14, -5.7165830534287467e-14, -3.5936383892293965e-14, -1.1380084519138131e-13, 9.4176333524136458e-14, 7.7406393378692183e-16, 3.0802286839980475e-15, -2.3573275472589349e-13, -1.3018327378045775e-13, 1.0520206501483371e-13, -6.2213644291038904e-14, 1.2145800400612989e-14, 2.7271297683652584e-14, -2.2535922871268711e-13, -7.6298928186738198e-14, 1.7255690675064885e-13, -9.0852635256292980e-14, -7.8101776477326909e-14, -8.6215405399587178e-14, 4.5189259409156241e-14, 1.6773935900994068e-13, 1.6659488983250428e-14, -2.3029664495695825e-14, 4.9882044749360307e-14, 1.1850055135335312e-13, -1.6889419531778083e-14, 7.5802404690310745e-14, 4.7496471682336465e-15, -6.0236075531674274e-14, -4.7790439973748918e-14, 1.0528243973915236e-14, 2.0302122716337677e-13, 4.8870674172048881e-14, 5.9145722182844837e-14, -3.6252017525118028e-14, 2.6839385139099395e-14, 7.8483748114372226e-14, -3.1698431394015554e-14, -3.7141479062747567e-14, 1.1275835568784933e-13, -4.4799710774576449e-14, -6.6076225108040054e-14, 4.9432907671096125e-14, -1.1915508175098585e-13, 7.1071624668919607e-14, 1.4874359999295257e-13, 4.9028118279404591e-14, 5.6995970859340297e-15, 1.8655926516135062e-14, 3.2409175615798361e-14, 7.1510069979380908e-14, -7.2558225742592175e-14, 4.1294505314113302e-14, -1.8304081875904709e-14, -4.6448090671875563e-14, 9.6949756857760571e-14, 1.1949578558177085e-14, 5.3441698191945163e-14, 4.9207462229933007e-14, -1.6005168277506475e-14, 8.2375100050737861e-15, 5.8811770905000782e-14, -3.8856969371752553e-15, 4.8345877891596704e-14, 9.6875037765842389e-14, 1.0795889278969854e-14, 2.7165003590955340e-14, 7.9664181703224841e-15, -3.1357633506603503e-14, 3.0114465704049404e-14, 5.4841606599486569e-14, 1.9665914005907120e-14, -2.8849555274550242e-14, -4.2752529356173103e-14, -8.5090430827758076e-15, 1.4753806570541977e-14, 4.1314792687095403e-15, 2.8114340045724569e-14, -8.9380771455156681e-15, 3.6308713608736668e-16, -4.9851972317585696e-14, -9.9115770904832069e-14, -1.2903366624947848e-14, 5.3938844852967152e-14, -3.7521135648997941e-14, 4.0086325460559029e-14, 8.9401622475124014e-15, -9.8967441436620103e-14, -6.5207531930586132e-14, 4.6622484011593159e-14, -1.7497072577375209e-14, 3.3453526916664849e-14, 4.8715471045751314e-14, 3.3943255654417215e-14, 5.7122398702729805e-15, -9.4574045519538209e-16, 7.2999684957756045e-15, 2.7503783126358897e-14, -7.8728766754343666e-15, 3.5695346037194369e-14, -6.2144904069338325e-14}, + dval: []float64{-2.9359856130945122e+01, 2.9359466144908321e+01, -2.9358296010652467e+01, 2.9356345199427643e+01, -2.9353612829040117e+01, 2.9350097662433203e+01, -2.9345798105693628e+01, 2.9340712205476311e+01, -2.9334837645838913e+01, 2.9328171744474844e+01, -2.9320711448331572e+01, 2.9312453328598878e+01, -2.9303393575049114e+01, 2.9293527989709105e+01, -2.9282851979841219e+01, 2.9271360550207469e+01, -2.9259048294588819e+01, 2.9245909386527547e+01, -2.9231937569258211e+01, 2.9217126144788914e+01, -2.9201467962090305e+01, 2.9184955404346880e+01, -2.9167580375219234e+01, 2.9149334284062515e+01, -2.9130208030040418e+01, 2.9110191985068738e+01, -2.9089275975516287e+01, 2.9067449262584439e+01, -2.9044700521279456e+01, 2.9021017817883422e+01, -2.8996388585821315e+01, 2.8970799599811929e+01, -2.8944236948180027e+01, 2.8916686003195352e+01, -2.8888131389291594e+01, 2.8858556949003940e+01, -2.8827945706448645e+01, 2.8796279828150276e+01, -2.8763540581003500e+01, 2.8729708287134510e+01, -2.8694762275403530e+01, 2.8658680829263389e+01, -2.8621441130659086e+01, 2.8583019199620328e+01, -2.8543389829161509e+01, 2.8502526515061934e+01, -2.8460401380051490e+01, 2.8416985091874288e+01, -2.8372246774642264e+01, 2.8326153912823038e+01, -2.8278672247129023e+01, 2.8229765661486780e+01, -2.8179396060166667e+01, 2.8127523234037294e+01, -2.8074104714780368e+01, 2.8019095615750661e+01, -2.7962448457994284e+01, 2.7904112979739949e+01, -2.7844035927448619e+01, 2.7782160826241114e+01, -2.7718427727214678e+01, 2.7652772928798939e+01, -2.7585128668881751e+01, 2.7515422783940377e+01, -2.7443578330833653e+01, 2.7369513166223744e+01, -2.7293139477783015e+01, 2.7214363260374000e+01, -2.7133083729234624e+01, 2.7049192660814349e+01, -2.6962573650237655e+01, 2.6873101272350418e+01, -2.6780640130847814e+01, 2.6685043776981328e+01, -2.6586153475654026e+01, 2.6483796792158806e+01, -2.6377785967154097e+01, 2.6267916040395356e+01, -2.6153962674834375e+01, 2.6035679621411987e+01, -2.5912795750458244e+01, 2.5785011557068451e+01, -2.5651995023754750e+01, 2.5513376692151542e+01, -2.5368743753874902e+01, 2.5217632914945817e+01, -2.5059521712941446e+01, 2.4893817863127481e+01, -2.4719846067215748e+01, 2.4536831517922678e+01, -2.4343879046261172e+01, 2.4139946442706954e+01, -2.3923809867873342e+01, 2.3694018337868730e+01, -2.3448832829669424e+01, 2.3186143264524159e+01, -2.2903352884404576e+01, 2.2597213200687420e+01, -2.2263581543490410e+01, 2.1897052704036888e+01, -2.1490376258451999e+01, 2.1033488463196083e+01, -2.0511802124949803e+01, 1.9902938183742044e+01, -1.9169784838249644e+01, 1.8243381633602628e+01, -1.6969663610835667e+01, 1.4853865657324123e+01}, + }, + { + n: 216, + theta: []float64{1.5671686105755729e+00, 1.5599127961686350e+00, 1.5526558355349958e+00, 1.5453969634500344e+00, 1.5381354130763418e+00, 1.5308704153134880e+00, 1.5236011981426352e+00, 1.5163269859644990e+00, 1.5090469989291080e+00, 1.5017604522557937e+00, 1.4944665555417909e+00, 1.4871645120577743e+00, 1.4798535180286077e+00, 1.4725327618975033e+00, 1.4652014235717277e+00, 1.4578586736478822e+00, 1.4505036726147191e+00, 1.4431355700313173e+00, 1.4357535036783504e+00, 1.4283565986800277e+00, 1.4209439665941588e+00, 1.4135147044676193e+00, 1.4060678938543345e+00, 1.3986025997926903e+00, 1.3911178697390723e+00, 1.3836127324540022e+00, 1.3760861968370792e+00, 1.3685372507066480e+00, 1.3609648595198076e+00, 1.3533679650280226e+00, 1.3457454838632317e+00, 1.3380963060489126e+00, 1.3304192934301153e+00, 1.3227132780159603e+00, 1.3149770602275335e+00, 1.3072094070434859e+00, 1.2994090500349611e+00, 1.2915746832807011e+00, 1.2837049611523335e+00, 1.2757984959588993e+00, 1.2678538554386305e+00, 1.2598695600848058e+00, 1.2518440802912205e+00, 1.2437758333013242e+00, 1.2356631799434625e+00, 1.2275044211328083e+00, 1.2192977941185159e+00, 1.2110414684522999e+00, 1.2027335416520410e+00, 1.1943720345310531e+00, 1.1859548861603062e+00, 1.1774799484271210e+00, 1.1689449801495315e+00, 1.1603476407006212e+00, 1.1516854830915373e+00, 1.1429559464555037e+00, 1.1341563478678038e+00, 1.1252838734282915e+00, 1.1163355685232694e+00, 1.1073083271723616e+00, 1.0981988803530085e+00, 1.0890037831801158e+00, 1.0797194008007944e+00, 1.0703418928435628e+00, 1.0608671962372638e+00, 1.0512910061865695e+00, 1.0416087550574320e+00, 1.0318155888861182e+00, 1.0219063411782010e+00, 1.0118755036074250e+00, 1.0017171931566209e+00, 9.9142511516121901e-01, 9.8099252161709072e-01, 9.7041216399420693e-01, 9.5967623965057169e-01, 9.4877633076008561e-01, 9.3770333444439402e-01, 9.2644738252057113e-01, 9.1499774892808761e-01, 9.0334274245922008e-01, 8.9146958185913860e-01, 8.7936424964779292e-01, 8.6701132009412707e-01, 8.5439375557323693e-01, 8.4149266395991695e-01, 8.2828700761781482e-01, 8.1475325173188318e-01, 8.0086493591225205e-01, 7.8659214774134534e-01, 7.7190086960046345e-01, 7.5675215971653753e-01, 7.4110111338801099e-01, 7.2489552835323978e-01, 7.0807416530075917e-01, 6.9056444397251160e-01, 6.7227933577676646e-01, 6.5311308498739518e-01, 6.3293517484306561e-01, 6.1158157942775537e-01, 5.8884165912926645e-01, 5.6443774724725360e-01, 5.3799179737419422e-01, 5.0896754324534177e-01, 4.7656218794974137e-01, 4.3948155571863207e-01, 3.9539936631707273e-01, 3.3931845258954985e-01, 2.5576413756997579e-01}, + val: []float64{6.1063360924047490e-11, -1.8435203658490556e-10, 3.0743162265786900e-10, -4.3161999307057153e-10, 5.5600184481941261e-10, -6.8154103751235407e-10, 8.0806640731641332e-10, -9.3648670703302450e-10, 1.0665511846836497e-09, -1.1984227187029326e-09, 1.3320294714997634e-09, -1.4683350272554789e-09, 1.6073141540400390e-09, -1.7488108299475996e-09, 1.8942373170611600e-09, -2.0425637634202854e-09, 2.1952560444756934e-09, -2.3517907718469464e-09, 2.5131243047743498e-09, -2.6788312866718815e-09, 2.8501736508238295e-09, -3.0272882762354559e-09, 3.2101466593235099e-09, -3.3995591281295402e-09, 3.5962230906180571e-09, -3.8005765479605162e-09, 4.0130477356611703e-09, -4.2339156669326267e-09, 4.4646349512119503e-09, -4.7049927091960580e-09, 4.9561002253847192e-09, -5.2191334055490069e-09, 5.4945583626542044e-09, -5.7832433193687254e-09, 6.0863314853460021e-09, -6.4051174909280434e-09, 6.7403553891566650e-09, -7.0933989938263408e-09, 7.4659234299589640e-09, -7.8591408458401506e-09, 8.2751055799843569e-09, -8.7148794606644850e-09, 9.1813301061361439e-09, -9.6760514978089342e-09, 1.0201632305616356e-08, -1.0760129925294149e-08, 1.1355163586751651e-08, -1.1989527720947381e-08, 1.2666360398983932e-08, -1.3390280463762196e-08, 1.4164961106968852e-08, -1.4995012747245716e-08, 1.5885976564229918e-08, -1.6843921766929025e-08, 1.7874947115661739e-08, -1.8986267082409428e-08, 2.0186191955347422e-08, -2.1484132370733845e-08, 2.2890126360750540e-08, -2.4415809556224372e-08, 2.6074391376958674e-08, -2.7880720950296676e-08, 2.9852038341333996e-08, -3.2007470796983141e-08, 3.4369209413828328e-08, -3.6962720963996261e-08, 3.9816961736227733e-08, -4.2965941232291533e-08, 4.6448638367911141e-08, -5.0310249303133202e-08, 5.4604204622873211e-08, -5.9392177920227513e-08, 6.4747522871256546e-08, -7.0756457006013807e-08, 7.7521575966439530e-08, -8.5165469547851754e-08, 9.3834858505459719e-08, -1.0370708662191418e-07, 1.1499734508496046e-07, -1.2796816261852297e-07, 1.4294288769073078e-07, -1.6032201969864769e-07, 1.8060502833216690e-07, -2.0442120587020166e-07, 2.3256958638562142e-07, -2.6607532013847684e-07, 3.0626738095928866e-07, -3.5488829260119791e-07, 4.1425182777935264e-07, -4.8747349724306658e-07, 5.7881217418665015e-07, -6.9418829303134906e-07, 8.4198941248161877e-07, -1.0343491900465793e-06, 1.2892453275257475e-06, -1.6340426463170451e-06, 2.1117130712431397e-06, -2.7922162634453614e-06, 3.7943899196860205e-06, -5.3305886421188924e-06, 7.8043580879824044e-06, -1.2043461755474721e-05, 1.9919842840142057e-05, -3.6251001189673213e-05, 7.5884216611786810e-05, -1.9885074842226311e-04, 7.9195669340038259e-04, -1.8028552886227383e-09}, + dval: []float64{-2.9427800603424885e+01, 2.9427025985916121e+01, -2.9425476404186753e+01, 2.9423151164251298e+01, -2.9420049223750460e+01, 2.9416169190288226e+01, -2.9411509319206207e+01, 2.9406067510787029e+01, -2.9399841306877359e+01, 2.9392827886918830e+01, -2.9385024063373031e+01, 2.9376426276524445e+01, -2.9367030588643040e+01, 2.9356832677485638e+01, -2.9345827829112856e+01, 2.9334010929995458e+01, -2.9321376458381245e+01, 2.9307918474890496e+01, -2.9293630612304742e+01, 2.9278506064510260e+01, -2.9262537574553473e+01, 2.9245717421762187e+01, -2.9228037407881232e+01, 2.9209488842167364e+01, -2.9190062525382210e+01, 2.9169748732617208e+01, -2.9148537194877900e+01, 2.9126417079348521e+01, -2.9103376968250728e+01, 2.9079404836201942e+01, -2.9054488025970496e+01, 2.9028613222515041e+01, -2.9001766425185139e+01, 2.8973932917948382e+01, -2.8945097237496739e+01, 2.8915243139070405e+01, -2.8884353559822184e+01, 2.8852410579527451e+01, -2.8819395378426641e+01, 2.8785288191964121e+01, -2.8750068262165129e+01, 2.8713713785364632e+01, -2.8676201855972838e+01, 2.8637508405928582e+01, -2.8597608139454216e+01, 2.8556474462684317e+01, -2.8514079407692357e+01, 2.8470393550387154e+01, -2.8425385921689980e+01, 2.8379023911335469e+01, -2.8331273163562241e+01, 2.8282097463870919e+01, -2.8231458615927721e+01, 2.8179316307577007e+01, -2.8125627964795978e+01, 2.8070348592274335e+01, -2.8013430599129791e+01, 2.7954823608071283e+01, -2.7894474246092045e+01, 2.7832325914509102e+01, -2.7768318535855649e+01, 2.7702388274772812e+01, -2.7634467229625290e+01, 2.7564483091071313e+01, -2.7492358763234872e+01, 2.7418011942441147e+01, -2.7341354647661582e+01, 2.7262292695845463e+01, -2.7180725114157759e+01, 2.7096543479754125e+01, -2.7009631176051933e+01, 2.6919862552432274e+01, -2.6827101971847423e+01, 2.6731202727801637e+01, -2.6632005808479860e+01, 2.6529338481236699e+01, -2.6423012664989045e+01, 2.6312823050968596e+01, -2.6198544923370154e+01, 2.6079931620126878e+01, -2.5956711559610614e+01, 2.5828584740479602e+01, -2.5695218597789456e+01, 2.5556243066913400e+01, -2.5411244665072719e+01, 2.5259759344501671e+01, -2.5101263795907457e+01, 2.4935164777812641e+01, -2.4760785904535670e+01, 2.4577351124781824e+01, -2.4383963836126313e+01, 2.4179580164227872e+01, -2.3962974319140965e+01, 2.3732693009179656e+01, -2.3486994450692443e+01, 2.3223765221215142e+01, -2.2940404454619134e+01, 2.2633658531147908e+01, -2.2299378247064869e+01, 2.1932149880547183e+01, -2.1524711604262862e+01, 2.1066983867982440e+01, -2.0544356598262947e+01, 1.9934415682618429e+01, -1.9199991275984207e+01, 1.8272015227078569e+01, -1.6996182114611788e+01, 1.4876958810870860e+01}, + }, + { + n: 216, + theta: []float64{1.5671686105755023e+00, 1.5599127961684220e+00, 1.5526558355346407e+00, 1.5453969634495357e+00, 1.5381354130756992e+00, 1.5308704153127000e+00, 1.5236011981417006e+00, 1.5163269859634152e+00, 1.5090469989278730e+00, 1.5017604522544048e+00, 1.4944665555402459e+00, 1.4871645120560699e+00, 1.4798535180267400e+00, 1.4725327618954691e+00, 1.4652014235695219e+00, 1.4578586736455008e+00, 1.4505036726121565e+00, 1.4431355700285682e+00, 1.4357535036754083e+00, 1.4283565986768869e+00, 1.4209439665908115e+00, 1.4135147044640579e+00, 1.4060678938505511e+00, 1.3986025997886760e+00, 1.3911178697348172e+00, 1.3836127324494960e+00, 1.3760861968323106e+00, 1.3685372507016056e+00, 1.3609648595144777e+00, 1.3533679650223920e+00, 1.3457454838572851e+00, 1.3380963060426339e+00, 1.3304192934234869e+00, 1.3227132780089634e+00, 1.3149770602201478e+00, 1.3072094070356892e+00, 1.2994090500267301e+00, 1.2915746832720101e+00, 1.2837049611431546e+00, 1.2757984959492026e+00, 1.2678538554283829e+00, 1.2598695600739727e+00, 1.2518440802797628e+00, 1.2437758332892002e+00, 1.2356631799306261e+00, 1.2275044211192108e+00, 1.2192977941041021e+00, 1.2110414684370108e+00, 1.2027335416358120e+00, 1.1943720345138122e+00, 1.1859548861419755e+00, 1.1774799484076148e+00, 1.1689449801287550e+00, 1.1603476406784692e+00, 1.1516854830678944e+00, 1.1429559464302423e+00, 1.1341563478407819e+00, 1.1252838733993509e+00, 1.1163355684922343e+00, 1.1073083271390356e+00, 1.0981988803171721e+00, 1.0890037831415225e+00, 1.0797194007591668e+00, 1.0703418927985888e+00, 1.0608671961885900e+00, 1.0512910061337959e+00, 1.0416087550001036e+00, 1.0318155888237164e+00, 1.0219063411101317e+00, 1.0118755035330074e+00, 1.0017171930750695e+00, 9.9142511507162645e-01, 9.8099252151840288e-01, 9.7041216388519547e-01, 9.5967623952979786e-01, 9.4877633062585665e-01, 9.3770333429470865e-01, 9.2644738235305046e-01, 9.1499774873988793e-01, 9.0334274224692235e-01, 8.9146958161860457e-01, 8.7936424937397950e-01, 8.6701131978084423e-01, 8.5439375521282512e-01, 8.4149266354281749e-01, 8.2828700713198744e-01, 8.1475325116200825e-01, 8.0086493523862246e-01, 7.8659214693830359e-01, 7.7190086863415974e-01, 7.5675215854165734e-01, 7.4110111194290051e-01, 7.2489552655247935e-01, 7.0807416302356885e-01, 6.9056444104412407e-01, 6.7227933193754241e-01, 6.5311307983969791e-01, 6.3293516775593595e-01, 6.1158156935716357e-01, 5.8884164425859431e-01, 5.6443772421506910e-01, 5.3799175946275157e-01, 5.0896747562778555e-01, 4.7656205323872197e-01, 4.3948124005672007e-01, 3.9539840620540745e-01, 3.3931369540774287e-01, 2.5576413755369809e-01}, + val: []float64{-2.1420664007171084e-13, 5.3170379037842784e-14, -3.4734236933038639e-15, 2.3242110868118431e-13, 3.7943143720204046e-14, -5.7160511614569708e-14, 2.1177269961331864e-13, -3.4948583926844979e-14, 1.7369271883827313e-13, 3.5623756291990570e-13, 6.5520118362261941e-14, 1.1255590127344777e-13, 9.4867994932892441e-14, -6.1601712969494469e-14, 4.7023788875015558e-14, -1.4272998866826663e-13, -2.6605445153274162e-14, -2.5223571223200907e-13, -1.3724084095111965e-13, -7.0111736669803626e-14, 5.7347666545680944e-14, -5.0924962889888544e-14, -5.2683776576685045e-15, -2.1544335394504838e-13, 4.0230445264824984e-15, 6.9175538975130938e-15, -1.1339463388095042e-13, -3.9896959286779273e-14, -8.8360560296236634e-14, -1.0474371284611670e-13, 1.2687327963040444e-14, -1.7782734520430910e-13, 2.0086781777635686e-13, -7.5400883703521135e-14, 1.2278140016266356e-13, -1.1244970732922019e-13, 1.6072100253117342e-14, 5.2340169298568757e-15, 1.1013085876614924e-13, -9.6621831158318670e-15, -1.8366177977891496e-13, 1.0601073284832238e-14, -1.3784763212103856e-13, -1.5863525424166753e-13, -1.6638681463670250e-13, 8.6360908147481066e-14, -7.8672683965135368e-14, 6.8378486764803313e-14, 9.0534733729868808e-14, 6.6505185887739604e-15, 3.3141885340142080e-15, -2.0537396911778824e-13, 7.3393589371575821e-14, 9.8483281662822096e-14, -2.3812738806298458e-13, 6.5975425886450090e-15, 8.7013139463913052e-14, 7.5278742714453987e-14, -1.0708940266003440e-13, 2.0958580081069137e-13, -1.5480716019053119e-14, 4.8469624575186930e-15, -6.1362291991375536e-14, -3.5942923464396180e-14, -7.6176865685553763e-14, 1.0095757892256693e-13, -4.2683956504767779e-14, -4.8938621882647329e-14, 1.6489272569372713e-15, -1.1390338364880240e-13, 2.1513601964632049e-14, -1.0152923724696736e-14, -3.9597826958407387e-14, -8.5123156147931521e-14, -6.5276802085245163e-14, 6.3966825794140229e-14, -2.8207572680644779e-14, -5.9767990455898208e-15, -1.1189271498293956e-13, -4.5600777141900301e-14, 1.5226732724861721e-14, 3.9473540473700922e-14, -5.6017378761616795e-15, -2.4079255903843183e-14, -3.1139558336514997e-14, -5.6034014603771978e-14, 6.9309294575728887e-14, -3.7871955014469560e-14, 4.2988763678275364e-14, 1.0661412180664073e-14, 6.2069599395465107e-14, -4.8913422170368503e-14, 3.3884911719768557e-14, 2.8191908465098299e-15, 2.1228960171536080e-14, -5.6191478942893769e-14, -1.4786950368470112e-14, -2.1665036441200809e-14, 1.4936420829725019e-14, -1.1615745673091571e-13, 1.4661728300981146e-13, -3.6088669931521093e-13, 1.1825080499589470e-12, -4.7300739521811106e-12, 2.5459387908526307e-11, -2.2842779135337983e-10, 5.3230524570865730e-09, 1.8504694403187737e-14}, + dval: []float64{-2.9427800603424888e+01, 2.9427025985916128e+01, -2.9425476404186732e+01, 2.9423151164251305e+01, -2.9420049223750453e+01, 2.9416169190288219e+01, -2.9411509319206210e+01, 2.9406067510787015e+01, -2.9399841306877356e+01, 2.9392827886918813e+01, -2.9385024063373031e+01, 2.9376426276524445e+01, -2.9367030588643043e+01, 2.9356832677485624e+01, -2.9345827829112846e+01, 2.9334010929995465e+01, -2.9321376458381234e+01, 2.9307918474890485e+01, -2.9293630612304742e+01, 2.9278506064510257e+01, -2.9262537574553480e+01, 2.9245717421762187e+01, -2.9228037407881235e+01, 2.9209488842167364e+01, -2.9190062525382206e+01, 2.9169748732617215e+01, -2.9148537194877896e+01, 2.9126417079348521e+01, -2.9103376968250736e+01, 2.9079404836201938e+01, -2.9054488025970500e+01, 2.9028613222515034e+01, -2.9001766425185131e+01, 2.8973932917948375e+01, -2.8945097237496743e+01, 2.8915243139070423e+01, -2.8884353559822181e+01, 2.8852410579527444e+01, -2.8819395378426645e+01, 2.8785288191964142e+01, -2.8750068262165122e+01, 2.8713713785364636e+01, -2.8676201855972852e+01, 2.8637508405928578e+01, -2.8597608139454227e+01, 2.8556474462684314e+01, -2.8514079407692350e+01, 2.8470393550387161e+01, -2.8425385921689987e+01, 2.8379023911335462e+01, -2.8331273163562233e+01, 2.8282097463870926e+01, -2.8231458615927728e+01, 2.8179316307577018e+01, -2.8125627964795974e+01, 2.8070348592274335e+01, -2.8013430599129794e+01, 2.7954823608071287e+01, -2.7894474246092045e+01, 2.7832325914509109e+01, -2.7768318535855656e+01, 2.7702388274772812e+01, -2.7634467229625294e+01, 2.7564483091071331e+01, -2.7492358763234883e+01, 2.7418011942441158e+01, -2.7341354647661582e+01, 2.7262292695845463e+01, -2.7180725114157763e+01, 2.7096543479754128e+01, -2.7009631176051940e+01, 2.6919862552432292e+01, -2.6827101971847430e+01, 2.6731202727801641e+01, -2.6632005808479885e+01, 2.6529338481236724e+01, -2.6423012664989066e+01, 2.6312823050968632e+01, -2.6198544923370196e+01, 2.6079931620126928e+01, -2.5956711559610671e+01, 2.5828584740479652e+01, -2.5695218597789530e+01, 2.5556243066913513e+01, -2.5411244665072843e+01, 2.5259759344501834e+01, -2.5101263795907666e+01, 2.4935164777812918e+01, -2.4760785904536036e+01, 2.4577351124782325e+01, -2.4383963836127013e+01, 2.4179580164228856e+01, -2.3962974319142369e+01, 2.3732693009181720e+01, -2.3486994450695558e+01, 2.3223765221219963e+01, -2.2940404454626893e+01, 2.2633658531160954e+01, -2.2299378247087898e+01, 2.1932149880590437e+01, -2.1524711604350518e+01, 2.1066983868178077e+01, -2.0544356598759389e+01, 1.9934415684120079e+01, -1.9199991281861426e+01, 1.8272015261833435e+01, -1.6996182557157578e+01, 1.4876958810870862e+01}, + }, + } { + got := make([]float64, len(test.theta)) + gotD := make([]float64, len(test.theta)) + for i := range got { + got[i], gotD[i] = Hermite{}.hermpolyAsyAiry(i, test.n, test.theta[i]) + } + if !floats.EqualApprox(test.val, got, 1e-12) { + t.Errorf("n = %v, hermpolyAsyAiry mismatch", test.n) + } + if !floats.EqualApprox(test.dval, gotD, 1e-12) { + t.Errorf("n = %v, hermpolyAsyAiry deriv mismatch", test.n) + } + } +} diff --git a/integrate/quad/internal/PrintGoSlice.m b/integrate/quad/internal/PrintGoSlice.m new file mode 100644 index 00000000..d3a51b28 --- /dev/null +++ b/integrate/quad/internal/PrintGoSlice.m @@ -0,0 +1,11 @@ +% Copyright 2016 The gonum Authors. All rights reserved. +% Use of this source code is governed by a BSD-style +% license that can be found in the LICENSE file. + +function PrintGoSlice(a) + fprintf('[]float64{') + for i = 1:length(a) + fprintf('%1.16e, ',a(i)) + end + fprintf('}\n') +end \ No newline at end of file diff --git a/integrate/quad/internal/genherm.m b/integrate/quad/internal/genherm.m new file mode 100644 index 00000000..f673f97d --- /dev/null +++ b/integrate/quad/internal/genherm.m @@ -0,0 +1,32 @@ +% Copyright 2016 The gonum Authors. All rights reserved. +% Use of this source code is governed by a BSD-style +% license that can be found in the LICENSE file. + +clc +clear all +close all + +% Generate herm points +min = 216; +max = 216; +fprintf('xCache = [][]float64{\n') +for i = min:max + [x,w] = hermpts(i); + fprintf('{') + for j = 1:i-1 + fprintf('%1.16e, ',x(j)) + end + fprintf('%1.16e},\n',x(i)) +end +fprintf('}\n') + +fprintf('wCache = [][]float64{\n') +for i = min:max + [x,w] = hermpts(i); + fprintf('{') + for j = 1:i-1 + fprintf('%1.16e, ',w(j)) + end + fprintf('%1.16e},\n',w(i)) +end +fprintf('}\n') diff --git a/integrate/quad/internal/hermpts.m b/integrate/quad/internal/hermpts.m new file mode 100644 index 00000000..9306ad60 --- /dev/null +++ b/integrate/quad/internal/hermpts.m @@ -0,0 +1,609 @@ +% Copyright (c) 2015, The Chancellor, Masters and Scholars of the University +% of Oxford, and the Chebfun Developers. +% Copyright (c) 2016 The gonum Authors +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% * Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% * Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% * Neither the name of the University of Oxford nor the names of its +% contributors may be used to endorse or promote products derived from +% this software without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +% ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +% WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +% DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +% ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +% ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +function [x, w, v] = hermpts(n, varargin) +%HERMPTS Hermite points and Gauss-Hermite Quadrature Weights. +% HERMPTS(N) returns N Hermite points X in (-inf, inf). By default these are +% roots of the 'physicist'-type Hermite polynomials, which are orthogonal with +% respect to the weight exp(-x.^2). +% +% HERMPTS(N, 'PROB') normalises instead by the probablist's definition (with +% weight exp(-x.^2/2)), which gives rise to monomials. +% +% [X, W] = HERMPTS(N) returns also a row vector W of weights for Gauss-Hermite +% quadrature. [X,W,V] = HERMPTS(N) returns in addition a column vector V of +% the barycentric weights corresponding to X. +% +% [X, W] = HERMPTS(N, METHOD) where METHOD is one of 'GW', 'REC', 'GLR', or +% 'ASY' allows the user to select which method is used. 'GW' will use the +% traditional Golub-Welsch eigenvalue method [1], best when n<=20. 'REC' +% uses Newton's method with polynomial evaluation via the 3-term +% recurrence for Hermite polynomials. 'GLR' uses Glaser-Liu-Rokhlin +% fast algorithm which is much faster for large N [2]. 'ASY' uses Newton's +% method with polynomial evaluation via asymptotic formula. 'ASY' is the +% fastest for N>=200, 'GLR' is the most accurate for nodes close to 0. +% By default HERMPTS uses 'GW' when N <= 20, 'REC' for 21<=N<200, and +% 'ASY' when N>=200. +% +% References: +% [1] G. H. Golub and J. A. Welsch, "Calculation of Gauss quadrature +% rules", Math. Comp. 23:221-230, 1969, +% [2] A. Glaser, X. Liu and V. Rokhlin, "A fast algorithm for the +% calculation of the roots of special functions", SIAM Journal +% on Scientific Computing", 29(4):1420-1438:, 2007. +% [3] A. Townsend, T. Trogdon and S. Olver, Fast computation of Gauss +% nodes and weights on the whole real line, submitted, 2014. +% +% See also CHEBPTS, LEGPTS, LAGPTS, and JACPTS. + +% Copyright 2015 by The University of Oxford and The Chebfun Developers. +% See http://www.chebfun.org/ for Chebfun information. +% +% 'GW' by Nick Trefethen, March 2009 - algorithm adapted from [1]. +% 'GLR' by Nick Hale, March 2010 - algorithm adapted from [2]. + +% Defaults: +method = 'default'; +type = 'phys'; + +if ( n < 0 ) + error('CHEBFUN:hermpts:n', 'First input should be a positive integer.'); +end + +% Return empty vector if n = 0. +if ( n == 0 ) + [x, w, v] = deal([]); + return +end + +% Check the inputs +while ( ~isempty(varargin) ) + s = varargin{1}; + varargin(1) = []; + if ( strcmpi(s, 'GW') ) + method = 'GW'; + elseif ( strcmpi(s,'glr') ) + method = 'GLR'; + elseif ( strcmpi(s,'rec') ) + method = 'REC'; + elseif ( strcmpi(s,'asy') ) + method = 'ASY'; + elseif ( strncmpi(s, 'phys', 3) ) + type = 'phys'; + elseif ( strncmpi(s, 'prob', 3) ) + type = 'prob'; + else + error('CHEBFUN:hermpts:input', 'Unrecognised input string; %s.', s); + end +end + +% Three cases: +% +% N <= 20: Use GW +% 21<=N<200: Use REC +% N>=200: Use ASY +if ( n == 1 ) + % n = 1 case is trivial + x = 0; + w = sqrt(pi); + v = 1; + +elseif ( (n < 21 && strcmpi(method,'default')) || strcmpi(method,'GW') ) + % GW, see [1] + + beta = sqrt(.5*(1:n-1)); % 3-term recurrence coeffs + T = diag(beta, 1) + diag(beta, -1); % Jacobi matrix + [V, D] = eig(T); % Eigenvalue decomposition + [x, indx] = sort(diag(D)); % Hermite points + w = sqrt(pi)*V(1, indx).^2; % weights + v = abs(V(1, indx)).'; % Barycentric weights + v = v./max(v); % Normalize + v(2:2:n) = -v(2:2:n); + + % Enforce symmetry: + ii = 1:floor(n/2); + x = x(ii); + w = w(ii); + vmid = v(floor(n/2)+1); + v = v(ii); + if ( mod(n, 2) ) + x = [x ; 0 ; -x(end:-1:1)]; + w = [w, sqrt(pi) - sum(2*w), w(end:-1:1)]; + v = [v ; vmid ; v(end:-1:1)]; + else + x = [x ; -x(end:-1:1)]; + w = [w, w(end:-1:1)]; + v = [v ; -v(end:-1:1)]; + end + +elseif ( strcmpi(method,'GLR') ) + % Fast, see [2] + + [x, ders] = alg0_Herm(n); % Nodes and H_n'(x) + w = (2*exp(-x.^2)./ders.^2)'; % Quadrature weights + v = exp(-x.^2/2)./ders; % Barycentric weights + v = v./max(abs(v)); % Normalize + if ( ~mod(n, 2) ) + ii = (n/2+1):n; + v(ii) = -v(ii); + end + +elseif ( (n < 200 && strcmpi(method,'default')) || strcmpi(method,'REC') ) + + [x, w, v] = hermpts_rec( n ); + +else + + [x, w, v] = hermpts_asy( n ); + +end + +% Normalise so that sum(w) = sqrt(pi) +w = (sqrt(pi)/sum(w))*w; + +if ( strcmpi(type, 'prob') ) + x = x*sqrt(2); + w = w*sqrt(2); +end + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %%%%%%%%%%%%%%%%%%%%%%% Routines for GLR algorithm %%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Driver for 'GLR'. +function [roots, ders] = alg0_Herm(n) +% Compute coefficients of H_m(0), H_m'(0), m = 0,..,N. + +Hm2 = 0; +Hm1 = pi^(-1/4); +Hpm2 = 0; +Hpm1 = 0; +for k = 0:n-1 + H = -sqrt(k/(k+1))*Hm2; + Hp = sqrt(2/(k+1))*Hm1-sqrt(k/(k+1))*Hpm2; + Hm2 = Hm1; + Hm1 = H; + Hpm2 = Hpm1; + Hpm1 = Hp; +end + +% allocate storage +roots = zeros(n, 1); +ders = zeros(n, 1); +if ( mod(n,2) ) + % zero is a root: + roots((n-1)/2) = 0; + ders((n+1)/2) = Hp; +else + % find first root: + [roots(n/2+1), ders(n/2+1)] = alg2_Herm(H,n); +end + +% compute roots and derivatives: +[roots, ders] = alg1_Herm(roots, ders); + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Main algorithm for 'GLR' +function [roots, ders] = alg1_Herm(roots, ders) + +n = length(roots); +s = mod(n, 2); +N = (n - s) / 2; + +% number of terms in Taylor expansion +m = 30; + +% initialise +hh1 = ones(m + 1, 1); +u = zeros(1, m + 1); +up = zeros(1, m + 1); + +for j = (N + 1):(n - 1) + + % previous root + x = roots(j); + + % initial approx + h = rk2_Herm(pi/2,-pi/2,x,n) - x; + + % scaling + M = 1/h; + + % recurrence relation for Hermite polynomials + c1 = -(2*n+1-x^2)/M^2; + c2 = 2*x./M^3; + c3 = 1./M^4; + u(1) = 0; + u(2) = ders(j)/M; + u(3) = .5*c1*u(1); + u(4) = (c1*u(2) + c2*u(1))/6; + up(1) = u(2); + up(2) = 2*u(3)*M; + up(3) = 3*u(4)*M; + up(m+1) = 0; + + for k = 2:m-2 + u(k+3) = (c1*u(k+1) + c2*u(k) + c3*u(k-1))/((k+1)*(k+2)); + up(k+2) = (k+2)*u(k+3)*M; + end + + % flip for more accuracy in inner product calculation + u = u(m+1:-1:1); + up = up(m+1:-1:1); + + % Newton iteration + hh = hh1; + hh(end) = M; + step = inf; + l = 0; + z = zeros(m, 1); + while ( (abs(step) > eps) && (l < 10) ) + l = l + 1; + step = (u*hh)/(up*hh); + h = h - step; + % powers of h (This is the fastest way!) + hh = [M ; cumprod(M*h + z)]; + % flip for more accuracy in inner product calculation + hh = hh(end:-1:1); + end + + % update + roots(j+1) = x + h; + ders(j+1) = up*hh; +end + +% nodes are symmetric +roots(1:N+s) = -roots(n:-1:N+1); +ders(1:N+s) = ders(n:-1:N+1); + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% find the first root (note H_n'(0) = 0) +function [x1, d1] = alg2_Herm(Hn0, n) + +% advance ODE via Runge-Kutta for initial approx +x1 = rk2_Herm(0, -pi/2, 0, n); + +% number of terms in Taylor expansion +m = 30; + +% scaling +M = 1/x1; +% c = log10(n); +% M = 1./x1.^(1-1.25/(c)); + +% initialise +u = zeros(1,m+1); +up = zeros(1,m+1); + +% recurrence relation for Legendre polynomials +u(1) = Hn0; +u(3) = -.5*(2*n+1)*u(1)/M^2; +up(1) = 0; +up(2) = 2*u(3)*M; +for k = 2:2:m-2 + u(k+3) = (-(2*n+1)*u(k+1)/M^2 + u(k-1)/M^4)/((k+1)*(k+2)); + up(k+2) = (k+2)*u(k+3)*M; +end + +% flip for more accuracy in inner product calculation +u = u(m+1:-1:1); +up = up(m+1:-1:1); + +z = zeros(m, 1); +x1k = [M ; cumprod(M*x1 + z)]; +step = inf; +l = 0; +% Newton iteration +while ( (abs(step) > eps) && (l < 10) ) + l = l + 1; + step = (u*x1k)/(up*x1k); + x1 = x1 - step; + % powers of h (This is the fastest way!) + x1k = [1 ; cumprod(M*x1 + z)]; + x1k = x1k(end:-1:1); +end + +% Update derivative +d1 = up*x1k; + +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Runge-Kutta for Hermite Equation +function x = rk2_Herm(t, tn, x, n) +m = 10; +h = (tn-t)/m; +for j = 1:m + k1 = -h/(sqrt(2*n+1-x^2) - .5*x*sin(2*t)/(2*n+1-x^2)); + t = t + h; + k2 = -h/(sqrt(2*n+1-(x+k1)^2) - .5*x*sin(2*t)/(2*n+1-(x+k1)^2)); + x = x + .5*(k1 + k2); +end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %%%%%%%%%%%%%%%%%%%%%%% Routines for ASY algorithm %%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [x, w, v] = hermpts_asy(n) +% HERMPTS_ASY, fast algorithm for computing Gauss-Hermite nodes and weights +% using Newton's method with polynomial evaluation via asymptotic expansions. +% +% x = Gauss-Hermite nodes, w = quad weights, v = bary weights. +% +% See [3]. + +[x, w, v] = hermpts_asy0( n ); + +if mod(n,2) == 1 % fold out + x = [-x(end:-1:1);x(2:end)]; + w = [w(end:-1:1) w(2:end)]; w = (sqrt(pi)/sum(w))*w; + v = [v(end:-1:1);v(2:end)]; v = v./max(abs(v)); +else + x = [-x(end:-1:1);x]; + w = [w(end:-1:1) w]; w = (sqrt(pi)/sum(w))*w; + v = [v(end:-1:1);-v]; v = v./max(abs(v)); +end + +% debug +%tic, exact = hermpts(n); toc +%semilogy(abs(exact-x)) +end + +function [x, w, v] = hermpts_asy0(n) +% Compute Hermite nodes and weights using asymptotic formula + +x0 = HermiteInitialGuesses(n); % get initial guesses +t0 = x0./sqrt(2*n+1); +theta0 = acos(t0); % convert to theta-variable +for k = 1:20 + [val, dval] = hermpoly_asy_airy(n, theta0); + dt = -val./(sqrt(2)*sqrt(2*n+1)*dval.*sin(theta0)); + theta0 = theta0 - dt; % Newton update + if norm(dt,inf) < sqrt(eps)/10, break; end +end +t0 = cos(theta0); +x = sqrt(2*n+1)*t0; % back to x-variable + +ders = x.*val + sqrt(2)*dval; +%ders = dval; +w = (exp(-x.^2)./ders.^2)'; % quadrature weights + +v = exp(-x.^2/2)./ders; % Barycentric weights +end + +function [val, dval] = hermpoly_asy_airy(n, theta) +% HERMPOLY_ASY evaluation hermite poly using Airy asymptotic formula in +% theta-space. + +musq = 2*n+1; +cosT = cos(theta); sinT = sin(theta); +sin2T = 2*cosT.*sinT; +eta = .5*theta - .25*sin2T; +chi = -(3*eta/2).^(2/3); +phi = (-chi./sinT.^2).^(1/4); +const = 2*sqrt(pi)*musq^(1/6)*phi; +Airy0 = real(airy(musq.^(2/3)*chi)); +Airy1 = real(airy(1,musq.^(2/3)*chi)); + +% Terms in (12.10.43): +a0 = 1; b0 = 1; +a1 = 15/144; b1 = -7/5*a1; +a2 = 5*7*9*11/2/144^2; b2 = -13/11*a2; +a3 = 7*9*11*13*15*17/6/144^3; +b3 = -19/17*a3; + +% u polynomials in (12.10.9) +u0 = 1; u1 = (cosT.^3-6*cosT)/24; +u2 = (-9*cosT.^4 + 249*cosT.^2 + 145)/1152; +u3 = (-4042*cosT.^9+18189*cosT.^7-28287*cosT.^5-151995*cosT.^3-259290*cosT)/414720; + +%first term +A0 = 1; +val = A0*Airy0; + +%second term +B0 = -(a0*phi.^6.*u1+a1*u0)./chi.^2; +val = val + B0.*Airy1./musq.^(4/3); + +%third term +A1 = (b0*phi.^12.*u2 + b1*phi.^6.*u1 + b2*u0)./chi.^3; +val = val + A1.*Airy0/musq.^2; + +%fourth term +B1 = -(phi.^18.*u3 + a1*phi.^12.*u2 + a2*phi.^6.*u1 + a3*u0)./chi.^5; +val = val + B1.*Airy1./musq.^(4/3+2); + +val = const.*val; + +%% Derivative + +eta = .5*theta - .25*sin2T; +chi = -(3*eta/2).^(2/3); +phi = (-chi./sinT.^2).^(1/4); +const = sqrt(2*pi)*musq^(1/3)./phi; + +% v polynomials in (12.10.10) +v0 = 1; v1 = (cosT.^3+6*cosT)/24; +v2 = (15*cosT.^4-327*cosT.^2-143)/1152; +v3 = (259290*cosT + 238425*cosT.^3 - 36387*cosT.^5 + 18189*cosT.^7 -... + 4042*cosT.^9)/414720; + +%first term +C0 = -(b0*phi.^6.*v1 + b1.*v0)./chi; +dval = C0.*Airy0/musq.^(2/3); + +% %second term +D0 = a0*v0; +dval = dval + D0*Airy1; + +% %third term +C1 = -(phi.^18.*v3 + b1*phi.^12.*v2 + b2*phi.^6.*v1 + b3*v0)./chi.^4; +dval = dval + C1.*Airy0/musq.^(2/3+2); + +%fourth term +D1 = (a0*phi.^12.*v2 + a1*phi.^6.*v1 + a2*v0)./chi.^3; +dval = dval + D1.*Airy1/musq.^2; + +dval = const.*dval; + +end + +function x_init = HermiteInitialGuesses(n) +%HERMITEINTITIALGUESSES(N), Initial guesses for Hermite zeros. +% +% [1] L. Gatteschi, Asymptotics and bounds for the zeros of Laguerre +% polynomials: a survey, J. Comput. Appl. Math., 144 (2002), pp. 7-27. +% +% [2] F. G. Tricomi, Sugli zeri delle funzioni di cui si conosce una +% rappresentazione asintotica, Ann. Mat. Pura Appl. 26 (1947), pp. 283-300. + +% Gatteschi formula involving airy roots [1]. +% These initial guess are good near x = sqrt(n+1/2); +if mod(n,2) == 1 + m = (n-1)/2; bess = (1:m)'*pi; a = .5; +else + m = n/2; bess = ((0:m-1)'+.5)*pi; a = -.5; +end +nu = 4*m + 2*a + 2; +T = @(t) t.^(2/3).*(1+5/48*t.^(-2)-5/36*t.^(-4)+(77125/82944)*t.^(-6) -... + 108056875/6967296*t.^(-8)+162375596875/334430208*t.^(-10)); +airyrts = -T(3/8*pi*(4*(1:m)'-1)); + +airyrts_exact = [ -2.338107410459762 % Exact Airy roots. + -4.087949444130970 + -5.520559828095555 + -6.786708090071765 + -7.944133587120863 + -9.022650853340979 + -10.040174341558084 + -11.008524303733260 + -11.936015563236262 + -12.828776752865757]; +airyrts(1:10) = airyrts_exact; % correct first 10. + +x_init = sqrt(nu + 2^(2/3)*airyrts*nu^(1/3) +... + 1/5*2^(4/3)*airyrts.^2*nu^(-1/3) +... + (11/35-a^2-12/175*airyrts.^3)/nu +... + (16/1575*airyrts+92/7875*airyrts.^4)*2^(2/3)*nu^(-5/3) -... + (15152/3031875*airyrts.^5+1088/121275*airyrts.^2)*2^(1/3)*nu^(-7/3)); +x_init_airy = real(x_init(end:-1:1)); + +% Tricomi initial guesses. Equation (2.1) in [1]. Originally in [2]. +% These initial guesses are good near x = 0 . Note: zeros of besselj(+/-.5,x) +% are integer and half-integer multiples of pi. +% x_init_bess = bess/sqrt(nu).*sqrt((1+ (bess.^2+2*(a^2-1))/3/nu^2) ); +Tnk0 = pi/2*ones(m,1); +nu = (4*m+2*a+2); +rhs = (4*m-4*(1:m)'+3)./nu*pi; + +for k = 1:7 + val = Tnk0 - sin(Tnk0) - rhs; + dval = 1 - cos(Tnk0); + dTnk0 = val./dval; + Tnk0 = Tnk0 - dTnk0; +end + +tnk = cos(Tnk0/2).^2; +x_init_sin = sqrt(nu*tnk - (5./(4*(1-tnk).^2) - 1./(1-tnk)-1+3*a^2)/3/nu); + +% Patch together +p = 0.4985+eps; +x_init = [x_init_sin(1:floor(p*n));x_init_airy(ceil(p*n):end)]; + + +if mod(n,2) == 1 + x_init = [0;x_init]; + x_init = x_init(1:m+1); +else + x_init = x_init(1:m); +end + +% debug: +%y = hermpts(n); +%semilogy(abs(y - x_init)); +%yhalf = -y(m:-1:1); +%semilogy(abs(yhalf - x_init)); +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% %%%%%%%%%%%%%%%%%%%%%%% Routines for REC algorithm %%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function [x, w, v] = hermpts_rec(n) +% Compute Hermite nodes and weights using recurrence relation. + +x0 = HermiteInitialGuesses(n); +x0 = x0.*sqrt(2); + +for kk = 1:10 + [val, dval] = hermpoly_rec(n, x0); + dx = val./dval; + dx(isnan(dx)) = 0; + x0 = x0 - dx; + if norm(dx, inf)= max { + panic("legendre: min >= max") + } + if math.IsInf(min, 0) || math.IsInf(max, 0) { + panic("legendre: infinite bound") + } + for i := range x { + x[i], weight[i] = l.boundedLocation(len(x), i, min, max) + } +} + +func (l Legendre) FixedLocationSingle(n, k int, min, max float64) (x, weight float64) { + if min >= max { + panic("legendre: min >= max") + } + if math.IsInf(min, 0) || math.IsInf(max, 0) { + panic("legendre: infinite bound") + } + return l.boundedLocation(n, k, min, max) +} + +func (l Legendre) boundedLocation(n, k int, min, max float64) (x, weight float64) { + x, weight = l.location(n, k) + return (x+1)/2*(max-min) + min, weight * (max - min) / 2 +} + +// Algorithm adapted from http://sourceforge.net/projects/fastgausslegendrequadrature. + +// Original Copyright Notice: +//******************************************* +// Copyright (C) 2014 by Ignace Bogaert * +//******************************************* + +// This software package is based on the paper +// I. Bogaert, "Iteration-Free Computation of Gauss-Legendre Quadrature Nodes and Weights", +// to be published in the SIAM Journal of Scientific Computing. + +// The main features of this software are: +// - Speed: due to the simple formulas and the O(1) complexity computation of individual Gauss-Legendre +// quadrature nodes and weights. This makes it compatible with parallel computing paradigms. +// - Accuracy: the error on the nodes and weights is within a few ulps (see the paper for details). + +// Disclaimer: +// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// location finds the location and weight for location k given n total samples. +func (l Legendre) location(n, k int) (x, weight float64) { + // Note: k is 1-indexed in the original algorithm. It has been translated to + // zero-indexed here. + if n < 101 { + theta, weight := l.tabulated(n, k) + return math.Cos(theta), weight + } + if 2*k+1 > n { + theta, weight := l.computed(n, n-k) + return math.Cos(math.Pi - theta), weight + } + theta, weight := l.computed(n, k+1) + return math.Cos(theta), weight +} + +// Returns tabulated theta and weight values: valid for l <= 100 +func (l Legendre) tabulated(n, k int) (theta, weight float64) { + if n%2 == 1 { + n2 := (n - 1) / 2 + if k == n2 { + return math.Pi / 2, 2.0 / (cl[n] * cl[n]) + } + if k < n2 { + return oddThetaZeros[n2-1][n2-k-1], oddWeights[n2-1][n2-k-1] + } + return math.Pi - oddThetaZeros[n2-1][k-n2-1], oddWeights[n2-1][k-n2-1] + } + n2 := n / 2 + if k < n2 { + return evenThetaZeros[n2-1][n2-k-1], evenWeights[n2-1][n2-k-1] + } + return math.Pi - evenThetaZeros[n2-1][k-n2], evenWeights[n2-1][k-n2] +} + +func (l Legendre) computed(n, k int) (theta, weight float64) { + // First, get the bessel zero + w := 1.0 / (float64(n) + 0.5) + nu := besselJZero(k) + theta = w * nu + x := theta * theta + + // Get the asymptotic BesselJ(1, nu) squared + b := besselJ1Squared(k) + + // Get the Chebyshev interpolants for the nodes. + sf1t := (((((-1.29052996274280508473467968379e-12*x+2.40724685864330121825976175184e-10)*x-3.13148654635992041468855740012e-8)*x+0.275573168962061235623801563453e-5)*x-0.148809523713909147898955880165e-3)*x+0.416666666665193394525296923981e-2)*x - 0.416666666666662959639712457549e-1 + sf2t := (((((+2.20639421781871003734786884322e-9*x-7.53036771373769326811030753538e-8)*x+0.161969259453836261731700382098e-5)*x-0.253300326008232025914059965302e-4)*x+0.282116886057560434805998583817e-3)*x-0.209022248387852902722635654229e-2)*x + 0.815972221772932265640401128517e-2 + sf3t := (((((-2.97058225375526229899781956673e-8*x+5.55845330223796209655886325712e-7)*x-0.567797841356833081642185432056e-5)*x+0.418498100329504574443885193835e-4)*x-0.251395293283965914823026348764e-3)*x+0.128654198542845137196151147483e-2)*x - 0.416012165620204364833694266818e-2 + + // and the weights + wsf1t := ((((((((-2.20902861044616638398573427475e-14*x+2.30365726860377376873232578871e-12)*x-1.75257700735423807659851042318e-10)*x+1.03756066927916795821098009353e-8)*x-4.63968647553221331251529631098e-7)*x+0.149644593625028648361395938176e-4)*x-0.326278659594412170300449074873e-3)*x+0.436507936507598105249726413120e-2)*x-0.305555555555553028279487898503e-1)*x + 0.833333333333333302184063103900e-1 + wsf2t := (((((((+3.63117412152654783455929483029e-12*x+7.67643545069893130779501844323e-11)*x-7.12912857233642220650643150625e-9)*x+2.11483880685947151466370130277e-7)*x-0.381817918680045468483009307090e-5)*x+0.465969530694968391417927388162e-4)*x-0.407297185611335764191683161117e-3)*x+0.268959435694729660779984493795e-2)*x - 0.111111111111214923138249347172e-1 + wsf3t := (((((((+2.01826791256703301806643264922e-9*x-4.38647122520206649251063212545e-8)*x+5.08898347288671653137451093208e-7)*x-0.397933316519135275712977531366e-5)*x+0.200559326396458326778521795392e-4)*x-0.422888059282921161626339411388e-4)*x-0.105646050254076140548678457002e-3)*x-0.947969308958577323145923317955e-4)*x + 0.656966489926484797412985260842e-2 + + // Then refine with the paper expansions + nuSin := nu / math.Sin(theta) + bNuSin := b * nuSin + wInvSinc := w * w * nuSin + wIS2 := wInvSinc * wInvSinc + + // Finally, compute the node and the weight + theta = w * (nu + theta*wInvSinc*(sf1t+wIS2*(sf2t+wIS2*sf3t))) + deno := bNuSin + bNuSin*wIS2*(wsf1t+wIS2*(wsf2t+wIS2*wsf3t)) + weight = 2.0 * w / deno + return theta, weight +} + +func besselJZero(k int) float64 { + if k < 20 { + return jz[k-1] + } + z := math.Pi * (float64(k) - 0.25) + r := 1.0 / z + r2 := r * r + z += r * (0.125 + r2*(-0.807291666666666666666666666667e-1+r2*(0.246028645833333333333333333333+r2*(-1.82443876720610119047619047619+r2*(25.3364147973439050099206349206+r2*(-567.644412135183381139802038240+r2*(18690.4765282320653831636345064+r2*(-8.49353580299148769921876983660e5+5.09225462402226769498681286758e7*r2)))))))) + return z +} + +func besselJ1Squared(k int) float64 { + if k < 21 { + return j1[k-1] + } + x := 1.0 / (float64(k) - 0.25) + x2 := x * x + return x * (0.202642367284675542887758926420 + x2*x2*(-0.303380429711290253026202643516e-3+x2*(0.198924364245969295201137972743e-3+x2*(-0.228969902772111653038747229723e-3+x2*(0.433710719130746277915572905025e-3+x2*(-0.123632349727175414724737657367e-2+x2*(0.496101423268883102872271417616e-2+x2*(-0.266837393702323757700998557826e-1+.185395398206345628711318848386*x2)))))))) +} + +// Tabulated values +var jz = [20]float64{2.40482555769577276862163187933, 5.52007811028631064959660411281, 8.65372791291101221695419871266, 11.7915344390142816137430449119, 14.9309177084877859477625939974, 18.0710639679109225431478829756, 21.2116366298792589590783933505, 24.3524715307493027370579447632, 27.4934791320402547958772882346, 30.6346064684319751175495789269, 33.7758202135735686842385463467, 36.9170983536640439797694930633, 40.0584257646282392947993073740, 43.1997917131767303575240727287, 46.3411883716618140186857888791, 49.4826098973978171736027615332, 52.6240518411149960292512853804, 55.7655107550199793116834927735, 58.9069839260809421328344066346, 62.0484691902271698828525002646} +var j1 = [21]float64{0.269514123941916926139021992911, 0.115780138582203695807812836182, 0.0736863511364082151406476811985, 0.0540375731981162820417749182758, 0.0426614290172430912655106063495, 0.0352421034909961013587473033648, 0.0300210701030546726750888157688, 0.0261473914953080885904584675399, 0.0231591218246913922652676382178, 0.0207838291222678576039808057297, 0.0188504506693176678161056800214, 0.0172461575696650082995240053542, 0.0158935181059235978027065594287, 0.0147376260964721895895742982592, 0.0137384651453871179182880484134, 0.0128661817376151328791406637228, 0.0120980515486267975471075438497, 0.0114164712244916085168627222986, 0.0108075927911802040115547286830, 0.0102603729262807628110423992790, 0.00976589713979105054059846736696} + +// Tabulated nodes and weights +// The required theta values for the Legendre nodes for l <= 100 +var evenThetaZeros = [][]float64{ + {0.9553166181245092781638573e0}, + {0.1223899586470372591854100e1, 0.5332956802491269896325121e0}, + {0.1329852612388110166006182e1, 0.8483666264874876548310910e0, 0.3696066519448289481138796e0}, + {0.1386317078892131346282665e1, 0.1017455539490153431016397e1, 0.6490365804607796100719162e0, 0.2827570635937967783987981e0}, + {0.1421366498439524924081833e1, 0.1122539327631709474018620e1, 0.8238386589997556048023640e0, 0.5255196555285001171749362e0, 0.2289442988470260178701589e0}, + {0.1445233238471440081118261e1, 0.1194120375947706635968399e1, 0.9430552870605735796668951e0, 0.6921076988818410126677201e0, 0.4414870814893317611922530e0, 0.1923346793046672033050762e0}, + {0.1462529992921481833498746e1, 0.1246003586776677662375070e1, 0.1029498592525136749641068e1, 0.8130407055389454598609888e0, 0.5966877608172733931509619e0, 0.3806189306666775272453522e0, 0.1658171411523664030454318e0}, + {0.1475640280808194256470687e1, 0.1285331444322965257106517e1, 0.1095033401803444343034890e1, 0.9047575323895165085030778e0, 0.7145252532340252146626998e0, 0.5243866409035941583262629e0, 0.3344986386876292124968005e0, 0.1457246820036738335698855e0}, + {0.1485919440392653014379727e1, 0.1316167494718022699851110e1, 0.1146421481056642228295923e1, 0.9766871104439832694094465e0, 0.8069738930788195349918620e0, 0.6373005058706191519531139e0, 0.4677113145328286263205134e0, 0.2983460782092324727528346e0, 0.1299747364196768405406564e0}, + {0.1494194914310399553510039e1, 0.1340993178589955138305166e1, 0.1187794926634098887711586e1, 0.1034603297590104231043189e1, 0.8814230742890135843662021e0, 0.7282625848696072912405713e0, 0.5751385026314284688366450e0, 0.4220907301111166004529037e0, 0.2692452880289302424376614e0, 0.1172969277059561308491253e0}, + {0.1501000399130816063282492e1, 0.1361409225664372117193308e1, 0.1221820208990359866348145e1, 0.1082235198111836788818162e1, 0.9426568273796608630446470e0, 0.8030892957063359443650460e0, 0.6635400754448062852164288e0, 0.5240242709487281141128643e0, 0.3845781703583910933413978e0, 0.2453165389983612942439953e0, 0.1068723357985259945018899e0}, + {0.1506695545558101030878728e1, 0.1378494427506219143960887e1, 0.1250294703417272987066314e1, 0.1122097523267250692925104e1, 0.9939044422989454674968570e0, 0.8657177770401081355080608e0, 0.7375413075437535618804594e0, 0.6093818382449565759195927e0, 0.4812531951313686873528891e0, 0.3531886675690780704072227e0, 0.2252936226353075734690198e0, 0.9814932949793685067733311e-1}, + {0.1511531546703289231944719e1, 0.1393002286179807923400254e1, 0.1274473959424494104852958e1, 0.1155947313793812040125722e1, 0.1037423319077439147088755e1, 0.9189033445598992550553862e0, 0.8003894803353296871788647e0, 0.6818851814129298518332401e0, 0.5633967073169293284500428e0, 0.4449368152119130526034289e0, 0.3265362611165358134766736e0, 0.2082924425598466358987549e0, 0.9074274842993199730441784e-1}, + {0.1515689149557281132993364e1, 0.1405475003062348722192382e1, 0.1295261501292316172835393e1, 0.1185049147889021579229406e1, 0.1074838574917869281769567e1, 0.9646306371285440922680794e0, 0.8544265718392254369377945e0, 0.7442282945111358297916378e0, 0.6340389954584301734412433e0, 0.5238644768825679339859620e0, 0.4137165857369637683488098e0, 0.3036239070914333637971179e0, 0.1936769929947376175341314e0, 0.8437551461511597225722252e-1}, + {0.1519301729274526620713294e1, 0.1416312682230741743401738e1, 0.1313324092045794720169874e1, 0.1210336308624476413072722e1, 0.1107349759228459143499061e1, 0.1004365001539081003659288e1, 0.9013828087667156388167226e0, 0.7984043170121235411718744e0, 0.6954313000299367256853883e0, 0.5924667257887385542924194e0, 0.4895160050896970092628705e0, 0.3865901987860504829542802e0, 0.2837160095793466884313556e0, 0.1809780449917272162574031e0, 0.7884320726554945051322849e-1}, + {0.1522469852641529230282387e1, 0.1425817011963825344615095e1, 0.1329164502391080681347666e1, 0.1232512573416362994802398e1, 0.1135861522840293704616614e1, 0.1039211728068951568003361e1, 0.9425636940046777101926515e0, 0.8459181315837993237739032e0, 0.7492760951181414487254243e0, 0.6526392394594561548023681e0, 0.5560103418005302722406995e0, 0.4593944730762095704649700e0, 0.3628020075350028174968692e0, 0.2662579994723859636910796e0, 0.1698418454282150179319973e0, 0.7399171309970959768773072e-1}, + {0.1525270780617194430047563e1, 0.1434219768045409606267345e1, 0.1343169000217435981125683e1, 0.1252118659062444379491066e1, 0.1161068957629157748792749e1, 0.1070020159291475075961444e1, 0.9789726059789103169325141e0, 0.8879267623988119819560021e0, 0.7968832893748414870413015e0, 0.7058431727509840105946884e0, 0.6148079652926100198490992e0, 0.5237802779694730663856110e0, 0.4327648832448234459097574e0, 0.3417715500266717765568488e0, 0.2508238767288223767569849e0, 0.1599966542668327644694431e0, 0.6970264809814094464033170e-1}, + {0.1527764849261740485876940e1, 0.1441701954349064743573367e1, 0.1355639243522655042028688e1, 0.1269576852063768424508476e1, 0.1183514935851550608323947e1, 0.1097453683555812711123880e1, 0.1011393333949027021740881e1, 0.9253342019812867059380523e0, 0.8392767201322475821509486e0, 0.7532215073977623159515351e0, 0.6671694908788198522546767e0, 0.5811221342350705406265672e0, 0.4950819018993074588093747e0, 0.4090533017972007314666814e0, 0.3230455648729987995657071e0, 0.2370809940997936908335290e0, 0.1512302802537625099602687e0, 0.6588357082399222649528476e-1}, + {0.1529999863223206659623262e1, 0.1448406982124841835685420e1, 0.1366814241651488684482888e1, 0.1285221744143731581870833e1, 0.1203629605904952775544878e1, 0.1122037965173751996510051e1, 0.1040446993107623345153211e1, 0.9588569097730895525404200e0, 0.8772680085516152329147030e0, 0.7956806951062012653043722e0, 0.7140955526031660805347356e0, 0.6325134568448222221560326e0, 0.5509357927460004487348532e0, 0.4693648943475422765864580e0, 0.3878050333015201414955289e0, 0.3062649591511896679168503e0, 0.2247658146033686460963295e0, 0.1433746167818849555570557e0, 0.6246124541276674097388211e-1}, + {0.1532014188279762793560699e1, 0.1454449946977268522285131e1, 0.1376885814601482670609845e1, 0.1299321869764876494939757e1, 0.1221758200747475205847413e1, 0.1144194910846247537582396e1, 0.1066632125552939823863593e1, 0.9890700026972186303565530e0, 0.9115087474225932692070479e0, 0.8339486352158799520695092e0, 0.7563900488174808348719219e0, 0.6788335401193977027577509e0, 0.6012799395312684623216685e0, 0.5237305617022755897200291e0, 0.4461876237541810478131970e0, 0.3686551849119556335824055e0, 0.2911415613085158758589405e0, 0.2136668503694680525340165e0, 0.1362947587312224822844743e0, 0.5937690028966411906487257e-1}, + {0.1533838971193864306068338e1, 0.1459924288056445029654271e1, 0.1386009690354996919044862e1, 0.1312095239305276612560739e1, 0.1238181002944535867235042e1, 0.1164267059803796726229370e1, 0.1090353503721897748980095e1, 0.1016440450472067349837507e1, 0.9425280472651469176638349e0, 0.8686164868955467866176243e0, 0.7947060295895204342519786e0, 0.7207970381018823842440224e0, 0.6468900366403721167107352e0, 0.5729858150363658839291287e0, 0.4990856247464946058899833e0, 0.4251915773724379089467945e0, 0.3513075400485981451355368e0, 0.2774414365914335857735201e0, 0.2036124177925793565507033e0, 0.1298811916061515892914930e0, 0.5658282534660210272754152e-1}, + {0.1535499761264077326499892e1, 0.1464906652494521470377318e1, 0.1394313611500109323616335e1, 0.1323720686538524176057236e1, 0.1253127930763390908996314e1, 0.1182535404796980113294400e1, 0.1111943180033868679273393e1, 0.1041351343083674290731439e1, 0.9707600019805773720746280e0, 0.9001692951667510715040632e0, 0.8295794049297955988640329e0, 0.7589905782114329186155957e0, 0.6884031600807736268672129e0, 0.6178176499732537480601935e0, 0.5472348011493452159473826e0, 0.4766558078624760377875119e0, 0.4060826859477620301047824e0, 0.3355191279517093844978473e0, 0.2649727008485465487101933e0, 0.1944616940738156405895778e0, 0.1240440866043499301839465e0, 0.5403988657613871827831605e-1}, + {0.1537017713608809830855653e1, 0.1469460505124226636602925e1, 0.1401903350962364703169699e1, 0.1334346289590505369693957e1, 0.1266789363044399933941254e1, 0.1199232618763735058848455e1, 0.1131676111906105521856066e1, 0.1064119908394702657537061e1, 0.9965640890815034701957497e0, 0.9290087556203499065939494e0, 0.8614540390091103102510609e0, 0.7939001124053586164046432e0, 0.7263472110048245091518914e0, 0.6587956640463586742461796e0, 0.5912459486086227271608064e0, 0.5236987847717837556177452e0, 0.4561553147193391989386660e0, 0.3886174669444433167860783e0, 0.3210887745896478259115420e0, 0.2535764786314617292100029e0, 0.1860980813776342452540915e0, 0.1187090676924131329841811e0, 0.5171568198966901682810573e-1}, + {0.1538410494858190444190279e1, 0.1473638845472165977392911e1, 0.1408867240039222913928858e1, 0.1344095709533508756473909e1, 0.1279324287566779722061664e1, 0.1214553011719528935181709e1, 0.1149781925191718586091000e1, 0.1085011078936665906275419e1, 0.1020240534516704208782618e1, 0.9554703680422404498752066e0, 0.8907006757608306209160649e0, 0.8259315822134856671969566e0, 0.7611632524946588128425351e0, 0.6963959112887657683892237e0, 0.6316298735371143844913976e0, 0.5668655960010826255149266e0, 0.5021037684870694065589284e0, 0.4373454855522296089897130e0, 0.3725925956833896735786860e0, 0.3078484858841616878136371e0, 0.2431200981264999375962973e0, 0.1784242126043536701754986e0, 0.1138140258514833068653307e0, 0.4958315373802413441075340e-1}, + {0.1539692973716708504412697e1, 0.1477486279394502338589519e1, 0.1415279620944410339318226e1, 0.1353073023537942666830874e1, 0.1290866514321280958405103e1, 0.1228660123395079609266898e1, 0.1166453885011658611362850e1, 0.1104247839096738022319035e1, 0.1042042033248543055386770e1, 0.9798365254403234947595400e0, 0.9176313877712591840677176e0, 0.8554267118081827231209625e0, 0.7932226163976800550406599e0, 0.7310192594231560707888939e0, 0.6688168560730805146438886e0, 0.6066157082814543103941755e0, 0.5444162542389049922529553e0, 0.4822191559963931133878621e0, 0.4200254643636986308379697e0, 0.3578369542536859435571624e0, 0.2956568781922605524959448e0, 0.2334919029083292837123583e0, 0.1713581437497397360313735e0, 0.1093066902335822942650053e0, 0.4761952998197036029817629e-1}, + {0.1540877753740080417345045e1, 0.1481040617373741365390254e1, 0.1421203510518656600018143e1, 0.1361366453804322852131292e1, 0.1301529469356044341206877e1, 0.1241692581525935716830402e1, 0.1181855817774264617619371e1, 0.1122019209772750368801179e1, 0.1062182794829879659341536e1, 0.1002346617783007482854908e1, 0.9425107335729934538419206e0, 0.8826752108319277463183701e0, 0.8228401370047382776784725e0, 0.7630056258499810562932058e0, 0.7031718287376427885875898e0, 0.6433389522119553277924537e0, 0.5835072863023426715977658e0, 0.5236772521416453354847559e0, 0.4638494862268433259444639e0, 0.4040249990308909882616381e0, 0.3442054975680110060507306e0, 0.2843941101955779333389742e0, 0.2245972494281051799602510e0, 0.1648304164747050021714385e0, 0.1051427544146599992432949e0, 0.4580550859172367960799915e-1}, + {0.1541975588842621898865181e1, 0.1484334121018556567335167e1, 0.1426692677652358867201800e1, 0.1369051275783071487471360e1, 0.1311409933595114953831618e1, 0.1253768670970438091691833e1, 0.1196127510146226323327062e1, 0.1138486476526912406867032e1, 0.1080845599717322003702293e1, 0.1023204914871722785830020e1, 0.9655644644970043364617272e0, 0.9079243009168822510582606e0, 0.8502844897148263889326479e0, 0.7926451146568312828354346e0, 0.7350062849078710810840430e0, 0.6773681459074923011631400e0, 0.6197308962817025162722438e0, 0.5620948151095422609589585e0, 0.5044603077892199488064657e0, 0.4468279872027509013135997e0, 0.3891988265038338944044115e0, 0.3315744698431505326770711e0, 0.2739579305700525818998611e0, 0.2163553856859193758294342e0, 0.1587817673749480300092784e0, 0.1012844151694839452028589e0, 0.4412462056235422293371300e-1}, + {0.1542995710582548837472073e1, 0.1487394484904746766220933e1, 0.1431793279635669382208875e1, 0.1376192108950239363921811e1, 0.1320590987909222553912422e1, 0.1264989932881031519687125e1, 0.1209388962038683919740547e1, 0.1153788095965648154683658e1, 0.1098187358416032947576489e1, 0.1042586777292402877200408e1, 0.9869863859317282394719449e0, 0.9313862248321055503829503e0, 0.8757863440192765677772914e0, 0.8201868063589761051746975e0, 0.7645876922981545448147078e0, 0.7089891068198449136125464e0, 0.6533911899285832425290628e0, 0.5977941329592257586198087e0, 0.5421982048745539015834188e0, 0.4866037965045890355211229e0, 0.4310114988353693539492225e0, 0.3754222503860499120445385e0, 0.3198376369331602148544626e0, 0.2642605649958747239907310e0, 0.2086969927688100977274751e0, 0.1531613237261629042774314e0, 0.9769922156300582041279299e-1, 0.4256272861907242306694832e-1}, + {0.1543946088331101630230404e1, 0.1490245617072432741470241e1, 0.1436545162952171175361532e1, 0.1382844737841275627385236e1, 0.1329144354302189376680665e1, 0.1275444025914442882448630e1, 0.1221743767654456436125309e1, 0.1168043596353244531685999e1, 0.1114343531263457295536939e1, 0.1060643594778787047442989e1, 0.1006943813366184678568021e1, 0.9532442187977767941200107e0, 0.8995448498101763729640445e0, 0.8458457543830885615091264e0, 0.7921469929325243736682034e0, 0.7384486428849507503612470e0, 0.6847508053901545384892447e0, 0.6310536154445759741044291e0, 0.5773572576394624029563656e0, 0.5236619915567428835581025e0, 0.4699681944935857341529219e0, 0.4162764370726533962791279e0, 0.3625876255789859906927245e0, 0.3089032914359211154562848e0, 0.2552262416643531728802047e0, 0.2015622306384971766058615e0, 0.1479251692966707827334002e0, 0.9435916010280739398532997e-1, 0.4110762866287674188292735e-1}, + {0.1544833637851665335244669e1, 0.1492908264756388370493025e1, 0.1440982906138650837480037e1, 0.1389057572001580364167786e1, 0.1337132272892735072773304e1, 0.1285207020157876647295968e1, 0.1233281826234298389291217e1, 0.1181356705000596722238457e1, 0.1129431672204958843918638e1, 0.1077506746001711267258715e1, 0.1025581947637229234301640e1, 0.9736573023432582093437126e0, 0.9217328405213548692702866e0, 0.8698085993416727107979968e0, 0.8178846249414537373941032e0, 0.7659609755086193214466010e0, 0.7140377257012462393241274e0, 0.6621149731355525426273686e0, 0.6101928481720243483360470e0, 0.5582715291407654489802101e0, 0.5063512668959282414914789e0, 0.4544324261262307197237056e0, 0.4025155584642650335664553e0, 0.3506015401168133792671488e0, 0.2986918517703509333332016e0, 0.2467892075469457255751440e0, 0.1948991714956708008247732e0, 0.1430351946011564171352354e0, 0.9123992133264713232350199e-1, 0.3974873026126591246235829e-1}, + {0.1545664389841685834178882e1, 0.1495400520006868605194165e1, 0.1445136662469633349524466e1, 0.1394872825707861196682996e1, 0.1344609018631531661347402e1, 0.1294345250782284139500904e1, 0.1244081532562166402923175e1, 0.1193817875503760392032898e1, 0.1143554292597402872188167e1, 0.1093290798696377946301336e1, 0.1043027411028491785799717e1, 0.9927641498535133311947588e0, 0.9425010393224361375194941e0, 0.8922381086194002226900769e0, 0.8419753935054036625982058e0, 0.7917129384431112475049142e0, 0.7414507995789214800057706e0, 0.6911890490185720721582180e0, 0.6409277811053987947460976e0, 0.5906671218914768219060599e0, 0.5404072438741681591850965e0, 0.4901483897634232956856935e0, 0.4398909124691513811974471e0, 0.3896353458699818240468259e0, 0.3393825380385224469051922e0, 0.2891339221891949677776928e0, 0.2388921255071779766209942e0, 0.1886625339124777570188312e0, 0.1384581678870181657476050e0, 0.8832030722827102577102185e-1, 0.3847679847963676404657822e-1}, + {0.1546443627125265521960044e1, 0.1497738231263909315513507e1, 0.1449032845902631477147772e1, 0.1400327478265391242178337e1, 0.1351622135921668846451224e1, 0.1302916826944702448727527e1, 0.1254211560091483702838765e1, 0.1205506345013417018443405e1, 0.1156801192508980685500292e1, 0.1108096114833249453312212e1, 0.1059391126084216587933501e1, 0.1010686242693213908544820e1, 0.9619814840575052973573711e0, 0.9132768733691264344256970e0, 0.8645724387181842642305406e0, 0.8158682145859558652971026e0, 0.7671642439014559105969752e0, 0.7184605809290069459742089e0, 0.6697572954095121564500879e0, 0.6210544786425143220264938e0, 0.5723522526623283741373995e0, 0.5236507845164779831804685e0, 0.4749503092950064087413842e0, 0.4262511688770346357064771e0, 0.3775538805043668894422883e0, 0.3288592658750793954850446e0, 0.2801687136893753887834348e0, 0.2314847695998852605184853e0, 0.1828126524563463299986617e0, 0.1341649789468091132459783e0, 0.8558174883654483804697753e-1, 0.3728374374031613183399036e-1}, + {0.1547175997094614757138430e1, 0.1499935340679181525271649e1, 0.1452694693272706215568985e1, 0.1405454061061768876728643e1, 0.1358213450511184239883293e1, 0.1310972868490444296079765e1, 0.1263732322416537730871712e1, 0.1216491820419724046503073e1, 0.1169251371540540180758674e1, 0.1122010985968754004469355e1, 0.1074770675338453464761893e1, 0.1027530453098431393666936e1, 0.9802903349842005856557204e0, 0.9330503396284544173873149e0, 0.8858104893623263267477775e0, 0.8385708112832335506864354e0, 0.7913313387011139500976360e0, 0.7440921131314510897906335e0, 0.6968531870945337206139839e0, 0.6496146281309018959581539e0, 0.6023765246993705639765525e0, 0.5551389950762090311242875e0, 0.5079022012032895030848024e0, 0.4606663710240282967569630e0, 0.4134318360639670775957014e0, 0.3661990979414348851212686e0, 0.3189689535781378596191439e0, 0.2717427498485401725509746e0, 0.2245229557871702595200694e0, 0.1773146332323969343091350e0, 0.1301300193754780766338959e0, 0.8300791095077070533235660e-1, 0.3616244959900389221395842e-1}, + {0.1547865604457777747119921e1, 0.1502004162357357213441384e1, 0.1456142728021903760325049e1, 0.1410281306774684706589738e1, 0.1364419904164498130803254e1, 0.1318558526067441138200403e1, 0.1272697178801115154796514e1, 0.1226835869256177571730448e1, 0.1180974605051351016009903e1, 0.1135113394719709026888693e1, 0.1089252247936466574864114e1, 0.1043391175801911243726755e1, 0.9975301911979639874925565e0, 0.9516693092438447484954432e0, 0.9058085478865097428655118e0, 0.8599479286766250282572181e0, 0.8140874778035996603018790e0, 0.7682272274981820559251592e0, 0.7223672179660643783333797e0, 0.6765075001043380283085699e0, 0.6306481393987597674748178e0, 0.5847892216487432573582268e0, 0.5389308616059791284685642e0, 0.4930732164176132508179420e0, 0.4472165073094733435432890e0, 0.4013610560689043520551232e0, 0.3555073496130768130758891e0, 0.3096561615434305328219637e0, 0.2638087993597793691714182e0, 0.2179676599607749036552390e0, 0.1721376573496165890967450e0, 0.1263306713881449555499955e0, 0.8058436603519718986295825e-1, 0.3510663068970053260227480e-1}, + {0.1548516088202564202943238e1, 0.1503955613246577879586994e1, 0.1459395145012190281751360e1, 0.1414834688100222735099866e1, 0.1370274247295441414922756e1, 0.1325713827649021532002630e1, 0.1281153434570536124285912e1, 0.1236593073933169034954499e1, 0.1192032752196710979323473e1, 0.1147472476554108430135576e1, 0.1102912255109027578275434e1, 0.1058352097094263144928973e1, 0.1013792013144153206047048e1, 0.9692320156388929821870602e0, 0.9246721191454417746654622e0, 0.8801123409896300773149632e0, 0.8355527020087518049947413e0, 0.7909932275560464363973909e0, 0.7464339488624693592395086e0, 0.7018749049145358048463504e0, 0.6573161450929179933243905e0, 0.6127577329584494909986789e0, 0.5681997518140860838771656e0, 0.5236423130979094957496400e0, 0.4790855694444512920982626e0, 0.4345297357523596151738496e0, 0.3899751246318782591316393e0, 0.3454222091410984787772492e0, 0.3008717408917773811461237e0, 0.2563249902500918978614004e0, 0.2117842860782107775954396e0, 0.1672544029381415755198150e0, 0.1227468836419337342946123e0, 0.7829832364814667171382217e-1, 0.3411071484766340151578357e-1}, + {0.1549130685823945998342524e1, 0.1505799405819664254557106e1, 0.1462468131657470292685966e1, 0.1419136867330461353369368e1, 0.1375805616982638895139986e1, 0.1332474384976155365522566e1, 0.1289143175965912901391449e1, 0.1245811994984327181800398e1, 0.1202480847539690438616688e1, 0.1159149739732435788417226e1, 0.1115818678394807971862305e1, 0.1072487671261111519215409e1, 0.1029156727178025494814510e1, 0.9858258563677261466814511e0, 0.9424950707611702085500992e0, 0.8991643844255133860018485e0, 0.8558338141192845596532563e0, 0.8125033800232146117493243e0, 0.7691731067161328174004981e0, 0.7258430244984030733808537e0, 0.6825131712172895509836733e0, 0.6391835948321685576634513e0, 0.5958543570955633038336902e0, 0.5525255389612023677479152e0, 0.5091972487450747080139606e0, 0.4658696348260689008126722e0, 0.4225429061321313393543928e0, 0.3792173666095906812269559e0, 0.3358934762285008809293807e0, 0.2925719658301625547639832e0, 0.2492540707015179370724365e0, 0.2059420554273186332219697e0, 0.1626405628266886976038507e0, 0.1193608172622853851645011e0, 0.7613840464754681957544313e-1, 0.3316974474186058622824911e-1}, + {0.1549712287207882890839045e1, 0.1507544209724862511636878e1, 0.1465376137339015815734558e1, 0.1423208073529702865859582e1, 0.1381040021900765225468989e1, 0.1338871986235691269778498e1, 0.1296703970558498635765633e1, 0.1254535979202491212629656e1, 0.1212368016889500927716256e1, 0.1170200088822853513468851e1, 0.1128032200798161849314963e1, 0.1085864359337236600941540e1, 0.1043696571852037437540940e1, 0.1001528846847853898635169e1, 0.9593611941780778060127795e0, 0.9171936253674231737318512e0, 0.8750261540268988114426643e0, 0.8328587963932301252176965e0, 0.7906915720393251716472997e0, 0.7485245048233193695739358e0, 0.7063576241759074809548715e0, 0.6641909668761970070284373e0, 0.6220245795476036586681135e0, 0.5798585222396645710869275e0, 0.5376928736905555113005422e0, 0.4955277392687366749125653e0, 0.4533632633323484070376718e0, 0.4111996491651493998151895e0, 0.3690371925202636251212886e0, 0.3268763409876008462653069e0, 0.2847178057580674399826003e0, 0.2425627889274157106498810e0, 0.2004134942584602007834507e0, 0.1582744399049656648660257e0, 0.1161565488818554609430574e0, 0.7409445176394481360104851e-1, 0.3227929535095246410912398e-1}, + {0.1550263480064160377720298e1, 0.1509197788083808185665328e1, 0.1468132100566875710992083e1, 0.1427066420556418463513913e1, 0.1386000751198712817289420e1, 0.1344935095788765217267069e1, 0.1303869457820298477498722e1, 0.1262803841041882838326682e1, 0.1221738249521212843639205e1, 0.1180672687719991159061894e1, 0.1139607160582508034089119e1, 0.1098541673641858946868449e1, 0.1057476233148907719560749e1, 0.1016410846230700992453501e1, 0.9753455210872527645472818e0, 0.9342802672387126698703291e0, 0.8932150958393123732306518e0, 0.8521500200807685012223049e0, 0.8110850557169691024167180e0, 0.7700202217553081279468270e0, 0.7289555413804262510029339e0, 0.6878910432074509889956044e0, 0.6468267630110350344178276e0, 0.6057627461556542068727688e0, 0.5646990510834698732732127e0, 0.5236357544389875315454201e0, 0.4825729588028297682338108e0, 0.4415108047277878179738561e0, 0.4004494901533595099830119e0, 0.3593893030723592157150581e0, 0.3183306793460978083354355e0, 0.2772743115465352362860883e0, 0.2362213703174823832436869e0, 0.1951740017836102296584907e0, 0.1541366059551230775894261e0, 0.1131198202589878992052369e0, 0.7215736988593890187079586e-1, 0.3143540438351454384152236e-1}, + {0.1550786588415152297375587e1, 0.1510767112957397367780716e1, 0.1470747641421582916022579e1, 0.1430728176478592843861361e1, 0.1390708720885325111445925e1, 0.1350689277522434511387126e1, 0.1310669849435604714836514e1, 0.1270650439881648370588402e1, 0.1230631052380981613091250e1, 0.1190611690778358944744052e1, 0.1150592359314214516523625e1, 0.1110573062709576809284752e1, 0.1070553806268363352417161e1, 0.1030534596002003296175373e1, 0.9905154387828984834423913e0, 0.9504963425353941517573974e0, 0.9104773164759498161192732e0, 0.8704583714184727086854142e0, 0.8304395201669023270865304e0, 0.7904207780260519973626051e0, 0.7504021634749074983118715e0, 0.7103836990664583264642972e0, 0.6703654126486745769832673e0, 0.6303473390491956215820085e0, 0.5903295224434431765765323e0, 0.5503120197533818815098408e0, 0.5102949056413983084126817e0, 0.4702782800468414863285692e0, 0.4302622799152491769326599e0, 0.3902470981180917254123191e0, 0.3502330152869736207185960e0, 0.3102204561556976356809728e0, 0.2702100956292792195263915e0, 0.2302030745053307298726703e0, 0.1902014842102915167005070e0, 0.1502096126336221315300686e0, 0.1102378261690820867329259e0, 0.7031899075931525095025389e-1, 0.3063451333411226493032265e-1}, + {0.1551283705347968314195100e1, 0.1512258463601911009913297e1, 0.1473233225313284690780287e1, 0.1434207992834186122366616e1, 0.1395182768588723275108301e1, 0.1356157555104474252423723e1, 0.1317132355046745793679891e1, 0.1278107171256650000336432e1, 0.1239082006794203284097135e1, 0.1200056864987904389011051e1, 0.1161031749492588664002624e1, 0.1122006664357811755961100e1, 0.1082981614109627397900573e1, 0.1043956603849447575483550e1, 0.1004931639374790125389322e1, 0.9659067273282460489273148e0, 0.9268818753831082867718635e0, 0.8878570924770502938457708e0, 0.8488323891094102606331406e0, 0.8098077777236123075833052e0, 0.7707832732049530424809748e0, 0.7317588935368492604710264e0, 0.6927346606780251833003950e0, 0.6537106017528970872810663e0, 0.6146867506941756306797580e0, 0.5756631505519364744300804e0, 0.5366398568077528417370132e0, 0.4976169422443344500752625e0, 0.4585945042946725387136724e0, 0.4195726764797194195007418e0, 0.3805516468579533335376469e0, 0.3415316890685593880011997e0, 0.3025132172735989410463832e0, 0.2634968895917008761291809e0, 0.2244838184598823563259898e0, 0.1854760433267094750424413e0, 0.1464777455344068532549101e0, 0.1074990339130794792907032e0, 0.6857195785426972961368108e-1, 0.2987341732561906608807860e-1}, + {0.1551756721003315464043007e1, 0.1513677510435354867644006e1, 0.1475598302924814895692182e1, 0.1437519100549654116408972e1, 0.1399439905448387106945081e1, 0.1361360719846430407096351e1, 0.1323281546084682430842605e1, 0.1285202386651141609385598e1, 0.1247123244216506877361870e1, 0.1209044121674894401873626e1, 0.1170965022191058363946285e1, 0.1132885949255841486220662e1, 0.1094806906752030657845562e1, 0.1056727899033393535018723e1, 0.1018648931020478788570327e1, 0.9805700083178549567966928e0, 0.9424911373589552049711100e0, 0.9044123255867553868253384e0, 0.8663335816813894348633149e0, 0.8282549158498738099497389e0, 0.7901763401989443875774432e0, 0.7520978692204962458482329e0, 0.7140195204316730003387055e0, 0.6759413152305656820841666e0, 0.6378632800575392064866756e0, 0.5997854479978337579981629e0, 0.5617078610344953281799357e0, 0.5236305732820186728652802e0, 0.4855536557378012985520074e0, 0.4474772034530068342865487e0, 0.4094013466928584958758982e0, 0.3713262689388439070717808e0, 0.3332522371792479009733062e0, 0.2951796555193184134657530e0, 0.2571091661074227554417865e0, 0.2190418543971735546480404e0, 0.1809797103814301725822348e0, 0.1429268140230164119614409e0, 0.1048930290780323497410212e0, 0.6690962797843649866645769e-1, 0.2914922224685900914817542e-1}, + {0.1552207346590136182648920e1, 0.1515029387081184115266415e1, 0.1477851430283927973458023e1, 0.1440673478039699629370259e1, 0.1403495532240969264030648e1, 0.1366317594853508812224152e1, 0.1329139667940348087929429e1, 0.1291961753688162615428688e1, 0.1254783854436838464182091e1, 0.1217605972713102930414639e1, 0.1180428111269300876868432e1, 0.1143250273128649048802100e1, 0.1106072461638634327789036e1, 0.1068894680534663975270023e1, 0.1031716934016664760314029e1, 0.9945392268421176498894610e0, 0.9573615644400829018748874e0, 0.9201839530522288586731642e0, 0.8830063999088902711516820e0, 0.8458289134509915302518266e0, 0.8086515036126424512848147e0, 0.7714741821849085841225787e0, 0.7342969632895448309937051e0, 0.6971198640037406540069491e0, 0.6599429051953912854163132e0, 0.6227661126567800124770610e0, 0.5855895186691062254659102e0, 0.5484131642019636734351025e0, 0.5112371020703309674589504e0, 0.4740614015734592960802666e0, 0.4368861554959151187817336e0, 0.3997114910036376358365916e0, 0.3625375872199777754435892e0, 0.3253647047992267079974806e0, 0.2881932382678453273830096e0, 0.2510238145617968753500674e0, 0.2138574934303919974438356e0, 0.1766962177535783269128215e0, 0.1395439709154010255199071e0, 0.1024103832005221866954023e0, 0.6532598686141261097119747e-1, 0.2845930797694291389393445e-1}, + {0.1552637135069155811491072e1, 0.1516318752418798211357541e1, 0.1480000372180291690418989e1, 0.1443681995989991700140976e1, 0.1407363625527612735973164e1, 0.1371045262534953065860219e1, 0.1334726908836065747097909e1, 0.1298408566359386697763653e1, 0.1262090237162411913706886e1, 0.1225771923459625279363960e1, 0.1189453627654523146514386e1, 0.1153135352376772077918208e1, 0.1116817100525785826106551e1, 0.1080498875322336017099434e1, 0.1044180680370244915946738e1, 0.1007862519730785566833872e1, 0.9715443980131875264637689e0, 0.9352263204856910439167915e0, 0.8989082932130182550456316e0, 0.8625903232280967802521182e0, 0.8262724187486163930514201e0, 0.7899545894528804342126058e0, 0.7536368468349768085155075e0, 0.7173192046673890278545072e0, 0.6810016796111441673128480e0, 0.6446842920316340773745262e0, 0.6083670671059611518530899e0, 0.5720500363511797523369558e0, 0.5357332397728172506411618e0, 0.4994167289487775362163415e0, 0.4631005715608865274454686e0, 0.4267848582339839676363509e0, 0.3904697131799790288672503e0, 0.3541553113674441557740819e0, 0.3178419074113077198829473e0, 0.2815298867038369044519273e0, 0.2452198616736214006194288e0, 0.2089128675558041239775998e0, 0.1726108022974787183994402e0, 0.1363175571713249458600521e0, 0.1000425397881322914313825e0, 0.6381557644960651200944222e-1, 0.2780129671121636039734655e-1}, + {0.1553047499032218401181962e1, 0.1517549844221432542461907e1, 0.1482052191561582448658478e1, 0.1446554542510861055782865e1, 0.1411056898564365493121105e1, 0.1375559261269981001734724e1, 0.1340061632245437638964436e1, 0.1304564013196950335363525e1, 0.1269066405939915513649123e1, 0.1233568812422221364483924e1, 0.1198071234750839346739124e1, 0.1162573675222508872274463e1, 0.1127076136359515473862368e1, 0.1091578620951808778363231e1, 0.1056081132107029235444226e1, 0.1020583673310438024843461e1, 0.9850862484973095869616622e0, 0.9495888621411026369897815e0, 0.9140915193617473526041913e0, 0.8785942260597805964360395e0, 0.8430969890839839780181254e0, 0.8075998164428632814935249e0, 0.7721027175741014967901450e0, 0.7366057036915554827257553e0, 0.7011087882372792641869964e0, 0.6656119874777629720186974e0, 0.6301153213012084608241887e0, 0.5946188142997514629085459e0, 0.5591224972630766104664894e0, 0.5236264092783024624074546e0, 0.4881306007441175888503326e0, 0.4526351377998500905914452e0, 0.4171401090099414677462070e0, 0.3816456357674021470057899e0, 0.3461518890753412856675063e0, 0.3106591177837409768492156e0, 0.2751676985649013361686770e0, 0.2396782299970584002479842e0, 0.2041917239104339765549482e0, 0.1687100353513348647833163e0, 0.1332369676454340307348264e0, 0.9778171579501174586520881e-1, 0.6237343205901608270979365e-1, 0.2717302558182235133513210e-1}, + {0.1553439726211153891540573e1, 0.1518726525682668668950427e1, 0.1484013327077361052080319e1, 0.1449300131698066374929113e1, 0.1414586940879145218883617e1, 0.1379873756000009717714844e1, 0.1345160578499605494109603e1, 0.1310447409892181029407508e1, 0.1275734251784724823396464e1, 0.1241021105896515467487132e1, 0.1206307974081314658309029e1, 0.1171594858352843571506531e1, 0.1136881760914326165420300e1, 0.1102168684193068774494217e1, 0.1067455630881287279906518e1, 0.1032742603984709761582283e1, 0.9980296068808995413713835e0, 0.9633166433897968474836258e0, 0.9286037178597176902839922e0, 0.8938908352730483454962679e0, 0.8591780013772376740585140e0, 0.8244652228485703565016715e0, 0.7897525074988288740747291e0, 0.7550398645386622329842600e0, 0.7203273049167972965433221e0, 0.6856148417619669061621766e0, 0.6509024909658764678789680e0, 0.6161902719627732109904446e0, 0.5814782087876726421060849e0, 0.5467663315368932859708410e0, 0.5120546784214694424751802e0, 0.4773432987146161851453875e0, 0.4426322570828636775769209e0, 0.4079216401227574252826633e0, 0.3732115665343573673240355e0, 0.3385022035318641142927744e0, 0.3037937944563405612019789e0, 0.2690867076466992914990193e0, 0.2343815284441088285495466e0, 0.1996792463094099012688324e0, 0.1649816752853099621072722e0, 0.1302925346385956500837770e0, 0.9562081616094948269905207e-1, 0.6099502786102040135198395e-1, 0.2657252290854776665952679e-1}, + {0.1553814992974904767594241e1, 0.1519852325907741898557817e1, 0.1485889660564341242674032e1, 0.1451926998111647785152899e1, 0.1417964339743630985906479e1, 0.1384001686692845945859686e1, 0.1350039040242776872946770e1, 0.1316076401741232369348729e1, 0.1282113772615099921371445e1, 0.1248151154386817288949698e1, 0.1214188548692984168143550e1, 0.1180225957305622474388020e1, 0.1146263382156703179022046e1, 0.1112300825366698998613230e1, 0.1078338289278105103916832e1, 0.1044375776495107627552926e1, 0.1010413289930890288650173e1, 0.9764508328644780886953041e0, 0.9424884090095589354132202e0, 0.9085260225984488659490189e0, 0.8745636784853451215455853e0, 0.8406013822743460048537475e0, 0.8066391404795569177534715e0, 0.7726769607271702244889884e0, 0.7387148520130367387469271e0, 0.7047528250344497011443004e0, 0.6707908926224332706815892e0, 0.6368290703120276715090693e0, 0.6028673771049329733376093e0, 0.5689058365047911420524623e0, 0.5349444779460832748774921e0, 0.5009833388030907720537138e0, 0.4670224672735823328060142e0, 0.4330619266162571710985599e0, 0.3991018015460700850326972e0, 0.3651422081877256344485503e0, 0.3311833101314466311103548e0, 0.2972253454486352538763297e0, 0.2632686745061683534910424e0, 0.2293138699815081215985284e0, 0.1953618999343470689252174e0, 0.1614145391777897730914718e0, 0.1274754265555317105245073e0, 0.9355335943686297111639257e-1, 0.5967622944002585907962555e-1, 0.2599798753052849047032580e-1}, + {0.1554174376112911655131098e1, 0.1520930475263640362170511e1, 0.1487686575963027013435604e1, 0.1454442679258803180913942e1, 0.1421198786221944168258440e1, 0.1387954897956585365296993e1, 0.1354711015610581847809736e1, 0.1321467140386931222410853e1, 0.1288223273556309404505081e1, 0.1254979416471008337267759e1, 0.1221735570580615776412743e1, 0.1188491737449843097435062e1, 0.1155247918778991542491874e1, 0.1122004116427655660730083e1, 0.1088760332442401967089102e1, 0.1055516569089340593777585e1, 0.1022272828892740925095715e1, 0.9890291146811467076264609e0, 0.9557854296428465678959260e0, 0.9225417773930866874628226e0, 0.8892981620561221868061383e0, 0.8560545883661619186153440e0, 0.8228110617925680415850631e0, 0.7895675886964734656602191e0, 0.7563241765284943282959446e0, 0.7230808340807681383862155e0, 0.6898375718116413059811978e0, 0.6565944022687408111136058e0, 0.6233513406471279431598408e0, 0.5901084055357449335782332e0, 0.5568656199307345199294838e0, 0.5236230126340485109018232e0, 0.4903806202198476810807501e0, 0.4571384898571183050552302e0, 0.4238966834573972483152713e0, 0.3906552839347125500730013e0, 0.3574144049483910279156003e0, 0.3241742066189948531421192e0, 0.2909349219721993995636414e0, 0.2576969037411283384416169e0, 0.2244607124763750082606152e0, 0.1912272957431274569912962e0, 0.1579983907861406744991899e0, 0.1247775594308675650267811e0, 0.9157341285433675818728635e-1, 0.5841325237532701385812948e-1, 0.2544777076240816313972829e-1}, + {0.1554518863153354618809409e1, 0.1521963936333782670214978e1, 0.1489409010908686292228052e1, 0.1456854087820918568482631e1, 0.1424299168033388494075931e1, 0.1391744252537595165009714e1, 0.1359189342362693116905575e1, 0.1326634438585269225516707e1, 0.1294079542340034988016159e1, 0.1261524654831668904330407e1, 0.1228969777348083696352705e1, 0.1196414911275444418157033e1, 0.1163860058115329026827193e1, 0.1131305219504506571098859e1, 0.1098750397237914982841550e1, 0.1066195593295557461150055e1, 0.1033640809874212986016967e1, 0.1001086049425085324651032e1, 0.9685313146988134601280153e0, 0.9359766087996588330547245e0, 0.9034219352512048766203636e0, 0.8708672980765996496647291e0, 0.8383127018973108640833295e0, 0.8057581520556423644789438e0, 0.7732036547680256450048242e0, 0.7406492173185620802637676e0, 0.7080948483057714882525616e0, 0.6755405579604902654406567e0, 0.6429863585601198571817691e0, 0.6104322649751623629236805e0, 0.5778782954001507969801437e0, 0.5453244723459250134170285e0, 0.5127708240092147734858477e0, 0.4802173861982495342372455e0, 0.4476642050968422792532389e0, 0.4151113413261211455132671e0, 0.3825588760747025757978563e0, 0.3500069206395502661556462e0, 0.3174556318161704671189642e0, 0.2849052377944113082878058e0, 0.2523560839907875626097181e0, 0.2198087193323827316322426e0, 0.1872640717400572601243546e0, 0.1547238424480887172335593e0, 0.1221915194567498709631299e0, 0.8967553546914315204781840e-1, 0.5720262597323678474637133e-1, 0.2492036059421555107245208e-1}, + {0.1554849361424470843090118e1, 0.1522955431101933730645303e1, 0.1491061502037751976297424e1, 0.1459167575082261894770634e1, 0.1427273651103158170602525e1, 0.1395379730992862183093282e1, 0.1363485815676330697886480e1, 0.1331591906119453530640248e1, 0.1299698003338207337770238e1, 0.1267804108408757103237650e1, 0.1235910222478728395590872e1, 0.1204016346779913703159712e1, 0.1172122482642727288439229e1, 0.1140228631512787910483320e1, 0.1108334794970091261912531e1, 0.1076440974751339138680154e1, 0.1044547172776127017814204e1, 0.1012653391177865049408482e1, 0.9807596323405319627306720e0, 0.9488658989426541583823449e0, 0.9169721940102869797082899e0, 0.8850785209812848825432963e0, 0.8531848837838285971960304e0, 0.8212912869330969580404013e0, 0.7893977356512249782795147e0, 0.7575042360174185552669765e0, 0.7256107951575083863622461e0, 0.6937174214856350398887716e0, 0.6618241250156435481462849e0, 0.6299309177668761147121611e0, 0.5980378142995696297245189e0, 0.5661448324309071185385071e0, 0.5342519942071113461815355e0, 0.5023593272451872220760104e0, 0.4704668666194035162003700e0, 0.4385746575692260390945883e0, 0.4066827594785525726660483e0, 0.3747912518813925812276922e0, 0.3429002438089823350625543e0, 0.3110098888674705209106637e0, 0.2791204106078991711912441e0, 0.2472321474279120600810915e0, 0.2153456371036966567922014e0, 0.1834617887100953140198272e0, 0.1515822689338083535939382e0, 0.1197104949484175660714864e0, 0.8785472823121690639967810e-1, 0.5604116141749524467628553e-1, 0.2441436781606819510490200e-1}, + {0.1555166706034023842787706e1, 0.1523907464890582273398300e1, 0.1492648224885016483409279e1, 0.1461388986785839210767990e1, 0.1430129751376631035251350e1, 0.1398870519462421720845393e1, 0.1367611291876438076975682e1, 0.1336352069487341263827064e1, 0.1305092853207091240256110e1, 0.1273833643999595441027728e1, 0.1242574442890323705495464e1, 0.1211315250977103200801981e1, 0.1180056069442347222927677e1, 0.1148796899567022469820701e1, 0.1117537742746723499546780e1, 0.1086278600510304367969825e1, 0.1055019474541620880304106e1, 0.1023760366705069175705639e1, 0.9925012790757765081567637e0, 0.9612422139755203374385844e0, 0.9299831740157389822411293e0, 0.8987241621493743180375722e0, 0.8674651817337867269827651e0, 0.8362062366076504452859926e0, 0.8049473311856388413561914e0, 0.7736884705759381993127359e0, 0.7424296607273230664538510e0, 0.7111709086148904840060001e0, 0.6799122224768919982385331e0, 0.6486536121198915829209739e0, 0.6173950893164463798129595e0, 0.5861366683298159921278400e0, 0.5548783666157332634604655e0, 0.5236202057751242467455922e0, 0.4923622128691229579358494e0, 0.4611044222679868504944176e0, 0.4298468783051183048132298e0, 0.3985896391770900735176252e0, 0.3673327828297899556279530e0, 0.3360764161195064368209114e0, 0.3048206895905456571224703e0, 0.2735658223403245791263072e0, 0.2423121460275046288225596e0, 0.2110601877217048587999889e0, 0.1798108384023314561549010e0, 0.1485657315840060835766576e0, 0.1173282164330337207824850e0, 0.8610639001623934211634967e-1, 0.5492592372249737419414775e-1, 0.2392851379957687254895331e-1}, +} + +var oddThetaZeros = [][]float64{ + {0.6847192030022829138880982e0}, + {0.1002176803643121641749915e1, 0.4366349492255221620374655e0}, + {0.1152892953722227341986065e1, 0.7354466143229520469385622e0, 0.3204050902900619825355950e0}, + {0.1240573923404363422789550e1, 0.9104740292261473250358755e0, 0.5807869795060065580284919e0, 0.2530224166119306882187233e0}, + {0.1297877729331450368298142e1, 0.1025003226369574843297844e1, 0.7522519395990821317003373e0, 0.4798534223256743217333579e0, 0.2090492874137409414071522e0}, + {0.1338247676100454369194835e1, 0.1105718066248490075175419e1, 0.8732366099401630367220948e0, 0.6408663264733867770811230e0, 0.4088002373420211722955679e0, 0.1780944581262765470585931e0}, + {0.1368219536992351783359098e1, 0.1165652065603030148723847e1, 0.9631067821301481995711685e0, 0.7606069572889918619145483e0, 0.5582062109125313357140248e0, 0.3560718303314725022788878e0, 0.1551231069747375098418591e0}, + {0.1391350647015287461874435e1, 0.1211909966211469688151240e1, 0.1032480728417239563449772e1, 0.8530732514258505686069670e0, 0.6737074594242522259878462e0, 0.4944303818194983217354808e0, 0.3153898594929282395996014e0, 0.1373998952992547671039022e0}, + {0.1409742336767428999667236e1, 0.1248691224331339221187704e1, 0.1087646521650454938943641e1, 0.9266134127998189551499083e0, 0.7656007620508340547558669e0, 0.6046261769405451549818494e0, 0.4437316659960951760051408e0, 0.2830497588453068048261493e0, 0.1233108673082312764916251e0}, + {0.1424715475176742734932665e1, 0.1278636375242898727771561e1, 0.1132561101012537613667002e1, 0.9864925055883793730483278e0, 0.8404350520135058972624775e0, 0.6943966110110701016065380e0, 0.5483930281810389839680525e0, 0.4024623099018152227701990e0, 0.2567245837448891192759858e0, 0.1118422651428890834760883e0}, + {0.1437141935303526306632113e1, 0.1303488659735581140681362e1, 0.1169837785762829821262819e1, 0.1036190996404462300207004e1, 0.9025507517347875930425807e0, 0.7689210263823624893974324e0, 0.6353089402976822861185532e0, 0.5017289283414202278167583e0, 0.3682157131008289798868520e0, 0.2348791589702580223688923e0, 0.1023252788872632487579640e0}, + {0.1447620393135667144403507e1, 0.1324445197736386798102445e1, 0.1201271573324181312770120e1, 0.1078100568411879956441542e1, 0.9549336362382321811515336e0, 0.8317729718814276781352878e0, 0.7086221837538611370849622e0, 0.5854877911108011727748238e0, 0.4623830630132757357909198e0, 0.3393399712563371486343129e0, 0.2164597408964339264361902e0, 0.9430083986305519349231898e-1}, + {0.1456575541704195839944967e1, 0.1342355260834552126304154e1, 0.1228136043468909663499174e1, 0.1113918572282611841378549e1, 0.9997037539874953933323299e0, 0.8854928869950799998575862e0, 0.7712879690777516856072467e0, 0.6570923167092416238233585e0, 0.5429119513798658239789812e0, 0.4287591577660783587509129e0, 0.3146635662674373982102762e0, 0.2007190266590380629766487e0, 0.8744338280630300217927750e-1}, + {0.1464317002991565219979113e1, 0.1357838033080061766980173e1, 0.1251359804334884770836945e1, 0.1144882777708662655968171e1, 0.1038407544520296695714932e1, 0.9319349156915986836657782e0, 0.8254660749671546663859351e0, 0.7190028636037068047812305e0, 0.6125483562383020473196681e0, 0.5061081521562999836102547e0, 0.3996936914666951732317457e0, 0.2933325857619472952507468e0, 0.1871123137498061864373407e0, 0.8151560650977882057817999e-1}, + {0.1471075823713997440657641e1, 0.1371355574944658989649887e1, 0.1271635855736122280723838e1, 0.1171916986981363820797100e1, 0.1072199368669106404814915e1, 0.9724835301003496870596165e0, 0.8727702114891848603047954e0, 0.7730605060747958359120755e0, 0.6733561257504194406005404e0, 0.5736599396529727772420934e0, 0.4739771829190733570809765e0, 0.3743185619229329461021810e0, 0.2747099287638327553949437e0, 0.1752332025619508475799133e0, 0.7634046205384429302353073e-1}, + {0.1477027911291552393547878e1, 0.1383259682348271685979143e1, 0.1289491840051302622319481e1, 0.1195724613675799550484673e1, 0.1101958282220461402990667e1, 0.1008193204014774090964219e1, 0.9144298626454031699590564e0, 0.8206689427646120483710056e0, 0.7269114630504563073034288e0, 0.6331590254855162126233733e0, 0.5394143214244183829842424e0, 0.4456822679082866369288652e0, 0.3519729273095236644049666e0, 0.2583106041071417718760275e0, 0.1647723231643112502628240e0, 0.7178317184275122449502857e-1}, + {0.1482309554825692463999299e1, 0.1393822922226542123661077e1, 0.1305336577335833571381699e1, 0.1216850687682353365944624e1, 0.1128365453024608460982204e1, 0.1039881123511957522668140e1, 0.9513980267579228357946521e0, 0.8629166105524045911461307e0, 0.7744375139383604902604254e0, 0.6859616923374368587817328e0, 0.5974906525247623278123711e0, 0.5090269299866796725116786e0, 0.4205751610647263669405267e0, 0.3321448379994943116084719e0, 0.2437588931448048912587688e0, 0.1554900095178924564386865e0, 0.6773932498157585698088354e-1}, + {0.1487027983239550912222135e1, 0.1403259745496922270264564e1, 0.1319491725464661433609663e1, 0.1235724047968681189212364e1, 0.1151956859289811446164825e1, 0.1068190338689553494802072e1, 0.9844247150109837231349622e0, 0.9006602918737365182850484e0, 0.8168974877846821404275069e0, 0.7331369031796229223580227e0, 0.6493794386888650054486281e0, 0.5656265174356596757139537e0, 0.4818805368222631487731579e0, 0.3981458834052590173509113e0, 0.3144315409387123154212535e0, 0.2307592167302372059759857e0, 0.1471977156945989772472748e0, 0.6412678117309944052403703e-1}, + {0.1491268718102344688271411e1, 0.1411741190914640487505771e1, 0.1332213830951015404441941e1, 0.1252686732830809999680267e1, 0.1173160005794509313174730e1, 0.1093633781237958896879965e1, 0.1014108223243148393065201e1, 0.9345835440325075907377330e0, 0.8550600276575269107773349e0, 0.7755380679025248517258532e0, 0.6960182317959841585145109e0, 0.6165013717819833504477346e0, 0.5369888366794912945318079e0, 0.4574829005269902932408889e0, 0.3779877260196973978940863e0, 0.2985118404618624984946326e0, 0.2190758506462427957069113e0, 0.1397450765119767349146353e0, 0.6088003363863534825005464e-1}, + {0.1495100801651051409999732e1, 0.1419405340110198552778393e1, 0.1343710008748627892724810e1, 0.1268014880389353000310414e1, 0.1192320038028903827079750e1, 0.1116625579891689469044026e1, 0.1040931626310454794079799e1, 0.9652383295306942866661884e0, 0.8895458882533946571137358e0, 0.8138545700535261740447950e0, 0.7381647473570304814395029e0, 0.6624769578126105498149624e0, 0.5867920109947446493391737e0, 0.5111111891461744489290992e0, 0.4354366553151050147918632e0, 0.3597723703299625354660452e0, 0.2841264494060559943920389e0, 0.2085185052177154996230005e0, 0.1330107089065635461375419e0, 0.5794620170990797798650123e-1}, + {0.1498580583401444174317386e1, 0.1426364890228584522673414e1, 0.1354149299629923281192036e1, 0.1281933868420423988034246e1, 0.1209718660626713399048551e1, 0.1137503750956414845248481e1, 0.1065289229411733880607916e1, 0.9930752076949068878557126e0, 0.9208618284397049456535757e0, 0.8486492789905562098591586e0, 0.7764378127156926158031943e0, 0.7042277832708635930867344e0, 0.6320197021480767602848178e0, 0.5598143404345395912377042e0, 0.4876129202946139420188428e0, 0.4154175043169533365541148e0, 0.3432318703096418027524597e0, 0.2710637595435203246492797e0, 0.1989318822110657561806962e0, 0.1268955503926593166308254e0, 0.5528212871240371048241379e-1}, + {0.1501754508594837337089856e1, 0.1432712730475143340404518e1, 0.1363671034069754274950592e1, 0.1294629464249430679064317e1, 0.1225588071083248538559259e1, 0.1156546912269029268686830e1, 0.1087506056298747798071893e1, 0.1018465586752840651469411e1, 0.9494256083335850798964741e0, 0.8803862556198167553278643e0, 0.8113477061841624760598814e0, 0.7423102009244498727845341e0, 0.6732740767851639064676858e0, 0.6042398217472142478598295e0, 0.5352081720899522889584566e0, 0.4661802954366277026594659e0, 0.3971581629712621730826920e0, 0.3281453857685808451825081e0, 0.2591493642052661979197670e0, 0.1901879854885491785792565e0, 0.1213179541186130699071317e0, 0.5285224511635143601147552e-1}, + {0.1504661202517196460191540e1, 0.1438526110541037227495230e1, 0.1372391084315255737540026e1, 0.1306256159670931796771616e1, 0.1240121376243315949825014e1, 0.1173986779205849344923421e1, 0.1107852421486856229076325e1, 0.1041718366715156747157745e1, 0.9755846932657442605621389e0, 0.9094514999854931965227238e0, 0.8433189145364798253029042e0, 0.7771871059265138564989363e0, 0.7110563039566125173946002e0, 0.6449268305419475123120585e0, 0.5787991523675322133651034e0, 0.5126739740395088296453592e0, 0.4465524134105889084933393e0, 0.3804363581140941600870992e0, 0.3143292666717729726674543e0, 0.2482382273986418438740754e0, 0.1821803739336923550363257e0, 0.1162100228791666307841708e0, 0.5062697144246344520692308e-1}, + {0.1507333049739684406957329e1, 0.1443869798951040686809862e1, 0.1380406601553595646811530e1, 0.1316943486448336467960940e1, 0.1253480485358734060913055e1, 0.1190017634088428795118215e1, 0.1126554974102287077081806e1, 0.1063092554588577221978254e1, 0.9996304352342330000643921e0, 0.9361686900661624628632729e0, 0.8727074129127595264965883e0, 0.8092467253835331800652228e0, 0.7457867888716805068068402e0, 0.6823278231980088937854296e0, 0.6188701366516795329577182e0, 0.5554141765061554178407906e0, 0.4919606183965743300387332e0, 0.4285105345527885639657014e0, 0.3650657359209552112046854e0, 0.3016295408979540017854803e0, 0.2382087510453128743250072e0, 0.1748198074104535338147956e0, 0.1115148317291502081079519e0, 0.4858150828905663931389750e-1}, + {0.1509797405521643600800862e1, 0.1448798505784201776188819e1, 0.1387799649767640868379247e1, 0.1326800860997572277878513e1, 0.1265802165120213614545418e1, 0.1204803590828283748583827e1, 0.1143805171007496028164312e1, 0.1082806944206958485218487e1, 0.1021808956582037259849130e1, 0.9608112645303606832220554e0, 0.8998139383584991342974664e0, 0.8388170675106567024157190e0, 0.7778207682214244793380700e0, 0.7168251950382156442798800e0, 0.6558305587295081487906238e0, 0.5948371551492265376377962e0, 0.5338454137827292925154468e0, 0.4728559836463229599006206e0, 0.4118698949811841042358258e0, 0.3508888880839026413717319e0, 0.2899161521835467942607342e0, 0.2289582244272697168835150e0, 0.1680309071251709912058722e0, 0.1071842976730454709494914e0, 0.4669490825917857848258897e-1}, + {0.1512077535592702651885542e1, 0.1453358762182399391553360e1, 0.1394640024852448295479492e1, 0.1335921342914185177270306e1, 0.1277202737290683500323248e1, 0.1218484231207691826029908e1, 0.1159765851037557179133987e1, 0.1101047627365156083369632e1, 0.1042329596373083545617043e1, 0.9836118016874520301049009e0, 0.9248942968954766185908511e0, 0.8661771490588063053774554e0, 0.8074604437333368789787031e0, 0.7487442923247565105494255e0, 0.6900288431709550365296138e0, 0.6313142987730108226833704e0, 0.5726009435739572428629866e0, 0.5138891906843943809444838e0, 0.4551796645660731149033106e0, 0.3964733566771858874923011e0, 0.3377719420068963817561906e0, 0.2790784903284342592940125e0, 0.2203992941938221111139898e0, 0.1617495649772923108686624e0, 0.1031775271253784724197264e0, 0.4494935602951385601335598e-1}, + {0.1514193352804819997509006e1, 0.1457590393617468793209691e1, 0.1400987464419153080392546e1, 0.1344384581184662080889348e1, 0.1287781761126833878758488e1, 0.1231179023218584237510462e1, 0.1174576388822640925688125e1, 0.1117973882475943676285829e1, 0.1061371532893653466992815e1, 0.1004769374285310770780417e1, 0.9481674481184788854172919e0, 0.8915658055327279211293483e0, 0.8349645107156934027761499e0, 0.7783636457331086848148917e0, 0.7217633176118399859733190e0, 0.6651636690166557413471029e0, 0.6085648948549621671933311e0, 0.5519672690500084950513985e0, 0.4953711895788266953367288e0, 0.4387772581729219934583483e0, 0.3821864303519236078766179e0, 0.3256003205491779498477363e0, 0.2690218877324958059454348e0, 0.2124571975249336244841297e0, 0.1559209129891515317090843e0, 0.9945952063842375053227931e-1, 0.4332960406341033436157524e-1}, + {0.1516162000094549207021851e1, 0.1461527685790782385188426e1, 0.1406893396579229558427657e1, 0.1352259145769086826235918e1, 0.1297624947629923059740243e1, 0.1242990817790597917328601e1, 0.1188356773715062198539162e1, 0.1133722835287525783953663e1, 0.1079089025551156002698850e1, 0.1024455371662101389801169e1, 0.9698219061474760364582928e0, 0.9151886685974009713577537e0, 0.8605557079864861100238346e0, 0.8059230859253162466918892e0, 0.7512908813164713594661588e0, 0.6966591971861112012613682e0, 0.6420281709850565965229799e0, 0.5873979906122764301937499e0, 0.5327689202536826556885353e0, 0.4781413438508069051295597e0, 0.4235158420269503798571552e0, 0.3688933369002844229314675e0, 0.3142753865947702189467806e0, 0.2596648470121556361200229e0, 0.2050675726616484232653526e0, 0.1504977164639767777858359e0, 0.9600014792058154736462106e-1, 0.4182252607645932321862773e-1}, + {0.1517998315905975681819213e1, 0.1465200315462026532129551e1, 0.1412402336143180968579639e1, 0.1359604389111228213837104e1, 0.1306806486279734731351497e1, 0.1254008640622089183072742e1, 0.1201210866535131048800458e1, 0.1148413180281179970113571e1, 0.1095615600538999408768381e1, 0.1042818149105710558651372e1, 0.9900208518088600875617620e0, 0.9372237397138955502862203e0, 0.8844268507524555199840381e0, 0.8316302319600398731649744e0, 0.7788339426133210890795576e0, 0.7260380587255163256281298e0, 0.6732426796448045921910045e0, 0.6204479380061240544867289e0, 0.5676540152134466427854705e0, 0.5148611664077887834613451e0, 0.4620697624728053757183766e0, 0.4092803643735033357684553e0, 0.3564938631002461237979451e0, 0.3037117642790043703921396e0, 0.2509368276982060978106092e0, 0.1981747109679032915697317e0, 0.1454390911823840643137232e0, 0.9277332955453467429763451e-1, 0.4041676055113025684436480e-1}, + {0.1519715208823086817411929e1, 0.1468634099702062550682430e1, 0.1417553008469014674939490e1, 0.1366471944542347269659860e1, 0.1315390917933946912760115e1, 0.1264309939489363760018555e1, 0.1213229021168654147755139e1, 0.1162148176384137345494752e1, 0.1111067420416500738111992e1, 0.1059986770938296676746064e1, 0.1008906248685091746434581e1, 0.9578258783312407255956784e0, 0.9067456896525242756445150e0, 0.8556657190967860708153477e0, 0.8045860119448479090873824e0, 0.7535066253423996943740445e0, 0.7024276326462752642452137e0, 0.6513491298057893513225544e0, 0.6002712449887427739045163e0, 0.5491941535583390603837715e0, 0.4981181022276018128369963e0, 0.4470434496975185070560821e0, 0.3959707385770101868486847e0, 0.3449008307748737032772825e0, 0.2938351828535981363494671e0, 0.2427764647581323719392653e0, 0.1917301500230701193408602e0, 0.1407094708800750523796875e0, 0.8975637836633630394302762e-1, 0.3910242380354419363081899e-1}, + {0.1521323961422700444944464e1, 0.1471851603590422118622546e1, 0.1422379260986849454727777e1, 0.1372906941604798453293218e1, 0.1323434653909307929892118e1, 0.1273962407026590487708892e1, 0.1224490210963055761921526e1, 0.1175018076866133593082748e1, 0.1125546017342156230227131e1, 0.1076074046851682267877939e1, 0.1026602182210094558879809e1, 0.9771304432322302018639612e0, 0.9276588535760335871906045e0, 0.8781874418647315968408864e0, 0.8287162432047307488040550e0, 0.7792453012756761070555010e0, 0.7297746712644485550469075e0, 0.6803044240724808212528033e0, 0.6308346524943159683026367e0, 0.5813654805388740483542438e0, 0.5318970779332963132260134e0, 0.4824296835154055410257004e0, 0.4329636445908698102350729e0, 0.3834994865870752458854056e0, 0.3340380441799942088370002e0, 0.2845807279748544733570760e0, 0.2351301237470960623526672e0, 0.1856915325646991222655151e0, 0.1362777698319134965765757e0, 0.8692946525012054120187353e-1, 0.3787087726949234365520114e-1}, + {0.1522834478472358672931947e1, 0.1474872636605138418026177e1, 0.1426910807768284322082436e1, 0.1378948998781055367310047e1, 0.1330987216841224680164684e1, 0.1283025469674968454386883e1, 0.1235063765709222885799986e1, 0.1187102114275073728898860e1, 0.1139140525853183114841234e1, 0.1091179012375759666645271e1, 0.1043217587604604879578741e1, 0.9952562676120370548458597e0, 0.9472950714021223337048082e0, 0.8993340217254078241758816e0, 0.8513731461641338285808219e0, 0.8034124786014693431693904e0, 0.7554520612457602368887930e0, 0.7074919474732165281510693e0, 0.6595322059052657580628641e0, 0.6115729263971504325174172e0, 0.5636142290734363894767612e0, 0.5156562783879918167717991e0, 0.4676993058012953469089537e0, 0.4197436479350834076514896e0, 0.3717898140987174444032373e0, 0.3238386134116156886828960e0, 0.2758914133405791810724762e0, 0.2279507206431424610498769e0, 0.1800216744637006612298520e0, 0.1321166988439841543825694e0, 0.8427518284958235696897899e-1, 0.3671453742186897322954009e-1}, + {0.1524255491013576804195881e1, 0.1477714660784952783237945e1, 0.1431173841758652772349485e1, 0.1384633039781787069436630e1, 0.1338092261006965672253841e1, 0.1291551512012124788593875e1, 0.1245010799937299944123195e1, 0.1198470132644670409416924e1, 0.1151929518909907204916554e1, 0.1105388968655282680015213e1, 0.1058848493238442193822372e1, 0.1012308105815651361079674e1, 0.9657678218054126734684090e0, 0.9192276594886802366068293e0, 0.8726876407972167893294764e0, 0.8261477923647281669131478e0, 0.7796081469509049827753598e0, 0.7330687454042532567721262e0, 0.6865296394193009886613469e0, 0.6399908954920466591029822e0, 0.5934526007301573325059582e0, 0.5469148716199143611697357e0, 0.5003778676688561814362271e0, 0.4538418134105091550464446e0, 0.4073070354279485829740435e0, 0.3607740278788822846227453e0, 0.3142435758510728338330843e0, 0.2677170062389944640113953e0, 0.2211967514739567668334169e0, 0.1746877983807874325844051e0, 0.1282022028383479964348629e0, 0.8177818680168764430245080e-1, 0.3562671947817428176226631e-1}, + {0.1525594725214770881206476e1, 0.1480393128432045740356817e1, 0.1435191541323085582529217e1, 0.1389989968924959812091252e1, 0.1344788416522907866060817e1, 0.1299586889746827997174554e1, 0.1254385394680661996389736e1, 0.1209183937989395175829969e1, 0.1163982527069600127515982e1, 0.1118781170231154762473596e1, 0.1073579876920155012130433e1, 0.1028378657996412636748477e1, 0.9831775260837211038023103e0, 0.9379764960179657076015136e0, 0.8927755854282048597997986e0, 0.8475748155007347757967789e0, 0.8023742119985848209905761e0, 0.7571738066433708695662393e0, 0.7119736390205872251796930e0, 0.6667737592565460745639184e0, 0.6215742318591892056934095e0, 0.5763751413603713322640298e0, 0.5311766008298875656047892e0, 0.4859787651249621588538330e0, 0.4407818522612533891543536e0, 0.3955861793705505114602136e0, 0.3503922263398633798966312e0, 0.3052007556167344348049303e0, 0.2600130558662051177480644e0, 0.2148314894784555841956251e0, 0.1696608997322034095150907e0, 0.1245129955389270002683579e0, 0.7942489891978153749097006e-1, 0.3460150809198016850782325e-1}, + {0.1526859042890589526378487e1, 0.1482921763148403842276533e1, 0.1438984491795164536567108e1, 0.1395047233189252525231459e1, 0.1351109991891878034957302e1, 0.1307172772745304669260382e1, 0.1263235580960968906699379e1, 0.1219298422221050703835127e1, 0.1175361302797916700875697e1, 0.1131424229697065895207730e1, 0.1087487210830887883186060e1, 0.1043550255232887174273672e1, 0.9996133733253190253881393e0, 0.9556765772578535710715874e0, 0.9117398813415957196221754e0, 0.8678033026125661948850687e0, 0.8238668615732247310812836e0, 0.7799305831824293601507400e0, 0.7359944981977457886183921e0, 0.6920586450266629333858465e0, 0.6481230723279649663476697e0, 0.6041878427445000852182582e0, 0.5602530383870993537615272e0, 0.5163187691099712879003757e0, 0.4723851853891499571797438e0, 0.4284524990953311047063058e0, 0.3845210184454249891341793e0, 0.3405912098612419399584605e0, 0.2966638144233703899038032e0, 0.2527400847124078576715667e0, 0.2088223170017057788708674e0, 0.1649152190599722827308055e0, 0.1210301722471160155498167e0, 0.7720326018898817828206987e-1, 0.3363364974516995102167462e-1}, + {0.1528054559083405137047563e1, 0.1485312794997097705446883e1, 0.1442571038214470776579613e1, 0.1399829292522320013570493e1, 0.1357087561874166765548658e1, 0.1314345850454078759228779e1, 0.1271604162748143389685638e1, 0.1228862503626296926524085e1, 0.1186120878437839368895715e1, 0.1143379293124832099340074e1, 0.1100637754358770795248912e1, 0.1057896269707576280860569e1, 0.1015154847842238156769126e1, 0.9724134987956584339974640e0, 0.9296722342907946818431047e0, 0.8869310681617368097575324e0, 0.8441900169008687429295884e0, 0.8014491003793523040286325e0, 0.7587083428093935362576859e0, 0.7159677740493625646700975e0, 0.6732274314040501413860867e0, 0.6304873621547357085895928e0, 0.5877476271899241333221832e0, 0.5450083063396327078463020e0, 0.5022695064252395155059223e0, 0.4595313737871711838065652e0, 0.4167941144922007176438387e0, 0.3740580283336802289311736e0, 0.3313235690067746553700419e0, 0.2885914573933480330041531e0, 0.2458629119584249278750153e0, 0.2031401664615301668533461e0, 0.1604278005405711652039491e0, 0.1177368858339244458607172e0, 0.7510252408650086658441596e-1, 0.3271846270775478856070884e-1}, + {0.1529186740959505109653289e1, 0.1487577158293388707508111e1, 0.1445967582009979387718202e1, 0.1404358015412336440816745e1, 0.1362748461941311565399969e1, 0.1321138925227929972823825e1, 0.1279529409151733277951100e1, 0.1237919917907156982173977e1, 0.1196310456080472987418488e1, 0.1154701028740456700905269e1, 0.1113091641546798022997704e1, 0.1071482300881451340842721e1, 0.1029873014009735917989475e1, 0.9882637892802373569245916e0, 0.9466546363756944528310758e0, 0.9050455666314926033869497e0, 0.8634365934447506520344540e0, 0.8218277328062565148449433e0, 0.7802190040012226850703573e0, 0.7386104305454957746359112e0, 0.6970020414556031913861513e0, 0.6553938730008771105113861e0, 0.6137859711661063914322283e0, 0.5721783951857430999179669e0, 0.5305712227365694155165922e0, 0.4889645577740232855661796e0, 0.4473585427277744403333139e0, 0.4057533781735039172217875e0, 0.3641493559322687127223795e0, 0.3225469176515179389138545e0, 0.2809467650889194227770571e0, 0.2393500844055270891104500e0, 0.1977590501629603151642330e0, 0.1561781206604067112364815e0, 0.1146180742271483316267615e0, 0.7311308274978660184520447e-1, 0.3185176130791400787169333e-1}, + {0.1530260491394766313570510e1, 0.1489724658775115137266557e1, 0.1449188831753177403184250e1, 0.1408653013220734918131897e1, 0.1368117206184034069757975e1, 0.1327581413807020172726043e1, 0.1287045639459248683416470e1, 0.1246509886770075360771330e1, 0.1205974159691064843702080e1, 0.1165438462569017837684371e1, 0.1124902800232641860108690e1, 0.1084367178096737546333982e1, 0.1043831602288925654461738e1, 0.1003296079805520648394589e1, 0.9627606187053432591598275e0, 0.9222252283533212928777294e0, 0.8816899197300536544215117e0, 0.8411547058297167490229198e0, 0.8006196021777239861105672e0, 0.7600846275129127849719743e0, 0.7195498046991648764002008e0, 0.6790151619622966197448464e0, 0.6384807345966275863946969e0, 0.5979465673637771458800754e0, 0.5574127179353942966481713e0, 0.5168792619515766918187819e0, 0.4763463006547495614450433e0, 0.4358139727703203523144583e0, 0.3952824736706231680817472e0, 0.3547520876199503791717895e0, 0.3142232448436673832093046e0, 0.2736966289659020439688229e0, 0.2331733955144496369946707e0, 0.1926556629116315949109922e0, 0.1521477743835989472840536e0, 0.1116602300918232453371161e0, 0.7122632005925390425640031e-1, 0.3102979192734513847869512e-1}, + {0.1531280219945530918862887e1, 0.1491764115543711582608611e1, 0.1452248016067723206269747e1, 0.1412731924058150689920340e1, 0.1373215842151127100608219e1, 0.1333699773114208203180680e1, 0.1294183719885939986844436e1, 0.1254667685620366764206205e1, 0.1215151673737978313041594e1, 0.1175635687984935008823566e1, 0.1136119732502868295328130e1, 0.1096603811912170337964094e1, 0.1057087931412518476253055e1, 0.1017572096905509113863513e1, 0.9780563151458206514020694e0, 0.9385405939294598498464432e0, 0.8990249423306286659734381e0, 0.8595093710029676968794279e0, 0.8199938925669823205931282e0, 0.7804785221142635001130339e0, 0.7409632778721439753645470e0, 0.7014481820920565808095373e0, 0.6619332622550151160558599e0, 0.6224185527349885679868616e0, 0.5829040971371158016902326e0, 0.5433899516536147244946347e0, 0.5038761899947552937603140e0, 0.4643629108305196256509391e0, 0.4248502493722176391609139e0, 0.3853383960541810555628366e0, 0.3458276279674767760058527e0, 0.3063183644932167228808922e0, 0.2668112720373341483108662e0, 0.2273074770384765519559169e0, 0.1878090446069578429818381e0, 0.1483202086882449059764783e0, 0.1088512052741322662621244e0, 0.6943448689600673838300180e-1, 0.3024917865720923179577363e-1}, + {0.1532249903371281818085917e1, 0.1493703482108998740614827e1, 0.1455157065195200346809599e1, 0.1416610654869340270223431e1, 0.1378064253450997606022340e1, 0.1339517863369794055919890e1, 0.1300971487198245305453001e1, 0.1262425127688525048786896e1, 0.1223878787814308166546501e1, 0.1185332470819113339105535e1, 0.1146786180272904774996439e1, 0.1108239920139165765487189e1, 0.1069693694855262920629379e1, 0.1031147509429735196850587e1, 0.9926013695612463310882198e0, 0.9540552817854489715123326e0, 0.9155092536580933534978986e0, 0.8769632939856246206308699e0, 0.8384174131186299393233148e0, 0.7998716233293992826192237e0, 0.7613259393034545837300323e0, 0.7227803787876118667749166e0, 0.6842349634562860931661901e0, 0.6456897200871628101751519e0, 0.6071446821835496233813653e0, 0.5685998922550279415939221e0, 0.5300554050908430047380815e0, 0.4915112925697217767572364e0, 0.4529676509187802579380104e0, 0.4144246120108054286121629e0, 0.3758823615873930314093573e0, 0.3373411699211847213003570e0, 0.2988014460838619282843952e0, 0.2602638401106843145315994e0, 0.2217294507811754336425535e0, 0.1832002925124018168986342e0, 0.1446804953347050655563166e0, 0.1061800440374660771048480e0, 0.6773059476567831336488402e-1, 0.2950687695527422224851832e-1}, + {0.1533173137460634461235066e1, 0.1495549950040734249895393e1, 0.1457926766471340970762709e1, 0.1420303588732694442267846e1, 0.1382680418872520759663065e1, 0.1345057259031099988676433e1, 0.1307434111468678960501903e1, 0.1269810978596001635506341e1, 0.1232187863008871596257323e1, 0.1194564767527851916244615e1, 0.1156941695244461089553108e1, 0.1119318649575559636172662e1, 0.1081695634328067979412755e1, 0.1044072653776750930510111e1, 0.1006449712758602402124214e1, 0.9688268167884441336521039e0, 0.9312039722018274751677424e0, 0.8935811863333633591901354e0, 0.8559584677414483220357356e0, 0.8183358264943738874932307e0, 0.7807132745385688213392421e0, 0.7430908261781095392995681e0, 0.7054684987070400358784448e0, 0.6678463132547297820965882e0, 0.6302242959332082940279826e0, 0.5926024794204980683238426e0, 0.5549809051864955237054951e0, 0.5173596266878257139037738e0, 0.4797387140623364241772428e0, 0.4421182612140318859822955e0, 0.4044983968396638104610711e0, 0.3668793022152994411560368e0, 0.3292612411240570212440856e0, 0.2916446128242035199998930e0, 0.2540300517665934607689814e0, 0.2164186303985620085027010e0, 0.1788123148742007754778852e0, 0.1412151362884411752920148e0, 0.1036368402634645114775150e0, 0.6610832470916409695729856e-1, 0.2880013396280840229218334e-1}, + {0.1534053181584449084854269e1, 0.1497310038074501005766978e1, 0.1460566897984002644464183e1, 0.1423823763069232867789940e1, 0.1387080635143547965139117e1, 0.1350337516098480646600889e1, 0.1313594407926723776707731e1, 0.1276851312747612578778902e1, 0.1240108232835827171448969e1, 0.1203365170654181674634873e1, 0.1166622128891556900019450e1, 0.1129879110507284864268762e1, 0.1093136118783624474731954e1, 0.1056393157388405786003046e1, 0.1019650230450503114577901e1, 0.9829073426515786199715451e0, 0.9461644993385942743541994e0, 0.9094217066630320811486021e0, 0.8726789717547518480094350e0, 0.8359363029411928866147184e0, 0.7991937100265521402467844e0, 0.7624512046511992388808212e0, 0.7257088007597790982554974e0, 0.6889665152185689899094400e0, 0.6522243686409073299342467e0, 0.6154823865075504175164916e0, 0.5787406007128420496638175e0, 0.5419990517384125648087865e0, 0.5052577917731960988645056e0, 0.4685168892980173635234519e0, 0.4317764360047099160222576e0, 0.3950365575646972937604113e0, 0.3582974309994310205507555e0, 0.3215593139080007759227897e0, 0.2848225961961619069649047e0, 0.2480878974611689122432227e0, 0.2113562650517154915467591e0, 0.1746296191183898065201571e0, 0.1379118964507339113271975e0, 0.1012126146941469342401701e0, 0.6456194899726137278760257e-1, 0.2812645439079299219187419e-1}, + {0.1534892997139557227614279e1, 0.1498989668998897501276994e1, 0.1463086343903285773505644e1, 0.1427183023414814244376429e1, 0.1391279709144040438287602e1, 0.1355376402767821814937864e1, 0.1319473106048673173924451e1, 0.1283569820856137399848247e1, 0.1247666549190742942502495e1, 0.1211763293211231530413995e1, 0.1175860055265884319525693e1, 0.1139956837928964066704190e1, 0.1104053644043538840797350e1, 0.1068150476772278342447444e1, 0.1032247339658243608912598e1, 0.9963442366982618328585493e0, 0.9604411724322426430586723e0, 0.9245381520528253319358567e0, 0.8886351815411563067305273e0, 0.8527322678365406966379400e0, 0.8168294190504262166761188e0, 0.7809266447390142664026016e0, 0.7450239562542930157586944e0, 0.7091213672012904985883029e0, 0.6732188940411854039055226e0, 0.6373165568977466866717861e0, 0.6014143806519714388063208e0, 0.5655123964528129857845238e0, 0.5296106438411039715966193e0, 0.4937091737981756577948229e0, 0.4578080532255782153525438e0, 0.4219073717059785387344039e0, 0.3860072520255396095683859e0, 0.3501078671472635990145335e0, 0.3142094687704932495909488e0, 0.2783124378775218384923333e0, 0.2424173798924625361874772e0, 0.2065253182141071551836492e0, 0.1706381290938671641708352e0, 0.1347596593282315198612592e0, 0.9889920900871122533586553e-1, 0.6308626356388784057588631e-1, 0.2748357108440508277394892e-1}, + {0.1535695280838629983064694e1, 0.1500594236235067817656313e1, 0.1465493194350303789230585e1, 0.1430392156577492526495371e1, 0.1395291124351096810858349e1, 0.1360190099162024176252063e1, 0.1325089082574000089379322e1, 0.1289988076241572027256558e1, 0.1254887081930202663795858e1, 0.1219786101538994920367859e1, 0.1184685137126702182946916e1, 0.1149584190941820846004092e1, 0.1114483265457749469332035e1, 0.1079382363414242848588494e1, 0.1044281487866708939888712e1, 0.1009180642245317812316634e1, 0.9740798304264509422659935e0, 0.9389790568197674899837757e0, 0.9038783264751749171405213e0, 0.8687776452153701566068907e0, 0.8336770198015192229270720e0, 0.7985764581422970742698971e0, 0.7634759695602610192254430e0, 0.7283755651349081311799055e0, 0.6932752581495918103871962e0, 0.6581750646810479477537782e0, 0.6230750043877162525265513e0, 0.5879751015798285374141491e0, 0.5528753866962970290878822e0, 0.5177758983811020490994086e0, 0.4826766864637186565865902e0, 0.4475778163386701445336738e0, 0.4124793755752883735361361e0, 0.3773814842049053432591527e0, 0.3422843113148581639684411e0, 0.3071881029697497767338606e0, 0.2720932316284942932084102e0, 0.2370002891767127567222407e0, 0.2019102761348421810146637e0, 0.1668250268181992892198073e0, 0.1317483020532982541977987e0, 0.9668919410176593344830717e-1, 0.6167652949817792358742135e-1, 0.2686941953400762687915995e-1}, + {0.1536462493634653558154673e1, 0.1502128661685489464262068e1, 0.1467794832169950298839286e1, 0.1433461006333747476463744e1, 0.1399127185457927306909792e1, 0.1364793370871767472755746e1, 0.1330459563966682507229700e1, 0.1296125766211456950047804e1, 0.1261791979169174443914592e1, 0.1227458204516276373551266e1, 0.1193124444064268679881601e1, 0.1158790699784705540565424e1, 0.1124456973838220917338613e1, 0.1090123268608563332983681e1, 0.1055789586742829027889885e1, 0.1021455931199402224481903e1, 0.9871223053055240306873772e0, 0.9527887128269590857605072e0, 0.9184551580529615732874848e0, 0.8841216459007313197085517e0, 0.8497881820448998068986446e0, 0.8154547730794463756650640e0, 0.7811214267220410983907210e0, 0.7467881520744805288579630e0, 0.7124549599581423848996086e0, 0.6781218633510390484774053e0, 0.6437888779643722276961833e0, 0.6094560230135452763170614e0, 0.5751233222647905281576305e0, 0.5407908054797110156395425e0, 0.5064585104462232763044121e0, 0.4721264858937837018545325e0, 0.4377947957771643018072936e0, 0.4034635257416918872885646e0, 0.3691327931855416440777167e0, 0.3348027634909946151567752e0, 0.3004736773353657517478163e0, 0.2661458990278703974149616e0, 0.2318200075085118064771005e0, 0.1974969814205034596217949e0, 0.1631786149772797106698111e0, 0.1288685867945150272796250e0, 0.9457579039019365184018477e-1, 0.6032842220945916819748797e-1, 0.2628211572883546008386342e-1}, + {0.1537196885933572311910085e1, 0.1503597446159129663218426e1, 0.1469998008568304160871417e1, 0.1436398574277729377094190e1, 0.1402799144434368418084898e1, 0.1369199720226542342210552e1, 0.1335600302895785666466344e1, 0.1302000893749787833197270e1, 0.1268401494176718217187838e1, 0.1234802105661283063077015e1, 0.1201202729802928570677208e1, 0.1167603368336689119731474e1, 0.1134004023157288628212183e1, 0.1100404696347243386055709e1, 0.1066805390209896030700280e1, 0.1033206107308545748870827e1, 0.9996068505131472996246808e0, 0.9660076230564559666956844e0, 0.9324084286020318648375284e0, 0.8988092713272342656758064e0, 0.8652101560253048754543914e0, 0.8316110882319595313175680e0, 0.7980120743837286767240920e0, 0.7644131220178278512956878e0, 0.7308142400269308414762795e0, 0.6972154389873656296775555e0, 0.6636167315867435235683334e0, 0.6300181331881122315700717e0, 0.5964196625844131090385918e0, 0.5628213430226633060114218e0, 0.5292232036175455988770345e0, 0.4956252813388603291268380e0, 0.4620276238643496856689332e0, 0.4284302937718012609061760e0, 0.3948333748659561479104270e0, 0.3612369820255324850503899e0, 0.3276412770872600895283016e0, 0.2940464955725917238672137e0, 0.2604529939906062681054034e0, 0.2268613388903867245835696e0, 0.1932724879746856807613294e0, 0.1596881970714452359218090e0, 0.1261120661032951679792394e0, 0.9255279834764232165670211e-1, 0.5903798711627596210077655e-1, 0.2571993685288741305807485e-1}, + {0.1537900519639177351485509e1, 0.1505004713461118831562885e1, 0.1472108909246876714959093e1, 0.1439213107999753788389740e1, 0.1406317310749171844429399e1, 0.1373421518560135827011261e1, 0.1340525732543378926238078e1, 0.1307629953866399941713193e1, 0.1274734183765634621652739e1, 0.1241838423560042429086765e1, 0.1208942674666441461574345e1, 0.1176046938616989970936899e1, 0.1143151217079296988032361e1, 0.1110255511879752164142939e1, 0.1077359825030803093319347e1, 0.1044464158763086533573607e1, 0.1011568515563550961534623e1, 0.9786728982210094134846821e0, 0.9457773098809579873452675e0, 0.9128817541120207886160886e0, 0.8799862349870845994262022e0, 0.8470907571831347751008168e0, 0.8141953261050969543263697e0, 0.7812999480407721032432037e0, 0.7484046303564402266425896e0, 0.7155093817462244075628281e0, 0.6826142125533466396520346e0, 0.6497191351887403950357432e0, 0.6168241646833332909207560e0, 0.5839293194266532352434130e0, 0.5510346221695150324949297e0, 0.5181401014079633610544426e0, 0.4852457933290632607369490e0, 0.4523517446039431388003505e0, 0.4194580164920722423612656e0, 0.3865646910356375140534892e0, 0.3536718807003189971969294e0, 0.3207797439266498255416416e0, 0.2878885112969848452450724e0, 0.2549985318477515756044100e0, 0.2221103602568508117102717e0, 0.1892249341643785313168465e0, 0.1563439726212394862316010e0, 0.1234710001537068179882843e0, 0.9061453776736619019094845e-1, 0.5780160090309369034797044e-1, 0.2518130440638251656980999e-1}, + {0.1538575287485045780713568e1, 0.1506354249056545799167351e1, 0.1474133212398093554231315e1, 0.1441912178413208451704314e1, 0.1409691148027973881079186e1, 0.1377470122199186272616473e1, 0.1345249101923067139210221e1, 0.1313028088244711409410919e1, 0.1280807082268469343020428e1, 0.1248586085169490583375238e1, 0.1216365098206699074213627e1, 0.1184144122737518830558069e1, 0.1151923160234735793613503e1, 0.1119702212305964062886069e1, 0.1087481280716290811591462e1, 0.1055260367414810028339009e1, 0.1023039474565930165787482e1, 0.9908186045865674272211987e0, 0.9585977601906320722299056e0, 0.9263769444426036830464570e0, 0.8941561608225061952846411e0, 0.8619354133052817812042663e0, 0.8297147064584916186566054e0, 0.7974940455635382827549679e0, 0.7652734367673509855003551e0, 0.7330528872739117793257283e0, 0.7008324055884451343305450e0, 0.6686120018320298047193041e0, 0.6363916881515750209117372e0, 0.6041714792607289968809847e0, 0.5719513931632926368357825e0, 0.5397314521353000325496229e0, 0.5075116840805377280486923e0, 0.4752921244363891783961832e0, 0.4430728189095547215892704e0, 0.4108538274961112658763390e0, 0.3786352305487998074788803e0, 0.3464171382200184643128623e0, 0.3141997056941599156198233e0, 0.2819831588178046655599196e0, 0.2497678394619649260592757e0, 0.2175542909210219972765731e0, 0.1853434315961135904158300e0, 0.1531369452704970394027659e0, 0.1209382841678252589048669e0, 0.8875579450016283173293810e-1, 0.5661593754525190873771522e-1, 0.2466476940450737058975552e-1}, + {0.1539222930035210331902410e1, 0.1507649534071729882214386e1, 0.1476076139707032453353232e1, 0.1444502747756546556830706e1, 0.1412929359055252480197337e1, 0.1381355974464721552102928e1, 0.1349782594880622732927647e1, 0.1318209221240839295255046e1, 0.1286635854534357387243172e1, 0.1255062495811112994872428e1, 0.1223489146193015470717893e1, 0.1191915806886406014313715e1, 0.1160342479196260434661502e1, 0.1128769164542510055952304e1, 0.1097195864478936528824546e1, 0.1065622580715200621234508e1, 0.1034049315142698534418744e1, 0.1002476069865111021377467e1, 0.9709028472347329448081481e0, 0.9393296498959608456620406e0, 0.9077564808376970380335442e0, 0.8761833434569334264096395e0, 0.8446102416364528348063321e0, 0.8130371798404960344077378e0, 0.7814641632334840064334645e0, 0.7498911978285964532098456e0, 0.7183182906753955596314298e0, 0.6867454500990591398232408e0, 0.6551726860086246453663390e0, 0.6236000102986843027011345e0, 0.5920274373793840619034224e0, 0.5604549848852622707385612e0, 0.5288826746375584896948472e0, 0.4973105339724571989307663e0, 0.4657385976085971045914307e0, 0.4341669103277770901346174e0, 0.4025955309141879357899857e0, 0.3710245380997234377015025e0, 0.3394540398171456073906403e0, 0.3078841881262277508367562e0, 0.2763152043287541015913350e0, 0.2447474234189502677044064e0, 0.2131813777658572006989977e0, 0.1816179673056091210434906e0, 0.1500588419721174291665790e0, 0.1185073845935281602210493e0, 0.8697177361567243680812898e-1, 0.5547793843128156580348541e-1, 0.2416899936118312040170588e-1}, +} + +// The weights of these nodes +var evenWeights = [][]float64{ + {1.0}, + {0.6521451548625461426269364e0, 0.3478548451374538573730642e0}, + {0.4679139345726910473898704e0, 0.3607615730481386075698336e0, 0.1713244923791703450402969e0}, + {0.3626837833783619829651504e0, 0.3137066458778872873379622e0, 0.2223810344533744705443556e0, 0.1012285362903762591525320e0}, + {0.2955242247147528701738930e0, 0.2692667193099963550912268e0, 0.2190863625159820439955350e0, 0.1494513491505805931457764e0, 0.6667134430868813759356850e-1}, + {0.2491470458134027850005624e0, 0.2334925365383548087608498e0, 0.2031674267230659217490644e0, 0.1600783285433462263346522e0, 0.1069393259953184309602552e0, 0.4717533638651182719461626e-1}, + {0.2152638534631577901958766e0, 0.2051984637212956039659240e0, 0.1855383974779378137417164e0, 0.1572031671581935345696019e0, 0.1215185706879031846894145e0, 0.8015808715976020980563266e-1, 0.3511946033175186303183410e-1}, + {0.1894506104550684962853967e0, 0.1826034150449235888667636e0, 0.1691565193950025381893119e0, 0.1495959888165767320815019e0, 0.1246289712555338720524763e0, 0.9515851168249278480992520e-1, 0.6225352393864789286284360e-1, 0.2715245941175409485178166e-1}, + {0.1691423829631435918406565e0, 0.1642764837458327229860538e0, 0.1546846751262652449254180e0, 0.1406429146706506512047311e0, 0.1225552067114784601845192e0, 0.1009420441062871655628144e0, 0.7642573025488905652912984e-1, 0.4971454889496979645333512e-1, 0.2161601352648331031334248e-1}, + {0.1527533871307258506980843e0, 0.1491729864726037467878288e0, 0.1420961093183820513292985e0, 0.1316886384491766268984948e0, 0.1181945319615184173123774e0, 0.1019301198172404350367504e0, 0.8327674157670474872475850e-1, 0.6267204833410906356950596e-1, 0.4060142980038694133103928e-1, 0.1761400713915211831186249e-1}, + {0.1392518728556319933754102e0, 0.1365414983460151713525738e0, 0.1311735047870623707329649e0, 0.1232523768105124242855609e0, 0.1129322960805392183934005e0, 0.1004141444428809649320786e0, 0.8594160621706772741444398e-1, 0.6979646842452048809496104e-1, 0.5229333515268328594031142e-1, 0.3377490158481415479330258e-1, 0.1462799529827220068498987e-1}, + {0.1279381953467521569740562e0, 0.1258374563468282961213754e0, 0.1216704729278033912044631e0, 0.1155056680537256013533445e0, 0.1074442701159656347825772e0, 0.9761865210411388826988072e-1, 0.8619016153195327591718514e-1, 0.7334648141108030573403386e-1, 0.5929858491543678074636724e-1, 0.4427743881741980616860272e-1, 0.2853138862893366318130802e-1, 0.1234122979998719954680507e-1}, + {0.1183214152792622765163711e0, 0.1166604434852965820446624e0, 0.1133618165463196665494407e0, 0.1084718405285765906565795e0, 0.1020591610944254232384142e0, 0.9421380035591414846366474e-1, 0.8504589431348523921044770e-1, 0.7468414976565974588707538e-1, 0.6327404632957483553945402e-1, 0.5097582529714781199831990e-1, 0.3796238329436276395030342e-1, 0.2441785109263190878961718e-1, 0, .1055137261734300715565387e-1}, + {0.1100470130164751962823763e0, 0.1087111922582941352535716e0, 0.1060557659228464179104165e0, 0.1021129675780607698142166e0, 0.9693065799792991585048880e-1, 0.9057174439303284094218612e-1, 0.8311341722890121839039666e-1, 0.7464621423456877902393178e-1, 0.6527292396699959579339794e-1, 0.5510734567571674543148330e-1, 0.4427293475900422783958756e-1, 0.3290142778230437997763004e-1, 0.2113211259277125975149896e-1, 0.9124282593094517738816778e-2}, + {0.1028526528935588403412856e0, 0.1017623897484055045964290e0, 0.9959342058679526706278018e-1, 0.9636873717464425963946864e-1, 0.9212252223778612871763266e-1, 0.8689978720108297980238752e-1, 0.8075589522942021535469516e-1, 0.7375597473770520626824384e-1, 0.6597422988218049512812820e-1, 0.5749315621761906648172152e-1, 0.4840267283059405290293858e-1, 0.3879919256962704959680230e-1, 0.2878470788332336934971862e-1, 0.1846646831109095914230276e-1, 0.7968192496166605615469690e-2}, + {0.9654008851472780056676488e-1, 0.9563872007927485941908208e-1, 0.9384439908080456563918026e-1, 0.9117387869576388471286854e-1, 0.8765209300440381114277140e-1, 0.8331192422694675522219922e-1, 0.7819389578707030647174106e-1, 0.7234579410884850622539954e-1, 0.6582222277636184683765034e-1, 0.5868409347853554714528360e-1, 0.5099805926237617619616316e-1, 0.4283589802222668065687810e-1, 0.3427386291302143310268716e-1, 0.2539206530926205945575196e-1, 0.1627439473090567060516896e-1, 0.7018610009470096600404748e-2}, + {0.9095674033025987361533764e-1, 0.9020304437064072957394216e-1, 0.8870189783569386928707642e-1, 0.8646573974703574978424688e-1, 0.8351309969984565518702044e-1, 0.7986844433977184473881888e-1, 0.7556197466003193127083398e-1, 0.7062937581425572499903896e-1, 0.6511152155407641137854442e-1, 0.5905413582752449319396124e-1, 0.5250741457267810616824590e-1, 0.4552561152335327245382266e-1, 0.3816659379638751632176606e-1, 0.3049138063844613180944194e-1, 0.2256372198549497008409476e-1, 0.1445016274859503541520101e-1, 0.6229140555908684718603220e-2}, + {0.8598327567039474749008516e-1, 0.8534668573933862749185052e-1, 0.8407821897966193493345756e-1, 0.8218726670433970951722338e-1, 0.7968782891207160190872470e-1, 0.7659841064587067452875784e-1, 0.7294188500565306135387342e-1, 0.6874532383573644261368974e-1, 0.6403979735501548955638454e-1, 0.5886014424532481730967550e-1, 0.5324471397775991909202590e-1, 0.4723508349026597841661708e-1, 0.4087575092364489547411412e-1, 0.3421381077030722992124474e-1, 0.2729862149856877909441690e-1, 0.2018151529773547153209770e-1, 0.1291594728406557440450307e-1, 0.5565719664245045361251818e-2}, + {0.8152502928038578669921876e-1, 0.8098249377059710062326952e-1, 0.7990103324352782158602774e-1, 0.7828784465821094807537540e-1, 0.7615366354844639606599344e-1, 0.7351269258474345714520658e-1, 0.7038250706689895473928292e-1, 0.6678393797914041193504612e-1, 0.6274093339213305405296984e-1, 0.5828039914699720602230556e-1, 0.5343201991033231997375704e-1, 0.4822806186075868337435238e-1, 0.4270315850467443423587832e-1, 0.3689408159402473816493978e-1, 0.3083950054517505465873166e-1, 0.2457973973823237589520214e-1, 0.1815657770961323689887502e-1, 0.1161344471646867417766868e-1, 0.5002880749639345675901886e-2}, + {0.7750594797842481126372404e-1, 0.7703981816424796558830758e-1, 0.7611036190062624237155810e-1, 0.7472316905796826420018930e-1, 0.7288658239580405906051074e-1, 0.7061164739128677969548346e-1, 0.6791204581523390382569024e-1, 0.6480401345660103807455446e-1, 0.6130624249292893916653822e-1, 0.5743976909939155136661768e-1, 0.5322784698393682435499678e-1, 0.4869580763507223206143380e-1, 0.4387090818567327199167442e-1, 0.3878216797447201763997196e-1, 0.3346019528254784739267780e-1, 0.2793700698002340109848970e-1, 0.2224584919416695726150432e-1, 0.1642105838190788871286396e-1, 0.1049828453115281361474434e-1, 0.4521277098533191258471490e-2}, + {0.7386423423217287999638556e-1, 0.7346081345346752826402828e-1, 0.7265617524380410488790570e-1, 0.7145471426517098292181042e-1, 0.6986299249259415976615480e-1, 0.6788970337652194485536350e-1, 0.6554562436490897892700504e-1, 0.6284355804500257640931846e-1, 0.5979826222758665431283142e-1, 0.5642636935801838164642686e-1, 0.5274629569917407034394234e-1, 0.4877814079280324502744954e-1, 0.4454357777196587787431674e-1, 0.4006573518069226176059618e-1, 0.3536907109759211083266214e-1, 0.3047924069960346836290502e-1, 0.2542295952611304788674188e-1, 0.2022786956905264475705664e-1, 0.1492244369735749414467869e-1, 0.9536220301748502411822340e-2, 0.4105998604649084610599928e-2}, + {0.7054915778935406881133824e-1, 0.7019768547355821258714200e-1, 0.6949649186157257803708402e-1, 0.6844907026936666098545864e-1, 0.6706063890629365239570506e-1, 0.6533811487918143498424096e-1, 0.6329007973320385495013890e-1, 0.6092673670156196803855800e-1, 0.5825985987759549533421064e-1, 0.5530273556372805254874660e-1, 0.5207009609170446188123162e-1, 0.4857804644835203752763920e-1, 0.4484398408197003144624282e-1, 0.4088651231034621890844686e-1, 0.3672534781380887364290888e-1, 0.3238122281206982088084682e-1, 0.2787578282128101008111450e-1, 0.2323148190201921062895910e-1, 0.1847148173681474917204335e-1, 0.1361958675557998552020491e-1, 0.8700481367524844122565470e-2, 0.3745404803112777515171456e-2}, + {0.6751868584903645882021418e-1, 0.6721061360067817586237416e-1, 0.6659587476845488737576196e-1, 0.6567727426778120737875756e-1, 0.6445900346713906958827948e-1, 0.6294662106439450817895206e-1, 0.6114702772465048101535670e-1, 0.5906843459554631480755080e-1, 0.5672032584399123581687444e-1, 0.5411341538585675449163752e-1, 0.5125959800714302133536554e-1, 0.4817189510171220053046892e-1, 0.4486439527731812676709458e-1, 0.4135219010967872970421980e-1, 0.3765130535738607132766076e-1, 0.3377862799910689652060416e-1, 0.2975182955220275579905234e-1, 0.2558928639713001063470016e-1, 0.2130999875413650105447862e-1, 0.1693351400783623804623151e-1, 0.1247988377098868420673525e-1, 0.7969898229724622451610710e-2, 0.3430300868107048286016700e-2}, + {0.6473769681268392250302496e-1, 0.6446616443595008220650418e-1, 0.6392423858464818662390622e-1, 0.6311419228625402565712596e-1, 0.6203942315989266390419786e-1, 0.6070443916589388005296916e-1, 0.5911483969839563574647484e-1, 0.5727729210040321570515042e-1, 0.5519950369998416286820356e-1, 0.5289018948519366709550490e-1, 0.5035903555385447495780746e-1, 0.4761665849249047482590674e-1, 0.4467456085669428041944838e-1, 0.4154508294346474921405856e-1, 0.3824135106583070631721688e-1, 0.3477722256477043889254814e-1, 0.3116722783279808890206628e-1, 0.2742650970835694820007336e-1, 0.2357076083932437914051962e-1, 0.1961616045735552781446139e-1, 0.1557931572294384872817736e-1, 0.1147723457923453948959265e-1, 0.7327553901276262102386656e-2, 0.3153346052305838632678320e-2}, + {0.6217661665534726232103316e-1, 0.6193606742068324338408750e-1, 0.6145589959031666375640678e-1, 0.6073797084177021603175000e-1, 0.5978505870426545750957640e-1, 0.5860084981322244583512250e-1, 0.5718992564772838372302946e-1, 0.5555774480621251762356746e-1, 0.5371062188899624652345868e-1, 0.5165570306958113848990528e-1, 0.4940093844946631492124360e-1, 0.4695505130394843296563322e-1, 0.4432750433880327549202254e-1, 0.4152846309014769742241230e-1, 0.3856875661258767524477018e-1, 0.3545983561514615416073452e-1, 0.3221372822357801664816538e-1, 0.2884299358053519802990658e-1, 0.2536067357001239044019428e-1, 0.2178024317012479298159128e-1, 0.1811556071348939035125903e-1, 0.1438082276148557441937880e-1, 0.1059054838365096926356876e-1, 0.6759799195745401502778824e-2, 0.2908622553155140958394976e-2}, + {0.5981036574529186024778538e-1, 0.5959626017124815825831088e-1, 0.5916881546604297036933200e-1, 0.5852956177181386855029062e-1, 0.5768078745252682765393200e-1, 0.5662553090236859719080832e-1, 0.5536756966930265254904124e-1, 0.5391140693275726475083694e-1, 0.5226225538390699303439404e-1, 0.5042601856634237721821144e-1, 0.4840926974407489685396032e-1, 0.4621922837278479350764582e-1, 0.4386373425900040799512978e-1, 0.4135121950056027167904044e-1, 0.3869067831042397898510146e-1, 0.3589163483509723294194276e-1, 0.3296410908971879791501014e-1, 0.2991858114714394664128188e-1, 0.2676595374650401344949324e-1, 0.2351751355398446159032286e-1, 0.2018489150798079220298930e-1, 0.1678002339630073567792252e-1, 0.1331511498234096065660116e-1, 0.9802634579462752061952706e-2, 0.6255523962973276899717754e-2, 0.2691316950047111118946698e-2}, + {0.5761753670714702467237616e-1, 0.5742613705411211485929010e-1, 0.5704397355879459856782852e-1, 0.5647231573062596503104434e-1, 0.5571306256058998768336982e-1, 0.5476873621305798630622270e-1, 0.5364247364755361127210060e-1, 0.5233801619829874466558872e-1, 0.5085969714618814431970910e-1, 0.4921242732452888606879048e-1, 0.4740167880644499105857626e-1, 0.4543346672827671397485208e-1, 0.4331432930959701544192564e-1, 0.4105130613664497422171834e-1, 0.3865191478210251683685736e-1, 0.3612412584038355258288694e-1, 0.3347633646437264571604038e-1, 0.3071734249787067605400450e-1, 0.2785630931059587028700164e-1, 0.2490274146720877305005456e-1, 0.2186645142285308594551102e-1, 0.1875752762146937791200757e-1, 0.1558630303592413170296832e-1, 0.1236332812884764416646861e-1, 0.9099369455509396948032734e-2, 0.5805611015239984878826112e-2, 0.2497481835761585775945054e-2}, + {0.5557974630651439584627342e-1, 0.5540795250324512321779340e-1, 0.5506489590176242579630464e-1, 0.5455163687088942106175058e-1, 0.5386976186571448570895448e-1, 0.5302137852401076396799152e-1, 0.5200910915174139984305222e-1, 0.5083608261779848056012412e-1, 0.4950592468304757891996610e-1, 0.4802274679360025812073550e-1, 0.4639113337300189676219012e-1, 0.4461612765269228321341510e-1, 0.4270321608466708651103858e-1, 0.4065831138474451788012514e-1, 0.3848773425924766248682568e-1, 0.3619819387231518603588452e-1, 0.3379676711561176129542654e-1, 0.3129087674731044786783572e-1, 0.2868826847382274172988602e-1, 0.2599698705839195219181960e-1, 0.2322535156256531693725830e-1, 0.2038192988240257263480560e-1, 0.1747551291140094650495930e-1, 0.1451508927802147180777130e-1, 0.1150982434038338217377419e-1, 0.8469063163307887661628584e-2, 0.5402522246015337761313780e-2, 0.2323855375773215501098716e-2}, + {0.5368111986333484886390600e-1, 0.5352634330405825210061082e-1, 0.5321723644657901410348096e-1, 0.5275469052637083342964580e-1, 0.5214003918366981897126058e-1, 0.5137505461828572547451486e-1, 0.5046194247995312529765992e-1, 0.4940333550896239286651076e-1, 0.4820228594541774840657052e-1, 0.4686225672902634691841818e-1, 0.4538711151481980250398048e-1, 0.4378110353364025103902560e-1, 0.4204886332958212599457020e-1, 0.4019538540986779688807676e-1, 0.3822601384585843322945902e-1, 0.3614642686708727054078062e-1, 0.3396262049341601079772722e-1, 0.3168089125380932732029244e-1, 0.2930781804416049071839382e-1, 0.2685024318198186847590714e-1, 0.2431525272496395254025850e-1, 0.2171015614014623576691612e-1, 0.1904246546189340865578709e-1, 0.1631987423497096505212063e-1, 0.1355023711298881214517933e-1, 0.1074155353287877411685532e-1, 0.7901973849998674754018608e-2, 0.5039981612650243085015810e-2, 0.2167723249627449943047768e-2}, + {0.5190787763122063973286496e-1, 0.5176794317491018754380368e-1, 0.5148845150098093399504444e-1, 0.5107015606985562740454910e-1, 0.5051418453250937459823872e-1, 0.4982203569055018101115930e-1, 0.4899557545575683538947578e-1, 0.4803703181997118096366674e-1, 0.4694898884891220484701330e-1, 0.4573437971611448664719662e-1, 0.4439647879578711332778398e-1, 0.4293889283593564195423128e-1, 0.4136555123558475561316394e-1, 0.3968069545238079947012286e-1, 0.3788886756924344403094056e-1, 0.3599489805108450306657888e-1, 0.3400389272494642283491466e-1, 0.3192121901929632894945890e-1, 0.2975249150078894524083642e-1, 0.2750355674992479163522324e-1, 0.2518047762152124837957096e-1, 0.2278951694399781986378308e-1, 0.2033712072945728677503268e-1, 0.1782990101420772026039605e-1, 0.1527461859678479930672510e-1, 0.1267816647681596013149540e-1, 0.1004755718228798435788578e-1, 0.7389931163345455531517530e-2, 0.4712729926953568640893942e-2, 0.2026811968873758496433874e-2}, + {0.5024800037525628168840300e-1, 0.5012106956904328807480410e-1, 0.4986752859495239424476130e-1, 0.4948801791969929252786578e-1, 0.4898349622051783710485112e-1, 0.4835523796347767283480314e-1, 0.4760483018410123227045008e-1, 0.4673416847841552480220700e-1, 0.4574545221457018077723242e-1, 0.4464117897712441429364478e-1, 0.4342413825804741958006920e-1, 0.4209740441038509664302268e-1, 0.4066432888241744096828524e-1, 0.3912853175196308412331100e-1, 0.3749389258228002998561838e-1, 0.3576454062276814128558760e-1, 0.3394484437941054509111762e-1, 0.3203940058162467810633926e-1, 0.3005302257398987007700934e-1, 0.2799072816331463754123820e-1, 0.2585772695402469802709536e-1, 0.2365940720868279257451652e-1, 0.2140132227766996884117906e-1, 0.1908917665857319873250324e-1, 0.1672881179017731628855027e-1, 0.1432619182380651776740340e-1, 0.1188739011701050194481938e-1, 0.9418579428420387637936636e-2, 0.6926041901830960871704530e-2, 0.4416333456930904813271960e-2, 0.1899205679513690480402948e-2}, + {0.4869095700913972038336538e-1, 0.4857546744150342693479908e-1, 0.4834476223480295716976954e-1, 0.4799938859645830772812614e-1, 0.4754016571483030866228214e-1, 0.4696818281621001732532634e-1, 0.4628479658131441729595326e-1, 0.4549162792741814447977098e-1, 0.4459055816375656306013478e-1, 0.4358372452932345337682780e-1, 0.4247351512365358900733972e-1, 0.4126256324262352861015628e-1, 0.3995374113272034138665686e-1, 0.3855015317861562912896262e-1, 0.3705512854024004604041492e-1, 0.3547221325688238381069330e-1, 0.3380516183714160939156536e-1, 0.3205792835485155358546770e-1, 0.3023465707240247886797386e-1, 0.2833967261425948322751098e-1, 0.2637746971505465867169136e-1, 0.2435270256871087333817770e-1, 0.2227017380838325415929788e-1, 0.2013482315353020937234076e-1, 0.1795171577569734308504602e-1, 0.1572603047602471932196614e-1, 0.1346304789671864259806029e-1, 0.1116813946013112881859029e-1, 0.8846759826363947723030856e-2, 0.6504457968978362856118112e-2, 0.4147033260562467635287472e-2, 0.1783280721696432947292054e-2}, + {0.4722748126299855484563332e-1, 0.4712209828764473218544518e-1, 0.4691156748762082774625404e-1, 0.4659635863958410362582412e-1, 0.4617717509791597547166640e-1, 0.4565495222527305612043888e-1, 0.4503085530544150021519278e-1, 0.4430627694315316190460328e-1, 0.4348283395666747864757528e-1, 0.4256236377005571631890662e-1, 0.4154692031324188131773448e-1, 0.4043876943895497912586836e-1, 0.3924038386682833018781280e-1, 0.3795443766594162094913028e-1, 0.3658380028813909441368980e-1, 0.3513153016547255590064132e-1, 0.3360086788611223267034862e-1, 0.3199522896404688727128174e-1, 0.3031819621886851919364104e-1, 0.2857351178293187118282268e-1, 0.2676506875425000190879332e-1, 0.2489690251475737263773110e-1, 0.2297318173532665591809836e-1, 0.2099819909186462577733052e-1, 0.1897636172277132593486659e-1, 0.1691218147224521718035102e-1, 0.1481026500273396017364296e-1, 0.1267530398126168187644599e-1, 0.1051206598770575465737803e-1, 0.8325388765990901416725080e-2, 0.6120192018447936365568516e-2, 0.3901625641744248259228942e-2, 0.1677653744007238599334225e-2}, + {0.4584938738725097468656398e-1, 0.4575296541606795051900614e-1, 0.4556032425064828598070770e-1, 0.4527186901844377786941174e-1, 0.4488820634542666782635216e-1, 0.4441014308035275590934876e-1, 0.4383868459795605201060492e-1, 0.4317503268464422322584344e-1, 0.4242058301114249930061428e-1, 0.4157692219740291648457550e-1, 0.4064582447595407614088174e-1, 0.3962924796071230802540652e-1, 0.3852933052910671449325372e-1, 0.3734838532618666771607896e-1, 0.3608889590017987071497568e-1, 0.3475351097975151316679320e-1, 0.3334503890398068790314300e-1, 0.3186644171682106493934736e-1, 0.3032082893855398034157906e-1, 0.2871145102748499071080394e-1, 0.2704169254590396155797848e-1, 0.2531506504517639832390244e-1, 0.2353519968587633336129308e-1, 0.2170583961037807980146532e-1, 0.1983083208795549829102926e-1, 0.1791412045792315248940600e-1, 0.1595973590961380007213420e-1, 0.1397178917445765581596455e-1, 0.1195446231976944210322336e-1, 0.9912001251585937209131520e-2, 0.7848711393177167415052160e-2, 0.5768969918729952021468320e-2, 0.3677366595011730633570254e-2, 0.1581140256372912939103728e-2}, + {0.4454941715975466720216750e-1, 0.4446096841724637082355728e-1, 0.4428424653905540677579966e-1, 0.4401960239018345875735580e-1, 0.4366756139720144025254848e-1, 0.4322882250506869978939520e-1, 0.4270425678944977776996576e-1, 0.4209490572728440602098398e-1, 0.4140197912904520863822652e-1, 0.4062685273678961635122600e-1, 0.3977106549277656747784952e-1, 0.3883631648407340397900292e-1, 0.3782446156922281719727230e-1, 0.3673750969367269534804046e-1, 0.3557761890129238053276980e-1, 0.3434709204990653756854510e-1, 0.3304837223937242047087430e-1, 0.3168403796130848173465310e-1, 0.3025679798015423781653688e-1, 0.2876948595580828066131070e-1, 0.2722505481866441715910742e-1, 0.2562657090846848279898494e-1, 0.2397720788910029227868640e-1, 0.2228024045225659583389064e-1, 0.2053903782432645338449270e-1, 0.1875705709313342341545081e-1, 0.1693783637630293253183738e-1, 0.1508498786544312768229492e-1, 0.1320219081467674762507440e-1, 0.1129318464993153764963015e-1, 0.9361762769699026811498692e-2, 0.7411769363190210362109460e-2, 0.5447111874217218312821680e-2, 0.3471894893078143254999524e-2, 0.1492721288844515731042666e-2}, + {0.4332111216548653707639384e-1, 0.4323978130522261748526514e-1, 0.4307727227491369974525036e-1, 0.4283389016833881366683982e-1, 0.4251009191005772007780078e-1, 0.4210648539758646414658732e-1, 0.4162382836013859820760788e-1, 0.4106302693607506110193610e-1, 0.4042513397173397004332898e-1, 0.3971134704483490178239872e-1, 0.3892300621616966379996300e-1, 0.3806159151380216383437540e-1, 0.3712872015450289946055536e-1, 0.3612614350763799298563092e-1, 0.3505574380721787043413848e-1, 0.3391953061828605949719618e-1, 0.3271963706429384670431246e-1, 0.3145831582256181397777608e-1, 0.3013793489537547929298290e-1, 0.2876097316470176109512506e-1, 0.2733001573895093443379638e-1, 0.2584774910065589028389804e-1, 0.2431695606441916432634724e-1, 0.2274051055503575445593134e-1, 0.2112137221644055350981986e-1, 0.1946258086329427804301667e-1, 0.1776725078920065359435915e-1, 0.1603856495028515521816122e-1, 0.1427976905455419326655572e-1, 0.1249416561987375776778277e-1, 0.1068510816535189715895734e-1, 0.8855996073706153383956510e-2, 0.7010272321861863296081600e-2, 0.5151436018790886908248502e-2, 0.3283169774667495801897558e-2, 0.1411516393973434135715864e-2}, + {0.4215870660994342212223066e-1, 0.4208374996915697247489576e-1, 0.4193396995777702146995522e-1, 0.4170963287924075437870998e-1, 0.4141113759675351082006810e-1, 0.4103901482412726684741876e-1, 0.4059392618219472805807676e-1, 0.4007666302247696675915112e-1, 0.3948814502019646832363280e-1, 0.3882941853913770775808220e-1, 0.3810165477126324889635168e-1, 0.3730614765439415573370658e-1, 0.3644431157165856448181076e-1, 0.3551767883680095992585374e-1, 0.3452789696982646100333388e-1, 0.3347672576782876626372244e-1, 0.3236603417621699952527994e-1, 0.3119779696591542603337254e-1, 0.2997409122246118733996502e-1, 0.2869709265326987534209508e-1, 0.2736907171967935230243778e-1, 0.2599238960072378786677346e-1, 0.2456949399594276724564910e-1, 0.2310291477491582303093246e-1, 0.2159525948167588896969968e-1, 0.2004920870279494425273506e-1, 0.1846751130897987978285368e-1, 0.1685297958202485358484807e-1, 0.1520848424340123480887426e-1, 0.1353694941178749434105245e-1, 0.1184134754749966732316814e-1, 0.1012469453828730542112095e-1, 0.8390045433971397064089364e-2, 0.6640492909114357634760192e-2, 0.4879179758594144584288316e-2, 0.3109420149896754678673688e-2, 0.1336761650069883550325931e-2}, + {0.4105703691622942259325972e-1, 0.4098780546479395154130842e-1, 0.4084945930182849228039176e-1, 0.4064223171029473877745496e-1, 0.4036647212284402315409558e-1, 0.4002264553259682611646172e-1, 0.3961133170906205842314674e-1, 0.3913322422051844076750754e-1, 0.3858912926450673834292118e-1, 0.3797996430840528319523540e-1, 0.3730675654238160982756716e-1, 0.3657064114732961700724404e-1, 0.3577285938071394752777924e-1, 0.3491475648355076744412550e-1, 0.3399777941205638084674262e-1, 0.3302347439779174100654158e-1, 0.3199348434042160006853510e-1, 0.3090954603749159538993714e-1, 0.2977348725590504095670750e-1, 0.2858722365005400377397500e-1, 0.2735275553182752167415270e-1, 0.2607216449798598352427480e-1, 0.2474760992065967164326474e-1, 0.2338132530701118662247962e-1, 0.2197561453441624916801320e-1, 0.2053284796790802109297466e-1, 0.1905545846719058280680223e-1, 0.1754593729147423095419928e-1, 0.1600682991224857088850986e-1, 0.1444073174827667993988980e-1, 0.1285028384751014494492467e-1, 0.1123816856966768723967455e-1, 0.9607105414713754082404616e-2, 0.7959847477239734621118374e-2, 0.6299180497328445866575096e-2, 0.4627935228037421326126844e-2, 0.2949102953642474900394994e-2, 0.1267791634085359663272804e-2}, + {0.4001146511842048298877858e-1, 0.3994739036908802487930490e-1, 0.3981934348036408922503176e-1, 0.3962752950781054295639346e-1, 0.3937225562423312193722022e-1, 0.3905393062777341314731136e-1, 0.3867306428725767400389548e-1, 0.3823026652585098764962036e-1, 0.3772624644432424786429014e-1, 0.3716181118549838685067108e-1, 0.3653786464168470064819248e-1, 0.3585540600719169544500572e-1, 0.3511552817821718947488010e-1, 0.3431941600268909029029166e-1, 0.3346834438285897797298150e-1, 0.3256367623368904440805548e-1, 0.3160686030030479773888294e-1, 0.3059942883801304528943330e-1, 0.2954299515860694641162030e-1, 0.2843925104689751626239046e-1, 0.2728996405162436486456432e-1, 0.2609697465510883502983394e-1, 0.2486219332622245076144308e-1, 0.2358759746145747209645146e-1, 0.2227522821911388676305032e-1, 0.2092718725187772678537816e-1, 0.1954563334339992337791787e-1, 0.1813277895498232864440684e-1, 0.1669088668934389186621294e-1, 0.1522226568017845169331591e-1, 0.1372926792014414839372596e-1, 0.1221428454978988639768250e-1, 0.1067974215748111335351669e-1, 0.9128099227255087276943326e-2, 0.7561843189439718826977318e-2, 0.5983489944440407989648850e-2, 0.4395596039460346742737866e-2, 0.2800868811838630411609396e-2, 0.1204024566067353280336448e-2}, + {0.3901781365630665481128044e-1, 0.3895839596276953119862554e-1, 0.3883965105905196893177418e-1, 0.3866175977407646332707712e-1, 0.3842499300695942318521238e-1, 0.3812971131447763834420674e-1, 0.3777636436200139748977496e-1, 0.3736549023873049002670538e-1, 0.3689771463827600883915092e-1, 0.3637374990583597804396502e-1, 0.3579439395341605460286146e-1, 0.3516052904474759349552658e-1, 0.3447312045175392879436434e-1, 0.3373321498461152281667534e-1, 0.3294193939764540138283636e-1, 0.3210049867348777314805654e-1, 0.3121017418811470164244288e-1, 0.3027232175955798066122008e-1, 0.2928836958326784769276746e-1, 0.2825981605727686239675312e-1, 0.2718822750048638067441898e-1, 0.2607523576756511790296854e-1, 0.2492253576411549110511808e-1, 0.2373188286593010129319242e-1, 0.2250509024633246192622164e-1, 0.2124402611578200638871032e-1, 0.1995061087814199892889169e-1, 0.1862681420829903142873492e-1, 0.1727465205626930635858456e-1, 0.1589618358372568804490352e-1, 0.1449350804050907611696272e-1, 0.1306876159240133929378674e-1, 0.1162411412079782691646643e-1, 0.1016176604110306452083288e-1, 0.8683945269260858426408640e-2, 0.7192904768117312752674654e-2, 0.5690922451403198649270494e-2, 0.4180313124694895236739096e-2, 0.2663533589512681669292770e-2, 0.1144950003186941534544369e-2}, + {0.3807230964014187120769602e-1, 0.3801710843143526990530278e-1, 0.3790678605050578477946422e-1, 0.3774150245427586967153708e-1, 0.3752149728818502087157412e-1, 0.3724708953872766418784006e-1, 0.3691867707095445699853162e-1, 0.3653673605160765284219780e-1, 0.3610182025872702307569544e-1, 0.3561456027872747268049598e-1, 0.3507566259211269038478042e-1, 0.3448590854915070550737888e-1, 0.3384615323699685874463648e-1, 0.3315732423990721132775848e-1, 0.3242042029434060507783656e-1, 0.3163650984090024553762352e-1, 0.3080672947521562981366802e-1, 0.2993228230001272463508596e-1, 0.2901443618076440396145302e-1, 0.2805452190745423047171398e-1, 0.2705393126512477151978662e-1, 0.2601411501601702375386842e-1, 0.2493658079624075515577230e-1, 0.2382289093004782634222678e-1, 0.2267466016491410310244200e-1, 0.2149355333077484404348958e-1, 0.2028128292691215890157032e-1, 0.1903960664017892507303976e-1, 0.1777032479849840714698234e-1, 0.1647527776398370889101217e-1, 0.1515634327076256178846848e-1, 0.1381543371412645938772740e-1, 0.1245449340114210467973318e-1, 0.1107549578175989632022419e-1, 0.9680440704371073736965104e-2, 0.8271351818383685604431294e-2, 0.6850274534183526184325356e-2, 0.5419276232446765090703842e-2, 0.3980457937856074619030326e-2, 0.2536054696856106109823094e-2, 0.1090118595275830866109234e-2}, + {0.3717153701903406760328362e-1, 0.3712016261260209427372758e-1, 0.3701748480379452058524442e-1, 0.3686364550259030771845208e-1, 0.3665885732875907563657692e-1, 0.3640340331800212248862624e-1, 0.3609763653077256670175260e-1, 0.3574197956431530727788894e-1, 0.3533692396860127616038866e-1, 0.3488302956696330845641672e-1, 0.3438092368237270062133504e-1, 0.3383130027042598480372494e-1, 0.3323491896024044407471552e-1, 0.3259260400458425718361322e-1, 0.3190524314069272748402282e-1, 0.3117378636334566129196750e-1, 0.3039924461190246977311372e-1, 0.2958268837311084528960516e-1, 0.2872524620162180221266452e-1, 0.2782810316025840603576668e-1, 0.2689249918219763751581640e-1, 0.2591972735733464772516052e-1, 0.2491113214520642888439108e-1, 0.2386810751695823938471552e-1, 0.2279209502894212933888898e-1, 0.2168458183064482298924430e-1, 0.2054709860975627861152400e-1, 0.1938121747731880864780669e-1, 0.1818854979605654992760044e-1, 0.1697074395521161134308213e-1, 0.1572948309558359820159970e-1, 0.1446648278916118624227443e-1, 0.1318348867918234598679997e-1, 0.1188227408980122349505120e-1, 0.1056463762300824526484878e-1, 0.9232400784190247014382770e-2, 0.7887405752648146382107148e-2, 0.6531513687713654601121566e-2, 0.5166605182746808329881136e-2, 0.3794591650452349696393000e-2, 0.2417511265443122855238466e-2, 0.1039133516451971889197062e-2}, + {0.3631239537581333828231516e-1, 0.3626450208420238743149194e-1, 0.3616877866860063758274494e-1, 0.3602535138093525771008956e-1, 0.3583440939092405578977942e-1, 0.3559620453657549559069116e-1, 0.3531105099203420508058466e-1, 0.3497932485321009937141316e-1, 0.3460146364173769225993442e-1, 0.3417796572791990463423808e-1, 0.3370938967341755486497158e-1, 0.3319635349455159712009034e-1, 0.3263953384718992195609868e-1, 0.3203966513429401611022852e-1, 0.3139753853730286555853332e-1, 0.3071400097263205318303994e-1, 0.2998995397466493249133840e-1, 0.2922635250670994458366154e-1, 0.2842420370149349475731242e-1, 0.2758456553285124838738412e-1, 0.2670854542037220957530654e-1, 0.2579729876883953540777106e-1, 0.2485202744439983591832606e-1, 0.2387397818947900497321768e-1, 0.2286444097854800644577274e-1, 0.2182474731692762780068420e-1, 0.2075626848490914279058154e-1, 0.1966041372956217980740210e-1, 0.1853862840670985920631482e-1, 0.1739239207569054238672012e-1, 0.1622321654972902258808405e-1, 0.1503264390508137868494523e-1, 0.1382224445276667086664874e-1, 0.1259361467806969781040954e-1, 0.1134837515617770397716730e-1, 0.1008816846038610565467284e-1, 0.8814657101954815703782366e-2, 0.7529521612194562606844596e-2, 0.6234459139140123463885784e-2, 0.4931184096960103696423408e-2, 0.3621439249610901437553882e-2, 0.2307087488809902925963262e-2, 0.9916432666203635255681510e-3}, + {0.3549206430171454529606746e-1, 0.3544734460447076970614316e-1, 0.3535796155642384379366902e-1, 0.3522402777945910853287866e-1, 0.3504571202900426139658624e-1, 0.3482323898139935499312912e-1, 0.3455688895080708413486530e-1, 0.3424699753602007873736958e-1, 0.3389395519761025923989258e-1, 0.3349820676595309252806520e-1, 0.3306025088074670014528066e-1, 0.3258063936273210868623942e-1, 0.3205997651840638806926700e-1, 0.3149891837860489232004182e-1, 0.3089817187191219763370292e-1, 0.3025849393394352533513752e-1, 0.2958069055361934911335230e-1, 0.2886561575763542924647688e-1, 0.2811417053440861349157908e-1, 0.2732730169885533083562360e-1, 0.2650600069943473772140906e-1, 0.2565130236896194788477952e-1, 0.2476428362076873302532156e-1, 0.2384606209185966126357838e-1, 0.2289779473478114232724788e-1, 0.2192067635998985359563460e-1, 0.2091593813057662423225406e-1, 0.1988484601127411324360109e-1, 0.1882869917375545139470985e-1, 0.1774882836032407455649534e-1, 0.1664659420821765604511323e-1, 0.1552338553693355384016474e-1, 0.1438061760129994423593466e-1, 0.1321973031362791170818164e-1, 0.1204218643958121230973900e-1, 0.1084946977542927125940107e-1, 0.9643083322053204400769368e-2, 0.8424547492702473015098308e-2, 0.7195398459796372059759572e-2, 0.5957186996138046583131162e-2, 0.4711479279598661743021848e-2, 0.3459867667862796423976646e-2, 0.2204058563143696628535344e-2, 0.9473355981619272667700360e-3}, + {0.3470797248895005792046014e-1, 0.3466615208568824018827232e-1, 0.3458256166949689141805380e-1, 0.3445730196032425617459566e-1, 0.3429052388637504193169728e-1, 0.3408242840225399546360508e-1, 0.3383326624683168725792750e-1, 0.3354333764112427668293316e-1, 0.3321299192655131651404080e-1, 0.3284262714400750457863018e-1, 0.3243268955425561691178950e-1, 0.3198367310021857603945600e-1, 0.3149611881181863607695780e-1, 0.3097061415408092094593650e-1, 0.3040779231928695269039426e-1, 0.2980833146403127548714788e-1, 0.2917295389210074248655798e-1, 0.2850242518416141631875546e-1, 0.2779755327530227515803874e-1, 0.2705918748154795852161408e-1, 0.2628821747651458736159580e-1, 0.2548557221944322848446706e-1, 0.2465221883590485293596628e-1, 0.2378916145252872321010090e-1, 0.2289743998716318463498862e-1, 0.2197812889593413383869188e-1, 0.2103233587872256311706242e-1, 0.2006120054463959596453232e-1, 0.1906589303913731842532399e-1, 0.1804761263446023616404962e-1, 0.1700758628522267570939747e-1, 0.1594706715100663901320649e-1, 0.1486733308804332405038481e-1, 0.1376968511233709343075118e-1, 0.1265544583716812886887583e-1, 0.1152595788914805885059348e-1, 0.1038258230989321461380844e-1, 0.9226696957741990940319884e-2, 0.8059694944620015658670990e-2, 0.6882983208463284314729370e-2, 0.5697981560747352600849438e-2, 0.4506123613674977864136850e-2, 0.3308867243336018195431340e-2, 0.2107778774526329891473788e-2, 0.9059323712148330937360098e-3}, + {0.3395777082810234796700260e-1, 0.3391860442372254949502722e-1, 0.3384031678893360189141840e-1, 0.3372299821957387169380074e-1, 0.3356678402920367631007550e-1, 0.3337185439303681030780114e-1, 0.3313843414012938182262046e-1, 0.3286679249406566032646806e-1, 0.3255724276244004524316198e-1, 0.3221014197549332953574452e-1, 0.3182589047432008582597260e-1, 0.3140493144912217791614030e-1, 0.3094775042804103166804096e-1, 0.3045487471715832098063528e-1, 0.2992687279231107330786762e-1, 0.2936435364342281261274650e-1, 0.2876796607210717582237958e-1, 0.2813839794335440451445112e-1, 0.2747637539216417339517938e-1, 0.2678266198604032330048838e-1, 0.2605805784431417922245786e-1, 0.2530339871531322569754810e-1, 0.2451955501244097425717108e-1, 0.2370743081028191239353720e-1, 0.2286796280189254240434106e-1, 0.2200211921848585739874382e-1, 0.2111089871276246180997612e-1, 0.2019532920718748374956428e-1, 0.1925646670855947471237209e-1, 0.1829539409026755729118717e-1, 0.1731321984368977636114053e-1, 0.1631107680025595800481463e-1, 0.1529012082579650150690625e-1, 0.1425152948895392526580707e-1, 0.1319650070571113802911160e-1, 0.1212625136263771052929676e-1, 0.1104201592263539422398575e-1, 0.9945045019726082041770092e-2, 0.8836604056467877374547944e-2, 0.7717971837373568504533128e-2, 0.6590439334214895223179124e-2, 0.5455308908000870987158870e-2, 0.4313895331861700472339122e-2, 0.3167535943396097874261610e-2, 0.2017671366262838591883234e-2, 0.8671851787671421353540866e-3}, + {0.3323930891781532080070524e-1, 0.3320257661860686379876634e-1, 0.3312915261254696321600516e-1, 0.3301911803949165507667076e-1, 0.3287259449712959072614770e-1, 0.3268974390660630715252838e-1, 0.3247076833358767948450850e-1, 0.3221590976496030711281812e-1, 0.3192544984141561392584074e-1, 0.3159970954621320046477392e-1, 0.3123904885046741788219108e-1, 0.3084386631534918741110674e-1, 0.3041459865164271220328128e-1, 0.2995172023714386920008800e-1, 0.2945574259243367639719146e-1, 0.2892721381560625584227516e-1, 0.2836671797657610681272962e-1, 0.2777487447163422062065088e-1, 0.2715233733896656472388262e-1, 0.2649979453589169919669406e-1, 0.2581796717861672816440260e-1, 0.2510760874535240512858038e-1, 0.2436950424366898830634656e-1, 0.2360446934301438228050796e-1, 0.2281334947335523641001192e-1, 0.2199701889094007717339700e-1, 0.2115637971222138981504522e-1, 0.2029236091701113217988866e-1, 0.1940591732198200488605189e-1, 0.1849802852566591095380957e-1, 0.1756969782614325199872555e-1, 0.1662195111266549663832874e-1, 0.1565583573251555786002188e-1, 0.1467241933449946420426407e-1, 0.1367278869060687850644038e-1, 0.1265804849763899444482439e-1, 0.1162932016112241459607371e-1, 0.1058774056495412223672440e-1, 0.9534460832865158250063918e-2, 0.8470645094534635999910406e-2, 0.7397469288142356200862272e-2, 0.6316120091036448223107804e-2, 0.5227794289507767545307002e-2, 0.4133699875407776483295790e-2, 0.3035065891038628027389626e-2, 0.1933219888725418943121000e-2, 0.8308716126821624946495838e-3}, + {0.3255061449236316624196142e-1, 0.3251611871386883598720548e-1, 0.3244716371406426936401278e-1, 0.3234382256857592842877486e-1, 0.3220620479403025066866710e-1, 0.3203445623199266321813896e-1, 0.3182875889441100653475374e-1, 0.3158933077072716855802074e-1, 0.3131642559686135581278434e-1, 0.3101033258631383742324982e-1, 0.3067137612366914901422878e-1, 0.3029991542082759379408878e-1, 0.2989634413632838598438796e-1, 0.2946108995816790597043632e-1, 0.2899461415055523654267862e-1, 0.2849741106508538564559948e-1, 0.2797000761684833443981840e-1, 0.2741296272602924282342110e-1, 0.2682686672559176219805676e-1, 0.2621234073567241391345816e-1, 0.2557003600534936149879724e-1, 0.2490063322248361028838244e-1, 0.2420484179236469128226730e-1, 0.2348339908592621984223612e-1, 0.2273706965832937400134754e-1, 0.2196664443874434919475618e-1, 0.2117293989219129898767356e-1, 0.2035679715433332459524556e-1, 0.1951908114014502241008485e-1, 0.1866067962741146738515655e-1, 0.1778250231604526083761406e-1, 0.1688547986424517245047785e-1, 0.1597056290256229138061685e-1, 0.1503872102699493800587588e-1, 0.1409094177231486091586166e-1, 0.1312822956696157263706415e-1, 0.1215160467108831963518178e-1, 0.1116210209983849859121361e-1, 0.1016077053500841575758671e-1, 0.9148671230783386632584044e-2, 0.8126876925698759217383246e-2, 0.7096470791153865269143206e-2, 0.6058545504235961683315686e-2, 0.5014202742927517692471308e-2, 0.3964554338444686673733524e-2, 0.2910731817934946408411678e-2, 0.1853960788946921732331620e-2, 0.7967920655520124294367096e-3}, + {0.3188987535287646727794502e-1, 0.3185743815812401071309920e-1, 0.3179259676252863019831786e-1, 0.3169541712034925160907410e-1, 0.3156599807910805290145092e-1, 0.3140447127904656151748860e-1, 0.3121100101922626441684056e-1, 0.3098578409040993463104290e-1, 0.3072904957489366992001356e-1, 0.3044105861349325839490764e-1, 0.3012210413992189884853100e-1, 0.2977251058282947626617570e-1, 0.2939263353580649216776328e-1, 0.2898285939568834204744914e-1, 0.2854360496952788570349054e-1, 0.2807531705063613875324586e-1, 0.2757847196412239390009986e-1, 0.2705357508239612827767608e-1, 0.2650116031112363935248738e-1, 0.2592178954616244891846836e-1, 0.2531605210202609734314644e-1, 0.2468456411246099618197954e-1, 0.2402796790374549880324124e-1, 0.2334693134134927471268304e-1, 0.2264214715061843311126274e-1, 0.2191433221217865041901888e-1, 0.2116422683277485691127980e-1, 0.2039259399229191457948346e-1, 0.1960021856772633077323700e-1, 0.1878790653490468656148738e-1, 0.1795648414877062812244296e-1, 0.1710679710308990026235402e-1, 0.1623970967045369565272614e-1, 0.1535610382349775576849818e-1, 0.1445687833830440197756895e-1, 0.1354294788102946514364726e-1, 0.1261524207892195285778215e-1, 0.1167470457713812428742924e-1, 0.1072229208322431712024324e-1, 0.9758973402174096835348026e-2, 0.8785728467392263202699392e-2, 0.7803547379100754890979542e-2, 0.6813429479165215998771186e-2, 0.5816382546439639112764538e-2, 0.4813422398586770918478190e-2, 0.3805574085352359565512666e-2, 0.2793881135722130870629084e-2, 0.1779477041014528741695358e-2, 0.7647669822743134580383448e-3}, + {0.3125542345386335694764248e-1, 0.3122488425484935773237650e-1, 0.3116383569620990678381832e-1, 0.3107233742756651658781016e-1, 0.3095047885049098823406346e-1, 0.3079837903115259042771392e-1, 0.3061618658398044849645950e-1, 0.3040407952645482001650792e-1, 0.3016226510516914491906862e-1, 0.2989097959333283091683684e-1, 0.2959048805991264251175454e-1, 0.2926108411063827662011896e-1, 0.2890308960112520313487610e-1, 0.2851685432239509799093676e-1, 0.2810275565910117331764820e-1, 0.2766119822079238829420408e-1, 0.2719261344657688013649158e-1, 0.2669745918357096266038448e-1, 0.2617621923954567634230892e-1, 0.2562940291020811607564182e-1, 0.2505754448157958970376402e-1, 0.2446120270795705271997480e-1, 0.2384096026596820596256040e-1, 0.2319742318525412162248878e-1, 0.2253122025633627270179672e-1, 0.2184300241624738631395360e-1, 0.2113344211252764154267220e-1, 0.2040323264620943276683910e-1, 0.1965308749443530586538157e-1, 0.1888373961337490455294131e-1, 0.1809594072212811666439111e-1, 0.1729046056832358243934388e-1, 0.1646808617614521264310506e-1, 0.1562962107754600272393719e-1, 0.1477588452744130176887969e-1, 0.1390771070371877268795387e-1, 0.1302594789297154228555807e-1, 0.1213145766297949740774437e-1, 0.1122511402318597711722209e-1, 0.1030780257486896958578198e-1, 0.9380419653694457951417628e-2, 0.8443871469668971402620252e-2, 0.7499073255464711578829804e-2, 0.6546948450845322764152444e-2, 0.5588428003865515157213478e-2, 0.4624450063422119351093868e-2, 0.3655961201326375182342828e-2, 0.2683925371553482419437272e-2, 0.1709392653518105239533969e-2, 0.7346344905056717304142370e-3}, +} + +var oddWeights = [][]float64{ + {0.5555555555555555555555555}, + {0.4786286704993664680412916e0, 0.2369268850561890875142644e0}, + {0.3818300505051189449503698e0, 0.2797053914892766679014680e0, 0.1294849661688696932706118e0}, + {0.3123470770400028400686304e0, 0.2606106964029354623187428e0, 0.1806481606948574040584721e0, 0.8127438836157441197189206e-1}, + {0.2628045445102466621806890e0, 0.2331937645919904799185238e0, 0.1862902109277342514260979e0, 0.1255803694649046246346947e0, 0.5566856711617366648275374e-1}, + {0.2262831802628972384120902e0, 0.2078160475368885023125234e0, 0.1781459807619457382800468e0, 0.1388735102197872384636019e0, 0.9212149983772844791442126e-1, 0.4048400476531587952001996e-1}, + {0.1984314853271115764561182e0, 0.1861610000155622110268006e0, 0.1662692058169939335532006e0, 0.1395706779261543144478051e0, 0.1071592204671719350118693e0, 0.7036604748810812470926662e-1, 0.3075324199611726835462762e-1}, + {0.1765627053669926463252710e0, 0.1680041021564500445099705e0, 0.1540457610768102880814317e0, 0.1351363684685254732863199e0, 0.1118838471934039710947887e0, 0.8503614831717918088353538e-1, 0.5545952937398720112944102e-1, 0.2414830286854793196010920e-1}, + {0.1589688433939543476499565e0, 0.1527660420658596667788553e0, 0.1426067021736066117757460e0, 0.1287539625393362276755159e0, 0.1115666455473339947160242e0, 0.9149002162244999946446222e-1, 0.6904454273764122658070790e-1, 0.4481422676569960033283728e-1, 0.1946178822972647703631351e-1}, + {0.1445244039899700590638271e0, 0.1398873947910731547221335e0, 0.1322689386333374617810526e0, 0.1218314160537285341953671e0, 0.1087972991671483776634747e0, 0.9344442345603386155329010e-1, 0.7610011362837930201705132e-1, 0.5713442542685720828363528e-1, 0.3695378977085249379995034e-1, 0.1601722825777433332422273e-1}, + {0.1324620394046966173716425e0, 0.1289057221880821499785954e0, 0.1230490843067295304675784e0, 0.1149966402224113649416434e0, 0.1048920914645414100740861e0, 0.9291576606003514747701876e-1, 0.7928141177671895492289248e-1, 0.6423242140852585212716980e-1, 0.4803767173108466857164124e-1, 0.3098800585697944431069484e-1, 0.1341185948714177208130864e-1}, + {0.1222424429903100416889594e0, 0.1194557635357847722281782e0, 0.1148582591457116483393255e0, 0.1085196244742636531160939e0, 0.1005359490670506442022068e0, 0.9102826198296364981149704e-1, 0.8014070033500101801323524e-1, 0.6803833381235691720718712e-1, 0.5490469597583519192593686e-1, 0.4093915670130631265562402e-1, 0.2635498661503213726190216e-1, 0.1139379850102628794789998e-1}, + {0.1134763461089651486203700e0, 0.1112524883568451926721632e0, 0.1075782857885331872121629e0, 0.1025016378177457986712478e0, 0.9608872737002850756565252e-1, 0.8842315854375695019432262e-1, 0.7960486777305777126307488e-1, 0.6974882376624559298432254e-1, 0.5898353685983359911030058e-1, 0.4744941252061506270409646e-1, 0.3529705375741971102257772e-1, 0.2268623159618062319603554e-1, 0.9798996051294360261149438e-2}, + {0.1058761550973209414065914e0, 0.1040733100777293739133284e0, 0.1010912737599149661218204e0, 0.9696383409440860630190016e-1, 0.9173775713925876334796636e-1, 0.8547225736617252754534480e-1, 0.7823832713576378382814484e-1, 0.7011793325505127856958160e-1, 0.6120309065707913854210970e-1, 0.5159482690249792391259412e-1, 0.4140206251868283610482948e-1, 0.3074049220209362264440778e-1, 0.1973208505612270598385931e-1, 0.8516903878746409654261436e-2}, + {0.9922501122667230787487546e-1, 0.9774333538632872509347402e-1, 0.9529024291231951280720412e-1, 0.9189011389364147821536290e-1, 0.8757674060847787612619794e-1, 0.8239299176158926390382334e-1, 0.7639038659877661642635764e-1, 0.6962858323541036616775632e-1, 0.6217478656102842691034334e-1, 0.5410308242491685371166596e-1, 0.4549370752720110290231576e-1, 0.3643227391238546402439264e-1, 0.2700901918497942180060860e-1, 0.1731862079031058246315918e-1, 0.7470831579248775858700554e-2}, + {0.9335642606559611616099912e-1, 0.9212398664331684621324104e-1, 0.9008195866063857723974370e-1, 0.8724828761884433760728158e-1, 0.8364787606703870761392808e-1, 0.7931236479488673836390848e-1, 0.7427985484395414934247216e-1, 0.6859457281865671280595482e-1, 0.6230648253031748003162750e-1, 0.5547084663166356128494468e-1, 0.4814774281871169567014706e-1, 0.4040154133166959156340938e-1, 0.3230035863232895328156104e-1, 0.2391554810174948035053310e-1, 0.1532170151293467612794584e-1, 0.6606227847587378058647800e-2}, + {0.8814053043027546297073886e-1, 0.8710444699718353424332214e-1, 0.8538665339209912522594402e-1, 0.8300059372885658837992644e-1, 0.7996494224232426293266204e-1, 0.7630345715544205353865872e-1, 0.7204479477256006466546180e-1, 0.6722228526908690396430546e-1, 0.6187367196608018888701398e-1, 0.5604081621237012857832772e-1, 0.4976937040135352980519956e-1, 0.4310842232617021878230592e-1, 0.3611011586346338053271748e-1, 0.2882926010889425404871630e-1, 0.2132297991148358088343844e-1, 0.1365082834836149226640441e-1, 0.5883433420443084975750336e-2}, + {0.8347457362586278725225302e-1, 0.8259527223643725089123018e-1, 0.8113662450846503050987774e-1, 0.7910886183752938076721222e-1, 0.7652620757052923788588804e-1, 0.7340677724848817272462668e-1, 0.6977245155570034488508154e-1, 0.6564872287275124948402376e-1, 0.6106451652322598613098804e-1, 0.5605198799827491780853916e-1, 0.5064629765482460160387558e-1, 0.4488536466243716665741054e-1, 0.3880960250193454448896226e-1, 0.3246163984752148106723444e-1, 0.2588603699055893352275954e-1, 0.1912904448908396604350259e-1, 0.1223878010030755652630649e-1, 0.5273057279497939351724544e-2}, + {0.7927622256836847101015574e-1, 0.7852361328737117672506330e-1, 0.7727455254468201672851160e-1, 0.7553693732283605770478448e-1, 0.7332175341426861738115402e-1, 0.7064300597060876077011486e-1, 0.6751763096623126536302120e-1, 0.6396538813868238898670650e-1, 0.6000873608859614957494160e-1, 0.5567269034091629990739094e-1, 0.5098466529212940521402098e-1, 0.4597430110891663188417682e-1, 0.4067327684793384393905618e-1, 0.3511511149813133076106530e-1, 0.2933495598390337859215654e-1, 0.2336938483217816459471240e-1, 0.1725622909372491904080491e-1, 0.1103478893916459424267603e-1, 0.4752944691635101370775866e-2}, + {0.7547874709271582402724706e-1, 0.7482962317622155189130518e-1, 0.7375188202722346993928094e-1, 0.7225169686102307339634646e-1, 0.7033766062081749748165896e-1, 0.6802073676087676673553342e-1, 0.6531419645352741043616384e-1, 0.6223354258096631647157330e-1, 0.5879642094987194499118590e-1, 0.5502251924257874188014710e-1, 0.5093345429461749478117008e-1, 0.4655264836901434206075674e-1, 0.4190519519590968942934048e-1, 0.3701771670350798843526154e-1, 0.3191821173169928178706676e-1, 0.2663589920711044546754900e-1, 0.2120106336877955307569710e-1, 0.1564493840781858853082666e-1, 0.9999938773905945338496546e-2, 0.4306140358164887684003630e-2}, + {0.7202750197142197434530754e-1, 0.7146373425251414129758106e-1, 0.7052738776508502812628636e-1, 0.6922334419365668428229950e-1, 0.6755840222936516919240796e-1, 0.6554124212632279749123378e-1, 0.6318238044939611232562970e-1, 0.6049411524999129451967862e-1, 0.5749046195691051942760910e-1, 0.5418708031888178686337342e-1, 0.5060119278439015652385048e-1, 0.4675149475434658001064704e-1, 0.4265805719798208376380686e-1, 0.3834222219413265757212856e-1, 0.3382649208686029234496834e-1, 0.2913441326149849491594084e-1, 0.2429045661383881590201850e-1, 0.1931990142368390039612543e-1, 0.1424875643157648610854214e-1, 0.9103996637401403318866628e-2, 0.3919490253844127282968528e-2}, + {0.6887731697766132288200278e-1, 0.6838457737866967453169206e-1, 0.6756595416360753627091012e-1, 0.6642534844984252808291474e-1, 0.6496819575072343085382664e-1, 0.6320144007381993774996374e-1, 0.6113350083106652250188634e-1, 0.5877423271884173857436156e-1, 0.5613487875978647664392382e-1, 0.5322801673126895194590376e-1, 0.5006749923795202979913194e-1, 0.4666838771837336526776814e-1, 0.4304688070916497115169120e-1, 0.3922023672930244756418756e-1, 0.3520669220160901624770010e-1, 0.3102537493451546716250854e-1, 0.2669621396757766480567536e-1, 0.2223984755057873239395080e-1, 0.1767753525793759061709347e-1, 0.1303110499158278432063191e-1, 0.8323189296218241645734836e-2, 0.3582663155283558931145652e-2}, + {0.6599053358881047453357062e-1, 0.6555737776654974025114294e-1, 0.6483755623894572670260402e-1, 0.6383421660571703063129384e-1, 0.6255174622092166264056434e-1, 0.6099575300873964533071060e-1, 0.5917304094233887597615438e-1, 0.5709158029323154022201646e-1, 0.5476047278153022595712512e-1, 0.5218991178005714487221170e-1, 0.4939113774736116960457022e-1, 0.4637638908650591120440168e-1, 0.4315884864847953826830162e-1, 0.3975258612253100378090162e-1, 0.3617249658417495161345948e-1, 0.3243423551518475676761786e-1, 0.2855415070064338650473990e-1, 0.2454921165965881853783378e-1, 0.2043693814766842764203432e-1, 0.1623533314643305967072624e-1, 0.1196284846431232096394232e-1, 0.7638616295848833614105174e-2, 0.3287453842528014883248206e-2}, + {0.6333550929649174859083696e-1, 0.6295270746519569947439960e-1, 0.6231641732005726740107682e-1, 0.6142920097919293629682652e-1, 0.6029463095315201730310616e-1, 0.5891727576002726602452756e-1, 0.5730268153018747548516450e-1, 0.5545734967480358869043158e-1, 0.5338871070825896852794302e-1, 0.5110509433014459067462262e-1, 0.4861569588782824027765094e-1, 0.4593053935559585354249958e-1, 0.4306043698125959798834538e-1, 0.4001694576637302136860494e-1, 0.3681232096300068981946734e-1, 0.3345946679162217434248744e-1, 0.2997188462058382535069014e-1, 0.2636361892706601696094518e-1, 0.2264920158744667649877160e-1, 0.1884359585308945844445106e-1, 0.1496214493562465102958377e-1, 0.1102055103159358049750846e-1, 0.7035099590086451473452956e-2, 0.3027278988922905077484090e-2}, + {0.6088546484485634388119860e-1, 0.6054550693473779513812526e-1, 0.5998031577750325209006396e-1, 0.5919199392296154378353896e-1, 0.5818347398259214059843780e-1, 0.5695850772025866210007778e-1, 0.5552165209573869301673704e-1, 0.5387825231304556143409938e-1, 0.5203442193669708756413650e-1, 0.4999702015005740977954886e-1, 0.4777362624062310199999514e-1, 0.4537251140765006874816670e-1, 0.4280260799788008665360980e-1, 0.4007347628549645318680892e-1, 0.3719526892326029284290846e-1, 0.3417869320418833623620910e-1, 0.3103497129016000845442504e-1, 0.2777579859416247719599602e-1, 0.2441330057378143427314164e-1, 0.2095998840170321057979252e-1, 0.1742871472340105225950284e-1, 0.1383263400647782229668883e-1, 0.1018519129782172993923731e-1, 0.6500337783252600292109494e-2, 0.2796807171089895575547228e-2}, + {0.5861758623272026331807196e-1, 0.5831431136225600755627570e-1, 0.5781001499171319631968304e-1, 0.5710643553626719177338328e-1, 0.5620599838173970980865512e-1, 0.5511180752393359900234954e-1, 0.5382763486873102904208140e-1, 0.5235790722987271819970160e-1, 0.5070769106929271529648556e-1, 0.4888267503269914042044844e-1, 0.4688915034075031402187278e-1, 0.4473398910367281021276570e-1, 0.4242462063452001359228150e-1, 0.3996900584354038212709364e-1, 0.3737560980348291567417214e-1, 0.3465337258353423795838740e-1, 0.3181167845901932306323576e-1, 0.2886032361782373626279970e-1, 0.2580948251075751771396152e-1, 0.2266967305707020839878928e-1, 0.1945172110763689538804750e-1, 0.1616672525668746392806095e-1, 0.1282602614424037917915135e-1, 0.9441202284940344386662890e-2, 0.6024276226948673281242120e-2, 0.2591683720567031811603734e-2}, + {0.5651231824977200140065834e-1, 0.5624063407108436802827906e-1, 0.5578879419528408710293598e-1, 0.5515824600250868759665114e-1, 0.5435100932991110207032224e-1, 0.5336967000160547272357054e-1, 0.5221737154563208456439348e-1, 0.5089780512449397922477522e-1, 0.4941519771155173948075862e-1, 0.4777429855120069555003682e-1, 0.4598036394628383810390480e-1, 0.4403914042160658989516800e-1, 0.4195684631771876239520718e-1, 0.3974015187433717960946388e-1, 0.3739615786796554528291572e-1, 0.3493237287358988740726862e-1, 0.3235668922618583168470572e-1, 0.2967735776516104122129630e-1, 0.2690296145639627066711996e-1, 0.2404238800972562200779126e-1, 0.2110480166801645412020978e-1, 0.1809961452072906240796732e-1, 0.1503645833351178821315019e-1, 0.1192516071984861217075236e-1, 0.8775746107058528177390204e-2, 0.5598632266560767354082364e-2, 0.2408323619979788819164582e-2}, + {0.5455280360476188648013898e-1, 0.5430847145249864313874678e-1, 0.5390206148329857464280950e-1, 0.5333478658481915842657698e-1, 0.5260833972917743244023134e-1, 0.5172488892051782472062386e-1, 0.5068707072492740865664050e-1, 0.4949798240201967899383808e-1, 0.4816117266168775126885110e-1, 0.4668063107364150378384082e-1, 0.4506077616138115779721374e-1, 0.4330644221621519659643210e-1, 0.4142286487080111036319668e-1, 0.3941566547548011408995280e-1, 0.3729083432441731735473546e-1, 0.3505471278231261750575064e-1, 0.3271397436637156854248994e-1, 0.3027560484269399945849064e-1, 0.2774688140218019232125814e-1, 0.2513535099091812264727322e-1, 0.2244880789077643807968978e-1, 0.1969527069948852038242318e-1, 0.1688295902344154903500062e-1, 0.1402027079075355617024753e-1, 0.1111576373233599014567619e-1, 0.8178160067821232626211086e-2, 0.5216533474718779390504886e-2, 0.2243753872250662909727492e-2}, + {0.5272443385912793196130422e-1, 0.5250390264782873905094128e-1, 0.5213703364837539138398724e-1, 0.5162484939089148214644000e-1, 0.5096877742539391685024800e-1, 0.5017064634299690281072034e-1, 0.4923268067936198577969374e-1, 0.4815749471460644038814684e-1, 0.4694808518696201919315986e-1, 0.4560782294050976983186828e-1, 0.4414044353029738069079808e-1, 0.4255003681106763866730838e-1, 0.4084103553868670766020196e-1, 0.3901820301616000950303072e-1, 0.3708661981887092269183778e-1, 0.3505166963640010878371850e-1, 0.3291902427104527775751116e-1, 0.3069462783611168323975056e-1, 0.2838468020053479790515332e-1, 0.2599561973129850018665014e-1, 0.2353410539371336342527500e-1, 0.2100699828843718735046168e-1, 0.1842134275361002936061624e-1, 0.1578434731308146614732024e-1, 0.1310336630634519101831859e-1, 0.1038588550099586219379846e-1, 0.7639529453487575142699186e-2, 0.4872239168265284768580414e-2, 0.2095492284541223402697724e-2}, + {0.5101448703869726354373512e-1, 0.5081476366881834320770052e-1, 0.5048247038679740464814450e-1, 0.5001847410817825342505160e-1, 0.4942398534673558993996884e-1, 0.4870055505641152608753004e-1, 0.4785007058509560716183348e-1, 0.4687475075080906597642932e-1, 0.4577714005314595937133982e-1, 0.4456010203508348827154136e-1, 0.4322681181249609790104358e-1, 0.4178074779088849206667564e-1, 0.4022568259099824736764020e-1, 0.3856567320700817274615216e-1, 0.3680505042315481738432126e-1, 0.3494840751653335109085198e-1, 0.3300058827590741063272390e-1, 0.3096667436839739482469792e-1, 0.2885197208818340150434184e-1, 0.2666199852415088966281066e-1, 0.2440246718754420291534050e-1, 0.2207927314831904400247522e-1, 0.1969847774610118133051782e-1, 0.1726629298761374359443389e-1, 0.1478906588493791454617878e-1, 0.1227326350781210462927897e-1, 0.9725461830356133736135366e-2, 0.7152354991749089585834616e-2, 0.4560924006012417184541648e-2, 0.1961453361670282671779431e-2}, + {0.4941183303991817896703964e-1, 0.4923038042374756078504314e-1, 0.4892845282051198994470936e-1, 0.4850678909788384786409014e-1, 0.4796642113799513141105276e-1, 0.4730867131226891908060508e-1, 0.4653514924538369651039536e-1, 0.4564774787629260868588592e-1, 0.4464863882594139537033256e-1, 0.4354026708302759079896428e-1, 0.4232534502081582298250554e-1, 0.4100684575966639863511004e-1, 0.3958799589154409398480778e-1, 0.3807226758434955676363856e-1, 0.3646337008545728963045232e-1, 0.3476524064535587769718026e-1, 0.3298203488377934176568344e-1, 0.3111811662221981750821608e-1, 0.2917804720828052694555162e-1, 0.2716657435909793322519012e-1, 0.2508862055334498661862972e-1, 0.2294927100488993314894282e-1, 0.2075376125803909077534152e-1, 0.1850746446016127040926083e-1, 0.1621587841033833888228333e-1, 0.1388461261611561082486681e-1, 0.1151937607688004175075116e-1, 0.9125968676326656354058462e-2, 0.6710291765960136251908410e-2, 0.4278508346863761866081200e-2, 0.1839874595577084117085868e-2}, + {0.4790669250049586203134730e-1, 0.4774134868124062155903898e-1, 0.4746619823288550315264446e-1, 0.4708187401045452224600686e-1, 0.4658925997223349830225508e-1, 0.4598948914665169696389334e-1, 0.4528394102630023065712822e-1, 0.4447423839508297442732352e-1, 0.4356224359580048653228480e-1, 0.4255005424675580271921714e-1, 0.4143999841724029302268646e-1, 0.4023462927300553381544642e-1, 0.3893671920405119761667398e-1, 0.3754925344825770980977246e-1, 0.3607542322556527393216642e-1, 0.3451861839854905862522142e-1, 0.3288241967636857498404946e-1, 0.3117059038018914246443218e-1, 0.2938706778931066806264472e-1, 0.2753595408845034394249940e-1, 0.2562150693803775821408458e-1, 0.2364812969128723669878144e-1, 0.2162036128493406284165378e-1, 0.1954286583675006282683714e-1, 0.1742042199767024849536596e-1, 0.1525791214644831034926464e-1, 0.1306031163999484633616732e-1, 0.1083267878959796862151440e-1, 0.8580148266881459893636434e-2, 0.6307942578971754550189764e-2, 0.4021524172003736347075858e-2, 0.1729258251300250898337759e-2}, + {0.4649043816026462820831466e-1, 0.4633935168241562110844706e-1, 0.4608790448976157619721740e-1, 0.4573664116106369093689412e-1, 0.4528632245466953156805004e-1, 0.4473792366088982547214182e-1, 0.4409263248975101830783160e-1, 0.4335184649869951735915584e-1, 0.4251717006583049147154770e-1, 0.4159041091519924309854838e-1, 0.4057357620174452522725164e-1, 0.3946886816430888264288692e-1, 0.3827867935617948064763712e-1, 0.3700558746349258202313488e-1, 0.3565234972274500666133270e-1, 0.3422189694953664673983902e-1, 0.3271732719153120542712204e-1, 0.3114189901947282393742616e-1, 0.2949902447094566969584718e-1, 0.2779226166243676998720012e-1, 0.2602530708621323880370460e-1, 0.2420198760967316472069180e-1, 0.2232625219645207692279754e-1, 0.2040216337134354044925720e-1, 0.1843388845680457387216616e-1, 0.1642569062253087920472674e-1, 0.1438191982720055093097663e-1, 0.1230700384928815052195302e-1, 0.1020544003410244098666155e-1, 0.8081790299023136215346300e-2, 0.5940693177582235216514606e-2, 0.3787008301825508445960626e-2, 0.1628325035240012866460003e-2}, + {0.4515543023614546051651704e-1, 0.4501700814039980219871620e-1, 0.4478661887831255754213528e-1, 0.4446473312204713809623108e-1, 0.4405200846590928438098588e-1, 0.4354928808292674103357578e-1, 0.4295759900230521387841984e-1, 0.4227815001128051285158270e-1, 0.4151232918565450208287406e-1, 0.4066170105406160053752604e-1, 0.3972800340176164120645862e-1, 0.3871314372049251393273936e-1, 0.3761919531164090650815840e-1, 0.3644839305070051405664348e-1, 0.3520312882168348614775456e-1, 0.3388594663083228949780964e-1, 0.3249953740964611124473418e-1, 0.3104673351789053903268552e-1, 0.2953050295790671177981110e-1, 0.2795394331218770599086132e-1, 0.2632027541686948379176090e-1, 0.2463283678454245536433616e-1, 0.2289507479074078565552120e-1, 0.2111053963987189462789068e-1, 0.1928287712884940278924393e-1, 0.1741582123196982913207401e-1, 0.1551318654340616473976910e-1, 0.1357886064907567099981112e-1, 0.1161679661067196554873961e-1, 0.9631006150415575588660562e-2, 0.7625555931201510611459992e-2, 0.5604579927870594828535346e-2, 0.3572416739397372609702552e-2, 0.1535976952792084075135094e-2}, + {0.4389487921178858632125256e-1, 0.4376774491340214497230982e-1, 0.4355612710410853337113396e-1, 0.4326043426324126659885626e-1, 0.4288123715758043502060704e-1, 0.4241926773962459303533940e-1, 0.4187541773473300618954268e-1, 0.4125073691986602424910896e-1, 0.4054643109724689643492514e-1, 0.3976385976685758167433708e-1, 0.3890453350226294749240264e-1, 0.3797011103483115621441804e-1, 0.3696239605198203185608278e-1, 0.3588333371564891077796844e-1, 0.3473500690768218837536532e-1, 0.3351963220945403083440624e-1, 0.3223955562344352694190700e-1, 0.3089724804509072169860608e-1, 0.2949530049370881246493644e-1, 0.2803641911174149061798030e-1, 0.2652341994215790800810512e-1, 0.2495922349431387305527612e-1, 0.2334684910922325263171504e-1, 0.2168940913598536796183230e-1, 0.1999010293235011128748561e-1, 0.1825221070467867050232934e-1, 0.1647908720746239655059230e-1, 0.1467415533461152920040808e-1, 0.1284089966808780607041846e-1, 0.1098286015429855170627475e-1, 0.9103626461992005851317578e-2, 0.7206835281831493387342912e-2, 0.5296182844025892632677844e-2, 0.3375555496730675865126842e-2, 0.1451267330029397268489446e-2}, + {0.4270273086485722207660098e-1, 0.4258568982601838702576300e-1, 0.4239085899223159440537396e-1, 0.4211859425425563626894556e-1, 0.4176939294869285375410172e-1, 0.4134389294952549452688336e-1, 0.4084287150293886154936056e-1, 0.4026724380756003336494178e-1, 0.3961806134270614331650800e-1, 0.3889650994769673952047552e-1, 0.3810390765573980059550798e-1, 0.3724170228634977315689404e-1, 0.3631146880069778469034650e-1, 0.3531490642472828750906318e-1, 0.3425383554530221541412972e-1, 0.3313019438504384067706900e-1, 0.3194603546197670648650132e-1, 0.3070352184043350493812614e-1, 0.2940492318011656010545704e-1, 0.2805261159057206032380240e-1, 0.2664905729872748295223048e-1, 0.2519682413753831281333190e-1, 0.2369856486421897462660896e-1, 0.2215701631704007205676952e-1, 0.2057499442036116916601972e-1, 0.1895538904867002168973610e-1, 0.1730115876248908300560664e-1, 0.1561532543359142299553300e-1, 0.1390096878831465086752053e-1, 0.1216122092928111272776412e-1, 0.1039926099500053220130511e-1, 0.8618310479532247613912182e-2, 0.6821631349174792362208078e-2, 0.5012538571606190263812266e-2, 0.3194524377289034522078870e-2, 0.1373376462759619223985654e-2}, + {0.4157356944178127878299940e-1, 0.4146558103261909213524834e-1, 0.4128580808246718908346088e-1, 0.4103456181139210667622250e-1, 0.4071227717293733029875788e-1, 0.4031951210114157755817430e-1, 0.3985694654465635257596536e-1, 0.3932538128963516252076754e-1, 0.3872573657343257584146640e-1, 0.3805905049151360313563098e-1, 0.3732647720033209016730652e-1, 0.3652928491929033900685118e-1, 0.3566885373524045308911856e-1, 0.3474667321333040653509838e-1, 0.3376433981833409264695562e-1, 0.3272355415093422052152286e-1, 0.3162611800374964805603220e-1, 0.3047393124221453920313760e-1, 0.2926898851572598680503318e-1, 0.2801337580478054082525924e-1, 0.2670926681012085177235442e-1, 0.2535891919021637909420806e-1, 0.2396467065371695917476570e-1, 0.2252893491386577645054636e-1, 0.2105419751228284223644546e-1, 0.1954301152012788937957076e-1, 0.1799799312564505063794604e-1, 0.1642181711902464004359937e-1, 0.1481721228981446852013731e-1, 0.1318695676282480211961300e-1, 0.1153387332830449596681366e-1, 0.9860824916114018392051822e-2, 0.8170710707327826403717118e-2, 0.6466464907037538401963982e-2, 0.4751069185015273965898868e-2, 0.3027671014606041291230134e-2, 0.1301591717375855993899257e-2}, + {0.4050253572678803195524960e-1, 0.4040269003221775617032620e-1, 0.4023646282485108419526524e-1, 0.4000412721559123741035150e-1, 0.3970606493128931068103760e-1, 0.3934276568757015193713232e-1, 0.3891482638423378562103292e-1, 0.3842295012455452367368120e-1, 0.3786794506008932026166678e-1, 0.3725072306289371887876038e-1, 0.3657229822732745453345840e-1, 0.3583378520391196260264276e-1, 0.3503639736797827845487748e-1, 0.3418144482611567926531782e-1, 0.3327033226369854530283962e-1, 0.3230455663703097559357210e-1, 0.3128570471390543339395640e-1, 0.3021545046662299869139892e-1, 0.2909555232176876134870268e-1, 0.2792785027127696854150716e-1, 0.2671426284955789083200264e-1, 0.2545678398169440375263742e-1, 0.2415747970795584494059388e-1, 0.2281848479012952051290956e-1, 0.2144199920545613550512462e-1, 0.2003028453431617639624646e-1, 0.1858566024834148550917969e-1, 0.1711049990653110417623953e-1, 0.1560722726874913129508073e-1, 0.1407831234002700405016720e-1, 0.1252626736922736518735940e-1, 0.1095364285391135423859170e-1, 0.9363023692386430769260798e-2, 0.7757025950083070731841176e-2, 0.6138296159756341839268696e-2, 0.4509523600205835333238688e-2, 0.2873553083652691657275240e-2, 0.1235291177139409614163874e-2}, + {0.3948525740129116475372166e-1, 0.3939275600474300393426418e-1, 0.3923874749659464355491890e-1, 0.3902347234287979602650502e-1, 0.3874726667023996706818530e-1, 0.3841056174110417740541666e-1, 0.3801388328032604954551756e-1, 0.3755785065432977047790708e-1, 0.3704317590404678415983790e-1, 0.3647066263315342752925638e-1, 0.3584120475334575228920704e-1, 0.3515578508861113112825058e-1, 0.3441547384067660088259166e-1, 0.3362142691803093004992252e-1, 0.3277488413113081785342150e-1, 0.3187716725661117036051890e-1, 0.3092967797352483528829388e-1, 0.2993389567483836289564858e-1, 0.2889137515760726678163634e-1, 0.2780374419544705894443552e-1, 0.2667270099710555653788310e-1, 0.2550001155512877394733978e-1, 0.2428750688879949263942200e-1, 0.2303708018571902627697914e-1, 0.2175068384660807976864198e-1, 0.2043032643814085987844290e-1, 0.1907806955893748858478357e-1, 0.1769602462431041786466318e-1, 0.1628634957619168209183741e-1, 0.1485124552635006931857919e-1, 0.1339295334482567619730830e-1, 0.1191375021511699869960077e-1, 0.1041594620451338257918368e-1, 0.8901880982652486253740074e-2, 0.7373921131330176830391914e-2, 0.5834459868763465589211910e-2, 0.4285929113126531218219446e-2, 0.2730907065754855918535274e-2, 0.1173930129956613021207112e-2}, + {0.3851778959688469523783810e-1, 0.3843192958037517210025656e-1, 0.3828897129558352443032002e-1, 0.3808912713547560183102332e-1, 0.3783269400830055924757518e-1, 0.3752005289647583785923924e-1, 0.3715166829056371214474266e-1, 0.3672808749918043951690600e-1, 0.3624993983586341279832570e-1, 0.3571793568410456853072614e-1, 0.3513286544193937941597898e-1, 0.3449559834765979589474544e-1, 0.3380708118839624555119598e-1, 0.3306833689348800442087536e-1, 0.3228046301473268887240310e-1, 0.3144463009577406641803652e-1, 0.3056207993305266189565968e-1, 0.2963412373090559765847516e-1, 0.2866214015356067622579182e-1, 0.2764757327692492691108618e-1, 0.2659193044321992109092004e-1, 0.2549678002166567706947970e-1, 0.2436374907856309733249090e-1, 0.2319452096027391988145570e-1, 0.2199083279275163277050144e-1, 0.2075447290144560853952252e-1, 0.1948727815560191821592671e-1, 0.1819113124125576115176324e-1, 0.1686795786763513947433495e-1, 0.1551972391246436293824549e-1, 0.1414843251323606554825229e-1, 0.1275612111513442100025550e-1, 0.1134485849541625576200880e-1, 0.9916741809595875499750926e-2, 0.8473893785345565449616918e-2, 0.7018460484931625511609624e-2, 0.5552611370256278902273182e-2, 0.4078551113421395586018386e-2, 0.2598622299928953013499446e-2, 0.1117029847124606606122469e-2}, + {0.3759656394395517759196934e-1, 0.3751672450373727271505762e-1, 0.3738378433575740441091762e-1, 0.3719793160197673054400130e-1, 0.3695942935618497107975802e-1, 0.3666861517167809004390068e-1, 0.3632590066346228889989584e-1, 0.3593177090566064734733082e-1, 0.3548678374494710264584324e-1, 0.3499156901097965473152462e-1, 0.3444682762495051683252180e-1, 0.3385333060751519869931002e-1, 0.3321191798750501518117324e-1, 0.3252349761296806599129116e-1, 0.3178904386622215064354856e-1, 0.3100959628473919484306724e-1, 0.3018625808981441705410184e-1, 0.2932019462510452791804122e-1, 0.2841263170724764156375054e-1, 0.2746485389090326123892810e-1, 0.2647820265067376248510830e-1, 0.2545407448248949675081806e-1, 0.2439391892715855749743432e-1, 0.2329923651890054937016126e-1, 0.2217157666180362262199056e-1, 0.2101253543726991787400918e-1, 0.1982375334565493904931242e-1, 0.1860691298547847284166721e-1, 0.1736373667382462235016547e-1, 0.1609598401193537091543832e-1, 0.1480544940071787768084914e-1, 0.1349395951237523498069998e-1, 0.1216337072779861206303406e-1, 0.1081556655803715872036043e-1, 0.9452455092479699888244178e-2, 0.8075966593123452283593892e-2, 0.6688051635243685741358420e-2, 0.5290681445859865555240374e-2, 0.3885859435353202192003776e-2, 0.2475719322545939743331242e-2, 0.1064168219666567756385077e-2}, + {0.3671834473341961622215226e-1, 0.3664397593378570248640692e-1, 0.3652013948874488485747660e-1, 0.3634700257169520376675674e-1, 0.3612479890936246037475190e-1, 0.3585382846628081255691520e-1, 0.3553445703985569908199156e-1, 0.3516711576655578824981280e-1, 0.3475230053990063752924744e-1, 0.3429057134102984670822224e-1, 0.3378255148275753033131186e-1, 0.3322892676813276976252854e-1, 0.3263044456464217818903764e-1, 0.3198791279530467445976990e-1, 0.3130219884802087044839684e-1, 0.3057422840464999572392432e-1, 0.2980498419139588737561256e-1, 0.2899550465219015208986610e-1, 0.2814688254686507584638292e-1, 0.2726026347601116478577010e-1, 0.2633684433451435982173160e-1, 0.2537787169586608847736972e-1, 0.2438464012943568314241580e-1, 0.2335849045298989189769872e-1, 0.2230080792283937418945736e-1, 0.2121302036408937967241628e-1, 0.2009659624357542174179408e-1, 0.1895304268818284044680496e-1, 0.1778390345139817090774314e-1, 0.1659075683115467007520452e-1, 0.1537521354238962687440865e-1, 0.1413891454840083293055609e-1, 0.1288352885649808429050626e-1, 0.1161075128670389800962475e-1, 0.1032230023052424589381722e-1, 0.9019915439993631278967098e-2, 0.7705355960382757079897960e-2, 0.6380398587897515098686098e-2, 0.5046838426924442725450432e-2, 0.3706500125759316706868292e-2, 0.2361331704285020896763904e-2, 0.1014971908967743695374167e-2}, + {0.3588019106018701587773518e-1, 0.3581080434383374175662560e-1, 0.3569525919440943377647946e-1, 0.3553370454416059391133478e-1, 0.3532634862941021369843054e-1, 0.3507345872215153655662536e-1, 0.3477536078554782924871120e-1, 0.3443243905378224376593820e-1, 0.3404513553679937345518354e-1, 0.3361394945057693558422230e-1, 0.3313943657366202353628890e-1, 0.3262220853080144392580048e-1, 0.3206293200458966777765818e-1, 0.3146232787615076393796228e-1, 0.3082117029596223415371898e-1, 0.3014028568601882474395096e-1, 0.2942055167462304824922484e-1, 0.2866289596517621838858744e-1, 0.2786829514042920598963448e-1, 0.2703777340373580728397710e-1, 0.2617240125893355894972542e-1, 0.2527329413055707316411874e-1, 0.2434161092616763233921348e-1, 0.2337855254266017225782364e-1, 0.2238536031848547821419758e-1, 0.2136331443380253159361604e-1, 0.2031373226065556952656956e-1, 0.1923796666535655878505047e-1, 0.1813740426535425205021816e-1, 0.1701346364300153443364516e-1, 0.1586759351882631900292224e-1, 0.1470127088723984222989451e-1, 0.1351599911824565808188095e-1, 0.1231330603004803654228712e-1, 0.1109474194056071927972064e-1, 0.9861877713701826716584494e-2, 0.8616302838488951832949878e-2, 0.7359623648818063660769462e-2, 0.6093462047634872130101964e-2, 0.4819456238501885899307624e-2, 0.3539271655388628540179688e-2, 0.2254690753752853092482060e-2, 0.9691097381770753376096654e-3}, + {0.3507942401790202531716760e-1, 0.3501458416619644336915306e-1, 0.3490660650856070989101148e-1, 0.3475562407298142092081152e-1, 0.3456182286913780813643384e-1, 0.3432544165923908781796544e-1, 0.3404677166387108716735582e-1, 0.3372615620321457070630952e-1, 0.3336399027407732093971928e-1, 0.3296072006326111707429234e-1, 0.3251684239786320696758578e-1, 0.3203290413318958550703170e-1, 0.3150950147903428365879858e-1, 0.3094727926515484478947892e-1, 0.3034693014684912934340756e-1, 0.2970919375161245962730194e-1, 0.2903485576792681183001942e-1, 0.2832474697730520722803496e-1, 0.2757974223078458253347716e-1, 0.2680075937112917771256550e-1, 0.2598875810207383625148160e-1, 0.2514473880600256862281534e-1, 0.2426974131152233927366188e-1, 0.2336484361245544582716880e-1, 0.2243116053983636712835892e-1, 0.2146984238856114084341254e-1, 0.2048207350040027021224486e-1, 0.1946907080515187313867415e-1, 0.1843208232178411567584622e-1, 0.1737238562150240166964102e-1, 0.1629128625479238457754130e-1, 0.1519011614466612339747308e-1, 0.1407023194864448281388687e-1, 0.1293301339260267729158710e-1, 0.1177986158087489217661933e-1, 0.1061219728997218803268093e-1, 0.9431459260797890539711922e-2, 0.8239102525389078730572362e-2, 0.7036596870989114137389446e-2, 0.5825425788770107459644064e-2, 0.4607087343463241433054622e-2, 0.3383104792407455132632698e-2, 0.2155112582219113764637582e-2, 0.9262871051934728155239026e-3}, + {0.3431359817623139857242020e-1, 0.3425291647165106006719224e-1, 0.3415185977541012618567448e-1, 0.3401054720622907866548866e-1, 0.3382914533369793579365620e-1, 0.3360786798193575310982430e-1, 0.3334697597754983863697838e-1, 0.3304677684219179120016898e-1, 0.3270762443007278294842040e-1, 0.3232991851086539448409380e-1, 0.3191410429848369728859888e-1, 0.3146067192629708854519032e-1, 0.3097015586939654421561894e-1, 0.3044313431459439490344712e-1, 0.2988022847890037493277136e-1, 0.2928210187727747971826382e-1, 0.2864945954054102439649608e-1, 0.2798304718432316638118606e-1, 0.2728365033008298027898986e-1, 0.2655209337919890810307922e-1, 0.2578923864123601618879028e-1, 0.2499598531753495743256148e-1, 0.2417326844132287942221788e-1, 0.2332205777559880283599600e-1, 0.2244335667009737337332098e-1, 0.2153820087868566629622426e-1, 0.2060765733859846074045938e-1, 0.1965282291296914660474199e-1, 0.1867482309816812542178599e-1, 0.1767481069752190506037194e-1, 0.1665396446306124017225753e-1, 0.1561348770705005975095101e-1, 0.1455460688520869608484063e-1, 0.1347857015383097919431856e-1, 0.1238664590355674305453526e-1, 0.1128012127376968298340906e-1, 0.1016030065441547672889225e-1, 0.9028504189234487748913298e-2, 0.7886066314628901599629988e-2, 0.6734334432268884665261132e-2, 0.5574668047479788997832340e-2, 0.4408439747302676819065170e-2, 0.3237045507972104977098260e-2, 0.2061987122032229660677942e-2, 0.8862412406694141765769646e-3}, + {0.3358047670273290820423322e-1, 0.3352360509236689973246714e-1, 0.3342889041048296629425518e-1, 0.3329643957561578934524218e-1, 0.3312640210470322597293962e-1, 0.3291896994430459113247722e-1, 0.3267437725392241575486392e-1, 0.3239290014167229270630344e-1, 0.3207485635259921958171598e-1, 0.3172060490999230883258760e-1, 0.3133054571010280192591498e-1, 0.3090511907072293590876800e-1, 0.3044480523413530949647580e-1, 0.2995012382499392416587776e-1, 0.2942163326374897748551588e-1, 0.2885993013627770636290672e-1, 0.2826564852043306435742870e-1, 0.2763945927027071971311622e-1, 0.2698206925876273304878794e-1, 0.2629422057985327475229788e-1, 0.2557668971075783892217594e-1, 0.2483028663545258189183534e-1, 0.2405585393034465615306556e-1, 0.2325426581315775168991978e-1, 0.2242642715610957188910656e-1, 0.2157327246449981801505782e-1, 0.2069576482186873448858912e-1, 0.1979489480292792866805571e-1, 0.1887167935550803461442971e-1, 0.1792716065281371317885285e-1, 0.1696240491732901090122756e-1, 0.1597850121778211678831695e-1, 0.1497656024067188095391932e-1, 0.1395771303800797072406999e-1, 0.1292310975318535045602668e-1, 0.1187391832744712509861298e-1, 0.1081132319054248938202577e-1, 0.9736523941887687826947068e-2, 0.8650734035428648314139846e-2, 0.7555179500769820751618632e-2, 0.6451097794311275889059324e-2, 0.5339737098169214613757504e-2, 0.4222357382406607998634106e-2, 0.3100240403099316775464478e-2, 0.1974768768686808388940061e-2, 0.8487371680679110048896640e-3}, + {0.3287800959763194823557646e-1, 0.3282463569369918669308888e-1, 0.3273574336068393226919658e-1, 0.3261142878598215425670652e-1, 0.3245182648620325926685946e-1, 0.3225710916161441434734840e-1, 0.3202748750926769529295728e-1, 0.3176320999501228029097900e-1, 0.3146456258463840201321734e-1, 0.3113186843444399825682258e-1, 0.3076548754155891475295788e-1, 0.3036581635440506677724356e-1, 0.2993328734371411225240016e-1, 0.2946836853456688237515152e-1, 0.2897156299996101153484194e-1, 0.2844340831645486261311894e-1, 0.2788447598247691424309350e-1, 0.2729537079993022266578380e-1, 0.2667673021976135431896846e-1, 0.2602922365220227153290076e-1, 0.2535355174243201293660006e-1, 0.2465044561244261997612948e-1, 0.2392066606993061007707546e-1, 0.2316500278507139174920030e-1, 0.2238427343606939184041926e-1, 0.2157932282441140120676856e-1, 0.2075102196078490181790884e-1, 0.1990026712265721124487174e-1, 0.1902797888454570639306994e-1, 0.1813510112204514410759734e-1, 0.1722259999071698441334003e-1, 0.1629146288099104326591566e-1, 0.1534269735028835663459242e-1, 0.1437733003365908208357459e-1, 0.1339640553436828544136536e-1, 0.1240098529611606104018197e-1, 0.1139214645908584403924275e-1, 0.1037098070311609684083942e-1, 0.9338593083876397086740596e-2, 0.8296100874530990238145090e-2, 0.7244632443933199672626606e-2, 0.6185326261033323769312750e-2, 0.5119330329927718280032034e-2, 0.4047803316371759906879922e-2, 0.2971924240818190718436604e-2, 0.1892968377922935762776147e-2, 0.8135642494541165010544716e-3}, + {0.3220431459661350533475748e-1, 0.3215415737958550153577998e-1, 0.3207061987527279934927952e-1, 0.3195378880670864194528382e-1, 0.3180378546007149044495368e-1, 0.3162076555877401604294910e-1, 0.3140491910180172362457798e-1, 0.3115647016646904145775102e-1, 0.3087567667579765382432642e-1, 0.3056283013075858386135104e-1, 0.3021825530765601453452082e-1, 0.2984230992096702903457814e-1, 0.2943538425198732086424294e-1, 0.2899790074366843187205222e-1, 0.2853031356206718751823808e-1, 0.2803310812486267752680532e-1, 0.2750680059743034256009616e-1, 0.2695193735699644067363378e-1, 0.2636909442542934975707846e-1, 0.2575887687125678489535242e-1, 0.2512191818153004673565192e-1, 0.2445887960418784729059960e-1, 0.2377044946160306882104198e-1, 0.2305734243602599579639616e-1, 0.2232029882766713237862322e-1, 0.2156008378619171827843500e-1, 0.2077748651642656849799008e-1, 0.1997331945910804688818908e-1, 0.1914841744752812933525703e-1, 0.1830363684096414082229124e-1, 0.1743985463580780463940516e-1, 0.1655796755534245662902801e-1, 0.1565889111915692052020687e-1, 0.1474355869323695017635984e-1, 0.1381292052185304327114855e-1, 0.1286794274249338667571135e-1, 0.1190960638533075683273654e-1, 0.1093890635919594895396767e-1, 0.9956850427084044948237490e-2, 0.8964458176697999432566250e-2, 0.7962759997865495595598110e-2, 0.6952796096469405526464256e-2, 0.5935615630788222954183688e-2, 0.4912276262166028130833504e-2, 0.3883845329489294421733034e-2, 0.2851409243213055771419126e-2, 0.1816146398210039609502983e-2, 0.7805332219425612457264822e-3}, + {0.3155766036791122885809208e-1, 0.3151046648162834771323796e-1, 0.3143186227722154616152128e-1, 0.3132192610907518012817474e-1, 0.3118076756395815837033438e-1, 0.3100852735178559535833486e-1, 0.3080537716535627949917920e-1, 0.3057151950920577999218210e-1, 0.3030718749774580397961262e-1, 0.3001264462289103447190280e-1, 0.2968818449140509844801766e-1, 0.2933413053222750347643324e-1, 0.2895083567407331040373860e-1, 0.2853868199362694972663692e-1, 0.2809808033468091126593440e-1, 0.2762946989859901232207604e-1, 0.2713331780651255092639320e-1, 0.2661011863368585130179228e-1, 0.2606039391651548254092866e-1, 0.2548469163265475465058230e-1, 0.2488358565478194644598738e-1, 0.2425767517855707823164026e-1, 0.2360758412533789404661778e-1, 0.2293396052025105528408320e-1, 0.2223747584623937158435550e-1, 0.2151882437473022381824646e-1, 0.2077872247359421120742490e-1, 0.2001790789308656620794778e-1, 0.1923713903048718479867380e-1, 0.1843719417417849927098560e-1, 0.1761887072792438050675710e-1, 0.1678298441613870708950299e-1, 0.1593036847096084971103802e-1, 0.1506187280199023331295260e-1, 0.1417836314957944606614279e-1, 0.1328072022265728347995425e-1, 0.1236983882217516210343368e-1, 0.1144662695149825376113323e-1, 0.1051200491552474540574917e-1, 0.9566904411326136356898158e-2, 0.8612267615478888991732218e-2, 0.7649046279335257935390770e-2, 0.6678200860575098165183170e-2, 0.5700699773395926875152328e-2, 0.4717519037520830079689318e-2, 0.3729643487243034749198276e-2, 0.2738075873626878091327392e-2, 0.1743906958219244938639563e-2, 0.7494736467374053633626714e-3}, +} + +// The factor in front of the direct product representation +var cl = [...]float64{1.0, 1.0, -0.5000000000000000000000000e0, -0.1500000000000000000000000e1, 0.3750000000000000000000000e0, 0.1875000000000000000000000e1, -0.3125000000000000000000000e0, -0.2187500000000000000000000e1, 0.2734375000000000000000000e0, 0.2460937500000000000000000e1, -0.2460937500000000000000000e0, -0.2707031250000000000000000e1, 0.2255859375000000000000000e0, 0.2932617187500000000000000e1, -0.2094726562500000000000000e0, -0.3142089843750000000000000e1, 0.1963806152343750000000000e0, 0.3338470458984375000000000e1, -0.1854705810546875000000000e0, -0.3523941040039062500000000e1, 0.1761970520019531250000000e0, 0.3700138092041015625000000e1, -0.1681880950927734375000000e0, -0.3868326187133789062500000e1, 0.1611802577972412109375000e0, 0.4029506444931030273437500e1, -0.1549810171127319335937500e0, -0.4184487462043762207031250e1, 0.1494459807872772216796875e0, 0.4333933442831039428710938e1, -0.1444644480943679809570312e0, -0.4478397890925407409667969e1, 0.1399499340914189815521240e0, 0.4618347825016826391220093e1, -0.1358337595593184232711792e0, -0.4754181584576144814491272e1, 0.1320605995715595781803131e0, 0.4886242184147704392671585e1, -0.1285853206354659050703049e0, -0.5014827504783170297741890e1, 0.1253706876195792574435472e0, 0.5140198192402749555185437e1, -0.1223856712476845132187009e0, -0.5262583863650434068404138e1, 0.1196041787193280470091850e0, 0.5382188042369762115413323e1, -0.1170040878776035242481157e0, -0.5499192130247365639661439e1, 0.1145665027134867841596133e0, 0.5613758632960852423821052e1, -0.1122751726592170484764210e0, -0.5726033805620069472297473e1, 0.1101160347234628744672591e0, 0.5836149840343532346764732e1, -0.1080768488952505990141617e0, -0.5944226689238782945778894e1, 0.1061469051649782668889088e0, 0.6050373594403761212667803e1, -0.1043167861104096760804794e0, -0.6154690380514170888748282e1, 0.1025781730085695148124714e0, 0.6257268553522740403560753e1, -0.1009236863471409742509799e0, -0.6358192239869881377811733e1, 0.9934675374796689652830833e-1, 0.6457538993617848274340042e1, -0.9784149990330073142939457e-1, -0.6555380493521149005769436e1, 0.9640265431648748537896230e-1, 0.6651783147837636491148399e1, -0.9502547354053766415926284e-1, -0.6746808621378174155307661e1, 0.9370567529691908549038419e-1, 0.6840514296675093240798046e1, -0.9243938238750126001078440e-1, -0.6932953679062594500808830e1, 0.9122307472450782237906355e-1, 0.7024176753787102323187894e1, -0.9005354812547567081010120e-1, -0.7114230301912577993997995e1, 0.8892787877390722492497493e-1, 0.7203158180686485218922970e1, -0.8784339244739616120637768e-1, -0.7291001573133881380129347e1, 0.8679763777540334976344461e-1, 0.7377799210909284729892792e1, -0.8578836291754982244061386e-1, -0.7463587573826834552333406e1, 0.8481349515712311991287961e-1, 0.7548401068983957672246285e1, -0.8387112298871064080273650e-1, -0.7632272191972668313049022e1, 0.8295948034752900340270676e-1, 0.7715231672320197316451729e1, -0.8207693268425741826012477e-1, -0.7797308605004454734711853e1, 0.8122196463546307015324847e-1, 0.7878530569639917804865102e1, -0.8039316907795834494760308e-1, -0.7958923738717876149812705e1, 0.7958923738717876149812705e-1} diff --git a/integrate/quad/legendre_test.go b/integrate/quad/legendre_test.go new file mode 100644 index 00000000..7fb5bb09 --- /dev/null +++ b/integrate/quad/legendre_test.go @@ -0,0 +1,84 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package quad + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestLegendre(t *testing.T) { + for i, test := range []struct { + f func(float64) float64 + min, max float64 + n []int + tol []float64 + ans float64 + }{ + // Tolerances determined from intuition and a bit of post-hoc tweaking. + { + f: func(x float64) float64 { return math.Exp(x) }, + min: -3, + max: 5, + n: []int{3, 4, 6, 7, 15, 16, 300, 301}, + tol: []float64{5e-2, 5e-3, 5e-6, 1e-7, 1e-14, 1e-14, 1e-14, 1e-14}, + ans: math.Exp(5) - math.Exp(-3), + }, + } { + for j, n := range test.n { + ans := Fixed(test.f, test.min, test.max, n, Legendre{}, 0) + if !floats.EqualWithinAbsOrRel(ans, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Mismatch. Case = %d, n = %d. Want %v, got %v", i, n, test.ans, ans) + } + ans2 := Fixed(test.f, test.min, test.max, n, Legendre{}, 3) + if !floats.EqualWithinAbsOrRel(ans2, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Mismatch concurrent. Case = %d, n = %d. Want %v, got %v", i, n, test.ans, ans) + } + } + } +} + +func TestLegendreSingle(t *testing.T) { + for c, test := range []struct { + n int + min, max float64 + }{ + { + n: 100, + min: -1, + max: 1, + }, + { + n: 50, + min: -3, + max: -1, + }, + { + n: 1000, + min: 2, + max: 7, + }, + } { + l := Legendre{} + n := test.n + xs := make([]float64, n) + weights := make([]float64, n) + l.FixedLocations(xs, weights, test.min, test.max) + + xsSingle := make([]float64, n) + weightsSingle := make([]float64, n) + for i := range xsSingle { + xsSingle[i], weightsSingle[i] = l.FixedLocationSingle(n, i, test.min, test.max) + } + if !floats.Equal(xs, xsSingle) { + t.Errorf("Case %d: xs mismatch batch and single", c) + } + if !floats.Equal(weights, weightsSingle) { + t.Errorf("Case %d: weights mismatch batch and single", c) + } + } +} diff --git a/integrate/quad/quad.go b/integrate/quad/quad.go new file mode 100644 index 00000000..0927254e --- /dev/null +++ b/integrate/quad/quad.go @@ -0,0 +1,159 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package quad provides numerical evaluation of definite integrals of single-variable functions. +// +package quad + +import ( + "math" + "sync" +) + +// FixedLocationer computes a set of quadrature locations and weights and stores +// them in-place into x and weight respectively. The number of points generated is equal to +// the len(x). The weights and locations should be chosen such that +// int_min^max f(x) dx ≈ \sum_i w_i f(x_i) +type FixedLocationer interface { + FixedLocations(x, weight []float64, min, max float64) +} + +// FixedLocationSingle returns the location and weight for element k in a +// fixed quadrature rule with n total samples and integral bounds from min to max. +type FixedLocationSingler interface { + FixedLocationSingle(n, k int, min, max float64) (x, weight float64) +} + +// Fixed approximates the integral of the function f from min to max using a fixed +// n-point quadrature rule. During evaluation, f will be evaluated n times using +// the weights and locations specified by rule. That is, Fixed estimates +// int_min^max f(x) dx ≈ \sum_i w_i f(x_i) +// If rule is nil, an acceptable default is chosen, otherwise it is +// assumed that the properties of the integral match the assumptions of rule. +// For example, Legendre assumes that the integration bounds are finite. If +// rule is also a FixedLocationSingler, the quadrature points are computed +// individually rather than as a unit. +// +// If concurrent <= 0, f is evaluated serially, while if concurrent > 0, f +// may be evaluated with at most concurrent simultaneous evaluations. +// +// min must be less than or equal to max, and n must be positive, otherwise +// Fixed will panic. +func Fixed(f func(float64) float64, min, max float64, n int, rule FixedLocationer, concurrent int) float64 { + // TODO(btracey): When there are Hermite polynomial quadrature, add an additional + // example to the documentation comment that talks about weight functions. + if n <= 0 { + panic("quad: non-positive number of locations") + } + if min > max { + panic("quad: min > max") + } + if min == max { + return 0 + } + intfunc := f + // If rule is non-nil it is assumed that the function and the constraints + // of rule are aligned. If it is nil, wrap the function and do something + // reasonable. + // TODO(btracey): Replace wrapping with other quadrature rules when + // we have rules that support infinite-bound integrals. + if rule == nil { + // int_a^b f(x)dx = int_u^-1(a)^u^-1(b) f(u(t))u'(t)dt + switch { + case math.IsInf(max, 1) && math.IsInf(min, -1): + // u(t) = (t/(1-t^2)) + min = -1 + max = 1 + intfunc = func(x float64) float64 { + v := 1 - x*x + return f(x/v) * (1 + x*x) / (v * v) + } + case math.IsInf(max, 1): + // u(t) = a + t / (1-t) + a := min + min = 0 + max = 1 + intfunc = func(x float64) float64 { + v := 1 - x + return f(a+x/v) / (v * v) + } + case math.IsInf(min, -1): + // u(t) = a - (1-t)/t + a := max + min = 0 + max = 1 + intfunc = func(x float64) float64 { + return f(a-(1-x)/x) / (x * x) + } + } + rule = Legendre{} + } + singler, isSingler := rule.(FixedLocationSingler) + + var xs, weights []float64 + if !isSingler { + xs = make([]float64, n) + weights = make([]float64, n) + rule.FixedLocations(xs, weights, min, max) + } + + if concurrent > n { + concurrent = n + } + + if concurrent <= 0 { + var integral float64 + // Evaluate in serial. + if isSingler { + for k := 0; k < n; k++ { + x, weight := singler.FixedLocationSingle(n, k, min, max) + integral += weight * intfunc(x) + } + return integral + } + for i, x := range xs { + integral += weights[i] * intfunc(x) + } + return integral + } + + // Evaluate concurrently + tasks := make(chan int) + + // Launch distributor + go func() { + for i := 0; i < n; i++ { + tasks <- i + } + close(tasks) + }() + + var mux sync.Mutex + var integral float64 + var wg sync.WaitGroup + wg.Add(concurrent) + for i := 0; i < concurrent; i++ { + // Launch workers + go func() { + defer wg.Done() + var subIntegral float64 + for k := range tasks { + var x, weight float64 + if isSingler { + x, weight = singler.FixedLocationSingle(n, k, min, max) + } else { + x = xs[k] + weight = weights[k] + } + f := intfunc(x) + subIntegral += f * weight + } + mux.Lock() + integral += subIntegral + mux.Unlock() + }() + } + wg.Wait() + return integral +} diff --git a/integrate/quad/quad_test.go b/integrate/quad/quad_test.go new file mode 100644 index 00000000..5e25ffdd --- /dev/null +++ b/integrate/quad/quad_test.go @@ -0,0 +1,126 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package quad + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/stat/distuv" +) + +func TestFixed(t *testing.T) { + for i, test := range []struct { + f func(float64) float64 + min, max float64 + n []int + tol []float64 + ans float64 + }{ + // Tolerances determined from intuition and a bit of post-hoc tweaking. + { + f: func(x float64) float64 { return math.Exp(x) }, + min: -3, + max: 5, + n: []int{3, 4, 6, 7, 15, 16, 300, 301}, + tol: []float64{5e-2, 5e-3, 5e-6, 1e-7, 1e-14, 1e-14, 1e-14, 1e-14}, + ans: math.Exp(5) - math.Exp(-3), + }, + { + f: distuv.UnitNormal.Prob, + min: math.Inf(-1), + max: math.Inf(1), + n: []int{15, 16, 50, 51, 300, 301}, + tol: []float64{5e-3, 1e-3, 1e-7, 1e-7, 1e-14, 1e-14}, + ans: 1, + }, + { + f: func(x float64) float64 { return math.Exp(-x) }, + min: 5, + max: math.Inf(1), + n: []int{15, 16, 50, 51, 300, 301}, + tol: []float64{5e-3, 1e-3, 1e-7, 1e-7, 1e-14, 1e-14}, + ans: math.Exp(-5), + }, + { + f: func(x float64) float64 { return math.Exp(x) }, + min: math.Inf(-1), + max: -5, + n: []int{15, 16, 50, 51, 300, 301}, + tol: []float64{5e-3, 1e-3, 1e-7, 1e-7, 1e-14, 1e-14}, + ans: math.Exp(-5), + }, + { + f: func(x float64) float64 { return math.Exp(x) }, + min: 3, + max: 3, + n: []int{15, 16, 50, 51, 300, 301}, + tol: []float64{0, 0, 0, 0, 0, 0}, + ans: 0, + }, + } { + for j, n := range test.n { + ans := Fixed(test.f, test.min, test.max, n, nil, 0) + if !floats.EqualWithinAbsOrRel(ans, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Case %d, n = %d: Mismatch. Want %v, got %v", i, n, test.ans, ans) + } + ans2 := Fixed(test.f, test.min, test.max, n, nil, 3) + if !floats.EqualWithinAbsOrRel(ans2, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Case %d, n = %d: Mismatch concurrent. Want %v, got %v", i, n, test.ans, ans) + } + } + } +} + +// legendreNonSingle wraps Legendre but does not implement FixedLocationSingle. +type legendreNonSingle struct { + Legendre Legendre +} + +func (l legendreNonSingle) FixedLocations(x, weight []float64, min, max float64) { + l.Legendre.FixedLocations(x, weight, min, max) +} + +func TestFixedNonSingle(t *testing.T) { + // TODO(btracey): Add tests with infinite bounds when we have native support + // for indefinite integrals. + for i, test := range []struct { + f func(float64) float64 + min, max float64 + n []int + tol []float64 + ans float64 + }{ + // Tolerances determined from intuition and a bit of post-hoc tweaking. + { + f: func(x float64) float64 { return math.Exp(x) }, + min: -3, + max: 5, + n: []int{3, 4, 6, 7, 15, 16, 300, 301}, + tol: []float64{5e-2, 5e-3, 5e-6, 1e-7, 1e-14, 1e-14, 1e-14, 1e-14}, + ans: math.Exp(5) - math.Exp(-3), + }, + { + f: func(x float64) float64 { return math.Exp(x) }, + min: 3, + max: 3, + n: []int{3, 4, 6, 7, 15, 16, 300, 301}, + tol: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + ans: 0, + }, + } { + for j, n := range test.n { + ans := Fixed(test.f, test.min, test.max, n, legendreNonSingle{}, 0) + if !floats.EqualWithinAbsOrRel(ans, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Case = %d, n = %d: Mismatch. Want %v, got %v", i, n, test.ans, ans) + } + ans2 := Fixed(test.f, test.min, test.max, n, legendreNonSingle{}, 3) + if !floats.EqualWithinAbsOrRel(ans2, test.ans, test.tol[j], test.tol[j]) { + t.Errorf("Case = %d, n = %d: Mismatch concurrent. Want %v, got %v", i, n, test.ans, ans) + } + } + } +} diff --git a/integrate/trapezoidal.go b/integrate/trapezoidal.go new file mode 100644 index 00000000..3f402ac3 --- /dev/null +++ b/integrate/trapezoidal.go @@ -0,0 +1,40 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integrate + +import "sort" + +// Trapezoidal estimates the integral of a function f +// \int_a^b f(x) dx +// from a set of evaluations of the function using the trapezoidal rule. +// The trapezoidal rule makes piecewise linear approximations to the function, +// and estimates +// \int_x[i]^x[i+1] f(x) dx +// as +// (x[i+1] - x[i]) * (f[i] + f[i+1])/2 +// where f[i] is the value of the function at x[i]. +// More details on the trapezoidal rule can be found at: +// https://en.wikipedia.org/wiki/Trapezoidal_rule +// +// The (x,f) input data points must be sorted along x. +// One can use github.com/gonum/stat.SortWeighted to do that. +// The x and f slices must be of equal length and have length > 1. +func Trapezoidal(x, f []float64) float64 { + switch { + case len(x) != len(f): + panic("integrate: slice length mismatch") + case len(x) < 2: + panic("integrate: input data too small") + case !sort.Float64sAreSorted(x): + panic("integrate: input must be sorted") + } + + integral := 0.0 + for i := 0; i < len(x)-1; i++ { + integral += 0.5 * (x[i+1] - x[i]) * (f[i+1] + f[i]) + } + + return integral +} diff --git a/integrate/trapezoidal_test.go b/integrate/trapezoidal_test.go new file mode 100644 index 00000000..c52ee0e6 --- /dev/null +++ b/integrate/trapezoidal_test.go @@ -0,0 +1,82 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integrate + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestTrapezoidal(t *testing.T) { + const N = 1e6 + x := floats.Span(make([]float64, N), 0, 1) + for i, test := range []struct { + x []float64 + f func(x float64) float64 + want float64 + }{ + { + x: x, + f: func(x float64) float64 { return x }, + want: 0.5, + }, + { + x: floats.Span(make([]float64, N), -1, 1), + f: func(x float64) float64 { return x }, + want: 0, + }, + { + x: x, + f: func(x float64) float64 { return x + 10 }, + want: 10.5, + }, + { + x: x, + f: func(x float64) float64 { return 3*x*x + 10 }, + want: 11, + }, + { + x: x, + f: func(x float64) float64 { return math.Exp(x) }, + want: 1.7182818284591876, + }, + { + x: floats.Span(make([]float64, N), 0, math.Pi), + f: func(x float64) float64 { return math.Cos(x) }, + want: 0, + }, + { + x: floats.Span(make([]float64, N), 0, 2*math.Pi), + f: func(x float64) float64 { return math.Cos(x) }, + want: 0, + }, + { + x: floats.Span(make([]float64, N*10), 0, math.Pi), + f: func(x float64) float64 { return math.Sin(x) }, + want: 2, + }, + { + x: floats.Span(make([]float64, N*10), 0, 0.5*math.Pi), + f: func(x float64) float64 { return math.Sin(x) }, + want: 1, + }, + { + x: floats.Span(make([]float64, N), 0, 2*math.Pi), + f: func(x float64) float64 { return math.Sin(x) }, + want: 0, + }, + } { + y := make([]float64, len(test.x)) + for i, v := range test.x { + y[i] = test.f(v) + } + v := Trapezoidal(test.x, y) + if !floats.EqualWithinAbs(v, test.want, 1e-12) { + t.Errorf("test #%d: got=%v want=%v\n", i, v, test.want) + } + } +} diff --git a/internal/README.md b/internal/README.md new file mode 100644 index 00000000..d1168f65 --- /dev/null +++ b/internal/README.md @@ -0,0 +1,13 @@ +# Gonum Internal [![Build Status](https://travis-ci.org/gonum/internal.svg?branch=master)](https://travis-ci.org/gonum/internal) [![Coverage Status](https://coveralls.io/repos/gonum/internal/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/internal?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/internal?status.svg)](https://godoc.org/github.com/gonum/internal) + +This is the set of internal packages for the Gonum project. + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see [github.com/gonum/license](https://github.com/gonum/license) for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/internal/asm/bench_gen.sh b/internal/asm/bench_gen.sh new file mode 100755 index 00000000..e7115c07 --- /dev/null +++ b/internal/asm/bench_gen.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Copyright ©2016 The gonum Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +cat c64/bench_test.go \ + | gofmt -r 'complex(float32(n), float32(n)) -> float32(n)' \ + | gofmt -r 'complex64 -> float32' \ + | gofmt -r '1 + 1i -> 1' \ + | gofmt -r '2 + 2i -> 2' \ + | sed 's/C64/F32/g' \ + | sed 's/c64/f32/g' \ + > f32/bench_test.go + +cat c64/bench_test.go \ + | gofmt -r 'complex(float32(n), float32(n)) -> float64(n)' \ + | gofmt -r 'complex64 -> float64' \ + | gofmt -r '1 + 1i -> 1' \ + | gofmt -r '2 + 2i -> 2' \ + | sed 's/C64/F64/g' \ + | sed 's/c64/f64/g' \ + > f64/bench_test.go + +cat c64/bench_test.go \ + | gofmt -r 'float32 -> float64' \ + | gofmt -r 'complex64 -> complex128' \ + | sed 's/C64/C128/g' \ + | sed 's/c64/c128/g' \ + > c128/bench_test.go diff --git a/internal/asm/c128/axpyinc_amd64.s b/internal/asm/c128/axpyinc_amd64.s new file mode 100644 index 00000000..c66a667b --- /dev/null +++ b/internal/asm/c128/axpyinc_amd64.s @@ -0,0 +1,134 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVDDUP X2, X3 +#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA +// MOVDDUP X4, X5 +#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC +// MOVDDUP X6, X7 +#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE +// MOVDDUP X8, X9 +#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 + +// ADDSUBPD X2, X3 +#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA +// ADDSUBPD X4, X5 +#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC +// ADDSUBPD X6, X7 +#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE +// ADDSUBPD X8, X9 +#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyInc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyInc(SB), NOSPLIT, $0 + MOVQ x_base+16(FP), SI // SI = &x + MOVQ y_base+40(FP), DI // DI = &y + MOVQ n+64(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JE axpyi_end + MOVQ ix+88(FP), R8 // R8 = ix // Load the first index + SHLQ $4, R8 // R8 *= sizeof(complex128) + MOVQ iy+96(FP), R9 // R9 = iy + SHLQ $4, R9 // R9 *= sizeof(complex128) + LEAQ (SI)(R8*1), SI // SI = &(x[ix]) + LEAQ (DI)(R9*1), DI // DI = &(y[iy]) + MOVQ DI, DX // DX = DI // Separate Read/Write pointers + MOVQ incX+72(FP), R8 // R8 = incX + SHLQ $4, R8 // R8 *= sizeof(complex128) + MOVQ incY+80(FP), R9 // R9 = iy + SHLQ $4, R9 // R9 *= sizeof(complex128) + MOVUPS alpha+0(FP), X0 // X0 = { imag(a), real(a) } + MOVAPS X0, X1 + SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ axpyi_tail // if BX == 0 { goto axpyi_tail } + +axpyi_loop: // do { + MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS (SI)(R8*1), X4 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVUPS (SI), X6 + MOVUPS (SI)(R8*1), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPD X1, X2 + MULPD X0, X3 + MULPD X11, X4 + MULPD X10, X5 + MULPD X1, X6 + MULPD X0, X7 + MULPD X11, X8 + MULPD X10, X9 + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX), X3 + ADDPD (DX)(R9*1), X5 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + ADDPD (DX), X7 + ADDPD (DX)(R9*1), X9 + MOVUPS X3, (DI) // dst[i] = X_(i+1) + MOVUPS X5, (DI)(R9*1) + LEAQ (DI)(R9*2), DI + MOVUPS X7, (DI) + MOVUPS X9, (DI)(R9*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R9*2), DI // DI = &(DI[incY*2]) + DECQ BX + JNZ axpyi_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE axpyi_end + +axpyi_tail: // do { + MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DI), X3 + MOVUPS X3, (DI) // y[i] = X_i + ADDQ R8, SI // SI = &(SI[incX]) + ADDQ R9, DI // DI = &(DI[incY]) + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET diff --git a/internal/asm/c128/axpyincto_amd64.s b/internal/asm/c128/axpyincto_amd64.s new file mode 100644 index 00000000..edc0957c --- /dev/null +++ b/internal/asm/c128/axpyincto_amd64.s @@ -0,0 +1,141 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVDDUP X2, X3 +#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA +// MOVDDUP X4, X5 +#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC +// MOVDDUP X6, X7 +#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE +// MOVDDUP X8, X9 +#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 + +// ADDSUBPD X2, X3 +#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA +// ADDSUBPD X4, X5 +#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC +// ADDSUBPD X6, X7 +#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE +// ADDSUBPD X8, X9 +#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyIncTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+56(FP), SI // SI = &x + MOVQ y_base+80(FP), DX // DX = &y + MOVQ n+104(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JE axpyi_end + MOVQ ix+128(FP), R8 // R8 = ix // Load the first index + SHLQ $4, R8 // R8 *= sizeof(complex128) + MOVQ iy+136(FP), R9 // R9 = iy + SHLQ $4, R9 // R9 *= sizeof(complex128) + MOVQ idst+32(FP), R10 // R10 = idst + SHLQ $4, R10 // R10 *= sizeof(complex128) + LEAQ (SI)(R8*1), SI // SI = &(x[ix]) + LEAQ (DX)(R9*1), DX // DX = &(y[iy]) + LEAQ (DI)(R10*1), DI // DI = &(dst[idst]) + MOVQ incX+112(FP), R8 // R8 = incX + SHLQ $4, R8 // R8 *= sizeof(complex128) + MOVQ incY+120(FP), R9 // R9 = incY + SHLQ $4, R9 // R9 *= sizeof(complex128) + MOVQ incDst+24(FP), R10 // R10 = incDst + SHLQ $4, R10 // R10 *= sizeof(complex128) + MOVUPS alpha+40(FP), X0 // X0 = { imag(a), real(a) } + MOVAPS X0, X1 + SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ axpyi_tail // if BX == 0 { goto axpyi_tail } + +axpyi_loop: // do { + MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS (SI)(R8*1), X4 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + + MOVUPS (SI), X6 + MOVUPS (SI)(R8*1), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPD X1, X2 + MULPD X0, X3 + MULPD X11, X4 + MULPD X10, X5 + MULPD X1, X6 + MULPD X0, X7 + MULPD X11, X8 + MULPD X10, X9 + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX), X3 + ADDPD (DX)(R9*1), X5 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + ADDPD (DX), X7 + ADDPD (DX)(R9*1), X9 + MOVUPS X3, (DI) // dst[i] = X_(i+1) + MOVUPS X5, (DI)(R10*1) + LEAQ (DI)(R10*2), DI + MOVUPS X7, (DI) + MOVUPS X9, (DI)(R10*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) + DECQ BX + JNZ axpyi_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE axpyi_end + +axpyi_tail: // do { + MOVUPS (SI), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX), X3 + MOVUPS X3, (DI) // y[i] X_(i+1) + ADDQ R8, SI // SI += incX + ADDQ R9, DX // DX += incY + ADDQ R10, DI // DI += incDst + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET diff --git a/internal/asm/c128/axpyunitary_amd64.s b/internal/asm/c128/axpyunitary_amd64.s new file mode 100644 index 00000000..c9e119d3 --- /dev/null +++ b/internal/asm/c128/axpyunitary_amd64.s @@ -0,0 +1,122 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVDDUP X2, X3 +#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA +// MOVDDUP X4, X5 +#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC +// MOVDDUP X6, X7 +#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE +// MOVDDUP X8, X9 +#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 + +// ADDSUBPD X2, X3 +#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA +// ADDSUBPD X4, X5 +#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC +// ADDSUBPD X6, X7 +#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE +// ADDSUBPD X8, X9 +#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyUnitary(alpha complex128, x, y []complex128) +TEXT ·AxpyUnitary(SB), NOSPLIT, $0 + MOVQ x_base+16(FP), SI // SI = &x + MOVQ y_base+40(FP), DI // DI = &y + MOVQ x_len+24(FP), CX // CX = min( len(x), len(y) ) + CMPQ y_len+48(FP), CX + CMOVQLE y_len+48(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + PXOR X0, X0 // Clear work registers and cache-align loop + PXOR X1, X1 + MOVUPS alpha+0(FP), X0 // X0 = { imag(a), real(a) } + MOVAPS X0, X1 + SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } + XORQ AX, AX // i = 0 + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_loop: // do { + MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS 16(SI)(AX*8), X4 + MOVUPS 32(SI)(AX*8), X6 + MOVUPS 48(SI)(AX*8), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPD X1, X2 + MULPD X0, X3 + MULPD X11, X4 + MULPD X10, X5 + MULPD X1, X6 + MULPD X0, X7 + MULPD X11, X8 + MULPD X10, X9 + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DI)(AX*8), X3 + ADDPD 16(DI)(AX*8), X5 + ADDPD 32(DI)(AX*8), X7 + ADDPD 48(DI)(AX*8), X9 + MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) + MOVUPS X5, 16(DI)(AX*8) + MOVUPS X7, 32(DI)(AX*8) + MOVUPS X9, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + DECQ BX + JNZ caxy_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + +caxy_tail: // do { + MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DI)(AX*8), X3 + MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) + ADDQ $2, AX // i += 2 + LOOP caxy_tail // } while --CX > 0 + +caxy_end: + RET diff --git a/internal/asm/c128/axpyunitaryto_amd64.s b/internal/asm/c128/axpyunitaryto_amd64.s new file mode 100644 index 00000000..9dcfc67e --- /dev/null +++ b/internal/asm/c128/axpyunitaryto_amd64.s @@ -0,0 +1,123 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVDDUP X2, X3 +#define MOVDDUP_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xDA +// MOVDDUP X4, X5 +#define MOVDDUP_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xEC +// MOVDDUP X6, X7 +#define MOVDDUP_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0x12; BYTE $0xFE +// MOVDDUP X8, X9 +#define MOVDDUP_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC8 + +// ADDSUBPD X2, X3 +#define ADDSUBPD_X2_X3 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA +// ADDSUBPD X4, X5 +#define ADDSUBPD_X4_X5 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC +// ADDSUBPD X6, X7 +#define ADDSUBPD_X6_X7 BYTE $0x66; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE +// ADDSUBPD X8, X9 +#define ADDSUBPD_X8_X9 BYTE $0x66; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyUnitaryTo(dst []complex128, alpha complex64, x, y []complex128) +TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+40(FP), SI // SI = &x + MOVQ y_base+64(FP), DX // DX = &y + MOVQ x_len+48(FP), CX // CX = min( len(x), len(y), len(dst) ) + CMPQ y_len+72(FP), CX + CMOVQLE y_len+72(FP), CX + CMPQ dst_len+8(FP), CX + CMOVQLE dst_len+8(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + MOVUPS alpha+24(FP), X0 // X0 = { imag(a), real(a) } + MOVAPS X0, X1 + SHUFPD $0x1, X1, X1 // X1 = { real(a), imag(a) } + XORQ AX, AX // i = 0 + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_loop: // do { + MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVUPS 16(SI)(AX*8), X4 + MOVUPS 32(SI)(AX*8), X6 + MOVUPS 48(SI)(AX*8), X8 + + // X_(i+1) = { real(x[i], real(x[i]) } + MOVDDUP_X2_X3 // Load and duplicate imag elements (xi, xi) + MOVDDUP_X4_X5 + MOVDDUP_X6_X7 + MOVDDUP_X8_X9 + + // X_i = { imag(x[i]), imag(x[i]) } + SHUFPD $0x3, X2, X2 // duplicate real elements (xr, xr) + SHUFPD $0x3, X4, X4 + SHUFPD $0x3, X6, X6 + SHUFPD $0x3, X8, X8 + + // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPD X1, X2 + MULPD X0, X3 + MULPD X11, X4 + MULPD X10, X5 + MULPD X1, X6 + MULPD X0, X7 + MULPD X11, X8 + MULPD X10, X9 + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + ADDSUBPD_X4_X5 + ADDSUBPD_X6_X7 + ADDSUBPD_X8_X9 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX)(AX*8), X3 + ADDPD 16(DX)(AX*8), X5 + ADDPD 32(DX)(AX*8), X7 + ADDPD 48(DX)(AX*8), X9 + MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) + MOVUPS X5, 16(DI)(AX*8) + MOVUPS X7, 32(DI)(AX*8) + MOVUPS X9, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + DECQ BX + JNZ caxy_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + +caxy_tail: // Same calculation, but read in values to avoid trampling memory + MOVUPS (SI)(AX*8), X2 // X_i = { imag(x[i]), real(x[i]) } + MOVDDUP_X2_X3 // X_(i+1) = { real(x[i], real(x[i]) } + SHUFPD $0x3, X2, X2 // X_i = { imag(x[i]), imag(x[i]) } + MULPD X1, X2 // X_i = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPD X0, X3 // X_(i+1) = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X_(i+1) = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]) + // } + ADDSUBPD_X2_X3 + + // X_(i+1) = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + ADDPD (DX)(AX*8), X3 + MOVUPS X3, (DI)(AX*8) // y[i] = X_(i+1) + ADDQ $2, AX // i += 2 + LOOP caxy_tail // } while --CX > 0 + +caxy_end: + RET diff --git a/internal/asm/c128/bench_test.go b/internal/asm/c128/bench_test.go new file mode 100644 index 00000000..61049beb --- /dev/null +++ b/internal/asm/c128/bench_test.go @@ -0,0 +1,284 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c128 + +import "testing" + +var ( + a = complex128(2 + 2i) + x = make([]complex128, 1000000) + y = make([]complex128, 1000000) + z = make([]complex128, 1000000) +) + +func init() { + for n := range x { + x[n] = complex(float64(n), float64(n)) + y[n] = complex(float64(n), float64(n)) + } +} + +func benchaxpyu(t *testing.B, n int, f func(a complex128, x, y []complex128)) { + x, y := x[:n], y[:n] + for i := 0; i < t.N; i++ { + f(a, x, y) + } +} + +func naiveaxpyu(a complex128, x, y []complex128) { + for i, v := range x { + y[i] += a * v + } +} + +func BenchmarkC128AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, AxpyUnitary) } +func BenchmarkC128AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, AxpyUnitary) } +func BenchmarkC128AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, AxpyUnitary) } +func BenchmarkC128AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, AxpyUnitary) } +func BenchmarkC128AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, AxpyUnitary) } +func BenchmarkC128AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, AxpyUnitary) } +func BenchmarkC128AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, AxpyUnitary) } +func BenchmarkC128AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, AxpyUnitary) } +func BenchmarkC128AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, AxpyUnitary) } +func BenchmarkC128AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, AxpyUnitary) } +func BenchmarkC128AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, AxpyUnitary) } + +func BenchmarkLC128AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, naiveaxpyu) } +func BenchmarkLC128AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, naiveaxpyu) } + +func benchaxpyut(t *testing.B, n int, f func(d []complex128, a complex128, x, y []complex128)) { + x, y, z := x[:n], y[:n], z[:n] + for i := 0; i < t.N; i++ { + f(z, a, x, y) + } +} + +func naiveaxpyut(d []complex128, a complex128, x, y []complex128) { + for i, v := range x { + d[i] = y[i] + a*v + } +} + +func BenchmarkC128AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, AxpyUnitaryTo) } +func BenchmarkC128AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, AxpyUnitaryTo) } + +func BenchmarkLC128AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, naiveaxpyut) } +func BenchmarkLC128AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, naiveaxpyut) } + +func benchaxpyinc(t *testing.B, ln, t_inc int, f func(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(1+1i, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyinc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +func BenchmarkC128AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, AxpyInc) } + +func BenchmarkC128AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, AxpyInc) } +func BenchmarkC128AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, AxpyInc) } +func BenchmarkC128AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, AxpyInc) } +func BenchmarkC128AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, AxpyInc) } +func BenchmarkC128AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, AxpyInc) } +func BenchmarkC128AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, AxpyInc) } +func BenchmarkC128AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, AxpyInc) } +func BenchmarkC128AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, AxpyInc) } +func BenchmarkC128AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, AxpyInc) } +func BenchmarkC128AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, AxpyInc) } +func BenchmarkC128AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, AxpyInc) } +func BenchmarkC128AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, AxpyInc) } +func BenchmarkC128AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, AxpyInc) } +func BenchmarkC128AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, AxpyInc) } +func BenchmarkC128AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, AxpyInc) } +func BenchmarkC128AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, AxpyInc) } +func BenchmarkC128AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, AxpyInc) } +func BenchmarkC128AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, AxpyInc) } +func BenchmarkC128AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, AxpyInc) } + +func BenchmarkC128AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, AxpyInc) } +func BenchmarkC128AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, AxpyInc) } +func BenchmarkC128AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, AxpyInc) } +func BenchmarkC128AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, AxpyInc) } + +func BenchmarkLC128AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, naiveaxpyinc) } + +func BenchmarkLC128AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, naiveaxpyinc) } +func BenchmarkLC128AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, naiveaxpyinc) } + +func benchaxpyincto(t *testing.B, ln, t_inc int, f func(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(z, inc, uintptr(idx), 1+1i, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyincto(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} + +func BenchmarkC128AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, AxpyIncTo) } + +func BenchmarkC128AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, AxpyIncTo) } +func BenchmarkC128AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, AxpyIncTo) } + +func BenchmarkLC128AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, naiveaxpyincto) } + +func BenchmarkLC128AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, naiveaxpyincto) } +func BenchmarkLC128AxpyIncToN100000IncM10(b *testing.B) { + benchaxpyincto(b, 100000, -10, naiveaxpyincto) +} diff --git a/internal/asm/c128/doc.go b/internal/asm/c128/doc.go new file mode 100644 index 00000000..1a03f2b8 --- /dev/null +++ b/internal/asm/c128/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package c128 provides complex128 vector primitives. +package c128 diff --git a/internal/asm/c128/dotc.go b/internal/asm/c128/dotc.go new file mode 100644 index 00000000..a852f0d2 --- /dev/null +++ b/internal/asm/c128/dotc.go @@ -0,0 +1,35 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c128 + +import "math/cmplx" + +// DotcUnitary is +// for i, v := range x { +// sum += y[i] * cmplx.Conj(v) +// } +// return sum +func DotcUnitary(x, y []complex128) (sum complex128) { + for i, v := range x { + sum += y[i] * cmplx.Conj(v) + } + return sum +} + +// DotcInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * cmplx.Conj(x[ix]) +// ix += incX +// iy += incY +// } +// return sum +func DotcInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) { + for i := 0; i < int(n); i++ { + sum += y[iy] * cmplx.Conj(x[ix]) + ix += incX + iy += incY + } + return sum +} diff --git a/internal/asm/c128/dotu.go b/internal/asm/c128/dotu.go new file mode 100644 index 00000000..d82dc467 --- /dev/null +++ b/internal/asm/c128/dotu.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c128 + +// DotuUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotuUnitary(x, y []complex128) (sum complex128) { + for i, v := range x { + sum += y[i] * v + } + return sum +} + +// DotuInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotuInc(x, y []complex128, n, incX, incY, ix, iy uintptr) (sum complex128) { + for i := 0; i < int(n); i++ { + sum += y[iy] * x[ix] + ix += incX + iy += incY + } + return sum +} diff --git a/internal/asm/c128/scal.go b/internal/asm/c128/scal.go new file mode 100644 index 00000000..9d26973d --- /dev/null +++ b/internal/asm/c128/scal.go @@ -0,0 +1,55 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c128 + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha complex128, x []complex128) { + for i := range x { + x[i] *= alpha + } +} + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []complex128, alpha complex128, x []complex128) { + for i, v := range x { + dst[i] = alpha * v + } +} + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha complex128, x []complex128, n, incX uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] *= alpha + ix += incX + } +} + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []complex128, incDst uintptr, alpha complex128, x []complex128, n, incX uintptr) { + var idst, ix uintptr + for i := 0; i < int(n); i++ { + dst[idst] = alpha * x[ix] + ix += incX + idst += incDst + } +} diff --git a/internal/asm/c128/stubs_amd64.go b/internal/asm/c128/stubs_amd64.go new file mode 100644 index 00000000..fe190299 --- /dev/null +++ b/internal/asm/c128/stubs_amd64.go @@ -0,0 +1,36 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +package c128 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha complex128, x, y []complex128) + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []complex128, alpha complex128, x, y []complex128) + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) diff --git a/internal/asm/c128/stubs_noasm.go b/internal/asm/c128/stubs_noasm.go new file mode 100644 index 00000000..bf373612 --- /dev/null +++ b/internal/asm/c128/stubs_noasm.go @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package c128 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha complex128, x, y []complex128) { + for i, v := range x { + y[i] += alpha * v + } +} + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []complex128, alpha complex128, x, y []complex128) { + for i, v := range x { + dst[i] = alpha*v + y[i] + } +} + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []complex128, incDst, idst uintptr, alpha complex128, x, y []complex128, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} diff --git a/internal/asm/c128/stubs_test.go b/internal/asm/c128/stubs_test.go new file mode 100644 index 00000000..2c739045 --- /dev/null +++ b/internal/asm/c128/stubs_test.go @@ -0,0 +1,231 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c128 + +import "testing" + +var tests = []struct { + incX, incY, incDst int + ix, iy, idst uintptr + a complex128 + dst, x, y []complex128 + ex []complex128 +}{ + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 1i, + dst: []complex128{5}, + x: []complex128{1}, + y: []complex128{1i}, + ex: []complex128{1 + 2i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex128{0, 0, 0}, + x: []complex128{0, 0, 0}, + y: []complex128{1, 1, 1}, + ex: []complex128{1, 1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex128{0, 0, 0}, + x: []complex128{0, 0}, + y: []complex128{1, 1, 1}, + ex: []complex128{1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex128{1i, 1i, 1i}, + x: []complex128{1i, 1i, 1i}, + y: []complex128{1, 2, 1}, + ex: []complex128{-1 + 1i, 1i, -1 + 1i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1i, + dst: []complex128{1i, 1i, 1i}, + x: []complex128{1i, 1i, 1i}, + y: []complex128{1, 2, 1}, + ex: []complex128{2, 3, 2}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1i, + dst: []complex128{1i, 1i, 1i}, + x: []complex128{1i, 1i, 1i, 1i, 1i}[1:4], + y: []complex128{1, 1, 2, 1, 1}[1:4], + ex: []complex128{2, 3, 2}}, + {incX: 2, incY: 4, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -2, + dst: []complex128{1i, 1i, 1i, 1i, 1i}, + x: []complex128{2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i}, + y: []complex128{1, 1, 2, 1, 1}, + ex: []complex128{-3 - 2i, -3 - 2i, -2 - 2i, -3 - 2i, -3 - 2i}}, + // Run big test twice, once aligned once unaligned. + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 - 1i, + dst: make([]complex128, 10), + x: []complex128{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex128{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex128{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 - 1i, + dst: make([]complex128, 10), + x: []complex128{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex128{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex128{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: -2, incY: -2, incDst: -3, ix: 18, iy: 18, idst: 27, + a: 1 - 1i, + dst: make([]complex128, 10), + x: []complex128{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex128{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex128{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: -2, incY: 2, incDst: -3, ix: 18, iy: 0, idst: 27, + a: 1 - 1i, + dst: make([]complex128, 10), + x: []complex128{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex128{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex128{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, +} + +func guardVector(vec []complex128, guard_val complex128, guard_len int) (guarded []complex128) { + guarded = make([]complex128, len(vec)+guard_len*2) + copy(guarded[guard_len:], vec) + for i := 0; i < guard_len; i++ { + guarded[i] = guard_val + guarded[len(guarded)-1-i] = guard_val + } + return guarded +} + +func isValidGuard(vec []complex128, guard_val complex128, guard_len int) bool { + for i := 0; i < guard_len; i++ { + if vec[i] != guard_val || vec[len(vec)-1-i] != guard_val { + return false + } + } + return true +} + +func TestAxpyUnitary(t *testing.T) { + var x_gd, y_gd complex128 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyUnitary(test.a, x, y) + for i := range test.ex { + if y[i] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + } +} + +func TestAxpyUnitaryTo(t *testing.T) { + var x_gd, y_gd, dst_gd complex128 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + test.dst = guardVector(test.dst, dst_gd, xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyUnitaryTo(dst, test.a, x, y) + for i := range test.ex { + if dst[i] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + if !isValidGuard(test.dst, dst_gd, xg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", cas, test.dst[:xg_ln], test.dst[len(test.dst)-xg_ln:]) + } + + } +} + +func guardIncVector(vec []complex128, guard_val complex128, incV uintptr, guard_len int) (guarded []complex128) { + inc := int(incV) + s_ln := len(vec) * inc + if inc < 0 { + s_ln = len(vec) * -inc + } + guarded = make([]complex128, s_ln+guard_len*2) + for i, cas := 0, 0; i < len(guarded); i++ { + switch { + case i < guard_len, i > guard_len+s_ln: + guarded[i] = guard_val + case (i-guard_len)%(inc) == 0 && cas < len(vec): + guarded[i] = vec[cas] + cas++ + default: + guarded[i] = guard_val + } + } + return guarded +} + +func checkValidIncGuard(t *testing.T, vec []complex128, guard_val complex128, incV uintptr, guard_len int) { + inc := int(incV) + s_ln := len(vec) - 2*guard_len + if inc < 0 { + s_ln = len(vec) * -inc + } + + for i := range vec { + switch { + case vec[i] == guard_val: + // Correct value + case i < guard_len: + t.Errorf("Front guard violated at %d %v", i, vec[:guard_len]) + case i > guard_len+s_ln: + t.Errorf("Back guard violated at %d %v", i-guard_len-s_ln, vec[guard_len+s_ln:]) + case (i-guard_len)%inc == 0 && (i-guard_len)/inc < len(vec): + // Ignore input values + default: + t.Errorf("Internal guard violated at %d %v", i-guard_len, vec[guard_len:guard_len+s_ln]) + } + } +} + +func TestAxpyInc(t *testing.T) { + var x_gd, y_gd complex128 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyInc(test.a, x, y, uintptr(len(test.ex)), uintptr(test.incX), uintptr(test.incY), test.ix, test.iy) + for i := range test.ex { + if y[int(test.iy)+i*int(test.incY)] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i*int(test.incY)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + } +} + +func TestAxpyIncTo(t *testing.T) { + var x_gd, y_gd, dst_gd complex128 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + test.dst = guardIncVector(test.dst, dst_gd, uintptr(test.incDst), xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyIncTo(dst, uintptr(test.incDst), test.idst, test.a, x, y, uintptr(len(test.ex)), uintptr(test.incX), uintptr(test.incY), test.ix, test.iy) + for i := range test.ex { + if dst[int(test.idst)+i*int(test.incDst)] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i*int(test.incDst)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + checkValidIncGuard(t, test.dst, dst_gd, uintptr(test.incDst), xg_ln) + } +} diff --git a/internal/asm/c64/axpyinc_amd64.s b/internal/asm/c64/axpyinc_amd64.s new file mode 100644 index 00000000..82c28862 --- /dev/null +++ b/internal/asm/c64/axpyinc_amd64.s @@ -0,0 +1,151 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVSHDUP X3, X2 +#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 +// MOVSLDUP X3, X3 +#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB +// ADDSUBPS X2, X3 +#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA + +// MOVSHDUP X5, X4 +#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 +// MOVSLDUP X5, X5 +#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED +// ADDSUBPS X4, X5 +#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC + +// MOVSHDUP X7, X6 +#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 +// MOVSLDUP X7, X7 +#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF +// ADDSUBPS X6, X7 +#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE + +// MOVSHDUP X9, X8 +#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 +// MOVSLDUP X9, X9 +#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 +// ADDSUBPS X8, X9 +#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyInc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyInc(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SI // SI = &x + MOVQ y_base+32(FP), DI // DI = &y + MOVQ n+56(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JE axpyi_end + MOVQ ix+80(FP), R8 // R8 = ix + MOVQ iy+88(FP), R9 // R9 = iy + LEAQ (SI)(R8*8), SI // SI = &(x[ix]) + LEAQ (DI)(R9*8), DI // DI = &(y[iy]) + MOVQ DI, DX // DX = DI // Read/Write pointers + MOVQ incX+64(FP), R8 // R8 = incX + SHLQ $3, R8 // R8 *= sizeof(complex64) + MOVQ incY+72(FP), R9 // R9 = incY + SHLQ $3, R9 // R9 *= sizeof(complex64) + MOVSD alpha+0(FP), X0 // X0 = { 0, 0, imag(a), real(a) } + MOVAPS X0, X1 + SHUFPS $0x11, X1, X1 // X1 = { 0, 0, real(a), imag(a) } + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ axpyi_tail // if BX == 0 { goto axpyi_tail } + +axpyi_loop: // do { + MOVSD (SI), X3 // X_i = { imag(x[i+1]), real(x[i+1]) } + MOVSD (SI)(R8*1), X5 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVSD (SI), X7 + MOVSD (SI)(R8*1), X9 + + // X_(i-1) = { imag(x[i]), imag(x[i]) } + MOVSHDUP_X3_X2 + MOVSHDUP_X5_X4 + MOVSHDUP_X7_X6 + MOVSHDUP_X9_X8 + + // X_i = { real(x[i]), real(x[i]) } + MOVSLDUP_X3_X3 + MOVSLDUP_X5_X5 + MOVSLDUP_X7_X7 + MOVSLDUP_X9_X9 + + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPS X1, X2 + MULPS X0, X3 + MULPS X11, X4 + MULPS X10, X5 + MULPS X1, X6 + MULPS X0, X7 + MULPS X11, X8 + MULPS X10, X9 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + MOVSD (DX), X2 + MOVSD (DX)(R9*1), X4 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + MOVSD (DX), X6 + MOVSD (DX)(R9*1), X8 + ADDPS X2, X3 + ADDPS X4, X5 + ADDPS X6, X7 + ADDPS X8, X9 + + MOVSD X3, (DI) // y[i] = X_i + MOVSD X5, (DI)(R9*1) + LEAQ (DI)(R9*2), DI // DI = &(DI[incDst]) + MOVSD X7, (DI) + MOVSD X9, (DI)(R9*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R9*2), DI // DI = &(DI[incDst]) + DECQ BX + JNZ axpyi_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE axpyi_end + +axpyi_tail: // do { + MOVSD (SI), X3 // X_i = { imag(x[i+1]), real(x[i+1]) } + MOVSHDUP_X3_X2 // X_(i-1) = { real(x[i]), real(x[i]) } + MOVSLDUP_X3_X3 // X_i = { imag(x[i]), imag(x[i]) } + + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X1, X2 + MULPS X0, X3 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // } + ADDSUBPS_X2_X3 // (ai*x1r+ar*x1i, ar*x1r-ai*x1i) + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + MOVSD (DI), X4 + ADDPS X4, X3 + MOVSD X3, (DI) // y[i] = X_i + ADDQ R8, SI // SI += incX + ADDQ R9, DI // DI += incY + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET diff --git a/internal/asm/c64/axpyincto_amd64.s b/internal/asm/c64/axpyincto_amd64.s new file mode 100644 index 00000000..9fdc3ef3 --- /dev/null +++ b/internal/asm/c64/axpyincto_amd64.s @@ -0,0 +1,156 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVSHDUP X3, X2 +#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 +// MOVSLDUP X3, X3 +#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB +// ADDSUBPS X2, X3 +#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA + +// MOVSHDUP X5, X4 +#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 +// MOVSLDUP X5, X5 +#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED +// ADDSUBPS X4, X5 +#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC + +// MOVSHDUP X7, X6 +#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 +// MOVSLDUP X7, X7 +#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF +// ADDSUBPS X6, X7 +#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE + +// MOVSHDUP X9, X8 +#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 +// MOVSLDUP X9, X9 +#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 +// ADDSUBPS X8, X9 +#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyIncTo(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyIncTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+48(FP), SI // SI = &x + MOVQ y_base+72(FP), DX // DX = &y + MOVQ n+96(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JE axpyi_end + MOVQ ix+120(FP), R8 // Load the first index + MOVQ iy+128(FP), R9 + MOVQ idst+32(FP), R10 + LEAQ (SI)(R8*8), SI // SI = &(x[ix]) + LEAQ (DX)(R9*8), DX // DX = &(y[iy]) + LEAQ (DI)(R10*8), DI // DI = &(dst[idst]) + MOVQ incX+104(FP), R8 // Incrementors*8 for easy iteration (ADDQ) + SHLQ $3, R8 + MOVQ incY+112(FP), R9 + SHLQ $3, R9 + MOVQ incDst+24(FP), R10 + SHLQ $3, R10 + MOVSD alpha+40(FP), X0 // X0 = { 0, 0, imag(a), real(a) } + MOVAPS X0, X1 + SHUFPS $0x11, X1, X1 // X1 = { 0, 0, real(a), imag(a) } + MOVAPS X0, X10 // Copy X0 and X1 for pipelining + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $3, CX // CX = n % 4 + SHRQ $2, BX // BX = floor( n / 4 ) + JZ axpyi_tail // if BX == 0 { goto axpyi_tail } + +axpyi_loop: // do { + MOVSD (SI), X3 // X_i = { imag(x[i]), real(x[i]) } + MOVSD (SI)(R8*1), X5 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVSD (SI), X7 + MOVSD (SI)(R8*1), X9 + + // X_(i-1) = { imag(x[i]), imag(x[i]) } + MOVSHDUP_X3_X2 + MOVSHDUP_X5_X4 + MOVSHDUP_X7_X6 + MOVSHDUP_X9_X8 + + // X_i = { real(x[i]), real(x[i]) } + MOVSLDUP_X3_X3 + MOVSLDUP_X5_X5 + MOVSLDUP_X7_X7 + MOVSLDUP_X9_X9 + + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } + MULPS X1, X2 + MULPS X0, X3 + MULPS X11, X4 + MULPS X10, X5 + MULPS X1, X6 + MULPS X0, X7 + MULPS X11, X8 + MULPS X10, X9 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + MOVSD (DX), X2 + MOVSD (DX)(R9*1), X4 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + MOVSD (DX), X6 + MOVSD (DX)(R9*1), X8 + ADDPS X2, X3 + ADDPS X4, X5 + ADDPS X6, X7 + ADDPS X8, X9 + + MOVSD X3, (DI) // y[i] = X_i + MOVSD X5, (DI)(R10*1) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst]) + MOVSD X7, (DI) + MOVSD X9, (DI)(R10*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst]) + DECQ BX + JNZ axpyi_loop // } while --BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE axpyi_end + +axpyi_tail: + MOVSD (SI), X3 // X_i = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X_(i-1) = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X_i = { real(x[i]), real(x[i]) } + + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]) } + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X1, X2 + MULPS X0, X3 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // } + ADDSUBPS_X2_X3 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]) } + MOVSD (DX), X4 + ADDPS X4, X3 + MOVSD X3, (DI) // y[i] = X_i + ADDQ R8, SI // SI += incX + ADDQ R9, DX // DX += incY + ADDQ R10, DI // DI += incDst + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET diff --git a/internal/asm/c64/axpyunitary_amd64.s b/internal/asm/c64/axpyunitary_amd64.s new file mode 100644 index 00000000..807a1c42 --- /dev/null +++ b/internal/asm/c64/axpyunitary_amd64.s @@ -0,0 +1,160 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVSHDUP X3, X2 +#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 +// MOVSLDUP X3, X3 +#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB +// ADDSUBPS X2, X3 +#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA + +// MOVSHDUP X5, X4 +#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 +// MOVSLDUP X5, X5 +#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED +// ADDSUBPS X4, X5 +#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC + +// MOVSHDUP X7, X6 +#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 +// MOVSLDUP X7, X7 +#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF +// ADDSUBPS X6, X7 +#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE + +// MOVSHDUP X9, X8 +#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 +// MOVSLDUP X9, X9 +#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 +// ADDSUBPS X8, X9 +#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyUnitary(alpha complex64, x, y []complex64) +TEXT ·AxpyUnitary(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SI // SI = &x + MOVQ y_base+32(FP), DI // DI = &y + MOVQ x_len+16(FP), CX // CX = min( len(x), len(y) ) + CMPQ y_len+40(FP), CX + CMOVQLE y_len+40(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + PXOR X0, X0 // Clear work registers and cache-align loop + PXOR X1, X1 + MOVSD alpha+0(FP), X0 // X0 = { 0, 0, imag(a), real(a) } + SHUFPD $0, X0, X0 // X0 = { imag(a), real(a), imag(a), real(a) } + MOVAPS X0, X1 + SHUFPS $0x11, X1, X1 // X1 = { real(a), imag(a), real(a), imag(a) } + XORQ AX, AX // i = 0 + MOVQ DI, BX // Align on 16-byte boundary for ADDPS + ANDQ $15, BX // BX = &y & 15 + JZ caxy_no_trim // if BX == 0 { goto caxy_no_trim } + + // Trim first value in unaligned buffer + XORPS X2, X2 // Clear work registers and cache-align loop + XORPS X3, X3 + XORPS X4, X4 + MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } + MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), real(a)*real(x[i]) - imag(a)*imag(x[i]) } + ADDSUBPS_X2_X3 + MOVSD (DI)(AX*8), X4 // X3 += y[i] + ADDPS X4, X3 + MOVSD X3, (DI)(AX*8) // y[i] = X3 + INCQ AX // i++ + DECQ CX // --CX + JZ caxy_end // if CX == 0 { return } + +caxy_no_trim: + MOVAPS X0, X10 // Copy X0 and X1 for pipelineing + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $7, CX // CX = n % 8 + SHRQ $3, BX // BX = floor( n / 8 ) + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_loop: // do { + // X_i = { imag(x[i]), real(x[i]), imag(x[i+1]), real(x[i+1]) } + MOVUPS (SI)(AX*8), X3 + MOVUPS 16(SI)(AX*8), X5 + MOVUPS 32(SI)(AX*8), X7 + MOVUPS 48(SI)(AX*8), X9 + + // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } + MOVSHDUP_X3_X2 + MOVSHDUP_X5_X4 + MOVSHDUP_X7_X6 + MOVSHDUP_X9_X8 + + // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } + MOVSLDUP_X3_X3 + MOVSLDUP_X5_X5 + MOVSLDUP_X7_X7 + MOVSLDUP_X9_X9 + + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]), + // imag(a) * real(x[i+1]), real(a) * real(x[i+1]) } + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]), + // real(a) * imag(x[i+1]), imag(a) * imag(x[i+1]) } + MULPS X1, X2 + MULPS X0, X3 + MULPS X11, X4 + MULPS X10, X5 + MULPS X1, X6 + MULPS X0, X7 + MULPS X11, X8 + MULPS X10, X9 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // imag(result[i+1]): imag(a)*real(x[i+1]) + real(a)*imag(x[i+1]), + // real(result[i+1]): real(a)*real(x[i+1]) - imag(a)*imag(x[i+1]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]), + // imag(result[i+1]) + imag(y[i+1]), real(result[i+1]) + real(y[i+1]) } + ADDPS (DI)(AX*8), X3 + ADDPS 16(DI)(AX*8), X5 + ADDPS 32(DI)(AX*8), X7 + ADDPS 48(DI)(AX*8), X9 + MOVUPS X3, (DI)(AX*8) // y[i:i+1] = X_i + MOVUPS X5, 16(DI)(AX*8) + MOVUPS X7, 32(DI)(AX*8) + MOVUPS X9, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + DECQ BX // --BX + JNZ caxy_loop // } while BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + +caxy_tail: // do { + MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } + MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(a)*real(x[i]) - imag(a)*imag(x[i]) } + ADDSUBPS_X2_X3 + MOVSD (DI)(AX*8), X4 // X3 += y[i] + ADDPS X4, X3 + MOVSD X3, (DI)(AX*8) // y[i] = X3 + INCQ AX // ++i + LOOP caxy_tail // } while --CX > 0 + +caxy_end: + RET diff --git a/internal/asm/c64/axpyunitaryto_amd64.s b/internal/asm/c64/axpyunitaryto_amd64.s new file mode 100644 index 00000000..ed5a8c93 --- /dev/null +++ b/internal/asm/c64/axpyunitaryto_amd64.s @@ -0,0 +1,157 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// MOVSHDUP X3, X2 +#define MOVSHDUP_X3_X2 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xD3 +// MOVSLDUP X3, X3 +#define MOVSLDUP_X3_X3 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xDB +// ADDSUBPS X2, X3 +#define ADDSUBPS_X2_X3 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xDA + +// MOVSHDUP X5, X4 +#define MOVSHDUP_X5_X4 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xE5 +// MOVSLDUP X5, X5 +#define MOVSLDUP_X5_X5 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xED +// ADDSUBPS X4, X5 +#define ADDSUBPS_X4_X5 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xEC + +// MOVSHDUP X7, X6 +#define MOVSHDUP_X7_X6 BYTE $0xF3; BYTE $0x0F; BYTE $0x16; BYTE $0xF7 +// MOVSLDUP X7, X7 +#define MOVSLDUP_X7_X7 BYTE $0xF3; BYTE $0x0F; BYTE $0x12; BYTE $0xFF +// ADDSUBPS X6, X7 +#define ADDSUBPS_X6_X7 BYTE $0xF2; BYTE $0x0F; BYTE $0xD0; BYTE $0xFE + +// MOVSHDUP X9, X8 +#define MOVSHDUP_X9_X8 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x16; BYTE $0xC1 +// MOVSLDUP X9, X9 +#define MOVSLDUP_X9_X9 BYTE $0xF3; BYTE $0x45; BYTE $0x0F; BYTE $0x12; BYTE $0xC9 +// ADDSUBPS X8, X9 +#define ADDSUBPS_X8_X9 BYTE $0xF2; BYTE $0x45; BYTE $0x0F; BYTE $0xD0; BYTE $0xC8 + +// func AxpyUnitaryTo(dst []complex64, alpha complex64, x, y []complex64) +TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+32(FP), SI // SI = &x + MOVQ y_base+56(FP), DX // DX = &y + MOVQ x_len+40(FP), CX + CMPQ y_len+64(FP), CX // CX = min( len(x), len(y), len(dst) ) + CMOVQLE y_len+64(FP), CX + CMPQ dst_len+8(FP), CX + CMOVQLE dst_len+8(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + MOVSD alpha+24(FP), X0 // X0 = { 0, 0, imag(a), real(a) } + SHUFPD $0, X0, X0 // X0 = { imag(a), real(a), imag(a), real(a) } + MOVAPS X0, X1 + SHUFPS $0x11, X1, X1 // X1 = { real(a), imag(a), real(a), imag(a) } + XORQ AX, AX // i = 0 + MOVQ DX, BX // Align on 16-byte boundary for ADDPS + ANDQ $15, BX // BX = &y & 15 + JZ caxy_no_trim // if BX == 0 { goto caxy_no_trim } + + MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } + MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), real(a)*real(x[i]) - imag(a)*imag(x[i]) } + ADDSUBPS_X2_X3 + MOVSD (DX)(AX*8), X4 // X3 += y[i] + ADDPS X4, X3 + MOVSD X3, (DI)(AX*8) // dst[i] = X3 + INCQ AX // i++ + DECQ CX // --CX + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_no_trim: + MOVAPS X0, X10 // Copy X0 and X1 for pipelineing + MOVAPS X1, X11 + MOVQ CX, BX + ANDQ $7, CX // CX = n % 8 + SHRQ $3, BX // BX = floor( n / 8 ) + JZ caxy_tail // if BX == 0 { goto caxy_tail } + +caxy_loop: + // X_i = { imag(x[i]), real(x[i]), imag(x[i+1]), real(x[i+1]) } + MOVUPS (SI)(AX*8), X3 + MOVUPS 16(SI)(AX*8), X5 + MOVUPS 32(SI)(AX*8), X7 + MOVUPS 48(SI)(AX*8), X9 + + // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } + MOVSHDUP_X3_X2 + MOVSHDUP_X5_X4 + MOVSHDUP_X7_X6 + MOVSHDUP_X9_X8 + + // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } + MOVSLDUP_X3_X3 + MOVSLDUP_X5_X5 + MOVSLDUP_X7_X7 + MOVSLDUP_X9_X9 + + // X_i = { imag(a) * real(x[i]), real(a) * real(x[i]), + // imag(a) * real(x[i+1]), real(a) * real(x[i+1]) } + // X_(i-1) = { real(a) * imag(x[i]), imag(a) * imag(x[i]), + // real(a) * imag(x[i+1]), imag(a) * imag(x[i+1]) } + MULPS X1, X2 + MULPS X0, X3 + MULPS X11, X4 + MULPS X10, X5 + MULPS X1, X6 + MULPS X0, X7 + MULPS X11, X8 + MULPS X10, X9 + + // X_i = { + // imag(result[i]): imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(result[i]): real(a)*real(x[i]) - imag(a)*imag(x[i]), + // imag(result[i+1]): imag(a)*real(x[i+1]) + real(a)*imag(x[i+1]), + // real(result[i+1]): real(a)*real(x[i+1]) - imag(a)*imag(x[i+1]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // X_i = { imag(result[i]) + imag(y[i]), real(result[i]) + real(y[i]), + // imag(result[i+1]) + imag(y[i+1]), real(result[i+1]) + real(y[i+1]) } + ADDPS (DX)(AX*8), X3 + ADDPS 16(DX)(AX*8), X5 + ADDPS 32(DX)(AX*8), X7 + ADDPS 48(DX)(AX*8), X9 + MOVUPS X3, (DI)(AX*8) // y[i:i+1] = X_i + MOVUPS X5, 16(DI)(AX*8) + MOVUPS X7, 32(DI)(AX*8) + MOVUPS X9, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + DECQ BX // --BX + JNZ caxy_loop // } while BX > 0 + CMPQ CX, $0 // if CX == 0 { return } + JE caxy_end + +caxy_tail: // do { + MOVSD (SI)(AX*8), X3 // X3 = { imag(x[i]), real(x[i]) } + MOVSHDUP_X3_X2 // X2 = { imag(x[i]), imag(x[i]) } + MOVSLDUP_X3_X3 // X3 = { real(x[i]), real(x[i]) } + MULPS X1, X2 // X2 = { real(a) * imag(x[i]), imag(a) * imag(x[i]) } + MULPS X0, X3 // X3 = { imag(a) * real(x[i]), real(a) * real(x[i]) } + + // X3 = { imag(a)*real(x[i]) + real(a)*imag(x[i]), + // real(a)*real(x[i]) - imag(a)*imag(x[i]) } + ADDSUBPS_X2_X3 + MOVSD (DX)(AX*8), X4 // X3 += y[i] + ADDPS X4, X3 + MOVSD X3, (DI)(AX*8) // y[i] = X3 + INCQ AX // ++i + LOOP caxy_tail // } while --CX > 0 + +caxy_end: + RET diff --git a/internal/asm/c64/bench_test.go b/internal/asm/c64/bench_test.go new file mode 100644 index 00000000..0b7b5b83 --- /dev/null +++ b/internal/asm/c64/bench_test.go @@ -0,0 +1,282 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c64 + +import "testing" + +var ( + a = complex64(2 + 2i) + x = make([]complex64, 1000000) + y = make([]complex64, 1000000) + z = make([]complex64, 1000000) +) + +func init() { + for n := range x { + x[n] = complex(float32(n), float32(n)) + y[n] = complex(float32(n), float32(n)) + } +} + +func benchaxpyu(t *testing.B, n int, f func(a complex64, x, y []complex64)) { + x, y := x[:n], y[:n] + for i := 0; i < t.N; i++ { + f(a, x, y) + } +} + +func naiveaxpyu(a complex64, x, y []complex64) { + for i, v := range x { + y[i] += a * v + } +} + +func BenchmarkC64AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, AxpyUnitary) } +func BenchmarkC64AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, AxpyUnitary) } +func BenchmarkC64AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, AxpyUnitary) } +func BenchmarkC64AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, AxpyUnitary) } +func BenchmarkC64AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, AxpyUnitary) } +func BenchmarkC64AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, AxpyUnitary) } +func BenchmarkC64AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, AxpyUnitary) } +func BenchmarkC64AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, AxpyUnitary) } +func BenchmarkC64AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, AxpyUnitary) } +func BenchmarkC64AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, AxpyUnitary) } +func BenchmarkC64AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, AxpyUnitary) } + +func BenchmarkLC64AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, naiveaxpyu) } +func BenchmarkLC64AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, naiveaxpyu) } + +func benchaxpyut(t *testing.B, n int, f func(d []complex64, a complex64, x, y []complex64)) { + x, y, z := x[:n], y[:n], z[:n] + for i := 0; i < t.N; i++ { + f(z, a, x, y) + } +} + +func naiveaxpyut(d []complex64, a complex64, x, y []complex64) { + for i, v := range x { + d[i] = y[i] + a*v + } +} + +func BenchmarkC64AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, AxpyUnitaryTo) } +func BenchmarkC64AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, AxpyUnitaryTo) } + +func BenchmarkLC64AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, naiveaxpyut) } +func BenchmarkLC64AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, naiveaxpyut) } + +func benchaxpyinc(t *testing.B, ln, t_inc int, f func(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(1+1i, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyinc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +func BenchmarkC64AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, AxpyInc) } + +func BenchmarkC64AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, AxpyInc) } +func BenchmarkC64AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, AxpyInc) } +func BenchmarkC64AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, AxpyInc) } +func BenchmarkC64AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, AxpyInc) } +func BenchmarkC64AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, AxpyInc) } +func BenchmarkC64AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, AxpyInc) } +func BenchmarkC64AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, AxpyInc) } +func BenchmarkC64AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, AxpyInc) } +func BenchmarkC64AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, AxpyInc) } +func BenchmarkC64AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, AxpyInc) } +func BenchmarkC64AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, AxpyInc) } +func BenchmarkC64AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, AxpyInc) } +func BenchmarkC64AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, AxpyInc) } +func BenchmarkC64AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, AxpyInc) } +func BenchmarkC64AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, AxpyInc) } +func BenchmarkC64AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, AxpyInc) } +func BenchmarkC64AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, AxpyInc) } +func BenchmarkC64AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, AxpyInc) } +func BenchmarkC64AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, AxpyInc) } + +func BenchmarkC64AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, AxpyInc) } +func BenchmarkC64AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, AxpyInc) } +func BenchmarkC64AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, AxpyInc) } +func BenchmarkC64AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, AxpyInc) } + +func BenchmarkLC64AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, naiveaxpyinc) } + +func BenchmarkLC64AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, naiveaxpyinc) } +func BenchmarkLC64AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, naiveaxpyinc) } + +func benchaxpyincto(t *testing.B, ln, t_inc int, f func(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(z, inc, uintptr(idx), 1+1i, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyincto(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} + +func BenchmarkC64AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, AxpyIncTo) } + +func BenchmarkC64AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, AxpyIncTo) } +func BenchmarkC64AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, AxpyIncTo) } + +func BenchmarkLC64AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, naiveaxpyincto) } + +func BenchmarkLC64AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, naiveaxpyincto) } +func BenchmarkLC64AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, naiveaxpyincto) } diff --git a/internal/asm/c64/conj.go b/internal/asm/c64/conj.go new file mode 100644 index 00000000..932be953 --- /dev/null +++ b/internal/asm/c64/conj.go @@ -0,0 +1,7 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c64 + +func conj(c complex64) complex64 { return complex(real(c), -imag(c)) } diff --git a/internal/asm/c64/doc.go b/internal/asm/c64/doc.go new file mode 100644 index 00000000..9e524a89 --- /dev/null +++ b/internal/asm/c64/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package c64 provides complex64 vector primitives. +package c64 diff --git a/internal/asm/c64/dotc.go b/internal/asm/c64/dotc.go new file mode 100644 index 00000000..cd5b862b --- /dev/null +++ b/internal/asm/c64/dotc.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c64 + +// DotcUnitary is +// for i, v := range x { +// sum += y[i] * conj(v) +// } +// return sum +func DotcUnitary(x, y []complex64) (sum complex64) { + for i, v := range x { + sum += y[i] * conj(v) + } + return sum +} + +// DotcInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * conj(x[ix]) +// ix += incX +// iy += incY +// } +// return sum +func DotcInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) { + for i := 0; i < int(n); i++ { + sum += y[iy] * conj(x[ix]) + ix += incX + iy += incY + } + return sum +} diff --git a/internal/asm/c64/dotu.go b/internal/asm/c64/dotu.go new file mode 100644 index 00000000..ff15d659 --- /dev/null +++ b/internal/asm/c64/dotu.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c64 + +// DotuUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotuUnitary(x, y []complex64) (sum complex64) { + for i, v := range x { + sum += y[i] * v + } + return sum +} + +// DotuInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotuInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) { + for i := 0; i < int(n); i++ { + sum += y[iy] * x[ix] + ix += incX + iy += incY + } + return sum +} diff --git a/internal/asm/c64/scal.go b/internal/asm/c64/scal.go new file mode 100644 index 00000000..11212813 --- /dev/null +++ b/internal/asm/c64/scal.go @@ -0,0 +1,55 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c64 + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha complex64, x []complex64) { + for i := range x { + x[i] *= alpha + } +} + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []complex64, alpha complex64, x []complex64) { + for i, v := range x { + dst[i] = alpha * v + } +} + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha complex64, x []complex64, n, incX uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] *= alpha + ix += incX + } +} + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []complex64, incDst uintptr, alpha complex64, x []complex64, n, incX uintptr) { + var idst, ix uintptr + for i := 0; i < int(n); i++ { + dst[idst] = alpha * x[ix] + ix += incX + idst += incDst + } +} diff --git a/internal/asm/c64/stubs_amd64.go b/internal/asm/c64/stubs_amd64.go new file mode 100644 index 00000000..bd6486c3 --- /dev/null +++ b/internal/asm/c64/stubs_amd64.go @@ -0,0 +1,36 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +package c64 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha complex64, x, y []complex64) + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []complex64, alpha complex64, x, y []complex64) + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) diff --git a/internal/asm/c64/stubs_noasm.go b/internal/asm/c64/stubs_noasm.go new file mode 100644 index 00000000..78aebbd6 --- /dev/null +++ b/internal/asm/c64/stubs_noasm.go @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package c64 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha complex64, x, y []complex64) { + for i, v := range x { + y[i] += alpha * v + } +} + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []complex64, alpha complex64, x, y []complex64) { + for i, v := range x { + dst[i] = alpha*v + y[i] + } +} + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []complex64, incDst, idst uintptr, alpha complex64, x, y []complex64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} diff --git a/internal/asm/c64/stubs_test.go b/internal/asm/c64/stubs_test.go new file mode 100644 index 00000000..8049a763 --- /dev/null +++ b/internal/asm/c64/stubs_test.go @@ -0,0 +1,231 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package c64 + +import "testing" + +var tests = []struct { + incX, incY, incDst int + ix, iy, idst uintptr + a complex64 + dst, x, y []complex64 + ex []complex64 +}{ + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 1i, + dst: []complex64{5}, + x: []complex64{1}, + y: []complex64{1i}, + ex: []complex64{1 + 2i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex64{0, 0, 0}, + x: []complex64{0, 0, 0}, + y: []complex64{1, 1, 1}, + ex: []complex64{1, 1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex64{0, 0, 0}, + x: []complex64{0, 0}, + y: []complex64{1, 1, 1}, + ex: []complex64{1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 + 2i, + dst: []complex64{1i, 1i, 1i}, + x: []complex64{1i, 1i, 1i}, + y: []complex64{1, 2, 1}, + ex: []complex64{-1 + 1i, 1i, -1 + 1i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1i, + dst: []complex64{1i, 1i, 1i}, + x: []complex64{1i, 1i, 1i}, + y: []complex64{1, 2, 1}, + ex: []complex64{2, 3, 2}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1i, + dst: []complex64{1i, 1i, 1i}, + x: []complex64{1i, 1i, 1i, 1i, 1i}[1:4], + y: []complex64{1, 1, 2, 1, 1}[1:4], + ex: []complex64{2, 3, 2}}, + {incX: 2, incY: 4, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -2, + dst: []complex64{1i, 1i, 1i, 1i, 1i}, + x: []complex64{2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i}, + y: []complex64{1, 1, 2, 1, 1}, + ex: []complex64{-3 - 2i, -3 - 2i, -2 - 2i, -3 - 2i, -3 - 2i}}, + // Run big test twice, once aligned once unaligned. + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 - 1i, + dst: make([]complex64, 10), + x: []complex64{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex64{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex64{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 1 - 1i, + dst: make([]complex64, 10), + x: []complex64{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex64{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex64{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: -2, incY: -2, incDst: -3, ix: 18, iy: 18, idst: 27, + a: 1 - 1i, + dst: make([]complex64, 10), + x: []complex64{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex64{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex64{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, + {incX: -2, incY: 2, incDst: -3, ix: 18, iy: 0, idst: 27, + a: 1 - 1i, + dst: make([]complex64, 10), + x: []complex64{1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i, 1i}, + y: []complex64{1, 1, 2, 1, 1, 1, 1, 2, 1, 1}, + ex: []complex64{2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 2 + 1i, 3 + 1i, 2 + 1i, 2 + 1i}}, +} + +func guardVector(vec []complex64, guard_val complex64, guard_len int) (guarded []complex64) { + guarded = make([]complex64, len(vec)+guard_len*2) + copy(guarded[guard_len:], vec) + for i := 0; i < guard_len; i++ { + guarded[i] = guard_val + guarded[len(guarded)-1-i] = guard_val + } + return guarded +} + +func isValidGuard(vec []complex64, guard_val complex64, guard_len int) bool { + for i := 0; i < guard_len; i++ { + if vec[i] != guard_val || vec[len(vec)-1-i] != guard_val { + return false + } + } + return true +} + +func TestAxpyUnitary(t *testing.T) { + var x_gd, y_gd complex64 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyUnitary(test.a, x, y) + for i := range test.ex { + if y[i] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + } +} + +func TestAxpyUnitaryTo(t *testing.T) { + var x_gd, y_gd, dst_gd complex64 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + test.dst = guardVector(test.dst, dst_gd, xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyUnitaryTo(dst, test.a, x, y) + for i := range test.ex { + if dst[i] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + if !isValidGuard(test.dst, dst_gd, xg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", cas, test.dst[:xg_ln], test.dst[len(test.dst)-xg_ln:]) + } + + } +} + +func guardIncVector(vec []complex64, guard_val complex64, incV uintptr, guard_len int) (guarded []complex64) { + inc := int(incV) + s_ln := len(vec) * inc + if inc < 0 { + s_ln = len(vec) * -inc + } + guarded = make([]complex64, s_ln+guard_len*2) + for i, cas := 0, 0; i < len(guarded); i++ { + switch { + case i < guard_len, i > guard_len+s_ln: + guarded[i] = guard_val + case (i-guard_len)%(inc) == 0 && cas < len(vec): + guarded[i] = vec[cas] + cas++ + default: + guarded[i] = guard_val + } + } + return guarded +} + +func checkValidIncGuard(t *testing.T, vec []complex64, guard_val complex64, incV uintptr, guard_len int) { + inc := int(incV) + s_ln := len(vec) - 2*guard_len + if inc < 0 { + s_ln = len(vec) * -inc + } + + for i := range vec { + switch { + case vec[i] == guard_val: + // Correct value + case i < guard_len: + t.Errorf("Front guard violated at %d %v", i, vec[:guard_len]) + case i > guard_len+s_ln: + t.Errorf("Back guard violated at %d %v", i-guard_len-s_ln, vec[guard_len+s_ln:]) + case (i-guard_len)%inc == 0 && (i-guard_len)/inc < len(vec): + // Ignore input values + default: + t.Errorf("Internal guard violated at %d %v", i-guard_len, vec[guard_len:guard_len+s_ln]) + } + } +} + +func TestAxpyInc(t *testing.T) { + var x_gd, y_gd complex64 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyInc(test.a, x, y, uintptr(len(test.ex)), uintptr(test.incX), uintptr(test.incY), test.ix, test.iy) + for i := range test.ex { + if y[int(test.iy)+i*int(test.incY)] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i*int(test.incY)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + } +} + +func TestAxpyIncTo(t *testing.T) { + var x_gd, y_gd, dst_gd complex64 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + test.dst = guardIncVector(test.dst, dst_gd, uintptr(test.incDst), xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyIncTo(dst, uintptr(test.incDst), test.idst, test.a, x, y, uintptr(len(test.ex)), uintptr(test.incX), uintptr(test.incY), test.ix, test.iy) + for i := range test.ex { + if dst[int(test.idst)+i*int(test.incDst)] != test.ex[i] { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i*int(test.incDst)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + checkValidIncGuard(t, test.dst, dst_gd, uintptr(test.incDst), xg_ln) + } +} diff --git a/internal/asm/f32/axpyinc_amd64.s b/internal/asm/f32/axpyinc_amd64.s new file mode 100644 index 00000000..a6462f0e --- /dev/null +++ b/internal/asm/f32/axpyinc_amd64.s @@ -0,0 +1,73 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func AxpyInc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyInc(SB), NOSPLIT, $0 + MOVQ n+56(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JLE axpyi_end + MOVQ x_base+8(FP), SI // SI = &x + MOVQ y_base+32(FP), DI // DI = &y + MOVQ ix+80(FP), R8 // R8 = ix + MOVQ iy+88(FP), R9 // R9 = iy + LEAQ (SI)(R8*4), SI // SI = &(x[ix]) + LEAQ (DI)(R9*4), DI // DI = &(y[iy]) + MOVQ DI, DX // DX = DI Read Pointer for y + MOVQ incX+64(FP), R8 // R8 = incX + SHLQ $2, R8 // R8 *= sizeof(float32) + MOVQ incY+72(FP), R9 // R9 = incY + SHLQ $2, R9 // R9 *= sizeof(float32) + MOVSS alpha+0(FP), X0 // X0 = alpha + MOVSS X0, X1 // X1 = X0 // for pipelining + MOVQ CX, BX + ANDQ $3, BX // BX = n % 4 + SHRQ $2, CX // CX = floor( n / 4 ) + JZ axpyi_tail_start // if CX == 0 { goto axpyi_tail_start } + +axpyi_loop: // Loop unrolled 4x do { + MOVSS (SI), X2 // X_i = x[i] + MOVSS (SI)(R8*1), X3 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVSS (SI), X4 + MOVSS (SI)(R8*1), X5 + MULSS X1, X2 // X_i *= a + MULSS X0, X3 + MULSS X1, X4 + MULSS X0, X5 + ADDSS (DX), X2 // X_i += y[i] + ADDSS (DX)(R9*1), X3 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + ADDSS (DX), X4 + ADDSS (DX)(R9*1), X5 + MOVSS X2, (DI) // y[i] = X_i + MOVSS X3, (DI)(R9*1) + LEAQ (DI)(R9*2), DI // DI = &(DI[incY*2]) + MOVSS X4, (DI) + MOVSS X5, (DI)(R9*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) // Increment addresses + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R9*2), DI // DI = &(DI[incY*2]) + LOOP axpyi_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE axpyi_end + +axpyi_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +axpyi_tail: // do { + MOVSS (SI), X2 // X2 = x[i] + MULSS X1, X2 // X2 *= a + ADDSS (DI), X2 // X2 += y[i] + MOVSS X2, (DI) // y[i] = X2 + ADDQ R8, SI // SI = &(SI[incX]) + ADDQ R9, DI // DI = &(DI[incY]) + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET + diff --git a/internal/asm/f32/axpyincto_amd64.s b/internal/asm/f32/axpyincto_amd64.s new file mode 100644 index 00000000..e1c39e90 --- /dev/null +++ b/internal/asm/f32/axpyincto_amd64.s @@ -0,0 +1,78 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyIncTo(SB), NOSPLIT, $0 + MOVQ n+96(FP), CX // CX = n + CMPQ CX, $0 // if n==0 { return } + JLE axpyi_end + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+48(FP), SI // SI = &x + MOVQ y_base+72(FP), DX // DX = &y + MOVQ ix+120(FP), R8 // R8 = ix // Load the first index + MOVQ iy+128(FP), R9 // R9 = iy + MOVQ idst+32(FP), R10 // R10 = idst + LEAQ (SI)(R8*4), SI // SI = &(x[ix]) + LEAQ (DX)(R9*4), DX // DX = &(y[iy]) + LEAQ (DI)(R10*4), DI // DI = &(dst[idst]) + MOVQ incX+104(FP), R8 // R8 = incX + SHLQ $2, R8 // R8 *= sizeof(float32) + MOVQ incY+112(FP), R9 // R9 = incY + SHLQ $2, R9 // R9 *= sizeof(float32) + MOVQ incDst+24(FP), R10 // R10 = incDst + SHLQ $2, R10 // R10 *= sizeof(float32) + MOVSS alpha+40(FP), X0 // X0 = alpha + MOVSS X0, X1 // X1 = X0 // for pipelining + MOVQ CX, BX + ANDQ $3, BX // BX = n % 4 + SHRQ $2, CX // CX = floor( n / 4 ) + JZ axpyi_tail_start // if CX == 0 { goto axpyi_tail_start } + +axpyi_loop: // Loop unrolled 4x do { + MOVSS (SI), X2 // X_i = x[i] + MOVSS (SI)(R8*1), X3 + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) + MOVSS (SI), X4 + MOVSS (SI)(R8*1), X5 + MULSS X1, X2 // X_i *= a + MULSS X0, X3 + MULSS X1, X4 + MULSS X0, X5 + ADDSS (DX), X2 // X_i += y[i] + ADDSS (DX)(R9*1), X3 + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + ADDSS (DX), X4 + ADDSS (DX)(R9*1), X5 + MOVSS X2, (DI) // dst[i] = X_i + MOVSS X3, (DI)(R10*1) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) + MOVSS X4, (DI) + MOVSS X5, (DI)(R10*1) + LEAQ (SI)(R8*2), SI // SI = &(SI[incX*2]) // Increment addresses + LEAQ (DX)(R9*2), DX // DX = &(DX[incY*2]) + LEAQ (DI)(R10*2), DI // DI = &(DI[incDst*2]) + LOOP axpyi_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE axpyi_end + +axpyi_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +axpyi_tail: // do { + MOVSS (SI), X2 // X2 = x[i] + MULSS X1, X2 // X2 *= a + ADDSS (DX), X2 // X2 += y[i] + MOVSS X2, (DI) // dst[i] = X2 + ADDQ R8, SI // SI = &(SI[incX]) + ADDQ R9, DX // DX = &(DX[incY]) + ADDQ R10, DI // DI = &(DI[incY]) + LOOP axpyi_tail // } while --CX > 0 + +axpyi_end: + RET + diff --git a/internal/asm/f32/axpyunitary_amd64.s b/internal/asm/f32/axpyunitary_amd64.s new file mode 100644 index 00000000..a5bfaac9 --- /dev/null +++ b/internal/asm/f32/axpyunitary_amd64.s @@ -0,0 +1,97 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func AxpyUnitary(alpha float32, x, y []float32) +TEXT ·AxpyUnitary(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SI // SI = &x + MOVQ y_base+32(FP), DI // DI = &y + MOVQ x_len+16(FP), BX // BX = min( len(x), len(y) ) + CMPQ y_len+40(FP), BX + CMOVQLE y_len+40(FP), BX + CMPQ BX, $0 // if BX == 0 { return } + JE axpy_end + MOVSS alpha+0(FP), X0 + SHUFPS $0, X0, X0 // X0 = { a, a, a, a } + XORQ AX, AX // i = 0 + PXOR X2, X2 // 2 NOP instructions (PXOR) to align + PXOR X3, X3 // loop to cache line + MOVQ DI, CX + ANDQ $0xF, CX // Align on 16-byte boundary for ADDPS + JZ axpy_no_trim // if CX == 0 { goto axpy_no_trim } + + XORQ $0xF, CX // CX = 4 - floor( BX % 16 / 4 ) + INCQ CX + SHRQ $2, CX + +axpy_align: // Trim first value(s) in unaligned buffer do { + MOVSS (SI)(AX*4), X2 // X2 = x[i] + MULSS X0, X2 // X2 *= a + ADDSS (DI)(AX*4), X2 // X2 += y[i] + MOVSS X2, (DI)(AX*4) // y[i] = X2 + INCQ AX // i++ + DECQ BX + JZ axpy_end // if --BX == 0 { return } + LOOP axpy_align // } while --CX > 0 + +axpy_no_trim: + MOVUPS X0, X1 // Copy X0 to X1 for pipelining + MOVQ BX, CX + ANDQ $0xF, BX // BX = len % 16 + SHRQ $4, CX // CX = int( len / 16 ) + JZ axpy_tail4_start // if CX == 0 { return } + +axpy_loop: // Loop unrolled 16x do { + MOVUPS (SI)(AX*4), X2 // X2 = x[i:i+4] + MOVUPS 16(SI)(AX*4), X3 + MOVUPS 32(SI)(AX*4), X4 + MOVUPS 48(SI)(AX*4), X5 + MULPS X0, X2 // X2 *= a + MULPS X1, X3 + MULPS X0, X4 + MULPS X1, X5 + ADDPS (DI)(AX*4), X2 // X2 += y[i:i+4] + ADDPS 16(DI)(AX*4), X3 + ADDPS 32(DI)(AX*4), X4 + ADDPS 48(DI)(AX*4), X5 + MOVUPS X2, (DI)(AX*4) // dst[i:i+4] = X2 + MOVUPS X3, 16(DI)(AX*4) + MOVUPS X4, 32(DI)(AX*4) + MOVUPS X5, 48(DI)(AX*4) + ADDQ $16, AX // i += 16 + LOOP axpy_loop // while (--CX) > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE axpy_end + +axpy_tail4_start: // Reset loop counter for 4-wide tail loop + MOVQ BX, CX // CX = floor( BX / 4 ) + SHRQ $2, CX + JZ axpy_tail_start // if CX == 0 { goto axpy_tail_start } + +axpy_tail4: // Loop unrolled 4x do { + MOVUPS (SI)(AX*4), X2 // X2 = x[i] + MULPS X0, X2 // X2 *= a + ADDPS (DI)(AX*4), X2 // X2 += y[i] + MOVUPS X2, (DI)(AX*4) // y[i] = X2 + ADDQ $4, AX // i += 4 + LOOP axpy_tail4 // } while --CX > 0 + +axpy_tail_start: // Reset loop counter for 1-wide tail loop + MOVQ BX, CX // CX = BX % 4 + ANDQ $3, CX + JZ axpy_end // if CX == 0 { return } + +axpy_tail: + MOVSS (SI)(AX*4), X1 // X1 = x[i] + MULSS X0, X1 // X1 *= a + ADDSS (DI)(AX*4), X1 // X1 += y[i] + MOVSS X1, (DI)(AX*4) // y[i] = X1 + INCQ AX // i++ + LOOP axpy_tail // } while --CX > 0 + +axpy_end: + RET diff --git a/internal/asm/f32/axpyunitaryto_amd64.s b/internal/asm/f32/axpyunitaryto_amd64.s new file mode 100644 index 00000000..9a8289f8 --- /dev/null +++ b/internal/asm/f32/axpyunitaryto_amd64.s @@ -0,0 +1,98 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func AxpyUnitaryTo(dst []float32, alpha float32, x, y []float32) +TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ x_base+32(FP), SI // SI = &x + MOVQ y_base+56(FP), DX // DX = &y + MOVQ x_len+40(FP), BX // BX = min( len(x), len(y), len(dst) ) + CMPQ y_len+64(FP), BX + CMOVQLE y_len+64(FP), BX + CMPQ dst_len+8(FP), BX + CMOVQLE dst_len+8(FP), BX + CMPQ BX, $0 // if BX == 0 { return } + JE axpy_end + MOVSS alpha+24(FP), X0 + SHUFPS $0, X0, X0 // X0 = { a, a, a, a, } + XORQ AX, AX // i = 0 + MOVQ DX, CX + ANDQ $0xF, CX // Align on 16-byte boundary for ADDPS + JZ axpy_no_trim // if CX == 0 { goto axpy_no_trim } + + XORQ $0xF, CX // CX = 4 - floor ( B % 16 / 4 ) + INCQ CX + SHRQ $2, CX + +axpy_align: // Trim first value(s) in unaligned buffer do { + MOVSS (SI)(AX*4), X2 // X2 = x[i] + MULSS X0, X2 // X2 *= a + ADDSS (DX)(AX*4), X2 // X2 += y[i] + MOVSS X2, (DI)(AX*4) // y[i] = X2 + INCQ AX // i++ + DECQ BX + JZ axpy_end // if --BX == 0 { return } + LOOP axpy_align // } while --CX > 0 + +axpy_no_trim: + MOVUPS X0, X1 // Copy X0 to X1 for pipelining + MOVQ BX, CX + ANDQ $0xF, BX // BX = len % 16 + SHRQ $4, CX // CX = floor( len / 16 ) + JZ axpy_tail4_start // if CX == 0 { return } + +axpy_loop: // Loop unrolled 16x do { + MOVUPS (SI)(AX*4), X2 // X2 = x[i:i+4] + MOVUPS 16(SI)(AX*4), X3 + MOVUPS 32(SI)(AX*4), X4 + MOVUPS 48(SI)(AX*4), X5 + MULPS X0, X2 // X2 *= a + MULPS X1, X3 + MULPS X0, X4 + MULPS X1, X5 + ADDPS (DX)(AX*4), X2 // X2 += y[i:i+4] + ADDPS 16(DX)(AX*4), X3 + ADDPS 32(DX)(AX*4), X4 + ADDPS 48(DX)(AX*4), X5 + MOVUPS X2, (DI)(AX*4) // dst[i:i+4] = X2 + MOVUPS X3, 16(DI)(AX*4) + MOVUPS X4, 32(DI)(AX*4) + MOVUPS X5, 48(DI)(AX*4) + ADDQ $16, AX // i += 16 + LOOP axpy_loop // while (--CX) > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE axpy_end + +axpy_tail4_start: // Reset loop counter for 4-wide tail loop + MOVQ BX, CX // CX = floor( BX / 4 ) + SHRQ $2, CX + JZ axpy_tail_start // if CX == 0 { goto axpy_tail_start } + +axpy_tail4: // Loop unrolled 4x do { + MOVUPS (SI)(AX*4), X2 // X2 = x[i] + MULPS X0, X2 // X2 *= a + ADDPS (DX)(AX*4), X2 // X2 += y[i] + MOVUPS X2, (DI)(AX*4) // y[i] = X2 + ADDQ $4, AX // i += 4 + LOOP axpy_tail4 // } while --CX > 0 + +axpy_tail_start: // Reset loop counter for 1-wide tail loop + MOVQ BX, CX // CX = BX % 4 + ANDQ $3, CX + JZ axpy_end // if CX == 0 { return } + +axpy_tail: + MOVSS (SI)(AX*4), X1 // X1 = x[i] + MULSS X0, X1 // X1 *= a + ADDSS (DX)(AX*4), X1 // X1 += y[i] + MOVSS X1, (DI)(AX*4) // y[i] = X1 + INCQ AX // i++ + LOOP axpy_tail // } while --CX > 0 + +axpy_end: + RET diff --git a/internal/asm/f32/bench_test.go b/internal/asm/f32/bench_test.go new file mode 100644 index 00000000..a1c415ce --- /dev/null +++ b/internal/asm/f32/bench_test.go @@ -0,0 +1,282 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f32 + +import "testing" + +var ( + a = float32(2) + x = make([]float32, 1000000) + y = make([]float32, 1000000) + z = make([]float32, 1000000) +) + +func init() { + for n := range x { + x[n] = float32(n) + y[n] = float32(n) + } +} + +func benchaxpyu(t *testing.B, n int, f func(a float32, x, y []float32)) { + x, y := x[:n], y[:n] + for i := 0; i < t.N; i++ { + f(a, x, y) + } +} + +func naiveaxpyu(a float32, x, y []float32) { + for i, v := range x { + y[i] += a * v + } +} + +func BenchmarkF32AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, AxpyUnitary) } +func BenchmarkF32AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, AxpyUnitary) } +func BenchmarkF32AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, AxpyUnitary) } +func BenchmarkF32AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, AxpyUnitary) } +func BenchmarkF32AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, AxpyUnitary) } +func BenchmarkF32AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, AxpyUnitary) } +func BenchmarkF32AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, AxpyUnitary) } +func BenchmarkF32AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, AxpyUnitary) } +func BenchmarkF32AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, AxpyUnitary) } +func BenchmarkF32AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, AxpyUnitary) } +func BenchmarkF32AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, AxpyUnitary) } + +func BenchmarkLF32AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, naiveaxpyu) } +func BenchmarkLF32AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, naiveaxpyu) } + +func benchaxpyut(t *testing.B, n int, f func(d []float32, a float32, x, y []float32)) { + x, y, z := x[:n], y[:n], z[:n] + for i := 0; i < t.N; i++ { + f(z, a, x, y) + } +} + +func naiveaxpyut(d []float32, a float32, x, y []float32) { + for i, v := range x { + d[i] = y[i] + a*v + } +} + +func BenchmarkF32AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, AxpyUnitaryTo) } +func BenchmarkF32AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, AxpyUnitaryTo) } + +func BenchmarkLF32AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, naiveaxpyut) } +func BenchmarkLF32AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, naiveaxpyut) } + +func benchaxpyinc(t *testing.B, ln, t_inc int, f func(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(1, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyinc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +func BenchmarkF32AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, AxpyInc) } + +func BenchmarkF32AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, AxpyInc) } +func BenchmarkF32AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, AxpyInc) } +func BenchmarkF32AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, AxpyInc) } +func BenchmarkF32AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, AxpyInc) } +func BenchmarkF32AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, AxpyInc) } +func BenchmarkF32AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, AxpyInc) } +func BenchmarkF32AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, AxpyInc) } +func BenchmarkF32AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, AxpyInc) } +func BenchmarkF32AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, AxpyInc) } +func BenchmarkF32AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, AxpyInc) } +func BenchmarkF32AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, AxpyInc) } +func BenchmarkF32AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, AxpyInc) } +func BenchmarkF32AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, AxpyInc) } +func BenchmarkF32AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, AxpyInc) } +func BenchmarkF32AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, AxpyInc) } +func BenchmarkF32AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, AxpyInc) } +func BenchmarkF32AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, AxpyInc) } +func BenchmarkF32AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, AxpyInc) } +func BenchmarkF32AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, AxpyInc) } + +func BenchmarkF32AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, AxpyInc) } +func BenchmarkF32AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, AxpyInc) } +func BenchmarkF32AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, AxpyInc) } +func BenchmarkF32AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, AxpyInc) } + +func BenchmarkLF32AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, naiveaxpyinc) } + +func BenchmarkLF32AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, naiveaxpyinc) } +func BenchmarkLF32AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, naiveaxpyinc) } + +func benchaxpyincto(t *testing.B, ln, t_inc int, f func(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + for i := 0; i < t.N; i++ { + f(z, inc, uintptr(idx), 1, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyincto(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} + +func BenchmarkF32AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, AxpyIncTo) } + +func BenchmarkF32AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, AxpyIncTo) } +func BenchmarkF32AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, AxpyIncTo) } + +func BenchmarkLF32AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, naiveaxpyincto) } + +func BenchmarkLF32AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, naiveaxpyincto) } +func BenchmarkLF32AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, naiveaxpyincto) } diff --git a/internal/asm/f32/ddot.go b/internal/asm/f32/ddot.go new file mode 100644 index 00000000..6920f659 --- /dev/null +++ b/internal/asm/f32/ddot.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f32 + +// DdotUnitary is +// for i, v := range x { +// sum += float64(y[i]) * float64(v) +// } +// return +func DdotUnitary(x, y []float32) (sum float64) { + for i, v := range x { + sum += float64(y[i]) * float64(v) + } + return +} + +// DdotInc is +// for i := 0; i < int(n); i++ { +// sum += float64(y[iy]) * float64(x[ix]) +// ix += incX +// iy += incY +// } +// return +func DdotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float64) { + for i := 0; i < int(n); i++ { + sum += float64(y[iy]) * float64(x[ix]) + ix += incX + iy += incY + } + return +} diff --git a/internal/asm/f32/doc.go b/internal/asm/f32/doc.go new file mode 100644 index 00000000..e7e1d9f8 --- /dev/null +++ b/internal/asm/f32/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package f32 provides float32 vector primitives. +package f32 diff --git a/internal/asm/f32/dot.go b/internal/asm/f32/dot.go new file mode 100644 index 00000000..7a27d35e --- /dev/null +++ b/internal/asm/f32/dot.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f32 + +// DotUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotUnitary(x, y []float32) (sum float32) { + for i, v := range x { + sum += y[i] * v + } + return sum +} + +// DotInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotInc(x, y []float32, n, incX, incY, ix, iy uintptr) (sum float32) { + for i := 0; i < int(n); i++ { + sum += y[iy] * x[ix] + ix += incX + iy += incY + } + return sum +} diff --git a/internal/asm/f32/scal.go b/internal/asm/f32/scal.go new file mode 100644 index 00000000..c4f61e87 --- /dev/null +++ b/internal/asm/f32/scal.go @@ -0,0 +1,55 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f32 + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha float32, x []float32) { + for i := range x { + x[i] *= alpha + } +} + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []float32, alpha float32, x []float32) { + for i, v := range x { + dst[i] = alpha * v + } +} + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha float32, x []float32, n, incX uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] *= alpha + ix += incX + } +} + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []float32, incDst uintptr, alpha float32, x []float32, n, incX uintptr) { + var idst, ix uintptr + for i := 0; i < int(n); i++ { + dst[idst] = alpha * x[ix] + ix += incX + idst += incDst + } +} diff --git a/internal/asm/f32/stubs_amd64.go b/internal/asm/f32/stubs_amd64.go new file mode 100644 index 00000000..00ad520a --- /dev/null +++ b/internal/asm/f32/stubs_amd64.go @@ -0,0 +1,36 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +package f32 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha float32, x, y []float32) + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []float32, alpha float32, x, y []float32) + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) diff --git a/internal/asm/f32/stubs_noasm.go b/internal/asm/f32/stubs_noasm.go new file mode 100644 index 00000000..a6272ea5 --- /dev/null +++ b/internal/asm/f32/stubs_noasm.go @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f32 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha float32, x, y []float32) { + for i, v := range x { + y[i] += alpha * v + } +} + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []float32, alpha float32, x, y []float32) { + for i, v := range x { + dst[i] = alpha*v + y[i] + } +} + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []float32, incDst, idst uintptr, alpha float32, x, y []float32, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} diff --git a/internal/asm/f32/stubs_test.go b/internal/asm/f32/stubs_test.go new file mode 100644 index 00000000..df7a1421 --- /dev/null +++ b/internal/asm/f32/stubs_test.go @@ -0,0 +1,217 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f32 + +import ( + "math" + "testing" +) + +var ( + nan = float32(math.NaN()) + inf = float32(math.Inf(1)) +) + +var tests = []struct { + incX, incY, incDst uintptr + ix, iy, idst uintptr + a float32 + dst, x, y []float32 + ex []float32 +}{ + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 3, + dst: []float32{5}, + x: []float32{2}, + y: []float32{1}, + ex: []float32{7}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 5, + dst: []float32{0, 0, 0}, + x: []float32{0, 0, 0}, + y: []float32{1, 1, 1}, + ex: []float32{1, 1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 5, + dst: []float32{0, 0, 0}, + x: []float32{0, 0}, + y: []float32{1, 1, 1}, + ex: []float32{1, 1}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1, + dst: []float32{-1, -1, -1}, + x: []float32{1, 1, 1}, + y: []float32{1, 2, 1}, + ex: []float32{0, 1, 0}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: -1, + dst: []float32{1, 1, 1}, + x: []float32{1, 2, 1}, + y: []float32{-1, -2, -1}, + ex: []float32{-2, -4, -2}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 2.5, + dst: []float32{1, 1, 1, 1, 1}, + x: []float32{1, 2, 3, 2, 1}, + y: []float32{0, 0, 0, 0, 0}, + ex: []float32{2.5, 5, 7.5, 5, 2.5}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, // Run big test twice, once aligned once unaligned. + a: 16.5, + dst: make([]float32, 20), + x: []float32{.5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5}, + y: []float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ex: []float32{9.25, 10.25, 11.25, 12.25, 13.25, 14.25, 15.25, 16.25, 17.25, 18.25, 9.25, 10.25, 11.25, 12.25, 13.25, 14.25, 15.25, 16.25, 17.25, 18.25}}, + {incX: 2, incY: 2, incDst: 3, ix: 0, iy: 0, idst: 0, + a: 16.5, + dst: make([]float32, 10), + x: []float32{.5, .5, .5, .5, .5, .5, .5, .5, .5, .5}, + y: []float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + ex: []float32{9.25, 10.25, 11.25, 12.25, 13.25, 14.25, 15.25, 16.25, 17.25, 18.25}}, +} + +func guardVector(vec []float32, guard_val float32, guard_len int) (guarded []float32) { + guarded = make([]float32, len(vec)+guard_len*2) + copy(guarded[guard_len:], vec) + for i := 0; i < guard_len; i++ { + guarded[i] = guard_val + guarded[len(guarded)-1-i] = guard_val + } + return guarded +} + +func isValidGuard(vec []float32, guard_val float32, guard_len int) bool { + for i := 0; i < guard_len; i++ { + if vec[i] != guard_val || vec[len(vec)-1-i] != guard_val { + return false + } + } + return true +} + +func same(x, y float32) bool { + a, b := float64(x), float64(y) + return a == b || (math.IsNaN(a) && math.IsNaN(b)) +} + +func TestAxpyUnitary(t *testing.T) { + var x_gd, y_gd float32 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyUnitary(test.a, x, y) + for i := range test.ex { + if !same(y[i], test.ex[i]) { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + } +} + +func TestAxpyUnitaryTo(t *testing.T) { + var x_gd, y_gd, dst_gd float32 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardVector(test.x, x_gd, xg_ln), guardVector(test.y, y_gd, yg_ln) + test.dst = guardVector(test.dst, dst_gd, xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyUnitaryTo(dst, test.a, x, y) + for i := range test.ex { + if !same(test.ex[i], dst[i]) { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i], test.ex[i]) + } + } + if !isValidGuard(test.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", cas, test.x[:xg_ln], test.x[len(test.x)-xg_ln:]) + } + if !isValidGuard(test.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", cas, test.y[:yg_ln], test.y[len(test.y)-yg_ln:]) + } + if !isValidGuard(test.dst, dst_gd, xg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", cas, test.dst[:xg_ln], test.dst[len(test.dst)-xg_ln:]) + } + } +} + +func guardIncVector(vec []float32, guard_val float32, incV uintptr, guard_len int) (guarded []float32) { + inc := int(incV) + s_ln := len(vec) * (inc) + guarded = make([]float32, s_ln+guard_len*2) + for i, j := 0, 0; i < len(guarded); i++ { + switch { + case i < guard_len, i > guard_len+s_ln: + guarded[i] = guard_val + case (i-guard_len)%(inc) == 0 && j < len(vec): + guarded[i] = vec[j] + j++ + default: + guarded[i] = guard_val + } + } + return guarded +} + +func checkValidIncGuard(t *testing.T, vec []float32, guard_val float32, incV uintptr, guard_len int) { + inc := int(incV) + s_ln := len(vec) - 2*guard_len + for i := range vec { + switch { + case same(vec[i], guard_val): + // Correct value + case i < guard_len: + t.Errorf("Front guard violated at %d %v", i, vec[:guard_len]) + case i > guard_len+s_ln: + t.Errorf("Back guard violated at %d %v", i-guard_len-s_ln, vec[guard_len+s_ln:]) + case (i-guard_len)%inc == 0 && (i-guard_len)/inc < len(vec): + // Ignore input values + default: + t.Errorf("Internal guard violated at %d %v", i-guard_len, vec[guard_len:guard_len+s_ln]) + } + } +} + +func TestAxpyInc(t *testing.T) { + var x_gd, y_gd float32 = 1, 1 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + AxpyInc(test.a, x, y, uintptr(len(test.ex)), test.incX, test.incY, test.ix, test.iy) + for i := range test.ex { + if !same(y[i*int(test.incY)], test.ex[i]) { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, y[i*int(test.incY)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + } +} + +func TestAxpyIncTo(t *testing.T) { + var x_gd, y_gd, dst_gd float32 = 1, 1, 0 + for cas, test := range tests { + xg_ln, yg_ln := 4+cas%2, 4+cas%3 + test.x, test.y = guardIncVector(test.x, x_gd, uintptr(test.incX), xg_ln), guardIncVector(test.y, y_gd, uintptr(test.incY), yg_ln) + test.dst = guardIncVector(test.dst, dst_gd, uintptr(test.incDst), xg_ln) + x, y := test.x[xg_ln:len(test.x)-xg_ln], test.y[yg_ln:len(test.y)-yg_ln] + dst := test.dst[xg_ln : len(test.dst)-xg_ln] + AxpyIncTo(dst, test.incDst, test.idst, test.a, x, y, uintptr(len(test.ex)), test.incX, test.incY, test.ix, test.iy) + for i := range test.ex { + if !same(dst[i*int(test.incDst)], test.ex[i]) { + t.Errorf("Test %d Unexpected result at %d Got: %v Expected: %v", cas, i, dst[i*int(test.incDst)], test.ex[i]) + } + } + checkValidIncGuard(t, test.x, x_gd, uintptr(test.incX), xg_ln) + checkValidIncGuard(t, test.y, y_gd, uintptr(test.incY), yg_ln) + checkValidIncGuard(t, test.dst, dst_gd, uintptr(test.incDst), xg_ln) + } +} diff --git a/internal/asm/f64/abssum_amd64.s b/internal/asm/f64/abssum_amd64.s new file mode 100644 index 00000000..7e7e5d07 --- /dev/null +++ b/internal/asm/f64/abssum_amd64.s @@ -0,0 +1,82 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func L1Norm(x []float64) float64 +TEXT ·L1Norm(SB), NOSPLIT, $0 + MOVQ x_base+0(FP), SI // SI = &x + MOVQ x_len+8(FP), CX // CX = len(x) + XORQ AX, AX // i = 0 + PXOR X0, X0 // p_sum_i = 0 + PXOR X1, X1 + PXOR X2, X2 + PXOR X3, X3 + PXOR X4, X4 + PXOR X5, X5 + PXOR X6, X6 + PXOR X7, X7 + CMPQ CX, $0 // if CX == 0 { return 0 } + JE absum_end + MOVQ CX, BX + ANDQ $7, BX // BX = len(x) % 8 + SHRQ $3, CX // CX = floor( len(x) / 8 ) + JZ absum_tail_start // if CX == 0 { goto absum_tail_start } + +absum_loop: // do { + // p_sum += max( p_sum + x[i], p_sum - x[i] ) + MOVUPS (SI)(AX*8), X8 // X_i = x[i:i+1] + MOVUPS 16(SI)(AX*8), X9 + MOVUPS 32(SI)(AX*8), X10 + MOVUPS 48(SI)(AX*8), X11 + ADDPD X8, X0 // p_sum_i += X_i ( positive values ) + ADDPD X9, X2 + ADDPD X10, X4 + ADDPD X11, X6 + SUBPD X8, X1 // p_sum_(i+1) -= X_i ( negative values ) + SUBPD X9, X3 + SUBPD X10, X5 + SUBPD X11, X7 + MAXPD X1, X0 // p_sum_i = max( p_sum_i, p_sum_(i+1) ) + MAXPD X3, X2 + MAXPD X5, X4 + MAXPD X7, X6 + MOVAPS X0, X1 // p_sum_(i+1) = p_sum_i + MOVAPS X2, X3 + MOVAPS X4, X5 + MOVAPS X6, X7 + ADDQ $8, AX // i += 8 + LOOP absum_loop // } while --CX > 0 + + // p_sum_0 = \sum_{i=1}^{3}( p_sum_(i*2) ) + ADDPD X3, X0 + ADDPD X5, X7 + ADDPD X7, X0 + + // p_sum_0[0] = p_sum_0[0] + p_sum_0[1] + MOVAPS X0, X1 + SHUFPD $0x3, X0, X0 // lower( p_sum_0 ) = upper( p_sum_0 ) + ADDSD X1, X0 + CMPQ BX, $0 + JE absum_end // if BX == 0 { goto absum_end } + +absum_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + XORPS X8, X8 // X_8 = 0 + +absum_tail: // do { + // p_sum += max( p_sum + x[i], p_sum - x[i] ) + MOVSD (SI)(AX*8), X8 // X_8 = x[i] + MOVSD X0, X1 // p_sum_1 = p_sum_0 + ADDSD X8, X0 // p_sum_0 += X_8 + SUBSD X8, X1 // p_sum_1 -= X_8 + MAXSD X1, X0 // p_sum_0 = max( p_sum_0, p_sum_1 ) + INCQ AX // i++ + LOOP absum_tail // } while --CX > 0 + +absum_end: // return p_sum_0 + MOVSD X0, sum+24(FP) + RET diff --git a/internal/asm/f64/abssuminc_amd64.s b/internal/asm/f64/abssuminc_amd64.s new file mode 100644 index 00000000..f4db05bd --- /dev/null +++ b/internal/asm/f64/abssuminc_amd64.s @@ -0,0 +1,90 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func L1NormInc(x []float64, n, incX int) (sum float64) +TEXT ·L1NormInc(SB), NOSPLIT, $0 + MOVQ x_base+0(FP), SI // SI = &x + MOVQ n+24(FP), CX // CX = n + MOVQ incX+32(FP), AX // AX = increment * sizeof( float64 ) + SHLQ $3, AX + MOVQ AX, DX // DX = AX * 3 + IMULQ $3, DX + PXOR X0, X0 // p_sum_i = 0 + PXOR X1, X1 + PXOR X2, X2 + PXOR X3, X3 + PXOR X4, X4 + PXOR X5, X5 + PXOR X6, X6 + PXOR X7, X7 + CMPQ CX, $0 // if CX == 0 { return 0 } + JE absum_end + MOVQ CX, BX + ANDQ $7, BX // BX = n % 8 + SHRQ $3, CX // CX = floor( n / 8 ) + JZ absum_tail_start // if CX == 0 { goto absum_tail_start } + +absum_loop: // do { + // p_sum = max( p_sum + x[i], p_sum - x[i] ) + MOVSD (SI), X8 // X_i[0] = x[i] + MOVSD (SI)(AX*1), X9 + MOVSD (SI)(AX*2), X10 + MOVSD (SI)(DX*1), X11 + LEAQ (SI)(AX*4), SI // SI = SI + 4 + MOVHPD (SI), X8 // X_i[1] = x[i+4] + MOVHPD (SI)(AX*1), X9 + MOVHPD (SI)(AX*2), X10 + MOVHPD (SI)(DX*1), X11 + ADDPD X8, X0 // p_sum_i += X_i ( positive values ) + ADDPD X9, X2 + ADDPD X10, X4 + ADDPD X11, X6 + SUBPD X8, X1 // p_sum_(i+1) -= X_i ( negative values ) + SUBPD X9, X3 + SUBPD X10, X5 + SUBPD X11, X7 + MAXPD X1, X0 // p_sum_i = max( p_sum_i, p_sum_(i+1) ) + MAXPD X3, X2 + MAXPD X5, X4 + MAXPD X7, X6 + MOVAPS X0, X1 // p_sum_(i+1) = p_sum_i + MOVAPS X2, X3 + MOVAPS X4, X5 + MOVAPS X6, X7 + LEAQ (SI)(AX*4), SI // SI = SI + 4 + LOOP absum_loop // } while --CX > 0 + + // p_sum_0 = \sum_{i=1}^{3}( p_sum_(i*2) ) + ADDPD X3, X0 + ADDPD X5, X7 + ADDPD X7, X0 + + // p_sum_0[0] = p_sum_0[0] + p_sum_0[1] + MOVAPS X0, X1 + SHUFPD $0x3, X0, X0 // lower( p_sum_0 ) = upper( p_sum_0 ) + ADDSD X1, X0 + CMPQ BX, $0 + JE absum_end // if BX == 0 { goto absum_end } + +absum_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + XORPS X8, X8 // X_8 = 0 + +absum_tail: // do { + // p_sum += max( p_sum + x[i], p_sum - x[i] ) + MOVSD (SI), X8 // X_8 = x[i] + MOVSD X0, X1 // p_sum_1 = p_sum_0 + ADDSD X8, X0 // p_sum_0 += X_8 + SUBSD X8, X1 // p_sum_1 -= X_8 + MAXSD X1, X0 // p_sum_0 = max( p_sum_0, p_sum_1 ) + ADDQ AX, SI // i++ + LOOP absum_tail // } while --CX > 0 + +absum_end: // return p_sum_0 + MOVSD X0, sum+40(FP) + RET diff --git a/internal/asm/f64/add_amd64.s b/internal/asm/f64/add_amd64.s new file mode 100644 index 00000000..27329699 --- /dev/null +++ b/internal/asm/f64/add_amd64.s @@ -0,0 +1,66 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func Add(dst, s []float64) +TEXT ·Add(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ s_base+24(FP), SI // SI = &s + CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) + CMOVQLE s_len+32(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE add_end + XORQ AX, AX + MOVQ DI, BX + ANDQ $0x0F, BX // BX = &dst & 15 + JZ add_no_trim // if BX == 0 { goto add_no_trim } + + // Align on 16-bit boundary + MOVSD (SI)(AX*8), X0 // X0 = s[i] + ADDSD (DI)(AX*8), X0 // X0 += dst[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // i++ + DECQ CX // --CX + JE add_end // if CX == 0 { return } + +add_no_trim: + MOVQ CX, BX + ANDQ $7, BX // BX = len(dst) % 8 + SHRQ $3, CX // CX = floor( len(dst) / 8 ) + JZ add_tail_start // if CX == 0 { goto add_tail_start } + +add_loop: // Loop unrolled 8x do { + MOVUPS (SI)(AX*8), X0 // X_i = s[i:i+1] + MOVUPS 16(SI)(AX*8), X1 + MOVUPS 32(SI)(AX*8), X2 + MOVUPS 48(SI)(AX*8), X3 + ADDPD (DI)(AX*8), X0 // X_i += dst[i:i+1] + ADDPD 16(DI)(AX*8), X1 + ADDPD 32(DI)(AX*8), X2 + ADDPD 48(DI)(AX*8), X3 + MOVUPS X0, (DI)(AX*8) // dst[i:i+1] = X_i + MOVUPS X1, 16(DI)(AX*8) + MOVUPS X2, 32(DI)(AX*8) + MOVUPS X3, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + LOOP add_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE add_end + +add_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +add_tail: // do { + MOVSD (SI)(AX*8), X0 // X0 = s[i] + ADDSD (DI)(AX*8), X0 // X0 += dst[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // ++i + LOOP add_tail // } while --CX > 0 + +add_end: + RET diff --git a/internal/asm/f64/addconst_amd64.s b/internal/asm/f64/addconst_amd64.s new file mode 100644 index 00000000..88fed071 --- /dev/null +++ b/internal/asm/f64/addconst_amd64.s @@ -0,0 +1,53 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func Addconst(alpha float64, x []float64) +TEXT ·AddConst(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), SI // SI = &x + MOVQ x_len+16(FP), CX // CX = len(x) + CMPQ CX, $0 // if len(x) == 0 { return } + JE ac_end + MOVSD alpha+0(FP), X4 // X4 = { a, a } + SHUFPD $0, X4, X4 + MOVUPS X4, X5 // X5 = X4 + XORQ AX, AX // i = 0 + MOVQ CX, BX + ANDQ $7, BX // BX = len(x) % 8 + SHRQ $3, CX // CX = floor( len(x) / 8 ) + JZ ac_tail_start // if CX == 0 { goto ac_tail_start } + +ac_loop: // Loop unrolled 8x do { + MOVUPS (SI)(AX*8), X0 // X_i = s[i:i+1] + MOVUPS 16(SI)(AX*8), X1 + MOVUPS 32(SI)(AX*8), X2 + MOVUPS 48(SI)(AX*8), X3 + ADDPD X4, X0 // X_i += a + ADDPD X5, X1 + ADDPD X4, X2 + ADDPD X5, X3 + MOVUPS X0, (SI)(AX*8) // s[i:i+1] = X_i + MOVUPS X1, 16(SI)(AX*8) + MOVUPS X2, 32(SI)(AX*8) + MOVUPS X3, 48(SI)(AX*8) + ADDQ $8, AX // i += 8 + LOOP ac_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE ac_end + +ac_tail_start: // Reset loop counters + MOVQ BX, CX // Loop counter: CX = BX + +ac_tail: // do { + MOVSD (SI)(AX*8), X0 // X0 = s[i] + ADDSD X4, X0 // X0 += a + MOVSD X0, (SI)(AX*8) // s[i] = X0 + INCQ AX // ++i + LOOP ac_tail // } while --CX > 0 + +ac_end: + RET diff --git a/internal/asm/f64/asm_test.go b/internal/asm/f64/asm_test.go new file mode 100644 index 00000000..cca86e84 --- /dev/null +++ b/internal/asm/f64/asm_test.go @@ -0,0 +1,204 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f64 + +import ( + "math" + "math/rand" + "testing" +) + +var ( + nan = math.NaN() + inf = math.Inf(1) +) + +// newGuardedVector allocates a new slice and returns it as three subslices. +// v is a strided vector that contains elements of data at indices i*inc and +// NaN elsewhere. frontGuard and backGuard are filled with NaN values, and +// their backing arrays are directly adjacent to v in memory. The three slices +// can be used to detect invalid memory reads and writes. +func newGuardedVector(data []float64, inc int) (v, frontGuard, backGuard []float64) { + if inc < 0 { + inc = -inc + } + guard := 2 * inc + size := (len(data)-1)*inc + 1 + whole := make([]float64, size+2*guard) + v = whole[guard : len(whole)-guard] + for i := range whole { + whole[i] = math.NaN() + } + for i, d := range data { + v[i*inc] = d + } + return v, whole[:guard], whole[len(whole)-guard:] +} + +// allNaN returns true if x contains only NaN values, and false otherwise. +func allNaN(x []float64) bool { + for _, v := range x { + if !math.IsNaN(v) { + return false + } + } + return true +} + +// equalStrided returns true if the strided vector x contains elements of the +// dense vector ref at indices i*inc, false otherwise. +func equalStrided(ref, x []float64, inc int) bool { + if inc < 0 { + inc = -inc + } + for i, v := range ref { + if !same(x[i*inc], v) { + return false + } + } + return true +} + +// nonStridedWrite returns false if all elements of x at non-stride indices are +// equal to NaN, true otherwise. +func nonStridedWrite(x []float64, inc int) bool { + if inc < 0 { + inc = -inc + } + for i, v := range x { + if i%inc != 0 && !math.IsNaN(v) { + return true + } + } + return false +} + +// guardVector copies the source vector (vec) into a new slice with guards. +// Guards guarded[:gdLn] and guarded[len-gdLn:] will be filled with sigil value gdVal. +func guardVector(vec []float64, gdVal float64, gdLn int) (guarded []float64) { + guarded = make([]float64, len(vec)+gdLn*2) + copy(guarded[gdLn:], vec) + for i := 0; i < gdLn; i++ { + guarded[i] = gdVal + guarded[len(guarded)-1-i] = gdVal + } + return guarded +} + +// isValidGuard will test for violated guards, generated by guardVector. +func isValidGuard(vec []float64, gdVal float64, gdLn int) bool { + for i := 0; i < gdLn; i++ { + if !same(vec[i], gdVal) || !same(vec[len(vec)-1-i], gdVal) { + return false + } + } + return true +} + +// guardIncVector copies the source vector (vec) into a new incremented slice with guards. +// End guards will be length gdLen. +// Internal and end guards will be filled with sigil value gdVal. +func guardIncVector(vec []float64, gdVal float64, inc, gdLen int) (guarded []float64) { + if inc < 0 { + inc = -inc + } + inrLen := len(vec) * inc + guarded = make([]float64, inrLen+gdLen*2) + for i := range guarded { + guarded[i] = gdVal + } + for i, v := range vec { + guarded[gdLen+i*inc] = v + } + return guarded +} + +// checkValidIncGuard will test for violated guards, generated by guardIncVector +func checkValidIncGuard(t *testing.T, vec []float64, gdVal float64, inc, gdLen int) { + srcLn := len(vec) - 2*gdLen + for i := range vec { + switch { + case same(vec[i], gdVal): + // Correct value + case (i-gdLen)%inc == 0 && (i-gdLen)/inc < len(vec): + // Ignore input values + case i < gdLen: + t.Errorf("Front guard violated at %d %v", i, vec[:gdLen]) + case i > gdLen+srcLn: + t.Errorf("Back guard violated at %d %v", i-gdLen-srcLn, vec[gdLen+srcLn:]) + default: + t.Errorf("Internal guard violated at %d %v", i-gdLen, vec[gdLen:gdLen+srcLn]) + } + } +} + +// same tests for nan-aware equality. +func same(a, b float64) bool { + return a == b || (math.IsNaN(a) && math.IsNaN(b)) +} + +var ( // Offset sets for testing alignment handling in Unitary assembly functions. + align1 = []int{0, 1} + align2 = newIncSet(0, 1) + align3 = newIncToSet(0, 1) +) + +type incSet struct { + x, y int +} + +// genInc will generate all (x,y) combinations of the input increment set. +func newIncSet(inc ...int) []incSet { + n := len(inc) + is := make([]incSet, n*n) + for x := range inc { + for y := range inc { + is[x*n+y] = incSet{inc[x], inc[y]} + } + } + return is +} + +type incToSet struct { + dst, x, y int +} + +// genIncTo will generate all (dst,x,y) combinations of the input increment set. +func newIncToSet(inc ...int) []incToSet { + n := len(inc) + is := make([]incToSet, n*n*n) + for i, dst := range inc { + for x := range inc { + for y := range inc { + is[i*n*n+x*n+y] = incToSet{dst, inc[x], inc[y]} + } + } + } + return is +} + +var benchSink []float64 + +func randomSlice(n, inc int) []float64 { + if inc < 0 { + inc = -inc + } + x := make([]float64, (n-1)*inc+1) + for i := range x { + x[i] = rand.Float64() + } + return x +} + +func randSlice(n, inc int, r *rand.Rand) []float64 { + if inc < 0 { + inc = -inc + } + x := make([]float64, (n-1)*inc+1) + for i := range x { + x[i] = r.Float64() + } + return x +} diff --git a/internal/asm/f64/axpy.go b/internal/asm/f64/axpy.go new file mode 100644 index 00000000..455a5d7e --- /dev/null +++ b/internal/asm/f64/axpy.go @@ -0,0 +1,57 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f64 + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha float64, x, y []float64) { + for i, v := range x { + y[i] += alpha * v + } +} + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []float64, alpha float64, x, y []float64) { + for i, v := range x { + dst[i] = alpha*v + y[i] + } +} + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} diff --git a/internal/asm/f64/axpy_test.go b/internal/asm/f64/axpy_test.go new file mode 100644 index 00000000..2f096aaf --- /dev/null +++ b/internal/asm/f64/axpy_test.go @@ -0,0 +1,274 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f64 + +import ( + "fmt" + "testing" +) + +const ( + msgVal = "%v: unexpected value at %v Got: %v Expected: %v" + msgGuard = "%v: Guard violated in %s vector %v %v" +) + +var axpyTests = []struct { + alpha float64 + x []float64 + y []float64 + want []float64 + wantRev []float64 // Result when x is traversed in reverse direction. +}{ + { + alpha: 0, + x: []float64{}, + y: []float64{}, + want: []float64{}, + wantRev: []float64{}, + }, + { + alpha: 0, + x: []float64{2}, + y: []float64{-3}, + want: []float64{-3}, + wantRev: []float64{-3}, + }, + { + alpha: 1, + x: []float64{2}, + y: []float64{-3}, + want: []float64{-1}, + wantRev: []float64{-1}, + }, + { + alpha: 3, + x: []float64{2}, + y: []float64{-3}, + want: []float64{3}, + wantRev: []float64{3}, + }, + { + alpha: -3, + x: []float64{2}, + y: []float64{-3}, + want: []float64{-9}, + wantRev: []float64{-9}, + }, + { + alpha: 1, + x: []float64{1, 5}, + y: []float64{2, -3}, + want: []float64{3, 2}, + wantRev: []float64{7, -2}, + }, + { + alpha: 1, + x: []float64{2, 3, 4}, + y: []float64{-3, -2, -1}, + want: []float64{-1, 1, 3}, + wantRev: []float64{1, 1, 1}, + }, + { + alpha: 0, + x: []float64{0, 0, 1, 1, 2, -3, -4}, + y: []float64{0, 1, 0, 3, -4, 5, -6}, + want: []float64{0, 1, 0, 3, -4, 5, -6}, + wantRev: []float64{0, 1, 0, 3, -4, 5, -6}, + }, + { + alpha: 1, + x: []float64{0, 0, 1, 1, 2, -3, -4}, + y: []float64{0, 1, 0, 3, -4, 5, -6}, + want: []float64{0, 1, 1, 4, -2, 2, -10}, + wantRev: []float64{-4, -2, 2, 4, -3, 5, -6}, + }, + { + alpha: 3, + x: []float64{0, 0, 1, 1, 2, -3, -4}, + y: []float64{0, 1, 0, 3, -4, 5, -6}, + want: []float64{0, 1, 3, 6, 2, -4, -18}, + wantRev: []float64{-12, -8, 6, 6, -1, 5, -6}, + }, + { + alpha: -3, + x: []float64{0, 0, 1, 1, 2, -3, -4, 0, 0, 1, 1, 2, -3, -4}, + y: []float64{0, 1, 0, 3, -4, 5, -6, 0, 1, 0, 3, -4, 5, -6}, + want: []float64{0, 1, -3, 0, -10, 14, 6, 0, 1, -3, 0, -10, 14, 6}, + wantRev: []float64{12, 10, -6, 0, -7, 5, -6, 12, 10, -6, 0, -7, 5, -6}, + }, + { + alpha: -5, + x: []float64{0, 0, 1, 1, 2, -3, -4, 5, 1, 2, -3, -4, 5}, + y: []float64{0, 1, 0, 3, -4, 5, -6, 7, 3, -4, 5, -6, 7}, + want: []float64{0, 1, -5, -2, -14, 20, 14, -18, -2, -14, 20, 14, -18}, + wantRev: []float64{-25, 21, 15, -7, -9, -20, 14, 22, -7, -9, 0, -6, 7}, + }, +} + +func TestAxpyUnitary(t *testing.T) { + const xGdVal, yGdVal = -1, 0.5 + for i, test := range axpyTests { + for _, align := range align2 { + prefix := fmt.Sprintf("Test %v (x:%v y:%v)", i, align.x, align.y) + xgLn, ygLn := 4+align.x, 4+align.y + xg, yg := guardVector(test.x, xGdVal, xgLn), guardVector(test.y, yGdVal, ygLn) + x, y := xg[xgLn:len(xg)-xgLn], yg[ygLn:len(yg)-ygLn] + AxpyUnitary(test.alpha, x, y) + for i := range test.want { + if !same(y[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, y[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + if !isValidGuard(yg, yGdVal, ygLn) { + t.Errorf(msgGuard, prefix, "y", yg[:ygLn], yg[len(yg)-ygLn:]) + } + if !equalStrided(test.x, x, 1) { + t.Errorf("%v: modified read-only x argument", prefix) + } + } + } +} + +func TestAxpyUnitaryTo(t *testing.T) { + const dstGdVal, xGdVal, yGdVal = 1, -1, 0.5 + for i, test := range axpyTests { + for _, align := range align3 { + prefix := fmt.Sprintf("Test %v (x:%v y:%v dst:%v)", i, align.x, align.y, align.dst) + + dgLn, xgLn, ygLn := 4+align.dst, 4+align.x, 4+align.y + dstOrig := make([]float64, len(test.x)) + xg, yg := guardVector(test.x, xGdVal, xgLn), guardVector(test.y, yGdVal, ygLn) + dstg := guardVector(dstOrig, dstGdVal, dgLn) + x, y := xg[xgLn:len(xg)-xgLn], yg[ygLn:len(yg)-ygLn] + dst := dstg[dgLn : len(dstg)-dgLn] + + AxpyUnitaryTo(dst, test.alpha, x, y) + for i := range test.want { + if !same(dst[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, dst[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + if !isValidGuard(yg, yGdVal, ygLn) { + t.Errorf(msgGuard, prefix, "y", yg[:ygLn], yg[len(yg)-ygLn:]) + } + if !isValidGuard(dstg, dstGdVal, dgLn) { + t.Errorf(msgGuard, prefix, "dst", dstg[:dgLn], dstg[len(dstg)-dgLn:]) + } + if !equalStrided(test.x, x, 1) { + t.Errorf("%v: modified read-only x argument", prefix) + } + if !equalStrided(test.y, y, 1) { + t.Errorf("%v: modified read-only y argument", prefix) + } + } + } +} + +func TestAxpyInc(t *testing.T) { + const xGdVal, yGdVal = -1, 0.5 + gdLn := 4 + for i, test := range axpyTests { + n := len(test.x) + for _, inc := range newIncSet(-7, -4, -3, -2, -1, 1, 2, 3, 4, 7) { + var ix, iy int + if inc.x < 0 { + ix = (-n + 1) * inc.x + } + if inc.y < 0 { + iy = (-n + 1) * inc.y + } + prefix := fmt.Sprintf("test %v, inc.x = %v, inc.y = %v", i, inc.x, inc.y) + xg := guardIncVector(test.x, xGdVal, inc.x, gdLn) + yg := guardIncVector(test.y, yGdVal, inc.y, gdLn) + x, y := xg[gdLn:len(xg)-gdLn], yg[gdLn:len(yg)-gdLn] + + AxpyInc(test.alpha, x, y, uintptr(n), + uintptr(inc.x), uintptr(inc.y), uintptr(ix), uintptr(iy)) + + want := test.want + if inc.x*inc.y < 0 { + want = test.wantRev + } + if inc.y < 0 { + inc.y = -inc.y + } + for i := range want { + if !same(y[i*inc.y], want[i]) { + t.Errorf(msgVal, prefix, i, y[iy+i*inc.y], want[i]) + } + } + if !equalStrided(test.x, x, inc.x) { + t.Errorf("%v: modified read-only x argument", prefix) + } + checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn) + checkValidIncGuard(t, yg, yGdVal, inc.y, gdLn) + } + } +} + +func TestAxpyIncTo(t *testing.T) { + const dstGdVal, xGdVal, yGdVal = 1, -1, 0.5 + var want []float64 + gdLn := 4 + for i, test := range axpyTests { + n := len(test.x) + for _, inc := range newIncToSet(-7, -4, -3, -2, -1, 1, 2, 3, 4, 7) { + var ix, iy, idst uintptr + if inc.x < 0 { + ix = uintptr((-n + 1) * inc.x) + } + if inc.y < 0 { + iy = uintptr((-n + 1) * inc.y) + } + if inc.dst < 0 { + idst = uintptr((-n + 1) * inc.dst) + } + + prefix := fmt.Sprintf("Test %v: (x: %v, y: %v, dst:%v)", i, inc.x, inc.y, inc.dst) + dstOrig := make([]float64, len(test.want)) + xg := guardIncVector(test.x, xGdVal, inc.x, gdLn) + yg := guardIncVector(test.y, yGdVal, inc.y, gdLn) + dstg := guardIncVector(dstOrig, dstGdVal, inc.dst, gdLn) + x, y := xg[gdLn:len(xg)-gdLn], yg[gdLn:len(yg)-gdLn] + dst := dstg[gdLn : len(dstg)-gdLn] + + AxpyIncTo(dst, uintptr(inc.dst), idst, + test.alpha, x, y, uintptr(n), + uintptr(inc.x), uintptr(inc.y), ix, iy) + want = test.want + if inc.x*inc.y < 0 { + want = test.wantRev + } + var iW, incW int = 0, 1 + if inc.y*inc.dst < 0 { + iW, incW = len(want)-1, -1 + } + if inc.dst < 0 { + inc.dst = -inc.dst + } + for i := range want { + if !same(dst[i*inc.dst], want[iW+i*incW]) { + t.Errorf(msgVal, prefix, i, dst[i*inc.dst], want[iW+i*incW]) + } + } + + checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn) + checkValidIncGuard(t, yg, yGdVal, inc.y, gdLn) + checkValidIncGuard(t, dstg, dstGdVal, inc.dst, gdLn) + if !equalStrided(test.x, x, inc.x) { + t.Errorf("%v: modified read-only x argument", prefix) + } + if !equalStrided(test.y, y, inc.y) { + t.Errorf("%v: modified read-only y argument", prefix) + } + } + } +} diff --git a/internal/asm/f64/axpyinc_amd64.s b/internal/asm/f64/axpyinc_amd64.s new file mode 100644 index 00000000..214f9704 --- /dev/null +++ b/internal/asm/f64/axpyinc_amd64.s @@ -0,0 +1,142 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define Y_PTR DI +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define INC_X R8 +#define INCx3_X R11 +#define INC_Y R9 +#define INCx3_Y R12 +#define INC_DST R9 +#define INCx3_DST R12 +#define ALPHA X0 +#define ALPHA_2 X1 + +// func AxpyInc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyInc(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), X_PTR // X_PTR = &x + MOVQ y_base+32(FP), Y_PTR // Y_PTR = &y + MOVQ n+56(FP), LEN // LEN = n + CMPQ LEN, $0 // if LEN == 0 { return } + JE end + + MOVQ ix+80(FP), INC_X + MOVQ iy+88(FP), INC_Y + LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(x[ix]) + LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(y[iy]) + MOVQ Y_PTR, DST_PTR // DST_PTR = Y_PTR // Write pointer + + MOVQ incX+64(FP), INC_X // INC_X = incX * sizeof(float64) + SHLQ $3, INC_X + MOVQ incY+72(FP), INC_Y // INC_Y = incY * sizeof(float64) + SHLQ $3, INC_Y + + MOVSD alpha+0(FP), ALPHA // ALPHA = alpha + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = n % 4 + SHRQ $2, LEN // LEN = floor( n / 4 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVAPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 + LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 + +loop: // do { // y[i] += alpha * x[i] unrolled 4x. + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MOVSD (X_PTR)(INC_X*2), X4 + MOVSD (X_PTR)(INCx3_X*1), X5 + + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA_2, X3 + MULSD ALPHA, X4 + MULSD ALPHA_2, X5 + + ADDSD (Y_PTR), X2 // X_i += y[i] + ADDSD (Y_PTR)(INC_Y*1), X3 + ADDSD (Y_PTR)(INC_Y*2), X4 + ADDSD (Y_PTR)(INCx3_Y*1), X5 + + MOVSD X2, (DST_PTR) // y[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + MOVSD X4, (DST_PTR)(INC_DST*2) + MOVSD X5, (DST_PTR)(INCx3_DST*1) + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) + LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[incY*4]) + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE end + +tail_start: // Reset Loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ tail_one + +tail_two: + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA, X3 + ADDSD (Y_PTR), X2 // X_i += y[i] + ADDSD (Y_PTR)(INC_Y*1), X3 + MOVSD X2, (DST_PTR) // y[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + + LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) + LEAQ (Y_PTR)(INC_Y*2), Y_PTR // Y_PTR = &(Y_PTR[incY*2]) + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { goto end } + +tail_one: + // y[i] += alpha * x[i] for the last n % 4 iterations. + MOVSD (X_PTR), X2 // X2 = x[i] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR), X2 // X2 += y[i] + MOVSD X2, (DST_PTR) // y[i] = X2 + +end: + RET diff --git a/internal/asm/f64/axpyincto_amd64.s b/internal/asm/f64/axpyincto_amd64.s new file mode 100644 index 00000000..a873b1c9 --- /dev/null +++ b/internal/asm/f64/axpyincto_amd64.s @@ -0,0 +1,148 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define Y_PTR DI +#define DST_PTR DX +#define IDX AX +#define LEN CX +#define TAIL BX +#define INC_X R8 +#define INCx3_X R11 +#define INC_Y R9 +#define INCx3_Y R12 +#define INC_DST R10 +#define INCx3_DST R13 +#define ALPHA X0 +#define ALPHA_2 X1 + +// func AxpyIncTo(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) +TEXT ·AxpyIncTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DST_PTR // DST_PTR := &dst + MOVQ x_base+48(FP), X_PTR // X_PTR := &x + MOVQ y_base+72(FP), Y_PTR // Y_PTR := &y + MOVQ n+96(FP), LEN // LEN := n + CMPQ LEN, $0 // if LEN == 0 { return } + JE end + + MOVQ ix+120(FP), INC_X + LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(x[ix]) + MOVQ iy+128(FP), INC_Y + LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(dst[idst]) + MOVQ idst+32(FP), INC_DST + LEAQ (DST_PTR)(INC_DST*8), DST_PTR // DST_PTR = &(y[iy]) + + MOVQ incX+104(FP), INC_X // INC_X = incX * sizeof(float64) + SHLQ $3, INC_X + MOVQ incY+112(FP), INC_Y // INC_Y = incY * sizeof(float64) + SHLQ $3, INC_Y + MOVQ incDst+24(FP), INC_DST // INC_DST = incDst * sizeof(float64) + SHLQ $3, INC_DST + MOVSD alpha+40(FP), ALPHA + + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = n % 4 + SHRQ $2, LEN // LEN = floor( n / 4 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVSD ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 + LEAQ (INC_Y)(INC_Y*2), INCx3_Y // INCx3_Y = INC_Y * 3 + LEAQ (INC_DST)(INC_DST*2), INCx3_DST // INCx3_DST = INC_DST * 3 + +loop: // do { // y[i] += alpha * x[i] unrolled 2x. + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MOVSD (X_PTR)(INC_X*2), X4 + MOVSD (X_PTR)(INCx3_X*1), X5 + + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA_2, X3 + MULSD ALPHA, X4 + MULSD ALPHA_2, X5 + + ADDSD (Y_PTR), X2 // X_i += y[i] + ADDSD (Y_PTR)(INC_Y*1), X3 + ADDSD (Y_PTR)(INC_Y*2), X4 + ADDSD (Y_PTR)(INCx3_Y*1), X5 + + MOVSD X2, (DST_PTR) // y[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + MOVSD X4, (DST_PTR)(INC_DST*2) + MOVSD X5, (DST_PTR)(INCx3_DST*1) + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) + LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[incY*4]) + LEAQ (DST_PTR)(INC_DST*4), DST_PTR // DST_PTR = &(DST_PTR[incDst*4] + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE end + +tail_start: // Reset Loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ tail_one + +tail_two: + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA, X3 + ADDSD (Y_PTR), X2 // X_i += y[i] + ADDSD (Y_PTR)(INC_Y*1), X3 + MOVSD X2, (DST_PTR) // y[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + + LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) + LEAQ (Y_PTR)(INC_Y*2), Y_PTR // Y_PTR = &(Y_PTR[incY*2]) + LEAQ (DST_PTR)(INC_DST*2), DST_PTR // DST_PTR = &(DST_PTR[incY*2] + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { goto end } + +tail_one: + MOVSD (X_PTR), X2 // X2 = x[i] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR), X2 // X2 += y[i] + MOVSD X2, (DST_PTR) // y[i] = X2 + +end: + RET diff --git a/internal/asm/f64/axpyunitary_amd64.s b/internal/asm/f64/axpyunitary_amd64.s new file mode 100644 index 00000000..668f091e --- /dev/null +++ b/internal/asm/f64/axpyunitary_amd64.s @@ -0,0 +1,134 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define Y_PTR DI +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_2 X1 + +// func AxpyUnitary(alpha float64, x, y []float64) +TEXT ·AxpyUnitary(SB), NOSPLIT, $0 + MOVQ x_base+8(FP), X_PTR // X_PTR := &x + MOVQ y_base+32(FP), Y_PTR // Y_PTR := &y + MOVQ x_len+16(FP), LEN // LEN = min( len(x), len(y) ) + CMPQ y_len+40(FP), LEN + CMOVQLE y_len+40(FP), LEN + CMPQ LEN, $0 // if LEN == 0 { return } + JE end + XORQ IDX, IDX + MOVSD alpha+0(FP), ALPHA // ALPHA := { alpha, alpha } + SHUFPD $0, ALPHA, ALPHA + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 := ALPHA for pipelining + MOVQ Y_PTR, TAIL // Check memory alignment + ANDQ $15, TAIL // TAIL = &y % 16 + JZ no_trim // if TAIL == 0 { goto no_trim } + + // Align on 16-byte boundary + MOVSD (X_PTR), X2 // X2 := x[0] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR), X2 // X2 += y[0] + MOVSD X2, (DST_PTR) // y[0] = X2 + INCQ IDX // i++ + DECQ LEN // LEN-- + JZ end // if LEN == 0 { return } + +no_trim: + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL := n % 8 + SHRQ $3, LEN // LEN = floor( n / 8 ) + JZ tail_start // if LEN == 0 { goto tail2_start } + +loop: // do { + // y[i] += alpha * x[i] unrolled 8x. + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MOVUPS 16(X_PTR)(IDX*8), X3 + MOVUPS 32(X_PTR)(IDX*8), X4 + MOVUPS 48(X_PTR)(IDX*8), X5 + + MULPD ALPHA, X2 // X_i *= a + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + ADDPD (Y_PTR)(IDX*8), X2 // X_i += y[i] + ADDPD 16(Y_PTR)(IDX*8), X3 + ADDPD 32(Y_PTR)(IDX*8), X4 + ADDPD 48(Y_PTR)(IDX*8), X5 + + MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X_i + MOVUPS X3, 16(DST_PTR)(IDX*8) + MOVUPS X4, 32(DST_PTR)(IDX*8) + MOVUPS X5, 48(DST_PTR)(IDX*8) + + ADDQ $8, IDX // i += 8 + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE end + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( TAIL / 2 ) + JZ tail_one // if TAIL == 0 { goto tail } + +tail_two: // do { + MOVUPS (X_PTR)(IDX*8), X2 // X2 = x[i] + MULPD ALPHA, X2 // X2 *= a + ADDPD (Y_PTR)(IDX*8), X2 // X2 += y[i] + MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X2 + ADDQ $2, IDX // i += 2 + DECQ LEN + JNZ tail_two // } while --LEN > 0 + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { goto end } + +tail_one: + MOVSD (X_PTR)(IDX*8), X2 // X2 = x[i] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR)(IDX*8), X2 // X2 += y[i] + MOVSD X2, (DST_PTR)(IDX*8) // y[i] = X2 + +end: + RET diff --git a/internal/asm/f64/axpyunitaryto_amd64.s b/internal/asm/f64/axpyunitaryto_amd64.s new file mode 100644 index 00000000..03132e9d --- /dev/null +++ b/internal/asm/f64/axpyunitaryto_amd64.s @@ -0,0 +1,140 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define Y_PTR DX +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_2 X1 + +// func AxpyUnitaryTo(dst []float64, alpha float64, x, y []float64) +TEXT ·AxpyUnitaryTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DST_PTR // DST_PTR := &dst + MOVQ x_base+32(FP), X_PTR // X_PTR := &x + MOVQ y_base+56(FP), Y_PTR // Y_PTR := &y + MOVQ x_len+40(FP), LEN // LEN = min( len(x), len(y), len(dst) ) + CMPQ y_len+64(FP), LEN + CMOVQLE y_len+64(FP), LEN + CMPQ dst_len+8(FP), LEN + CMOVQLE dst_len+8(FP), LEN + + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + + XORQ IDX, IDX // IDX = 0 + MOVSD alpha+24(FP), ALPHA + SHUFPD $0, ALPHA, ALPHA // ALPHA := { alpha, alpha } + MOVQ Y_PTR, TAIL // Check memory alignment + ANDQ $15, TAIL // TAIL = &y % 16 + JZ no_trim // if TAIL == 0 { goto no_trim } + + // Align on 16-byte boundary + MOVSD (X_PTR), X2 // X2 := x[0] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR), X2 // X2 += y[0] + MOVSD X2, (DST_PTR) // y[0] = X2 + INCQ IDX // i++ + DECQ LEN // LEN-- + JZ end // if LEN == 0 { return } + +no_trim: + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL := n % 8 + SHRQ $3, LEN // LEN = floor( n / 8 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 := ALPHA for pipelining + +loop: // do { + // y[i] += alpha * x[i] unrolled 8x. + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MOVUPS 16(X_PTR)(IDX*8), X3 + MOVUPS 32(X_PTR)(IDX*8), X4 + MOVUPS 48(X_PTR)(IDX*8), X5 + + MULPD ALPHA, X2 // X_i *= alpha + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + ADDPD (Y_PTR)(IDX*8), X2 // X_i += y[i] + ADDPD 16(Y_PTR)(IDX*8), X3 + ADDPD 32(Y_PTR)(IDX*8), X4 + ADDPD 48(Y_PTR)(IDX*8), X5 + + MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X_i + MOVUPS X3, 16(DST_PTR)(IDX*8) + MOVUPS X4, 32(DST_PTR)(IDX*8) + MOVUPS X5, 48(DST_PTR)(IDX*8) + + ADDQ $8, IDX // i += 8 + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE end + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( TAIL / 2 ) + JZ tail_one // if LEN == 0 { goto tail } + +tail_two: // do { + MOVUPS (X_PTR)(IDX*8), X2 // X2 = x[i] + MULPD ALPHA, X2 // X2 *= alpha + ADDPD (Y_PTR)(IDX*8), X2 // X2 += y[i] + MOVUPS X2, (DST_PTR)(IDX*8) // y[i] = X2 + ADDQ $2, IDX // i += 2 + DECQ LEN + JNZ tail_two // } while --LEN > 0 + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { goto end } + +tail_one: + MOVSD (X_PTR)(IDX*8), X2 // X2 = x[i] + MULSD ALPHA, X2 // X2 *= a + ADDSD (Y_PTR)(IDX*8), X2 // X2 += y[i] + MOVSD X2, (DST_PTR)(IDX*8) // y[i] = X2 + +end: + RET diff --git a/internal/asm/f64/benchAxpy_test.go b/internal/asm/f64/benchAxpy_test.go new file mode 100644 index 00000000..7bd3dca7 --- /dev/null +++ b/internal/asm/f64/benchAxpy_test.go @@ -0,0 +1,167 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package f64 + +import ( + "fmt" + "testing" +) + +const ( + testLen = 1e5 +) + +var ( + a = 2.0 + x = make([]float64, testLen) + y = make([]float64, testLen) + z = make([]float64, testLen) +) + +func init() { + for n := range x { + x[n] = float64(n) + y[n] = float64(n) + } +} + +func BenchmarkAxpyUnitary(t *testing.B) { + naiveaxpyu := func(a float64, x, y []float64) { + for i, v := range x { + y[i] += a * v + } + } + tests := []struct { + name string + f func(a float64, x, y []float64) + }{ + {"AxpyUnitary", AxpyUnitary}, + {"NaiveAxpyUnitary", naiveaxpyu}, + } + for _, test := range tests { + for _, ln := range []uintptr{1, 3, 10, 30, 1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5} { + t.Run(fmt.Sprintf("%s-%d", test.name, ln), func(b *testing.B) { + b.SetBytes(int64(64 * ln)) + x, y := x[:ln], y[:ln] + b.ResetTimer() + for i := 0; i < b.N; i++ { + test.f(a, x, y) + } + }) + } + } +} + +func BenchmarkAxpyUnitaryTo(t *testing.B) { + naiveaxpyut := func(d []float64, a float64, x, y []float64) { + for i, v := range x { + d[i] = y[i] + a*v + } + } + tests := []struct { + name string + f func(z []float64, a float64, x, y []float64) + }{ + {"AxpyUnitaryTo", AxpyUnitaryTo}, + {"NaiveAxpyUnitaryTo", naiveaxpyut}, + } + for _, test := range tests { + for _, ln := range []uintptr{1, 3, 10, 30, 1e2, 3e2, 1e3, 3e3, 1e4, 3e4, 1e5} { + t.Run(fmt.Sprintf("%s-%d", test.name, ln), func(b *testing.B) { + b.SetBytes(int64(64 * ln)) + x, y, z := x[:ln], y[:ln], z[:ln] + b.ResetTimer() + for i := 0; i < b.N; i++ { + test.f(z, a, x, y) + } + }) + } + } +} + +var incsAxpy = []struct { + len uintptr + inc []int +}{ + {1, []int{1}}, + {2, []int{1, 2, 4, 10}}, + {3, []int{1, 2, 4, 10}}, + {4, []int{1, 2, 4, 10}}, + {5, []int{1, 2, 4, 10}}, + {10, []int{1, 2, 4, 10}}, + {500, []int{1, 2, 4, 10}}, + {1e3, []int{1, 2, 4, 10}}, + {1e4, []int{1, 2, 4, 10, -1, -2, -4, -10}}, +} + +func BenchmarkAxpyInc(t *testing.B) { + naiveaxpyinc := func(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } + } + tests := []struct { + name string + f func(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) + }{ + {"AxpyInc", AxpyInc}, + {"NaiveAxpyInc", naiveaxpyinc}, + } + for _, test := range tests { + for _, tt := range incsAxpy { + for _, inc := range tt.inc { + t.Run(fmt.Sprintf("%s-%d-inc(%d)", test.name, tt.len, inc), func(b *testing.B) { + b.SetBytes(int64(64 * tt.len)) + var idx, tstInc uintptr = 0, uintptr(inc) + if inc < 0 { + idx = uintptr((-int(tt.len) + 1) * inc) + } + for i := 0; i < b.N; i++ { + test.f(a, x, y, uintptr(tt.len), tstInc, tstInc, idx, idx) + } + }) + } + } + } +} + +func BenchmarkAxpyIncTo(t *testing.B) { + naiveaxpyincto := func(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } + } + tests := []struct { + name string + f func(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) + }{ + {"AxpyIncTo", AxpyIncTo}, + {"NaiveAxpyIncTo", naiveaxpyincto}, + } + for _, test := range tests { + for _, tt := range incsAxpy { + for _, inc := range tt.inc { + t.Run(fmt.Sprintf("%s-%d-inc(%d)", test.name, tt.len, inc), func(b *testing.B) { + b.SetBytes(int64(64 * tt.len)) + var idx, tstInc uintptr = 0, uintptr(inc) + if inc < 0 { + idx = uintptr((-int(tt.len) + 1) * inc) + } + for i := 0; i < b.N; i++ { + test.f(z, tstInc, idx, a, x, y, uintptr(tt.len), + tstInc, tstInc, idx, idx) + } + }) + } + } + } +} diff --git a/internal/asm/f64/benchScal_test.go b/internal/asm/f64/benchScal_test.go new file mode 100644 index 00000000..b4fb19ad --- /dev/null +++ b/internal/asm/f64/benchScal_test.go @@ -0,0 +1,87 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package f64 + +import ( + "fmt" + "testing" +) + +var uniScal = []int64{1, 3, 10, 30, 1e2, 3e2, 1e3, 3e3, 1e4, 3e4} + +func BenchmarkScalUnitary(t *testing.B) { + tstName := "ScalUnitary" + for _, ln := range uniScal { + t.Run(fmt.Sprintf("%s-%d", tstName, ln), func(b *testing.B) { + b.SetBytes(64 * ln) + x := x[:ln] + b.ResetTimer() + for i := 0; i < b.N; i++ { + ScalUnitary(a, x) + } + }) + } +} + +func BenchmarkScalUnitaryTo(t *testing.B) { + tstName := "ScalUnitaryTo" + for _, ln := range uniScal { + t.Run(fmt.Sprintf("%s-%d", tstName, ln), func(b *testing.B) { + b.SetBytes(int64(64 * ln)) + x, y := x[:ln], y[:ln] + b.ResetTimer() + for i := 0; i < b.N; i++ { + ScalUnitaryTo(y, a, x) + } + }) + } +} + +var incScal = []struct { + len uintptr + inc []int +}{ + {1, []int{1}}, + {3, []int{1, 2, 4, 10}}, + {10, []int{1, 2, 4, 10}}, + {30, []int{1, 2, 4, 10}}, + {1e2, []int{1, 2, 4, 10}}, + {3e2, []int{1, 2, 4, 10}}, + {1e3, []int{1, 2, 4, 10}}, + {3e3, []int{1, 2, 4, 10}}, + {1e4, []int{1, 2, 4, 10}}, +} + +func BenchmarkScalInc(t *testing.B) { + tstName := "ScalInc" + for _, tt := range incScal { + for _, inc := range tt.inc { + t.Run(fmt.Sprintf("%s-%d-inc(%d)", tstName, tt.len, inc), func(b *testing.B) { + b.SetBytes(int64(64 * tt.len)) + tstInc := uintptr(inc) + for i := 0; i < b.N; i++ { + ScalInc(a, x, uintptr(tt.len), tstInc) + } + }) + } + } +} + +func BenchmarkScalIncTo(t *testing.B) { + tstName := "ScalIncTo" + for _, tt := range incScal { + for _, inc := range tt.inc { + t.Run(fmt.Sprintf("%s-%d-inc(%d)", tstName, tt.len, inc), func(b *testing.B) { + b.SetBytes(int64(64 * tt.len)) + tstInc := uintptr(inc) + for i := 0; i < b.N; i++ { + ScalIncTo(z, tstInc, a, x, uintptr(tt.len), tstInc) + } + }) + } + } +} diff --git a/internal/asm/f64/bench_other_test.go b/internal/asm/f64/bench_other_test.go new file mode 100644 index 00000000..851252ba --- /dev/null +++ b/internal/asm/f64/bench_other_test.go @@ -0,0 +1,443 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f64 + +import ( + "math" + "testing" +) + +func benchL1Norm(f func(x []float64) float64, sz int, t *testing.B) { + dst := y[:sz] + for i := 0; i < t.N; i++ { + f(dst) + } +} + +var naiveL1Norm = func(x []float64) (sum float64) { + for _, v := range x { + sum += math.Abs(v) + } + return sum +} + +func BenchmarkL1Norm1(t *testing.B) { benchL1Norm(L1Norm, 1, t) } +func BenchmarkL1Norm2(t *testing.B) { benchL1Norm(L1Norm, 2, t) } +func BenchmarkL1Norm3(t *testing.B) { benchL1Norm(L1Norm, 3, t) } +func BenchmarkL1Norm4(t *testing.B) { benchL1Norm(L1Norm, 4, t) } +func BenchmarkL1Norm5(t *testing.B) { benchL1Norm(L1Norm, 5, t) } +func BenchmarkL1Norm10(t *testing.B) { benchL1Norm(L1Norm, 10, t) } +func BenchmarkL1Norm100(t *testing.B) { benchL1Norm(L1Norm, 100, t) } +func BenchmarkL1Norm1000(t *testing.B) { benchL1Norm(L1Norm, 1000, t) } +func BenchmarkL1Norm10000(t *testing.B) { benchL1Norm(L1Norm, 10000, t) } +func BenchmarkL1Norm100000(t *testing.B) { benchL1Norm(L1Norm, 100000, t) } +func BenchmarkL1Norm500000(t *testing.B) { benchL1Norm(L1Norm, 500000, t) } + +func BenchmarkLL1Norm1(t *testing.B) { benchL1Norm(naiveL1Norm, 1, t) } +func BenchmarkLL1Norm2(t *testing.B) { benchL1Norm(naiveL1Norm, 2, t) } +func BenchmarkLL1Norm3(t *testing.B) { benchL1Norm(naiveL1Norm, 3, t) } +func BenchmarkLL1Norm4(t *testing.B) { benchL1Norm(naiveL1Norm, 4, t) } +func BenchmarkLL1Norm5(t *testing.B) { benchL1Norm(naiveL1Norm, 5, t) } +func BenchmarkLL1Norm10(t *testing.B) { benchL1Norm(naiveL1Norm, 10, t) } +func BenchmarkLL1Norm100(t *testing.B) { benchL1Norm(naiveL1Norm, 100, t) } +func BenchmarkLL1Norm1000(t *testing.B) { benchL1Norm(naiveL1Norm, 1000, t) } +func BenchmarkLL1Norm10000(t *testing.B) { benchL1Norm(naiveL1Norm, 10000, t) } +func BenchmarkLL1Norm100000(t *testing.B) { benchL1Norm(naiveL1Norm, 100000, t) } +func BenchmarkLL1Norm500000(t *testing.B) { benchL1Norm(naiveL1Norm, 500000, t) } + +func benchL1NormInc(t *testing.B, ln, inc int, f func(x []float64, n, incX int) float64) { + for i := 0; i < t.N; i++ { + f(x, ln, inc) + } +} + +var naiveL1NormInc = func(x []float64, n, incX int) (sum float64) { + for i := 0; i < n*incX; i += incX { + sum += math.Abs(x[i]) + } + return sum +} + +func BenchmarkF64L1NormIncN1Inc1(b *testing.B) { benchL1NormInc(b, 1, 1, L1NormInc) } + +func BenchmarkF64L1NormIncN2Inc1(b *testing.B) { benchL1NormInc(b, 2, 1, L1NormInc) } +func BenchmarkF64L1NormIncN2Inc2(b *testing.B) { benchL1NormInc(b, 2, 2, L1NormInc) } +func BenchmarkF64L1NormIncN2Inc4(b *testing.B) { benchL1NormInc(b, 2, 4, L1NormInc) } +func BenchmarkF64L1NormIncN2Inc10(b *testing.B) { benchL1NormInc(b, 2, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN3Inc1(b *testing.B) { benchL1NormInc(b, 3, 1, L1NormInc) } +func BenchmarkF64L1NormIncN3Inc2(b *testing.B) { benchL1NormInc(b, 3, 2, L1NormInc) } +func BenchmarkF64L1NormIncN3Inc4(b *testing.B) { benchL1NormInc(b, 3, 4, L1NormInc) } +func BenchmarkF64L1NormIncN3Inc10(b *testing.B) { benchL1NormInc(b, 3, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN4Inc1(b *testing.B) { benchL1NormInc(b, 4, 1, L1NormInc) } +func BenchmarkF64L1NormIncN4Inc2(b *testing.B) { benchL1NormInc(b, 4, 2, L1NormInc) } +func BenchmarkF64L1NormIncN4Inc4(b *testing.B) { benchL1NormInc(b, 4, 4, L1NormInc) } +func BenchmarkF64L1NormIncN4Inc10(b *testing.B) { benchL1NormInc(b, 4, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN10Inc1(b *testing.B) { benchL1NormInc(b, 10, 1, L1NormInc) } +func BenchmarkF64L1NormIncN10Inc2(b *testing.B) { benchL1NormInc(b, 10, 2, L1NormInc) } +func BenchmarkF64L1NormIncN10Inc4(b *testing.B) { benchL1NormInc(b, 10, 4, L1NormInc) } +func BenchmarkF64L1NormIncN10Inc10(b *testing.B) { benchL1NormInc(b, 10, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN1000Inc1(b *testing.B) { benchL1NormInc(b, 1000, 1, L1NormInc) } +func BenchmarkF64L1NormIncN1000Inc2(b *testing.B) { benchL1NormInc(b, 1000, 2, L1NormInc) } +func BenchmarkF64L1NormIncN1000Inc4(b *testing.B) { benchL1NormInc(b, 1000, 4, L1NormInc) } +func BenchmarkF64L1NormIncN1000Inc10(b *testing.B) { benchL1NormInc(b, 1000, 10, L1NormInc) } + +func BenchmarkF64L1NormIncN100000Inc1(b *testing.B) { benchL1NormInc(b, 100000, 1, L1NormInc) } +func BenchmarkF64L1NormIncN100000Inc2(b *testing.B) { benchL1NormInc(b, 100000, 2, L1NormInc) } +func BenchmarkF64L1NormIncN100000Inc4(b *testing.B) { benchL1NormInc(b, 100000, 4, L1NormInc) } +func BenchmarkF64L1NormIncN100000Inc10(b *testing.B) { benchL1NormInc(b, 100000, 10, L1NormInc) } + +func BenchmarkLF64L1NormIncN1Inc1(b *testing.B) { benchL1NormInc(b, 1, 1, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN2Inc1(b *testing.B) { benchL1NormInc(b, 2, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN2Inc2(b *testing.B) { benchL1NormInc(b, 2, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN2Inc4(b *testing.B) { benchL1NormInc(b, 2, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN2Inc10(b *testing.B) { benchL1NormInc(b, 2, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN3Inc1(b *testing.B) { benchL1NormInc(b, 3, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN3Inc2(b *testing.B) { benchL1NormInc(b, 3, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN3Inc4(b *testing.B) { benchL1NormInc(b, 3, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN3Inc10(b *testing.B) { benchL1NormInc(b, 3, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN4Inc1(b *testing.B) { benchL1NormInc(b, 4, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN4Inc2(b *testing.B) { benchL1NormInc(b, 4, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN4Inc4(b *testing.B) { benchL1NormInc(b, 4, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN4Inc10(b *testing.B) { benchL1NormInc(b, 4, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN10Inc1(b *testing.B) { benchL1NormInc(b, 10, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN10Inc2(b *testing.B) { benchL1NormInc(b, 10, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN10Inc4(b *testing.B) { benchL1NormInc(b, 10, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN10Inc10(b *testing.B) { benchL1NormInc(b, 10, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN1000Inc1(b *testing.B) { benchL1NormInc(b, 1000, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN1000Inc2(b *testing.B) { benchL1NormInc(b, 1000, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN1000Inc4(b *testing.B) { benchL1NormInc(b, 1000, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN1000Inc10(b *testing.B) { benchL1NormInc(b, 1000, 10, naiveL1NormInc) } + +func BenchmarkLF64L1NormIncN100000Inc1(b *testing.B) { benchL1NormInc(b, 100000, 1, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN100000Inc2(b *testing.B) { benchL1NormInc(b, 100000, 2, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN100000Inc4(b *testing.B) { benchL1NormInc(b, 100000, 4, naiveL1NormInc) } +func BenchmarkLF64L1NormIncN100000Inc10(b *testing.B) { benchL1NormInc(b, 100000, 10, naiveL1NormInc) } + +func benchAdd(f func(dst, s []float64), sz int, t *testing.B) { + dst, s := y[:sz], x[:sz] + for i := 0; i < t.N; i++ { + f(dst, s) + } +} + +var naiveAdd = func(dst, s []float64) { + for i, v := range s { + dst[i] += v + } +} + +func BenchmarkAdd1(t *testing.B) { benchAdd(Add, 1, t) } +func BenchmarkAdd2(t *testing.B) { benchAdd(Add, 2, t) } +func BenchmarkAdd3(t *testing.B) { benchAdd(Add, 3, t) } +func BenchmarkAdd4(t *testing.B) { benchAdd(Add, 4, t) } +func BenchmarkAdd5(t *testing.B) { benchAdd(Add, 5, t) } +func BenchmarkAdd10(t *testing.B) { benchAdd(Add, 10, t) } +func BenchmarkAdd100(t *testing.B) { benchAdd(Add, 100, t) } +func BenchmarkAdd1000(t *testing.B) { benchAdd(Add, 1000, t) } +func BenchmarkAdd10000(t *testing.B) { benchAdd(Add, 10000, t) } +func BenchmarkAdd100000(t *testing.B) { benchAdd(Add, 100000, t) } +func BenchmarkAdd500000(t *testing.B) { benchAdd(Add, 500000, t) } + +func BenchmarkLAdd1(t *testing.B) { benchAdd(naiveAdd, 1, t) } +func BenchmarkLAdd2(t *testing.B) { benchAdd(naiveAdd, 2, t) } +func BenchmarkLAdd3(t *testing.B) { benchAdd(naiveAdd, 3, t) } +func BenchmarkLAdd4(t *testing.B) { benchAdd(naiveAdd, 4, t) } +func BenchmarkLAdd5(t *testing.B) { benchAdd(naiveAdd, 5, t) } +func BenchmarkLAdd10(t *testing.B) { benchAdd(naiveAdd, 10, t) } +func BenchmarkLAdd100(t *testing.B) { benchAdd(naiveAdd, 100, t) } +func BenchmarkLAdd1000(t *testing.B) { benchAdd(naiveAdd, 1000, t) } +func BenchmarkLAdd10000(t *testing.B) { benchAdd(naiveAdd, 10000, t) } +func BenchmarkLAdd100000(t *testing.B) { benchAdd(naiveAdd, 100000, t) } +func BenchmarkLAdd500000(t *testing.B) { benchAdd(naiveAdd, 500000, t) } + +func benchAddConst(f func(a float64, x []float64), sz int, t *testing.B) { + a, x := 1., x[:sz] + for i := 0; i < t.N; i++ { + f(a, x) + } +} + +var naiveAddConst = func(a float64, x []float64) { + for i := range x { + x[i] += a + } +} + +func BenchmarkAddConst1(t *testing.B) { benchAddConst(AddConst, 1, t) } +func BenchmarkAddConst2(t *testing.B) { benchAddConst(AddConst, 2, t) } +func BenchmarkAddConst3(t *testing.B) { benchAddConst(AddConst, 3, t) } +func BenchmarkAddConst4(t *testing.B) { benchAddConst(AddConst, 4, t) } +func BenchmarkAddConst5(t *testing.B) { benchAddConst(AddConst, 5, t) } +func BenchmarkAddConst10(t *testing.B) { benchAddConst(AddConst, 10, t) } +func BenchmarkAddConst100(t *testing.B) { benchAddConst(AddConst, 100, t) } +func BenchmarkAddConst1000(t *testing.B) { benchAddConst(AddConst, 1000, t) } +func BenchmarkAddConst10000(t *testing.B) { benchAddConst(AddConst, 10000, t) } +func BenchmarkAddConst100000(t *testing.B) { benchAddConst(AddConst, 100000, t) } +func BenchmarkAddConst500000(t *testing.B) { benchAddConst(AddConst, 500000, t) } + +func BenchmarkLAddConst1(t *testing.B) { benchAddConst(naiveAddConst, 1, t) } +func BenchmarkLAddConst2(t *testing.B) { benchAddConst(naiveAddConst, 2, t) } +func BenchmarkLAddConst3(t *testing.B) { benchAddConst(naiveAddConst, 3, t) } +func BenchmarkLAddConst4(t *testing.B) { benchAddConst(naiveAddConst, 4, t) } +func BenchmarkLAddConst5(t *testing.B) { benchAddConst(naiveAddConst, 5, t) } +func BenchmarkLAddConst10(t *testing.B) { benchAddConst(naiveAddConst, 10, t) } +func BenchmarkLAddConst100(t *testing.B) { benchAddConst(naiveAddConst, 100, t) } +func BenchmarkLAddConst1000(t *testing.B) { benchAddConst(naiveAddConst, 1000, t) } +func BenchmarkLAddConst10000(t *testing.B) { benchAddConst(naiveAddConst, 10000, t) } +func BenchmarkLAddConst100000(t *testing.B) { benchAddConst(naiveAddConst, 100000, t) } +func BenchmarkLAddConst500000(t *testing.B) { benchAddConst(naiveAddConst, 500000, t) } + +func benchCumSum(f func(a, b []float64) []float64, sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveCumSum = func(dst, s []float64) []float64 { + if len(s) == 0 { + return dst + } + dst[0] = s[0] + for i, v := range s[1:] { + dst[i+1] = dst[i] + v + } + return dst +} + +func BenchmarkCumSum1(t *testing.B) { benchCumSum(CumSum, 1, t) } +func BenchmarkCumSum2(t *testing.B) { benchCumSum(CumSum, 2, t) } +func BenchmarkCumSum3(t *testing.B) { benchCumSum(CumSum, 3, t) } +func BenchmarkCumSum4(t *testing.B) { benchCumSum(CumSum, 4, t) } +func BenchmarkCumSum5(t *testing.B) { benchCumSum(CumSum, 5, t) } +func BenchmarkCumSum10(t *testing.B) { benchCumSum(CumSum, 10, t) } +func BenchmarkCumSum100(t *testing.B) { benchCumSum(CumSum, 100, t) } +func BenchmarkCumSum1000(t *testing.B) { benchCumSum(CumSum, 1000, t) } +func BenchmarkCumSum10000(t *testing.B) { benchCumSum(CumSum, 10000, t) } +func BenchmarkCumSum100000(t *testing.B) { benchCumSum(CumSum, 100000, t) } +func BenchmarkCumSum500000(t *testing.B) { benchCumSum(CumSum, 500000, t) } + +func BenchmarkLCumSum1(t *testing.B) { benchCumSum(naiveCumSum, 1, t) } +func BenchmarkLCumSum2(t *testing.B) { benchCumSum(naiveCumSum, 2, t) } +func BenchmarkLCumSum3(t *testing.B) { benchCumSum(naiveCumSum, 3, t) } +func BenchmarkLCumSum4(t *testing.B) { benchCumSum(naiveCumSum, 4, t) } +func BenchmarkLCumSum5(t *testing.B) { benchCumSum(naiveCumSum, 5, t) } +func BenchmarkLCumSum10(t *testing.B) { benchCumSum(naiveCumSum, 10, t) } +func BenchmarkLCumSum100(t *testing.B) { benchCumSum(naiveCumSum, 100, t) } +func BenchmarkLCumSum1000(t *testing.B) { benchCumSum(naiveCumSum, 1000, t) } +func BenchmarkLCumSum10000(t *testing.B) { benchCumSum(naiveCumSum, 10000, t) } +func BenchmarkLCumSum100000(t *testing.B) { benchCumSum(naiveCumSum, 100000, t) } +func BenchmarkLCumSum500000(t *testing.B) { benchCumSum(naiveCumSum, 500000, t) } + +func benchCumProd(f func(a, b []float64) []float64, sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveCumProd = func(dst, s []float64) []float64 { + if len(s) == 0 { + return dst + } + dst[0] = s[0] + for i, v := range s[1:] { + dst[i+1] = dst[i] + v + } + return dst +} + +func BenchmarkCumProd1(t *testing.B) { benchCumProd(CumProd, 1, t) } +func BenchmarkCumProd2(t *testing.B) { benchCumProd(CumProd, 2, t) } +func BenchmarkCumProd3(t *testing.B) { benchCumProd(CumProd, 3, t) } +func BenchmarkCumProd4(t *testing.B) { benchCumProd(CumProd, 4, t) } +func BenchmarkCumProd5(t *testing.B) { benchCumProd(CumProd, 5, t) } +func BenchmarkCumProd10(t *testing.B) { benchCumProd(CumProd, 10, t) } +func BenchmarkCumProd100(t *testing.B) { benchCumProd(CumProd, 100, t) } +func BenchmarkCumProd1000(t *testing.B) { benchCumProd(CumProd, 1000, t) } +func BenchmarkCumProd10000(t *testing.B) { benchCumProd(CumProd, 10000, t) } +func BenchmarkCumProd100000(t *testing.B) { benchCumProd(CumProd, 100000, t) } +func BenchmarkCumProd500000(t *testing.B) { benchCumProd(CumProd, 500000, t) } + +func BenchmarkLCumProd1(t *testing.B) { benchCumProd(naiveCumProd, 1, t) } +func BenchmarkLCumProd2(t *testing.B) { benchCumProd(naiveCumProd, 2, t) } +func BenchmarkLCumProd3(t *testing.B) { benchCumProd(naiveCumProd, 3, t) } +func BenchmarkLCumProd4(t *testing.B) { benchCumProd(naiveCumProd, 4, t) } +func BenchmarkLCumProd5(t *testing.B) { benchCumProd(naiveCumProd, 5, t) } +func BenchmarkLCumProd10(t *testing.B) { benchCumProd(naiveCumProd, 10, t) } +func BenchmarkLCumProd100(t *testing.B) { benchCumProd(naiveCumProd, 100, t) } +func BenchmarkLCumProd1000(t *testing.B) { benchCumProd(naiveCumProd, 1000, t) } +func BenchmarkLCumProd10000(t *testing.B) { benchCumProd(naiveCumProd, 10000, t) } +func BenchmarkLCumProd100000(t *testing.B) { benchCumProd(naiveCumProd, 100000, t) } +func BenchmarkLCumProd500000(t *testing.B) { benchCumProd(naiveCumProd, 500000, t) } + +func benchDiv(f func(a, b []float64), sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveDiv = func(a, b []float64) { + for i, v := range b { + a[i] /= v + } +} + +func BenchmarkDiv1(t *testing.B) { benchDiv(Div, 1, t) } +func BenchmarkDiv2(t *testing.B) { benchDiv(Div, 2, t) } +func BenchmarkDiv3(t *testing.B) { benchDiv(Div, 3, t) } +func BenchmarkDiv4(t *testing.B) { benchDiv(Div, 4, t) } +func BenchmarkDiv5(t *testing.B) { benchDiv(Div, 5, t) } +func BenchmarkDiv10(t *testing.B) { benchDiv(Div, 10, t) } +func BenchmarkDiv100(t *testing.B) { benchDiv(Div, 100, t) } +func BenchmarkDiv1000(t *testing.B) { benchDiv(Div, 1000, t) } +func BenchmarkDiv10000(t *testing.B) { benchDiv(Div, 10000, t) } +func BenchmarkDiv100000(t *testing.B) { benchDiv(Div, 100000, t) } +func BenchmarkDiv500000(t *testing.B) { benchDiv(Div, 500000, t) } + +func BenchmarkLDiv1(t *testing.B) { benchDiv(naiveDiv, 1, t) } +func BenchmarkLDiv2(t *testing.B) { benchDiv(naiveDiv, 2, t) } +func BenchmarkLDiv3(t *testing.B) { benchDiv(naiveDiv, 3, t) } +func BenchmarkLDiv4(t *testing.B) { benchDiv(naiveDiv, 4, t) } +func BenchmarkLDiv5(t *testing.B) { benchDiv(naiveDiv, 5, t) } +func BenchmarkLDiv10(t *testing.B) { benchDiv(naiveDiv, 10, t) } +func BenchmarkLDiv100(t *testing.B) { benchDiv(naiveDiv, 100, t) } +func BenchmarkLDiv1000(t *testing.B) { benchDiv(naiveDiv, 1000, t) } +func BenchmarkLDiv10000(t *testing.B) { benchDiv(naiveDiv, 10000, t) } +func BenchmarkLDiv100000(t *testing.B) { benchDiv(naiveDiv, 100000, t) } +func BenchmarkLDiv500000(t *testing.B) { benchDiv(naiveDiv, 500000, t) } + +func benchDivTo(f func(dst, a, b []float64) []float64, sz int, t *testing.B) { + dst, a, b := z[:sz], x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(dst, a, b) + } +} + +var naiveDivTo = func(dst, s, t []float64) []float64 { + for i, v := range s { + dst[i] = v / t[i] + } + return dst +} + +func BenchmarkDivTo1(t *testing.B) { benchDivTo(DivTo, 1, t) } +func BenchmarkDivTo2(t *testing.B) { benchDivTo(DivTo, 2, t) } +func BenchmarkDivTo3(t *testing.B) { benchDivTo(DivTo, 3, t) } +func BenchmarkDivTo4(t *testing.B) { benchDivTo(DivTo, 4, t) } +func BenchmarkDivTo5(t *testing.B) { benchDivTo(DivTo, 5, t) } +func BenchmarkDivTo10(t *testing.B) { benchDivTo(DivTo, 10, t) } +func BenchmarkDivTo100(t *testing.B) { benchDivTo(DivTo, 100, t) } +func BenchmarkDivTo1000(t *testing.B) { benchDivTo(DivTo, 1000, t) } +func BenchmarkDivTo10000(t *testing.B) { benchDivTo(DivTo, 10000, t) } +func BenchmarkDivTo100000(t *testing.B) { benchDivTo(DivTo, 100000, t) } +func BenchmarkDivTo500000(t *testing.B) { benchDivTo(DivTo, 500000, t) } + +func BenchmarkLDivTo1(t *testing.B) { benchDivTo(naiveDivTo, 1, t) } +func BenchmarkLDivTo2(t *testing.B) { benchDivTo(naiveDivTo, 2, t) } +func BenchmarkLDivTo3(t *testing.B) { benchDivTo(naiveDivTo, 3, t) } +func BenchmarkLDivTo4(t *testing.B) { benchDivTo(naiveDivTo, 4, t) } +func BenchmarkLDivTo5(t *testing.B) { benchDivTo(naiveDivTo, 5, t) } +func BenchmarkLDivTo10(t *testing.B) { benchDivTo(naiveDivTo, 10, t) } +func BenchmarkLDivTo100(t *testing.B) { benchDivTo(naiveDivTo, 100, t) } +func BenchmarkLDivTo1000(t *testing.B) { benchDivTo(naiveDivTo, 1000, t) } +func BenchmarkLDivTo10000(t *testing.B) { benchDivTo(naiveDivTo, 10000, t) } +func BenchmarkLDivTo100000(t *testing.B) { benchDivTo(naiveDivTo, 100000, t) } +func BenchmarkLDivTo500000(t *testing.B) { benchDivTo(naiveDivTo, 500000, t) } + +func benchL1Dist(f func(a, b []float64) float64, sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveL1Dist = func(s, t []float64) float64 { + var norm float64 + for i, v := range s { + norm += math.Abs(t[i] - v) + } + return norm +} + +func BenchmarkL1Dist1(t *testing.B) { benchL1Dist(L1Dist, 1, t) } +func BenchmarkL1Dist2(t *testing.B) { benchL1Dist(L1Dist, 2, t) } +func BenchmarkL1Dist3(t *testing.B) { benchL1Dist(L1Dist, 3, t) } +func BenchmarkL1Dist4(t *testing.B) { benchL1Dist(L1Dist, 4, t) } +func BenchmarkL1Dist5(t *testing.B) { benchL1Dist(L1Dist, 5, t) } +func BenchmarkL1Dist10(t *testing.B) { benchL1Dist(L1Dist, 10, t) } +func BenchmarkL1Dist100(t *testing.B) { benchL1Dist(L1Dist, 100, t) } +func BenchmarkL1Dist1000(t *testing.B) { benchL1Dist(L1Dist, 1000, t) } +func BenchmarkL1Dist10000(t *testing.B) { benchL1Dist(L1Dist, 10000, t) } +func BenchmarkL1Dist100000(t *testing.B) { benchL1Dist(L1Dist, 100000, t) } +func BenchmarkL1Dist500000(t *testing.B) { benchL1Dist(L1Dist, 500000, t) } + +func BenchmarkLL1Dist1(t *testing.B) { benchL1Dist(naiveL1Dist, 1, t) } +func BenchmarkLL1Dist2(t *testing.B) { benchL1Dist(naiveL1Dist, 2, t) } +func BenchmarkLL1Dist3(t *testing.B) { benchL1Dist(naiveL1Dist, 3, t) } +func BenchmarkLL1Dist4(t *testing.B) { benchL1Dist(naiveL1Dist, 4, t) } +func BenchmarkLL1Dist5(t *testing.B) { benchL1Dist(naiveL1Dist, 5, t) } +func BenchmarkLL1Dist10(t *testing.B) { benchL1Dist(naiveL1Dist, 10, t) } +func BenchmarkLL1Dist100(t *testing.B) { benchL1Dist(naiveL1Dist, 100, t) } +func BenchmarkLL1Dist1000(t *testing.B) { benchL1Dist(naiveL1Dist, 1000, t) } +func BenchmarkLL1Dist10000(t *testing.B) { benchL1Dist(naiveL1Dist, 10000, t) } +func BenchmarkLL1Dist100000(t *testing.B) { benchL1Dist(naiveL1Dist, 100000, t) } +func BenchmarkLL1Dist500000(t *testing.B) { benchL1Dist(naiveL1Dist, 500000, t) } + +func benchLinfDist(f func(a, b []float64) float64, sz int, t *testing.B) { + a, b := x[:sz], y[:sz] + for i := 0; i < t.N; i++ { + f(a, b) + } +} + +var naiveLinfDist = func(s, t []float64) float64 { + var norm float64 + if len(s) == 0 { + return 0 + } + norm = math.Abs(t[0] - s[0]) + for i, v := range s[1:] { + absDiff := math.Abs(t[i+1] - v) + if absDiff > norm || math.IsNaN(norm) { + norm = absDiff + } + } + return norm +} + +func BenchmarkLinfDist1(t *testing.B) { benchLinfDist(LinfDist, 1, t) } +func BenchmarkLinfDist2(t *testing.B) { benchLinfDist(LinfDist, 2, t) } +func BenchmarkLinfDist3(t *testing.B) { benchLinfDist(LinfDist, 3, t) } +func BenchmarkLinfDist4(t *testing.B) { benchLinfDist(LinfDist, 4, t) } +func BenchmarkLinfDist5(t *testing.B) { benchLinfDist(LinfDist, 5, t) } +func BenchmarkLinfDist10(t *testing.B) { benchLinfDist(LinfDist, 10, t) } +func BenchmarkLinfDist100(t *testing.B) { benchLinfDist(LinfDist, 100, t) } +func BenchmarkLinfDist1000(t *testing.B) { benchLinfDist(LinfDist, 1000, t) } +func BenchmarkLinfDist10000(t *testing.B) { benchLinfDist(LinfDist, 10000, t) } +func BenchmarkLinfDist100000(t *testing.B) { benchLinfDist(LinfDist, 100000, t) } +func BenchmarkLinfDist500000(t *testing.B) { benchLinfDist(LinfDist, 500000, t) } + +func BenchmarkLLinfDist1(t *testing.B) { benchLinfDist(naiveLinfDist, 1, t) } +func BenchmarkLLinfDist2(t *testing.B) { benchLinfDist(naiveLinfDist, 2, t) } +func BenchmarkLLinfDist3(t *testing.B) { benchLinfDist(naiveLinfDist, 3, t) } +func BenchmarkLLinfDist4(t *testing.B) { benchLinfDist(naiveLinfDist, 4, t) } +func BenchmarkLLinfDist5(t *testing.B) { benchLinfDist(naiveLinfDist, 5, t) } +func BenchmarkLLinfDist10(t *testing.B) { benchLinfDist(naiveLinfDist, 10, t) } +func BenchmarkLLinfDist100(t *testing.B) { benchLinfDist(naiveLinfDist, 100, t) } +func BenchmarkLLinfDist1000(t *testing.B) { benchLinfDist(naiveLinfDist, 1000, t) } +func BenchmarkLLinfDist10000(t *testing.B) { benchLinfDist(naiveLinfDist, 10000, t) } +func BenchmarkLLinfDist100000(t *testing.B) { benchLinfDist(naiveLinfDist, 100000, t) } +func BenchmarkLLinfDist500000(t *testing.B) { benchLinfDist(naiveLinfDist, 500000, t) } diff --git a/internal/asm/f64/bench_test.go b/internal/asm/f64/bench_test.go new file mode 100644 index 00000000..78d26d77 --- /dev/null +++ b/internal/asm/f64/bench_test.go @@ -0,0 +1,438 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !go1.7 + +package f64 + +import ( + "math/rand" + "testing" +) + +var ( + a = float64(2) + x = make([]float64, 1000000) + y = make([]float64, 1000000) + z = make([]float64, 1000000) +) + +func init() { + for n := range x { + x[n] = float64(n) + y[n] = float64(n) + } +} + +func benchaxpyu(t *testing.B, n int, f func(a float64, x, y []float64)) { + x, y := x[:n], y[:n] + + for i := 0; i < t.N; i++ { + f(a, x, y) + } +} + +func naiveaxpyu(a float64, x, y []float64) { + for i, v := range x { + y[i] += a * v + } +} + +func BenchmarkF64AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, AxpyUnitary) } +func BenchmarkF64AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, AxpyUnitary) } +func BenchmarkF64AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, AxpyUnitary) } +func BenchmarkF64AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, AxpyUnitary) } +func BenchmarkF64AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, AxpyUnitary) } +func BenchmarkF64AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, AxpyUnitary) } +func BenchmarkF64AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, AxpyUnitary) } +func BenchmarkF64AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, AxpyUnitary) } +func BenchmarkF64AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, AxpyUnitary) } +func BenchmarkF64AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, AxpyUnitary) } +func BenchmarkF64AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, AxpyUnitary) } + +func BenchmarkLF64AxpyUnitary1(t *testing.B) { benchaxpyu(t, 1, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary2(t *testing.B) { benchaxpyu(t, 2, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary3(t *testing.B) { benchaxpyu(t, 3, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary4(t *testing.B) { benchaxpyu(t, 4, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary5(t *testing.B) { benchaxpyu(t, 5, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary10(t *testing.B) { benchaxpyu(t, 10, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary100(t *testing.B) { benchaxpyu(t, 100, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary1000(t *testing.B) { benchaxpyu(t, 1000, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary5000(t *testing.B) { benchaxpyu(t, 5000, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary10000(t *testing.B) { benchaxpyu(t, 10000, naiveaxpyu) } +func BenchmarkLF64AxpyUnitary50000(t *testing.B) { benchaxpyu(t, 50000, naiveaxpyu) } + +func benchaxpyut(t *testing.B, n int, f func(d []float64, a float64, x, y []float64)) { + x, y, z := x[:n], y[:n], z[:n] + + for i := 0; i < t.N; i++ { + f(z, a, x, y) + } +} + +func naiveaxpyut(d []float64, a float64, x, y []float64) { + for i, v := range x { + d[i] = y[i] + a*v + } +} + +func BenchmarkF64AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, AxpyUnitaryTo) } +func BenchmarkF64AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, AxpyUnitaryTo) } + +func BenchmarkLF64AxpyUnitaryTo1(t *testing.B) { benchaxpyut(t, 1, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo2(t *testing.B) { benchaxpyut(t, 2, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo3(t *testing.B) { benchaxpyut(t, 3, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo4(t *testing.B) { benchaxpyut(t, 4, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo5(t *testing.B) { benchaxpyut(t, 5, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo10(t *testing.B) { benchaxpyut(t, 10, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo100(t *testing.B) { benchaxpyut(t, 100, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo1000(t *testing.B) { benchaxpyut(t, 1000, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo5000(t *testing.B) { benchaxpyut(t, 5000, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo10000(t *testing.B) { benchaxpyut(t, 10000, naiveaxpyut) } +func BenchmarkLF64AxpyUnitaryTo50000(t *testing.B) { benchaxpyut(t, 50000, naiveaxpyut) } + +func benchaxpyinc(t *testing.B, ln, t_inc int, f func(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + + for i := 0; i < t.N; i++ { + f(1, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyinc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + y[iy] += alpha * x[ix] + ix += incX + iy += incY + } +} + +func BenchmarkF64AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, AxpyInc) } + +func BenchmarkF64AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, AxpyInc) } +func BenchmarkF64AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, AxpyInc) } +func BenchmarkF64AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, AxpyInc) } +func BenchmarkF64AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, AxpyInc) } +func BenchmarkF64AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, AxpyInc) } +func BenchmarkF64AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, AxpyInc) } +func BenchmarkF64AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, AxpyInc) } +func BenchmarkF64AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, AxpyInc) } +func BenchmarkF64AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, AxpyInc) } +func BenchmarkF64AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, AxpyInc) } +func BenchmarkF64AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, AxpyInc) } +func BenchmarkF64AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, AxpyInc) } +func BenchmarkF64AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, AxpyInc) } +func BenchmarkF64AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, AxpyInc) } +func BenchmarkF64AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, AxpyInc) } +func BenchmarkF64AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, AxpyInc) } +func BenchmarkF64AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, AxpyInc) } +func BenchmarkF64AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, AxpyInc) } +func BenchmarkF64AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, AxpyInc) } + +func BenchmarkF64AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, AxpyInc) } +func BenchmarkF64AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, AxpyInc) } +func BenchmarkF64AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, AxpyInc) } +func BenchmarkF64AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, AxpyInc) } + +func BenchmarkLF64AxpyIncN1Inc1(b *testing.B) { benchaxpyinc(b, 1, 1, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN2Inc1(b *testing.B) { benchaxpyinc(b, 2, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN2Inc2(b *testing.B) { benchaxpyinc(b, 2, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN2Inc4(b *testing.B) { benchaxpyinc(b, 2, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN2Inc10(b *testing.B) { benchaxpyinc(b, 2, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN3Inc1(b *testing.B) { benchaxpyinc(b, 3, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN3Inc2(b *testing.B) { benchaxpyinc(b, 3, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN3Inc4(b *testing.B) { benchaxpyinc(b, 3, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN3Inc10(b *testing.B) { benchaxpyinc(b, 3, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN4Inc1(b *testing.B) { benchaxpyinc(b, 4, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN4Inc2(b *testing.B) { benchaxpyinc(b, 4, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN4Inc4(b *testing.B) { benchaxpyinc(b, 4, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN4Inc10(b *testing.B) { benchaxpyinc(b, 4, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN10Inc1(b *testing.B) { benchaxpyinc(b, 10, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN10Inc2(b *testing.B) { benchaxpyinc(b, 10, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN10Inc4(b *testing.B) { benchaxpyinc(b, 10, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN10Inc10(b *testing.B) { benchaxpyinc(b, 10, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN1000Inc1(b *testing.B) { benchaxpyinc(b, 1000, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN1000Inc2(b *testing.B) { benchaxpyinc(b, 1000, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN1000Inc4(b *testing.B) { benchaxpyinc(b, 1000, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN1000Inc10(b *testing.B) { benchaxpyinc(b, 1000, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN100000Inc1(b *testing.B) { benchaxpyinc(b, 100000, 1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000Inc2(b *testing.B) { benchaxpyinc(b, 100000, 2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000Inc4(b *testing.B) { benchaxpyinc(b, 100000, 4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000Inc10(b *testing.B) { benchaxpyinc(b, 100000, 10, naiveaxpyinc) } + +func BenchmarkLF64AxpyIncN100000IncM1(b *testing.B) { benchaxpyinc(b, 100000, -1, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000IncM2(b *testing.B) { benchaxpyinc(b, 100000, -2, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000IncM4(b *testing.B) { benchaxpyinc(b, 100000, -4, naiveaxpyinc) } +func BenchmarkLF64AxpyIncN100000IncM10(b *testing.B) { benchaxpyinc(b, 100000, -10, naiveaxpyinc) } + +func benchaxpyincto(t *testing.B, ln, t_inc int, f func(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr)) { + n, inc := uintptr(ln), uintptr(t_inc) + var idx int + if t_inc < 0 { + idx = (-ln + 1) * t_inc + } + + for i := 0; i < t.N; i++ { + f(z, inc, uintptr(idx), 1, x, y, n, inc, inc, uintptr(idx), uintptr(idx)) + } +} + +func naiveaxpyincto(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) { + for i := 0; i < int(n); i++ { + dst[idst] = alpha*x[ix] + y[iy] + ix += incX + iy += incY + idst += incDst + } +} + +func BenchmarkF64AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, AxpyIncTo) } + +func BenchmarkF64AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, AxpyIncTo) } +func BenchmarkF64AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, AxpyIncTo) } + +func BenchmarkLF64AxpyIncToN1Inc1(b *testing.B) { benchaxpyincto(b, 1, 1, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN2Inc1(b *testing.B) { benchaxpyincto(b, 2, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN2Inc2(b *testing.B) { benchaxpyincto(b, 2, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN2Inc4(b *testing.B) { benchaxpyincto(b, 2, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN2Inc10(b *testing.B) { benchaxpyincto(b, 2, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN3Inc1(b *testing.B) { benchaxpyincto(b, 3, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN3Inc2(b *testing.B) { benchaxpyincto(b, 3, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN3Inc4(b *testing.B) { benchaxpyincto(b, 3, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN3Inc10(b *testing.B) { benchaxpyincto(b, 3, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN4Inc1(b *testing.B) { benchaxpyincto(b, 4, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN4Inc2(b *testing.B) { benchaxpyincto(b, 4, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN4Inc4(b *testing.B) { benchaxpyincto(b, 4, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN4Inc10(b *testing.B) { benchaxpyincto(b, 4, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN10Inc1(b *testing.B) { benchaxpyincto(b, 10, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN10Inc2(b *testing.B) { benchaxpyincto(b, 10, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN10Inc4(b *testing.B) { benchaxpyincto(b, 10, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN10Inc10(b *testing.B) { benchaxpyincto(b, 10, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN1000Inc1(b *testing.B) { benchaxpyincto(b, 1000, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN1000Inc2(b *testing.B) { benchaxpyincto(b, 1000, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN1000Inc4(b *testing.B) { benchaxpyincto(b, 1000, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN1000Inc10(b *testing.B) { benchaxpyincto(b, 1000, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN100000Inc1(b *testing.B) { benchaxpyincto(b, 100000, 1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000Inc2(b *testing.B) { benchaxpyincto(b, 100000, 2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000Inc4(b *testing.B) { benchaxpyincto(b, 100000, 4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000Inc10(b *testing.B) { benchaxpyincto(b, 100000, 10, naiveaxpyincto) } + +func BenchmarkLF64AxpyIncToN100000IncM1(b *testing.B) { benchaxpyincto(b, 100000, -1, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000IncM2(b *testing.B) { benchaxpyincto(b, 100000, -2, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000IncM4(b *testing.B) { benchaxpyincto(b, 100000, -4, naiveaxpyincto) } +func BenchmarkLF64AxpyIncToN100000IncM10(b *testing.B) { benchaxpyincto(b, 100000, -10, naiveaxpyincto) } + +// Scal* benchmarks +func BenchmarkDscalUnitaryN1(b *testing.B) { benchmarkDscalUnitary(b, 1) } +func BenchmarkDscalUnitaryN2(b *testing.B) { benchmarkDscalUnitary(b, 2) } +func BenchmarkDscalUnitaryN3(b *testing.B) { benchmarkDscalUnitary(b, 3) } +func BenchmarkDscalUnitaryN4(b *testing.B) { benchmarkDscalUnitary(b, 4) } +func BenchmarkDscalUnitaryN10(b *testing.B) { benchmarkDscalUnitary(b, 10) } +func BenchmarkDscalUnitaryN100(b *testing.B) { benchmarkDscalUnitary(b, 100) } +func BenchmarkDscalUnitaryN1000(b *testing.B) { benchmarkDscalUnitary(b, 1000) } +func BenchmarkDscalUnitaryN10000(b *testing.B) { benchmarkDscalUnitary(b, 10000) } +func BenchmarkDscalUnitaryN100000(b *testing.B) { benchmarkDscalUnitary(b, 100000) } + +func benchmarkDscalUnitary(b *testing.B, n int) { + x := randomSlice(n, 1) + b.ResetTimer() + for i := 0; i < b.N; i += 2 { + ScalUnitary(2, x) + ScalUnitary(0.5, x) + } + benchSink = x +} + +func BenchmarkDscalUnitaryToN1(b *testing.B) { benchmarkDscalUnitaryTo(b, 1) } +func BenchmarkDscalUnitaryToN2(b *testing.B) { benchmarkDscalUnitaryTo(b, 2) } +func BenchmarkDscalUnitaryToN3(b *testing.B) { benchmarkDscalUnitaryTo(b, 3) } +func BenchmarkDscalUnitaryToN4(b *testing.B) { benchmarkDscalUnitaryTo(b, 4) } +func BenchmarkDscalUnitaryToN10(b *testing.B) { benchmarkDscalUnitaryTo(b, 10) } +func BenchmarkDscalUnitaryToN100(b *testing.B) { benchmarkDscalUnitaryTo(b, 100) } +func BenchmarkDscalUnitaryToN1000(b *testing.B) { benchmarkDscalUnitaryTo(b, 1000) } +func BenchmarkDscalUnitaryToN10000(b *testing.B) { benchmarkDscalUnitaryTo(b, 10000) } +func BenchmarkDscalUnitaryToN100000(b *testing.B) { benchmarkDscalUnitaryTo(b, 100000) } + +func benchmarkDscalUnitaryTo(b *testing.B, n int) { + x := randomSlice(n, 1) + dst := randomSlice(n, 1) + a := rand.Float64() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ScalUnitaryTo(dst, a, x) + } + benchSink = dst +} + +func BenchmarkDscalUnitaryToXN1(b *testing.B) { benchmarkDscalUnitaryToX(b, 1) } +func BenchmarkDscalUnitaryToXN2(b *testing.B) { benchmarkDscalUnitaryToX(b, 2) } +func BenchmarkDscalUnitaryToXN3(b *testing.B) { benchmarkDscalUnitaryToX(b, 3) } +func BenchmarkDscalUnitaryToXN4(b *testing.B) { benchmarkDscalUnitaryToX(b, 4) } +func BenchmarkDscalUnitaryToXN10(b *testing.B) { benchmarkDscalUnitaryToX(b, 10) } +func BenchmarkDscalUnitaryToXN100(b *testing.B) { benchmarkDscalUnitaryToX(b, 100) } +func BenchmarkDscalUnitaryToXN1000(b *testing.B) { benchmarkDscalUnitaryToX(b, 1000) } +func BenchmarkDscalUnitaryToXN10000(b *testing.B) { benchmarkDscalUnitaryToX(b, 10000) } +func BenchmarkDscalUnitaryToXN100000(b *testing.B) { benchmarkDscalUnitaryToX(b, 100000) } + +func benchmarkDscalUnitaryToX(b *testing.B, n int) { + x := randomSlice(n, 1) + b.ResetTimer() + for i := 0; i < b.N; i += 2 { + ScalUnitaryTo(x, 2, x) + ScalUnitaryTo(x, 0.5, x) + } + benchSink = x +} + +func BenchmarkDscalIncN1Inc1(b *testing.B) { benchmarkDscalInc(b, 1, 1) } + +func BenchmarkDscalIncN2Inc1(b *testing.B) { benchmarkDscalInc(b, 2, 1) } +func BenchmarkDscalIncN2Inc2(b *testing.B) { benchmarkDscalInc(b, 2, 2) } +func BenchmarkDscalIncN2Inc4(b *testing.B) { benchmarkDscalInc(b, 2, 4) } +func BenchmarkDscalIncN2Inc10(b *testing.B) { benchmarkDscalInc(b, 2, 10) } + +func BenchmarkDscalIncN3Inc1(b *testing.B) { benchmarkDscalInc(b, 3, 1) } +func BenchmarkDscalIncN3Inc2(b *testing.B) { benchmarkDscalInc(b, 3, 2) } +func BenchmarkDscalIncN3Inc4(b *testing.B) { benchmarkDscalInc(b, 3, 4) } +func BenchmarkDscalIncN3Inc10(b *testing.B) { benchmarkDscalInc(b, 3, 10) } + +func BenchmarkDscalIncN4Inc1(b *testing.B) { benchmarkDscalInc(b, 4, 1) } +func BenchmarkDscalIncN4Inc2(b *testing.B) { benchmarkDscalInc(b, 4, 2) } +func BenchmarkDscalIncN4Inc4(b *testing.B) { benchmarkDscalInc(b, 4, 4) } +func BenchmarkDscalIncN4Inc10(b *testing.B) { benchmarkDscalInc(b, 4, 10) } + +func BenchmarkDscalIncN10Inc1(b *testing.B) { benchmarkDscalInc(b, 10, 1) } +func BenchmarkDscalIncN10Inc2(b *testing.B) { benchmarkDscalInc(b, 10, 2) } +func BenchmarkDscalIncN10Inc4(b *testing.B) { benchmarkDscalInc(b, 10, 4) } +func BenchmarkDscalIncN10Inc10(b *testing.B) { benchmarkDscalInc(b, 10, 10) } + +func BenchmarkDscalIncN1000Inc1(b *testing.B) { benchmarkDscalInc(b, 1000, 1) } +func BenchmarkDscalIncN1000Inc2(b *testing.B) { benchmarkDscalInc(b, 1000, 2) } +func BenchmarkDscalIncN1000Inc4(b *testing.B) { benchmarkDscalInc(b, 1000, 4) } +func BenchmarkDscalIncN1000Inc10(b *testing.B) { benchmarkDscalInc(b, 1000, 10) } + +func BenchmarkDscalIncN100000Inc1(b *testing.B) { benchmarkDscalInc(b, 100000, 1) } +func BenchmarkDscalIncN100000Inc2(b *testing.B) { benchmarkDscalInc(b, 100000, 2) } +func BenchmarkDscalIncN100000Inc4(b *testing.B) { benchmarkDscalInc(b, 100000, 4) } +func BenchmarkDscalIncN100000Inc10(b *testing.B) { benchmarkDscalInc(b, 100000, 10) } + +func benchmarkDscalInc(b *testing.B, n, inc int) { + x := randomSlice(n, inc) + b.ResetTimer() + for i := 0; i < b.N; i += 2 { + ScalInc(2, x, uintptr(n), uintptr(inc)) + ScalInc(0.5, x, uintptr(n), uintptr(inc)) + } + benchSink = x +} + +func BenchmarkDscalIncToN1Inc1(b *testing.B) { benchmarkDscalIncTo(b, 1, 1) } + +func BenchmarkDscalIncToN2Inc1(b *testing.B) { benchmarkDscalIncTo(b, 2, 1) } +func BenchmarkDscalIncToN2Inc2(b *testing.B) { benchmarkDscalIncTo(b, 2, 2) } +func BenchmarkDscalIncToN2Inc4(b *testing.B) { benchmarkDscalIncTo(b, 2, 4) } +func BenchmarkDscalIncToN2Inc10(b *testing.B) { benchmarkDscalIncTo(b, 2, 10) } + +func BenchmarkDscalIncToN3Inc1(b *testing.B) { benchmarkDscalIncTo(b, 3, 1) } +func BenchmarkDscalIncToN3Inc2(b *testing.B) { benchmarkDscalIncTo(b, 3, 2) } +func BenchmarkDscalIncToN3Inc4(b *testing.B) { benchmarkDscalIncTo(b, 3, 4) } +func BenchmarkDscalIncToN3Inc10(b *testing.B) { benchmarkDscalIncTo(b, 3, 10) } + +func BenchmarkDscalIncToN4Inc1(b *testing.B) { benchmarkDscalIncTo(b, 4, 1) } +func BenchmarkDscalIncToN4Inc2(b *testing.B) { benchmarkDscalIncTo(b, 4, 2) } +func BenchmarkDscalIncToN4Inc4(b *testing.B) { benchmarkDscalIncTo(b, 4, 4) } +func BenchmarkDscalIncToN4Inc10(b *testing.B) { benchmarkDscalIncTo(b, 4, 10) } + +func BenchmarkDscalIncToN10Inc1(b *testing.B) { benchmarkDscalIncTo(b, 10, 1) } +func BenchmarkDscalIncToN10Inc2(b *testing.B) { benchmarkDscalIncTo(b, 10, 2) } +func BenchmarkDscalIncToN10Inc4(b *testing.B) { benchmarkDscalIncTo(b, 10, 4) } +func BenchmarkDscalIncToN10Inc10(b *testing.B) { benchmarkDscalIncTo(b, 10, 10) } + +func BenchmarkDscalIncToN1000Inc1(b *testing.B) { benchmarkDscalIncTo(b, 1000, 1) } +func BenchmarkDscalIncToN1000Inc2(b *testing.B) { benchmarkDscalIncTo(b, 1000, 2) } +func BenchmarkDscalIncToN1000Inc4(b *testing.B) { benchmarkDscalIncTo(b, 1000, 4) } +func BenchmarkDscalIncToN1000Inc10(b *testing.B) { benchmarkDscalIncTo(b, 1000, 10) } + +func BenchmarkDscalIncToN100000Inc1(b *testing.B) { benchmarkDscalIncTo(b, 100000, 1) } +func BenchmarkDscalIncToN100000Inc2(b *testing.B) { benchmarkDscalIncTo(b, 100000, 2) } +func BenchmarkDscalIncToN100000Inc4(b *testing.B) { benchmarkDscalIncTo(b, 100000, 4) } +func BenchmarkDscalIncToN100000Inc10(b *testing.B) { benchmarkDscalIncTo(b, 100000, 10) } + +func benchmarkDscalIncTo(b *testing.B, n, inc int) { + x := randomSlice(n, inc) + dst := randomSlice(n, inc) + a := rand.Float64() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ScalIncTo(dst, uintptr(inc), a, x, uintptr(n), uintptr(inc)) + } + benchSink = dst +} diff --git a/internal/asm/f64/cumprod_amd64.s b/internal/asm/f64/cumprod_amd64.s new file mode 100644 index 00000000..3d438093 --- /dev/null +++ b/internal/asm/f64/cumprod_amd64.s @@ -0,0 +1,71 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +TEXT ·CumProd(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ s_base+24(FP), SI // SI = &s + CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) + CMOVQLE s_len+32(FP), CX + MOVQ CX, ret_len+56(FP) // len(ret) = CX + CMPQ CX, $0 // if CX == 0 { return } + JE cp_end + XORQ AX, AX // i = 0 + + MOVSD (SI), X5 // p_prod = { s[0], s[0] } + SHUFPD $0, X5, X5 + MOVSD X5, (DI) // dst[0] = s[0] + INCQ AX // ++i + DECQ CX // -- CX + JZ cp_end // if CX == 0 { return } + + MOVQ CX, BX + ANDQ $3, BX // BX = CX % 4 + SHRQ $2, CX // CX = floor( CX / 4 ) + JZ cp_tail_start // if CX == 0 { goto cp_tail_start } + +cp_loop: // Loop unrolled 4x do { + MOVUPS (SI)(AX*8), X0 // X0 = s[i:i+1] + MOVUPS 16(SI)(AX*8), X2 + MOVAPS X0, X1 // X1 = X0 + MOVAPS X2, X3 + SHUFPD $1, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[0] } + SHUFPD $1, X3, X3 + MULPD X0, X1 // X1 *= X0 + MULPD X2, X3 + SHUFPD $2, X1, X0 // { X0[0], X0[1] } = { X0[0], X1[1] } + SHUFPD $3, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[1] } + SHUFPD $2, X3, X2 + SHUFPD $3, X3, X3 + MULPD X5, X0 // X0 *= p_prod + MULPD X1, X5 // p_prod *= X1 + MULPD X5, X2 + MOVUPS X0, (DI)(AX*8) // dst[i] = X0 + MOVUPS X2, 16(DI)(AX*8) + MULPD X3, X5 + ADDQ $4, AX // i += 4 + LOOP cp_loop // } while --CX > 0 + + // if BX == 0 { return } + CMPQ BX, $0 + JE cp_end + +cp_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +cp_tail: // do { + MULSD (SI)(AX*8), X5 // p_prod *= s[i] + MOVSD X5, (DI)(AX*8) // dst[i] = p_prod + INCQ AX // ++i + LOOP cp_tail // } while --CX > 0 + +cp_end: + MOVQ DI, ret_base+48(FP) // &ret = &dst + MOVQ dst_cap+16(FP), SI // cap(ret) = cap(dst) + MOVQ SI, ret_cap+64(FP) + RET diff --git a/internal/asm/f64/cumsum_amd64.s b/internal/asm/f64/cumsum_amd64.s new file mode 100644 index 00000000..eecfbbe1 --- /dev/null +++ b/internal/asm/f64/cumsum_amd64.s @@ -0,0 +1,64 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +TEXT ·CumSum(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ s_base+24(FP), SI // SI = &s + CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) + CMOVQLE s_len+32(FP), CX + MOVQ CX, ret_len+56(FP) // len(ret) = CX + CMPQ CX, $0 // if CX == 0 { return } + JE cs_end + XORQ AX, AX // i = 0 + PXOR X5, X5 // p_sum = 0 + MOVQ CX, BX + ANDQ $3, BX // BX = CX % 4 + SHRQ $2, CX // CX = floor( CX / 4 ) + JZ cs_tail_start // if CX == 0 { goto cs_tail_start } + +cs_loop: // Loop unrolled 4x do { + MOVUPS (SI)(AX*8), X0 // X0 = s[i:i+1] + MOVUPS 16(SI)(AX*8), X2 + MOVAPS X0, X1 // X1 = X0 + MOVAPS X2, X3 + SHUFPD $1, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[0] } + SHUFPD $1, X3, X3 + ADDPD X0, X1 // X1 += X0 + ADDPD X2, X3 + SHUFPD $2, X1, X0 // { X0[0], X0[1] } = { X0[0], X1[1] } + SHUFPD $3, X1, X1 // { X1[0], X1[1] } = { X1[1], X1[1] } + SHUFPD $2, X3, X2 + SHUFPD $3, X3, X3 + ADDPD X5, X0 // X0 += p_sum + ADDPD X1, X5 // p_sum += X1 + ADDPD X5, X2 + MOVUPS X0, (DI)(AX*8) // dst[i] = X0 + MOVUPS X2, 16(DI)(AX*8) + ADDPD X3, X5 + ADDQ $4, AX // i += 4 + LOOP cs_loop // } while --CX > 0 + + // if BX == 0 { return } + CMPQ BX, $0 + JE cs_end + +cs_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +cs_tail: // do { + ADDSD (SI)(AX*8), X5 // p_sum *= s[i] + MOVSD X5, (DI)(AX*8) // dst[i] = p_sum + INCQ AX // ++i + LOOP cs_tail // } while --CX > 0 + +cs_end: + MOVQ DI, ret_base+48(FP) // &ret = &dst + MOVQ dst_cap+16(FP), SI // cap(ret) = cap(dst) + MOVQ SI, ret_cap+64(FP) + RET diff --git a/internal/asm/f64/div_amd64.s b/internal/asm/f64/div_amd64.s new file mode 100644 index 00000000..da417708 --- /dev/null +++ b/internal/asm/f64/div_amd64.s @@ -0,0 +1,67 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func Div(dst, s []float64) +TEXT ·Div(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ s_base+24(FP), SI // SI = &s + CMPQ s_len+32(FP), CX // CX = max( CX, len(s) ) + CMOVQLE s_len+32(FP), CX + CMPQ CX, $0 // if CX == 0 { return } + JE div_end + XORQ AX, AX // i = 0 + MOVQ SI, BX + ANDQ $15, BX // BX = &s & 15 + JZ div_no_trim // if BX == 0 { goto div_no_trim } + + // Align on 16-bit boundary + MOVSD (DI)(AX*8), X0 // X0 = dst[i] + DIVSD (SI)(AX*8), X0 // X0 /= s[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // ++i + DECQ CX // --CX + JZ div_end // if CX == 0 { return } + +div_no_trim: + MOVQ CX, BX + ANDQ $7, BX // BX = len(dst) % 8 + SHRQ $3, CX // CX = floor( len(dst) / 8 ) + JZ div_tail_start // if CX == 0 { goto div_tail_start } + +div_loop: // Loop unrolled 8x do { + MOVUPS (DI)(AX*8), X0 // X0 = dst[i:i+1] + MOVUPS 16(DI)(AX*8), X1 + MOVUPS 32(DI)(AX*8), X2 + MOVUPS 48(DI)(AX*8), X3 + DIVPD (SI)(AX*8), X0 // X0 /= s[i:i+1] + DIVPD 16(SI)(AX*8), X1 + DIVPD 32(SI)(AX*8), X2 + DIVPD 48(SI)(AX*8), X3 + MOVUPS X0, (DI)(AX*8) // dst[i] = X0 + MOVUPS X1, 16(DI)(AX*8) + MOVUPS X2, 32(DI)(AX*8) + MOVUPS X3, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + LOOP div_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE div_end + +div_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +div_tail: // do { + MOVSD (DI)(AX*8), X0 // X0 = dst[i] + DIVSD (SI)(AX*8), X0 // X0 /= s[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // ++i + LOOP div_tail // } while --CX > 0 + +div_end: + RET + diff --git a/internal/asm/f64/divto_amd64.s b/internal/asm/f64/divto_amd64.s new file mode 100644 index 00000000..6280aab4 --- /dev/null +++ b/internal/asm/f64/divto_amd64.s @@ -0,0 +1,73 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func DivTo(dst, x, y []float64) +TEXT ·DivTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DI // DI = &dst + MOVQ dst_len+8(FP), CX // CX = len(dst) + MOVQ x_base+24(FP), SI // SI = &x + MOVQ y_base+48(FP), DX // DX = &y + CMPQ x_len+32(FP), CX // CX = max( len(dst), len(x), len(y) ) + CMOVQLE x_len+32(FP), CX + CMPQ y_len+56(FP), CX + CMOVQLE y_len+56(FP), CX + MOVQ CX, ret_len+80(FP) // len(ret) = CX + CMPQ CX, $0 // if CX == 0 { return } + JE div_end + XORQ AX, AX // i = 0 + MOVQ DX, BX + ANDQ $15, BX // BX = &y & OxF + JZ div_no_trim // if BX == 0 { goto div_no_trim } + + // Align on 16-bit boundary + MOVSD (SI)(AX*8), X0 // X0 = s[i] + DIVSD (DX)(AX*8), X0 // X0 /= t[i] + MOVSD X0, (DI)(AX*8) // dst[i] = X0 + INCQ AX // ++i + DECQ CX // --CX + JZ div_end // if CX == 0 { return } + +div_no_trim: + MOVQ CX, BX + ANDQ $7, BX // BX = len(dst) % 8 + SHRQ $3, CX // CX = floor( len(dst) / 8 ) + JZ div_tail_start // if CX == 0 { goto div_tail_start } + +div_loop: // Loop unrolled 8x do { + MOVUPS (SI)(AX*8), X0 // X0 = x[i:i+1] + MOVUPS 16(SI)(AX*8), X1 + MOVUPS 32(SI)(AX*8), X2 + MOVUPS 48(SI)(AX*8), X3 + DIVPD (DX)(AX*8), X0 // X0 /= y[i:i+1] + DIVPD 16(DX)(AX*8), X1 + DIVPD 32(DX)(AX*8), X2 + DIVPD 48(DX)(AX*8), X3 + MOVUPS X0, (DI)(AX*8) // dst[i:i+1] = X0 + MOVUPS X1, 16(DI)(AX*8) + MOVUPS X2, 32(DI)(AX*8) + MOVUPS X3, 48(DI)(AX*8) + ADDQ $8, AX // i += 8 + LOOP div_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE div_end + +div_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + +div_tail: // do { + MOVSD (SI)(AX*8), X0 // X0 = x[i] + DIVSD (DX)(AX*8), X0 // X0 /= y[i] + MOVSD X0, (DI)(AX*8) + INCQ AX // ++i + LOOP div_tail // } while --CX > 0 + +div_end: + MOVQ DI, ret_base+72(FP) // &ret = &dst + MOVQ dst_cap+16(FP), DI // cap(ret) = cap(dst) + MOVQ DI, ret_cap+88(FP) + RET diff --git a/internal/asm/f64/doc.go b/internal/asm/f64/doc.go new file mode 100644 index 00000000..7f1cc87c --- /dev/null +++ b/internal/asm/f64/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package f64 provides float64 vector primitives. +package f64 diff --git a/internal/asm/f64/dot.go b/internal/asm/f64/dot.go new file mode 100644 index 00000000..7b86b5b4 --- /dev/null +++ b/internal/asm/f64/dot.go @@ -0,0 +1,35 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f64 + +// DotUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotUnitary(x, y []float64) (sum float64) { + for i, v := range x { + sum += y[i] * v + } + return sum +} + +// DotInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotInc(x, y []float64, n, incX, incY, ix, iy uintptr) (sum float64) { + for i := 0; i < int(n); i++ { + sum += y[iy] * x[ix] + ix += incX + iy += incY + } + return sum +} diff --git a/internal/asm/f64/dot_amd64.s b/internal/asm/f64/dot_amd64.s new file mode 100644 index 00000000..02e654d5 --- /dev/null +++ b/internal/asm/f64/dot_amd64.s @@ -0,0 +1,145 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//+build !noasm,!appengine + +#include "textflag.h" + +// func DdotUnitary(x, y []float64) (sum float64) +// This function assumes len(y) >= len(x). +TEXT ·DotUnitary(SB), NOSPLIT, $0 + MOVQ x+0(FP), R8 + MOVQ x_len+8(FP), DI // n = len(x) + MOVQ y+24(FP), R9 + + MOVSD $(0.0), X7 // sum = 0 + MOVSD $(0.0), X8 // sum = 0 + + MOVQ $0, SI // i = 0 + SUBQ $4, DI // n -= 4 + JL tail_uni // if n < 0 goto tail_uni + +loop_uni: + // sum += x[i] * y[i] unrolled 4x. + MOVUPD 0(R8)(SI*8), X0 + MOVUPD 0(R9)(SI*8), X1 + MOVUPD 16(R8)(SI*8), X2 + MOVUPD 16(R9)(SI*8), X3 + MULPD X1, X0 + MULPD X3, X2 + ADDPD X0, X7 + ADDPD X2, X8 + + ADDQ $4, SI // i += 4 + SUBQ $4, DI // n -= 4 + JGE loop_uni // if n >= 0 goto loop_uni + +tail_uni: + ADDQ $4, DI // n += 4 + JLE end_uni // if n <= 0 goto end_uni + +onemore_uni: + // sum += x[i] * y[i] for the remaining 1-3 elements. + MOVSD 0(R8)(SI*8), X0 + MOVSD 0(R9)(SI*8), X1 + MULSD X1, X0 + ADDSD X0, X7 + + ADDQ $1, SI // i++ + SUBQ $1, DI // n-- + JNZ onemore_uni // if n != 0 goto onemore_uni + +end_uni: + // Add the four sums together. + ADDPD X8, X7 + MOVSD X7, X0 + UNPCKHPD X7, X7 + ADDSD X0, X7 + MOVSD X7, sum+48(FP) // Return final sum. + RET + +// func DdotInc(x, y []float64, n, incX, incY, ix, iy uintptr) (sum float64) +TEXT ·DotInc(SB), NOSPLIT, $0 + MOVQ x+0(FP), R8 + MOVQ y+24(FP), R9 + MOVQ n+48(FP), CX + MOVQ incX+56(FP), R11 + MOVQ incY+64(FP), R12 + MOVQ ix+72(FP), R13 + MOVQ iy+80(FP), R14 + + MOVSD $(0.0), X7 // sum = 0 + LEAQ (R8)(R13*8), SI // p = &x[ix] + LEAQ (R9)(R14*8), DI // q = &y[ix] + SHLQ $3, R11 // incX *= sizeof(float64) + SHLQ $3, R12 // indY *= sizeof(float64) + + SUBQ $2, CX // n -= 2 + JL tail_inc // if n < 0 goto tail_inc + +loop_inc: + // sum += *p * *q unrolled 2x. + MOVHPD (SI), X0 + MOVHPD (DI), X1 + ADDQ R11, SI // p += incX + ADDQ R12, DI // q += incY + MOVLPD (SI), X0 + MOVLPD (DI), X1 + ADDQ R11, SI // p += incX + ADDQ R12, DI // q += incY + + MULPD X1, X0 + ADDPD X0, X7 + + SUBQ $2, CX // n -= 2 + JGE loop_inc // if n >= 0 goto loop_inc + +tail_inc: + ADDQ $2, CX // n += 2 + JLE end_inc // if n <= 0 goto end_inc + + // sum += *p * *q for the last iteration if n is odd. + MOVSD (SI), X0 + MULSD (DI), X0 + ADDSD X0, X7 + +end_inc: + // Add the two sums together. + MOVSD X7, X0 + UNPCKHPD X7, X7 + ADDSD X0, X7 + MOVSD X7, sum+88(FP) // Return final sum. + RET diff --git a/internal/asm/f64/dot_test.go b/internal/asm/f64/dot_test.go new file mode 100644 index 00000000..5ca88b8b --- /dev/null +++ b/internal/asm/f64/dot_test.go @@ -0,0 +1,280 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f64 + +import ( + "fmt" + "math" + "math/rand" + "testing" +) + +func TestDotUnitary(t *testing.T) { + for i, test := range []struct { + xData []float64 + yData []float64 + + want float64 + }{ + { + xData: []float64{2}, + yData: []float64{-3}, + want: -6, + }, + { + xData: []float64{2, 3}, + yData: []float64{-3, 4}, + want: 6, + }, + { + xData: []float64{2, 3, -4}, + yData: []float64{-3, 4, 5}, + want: -14, + }, + { + xData: []float64{2, 3, -4, -5}, + yData: []float64{-3, 4, 5, -6}, + want: 16, + }, + { + xData: []float64{0, 2, 3, -4, -5}, + yData: []float64{0, -3, 4, 5, -6}, + want: 16, + }, + { + xData: []float64{0, 0, 2, 3, -4, -5}, + yData: []float64{0, 1, -3, 4, 5, -6}, + want: 16, + }, + { + xData: []float64{0, 0, 1, 1, 2, -3, -4}, + yData: []float64{0, 1, 0, 3, -4, 5, -6}, + want: 4, + }, + { + xData: []float64{0, 0, 1, 1, 2, -3, -4, 5}, + yData: []float64{0, 1, 0, 3, -4, 5, -6, 7}, + want: 39, + }, + } { + const msgGuard = "test %v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v" + + x, xFront, xBack := newGuardedVector(test.xData, 1) + y, yFront, yBack := newGuardedVector(test.yData, 1) + got := DotUnitary(x, y) + + if !allNaN(xFront) || !allNaN(xBack) { + t.Errorf(msgGuard, i, "x", xFront, xBack) + } + if !allNaN(yFront) || !allNaN(yBack) { + t.Errorf(msgGuard, i, "y", yFront, yBack) + } + if !equalStrided(test.xData, x, 1) { + t.Errorf("test %v: modified read-only x argument", i) + } + if !equalStrided(test.yData, y, 1) { + t.Errorf("test %v: modified read-only y argument", i) + } + if math.IsNaN(got) { + t.Errorf("test %v: invalid memory read", i) + continue + } + + if got != test.want { + t.Errorf("test %v: unexpected result. want %v, got %v", i, test.want, got) + } + } +} + +func TestDotInc(t *testing.T) { + for i, test := range []struct { + xData []float64 + yData []float64 + + want float64 + wantRev float64 // Result when one of the vectors is reversed. + }{ + { + xData: []float64{2}, + yData: []float64{-3}, + want: -6, + wantRev: -6, + }, + { + xData: []float64{2, 3}, + yData: []float64{-3, 4}, + want: 6, + wantRev: -1, + }, + { + xData: []float64{2, 3, -4}, + yData: []float64{-3, 4, 5}, + want: -14, + wantRev: 34, + }, + { + xData: []float64{2, 3, -4, -5}, + yData: []float64{-3, 4, 5, -6}, + want: 16, + wantRev: 2, + }, + { + xData: []float64{0, 2, 3, -4, -5}, + yData: []float64{0, -3, 4, 5, -6}, + want: 16, + wantRev: 34, + }, + { + xData: []float64{0, 0, 2, 3, -4, -5}, + yData: []float64{0, 1, -3, 4, 5, -6}, + want: 16, + wantRev: -5, + }, + { + xData: []float64{0, 0, 1, 1, 2, -3, -4}, + yData: []float64{0, 1, 0, 3, -4, 5, -6}, + want: 4, + wantRev: -4, + }, + { + xData: []float64{0, 0, 1, 1, 2, -3, -4, 5}, + yData: []float64{0, 1, 0, 3, -4, 5, -6, 7}, + want: 39, + wantRev: 3, + }, + } { + const msgGuard = "%v: out-of-bounds write to %v argument\nfront guard: %v\nback guard: %v" + + for _, incX := range []int{-7, -3, -2, -1, 1, 2, 3, 7} { + for _, incY := range []int{-7, -3, -2, -1, 1, 2, 3, 7} { + n := len(test.xData) + x, xFront, xBack := newGuardedVector(test.xData, incX) + y, yFront, yBack := newGuardedVector(test.yData, incY) + + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + got := DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) + + prefix := fmt.Sprintf("test %v, incX = %v, incY = %v", i, incX, incY) + if !allNaN(xFront) || !allNaN(xBack) { + t.Errorf(msgGuard, prefix, "x", xFront, xBack) + } + if !allNaN(yFront) || !allNaN(yBack) { + t.Errorf(msgGuard, prefix, "y", yFront, yBack) + } + if nonStridedWrite(x, incX) || !equalStrided(test.xData, x, incX) { + t.Errorf("%v: modified read-only x argument", prefix) + } + if nonStridedWrite(y, incY) || !equalStrided(test.yData, y, incY) { + t.Errorf("%v: modified read-only y argument", prefix) + } + if math.IsNaN(got) { + t.Errorf("%v: invalid memory read", prefix) + continue + } + + want := test.want + if incX*incY < 0 { + want = test.wantRev + } + if got != want { + t.Errorf("%v: unexpected result. want %v, got %v", prefix, want, got) + } + } + } + } +} + +func BenchmarkDotUnitaryN1(b *testing.B) { dotUnitaryBenchmark(b, 1) } +func BenchmarkDotUnitaryN2(b *testing.B) { dotUnitaryBenchmark(b, 2) } +func BenchmarkDotUnitaryN3(b *testing.B) { dotUnitaryBenchmark(b, 3) } +func BenchmarkDotUnitaryN4(b *testing.B) { dotUnitaryBenchmark(b, 4) } +func BenchmarkDotUnitaryN10(b *testing.B) { dotUnitaryBenchmark(b, 10) } +func BenchmarkDotUnitaryN100(b *testing.B) { dotUnitaryBenchmark(b, 100) } +func BenchmarkDotUnitaryN1000(b *testing.B) { dotUnitaryBenchmark(b, 1000) } +func BenchmarkDotUnitaryN10000(b *testing.B) { dotUnitaryBenchmark(b, 10000) } +func BenchmarkDotUnitaryN100000(b *testing.B) { dotUnitaryBenchmark(b, 100000) } + +var r float64 + +func dotUnitaryBenchmark(b *testing.B, n int) { + x := make([]float64, n) + for i := range x { + x[i] = rand.Float64() + } + y := make([]float64, n) + for i := range y { + y[i] = rand.Float64() + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + r = DotUnitary(x, y) + } +} + +func BenchmarkDotIncN1Inc1(b *testing.B) { dotIncBenchmark(b, 1, 1) } + +func BenchmarkDotIncN2Inc1(b *testing.B) { dotIncBenchmark(b, 2, 1) } +func BenchmarkDotIncN2Inc2(b *testing.B) { dotIncBenchmark(b, 2, 2) } +func BenchmarkDotIncN2Inc4(b *testing.B) { dotIncBenchmark(b, 2, 4) } +func BenchmarkDotIncN2Inc10(b *testing.B) { dotIncBenchmark(b, 2, 10) } + +func BenchmarkDotIncN3Inc1(b *testing.B) { dotIncBenchmark(b, 3, 1) } +func BenchmarkDotIncN3Inc2(b *testing.B) { dotIncBenchmark(b, 3, 2) } +func BenchmarkDotIncN3Inc4(b *testing.B) { dotIncBenchmark(b, 3, 4) } +func BenchmarkDotIncN3Inc10(b *testing.B) { dotIncBenchmark(b, 3, 10) } + +func BenchmarkDotIncN4Inc1(b *testing.B) { dotIncBenchmark(b, 4, 1) } +func BenchmarkDotIncN4Inc2(b *testing.B) { dotIncBenchmark(b, 4, 2) } +func BenchmarkDotIncN4Inc4(b *testing.B) { dotIncBenchmark(b, 4, 4) } +func BenchmarkDotIncN4Inc10(b *testing.B) { dotIncBenchmark(b, 4, 10) } + +func BenchmarkDotIncN10Inc1(b *testing.B) { dotIncBenchmark(b, 10, 1) } +func BenchmarkDotIncN10Inc2(b *testing.B) { dotIncBenchmark(b, 10, 2) } +func BenchmarkDotIncN10Inc4(b *testing.B) { dotIncBenchmark(b, 10, 4) } +func BenchmarkDotIncN10Inc10(b *testing.B) { dotIncBenchmark(b, 10, 10) } + +func BenchmarkDotIncN1000Inc1(b *testing.B) { dotIncBenchmark(b, 1000, 1) } +func BenchmarkDotIncN1000Inc2(b *testing.B) { dotIncBenchmark(b, 1000, 2) } +func BenchmarkDotIncN1000Inc4(b *testing.B) { dotIncBenchmark(b, 1000, 4) } +func BenchmarkDotIncN1000Inc10(b *testing.B) { dotIncBenchmark(b, 1000, 10) } + +func BenchmarkDotIncN100000Inc1(b *testing.B) { dotIncBenchmark(b, 100000, 1) } +func BenchmarkDotIncN100000Inc2(b *testing.B) { dotIncBenchmark(b, 100000, 2) } +func BenchmarkDotIncN100000Inc4(b *testing.B) { dotIncBenchmark(b, 100000, 4) } +func BenchmarkDotIncN100000Inc10(b *testing.B) { dotIncBenchmark(b, 100000, 10) } + +func BenchmarkDotIncN100000IncM1(b *testing.B) { dotIncBenchmark(b, 100000, -1) } +func BenchmarkDotIncN100000IncM2(b *testing.B) { dotIncBenchmark(b, 100000, -2) } +func BenchmarkDotIncN100000IncM4(b *testing.B) { dotIncBenchmark(b, 100000, -4) } +func BenchmarkDotIncN100000IncM10(b *testing.B) { dotIncBenchmark(b, 100000, -10) } + +func dotIncBenchmark(b *testing.B, n, inc int) { + absInc := inc + if inc < 0 { + absInc = -inc + } + x := make([]float64, (n-1)*absInc+1) + for i := range x { + x[i] = rand.Float64() + } + y := make([]float64, (n-1)*absInc+1) + for i := range y { + y[i] = rand.Float64() + } + var ini int + if inc < 0 { + ini = (-n + 1) * inc + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + r = DotInc(x, y, uintptr(n), uintptr(inc), uintptr(inc), uintptr(ini), uintptr(ini)) + } +} diff --git a/internal/asm/f64/l1norm_amd64.s b/internal/asm/f64/l1norm_amd64.s new file mode 100644 index 00000000..2a8c5a38 --- /dev/null +++ b/internal/asm/f64/l1norm_amd64.s @@ -0,0 +1,58 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func L1Dist(s, t []float64) float64 +TEXT ·L1Dist(SB), NOSPLIT, $0 + MOVQ s_base+0(FP), DI // DI = &s + MOVQ t_base+24(FP), SI // SI = &t + MOVQ s_len+8(FP), CX // CX = len(s) + CMPQ t_len+32(FP), CX // CX = max( CX, len(t) ) + CMOVQLE t_len+32(FP), CX + PXOR X3, X3 // norm = 0 + CMPQ CX, $0 // if CX == 0 { return 0 } + JE l1_end + XORQ AX, AX // i = 0 + MOVQ CX, BX + ANDQ $1, BX // BX = CX % 2 + SHRQ $1, CX // CX = floor( CX / 2 ) + JZ l1_tail_start // if CX == 0 { return 0 } + +l1_loop: // Loop unrolled 2x do { + MOVUPS (SI)(AX*8), X0 // X0 = t[i:i+1] + MOVUPS (DI)(AX*8), X1 // X1 = s[i:i+1] + MOVAPS X0, X2 + SUBPD X1, X0 + SUBPD X2, X1 + MAXPD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) + ADDPD X0, X3 // norm += X0 + ADDQ $2, AX // i += 2 + LOOP l1_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE l1_end + +l1_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + PXOR X0, X0 // reset X0, X1 to break dependencies + PXOR X1, X1 + +l1_tail: + MOVSD (SI)(AX*8), X0 // X0 = t[i] + MOVSD (DI)(AX*8), X1 // x1 = s[i] + MOVAPD X0, X2 + SUBSD X1, X0 + SUBSD X2, X1 + MAXSD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) + ADDSD X0, X3 // norm += X0 + +l1_end: + MOVAPS X3, X2 + SHUFPD $1, X2, X2 + ADDSD X3, X2 // X2 = X3[1] + X3[0] + MOVSD X2, ret+48(FP) // return X2 + RET + diff --git a/internal/asm/f64/linfnorm_amd64.s b/internal/asm/f64/linfnorm_amd64.s new file mode 100644 index 00000000..fb6ef8d2 --- /dev/null +++ b/internal/asm/f64/linfnorm_amd64.s @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !noasm,!appengine + +#include "textflag.h" + +// func LinfDist(s, t []float64) float64 +TEXT ·LinfDist(SB), NOSPLIT, $0 + MOVQ s_base+0(FP), DI // DI = &s + MOVQ t_base+24(FP), SI // SI = &t + MOVQ s_len+8(FP), CX // CX = len(s) + CMPQ t_len+32(FP), CX // CX = max( CX, len(t) ) + CMOVQLE t_len+32(FP), CX + PXOR X3, X3 // norm = 0 + CMPQ CX, $0 // if CX == 0 { return 0 } + JE l1_end + XORQ AX, AX // i = 0 + MOVQ CX, BX + ANDQ $1, BX // BX = CX % 2 + SHRQ $1, CX // CX = floor( CX / 2 ) + JZ l1_tail_start // if CX == 0 { return 0 } + +l1_loop: // Loop unrolled 2x do { + MOVUPS (SI)(AX*8), X0 // X0 = t[i:i+1] + MOVUPS (DI)(AX*8), X1 // X1 = s[i:i+1] + MOVAPS X0, X2 + SUBPD X1, X0 + SUBPD X2, X1 + MAXPD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) + MAXPD X0, X3 // norm = max( norm, X0 ) + ADDQ $2, AX // i += 2 + LOOP l1_loop // } while --CX > 0 + CMPQ BX, $0 // if BX == 0 { return } + JE l1_end + +l1_tail_start: // Reset loop registers + MOVQ BX, CX // Loop counter: CX = BX + PXOR X0, X0 // reset X0, X1 to break dependencies + PXOR X1, X1 + +l1_tail: + MOVSD (SI)(AX*8), X0 // X0 = t[i] + MOVSD (DI)(AX*8), X1 // X1 = s[i] + MOVAPD X0, X2 + SUBSD X1, X0 + SUBSD X2, X1 + MAXSD X1, X0 // X0 = max( X0 - X1, X1 - X0 ) + MAXSD X0, X3 // norm = max( norm, X0 ) + +l1_end: + MOVAPS X3, X2 + SHUFPD $1, X2, X2 + MAXSD X3, X2 // X2 = max( X3[1], X3[0] ) + MOVSD X2, ret+48(FP) // return X2 + RET diff --git a/internal/asm/f64/scal.go b/internal/asm/f64/scal.go new file mode 100644 index 00000000..357e6c4a --- /dev/null +++ b/internal/asm/f64/scal.go @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f64 + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha float64, x []float64) { + for i := range x { + x[i] *= alpha + } +} + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []float64, alpha float64, x []float64) { + for i, v := range x { + dst[i] = alpha * v + } +} + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha float64, x []float64, n, incX uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] *= alpha + ix += incX + } +} + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) { + var idst, ix uintptr + for i := 0; i < int(n); i++ { + dst[idst] = alpha * x[ix] + ix += incX + idst += incDst + } +} diff --git a/internal/asm/f64/scal_test.go b/internal/asm/f64/scal_test.go new file mode 100644 index 00000000..d88b7d10 --- /dev/null +++ b/internal/asm/f64/scal_test.go @@ -0,0 +1,179 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f64 + +import ( + "fmt" + "math/rand" + "testing" +) + +var scalTests = []struct { + alpha float64 + x []float64 + want []float64 +}{ + { + alpha: 0, + x: []float64{}, + want: []float64{}, + }, + { + alpha: 0, + x: []float64{1}, + want: []float64{0}, + }, + { + alpha: 1, + x: []float64{1}, + want: []float64{1}, + }, + { + alpha: 2, + x: []float64{1, -2}, + want: []float64{2, -4}, + }, + { + alpha: 2, + x: []float64{1, -2, 3}, + want: []float64{2, -4, 6}, + }, + { + alpha: 2, + x: []float64{1, -2, 3, 4}, + want: []float64{2, -4, 6, 8}, + }, + { + alpha: 2, + x: []float64{1, -2, 3, 4, -5}, + want: []float64{2, -4, 6, 8, -10}, + }, + { + alpha: 2, + x: []float64{0, 1, -2, 3, 4, -5, 6, -7}, + want: []float64{0, 2, -4, 6, 8, -10, 12, -14}, + }, + { + alpha: 2, + x: []float64{0, 1, -2, 3, 4, -5, 6, -7, 8}, + want: []float64{0, 2, -4, 6, 8, -10, 12, -14, 16}, + }, + { + alpha: 2, + x: []float64{0, 1, -2, 3, 4, -5, 6, -7, 8, 9}, + want: []float64{0, 2, -4, 6, 8, -10, 12, -14, 16, 18}, + }, + { + alpha: 3, + x: []float64{0, 1, -2, 3, 4, -5, 6, -7, 8, 9, 12}, + want: []float64{0, 3, -6, 9, 12, -15, 18, -21, 24, 27, 36}, + }, +} + +func TestScalUnitary(t *testing.T) { + const xGdVal = -0.5 + for i, test := range scalTests { + for _, align := range align1 { + prefix := fmt.Sprintf("Test %v (x:%v)", i, align) + xgLn := 4 + align + xg := guardVector(test.x, xGdVal, xgLn) + x := xg[xgLn : len(xg)-xgLn] + + ScalUnitary(test.alpha, x) + + for i := range test.want { + if !same(x[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, x[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + } + } +} + +func TestScalUnitaryTo(t *testing.T) { + const xGdVal, dstGdVal = -1, 0.5 + rng := rand.New(rand.NewSource(42)) + for i, test := range scalTests { + n := len(test.x) + for _, align := range align2 { + prefix := fmt.Sprintf("Test %v (x:%v dst:%v)", i, align.x, align.y) + xgLn, dgLn := 4+align.x, 4+align.y + xg := guardVector(test.x, xGdVal, xgLn) + dg := guardVector(randSlice(n, 1, rng), dstGdVal, dgLn) + x, dst := xg[xgLn:len(xg)-xgLn], dg[dgLn:len(dg)-dgLn] + + ScalUnitaryTo(dst, test.alpha, x) + + for i := range test.want { + if !same(dst[i], test.want[i]) { + t.Errorf(msgVal, prefix, i, dst[i], test.want[i]) + } + } + if !isValidGuard(xg, xGdVal, xgLn) { + t.Errorf(msgGuard, prefix, "x", xg[:xgLn], xg[len(xg)-xgLn:]) + } + if !isValidGuard(dg, dstGdVal, dgLn) { + t.Errorf(msgGuard, prefix, "y", dg[:dgLn], dg[len(dg)-dgLn:]) + } + if !equalStrided(test.x, x, 1) { + t.Errorf("%v: modified read-only x argument", prefix) + } + } + } +} + +func TestScalInc(t *testing.T) { + const xGdVal = -0.5 + gdLn := 4 + for i, test := range scalTests { + n := len(test.x) + for _, incX := range []int{1, 2, 3, 4, 7, 10} { + prefix := fmt.Sprintf("Test %v (x:%v)", i, incX) + xg := guardIncVector(test.x, xGdVal, incX, gdLn) + x := xg[gdLn : len(xg)-gdLn] + + ScalInc(test.alpha, x, uintptr(n), uintptr(incX)) + + for i := range test.want { + if !same(x[i*incX], test.want[i]) { + t.Errorf(msgVal, prefix, i, x[i*incX], test.want[i]) + } + } + checkValidIncGuard(t, xg, xGdVal, incX, gdLn) + } + } +} + +func TestScalIncTo(t *testing.T) { + const xGdVal, dstGdVal = -1, 0.5 + gdLn := 4 + rng := rand.New(rand.NewSource(42)) + for i, test := range scalTests { + n := len(test.x) + for _, inc := range newIncSet(1, 2, 3, 4, 7, 10) { + prefix := fmt.Sprintf("test %v (x:%v dst:%v)", i, inc.x, inc.y) + xg := guardIncVector(test.x, xGdVal, inc.x, gdLn) + dg := guardIncVector(randSlice(n, 1, rng), dstGdVal, inc.y, gdLn) + x, dst := xg[gdLn:len(xg)-gdLn], dg[gdLn:len(dg)-gdLn] + + ScalIncTo(dst, uintptr(inc.y), test.alpha, x, uintptr(n), uintptr(inc.x)) + + for i := range test.want { + if !same(dst[i*inc.y], test.want[i]) { + t.Errorf(msgVal, prefix, i, dst[i*inc.y], test.want[i]) + } + } + checkValidIncGuard(t, xg, xGdVal, inc.x, gdLn) + checkValidIncGuard(t, dg, dstGdVal, inc.y, gdLn) + if !equalStrided(test.x, x, inc.x) { + t.Errorf("%v: modified read-only x argument", prefix) + } + + } + } +} diff --git a/internal/asm/f64/scalinc_amd64.s b/internal/asm/f64/scalinc_amd64.s new file mode 100644 index 00000000..55a5758e --- /dev/null +++ b/internal/asm/f64/scalinc_amd64.s @@ -0,0 +1,113 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define LEN CX +#define TAIL BX +#define INC_X R8 +#define INCx3_X R9 +#define ALPHA X0 +#define ALPHA_2 X1 + +// func ScalInc(alpha float64, x []float64, n, incX uintptr) +TEXT ·ScalInc(SB), NOSPLIT, $0 + MOVSD alpha+0(FP), ALPHA // ALPHA = alpha + MOVQ x_base+8(FP), X_PTR // X_PTR = &x + MOVQ incX+40(FP), INC_X // INC_X = incX + SHLQ $3, INC_X // INC_X *= sizeof(float64) + MOVQ n+32(FP), LEN // LEN = n + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = LEN % 4 + SHRQ $2, LEN // LEN = floor( LEN / 4 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 + +loop: // do { // x[i] *= alpha unrolled 4x. + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MOVSD (X_PTR)(INC_X*2), X4 + MOVSD (X_PTR)(INCx3_X*1), X5 + + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA_2, X3 + MULSD ALPHA, X4 + MULSD ALPHA_2, X5 + + MOVSD X2, (X_PTR) // x[i] = X_i + MOVSD X3, (X_PTR)(INC_X*1) + MOVSD X4, (X_PTR)(INC_X*2) + MOVSD X5, (X_PTR)(INCx3_X*1) + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 + JE end // if TAIL == 0 { return } + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ tail_one + +tail_two: // do { + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA, X3 + MOVSD X2, (X_PTR) // x[i] = X_i + MOVSD X3, (X_PTR)(INC_X*1) + + LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) + + ANDQ $1, TAIL + JZ end + +tail_one: + MOVSD (X_PTR), X2 // X_i = x[i] + MULSD ALPHA, X2 // X_i *= ALPHA + MOVSD X2, (X_PTR) // x[i] = X_i + +end: + RET diff --git a/internal/asm/f64/scalincto_amd64.s b/internal/asm/f64/scalincto_amd64.s new file mode 100644 index 00000000..57c90a2a --- /dev/null +++ b/internal/asm/f64/scalincto_amd64.s @@ -0,0 +1,122 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define X_PTR SI +#define DST_PTR DI +#define LEN CX +#define TAIL BX +#define INC_X R8 +#define INCx3_X R9 +#define INC_DST R10 +#define INCx3_DST R11 +#define ALPHA X0 +#define ALPHA_2 X1 + +// func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) +TEXT ·ScalIncTo(SB), NOSPLIT, $0 + MOVQ dst_base+0(FP), DST_PTR // DST_PTR = &dst + MOVQ incDst+24(FP), INC_DST // INC_DST = incDst + SHLQ $3, INC_DST // INC_DST *= sizeof(float64) + MOVSD alpha+32(FP), ALPHA // ALPHA = alpha + MOVQ x_base+40(FP), X_PTR // X_PTR = &x + MOVQ n+64(FP), LEN // LEN = n + MOVQ incX+72(FP), INC_X // INC_X = incX + SHLQ $3, INC_X // INC_X *= sizeof(float64) + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = LEN % 4 + SHRQ $2, LEN // LEN = floor( LEN / 4 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + LEAQ (INC_X)(INC_X*2), INCx3_X // INCx3_X = INC_X * 3 + LEAQ (INC_DST)(INC_DST*2), INCx3_DST // INCx3_DST = INC_DST * 3 + +loop: // do { // x[i] *= alpha unrolled 4x. + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MOVSD (X_PTR)(INC_X*2), X4 + MOVSD (X_PTR)(INCx3_X*1), X5 + + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA_2, X3 + MULSD ALPHA, X4 + MULSD ALPHA_2, X5 + + MOVSD X2, (DST_PTR) // dst[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + MOVSD X4, (DST_PTR)(INC_DST*2) + MOVSD X5, (DST_PTR)(INCx3_DST*1) + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[incX*4]) + LEAQ (DST_PTR)(INC_DST*4), DST_PTR // DST_PTR = &(DST_PTR[incDst*4]) + DECQ LEN + JNZ loop // } while --LEN > 0 + CMPQ TAIL, $0 + JE end // if TAIL == 0 { return } + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ tail_one + +tail_two: + MOVSD (X_PTR), X2 // X_i = x[i] + MOVSD (X_PTR)(INC_X*1), X3 + MULSD ALPHA, X2 // X_i *= a + MULSD ALPHA, X3 + MOVSD X2, (DST_PTR) // dst[i] = X_i + MOVSD X3, (DST_PTR)(INC_DST*1) + + LEAQ (X_PTR)(INC_X*2), X_PTR // X_PTR = &(X_PTR[incX*2]) + LEAQ (DST_PTR)(INC_DST*2), DST_PTR // DST_PTR = &(DST_PTR[incDst*2]) + + ANDQ $1, TAIL + JZ end + +tail_one: + MOVSD (X_PTR), X2 // X_i = x[i] + MULSD ALPHA, X2 // X_i *= ALPHA + MOVSD X2, (DST_PTR) // x[i] = X_i + +end: + RET diff --git a/internal/asm/f64/scalunitary_amd64.s b/internal/asm/f64/scalunitary_amd64.s new file mode 100644 index 00000000..da23af77 --- /dev/null +++ b/internal/asm/f64/scalunitary_amd64.s @@ -0,0 +1,112 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x0824 // @ MOVDDUP XMM0, 8[RSP] + +#define X_PTR SI +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_2 X1 + +// func ScalUnitary(alpha float64, x []float64) +TEXT ·ScalUnitary(SB), NOSPLIT, $0 + MOVDDUP_ALPHA // ALPHA = { alpha, alpha } + MOVQ x_base+8(FP), X_PTR // X_PTR = &x + MOVQ x_len+16(FP), LEN // LEN = len(x) + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + XORQ IDX, IDX // IDX = 0 + + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL = LEN % 8 + SHRQ $3, LEN // LEN = floor( LEN / 8 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 + +loop: // do { // x[i] *= alpha unrolled 8x. + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MOVUPS 16(X_PTR)(IDX*8), X3 + MOVUPS 32(X_PTR)(IDX*8), X4 + MOVUPS 48(X_PTR)(IDX*8), X5 + + MULPD ALPHA, X2 // X_i *= ALPHA + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + MOVUPS X2, (X_PTR)(IDX*8) // x[i] = X_i + MOVUPS X3, 16(X_PTR)(IDX*8) + MOVUPS X4, 32(X_PTR)(IDX*8) + MOVUPS X5, 48(X_PTR)(IDX*8) + + ADDQ $8, IDX // i += 8 + DECQ LEN + JNZ loop // while --LEN > 0 + CMPQ TAIL, $0 + JE end // if TAIL == 0 { return } + +tail_start: // Reset loop registers + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( TAIL / 2 ) + JZ tail_one // if n == 0 goto end + +tail_two: // do { + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MULPD ALPHA, X2 // X_i *= ALPHA + MOVUPS X2, (X_PTR)(IDX*8) // x[i] = X_i + ADDQ $2, IDX // i += 2 + DECQ LEN + JNZ tail_two // while --LEN > 0 + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { return } + +tail_one: + // x[i] *= alpha for the remaining element. + MOVSD (X_PTR)(IDX*8), X2 + MULSD ALPHA, X2 + MOVSD X2, (X_PTR)(IDX*8) + +end: + RET diff --git a/internal/asm/f64/scalunitaryto_amd64.s b/internal/asm/f64/scalunitaryto_amd64.s new file mode 100644 index 00000000..3685d5b5 --- /dev/null +++ b/internal/asm/f64/scalunitaryto_amd64.s @@ -0,0 +1,113 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// Some of the loop unrolling code is copied from: +// http://golang.org/src/math/big/arith_amd64.s +// which is distributed under these terms: +// +// Copyright (c) 2012 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//+build !noasm,!appengine + +#include "textflag.h" + +#define MOVDDUP_ALPHA LONG $0x44120FF2; WORD $0x2024 // @ MOVDDUP 32(SP), X0 /*XMM0, 32[RSP]*/ + +#define X_PTR SI +#define DST_PTR DI +#define IDX AX +#define LEN CX +#define TAIL BX +#define ALPHA X0 +#define ALPHA_2 X1 + +// func ScalUnitaryTo(dst []float64, alpha float64, x []float64) +// This function assumes len(dst) >= len(x). +TEXT ·ScalUnitaryTo(SB), NOSPLIT, $0 + MOVQ x_base+32(FP), X_PTR // X_PTR = &x + MOVQ dst_base+0(FP), DST_PTR // DST_PTR = &dst + MOVDDUP_ALPHA // ALPHA = { alpha, alpha } + MOVQ x_len+40(FP), LEN // LEN = len(x) + CMPQ LEN, $0 + JE end // if LEN == 0 { return } + + XORQ IDX, IDX // IDX = 0 + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL = LEN % 8 + SHRQ $3, LEN // LEN = floor( LEN / 8 ) + JZ tail_start // if LEN == 0 { goto tail_start } + + MOVUPS ALPHA, ALPHA_2 // ALPHA_2 = ALPHA for pipelining + +loop: // do { // dst[i] = alpha * x[i] unrolled 8x. + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MOVUPS 16(X_PTR)(IDX*8), X3 + MOVUPS 32(X_PTR)(IDX*8), X4 + MOVUPS 48(X_PTR)(IDX*8), X5 + + MULPD ALPHA, X2 // X_i *= ALPHA + MULPD ALPHA_2, X3 + MULPD ALPHA, X4 + MULPD ALPHA_2, X5 + + MOVUPS X2, (DST_PTR)(IDX*8) // dst[i] = X_i + MOVUPS X3, 16(DST_PTR)(IDX*8) + MOVUPS X4, 32(DST_PTR)(IDX*8) + MOVUPS X5, 48(DST_PTR)(IDX*8) + + ADDQ $8, IDX // i += 8 + DECQ LEN + JNZ loop // while --LEN > 0 + CMPQ TAIL, $0 + JE end // if TAIL == 0 { return } + +tail_start: // Reset loop counters + MOVQ TAIL, LEN // Loop counter: LEN = TAIL + SHRQ $1, LEN // LEN = floor( TAIL / 2 ) + JZ tail_one // if LEN == 0 { goto tail_one } + +tail_two: // do { + MOVUPS (X_PTR)(IDX*8), X2 // X_i = x[i] + MULPD ALPHA, X2 // X_i *= ALPHA + MOVUPS X2, (DST_PTR)(IDX*8) // dst[i] = X_i + ADDQ $2, IDX // i += 2 + DECQ LEN + JNZ tail_two // while --LEN > 0 + + ANDQ $1, TAIL + JZ end // if TAIL == 0 { return } + +tail_one: + MOVSD (X_PTR)(IDX*8), X2 // X_i = x[i] + MULSD ALPHA, X2 // X_i *= ALPHA + MOVSD X2, (DST_PTR)(IDX*8) // dst[i] = X_i + +end: + RET diff --git a/internal/asm/f64/stubs_amd64.go b/internal/asm/f64/stubs_amd64.go new file mode 100644 index 00000000..d4de1919 --- /dev/null +++ b/internal/asm/f64/stubs_amd64.go @@ -0,0 +1,165 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !noasm,!appengine + +package f64 + +// L1Norm is +// for _, v := range x { +// sum += math.Abs(v) +// } +// return sum +func L1Norm(x []float64) (sum float64) + +// L1NormInc is +// for i := 0; i < n*incX; i += incX { +// sum += math.Abs(x[i]) +// } +// return sum +func L1NormInc(x []float64, n, incX int) (sum float64) + +// AddConst is +// for i := range x { +// x[i] += alpha +// } +func AddConst(alpha float64, x []float64) + +// Add is +// for i, v := range s { +// dst[i] += v +// } +func Add(dst, s []float64) + +// AxpyUnitary is +// for i, v := range x { +// y[i] += alpha * v +// } +func AxpyUnitary(alpha float64, x, y []float64) + +// AxpyUnitaryTo is +// for i, v := range x { +// dst[i] = alpha*v + y[i] +// } +func AxpyUnitaryTo(dst []float64, alpha float64, x, y []float64) + +// AxpyInc is +// for i := 0; i < int(n); i++ { +// y[iy] += alpha * x[ix] +// ix += incX +// iy += incY +// } +func AxpyInc(alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) + +// AxpyIncTo is +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha*x[ix] + y[iy] +// ix += incX +// iy += incY +// idst += incDst +// } +func AxpyIncTo(dst []float64, incDst, idst uintptr, alpha float64, x, y []float64, n, incX, incY, ix, iy uintptr) + +// CumSum is +// if len(s) == 0 { +// return dst +// } +// dst[0] = s[0] +// for i, v := range s[1:] { +// dst[i+1] = dst[i] + v +// } +// return dst +func CumSum(dst, s []float64) []float64 + +// CumProd is +// if len(s) == 0 { +// return dst +// } +// dst[0] = s[0] +// for i, v := range s[1:] { +// dst[i+1] = dst[i] * v +// } +// return dst +func CumProd(dst, s []float64) []float64 + +// Div is +// for i, v := range s { +// dst[i] /= v +// } +func Div(dst, s []float64) + +// DivTo is +// for i, v := range s { +// dst[i] = v / t[i] +// } +// return dst +func DivTo(dst, x, y []float64) []float64 + +// DotUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotUnitary(x, y []float64) (sum float64) + +// DotInc is +// for i := 0; i < int(n); i++ { +// sum += y[iy] * x[ix] +// ix += incX +// iy += incY +// } +// return sum +func DotInc(x, y []float64, n, incX, incY, ix, iy uintptr) (sum float64) + +// L1Dist is +// var norm float64 +// for i, v := range s { +// norm += math.Abs(t[i] - v) +// } +// return norm +func L1Dist(s, t []float64) float64 + +// LinfDist is +// var norm float64 +// if len(s) == 0 { +// return 0 +// } +// norm = math.Abs(t[0] - s[0]) +// for i, v := range s[1:] { +// absDiff := math.Abs(t[i+1] - v) +// if absDiff > norm || math.IsNaN(norm) { +// norm = absDiff +// } +// } +// return norm +func LinfDist(s, t []float64) float64 + +// ScalUnitary is +// for i := range x { +// x[i] *= alpha +// } +func ScalUnitary(alpha float64, x []float64) + +// ScalUnitaryTo is +// for i, v := range x { +// dst[i] = alpha * v +// } +func ScalUnitaryTo(dst []float64, alpha float64, x []float64) + +// ScalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] *= alpha +// ix += incX +// } +func ScalInc(alpha float64, x []float64, n, incX uintptr) + +// ScalIncTo is +// var idst, ix uintptr +// for i := 0; i < int(n); i++ { +// dst[idst] = alpha * x[ix] +// ix += incX +// idst += incDst +// } +func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) diff --git a/internal/asm/f64/stubs_noasm.go b/internal/asm/f64/stubs_noasm.go new file mode 100644 index 00000000..5e4ae69c --- /dev/null +++ b/internal/asm/f64/stubs_noasm.go @@ -0,0 +1,157 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !amd64 noasm appengine + +package f64 + +import "math" + +// L1Norm is +// for _, v := range x { +// sum += math.Abs(v) +// } +// return sum +func L1Norm(x []float64) (sum float64) { + for _, v := range x { + sum += math.Abs(v) + } + return sum +} + +// L1NormInc is +// for i := 0; i < n*incX; i += incX { +// sum += math.Abs(x[i]) +// } +// return sum +func L1NormInc(x []float64, n, incX int) (sum float64) { + for i := 0; i < n*incX; i += incX { + sum += math.Abs(x[i]) + } + return sum +} + +// Add is +// for i, v := range s { +// dst[i] += v +// } +func Add(dst, s []float64) { + for i, v := range s { + dst[i] += v + } +} + +// AddConst is +// for i := range x { +// x[i] += alpha +// } +func AddConst(alpha float64, x []float64) { + for i := range x { + x[i] += alpha + } +} + +// CumSum is +// if len(s) == 0 { +// return dst +// } +// dst[0] = s[0] +// for i, v := range s[1:] { +// dst[i+1] = dst[i] + v +// } +// return dst +func CumSum(dst, s []float64) []float64 { + if len(s) == 0 { + return dst + } + dst[0] = s[0] + for i, v := range s[1:] { + dst[i+1] = dst[i] + v + } + return dst +} + +// CumProd is +// if len(s) == 0 { +// return dst +// } +// dst[0] = s[0] +// for i, v := range s[1:] { +// dst[i+1] = dst[i] * v +// } +// return dst +func CumProd(dst, s []float64) []float64 { + if len(s) == 0 { + return dst + } + dst[0] = s[0] + for i, v := range s[1:] { + dst[i+1] = dst[i] * v + } + return dst +} + +// Div is +// for i, v := range s { +// dst[i] /= v +// } +func Div(dst, s []float64) { + for i, v := range s { + dst[i] /= v + } +} + +// DivTo is +// for i, v := range s { +// dst[i] = v / t[i] +// } +// return dst +func DivTo(dst, s, t []float64) []float64 { + for i, v := range s { + dst[i] = v / t[i] + } + return dst +} + +// L1Dist is +// var norm float64 +// for i, v := range s { +// norm += math.Abs(t[i] - v) +// } +// return norm +func L1Dist(s, t []float64) float64 { + var norm float64 + for i, v := range s { + norm += math.Abs(t[i] - v) + } + return norm +} + +// LinfDist is +// var norm float64 +// if len(s) == 0 { +// return 0 +// } +// norm = math.Abs(t[0] - s[0]) +// for i, v := range s[1:] { +// absDiff := math.Abs(t[i+1] - v) +// if absDiff > norm || math.IsNaN(norm) { +// norm = absDiff +// } +// } +// return norm +func LinfDist(s, t []float64) float64 { + var norm float64 + if len(s) == 0 { + return 0 + } + norm = math.Abs(t[0] - s[0]) + for i, v := range s[1:] { + absDiff := math.Abs(t[i+1] - v) + if absDiff > norm || math.IsNaN(norm) { + norm = absDiff + } + } + return norm +} diff --git a/internal/asm/f64/stubs_test.go b/internal/asm/f64/stubs_test.go new file mode 100644 index 00000000..6dd949fc --- /dev/null +++ b/internal/asm/f64/stubs_test.go @@ -0,0 +1,574 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package f64 + +import "testing" + +func TestL1Norm(t *testing.T) { + var src_gd float64 = 1 + for j, v := range []struct { + want float64 + x []float64 + }{ + {want: 0, x: []float64{}}, + {want: 2, x: []float64{2}}, + {want: 6, x: []float64{1, 2, 3}}, + {want: 6, x: []float64{-1, -2, -3}}, + {want: nan, x: []float64{nan}}, + {want: 40, x: []float64{8, -8, 8, -8, 8}}, + {want: 5, x: []float64{0, 1, 0, -1, 0, 1, 0, -1, 0, 1}}, + } { + g_ln := 4 + j%2 + v.x = guardVector(v.x, src_gd, g_ln) + src := v.x[g_ln : len(v.x)-g_ln] + ret := L1Norm(src) + if !same(ret, v.want) { + t.Errorf("Test %d L1Norm error Got: %f Expected: %f", j, ret, v.want) + } + if !isValidGuard(v.x, src_gd, g_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.x[:g_ln], v.x[len(v.x)-g_ln:]) + } + } +} + +func TestL1NormInc(t *testing.T) { + var src_gd float64 = 1 + for j, v := range []struct { + inc int + want float64 + x []float64 + }{ + {inc: 2, want: 0, x: []float64{}}, + {inc: 3, want: 2, x: []float64{2}}, + {inc: 10, want: 6, x: []float64{1, 2, 3}}, + {inc: 5, want: 6, x: []float64{-1, -2, -3}}, + {inc: 3, want: nan, x: []float64{nan}}, + {inc: 15, want: 40, x: []float64{8, -8, 8, -8, 8}}, + {inc: 1, want: 5, x: []float64{0, 1, 0, -1, 0, 1, 0, -1, 0, 1}}, + } { + g_ln, ln := 4+j%2, len(v.x) + v.x = guardIncVector(v.x, src_gd, v.inc, g_ln) + src := v.x[g_ln : len(v.x)-g_ln] + ret := L1NormInc(src, ln, v.inc) + if !same(ret, v.want) { + t.Errorf("Test %d L1NormInc error Got: %f Expected: %f", j, ret, v.want) + } + checkValidIncGuard(t, v.x, src_gd, v.inc, g_ln) + } +} + +func TestAdd(t *testing.T) { + var src_gd, dst_gd float64 = 1, 0 + for j, v := range []struct { + dst, src, expect []float64 + }{ + { + dst: []float64{1}, + src: []float64{0}, + expect: []float64{1}, + }, + { + dst: []float64{1, 2, 3}, + src: []float64{1}, + expect: []float64{2, 2, 3}, + }, + { + dst: []float64{}, + src: []float64{}, + expect: []float64{}, + }, + { + dst: []float64{1}, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{8, 8, 8, 8, 8}, + src: []float64{2, 4, nan, 8, 9}, + expect: []float64{10, 12, nan, 16, 17}, + }, + { + dst: []float64{0, 1, 2, 3, 4}, + src: []float64{-inf, 4, nan, 8, 9}, + expect: []float64{-inf, 5, nan, 11, 13}, + }, + { + dst: make([]float64, 50)[1:49], + src: make([]float64, 50)[1:49], + expect: make([]float64, 50)[1:49], + }, + } { + sg_ln, dg_ln := 4+j%2, 4+j%3 + v.src, v.dst = guardVector(v.src, src_gd, sg_ln), guardVector(v.dst, dst_gd, dg_ln) + src, dst := v.src[sg_ln:len(v.src)-sg_ln], v.dst[dg_ln:len(v.dst)-dg_ln] + Add(dst, src) + for i := range v.expect { + if !same(dst[i], v.expect[i]) { + t.Errorf("Test %d Add error at %d Got: %v Expected: %v", j, i, dst[i], v.expect[i]) + } + } + if !isValidGuard(v.src, src_gd, sg_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:sg_ln], v.src[len(v.src)-sg_ln:]) + } + if !isValidGuard(v.dst, dst_gd, dg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:dg_ln], v.dst[len(v.dst)-dg_ln:]) + } + } +} + +func TestAddConst(t *testing.T) { + var src_gd float64 = 0 + for j, v := range []struct { + alpha float64 + src, expect []float64 + }{ + { + alpha: 1, + src: []float64{0}, + expect: []float64{1}, + }, + { + alpha: 5, + src: []float64{}, + expect: []float64{}, + }, + { + alpha: 1, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + alpha: 8, + src: []float64{2, 4, nan, 8, 9}, + expect: []float64{10, 12, nan, 16, 17}, + }, + { + alpha: inf, + src: []float64{-inf, 4, nan, 8, 9}, + expect: []float64{nan, inf, nan, inf, inf}, + }, + } { + g_ln := 4 + j%2 + v.src = guardVector(v.src, src_gd, g_ln) + src := v.src[g_ln : len(v.src)-g_ln] + AddConst(v.alpha, src) + for i := range v.expect { + if !same(src[i], v.expect[i]) { + t.Errorf("Test %d AddConst error at %d Got: %v Expected: %v", j, i, src[i], v.expect[i]) + } + } + if !isValidGuard(v.src, src_gd, g_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:g_ln], v.src[len(v.src)-g_ln:]) + } + } +} + +func TestCumSum(t *testing.T) { + var src_gd, dst_gd float64 = -1, 0 + for j, v := range []struct { + dst, src, expect []float64 + }{ + { + dst: []float64{}, + src: []float64{}, + expect: []float64{}, + }, + { + dst: []float64{0}, + src: []float64{1}, + expect: []float64{1}, + }, + { + dst: []float64{nan}, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{1, 3, 6}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{1, 3, 6}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3, 4}, + expect: []float64{1, 3, 6, 10}, + }, + { + dst: []float64{1, nan, nan, 1, 1}, + src: []float64{1, 1, nan, 1, 1}, + expect: []float64{1, 2, nan, nan, nan}, + }, + { + dst: []float64{nan, 4, inf, -inf, 9}, + src: []float64{inf, 4, nan, -inf, 9}, + expect: []float64{inf, inf, nan, nan, nan}, + }, + { + dst: make([]float64, 16), + src: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + expect: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, + }, + } { + g_ln := 4 + j%2 + v.src, v.dst = guardVector(v.src, src_gd, g_ln), guardVector(v.dst, dst_gd, g_ln) + src, dst := v.src[g_ln:len(v.src)-g_ln], v.dst[g_ln:len(v.dst)-g_ln] + ret := CumSum(dst, src) + for i := range v.expect { + if !same(ret[i], v.expect[i]) { + t.Errorf("Test %d CumSum error at %d Got: %v Expected: %v", j, i, ret[i], v.expect[i]) + } + if !same(ret[i], dst[i]) { + t.Errorf("Test %d CumSum ret/dst mismatch %d Ret: %v Dst: %v", j, i, ret[i], dst[i]) + } + } + if !isValidGuard(v.src, src_gd, g_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:g_ln], v.src[len(v.src)-g_ln:]) + } + if !isValidGuard(v.dst, dst_gd, g_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:g_ln], v.dst[len(v.dst)-g_ln:]) + } + } +} + +func TestCumProd(t *testing.T) { + var src_gd, dst_gd float64 = -1, 1 + for j, v := range []struct { + dst, src, expect []float64 + }{ + { + dst: []float64{}, + src: []float64{}, + expect: []float64{}, + }, + { + dst: []float64{1}, + src: []float64{1}, + expect: []float64{1}, + }, + { + dst: []float64{nan}, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3, 4}, + expect: []float64{1, 2, 6, 24}, + }, + { + dst: []float64{0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{1, 2, 6}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{1, 2, 6}, + }, + { + dst: []float64{nan, 1, nan, 1, 0}, + src: []float64{1, 1, nan, 1, 1}, + expect: []float64{1, 1, nan, nan, nan}, + }, + { + dst: []float64{nan, 4, nan, -inf, 9}, + src: []float64{inf, 4, nan, -inf, 9}, + expect: []float64{inf, inf, nan, nan, nan}, + }, + { + dst: make([]float64, 18), + src: []float64{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, + expect: []float64{2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}, + }, + } { + sg_ln, dg_ln := 4+j%2, 4+j%3 + v.src, v.dst = guardVector(v.src, src_gd, sg_ln), guardVector(v.dst, dst_gd, dg_ln) + src, dst := v.src[sg_ln:len(v.src)-sg_ln], v.dst[dg_ln:len(v.dst)-dg_ln] + ret := CumProd(dst, src) + for i := range v.expect { + if !same(ret[i], v.expect[i]) { + t.Errorf("Test %d CumProd error at %d Got: %v Expected: %v", j, i, ret[i], v.expect[i]) + } + if !same(ret[i], dst[i]) { + t.Errorf("Test %d CumProd ret/dst mismatch %d Ret: %v Dst: %v", j, i, ret[i], dst[i]) + } + } + if !isValidGuard(v.src, src_gd, sg_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:sg_ln], v.src[len(v.src)-sg_ln:]) + } + if !isValidGuard(v.dst, dst_gd, dg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:dg_ln], v.dst[len(v.dst)-dg_ln:]) + } + } +} + +func TestDiv(t *testing.T) { + var src_gd, dst_gd float64 = -1, 0.5 + for j, v := range []struct { + dst, src, expect []float64 + }{ + { + dst: []float64{1}, + src: []float64{1}, + expect: []float64{1}, + }, + { + dst: []float64{nan}, + src: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{1, 2, 3, 4}, + src: []float64{1, 2, 3, 4}, + expect: []float64{1, 1, 1, 1}, + }, + { + dst: []float64{1, 2, 3, 4, 2, 4, 6, 8}, + src: []float64{1, 2, 3, 4, 1, 2, 3, 4}, + expect: []float64{1, 1, 1, 1, 2, 2, 2, 2}, + }, + { + dst: []float64{2, 4, 6}, + src: []float64{1, 2, 3}, + expect: []float64{2, 2, 2}, + }, + { + dst: []float64{0, 0, 0, 0}, + src: []float64{1, 2, 3}, + expect: []float64{0, 0, 0}, + }, + { + dst: []float64{nan, 1, nan, 1, 0, nan, 1, nan, 1, 0}, + src: []float64{1, 1, nan, 1, 1, 1, 1, nan, 1, 1}, + expect: []float64{nan, 1, nan, 1, 0, nan, 1, nan, 1, 0}, + }, + { + dst: []float64{inf, 4, nan, -inf, 9, inf, 4, nan, -inf, 9}, + src: []float64{inf, 4, nan, -inf, 3, inf, 4, nan, -inf, 3}, + expect: []float64{nan, 1, nan, nan, 3, nan, 1, nan, nan, 3}, + }, + } { + sg_ln, dg_ln := 4+j%2, 4+j%3 + v.src, v.dst = guardVector(v.src, src_gd, sg_ln), guardVector(v.dst, dst_gd, dg_ln) + src, dst := v.src[sg_ln:len(v.src)-sg_ln], v.dst[dg_ln:len(v.dst)-dg_ln] + Div(dst, src) + for i := range v.expect { + if !same(dst[i], v.expect[i]) { + t.Errorf("Test %d Div error at %d Got: %v Expected: %v", j, i, dst[i], v.expect[i]) + } + } + if !isValidGuard(v.src, src_gd, sg_ln) { + t.Errorf("Test %d Guard violated in src vector %v %v", j, v.src[:sg_ln], v.src[len(v.src)-sg_ln:]) + } + if !isValidGuard(v.dst, dst_gd, dg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:dg_ln], v.dst[len(v.dst)-dg_ln:]) + } + } +} + +func TestDivTo(t *testing.T) { + var dst_gd, x_gd, y_gd float64 = -1, 0.5, 0.25 + for j, v := range []struct { + dst, x, y, expect []float64 + }{ + { + dst: []float64{1}, + x: []float64{1}, + y: []float64{1}, + expect: []float64{1}, + }, + { + dst: []float64{1}, + x: []float64{nan}, + y: []float64{nan}, + expect: []float64{nan}, + }, + { + dst: []float64{-2, -2, -2}, + x: []float64{1, 2, 3}, + y: []float64{1, 2, 3}, + expect: []float64{1, 1, 1}, + }, + { + dst: []float64{0, 0, 0}, + x: []float64{2, 4, 6}, + y: []float64{1, 2, 3, 4}, + expect: []float64{2, 2, 2}, + }, + { + dst: []float64{-1, -1, -1}, + x: []float64{0, 0, 0}, + y: []float64{1, 2, 3}, + expect: []float64{0, 0, 0}, + }, + { + dst: []float64{inf, inf, inf, inf, inf, inf, inf, inf, inf, inf}, + x: []float64{nan, 1, nan, 1, 0, nan, 1, nan, 1, 0}, + y: []float64{1, 1, nan, 1, 1, 1, 1, nan, 1, 1}, + expect: []float64{nan, 1, nan, 1, 0, nan, 1, nan, 1, 0}, + }, + { + dst: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + x: []float64{inf, 4, nan, -inf, 9, inf, 4, nan, -inf, 9}, + y: []float64{inf, 4, nan, -inf, 3, inf, 4, nan, -inf, 3}, + expect: []float64{nan, 1, nan, nan, 3, nan, 1, nan, nan, 3}, + }, + } { + xg_ln, yg_ln := 4+j%2, 4+j%3 + v.y, v.x = guardVector(v.y, y_gd, yg_ln), guardVector(v.x, x_gd, xg_ln) + y, x := v.y[yg_ln:len(v.y)-yg_ln], v.x[xg_ln:len(v.x)-xg_ln] + v.dst = guardVector(v.dst, dst_gd, xg_ln) + dst := v.dst[xg_ln : len(v.dst)-xg_ln] + ret := DivTo(dst, x, y) + for i := range v.expect { + if !same(ret[i], v.expect[i]) { + t.Errorf("Test %d DivTo error at %d Got: %v Expected: %v", j, i, ret[i], v.expect[i]) + } + if !same(ret[i], dst[i]) { + t.Errorf("Test %d DivTo ret/dst mismatch %d Ret: %v Dst: %v", j, i, ret[i], dst[i]) + } + } + if !isValidGuard(v.y, y_gd, yg_ln) { + t.Errorf("Test %d Guard violated in y vector %v %v", j, v.y[:yg_ln], v.y[len(v.y)-yg_ln:]) + } + if !isValidGuard(v.x, x_gd, xg_ln) { + t.Errorf("Test %d Guard violated in x vector %v %v", j, v.x[:xg_ln], v.x[len(v.x)-xg_ln:]) + } + if !isValidGuard(v.dst, dst_gd, xg_ln) { + t.Errorf("Test %d Guard violated in dst vector %v %v", j, v.dst[:xg_ln], v.dst[len(v.dst)-xg_ln:]) + } + } +} + +func TestL1Dist(t *testing.T) { + var t_gd, s_gd float64 = -inf, inf + for j, v := range []struct { + s, t []float64 + expect float64 + }{ + { + s: []float64{1}, + t: []float64{1}, + expect: 0, + }, + { + s: []float64{nan}, + t: []float64{nan}, + expect: nan, + }, + { + s: []float64{1, 2, 3, 4}, + t: []float64{1, 2, 3, 4}, + expect: 0, + }, + { + s: []float64{2, 4, 6}, + t: []float64{1, 2, 3, 4}, + expect: 6, + }, + { + s: []float64{0, 0, 0}, + t: []float64{1, 2, 3}, + expect: 6, + }, + { + s: []float64{0, -4, -10}, + t: []float64{1, 2, 3}, + expect: 20, + }, + { + s: []float64{0, 1, 0, 1, 0}, + t: []float64{1, 1, inf, 1, 1}, + expect: inf, + }, + { + s: []float64{inf, 4, nan, -inf, 9}, + t: []float64{inf, 4, nan, -inf, 3}, + expect: nan, + }, + } { + sg_ln, tg_ln := 4+j%2, 4+j%3 + v.s, v.t = guardVector(v.s, s_gd, sg_ln), guardVector(v.t, t_gd, tg_ln) + s_lc, t_lc := v.s[sg_ln:len(v.s)-sg_ln], v.t[tg_ln:len(v.t)-tg_ln] + ret := L1Dist(s_lc, t_lc) + if !same(ret, v.expect) { + t.Errorf("Test %d L1Dist error Got: %f Expected: %f", j, ret, v.expect) + } + if !isValidGuard(v.s, s_gd, sg_ln) { + t.Errorf("Test %d Guard violated in s vector %v %v", j, v.s[:sg_ln], v.s[len(v.s)-sg_ln:]) + } + if !isValidGuard(v.t, t_gd, tg_ln) { + t.Errorf("Test %d Guard violated in t vector %v %v", j, v.t[:tg_ln], v.t[len(v.t)-tg_ln:]) + } + } +} + +func TestLinfDist(t *testing.T) { + var t_gd, s_gd float64 = 0, inf + for j, v := range []struct { + s, t []float64 + expect float64 + }{ + { + s: []float64{}, + t: []float64{}, + expect: 0, + }, + { + s: []float64{1}, + t: []float64{1}, + expect: 0, + }, + { + s: []float64{nan}, + t: []float64{nan}, + expect: nan, + }, + { + s: []float64{1, 2, 3, 4}, + t: []float64{1, 2, 3, 4}, + expect: 0, + }, + { + s: []float64{2, 4, 6}, + t: []float64{1, 2, 3, 4}, + expect: 3, + }, + { + s: []float64{0, 0, 0}, + t: []float64{1, 2, 3}, + expect: 3, + }, + { + s: []float64{0, 1, 0, 1, 0}, + t: []float64{1, 1, inf, 1, 1}, + expect: inf, + }, + { + s: []float64{inf, 4, nan, -inf, 9}, + t: []float64{inf, 4, nan, -inf, 3}, + expect: 6, + }, + } { + sg_ln, tg_ln := 4+j%2, 4+j%3 + v.s, v.t = guardVector(v.s, s_gd, sg_ln), guardVector(v.t, t_gd, tg_ln) + s_lc, t_lc := v.s[sg_ln:len(v.s)-sg_ln], v.t[tg_ln:len(v.t)-tg_ln] + ret := LinfDist(s_lc, t_lc) + if !same(ret, v.expect) { + t.Errorf("Test %d LinfDist error Got: %f Expected: %f", j, ret, v.expect) + } + if !isValidGuard(v.s, s_gd, sg_ln) { + t.Errorf("Test %d Guard violated in s vector %v %v", j, v.s[:sg_ln], v.s[len(v.s)-sg_ln:]) + } + if !isValidGuard(v.t, t_gd, tg_ln) { + t.Errorf("Test %d Guard violated in t vector %v %v", j, v.t[:tg_ln], v.t[len(v.t)-tg_ln:]) + } + } +} diff --git a/internal/binding/binding.go b/internal/binding/binding.go new file mode 100644 index 00000000..1b02a4bb --- /dev/null +++ b/internal/binding/binding.go @@ -0,0 +1,408 @@ +// Copyright ©2016 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package binding provides helpers for building autogenerated cgo bindings. +package binding + +import ( + "bytes" + "fmt" + "go/ast" + "go/parser" + "go/token" + "sort" + "text/template" + "unsafe" + + "github.com/cznic/cc" + "github.com/cznic/xc" +) + +func model() *cc.Model { + p := int(unsafe.Sizeof(uintptr(0))) + i := int(unsafe.Sizeof(int(0))) + return &cc.Model{ + Items: map[cc.Kind]cc.ModelItem{ + cc.Ptr: {Size: p, Align: p, StructAlign: p}, + cc.UintPtr: {Size: p, Align: p, StructAlign: p}, + cc.Void: {Size: 0, Align: 1, StructAlign: 1}, + cc.Char: {Size: 1, Align: 1, StructAlign: 1}, + cc.SChar: {Size: 1, Align: 1, StructAlign: 1}, + cc.UChar: {Size: 1, Align: 1, StructAlign: 1}, + cc.Short: {Size: 2, Align: 2, StructAlign: 2}, + cc.UShort: {Size: 2, Align: 2, StructAlign: 2}, + cc.Int: {Size: 4, Align: 4, StructAlign: 4}, + cc.UInt: {Size: 4, Align: 4, StructAlign: 4}, + cc.Long: {Size: i, Align: i, StructAlign: i}, + cc.ULong: {Size: i, Align: i, StructAlign: i}, + cc.LongLong: {Size: 8, Align: 8, StructAlign: 8}, + cc.ULongLong: {Size: 8, Align: 8, StructAlign: 8}, + cc.Float: {Size: 4, Align: 4, StructAlign: 4}, + cc.Double: {Size: 8, Align: 8, StructAlign: 8}, + cc.LongDouble: {Size: 8, Align: 8, StructAlign: 8}, + cc.Bool: {Size: 1, Align: 1, StructAlign: 1}, + cc.FloatComplex: {Size: 8, Align: 8, StructAlign: 8}, + cc.DoubleComplex: {Size: 16, Align: 16, StructAlign: 16}, + cc.LongDoubleComplex: {Size: 16, Align: 16, StructAlign: 16}, + }, + } +} + +// TypeKey is a terse C type description. +type TypeKey struct { + IsPointer bool + Kind cc.Kind +} + +var goTypes = map[TypeKey]*template.Template{ + {Kind: cc.Undefined}: template.Must(template.New("").Parse("")), + {Kind: cc.Int}: template.Must(template.New("int").Parse("int")), + {Kind: cc.Float}: template.Must(template.New("float32").Parse("float32")), + {Kind: cc.Float, IsPointer: true}: template.Must(template.New("[]float32").Parse("[]float32")), + {Kind: cc.Double}: template.Must(template.New("float64").Parse("float64")), + {Kind: cc.Double, IsPointer: true}: template.Must(template.New("[]float64").Parse("[]float64")), + {Kind: cc.Bool}: template.Must(template.New("bool").Parse("bool")), + {Kind: cc.FloatComplex}: template.Must(template.New("complex64").Parse("complex64")), + {Kind: cc.DoubleComplex}: template.Must(template.New("complex128").Parse("complex128")), +} + +// GoTypeFor returns a string representation of the given type using a mapping in +// types. GoTypeFor will panic if no type mapping is found after searching the +// user-provided types mappings and then the following mapping: +// {Kind: cc.Int}: "int", +// {Kind: cc.Float}: "float32", +// {Kind: cc.Float, IsPointer: true}: "[]float32", +// {Kind: cc.Double}: "float64", +// {Kind: cc.Double, IsPointer: true}: "[]float64", +// {Kind: cc.Bool}: "bool", +// {Kind: cc.FloatComplex}: "complex64", +// {Kind: cc.DoubleComplex}: "complex128", +func GoTypeFor(typ cc.Type, name string, types ...map[TypeKey]*template.Template) string { + if typ == nil { + return "" + } + k := typ.Kind() + isPtr := typ.Kind() == cc.Ptr + if isPtr { + k = typ.Element().Kind() + } + var buf bytes.Buffer + for _, t := range types { + if s, ok := t[TypeKey{Kind: k, IsPointer: isPtr}]; ok { + err := s.Execute(&buf, name) + if err != nil { + panic(err) + } + return buf.String() + } + } + s, ok := goTypes[TypeKey{Kind: k, IsPointer: isPtr}] + if ok { + err := s.Execute(&buf, name) + if err != nil { + panic(err) + } + return buf.String() + } + panic(fmt.Sprintf("unknown type key: %+v", TypeKey{Kind: k, IsPointer: isPtr})) +} + +// GoTypeForEnum returns a string representation of the given enum type using a mapping +// in types. GoTypeForEnum will panic if no type mapping is found after searching the +// user-provided types mappings or the type is not an enum. +func GoTypeForEnum(typ cc.Type, name string, types ...map[string]*template.Template) string { + if typ == nil { + return "" + } + if typ.Kind() != cc.Enum { + panic(fmt.Sprintf("invalid type: %v", typ)) + } + tag := typ.Tag() + if tag != 0 { + n := string(xc.Dict.S(tag)) + for _, t := range types { + if s, ok := t[n]; ok { + var buf bytes.Buffer + err := s.Execute(&buf, name) + if err != nil { + panic(err) + } + return buf.String() + } + } + } + panic(fmt.Sprintf("unknown type: %+v", typ)) +} + +var cgoTypes = map[TypeKey]*template.Template{ + {Kind: cc.Void, IsPointer: true}: template.Must(template.New("void*").Parse("unsafe.Pointer(&{{.}}[0])")), + + {Kind: cc.Int}: template.Must(template.New("int").Parse("C.int({{.}})")), + + {Kind: cc.Float}: template.Must(template.New("float").Parse("C.float({{.}})")), + {Kind: cc.Double}: template.Must(template.New("double").Parse("C.double({{.}})")), + + {Kind: cc.Float, IsPointer: true}: template.Must(template.New("float*").Parse("(*C.float)(&{{.}}[0])")), + {Kind: cc.Double, IsPointer: true}: template.Must(template.New("double*").Parse("(*C.double)(&{{.}}[0])")), + + {Kind: cc.Bool}: template.Must(template.New("bool").Parse("C.bool({{.}})")), + + {Kind: cc.FloatComplex}: template.Must(template.New("floatcomplex").Parse("unsafe.Pointer({{.}})")), + {Kind: cc.DoubleComplex}: template.Must(template.New("doublecomplex").Parse("unsafe.Pointer({{.}})")), + {Kind: cc.FloatComplex, IsPointer: true}: template.Must(template.New("floatcomplex*").Parse("unsafe.Pointer(&{{.}}[0])")), + {Kind: cc.DoubleComplex, IsPointer: true}: template.Must(template.New("doublecomplex*").Parse("unsafe.Pointer(&{{.}}[0])")), +} + +// CgoConversionFor returns a string representation of the given type using a mapping in +// types. CgoConversionFor will panic if no type mapping is found after searching the +// user-provided types mappings and then the following mapping: +// {Kind: cc.Void, IsPointer: true}: "unsafe.Pointer(&{{.}}[0])", +// {Kind: cc.Int}: "C.int({{.}})", +// {Kind: cc.Float}: "C.float({{.}})", +// {Kind: cc.Float, IsPointer: true}: "(*C.float)({{.}})", +// {Kind: cc.Double}: "C.double({{.}})", +// {Kind: cc.Double, IsPointer: true}: "(*C.double)({{.}})", +// {Kind: cc.Bool}: "C.bool({{.}})", +// {Kind: cc.FloatComplex}: "unsafe.Pointer(&{{.}})", +// {Kind: cc.DoubleComplex}: "unsafe.Pointer(&{{.}})", +// {Kind: cc.FloatComplex, IsPointer: true}: "unsafe.Pointer(&{{.}}[0])", +// {Kind: cc.DoubleComplex, IsPointer: true}: "unsafe.Pointer(&{{.}}[0])", +func CgoConversionFor(name string, typ cc.Type, types ...map[TypeKey]*template.Template) string { + if typ == nil { + return "" + } + k := typ.Kind() + isPtr := typ.Kind() == cc.Ptr + if isPtr { + k = typ.Element().Kind() + } + for _, t := range types { + if s, ok := t[TypeKey{Kind: k, IsPointer: isPtr}]; ok { + var buf bytes.Buffer + err := s.Execute(&buf, name) + if err != nil { + panic(err) + } + return buf.String() + } + } + s, ok := cgoTypes[TypeKey{Kind: k, IsPointer: isPtr}] + if ok { + var buf bytes.Buffer + err := s.Execute(&buf, name) + if err != nil { + panic(err) + } + return buf.String() + } + panic(fmt.Sprintf("unknown type key: %+v", TypeKey{Kind: k, IsPointer: isPtr})) +} + +// CgoConversionForEnum returns a string representation of the given enum type using a mapping +// in types. GoTypeForEnum will panic if no type mapping is found after searching the +// user-provided types mappings or the type is not an enum. +func CgoConversionForEnum(name string, typ cc.Type, types ...map[string]*template.Template) string { + if typ == nil { + return "" + } + if typ.Kind() != cc.Enum { + panic(fmt.Sprintf("invalid type: %v", typ)) + } + tag := typ.Tag() + if tag != 0 { + n := string(xc.Dict.S(tag)) + for _, t := range types { + if s, ok := t[n]; ok { + var buf bytes.Buffer + err := s.Execute(&buf, name) + if err != nil { + panic(err) + } + return buf.String() + } + } + } + panic(fmt.Sprintf("unknown type: %+v", typ)) +} + +// LowerCaseFirst returns s with the first character lower-cased. LowerCaseFirst +// assumes s is an ASCII-represented string. +func LowerCaseFirst(s string) string { + if len(s) == 0 { + return s + } + return string(s[0]|' ') + s[1:] +} + +// UpperCaseFirst returns s with the first character upper-cased. UpperCaseFirst +// assumes s is an ASCII-represented string. +func UpperCaseFirst(s string) string { + if len(s) == 0 { + return s + } + return string(s[0]&^' ') + s[1:] +} + +// DocComments returns a map of method documentation comments for the package at the +// given path. The first key of the returned map is the type name and the second +// is the method name. Non-method function documentation are in docs[""]. +func DocComments(path string) (docs map[string]map[string][]*ast.Comment, err error) { + fset := token.NewFileSet() + pkgs, err := parser.ParseDir(fset, path, nil, parser.ParseComments) + if err != nil { + return nil, err + } + + docs = make(map[string]map[string][]*ast.Comment) + for _, p := range pkgs { + for _, f := range p.Files { + for _, n := range f.Decls { + fn, ok := n.(*ast.FuncDecl) + if !ok || fn.Doc == nil { + continue + } + + var typ string + if fn.Recv != nil && len(fn.Recv.List) > 0 { + id, ok := fn.Recv.List[0].Type.(*ast.Ident) + if ok { + typ = id.Name + } + } + doc, ok := docs[typ] + if !ok { + doc = make(map[string][]*ast.Comment) + docs[typ] = doc + } + doc[fn.Name.String()] = fn.Doc.List + } + } + } + + return docs, nil +} + +// Declaration is a description of a C function declaration. +type Declaration struct { + Pos token.Pos + Name string + Return cc.Type + CParameters []cc.Parameter + Variadic bool +} + +// Position returns the token position of the declaration. +func (d *Declaration) Position() token.Position { return xc.FileSet.Position(d.Pos) } + +// Parameter is a C function parameter. +type Parameter struct{ Parameter cc.Parameter } + +// Name returns the name of the parameter. +func (p *Parameter) Name() string { return string(xc.Dict.S(p.Parameter.Name)) } + +// Type returns the C type of the parameter. +func (p *Parameter) Type() cc.Type { return p.Parameter.Type } + +// Kind returns the C kind of the parameter. +func (p *Parameter) Kind() cc.Kind { return p.Parameter.Type.Kind() } + +// Elem returns the pointer type of a pointer parameter or the element type of an +// array parameter. +func (p *Parameter) Elem() cc.Type { return p.Parameter.Type.Element() } + +// Parameters returns the declaration's CParameters converted to a []Parameter. +func (d *Declaration) Parameters() []Parameter { + p := make([]Parameter, len(d.CParameters)) + for i, c := range d.CParameters { + p[i] = Parameter{c} + } + return p +} + +// Declarations returns the C function declarations in the givel set of file paths. +func Declarations(paths ...string) ([]Declaration, error) { + predefined, includePaths, sysIncludePaths, err := cc.HostConfig() + if err != nil { + return nil, fmt.Errorf("binding: failed to get host config: %v", err) + } + + t, err := cc.Parse( + predefined+` +#define __const const +#define __attribute__(...) +#define __extension__ +#define __inline +#define __restrict +unsigned __builtin_bswap32 (unsigned x); +unsigned long long __builtin_bswap64 (unsigned long long x); +`, + paths, + model(), + cc.IncludePaths(includePaths), + cc.SysIncludePaths(sysIncludePaths), + ) + if err != nil { + return nil, fmt.Errorf("binding: failed to parse %q: %v", paths, err) + } + + var decls []Declaration + for ; t != nil; t = t.TranslationUnit { + if t.ExternalDeclaration.Case != 1 /* Declaration */ { + continue + } + + d := t.ExternalDeclaration.Declaration + if d.Case != 0 { + // Other case is 1: StaticAssertDeclaration. + continue + } + + init := d.InitDeclaratorListOpt + if init == nil { + continue + } + idl := init.InitDeclaratorList + if idl.InitDeclaratorList != nil { + // We do not want comma-separated lists. + continue + } + id := idl.InitDeclarator + if id.Case != 0 { + // We do not want assignments. + continue + } + + declarator := id.Declarator + if declarator.Type.Kind() != cc.Function { + // We want only functions. + continue + } + params, variadic := declarator.Type.Parameters() + name, _ := declarator.Identifier() + decls = append(decls, Declaration{ + Pos: declarator.Pos(), + Name: string(xc.Dict.S(name)), + Return: declarator.Type.Result(), + CParameters: params, + Variadic: variadic, + }) + } + + sort.Sort(byPosition(decls)) + + return decls, nil +} + +type byPosition []Declaration + +func (d byPosition) Len() int { return len(d) } +func (d byPosition) Less(i, j int) bool { + iPos := d[i].Position() + jPos := d[j].Position() + if iPos.Filename == jPos.Filename { + return iPos.Line < jPos.Line + } + return iPos.Filename < jPos.Filename +} +func (d byPosition) Swap(i, j int) { d[i], d[j] = d[j], d[i] } diff --git a/lapack/.gitignore b/lapack/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/lapack/.travis/check-generate.sh b/lapack/.travis/check-generate.sh new file mode 100755 index 00000000..d25efa7f --- /dev/null +++ b/lapack/.travis/check-generate.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -ex + +go generate github.com/gonum/lapack/cgo/lapacke +if [ -n "$(git diff)" ]; then + exit 1 +fi diff --git a/lapack/.travis/linux/ATLAS/install.sh b/lapack/.travis/linux/ATLAS/install.sh new file mode 100644 index 00000000..9c93a053 --- /dev/null +++ b/lapack/.travis/linux/ATLAS/install.sh @@ -0,0 +1,26 @@ +set -ex + +# fetch and install ATLAS +sudo apt-get update -qq +sudo apt-get install -qq libatlas-base-dev + + +# fetch and install gonum/blas and gonum/matrix +export CGO_LDFLAGS="-L/usr/lib -latlas -llapack_atlas" +go get github.com/gonum/blas +go get github.com/gonum/matrix/mat64 + +# install lapack against ATLAS +pushd cgo/lapacke +go install -v -x +popd + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/lapack/.travis/linux/OpenBLAS/install.sh b/lapack/.travis/linux/OpenBLAS/install.sh new file mode 100644 index 00000000..bddd62df --- /dev/null +++ b/lapack/.travis/linux/OpenBLAS/install.sh @@ -0,0 +1,71 @@ +set -ex + +CACHE_DIR=${TRAVIS_BUILD_DIR}/.travis/${BLAS_LIB}.cache + +# fetch fortran to build OpenBLAS +sudo apt-get update -qq && sudo apt-get install -qq gfortran + +# check if cache exists +if [ -e ${CACHE_DIR}/last_commit_id ]; then + echo "Cache $CACHE_DIR hit" + LAST_COMMIT="$(git ls-remote git://github.com/xianyi/OpenBLAS HEAD | grep -o '^\S*')" + CACHED_COMMIT="$(cat ${CACHE_DIR}/last_commit_id)" + # determine current OpenBLAS master commit id and compare + # with commit id in cache directory + if [ "$LAST_COMMIT" != "$CACHED_COMMIT" ]; then + echo "Cache Directory $CACHE_DIR has stale commit" + # if commit is different, delete the cache + rm -rf ${CACHE_DIR} + fi +fi + +if [ ! -e ${CACHE_DIR}/last_commit_id ]; then + # Clear cache. + rm -rf ${CACHE_DIR} + + # cache generation + echo "Building cache at $CACHE_DIR" + mkdir ${CACHE_DIR} + sudo git clone --depth=1 git://github.com/xianyi/OpenBLAS + + pushd OpenBLAS + sudo make FC=gfortran &> /dev/null && sudo make PREFIX=${CACHE_DIR} install + popd + + curl http://www.netlib.org/blas/blast-forum/cblas.tgz | tar -zx + + pushd CBLAS + sudo mv Makefile.LINUX Makefile.in + sudo BLLIB=${CACHE_DIR}/lib/libopenblas.a make alllib + sudo mv lib/cblas_LINUX.a ${CACHE_DIR}/lib/libcblas.a + popd + + # Record commit id used to generate cache. + pushd OpenBLAS + echo $(git rev-parse HEAD) > ${CACHE_DIR}/last_commit_id + popd + +fi + +# copy the cache files into /usr +sudo cp -r ${CACHE_DIR}/* /usr/ + +# install gonum/blas against OpenBLAS +# fetch and install gonum/blas +export CGO_LDFLAGS="-L/usr/lib -lopenblas" +go get github.com/gonum/blas + +# install lapacke against OpenBLAS +pushd cgo/lapacke +go install -v -x +popd + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/lapack/.travis/linux/gonum/install.sh b/lapack/.travis/linux/gonum/install.sh new file mode 100644 index 00000000..4ebb7009 --- /dev/null +++ b/lapack/.travis/linux/gonum/install.sh @@ -0,0 +1,14 @@ +set -ex + +# fetch gonum/blas +go get github.com/gonum/blas/native + +# travis compiles commands in script and then executes in bash. By adding +# set -e we are changing the travis build script's behavior, and the set +# -e lives on past the commands we are providing it. Some of the travis +# commands are supposed to exit with non zero status, but then continue +# executing. set -x makes the travis log files extremely verbose and +# difficult to understand. +# +# see travis-ci/travis-ci#5120 +set +ex diff --git a/lapack/README.md b/lapack/README.md new file mode 100644 index 00000000..4e61e4d9 --- /dev/null +++ b/lapack/README.md @@ -0,0 +1,58 @@ +Gonum LAPACK [![Build Status](https://travis-ci.org/gonum/lapack.svg?branch=master)](https://travis-ci.org/gonum/lapack) [![Coverage Status](https://coveralls.io/repos/gonum/lapack/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/lapack?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/lapack?status.svg)](https://godoc.org/github.com/gonum/lapack) +====== + +A collection of packages to provide LAPACK functionality for the Go programming +language (http://golang.org). This provides a partial implementation in native go +and a wrapper using cgo to a c-based implementation. + +## Installation + +``` + go get github.com/gonum/lapack +``` + + +Install OpenBLAS: +``` + git clone https://github.com/xianyi/OpenBLAS + cd OpenBLAS + make +``` + +Then install the lapack/cgo package: +```sh + CGO_LDFLAGS="-L/path/to/OpenBLAS -lopenblas" go install github.com/gonum/lapack/cgo +``` + +For Windows you can download binary packages for OpenBLAS at +http://sourceforge.net/projects/openblas/files/ + +If you want to use a different BLAS package such as the Intel MKL you can +adjust the `CGO_LDFLAGS` variable: +```sh + CGO_LDFLAGS="-lmkl_rt" go install github.com/gonum/lapack/cgo +``` + +## Packages + +### lapack + +Defines the LAPACK API based on http://www.netlib.org/lapack/lapacke.html + +### lapack/lapacke + +Binding to a C implementation of the lapacke interface (e.g. OpenBLAS or intel MKL) + +The linker flags (i.e. path to the BLAS library and library name) might have to be adapted. + +The recommended (free) option for good performance on both linux and darwin is OpenBLAS. + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/lapack/cgo/bench_test.go b/lapack/cgo/bench_test.go new file mode 100644 index 00000000..1722d11c --- /dev/null +++ b/lapack/cgo/bench_test.go @@ -0,0 +1,15 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package cgo + +import ( + "testing" + + "gonum.org/v1/gonum/lapack/testlapack" +) + +func BenchmarkDgeev(b *testing.B) { testlapack.DgeevBenchmark(b, impl) } diff --git a/lapack/cgo/lapack.go b/lapack/cgo/lapack.go new file mode 100644 index 00000000..803bc517 --- /dev/null +++ b/lapack/cgo/lapack.go @@ -0,0 +1,2982 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cgo provides an interface to bindings for a C LAPACK library. +package cgo + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/cgo/lapacke" +) + +// Copied from lapack/native. Keep in sync. +const ( + absIncNotOne = "lapack: increment not one or negative one" + badAlpha = "lapack: bad alpha length" + badAuxv = "lapack: auxv has insufficient length" + badBeta = "lapack: bad beta length" + badD = "lapack: d has insufficient length" + badDecompUpdate = "lapack: bad decomp update" + badDiag = "lapack: bad diag" + badDims = "lapack: bad input dimensions" + badDirect = "lapack: bad direct" + badE = "lapack: e has insufficient length" + badEVComp = "lapack: bad EVComp" + badEVJob = "lapack: bad EVJob" + badEVSide = "lapack: bad EVSide" + badGSVDJob = "lapack: bad GSVDJob" + badHowMany = "lapack: bad HowMany" + badIlo = "lapack: ilo out of range" + badIhi = "lapack: ihi out of range" + badIpiv = "lapack: bad permutation length" + badJob = "lapack: bad Job" + badK1 = "lapack: k1 out of range" + badK2 = "lapack: k2 out of range" + badKperm = "lapack: incorrect permutation length" + badLdA = "lapack: index of a out of range" + badNb = "lapack: nb out of range" + badNorm = "lapack: bad norm" + badPivot = "lapack: bad pivot" + badS = "lapack: s has insufficient length" + badShifts = "lapack: bad shifts" + badSide = "lapack: bad side" + badSlice = "lapack: bad input slice length" + badSort = "lapack: bad Sort" + badStore = "lapack: bad store" + badTau = "lapack: tau has insufficient length" + badTauQ = "lapack: tauQ has insufficient length" + badTauP = "lapack: tauP has insufficient length" + badTrans = "lapack: bad trans" + badVn1 = "lapack: vn1 has insufficient length" + badVn2 = "lapack: vn2 has insufficient length" + badUplo = "lapack: illegal triangle" + badWork = "lapack: insufficient working memory" + badWorkStride = "lapack: insufficient working array stride" + badZ = "lapack: insufficient z length" + kGTM = "lapack: k > m" + kGTN = "lapack: k > n" + kLT0 = "lapack: k < 0" + mLT0 = "lapack: m < 0" + mLTN = "lapack: m < n" + nanScale = "lapack: NaN scale factor" + negDimension = "lapack: negative matrix dimension" + negZ = "lapack: negative z value" + nLT0 = "lapack: n < 0" + nLTM = "lapack: n < m" + offsetGTM = "lapack: offset > m" + shortWork = "lapack: working array shorter than declared" + zeroDiv = "lapack: zero divisor" +) + +func min(m, n int) int { + if m < n { + return m + } + return n +} + +func max(m, n int) int { + if m < n { + return n + } + return m +} + +// checkMatrix verifies the parameters of a matrix input. +// Copied from lapack/native. Keep in sync. +func checkMatrix(m, n int, a []float64, lda int) { + if m < 0 { + panic("lapack: has negative number of rows") + } + if n < 0 { + panic("lapack: has negative number of columns") + } + if lda < n { + panic("lapack: stride less than number of columns") + } + if len(a) < (m-1)*lda+n { + panic("lapack: insufficient matrix slice length") + } +} + +// checkVector verifies the parameters of a vector input. +// Copied from lapack/native. Keep in sync. +func checkVector(n int, v []float64, inc int) { + if n < 0 { + panic("lapack: negative vector length") + } + if (inc > 0 && (n-1)*inc >= len(v)) || (inc < 0 && (1-n)*inc >= len(v)) { + panic("lapack: insufficient vector slice length") + } +} + +// Implementation is the cgo-based C implementation of LAPACK routines. +type Implementation struct{} + +var _ lapack.Float64 = Implementation{} + +// Dgeqp3 computes a QR factorization with column pivoting of the +// m×n matrix A: A*P = Q*R using Level 3 BLAS. +// +// The matrix Q is represented as a product of elementary reflectors +// Q = H_0 H_1 . . . H_{k-1}, where k = min(m,n). +// Each H_i has the form +// H_i = I - tau * v * v^T +// where tau and v are real vectors with v[0:i-1] = 0 and v[i] = 1; +// v[i:m] is stored on exit in A[i:m, i], and tau in tau[i]. +// +// jpvt specifies a column pivot to be applied to A. If +// jpvt[j] is at least zero, the jth column of A is permuted +// to the front of A*P (a leading column), if jpvt[j] is -1 +// the jth column of A is a free column. If jpvt[j] < -1, Dgeqp3 +// will panic. On return, jpvt holds the permutation that was +// applied; the jth column of A*P was the jpvt[j] column of A. +// jpvt must have length n or Dgeqp3 will panic. +// +// tau holds the scalar factors of the elementary reflectors. +// It must have length min(m, n), otherwise Dgeqp3 will panic. +// +// work must have length at least max(1,lwork), and lwork must be at least +// 3*n+1, otherwise Dgeqp3 will panic. For optimal performance lwork must +// be at least 2*n+(n+1)*nb, where nb is the optimal blocksize. On return, +// work[0] will contain the optimal value of lwork. +// +// If lwork == -1, instead of performing Dgeqp3, only the optimal value of lwork +// will be stored in work[0]. +// +// Dgeqp3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgeqp3(m, n int, a []float64, lda int, jpvt []int, tau, work []float64, lwork int) { + checkMatrix(m, n, a, lda) + if len(jpvt) != n { + panic(badIpiv) + } + if len(tau) != min(m, n) { + panic(badTau) + } + if len(work) < max(1, lwork) { + panic(badWork) + } + + // Don't update jpvt if querying lwkopt. + if lwork == -1 { + lapacke.Dgeqp3(m, n, a, lda, nil, nil, work, -1) + return + } + + jpvt32 := make([]int32, len(jpvt)) + for i, v := range jpvt { + v++ + if v != int(int32(v)) || v < 0 || n < v { + panic("lapack: jpvt element out of range") + } + jpvt32[i] = int32(v) + } + + lapacke.Dgeqp3(m, n, a, lda, jpvt32, tau, work, lwork) + + for i, v := range jpvt32 { + jpvt[i] = int(v - 1) + } +} + +// Dgerqf computes an RQ factorization of the m×n matrix A, +// A = R * Q. +// On exit, if m <= n, the upper triangle of the subarray +// A[0:m, n-m:n] contains the m×m upper triangular matrix R. +// If m >= n, the elements on and above the (m-n)-th subdiagonal +// contain the m×n upper trapezoidal matrix R. +// The remaining elements, with tau, represent the +// orthogonal matrix Q as a product of min(m,n) elementary +// reflectors. +// +// The matrix Q is represented as a product of elementary reflectors +// Q = H_0 H_1 . . . H_{min(m,n)-1}. +// Each H(i) has the form +// H_i = I - tau_i * v * v^T +// where v is a vector with v[0:n-k+i-1] stored in A[m-k+i, 0:n-k+i-1], +// v[n-k+i:n] = 0 and v[n-k+i] = 1. +// +// tau must have length min(m,n), work must have length max(1, lwork), +// and lwork must be -1 or at least max(1, m), otherwise Dgerqf will panic. +// On exit, work[0] will contain the optimal length for work. +// +// Dgerqf is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { + checkMatrix(m, n, a, lda) + + if len(work) < max(1, lwork) { + panic(shortWork) + } + if lwork != -1 && lwork < max(1, m) { + panic(badWork) + } + + k := min(m, n) + if len(tau) != k { + panic(badTau) + } + + lapacke.Dgerqf(m, n, a, lda, tau, work, lwork) +} + +// Dlacn2 estimates the 1-norm of an n×n matrix A using sequential updates with +// matrix-vector products provided externally. +// +// Dlacn2 is called sequentially and it returns the value of est and kase to be +// used on the next call. +// On the initial call, kase must be 0. +// In between calls, x must be overwritten by +// A * X if kase was returned as 1, +// A^T * X if kase was returned as 2, +// and all other parameters must not be changed. +// On the final return, kase is returned as 0, v contains A*W where W is a +// vector, and est = norm(V)/norm(W) is a lower bound for 1-norm of A. +// +// v, x, and isgn must all have length n and n must be at least 1, otherwise +// Dlacn2 will panic. isave is used for temporary storage. +// +// Dlacn2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlacn2(n int, v, x []float64, isgn []int, est float64, kase int, isave *[3]int) (float64, int) { + if n < 1 { + panic("lapack: non-positive n") + } + checkVector(n, x, 1) + checkVector(n, v, 1) + if len(isgn) < n { + panic("lapack: insufficient isgn length") + } + if isave[0] < 0 || isave[0] > 5 { + panic("lapack: bad isave value") + } + if isave[0] == 0 && kase != 0 { + panic("lapack: bad isave value") + } + + isgn32 := make([]int32, n) + for i, v := range isgn { + isgn32[i] = int32(v) + } + pest := []float64{est} + // Save one allocation by putting isave and kase into the same slice. + isavekase := []int32{int32(isave[0]), int32(isave[1]), int32(isave[2]), int32(kase)} + lapacke.Dlacn2(n, v, x, isgn32, pest, isavekase[3:], isavekase[:3]) + for i, v := range isgn32 { + isgn[i] = int(v) + } + isave[0] = int(isavekase[0]) + isave[1] = int(isavekase[1]) + isave[2] = int(isavekase[2]) + + return pest[0], int(isavekase[3]) +} + +// Dlacpy copies the elements of A specified by uplo into B. Uplo can specify +// a triangular portion with blas.Upper or blas.Lower, or can specify all of the +// elemest with blas.All. +func (impl Implementation) Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) { + checkMatrix(m, n, a, lda) + checkMatrix(m, n, b, ldb) + lapacke.Dlacpy(uplo, m, n, a, lda, b, ldb) +} + +// Dlapmt rearranges the columns of the m×n matrix X as specified by the +// permutation k_0, k_1, ..., k_n-1 of the integers 0, ..., n-1. +// +// If forward is true a forward permutation is performed: +// +// X[0:m, k[j]] is moved to X[0:m, j] for j = 0, 1, ..., n-1. +// +// otherwise a backward permutation is performed: +// +// X[0:m, j] is moved to X[0:m, k[j]] for j = 0, 1, ..., n-1. +// +// k must have length n, otherwise Dlapmt will panic. k is zero-indexed. +func (impl Implementation) Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) { + checkMatrix(m, n, x, ldx) + if len(k) != n { + panic(badKperm) + } + + if n <= 1 { + return + } + + var forwrd int32 + if forward { + forwrd = 1 + } + k32 := make([]int32, len(k)) + for i, v := range k { + v++ // Convert to 1-based indexing. + if v != int(int32(v)) { + panic("lapack: k element out of range") + } + k32[i] = int32(v) + } + + lapacke.Dlapmt(forwrd, m, n, x, ldx, k32) +} + +// Dlapy2 is the LAPACK version of math.Hypot. +// +// Dlapy2 is an internal routine. It is exported for testing purposes. +func (Implementation) Dlapy2(x, y float64) float64 { + return lapacke.Dlapy2(x, y) +} + +// Dlarfb applies a block reflector to a matrix. +// +// In the call to Dlarfb, the mxn c is multiplied by the implicitly defined matrix h as follows: +// c = h * c if side == Left and trans == NoTrans +// c = c * h if side == Right and trans == NoTrans +// c = h^T * c if side == Left and trans == Trans +// c = c * h^T if side == Right and trans == Trans +// h is a product of elementary reflectors. direct sets the direction of multiplication +// h = h_1 * h_2 * ... * h_k if direct == Forward +// h = h_k * h_k-1 * ... * h_1 if direct == Backward +// The combination of direct and store defines the orientation of the elementary +// reflectors. In all cases the ones on the diagonal are implicitly represented. +// +// If direct == lapack.Forward and store == lapack.ColumnWise +// V = [ 1 ] +// [v1 1 ] +// [v1 v2 1] +// [v1 v2 v3] +// [v1 v2 v3] +// If direct == lapack.Forward and store == lapack.RowWise +// V = [ 1 v1 v1 v1 v1] +// [ 1 v2 v2 v2] +// [ 1 v3 v3] +// If direct == lapack.Backward and store == lapack.ColumnWise +// V = [v1 v2 v3] +// [v1 v2 v3] +// [ 1 v2 v3] +// [ 1 v3] +// [ 1] +// If direct == lapack.Backward and store == lapack.RowWise +// V = [v1 v1 1 ] +// [v2 v2 v2 1 ] +// [v3 v3 v3 v3 1] +// An elementary reflector can be explicitly constructed by extracting the +// corresponding elements of v, placing a 1 where the diagonal would be, and +// placing zeros in the remaining elements. +// +// t is a k×k matrix containing the block reflector, and this function will panic +// if t is not of sufficient size. See Dlarft for more information. +// +// work is a temporary storage matrix with stride ldwork. +// work must be of size at least n×k side == Left and m×k if side == Right, and +// this function will panic if this size is not met. +// +// Dlarfb is an internal routine. It is exported for testing purposes. +func (Implementation) Dlarfb(side blas.Side, trans blas.Transpose, direct lapack.Direct, store lapack.StoreV, m, n, k int, v []float64, ldv int, t []float64, ldt int, c []float64, ldc int, work []float64, ldwork int) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + if direct != lapack.Forward && direct != lapack.Backward { + panic(badDirect) + } + if store != lapack.ColumnWise && store != lapack.RowWise { + panic(badStore) + } + checkMatrix(m, n, c, ldc) + if k < 0 { + panic(kLT0) + } + checkMatrix(k, k, t, ldt) + nv := m + nw := n + if side == blas.Right { + nv = n + nw = m + } + if store == lapack.ColumnWise { + checkMatrix(nv, k, v, ldv) + } else { + checkMatrix(k, nv, v, ldv) + } + // TODO(vladimir-ch): Replace the following two lines with + // checkMatrix(nw, k, work, ldwork) + // if and when the issue + // https://github.com/Reference-LAPACK/lapack/issues/37 + // has been resolved. + ldwork = nw + work = make([]float64, ldwork*k) + + lapacke.Dlarfb(side, trans, byte(direct), byte(store), m, n, k, v, ldv, t, ldt, c, ldc, work, ldwork) +} + +// Dlarfg generates an elementary reflector for a Householder matrix. It creates +// a real elementary reflector of order n such that +// H * (alpha) = (beta) +// ( x) ( 0) +// H^T * H = I +// H is represented in the form +// H = 1 - tau * (1; v) * (1 v^T) +// where tau is a real scalar. +// +// On entry, x contains the vector x, on exit it contains v. +// +// Dlarfg is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlarfg(n int, alpha float64, x []float64, incX int) (beta, tau float64) { + if n < 0 { + panic(nLT0) + } + if n <= 1 { + return alpha, 0 + } + checkVector(n-1, x, incX) + _alpha := []float64{alpha} + _tau := []float64{0} + lapacke.Dlarfg(n, _alpha, x, incX, _tau) + return _alpha[0], _tau[0] +} + +// Dlarft forms the triangular factor T of a block reflector H, storing the answer +// in t. +// H = I - V * T * V^T if store == lapack.ColumnWise +// H = I - V^T * T * V if store == lapack.RowWise +// H is defined by a product of the elementary reflectors where +// H = H_0 * H_1 * ... * H_{k-1} if direct == lapack.Forward +// H = H_{k-1} * ... * H_1 * H_0 if direct == lapack.Backward +// +// t is a k×k triangular matrix. t is upper triangular if direct = lapack.Forward +// and lower triangular otherwise. This function will panic if t is not of +// sufficient size. +// +// store describes the storage of the elementary reflectors in v. Please see +// Dlarfb for a description of layout. +// +// tau contains the scalar factors of the elementary reflectors H_i. +// +// Dlarft is an internal routine. It is exported for testing purposes. +func (Implementation) Dlarft(direct lapack.Direct, store lapack.StoreV, n, k int, + v []float64, ldv int, tau []float64, t []float64, ldt int) { + if n == 0 { + return + } + if n < 0 || k < 0 { + panic(negDimension) + } + if direct != lapack.Forward && direct != lapack.Backward { + panic(badDirect) + } + if store != lapack.RowWise && store != lapack.ColumnWise { + panic(badStore) + } + if len(tau) < k { + panic(badTau) + } + checkMatrix(k, k, t, ldt) + + lapacke.Dlarft(byte(direct), byte(store), n, k, v, ldv, tau, t, ldt) +} + +// Dlange computes the matrix norm of the general m×n matrix a. The input norm +// specifies the norm computed. +// lapack.MaxAbs: the maximum absolute value of an element. +// lapack.MaxColumnSum: the maximum column sum of the absolute values of the entries. +// lapack.MaxRowSum: the maximum row sum of the absolute values of the entries. +// lapack.NormFrob: the square root of the sum of the squares of the entries. +// If norm == lapack.MaxColumnSum, work must be of length n, and this function will panic otherwise. +// There are no restrictions on work for the other matrix norms. +func (impl Implementation) Dlange(norm lapack.MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 { + checkMatrix(m, n, a, lda) + switch norm { + case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: + default: + panic(badNorm) + } + if norm == lapack.MaxColumnSum && len(work) < n { + panic(badWork) + } + return lapacke.Dlange(byte(norm), m, n, a, lda, work) +} + +// Dlansy computes the specified norm of an n×n symmetric matrix. If +// norm == lapack.MaxColumnSum or norm == lapackMaxRowSum work must have length +// at least n, otherwise work is unused. +func (impl Implementation) Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 { + checkMatrix(n, n, a, lda) + switch norm { + case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: + default: + panic(badNorm) + } + if (norm == lapack.MaxColumnSum || norm == lapack.MaxRowSum) && len(work) < n { + panic(badWork) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + return lapacke.Dlansy(byte(norm), uplo, n, a, lda, work) +} + +// Dlantr computes the specified norm of an m×n trapezoidal matrix A. If +// norm == lapack.MaxColumnSum work must have length at least n, otherwise work +// is unused. +func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 { + checkMatrix(m, n, a, lda) + switch norm { + case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: + default: + panic(badNorm) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.Unit && diag != blas.NonUnit { + panic(badDiag) + } + if norm == lapack.MaxColumnSum && len(work) < n { + panic(badWork) + } + return lapacke.Dlantr(byte(norm), uplo, diag, m, n, a, lda, work) +} + +// Dlarfx applies an elementary reflector H to a real m×n matrix C, from either +// the left or the right, with loop unrolling when the reflector has order less +// than 11. +// +// H is represented in the form +// H = I - tau * v * v^T, +// where tau is a real scalar and v is a real vector. If tau = 0, then H is +// taken to be the identity matrix. +// +// v must have length equal to m if side == blas.Left, and equal to n if side == +// blas.Right, otherwise Dlarfx will panic. +// +// c and ldc represent the m×n matrix C. On return, C is overwritten by the +// matrix H * C if side == blas.Left, or C * H if side == blas.Right. +// +// work must have length at least n if side == blas.Left, and at least m if side +// == blas.Right, otherwise Dlarfx will panic. work is not referenced if H has +// order < 11. +func (impl Implementation) Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) { + checkMatrix(m, n, c, ldc) + switch side { + case blas.Left: + checkVector(m, v, 1) + if len(work) < n && m > 10 { + panic(badWork) + } + case blas.Right: + checkVector(n, v, 1) + if len(work) < m && n > 10 { + panic(badWork) + } + default: + panic(badSide) + } + + lapacke.Dlarfx(side, m, n, v, tau, c, ldc, work) +} + +// Dlascl multiplies an m×n matrix by the scalar cto/cfrom. +// +// cfrom must not be zero, and cto and cfrom must not be NaN, otherwise Dlascl +// will panic. +// +// Dlascl is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlascl(kind lapack.MatrixType, kl, ku int, cfrom, cto float64, m, n int, a []float64, lda int) { + checkMatrix(m, n, a, lda) + if cfrom == 0 { + panic(zeroDiv) + } + if math.IsNaN(cfrom) || math.IsNaN(cto) { + panic(nanScale) + } + lapacke.Dlascl(byte(kind), kl, ku, cfrom, cto, m, n, a, lda) +} + +// Dlaset sets the off-diagonal elements of A to alpha, and the diagonal +// elements to beta. If uplo == blas.Upper, only the elements in the upper +// triangular part are set. If uplo == blas.Lower, only the elements in the +// lower triangular part are set. If uplo is otherwise, all of the elements of A +// are set. +// +// Dlaset is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaset(uplo blas.Uplo, m, n int, alpha, beta float64, a []float64, lda int) { + checkMatrix(m, n, a, lda) + lapacke.Dlaset(uplo, m, n, alpha, beta, a, lda) +} + +// Dlasrt sorts the numbers in the input slice d. If s == lapack.SortIncreasing, +// the elements are sorted in increasing order. If s == lapack.SortDecreasing, +// the elements are sorted in decreasing order. For other values of s Dlasrt +// will panic. +// +// Dlasrt is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasrt(s lapack.Sort, n int, d []float64) { + checkVector(n, d, 1) + switch s { + default: + panic(badSort) + case lapack.SortIncreasing, lapack.SortDecreasing: + } + lapacke.Dlasrt(byte(s), n, d[:n]) +} + +// Dlaswp swaps the rows k1 to k2 of a rectangular matrix A according to the +// indices in ipiv so that row k is swapped with ipiv[k]. +// +// n is the number of columns of A and incX is the increment for ipiv. If incX +// is 1, the swaps are applied from k1 to k2. If incX is -1, the swaps are +// applied in reverse order from k2 to k1. For other values of incX Dlaswp will +// panic. ipiv must have length k2+1, otherwise Dlaswp will panic. +// +// The indices k1, k2, and the elements of ipiv are zero-based. +// +// Dlaswp is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaswp(n int, a []float64, lda, k1, k2 int, ipiv []int, incX int) { + switch { + case n < 0: + panic(nLT0) + case k2 < 0: + panic(badK2) + case k1 < 0 || k2 < k1: + panic(badK1) + case len(ipiv) != k2+1: + panic(badIpiv) + case incX != 1 && incX != -1: + panic(absIncNotOne) + } + + ipiv32 := make([]int32, len(ipiv)) + for i, v := range ipiv { + ipiv32[i] = int32(v + 1) + } + lapacke.Dlaswp(n, a, lda, k1+1, k2+1, ipiv32, incX) +} + +// Dpotrf computes the Cholesky decomposition of the symmetric positive definite +// matrix a. If ul == blas.Upper, then a is stored as an upper-triangular matrix, +// and a = U U^T is stored in place into a. If ul == blas.Lower, then a = L L^T +// is computed and stored in-place into a. If a is not positive definite, false +// is returned. This is the blocked version of the algorithm. +func (impl Implementation) Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) { + // ul is checked in lapacke.Dpotrf. + if n < 0 { + panic(nLT0) + } + if lda < n { + panic(badLdA) + } + if n == 0 { + return true + } + return lapacke.Dpotrf(ul, n, a, lda) +} + +// Dgebal balances an n×n matrix A. Balancing consists of two stages, permuting +// and scaling. Both steps are optional and depend on the value of job. +// +// Permuting consists of applying a permutation matrix P such that the matrix +// that results from P^T*A*P takes the upper block triangular form +// [ T1 X Y ] +// P^T A P = [ 0 B Z ], +// [ 0 0 T2 ] +// where T1 and T2 are upper triangular matrices and B contains at least one +// nonzero off-diagonal element in each row and column. The indices ilo and ihi +// mark the starting and ending columns of the submatrix B. The eigenvalues of A +// isolated in the first 0 to ilo-1 and last ihi+1 to n-1 elements on the +// diagonal can be read off without any roundoff error. +// +// Scaling consists of applying a diagonal similarity transformation D such that +// D^{-1}*B*D has the 1-norm of each row and its corresponding column nearly +// equal. The output matrix is +// [ T1 X*D Y ] +// [ 0 inv(D)*B*D inv(D)*Z ]. +// [ 0 0 T2 ] +// Scaling may reduce the 1-norm of the matrix, and improve the accuracy of +// the computed eigenvalues and/or eigenvectors. +// +// job specifies the operations that will be performed on A. +// If job is lapack.None, Dgebal sets scale[i] = 1 for all i and returns ilo=0, ihi=n-1. +// If job is lapack.Permute, only permuting will be done. +// If job is lapack.Scale, only scaling will be done. +// If job is lapack.PermuteScale, both permuting and scaling will be done. +// +// On return, if job is lapack.Permute or lapack.PermuteScale, it will hold that +// A[i,j] == 0, for i > j and j ∈ {0, ..., ilo-1, ihi+1, ..., n-1}. +// If job is lapack.None or lapack.Scale, or if n == 0, it will hold that +// ilo == 0 and ihi == n-1. +// +// On return, scale will contain information about the permutations and scaling +// factors applied to A. If π(j) denotes the index of the column interchanged +// with column j, and D[j,j] denotes the scaling factor applied to column j, +// then +// scale[j] == π(j), for j ∈ {0, ..., ilo-1, ihi+1, ..., n-1}, +// == D[j,j], for j ∈ {ilo, ..., ihi}. +// scale must have length equal to n, otherwise Dgebal will panic. +// +// Dgebal is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebal(job lapack.Job, n int, a []float64, lda int, scale []float64) (ilo, ihi int) { + switch job { + default: + panic(badJob) + case lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale: + } + checkMatrix(n, n, a, lda) + if len(scale) != n { + panic("lapack: bad length of scale") + } + + ilo32 := make([]int32, 1) + ihi32 := make([]int32, 1) + lapacke.Dgebal(job, n, a, lda, ilo32, ihi32, scale) + ilo = int(ilo32[0]) - 1 + ihi = int(ihi32[0]) - 1 + for j := 0; j < ilo; j++ { + scale[j]-- + } + for j := ihi + 1; j < n; j++ { + scale[j]-- + } + return ilo, ihi +} + +// Dgebak transforms an n×m matrix V as +// V = P D V, if side == blas.Right, +// V = P D^{-1} V, if side == blas.Left, +// where P and D are n×n permutation and scaling matrices, respectively, +// implicitly represented by job, scale, ilo and ihi as returned by Dgebal. +// +// Typically, columns of the matrix V contain the right or left (determined by +// side) eigenvectors of the balanced matrix output by Dgebal, and Dgebak forms +// the eigenvectors of the original matrix. +// +// Dgebak is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebak(job lapack.Job, side lapack.EVSide, n, ilo, ihi int, scale []float64, m int, v []float64, ldv int) { + switch job { + default: + panic(badJob) + case lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale: + } + var bside blas.Side + switch side { + default: + panic(badSide) + case lapack.LeftEV: + bside = blas.Left + case lapack.RightEV: + bside = blas.Right + } + checkMatrix(n, m, v, ldv) + switch { + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + } + + // Convert permutation indices to 1-based. + for j := 0; j < ilo; j++ { + scale[j]++ + } + for j := ihi + 1; j < n; j++ { + scale[j]++ + } + lapacke.Dgebak(job, bside, n, ilo+1, ihi+1, scale, m, v, ldv) + // Convert permutation indices back to 0-based. + for j := 0; j < ilo; j++ { + scale[j]-- + } + for j := ihi + 1; j < n; j++ { + scale[j]-- + } +} + +// Dbdsqr performs a singular value decomposition of a real n×n bidiagonal matrix. +// +// The SVD of the bidiagonal matrix B is +// B = Q * S * P^T +// where S is a diagonal matrix of singular values, Q is an orthogonal matrix of +// left singular vectors, and P is an orthogonal matrix of right singular vectors. +// +// Q and P are only computed if requested. If left singular vectors are requested, +// this routine returns U * Q instead of Q, and if right singular vectors are +// requested P^T * VT is returned instead of P^T. +// +// Frequently Dbdsqr is used in conjunction with Dgebrd which reduces a general +// matrix A into bidiagonal form. In this case, the SVD of A is +// A = (U * Q) * S * (P^T * VT) +// +// This routine may also compute Q^T * C. +// +// d and e contain the elements of the bidiagonal matrix b. d must have length at +// least n, and e must have length at least n-1. Dbdsqr will panic if there is +// insufficient length. On exit, D contains the singular values of B in decreasing +// order. +// +// VT is a matrix of size n×ncvt whose elements are stored in vt. The elements +// of vt are modified to contain P^T * VT on exit. VT is not used if ncvt == 0. +// +// U is a matrix of size nru×n whose elements are stored in u. The elements +// of u are modified to contain U * Q on exit. U is not used if nru == 0. +// +// C is a matrix of size n×ncc whose elements are stored in c. The elements +// of c are modified to contain Q^T * C on exit. C is not used if ncc == 0. +// +// work contains temporary storage and must have length at least 4*n. Dbdsqr +// will panic if there is insufficient working memory. +// +// Dbdsqr returns whether the decomposition was successful. +func (impl Implementation) Dbdsqr(uplo blas.Uplo, n, ncvt, nru, ncc int, d, e, vt []float64, ldvt int, u []float64, ldu int, c []float64, ldc int, work []float64) (ok bool) { + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if ncvt != 0 { + checkMatrix(n, ncvt, vt, ldvt) + } + if nru != 0 { + checkMatrix(nru, n, u, ldu) + } + if ncc != 0 { + checkMatrix(n, ncc, c, ldc) + } + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if len(work) < 4*n { + panic(badWork) + } + // An address must be passed to cgo. If lengths are zero, allocate a slice. + if len(vt) == 0 { + vt = make([]float64, 1) + } + if len(u) == 0 { + vt = make([]float64, 1) + } + if len(c) == 0 { + c = make([]float64, 1) + } + return lapacke.Dbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work) +} + +// Dgebrd reduces a general m×n matrix A to upper or lower bidiagonal form B by +// an orthogonal transformation: +// Q^T * A * P = B. +// The diagonal elements of B are stored in d and the off-diagonal elements are +// stored in e. These are additionally stored along the diagonal of A and the +// off-diagonal of A. If m >= n B is an upper-bidiagonal matrix, and if m < n B +// is a lower-bidiagonal matrix. +// +// The remaining elements of A store the data needed to construct Q and P. +// The matrices Q and P are products of elementary reflectors +// if m >= n, Q = H_0 * H_1 * ... * H_{n-1}, +// P = G_0 * G_1 * ... * G_{n-2}, +// if m < n, Q = H_0 * H_1 * ... * H_{m-2}, +// P = G_0 * G_1 * ... * G_{m-1}, +// where +// H_i = I - tauQ[i] * v_i * v_i^T, +// G_i = I - tauP[i] * u_i * u_i^T. +// +// As an example, on exit the entries of A when m = 6, and n = 5 +// [ d e u1 u1 u1] +// [v1 d e u2 u2] +// [v1 v2 d e u3] +// [v1 v2 v3 d e] +// [v1 v2 v3 v4 d] +// [v1 v2 v3 v4 v5] +// and when m = 5, n = 6 +// [ d u1 u1 u1 u1 u1] +// [ e d u2 u2 u2 u2] +// [v1 e d u3 u3 u3] +// [v1 v2 e d u4 u4] +// [v1 v2 v3 e d u5] +// +// d, tauQ, and tauP must all have length at least min(m,n), and e must have +// length min(m,n) - 1, unless lwork is -1 when there is no check except for +// work which must have a length of at least one. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= max(1,m,n) or be -1 and this function will panic otherwise. +// Dgebrd is blocked decomposition, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgebrd, +// the optimal work length will be stored into work[0]. +// +// Dgebrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64, lwork int) { + checkMatrix(m, n, a, lda) + minmn := min(m, n) + if len(d) < minmn { + panic(badD) + } + if len(e) < minmn-1 { + panic(badE) + } + if len(tauQ) < minmn { + panic(badTauQ) + } + if len(tauP) < minmn { + panic(badTauP) + } + if lwork != -1 && lwork < max(1, max(m, n)) { + panic(badWork) + } + if len(work) < max(1, lwork) { + panic(badWork) + } + + lapacke.Dgebrd(m, n, a, lda, d, e, tauQ, tauP, work, lwork) +} + +// Dgecon estimates the reciprocal of the condition number of the n×n matrix A +// given the LU decomposition of the matrix. The condition number computed may +// be based on the 1-norm or the ∞-norm. +// +// The slice a contains the result of the LU decomposition of A as computed by Dgetrf. +// +// anorm is the corresponding 1-norm or ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 4*n and Dgecon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Dgecon will panic otherwise. +// Elements of iwork must fit within the int32 type or Dgecon will panic. +func (impl Implementation) Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { + checkMatrix(n, n, a, lda) + if norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum { + panic("bad norm") + } + if len(work) < 4*n { + panic(badWork) + } + if len(iwork) < n { + panic(badWork) + } + rcond := make([]float64, 1) + _iwork := make([]int32, len(iwork)) + for i, v := range iwork { + if v != int(int32(v)) { + panic("lapack: iwork element out of range") + } + _iwork[i] = int32(v) + } + lapacke.Dgecon(byte(norm), n, a, lda, anorm, rcond, work, _iwork) + for i, v := range _iwork { + iwork[i] = int(v) + } + return rcond[0] +} + +// Dgelq2 computes the LQ factorization of the m×n matrix A. +// +// In an LQ factorization, L is a lower triangular m×n matrix, and Q is an n×n +// orthonormal matrix. +// +// a is modified to contain the information to construct L and Q. +// The lower triangle of a contains the matrix L. The upper triangular elements +// (not including the diagonal) contain the elementary reflectors. Tau is modified +// to contain the reflector scales. tau must have length of at least k = min(m,n) +// and this function will panic otherwise. +// +// See Dgeqr2 for a description of the elementary reflectors and orthonormal +// matrix Q. Q is constructed as a product of these elementary reflectors, +// Q = H_{k-1} * ... * H_1 * H_0, +// where k = min(m,n). +// +// Work is temporary storage of length at least m and this function will panic otherwise. +func (impl Implementation) Dgelq2(m, n int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + if len(tau) < min(m, n) { + panic(badTau) + } + if len(work) < m { + panic(badWork) + } + lapacke.Dgelq2(m, n, a, lda, tau, work) +} + +// Dgelqf computes the LQ factorization of the m×n matrix A using a blocked +// algorithm. See the documentation for Dgelq2 for a description of the +// parameters at entry and exit. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m, and this function will panic otherwise. +// Dgelqf is a blocked LQ factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgelqf, +// the optimal work length will be stored into work[0]. +// +// tau must have length at least min(m,n), and this function will panic otherwise. +func (impl Implementation) Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { + if lwork == -1 { + work[0] = float64(m) + return + } + checkMatrix(m, n, a, lda) + if len(work) < lwork { + panic(shortWork) + } + if lwork < m { + panic(badWork) + } + if len(tau) < min(m, n) { + panic(badTau) + } + lapacke.Dgelqf(m, n, a, lda, tau, work, lwork) +} + +// Dgeqr2 computes a QR factorization of the m×n matrix A. +// +// In a QR factorization, Q is an m×m orthonormal matrix, and R is an +// upper triangular m×n matrix. +// +// A is modified to contain the information to construct Q and R. +// The upper triangle of a contains the matrix R. The lower triangular elements +// (not including the diagonal) contain the elementary reflectors. Tau is modified +// to contain the reflector scales. tau must have length at least min(m,n), and +// this function will panic otherwise. +// +// The ith elementary reflector can be explicitly constructed by first extracting +// the +// v[j] = 0 j < i +// v[j] = 1 j == i +// v[j] = a[j*lda+i] j > i +// and computing H_i = I - tau[i] * v * v^T. +// +// The orthonormal matrix Q can be constucted from a product of these elementary +// reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). +// +// Work is temporary storage of length at least n and this function will panic otherwise. +func (impl Implementation) Dgeqr2(m, n int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + if len(work) < n { + panic(badWork) + } + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + lapacke.Dgeqr2(m, n, a, lda, tau, work) +} + +// Dgeqrf computes the QR factorization of the m×n matrix A using a blocked +// algorithm. See the documentation for Dgeqr2 for a description of the +// parameters at entry and exit. +// +// work is temporary storage, and lwork specifies the usable memory length. +// The length of work must be at least max(1, lwork) and lwork must be -1 +// or at least n, otherwise this function will panic. +// Dgeqrf is a blocked QR factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgeqrf, +// the optimal work length will be stored into work[0]. +// +// tau must have length at least min(m,n), and this function will panic otherwise. +func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { + if len(work) < max(1, lwork) { + panic(shortWork) + } + if lwork == -1 { + work[0] = float64(n) + return + } + checkMatrix(m, n, a, lda) + if lwork < n { + panic(badWork) + } + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + lapacke.Dgeqrf(m, n, a, lda, tau, work, lwork) +} + +// Dgehrd reduces a block of a real n×n general matrix A to upper Hessenberg +// form H by an orthogonal similarity transformation Q^T * A * Q = H. +// +// The matrix Q is represented as a product of (ihi-ilo) elementary +// reflectors +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// Each H_i has the form +// H_i = I - tau[i] * v * v^T +// where v is a real vector with v[0:i+1] = 0, v[i+1] = 1 and v[ihi+1:n] = 0. +// v[i+2:ihi+1] is stored on exit in A[i+2:ihi+1,i]. +// +// On entry, a contains the n×n general matrix to be reduced. On return, the +// upper triangle and the first subdiagonal of A will be overwritten with the +// upper Hessenberg matrix H, and the elements below the first subdiagonal, with +// the slice tau, represent the orthogonal matrix Q as a product of elementary +// reflectors. +// +// The contents of a are illustrated by the following example, with n = 7, ilo = +// 1 and ihi = 5. +// On entry, +// [ a a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a ] +// on return, +// [ a a h h h h a ] +// [ a h h h h a ] +// [ h h h h h h ] +// [ v1 h h h h h ] +// [ v1 v2 h h h h ] +// [ v1 v2 v3 h h h ] +// [ a ] +// where a denotes an element of the original matrix A, h denotes a +// modified element of the upper Hessenberg matrix H, and vi denotes an +// element of the vector defining H_i. +// +// ilo and ihi determine the block of A that will be reduced to upper Hessenberg +// form. It must hold that 0 <= ilo <= ihi < n if n > 0, and ilo == 0 and ihi == +// -1 if n == 0, otherwise Dgehrd will panic. +// +// On return, tau will contain the scalar factors of the elementary reflectors. +// Elements tau[:ilo] and tau[ihi:] will be set to zero. tau must have length +// equal to n-1 if n > 0, otherwise Dgehrd will panic. +// +// work must have length at least lwork and lwork must be at least max(1,n), +// otherwise Dgehrd will panic. On return, work[0] contains the optimal value of +// lwork. +// +// If lwork == -1, instead of performing Dgehrd, only the optimal value of lwork +// will be stored in work[0]. +// +// Dgehrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgehrd(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) { + switch { + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case lwork < max(1, n) && lwork != -1: + panic(badWork) + case len(work) < lwork: + panic(shortWork) + } + if lwork != -1 { + checkMatrix(n, n, a, lda) + if len(tau) != n-1 && n > 0 { + panic(badTau) + } + } + lapacke.Dgehrd(n, ilo+1, ihi+1, a, lda, tau, work, lwork) +} + +// Dgels finds a minimum-norm solution based on the matrices A and B using the +// QR or LQ factorization. Dgels returns false if the matrix +// A is singular, and true if this solution was successfully found. +// +// The minimization problem solved depends on the input parameters. +// +// 1. If m >= n and trans == blas.NoTrans, Dgels finds X such that || A*X - B||_2 +// is minimized. +// 2. If m < n and trans == blas.NoTrans, Dgels finds the minimum norm solution of +// A * X = B. +// 3. If m >= n and trans == blas.Trans, Dgels finds the minimum norm solution of +// A^T * X = B. +// 4. If m < n and trans == blas.Trans, Dgels finds X such that || A*X - B||_2 +// is minimized. +// Note that the least-squares solutions (cases 1 and 3) perform the minimization +// per column of B. This is not the same as finding the minimum-norm matrix. +// +// The matrix A is a general matrix of size m×n and is modified during this call. +// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry, +// the elements of b specify the input matrix B. B has size m×nrhs if +// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the +// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans, +// this submatrix is of size n×nrhs, and of size m×nrhs otherwise. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic +// otherwise. A longer work will enable blocked algorithms to be called. +// In the special case that lwork == -1, work[0] will be set to the optimal working +// length. +func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool { + mn := min(m, n) + if lwork == -1 { + work[0] = float64(mn + max(mn, nrhs)) + return true + } + checkMatrix(m, n, a, lda) + checkMatrix(max(m, n), nrhs, b, ldb) + if len(work) < lwork { + panic(shortWork) + } + if lwork < mn+max(mn, nrhs) { + panic(badWork) + } + return lapacke.Dgels(trans, m, n, nrhs, a, lda, b, ldb, work, lwork) +} + +const noSVDO = "dgesvd: not coded for overwrite" + +// Dgesvd computes the singular value decomposition of the input matrix A. +// +// The singular value decomposition is +// A = U * Sigma * V^T +// where Sigma is an m×n diagonal matrix containing the singular values of A, +// U is an m×m orthogonal matrix and V is an n×n orthogonal matrix. The first +// min(m,n) columns of U and V are the left and right singular vectors of A +// respectively. +// +// jobU and jobVT are options for computing the singular vectors. The behavior +// is as follows +// jobU == lapack.SVDAll All m columns of U are returned in u +// jobU == lapack.SVDInPlace The first min(m,n) columns are returned in u +// jobU == lapack.SVDOverwrite The first min(m,n) columns of U are written into a +// jobU == lapack.SVDNone The columns of U are not computed. +// The behavior is the same for jobVT and the rows of V^T. At most one of jobU +// and jobVT can equal lapack.SVDOverwrite, and Dgesvd will panic otherwise. +// +// On entry, a contains the data for the m×n matrix A. During the call to Dgesvd +// the data is overwritten. On exit, A contains the appropriate singular vectors +// if either job is lapack.SVDOverwrite. +// +// s is a slice of length at least min(m,n) and on exit contains the singular +// values in decreasing order. +// +// u contains the left singular vectors on exit, stored column-wise. If +// jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDInPlace u is +// of size m×min(m,n). If jobU == lapack.SVDOverwrite or lapack.SVDNone, u is +// not used. +// +// vt contains the left singular vectors on exit, stored rowwise. If +// jobV == lapack.SVDAll, vt is of size n×m. If jobVT == lapack.SVDInPlace vt is +// of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is +// not used. +// +// work is a slice for storing temporary memory, and lwork is the usable size of +// the slice. lwork must be at least max(5*min(m,n), 3*min(m,n)+max(m,n)). +// If lwork == -1, instead of performing Dgesvd, the optimal work length will be +// stored into work[0]. Dgesvd will panic if the working memory has insufficient +// storage. +// +// Dgesvd returns whether the decomposition successfully completed. +func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) (ok bool) { + checkMatrix(m, n, a, lda) + if jobU == lapack.SVDAll { + checkMatrix(m, m, u, ldu) + } else if jobU == lapack.SVDInPlace { + checkMatrix(m, min(m, n), u, ldu) + } + if jobVT == lapack.SVDAll { + checkMatrix(n, n, vt, ldvt) + } else if jobVT == lapack.SVDInPlace { + checkMatrix(min(m, n), n, vt, ldvt) + } + if jobU == lapack.SVDOverwrite && jobVT == lapack.SVDOverwrite { + panic(noSVDO) + } + if len(s) < min(m, n) { + panic(badS) + } + if jobU == lapack.SVDOverwrite || jobVT == lapack.SVDOverwrite { + panic("lapack: SVD not coded to overwrite original matrix") + } + minWork := max(5*min(m, n), 3*min(m, n)+max(m, n)) + if lwork != -1 { + if len(work) < lwork { + panic(badWork) + } + if lwork < minWork { + panic(badWork) + } + } + if lwork == -1 { + work[0] = float64(minWork) + return true + } + return lapacke.Dgesvd(lapack.Job(jobU), lapack.Job(jobVT), m, n, a, lda, s, u, ldu, vt, ldvt, work, lwork) +} + +// Dgetf2 computes the LU decomposition of the m×n matrix A. +// The LU decomposition is a factorization of a into +// A = P * L * U +// where P is a permutation matrix, L is a unit lower triangular matrix, and +// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored +// in place into a. +// +// ipiv is a permutation vector. It indicates that row i of the matrix was +// changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic +// otherwise. ipiv is zero-indexed. +// +// Dgetf2 returns whether the matrix A is singular. The LU decomposition will +// be computed regardless of the singularity of A, but division by zero +// will occur if the false is returned and the result is used to solve a +// system of equations. +func (Implementation) Dgetf2(m, n int, a []float64, lda int, ipiv []int) (ok bool) { + mn := min(m, n) + checkMatrix(m, n, a, lda) + if len(ipiv) < mn { + panic(badIpiv) + } + ipiv32 := make([]int32, len(ipiv)) + ok = lapacke.Dgetf2(m, n, a, lda, ipiv32) + for i, v := range ipiv32 { + ipiv[i] = int(v) - 1 // Transform to zero-indexed. + } + return ok +} + +// Dgetrf computes the LU decomposition of the m×n matrix A. +// The LU decomposition is a factorization of A into +// A = P * L * U +// where P is a permutation matrix, L is a unit lower triangular matrix, and +// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored +// in place into a. +// +// ipiv is a permutation vector. It indicates that row i of the matrix was +// changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic +// otherwise. ipiv is zero-indexed. +// +// Dgetrf is the blocked version of the algorithm. +// +// Dgetrf returns whether the matrix A is singular. The LU decomposition will +// be computed regardless of the singularity of A, but division by zero +// will occur if the false is returned and the result is used to solve a +// system of equations. +func (impl Implementation) Dgetrf(m, n int, a []float64, lda int, ipiv []int) (ok bool) { + mn := min(m, n) + checkMatrix(m, n, a, lda) + if len(ipiv) < mn { + panic(badIpiv) + } + ipiv32 := make([]int32, len(ipiv)) + ok = lapacke.Dgetrf(m, n, a, lda, ipiv32) + for i, v := range ipiv32 { + ipiv[i] = int(v) - 1 // Transform to zero-indexed. + } + return ok +} + +// Dgetri computes the inverse of the matrix A using the LU factorization computed +// by Dgetrf. On entry, a contains the PLU decomposition of A as computed by +// Dgetrf and on exit contains the reciprocal of the original matrix. +// +// Dgetri will not perform the inversion if the matrix is singular, and returns +// a boolean indicating whether the inversion was successful. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= n and this function will panic otherwise. +// Dgetri is a blocked inversion, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgetri, +// the optimal work length will be stored into work[0]. +func (impl Implementation) Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) (ok bool) { + checkMatrix(n, n, a, lda) + if len(ipiv) < n { + panic(badIpiv) + } + if lwork == -1 { + work[0] = float64(n) + return true + } + if lwork < n { + panic(badWork) + } + if len(work) < lwork { + panic(badWork) + } + ipiv32 := make([]int32, len(ipiv)) + for i, v := range ipiv { + ipiv32[i] = int32(v) + 1 // Transform to one-indexed. + } + return lapacke.Dgetri(n, a, lda, ipiv32, work, lwork) +} + +// Dgetrs solves a system of equations using an LU factorization. +// The system of equations solved is +// A * X = B if trans == blas.Trans +// A^T * X = B if trans == blas.NoTrans +// A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs. +// +// On entry b contains the elements of the matrix B. On exit, b contains the +// elements of X, the solution to the system of equations. +// +// a and ipiv contain the LU factorization of A and the permutation indices as +// computed by Dgetrf. ipiv is zero-indexed. +func (impl Implementation) Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) { + checkMatrix(n, n, a, lda) + checkMatrix(n, nrhs, b, ldb) + if len(ipiv) < n { + panic(badIpiv) + } + ipiv32 := make([]int32, len(ipiv)) + for i, v := range ipiv { + ipiv32[i] = int32(v) + 1 // Transform to one-indexed. + } + lapacke.Dgetrs(trans, n, nrhs, a, lda, ipiv32, b, ldb) +} + +// Dggsvd3 computes the generalized singular value decomposition (GSVD) +// of an m×n matrix A and p×n matrix B: +// U^T*A*Q = D1*[ 0 R ] +// +// V^T*B*Q = D2*[ 0 R ] +// where U, V and Q are orthogonal matrices. +// +// Dggsvd3 returns k and l, the dimensions of the sub-blocks. k+l +// is the effective numerical rank of the (m+p)×n matrix [ A^T B^T ]^T. +// R is a (k+l)×(k+l) nonsingular upper triangular matrix, D1 and +// D2 are m×(k+l) and p×(k+l) diagonal matrices and of the following +// structures, respectively: +// +// If m-k-l >= 0, +// +// k l +// D1 = k [ I 0 ] +// l [ 0 C ] +// m-k-l [ 0 0 ] +// +// k l +// D2 = l [ 0 S ] +// p-l [ 0 0 ] +// +// n-k-l k l +// [ 0 R ] = k [ 0 R11 R12 ] k +// l [ 0 0 R22 ] l +// +// where +// +// C = diag( alpha_k, ... , alpha_{k+l} ), +// S = diag( beta_k, ... , beta_{k+l} ), +// C^2 + S^2 = I. +// +// R is stored in +// A[0:k+l, n-k-l:n] +// on exit. +// +// If m-k-l < 0, +// +// k m-k k+l-m +// D1 = k [ I 0 0 ] +// m-k [ 0 C 0 ] +// +// k m-k k+l-m +// D2 = m-k [ 0 S 0 ] +// k+l-m [ 0 0 I ] +// p-l [ 0 0 0 ] +// +// n-k-l k m-k k+l-m +// [ 0 R ] = k [ 0 R11 R12 R13 ] +// m-k [ 0 0 R22 R23 ] +// k+l-m [ 0 0 0 R33 ] +// +// where +// C = diag( alpha_k, ... , alpha_m ), +// S = diag( beta_k, ... , beta_m ), +// C^2 + S^2 = I. +// +// R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n] +// [ 0 R22 R23 ] +// and R33 is stored in +// B[m-k:l, n+m-k-l:n] on exit. +// +// Dggsvd3 computes C, S, R, and optionally the orthogonal transformation +// matrices U, V and Q. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// alpha and beta must have length n or Dggsvd3 will panic. On exit, alpha and +// beta contain the generalized singular value pairs of A and B +// alpha[0:k] = 1, +// beta[0:k] = 0, +// if m-k-l >= 0, +// alpha[k:k+l] = diag(C), +// beta[k:k+l] = diag(S), +// if m-k-l < 0, +// alpha[k:m]= C, alpha[m:k+l]= 0 +// beta[k:m] = S, beta[m:k+l] = 1. +// if k+l < n, +// alpha[k+l:n] = 0 and +// beta[k+l:n] = 0. +// +// On exit, iwork contains the permutation required to sort alpha descending. +// +// iwork must have length n, work must have length at least max(1, lwork), and +// lwork must be -1 or greater than n, otherwise Dggsvd3 will panic. If +// lwork is -1, work[0] holds the optimal lwork on return, but Dggsvd3 does +// not perform the GSVD. +func (impl Implementation) Dggsvd3(jobU, jobV, jobQ lapack.GSVDJob, m, n, p int, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int) (k, l int, ok bool) { + checkMatrix(m, n, a, lda) + checkMatrix(p, n, b, ldb) + + switch jobU { + case lapack.GSVDU: + checkMatrix(m, m, u, ldu) + case lapack.GSVDNone: + default: + panic(badGSVDJob + "U") + } + switch jobV { + case lapack.GSVDV: + checkMatrix(p, p, v, ldv) + case lapack.GSVDNone: + default: + panic(badGSVDJob + "V") + } + switch jobQ { + case lapack.GSVDQ: + checkMatrix(n, n, q, ldq) + case lapack.GSVDNone: + default: + panic(badGSVDJob + "Q") + } + + if len(alpha) != n { + panic(badAlpha) + } + if len(beta) != n { + panic(badBeta) + } + + if lwork != -1 && lwork <= n { + panic(badWork) + } + if len(work) < max(1, lwork) { + panic(shortWork) + } + if len(iwork) < n { + panic(badWork) + } + + _k := []int32{0} + _l := []int32{0} + _iwork := make([]int32, len(iwork)) + for i, v := range iwork { + v++ + if v != int(int32(v)) { + panic("lapack: iwork element out of range") + } + _iwork[i] = int32(v) + } + ok = lapacke.Dggsvd3(lapack.Job(jobU), lapack.Job(jobV), lapack.Job(jobQ), m, n, p, _k, _l, a, lda, b, ldb, alpha, beta, u, ldu, v, ldv, q, ldq, work, lwork, _iwork) + for i, v := range _iwork { + iwork[i] = int(v - 1) + } + + return int(_k[0]), int(_l[0]), ok +} + +// Dggsvp3 computes orthogonal matrices U, V and Q such that +// +// n-k-l k l +// U^T*A*Q = k [ 0 A12 A13 ] if m-k-l >= 0; +// l [ 0 0 A23 ] +// m-k-l [ 0 0 0 ] +// +// n-k-l k l +// U^T*A*Q = k [ 0 A12 A13 ] if m-k-l < 0; +// m-k [ 0 0 A23 ] +// +// n-k-l k l +// V^T*B*Q = l [ 0 0 B13 ] +// p-l [ 0 0 0 ] +// +// where the k×k matrix A12 and l×l matrix B13 are non-singular +// upper triangular. A23 is l×l upper triangular if m-k-l >= 0, +// otherwise A23 is (m-k)×l upper trapezoidal. +// +// Dggsvp3 returns k and l, the dimensions of the sub-blocks. k+l +// is the effective numerical rank of the (m+p)×n matrix [ A^T B^T ]^T. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// tola and tolb are the convergence criteria for the Jacobi-Kogbetliantz +// iteration procedure. Generally, they are the same as used in the preprocessing +// step, for example, +// tola = max(m, n)*norm(A)*eps, +// tolb = max(p, n)*norm(B)*eps. +// Where eps is the machine epsilon. +// +// iwork must have length n, work must have length at least max(1, lwork), and +// lwork must be -1 or greater than zero, otherwise Dggsvp3 will panic. +// +// Dggsvp3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, iwork []int, tau, work []float64, lwork int) (k, l int) { + checkMatrix(m, n, a, lda) + checkMatrix(p, n, b, ldb) + + wantu := jobU == lapack.GSVDU + if !wantu && jobU != lapack.GSVDNone { + panic(badGSVDJob + "U") + } + if jobU != lapack.GSVDNone { + checkMatrix(m, m, u, ldu) + } + + wantv := jobV == lapack.GSVDV + if !wantv && jobV != lapack.GSVDNone { + panic(badGSVDJob + "V") + } + if jobV != lapack.GSVDNone { + checkMatrix(p, p, v, ldv) + } + + wantq := jobQ == lapack.GSVDQ + if !wantq && jobQ != lapack.GSVDNone { + panic(badGSVDJob + "Q") + } + if jobQ != lapack.GSVDNone { + checkMatrix(n, n, q, ldq) + } + + if len(tau) < n { + panic(badTau) + } + if len(iwork) != n { + panic(badWork) + } + if lwork != -1 && lwork < 1 { + panic(badWork) + } + if len(work) < max(1, lwork) { + panic(shortWork) + } + + _k := []int32{0} + _l := []int32{0} + _iwork := make([]int32, len(iwork)) + for i, v := range iwork { + v++ + if v != int(int32(v)) { + panic("lapack: iwork element out of range") + } + _iwork[i] = int32(v) + } + lapacke.Dggsvp3(lapack.Job(jobU), lapack.Job(jobV), lapack.Job(jobQ), m, p, n, a, lda, b, ldb, tola, tolb, _k, _l, u, ldu, v, ldv, q, ldq, _iwork, tau, work, lwork) + for i, v := range _iwork { + iwork[i] = int(v - 1) + } + + return int(_k[0]), int(_l[0]) +} + +// Dorgbr generates one of the matrices Q or P^T computed by Dgebrd. +// See Dgebrd for the description of Q and P^T. +// +// If vect == lapack.ApplyQ, then a is assumed to have been an m×k matrix and +// Q is of order m. If m >= k, then Dorgbr returns the first n columns of Q +// where m >= n >= k. If m < k, then Dorgbr returns Q as an m×m matrix. +// +// If vect == lapack.ApplyP, then A is assumed to have been a k×n matrix, and +// P^T is of order n. If k < n, then Dorgbr returns the first m rows of P^T, +// where n >= m >= k. If k >= n, then Dorgbr returns P^T as an n×n matrix. +func (impl Implementation) Dorgbr(vect lapack.DecompUpdate, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + mn := min(m, n) + wantq := vect == lapack.ApplyQ + if wantq { + if m < n || n < min(m, k) || m < min(m, k) { + panic(badDims) + } + } else { + if n < m || m < min(n, k) || n < min(n, k) { + panic(badDims) + } + } + if wantq { + checkMatrix(m, k, a, lda) + } else { + checkMatrix(k, n, a, lda) + } + if lwork == -1 { + work[0] = float64(mn) + return + } + if len(work) < lwork { + panic(badWork) + } + if lwork < mn { + panic(badWork) + } + lapacke.Dorgbr(byte(vect), m, n, k, a, lda, tau, work, lwork) +} + +// Dorghr generates an n×n orthogonal matrix Q which is defined as the product +// of ihi-ilo elementary reflectors: +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// +// a and lda represent an n×n matrix that contains the elementary reflectors, as +// returned by Dgehrd. On return, a is overwritten by the n×n orthogonal matrix +// Q. Q will be equal to the identity matrix except in the submatrix +// Q[ilo+1:ihi+1,ilo+1:ihi+1]. +// +// ilo and ihi must have the same values as in the previous call of Dgehrd. It +// must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo = 0, ihi = -1, if n == 0. +// +// tau contains the scalar factors of the elementary reflectors, as returned by +// Dgehrd. tau must have length n-1. +// +// work must have length at least max(1,lwork) and lwork must be at least +// ihi-ilo. For optimum performance lwork must be at least (ihi-ilo)*nb where nb +// is the optimal blocksize. On return, work[0] will contain the optimal value +// of lwork. +// +// If lwork == -1, instead of performing Dorghr, only the optimal value of lwork +// will be stored into work[0]. +// +// If any requirement on input sizes is not met, Dorghr will panic. +// +// Dorghr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorghr(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) { + checkMatrix(n, n, a, lda) + nh := ihi - ilo + switch { + case ilo < 0 || max(1, n) <= ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case lwork < max(1, nh) && lwork != -1: + panic(badWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + lapacke.Dorghr(n, ilo+1, ihi+1, a, lda, tau, work, lwork) +} + +// Dorglq generates an m×n matrix Q with orthonormal rows defined by the product +// of elementary reflectors +// Q = H_{k-1} * ... * H_1 * H_0 +// as computed by Dgelqf. Dorglq is the blocked version of Dorgl2 that makes +// greater use of level-3 BLAS routines. +// +// len(tau) >= k, 0 <= k <= n, and 0 <= m <= n. +// +// work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= m, and the amount of blocking is limited by the usable length. +// If lwork == -1, instead of computing Dorglq the optimal work length is stored +// into work[0]. +// +// Dorglq will panic if the conditions on input values are not met. +// +// Dorglq is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + if lwork == -1 { + work[0] = float64(m) + return + } + checkMatrix(m, n, a, lda) + if k < 0 { + panic(kLT0) + } + if k > m { + panic(kGTM) + } + if m > n { + panic(nLTM) + } + if len(tau) < k { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + if lwork < m { + panic(badWork) + } + lapacke.Dorglq(m, n, k, a, lda, tau, work, lwork) +} + +// Dorgql generates the m×n matrix Q with orthonormal columns defined as the +// last n columns of a product of k elementary reflectors of order m +// Q = H_{k-1} * ... * H_1 * H_0. +// +// It must hold that +// 0 <= k <= n <= m, +// and Dorgql will panic otherwise. +// +// On entry, the (n-k+i)-th column of A must contain the vector which defines +// the elementary reflector H_i, for i=0,...,k-1, and tau[i] must contain its +// scalar factor. On return, a contains the m×n matrix Q. +// +// tau must have length at least k, and Dorgql will panic otherwise. +// +// work must have length at least max(1,lwork), and lwork must be at least +// max(1,n), otherwise Dorgql will panic. For optimum performance lwork must +// be a sufficiently large multiple of n. +// +// If lwork == -1, instead of computing Dorgql the optimal work length is stored +// into work[0]. +// +// Dorgql is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgql(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + switch { + case n < 0: + panic(nLT0) + case m < n: + panic(mLTN) + case k < 0: + panic(kLT0) + case k > n: + panic(kGTN) + case lwork < max(1, n) && lwork != -1: + panic(badWork) + case len(work) < lwork: + panic(shortWork) + } + if lwork != -1 { + checkMatrix(m, n, a, lda) + if len(tau) < k { + panic(badTau) + } + } + + lapacke.Dorgql(m, n, k, a, lda, tau, work, lwork) +} + +// Dorgqr generates an m×n matrix Q with orthonormal columns defined by the +// product of elementary reflectors +// Q = H_0 * H_1 * ... * H_{k-1} +// as computed by Dgeqrf. Dorgqr is the blocked version of Dorg2r that makes +// greater use of level-3 BLAS routines. +// +// The length of tau must be at least k, and the length of work must be at least n. +// It also must be that 0 <= k <= n and 0 <= n <= m. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= n, and the amount of blocking is limited by the usable +// length. If lwork == -1, instead of computing Dorgqr the optimal work length +// is stored into work[0]. +// +// Dorgqr will panic if the conditions on input values are not met. +// +// Dorgqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + if lwork == -1 { + work[0] = float64(n) + return + } + checkMatrix(m, n, a, lda) + if k < 0 { + panic(kLT0) + } + if k > n { + panic(kGTN) + } + if n > m { + panic(mLTN) + } + if len(tau) < k { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + if lwork < n { + panic(badWork) + } + lapacke.Dorgqr(m, n, k, a, lda, tau, work, lwork) +} + +// Dorgtr generates a real orthogonal matrix Q which is defined as the product +// of n-1 elementary reflectors of order n as returned by Dsytrd. +// +// The construction of Q depends on the value of uplo: +// Q = H_{n-1} * ... * H_1 * H_0 if uplo == blas.Upper +// Q = H_0 * H_1 * ... * H_{n-1} if uplo == blas.Lower +// where H_i is constructed from the elementary reflectors as computed by Dsytrd. +// See the documentation for Dsytrd for more information. +// +// tau must have length at least n-1, and Dorgtr will panic otherwise. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= max(1,n-1), and Dorgtr will panic otherwise. The amount of blocking +// is limited by the usable length. +// If lwork == -1, instead of computing Dorgtr the optimal work length is stored +// into work[0]. +// +// Dorgtr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, tau, work []float64, lwork int) { + checkMatrix(n, n, a, lda) + if len(tau) < n-1 { + panic(badTau) + } + if len(work) < lwork { + panic(badWork) + } + if lwork < n-1 && lwork != -1 { + panic(badWork) + } + upper := uplo == blas.Upper + if !upper && uplo != blas.Lower { + panic(badUplo) + } + lapacke.Dorgtr(uplo, n, a, lda, tau, work, lwork) +} + +// Dormbr applies a multiplicative update to the matrix C based on a +// decomposition computed by Dgebrd. +// +// Dormbr overwrites the m×n matrix C with +// Q * C if vect == lapack.ApplyQ, side == blas.Left, and trans == blas.NoTrans +// C * Q if vect == lapack.ApplyQ, side == blas.Right, and trans == blas.NoTrans +// Q^T * C if vect == lapack.ApplyQ, side == blas.Left, and trans == blas.Trans +// C * Q^T if vect == lapack.ApplyQ, side == blas.Right, and trans == blas.Trans +// +// P * C if vect == lapack.ApplyP, side == blas.Left, and trans == blas.NoTrans +// C * P if vect == lapack.ApplyP, side == blas.Right, and trans == blas.NoTrans +// P^T * C if vect == lapack.ApplyP, side == blas.Left, and trans == blas.Trans +// C * P^T if vect == lapack.ApplyP, side == blas.Right, and trans == blas.Trans +// where P and Q are the orthogonal matrices determined by Dgebrd when reducing +// a matrix A to bidiagonal form: A = Q * B * P^T. See Dgebrd for the +// definitions of Q and P. +// +// If vect == lapack.ApplyQ, A is assumed to have been an nq×k matrix, while if +// vect == lapack.ApplyP, A is assumed to have been a k×nq matrix. nq = m if +// side == blas.Left, while nq = n if side == blas.Right. +// +// tau must have length min(nq,k), and Dormbr will panic otherwise. tau contains +// the elementary reflectors to construct Q or P depending on the value of +// vect. +// +// work must have length at least max(1,lwork), and lwork must be either -1 or +// at least max(1,n) if side == blas.Left, and at least max(1,m) if side == +// blas.Right. For optimum performance lwork should be at least n*nb if side == +// blas.Left, and at least m*nb if side == blas.Right, where nb is the optimal +// block size. On return, work[0] will contain the optimal value of lwork. +// +// If lwork == -1, the function only calculates the optimal value of lwork and +// returns it in work[0]. +// +// Dormbr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dormbr(vect lapack.DecompUpdate, side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.NoTrans && trans != blas.Trans { + panic(badTrans) + } + if vect != lapack.ApplyP && vect != lapack.ApplyQ { + panic(badDecompUpdate) + } + nq := n + nw := m + if side == blas.Left { + nq = m + nw = n + } + if vect == lapack.ApplyQ { + checkMatrix(nq, min(nq, k), a, lda) + } else { + checkMatrix(min(nq, k), nq, a, lda) + } + if len(tau) < min(nq, k) { + panic(badTau) + } + checkMatrix(m, n, c, ldc) + if len(work) < lwork { + panic(shortWork) + } + if lwork < max(1, nw) && lwork != -1 { + panic(badWork) + } + lapacke.Dormbr(byte(vect), side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork) +} + +// Dormhr multiplies an m×n general matrix C with an nq×nq orthogonal matrix Q +// Q * C, if side == blas.Left and trans == blas.NoTrans, +// Q^T * C, if side == blas.Left and trans == blas.Trans, +// C * Q, if side == blas.Right and trans == blas.NoTrans, +// C * Q^T, if side == blas.Right and trans == blas.Trans, +// where nq == m if side == blas.Left and nq == n if side == blas.Right. +// +// Q is defined implicitly as the product of ihi-ilo elementary reflectors, as +// returned by Dgehrd: +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// Q is equal to the identity matrix except in the submatrix +// Q[ilo+1:ihi+1,ilo+1:ihi+1]. +// +// ilo and ihi must have the same values as in the previous call of Dgehrd. It +// must hold that +// 0 <= ilo <= ihi < m, if m > 0 and side == blas.Left, +// ilo = 0 and ihi = -1, if m = 0 and side == blas.Left, +// 0 <= ilo <= ihi < n, if n > 0 and side == blas.Right, +// ilo = 0 and ihi = -1, if n = 0 and side == blas.Right. +// +// a and lda represent an m×m matrix if side == blas.Left and an n×n matrix if +// side == blas.Right. The matrix contains vectors which define the elementary +// reflectors, as returned by Dgehrd. +// +// tau contains the scalar factors of the elementary reflectors, as returned by +// Dgehrd. tau must have length m-1 if side == blas.Left and n-1 if side == +// blas.Right. +// +// c and ldc represent the m×n matrix C. On return, c is overwritten by the +// product with Q. +// +// work must have length at least max(1,lwork), and lwork must be at least +// max(1,n), if side == blas.Left, and max(1,m), if side == blas.Right. For +// optimum performance lwork should be at least n*nb if side == blas.Left and +// m*nb if side == blas.Right, where nb is the optimal block size. On return, +// work[0] will contain the optimal value of lwork. +// +// If lwork == -1, instead of performing Dormhr, only the optimal value of lwork +// will be stored in work[0]. +// +// If any requirement on input sizes is not met, Dormhr will panic. +// +// Dormhr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dormhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + var ( + nq int // The order of Q. + nw int // The minimum length of work. + ) + switch side { + case blas.Left: + nq = m + nw = n + case blas.Right: + nq = n + nw = m + default: + panic(badSide) + } + switch { + case trans != blas.NoTrans && trans != blas.Trans: + panic(badTrans) + case ilo < 0 || max(1, nq) <= ilo: + panic(badIlo) + case ihi < min(ilo, nq-1) || nq <= ihi: + panic(badIhi) + case lwork < max(1, nw) && lwork != -1: + panic(badWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + if lwork != -1 { + checkMatrix(m, n, c, ldc) + checkMatrix(nq, nq, a, lda) + if len(tau) != nq-1 && nq > 0 { + panic(badTau) + } + } + lapacke.Dormhr(side, trans, m, n, ilo+1, ihi+1, a, lda, tau, c, ldc, work, lwork) +} + +// Dormlq multiplies the matrix C by the orthogonal matrix Q defined by the +// slices a and tau. A and tau are as returned from Dgelqf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, A is a matrix of side k×m, and if side == blas.Right +// A is of size k×n. This uses a blocked algorithm. +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right, +// and this function will panic otherwise. +// Dormlq uses a block algorithm, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dormlq, +// the optimal work length will be stored into work[0]. +// +// tau contains the Householder scales and must have length at least k, and +// this function will panic otherwise. +func (impl Implementation) Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + left := side == blas.Left + if left { + checkMatrix(k, m, a, lda) + } else { + checkMatrix(k, n, a, lda) + } + checkMatrix(m, n, c, ldc) + if len(tau) < k { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + nw := m + if left { + nw = n + } + if lwork < max(1, nw) && lwork != -1 { + panic(badWork) + } + + lapacke.Dormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork) +} + +// Dormqr multiplies an m×n matrix C by an orthogonal matrix Q as +// C = Q * C, if side == blas.Left and trans == blas.NoTrans, +// C = Q^T * C, if side == blas.Left and trans == blas.Trans, +// C = C * Q, if side == blas.Right and trans == blas.NoTrans, +// C = C * Q^T, if side == blas.Right and trans == blas.Trans, +// where Q is defined as the product of k elementary reflectors +// Q = H_0 * H_1 * ... * H_{k-1}. +// +// If side == blas.Left, A is an m×k matrix and 0 <= k <= m. +// If side == blas.Right, A is an n×k matrix and 0 <= k <= n. +// The ith column of A contains the vector which defines the elementary +// reflector H_i and tau[i] contains its scalar factor. tau must have length k +// and Dormqr will panic otherwise. Dgeqrf returns A and tau in the required +// form. +// +// work must have length at least max(1,lwork), and lwork must be at least n if +// side == blas.Left and at least m if side == blas.Right, otherwise Dormqr will +// panic. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= m if side == blas.Left and lwork >= n if side == +// blas.Right, and this function will panic otherwise. Larger values of lwork +// will generally give better performance. On return, work[0] will contain the +// optimal value of lwork. +// +// If lwork is -1, instead of performing Dormqr, the optimal workspace size will +// be stored into work[0]. +func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + var nq, nw int + switch side { + default: + panic(badSide) + case blas.Left: + nq = m + nw = n + case blas.Right: + nq = n + nw = m + } + switch { + case trans != blas.NoTrans && trans != blas.Trans: + panic(badTrans) + case m < 0 || n < 0: + panic(negDimension) + case k < 0 || nq < k: + panic("lapack: invalid value of k") + case len(work) < lwork: + panic(shortWork) + case lwork < max(1, nw) && lwork != -1: + panic(badWork) + } + if lwork != -1 { + checkMatrix(nq, k, a, lda) + checkMatrix(m, n, c, ldc) + if len(tau) != k { + panic(badTau) + } + } + + lapacke.Dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork) +} + +// Dpocon estimates the reciprocal of the condition number of a positive-definite +// matrix A given the Cholesky decomposition of A. The condition number computed +// is based on the 1-norm and the ∞-norm. +// +// anorm is the 1-norm and the ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 3*n and Dpocon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Dpocon will panic otherwise. +// Elements of iwork must fit within the int32 type or Dpocon will panic. +func (impl Implementation) Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { + checkMatrix(n, n, a, lda) + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if len(work) < 3*n { + panic(badWork) + } + if len(iwork) < n { + panic(badWork) + } + rcond := make([]float64, 1) + _iwork := make([]int32, len(iwork)) + for i, v := range iwork { + if v != int(int32(v)) { + panic("lapack: iwork element out of range") + } + _iwork[i] = int32(v) + } + lapacke.Dpocon(uplo, n, a, lda, anorm, rcond, work, _iwork) + for i, v := range _iwork { + iwork[i] = int(v) + } + return rcond[0] +} + +// Dsteqr computes the eigenvalues and optionally the eigenvectors of a symmetric +// tridiagonal matrix using the implicit QL or QR method. The eigenvectors of a +// full or band symmetric matrix can also be found if Dsytrd, Dsptrd, or Dsbtrd +// have been used to reduce this matrix to tridiagonal form. +// +// d, on entry, contains the diagonal elements of the tridiagonal matrix. On exit, +// d contains the eigenvalues in ascending order. d must have length n and +// Dsteqr will panic otherwise. +// +// e, on entry, contains the off-diagonal elements of the tridiagonal matrix on +// entry, and is overwritten during the call to Dsteqr. e must have length n-1 and +// Dsteqr will panic otherwise. +// +// z, on entry, contains the n×n orthogonal matrix used in the reduction to +// tridiagonal form if compz == lapack.OriginalEV. On exit, if +// compz == lapack.OriginalEV, z contains the orthonormal eigenvectors of the +// original symmetric matrix, and if compz == lapack.TridiagEV, z contains the +// orthonormal eigenvectors of the symmetric tridiagonal matrix. z is not used +// if compz == lapack.None. +// +// work must have length at least max(1, 2*n-2) if the eigenvectors are computed, +// and Dsteqr will panic otherwise. +// +// Dsteqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsteqr(compz lapack.EVComp, n int, d, e, z []float64, ldz int, work []float64) (ok bool) { + if n < 0 { + panic(nLT0) + } + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if compz != lapack.None && compz != lapack.TridiagEV && compz != lapack.OriginalEV { + panic(badEVComp) + } + if compz != lapack.None { + if len(work) < max(1, 2*n-2) { + panic(badWork) + } + checkMatrix(n, n, z, ldz) + } + + return lapacke.Dsteqr(lapack.Comp(compz), n, d, e, z, ldz, work) +} + +// Dsterf computes all eigenvalues of a symmetric tridiagonal matrix using the +// Pal-Walker-Kahan variant of the QL or QR algorithm. +// +// d contains the diagonal elements of the tridiagonal matrix on entry, and +// contains the eigenvalues in ascending order on exit. d must have length at +// least n, or Dsterf will panic. +// +// e contains the off-diagonal elements of the tridiagonal matrix on entry, and is +// overwritten during the call to Dsterf. e must have length of at least n-1 or +// Dsterf will panic. +// +// Dsterf is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsterf(n int, d, e []float64) (ok bool) { + if n < 0 { + panic(nLT0) + } + if n == 0 { + return true + } + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + + return lapacke.Dsterf(n, d, e) +} + +// Dsyev computes all eigenvalues and, optionally, the eigenvectors of a real +// symmetric matrix A. +// +// w contains the eigenvalues in ascending order upon return. w must have length +// at least n, and Dsyev will panic otherwise. +// +// On entry, a contains the elements of the symmetric matrix A in the triangular +// portion specified by uplo. If jobz == lapack.ComputeEV a contains the +// orthonormal eigenvectors of A on exit, otherwise on exit the specified +// triangular region is overwritten. +// +// work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= 3*n-1, and Dsyev will panic otherwise. The amount of blocking is +// limited by the usable length. If lwork == -1, instead of computing Dsyev the +// optimal work length is stored into work[0]. +func (impl Implementation) Dsyev(jobz lapack.EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) { + checkMatrix(n, n, a, lda) + if lwork == -1 { + work[0] = 3*float64(n) - 1 + return + } + if len(work) < lwork { + panic(badWork) + } + if lwork < 3*n-1 { + panic(badWork) + } + return lapacke.Dsyev(lapack.Job(jobz), uplo, n, a, lda, w, work, lwork) +} + +// Dsytrd reduces a symmetric n×n matrix A to symmetric tridiagonal form by an +// orthogonal similarity transformation +// Q^T * A * Q = T +// where Q is an orthonormal matrix and T is symmetric and tridiagonal. +// +// On entry, a contains the elements of the input matrix in the triangle specified +// by uplo. On exit, the diagonal and sub/super-diagonal are overwritten by the +// corresponding elements of the tridiagonal matrix T. The remaining elements in +// the triangle, along with the array tau, contain the data to construct Q as +// the product of elementary reflectors. +// +// If uplo == blas.Upper, Q is constructed with +// Q = H_{n-2} * ... * H_1 * H_0 +// where +// H_i = I - tau_i * v * v^T +// v is constructed as v[i+1:n] = 0, v[i] = 1, v[0:i-1] is stored in A[0:i-1, i+1]. +// The elements of A are +// [ d e v1 v2 v3] +// [ d e v2 v3] +// [ d e v3] +// [ d e] +// [ e] +// +// If uplo == blas.Lower, Q is constructed with +// Q = H_0 * H_1 * ... * H_{n-2} +// where +// H_i = I - tau_i * v * v^T +// v is constructed as v[0:i+1] = 0, v[i+1] = 1, v[i+2:n] is stored in A[i+2:n, i]. +// The elements of A are +// [ d ] +// [ e d ] +// [v0 e d ] +// [v0 v1 e d ] +// [v0 v1 v2 e d] +// +// d must have length n, and e and tau must have length n-1. Dsytrd will panic if +// these conditions are not met. +// +// work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= 1, and Dsytrd will panic otherwise. The amount of blocking is +// limited by the usable length. +// If lwork == -1, instead of computing Dsytrd the optimal work length is stored +// into work[0]. +// +// Dsytrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsytrd(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau, work []float64, lwork int) { + checkMatrix(n, n, a, lda) + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if len(tau) < n-1 { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + if lwork != -1 && lwork < 1 { + panic(badWork) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + + lapacke.Dsytrd(uplo, n, a, lda, d, e, tau, work, lwork) +} + +// Dtrcon estimates the reciprocal of the condition number of a triangular matrix A. +// The condition number computed may be based on the 1-norm or the ∞-norm. +// +// work is a temporary data slice of length at least 3*n and Dtrcon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Dtrcon will panic otherwise. +// Elements of iwork must fit within the int32 type or Dtrcon will panic. +func (impl Implementation) Dtrcon(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 { + if norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum { + panic(badNorm) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.NonUnit && diag != blas.Unit { + panic(badDiag) + } + if len(work) < 3*n { + panic(badWork) + } + if len(iwork) < n { + panic(badWork) + } + rcond := []float64{0} + _iwork := make([]int32, len(iwork)) + for i, v := range iwork { + if v != int(int32(v)) { + panic("lapack: iwork element out of range") + } + _iwork[i] = int32(v) + } + lapacke.Dtrcon(byte(norm), uplo, diag, n, a, lda, rcond, work, _iwork) + for i, v := range _iwork { + iwork[i] = int(v) + } + return rcond[0] +} + +// Dtrexc reorders the real Schur factorization of a n×n real matrix +// A = Q*T*Q^T +// so that the diagonal block of T with row index ifst is moved to row ilst. +// +// On entry, T must be in Schur canonical form, that is, block upper triangular +// with 1×1 and 2×2 diagonal blocks; each 2×2 diagonal block has its diagonal +// elements equal and its off-diagonal elements of opposite sign. +// +// On return, T will be reordered by an orthogonal similarity transformation Z +// as Z^T*T*Z, and will be again in Schur canonical form. +// +// If compq is lapack.UpdateSchur, on return the matrix Q of Schur vectors will be +// updated by postmultiplying it with Z. +// If compq is lapack.None, the matrix Q is not referenced and will not be +// updated. +// For other values of compq Dtrexc will panic. +// +// ifst and ilst specify the reordering of the diagonal blocks of T. The block +// with row index ifst is moved to row ilst, by a sequence of transpositions +// between adjacent blocks. +// +// If ifst points to the second row of a 2×2 block, ifstOut will point to the +// first row, otherwise it will be equal to ifst. +// +// ilstOut will point to the first row of the block in its final position. If ok +// is true, ilstOut may differ from ilst by +1 or -1. +// +// It must hold that +// 0 <= ifst < n, and 0 <= ilst < n, +// otherwise Dtrexc will panic. +// +// If ok is false, two adjacent blocks were too close to swap because the +// problem is very ill-conditioned. T may have been partially reordered, and +// ilstOut will point to the first row of the block at the position to which it +// has been moved. +// +// work must have length at least n, otherwise Dtrexc will panic. +// +// Dtrexc is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtrexc(compq lapack.EVComp, n int, t []float64, ldt int, q []float64, ldq int, ifst, ilst int, work []float64) (ifstOut, ilstOut int, ok bool) { + checkMatrix(n, n, t, ldt) + switch compq { + default: + panic("lapack: bad value of compq") + case lapack.None: + // q is not referenced but LAPACKE checks that ldq >= n always. + q = nil + ldq = max(1, n) + case lapack.UpdateSchur: + checkMatrix(n, n, q, ldq) + } + if (ifst < 0 || n <= ifst) && n > 0 { + panic("lapack: ifst out of range") + } + if (ilst < 0 || n <= ilst) && n > 0 { + panic("lapack: ilst out of range") + } + if len(work) < n { + panic(badWork) + } + + // Quick return if possible. + if n <= 1 { + return ifst, ilst, true + } + + ifst32 := []int32{int32(ifst + 1)} + ilst32 := []int32{int32(ilst + 1)} + ok = lapacke.Dtrexc(lapack.Comp(compq), n, t, ldt, q, ldq, ifst32, ilst32, work) + ifst = int(ifst32[0] - 1) + ilst = int(ilst32[0] - 1) + return ifst, ilst, ok +} + +// Dtrtri computes the inverse of a triangular matrix, storing the result in place +// into a. This is the BLAS level 3 version of the algorithm which builds upon +// Dtrti2 to operate on matrix blocks instead of only individual columns. +// +// Dtrtri returns whether the matrix a is singular. +// If the matrix is singular, the inversion is not performed. +func (impl Implementation) Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) (ok bool) { + checkMatrix(n, n, a, lda) + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.NonUnit && diag != blas.Unit { + panic(badDiag) + } + return lapacke.Dtrtri(uplo, diag, n, a, lda) +} + +// Dtrtrs solves a triangular system of the form A * X = B or A^T * X = B. +// Dtrtrs returns whether the solve completed successfully. +// If A is singular, no solve is performed. +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) { + return lapacke.Dtrtrs(uplo, trans, diag, n, nrhs, a, lda, b, ldb) +} + +// Dhseqr computes the eigenvalues of an n×n Hessenberg matrix H and, +// optionally, the matrices T and Z from the Schur decomposition +// H = Z T Z^T, +// where T is an n×n upper quasi-triangular matrix (the Schur form), and Z is +// the n×n orthogonal matrix of Schur vectors. +// +// Optionally Z may be postmultiplied into an input orthogonal matrix Q so that +// this routine can give the Schur factorization of a matrix A which has been +// reduced to the Hessenberg form H by the orthogonal matrix Q: +// A = Q H Q^T = (QZ) T (QZ)^T. +// +// If job == lapack.EigenvaluesOnly, only the eigenvalues will be computed. +// If job == lapack.EigenvaluesAndSchur, the eigenvalues and the Schur form T will +// be computed. +// For other values of job Dhseqr will panic. +// +// If compz == lapack.None, no Schur vectors will be computed and Z will not be +// referenced. +// If compz == lapack.HessEV, on return Z will contain the matrix of Schur +// vectors of H. +// If compz == lapack.OriginalEV, on entry z is assumed to contain the orthogonal +// matrix Q that is the identity except for the submatrix +// Q[ilo:ihi+1,ilo:ihi+1]. On return z will be updated to the product Q*Z. +// +// ilo and ihi determine the block of H on which Dhseqr operates. It is assumed +// that H is already upper triangular in rows and columns [0:ilo] and [ihi+1:n], +// although it will be only checked that the block is isolated, that is, +// ilo == 0 or H[ilo,ilo-1] == 0, +// ihi == n-1 or H[ihi+1,ihi] == 0, +// and Dhseqr will panic otherwise. ilo and ihi are typically set by a previous +// call to Dgebal, otherwise they should be set to 0 and n-1, respectively. It +// must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo == 0 and ihi == -1, if n == 0. +// +// wr and wi must have length n. +// +// work must have length at least lwork and lwork must be at least max(1,n) +// otherwise Dhseqr will panic. The minimum lwork delivers very good and +// sometimes optimal performance, although lwork as large as 11*n may be +// required. On return, work[0] will contain the optimal value of lwork. +// +// If lwork is -1, instead of performing Dhseqr, the function only estimates the +// optimal workspace size and stores it into work[0]. Neither h nor z are +// accessed. +// +// unconverged indicates whether Dhseqr computed all the eigenvalues. +// +// If unconverged == 0, all the eigenvalues have been computed and their real +// and imaginary parts will be stored on return in wr and wi, respectively. If +// two eigenvalues are computed as a complex conjugate pair, they are stored in +// consecutive elements of wr and wi, say the i-th and (i+1)th, with wi[i] > 0 +// and wi[i+1] < 0. +// +// If unconverged == 0 and job == lapack.EigenvaluesAndSchur, on return H will +// contain the upper quasi-triangular matrix T from the Schur decomposition (the +// Schur form). 2×2 diagonal blocks (corresponding to complex conjugate pairs of +// eigenvalues) will be returned in standard form, with +// H[i,i] == H[i+1,i+1], +// and +// H[i+1,i]*H[i,i+1] < 0. +// The eigenvalues will be stored in wr and wi in the same order as on the +// diagonal of the Schur form returned in H, with +// wr[i] = H[i,i], +// and, if H[i:i+2,i:i+2] is a 2×2 diagonal block, +// wi[i] = sqrt(-H[i+1,i]*H[i,i+1]), +// wi[i+1] = -wi[i]. +// +// If unconverged == 0 and job == lapack.EigenvaluesOnly, the contents of h +// on return is unspecified. +// +// If unconverged > 0, some eigenvalues have not converged, and the blocks +// [0:ilo] and [unconverged:n] of wr and wi will contain those eigenvalues which +// have been successfully computed. Failures are rare. +// +// If unconverged > 0 and job == lapack.EigenvaluesOnly, on return the +// remaining unconverged eigenvalues are the eigenvalues of the upper Hessenberg +// matrix H[ilo:unconverged,ilo:unconverged]. +// +// If unconverged > 0 and job == lapack.EigenvaluesAndSchur, then on +// return +// (initial H) U = U (final H), (*) +// where U is an orthogonal matrix. The final H is upper Hessenberg and +// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. +// +// If unconverged > 0 and compz == lapack.OriginalEV, then on return +// (final Z) = (initial Z) U, +// where U is the orthogonal matrix in (*) regardless of the value of job. +// +// If unconverged > 0 and compz == lapack.InitZ, then on return +// (final Z) = U, +// where U is the orthogonal matrix in (*) regardless of the value of job. +// +// References: +// [1] R. Byers. LAPACK 3.1 xHSEQR: Tuning and Implementation Notes on the +// Small Bulge Multi-Shift QR Algorithm with Aggressive Early Deflation. +// LAPACK Working Note 187 (2007) +// URL: http://www.netlib.org/lapack/lawnspdf/lawn187.pdf +// [2] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part I: +// Maintaining Well-Focused Shifts and Level 3 Performance. SIAM J. Matrix +// Anal. Appl. 23(4) (2002), pp. 929—947 +// URL: http://dx.doi.org/10.1137/S0895479801384573 +// [3] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: +// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl. 23(4) (2002), pp. 948—973 +// URL: http://dx.doi.org/10.1137/S0895479801384585 +// +// Dhseqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dhseqr(job lapack.EVJob, compz lapack.EVComp, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, z []float64, ldz int, work []float64, lwork int) (unconverged int) { + switch job { + default: + panic(badEVJob) + case lapack.EigenvaluesOnly, lapack.EigenvaluesAndSchur: + } + var wantz bool + switch compz { + default: + panic(badEVComp) + case lapack.None: + case lapack.HessEV, lapack.OriginalEV: + wantz = true + } + switch { + case n < 0: + panic(nLT0) + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case len(work) < lwork: + panic(shortWork) + case lwork < max(1, n) && lwork != -1: + panic(badWork) + } + if lwork != -1 { + checkMatrix(n, n, h, ldh) + switch { + case wantz: + checkMatrix(n, n, z, ldz) + case len(wr) < n: + panic("lapack: wr has insufficient length") + case len(wi) < n: + panic("lapack: wi has insufficient length") + } + } + + return lapacke.Dhseqr(lapack.Job(job), lapack.Comp(compz), n, ilo+1, ihi+1, + h, ldh, wr, wi, z, ldz, work, lwork) +} + +// Dgeev computes the eigenvalues and, optionally, the left and/or right +// eigenvectors for an n×n real nonsymmetric matrix A. +// +// The right eigenvector v_j of A corresponding to an eigenvalue λ_j +// is defined by +// A v_j = λ_j v_j, +// and the left eigenvector u_j corresponding to an eigenvalue λ_j is defined by +// u_j^H A = λ_j u_j^H, +// where u_j^H is the conjugate transpose of u_j. +// +// On return, A will be overwritten and the left and right eigenvectors will be +// stored, respectively, in the columns of the n×n matrices VL and VR in the +// same order as their eigenvalues. If the j-th eigenvalue is real, then +// u_j = VL[:,j], +// v_j = VR[:,j], +// and if it is not real, then j and j+1 form a complex conjugate pair and the +// eigenvectors can be recovered as +// u_j = VL[:,j] + i*VL[:,j+1], +// u_{j+1} = VL[:,j] - i*VL[:,j+1], +// v_j = VR[:,j] + i*VR[:,j+1], +// v_{j+1} = VR[:,j] - i*VR[:,j+1]. +// where i is the imaginary unit. The computed eigenvectors are normalized to +// have Euclidean norm equal to 1 and largest component real. +// +// Left eigenvectors will be computed only if jobvl == lapack.ComputeLeftEV, +// otherwise jobvl must be lapack.None. Right eigenvectors will be computed +// only if jobvr == lapack.ComputeRightEV, otherwise jobvr must be lapack.None. +// For other values of jobvl and jobvr Dgeev will panic. +// +// wr and wi contain the real and imaginary parts, respectively, of the computed +// eigenvalues. Complex conjugate pairs of eigenvalues appear consecutively with +// the eigenvalue having the positive imaginary part first. +// wr and wi must have length n, and Dgeev will panic otherwise. +// +// work must have length at least lwork and lwork must be at least max(1,4*n) if +// the left or right eigenvectors are computed, and at least max(1,3*n) if no +// eigenvectors are computed. For good performance, lwork must generally be +// larger. On return, optimal value of lwork will be stored in work[0]. +// +// If lwork == -1, instead of performing Dgeev, the function only calculates the +// optimal vaule of lwork and stores it into work[0]. +// +// On return, first is the index of the first valid eigenvalue. If first == 0, +// all eigenvalues and eigenvectors have been computed. If first is positive, +// Dgeev failed to compute all the eigenvalues, no eigenvectors have been +// computed and wr[first:] and wi[first:] contain those eigenvalues which have +// converged. +func (impl Implementation) Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, n int, a []float64, lda int, wr, wi []float64, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) (first int) { + var wantvl bool + switch jobvl { + default: + panic("lapack: invalid LeftEVJob") + case lapack.ComputeLeftEV: + wantvl = true + case lapack.None: + wantvl = false + } + var wantvr bool + switch jobvr { + default: + panic("lapack: invalid RightEVJob") + case lapack.ComputeRightEV: + wantvr = true + case lapack.None: + wantvr = false + } + switch { + case n < 0: + panic(nLT0) + case len(work) < lwork: + panic(shortWork) + } + var minwrk int + if wantvl || wantvr { + minwrk = max(1, 4*n) + } else { + minwrk = max(1, 3*n) + } + if lwork != -1 { + checkMatrix(n, n, a, lda) + if wantvl { + checkMatrix(n, n, vl, ldvl) + } + if wantvr { + checkMatrix(n, n, vr, ldvr) + } + switch { + case len(wr) != n: + panic("lapack: bad length of wr") + case len(wi) != n: + panic("lapack: bad length of wi") + case lwork < minwrk: + panic(badWork) + } + } + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return 0 + } + + first = lapacke.Dgeev(lapack.Job(jobvl), lapack.Job(jobvr), n, a, max(n, lda), wr, wi, + vl, max(n, ldvl), vr, max(n, ldvr), work, lwork) + if lwork == -1 && int(work[0]) < minwrk { + work[0] = float64(minwrk) + } + return first +} + +// Dtgsja computes the generalized singular value decomposition (GSVD) +// of two real upper triangular or trapezoidal matrices A and B. +// +// A and B have the following forms, which may be obtained by the +// preprocessing subroutine Dggsvp from a general m×n matrix A and p×n +// matrix B: +// +// n-k-l k l +// A = k [ 0 A12 A13 ] if m-k-l >= 0; +// l [ 0 0 A23 ] +// m-k-l [ 0 0 0 ] +// +// n-k-l k l +// A = k [ 0 A12 A13 ] if m-k-l < 0; +// m-k [ 0 0 A23 ] +// +// n-k-l k l +// B = l [ 0 0 B13 ] +// p-l [ 0 0 0 ] +// +// where the k×k matrix A12 and l×l matrix B13 are non-singular +// upper triangular. A23 is l×l upper triangular if m-k-l >= 0, +// otherwise A23 is (m-k)×l upper trapezoidal. +// +// On exit, +// +// U^T*A*Q = D1*[ 0 R ], V^T*B*Q = D2*[ 0 R ], +// +// where U, V and Q are orthogonal matrices. +// R is a non-singular upper triangular matrix, and D1 and D2 are +// diagonal matrices, which are of the following structures: +// +// If m-k-l >= 0, +// +// k l +// D1 = k [ I 0 ] +// l [ 0 C ] +// m-k-l [ 0 0 ] +// +// k l +// D2 = l [ 0 S ] +// p-l [ 0 0 ] +// +// n-k-l k l +// [ 0 R ] = k [ 0 R11 R12 ] k +// l [ 0 0 R22 ] l +// +// where +// +// C = diag( alpha_k, ... , alpha_{k+l} ), +// S = diag( beta_k, ... , beta_{k+l} ), +// C^2 + S^2 = I. +// +// R is stored in +// A[0:k+l, n-k-l:n] +// on exit. +// +// If m-k-l < 0, +// +// k m-k k+l-m +// D1 = k [ I 0 0 ] +// m-k [ 0 C 0 ] +// +// k m-k k+l-m +// D2 = m-k [ 0 S 0 ] +// k+l-m [ 0 0 I ] +// p-l [ 0 0 0 ] +// +// n-k-l k m-k k+l-m +// [ 0 R ] = k [ 0 R11 R12 R13 ] +// m-k [ 0 0 R22 R23 ] +// k+l-m [ 0 0 0 R33 ] +// +// where +// C = diag( alpha_k, ... , alpha_m ), +// S = diag( beta_k, ... , beta_m ), +// C^2 + S^2 = I. +// +// R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n] +// [ 0 R22 R23 ] +// and R33 is stored in +// B[m-k:l, n+m-k-l:n] on exit. +// +// The computation of the orthogonal transformation matrices U, V or Q +// is optional. These matrices may either be formed explicitly, or they +// may be post-multiplied into input matrices U1, V1, or Q1. +// +// Dtgsja essentially uses a variant of Kogbetliantz algorithm to reduce +// min(l,m-k)×l triangular or trapezoidal matrix A23 and l×l +// matrix B13 to the form: +// +// U1^T*A13*Q1 = C1*R1; V1^T*B13*Q1 = S1*R1, +// +// where U1, V1 and Q1 are orthogonal matrices. C1 and S1 are diagonal +// matrices satisfying +// +// C1^2 + S1^2 = I, +// +// and R1 is an l×l non-singular upper triangular matrix. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDUnit Use unit-initialized matrix +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// k and l specify the sub-blocks in the input matrices A and B: +// A23 = A[k:min(k+l,m), n-l:n) and B13 = B[0:l, n-l:n] +// of A and B, whose GSVD is going to be computed by Dtgsja. +// +// tola and tolb are the convergence criteria for the Jacobi-Kogbetliantz +// iteration procedure. Generally, they are the same as used in the preprocessing +// step, for example, +// tola = max(m, n)*norm(A)*eps, +// tolb = max(p, n)*norm(B)*eps, +// where eps is the machine epsilon. +// +// work must have length at least 2*n, otherwise Dtgsja will panic. +// +// alpha and beta must have length n or Dtgsja will panic. On exit, alpha and +// beta contain the generalized singular value pairs of A and B +// alpha[0:k] = 1, +// beta[0:k] = 0, +// if m-k-l >= 0, +// alpha[k:k+l] = diag(C), +// beta[k:k+l] = diag(S), +// if m-k-l < 0, +// alpha[k:m]= C, alpha[m:k+l]= 0 +// beta[k:m] = S, beta[m:k+l] = 1. +// if k+l < n, +// alpha[k+l:n] = 0 and +// beta[k+l:n] = 0. +// +// On exit, A[n-k:n, 0:min(k+l,m)] contains the triangular matrix R or part of R +// and if necessary, B[m-k:l, n+m-k-l:n] contains a part of R. +// +// Dtgsja returns whether the routine converged and the number of iteration cycles +// that were run. +// +// Dtgsja is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtgsja(jobU, jobV, jobQ lapack.GSVDJob, m, p, n, k, l int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64) (cycles int, ok bool) { + checkMatrix(m, n, a, lda) + checkMatrix(p, n, b, ldb) + + if len(alpha) != n { + panic(badAlpha) + } + if len(beta) != n { + panic(badBeta) + } + + initu := jobU == lapack.GSVDUnit + wantu := initu || jobU == lapack.GSVDU + if !initu && !wantu && jobU != lapack.GSVDNone { + panic(badGSVDJob + "U") + } + if jobU != lapack.GSVDNone { + checkMatrix(m, m, u, ldu) + } + + initv := jobV == lapack.GSVDUnit + wantv := initv || jobV == lapack.GSVDV + if !initv && !wantv && jobV != lapack.GSVDNone { + panic(badGSVDJob + "V") + } + if jobV != lapack.GSVDNone { + checkMatrix(p, p, v, ldv) + } + + initq := jobQ == lapack.GSVDUnit + wantq := initq || jobQ == lapack.GSVDQ + if !initq && !wantq && jobQ != lapack.GSVDNone { + panic(badGSVDJob + "Q") + } + if jobQ != lapack.GSVDNone { + checkMatrix(n, n, q, ldq) + } + + if len(work) < 2*n { + panic(badWork) + } + + ncycle := []int32{0} + ok = lapacke.Dtgsja(lapack.Job(jobU), lapack.Job(jobV), lapack.Job(jobQ), m, p, n, k, l, a, lda, b, ldb, tola, tolb, alpha, beta, u, ldu, v, ldv, q, ldq, work, ncycle) + return int(ncycle[0]), ok +} diff --git a/lapack/cgo/lapack_test.go b/lapack/cgo/lapack_test.go new file mode 100644 index 00000000..f4738263 --- /dev/null +++ b/lapack/cgo/lapack_test.go @@ -0,0 +1,273 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgo + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack/testlapack" +) + +var impl = Implementation{} + +// blockedTranslate transforms some blocked C calls to be the unblocked algorithms +// for testing, as several of the unblocked algorithms are not defined by the C +// interface. +type blockedTranslate struct { + Implementation +} + +func TestDbdsqr(t *testing.T) { + testlapack.DbdsqrTest(t, impl) +} + +func (bl blockedTranslate) Dgebd2(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64) { + impl.Dgebrd(m, n, a, lda, d, e, tauQ, tauP, work, len(work)) +} + +func (bl blockedTranslate) Dorm2r(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { + impl.Dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, len(work)) +} + +func (bl blockedTranslate) Dorml2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { + impl.Dormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, len(work)) +} + +func (bl blockedTranslate) Dorg2r(m, n, k int, a []float64, lda int, tau, work []float64) { + impl.Dorgqr(m, n, k, a, lda, tau, work, len(work)) +} + +func (bl blockedTranslate) Dorgl2(m, n, k int, a []float64, lda int, tau, work []float64) { + impl.Dorglq(m, n, k, a, lda, tau, work, len(work)) +} + +func TestDgeqp3(t *testing.T) { + testlapack.Dgeqp3Test(t, impl) +} + +func TestDlacn2(t *testing.T) { + testlapack.Dlacn2Test(t, impl) +} + +func TestDlascl(t *testing.T) { + testlapack.DlasclTest(t, impl) +} + +func TestDlacpy(t *testing.T) { + testlapack.DlacpyTest(t, impl) +} + +func TestDlange(t *testing.T) { + testlapack.DlangeTest(t, impl) +} + +func TestDlarfb(t *testing.T) { + testlapack.DlarfbTest(t, impl) +} + +func TestDlarfg(t *testing.T) { + testlapack.DlarfgTest(t, impl) +} + +func TestDlarft(t *testing.T) { + testlapack.DlarftTest(t, impl) +} + +func TestDlantr(t *testing.T) { + testlapack.DlantrTest(t, impl) +} + +func TestDlapmt(t *testing.T) { + testlapack.DlapmtTest(t, impl) +} + +func TestDlapy2(t *testing.T) { + testlapack.Dlapy2Test(t, impl) +} + +func TestDlarfx(t *testing.T) { + testlapack.DlarfxTest(t, impl) +} + +func TestDlaset(t *testing.T) { + testlapack.DlasetTest(t, impl) +} + +func TestDlasrt(t *testing.T) { + testlapack.DlasrtTest(t, impl) +} + +func TestDlaswp(t *testing.T) { + testlapack.DlaswpTest(t, impl) +} + +func TestDpotrf(t *testing.T) { + testlapack.DpotrfTest(t, impl) +} + +func TestDgebak(t *testing.T) { + testlapack.DgebakTest(t, impl) +} + +func TestDgebal(t *testing.T) { + testlapack.DgebalTest(t, impl) +} + +func TestDgebd2(t *testing.T) { + testlapack.Dgebd2Test(t, blockedTranslate{impl}) +} + +func TestDgecon(t *testing.T) { + testlapack.DgeconTest(t, impl) +} + +func TestDgeev(t *testing.T) { + testlapack.DgeevTest(t, impl) +} + +func TestDgehrd(t *testing.T) { + testlapack.DgehrdTest(t, impl) +} + +func TestDgelq2(t *testing.T) { + testlapack.Dgelq2Test(t, impl) +} + +func TestDgels(t *testing.T) { + testlapack.DgelsTest(t, impl) +} + +func TestDgelqf(t *testing.T) { + testlapack.DgelqfTest(t, impl) +} + +func TestDgeqr2(t *testing.T) { + testlapack.Dgeqr2Test(t, impl) +} + +func TestDgeqrf(t *testing.T) { + testlapack.DgeqrfTest(t, impl) +} + +func TestDgerqf(t *testing.T) { + testlapack.DgerqfTest(t, impl) +} + +func TestDgesvd(t *testing.T) { + testlapack.DgesvdTest(t, impl) +} + +func TestDgetf2(t *testing.T) { + testlapack.Dgetf2Test(t, impl) +} + +func TestDgetrf(t *testing.T) { + testlapack.DgetrfTest(t, impl) +} + +func TestDgetri(t *testing.T) { + testlapack.DgetriTest(t, impl) +} + +func TestDgetrs(t *testing.T) { + testlapack.DgetrsTest(t, impl) +} + +func TestDggsvd3(t *testing.T) { + testlapack.Dggsvd3Test(t, impl) +} + +func TestDggsvp3(t *testing.T) { + testlapack.Dggsvp3Test(t, impl) +} + +func TestDhseqr(t *testing.T) { + testlapack.DhseqrTest(t, impl) +} + +func TestDorglq(t *testing.T) { + testlapack.DorglqTest(t, blockedTranslate{impl}) +} + +func TestDorgql(t *testing.T) { + testlapack.DorgqlTest(t, impl) +} + +func TestDorgqr(t *testing.T) { + testlapack.DorgqrTest(t, blockedTranslate{impl}) +} + +func TestDorgtr(t *testing.T) { + testlapack.DorgtrTest(t, impl) +} + +func TestDorgl2(t *testing.T) { + testlapack.Dorgl2Test(t, blockedTranslate{impl}) +} + +func TestDorg2r(t *testing.T) { + testlapack.Dorg2rTest(t, blockedTranslate{impl}) +} + +func TestDormbr(t *testing.T) { + testlapack.DormbrTest(t, blockedTranslate{impl}) +} + +func TestDormhr(t *testing.T) { + testlapack.DormhrTest(t, impl) +} + +func TestDorgbr(t *testing.T) { + testlapack.DorgbrTest(t, blockedTranslate{impl}) +} + +func TestDorghr(t *testing.T) { + testlapack.DorghrTest(t, impl) +} + +func TestDormqr(t *testing.T) { + testlapack.Dorm2rTest(t, blockedTranslate{impl}) +} + +func TestDormlq(t *testing.T) { + testlapack.Dorml2Test(t, blockedTranslate{impl}) +} + +func TestDpocon(t *testing.T) { + testlapack.DpoconTest(t, impl) +} + +func TestDsteqr(t *testing.T) { + testlapack.DsteqrTest(t, impl) +} + +func TestDsterf(t *testing.T) { + testlapack.DsterfTest(t, impl) +} + +func TestDsyev(t *testing.T) { + testlapack.DsyevTest(t, impl) +} + +func TestDsytrd(t *testing.T) { + testlapack.DsytrdTest(t, impl) +} + +func TestDtgsja(t *testing.T) { + testlapack.DtgsjaTest(t, impl) +} + +func TestDtrexc(t *testing.T) { + testlapack.DtrexcTest(t, impl) +} + +func TestDtrcon(t *testing.T) { + testlapack.DtrconTest(t, impl) +} + +func TestDtrtri(t *testing.T) { + testlapack.DtrtriTest(t, impl) +} diff --git a/lapack/cgo/lapacke/generate.go b/lapack/cgo/lapacke/generate.go new file mode 100644 index 00000000..e50c2da1 --- /dev/null +++ b/lapack/cgo/lapacke/generate.go @@ -0,0 +1,7 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run generate_lapacke.go + +package lapacke diff --git a/lapack/cgo/lapacke/generate_lapacke.go b/lapack/cgo/lapacke/generate_lapacke.go new file mode 100644 index 00000000..7f477eae --- /dev/null +++ b/lapack/cgo/lapacke/generate_lapacke.go @@ -0,0 +1,551 @@ +// Copyright ©2016 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build ignore + +// generate_lapacke creates a lapacke.go file from the provided C header file +// with optionally added documentation from the documentation package. +package main + +import ( + "bytes" + "fmt" + "go/format" + "io/ioutil" + "log" + "os" + "strings" + "text/template" + + "github.com/cznic/cc" + + "gonum.org/v1/gonum/internal/binding" +) + +const ( + header = "lapacke.h" + target = "lapacke.go" + + prefix = "LAPACKE_" + suffix = "_work" +) + +const ( + elideRepeat = true + noteOrigin = false +) + +var skip = map[string]bool{ + // Deprecated. + "LAPACKE_cggsvp_work": true, + "LAPACKE_dggsvp_work": true, + "LAPACKE_sggsvp_work": true, + "LAPACKE_zggsvp_work": true, + "LAPACKE_cggsvd_work": true, + "LAPACKE_dggsvd_work": true, + "LAPACKE_sggsvd_work": true, + "LAPACKE_zggsvd_work": true, + "LAPACKE_cgeqpf_work": true, + "LAPACKE_dgeqpf_work": true, + "LAPACKE_sgeqpf_work": true, + "LAPACKE_zgeqpf_work": true, +} + +// needsInt is a list of routines that need to return the integer info value and +// and cannot convert to a success boolean. +var needsInt = map[string]bool{ + "hseqr": true, + "geev": true, + "geevx": true, +} + +// allUplo is a list of routines that allow 'A' for their uplo argument. +// The list keys are truncated by one character to cover all four numeric types. +var allUplo = map[string]bool{ + "lacpy": true, + "laset": true, +} + +var cToGoType = map[string]string{ + "char": "byte", + "int_must": "int", + "int_must32": "int32", + "int": "bool", + "float": "float32", + "double": "float64", + "float complex": "complex64", + "double complex": "complex128", +} + +var cToGoTypeConv = map[string]string{ + "int_must": "int", + "int": "isZero", + "float": "float32", + "double": "float64", + "float complex": "complex64", + "double complex": "complex128", +} + +var cgoEnums = map[string]*template.Template{} + +var byteTypes = map[string]string{ + "compq": "lapack.Comp", + "compz": "lapack.Comp", + + "d": "blas.Diag", + + "job": "lapack.Job", + "joba": "lapack.Job", + "jobr": "lapack.Job", + "jobp": "lapack.Job", + "jobq": "lapack.Job", + "jobt": "lapack.Job", + "jobu": "lapack.Job", + "jobu1": "lapack.Job", + "jobu2": "lapack.Job", + "jobv": "lapack.Job", + "jobv1t": "lapack.Job", + "jobv2t": "lapack.Job", + "jobvl": "lapack.Job", + "jobvr": "lapack.Job", + "jobvt": "lapack.Job", + "jobz": "lapack.Job", + + "side": "blas.Side", + + "trans": "blas.Transpose", + "trana": "blas.Transpose", + "tranb": "blas.Transpose", + "transr": "blas.Transpose", + + "ul": "blas.Uplo", + + "balanc": "byte", + "cmach": "byte", + "direct": "byte", + "dist": "byte", + "equed": "byte", + "eigsrc": "byte", + "fact": "byte", + "howmny": "byte", + "id": "byte", + "initv": "byte", + "norm": "byte", + "order": "byte", + "pack": "byte", + "sense": "byte", + "signs": "byte", + "storev": "byte", + "sym": "byte", + "typ": "byte", + "rng": "byte", + "vect": "byte", + "way": "byte", +} + +func typeForByte(n string) string { + t, ok := byteTypes[n] + if !ok { + return fmt.Sprintf("", n) + } + return t +} + +var intTypes = map[string]string{ + "forwrd": "int32", + + "ijob": "lapack.Job", + + "wantq": "int32", + "wantz": "int32", +} + +func typeForInt(n string) string { + t, ok := intTypes[n] + if !ok { + return "int" + } + return t +} + +// TODO(kortschak): convForInt* are for #define types, +// so they could go away. Kept here now for diff reduction. + +func convForInt(n string) string { + switch n { + case "rowMajor": + return "C.int" + case "forwrd", "wantq", "wantz": + return "C.lapack_logical" + default: + return "C.lapack_int" + } +} + +func convForIntSlice(n string) string { + switch n { + case "bwork", "tryrac": + return "*C.lapack_logical" + default: + return "*C.lapack_int" + } +} + +var goTypes = map[binding.TypeKey]*template.Template{ + {Kind: cc.Char}: template.Must(template.New("byte").Funcs(map[string]interface{}{"typefor": typeForByte}).Parse("{{typefor .}}")), + {Kind: cc.Int}: template.Must(template.New("int").Funcs(map[string]interface{}{"typefor": typeForInt}).Parse("{{typefor .}}")), + {Kind: cc.Char, IsPointer: true}: template.Must(template.New("[]byte").Parse("[]byte")), + {Kind: cc.Int, IsPointer: true}: template.Must(template.New("[]int32").Parse("[]int32")), + {Kind: cc.FloatComplex, IsPointer: true}: template.Must(template.New("[]complex64").Parse("[]complex64")), + {Kind: cc.DoubleComplex, IsPointer: true}: template.Must(template.New("[]complex128").Parse("[]complex128")), +} + +var cgoTypes = map[binding.TypeKey]*template.Template{ + {Kind: cc.Char}: template.Must(template.New("char").Parse("(C.char)({{.}})")), + {Kind: cc.Int}: template.Must(template.New("int").Funcs(map[string]interface{}{"conv": convForInt}).Parse(`({{conv .}})({{.}})`)), + {Kind: cc.Float}: template.Must(template.New("float").Parse("(C.float)({{.}})")), + {Kind: cc.Double}: template.Must(template.New("double").Parse("(C.double)({{.}})")), + {Kind: cc.FloatComplex}: template.Must(template.New("lapack_complex_float").Parse("(C.lapack_complex_float)({{.}})")), + {Kind: cc.DoubleComplex}: template.Must(template.New("lapack_complex_double").Parse("(C.lapack_complex_double)({{.}})")), + {Kind: cc.Char, IsPointer: true}: template.Must(template.New("char*").Parse("(*C.char)(unsafe.Pointer(_{{.}}))")), + {Kind: cc.Int, IsPointer: true}: template.Must(template.New("int*").Funcs(map[string]interface{}{"conv": convForIntSlice}).Parse("({{conv .}})(_{{.}})")), + {Kind: cc.Float, IsPointer: true}: template.Must(template.New("float").Parse("(*C.float)(_{{.}})")), + {Kind: cc.Double, IsPointer: true}: template.Must(template.New("double").Parse("(*C.double)(_{{.}})")), + {Kind: cc.FloatComplex, IsPointer: true}: template.Must(template.New("lapack_complex_float*").Parse("(*C.lapack_complex_float)(_{{.}})")), + {Kind: cc.DoubleComplex, IsPointer: true}: template.Must(template.New("lapack_complex_double*").Parse("(*C.lapack_complex_double)(_{{.}})")), +} + +var names = map[string]string{ + "matrix_layout": "rowMajor", + "uplo": "ul", + "range": "rng", + "diag": "d", + "select": "sel", + "type": "typ", +} + +func shorten(n string) string { + s, ok := names[n] + if ok { + return s + } + return n +} + +func join(a []string) string { + return strings.Join(a, " ") +} + +func main() { + decls, err := binding.Declarations(header) + if err != nil { + log.Fatal(err) + } + + var buf bytes.Buffer + + h, err := template.New("handwritten"). + Funcs(map[string]interface{}{"join": join}). + Parse(handwritten) + if err != nil { + log.Fatal(err) + } + err = h.Execute(&buf, struct { + Header string + Lib []string + }{ + Header: header, + Lib: os.Args[1:], + }) + if err != nil { + log.Fatal(err) + } + + for _, d := range decls { + if !strings.HasPrefix(d.Name, prefix) || !strings.HasSuffix(d.Name, suffix) || skip[d.Name] { + continue + } + lapackeName := strings.TrimSuffix(strings.TrimPrefix(d.Name, prefix), suffix) + switch { + case strings.HasSuffix(lapackeName, "fsx"): + continue + case strings.HasSuffix(lapackeName, "vxx"): + continue + case strings.HasSuffix(lapackeName, "rook"): + continue + } + if hasFuncParameter(d) { + continue + } + + goSignature(&buf, d) + if noteOrigin { + fmt.Fprintf(&buf, "\t// %s %s %s ...\n\n", d.Position(), d.Return, d.Name) + } + parameterChecks(&buf, d, parameterCheckRules) + buf.WriteByte('\t') + cgoCall(&buf, d) + buf.WriteString("}\n") + } + + b, err := format.Source(buf.Bytes()) + if err != nil { + log.Fatal(err) + } + err = ioutil.WriteFile(target, b, 0664) + if err != nil { + log.Fatal(err) + } +} + +// This removes select and selctg parameterised functions. +func hasFuncParameter(d binding.Declaration) bool { + for _, p := range d.Parameters() { + if p.Kind() != cc.Ptr { + continue + } + if p.Elem().Kind() == cc.Function { + return true + } + } + return false +} + +func goSignature(buf *bytes.Buffer, d binding.Declaration) { + lapackeName := strings.TrimSuffix(strings.TrimPrefix(d.Name, prefix), suffix) + goName := binding.UpperCaseFirst(lapackeName) + + parameters := d.Parameters() + + fmt.Fprintf(buf, "\n// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/%s.f.\n", lapackeName) + fmt.Fprintf(buf, "func %s(", goName) + c := 0 + for i, p := range parameters { + if p.Name() == "matrix_layout" { + continue + } + if c != 0 { + buf.WriteString(", ") + } + c++ + + n := shorten(binding.LowerCaseFirst(p.Name())) + var this, next string + + if p.Kind() == cc.Enum { + this = binding.GoTypeForEnum(p.Type(), n) + } else { + this = binding.GoTypeFor(p.Type(), n, goTypes) + } + + if elideRepeat && i < len(parameters)-1 && p.Type().Kind() == parameters[i+1].Type().Kind() { + p := parameters[i+1] + n := shorten(binding.LowerCaseFirst(p.Name())) + if p.Kind() == cc.Enum { + next = binding.GoTypeForEnum(p.Type(), n) + } else { + next = binding.GoTypeFor(p.Type(), n, goTypes) + } + } + if next == this { + buf.WriteString(n) + } else { + fmt.Fprintf(buf, "%s %s", n, this) + } + } + if d.Return.Kind() != cc.Void { + var must string + if needsInt[lapackeName[1:]] { + must = "_must" + } + fmt.Fprintf(buf, ") %s {\n", cToGoType[d.Return.String()+must]) + } else { + buf.WriteString(") {\n") + } +} + +func parameterChecks(buf *bytes.Buffer, d binding.Declaration, rules []func(*bytes.Buffer, binding.Declaration, binding.Parameter) bool) { + done := make(map[int]bool) + for _, p := range d.Parameters() { + for i, r := range rules { + if done[i] { + continue + } + done[i] = r(buf, d, p) + } + } +} + +func cgoCall(buf *bytes.Buffer, d binding.Declaration) { + if d.Return.Kind() != cc.Void { + lapackeName := strings.TrimSuffix(strings.TrimPrefix(d.Name, prefix), suffix) + var must string + if needsInt[lapackeName[1:]] { + must = "_must" + } + fmt.Fprintf(buf, "return %s(", cToGoTypeConv[d.Return.String()+must]) + } + fmt.Fprintf(buf, "C.%s(", d.Name) + for i, p := range d.Parameters() { + if i != 0 { + buf.WriteString(", ") + } + if p.Type().Kind() == cc.Enum { + buf.WriteString(binding.CgoConversionForEnum(shorten(binding.LowerCaseFirst(p.Name())), p.Type())) + } else { + buf.WriteString(binding.CgoConversionFor(shorten(binding.LowerCaseFirst(p.Name())), p.Type(), cgoTypes)) + } + } + if d.Return.Kind() != cc.Void { + buf.WriteString(")") + } + buf.WriteString(")\n") +} + +var parameterCheckRules = []func(*bytes.Buffer, binding.Declaration, binding.Parameter) bool{ + uplo, + diag, + side, + trans, + address, +} + +func uplo(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + if p.Name() != "uplo" { + return false + } + lapackeName := strings.TrimSuffix(strings.TrimPrefix(d.Name, prefix), suffix) + if allUplo[lapackeName[1:]] { + fmt.Fprint(buf, ` switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + ul = 'A' + } +`) + } else { + fmt.Fprint(buf, ` switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } +`) + } + return true +} + +func diag(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + if p.Name() != "diag" { + return false + } + fmt.Fprint(buf, ` switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } +`) + return true +} + +func side(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + if p.Name() != "side" { + return false + } + fmt.Fprint(buf, ` switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } +`) + return true +} + +func trans(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + n := shorten(binding.LowerCaseFirst(p.Name())) + if !strings.HasPrefix(n, "tran") { + return false + } + fmt.Fprintf(buf, ` switch %[1]s { + case blas.NoTrans: + %[1]s = 'N' + case blas.Trans: + %[1]s = 'T' + case blas.ConjTrans: + %[1]s = 'C' + default: + panic("lapack: bad trans") + } +`, n) + return false +} + +var addrTypes = map[string]string{ + "char": "byte", + "int": "int32", + "float": "float32", + "double": "float64", + "float complex": "complex64", + "double complex": "complex128", +} + +func address(buf *bytes.Buffer, d binding.Declaration, p binding.Parameter) bool { + n := shorten(binding.LowerCaseFirst(p.Name())) + if p.Type().Kind() == cc.Ptr { + t := strings.TrimPrefix(p.Type().Element().String(), "const ") + fmt.Fprintf(buf, ` var _%[1]s *%[2]s + if len(%[1]s) > 0 { + _%[1]s = &%[1]s[0] + } +`, n, addrTypes[t]) + } + return false +} + +const handwritten = `// Code generated by "go generate github.com/gonum/lapack/cgo/lapacke" from {{.Header}}; DO NOT EDIT. + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package lapacke provides bindings to the LAPACKE C Interface to LAPACK. +// +// Links are provided to the NETLIB fortran implementation/dependencies for each function. +package lapacke + +/* +#cgo CFLAGS: -g -O2{{if .Lib}} +#cgo LDFLAGS: {{join .Lib}}{{end}} +#include "{{.Header}}" +*/ +import "C" + +import ( + "unsafe" + + "github.com/gonum/blas" + "github.com/gonum/lapack" +) + +// Type order is used to specify the matrix storage format. We still interact with +// an API that allows client calls to specify order, so this is here to document that fact. +type order int + +const ( + rowMajor order = 101 + iota + colMajor +) + +func isZero(ret C.int) bool { return ret == 0 } +` diff --git a/lapack/cgo/lapacke/lapacke.go b/lapack/cgo/lapacke/lapacke.go new file mode 100644 index 00000000..bd5953d6 --- /dev/null +++ b/lapack/cgo/lapacke/lapacke.go @@ -0,0 +1,31444 @@ +// Code generated by "go generate github.com/gonum/lapack/cgo/lapacke" from lapacke.h; DO NOT EDIT. + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package lapacke provides bindings to the LAPACKE C Interface to LAPACK. +// +// Links are provided to the NETLIB fortran implementation/dependencies for each function. +package lapacke + +/* +#cgo CFLAGS: -g -O2 +#include "lapacke.h" +*/ +import "C" + +import ( + "unsafe" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Type order is used to specify the matrix storage format. We still interact with +// an API that allows client calls to specify order, so this is here to document that fact. +type order int + +const ( + rowMajor order = 101 + iota + colMajor +) + +func isZero(ret C.int) bool { return ret == 0 } + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sbdsdc.f. +func Sbdsdc(ul blas.Uplo, compq lapack.Comp, n int, d, e, u []float32, ldu int, vt []float32, ldvt int, q []float32, iq []int32, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _u *float32 + if len(u) > 0 { + _u = &u[0] + } + var _vt *float32 + if len(vt) > 0 { + _vt = &vt[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _iq *int32 + if len(iq) > 0 { + _iq = &iq[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sbdsdc_work((C.int)(rowMajor), (C.char)(ul), (C.char)(compq), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (*C.float)(_u), (C.lapack_int)(ldu), (*C.float)(_vt), (C.lapack_int)(ldvt), (*C.float)(_q), (*C.lapack_int)(_iq), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dbdsdc.f. +func Dbdsdc(ul blas.Uplo, compq lapack.Comp, n int, d, e, u []float64, ldu int, vt []float64, ldvt int, q []float64, iq []int32, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _u *float64 + if len(u) > 0 { + _u = &u[0] + } + var _vt *float64 + if len(vt) > 0 { + _vt = &vt[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _iq *int32 + if len(iq) > 0 { + _iq = &iq[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dbdsdc_work((C.int)(rowMajor), (C.char)(ul), (C.char)(compq), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (*C.double)(_u), (C.lapack_int)(ldu), (*C.double)(_vt), (C.lapack_int)(ldvt), (*C.double)(_q), (*C.lapack_int)(_iq), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sbdsvdx.f. +func Sbdsvdx(ul blas.Uplo, jobz lapack.Job, rng byte, n int, d, e []float32, vl, vu, il, iu, ns int, s, z []float32, ldz int, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sbdsvdx_work((C.int)(rowMajor), (C.char)(ul), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.lapack_int)(vl), (C.lapack_int)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.lapack_int)(ns), (*C.float)(_s), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dbdsvdx.f. +func Dbdsvdx(ul blas.Uplo, jobz lapack.Job, rng byte, n int, d, e []float64, vl, vu, il, iu, ns int, s, z []float64, ldz int, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dbdsvdx_work((C.int)(rowMajor), (C.char)(ul), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.lapack_int)(vl), (C.lapack_int)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.lapack_int)(ns), (*C.double)(_s), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sbdsqr.f. +func Sbdsqr(ul blas.Uplo, n, ncvt, nru, ncc int, d, e, vt []float32, ldvt int, u []float32, ldu int, c []float32, ldc int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _vt *float32 + if len(vt) > 0 { + _vt = &vt[0] + } + var _u *float32 + if len(u) > 0 { + _u = &u[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sbdsqr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ncvt), (C.lapack_int)(nru), (C.lapack_int)(ncc), (*C.float)(_d), (*C.float)(_e), (*C.float)(_vt), (C.lapack_int)(ldvt), (*C.float)(_u), (C.lapack_int)(ldu), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dbdsqr.f. +func Dbdsqr(ul blas.Uplo, n, ncvt, nru, ncc int, d, e, vt []float64, ldvt int, u []float64, ldu int, c []float64, ldc int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _vt *float64 + if len(vt) > 0 { + _vt = &vt[0] + } + var _u *float64 + if len(u) > 0 { + _u = &u[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dbdsqr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ncvt), (C.lapack_int)(nru), (C.lapack_int)(ncc), (*C.double)(_d), (*C.double)(_e), (*C.double)(_vt), (C.lapack_int)(ldvt), (*C.double)(_u), (C.lapack_int)(ldu), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cbdsqr.f. +func Cbdsqr(ul blas.Uplo, n, ncvt, nru, ncc int, d, e []float32, vt []complex64, ldvt int, u []complex64, ldu int, c []complex64, ldc int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _vt *complex64 + if len(vt) > 0 { + _vt = &vt[0] + } + var _u *complex64 + if len(u) > 0 { + _u = &u[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cbdsqr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ncvt), (C.lapack_int)(nru), (C.lapack_int)(ncc), (*C.float)(_d), (*C.float)(_e), (*C.lapack_complex_float)(_vt), (C.lapack_int)(ldvt), (*C.lapack_complex_float)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zbdsqr.f. +func Zbdsqr(ul blas.Uplo, n, ncvt, nru, ncc int, d, e []float64, vt []complex128, ldvt int, u []complex128, ldu int, c []complex128, ldc int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _vt *complex128 + if len(vt) > 0 { + _vt = &vt[0] + } + var _u *complex128 + if len(u) > 0 { + _u = &u[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zbdsqr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ncvt), (C.lapack_int)(nru), (C.lapack_int)(ncc), (*C.double)(_d), (*C.double)(_e), (*C.lapack_complex_double)(_vt), (C.lapack_int)(ldvt), (*C.lapack_complex_double)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sdisna.f. +func Sdisna(job lapack.Job, m, n int, d, sep []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _sep *float32 + if len(sep) > 0 { + _sep = &sep[0] + } + return isZero(C.LAPACKE_sdisna_work((C.char)(job), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_sep))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ddisna.f. +func Ddisna(job lapack.Job, m, n int, d, sep []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _sep *float64 + if len(sep) > 0 { + _sep = &sep[0] + } + return isZero(C.LAPACKE_ddisna_work((C.char)(job), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_sep))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgbbrd.f. +func Sgbbrd(vect byte, m, n, ncc, kl, ku int, ab []float32, ldab int, d, e, q []float32, ldq int, pt []float32, ldpt int, c []float32, ldc int, work []float32) bool { + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _pt *float32 + if len(pt) > 0 { + _pt = &pt[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgbbrd_work((C.int)(rowMajor), (C.char)(vect), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(ncc), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_d), (*C.float)(_e), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_pt), (C.lapack_int)(ldpt), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgbbrd.f. +func Dgbbrd(vect byte, m, n, ncc, kl, ku int, ab []float64, ldab int, d, e, q []float64, ldq int, pt []float64, ldpt int, c []float64, ldc int, work []float64) bool { + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _pt *float64 + if len(pt) > 0 { + _pt = &pt[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgbbrd_work((C.int)(rowMajor), (C.char)(vect), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(ncc), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_d), (*C.double)(_e), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_pt), (C.lapack_int)(ldpt), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgbbrd.f. +func Cgbbrd(vect byte, m, n, ncc, kl, ku int, ab []complex64, ldab int, d, e []float32, q []complex64, ldq int, pt []complex64, ldpt int, c []complex64, ldc int, work []complex64, rwork []float32) bool { + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _pt *complex64 + if len(pt) > 0 { + _pt = &pt[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgbbrd_work((C.int)(rowMajor), (C.char)(vect), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(ncc), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.float)(_d), (*C.float)(_e), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_pt), (C.lapack_int)(ldpt), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgbbrd.f. +func Zgbbrd(vect byte, m, n, ncc, kl, ku int, ab []complex128, ldab int, d, e []float64, q []complex128, ldq int, pt []complex128, ldpt int, c []complex128, ldc int, work []complex128, rwork []float64) bool { + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _pt *complex128 + if len(pt) > 0 { + _pt = &pt[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgbbrd_work((C.int)(rowMajor), (C.char)(vect), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(ncc), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.double)(_d), (*C.double)(_e), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_pt), (C.lapack_int)(ldpt), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgbcon.f. +func Sgbcon(norm byte, n, kl, ku int, ab []float32, ldab int, ipiv []int32, anorm float32, rcond, work []float32, iwork []int32) bool { + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgbcon_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgbcon.f. +func Dgbcon(norm byte, n, kl, ku int, ab []float64, ldab int, ipiv []int32, anorm float64, rcond, work []float64, iwork []int32) bool { + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgbcon_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgbcon.f. +func Cgbcon(norm byte, n, kl, ku int, ab []complex64, ldab int, ipiv []int32, anorm float32, rcond []float32, work []complex64, rwork []float32) bool { + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgbcon_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgbcon.f. +func Zgbcon(norm byte, n, kl, ku int, ab []complex128, ldab int, ipiv []int32, anorm float64, rcond []float64, work []complex128, rwork []float64) bool { + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgbcon_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgbequ.f. +func Sgbequ(m, n, kl, ku int, ab []float32, ldab int, r, c, rowcnd, colcnd, amax []float32) bool { + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float32 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float32 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_sgbequ_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_r), (*C.float)(_c), (*C.float)(_rowcnd), (*C.float)(_colcnd), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgbequ.f. +func Dgbequ(m, n, kl, ku int, ab []float64, ldab int, r, c, rowcnd, colcnd, amax []float64) bool { + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float64 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float64 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_dgbequ_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_r), (*C.double)(_c), (*C.double)(_rowcnd), (*C.double)(_colcnd), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgbequ.f. +func Cgbequ(m, n, kl, ku int, ab []complex64, ldab int, r, c, rowcnd, colcnd, amax []float32) bool { + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float32 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float32 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_cgbequ_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.float)(_r), (*C.float)(_c), (*C.float)(_rowcnd), (*C.float)(_colcnd), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgbequ.f. +func Zgbequ(m, n, kl, ku int, ab []complex128, ldab int, r, c, rowcnd, colcnd, amax []float64) bool { + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float64 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float64 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_zgbequ_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.double)(_r), (*C.double)(_c), (*C.double)(_rowcnd), (*C.double)(_colcnd), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgbequb.f. +func Sgbequb(m, n, kl, ku int, ab []float32, ldab int, r, c, rowcnd, colcnd, amax []float32) bool { + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float32 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float32 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_sgbequb_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_r), (*C.float)(_c), (*C.float)(_rowcnd), (*C.float)(_colcnd), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgbequb.f. +func Dgbequb(m, n, kl, ku int, ab []float64, ldab int, r, c, rowcnd, colcnd, amax []float64) bool { + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float64 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float64 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_dgbequb_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_r), (*C.double)(_c), (*C.double)(_rowcnd), (*C.double)(_colcnd), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgbequb.f. +func Cgbequb(m, n, kl, ku int, ab []complex64, ldab int, r, c, rowcnd, colcnd, amax []float32) bool { + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float32 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float32 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_cgbequb_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.float)(_r), (*C.float)(_c), (*C.float)(_rowcnd), (*C.float)(_colcnd), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgbequb.f. +func Zgbequb(m, n, kl, ku int, ab []complex128, ldab int, r, c, rowcnd, colcnd, amax []float64) bool { + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float64 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float64 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_zgbequb_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.double)(_r), (*C.double)(_c), (*C.double)(_rowcnd), (*C.double)(_colcnd), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgbrfs.f. +func Sgbrfs(trans blas.Transpose, n, kl, ku, nrhs int, ab []float32, ldab int, afb []float32, ldafb int, ipiv []int32, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *float32 + if len(afb) > 0 { + _afb = &afb[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgbrfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_afb), (C.lapack_int)(ldafb), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgbrfs.f. +func Dgbrfs(trans blas.Transpose, n, kl, ku, nrhs int, ab []float64, ldab int, afb []float64, ldafb int, ipiv []int32, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *float64 + if len(afb) > 0 { + _afb = &afb[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgbrfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_afb), (C.lapack_int)(ldafb), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgbrfs.f. +func Cgbrfs(trans blas.Transpose, n, kl, ku, nrhs int, ab []complex64, ldab int, afb []complex64, ldafb int, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *complex64 + if len(afb) > 0 { + _afb = &afb[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgbrfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_afb), (C.lapack_int)(ldafb), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgbrfs.f. +func Zgbrfs(trans blas.Transpose, n, kl, ku, nrhs int, ab []complex128, ldab int, afb []complex128, ldafb int, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *complex128 + if len(afb) > 0 { + _afb = &afb[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgbrfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_afb), (C.lapack_int)(ldafb), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgbsv.f. +func Sgbsv(n, kl, ku, nrhs int, ab []float32, ldab int, ipiv []int32, b []float32, ldb int) bool { + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sgbsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgbsv.f. +func Dgbsv(n, kl, ku, nrhs int, ab []float64, ldab int, ipiv []int32, b []float64, ldb int) bool { + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dgbsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgbsv.f. +func Cgbsv(n, kl, ku, nrhs int, ab []complex64, ldab int, ipiv []int32, b []complex64, ldb int) bool { + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cgbsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgbsv.f. +func Zgbsv(n, kl, ku, nrhs int, ab []complex128, ldab int, ipiv []int32, b []complex128, ldb int) bool { + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zgbsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgbsvx.f. +func Sgbsvx(fact byte, trans blas.Transpose, n, kl, ku, nrhs int, ab []float32, ldab int, afb []float32, ldafb int, ipiv []int32, equed []byte, r, c, b []float32, ldb int, x []float32, ldx int, rcond, ferr, berr, work []float32, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *float32 + if len(afb) > 0 { + _afb = &afb[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgbsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_afb), (C.lapack_int)(ldafb), (*C.lapack_int)(_ipiv), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_r), (*C.float)(_c), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgbsvx.f. +func Dgbsvx(fact byte, trans blas.Transpose, n, kl, ku, nrhs int, ab []float64, ldab int, afb []float64, ldafb int, ipiv []int32, equed []byte, r, c, b []float64, ldb int, x []float64, ldx int, rcond, ferr, berr, work []float64, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *float64 + if len(afb) > 0 { + _afb = &afb[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgbsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_afb), (C.lapack_int)(ldafb), (*C.lapack_int)(_ipiv), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_r), (*C.double)(_c), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgbsvx.f. +func Cgbsvx(fact byte, trans blas.Transpose, n, kl, ku, nrhs int, ab []complex64, ldab int, afb []complex64, ldafb int, ipiv []int32, equed []byte, r, c []float32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *complex64 + if len(afb) > 0 { + _afb = &afb[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgbsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_afb), (C.lapack_int)(ldafb), (*C.lapack_int)(_ipiv), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_r), (*C.float)(_c), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgbsvx.f. +func Zgbsvx(fact byte, trans blas.Transpose, n, kl, ku, nrhs int, ab []complex128, ldab int, afb []complex128, ldafb int, ipiv []int32, equed []byte, r, c []float64, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *complex128 + if len(afb) > 0 { + _afb = &afb[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgbsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_afb), (C.lapack_int)(ldafb), (*C.lapack_int)(_ipiv), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_r), (*C.double)(_c), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgbtrf.f. +func Sgbtrf(m, n, kl, ku int, ab []float32, ldab int, ipiv []int32) bool { + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_sgbtrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgbtrf.f. +func Dgbtrf(m, n, kl, ku int, ab []float64, ldab int, ipiv []int32) bool { + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_dgbtrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgbtrf.f. +func Cgbtrf(m, n, kl, ku int, ab []complex64, ldab int, ipiv []int32) bool { + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_cgbtrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgbtrf.f. +func Zgbtrf(m, n, kl, ku int, ab []complex128, ldab int, ipiv []int32) bool { + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_zgbtrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgbtrs.f. +func Sgbtrs(trans blas.Transpose, n, kl, ku, nrhs int, ab []float32, ldab int, ipiv []int32, b []float32, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sgbtrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgbtrs.f. +func Dgbtrs(trans blas.Transpose, n, kl, ku, nrhs int, ab []float64, ldab int, ipiv []int32, b []float64, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dgbtrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgbtrs.f. +func Cgbtrs(trans blas.Transpose, n, kl, ku, nrhs int, ab []complex64, ldab int, ipiv []int32, b []complex64, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cgbtrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgbtrs.f. +func Zgbtrs(trans blas.Transpose, n, kl, ku, nrhs int, ab []complex128, ldab int, ipiv []int32, b []complex128, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zgbtrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgebak.f. +func Sgebak(job lapack.Job, side blas.Side, n, ilo, ihi int, scale []float32, m int, v []float32, ldv int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + return isZero(C.LAPACKE_sgebak_work((C.int)(rowMajor), (C.char)(job), (C.char)(side), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_scale), (C.lapack_int)(m), (*C.float)(_v), (C.lapack_int)(ldv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgebak.f. +func Dgebak(job lapack.Job, side blas.Side, n, ilo, ihi int, scale []float64, m int, v []float64, ldv int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + return isZero(C.LAPACKE_dgebak_work((C.int)(rowMajor), (C.char)(job), (C.char)(side), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_scale), (C.lapack_int)(m), (*C.double)(_v), (C.lapack_int)(ldv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgebak.f. +func Cgebak(job lapack.Job, side blas.Side, n, ilo, ihi int, scale []float32, m int, v []complex64, ldv int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + return isZero(C.LAPACKE_cgebak_work((C.int)(rowMajor), (C.char)(job), (C.char)(side), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_scale), (C.lapack_int)(m), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgebak.f. +func Zgebak(job lapack.Job, side blas.Side, n, ilo, ihi int, scale []float64, m int, v []complex128, ldv int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + return isZero(C.LAPACKE_zgebak_work((C.int)(rowMajor), (C.char)(job), (C.char)(side), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_scale), (C.lapack_int)(m), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgebal.f. +func Sgebal(job lapack.Job, n int, a []float32, lda int, ilo, ihi []int32, scale []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + return isZero(C.LAPACKE_sgebal_work((C.int)(rowMajor), (C.char)(job), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.float)(_scale))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgebal.f. +func Dgebal(job lapack.Job, n int, a []float64, lda int, ilo, ihi []int32, scale []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + return isZero(C.LAPACKE_dgebal_work((C.int)(rowMajor), (C.char)(job), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.double)(_scale))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgebal.f. +func Cgebal(job lapack.Job, n int, a []complex64, lda int, ilo, ihi []int32, scale []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + return isZero(C.LAPACKE_cgebal_work((C.int)(rowMajor), (C.char)(job), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.float)(_scale))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgebal.f. +func Zgebal(job lapack.Job, n int, a []complex128, lda int, ilo, ihi []int32, scale []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + return isZero(C.LAPACKE_zgebal_work((C.int)(rowMajor), (C.char)(job), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.double)(_scale))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgebrd.f. +func Sgebrd(m, n int, a []float32, lda int, d, e, tauq, taup, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _tauq *float32 + if len(tauq) > 0 { + _tauq = &tauq[0] + } + var _taup *float32 + if len(taup) > 0 { + _taup = &taup[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgebrd_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_d), (*C.float)(_e), (*C.float)(_tauq), (*C.float)(_taup), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgebrd.f. +func Dgebrd(m, n int, a []float64, lda int, d, e, tauq, taup, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _tauq *float64 + if len(tauq) > 0 { + _tauq = &tauq[0] + } + var _taup *float64 + if len(taup) > 0 { + _taup = &taup[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgebrd_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_d), (*C.double)(_e), (*C.double)(_tauq), (*C.double)(_taup), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgebrd.f. +func Cgebrd(m, n int, a []complex64, lda int, d, e []float32, tauq, taup, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _tauq *complex64 + if len(tauq) > 0 { + _tauq = &tauq[0] + } + var _taup *complex64 + if len(taup) > 0 { + _taup = &taup[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgebrd_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_d), (*C.float)(_e), (*C.lapack_complex_float)(_tauq), (*C.lapack_complex_float)(_taup), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgebrd.f. +func Zgebrd(m, n int, a []complex128, lda int, d, e []float64, tauq, taup, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _tauq *complex128 + if len(tauq) > 0 { + _tauq = &tauq[0] + } + var _taup *complex128 + if len(taup) > 0 { + _taup = &taup[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgebrd_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_d), (*C.double)(_e), (*C.lapack_complex_double)(_tauq), (*C.lapack_complex_double)(_taup), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgecon.f. +func Sgecon(norm byte, n int, a []float32, lda int, anorm float32, rcond, work []float32, iwork []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgecon_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgecon.f. +func Dgecon(norm byte, n int, a []float64, lda int, anorm float64, rcond, work []float64, iwork []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgecon_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgecon.f. +func Cgecon(norm byte, n int, a []complex64, lda int, anorm float32, rcond []float32, work []complex64, rwork []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgecon_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgecon.f. +func Zgecon(norm byte, n int, a []complex128, lda int, anorm float64, rcond []float64, work []complex128, rwork []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgecon_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeequ.f. +func Sgeequ(m, n int, a []float32, lda int, r, c, rowcnd, colcnd, amax []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float32 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float32 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_sgeequ_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_r), (*C.float)(_c), (*C.float)(_rowcnd), (*C.float)(_colcnd), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeequ.f. +func Dgeequ(m, n int, a []float64, lda int, r, c, rowcnd, colcnd, amax []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float64 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float64 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_dgeequ_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_r), (*C.double)(_c), (*C.double)(_rowcnd), (*C.double)(_colcnd), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeequ.f. +func Cgeequ(m, n int, a []complex64, lda int, r, c, rowcnd, colcnd, amax []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float32 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float32 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_cgeequ_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_r), (*C.float)(_c), (*C.float)(_rowcnd), (*C.float)(_colcnd), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeequ.f. +func Zgeequ(m, n int, a []complex128, lda int, r, c, rowcnd, colcnd, amax []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float64 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float64 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_zgeequ_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_r), (*C.double)(_c), (*C.double)(_rowcnd), (*C.double)(_colcnd), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeequb.f. +func Sgeequb(m, n int, a []float32, lda int, r, c, rowcnd, colcnd, amax []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float32 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float32 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_sgeequb_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_r), (*C.float)(_c), (*C.float)(_rowcnd), (*C.float)(_colcnd), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeequb.f. +func Dgeequb(m, n int, a []float64, lda int, r, c, rowcnd, colcnd, amax []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float64 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float64 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_dgeequb_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_r), (*C.double)(_c), (*C.double)(_rowcnd), (*C.double)(_colcnd), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeequb.f. +func Cgeequb(m, n int, a []complex64, lda int, r, c, rowcnd, colcnd, amax []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float32 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float32 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_cgeequb_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_r), (*C.float)(_c), (*C.float)(_rowcnd), (*C.float)(_colcnd), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeequb.f. +func Zgeequb(m, n int, a []complex128, lda int, r, c, rowcnd, colcnd, amax []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _rowcnd *float64 + if len(rowcnd) > 0 { + _rowcnd = &rowcnd[0] + } + var _colcnd *float64 + if len(colcnd) > 0 { + _colcnd = &colcnd[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_zgeequb_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_r), (*C.double)(_c), (*C.double)(_rowcnd), (*C.double)(_colcnd), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeev.f. +func Sgeev(jobvl, jobvr lapack.Job, n int, a []float32, lda int, wr, wi, vl []float32, ldvl int, vr []float32, ldvr int, work []float32, lwork int) int { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _wr *float32 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float32 + if len(wi) > 0 { + _wi = &wi[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return int(C.LAPACKE_sgeev_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_wr), (*C.float)(_wi), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeev.f. +func Dgeev(jobvl, jobvr lapack.Job, n int, a []float64, lda int, wr, wi, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) int { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _wr *float64 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float64 + if len(wi) > 0 { + _wi = &wi[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return int(C.LAPACKE_dgeev_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_wr), (*C.double)(_wi), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeev.f. +func Cgeev(jobvl, jobvr lapack.Job, n int, a []complex64, lda int, w, vl []complex64, ldvl int, vr []complex64, ldvr int, work []complex64, lwork int, rwork []float32) int { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _w *complex64 + if len(w) > 0 { + _w = &w[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return int(C.LAPACKE_cgeev_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_w), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeev.f. +func Zgeev(jobvl, jobvr lapack.Job, n int, a []complex128, lda int, w, vl []complex128, ldvl int, vr []complex128, ldvr int, work []complex128, lwork int, rwork []float64) int { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _w *complex128 + if len(w) > 0 { + _w = &w[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return int(C.LAPACKE_zgeev_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_w), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeevx.f. +func Sgeevx(balanc byte, jobvl, jobvr lapack.Job, sense byte, n int, a []float32, lda int, wr, wi, vl []float32, ldvl int, vr []float32, ldvr int, ilo, ihi []int32, scale, abnrm, rconde, rcondv, work []float32, lwork int, iwork []int32) int { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _wr *float32 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float32 + if len(wi) > 0 { + _wi = &wi[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + var _abnrm *float32 + if len(abnrm) > 0 { + _abnrm = &abnrm[0] + } + var _rconde *float32 + if len(rconde) > 0 { + _rconde = &rconde[0] + } + var _rcondv *float32 + if len(rcondv) > 0 { + _rcondv = &rcondv[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return int(C.LAPACKE_sgeevx_work((C.int)(rowMajor), (C.char)(balanc), (C.char)(jobvl), (C.char)(jobvr), (C.char)(sense), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_wr), (*C.float)(_wi), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.float)(_scale), (*C.float)(_abnrm), (*C.float)(_rconde), (*C.float)(_rcondv), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeevx.f. +func Dgeevx(balanc byte, jobvl, jobvr lapack.Job, sense byte, n int, a []float64, lda int, wr, wi, vl []float64, ldvl int, vr []float64, ldvr int, ilo, ihi []int32, scale, abnrm, rconde, rcondv, work []float64, lwork int, iwork []int32) int { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _wr *float64 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float64 + if len(wi) > 0 { + _wi = &wi[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + var _abnrm *float64 + if len(abnrm) > 0 { + _abnrm = &abnrm[0] + } + var _rconde *float64 + if len(rconde) > 0 { + _rconde = &rconde[0] + } + var _rcondv *float64 + if len(rcondv) > 0 { + _rcondv = &rcondv[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return int(C.LAPACKE_dgeevx_work((C.int)(rowMajor), (C.char)(balanc), (C.char)(jobvl), (C.char)(jobvr), (C.char)(sense), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_wr), (*C.double)(_wi), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.double)(_scale), (*C.double)(_abnrm), (*C.double)(_rconde), (*C.double)(_rcondv), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeevx.f. +func Cgeevx(balanc byte, jobvl, jobvr lapack.Job, sense byte, n int, a []complex64, lda int, w, vl []complex64, ldvl int, vr []complex64, ldvr int, ilo, ihi []int32, scale, abnrm, rconde, rcondv []float32, work []complex64, lwork int, rwork []float32) int { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _w *complex64 + if len(w) > 0 { + _w = &w[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + var _abnrm *float32 + if len(abnrm) > 0 { + _abnrm = &abnrm[0] + } + var _rconde *float32 + if len(rconde) > 0 { + _rconde = &rconde[0] + } + var _rcondv *float32 + if len(rcondv) > 0 { + _rcondv = &rcondv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return int(C.LAPACKE_cgeevx_work((C.int)(rowMajor), (C.char)(balanc), (C.char)(jobvl), (C.char)(jobvr), (C.char)(sense), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_w), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.float)(_scale), (*C.float)(_abnrm), (*C.float)(_rconde), (*C.float)(_rcondv), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeevx.f. +func Zgeevx(balanc byte, jobvl, jobvr lapack.Job, sense byte, n int, a []complex128, lda int, w, vl []complex128, ldvl int, vr []complex128, ldvr int, ilo, ihi []int32, scale, abnrm, rconde, rcondv []float64, work []complex128, lwork int, rwork []float64) int { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _w *complex128 + if len(w) > 0 { + _w = &w[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + var _abnrm *float64 + if len(abnrm) > 0 { + _abnrm = &abnrm[0] + } + var _rconde *float64 + if len(rconde) > 0 { + _rconde = &rconde[0] + } + var _rcondv *float64 + if len(rcondv) > 0 { + _rcondv = &rcondv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return int(C.LAPACKE_zgeevx_work((C.int)(rowMajor), (C.char)(balanc), (C.char)(jobvl), (C.char)(jobvr), (C.char)(sense), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_w), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.double)(_scale), (*C.double)(_abnrm), (*C.double)(_rconde), (*C.double)(_rcondv), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgehrd.f. +func Sgehrd(n, ilo, ihi int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgehrd_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgehrd.f. +func Dgehrd(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgehrd_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgehrd.f. +func Cgehrd(n, ilo, ihi int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgehrd_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgehrd.f. +func Zgehrd(n, ilo, ihi int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgehrd_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgejsv.f. +func Sgejsv(joba, jobu, jobv, jobr, jobt, jobp lapack.Job, m, n int, a []float32, lda int, sva, u []float32, ldu int, v []float32, ldv int, work []float32, lwork int, iwork []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _sva *float32 + if len(sva) > 0 { + _sva = &sva[0] + } + var _u *float32 + if len(u) > 0 { + _u = &u[0] + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgejsv_work((C.int)(rowMajor), (C.char)(joba), (C.char)(jobu), (C.char)(jobv), (C.char)(jobr), (C.char)(jobt), (C.char)(jobp), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_sva), (*C.float)(_u), (C.lapack_int)(ldu), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgejsv.f. +func Dgejsv(joba, jobu, jobv, jobr, jobt, jobp lapack.Job, m, n int, a []float64, lda int, sva, u []float64, ldu int, v []float64, ldv int, work []float64, lwork int, iwork []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _sva *float64 + if len(sva) > 0 { + _sva = &sva[0] + } + var _u *float64 + if len(u) > 0 { + _u = &u[0] + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgejsv_work((C.int)(rowMajor), (C.char)(joba), (C.char)(jobu), (C.char)(jobv), (C.char)(jobr), (C.char)(jobt), (C.char)(jobp), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_sva), (*C.double)(_u), (C.lapack_int)(ldu), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgejsv.f. +func Cgejsv(joba, jobu, jobv, jobr, jobt, jobp lapack.Job, m, n int, a []complex64, lda int, sva []float32, u []complex64, ldu int, v []complex64, ldv int, cwork []complex64, lwork int, work []float32, lrwork int, iwork []int32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _sva *float32 + if len(sva) > 0 { + _sva = &sva[0] + } + var _u *complex64 + if len(u) > 0 { + _u = &u[0] + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _cwork *complex64 + if len(cwork) > 0 { + _cwork = &cwork[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cgejsv_work((C.int)(rowMajor), (C.char)(joba), (C.char)(jobu), (C.char)(jobv), (C.char)(jobr), (C.char)(jobt), (C.char)(jobp), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_sva), (*C.lapack_complex_float)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_cwork), (C.lapack_int)(lwork), (*C.float)(_work), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgejsv.f. +func Zgejsv(joba, jobu, jobv, jobr, jobt, jobp lapack.Job, m, n int, a []complex128, lda int, sva []float64, u []complex128, ldu int, v []complex128, ldv int, cwork []complex128, lwork int, work []float64, lrwork int, iwork []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _sva *float64 + if len(sva) > 0 { + _sva = &sva[0] + } + var _u *complex128 + if len(u) > 0 { + _u = &u[0] + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _cwork *complex128 + if len(cwork) > 0 { + _cwork = &cwork[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zgejsv_work((C.int)(rowMajor), (C.char)(joba), (C.char)(jobu), (C.char)(jobv), (C.char)(jobr), (C.char)(jobt), (C.char)(jobp), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_sva), (*C.lapack_complex_double)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_cwork), (C.lapack_int)(lwork), (*C.double)(_work), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgelq2.f. +func Sgelq2(m, n int, a []float32, lda int, tau, work []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgelq2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgelq2.f. +func Dgelq2(m, n int, a []float64, lda int, tau, work []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgelq2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgelq2.f. +func Cgelq2(m, n int, a []complex64, lda int, tau, work []complex64) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgelq2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgelq2.f. +func Zgelq2(m, n int, a []complex128, lda int, tau, work []complex128) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgelq2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgelqf.f. +func Sgelqf(m, n int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgelqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgelqf.f. +func Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgelqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgelqf.f. +func Cgelqf(m, n int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgelqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgelqf.f. +func Zgelqf(m, n int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgelqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgels.f. +func Sgels(trans blas.Transpose, m, n, nrhs int, a []float32, lda int, b []float32, ldb int, work []float32, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgels_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgels.f. +func Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgels_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgels.f. +func Cgels(trans blas.Transpose, m, n, nrhs int, a []complex64, lda int, b []complex64, ldb int, work []complex64, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgels_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgels.f. +func Zgels(trans blas.Transpose, m, n, nrhs int, a []complex128, lda int, b []complex128, ldb int, work []complex128, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgels_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgelsd.f. +func Sgelsd(m, n, nrhs int, a []float32, lda int, b []float32, ldb int, s []float32, rcond float32, rank []int32, work []float32, lwork int, iwork []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgelsd_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_s), (C.float)(rcond), (*C.lapack_int)(_rank), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgelsd.f. +func Dgelsd(m, n, nrhs int, a []float64, lda int, b []float64, ldb int, s []float64, rcond float64, rank []int32, work []float64, lwork int, iwork []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgelsd_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_s), (C.double)(rcond), (*C.lapack_int)(_rank), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgelsd.f. +func Cgelsd(m, n, nrhs int, a []complex64, lda int, b []complex64, ldb int, s []float32, rcond float32, rank []int32, work []complex64, lwork int, rwork []float32, iwork []int32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cgelsd_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.float)(_s), (C.float)(rcond), (*C.lapack_int)(_rank), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgelsd.f. +func Zgelsd(m, n, nrhs int, a []complex128, lda int, b []complex128, ldb int, s []float64, rcond float64, rank []int32, work []complex128, lwork int, rwork []float64, iwork []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zgelsd_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.double)(_s), (C.double)(rcond), (*C.lapack_int)(_rank), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgelss.f. +func Sgelss(m, n, nrhs int, a []float32, lda int, b []float32, ldb int, s []float32, rcond float32, rank []int32, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgelss_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_s), (C.float)(rcond), (*C.lapack_int)(_rank), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgelss.f. +func Dgelss(m, n, nrhs int, a []float64, lda int, b []float64, ldb int, s []float64, rcond float64, rank []int32, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgelss_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_s), (C.double)(rcond), (*C.lapack_int)(_rank), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgelss.f. +func Cgelss(m, n, nrhs int, a []complex64, lda int, b []complex64, ldb int, s []float32, rcond float32, rank []int32, work []complex64, lwork int, rwork []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgelss_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.float)(_s), (C.float)(rcond), (*C.lapack_int)(_rank), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgelss.f. +func Zgelss(m, n, nrhs int, a []complex128, lda int, b []complex128, ldb int, s []float64, rcond float64, rank []int32, work []complex128, lwork int, rwork []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgelss_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.double)(_s), (C.double)(rcond), (*C.lapack_int)(_rank), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgelsy.f. +func Sgelsy(m, n, nrhs int, a []float32, lda int, b []float32, ldb int, jpvt []int32, rcond float32, rank []int32, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _jpvt *int32 + if len(jpvt) > 0 { + _jpvt = &jpvt[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgelsy_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.lapack_int)(_jpvt), (C.float)(rcond), (*C.lapack_int)(_rank), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgelsy.f. +func Dgelsy(m, n, nrhs int, a []float64, lda int, b []float64, ldb int, jpvt []int32, rcond float64, rank []int32, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _jpvt *int32 + if len(jpvt) > 0 { + _jpvt = &jpvt[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgelsy_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.lapack_int)(_jpvt), (C.double)(rcond), (*C.lapack_int)(_rank), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgelsy.f. +func Cgelsy(m, n, nrhs int, a []complex64, lda int, b []complex64, ldb int, jpvt []int32, rcond float32, rank []int32, work []complex64, lwork int, rwork []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _jpvt *int32 + if len(jpvt) > 0 { + _jpvt = &jpvt[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgelsy_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_int)(_jpvt), (C.float)(rcond), (*C.lapack_int)(_rank), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgelsy.f. +func Zgelsy(m, n, nrhs int, a []complex128, lda int, b []complex128, ldb int, jpvt []int32, rcond float64, rank []int32, work []complex128, lwork int, rwork []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _jpvt *int32 + if len(jpvt) > 0 { + _jpvt = &jpvt[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgelsy_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_int)(_jpvt), (C.double)(rcond), (*C.lapack_int)(_rank), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeqlf.f. +func Sgeqlf(m, n int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgeqlf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeqlf.f. +func Dgeqlf(m, n int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgeqlf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeqlf.f. +func Cgeqlf(m, n int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgeqlf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeqlf.f. +func Zgeqlf(m, n int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgeqlf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeqp3.f. +func Sgeqp3(m, n int, a []float32, lda int, jpvt []int32, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _jpvt *int32 + if len(jpvt) > 0 { + _jpvt = &jpvt[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgeqp3_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_jpvt), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeqp3.f. +func Dgeqp3(m, n int, a []float64, lda int, jpvt []int32, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _jpvt *int32 + if len(jpvt) > 0 { + _jpvt = &jpvt[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgeqp3_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_jpvt), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeqp3.f. +func Cgeqp3(m, n int, a []complex64, lda int, jpvt []int32, tau, work []complex64, lwork int, rwork []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _jpvt *int32 + if len(jpvt) > 0 { + _jpvt = &jpvt[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgeqp3_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_jpvt), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeqp3.f. +func Zgeqp3(m, n int, a []complex128, lda int, jpvt []int32, tau, work []complex128, lwork int, rwork []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _jpvt *int32 + if len(jpvt) > 0 { + _jpvt = &jpvt[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgeqp3_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_jpvt), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeqr2.f. +func Sgeqr2(m, n int, a []float32, lda int, tau, work []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgeqr2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeqr2.f. +func Dgeqr2(m, n int, a []float64, lda int, tau, work []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgeqr2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeqr2.f. +func Cgeqr2(m, n int, a []complex64, lda int, tau, work []complex64) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgeqr2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeqr2.f. +func Zgeqr2(m, n int, a []complex128, lda int, tau, work []complex128) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgeqr2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeqrf.f. +func Sgeqrf(m, n int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgeqrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeqrf.f. +func Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgeqrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeqrf.f. +func Cgeqrf(m, n int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgeqrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeqrf.f. +func Zgeqrf(m, n int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgeqrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeqrfp.f. +func Sgeqrfp(m, n int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgeqrfp_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeqrfp.f. +func Dgeqrfp(m, n int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgeqrfp_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeqrfp.f. +func Cgeqrfp(m, n int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgeqrfp_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeqrfp.f. +func Zgeqrfp(m, n int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgeqrfp_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgerfs.f. +func Sgerfs(trans blas.Transpose, n, nrhs int, a []float32, lda int, af []float32, ldaf int, ipiv []int32, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _af *float32 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgerfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgerfs.f. +func Dgerfs(trans blas.Transpose, n, nrhs int, a []float64, lda int, af []float64, ldaf int, ipiv []int32, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _af *float64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgerfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgerfs.f. +func Cgerfs(trans blas.Transpose, n, nrhs int, a []complex64, lda int, af []complex64, ldaf int, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgerfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgerfs.f. +func Zgerfs(trans blas.Transpose, n, nrhs int, a []complex128, lda int, af []complex128, ldaf int, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex128 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgerfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgerqf.f. +func Sgerqf(m, n int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgerqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgerqf.f. +func Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgerqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgerqf.f. +func Cgerqf(m, n int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgerqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgerqf.f. +func Zgerqf(m, n int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgerqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgesdd.f. +func Sgesdd(jobz lapack.Job, m, n int, a []float32, lda int, s, u []float32, ldu int, vt []float32, ldvt int, work []float32, lwork int, iwork []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _u *float32 + if len(u) > 0 { + _u = &u[0] + } + var _vt *float32 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgesdd_work((C.int)(rowMajor), (C.char)(jobz), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.float)(_u), (C.lapack_int)(ldu), (*C.float)(_vt), (C.lapack_int)(ldvt), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesdd.f. +func Dgesdd(jobz lapack.Job, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int, iwork []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _u *float64 + if len(u) > 0 { + _u = &u[0] + } + var _vt *float64 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgesdd_work((C.int)(rowMajor), (C.char)(jobz), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.double)(_u), (C.lapack_int)(ldu), (*C.double)(_vt), (C.lapack_int)(ldvt), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgesdd.f. +func Cgesdd(jobz lapack.Job, m, n int, a []complex64, lda int, s []float32, u []complex64, ldu int, vt []complex64, ldvt int, work []complex64, lwork int, rwork []float32, iwork []int32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _u *complex64 + if len(u) > 0 { + _u = &u[0] + } + var _vt *complex64 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cgesdd_work((C.int)(rowMajor), (C.char)(jobz), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.lapack_complex_float)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_float)(_vt), (C.lapack_int)(ldvt), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgesdd.f. +func Zgesdd(jobz lapack.Job, m, n int, a []complex128, lda int, s []float64, u []complex128, ldu int, vt []complex128, ldvt int, work []complex128, lwork int, rwork []float64, iwork []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _u *complex128 + if len(u) > 0 { + _u = &u[0] + } + var _vt *complex128 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zgesdd_work((C.int)(rowMajor), (C.char)(jobz), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.lapack_complex_double)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_double)(_vt), (C.lapack_int)(ldvt), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgesv.f. +func Sgesv(n, nrhs int, a []float32, lda int, ipiv []int32, b []float32, ldb int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sgesv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesv.f. +func Dgesv(n, nrhs int, a []float64, lda int, ipiv []int32, b []float64, ldb int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dgesv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgesv.f. +func Cgesv(n, nrhs int, a []complex64, lda int, ipiv []int32, b []complex64, ldb int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cgesv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgesv.f. +func Zgesv(n, nrhs int, a []complex128, lda int, ipiv []int32, b []complex128, ldb int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zgesv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsgesv.f. +func Dsgesv(n, nrhs int, a []float64, lda int, ipiv []int32, b []float64, ldb int, x []float64, ldx int, work []float64, swork []float32, iter []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _swork *float32 + if len(swork) > 0 { + _swork = &swork[0] + } + var _iter *int32 + if len(iter) > 0 { + _iter = &iter[0] + } + return isZero(C.LAPACKE_dsgesv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_work), (*C.float)(_swork), (*C.lapack_int)(_iter))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zcgesv.f. +func Zcgesv(n, nrhs int, a []complex128, lda int, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, work []complex128, swork []complex64, rwork []float64, iter []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _swork *complex64 + if len(swork) > 0 { + _swork = &swork[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iter *int32 + if len(iter) > 0 { + _iter = &iter[0] + } + return isZero(C.LAPACKE_zcgesv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.lapack_complex_double)(_work), (*C.lapack_complex_float)(_swork), (*C.double)(_rwork), (*C.lapack_int)(_iter))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgesvd.f. +func Sgesvd(jobu, jobvt lapack.Job, m, n int, a []float32, lda int, s, u []float32, ldu int, vt []float32, ldvt int, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _u *float32 + if len(u) > 0 { + _u = &u[0] + } + var _vt *float32 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgesvd_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobvt), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.float)(_u), (C.lapack_int)(ldu), (*C.float)(_vt), (C.lapack_int)(ldvt), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesvd.f. +func Dgesvd(jobu, jobvt lapack.Job, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _u *float64 + if len(u) > 0 { + _u = &u[0] + } + var _vt *float64 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgesvd_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobvt), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.double)(_u), (C.lapack_int)(ldu), (*C.double)(_vt), (C.lapack_int)(ldvt), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgesvd.f. +func Cgesvd(jobu, jobvt lapack.Job, m, n int, a []complex64, lda int, s []float32, u []complex64, ldu int, vt []complex64, ldvt int, work []complex64, lwork int, rwork []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _u *complex64 + if len(u) > 0 { + _u = &u[0] + } + var _vt *complex64 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgesvd_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobvt), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.lapack_complex_float)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_float)(_vt), (C.lapack_int)(ldvt), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgesvd.f. +func Zgesvd(jobu, jobvt lapack.Job, m, n int, a []complex128, lda int, s []float64, u []complex128, ldu int, vt []complex128, ldvt int, work []complex128, lwork int, rwork []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _u *complex128 + if len(u) > 0 { + _u = &u[0] + } + var _vt *complex128 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgesvd_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobvt), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.lapack_complex_double)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_double)(_vt), (C.lapack_int)(ldvt), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgesvdx.f. +func Sgesvdx(jobu, jobvt lapack.Job, rng byte, m, n int, a []float32, lda, vl, vu, il, iu, ns int, s, u []float32, ldu int, vt []float32, ldvt int, work []float32, lwork int, iwork []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _u *float32 + if len(u) > 0 { + _u = &u[0] + } + var _vt *float32 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgesvdx_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobvt), (C.char)(rng), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (C.lapack_int)(vl), (C.lapack_int)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.lapack_int)(ns), (*C.float)(_s), (*C.float)(_u), (C.lapack_int)(ldu), (*C.float)(_vt), (C.lapack_int)(ldvt), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesvdx.f. +func Dgesvdx(jobu, jobvt lapack.Job, rng byte, m, n int, a []float64, lda, vl, vu, il, iu, ns int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int, iwork []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _u *float64 + if len(u) > 0 { + _u = &u[0] + } + var _vt *float64 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgesvdx_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobvt), (C.char)(rng), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (C.lapack_int)(vl), (C.lapack_int)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.lapack_int)(ns), (*C.double)(_s), (*C.double)(_u), (C.lapack_int)(ldu), (*C.double)(_vt), (C.lapack_int)(ldvt), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgesvdx.f. +func Cgesvdx(jobu, jobvt lapack.Job, rng byte, m, n int, a []complex64, lda, vl, vu, il, iu, ns int, s []float32, u []complex64, ldu int, vt []complex64, ldvt int, work []complex64, lwork int, rwork []float32, iwork []int32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _u *complex64 + if len(u) > 0 { + _u = &u[0] + } + var _vt *complex64 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cgesvdx_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobvt), (C.char)(rng), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (C.lapack_int)(vl), (C.lapack_int)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.lapack_int)(ns), (*C.float)(_s), (*C.lapack_complex_float)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_float)(_vt), (C.lapack_int)(ldvt), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgesvdx.f. +func Zgesvdx(jobu, jobvt lapack.Job, rng byte, m, n int, a []complex128, lda, vl, vu, il, iu, ns int, s []float64, u []complex128, ldu int, vt []complex128, ldvt int, work []complex128, lwork int, rwork []float64, iwork []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _u *complex128 + if len(u) > 0 { + _u = &u[0] + } + var _vt *complex128 + if len(vt) > 0 { + _vt = &vt[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zgesvdx_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobvt), (C.char)(rng), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (C.lapack_int)(vl), (C.lapack_int)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.lapack_int)(ns), (*C.double)(_s), (*C.lapack_complex_double)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_double)(_vt), (C.lapack_int)(ldvt), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgesvj.f. +func Sgesvj(joba, jobu, jobv lapack.Job, m, n int, a []float32, lda int, sva []float32, mv int, v []float32, ldv int, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _sva *float32 + if len(sva) > 0 { + _sva = &sva[0] + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgesvj_work((C.int)(rowMajor), (C.char)(joba), (C.char)(jobu), (C.char)(jobv), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_sva), (C.lapack_int)(mv), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesvj.f. +func Dgesvj(joba, jobu, jobv lapack.Job, m, n int, a []float64, lda int, sva []float64, mv int, v []float64, ldv int, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _sva *float64 + if len(sva) > 0 { + _sva = &sva[0] + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgesvj_work((C.int)(rowMajor), (C.char)(joba), (C.char)(jobu), (C.char)(jobv), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_sva), (C.lapack_int)(mv), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgesvj.f. +func Cgesvj(joba, jobu, jobv lapack.Job, m, n int, a []complex64, lda int, sva []float32, mv int, v []complex64, ldv int, cwork []complex64, lwork int, rwork []float32, lrwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _sva *float32 + if len(sva) > 0 { + _sva = &sva[0] + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _cwork *complex64 + if len(cwork) > 0 { + _cwork = &cwork[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgesvj_work((C.int)(rowMajor), (C.char)(joba), (C.char)(jobu), (C.char)(jobv), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_sva), (C.lapack_int)(mv), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_cwork), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgesvj.f. +func Zgesvj(joba, jobu, jobv lapack.Job, m, n int, a []complex128, lda int, sva []float64, mv int, v []complex128, ldv int, cwork []complex128, lwork int, rwork []float64, lrwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _sva *float64 + if len(sva) > 0 { + _sva = &sva[0] + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _cwork *complex128 + if len(cwork) > 0 { + _cwork = &cwork[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgesvj_work((C.int)(rowMajor), (C.char)(joba), (C.char)(jobu), (C.char)(jobv), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_sva), (C.lapack_int)(mv), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_cwork), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgesvx.f. +func Sgesvx(fact byte, trans blas.Transpose, n, nrhs int, a []float32, lda int, af []float32, ldaf int, ipiv []int32, equed []byte, r, c, b []float32, ldb int, x []float32, ldx int, rcond, ferr, berr, work []float32, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _af *float32 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgesvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_r), (*C.float)(_c), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgesvx.f. +func Dgesvx(fact byte, trans blas.Transpose, n, nrhs int, a []float64, lda int, af []float64, ldaf int, ipiv []int32, equed []byte, r, c, b []float64, ldb int, x []float64, ldx int, rcond, ferr, berr, work []float64, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _af *float64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgesvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_r), (*C.double)(_c), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgesvx.f. +func Cgesvx(fact byte, trans blas.Transpose, n, nrhs int, a []complex64, lda int, af []complex64, ldaf int, ipiv []int32, equed []byte, r, c []float32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgesvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_r), (*C.float)(_c), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgesvx.f. +func Zgesvx(fact byte, trans blas.Transpose, n, nrhs int, a []complex128, lda int, af []complex128, ldaf int, ipiv []int32, equed []byte, r, c []float64, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex128 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgesvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_r), (*C.double)(_c), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgetf2.f. +func Sgetf2(m, n int, a []float32, lda int, ipiv []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_sgetf2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgetf2.f. +func Dgetf2(m, n int, a []float64, lda int, ipiv []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_dgetf2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgetf2.f. +func Cgetf2(m, n int, a []complex64, lda int, ipiv []int32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_cgetf2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgetf2.f. +func Zgetf2(m, n int, a []complex128, lda int, ipiv []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_zgetf2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgetrf.f. +func Sgetrf(m, n int, a []float32, lda int, ipiv []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_sgetrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgetrf.f. +func Dgetrf(m, n int, a []float64, lda int, ipiv []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_dgetrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgetrf.f. +func Cgetrf(m, n int, a []complex64, lda int, ipiv []int32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_cgetrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgetrf.f. +func Zgetrf(m, n int, a []complex128, lda int, ipiv []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_zgetrf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgetrf2.f. +func Sgetrf2(m, n int, a []float32, lda int, ipiv []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_sgetrf2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgetrf2.f. +func Dgetrf2(m, n int, a []float64, lda int, ipiv []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_dgetrf2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgetrf2.f. +func Cgetrf2(m, n int, a []complex64, lda int, ipiv []int32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_cgetrf2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgetrf2.f. +func Zgetrf2(m, n int, a []complex128, lda int, ipiv []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_zgetrf2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgetri.f. +func Sgetri(n int, a []float32, lda int, ipiv []int32, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgetri_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgetri.f. +func Dgetri(n int, a []float64, lda int, ipiv []int32, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgetri_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgetri.f. +func Cgetri(n int, a []complex64, lda int, ipiv []int32, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgetri_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgetri.f. +func Zgetri(n int, a []complex128, lda int, ipiv []int32, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgetri_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgetrs.f. +func Sgetrs(trans blas.Transpose, n, nrhs int, a []float32, lda int, ipiv []int32, b []float32, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sgetrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgetrs.f. +func Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int32, b []float64, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dgetrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgetrs.f. +func Cgetrs(trans blas.Transpose, n, nrhs int, a []complex64, lda int, ipiv []int32, b []complex64, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cgetrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgetrs.f. +func Zgetrs(trans blas.Transpose, n, nrhs int, a []complex128, lda int, ipiv []int32, b []complex128, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zgetrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggbak.f. +func Sggbak(job lapack.Job, side blas.Side, n, ilo, ihi int, lscale, rscale []float32, m int, v []float32, ldv int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _lscale *float32 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float32 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + return isZero(C.LAPACKE_sggbak_work((C.int)(rowMajor), (C.char)(job), (C.char)(side), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_lscale), (*C.float)(_rscale), (C.lapack_int)(m), (*C.float)(_v), (C.lapack_int)(ldv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggbak.f. +func Dggbak(job lapack.Job, side blas.Side, n, ilo, ihi int, lscale, rscale []float64, m int, v []float64, ldv int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _lscale *float64 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float64 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + return isZero(C.LAPACKE_dggbak_work((C.int)(rowMajor), (C.char)(job), (C.char)(side), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_lscale), (*C.double)(_rscale), (C.lapack_int)(m), (*C.double)(_v), (C.lapack_int)(ldv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggbak.f. +func Cggbak(job lapack.Job, side blas.Side, n, ilo, ihi int, lscale, rscale []float32, m int, v []complex64, ldv int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _lscale *float32 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float32 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + return isZero(C.LAPACKE_cggbak_work((C.int)(rowMajor), (C.char)(job), (C.char)(side), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_lscale), (*C.float)(_rscale), (C.lapack_int)(m), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggbak.f. +func Zggbak(job lapack.Job, side blas.Side, n, ilo, ihi int, lscale, rscale []float64, m int, v []complex128, ldv int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _lscale *float64 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float64 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + return isZero(C.LAPACKE_zggbak_work((C.int)(rowMajor), (C.char)(job), (C.char)(side), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_lscale), (*C.double)(_rscale), (C.lapack_int)(m), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggbal.f. +func Sggbal(job lapack.Job, n int, a []float32, lda int, b []float32, ldb int, ilo, ihi []int32, lscale, rscale, work []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _lscale *float32 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float32 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sggbal_work((C.int)(rowMajor), (C.char)(job), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.float)(_lscale), (*C.float)(_rscale), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggbal.f. +func Dggbal(job lapack.Job, n int, a []float64, lda int, b []float64, ldb int, ilo, ihi []int32, lscale, rscale, work []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _lscale *float64 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float64 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dggbal_work((C.int)(rowMajor), (C.char)(job), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.double)(_lscale), (*C.double)(_rscale), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggbal.f. +func Cggbal(job lapack.Job, n int, a []complex64, lda int, b []complex64, ldb int, ilo, ihi []int32, lscale, rscale, work []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _lscale *float32 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float32 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cggbal_work((C.int)(rowMajor), (C.char)(job), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.float)(_lscale), (*C.float)(_rscale), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggbal.f. +func Zggbal(job lapack.Job, n int, a []complex128, lda int, b []complex128, ldb int, ilo, ihi []int32, lscale, rscale, work []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _lscale *float64 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float64 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zggbal_work((C.int)(rowMajor), (C.char)(job), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.double)(_lscale), (*C.double)(_rscale), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggev.f. +func Sggev(jobvl, jobvr lapack.Job, n int, a []float32, lda int, b []float32, ldb int, alphar, alphai, beta, vl []float32, ldvl int, vr []float32, ldvr int, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _alphar *float32 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float32 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float32 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sggev_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_alphar), (*C.float)(_alphai), (*C.float)(_beta), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggev.f. +func Dggev(jobvl, jobvr lapack.Job, n int, a []float64, lda int, b []float64, ldb int, alphar, alphai, beta, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _alphar *float64 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float64 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dggev_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_alphar), (*C.double)(_alphai), (*C.double)(_beta), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggev.f. +func Cggev(jobvl, jobvr lapack.Job, n int, a []complex64, lda int, b []complex64, ldb int, alpha, beta, vl []complex64, ldvl int, vr []complex64, ldvr int, work []complex64, lwork int, rwork []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *complex64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cggev_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_alpha), (*C.lapack_complex_float)(_beta), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggev.f. +func Zggev(jobvl, jobvr lapack.Job, n int, a []complex128, lda int, b []complex128, ldb int, alpha, beta, vl []complex128, ldvl int, vr []complex128, ldvr int, work []complex128, lwork int, rwork []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *complex128 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex128 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zggev_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_alpha), (*C.lapack_complex_double)(_beta), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggev3.f. +func Sggev3(jobvl, jobvr lapack.Job, n int, a []float32, lda int, b []float32, ldb int, alphar, alphai, beta, vl []float32, ldvl int, vr []float32, ldvr int, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _alphar *float32 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float32 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float32 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sggev3_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_alphar), (*C.float)(_alphai), (*C.float)(_beta), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggev3.f. +func Dggev3(jobvl, jobvr lapack.Job, n int, a []float64, lda int, b []float64, ldb int, alphar, alphai, beta, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _alphar *float64 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float64 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dggev3_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_alphar), (*C.double)(_alphai), (*C.double)(_beta), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggev3.f. +func Cggev3(jobvl, jobvr lapack.Job, n int, a []complex64, lda int, b []complex64, ldb int, alpha, beta, vl []complex64, ldvl int, vr []complex64, ldvr int, work []complex64, lwork int, rwork []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *complex64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cggev3_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_alpha), (*C.lapack_complex_float)(_beta), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggev3.f. +func Zggev3(jobvl, jobvr lapack.Job, n int, a []complex128, lda int, b []complex128, ldb int, alpha, beta, vl []complex128, ldvl int, vr []complex128, ldvr int, work []complex128, lwork int, rwork []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *complex128 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex128 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zggev3_work((C.int)(rowMajor), (C.char)(jobvl), (C.char)(jobvr), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_alpha), (*C.lapack_complex_double)(_beta), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggevx.f. +func Sggevx(balanc byte, jobvl, jobvr lapack.Job, sense byte, n int, a []float32, lda int, b []float32, ldb int, alphar, alphai, beta, vl []float32, ldvl int, vr []float32, ldvr int, ilo, ihi []int32, lscale, rscale, abnrm, bbnrm, rconde, rcondv, work []float32, lwork int, iwork, bwork []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _alphar *float32 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float32 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float32 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _lscale *float32 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float32 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _abnrm *float32 + if len(abnrm) > 0 { + _abnrm = &abnrm[0] + } + var _bbnrm *float32 + if len(bbnrm) > 0 { + _bbnrm = &bbnrm[0] + } + var _rconde *float32 + if len(rconde) > 0 { + _rconde = &rconde[0] + } + var _rcondv *float32 + if len(rcondv) > 0 { + _rcondv = &rcondv[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _bwork *int32 + if len(bwork) > 0 { + _bwork = &bwork[0] + } + return isZero(C.LAPACKE_sggevx_work((C.int)(rowMajor), (C.char)(balanc), (C.char)(jobvl), (C.char)(jobvr), (C.char)(sense), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_alphar), (*C.float)(_alphai), (*C.float)(_beta), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.float)(_lscale), (*C.float)(_rscale), (*C.float)(_abnrm), (*C.float)(_bbnrm), (*C.float)(_rconde), (*C.float)(_rcondv), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (*C.lapack_logical)(_bwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggevx.f. +func Dggevx(balanc byte, jobvl, jobvr lapack.Job, sense byte, n int, a []float64, lda int, b []float64, ldb int, alphar, alphai, beta, vl []float64, ldvl int, vr []float64, ldvr int, ilo, ihi []int32, lscale, rscale, abnrm, bbnrm, rconde, rcondv, work []float64, lwork int, iwork, bwork []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _alphar *float64 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float64 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _lscale *float64 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float64 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _abnrm *float64 + if len(abnrm) > 0 { + _abnrm = &abnrm[0] + } + var _bbnrm *float64 + if len(bbnrm) > 0 { + _bbnrm = &bbnrm[0] + } + var _rconde *float64 + if len(rconde) > 0 { + _rconde = &rconde[0] + } + var _rcondv *float64 + if len(rcondv) > 0 { + _rcondv = &rcondv[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _bwork *int32 + if len(bwork) > 0 { + _bwork = &bwork[0] + } + return isZero(C.LAPACKE_dggevx_work((C.int)(rowMajor), (C.char)(balanc), (C.char)(jobvl), (C.char)(jobvr), (C.char)(sense), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_alphar), (*C.double)(_alphai), (*C.double)(_beta), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.double)(_lscale), (*C.double)(_rscale), (*C.double)(_abnrm), (*C.double)(_bbnrm), (*C.double)(_rconde), (*C.double)(_rcondv), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (*C.lapack_logical)(_bwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggevx.f. +func Cggevx(balanc byte, jobvl, jobvr lapack.Job, sense byte, n int, a []complex64, lda int, b []complex64, ldb int, alpha, beta, vl []complex64, ldvl int, vr []complex64, ldvr int, ilo, ihi []int32, lscale, rscale, abnrm, bbnrm, rconde, rcondv []float32, work []complex64, lwork int, rwork []float32, iwork, bwork []int32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *complex64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _lscale *float32 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float32 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _abnrm *float32 + if len(abnrm) > 0 { + _abnrm = &abnrm[0] + } + var _bbnrm *float32 + if len(bbnrm) > 0 { + _bbnrm = &bbnrm[0] + } + var _rconde *float32 + if len(rconde) > 0 { + _rconde = &rconde[0] + } + var _rcondv *float32 + if len(rcondv) > 0 { + _rcondv = &rcondv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _bwork *int32 + if len(bwork) > 0 { + _bwork = &bwork[0] + } + return isZero(C.LAPACKE_cggevx_work((C.int)(rowMajor), (C.char)(balanc), (C.char)(jobvl), (C.char)(jobvr), (C.char)(sense), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_alpha), (*C.lapack_complex_float)(_beta), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.float)(_lscale), (*C.float)(_rscale), (*C.float)(_abnrm), (*C.float)(_bbnrm), (*C.float)(_rconde), (*C.float)(_rcondv), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_logical)(_bwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggevx.f. +func Zggevx(balanc byte, jobvl, jobvr lapack.Job, sense byte, n int, a []complex128, lda int, b []complex128, ldb int, alpha, beta, vl []complex128, ldvl int, vr []complex128, ldvr int, ilo, ihi []int32, lscale, rscale, abnrm, bbnrm, rconde, rcondv []float64, work []complex128, lwork int, rwork []float64, iwork, bwork []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *complex128 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex128 + if len(beta) > 0 { + _beta = &beta[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _ilo *int32 + if len(ilo) > 0 { + _ilo = &ilo[0] + } + var _ihi *int32 + if len(ihi) > 0 { + _ihi = &ihi[0] + } + var _lscale *float64 + if len(lscale) > 0 { + _lscale = &lscale[0] + } + var _rscale *float64 + if len(rscale) > 0 { + _rscale = &rscale[0] + } + var _abnrm *float64 + if len(abnrm) > 0 { + _abnrm = &abnrm[0] + } + var _bbnrm *float64 + if len(bbnrm) > 0 { + _bbnrm = &bbnrm[0] + } + var _rconde *float64 + if len(rconde) > 0 { + _rconde = &rconde[0] + } + var _rcondv *float64 + if len(rcondv) > 0 { + _rcondv = &rcondv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _bwork *int32 + if len(bwork) > 0 { + _bwork = &bwork[0] + } + return isZero(C.LAPACKE_zggevx_work((C.int)(rowMajor), (C.char)(balanc), (C.char)(jobvl), (C.char)(jobvr), (C.char)(sense), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_alpha), (*C.lapack_complex_double)(_beta), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (*C.lapack_int)(_ilo), (*C.lapack_int)(_ihi), (*C.double)(_lscale), (*C.double)(_rscale), (*C.double)(_abnrm), (*C.double)(_bbnrm), (*C.double)(_rconde), (*C.double)(_rcondv), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_logical)(_bwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggglm.f. +func Sggglm(n, m, p int, a []float32, lda int, b []float32, ldb int, d, x, y, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _y *float32 + if len(y) > 0 { + _y = &y[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sggglm_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(m), (C.lapack_int)(p), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_d), (*C.float)(_x), (*C.float)(_y), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggglm.f. +func Dggglm(n, m, p int, a []float64, lda int, b []float64, ldb int, d, x, y, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _y *float64 + if len(y) > 0 { + _y = &y[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dggglm_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(m), (C.lapack_int)(p), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_d), (*C.double)(_x), (*C.double)(_y), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggglm.f. +func Cggglm(n, m, p int, a []complex64, lda int, b []complex64, ldb int, d, x, y, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _d *complex64 + if len(d) > 0 { + _d = &d[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _y *complex64 + if len(y) > 0 { + _y = &y[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cggglm_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(m), (C.lapack_int)(p), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_d), (*C.lapack_complex_float)(_x), (*C.lapack_complex_float)(_y), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggglm.f. +func Zggglm(n, m, p int, a []complex128, lda int, b []complex128, ldb int, d, x, y, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _d *complex128 + if len(d) > 0 { + _d = &d[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _y *complex128 + if len(y) > 0 { + _y = &y[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zggglm_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(m), (C.lapack_int)(p), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_d), (*C.lapack_complex_double)(_x), (*C.lapack_complex_double)(_y), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgghrd.f. +func Sgghrd(compq, compz lapack.Comp, n, ilo, ihi int, a []float32, lda int, b []float32, ldb int, q []float32, ldq int, z []float32, ldz int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + return isZero(C.LAPACKE_sgghrd_work((C.int)(rowMajor), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_z), (C.lapack_int)(ldz))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgghrd.f. +func Dgghrd(compq, compz lapack.Comp, n, ilo, ihi int, a []float64, lda int, b []float64, ldb int, q []float64, ldq int, z []float64, ldz int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + return isZero(C.LAPACKE_dgghrd_work((C.int)(rowMajor), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_z), (C.lapack_int)(ldz))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgghrd.f. +func Cgghrd(compq, compz lapack.Comp, n, ilo, ihi int, a []complex64, lda int, b []complex64, ldb int, q []complex64, ldq int, z []complex64, ldz int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + return isZero(C.LAPACKE_cgghrd_work((C.int)(rowMajor), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgghrd.f. +func Zgghrd(compq, compz lapack.Comp, n, ilo, ihi int, a []complex128, lda int, b []complex128, ldb int, q []complex128, ldq int, z []complex128, ldz int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + return isZero(C.LAPACKE_zgghrd_work((C.int)(rowMajor), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgghd3.f. +func Sgghd3(compq, compz lapack.Comp, n, ilo, ihi int, a []float32, lda int, b []float32, ldb int, q []float32, ldq int, z []float32, ldz int, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgghd3_work((C.int)(rowMajor), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgghd3.f. +func Dgghd3(compq, compz lapack.Comp, n, ilo, ihi int, a []float64, lda int, b []float64, ldb int, q []float64, ldq int, z []float64, ldz int, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgghd3_work((C.int)(rowMajor), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgghd3.f. +func Cgghd3(compq, compz lapack.Comp, n, ilo, ihi int, a []complex64, lda int, b []complex64, ldb int, q []complex64, ldq int, z []complex64, ldz int, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgghd3_work((C.int)(rowMajor), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgghd3.f. +func Zgghd3(compq, compz lapack.Comp, n, ilo, ihi int, a []complex128, lda int, b []complex128, ldb int, q []complex128, ldq int, z []complex128, ldz int, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgghd3_work((C.int)(rowMajor), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgglse.f. +func Sgglse(m, n, p int, a []float32, lda int, b []float32, ldb int, c, d, x, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgglse_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(p), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_c), (*C.float)(_d), (*C.float)(_x), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgglse.f. +func Dgglse(m, n, p int, a []float64, lda int, b []float64, ldb int, c, d, x, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgglse_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(p), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_c), (*C.double)(_d), (*C.double)(_x), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgglse.f. +func Cgglse(m, n, p int, a []complex64, lda int, b []complex64, ldb int, c, d, x, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _d *complex64 + if len(d) > 0 { + _d = &d[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgglse_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(p), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_c), (*C.lapack_complex_float)(_d), (*C.lapack_complex_float)(_x), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgglse.f. +func Zgglse(m, n, p int, a []complex128, lda int, b []complex128, ldb int, c, d, x, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _d *complex128 + if len(d) > 0 { + _d = &d[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgglse_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(p), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_c), (*C.lapack_complex_double)(_d), (*C.lapack_complex_double)(_x), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggqrf.f. +func Sggqrf(n, m, p int, a []float32, lda int, taua, b []float32, ldb int, taub, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _taua *float32 + if len(taua) > 0 { + _taua = &taua[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _taub *float32 + if len(taub) > 0 { + _taub = &taub[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sggqrf_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(m), (C.lapack_int)(p), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_taua), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_taub), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggqrf.f. +func Dggqrf(n, m, p int, a []float64, lda int, taua, b []float64, ldb int, taub, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _taua *float64 + if len(taua) > 0 { + _taua = &taua[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _taub *float64 + if len(taub) > 0 { + _taub = &taub[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dggqrf_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(m), (C.lapack_int)(p), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_taua), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_taub), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggqrf.f. +func Cggqrf(n, m, p int, a []complex64, lda int, taua, b []complex64, ldb int, taub, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _taua *complex64 + if len(taua) > 0 { + _taua = &taua[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _taub *complex64 + if len(taub) > 0 { + _taub = &taub[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cggqrf_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(m), (C.lapack_int)(p), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_taua), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_taub), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggqrf.f. +func Zggqrf(n, m, p int, a []complex128, lda int, taua, b []complex128, ldb int, taub, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _taua *complex128 + if len(taua) > 0 { + _taua = &taua[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _taub *complex128 + if len(taub) > 0 { + _taub = &taub[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zggqrf_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(m), (C.lapack_int)(p), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_taua), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_taub), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggrqf.f. +func Sggrqf(m, p, n int, a []float32, lda int, taua, b []float32, ldb int, taub, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _taua *float32 + if len(taua) > 0 { + _taua = &taua[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _taub *float32 + if len(taub) > 0 { + _taub = &taub[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sggrqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_taua), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_taub), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggrqf.f. +func Dggrqf(m, p, n int, a []float64, lda int, taua, b []float64, ldb int, taub, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _taua *float64 + if len(taua) > 0 { + _taua = &taua[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _taub *float64 + if len(taub) > 0 { + _taub = &taub[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dggrqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_taua), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_taub), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggrqf.f. +func Cggrqf(m, p, n int, a []complex64, lda int, taua, b []complex64, ldb int, taub, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _taua *complex64 + if len(taua) > 0 { + _taua = &taua[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _taub *complex64 + if len(taub) > 0 { + _taub = &taub[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cggrqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_taua), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_taub), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggrqf.f. +func Zggrqf(m, p, n int, a []complex128, lda int, taua, b []complex128, ldb int, taub, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _taua *complex128 + if len(taua) > 0 { + _taua = &taua[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _taub *complex128 + if len(taub) > 0 { + _taub = &taub[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zggrqf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_taua), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_taub), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggsvd3.f. +func Sggsvd3(jobu, jobv, jobq lapack.Job, m, n, p int, k, l []int32, a []float32, lda int, b []float32, ldb int, alpha, beta, u []float32, ldu int, v []float32, ldv int, q []float32, ldq int, work []float32, lwork int, iwork []int32) bool { + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + var _l *int32 + if len(l) > 0 { + _l = &l[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *float32 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *float32 + if len(beta) > 0 { + _beta = &beta[0] + } + var _u *float32 + if len(u) > 0 { + _u = &u[0] + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sggsvd3_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(p), (*C.lapack_int)(_k), (*C.lapack_int)(_l), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_alpha), (*C.float)(_beta), (*C.float)(_u), (C.lapack_int)(ldu), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggsvd3.f. +func Dggsvd3(jobu, jobv, jobq lapack.Job, m, n, p int, k, l []int32, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int32) bool { + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + var _l *int32 + if len(l) > 0 { + _l = &l[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *float64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *float64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _u *float64 + if len(u) > 0 { + _u = &u[0] + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dggsvd3_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(p), (*C.lapack_int)(_k), (*C.lapack_int)(_l), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_alpha), (*C.double)(_beta), (*C.double)(_u), (C.lapack_int)(ldu), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggsvd3.f. +func Cggsvd3(jobu, jobv, jobq lapack.Job, m, n, p int, k, l []int32, a []complex64, lda int, b []complex64, ldb int, alpha, beta []float32, u []complex64, ldu int, v []complex64, ldv int, q []complex64, ldq int, work []complex64, lwork int, rwork []float32, iwork []int32) bool { + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + var _l *int32 + if len(l) > 0 { + _l = &l[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *float32 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *float32 + if len(beta) > 0 { + _beta = &beta[0] + } + var _u *complex64 + if len(u) > 0 { + _u = &u[0] + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cggsvd3_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(p), (*C.lapack_int)(_k), (*C.lapack_int)(_l), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.float)(_alpha), (*C.float)(_beta), (*C.lapack_complex_float)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggsvd3.f. +func Zggsvd3(jobu, jobv, jobq lapack.Job, m, n, p int, k, l []int32, a []complex128, lda int, b []complex128, ldb int, alpha, beta []float64, u []complex128, ldu int, v []complex128, ldv int, q []complex128, ldq int, work []complex128, lwork int, rwork []float64, iwork []int32) bool { + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + var _l *int32 + if len(l) > 0 { + _l = &l[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *float64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *float64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _u *complex128 + if len(u) > 0 { + _u = &u[0] + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zggsvd3_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(p), (*C.lapack_int)(_k), (*C.lapack_int)(_l), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.double)(_alpha), (*C.double)(_beta), (*C.lapack_complex_double)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sggsvp3.f. +func Sggsvp3(jobu, jobv, jobq lapack.Job, m, p, n int, a []float32, lda int, b []float32, ldb int, tola, tolb float32, k, l []int32, u []float32, ldu int, v []float32, ldv int, q []float32, ldq int, iwork []int32, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + var _l *int32 + if len(l) > 0 { + _l = &l[0] + } + var _u *float32 + if len(u) > 0 { + _u = &u[0] + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sggsvp3_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (C.float)(tola), (C.float)(tolb), (*C.lapack_int)(_k), (*C.lapack_int)(_l), (*C.float)(_u), (C.lapack_int)(ldu), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_q), (C.lapack_int)(ldq), (*C.lapack_int)(_iwork), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggsvp3.f. +func Dggsvp3(jobu, jobv, jobq lapack.Job, m, p, n int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, k, l []int32, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, iwork []int32, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + var _l *int32 + if len(l) > 0 { + _l = &l[0] + } + var _u *float64 + if len(u) > 0 { + _u = &u[0] + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dggsvp3_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (C.double)(tola), (C.double)(tolb), (*C.lapack_int)(_k), (*C.lapack_int)(_l), (*C.double)(_u), (C.lapack_int)(ldu), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_q), (C.lapack_int)(ldq), (*C.lapack_int)(_iwork), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cggsvp3.f. +func Cggsvp3(jobu, jobv, jobq lapack.Job, m, p, n int, a []complex64, lda int, b []complex64, ldb int, tola, tolb float32, k, l []int32, u []complex64, ldu int, v []complex64, ldv int, q []complex64, ldq int, iwork []int32, rwork []float32, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + var _l *int32 + if len(l) > 0 { + _l = &l[0] + } + var _u *complex64 + if len(u) > 0 { + _u = &u[0] + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cggsvp3_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (C.float)(tola), (C.float)(tolb), (*C.lapack_int)(_k), (*C.lapack_int)(_l), (*C.lapack_complex_float)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_int)(_iwork), (*C.float)(_rwork), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zggsvp3.f. +func Zggsvp3(jobu, jobv, jobq lapack.Job, m, p, n int, a []complex128, lda int, b []complex128, ldb int, tola, tolb float64, k, l []int32, u []complex128, ldu int, v []complex128, ldv int, q []complex128, ldq int, iwork []int32, rwork []float64, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + var _l *int32 + if len(l) > 0 { + _l = &l[0] + } + var _u *complex128 + if len(u) > 0 { + _u = &u[0] + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zggsvp3_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (C.double)(tola), (C.double)(tolb), (*C.lapack_int)(_k), (*C.lapack_int)(_l), (*C.lapack_complex_double)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_int)(_iwork), (*C.double)(_rwork), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgtcon.f. +func Sgtcon(norm byte, n int, dl, d, du, du2 []float32, ipiv []int32, anorm float32, rcond, work []float32, iwork []int32) bool { + var _dl *float32 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _du *float32 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *float32 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgtcon_work((C.char)(norm), (C.lapack_int)(n), (*C.float)(_dl), (*C.float)(_d), (*C.float)(_du), (*C.float)(_du2), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgtcon.f. +func Dgtcon(norm byte, n int, dl, d, du, du2 []float64, ipiv []int32, anorm float64, rcond, work []float64, iwork []int32) bool { + var _dl *float64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _du *float64 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *float64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgtcon_work((C.char)(norm), (C.lapack_int)(n), (*C.double)(_dl), (*C.double)(_d), (*C.double)(_du), (*C.double)(_du2), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgtcon.f. +func Cgtcon(norm byte, n int, dl, d, du, du2 []complex64, ipiv []int32, anorm float32, rcond []float32, work []complex64) bool { + var _dl *complex64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex64 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex64 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *complex64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgtcon_work((C.char)(norm), (C.lapack_int)(n), (*C.lapack_complex_float)(_dl), (*C.lapack_complex_float)(_d), (*C.lapack_complex_float)(_du), (*C.lapack_complex_float)(_du2), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgtcon.f. +func Zgtcon(norm byte, n int, dl, d, du, du2 []complex128, ipiv []int32, anorm float64, rcond []float64, work []complex128) bool { + var _dl *complex128 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex128 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex128 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *complex128 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgtcon_work((C.char)(norm), (C.lapack_int)(n), (*C.lapack_complex_double)(_dl), (*C.lapack_complex_double)(_d), (*C.lapack_complex_double)(_du), (*C.lapack_complex_double)(_du2), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgtrfs.f. +func Sgtrfs(trans blas.Transpose, n, nrhs int, dl, d, du, dlf, df, duf, du2 []float32, ipiv []int32, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *float32 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _du *float32 + if len(du) > 0 { + _du = &du[0] + } + var _dlf *float32 + if len(dlf) > 0 { + _dlf = &dlf[0] + } + var _df *float32 + if len(df) > 0 { + _df = &df[0] + } + var _duf *float32 + if len(duf) > 0 { + _duf = &duf[0] + } + var _du2 *float32 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgtrfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_dl), (*C.float)(_d), (*C.float)(_du), (*C.float)(_dlf), (*C.float)(_df), (*C.float)(_duf), (*C.float)(_du2), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgtrfs.f. +func Dgtrfs(trans blas.Transpose, n, nrhs int, dl, d, du, dlf, df, duf, du2 []float64, ipiv []int32, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *float64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _du *float64 + if len(du) > 0 { + _du = &du[0] + } + var _dlf *float64 + if len(dlf) > 0 { + _dlf = &dlf[0] + } + var _df *float64 + if len(df) > 0 { + _df = &df[0] + } + var _duf *float64 + if len(duf) > 0 { + _duf = &duf[0] + } + var _du2 *float64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgtrfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_dl), (*C.double)(_d), (*C.double)(_du), (*C.double)(_dlf), (*C.double)(_df), (*C.double)(_duf), (*C.double)(_du2), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgtrfs.f. +func Cgtrfs(trans blas.Transpose, n, nrhs int, dl, d, du, dlf, df, duf, du2 []complex64, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *complex64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex64 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex64 + if len(du) > 0 { + _du = &du[0] + } + var _dlf *complex64 + if len(dlf) > 0 { + _dlf = &dlf[0] + } + var _df *complex64 + if len(df) > 0 { + _df = &df[0] + } + var _duf *complex64 + if len(duf) > 0 { + _duf = &duf[0] + } + var _du2 *complex64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgtrfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_dl), (*C.lapack_complex_float)(_d), (*C.lapack_complex_float)(_du), (*C.lapack_complex_float)(_dlf), (*C.lapack_complex_float)(_df), (*C.lapack_complex_float)(_duf), (*C.lapack_complex_float)(_du2), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgtrfs.f. +func Zgtrfs(trans blas.Transpose, n, nrhs int, dl, d, du, dlf, df, duf, du2 []complex128, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *complex128 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex128 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex128 + if len(du) > 0 { + _du = &du[0] + } + var _dlf *complex128 + if len(dlf) > 0 { + _dlf = &dlf[0] + } + var _df *complex128 + if len(df) > 0 { + _df = &df[0] + } + var _duf *complex128 + if len(duf) > 0 { + _duf = &duf[0] + } + var _du2 *complex128 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgtrfs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_dl), (*C.lapack_complex_double)(_d), (*C.lapack_complex_double)(_du), (*C.lapack_complex_double)(_dlf), (*C.lapack_complex_double)(_df), (*C.lapack_complex_double)(_duf), (*C.lapack_complex_double)(_du2), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgtsv.f. +func Sgtsv(n, nrhs int, dl, d, du, b []float32, ldb int) bool { + var _dl *float32 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _du *float32 + if len(du) > 0 { + _du = &du[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sgtsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_dl), (*C.float)(_d), (*C.float)(_du), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgtsv.f. +func Dgtsv(n, nrhs int, dl, d, du, b []float64, ldb int) bool { + var _dl *float64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _du *float64 + if len(du) > 0 { + _du = &du[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dgtsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_dl), (*C.double)(_d), (*C.double)(_du), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgtsv.f. +func Cgtsv(n, nrhs int, dl, d, du, b []complex64, ldb int) bool { + var _dl *complex64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex64 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex64 + if len(du) > 0 { + _du = &du[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cgtsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_dl), (*C.lapack_complex_float)(_d), (*C.lapack_complex_float)(_du), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgtsv.f. +func Zgtsv(n, nrhs int, dl, d, du, b []complex128, ldb int) bool { + var _dl *complex128 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex128 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex128 + if len(du) > 0 { + _du = &du[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zgtsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_dl), (*C.lapack_complex_double)(_d), (*C.lapack_complex_double)(_du), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgtsvx.f. +func Sgtsvx(fact byte, trans blas.Transpose, n, nrhs int, dl, d, du, dlf, df, duf, du2 []float32, ipiv []int32, b []float32, ldb int, x []float32, ldx int, rcond, ferr, berr, work []float32, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *float32 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _du *float32 + if len(du) > 0 { + _du = &du[0] + } + var _dlf *float32 + if len(dlf) > 0 { + _dlf = &dlf[0] + } + var _df *float32 + if len(df) > 0 { + _df = &df[0] + } + var _duf *float32 + if len(duf) > 0 { + _duf = &duf[0] + } + var _du2 *float32 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sgtsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_dl), (*C.float)(_d), (*C.float)(_du), (*C.float)(_dlf), (*C.float)(_df), (*C.float)(_duf), (*C.float)(_du2), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgtsvx.f. +func Dgtsvx(fact byte, trans blas.Transpose, n, nrhs int, dl, d, du, dlf, df, duf, du2 []float64, ipiv []int32, b []float64, ldb int, x []float64, ldx int, rcond, ferr, berr, work []float64, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *float64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _du *float64 + if len(du) > 0 { + _du = &du[0] + } + var _dlf *float64 + if len(dlf) > 0 { + _dlf = &dlf[0] + } + var _df *float64 + if len(df) > 0 { + _df = &df[0] + } + var _duf *float64 + if len(duf) > 0 { + _duf = &duf[0] + } + var _du2 *float64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dgtsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_dl), (*C.double)(_d), (*C.double)(_du), (*C.double)(_dlf), (*C.double)(_df), (*C.double)(_duf), (*C.double)(_du2), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgtsvx.f. +func Cgtsvx(fact byte, trans blas.Transpose, n, nrhs int, dl, d, du, dlf, df, duf, du2 []complex64, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *complex64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex64 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex64 + if len(du) > 0 { + _du = &du[0] + } + var _dlf *complex64 + if len(dlf) > 0 { + _dlf = &dlf[0] + } + var _df *complex64 + if len(df) > 0 { + _df = &df[0] + } + var _duf *complex64 + if len(duf) > 0 { + _duf = &duf[0] + } + var _du2 *complex64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cgtsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_dl), (*C.lapack_complex_float)(_d), (*C.lapack_complex_float)(_du), (*C.lapack_complex_float)(_dlf), (*C.lapack_complex_float)(_df), (*C.lapack_complex_float)(_duf), (*C.lapack_complex_float)(_du2), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgtsvx.f. +func Zgtsvx(fact byte, trans blas.Transpose, n, nrhs int, dl, d, du, dlf, df, duf, du2 []complex128, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *complex128 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex128 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex128 + if len(du) > 0 { + _du = &du[0] + } + var _dlf *complex128 + if len(dlf) > 0 { + _dlf = &dlf[0] + } + var _df *complex128 + if len(df) > 0 { + _df = &df[0] + } + var _duf *complex128 + if len(duf) > 0 { + _duf = &duf[0] + } + var _du2 *complex128 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zgtsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_dl), (*C.lapack_complex_double)(_d), (*C.lapack_complex_double)(_du), (*C.lapack_complex_double)(_dlf), (*C.lapack_complex_double)(_df), (*C.lapack_complex_double)(_duf), (*C.lapack_complex_double)(_du2), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgttrf.f. +func Sgttrf(n int, dl, d, du, du2 []float32, ipiv []int32) bool { + var _dl *float32 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _du *float32 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *float32 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_sgttrf_work((C.lapack_int)(n), (*C.float)(_dl), (*C.float)(_d), (*C.float)(_du), (*C.float)(_du2), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgttrf.f. +func Dgttrf(n int, dl, d, du, du2 []float64, ipiv []int32) bool { + var _dl *float64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _du *float64 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *float64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_dgttrf_work((C.lapack_int)(n), (*C.double)(_dl), (*C.double)(_d), (*C.double)(_du), (*C.double)(_du2), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgttrf.f. +func Cgttrf(n int, dl, d, du, du2 []complex64, ipiv []int32) bool { + var _dl *complex64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex64 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex64 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *complex64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_cgttrf_work((C.lapack_int)(n), (*C.lapack_complex_float)(_dl), (*C.lapack_complex_float)(_d), (*C.lapack_complex_float)(_du), (*C.lapack_complex_float)(_du2), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgttrf.f. +func Zgttrf(n int, dl, d, du, du2 []complex128, ipiv []int32) bool { + var _dl *complex128 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex128 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex128 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *complex128 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_zgttrf_work((C.lapack_int)(n), (*C.lapack_complex_double)(_dl), (*C.lapack_complex_double)(_d), (*C.lapack_complex_double)(_du), (*C.lapack_complex_double)(_du2), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgttrs.f. +func Sgttrs(trans blas.Transpose, n, nrhs int, dl, d, du, du2 []float32, ipiv []int32, b []float32, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *float32 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _du *float32 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *float32 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sgttrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_dl), (*C.float)(_d), (*C.float)(_du), (*C.float)(_du2), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgttrs.f. +func Dgttrs(trans blas.Transpose, n, nrhs int, dl, d, du, du2 []float64, ipiv []int32, b []float64, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *float64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _du *float64 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *float64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dgttrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_dl), (*C.double)(_d), (*C.double)(_du), (*C.double)(_du2), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgttrs.f. +func Cgttrs(trans blas.Transpose, n, nrhs int, dl, d, du, du2 []complex64, ipiv []int32, b []complex64, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *complex64 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex64 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex64 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *complex64 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cgttrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_dl), (*C.lapack_complex_float)(_d), (*C.lapack_complex_float)(_du), (*C.lapack_complex_float)(_du2), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgttrs.f. +func Zgttrs(trans blas.Transpose, n, nrhs int, dl, d, du, du2 []complex128, ipiv []int32, b []complex128, ldb int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _dl *complex128 + if len(dl) > 0 { + _dl = &dl[0] + } + var _d *complex128 + if len(d) > 0 { + _d = &d[0] + } + var _du *complex128 + if len(du) > 0 { + _du = &du[0] + } + var _du2 *complex128 + if len(du2) > 0 { + _du2 = &du2[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zgttrs_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_dl), (*C.lapack_complex_double)(_d), (*C.lapack_complex_double)(_du), (*C.lapack_complex_double)(_du2), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chbev.f. +func Chbev(jobz lapack.Job, ul blas.Uplo, n, kd int, ab []complex64, ldab int, w []float32, z []complex64, ldz int, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chbev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhbev.f. +func Zhbev(jobz lapack.Job, ul blas.Uplo, n, kd int, ab []complex128, ldab int, w []float64, z []complex128, ldz int, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhbev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chbevd.f. +func Chbevd(jobz lapack.Job, ul blas.Uplo, n, kd int, ab []complex64, ldab int, w []float32, z []complex64, ldz int, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_chbevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhbevd.f. +func Zhbevd(jobz lapack.Job, ul blas.Uplo, n, kd int, ab []complex128, ldab int, w []float64, z []complex128, ldz int, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zhbevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chbevx.f. +func Chbevx(jobz lapack.Job, rng byte, ul blas.Uplo, n, kd int, ab []complex64, ldab int, q []complex64, ldq int, vl, vu float32, il, iu int, abstol float32, m []int32, w []float32, z []complex64, ldz int, work []complex64, rwork []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_chbevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (*C.float)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhbevx.f. +func Zhbevx(jobz lapack.Job, rng byte, ul blas.Uplo, n, kd int, ab []complex128, ldab int, q []complex128, ldq int, vl, vu float64, il, iu int, abstol float64, m []int32, w []float64, z []complex128, ldz int, work []complex128, rwork []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_zhbevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (*C.double)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chbgst.f. +func Chbgst(vect byte, ul blas.Uplo, n, ka, kb int, ab []complex64, ldab int, bb []complex64, ldbb int, x []complex64, ldx int, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *complex64 + if len(bb) > 0 { + _bb = &bb[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chbgst_work((C.int)(rowMajor), (C.char)(vect), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_bb), (C.lapack_int)(ldbb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhbgst.f. +func Zhbgst(vect byte, ul blas.Uplo, n, ka, kb int, ab []complex128, ldab int, bb []complex128, ldbb int, x []complex128, ldx int, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *complex128 + if len(bb) > 0 { + _bb = &bb[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhbgst_work((C.int)(rowMajor), (C.char)(vect), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_bb), (C.lapack_int)(ldbb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chbgv.f. +func Chbgv(jobz lapack.Job, ul blas.Uplo, n, ka, kb int, ab []complex64, ldab int, bb []complex64, ldbb int, w []float32, z []complex64, ldz int, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *complex64 + if len(bb) > 0 { + _bb = &bb[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chbgv_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_bb), (C.lapack_int)(ldbb), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhbgv.f. +func Zhbgv(jobz lapack.Job, ul blas.Uplo, n, ka, kb int, ab []complex128, ldab int, bb []complex128, ldbb int, w []float64, z []complex128, ldz int, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *complex128 + if len(bb) > 0 { + _bb = &bb[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhbgv_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_bb), (C.lapack_int)(ldbb), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chbgvd.f. +func Chbgvd(jobz lapack.Job, ul blas.Uplo, n, ka, kb int, ab []complex64, ldab int, bb []complex64, ldbb int, w []float32, z []complex64, ldz int, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *complex64 + if len(bb) > 0 { + _bb = &bb[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_chbgvd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_bb), (C.lapack_int)(ldbb), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhbgvd.f. +func Zhbgvd(jobz lapack.Job, ul blas.Uplo, n, ka, kb int, ab []complex128, ldab int, bb []complex128, ldbb int, w []float64, z []complex128, ldz int, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *complex128 + if len(bb) > 0 { + _bb = &bb[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zhbgvd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_bb), (C.lapack_int)(ldbb), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chbgvx.f. +func Chbgvx(jobz lapack.Job, rng byte, ul blas.Uplo, n, ka, kb int, ab []complex64, ldab int, bb []complex64, ldbb int, q []complex64, ldq int, vl, vu float32, il, iu int, abstol float32, m []int32, w []float32, z []complex64, ldz int, work []complex64, rwork []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *complex64 + if len(bb) > 0 { + _bb = &bb[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_chbgvx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_bb), (C.lapack_int)(ldbb), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (*C.float)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhbgvx.f. +func Zhbgvx(jobz lapack.Job, rng byte, ul blas.Uplo, n, ka, kb int, ab []complex128, ldab int, bb []complex128, ldbb int, q []complex128, ldq int, vl, vu float64, il, iu int, abstol float64, m []int32, w []float64, z []complex128, ldz int, work []complex128, rwork []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *complex128 + if len(bb) > 0 { + _bb = &bb[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_zhbgvx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_bb), (C.lapack_int)(ldbb), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (*C.double)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chbtrd.f. +func Chbtrd(vect byte, ul blas.Uplo, n, kd int, ab []complex64, ldab int, d, e []float32, q []complex64, ldq int, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chbtrd_work((C.int)(rowMajor), (C.char)(vect), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.float)(_d), (*C.float)(_e), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhbtrd.f. +func Zhbtrd(vect byte, ul blas.Uplo, n, kd int, ab []complex128, ldab int, d, e []float64, q []complex128, ldq int, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhbtrd_work((C.int)(rowMajor), (C.char)(vect), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.double)(_d), (*C.double)(_e), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/checon.f. +func Checon(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, anorm float32, rcond []float32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_checon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhecon.f. +func Zhecon(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, anorm float64, rcond []float64, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhecon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cheequb.f. +func Cheequb(ul blas.Uplo, n int, a []complex64, lda int, s, scond, amax []float32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cheequb_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zheequb.f. +func Zheequb(ul blas.Uplo, n int, a []complex128, lda int, s, scond, amax []float64, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zheequb_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cheev.f. +func Cheev(jobz lapack.Job, ul blas.Uplo, n int, a []complex64, lda int, w []float32, work []complex64, lwork int, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cheev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_w), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zheev.f. +func Zheev(jobz lapack.Job, ul blas.Uplo, n int, a []complex128, lda int, w []float64, work []complex128, lwork int, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zheev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_w), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cheevd.f. +func Cheevd(jobz lapack.Job, ul blas.Uplo, n int, a []complex64, lda int, w []float32, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cheevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_w), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zheevd.f. +func Zheevd(jobz lapack.Job, ul blas.Uplo, n int, a []complex128, lda int, w []float64, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zheevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_w), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cheevr.f. +func Cheevr(jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []complex64, lda int, vl, vu float32, il, iu int, abstol float32, m []int32, w []float32, z []complex64, ldz int, isuppz []int32, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cheevr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zheevr.f. +func Zheevr(jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []complex128, lda int, vl, vu float64, il, iu int, abstol float64, m []int32, w []float64, z []complex128, ldz int, isuppz []int32, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zheevr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cheevx.f. +func Cheevx(jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []complex64, lda int, vl, vu float32, il, iu int, abstol float32, m []int32, w []float32, z []complex64, ldz int, work []complex64, lwork int, rwork []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_cheevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zheevx.f. +func Zheevx(jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []complex128, lda int, vl, vu float64, il, iu int, abstol float64, m []int32, w []float64, z []complex128, ldz int, work []complex128, lwork int, rwork []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_zheevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chegst.f. +func Chegst(itype int, ul blas.Uplo, n int, a []complex64, lda int, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_chegst_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhegst.f. +func Zhegst(itype int, ul blas.Uplo, n int, a []complex128, lda int, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zhegst_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chegv.f. +func Chegv(itype int, jobz lapack.Job, ul blas.Uplo, n int, a []complex64, lda int, b []complex64, ldb int, w []float32, work []complex64, lwork int, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chegv_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.float)(_w), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhegv.f. +func Zhegv(itype int, jobz lapack.Job, ul blas.Uplo, n int, a []complex128, lda int, b []complex128, ldb int, w []float64, work []complex128, lwork int, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhegv_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.double)(_w), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chegvd.f. +func Chegvd(itype int, jobz lapack.Job, ul blas.Uplo, n int, a []complex64, lda int, b []complex64, ldb int, w []float32, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_chegvd_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.float)(_w), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhegvd.f. +func Zhegvd(itype int, jobz lapack.Job, ul blas.Uplo, n int, a []complex128, lda int, b []complex128, ldb int, w []float64, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zhegvd_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.double)(_w), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chegvx.f. +func Chegvx(itype int, jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []complex64, lda int, b []complex64, ldb int, vl, vu float32, il, iu int, abstol float32, m []int32, w []float32, z []complex64, ldz int, work []complex64, lwork int, rwork []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_chegvx_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhegvx.f. +func Zhegvx(itype int, jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []complex128, lda int, b []complex128, ldb int, vl, vu float64, il, iu int, abstol float64, m []int32, w []float64, z []complex128, ldz int, work []complex128, lwork int, rwork []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_zhegvx_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cherfs.f. +func Cherfs(ul blas.Uplo, n, nrhs int, a []complex64, lda int, af []complex64, ldaf int, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cherfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zherfs.f. +func Zherfs(ul blas.Uplo, n, nrhs int, a []complex128, lda int, af []complex128, ldaf int, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex128 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zherfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chesv.f. +func Chesv(ul blas.Uplo, n, nrhs int, a []complex64, lda int, ipiv []int32, b []complex64, ldb int, work []complex64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chesv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhesv.f. +func Zhesv(ul blas.Uplo, n, nrhs int, a []complex128, lda int, ipiv []int32, b []complex128, ldb int, work []complex128, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhesv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chesvx.f. +func Chesvx(fact byte, ul blas.Uplo, n, nrhs int, a []complex64, lda int, af []complex64, ldaf int, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, lwork int, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chesvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhesvx.f. +func Zhesvx(fact byte, ul blas.Uplo, n, nrhs int, a []complex128, lda int, af []complex128, ldaf int, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, lwork int, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex128 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhesvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetrd.f. +func Chetrd(ul blas.Uplo, n int, a []complex64, lda int, d, e []float32, tau, work []complex64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chetrd_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_d), (*C.float)(_e), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetrd.f. +func Zhetrd(ul blas.Uplo, n int, a []complex128, lda int, d, e []float64, tau, work []complex128, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhetrd_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_d), (*C.double)(_e), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetrf.f. +func Chetrf(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, work []complex64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chetrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetrf.f. +func Zhetrf(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, work []complex128, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhetrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetri.f. +func Chetri(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chetri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetri.f. +func Zhetri(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhetri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetrs.f. +func Chetrs(ul blas.Uplo, n, nrhs int, a []complex64, lda int, ipiv []int32, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_chetrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetrs.f. +func Zhetrs(ul blas.Uplo, n, nrhs int, a []complex128, lda int, ipiv []int32, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zhetrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chfrk.f. +func Chfrk(transr blas.Transpose, ul blas.Uplo, trans blas.Transpose, n, k int, alpha float32, a []complex64, lda int, beta float32, c []complex64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + return isZero(C.LAPACKE_chfrk_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(k), (C.float)(alpha), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (C.float)(beta), (*C.lapack_complex_float)(_c))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhfrk.f. +func Zhfrk(transr blas.Transpose, ul blas.Uplo, trans blas.Transpose, n, k int, alpha float64, a []complex128, lda int, beta float64, c []complex128) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + return isZero(C.LAPACKE_zhfrk_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(k), (C.double)(alpha), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (C.double)(beta), (*C.lapack_complex_double)(_c))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/shgeqz.f. +func Shgeqz(job lapack.Job, compq, compz lapack.Comp, n, ilo, ihi int, h []float32, ldh int, t []float32, ldt int, alphar, alphai, beta, q []float32, ldq int, z []float32, ldz int, work []float32, lwork int) bool { + var _h *float32 + if len(h) > 0 { + _h = &h[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _alphar *float32 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float32 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float32 + if len(beta) > 0 { + _beta = &beta[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_shgeqz_work((C.int)(rowMajor), (C.char)(job), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_h), (C.lapack_int)(ldh), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_alphar), (*C.float)(_alphai), (*C.float)(_beta), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dhgeqz.f. +func Dhgeqz(job lapack.Job, compq, compz lapack.Comp, n, ilo, ihi int, h []float64, ldh int, t []float64, ldt int, alphar, alphai, beta, q []float64, ldq int, z []float64, ldz int, work []float64, lwork int) bool { + var _h *float64 + if len(h) > 0 { + _h = &h[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _alphar *float64 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float64 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dhgeqz_work((C.int)(rowMajor), (C.char)(job), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_h), (C.lapack_int)(ldh), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_alphar), (*C.double)(_alphai), (*C.double)(_beta), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chgeqz.f. +func Chgeqz(job lapack.Job, compq, compz lapack.Comp, n, ilo, ihi int, h []complex64, ldh int, t []complex64, ldt int, alpha, beta, q []complex64, ldq int, z []complex64, ldz int, work []complex64, lwork int, rwork []float32) bool { + var _h *complex64 + if len(h) > 0 { + _h = &h[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _alpha *complex64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chgeqz_work((C.int)(rowMajor), (C.char)(job), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_float)(_h), (C.lapack_int)(ldh), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_alpha), (*C.lapack_complex_float)(_beta), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhgeqz.f. +func Zhgeqz(job lapack.Job, compq, compz lapack.Comp, n, ilo, ihi int, h []complex128, ldh int, t []complex128, ldt int, alpha, beta, q []complex128, ldq int, z []complex128, ldz int, work []complex128, lwork int, rwork []float64) bool { + var _h *complex128 + if len(h) > 0 { + _h = &h[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _alpha *complex128 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex128 + if len(beta) > 0 { + _beta = &beta[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhgeqz_work((C.int)(rowMajor), (C.char)(job), (C.char)(compq), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_double)(_h), (C.lapack_int)(ldh), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_alpha), (*C.lapack_complex_double)(_beta), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpcon.f. +func Chpcon(ul blas.Uplo, n int, ap []complex64, ipiv []int32, anorm float32, rcond []float32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chpcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpcon.f. +func Zhpcon(ul blas.Uplo, n int, ap []complex128, ipiv []int32, anorm float64, rcond []float64, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhpcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpev.f. +func Chpev(jobz lapack.Job, ul blas.Uplo, n int, ap []complex64, w []float32, z []complex64, ldz int, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chpev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpev.f. +func Zhpev(jobz lapack.Job, ul blas.Uplo, n int, ap []complex128, w []float64, z []complex128, ldz int, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhpev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpevd.f. +func Chpevd(jobz lapack.Job, ul blas.Uplo, n int, ap []complex64, w []float32, z []complex64, ldz int, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_chpevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpevd.f. +func Zhpevd(jobz lapack.Job, ul blas.Uplo, n int, ap []complex128, w []float64, z []complex128, ldz int, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zhpevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpevx.f. +func Chpevx(jobz lapack.Job, rng byte, ul blas.Uplo, n int, ap []complex64, vl, vu float32, il, iu int, abstol float32, m []int32, w []float32, z []complex64, ldz int, work []complex64, rwork []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_chpevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (*C.float)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpevx.f. +func Zhpevx(jobz lapack.Job, rng byte, ul blas.Uplo, n int, ap []complex128, vl, vu float64, il, iu int, abstol float64, m []int32, w []float64, z []complex128, ldz int, work []complex128, rwork []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_zhpevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (*C.double)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpgst.f. +func Chpgst(itype int, ul blas.Uplo, n int, ap, bp []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *complex64 + if len(bp) > 0 { + _bp = &bp[0] + } + return isZero(C.LAPACKE_chpgst_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_bp))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpgst.f. +func Zhpgst(itype int, ul blas.Uplo, n int, ap, bp []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *complex128 + if len(bp) > 0 { + _bp = &bp[0] + } + return isZero(C.LAPACKE_zhpgst_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_bp))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpgv.f. +func Chpgv(itype int, jobz lapack.Job, ul blas.Uplo, n int, ap, bp []complex64, w []float32, z []complex64, ldz int, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *complex64 + if len(bp) > 0 { + _bp = &bp[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chpgv_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_bp), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpgv.f. +func Zhpgv(itype int, jobz lapack.Job, ul blas.Uplo, n int, ap, bp []complex128, w []float64, z []complex128, ldz int, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *complex128 + if len(bp) > 0 { + _bp = &bp[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhpgv_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_bp), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpgvd.f. +func Chpgvd(itype int, jobz lapack.Job, ul blas.Uplo, n int, ap, bp []complex64, w []float32, z []complex64, ldz int, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *complex64 + if len(bp) > 0 { + _bp = &bp[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_chpgvd_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_bp), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpgvd.f. +func Zhpgvd(itype int, jobz lapack.Job, ul blas.Uplo, n int, ap, bp []complex128, w []float64, z []complex128, ldz int, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *complex128 + if len(bp) > 0 { + _bp = &bp[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zhpgvd_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_bp), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpgvx.f. +func Chpgvx(itype int, jobz lapack.Job, rng byte, ul blas.Uplo, n int, ap, bp []complex64, vl, vu float32, il, iu int, abstol float32, m []int32, w []float32, z []complex64, ldz int, work []complex64, rwork []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *complex64 + if len(bp) > 0 { + _bp = &bp[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_chpgvx_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_bp), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (*C.float)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpgvx.f. +func Zhpgvx(itype int, jobz lapack.Job, rng byte, ul blas.Uplo, n int, ap, bp []complex128, vl, vu float64, il, iu int, abstol float64, m []int32, w []float64, z []complex128, ldz int, work []complex128, rwork []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *complex128 + if len(bp) > 0 { + _bp = &bp[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_zhpgvx_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_bp), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (*C.double)(_rwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chprfs.f. +func Chprfs(ul blas.Uplo, n, nrhs int, ap, afp []complex64, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_afp), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhprfs.f. +func Zhprfs(ul blas.Uplo, n, nrhs int, ap, afp []complex128, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex128 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_afp), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpsv.f. +func Chpsv(ul blas.Uplo, n, nrhs int, ap []complex64, ipiv []int32, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_chpsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpsv.f. +func Zhpsv(ul blas.Uplo, n, nrhs int, ap []complex128, ipiv []int32, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zhpsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chpsvx.f. +func Chpsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []complex64, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_chpsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_afp), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhpsvx.f. +func Zhpsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []complex128, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex128 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zhpsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_afp), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chptrd.f. +func Chptrd(ul blas.Uplo, n int, ap []complex64, d, e []float32, tau []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + return isZero(C.LAPACKE_chptrd_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.float)(_d), (*C.float)(_e), (*C.lapack_complex_float)(_tau))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhptrd.f. +func Zhptrd(ul blas.Uplo, n int, ap []complex128, d, e []float64, tau []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + return isZero(C.LAPACKE_zhptrd_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.double)(_d), (*C.double)(_e), (*C.lapack_complex_double)(_tau))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chptrf.f. +func Chptrf(ul blas.Uplo, n int, ap []complex64, ipiv []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_chptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhptrf.f. +func Zhptrf(ul blas.Uplo, n int, ap []complex128, ipiv []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_zhptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chptri.f. +func Chptri(ul blas.Uplo, n int, ap []complex64, ipiv []int32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhptri.f. +func Zhptri(ul blas.Uplo, n int, ap []complex128, ipiv []int32, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chptrs.f. +func Chptrs(ul blas.Uplo, n, nrhs int, ap []complex64, ipiv []int32, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_chptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhptrs.f. +func Zhptrs(ul blas.Uplo, n, nrhs int, ap []complex128, ipiv []int32, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zhptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/shsein.f. +func Shsein(job lapack.Job, eigsrc, initv byte, sel []int32, n int, h []float32, ldh int, wr, wi, vl []float32, ldvl int, vr []float32, ldvr, mm int, m []int32, work []float32, ifaill, ifailr []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _h *float32 + if len(h) > 0 { + _h = &h[0] + } + var _wr *float32 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float32 + if len(wi) > 0 { + _wi = &wi[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _ifaill *int32 + if len(ifaill) > 0 { + _ifaill = &ifaill[0] + } + var _ifailr *int32 + if len(ifailr) > 0 { + _ifailr = &ifailr[0] + } + return isZero(C.LAPACKE_shsein_work((C.int)(rowMajor), (C.char)(job), (C.char)(eigsrc), (C.char)(initv), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.float)(_h), (C.lapack_int)(ldh), (*C.float)(_wr), (*C.float)(_wi), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.float)(_work), (*C.lapack_int)(_ifaill), (*C.lapack_int)(_ifailr))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dhsein.f. +func Dhsein(job lapack.Job, eigsrc, initv byte, sel []int32, n int, h []float64, ldh int, wr, wi, vl []float64, ldvl int, vr []float64, ldvr, mm int, m []int32, work []float64, ifaill, ifailr []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _h *float64 + if len(h) > 0 { + _h = &h[0] + } + var _wr *float64 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float64 + if len(wi) > 0 { + _wi = &wi[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _ifaill *int32 + if len(ifaill) > 0 { + _ifaill = &ifaill[0] + } + var _ifailr *int32 + if len(ifailr) > 0 { + _ifailr = &ifailr[0] + } + return isZero(C.LAPACKE_dhsein_work((C.int)(rowMajor), (C.char)(job), (C.char)(eigsrc), (C.char)(initv), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.double)(_h), (C.lapack_int)(ldh), (*C.double)(_wr), (*C.double)(_wi), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.double)(_work), (*C.lapack_int)(_ifaill), (*C.lapack_int)(_ifailr))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chsein.f. +func Chsein(job lapack.Job, eigsrc, initv byte, sel []int32, n int, h []complex64, ldh int, w, vl []complex64, ldvl int, vr []complex64, ldvr, mm int, m []int32, work []complex64, rwork []float32, ifaill, ifailr []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _h *complex64 + if len(h) > 0 { + _h = &h[0] + } + var _w *complex64 + if len(w) > 0 { + _w = &w[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _ifaill *int32 + if len(ifaill) > 0 { + _ifaill = &ifaill[0] + } + var _ifailr *int32 + if len(ifailr) > 0 { + _ifailr = &ifailr[0] + } + return isZero(C.LAPACKE_chsein_work((C.int)(rowMajor), (C.char)(job), (C.char)(eigsrc), (C.char)(initv), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_float)(_h), (C.lapack_int)(ldh), (*C.lapack_complex_float)(_w), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_float)(_work), (*C.float)(_rwork), (*C.lapack_int)(_ifaill), (*C.lapack_int)(_ifailr))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhsein.f. +func Zhsein(job lapack.Job, eigsrc, initv byte, sel []int32, n int, h []complex128, ldh int, w, vl []complex128, ldvl int, vr []complex128, ldvr, mm int, m []int32, work []complex128, rwork []float64, ifaill, ifailr []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _h *complex128 + if len(h) > 0 { + _h = &h[0] + } + var _w *complex128 + if len(w) > 0 { + _w = &w[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _ifaill *int32 + if len(ifaill) > 0 { + _ifaill = &ifaill[0] + } + var _ifailr *int32 + if len(ifailr) > 0 { + _ifailr = &ifailr[0] + } + return isZero(C.LAPACKE_zhsein_work((C.int)(rowMajor), (C.char)(job), (C.char)(eigsrc), (C.char)(initv), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_double)(_h), (C.lapack_int)(ldh), (*C.lapack_complex_double)(_w), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_double)(_work), (*C.double)(_rwork), (*C.lapack_int)(_ifaill), (*C.lapack_int)(_ifailr))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/shseqr.f. +func Shseqr(job lapack.Job, compz lapack.Comp, n, ilo, ihi int, h []float32, ldh int, wr, wi, z []float32, ldz int, work []float32, lwork int) int { + var _h *float32 + if len(h) > 0 { + _h = &h[0] + } + var _wr *float32 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float32 + if len(wi) > 0 { + _wi = &wi[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return int(C.LAPACKE_shseqr_work((C.int)(rowMajor), (C.char)(job), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_h), (C.lapack_int)(ldh), (*C.float)(_wr), (*C.float)(_wi), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dhseqr.f. +func Dhseqr(job lapack.Job, compz lapack.Comp, n, ilo, ihi int, h []float64, ldh int, wr, wi, z []float64, ldz int, work []float64, lwork int) int { + var _h *float64 + if len(h) > 0 { + _h = &h[0] + } + var _wr *float64 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float64 + if len(wi) > 0 { + _wi = &wi[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return int(C.LAPACKE_dhseqr_work((C.int)(rowMajor), (C.char)(job), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_h), (C.lapack_int)(ldh), (*C.double)(_wr), (*C.double)(_wi), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chseqr.f. +func Chseqr(job lapack.Job, compz lapack.Comp, n, ilo, ihi int, h []complex64, ldh int, w, z []complex64, ldz int, work []complex64, lwork int) int { + var _h *complex64 + if len(h) > 0 { + _h = &h[0] + } + var _w *complex64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return int(C.LAPACKE_chseqr_work((C.int)(rowMajor), (C.char)(job), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_float)(_h), (C.lapack_int)(ldh), (*C.lapack_complex_float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhseqr.f. +func Zhseqr(job lapack.Job, compz lapack.Comp, n, ilo, ihi int, h []complex128, ldh int, w, z []complex128, ldz int, work []complex128, lwork int) int { + var _h *complex128 + if len(h) > 0 { + _h = &h[0] + } + var _w *complex128 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return int(C.LAPACKE_zhseqr_work((C.int)(rowMajor), (C.char)(job), (C.char)(compz), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_double)(_h), (C.lapack_int)(ldh), (*C.lapack_complex_double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clacgv.f. +func Clacgv(n int, x []complex64, incx int) bool { + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + return isZero(C.LAPACKE_clacgv_work((C.lapack_int)(n), (*C.lapack_complex_float)(_x), (C.lapack_int)(incx))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlacgv.f. +func Zlacgv(n int, x []complex128, incx int) bool { + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + return isZero(C.LAPACKE_zlacgv_work((C.lapack_int)(n), (*C.lapack_complex_double)(_x), (C.lapack_int)(incx))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slacn2.f. +func Slacn2(n int, v, x []float32, isgn []int32, est []float32, kase, isave []int32) bool { + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _isgn *int32 + if len(isgn) > 0 { + _isgn = &isgn[0] + } + var _est *float32 + if len(est) > 0 { + _est = &est[0] + } + var _kase *int32 + if len(kase) > 0 { + _kase = &kase[0] + } + var _isave *int32 + if len(isave) > 0 { + _isave = &isave[0] + } + return isZero(C.LAPACKE_slacn2_work((C.lapack_int)(n), (*C.float)(_v), (*C.float)(_x), (*C.lapack_int)(_isgn), (*C.float)(_est), (*C.lapack_int)(_kase), (*C.lapack_int)(_isave))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlacn2.f. +func Dlacn2(n int, v, x []float64, isgn []int32, est []float64, kase, isave []int32) bool { + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _isgn *int32 + if len(isgn) > 0 { + _isgn = &isgn[0] + } + var _est *float64 + if len(est) > 0 { + _est = &est[0] + } + var _kase *int32 + if len(kase) > 0 { + _kase = &kase[0] + } + var _isave *int32 + if len(isave) > 0 { + _isave = &isave[0] + } + return isZero(C.LAPACKE_dlacn2_work((C.lapack_int)(n), (*C.double)(_v), (*C.double)(_x), (*C.lapack_int)(_isgn), (*C.double)(_est), (*C.lapack_int)(_kase), (*C.lapack_int)(_isave))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clacn2.f. +func Clacn2(n int, v, x []complex64, est []float32, kase, isave []int32) bool { + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _est *float32 + if len(est) > 0 { + _est = &est[0] + } + var _kase *int32 + if len(kase) > 0 { + _kase = &kase[0] + } + var _isave *int32 + if len(isave) > 0 { + _isave = &isave[0] + } + return isZero(C.LAPACKE_clacn2_work((C.lapack_int)(n), (*C.lapack_complex_float)(_v), (*C.lapack_complex_float)(_x), (*C.float)(_est), (*C.lapack_int)(_kase), (*C.lapack_int)(_isave))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlacn2.f. +func Zlacn2(n int, v, x []complex128, est []float64, kase, isave []int32) bool { + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _est *float64 + if len(est) > 0 { + _est = &est[0] + } + var _kase *int32 + if len(kase) > 0 { + _kase = &kase[0] + } + var _isave *int32 + if len(isave) > 0 { + _isave = &isave[0] + } + return isZero(C.LAPACKE_zlacn2_work((C.lapack_int)(n), (*C.lapack_complex_double)(_v), (*C.lapack_complex_double)(_x), (*C.double)(_est), (*C.lapack_int)(_kase), (*C.lapack_int)(_isave))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slacpy.f. +func Slacpy(ul blas.Uplo, m, n int, a []float32, lda int, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + ul = 'A' + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_slacpy_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlacpy.f. +func Dlacpy(ul blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + ul = 'A' + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dlacpy_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clacpy.f. +func Clacpy(ul blas.Uplo, m, n int, a []complex64, lda int, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + ul = 'A' + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_clacpy_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlacpy.f. +func Zlacpy(ul blas.Uplo, m, n int, a []complex128, lda int, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + ul = 'A' + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zlacpy_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clacp2.f. +func Clacp2(ul blas.Uplo, m, n int, a []float32, lda int, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_clacp2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlacp2.f. +func Zlacp2(ul blas.Uplo, m, n int, a []float64, lda int, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zlacp2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlag2c.f. +func Zlag2c(m, n int, a []complex128, lda int, sa []complex64, ldsa int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _sa *complex64 + if len(sa) > 0 { + _sa = &sa[0] + } + return isZero(C.LAPACKE_zlag2c_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_sa), (C.lapack_int)(ldsa))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slag2d.f. +func Slag2d(m, n int, sa []float32, ldsa int, a []float64, lda int) bool { + var _sa *float32 + if len(sa) > 0 { + _sa = &sa[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_slag2d_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_sa), (C.lapack_int)(ldsa), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlag2s.f. +func Dlag2s(m, n int, a []float64, lda int, sa []float32, ldsa int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _sa *float32 + if len(sa) > 0 { + _sa = &sa[0] + } + return isZero(C.LAPACKE_dlag2s_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.float)(_sa), (C.lapack_int)(ldsa))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clag2z.f. +func Clag2z(m, n int, sa []complex64, ldsa int, a []complex128, lda int) bool { + var _sa *complex64 + if len(sa) > 0 { + _sa = &sa[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_clag2z_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_sa), (C.lapack_int)(ldsa), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slagge.f. +func Slagge(m, n, kl, ku int, d, a []float32, lda int, iseed []int32, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_slagge_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.float)(_d), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlagge.f. +func Dlagge(m, n, kl, ku int, d, a []float64, lda int, iseed []int32, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dlagge_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.double)(_d), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clagge.f. +func Clagge(m, n, kl, ku int, d []float32, a []complex64, lda int, iseed []int32, work []complex64) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_clagge_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.float)(_d), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlagge.f. +func Zlagge(m, n, kl, ku int, d []float64, a []complex128, lda int, iseed []int32, work []complex128) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zlagge_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(kl), (C.lapack_int)(ku), (*C.double)(_d), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/claghe.f. +func Claghe(n, k int, d []float32, a []complex64, lda int, iseed []int32, work []complex64) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_claghe_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_d), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlaghe.f. +func Zlaghe(n, k int, d []float64, a []complex128, lda int, iseed []int32, work []complex128) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zlaghe_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_d), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slagsy.f. +func Slagsy(n, k int, d, a []float32, lda int, iseed []int32, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_slagsy_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_d), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlagsy.f. +func Dlagsy(n, k int, d, a []float64, lda int, iseed []int32, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dlagsy_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_d), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clagsy.f. +func Clagsy(n, k int, d []float32, a []complex64, lda int, iseed []int32, work []complex64) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_clagsy_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_d), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlagsy.f. +func Zlagsy(n, k int, d []float64, a []complex128, lda int, iseed []int32, work []complex128) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zlagsy_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_d), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_iseed), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slapmr.f. +func Slapmr(forwrd int32, m, n int, x []float32, ldx int, k []int32) bool { + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + return isZero(C.LAPACKE_slapmr_work((C.int)(rowMajor), (C.lapack_logical)(forwrd), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_x), (C.lapack_int)(ldx), (*C.lapack_int)(_k))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlapmr.f. +func Dlapmr(forwrd int32, m, n int, x []float64, ldx int, k []int32) bool { + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + return isZero(C.LAPACKE_dlapmr_work((C.int)(rowMajor), (C.lapack_logical)(forwrd), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_x), (C.lapack_int)(ldx), (*C.lapack_int)(_k))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clapmr.f. +func Clapmr(forwrd int32, m, n int, x []complex64, ldx int, k []int32) bool { + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + return isZero(C.LAPACKE_clapmr_work((C.int)(rowMajor), (C.lapack_logical)(forwrd), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.lapack_int)(_k))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlapmr.f. +func Zlapmr(forwrd int32, m, n int, x []complex128, ldx int, k []int32) bool { + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + return isZero(C.LAPACKE_zlapmr_work((C.int)(rowMajor), (C.lapack_logical)(forwrd), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.lapack_int)(_k))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slapmt.f. +func Slapmt(forwrd int32, m, n int, x []float32, ldx int, k []int32) bool { + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + return isZero(C.LAPACKE_slapmt_work((C.int)(rowMajor), (C.lapack_logical)(forwrd), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_x), (C.lapack_int)(ldx), (*C.lapack_int)(_k))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlapmt.f. +func Dlapmt(forwrd int32, m, n int, x []float64, ldx int, k []int32) bool { + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + return isZero(C.LAPACKE_dlapmt_work((C.int)(rowMajor), (C.lapack_logical)(forwrd), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_x), (C.lapack_int)(ldx), (*C.lapack_int)(_k))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clapmt.f. +func Clapmt(forwrd int32, m, n int, x []complex64, ldx int, k []int32) bool { + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + return isZero(C.LAPACKE_clapmt_work((C.int)(rowMajor), (C.lapack_logical)(forwrd), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.lapack_int)(_k))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlapmt.f. +func Zlapmt(forwrd int32, m, n int, x []complex128, ldx int, k []int32) bool { + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _k *int32 + if len(k) > 0 { + _k = &k[0] + } + return isZero(C.LAPACKE_zlapmt_work((C.int)(rowMajor), (C.lapack_logical)(forwrd), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.lapack_int)(_k))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slartgp.f. +func Slartgp(f, g float32, cs, sn, r []float32) bool { + var _cs *float32 + if len(cs) > 0 { + _cs = &cs[0] + } + var _sn *float32 + if len(sn) > 0 { + _sn = &sn[0] + } + var _r *float32 + if len(r) > 0 { + _r = &r[0] + } + return isZero(C.LAPACKE_slartgp_work((C.float)(f), (C.float)(g), (*C.float)(_cs), (*C.float)(_sn), (*C.float)(_r))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlartgp.f. +func Dlartgp(f, g float64, cs, sn, r []float64) bool { + var _cs *float64 + if len(cs) > 0 { + _cs = &cs[0] + } + var _sn *float64 + if len(sn) > 0 { + _sn = &sn[0] + } + var _r *float64 + if len(r) > 0 { + _r = &r[0] + } + return isZero(C.LAPACKE_dlartgp_work((C.double)(f), (C.double)(g), (*C.double)(_cs), (*C.double)(_sn), (*C.double)(_r))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slartgs.f. +func Slartgs(x, y, sigma float32, cs, sn []float32) bool { + var _cs *float32 + if len(cs) > 0 { + _cs = &cs[0] + } + var _sn *float32 + if len(sn) > 0 { + _sn = &sn[0] + } + return isZero(C.LAPACKE_slartgs_work((C.float)(x), (C.float)(y), (C.float)(sigma), (*C.float)(_cs), (*C.float)(_sn))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlartgs.f. +func Dlartgs(x, y, sigma float64, cs, sn []float64) bool { + var _cs *float64 + if len(cs) > 0 { + _cs = &cs[0] + } + var _sn *float64 + if len(sn) > 0 { + _sn = &sn[0] + } + return isZero(C.LAPACKE_dlartgs_work((C.double)(x), (C.double)(y), (C.double)(sigma), (*C.double)(_cs), (*C.double)(_sn))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slapy2.f. +func Slapy2(x, y float32) float32 { + return float32(C.LAPACKE_slapy2_work((C.float)(x), (C.float)(y))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlapy2.f. +func Dlapy2(x, y float64) float64 { + return float64(C.LAPACKE_dlapy2_work((C.double)(x), (C.double)(y))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slapy3.f. +func Slapy3(x, y, z float32) float32 { + return float32(C.LAPACKE_slapy3_work((C.float)(x), (C.float)(y), (C.float)(z))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlapy3.f. +func Dlapy3(x, y, z float64) float64 { + return float64(C.LAPACKE_dlapy3_work((C.double)(x), (C.double)(y), (C.double)(z))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slamch.f. +func Slamch(cmach byte) float32 { + return float32(C.LAPACKE_slamch_work((C.char)(cmach))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlamch.f. +func Dlamch(cmach byte) float64 { + return float64(C.LAPACKE_dlamch_work((C.char)(cmach))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slange.f. +func Slange(norm byte, m, n int, a []float32, lda int, work []float32) float32 { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return float32(C.LAPACKE_slange_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlange.f. +func Dlange(norm byte, m, n int, a []float64, lda int, work []float64) float64 { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return float64(C.LAPACKE_dlange_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clange.f. +func Clange(norm byte, m, n int, a []complex64, lda int, work []float32) float32 { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return float32(C.LAPACKE_clange_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlange.f. +func Zlange(norm byte, m, n int, a []complex128, lda int, work []float64) float64 { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return float64(C.LAPACKE_zlange_work((C.int)(rowMajor), (C.char)(norm), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clanhe.f. +func Clanhe(norm byte, ul blas.Uplo, n int, a []complex64, lda int, work []float32) float32 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return float32(C.LAPACKE_clanhe_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlanhe.f. +func Zlanhe(norm byte, ul blas.Uplo, n int, a []complex128, lda int, work []float64) float64 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return float64(C.LAPACKE_zlanhe_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slansy.f. +func Slansy(norm byte, ul blas.Uplo, n int, a []float32, lda int, work []float32) float32 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return float32(C.LAPACKE_slansy_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlansy.f. +func Dlansy(norm byte, ul blas.Uplo, n int, a []float64, lda int, work []float64) float64 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return float64(C.LAPACKE_dlansy_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clansy.f. +func Clansy(norm byte, ul blas.Uplo, n int, a []complex64, lda int, work []float32) float32 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return float32(C.LAPACKE_clansy_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlansy.f. +func Zlansy(norm byte, ul blas.Uplo, n int, a []complex128, lda int, work []float64) float64 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return float64(C.LAPACKE_zlansy_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slantr.f. +func Slantr(norm byte, ul blas.Uplo, d blas.Diag, m, n int, a []float32, lda int, work []float32) float32 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return float32(C.LAPACKE_slantr_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlantr.f. +func Dlantr(norm byte, ul blas.Uplo, d blas.Diag, m, n int, a []float64, lda int, work []float64) float64 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return float64(C.LAPACKE_dlantr_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clantr.f. +func Clantr(norm byte, ul blas.Uplo, d blas.Diag, m, n int, a []complex64, lda int, work []float32) float32 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return float32(C.LAPACKE_clantr_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlantr.f. +func Zlantr(norm byte, ul blas.Uplo, d blas.Diag, m, n int, a []complex128, lda int, work []float64) float64 { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return float64(C.LAPACKE_zlantr_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarfb.f. +func Slarfb(side blas.Side, trans blas.Transpose, direct, storev byte, m, n, k int, v []float32, ldv int, t []float32, ldt int, c []float32, ldc int, work []float32, ldwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_slarfb_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.char)(direct), (C.char)(storev), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work), (C.lapack_int)(ldwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarfb.f. +func Dlarfb(side blas.Side, trans blas.Transpose, direct, storev byte, m, n, k int, v []float64, ldv int, t []float64, ldt int, c []float64, ldc int, work []float64, ldwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dlarfb_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.char)(direct), (C.char)(storev), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work), (C.lapack_int)(ldwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clarfb.f. +func Clarfb(side blas.Side, trans blas.Transpose, direct, storev byte, m, n, k int, v []complex64, ldv int, t []complex64, ldt int, c []complex64, ldc int, work []complex64, ldwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_clarfb_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.char)(direct), (C.char)(storev), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (C.lapack_int)(ldwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarfb.f. +func Zlarfb(side blas.Side, trans blas.Transpose, direct, storev byte, m, n, k int, v []complex128, ldv int, t []complex128, ldt int, c []complex128, ldc int, work []complex128, ldwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zlarfb_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.char)(direct), (C.char)(storev), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (C.lapack_int)(ldwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarfg.f. +func Slarfg(n int, alpha, x []float32, incx int, tau []float32) bool { + var _alpha *float32 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + return isZero(C.LAPACKE_slarfg_work((C.lapack_int)(n), (*C.float)(_alpha), (*C.float)(_x), (C.lapack_int)(incx), (*C.float)(_tau))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarfg.f. +func Dlarfg(n int, alpha, x []float64, incx int, tau []float64) bool { + var _alpha *float64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + return isZero(C.LAPACKE_dlarfg_work((C.lapack_int)(n), (*C.double)(_alpha), (*C.double)(_x), (C.lapack_int)(incx), (*C.double)(_tau))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clarfg.f. +func Clarfg(n int, alpha, x []complex64, incx int, tau []complex64) bool { + var _alpha *complex64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + return isZero(C.LAPACKE_clarfg_work((C.lapack_int)(n), (*C.lapack_complex_float)(_alpha), (*C.lapack_complex_float)(_x), (C.lapack_int)(incx), (*C.lapack_complex_float)(_tau))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarfg.f. +func Zlarfg(n int, alpha, x []complex128, incx int, tau []complex128) bool { + var _alpha *complex128 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + return isZero(C.LAPACKE_zlarfg_work((C.lapack_int)(n), (*C.lapack_complex_double)(_alpha), (*C.lapack_complex_double)(_x), (C.lapack_int)(incx), (*C.lapack_complex_double)(_tau))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarft.f. +func Slarft(direct, storev byte, n, k int, v []float32, ldv int, tau, t []float32, ldt int) bool { + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_slarft_work((C.int)(rowMajor), (C.char)(direct), (C.char)(storev), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_tau), (*C.float)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarft.f. +func Dlarft(direct, storev byte, n, k int, v []float64, ldv int, tau, t []float64, ldt int) bool { + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_dlarft_work((C.int)(rowMajor), (C.char)(direct), (C.char)(storev), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_tau), (*C.double)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clarft.f. +func Clarft(direct, storev byte, n, k int, v []complex64, ldv int, tau, t []complex64, ldt int) bool { + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_clarft_work((C.int)(rowMajor), (C.char)(direct), (C.char)(storev), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarft.f. +func Zlarft(direct, storev byte, n, k int, v []complex128, ldv int, tau, t []complex128, ldt int) bool { + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_zlarft_work((C.int)(rowMajor), (C.char)(direct), (C.char)(storev), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarfx.f. +func Slarfx(side blas.Side, m, n int, v []float32, tau float32, c []float32, ldc int, work []float32) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_slarfx_work((C.int)(rowMajor), (C.char)(side), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_v), (C.float)(tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarfx.f. +func Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dlarfx_work((C.int)(rowMajor), (C.char)(side), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_v), (C.double)(tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clarfx.f. +func Clarfx(side blas.Side, m, n int, v []complex64, tau complex64, c []complex64, ldc int, work []complex64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_clarfx_work((C.int)(rowMajor), (C.char)(side), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_v), (C.lapack_complex_float)(tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarfx.f. +func Zlarfx(side blas.Side, m, n int, v []complex128, tau complex128, c []complex128, ldc int, work []complex128) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zlarfx_work((C.int)(rowMajor), (C.char)(side), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_v), (C.lapack_complex_double)(tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarnv.f. +func Slarnv(idist int, iseed []int32, n int, x []float32) bool { + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + return isZero(C.LAPACKE_slarnv_work((C.lapack_int)(idist), (*C.lapack_int)(_iseed), (C.lapack_int)(n), (*C.float)(_x))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarnv.f. +func Dlarnv(idist int, iseed []int32, n int, x []float64) bool { + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + return isZero(C.LAPACKE_dlarnv_work((C.lapack_int)(idist), (*C.lapack_int)(_iseed), (C.lapack_int)(n), (*C.double)(_x))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clarnv.f. +func Clarnv(idist int, iseed []int32, n int, x []complex64) bool { + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + return isZero(C.LAPACKE_clarnv_work((C.lapack_int)(idist), (*C.lapack_int)(_iseed), (C.lapack_int)(n), (*C.lapack_complex_float)(_x))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlarnv.f. +func Zlarnv(idist int, iseed []int32, n int, x []complex128) bool { + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + return isZero(C.LAPACKE_zlarnv_work((C.lapack_int)(idist), (*C.lapack_int)(_iseed), (C.lapack_int)(n), (*C.lapack_complex_double)(_x))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slascl.f. +func Slascl(typ byte, kl, ku int, cfrom, cto float32, m, n int, a []float32, lda int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_slascl_work((C.int)(rowMajor), (C.char)(typ), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.float)(cfrom), (C.float)(cto), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlascl.f. +func Dlascl(typ byte, kl, ku int, cfrom, cto float64, m, n int, a []float64, lda int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dlascl_work((C.int)(rowMajor), (C.char)(typ), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.double)(cfrom), (C.double)(cto), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clascl.f. +func Clascl(typ byte, kl, ku int, cfrom, cto float32, m, n int, a []complex64, lda int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_clascl_work((C.int)(rowMajor), (C.char)(typ), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.float)(cfrom), (C.float)(cto), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlascl.f. +func Zlascl(typ byte, kl, ku int, cfrom, cto float64, m, n int, a []complex128, lda int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zlascl_work((C.int)(rowMajor), (C.char)(typ), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.double)(cfrom), (C.double)(cto), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slaset.f. +func Slaset(ul blas.Uplo, m, n int, alpha, beta float32, a []float32, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + ul = 'A' + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_slaset_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (C.float)(alpha), (C.float)(beta), (*C.float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlaset.f. +func Dlaset(ul blas.Uplo, m, n int, alpha, beta float64, a []float64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + ul = 'A' + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dlaset_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (C.double)(alpha), (C.double)(beta), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/claset.f. +func Claset(ul blas.Uplo, m, n int, alpha, beta complex64, a []complex64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + ul = 'A' + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_claset_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_complex_float)(alpha), (C.lapack_complex_float)(beta), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlaset.f. +func Zlaset(ul blas.Uplo, m, n int, alpha, beta complex128, a []complex128, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + ul = 'A' + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zlaset_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_complex_double)(alpha), (C.lapack_complex_double)(beta), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slasrt.f. +func Slasrt(id byte, n int, d []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + return isZero(C.LAPACKE_slasrt_work((C.char)(id), (C.lapack_int)(n), (*C.float)(_d))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlasrt.f. +func Dlasrt(id byte, n int, d []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + return isZero(C.LAPACKE_dlasrt_work((C.char)(id), (C.lapack_int)(n), (*C.double)(_d))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slaswp.f. +func Slaswp(n int, a []float32, lda, k1, k2 int, ipiv []int32, incx int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_slaswp_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (C.lapack_int)(k1), (C.lapack_int)(k2), (*C.lapack_int)(_ipiv), (C.lapack_int)(incx))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlaswp.f. +func Dlaswp(n int, a []float64, lda, k1, k2 int, ipiv []int32, incx int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_dlaswp_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (C.lapack_int)(k1), (C.lapack_int)(k2), (*C.lapack_int)(_ipiv), (C.lapack_int)(incx))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/claswp.f. +func Claswp(n int, a []complex64, lda, k1, k2 int, ipiv []int32, incx int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_claswp_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (C.lapack_int)(k1), (C.lapack_int)(k2), (*C.lapack_int)(_ipiv), (C.lapack_int)(incx))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlaswp.f. +func Zlaswp(n int, a []complex128, lda, k1, k2 int, ipiv []int32, incx int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_zlaswp_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (C.lapack_int)(k1), (C.lapack_int)(k2), (*C.lapack_int)(_ipiv), (C.lapack_int)(incx))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slatms.f. +func Slatms(m, n int, dist byte, iseed []int32, sym byte, d []float32, mode int, cond, dmax float32, kl, ku int, pack byte, a []float32, lda int, work []float32) bool { + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_slatms_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.char)(dist), (*C.lapack_int)(_iseed), (C.char)(sym), (*C.float)(_d), (C.lapack_int)(mode), (C.float)(cond), (C.float)(dmax), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.char)(pack), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlatms.f. +func Dlatms(m, n int, dist byte, iseed []int32, sym byte, d []float64, mode int, cond, dmax float64, kl, ku int, pack byte, a []float64, lda int, work []float64) bool { + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dlatms_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.char)(dist), (*C.lapack_int)(_iseed), (C.char)(sym), (*C.double)(_d), (C.lapack_int)(mode), (C.double)(cond), (C.double)(dmax), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.char)(pack), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clatms.f. +func Clatms(m, n int, dist byte, iseed []int32, sym byte, d []float32, mode int, cond, dmax float32, kl, ku int, pack byte, a []complex64, lda int, work []complex64) bool { + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_clatms_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.char)(dist), (*C.lapack_int)(_iseed), (C.char)(sym), (*C.float)(_d), (C.lapack_int)(mode), (C.float)(cond), (C.float)(dmax), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.char)(pack), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlatms.f. +func Zlatms(m, n int, dist byte, iseed []int32, sym byte, d []float64, mode int, cond, dmax float64, kl, ku int, pack byte, a []complex128, lda int, work []complex128) bool { + var _iseed *int32 + if len(iseed) > 0 { + _iseed = &iseed[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zlatms_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.char)(dist), (*C.lapack_int)(_iseed), (C.char)(sym), (*C.double)(_d), (C.lapack_int)(mode), (C.double)(cond), (C.double)(dmax), (C.lapack_int)(kl), (C.lapack_int)(ku), (C.char)(pack), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slauum.f. +func Slauum(ul blas.Uplo, n int, a []float32, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_slauum_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlauum.f. +func Dlauum(ul blas.Uplo, n int, a []float64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dlauum_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/clauum.f. +func Clauum(ul blas.Uplo, n int, a []complex64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_clauum_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zlauum.f. +func Zlauum(ul blas.Uplo, n int, a []complex128, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zlauum_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sopgtr.f. +func Sopgtr(ul blas.Uplo, n int, ap, tau, q []float32, ldq int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sopgtr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_tau), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dopgtr.f. +func Dopgtr(ul blas.Uplo, n int, ap, tau, q []float64, ldq int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dopgtr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_tau), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sopmtr.f. +func Sopmtr(side blas.Side, ul blas.Uplo, trans blas.Transpose, m, n int, ap, tau, c []float32, ldc int, work []float32) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sopmtr_work((C.int)(rowMajor), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dopmtr.f. +func Dopmtr(side blas.Side, ul blas.Uplo, trans blas.Transpose, m, n int, ap, tau, c []float64, ldc int, work []float64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dopmtr_work((C.int)(rowMajor), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorgbr.f. +func Sorgbr(vect byte, m, n, k int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sorgbr_work((C.int)(rowMajor), (C.char)(vect), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorgbr.f. +func Dorgbr(vect byte, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dorgbr_work((C.int)(rowMajor), (C.char)(vect), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorghr.f. +func Sorghr(n, ilo, ihi int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sorghr_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorghr.f. +func Dorghr(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dorghr_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorglq.f. +func Sorglq(m, n, k int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sorglq_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorglq.f. +func Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dorglq_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorgql.f. +func Sorgql(m, n, k int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sorgql_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorgql.f. +func Dorgql(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dorgql_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorgqr.f. +func Sorgqr(m, n, k int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sorgqr_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorgqr.f. +func Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dorgqr_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorgrq.f. +func Sorgrq(m, n, k int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sorgrq_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorgrq.f. +func Dorgrq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dorgrq_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorgtr.f. +func Sorgtr(ul blas.Uplo, n int, a []float32, lda int, tau, work []float32, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sorgtr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorgtr.f. +func Dorgtr(ul blas.Uplo, n int, a []float64, lda int, tau, work []float64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dorgtr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sormbr.f. +func Sormbr(vect byte, side blas.Side, trans blas.Transpose, m, n, k int, a []float32, lda int, tau, c []float32, ldc int, work []float32, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sormbr_work((C.int)(rowMajor), (C.char)(vect), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dormbr.f. +func Dormbr(vect byte, side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dormbr_work((C.int)(rowMajor), (C.char)(vect), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sormhr.f. +func Sormhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []float32, lda int, tau, c []float32, ldc int, work []float32, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sormhr_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dormhr.f. +func Dormhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dormhr_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sormlq.f. +func Sormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float32, lda int, tau, c []float32, ldc int, work []float32, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sormlq_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dormlq.f. +func Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dormlq_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sormql.f. +func Sormql(side blas.Side, trans blas.Transpose, m, n, k int, a []float32, lda int, tau, c []float32, ldc int, work []float32, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sormql_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dormql.f. +func Dormql(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dormql_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sormqr.f. +func Sormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float32, lda int, tau, c []float32, ldc int, work []float32, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sormqr_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dormqr.f. +func Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dormqr_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sormrq.f. +func Sormrq(side blas.Side, trans blas.Transpose, m, n, k int, a []float32, lda int, tau, c []float32, ldc int, work []float32, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sormrq_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dormrq.f. +func Dormrq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dormrq_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sormrz.f. +func Sormrz(side blas.Side, trans blas.Transpose, m, n, k, l int, a []float32, lda int, tau, c []float32, ldc int, work []float32, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sormrz_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dormrz.f. +func Dormrz(side blas.Side, trans blas.Transpose, m, n, k, l int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dormrz_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sormtr.f. +func Sormtr(side blas.Side, ul blas.Uplo, trans blas.Transpose, m, n int, a []float32, lda int, tau, c []float32, ldc int, work []float32, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sormtr_work((C.int)(rowMajor), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dormtr.f. +func Dormtr(side blas.Side, ul blas.Uplo, trans blas.Transpose, m, n int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dormtr_work((C.int)(rowMajor), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spbcon.f. +func Spbcon(ul blas.Uplo, n, kd int, ab []float32, ldab int, anorm float32, rcond, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_spbcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.float)(_ab), (C.lapack_int)(ldab), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpbcon.f. +func Dpbcon(ul blas.Uplo, n, kd int, ab []float64, ldab int, anorm float64, rcond, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dpbcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.double)(_ab), (C.lapack_int)(ldab), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpbcon.f. +func Cpbcon(ul blas.Uplo, n, kd int, ab []complex64, ldab int, anorm float32, rcond []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cpbcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpbcon.f. +func Zpbcon(ul blas.Uplo, n, kd int, ab []complex128, ldab int, anorm float64, rcond []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zpbcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spbequ.f. +func Spbequ(ul blas.Uplo, n, kd int, ab []float32, ldab int, s, scond, amax []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_spbequ_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpbequ.f. +func Dpbequ(ul blas.Uplo, n, kd int, ab []float64, ldab int, s, scond, amax []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_dpbequ_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpbequ.f. +func Cpbequ(ul blas.Uplo, n, kd int, ab []complex64, ldab int, s, scond, amax []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_cpbequ_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpbequ.f. +func Zpbequ(ul blas.Uplo, n, kd int, ab []complex128, ldab int, s, scond, amax []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_zpbequ_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spbrfs.f. +func Spbrfs(ul blas.Uplo, n, kd, nrhs int, ab []float32, ldab int, afb []float32, ldafb int, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *float32 + if len(afb) > 0 { + _afb = &afb[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_spbrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_afb), (C.lapack_int)(ldafb), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpbrfs.f. +func Dpbrfs(ul blas.Uplo, n, kd, nrhs int, ab []float64, ldab int, afb []float64, ldafb int, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *float64 + if len(afb) > 0 { + _afb = &afb[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dpbrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_afb), (C.lapack_int)(ldafb), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpbrfs.f. +func Cpbrfs(ul blas.Uplo, n, kd, nrhs int, ab []complex64, ldab int, afb []complex64, ldafb int, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *complex64 + if len(afb) > 0 { + _afb = &afb[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cpbrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_afb), (C.lapack_int)(ldafb), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpbrfs.f. +func Zpbrfs(ul blas.Uplo, n, kd, nrhs int, ab []complex128, ldab int, afb []complex128, ldafb int, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *complex128 + if len(afb) > 0 { + _afb = &afb[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zpbrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_afb), (C.lapack_int)(ldafb), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spbstf.f. +func Spbstf(ul blas.Uplo, n, kb int, bb []float32, ldbb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _bb *float32 + if len(bb) > 0 { + _bb = &bb[0] + } + return isZero(C.LAPACKE_spbstf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kb), (*C.float)(_bb), (C.lapack_int)(ldbb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpbstf.f. +func Dpbstf(ul blas.Uplo, n, kb int, bb []float64, ldbb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _bb *float64 + if len(bb) > 0 { + _bb = &bb[0] + } + return isZero(C.LAPACKE_dpbstf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kb), (*C.double)(_bb), (C.lapack_int)(ldbb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpbstf.f. +func Cpbstf(ul blas.Uplo, n, kb int, bb []complex64, ldbb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _bb *complex64 + if len(bb) > 0 { + _bb = &bb[0] + } + return isZero(C.LAPACKE_cpbstf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kb), (*C.lapack_complex_float)(_bb), (C.lapack_int)(ldbb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpbstf.f. +func Zpbstf(ul blas.Uplo, n, kb int, bb []complex128, ldbb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _bb *complex128 + if len(bb) > 0 { + _bb = &bb[0] + } + return isZero(C.LAPACKE_zpbstf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kb), (*C.lapack_complex_double)(_bb), (C.lapack_int)(ldbb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spbsv.f. +func Spbsv(ul blas.Uplo, n, kd, nrhs int, ab []float32, ldab int, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_spbsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpbsv.f. +func Dpbsv(ul blas.Uplo, n, kd, nrhs int, ab []float64, ldab int, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dpbsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpbsv.f. +func Cpbsv(ul blas.Uplo, n, kd, nrhs int, ab []complex64, ldab int, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cpbsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpbsv.f. +func Zpbsv(ul blas.Uplo, n, kd, nrhs int, ab []complex128, ldab int, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zpbsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spbsvx.f. +func Spbsvx(fact byte, ul blas.Uplo, n, kd, nrhs int, ab []float32, ldab int, afb []float32, ldafb int, equed []byte, s, b []float32, ldb int, x []float32, ldx int, rcond, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *float32 + if len(afb) > 0 { + _afb = &afb[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_spbsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_afb), (C.lapack_int)(ldafb), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_s), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpbsvx.f. +func Dpbsvx(fact byte, ul blas.Uplo, n, kd, nrhs int, ab []float64, ldab int, afb []float64, ldafb int, equed []byte, s, b []float64, ldb int, x []float64, ldx int, rcond, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *float64 + if len(afb) > 0 { + _afb = &afb[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dpbsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_afb), (C.lapack_int)(ldafb), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_s), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpbsvx.f. +func Cpbsvx(fact byte, ul blas.Uplo, n, kd, nrhs int, ab []complex64, ldab int, afb []complex64, ldafb int, equed []byte, s []float32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *complex64 + if len(afb) > 0 { + _afb = &afb[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cpbsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_afb), (C.lapack_int)(ldafb), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_s), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpbsvx.f. +func Zpbsvx(fact byte, ul blas.Uplo, n, kd, nrhs int, ab []complex128, ldab int, afb []complex128, ldafb int, equed []byte, s []float64, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _afb *complex128 + if len(afb) > 0 { + _afb = &afb[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zpbsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_afb), (C.lapack_int)(ldafb), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_s), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spbtrf.f. +func Spbtrf(ul blas.Uplo, n, kd int, ab []float32, ldab int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + return isZero(C.LAPACKE_spbtrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.float)(_ab), (C.lapack_int)(ldab))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpbtrf.f. +func Dpbtrf(ul blas.Uplo, n, kd int, ab []float64, ldab int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + return isZero(C.LAPACKE_dpbtrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.double)(_ab), (C.lapack_int)(ldab))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpbtrf.f. +func Cpbtrf(ul blas.Uplo, n, kd int, ab []complex64, ldab int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + return isZero(C.LAPACKE_cpbtrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpbtrf.f. +func Zpbtrf(ul blas.Uplo, n, kd int, ab []complex128, ldab int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + return isZero(C.LAPACKE_zpbtrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spbtrs.f. +func Spbtrs(ul blas.Uplo, n, kd, nrhs int, ab []float32, ldab int, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_spbtrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpbtrs.f. +func Dpbtrs(ul blas.Uplo, n, kd, nrhs int, ab []float64, ldab int, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dpbtrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpbtrs.f. +func Cpbtrs(ul blas.Uplo, n, kd, nrhs int, ab []complex64, ldab int, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cpbtrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpbtrs.f. +func Zpbtrs(ul blas.Uplo, n, kd, nrhs int, ab []complex128, ldab int, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zpbtrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spftrf.f. +func Spftrf(transr blas.Transpose, ul blas.Uplo, n int, a []float32) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_spftrf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpftrf.f. +func Dpftrf(transr blas.Transpose, ul blas.Uplo, n int, a []float64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dpftrf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpftrf.f. +func Cpftrf(transr blas.Transpose, ul blas.Uplo, n int, a []complex64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_cpftrf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpftrf.f. +func Zpftrf(transr blas.Transpose, ul blas.Uplo, n int, a []complex128) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zpftrf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spftri.f. +func Spftri(transr blas.Transpose, ul blas.Uplo, n int, a []float32) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_spftri_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpftri.f. +func Dpftri(transr blas.Transpose, ul blas.Uplo, n int, a []float64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dpftri_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpftri.f. +func Cpftri(transr blas.Transpose, ul blas.Uplo, n int, a []complex64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_cpftri_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpftri.f. +func Zpftri(transr blas.Transpose, ul blas.Uplo, n int, a []complex128) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zpftri_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spftrs.f. +func Spftrs(transr blas.Transpose, ul blas.Uplo, n, nrhs int, a, b []float32, ldb int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_spftrs_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpftrs.f. +func Dpftrs(transr blas.Transpose, ul blas.Uplo, n, nrhs int, a, b []float64, ldb int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dpftrs_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpftrs.f. +func Cpftrs(transr blas.Transpose, ul blas.Uplo, n, nrhs int, a, b []complex64, ldb int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cpftrs_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpftrs.f. +func Zpftrs(transr blas.Transpose, ul blas.Uplo, n, nrhs int, a, b []complex128, ldb int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zpftrs_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spocon.f. +func Spocon(ul blas.Uplo, n int, a []float32, lda int, anorm float32, rcond, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_spocon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpocon.f. +func Dpocon(ul blas.Uplo, n int, a []float64, lda int, anorm float64, rcond, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dpocon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpocon.f. +func Cpocon(ul blas.Uplo, n int, a []complex64, lda int, anorm float32, rcond []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cpocon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpocon.f. +func Zpocon(ul blas.Uplo, n int, a []complex128, lda int, anorm float64, rcond []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zpocon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spoequ.f. +func Spoequ(n int, a []float32, lda int, s, scond, amax []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_spoequ_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpoequ.f. +func Dpoequ(n int, a []float64, lda int, s, scond, amax []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_dpoequ_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpoequ.f. +func Cpoequ(n int, a []complex64, lda int, s, scond, amax []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_cpoequ_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpoequ.f. +func Zpoequ(n int, a []complex128, lda int, s, scond, amax []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_zpoequ_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spoequb.f. +func Spoequb(n int, a []float32, lda int, s, scond, amax []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_spoequb_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpoequb.f. +func Dpoequb(n int, a []float64, lda int, s, scond, amax []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_dpoequb_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpoequb.f. +func Cpoequb(n int, a []complex64, lda int, s, scond, amax []float32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_cpoequb_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpoequb.f. +func Zpoequb(n int, a []complex128, lda int, s, scond, amax []float64) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_zpoequb_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sporfs.f. +func Sporfs(ul blas.Uplo, n, nrhs int, a []float32, lda int, af []float32, ldaf int, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _af *float32 + if len(af) > 0 { + _af = &af[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sporfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_af), (C.lapack_int)(ldaf), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dporfs.f. +func Dporfs(ul blas.Uplo, n, nrhs int, a []float64, lda int, af []float64, ldaf int, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _af *float64 + if len(af) > 0 { + _af = &af[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dporfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_af), (C.lapack_int)(ldaf), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cporfs.f. +func Cporfs(ul blas.Uplo, n, nrhs int, a []complex64, lda int, af []complex64, ldaf int, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex64 + if len(af) > 0 { + _af = &af[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cporfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_af), (C.lapack_int)(ldaf), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zporfs.f. +func Zporfs(ul blas.Uplo, n, nrhs int, a []complex128, lda int, af []complex128, ldaf int, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex128 + if len(af) > 0 { + _af = &af[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zporfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_af), (C.lapack_int)(ldaf), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sposv.f. +func Sposv(ul blas.Uplo, n, nrhs int, a []float32, lda int, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sposv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dposv.f. +func Dposv(ul blas.Uplo, n, nrhs int, a []float64, lda int, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dposv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cposv.f. +func Cposv(ul blas.Uplo, n, nrhs int, a []complex64, lda int, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cposv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zposv.f. +func Zposv(ul blas.Uplo, n, nrhs int, a []complex128, lda int, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zposv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsposv.f. +func Dsposv(ul blas.Uplo, n, nrhs int, a []float64, lda int, b []float64, ldb int, x []float64, ldx int, work []float64, swork []float32, iter []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _swork *float32 + if len(swork) > 0 { + _swork = &swork[0] + } + var _iter *int32 + if len(iter) > 0 { + _iter = &iter[0] + } + return isZero(C.LAPACKE_dsposv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_work), (*C.float)(_swork), (*C.lapack_int)(_iter))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zcposv.f. +func Zcposv(ul blas.Uplo, n, nrhs int, a []complex128, lda int, b []complex128, ldb int, x []complex128, ldx int, work []complex128, swork []complex64, rwork []float64, iter []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _swork *complex64 + if len(swork) > 0 { + _swork = &swork[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iter *int32 + if len(iter) > 0 { + _iter = &iter[0] + } + return isZero(C.LAPACKE_zcposv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.lapack_complex_double)(_work), (*C.lapack_complex_float)(_swork), (*C.double)(_rwork), (*C.lapack_int)(_iter))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sposvx.f. +func Sposvx(fact byte, ul blas.Uplo, n, nrhs int, a []float32, lda int, af []float32, ldaf int, equed []byte, s, b []float32, ldb int, x []float32, ldx int, rcond, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _af *float32 + if len(af) > 0 { + _af = &af[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sposvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_af), (C.lapack_int)(ldaf), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_s), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dposvx.f. +func Dposvx(fact byte, ul blas.Uplo, n, nrhs int, a []float64, lda int, af []float64, ldaf int, equed []byte, s, b []float64, ldb int, x []float64, ldx int, rcond, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _af *float64 + if len(af) > 0 { + _af = &af[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dposvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_af), (C.lapack_int)(ldaf), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_s), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cposvx.f. +func Cposvx(fact byte, ul blas.Uplo, n, nrhs int, a []complex64, lda int, af []complex64, ldaf int, equed []byte, s []float32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex64 + if len(af) > 0 { + _af = &af[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cposvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_af), (C.lapack_int)(ldaf), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_s), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zposvx.f. +func Zposvx(fact byte, ul blas.Uplo, n, nrhs int, a []complex128, lda int, af []complex128, ldaf int, equed []byte, s []float64, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex128 + if len(af) > 0 { + _af = &af[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zposvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_af), (C.lapack_int)(ldaf), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_s), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spotrf2.f. +func Spotrf2(ul blas.Uplo, n int, a []float32, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_spotrf2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpotrf2.f. +func Dpotrf2(ul blas.Uplo, n int, a []float64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dpotrf2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpotrf2.f. +func Cpotrf2(ul blas.Uplo, n int, a []complex64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_cpotrf2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpotrf2.f. +func Zpotrf2(ul blas.Uplo, n int, a []complex128, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zpotrf2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spotrf.f. +func Spotrf(ul blas.Uplo, n int, a []float32, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_spotrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpotrf.f. +func Dpotrf(ul blas.Uplo, n int, a []float64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dpotrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpotrf.f. +func Cpotrf(ul blas.Uplo, n int, a []complex64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_cpotrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpotrf.f. +func Zpotrf(ul blas.Uplo, n int, a []complex128, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zpotrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spotri.f. +func Spotri(ul blas.Uplo, n int, a []float32, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_spotri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpotri.f. +func Dpotri(ul blas.Uplo, n int, a []float64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dpotri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpotri.f. +func Cpotri(ul blas.Uplo, n int, a []complex64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_cpotri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpotri.f. +func Zpotri(ul blas.Uplo, n int, a []complex128, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zpotri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spotrs.f. +func Spotrs(ul blas.Uplo, n, nrhs int, a []float32, lda int, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_spotrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpotrs.f. +func Dpotrs(ul blas.Uplo, n, nrhs int, a []float64, lda int, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dpotrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpotrs.f. +func Cpotrs(ul blas.Uplo, n, nrhs int, a []complex64, lda int, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cpotrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpotrs.f. +func Zpotrs(ul blas.Uplo, n, nrhs int, a []complex128, lda int, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zpotrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sppcon.f. +func Sppcon(ul blas.Uplo, n int, ap []float32, anorm float32, rcond, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sppcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dppcon.f. +func Dppcon(ul blas.Uplo, n int, ap []float64, anorm float64, rcond, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dppcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cppcon.f. +func Cppcon(ul blas.Uplo, n int, ap []complex64, anorm float32, rcond []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cppcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zppcon.f. +func Zppcon(ul blas.Uplo, n int, ap []complex128, anorm float64, rcond []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zppcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sppequ.f. +func Sppequ(ul blas.Uplo, n int, ap, s, scond, amax []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_sppequ_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dppequ.f. +func Dppequ(ul blas.Uplo, n int, ap, s, scond, amax []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_dppequ_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cppequ.f. +func Cppequ(ul blas.Uplo, n int, ap []complex64, s, scond, amax []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_cppequ_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zppequ.f. +func Zppequ(ul blas.Uplo, n int, ap []complex128, s, scond, amax []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + return isZero(C.LAPACKE_zppequ_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spprfs.f. +func Spprfs(ul blas.Uplo, n, nrhs int, ap, afp, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *float32 + if len(afp) > 0 { + _afp = &afp[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_spprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.float)(_afp), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpprfs.f. +func Dpprfs(ul blas.Uplo, n, nrhs int, ap, afp, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *float64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dpprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.double)(_afp), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpprfs.f. +func Cpprfs(ul blas.Uplo, n, nrhs int, ap, afp, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cpprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_afp), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpprfs.f. +func Zpprfs(ul blas.Uplo, n, nrhs int, ap, afp, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex128 + if len(afp) > 0 { + _afp = &afp[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zpprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_afp), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sppsv.f. +func Sppsv(ul blas.Uplo, n, nrhs int, ap, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sppsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dppsv.f. +func Dppsv(ul blas.Uplo, n, nrhs int, ap, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dppsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cppsv.f. +func Cppsv(ul blas.Uplo, n, nrhs int, ap, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cppsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zppsv.f. +func Zppsv(ul blas.Uplo, n, nrhs int, ap, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zppsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sppsvx.f. +func Sppsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []float32, equed []byte, s, b []float32, ldb int, x []float32, ldx int, rcond, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *float32 + if len(afp) > 0 { + _afp = &afp[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sppsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.float)(_afp), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_s), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dppsvx.f. +func Dppsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []float64, equed []byte, s, b []float64, ldb int, x []float64, ldx int, rcond, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *float64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dppsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.double)(_afp), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_s), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cppsvx.f. +func Cppsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []complex64, equed []byte, s []float32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cppsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_afp), (*C.char)(unsafe.Pointer(_equed)), (*C.float)(_s), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zppsvx.f. +func Zppsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []complex128, equed []byte, s []float64, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex128 + if len(afp) > 0 { + _afp = &afp[0] + } + var _equed *byte + if len(equed) > 0 { + _equed = &equed[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zppsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_afp), (*C.char)(unsafe.Pointer(_equed)), (*C.double)(_s), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spptrf.f. +func Spptrf(ul blas.Uplo, n int, ap []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_spptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpptrf.f. +func Dpptrf(ul blas.Uplo, n int, ap []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_dpptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpptrf.f. +func Cpptrf(ul blas.Uplo, n int, ap []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_cpptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpptrf.f. +func Zpptrf(ul blas.Uplo, n int, ap []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_zpptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spptri.f. +func Spptri(ul blas.Uplo, n int, ap []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_spptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpptri.f. +func Dpptri(ul blas.Uplo, n int, ap []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_dpptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpptri.f. +func Cpptri(ul blas.Uplo, n int, ap []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_cpptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpptri.f. +func Zpptri(ul blas.Uplo, n int, ap []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_zpptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spptrs.f. +func Spptrs(ul blas.Uplo, n, nrhs int, ap, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_spptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpptrs.f. +func Dpptrs(ul blas.Uplo, n, nrhs int, ap, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dpptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpptrs.f. +func Cpptrs(ul blas.Uplo, n, nrhs int, ap, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cpptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpptrs.f. +func Zpptrs(ul blas.Uplo, n, nrhs int, ap, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zpptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spstrf.f. +func Spstrf(ul blas.Uplo, n int, a []float32, lda int, piv, rank []int32, tol float32, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _piv *int32 + if len(piv) > 0 { + _piv = &piv[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_spstrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_piv), (*C.lapack_int)(_rank), (C.float)(tol), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpstrf.f. +func Dpstrf(ul blas.Uplo, n int, a []float64, lda int, piv, rank []int32, tol float64, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _piv *int32 + if len(piv) > 0 { + _piv = &piv[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dpstrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_piv), (*C.lapack_int)(_rank), (C.double)(tol), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpstrf.f. +func Cpstrf(ul blas.Uplo, n int, a []complex64, lda int, piv, rank []int32, tol float32, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _piv *int32 + if len(piv) > 0 { + _piv = &piv[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cpstrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_piv), (*C.lapack_int)(_rank), (C.float)(tol), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpstrf.f. +func Zpstrf(ul blas.Uplo, n int, a []complex128, lda int, piv, rank []int32, tol float64, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _piv *int32 + if len(piv) > 0 { + _piv = &piv[0] + } + var _rank *int32 + if len(rank) > 0 { + _rank = &rank[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zpstrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_piv), (*C.lapack_int)(_rank), (C.double)(tol), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sptcon.f. +func Sptcon(n int, d, e []float32, anorm float32, rcond, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sptcon_work((C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dptcon.f. +func Dptcon(n int, d, e []float64, anorm float64, rcond, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dptcon_work((C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cptcon.f. +func Cptcon(n int, d []float32, e []complex64, anorm float32, rcond, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex64 + if len(e) > 0 { + _e = &e[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cptcon_work((C.lapack_int)(n), (*C.float)(_d), (*C.lapack_complex_float)(_e), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zptcon.f. +func Zptcon(n int, d []float64, e []complex128, anorm float64, rcond, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex128 + if len(e) > 0 { + _e = &e[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zptcon_work((C.lapack_int)(n), (*C.double)(_d), (*C.lapack_complex_double)(_e), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spteqr.f. +func Spteqr(compz lapack.Comp, n int, d, e, z []float32, ldz int, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_spteqr_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpteqr.f. +func Dpteqr(compz lapack.Comp, n int, d, e, z []float64, ldz int, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dpteqr_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpteqr.f. +func Cpteqr(compz lapack.Comp, n int, d, e []float32, z []complex64, ldz int, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cpteqr_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpteqr.f. +func Zpteqr(compz lapack.Comp, n int, d, e []float64, z []complex128, ldz int, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zpteqr_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sptrfs.f. +func Sptrfs(n, nrhs int, d, e, df, ef, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _df *float32 + if len(df) > 0 { + _df = &df[0] + } + var _ef *float32 + if len(ef) > 0 { + _ef = &ef[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sptrfs_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_d), (*C.float)(_e), (*C.float)(_df), (*C.float)(_ef), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dptrfs.f. +func Dptrfs(n, nrhs int, d, e, df, ef, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _df *float64 + if len(df) > 0 { + _df = &df[0] + } + var _ef *float64 + if len(ef) > 0 { + _ef = &ef[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dptrfs_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_d), (*C.double)(_e), (*C.double)(_df), (*C.double)(_ef), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cptrfs.f. +func Cptrfs(ul blas.Uplo, n, nrhs int, d []float32, e []complex64, df []float32, ef, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex64 + if len(e) > 0 { + _e = &e[0] + } + var _df *float32 + if len(df) > 0 { + _df = &df[0] + } + var _ef *complex64 + if len(ef) > 0 { + _ef = &ef[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cptrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_d), (*C.lapack_complex_float)(_e), (*C.float)(_df), (*C.lapack_complex_float)(_ef), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zptrfs.f. +func Zptrfs(ul blas.Uplo, n, nrhs int, d []float64, e []complex128, df []float64, ef, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex128 + if len(e) > 0 { + _e = &e[0] + } + var _df *float64 + if len(df) > 0 { + _df = &df[0] + } + var _ef *complex128 + if len(ef) > 0 { + _ef = &ef[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zptrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_d), (*C.lapack_complex_double)(_e), (*C.double)(_df), (*C.lapack_complex_double)(_ef), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sptsv.f. +func Sptsv(n, nrhs int, d, e, b []float32, ldb int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sptsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_d), (*C.float)(_e), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dptsv.f. +func Dptsv(n, nrhs int, d, e, b []float64, ldb int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dptsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_d), (*C.double)(_e), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cptsv.f. +func Cptsv(n, nrhs int, d []float32, e, b []complex64, ldb int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex64 + if len(e) > 0 { + _e = &e[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cptsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_d), (*C.lapack_complex_float)(_e), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zptsv.f. +func Zptsv(n, nrhs int, d []float64, e, b []complex128, ldb int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex128 + if len(e) > 0 { + _e = &e[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zptsv_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_d), (*C.lapack_complex_double)(_e), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sptsvx.f. +func Sptsvx(fact byte, n, nrhs int, d, e, df, ef, b []float32, ldb int, x []float32, ldx int, rcond, ferr, berr, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _df *float32 + if len(df) > 0 { + _df = &df[0] + } + var _ef *float32 + if len(ef) > 0 { + _ef = &ef[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sptsvx_work((C.int)(rowMajor), (C.char)(fact), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_d), (*C.float)(_e), (*C.float)(_df), (*C.float)(_ef), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dptsvx.f. +func Dptsvx(fact byte, n, nrhs int, d, e, df, ef, b []float64, ldb int, x []float64, ldx int, rcond, ferr, berr, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _df *float64 + if len(df) > 0 { + _df = &df[0] + } + var _ef *float64 + if len(ef) > 0 { + _ef = &ef[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dptsvx_work((C.int)(rowMajor), (C.char)(fact), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_d), (*C.double)(_e), (*C.double)(_df), (*C.double)(_ef), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cptsvx.f. +func Cptsvx(fact byte, n, nrhs int, d []float32, e []complex64, df []float32, ef, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, rwork []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex64 + if len(e) > 0 { + _e = &e[0] + } + var _df *float32 + if len(df) > 0 { + _df = &df[0] + } + var _ef *complex64 + if len(ef) > 0 { + _ef = &ef[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cptsvx_work((C.int)(rowMajor), (C.char)(fact), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_d), (*C.lapack_complex_float)(_e), (*C.float)(_df), (*C.lapack_complex_float)(_ef), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zptsvx.f. +func Zptsvx(fact byte, n, nrhs int, d []float64, e []complex128, df []float64, ef, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, rwork []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex128 + if len(e) > 0 { + _e = &e[0] + } + var _df *float64 + if len(df) > 0 { + _df = &df[0] + } + var _ef *complex128 + if len(ef) > 0 { + _ef = &ef[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zptsvx_work((C.int)(rowMajor), (C.char)(fact), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_d), (*C.lapack_complex_double)(_e), (*C.double)(_df), (*C.lapack_complex_double)(_ef), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spttrf.f. +func Spttrf(n int, d, e []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + return isZero(C.LAPACKE_spttrf_work((C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpttrf.f. +func Dpttrf(n int, d, e []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + return isZero(C.LAPACKE_dpttrf_work((C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpttrf.f. +func Cpttrf(n int, d []float32, e []complex64) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex64 + if len(e) > 0 { + _e = &e[0] + } + return isZero(C.LAPACKE_cpttrf_work((C.lapack_int)(n), (*C.float)(_d), (*C.lapack_complex_float)(_e))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpttrf.f. +func Zpttrf(n int, d []float64, e []complex128) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex128 + if len(e) > 0 { + _e = &e[0] + } + return isZero(C.LAPACKE_zpttrf_work((C.lapack_int)(n), (*C.double)(_d), (*C.lapack_complex_double)(_e))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/spttrs.f. +func Spttrs(n, nrhs int, d, e, b []float32, ldb int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_spttrs_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_d), (*C.float)(_e), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpttrs.f. +func Dpttrs(n, nrhs int, d, e, b []float64, ldb int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dpttrs_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_d), (*C.double)(_e), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cpttrs.f. +func Cpttrs(ul blas.Uplo, n, nrhs int, d []float32, e, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex64 + if len(e) > 0 { + _e = &e[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cpttrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_d), (*C.lapack_complex_float)(_e), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zpttrs.f. +func Zpttrs(ul blas.Uplo, n, nrhs int, d []float64, e, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex128 + if len(e) > 0 { + _e = &e[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zpttrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_d), (*C.lapack_complex_double)(_e), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssbev.f. +func Ssbev(jobz lapack.Job, ul blas.Uplo, n, kd int, ab []float32, ldab int, w, z []float32, ldz int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssbev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbev.f. +func Dsbev(jobz lapack.Job, ul blas.Uplo, n, kd int, ab []float64, ldab int, w, z []float64, ldz int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsbev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssbevd.f. +func Ssbevd(jobz lapack.Job, ul blas.Uplo, n, kd int, ab []float32, ldab int, w, z []float32, ldz int, work []float32, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ssbevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbevd.f. +func Dsbevd(jobz lapack.Job, ul blas.Uplo, n, kd int, ab []float64, ldab int, w, z []float64, ldz int, work []float64, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dsbevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssbevx.f. +func Ssbevx(jobz lapack.Job, rng byte, ul blas.Uplo, n, kd int, ab []float32, ldab int, q []float32, ldq int, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, work []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_ssbevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_q), (C.lapack_int)(ldq), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbevx.f. +func Dsbevx(jobz lapack.Job, rng byte, ul blas.Uplo, n, kd int, ab []float64, ldab int, q []float64, ldq int, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, work []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_dsbevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_q), (C.lapack_int)(ldq), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssbgst.f. +func Ssbgst(vect byte, ul blas.Uplo, n, ka, kb int, ab []float32, ldab int, bb []float32, ldbb int, x []float32, ldx int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *float32 + if len(bb) > 0 { + _bb = &bb[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssbgst_work((C.int)(rowMajor), (C.char)(vect), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_bb), (C.lapack_int)(ldbb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbgst.f. +func Dsbgst(vect byte, ul blas.Uplo, n, ka, kb int, ab []float64, ldab int, bb []float64, ldbb int, x []float64, ldx int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *float64 + if len(bb) > 0 { + _bb = &bb[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsbgst_work((C.int)(rowMajor), (C.char)(vect), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_bb), (C.lapack_int)(ldbb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssbgv.f. +func Ssbgv(jobz lapack.Job, ul blas.Uplo, n, ka, kb int, ab []float32, ldab int, bb []float32, ldbb int, w, z []float32, ldz int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *float32 + if len(bb) > 0 { + _bb = &bb[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssbgv_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_bb), (C.lapack_int)(ldbb), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbgv.f. +func Dsbgv(jobz lapack.Job, ul blas.Uplo, n, ka, kb int, ab []float64, ldab int, bb []float64, ldbb int, w, z []float64, ldz int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *float64 + if len(bb) > 0 { + _bb = &bb[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsbgv_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_bb), (C.lapack_int)(ldbb), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssbgvd.f. +func Ssbgvd(jobz lapack.Job, ul blas.Uplo, n, ka, kb int, ab []float32, ldab int, bb []float32, ldbb int, w, z []float32, ldz int, work []float32, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *float32 + if len(bb) > 0 { + _bb = &bb[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ssbgvd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_bb), (C.lapack_int)(ldbb), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbgvd.f. +func Dsbgvd(jobz lapack.Job, ul blas.Uplo, n, ka, kb int, ab []float64, ldab int, bb []float64, ldbb int, w, z []float64, ldz int, work []float64, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *float64 + if len(bb) > 0 { + _bb = &bb[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dsbgvd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_bb), (C.lapack_int)(ldbb), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssbgvx.f. +func Ssbgvx(jobz lapack.Job, rng byte, ul blas.Uplo, n, ka, kb int, ab []float32, ldab int, bb []float32, ldbb int, q []float32, ldq int, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, work []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *float32 + if len(bb) > 0 { + _bb = &bb[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_ssbgvx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_bb), (C.lapack_int)(ldbb), (*C.float)(_q), (C.lapack_int)(ldq), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbgvx.f. +func Dsbgvx(jobz lapack.Job, rng byte, ul blas.Uplo, n, ka, kb int, ab []float64, ldab int, bb []float64, ldbb int, q []float64, ldq int, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, work []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _bb *float64 + if len(bb) > 0 { + _bb = &bb[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_dsbgvx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(ka), (C.lapack_int)(kb), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_bb), (C.lapack_int)(ldbb), (*C.double)(_q), (C.lapack_int)(ldq), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssbtrd.f. +func Ssbtrd(vect byte, ul blas.Uplo, n, kd int, ab []float32, ldab int, d, e, q []float32, ldq int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssbtrd_work((C.int)(rowMajor), (C.char)(vect), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_d), (*C.float)(_e), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbtrd.f. +func Dsbtrd(vect byte, ul blas.Uplo, n, kd int, ab []float64, ldab int, d, e, q []float64, ldq int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsbtrd_work((C.int)(rowMajor), (C.char)(vect), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_d), (*C.double)(_e), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssfrk.f. +func Ssfrk(transr blas.Transpose, ul blas.Uplo, trans blas.Transpose, n, k int, alpha float32, a []float32, lda int, beta float32, c []float32) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + return isZero(C.LAPACKE_ssfrk_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(k), (C.float)(alpha), (*C.float)(_a), (C.lapack_int)(lda), (C.float)(beta), (*C.float)(_c))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsfrk.f. +func Dsfrk(transr blas.Transpose, ul blas.Uplo, trans blas.Transpose, n, k int, alpha float64, a []float64, lda int, beta float64, c []float64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + return isZero(C.LAPACKE_dsfrk_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.char)(trans), (C.lapack_int)(n), (C.lapack_int)(k), (C.double)(alpha), (*C.double)(_a), (C.lapack_int)(lda), (C.double)(beta), (*C.double)(_c))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspcon.f. +func Sspcon(ul blas.Uplo, n int, ap []float32, ipiv []int32, anorm float32, rcond, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sspcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspcon.f. +func Dspcon(ul blas.Uplo, n int, ap []float64, ipiv []int32, anorm float64, rcond, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dspcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cspcon.f. +func Cspcon(ul blas.Uplo, n int, ap []complex64, ipiv []int32, anorm float32, rcond []float32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cspcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zspcon.f. +func Zspcon(ul blas.Uplo, n int, ap []complex128, ipiv []int32, anorm float64, rcond []float64, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zspcon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspev.f. +func Sspev(jobz lapack.Job, ul blas.Uplo, n int, ap, w, z []float32, ldz int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sspev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspev.f. +func Dspev(jobz lapack.Job, ul blas.Uplo, n int, ap, w, z []float64, ldz int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dspev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspevd.f. +func Sspevd(jobz lapack.Job, ul blas.Uplo, n int, ap, w, z []float32, ldz int, work []float32, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sspevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspevd.f. +func Dspevd(jobz lapack.Job, ul blas.Uplo, n int, ap, w, z []float64, ldz int, work []float64, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dspevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspevx.f. +func Sspevx(jobz lapack.Job, rng byte, ul blas.Uplo, n int, ap []float32, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, work []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_sspevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspevx.f. +func Dspevx(jobz lapack.Job, rng byte, ul blas.Uplo, n int, ap []float64, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, work []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_dspevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspgst.f. +func Sspgst(itype int, ul blas.Uplo, n int, ap, bp []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *float32 + if len(bp) > 0 { + _bp = &bp[0] + } + return isZero(C.LAPACKE_sspgst_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_bp))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspgst.f. +func Dspgst(itype int, ul blas.Uplo, n int, ap, bp []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *float64 + if len(bp) > 0 { + _bp = &bp[0] + } + return isZero(C.LAPACKE_dspgst_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_bp))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspgv.f. +func Sspgv(itype int, jobz lapack.Job, ul blas.Uplo, n int, ap, bp, w, z []float32, ldz int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *float32 + if len(bp) > 0 { + _bp = &bp[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sspgv_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_bp), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspgv.f. +func Dspgv(itype int, jobz lapack.Job, ul blas.Uplo, n int, ap, bp, w, z []float64, ldz int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *float64 + if len(bp) > 0 { + _bp = &bp[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dspgv_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_bp), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspgvd.f. +func Sspgvd(itype int, jobz lapack.Job, ul blas.Uplo, n int, ap, bp, w, z []float32, ldz int, work []float32, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *float32 + if len(bp) > 0 { + _bp = &bp[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sspgvd_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_bp), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspgvd.f. +func Dspgvd(itype int, jobz lapack.Job, ul blas.Uplo, n int, ap, bp, w, z []float64, ldz int, work []float64, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *float64 + if len(bp) > 0 { + _bp = &bp[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dspgvd_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_bp), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspgvx.f. +func Sspgvx(itype int, jobz lapack.Job, rng byte, ul blas.Uplo, n int, ap, bp []float32, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, work []float32, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *float32 + if len(bp) > 0 { + _bp = &bp[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_sspgvx_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_bp), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspgvx.f. +func Dspgvx(itype int, jobz lapack.Job, rng byte, ul blas.Uplo, n int, ap, bp []float64, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, work []float64, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _bp *float64 + if len(bp) > 0 { + _bp = &bp[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_dspgvx_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_bp), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssprfs.f. +func Ssprfs(ul blas.Uplo, n, nrhs int, ap, afp []float32, ipiv []int32, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *float32 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ssprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.float)(_afp), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsprfs.f. +func Dsprfs(ul blas.Uplo, n, nrhs int, ap, afp []float64, ipiv []int32, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *float64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dsprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.double)(_afp), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csprfs.f. +func Csprfs(ul blas.Uplo, n, nrhs int, ap, afp []complex64, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_csprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_afp), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsprfs.f. +func Zsprfs(ul blas.Uplo, n, nrhs int, ap, afp []complex128, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex128 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zsprfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_afp), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspsv.f. +func Sspsv(ul blas.Uplo, n, nrhs int, ap []float32, ipiv []int32, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_sspsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspsv.f. +func Dspsv(ul blas.Uplo, n, nrhs int, ap []float64, ipiv []int32, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dspsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cspsv.f. +func Cspsv(ul blas.Uplo, n, nrhs int, ap []complex64, ipiv []int32, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_cspsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zspsv.f. +func Zspsv(ul blas.Uplo, n, nrhs int, ap []complex128, ipiv []int32, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zspsv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sspsvx.f. +func Sspsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []float32, ipiv []int32, b []float32, ldb int, x []float32, ldx int, rcond, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *float32 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sspsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.float)(_afp), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dspsvx.f. +func Dspsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []float64, ipiv []int32, b []float64, ldb int, x []float64, ldx int, rcond, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *float64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dspsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.double)(_afp), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cspsvx.f. +func Cspsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []complex64, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex64 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cspsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_afp), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zspsvx.f. +func Zspsvx(fact byte, ul blas.Uplo, n, nrhs int, ap, afp []complex128, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _afp *complex128 + if len(afp) > 0 { + _afp = &afp[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zspsvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_afp), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssptrd.f. +func Ssptrd(ul blas.Uplo, n int, ap, d, e, tau []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + return isZero(C.LAPACKE_ssptrd_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_d), (*C.float)(_e), (*C.float)(_tau))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsptrd.f. +func Dsptrd(ul blas.Uplo, n int, ap, d, e, tau []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + return isZero(C.LAPACKE_dsptrd_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_d), (*C.double)(_e), (*C.double)(_tau))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssptrf.f. +func Ssptrf(ul blas.Uplo, n int, ap []float32, ipiv []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_ssptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsptrf.f. +func Dsptrf(ul blas.Uplo, n int, ap []float64, ipiv []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_dsptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csptrf.f. +func Csptrf(ul blas.Uplo, n int, ap []complex64, ipiv []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_csptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsptrf.f. +func Zsptrf(ul blas.Uplo, n int, ap []complex128, ipiv []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + return isZero(C.LAPACKE_zsptrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssptri.f. +func Ssptri(ul blas.Uplo, n int, ap []float32, ipiv []int32, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.lapack_int)(_ipiv), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsptri.f. +func Dsptri(ul blas.Uplo, n int, ap []float64, ipiv []int32, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.lapack_int)(_ipiv), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csptri.f. +func Csptri(ul blas.Uplo, n int, ap []complex64, ipiv []int32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsptri.f. +func Zsptri(ul blas.Uplo, n int, ap []complex128, ipiv []int32, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsptri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssptrs.f. +func Ssptrs(ul blas.Uplo, n, nrhs int, ap []float32, ipiv []int32, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ssptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsptrs.f. +func Dsptrs(ul blas.Uplo, n, nrhs int, ap []float64, ipiv []int32, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dsptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csptrs.f. +func Csptrs(ul blas.Uplo, n, nrhs int, ap []complex64, ipiv []int32, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_csptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsptrs.f. +func Zsptrs(ul blas.Uplo, n, nrhs int, ap []complex128, ipiv []int32, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zsptrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstebz.f. +func Sstebz(rng, order byte, n int, vl, vu float32, il, iu int, abstol float32, d, e []float32, m, nsplit []int32, w []float32, iblock, isplit []int32, work []float32, iwork []int32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _nsplit *int32 + if len(nsplit) > 0 { + _nsplit = &nsplit[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _iblock *int32 + if len(iblock) > 0 { + _iblock = &iblock[0] + } + var _isplit *int32 + if len(isplit) > 0 { + _isplit = &isplit[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sstebz_work((C.char)(rng), (C.char)(order), (C.lapack_int)(n), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.float)(_d), (*C.float)(_e), (*C.lapack_int)(_m), (*C.lapack_int)(_nsplit), (*C.float)(_w), (*C.lapack_int)(_iblock), (*C.lapack_int)(_isplit), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstebz.f. +func Dstebz(rng, order byte, n int, vl, vu float64, il, iu int, abstol float64, d, e []float64, m, nsplit []int32, w []float64, iblock, isplit []int32, work []float64, iwork []int32) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _nsplit *int32 + if len(nsplit) > 0 { + _nsplit = &nsplit[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _iblock *int32 + if len(iblock) > 0 { + _iblock = &iblock[0] + } + var _isplit *int32 + if len(isplit) > 0 { + _isplit = &isplit[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dstebz_work((C.char)(rng), (C.char)(order), (C.lapack_int)(n), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.double)(_d), (*C.double)(_e), (*C.lapack_int)(_m), (*C.lapack_int)(_nsplit), (*C.double)(_w), (*C.lapack_int)(_iblock), (*C.lapack_int)(_isplit), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstedc.f. +func Sstedc(compz lapack.Comp, n int, d, e, z []float32, ldz int, work []float32, lwork int, iwork []int32, liwork int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sstedc_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstedc.f. +func Dstedc(compz lapack.Comp, n int, d, e, z []float64, ldz int, work []float64, lwork int, iwork []int32, liwork int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dstedc_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cstedc.f. +func Cstedc(compz lapack.Comp, n int, d, e []float32, z []complex64, ldz int, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32, liwork int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cstedc_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zstedc.f. +func Zstedc(compz lapack.Comp, n int, d, e []float64, z []complex128, ldz int, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32, liwork int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zstedc_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstegr.f. +func Sstegr(jobz lapack.Job, rng byte, n int, d, e []float32, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, isuppz []int32, work []float32, lwork int, iwork []int32, liwork int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sstegr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstegr.f. +func Dstegr(jobz lapack.Job, rng byte, n int, d, e []float64, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, isuppz []int32, work []float64, lwork int, iwork []int32, liwork int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dstegr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cstegr.f. +func Cstegr(jobz lapack.Job, rng byte, n int, d, e []float32, vl, vu float32, il, iu int, abstol float32, m []int32, w []float32, z []complex64, ldz int, isuppz []int32, work []float32, lwork int, iwork []int32, liwork int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cstegr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zstegr.f. +func Zstegr(jobz lapack.Job, rng byte, n int, d, e []float64, vl, vu float64, il, iu int, abstol float64, m []int32, w []float64, z []complex128, ldz int, isuppz []int32, work []float64, lwork int, iwork []int32, liwork int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zstegr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstein.f. +func Sstein(n int, d, e []float32, m int, w []float32, iblock, isplit []int32, z []float32, ldz int, work []float32, iwork, ifailv []int32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _iblock *int32 + if len(iblock) > 0 { + _iblock = &iblock[0] + } + var _isplit *int32 + if len(isplit) > 0 { + _isplit = &isplit[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifailv *int32 + if len(ifailv) > 0 { + _ifailv = &ifailv[0] + } + return isZero(C.LAPACKE_sstein_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.lapack_int)(m), (*C.float)(_w), (*C.lapack_int)(_iblock), (*C.lapack_int)(_isplit), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifailv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstein.f. +func Dstein(n int, d, e []float64, m int, w []float64, iblock, isplit []int32, z []float64, ldz int, work []float64, iwork, ifailv []int32) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _iblock *int32 + if len(iblock) > 0 { + _iblock = &iblock[0] + } + var _isplit *int32 + if len(isplit) > 0 { + _isplit = &isplit[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifailv *int32 + if len(ifailv) > 0 { + _ifailv = &ifailv[0] + } + return isZero(C.LAPACKE_dstein_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.lapack_int)(m), (*C.double)(_w), (*C.lapack_int)(_iblock), (*C.lapack_int)(_isplit), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifailv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cstein.f. +func Cstein(n int, d, e []float32, m int, w []float32, iblock, isplit []int32, z []complex64, ldz int, work []float32, iwork, ifailv []int32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _iblock *int32 + if len(iblock) > 0 { + _iblock = &iblock[0] + } + var _isplit *int32 + if len(isplit) > 0 { + _isplit = &isplit[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifailv *int32 + if len(ifailv) > 0 { + _ifailv = &ifailv[0] + } + return isZero(C.LAPACKE_cstein_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.lapack_int)(m), (*C.float)(_w), (*C.lapack_int)(_iblock), (*C.lapack_int)(_isplit), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifailv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zstein.f. +func Zstein(n int, d, e []float64, m int, w []float64, iblock, isplit []int32, z []complex128, ldz int, work []float64, iwork, ifailv []int32) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _iblock *int32 + if len(iblock) > 0 { + _iblock = &iblock[0] + } + var _isplit *int32 + if len(isplit) > 0 { + _isplit = &isplit[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifailv *int32 + if len(ifailv) > 0 { + _ifailv = &ifailv[0] + } + return isZero(C.LAPACKE_zstein_work((C.int)(rowMajor), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.lapack_int)(m), (*C.double)(_w), (*C.lapack_int)(_iblock), (*C.lapack_int)(_isplit), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifailv))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstemr.f. +func Sstemr(jobz lapack.Job, rng byte, n int, d, e []float32, vl, vu float32, il, iu int, m []int32, w, z []float32, ldz, nzc int, isuppz, tryrac []int32, work []float32, lwork int, iwork []int32, liwork int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _tryrac *int32 + if len(tryrac) > 0 { + _tryrac = &tryrac[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sstemr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (C.lapack_int)(nzc), (*C.lapack_int)(_isuppz), (*C.lapack_logical)(_tryrac), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstemr.f. +func Dstemr(jobz lapack.Job, rng byte, n int, d, e []float64, vl, vu float64, il, iu int, m []int32, w, z []float64, ldz, nzc int, isuppz, tryrac []int32, work []float64, lwork int, iwork []int32, liwork int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _tryrac *int32 + if len(tryrac) > 0 { + _tryrac = &tryrac[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dstemr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (C.lapack_int)(nzc), (*C.lapack_int)(_isuppz), (*C.lapack_logical)(_tryrac), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cstemr.f. +func Cstemr(jobz lapack.Job, rng byte, n int, d, e []float32, vl, vu float32, il, iu int, m []int32, w []float32, z []complex64, ldz, nzc int, isuppz, tryrac []int32, work []float32, lwork int, iwork []int32, liwork int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _tryrac *int32 + if len(tryrac) > 0 { + _tryrac = &tryrac[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cstemr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (*C.lapack_int)(_m), (*C.float)(_w), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (C.lapack_int)(nzc), (*C.lapack_int)(_isuppz), (*C.lapack_logical)(_tryrac), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zstemr.f. +func Zstemr(jobz lapack.Job, rng byte, n int, d, e []float64, vl, vu float64, il, iu int, m []int32, w []float64, z []complex128, ldz, nzc int, isuppz, tryrac []int32, work []float64, lwork int, iwork []int32, liwork int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _tryrac *int32 + if len(tryrac) > 0 { + _tryrac = &tryrac[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zstemr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (*C.lapack_int)(_m), (*C.double)(_w), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (C.lapack_int)(nzc), (*C.lapack_int)(_isuppz), (*C.lapack_logical)(_tryrac), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssteqr.f. +func Ssteqr(compz lapack.Comp, n int, d, e, z []float32, ldz int, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssteqr_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsteqr.f. +func Dsteqr(compz lapack.Comp, n int, d, e, z []float64, ldz int, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsteqr_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csteqr.f. +func Csteqr(compz lapack.Comp, n int, d, e []float32, z []complex64, ldz int, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csteqr_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsteqr.f. +func Zsteqr(compz lapack.Comp, n int, d, e []float64, z []complex128, ldz int, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsteqr_work((C.int)(rowMajor), (C.char)(compz), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssterf.f. +func Ssterf(n int, d, e []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + return isZero(C.LAPACKE_ssterf_work((C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsterf.f. +func Dsterf(n int, d, e []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + return isZero(C.LAPACKE_dsterf_work((C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstev.f. +func Sstev(jobz lapack.Job, n int, d, e, z []float32, ldz int, work []float32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sstev_work((C.int)(rowMajor), (C.char)(jobz), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstev.f. +func Dstev(jobz lapack.Job, n int, d, e, z []float64, ldz int, work []float64) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dstev_work((C.int)(rowMajor), (C.char)(jobz), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstevd.f. +func Sstevd(jobz lapack.Job, n int, d, e, z []float32, ldz int, work []float32, lwork int, iwork []int32, liwork int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sstevd_work((C.int)(rowMajor), (C.char)(jobz), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstevd.f. +func Dstevd(jobz lapack.Job, n int, d, e, z []float64, ldz int, work []float64, lwork int, iwork []int32, liwork int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dstevd_work((C.int)(rowMajor), (C.char)(jobz), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstevr.f. +func Sstevr(jobz lapack.Job, rng byte, n int, d, e []float32, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, isuppz []int32, work []float32, lwork int, iwork []int32, liwork int) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sstevr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstevr.f. +func Dstevr(jobz lapack.Job, rng byte, n int, d, e []float64, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, isuppz []int32, work []float64, lwork int, iwork []int32, liwork int) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dstevr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstevx.f. +func Sstevx(jobz lapack.Job, rng byte, n int, d, e []float32, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, work []float32, iwork, ifail []int32) bool { + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_sstevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.float)(_d), (*C.float)(_e), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstevx.f. +func Dstevx(jobz lapack.Job, rng byte, n int, d, e []float64, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, work []float64, iwork, ifail []int32) bool { + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_dstevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.lapack_int)(n), (*C.double)(_d), (*C.double)(_e), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssycon.f. +func Ssycon(ul blas.Uplo, n int, a []float32, lda int, ipiv []int32, anorm float32, rcond, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ssycon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsycon.f. +func Dsycon(ul blas.Uplo, n int, a []float64, lda int, ipiv []int32, anorm float64, rcond, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dsycon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csycon.f. +func Csycon(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, anorm float32, rcond []float32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csycon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (C.float)(anorm), (*C.float)(_rcond), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsycon.f. +func Zsycon(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, anorm float64, rcond []float64, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsycon_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (C.double)(anorm), (*C.double)(_rcond), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssyequb.f. +func Ssyequb(ul blas.Uplo, n int, a []float32, lda int, s, scond, amax, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssyequb_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsyequb.f. +func Dsyequb(ul blas.Uplo, n int, a []float64, lda int, s, scond, amax, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsyequb_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csyequb.f. +func Csyequb(ul blas.Uplo, n int, a []complex64, lda int, s, scond, amax []float32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float32 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float32 + if len(amax) > 0 { + _amax = &amax[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csyequb_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_s), (*C.float)(_scond), (*C.float)(_amax), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsyequb.f. +func Zsyequb(ul blas.Uplo, n int, a []complex128, lda int, s, scond, amax []float64, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _scond *float64 + if len(scond) > 0 { + _scond = &scond[0] + } + var _amax *float64 + if len(amax) > 0 { + _amax = &amax[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsyequb_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_s), (*C.double)(_scond), (*C.double)(_amax), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssyev.f. +func Ssyev(jobz lapack.Job, ul blas.Uplo, n int, a []float32, lda int, w, work []float32, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssyev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_w), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsyev.f. +func Dsyev(jobz lapack.Job, ul blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsyev_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_w), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssyevd.f. +func Ssyevd(jobz lapack.Job, ul blas.Uplo, n int, a []float32, lda int, w, work []float32, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ssyevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_w), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsyevd.f. +func Dsyevd(jobz lapack.Job, ul blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dsyevd_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_w), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssyevr.f. +func Ssyevr(jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []float32, lda int, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, isuppz []int32, work []float32, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ssyevr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsyevr.f. +func Dsyevr(jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []float64, lda int, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, isuppz []int32, work []float64, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _isuppz *int32 + if len(isuppz) > 0 { + _isuppz = &isuppz[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dsyevr_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_isuppz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssyevx.f. +func Ssyevx(jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []float32, lda int, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, work []float32, lwork int, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_ssyevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsyevx.f. +func Dsyevx(jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []float64, lda int, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, work []float64, lwork int, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_dsyevx_work((C.int)(rowMajor), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssygst.f. +func Ssygst(itype int, ul blas.Uplo, n int, a []float32, lda int, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ssygst_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsygst.f. +func Dsygst(itype int, ul blas.Uplo, n int, a []float64, lda int, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dsygst_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssygv.f. +func Ssygv(itype int, jobz lapack.Job, ul blas.Uplo, n int, a []float32, lda int, b []float32, ldb int, w, work []float32, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssygv_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_w), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsygv.f. +func Dsygv(itype int, jobz lapack.Job, ul blas.Uplo, n int, a []float64, lda int, b []float64, ldb int, w, work []float64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsygv_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_w), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssygvd.f. +func Ssygvd(itype int, jobz lapack.Job, ul blas.Uplo, n int, a []float32, lda int, b []float32, ldb int, w, work []float32, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ssygvd_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_w), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsygvd.f. +func Dsygvd(itype int, jobz lapack.Job, ul blas.Uplo, n int, a []float64, lda int, b []float64, ldb int, w, work []float64, lwork int, iwork []int32, liwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dsygvd_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_w), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssygvx.f. +func Ssygvx(itype int, jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []float32, lda int, b []float32, ldb int, vl, vu float32, il, iu int, abstol float32, m []int32, w, z []float32, ldz int, work []float32, lwork int, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float32 + if len(w) > 0 { + _w = &w[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_ssygvx_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (C.float)(vl), (C.float)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.float)(abstol), (*C.lapack_int)(_m), (*C.float)(_w), (*C.float)(_z), (C.lapack_int)(ldz), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsygvx.f. +func Dsygvx(itype int, jobz lapack.Job, rng byte, ul blas.Uplo, n int, a []float64, lda int, b []float64, ldb int, vl, vu float64, il, iu int, abstol float64, m []int32, w, z []float64, ldz int, work []float64, lwork int, iwork, ifail []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _w *float64 + if len(w) > 0 { + _w = &w[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + var _ifail *int32 + if len(ifail) > 0 { + _ifail = &ifail[0] + } + return isZero(C.LAPACKE_dsygvx_work((C.int)(rowMajor), (C.lapack_int)(itype), (C.char)(jobz), (C.char)(rng), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (C.double)(vl), (C.double)(vu), (C.lapack_int)(il), (C.lapack_int)(iu), (C.double)(abstol), (*C.lapack_int)(_m), (*C.double)(_w), (*C.double)(_z), (C.lapack_int)(ldz), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (*C.lapack_int)(_ifail))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssyrfs.f. +func Ssyrfs(ul blas.Uplo, n, nrhs int, a []float32, lda int, af []float32, ldaf int, ipiv []int32, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _af *float32 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ssyrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsyrfs.f. +func Dsyrfs(ul blas.Uplo, n, nrhs int, a []float64, lda int, af []float64, ldaf int, ipiv []int32, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _af *float64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dsyrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csyrfs.f. +func Csyrfs(ul blas.Uplo, n, nrhs int, a []complex64, lda int, af []complex64, ldaf int, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_csyrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsyrfs.f. +func Zsyrfs(ul blas.Uplo, n, nrhs int, a []complex128, lda int, af []complex128, ldaf int, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex128 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zsyrfs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssysv.f. +func Ssysv(ul blas.Uplo, n, nrhs int, a []float32, lda int, ipiv []int32, b []float32, ldb int, work []float32, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssysv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsysv.f. +func Dsysv(ul blas.Uplo, n, nrhs int, a []float64, lda int, ipiv []int32, b []float64, ldb int, work []float64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsysv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csysv.f. +func Csysv(ul blas.Uplo, n, nrhs int, a []complex64, lda int, ipiv []int32, b []complex64, ldb int, work []complex64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csysv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsysv.f. +func Zsysv(ul blas.Uplo, n, nrhs int, a []complex128, lda int, ipiv []int32, b []complex128, ldb int, work []complex128, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsysv_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssysvx.f. +func Ssysvx(fact byte, ul blas.Uplo, n, nrhs int, a []float32, lda int, af []float32, ldaf int, ipiv []int32, b []float32, ldb int, x []float32, ldx int, rcond, ferr, berr, work []float32, lwork int, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _af *float32 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ssysvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsysvx.f. +func Dsysvx(fact byte, ul blas.Uplo, n, nrhs int, a []float64, lda int, af []float64, ldaf int, ipiv []int32, b []float64, ldb int, x []float64, ldx int, rcond, ferr, berr, work []float64, lwork int, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _af *float64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dsysvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csysvx.f. +func Csysvx(fact byte, ul blas.Uplo, n, nrhs int, a []complex64, lda int, af []complex64, ldaf int, ipiv []int32, b []complex64, ldb int, x []complex64, ldx int, rcond, ferr, berr []float32, work []complex64, lwork int, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex64 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_csysvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_rcond), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsysvx.f. +func Zsysvx(fact byte, ul blas.Uplo, n, nrhs int, a []complex128, lda int, af []complex128, ldaf int, ipiv []int32, b []complex128, ldb int, x []complex128, ldx int, rcond, ferr, berr []float64, work []complex128, lwork int, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _af *complex128 + if len(af) > 0 { + _af = &af[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zsysvx_work((C.int)(rowMajor), (C.char)(fact), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_af), (C.lapack_int)(ldaf), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_rcond), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssytrd.f. +func Ssytrd(ul blas.Uplo, n int, a []float32, lda int, d, e, tau, work []float32, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssytrd_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_d), (*C.float)(_e), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsytrd.f. +func Dsytrd(ul blas.Uplo, n int, a []float64, lda int, d, e, tau, work []float64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsytrd_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_d), (*C.double)(_e), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssytrf.f. +func Ssytrf(ul blas.Uplo, n int, a []float32, lda int, ipiv []int32, work []float32, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssytrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsytrf.f. +func Dsytrf(ul blas.Uplo, n int, a []float64, lda int, ipiv []int32, work []float64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsytrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytrf.f. +func Csytrf(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, work []complex64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csytrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsytrf.f. +func Zsytrf(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, work []complex128, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsytrf_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssytri.f. +func Ssytri(ul blas.Uplo, n int, a []float32, lda int, ipiv []int32, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssytri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsytri.f. +func Dsytri(ul blas.Uplo, n int, a []float64, lda int, ipiv []int32, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsytri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytri.f. +func Csytri(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csytri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsytri.f. +func Zsytri(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsytri_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssytrs.f. +func Ssytrs(ul blas.Uplo, n, nrhs int, a []float32, lda int, ipiv []int32, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ssytrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsytrs.f. +func Dsytrs(ul blas.Uplo, n, nrhs int, a []float64, lda int, ipiv []int32, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dsytrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytrs.f. +func Csytrs(ul blas.Uplo, n, nrhs int, a []complex64, lda int, ipiv []int32, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_csytrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsytrs.f. +func Zsytrs(ul blas.Uplo, n, nrhs int, a []complex128, lda int, ipiv []int32, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_zsytrs_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stbcon.f. +func Stbcon(norm byte, ul blas.Uplo, d blas.Diag, n, kd int, ab []float32, ldab int, rcond, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_stbcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtbcon.f. +func Dtbcon(norm byte, ul blas.Uplo, d blas.Diag, n, kd int, ab []float64, ldab int, rcond, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtbcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctbcon.f. +func Ctbcon(norm byte, ul blas.Uplo, d blas.Diag, n, kd int, ab []complex64, ldab int, rcond []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ctbcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.float)(_rcond), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztbcon.f. +func Ztbcon(norm byte, ul blas.Uplo, d blas.Diag, n, kd int, ab []complex128, ldab int, rcond []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ztbcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.double)(_rcond), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stbrfs.f. +func Stbrfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, kd, nrhs int, ab []float32, ldab int, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_stbrfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtbrfs.f. +func Dtbrfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, kd, nrhs int, ab []float64, ldab int, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtbrfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctbrfs.f. +func Ctbrfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, kd, nrhs int, ab []complex64, ldab int, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ctbrfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztbrfs.f. +func Ztbrfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, kd, nrhs int, ab []complex128, ldab int, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ztbrfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stbtrs.f. +func Stbtrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, kd, nrhs int, ab []float32, ldab int, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *float32 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_stbtrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.float)(_ab), (C.lapack_int)(ldab), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtbtrs.f. +func Dtbtrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, kd, nrhs int, ab []float64, ldab int, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *float64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dtbtrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.double)(_ab), (C.lapack_int)(ldab), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctbtrs.f. +func Ctbtrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, kd, nrhs int, ab []complex64, ldab int, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *complex64 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ctbtrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztbtrs.f. +func Ztbtrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, kd, nrhs int, ab []complex128, ldab int, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ab *complex128 + if len(ab) > 0 { + _ab = &ab[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ztbtrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(kd), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ab), (C.lapack_int)(ldab), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stfsm.f. +func Stfsm(transr blas.Transpose, side blas.Side, ul blas.Uplo, trans blas.Transpose, d blas.Diag, m, n int, alpha float32, a, b []float32, ldb int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_stfsm_work((C.int)(rowMajor), (C.char)(transr), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(m), (C.lapack_int)(n), (C.float)(alpha), (*C.float)(_a), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtfsm.f. +func Dtfsm(transr blas.Transpose, side blas.Side, ul blas.Uplo, trans blas.Transpose, d blas.Diag, m, n int, alpha float64, a, b []float64, ldb int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dtfsm_work((C.int)(rowMajor), (C.char)(transr), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(m), (C.lapack_int)(n), (C.double)(alpha), (*C.double)(_a), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctfsm.f. +func Ctfsm(transr blas.Transpose, side blas.Side, ul blas.Uplo, trans blas.Transpose, d blas.Diag, m, n int, alpha complex64, a, b []complex64, ldb int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ctfsm_work((C.int)(rowMajor), (C.char)(transr), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_complex_float)(alpha), (*C.lapack_complex_float)(_a), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztfsm.f. +func Ztfsm(transr blas.Transpose, side blas.Side, ul blas.Uplo, trans blas.Transpose, d blas.Diag, m, n int, alpha complex128, a, b []complex128, ldb int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ztfsm_work((C.int)(rowMajor), (C.char)(transr), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_complex_double)(alpha), (*C.lapack_complex_double)(_a), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stftri.f. +func Stftri(transr blas.Transpose, ul blas.Uplo, d blas.Diag, n int, a []float32) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_stftri_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.float)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtftri.f. +func Dtftri(transr blas.Transpose, ul blas.Uplo, d blas.Diag, n int, a []float64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dtftri_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.double)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctftri.f. +func Ctftri(transr blas.Transpose, ul blas.Uplo, d blas.Diag, n int, a []complex64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_ctftri_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_float)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztftri.f. +func Ztftri(transr blas.Transpose, ul blas.Uplo, d blas.Diag, n int, a []complex128) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_ztftri_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_double)(_a))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stfttp.f. +func Stfttp(transr blas.Transpose, ul blas.Uplo, n int, arf, ap []float32) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _arf *float32 + if len(arf) > 0 { + _arf = &arf[0] + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_stfttp_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_arf), (*C.float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtfttp.f. +func Dtfttp(transr blas.Transpose, ul blas.Uplo, n int, arf, ap []float64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _arf *float64 + if len(arf) > 0 { + _arf = &arf[0] + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_dtfttp_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_arf), (*C.double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctfttp.f. +func Ctfttp(transr blas.Transpose, ul blas.Uplo, n int, arf, ap []complex64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _arf *complex64 + if len(arf) > 0 { + _arf = &arf[0] + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_ctfttp_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_arf), (*C.lapack_complex_float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztfttp.f. +func Ztfttp(transr blas.Transpose, ul blas.Uplo, n int, arf, ap []complex128) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _arf *complex128 + if len(arf) > 0 { + _arf = &arf[0] + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_ztfttp_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_arf), (*C.lapack_complex_double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stfttr.f. +func Stfttr(transr blas.Transpose, ul blas.Uplo, n int, arf, a []float32, lda int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _arf *float32 + if len(arf) > 0 { + _arf = &arf[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_stfttr_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_arf), (*C.float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtfttr.f. +func Dtfttr(transr blas.Transpose, ul blas.Uplo, n int, arf, a []float64, lda int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _arf *float64 + if len(arf) > 0 { + _arf = &arf[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dtfttr_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_arf), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctfttr.f. +func Ctfttr(transr blas.Transpose, ul blas.Uplo, n int, arf, a []complex64, lda int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _arf *complex64 + if len(arf) > 0 { + _arf = &arf[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_ctfttr_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_arf), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztfttr.f. +func Ztfttr(transr blas.Transpose, ul blas.Uplo, n int, arf, a []complex128, lda int) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _arf *complex128 + if len(arf) > 0 { + _arf = &arf[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_ztfttr_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_arf), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stgevc.f. +func Stgevc(side blas.Side, howmny byte, sel []int32, n int, s []float32, lds int, p []float32, ldp int, vl []float32, ldvl int, vr []float32, ldvr, mm int, m []int32, work []float32) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _p *float32 + if len(p) > 0 { + _p = &p[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_stgevc_work((C.int)(rowMajor), (C.char)(side), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.float)(_s), (C.lapack_int)(lds), (*C.float)(_p), (C.lapack_int)(ldp), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtgevc.f. +func Dtgevc(side blas.Side, howmny byte, sel []int32, n int, s []float64, lds int, p []float64, ldp int, vl []float64, ldvl int, vr []float64, ldvr, mm int, m []int32, work []float64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _p *float64 + if len(p) > 0 { + _p = &p[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dtgevc_work((C.int)(rowMajor), (C.char)(side), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.double)(_s), (C.lapack_int)(lds), (*C.double)(_p), (C.lapack_int)(ldp), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctgevc.f. +func Ctgevc(side blas.Side, howmny byte, sel []int32, n int, s []complex64, lds int, p []complex64, ldp int, vl []complex64, ldvl int, vr []complex64, ldvr, mm int, m []int32, work []complex64, rwork []float32) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _s *complex64 + if len(s) > 0 { + _s = &s[0] + } + var _p *complex64 + if len(p) > 0 { + _p = &p[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ctgevc_work((C.int)(rowMajor), (C.char)(side), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_float)(_s), (C.lapack_int)(lds), (*C.lapack_complex_float)(_p), (C.lapack_int)(ldp), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztgevc.f. +func Ztgevc(side blas.Side, howmny byte, sel []int32, n int, s []complex128, lds int, p []complex128, ldp int, vl []complex128, ldvl int, vr []complex128, ldvr, mm int, m []int32, work []complex128, rwork []float64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _s *complex128 + if len(s) > 0 { + _s = &s[0] + } + var _p *complex128 + if len(p) > 0 { + _p = &p[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ztgevc_work((C.int)(rowMajor), (C.char)(side), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_double)(_s), (C.lapack_int)(lds), (*C.lapack_complex_double)(_p), (C.lapack_int)(ldp), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stgexc.f. +func Stgexc(wantq, wantz int32, n int, a []float32, lda int, b []float32, ldb int, q []float32, ldq int, z []float32, ldz int, ifst, ilst []int32, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _ifst *int32 + if len(ifst) > 0 { + _ifst = &ifst[0] + } + var _ilst *int32 + if len(ilst) > 0 { + _ilst = &ilst[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_stgexc_work((C.int)(rowMajor), (C.lapack_logical)(wantq), (C.lapack_logical)(wantz), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_ifst), (*C.lapack_int)(_ilst), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtgexc.f. +func Dtgexc(wantq, wantz int32, n int, a []float64, lda int, b []float64, ldb int, q []float64, ldq int, z []float64, ldz int, ifst, ilst []int32, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _ifst *int32 + if len(ifst) > 0 { + _ifst = &ifst[0] + } + var _ilst *int32 + if len(ilst) > 0 { + _ilst = &ilst[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dtgexc_work((C.int)(rowMajor), (C.lapack_logical)(wantq), (C.lapack_logical)(wantz), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_ifst), (*C.lapack_int)(_ilst), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctgexc.f. +func Ctgexc(wantq, wantz int32, n int, a []complex64, lda int, b []complex64, ldb int, q []complex64, ldq int, z []complex64, ldz, ifst, ilst int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + return isZero(C.LAPACKE_ctgexc_work((C.int)(rowMajor), (C.lapack_logical)(wantq), (C.lapack_logical)(wantz), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (C.lapack_int)(ifst), (C.lapack_int)(ilst))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztgexc.f. +func Ztgexc(wantq, wantz int32, n int, a []complex128, lda int, b []complex128, ldb int, q []complex128, ldq int, z []complex128, ldz, ifst, ilst int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + return isZero(C.LAPACKE_ztgexc_work((C.int)(rowMajor), (C.lapack_logical)(wantq), (C.lapack_logical)(wantz), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (C.lapack_int)(ifst), (C.lapack_int)(ilst))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stgsen.f. +func Stgsen(ijob lapack.Job, wantq, wantz int32, sel []int32, n int, a []float32, lda int, b []float32, ldb int, alphar, alphai, beta, q []float32, ldq int, z []float32, ldz int, m []int32, pl, pr, dif, work []float32, lwork int, iwork []int32, liwork int) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _alphar *float32 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float32 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float32 + if len(beta) > 0 { + _beta = &beta[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _z *float32 + if len(z) > 0 { + _z = &z[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _pl *float32 + if len(pl) > 0 { + _pl = &pl[0] + } + var _pr *float32 + if len(pr) > 0 { + _pr = &pr[0] + } + var _dif *float32 + if len(dif) > 0 { + _dif = &dif[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_stgsen_work((C.int)(rowMajor), (C.lapack_int)(ijob), (C.lapack_logical)(wantq), (C.lapack_logical)(wantz), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_alphar), (*C.float)(_alphai), (*C.float)(_beta), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_m), (*C.float)(_pl), (*C.float)(_pr), (*C.float)(_dif), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtgsen.f. +func Dtgsen(ijob lapack.Job, wantq, wantz int32, sel []int32, n int, a []float64, lda int, b []float64, ldb int, alphar, alphai, beta, q []float64, ldq int, z []float64, ldz int, m []int32, pl, pr, dif, work []float64, lwork int, iwork []int32, liwork int) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _alphar *float64 + if len(alphar) > 0 { + _alphar = &alphar[0] + } + var _alphai *float64 + if len(alphai) > 0 { + _alphai = &alphai[0] + } + var _beta *float64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _z *float64 + if len(z) > 0 { + _z = &z[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _pl *float64 + if len(pl) > 0 { + _pl = &pl[0] + } + var _pr *float64 + if len(pr) > 0 { + _pr = &pr[0] + } + var _dif *float64 + if len(dif) > 0 { + _dif = &dif[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtgsen_work((C.int)(rowMajor), (C.lapack_int)(ijob), (C.lapack_logical)(wantq), (C.lapack_logical)(wantz), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_alphar), (*C.double)(_alphai), (*C.double)(_beta), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_m), (*C.double)(_pl), (*C.double)(_pr), (*C.double)(_dif), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctgsen.f. +func Ctgsen(ijob lapack.Job, wantq, wantz int32, sel []int32, n int, a []complex64, lda int, b []complex64, ldb int, alpha, beta, q []complex64, ldq int, z []complex64, ldz int, m []int32, pl, pr, dif []float32, work []complex64, lwork int, iwork []int32, liwork int) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *complex64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex64 + if len(z) > 0 { + _z = &z[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _pl *float32 + if len(pl) > 0 { + _pl = &pl[0] + } + var _pr *float32 + if len(pr) > 0 { + _pr = &pr[0] + } + var _dif *float32 + if len(dif) > 0 { + _dif = &dif[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ctgsen_work((C.int)(rowMajor), (C.lapack_int)(ijob), (C.lapack_logical)(wantq), (C.lapack_logical)(wantz), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_alpha), (*C.lapack_complex_float)(_beta), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_m), (*C.float)(_pl), (*C.float)(_pr), (*C.float)(_dif), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztgsen.f. +func Ztgsen(ijob lapack.Job, wantq, wantz int32, sel []int32, n int, a []complex128, lda int, b []complex128, ldb int, alpha, beta, q []complex128, ldq int, z []complex128, ldz int, m []int32, pl, pr, dif []float64, work []complex128, lwork int, iwork []int32, liwork int) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *complex128 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *complex128 + if len(beta) > 0 { + _beta = &beta[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _z *complex128 + if len(z) > 0 { + _z = &z[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _pl *float64 + if len(pl) > 0 { + _pl = &pl[0] + } + var _pr *float64 + if len(pr) > 0 { + _pr = &pr[0] + } + var _dif *float64 + if len(dif) > 0 { + _dif = &dif[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ztgsen_work((C.int)(rowMajor), (C.lapack_int)(ijob), (C.lapack_logical)(wantq), (C.lapack_logical)(wantz), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_alpha), (*C.lapack_complex_double)(_beta), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_z), (C.lapack_int)(ldz), (*C.lapack_int)(_m), (*C.double)(_pl), (*C.double)(_pr), (*C.double)(_dif), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stgsja.f. +func Stgsja(jobu, jobv, jobq lapack.Job, m, p, n, k, l int, a []float32, lda int, b []float32, ldb int, tola, tolb float32, alpha, beta, u []float32, ldu int, v []float32, ldv int, q []float32, ldq int, work []float32, ncycle []int32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *float32 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *float32 + if len(beta) > 0 { + _beta = &beta[0] + } + var _u *float32 + if len(u) > 0 { + _u = &u[0] + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _ncycle *int32 + if len(ncycle) > 0 { + _ncycle = &ncycle[0] + } + return isZero(C.LAPACKE_stgsja_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (C.float)(tola), (C.float)(tolb), (*C.float)(_alpha), (*C.float)(_beta), (*C.float)(_u), (C.lapack_int)(ldu), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_work), (*C.lapack_int)(_ncycle))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtgsja.f. +func Dtgsja(jobu, jobv, jobq lapack.Job, m, p, n, k, l int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, ncycle []int32) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *float64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *float64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _u *float64 + if len(u) > 0 { + _u = &u[0] + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _ncycle *int32 + if len(ncycle) > 0 { + _ncycle = &ncycle[0] + } + return isZero(C.LAPACKE_dtgsja_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (C.double)(tola), (C.double)(tolb), (*C.double)(_alpha), (*C.double)(_beta), (*C.double)(_u), (C.lapack_int)(ldu), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_work), (*C.lapack_int)(_ncycle))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctgsja.f. +func Ctgsja(jobu, jobv, jobq lapack.Job, m, p, n, k, l int, a []complex64, lda int, b []complex64, ldb int, tola, tolb float32, alpha, beta []float32, u []complex64, ldu int, v []complex64, ldv int, q []complex64, ldq int, work []complex64, ncycle []int32) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *float32 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *float32 + if len(beta) > 0 { + _beta = &beta[0] + } + var _u *complex64 + if len(u) > 0 { + _u = &u[0] + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _ncycle *int32 + if len(ncycle) > 0 { + _ncycle = &ncycle[0] + } + return isZero(C.LAPACKE_ctgsja_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (C.float)(tola), (C.float)(tolb), (*C.float)(_alpha), (*C.float)(_beta), (*C.lapack_complex_float)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_work), (*C.lapack_int)(_ncycle))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztgsja.f. +func Ztgsja(jobu, jobv, jobq lapack.Job, m, p, n, k, l int, a []complex128, lda int, b []complex128, ldb int, tola, tolb float64, alpha, beta []float64, u []complex128, ldu int, v []complex128, ldv int, q []complex128, ldq int, work []complex128, ncycle []int32) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _alpha *float64 + if len(alpha) > 0 { + _alpha = &alpha[0] + } + var _beta *float64 + if len(beta) > 0 { + _beta = &beta[0] + } + var _u *complex128 + if len(u) > 0 { + _u = &u[0] + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _ncycle *int32 + if len(ncycle) > 0 { + _ncycle = &ncycle[0] + } + return isZero(C.LAPACKE_ztgsja_work((C.int)(rowMajor), (C.char)(jobu), (C.char)(jobv), (C.char)(jobq), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (C.double)(tola), (C.double)(tolb), (*C.double)(_alpha), (*C.double)(_beta), (*C.lapack_complex_double)(_u), (C.lapack_int)(ldu), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_work), (*C.lapack_int)(_ncycle))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stgsna.f. +func Stgsna(job lapack.Job, howmny byte, sel []int32, n int, a []float32, lda int, b []float32, ldb int, vl []float32, ldvl int, vr []float32, ldvr int, s, dif []float32, mm int, m []int32, work []float32, lwork int, iwork []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _dif *float32 + if len(dif) > 0 { + _dif = &dif[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_stgsna_work((C.int)(rowMajor), (C.char)(job), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (*C.float)(_s), (*C.float)(_dif), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtgsna.f. +func Dtgsna(job lapack.Job, howmny byte, sel []int32, n int, a []float64, lda int, b []float64, ldb int, vl []float64, ldvl int, vr []float64, ldvr int, s, dif []float64, mm int, m []int32, work []float64, lwork int, iwork []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _dif *float64 + if len(dif) > 0 { + _dif = &dif[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtgsna_work((C.int)(rowMajor), (C.char)(job), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (*C.double)(_s), (*C.double)(_dif), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctgsna.f. +func Ctgsna(job lapack.Job, howmny byte, sel []int32, n int, a []complex64, lda int, b []complex64, ldb int, vl []complex64, ldvl int, vr []complex64, ldvr int, s, dif []float32, mm int, m []int32, work []complex64, lwork int, iwork []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _dif *float32 + if len(dif) > 0 { + _dif = &dif[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ctgsna_work((C.int)(rowMajor), (C.char)(job), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (*C.float)(_s), (*C.float)(_dif), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztgsna.f. +func Ztgsna(job lapack.Job, howmny byte, sel []int32, n int, a []complex128, lda int, b []complex128, ldb int, vl []complex128, ldvl int, vr []complex128, ldvr int, s, dif []float64, mm int, m []int32, work []complex128, lwork int, iwork []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _dif *float64 + if len(dif) > 0 { + _dif = &dif[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ztgsna_work((C.int)(rowMajor), (C.char)(job), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (*C.double)(_s), (*C.double)(_dif), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stgsyl.f. +func Stgsyl(trans blas.Transpose, ijob lapack.Job, m, n int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, d []float32, ldd int, e []float32, lde int, f []float32, ldf int, scale, dif, work []float32, lwork int, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _d *float32 + if len(d) > 0 { + _d = &d[0] + } + var _e *float32 + if len(e) > 0 { + _e = &e[0] + } + var _f *float32 + if len(f) > 0 { + _f = &f[0] + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + var _dif *float32 + if len(dif) > 0 { + _dif = &dif[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_stgsyl_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(ijob), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_d), (C.lapack_int)(ldd), (*C.float)(_e), (C.lapack_int)(lde), (*C.float)(_f), (C.lapack_int)(ldf), (*C.float)(_scale), (*C.float)(_dif), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtgsyl.f. +func Dtgsyl(trans blas.Transpose, ijob lapack.Job, m, n int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, d []float64, ldd int, e []float64, lde int, f []float64, ldf int, scale, dif, work []float64, lwork int, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _d *float64 + if len(d) > 0 { + _d = &d[0] + } + var _e *float64 + if len(e) > 0 { + _e = &e[0] + } + var _f *float64 + if len(f) > 0 { + _f = &f[0] + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + var _dif *float64 + if len(dif) > 0 { + _dif = &dif[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtgsyl_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(ijob), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_d), (C.lapack_int)(ldd), (*C.double)(_e), (C.lapack_int)(lde), (*C.double)(_f), (C.lapack_int)(ldf), (*C.double)(_scale), (*C.double)(_dif), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctgsyl.f. +func Ctgsyl(trans blas.Transpose, ijob lapack.Job, m, n int, a []complex64, lda int, b []complex64, ldb int, c []complex64, ldc int, d []complex64, ldd int, e []complex64, lde int, f []complex64, ldf int, scale, dif []float32, work []complex64, lwork int, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _d *complex64 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex64 + if len(e) > 0 { + _e = &e[0] + } + var _f *complex64 + if len(f) > 0 { + _f = &f[0] + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + var _dif *float32 + if len(dif) > 0 { + _dif = &dif[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ctgsyl_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(ijob), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_d), (C.lapack_int)(ldd), (*C.lapack_complex_float)(_e), (C.lapack_int)(lde), (*C.lapack_complex_float)(_f), (C.lapack_int)(ldf), (*C.float)(_scale), (*C.float)(_dif), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztgsyl.f. +func Ztgsyl(trans blas.Transpose, ijob lapack.Job, m, n int, a []complex128, lda int, b []complex128, ldb int, c []complex128, ldc int, d []complex128, ldd int, e []complex128, lde int, f []complex128, ldf int, scale, dif []float64, work []complex128, lwork int, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _d *complex128 + if len(d) > 0 { + _d = &d[0] + } + var _e *complex128 + if len(e) > 0 { + _e = &e[0] + } + var _f *complex128 + if len(f) > 0 { + _f = &f[0] + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + var _dif *float64 + if len(dif) > 0 { + _dif = &dif[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_ztgsyl_work((C.int)(rowMajor), (C.char)(trans), (C.lapack_int)(ijob), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_d), (C.lapack_int)(ldd), (*C.lapack_complex_double)(_e), (C.lapack_int)(lde), (*C.lapack_complex_double)(_f), (C.lapack_int)(ldf), (*C.double)(_scale), (*C.double)(_dif), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stpcon.f. +func Stpcon(norm byte, ul blas.Uplo, d blas.Diag, n int, ap, rcond, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_stpcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtpcon.f. +func Dtpcon(norm byte, ul blas.Uplo, d blas.Diag, n int, ap, rcond, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtpcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctpcon.f. +func Ctpcon(norm byte, ul blas.Uplo, d blas.Diag, n int, ap []complex64, rcond []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ctpcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.float)(_rcond), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztpcon.f. +func Ztpcon(norm byte, ul blas.Uplo, d blas.Diag, n int, ap []complex128, rcond []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ztpcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.double)(_rcond), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stprfs.f. +func Stprfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, ap, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_stprfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtprfs.f. +func Dtprfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, ap, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtprfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctprfs.f. +func Ctprfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, ap, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ctprfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztprfs.f. +func Ztprfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, ap, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ztprfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stptri.f. +func Stptri(ul blas.Uplo, d blas.Diag, n int, ap []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_stptri_work((C.int)(rowMajor), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtptri.f. +func Dtptri(ul blas.Uplo, d blas.Diag, n int, ap []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_dtptri_work((C.int)(rowMajor), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctptri.f. +func Ctptri(ul blas.Uplo, d blas.Diag, n int, ap []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_ctptri_work((C.int)(rowMajor), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztptri.f. +func Ztptri(ul blas.Uplo, d blas.Diag, n int, ap []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_ztptri_work((C.int)(rowMajor), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stptrs.f. +func Stptrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, ap, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_stptrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_ap), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtptrs.f. +func Dtptrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, ap, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dtptrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_ap), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctptrs.f. +func Ctptrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, ap, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ctptrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztptrs.f. +func Ztptrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, ap, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ztptrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stpttf.f. +func Stpttf(transr blas.Transpose, ul blas.Uplo, n int, ap, arf []float32) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _arf *float32 + if len(arf) > 0 { + _arf = &arf[0] + } + return isZero(C.LAPACKE_stpttf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_arf))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtpttf.f. +func Dtpttf(transr blas.Transpose, ul blas.Uplo, n int, ap, arf []float64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _arf *float64 + if len(arf) > 0 { + _arf = &arf[0] + } + return isZero(C.LAPACKE_dtpttf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_arf))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctpttf.f. +func Ctpttf(transr blas.Transpose, ul blas.Uplo, n int, ap, arf []complex64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _arf *complex64 + if len(arf) > 0 { + _arf = &arf[0] + } + return isZero(C.LAPACKE_ctpttf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_arf))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztpttf.f. +func Ztpttf(transr blas.Transpose, ul blas.Uplo, n int, ap, arf []complex128) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _arf *complex128 + if len(arf) > 0 { + _arf = &arf[0] + } + return isZero(C.LAPACKE_ztpttf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_arf))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stpttr.f. +func Stpttr(ul blas.Uplo, n int, ap, a []float32, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_stpttr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_ap), (*C.float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtpttr.f. +func Dtpttr(ul blas.Uplo, n int, ap, a []float64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dtpttr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_ap), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctpttr.f. +func Ctpttr(ul blas.Uplo, n int, ap, a []complex64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_ctpttr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztpttr.f. +func Ztpttr(ul blas.Uplo, n int, ap, a []complex128, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_ztpttr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strcon.f. +func Strcon(norm byte, ul blas.Uplo, d blas.Diag, n int, a []float32, lda int, rcond, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_strcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_rcond), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrcon.f. +func Dtrcon(norm byte, ul blas.Uplo, d blas.Diag, n int, a []float64, lda int, rcond, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtrcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_rcond), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrcon.f. +func Ctrcon(norm byte, ul blas.Uplo, d blas.Diag, n int, a []complex64, lda int, rcond []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float32 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ctrcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.float)(_rcond), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrcon.f. +func Ztrcon(norm byte, ul blas.Uplo, d blas.Diag, n int, a []complex128, lda int, rcond []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _rcond *float64 + if len(rcond) > 0 { + _rcond = &rcond[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ztrcon_work((C.int)(rowMajor), (C.char)(norm), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.double)(_rcond), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strevc.f. +func Strevc(side blas.Side, howmny byte, sel []int32, n int, t []float32, ldt int, vl []float32, ldvl int, vr []float32, ldvr, mm int, m []int32, work []float32) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_strevc_work((C.int)(rowMajor), (C.char)(side), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrevc.f. +func Dtrevc(side blas.Side, howmny byte, sel []int32, n int, t []float64, ldt int, vl []float64, ldvl int, vr []float64, ldvr, mm int, m []int32, work []float64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dtrevc_work((C.int)(rowMajor), (C.char)(side), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrevc.f. +func Ctrevc(side blas.Side, howmny byte, sel []int32, n int, t []complex64, ldt int, vl []complex64, ldvl int, vr []complex64, ldvr, mm int, m []int32, work []complex64, rwork []float32) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ctrevc_work((C.int)(rowMajor), (C.char)(side), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrevc.f. +func Ztrevc(side blas.Side, howmny byte, sel []int32, n int, t []complex128, ldt int, vl []complex128, ldvl int, vr []complex128, ldvr, mm int, m []int32, work []complex128, rwork []float64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ztrevc_work((C.int)(rowMajor), (C.char)(side), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strexc.f. +func Strexc(compq lapack.Comp, n int, t []float32, ldt int, q []float32, ldq int, ifst, ilst []int32, work []float32) bool { + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _ifst *int32 + if len(ifst) > 0 { + _ifst = &ifst[0] + } + var _ilst *int32 + if len(ilst) > 0 { + _ilst = &ilst[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_strexc_work((C.int)(rowMajor), (C.char)(compq), (C.lapack_int)(n), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_q), (C.lapack_int)(ldq), (*C.lapack_int)(_ifst), (*C.lapack_int)(_ilst), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrexc.f. +func Dtrexc(compq lapack.Comp, n int, t []float64, ldt int, q []float64, ldq int, ifst, ilst []int32, work []float64) bool { + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _ifst *int32 + if len(ifst) > 0 { + _ifst = &ifst[0] + } + var _ilst *int32 + if len(ilst) > 0 { + _ilst = &ilst[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dtrexc_work((C.int)(rowMajor), (C.char)(compq), (C.lapack_int)(n), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_q), (C.lapack_int)(ldq), (*C.lapack_int)(_ifst), (*C.lapack_int)(_ilst), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrexc.f. +func Ctrexc(compq lapack.Comp, n int, t []complex64, ldt int, q []complex64, ldq, ifst, ilst int) bool { + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + return isZero(C.LAPACKE_ctrexc_work((C.int)(rowMajor), (C.char)(compq), (C.lapack_int)(n), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (C.lapack_int)(ifst), (C.lapack_int)(ilst))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrexc.f. +func Ztrexc(compq lapack.Comp, n int, t []complex128, ldt int, q []complex128, ldq, ifst, ilst int) bool { + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + return isZero(C.LAPACKE_ztrexc_work((C.int)(rowMajor), (C.char)(compq), (C.lapack_int)(n), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (C.lapack_int)(ifst), (C.lapack_int)(ilst))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strrfs.f. +func Strrfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, a []float32, lda int, b []float32, ldb int, x []float32, ldx int, ferr, berr, work []float32, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _x *float32 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_strrfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.float)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrrfs.f. +func Dtrrfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, a []float64, lda int, b []float64, ldb int, x []float64, ldx int, ferr, berr, work []float64, iwork []int32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _x *float64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtrrfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.double)(_work), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrrfs.f. +func Ctrrfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, a []complex64, lda int, b []complex64, ldb int, x []complex64, ldx int, ferr, berr []float32, work []complex64, rwork []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float32 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float32 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ctrrfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_x), (C.lapack_int)(ldx), (*C.float)(_ferr), (*C.float)(_berr), (*C.lapack_complex_float)(_work), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrrfs.f. +func Ztrrfs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, a []complex128, lda int, b []complex128, ldb int, x []complex128, ldx int, ferr, berr []float64, work []complex128, rwork []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _ferr *float64 + if len(ferr) > 0 { + _ferr = &ferr[0] + } + var _berr *float64 + if len(berr) > 0 { + _berr = &berr[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ztrrfs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_x), (C.lapack_int)(ldx), (*C.double)(_ferr), (*C.double)(_berr), (*C.lapack_complex_double)(_work), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strsen.f. +func Strsen(job lapack.Job, compq lapack.Comp, sel []int32, n int, t []float32, ldt int, q []float32, ldq int, wr, wi []float32, m []int32, s, sep, work []float32, lwork int, iwork []int32, liwork int) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _q *float32 + if len(q) > 0 { + _q = &q[0] + } + var _wr *float32 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float32 + if len(wi) > 0 { + _wi = &wi[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _sep *float32 + if len(sep) > 0 { + _sep = &sep[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_strsen_work((C.int)(rowMajor), (C.char)(job), (C.char)(compq), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_q), (C.lapack_int)(ldq), (*C.float)(_wr), (*C.float)(_wi), (*C.lapack_int)(_m), (*C.float)(_s), (*C.float)(_sep), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrsen.f. +func Dtrsen(job lapack.Job, compq lapack.Comp, sel []int32, n int, t []float64, ldt int, q []float64, ldq int, wr, wi []float64, m []int32, s, sep, work []float64, lwork int, iwork []int32, liwork int) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _q *float64 + if len(q) > 0 { + _q = &q[0] + } + var _wr *float64 + if len(wr) > 0 { + _wr = &wr[0] + } + var _wi *float64 + if len(wi) > 0 { + _wi = &wi[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _sep *float64 + if len(sep) > 0 { + _sep = &sep[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtrsen_work((C.int)(rowMajor), (C.char)(job), (C.char)(compq), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_q), (C.lapack_int)(ldq), (*C.double)(_wr), (*C.double)(_wi), (*C.lapack_int)(_m), (*C.double)(_s), (*C.double)(_sep), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork), (C.lapack_int)(liwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrsen.f. +func Ctrsen(job lapack.Job, compq lapack.Comp, sel []int32, n int, t []complex64, ldt int, q []complex64, ldq int, w []complex64, m []int32, s, sep []float32, work []complex64, lwork int) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _w *complex64 + if len(w) > 0 { + _w = &w[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _sep *float32 + if len(sep) > 0 { + _sep = &sep[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ctrsen_work((C.int)(rowMajor), (C.char)(job), (C.char)(compq), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_w), (*C.lapack_int)(_m), (*C.float)(_s), (*C.float)(_sep), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrsen.f. +func Ztrsen(job lapack.Job, compq lapack.Comp, sel []int32, n int, t []complex128, ldt int, q []complex128, ldq int, w []complex128, m []int32, s, sep []float64, work []complex128, lwork int) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _w *complex128 + if len(w) > 0 { + _w = &w[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _sep *float64 + if len(sep) > 0 { + _sep = &sep[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ztrsen_work((C.int)(rowMajor), (C.char)(job), (C.char)(compq), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_w), (*C.lapack_int)(_m), (*C.double)(_s), (*C.double)(_sep), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strsna.f. +func Strsna(job lapack.Job, howmny byte, sel []int32, n int, t []float32, ldt int, vl []float32, ldvl int, vr []float32, ldvr int, s, sep []float32, mm int, m []int32, work []float32, ldwork int, iwork []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _vl *float32 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float32 + if len(vr) > 0 { + _vr = &vr[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _sep *float32 + if len(sep) > 0 { + _sep = &sep[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_strsna_work((C.int)(rowMajor), (C.char)(job), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_vl), (C.lapack_int)(ldvl), (*C.float)(_vr), (C.lapack_int)(ldvr), (*C.float)(_s), (*C.float)(_sep), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.float)(_work), (C.lapack_int)(ldwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrsna.f. +func Dtrsna(job lapack.Job, howmny byte, sel []int32, n int, t []float64, ldt int, vl []float64, ldvl int, vr []float64, ldvr int, s, sep []float64, mm int, m []int32, work []float64, ldwork int, iwork []int32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _vl *float64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *float64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _sep *float64 + if len(sep) > 0 { + _sep = &sep[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dtrsna_work((C.int)(rowMajor), (C.char)(job), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_vl), (C.lapack_int)(ldvl), (*C.double)(_vr), (C.lapack_int)(ldvr), (*C.double)(_s), (*C.double)(_sep), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.double)(_work), (C.lapack_int)(ldwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrsna.f. +func Ctrsna(job lapack.Job, howmny byte, sel []int32, n int, t []complex64, ldt int, vl []complex64, ldvl int, vr []complex64, ldvr int, s, sep []float32, mm int, m []int32, work []complex64, ldwork int, rwork []float32) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _vl *complex64 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex64 + if len(vr) > 0 { + _vr = &vr[0] + } + var _s *float32 + if len(s) > 0 { + _s = &s[0] + } + var _sep *float32 + if len(sep) > 0 { + _sep = &sep[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ctrsna_work((C.int)(rowMajor), (C.char)(job), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_float)(_vr), (C.lapack_int)(ldvr), (*C.float)(_s), (*C.float)(_sep), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_float)(_work), (C.lapack_int)(ldwork), (*C.float)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrsna.f. +func Ztrsna(job lapack.Job, howmny byte, sel []int32, n int, t []complex128, ldt int, vl []complex128, ldvl int, vr []complex128, ldvr int, s, sep []float64, mm int, m []int32, work []complex128, ldwork int, rwork []float64) bool { + var _sel *int32 + if len(sel) > 0 { + _sel = &sel[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _vl *complex128 + if len(vl) > 0 { + _vl = &vl[0] + } + var _vr *complex128 + if len(vr) > 0 { + _vr = &vr[0] + } + var _s *float64 + if len(s) > 0 { + _s = &s[0] + } + var _sep *float64 + if len(sep) > 0 { + _sep = &sep[0] + } + var _m *int32 + if len(m) > 0 { + _m = &m[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_ztrsna_work((C.int)(rowMajor), (C.char)(job), (C.char)(howmny), (*C.lapack_int)(_sel), (C.lapack_int)(n), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_vl), (C.lapack_int)(ldvl), (*C.lapack_complex_double)(_vr), (C.lapack_int)(ldvr), (*C.double)(_s), (*C.double)(_sep), (C.lapack_int)(mm), (*C.lapack_int)(_m), (*C.lapack_complex_double)(_work), (C.lapack_int)(ldwork), (*C.double)(_rwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strsyl.f. +func Strsyl(trana, tranb blas.Transpose, isgn, m, n int, a []float32, lda int, b []float32, ldb int, c []float32, ldc int, scale []float32) bool { + switch trana { + case blas.NoTrans: + trana = 'N' + case blas.Trans: + trana = 'T' + case blas.ConjTrans: + trana = 'C' + default: + panic("lapack: bad trans") + } + switch tranb { + case blas.NoTrans: + tranb = 'N' + case blas.Trans: + tranb = 'T' + case blas.ConjTrans: + tranb = 'C' + default: + panic("lapack: bad trans") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + return isZero(C.LAPACKE_strsyl_work((C.int)(rowMajor), (C.char)(trana), (C.char)(tranb), (C.lapack_int)(isgn), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_scale))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrsyl.f. +func Dtrsyl(trana, tranb blas.Transpose, isgn, m, n int, a []float64, lda int, b []float64, ldb int, c []float64, ldc int, scale []float64) bool { + switch trana { + case blas.NoTrans: + trana = 'N' + case blas.Trans: + trana = 'T' + case blas.ConjTrans: + trana = 'C' + default: + panic("lapack: bad trans") + } + switch tranb { + case blas.NoTrans: + tranb = 'N' + case blas.Trans: + tranb = 'T' + case blas.ConjTrans: + tranb = 'C' + default: + panic("lapack: bad trans") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + return isZero(C.LAPACKE_dtrsyl_work((C.int)(rowMajor), (C.char)(trana), (C.char)(tranb), (C.lapack_int)(isgn), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_scale))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrsyl.f. +func Ctrsyl(trana, tranb blas.Transpose, isgn, m, n int, a []complex64, lda int, b []complex64, ldb int, c []complex64, ldc int, scale []float32) bool { + switch trana { + case blas.NoTrans: + trana = 'N' + case blas.Trans: + trana = 'T' + case blas.ConjTrans: + trana = 'C' + default: + panic("lapack: bad trans") + } + switch tranb { + case blas.NoTrans: + tranb = 'N' + case blas.Trans: + tranb = 'T' + case blas.ConjTrans: + tranb = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _scale *float32 + if len(scale) > 0 { + _scale = &scale[0] + } + return isZero(C.LAPACKE_ctrsyl_work((C.int)(rowMajor), (C.char)(trana), (C.char)(tranb), (C.lapack_int)(isgn), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.float)(_scale))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrsyl.f. +func Ztrsyl(trana, tranb blas.Transpose, isgn, m, n int, a []complex128, lda int, b []complex128, ldb int, c []complex128, ldc int, scale []float64) bool { + switch trana { + case blas.NoTrans: + trana = 'N' + case blas.Trans: + trana = 'T' + case blas.ConjTrans: + trana = 'C' + default: + panic("lapack: bad trans") + } + switch tranb { + case blas.NoTrans: + tranb = 'N' + case blas.Trans: + tranb = 'T' + case blas.ConjTrans: + tranb = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _scale *float64 + if len(scale) > 0 { + _scale = &scale[0] + } + return isZero(C.LAPACKE_ztrsyl_work((C.int)(rowMajor), (C.char)(trana), (C.char)(tranb), (C.lapack_int)(isgn), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.double)(_scale))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strtri.f. +func Strtri(ul blas.Uplo, d blas.Diag, n int, a []float32, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_strtri_work((C.int)(rowMajor), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrtri.f. +func Dtrtri(ul blas.Uplo, d blas.Diag, n int, a []float64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dtrtri_work((C.int)(rowMajor), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrtri.f. +func Ctrtri(ul blas.Uplo, d blas.Diag, n int, a []complex64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_ctrtri_work((C.int)(rowMajor), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrtri.f. +func Ztrtri(ul blas.Uplo, d blas.Diag, n int, a []complex128, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_ztrtri_work((C.int)(rowMajor), (C.char)(ul), (C.char)(d), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strtrs.f. +func Strtrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, a []float32, lda int, b []float32, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_strtrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrtrs.f. +func Dtrtrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, a []float64, lda int, b []float64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_dtrtrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrtrs.f. +func Ctrtrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, a []complex64, lda int, b []complex64, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ctrtrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrtrs.f. +func Ztrtrs(ul blas.Uplo, trans blas.Transpose, d blas.Diag, n, nrhs int, a []complex128, lda int, b []complex128, ldb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + switch d { + case blas.Unit: + d = 'U' + case blas.NonUnit: + d = 'N' + default: + panic("lapack: illegal diagonal") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + return isZero(C.LAPACKE_ztrtrs_work((C.int)(rowMajor), (C.char)(ul), (C.char)(trans), (C.char)(d), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strttf.f. +func Strttf(transr blas.Transpose, ul blas.Uplo, n int, a []float32, lda int, arf []float32) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _arf *float32 + if len(arf) > 0 { + _arf = &arf[0] + } + return isZero(C.LAPACKE_strttf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_arf))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrttf.f. +func Dtrttf(transr blas.Transpose, ul blas.Uplo, n int, a []float64, lda int, arf []float64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _arf *float64 + if len(arf) > 0 { + _arf = &arf[0] + } + return isZero(C.LAPACKE_dtrttf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_arf))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrttf.f. +func Ctrttf(transr blas.Transpose, ul blas.Uplo, n int, a []complex64, lda int, arf []complex64) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _arf *complex64 + if len(arf) > 0 { + _arf = &arf[0] + } + return isZero(C.LAPACKE_ctrttf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_arf))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrttf.f. +func Ztrttf(transr blas.Transpose, ul blas.Uplo, n int, a []complex128, lda int, arf []complex128) bool { + switch transr { + case blas.NoTrans: + transr = 'N' + case blas.Trans: + transr = 'T' + case blas.ConjTrans: + transr = 'C' + default: + panic("lapack: bad trans") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _arf *complex128 + if len(arf) > 0 { + _arf = &arf[0] + } + return isZero(C.LAPACKE_ztrttf_work((C.int)(rowMajor), (C.char)(transr), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_arf))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/strttp.f. +func Strttp(ul blas.Uplo, n int, a []float32, lda int, ap []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ap *float32 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_strttp_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtrttp.f. +func Dtrttp(ul blas.Uplo, n int, a []float64, lda int, ap []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ap *float64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_dtrttp_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctrttp.f. +func Ctrttp(ul blas.Uplo, n int, a []complex64, lda int, ap []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_ctrttp_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztrttp.f. +func Ztrttp(ul blas.Uplo, n int, a []complex128, lda int, ap []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + return isZero(C.LAPACKE_ztrttp_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_ap))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stzrzf.f. +func Stzrzf(m, n int, a []float32, lda int, tau, work []float32, lwork int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float32 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_stzrzf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_tau), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtzrzf.f. +func Dtzrzf(m, n int, a []float64, lda int, tau, work []float64, lwork int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *float64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dtzrzf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_tau), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctzrzf.f. +func Ctzrzf(m, n int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ctzrzf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztzrzf.f. +func Ztzrzf(m, n int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ztzrzf_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cungbr.f. +func Cungbr(vect byte, m, n, k int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cungbr_work((C.int)(rowMajor), (C.char)(vect), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zungbr.f. +func Zungbr(vect byte, m, n, k int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zungbr_work((C.int)(rowMajor), (C.char)(vect), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunghr.f. +func Cunghr(n, ilo, ihi int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunghr_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunghr.f. +func Zunghr(n, ilo, ihi int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunghr_work((C.int)(rowMajor), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunglq.f. +func Cunglq(m, n, k int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunglq_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunglq.f. +func Zunglq(m, n, k int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunglq_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cungql.f. +func Cungql(m, n, k int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cungql_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zungql.f. +func Zungql(m, n, k int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zungql_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cungqr.f. +func Cungqr(m, n, k int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cungqr_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zungqr.f. +func Zungqr(m, n, k int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zungqr_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cungrq.f. +func Cungrq(m, n, k int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cungrq_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zungrq.f. +func Zungrq(m, n, k int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zungrq_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cungtr.f. +func Cungtr(ul blas.Uplo, n int, a []complex64, lda int, tau, work []complex64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cungtr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zungtr.f. +func Zungtr(ul blas.Uplo, n int, a []complex128, lda int, tau, work []complex128, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zungtr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunmbr.f. +func Cunmbr(vect byte, side blas.Side, trans blas.Transpose, m, n, k int, a []complex64, lda int, tau, c []complex64, ldc int, work []complex64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunmbr_work((C.int)(rowMajor), (C.char)(vect), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunmbr.f. +func Zunmbr(vect byte, side blas.Side, trans blas.Transpose, m, n, k int, a []complex128, lda int, tau, c []complex128, ldc int, work []complex128, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunmbr_work((C.int)(rowMajor), (C.char)(vect), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunmhr.f. +func Cunmhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []complex64, lda int, tau, c []complex64, ldc int, work []complex64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunmhr_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunmhr.f. +func Zunmhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []complex128, lda int, tau, c []complex128, ldc int, work []complex128, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunmhr_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(ilo), (C.lapack_int)(ihi), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunmlq.f. +func Cunmlq(side blas.Side, trans blas.Transpose, m, n, k int, a []complex64, lda int, tau, c []complex64, ldc int, work []complex64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunmlq_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunmlq.f. +func Zunmlq(side blas.Side, trans blas.Transpose, m, n, k int, a []complex128, lda int, tau, c []complex128, ldc int, work []complex128, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunmlq_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunmql.f. +func Cunmql(side blas.Side, trans blas.Transpose, m, n, k int, a []complex64, lda int, tau, c []complex64, ldc int, work []complex64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunmql_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunmql.f. +func Zunmql(side blas.Side, trans blas.Transpose, m, n, k int, a []complex128, lda int, tau, c []complex128, ldc int, work []complex128, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunmql_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunmqr.f. +func Cunmqr(side blas.Side, trans blas.Transpose, m, n, k int, a []complex64, lda int, tau, c []complex64, ldc int, work []complex64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunmqr_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunmqr.f. +func Zunmqr(side blas.Side, trans blas.Transpose, m, n, k int, a []complex128, lda int, tau, c []complex128, ldc int, work []complex128, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunmqr_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunmrq.f. +func Cunmrq(side blas.Side, trans blas.Transpose, m, n, k int, a []complex64, lda int, tau, c []complex64, ldc int, work []complex64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunmrq_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunmrq.f. +func Zunmrq(side blas.Side, trans blas.Transpose, m, n, k int, a []complex128, lda int, tau, c []complex128, ldc int, work []complex128, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunmrq_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunmrz.f. +func Cunmrz(side blas.Side, trans blas.Transpose, m, n, k, l int, a []complex64, lda int, tau, c []complex64, ldc int, work []complex64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunmrz_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunmrz.f. +func Zunmrz(side blas.Side, trans blas.Transpose, m, n, k, l int, a []complex128, lda int, tau, c []complex128, ldc int, work []complex128, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunmrz_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunmtr.f. +func Cunmtr(side blas.Side, ul blas.Uplo, trans blas.Transpose, m, n int, a []complex64, lda int, tau, c []complex64, ldc int, work []complex64, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunmtr_work((C.int)(rowMajor), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunmtr.f. +func Zunmtr(side blas.Side, ul blas.Uplo, trans blas.Transpose, m, n int, a []complex128, lda int, tau, c []complex128, ldc int, work []complex128, lwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunmtr_work((C.int)(rowMajor), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cupgtr.f. +func Cupgtr(ul blas.Uplo, n int, ap, tau, q []complex64, ldq int, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _q *complex64 + if len(q) > 0 { + _q = &q[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cupgtr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zupgtr.f. +func Zupgtr(ul blas.Uplo, n int, ap, tau, q []complex128, ldq int, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _q *complex128 + if len(q) > 0 { + _q = &q[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zupgtr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_q), (C.lapack_int)(ldq), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cupmtr.f. +func Cupmtr(side blas.Side, ul blas.Uplo, trans blas.Transpose, m, n int, ap, tau, c []complex64, ldc int, work []complex64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ap *complex64 + if len(ap) > 0 { + _ap = &ap[0] + } + var _tau *complex64 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cupmtr_work((C.int)(rowMajor), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_ap), (*C.lapack_complex_float)(_tau), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zupmtr.f. +func Zupmtr(side blas.Side, ul blas.Uplo, trans blas.Transpose, m, n int, ap, tau, c []complex128, ldc int, work []complex128) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _ap *complex128 + if len(ap) > 0 { + _ap = &ap[0] + } + var _tau *complex128 + if len(tau) > 0 { + _tau = &tau[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zupmtr_work((C.int)(rowMajor), (C.char)(side), (C.char)(ul), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_ap), (*C.lapack_complex_double)(_tau), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cbbcsd.f. +func Cbbcsd(jobu1, jobu2, jobv1t, jobv2t lapack.Job, trans blas.Transpose, m, p, q int, theta, phi []float32, u1 []complex64, ldu1 int, u2 []complex64, ldu2 int, v1t []complex64, ldv1t int, v2t []complex64, ldv2t int, b11d, b11e, b12d, b12e, b21d, b21e, b22d, b22e, rwork []float32, lrwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _theta *float32 + if len(theta) > 0 { + _theta = &theta[0] + } + var _phi *float32 + if len(phi) > 0 { + _phi = &phi[0] + } + var _u1 *complex64 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *complex64 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *complex64 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _v2t *complex64 + if len(v2t) > 0 { + _v2t = &v2t[0] + } + var _b11d *float32 + if len(b11d) > 0 { + _b11d = &b11d[0] + } + var _b11e *float32 + if len(b11e) > 0 { + _b11e = &b11e[0] + } + var _b12d *float32 + if len(b12d) > 0 { + _b12d = &b12d[0] + } + var _b12e *float32 + if len(b12e) > 0 { + _b12e = &b12e[0] + } + var _b21d *float32 + if len(b21d) > 0 { + _b21d = &b21d[0] + } + var _b21e *float32 + if len(b21e) > 0 { + _b21e = &b21e[0] + } + var _b22d *float32 + if len(b22d) > 0 { + _b22d = &b22d[0] + } + var _b22e *float32 + if len(b22e) > 0 { + _b22e = &b22e[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_cbbcsd_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.char)(jobv2t), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.float)(_theta), (*C.float)(_phi), (*C.lapack_complex_float)(_u1), (C.lapack_int)(ldu1), (*C.lapack_complex_float)(_u2), (C.lapack_int)(ldu2), (*C.lapack_complex_float)(_v1t), (C.lapack_int)(ldv1t), (*C.lapack_complex_float)(_v2t), (C.lapack_int)(ldv2t), (*C.float)(_b11d), (*C.float)(_b11e), (*C.float)(_b12d), (*C.float)(_b12e), (*C.float)(_b21d), (*C.float)(_b21e), (*C.float)(_b22d), (*C.float)(_b22e), (*C.float)(_rwork), (C.lapack_int)(lrwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cheswapr.f. +func Cheswapr(ul blas.Uplo, n int, a []complex64, i1, i2 int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_cheswapr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(i1), (C.lapack_int)(i2))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetri2.f. +func Chetri2(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, work []complex64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chetri2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetri2x.f. +func Chetri2x(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, work []complex64, nb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chetri2x_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work), (C.lapack_int)(nb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetrs2.f. +func Chetrs2(ul blas.Uplo, n, nrhs int, a []complex64, lda int, ipiv []int32, b []complex64, ldb int, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_chetrs2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csyconv.f. +func Csyconv(ul blas.Uplo, way byte, n int, a []complex64, lda int, ipiv []int32, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csyconv_work((C.int)(rowMajor), (C.char)(ul), (C.char)(way), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csyswapr.f. +func Csyswapr(ul blas.Uplo, n int, a []complex64, i1, i2 int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_csyswapr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(i1), (C.lapack_int)(i2))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytri2.f. +func Csytri2(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, work []complex64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csytri2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytri2x.f. +func Csytri2x(ul blas.Uplo, n int, a []complex64, lda int, ipiv []int32, work []complex64, nb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csytri2x_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work), (C.lapack_int)(nb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytrs2.f. +func Csytrs2(ul blas.Uplo, n, nrhs int, a []complex64, lda int, ipiv []int32, b []complex64, ldb int, work []complex64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_csytrs2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cunbdb.f. +func Cunbdb(trans blas.Transpose, signs byte, m, p, q int, x11 []complex64, ldx11 int, x12 []complex64, ldx12 int, x21 []complex64, ldx21 int, x22 []complex64, ldx22 int, theta, phi []float32, taup1, taup2, tauq1, tauq2, work []complex64, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _x11 *complex64 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x12 *complex64 + if len(x12) > 0 { + _x12 = &x12[0] + } + var _x21 *complex64 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _x22 *complex64 + if len(x22) > 0 { + _x22 = &x22[0] + } + var _theta *float32 + if len(theta) > 0 { + _theta = &theta[0] + } + var _phi *float32 + if len(phi) > 0 { + _phi = &phi[0] + } + var _taup1 *complex64 + if len(taup1) > 0 { + _taup1 = &taup1[0] + } + var _taup2 *complex64 + if len(taup2) > 0 { + _taup2 = &taup2[0] + } + var _tauq1 *complex64 + if len(tauq1) > 0 { + _tauq1 = &tauq1[0] + } + var _tauq2 *complex64 + if len(tauq2) > 0 { + _tauq2 = &tauq2[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cunbdb_work((C.int)(rowMajor), (C.char)(trans), (C.char)(signs), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.lapack_complex_float)(_x11), (C.lapack_int)(ldx11), (*C.lapack_complex_float)(_x12), (C.lapack_int)(ldx12), (*C.lapack_complex_float)(_x21), (C.lapack_int)(ldx21), (*C.lapack_complex_float)(_x22), (C.lapack_int)(ldx22), (*C.float)(_theta), (*C.float)(_phi), (*C.lapack_complex_float)(_taup1), (*C.lapack_complex_float)(_taup2), (*C.lapack_complex_float)(_tauq1), (*C.lapack_complex_float)(_tauq2), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cuncsd.f. +func Cuncsd(jobu1, jobu2, jobv1t, jobv2t lapack.Job, trans blas.Transpose, signs byte, m, p, q int, x11 []complex64, ldx11 int, x12 []complex64, ldx12 int, x21 []complex64, ldx21 int, x22 []complex64, ldx22 int, theta []float32, u1 []complex64, ldu1 int, u2 []complex64, ldu2 int, v1t []complex64, ldv1t int, v2t []complex64, ldv2t int, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _x11 *complex64 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x12 *complex64 + if len(x12) > 0 { + _x12 = &x12[0] + } + var _x21 *complex64 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _x22 *complex64 + if len(x22) > 0 { + _x22 = &x22[0] + } + var _theta *float32 + if len(theta) > 0 { + _theta = &theta[0] + } + var _u1 *complex64 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *complex64 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *complex64 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _v2t *complex64 + if len(v2t) > 0 { + _v2t = &v2t[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cuncsd_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.char)(jobv2t), (C.char)(trans), (C.char)(signs), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.lapack_complex_float)(_x11), (C.lapack_int)(ldx11), (*C.lapack_complex_float)(_x12), (C.lapack_int)(ldx12), (*C.lapack_complex_float)(_x21), (C.lapack_int)(ldx21), (*C.lapack_complex_float)(_x22), (C.lapack_int)(ldx22), (*C.float)(_theta), (*C.lapack_complex_float)(_u1), (C.lapack_int)(ldu1), (*C.lapack_complex_float)(_u2), (C.lapack_int)(ldu2), (*C.lapack_complex_float)(_v1t), (C.lapack_int)(ldv1t), (*C.lapack_complex_float)(_v2t), (C.lapack_int)(ldv2t), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cuncsd2by1.f. +func Cuncsd2by1(jobu1, jobu2, jobv1t lapack.Job, m, p, q int, x11 []complex64, ldx11 int, x21 []complex64, ldx21 int, theta, u1 []complex64, ldu1 int, u2 []complex64, ldu2 int, v1t []complex64, ldv1t int, work []complex64, lwork int, rwork []float32, lrwork int, iwork []int32) bool { + var _x11 *complex64 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x21 *complex64 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _theta *complex64 + if len(theta) > 0 { + _theta = &theta[0] + } + var _u1 *complex64 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *complex64 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *complex64 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float32 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_cuncsd2by1_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.lapack_complex_float)(_x11), (C.lapack_int)(ldx11), (*C.lapack_complex_float)(_x21), (C.lapack_int)(ldx21), (*C.lapack_complex_float)(_theta), (*C.lapack_complex_float)(_u1), (C.lapack_int)(ldu1), (*C.lapack_complex_float)(_u2), (C.lapack_int)(ldu2), (*C.lapack_complex_float)(_v1t), (C.lapack_int)(ldv1t), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork), (*C.float)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dbbcsd.f. +func Dbbcsd(jobu1, jobu2, jobv1t, jobv2t lapack.Job, trans blas.Transpose, m, p, q int, theta, phi, u1 []float64, ldu1 int, u2 []float64, ldu2 int, v1t []float64, ldv1t int, v2t []float64, ldv2t int, b11d, b11e, b12d, b12e, b21d, b21e, b22d, b22e, work []float64, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _theta *float64 + if len(theta) > 0 { + _theta = &theta[0] + } + var _phi *float64 + if len(phi) > 0 { + _phi = &phi[0] + } + var _u1 *float64 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *float64 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *float64 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _v2t *float64 + if len(v2t) > 0 { + _v2t = &v2t[0] + } + var _b11d *float64 + if len(b11d) > 0 { + _b11d = &b11d[0] + } + var _b11e *float64 + if len(b11e) > 0 { + _b11e = &b11e[0] + } + var _b12d *float64 + if len(b12d) > 0 { + _b12d = &b12d[0] + } + var _b12e *float64 + if len(b12e) > 0 { + _b12e = &b12e[0] + } + var _b21d *float64 + if len(b21d) > 0 { + _b21d = &b21d[0] + } + var _b21e *float64 + if len(b21e) > 0 { + _b21e = &b21e[0] + } + var _b22d *float64 + if len(b22d) > 0 { + _b22d = &b22d[0] + } + var _b22e *float64 + if len(b22e) > 0 { + _b22e = &b22e[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dbbcsd_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.char)(jobv2t), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.double)(_theta), (*C.double)(_phi), (*C.double)(_u1), (C.lapack_int)(ldu1), (*C.double)(_u2), (C.lapack_int)(ldu2), (*C.double)(_v1t), (C.lapack_int)(ldv1t), (*C.double)(_v2t), (C.lapack_int)(ldv2t), (*C.double)(_b11d), (*C.double)(_b11e), (*C.double)(_b12d), (*C.double)(_b12e), (*C.double)(_b21d), (*C.double)(_b21e), (*C.double)(_b22d), (*C.double)(_b22e), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorbdb.f. +func Dorbdb(trans blas.Transpose, signs byte, m, p, q int, x11 []float64, ldx11 int, x12 []float64, ldx12 int, x21 []float64, ldx21 int, x22 []float64, ldx22 int, theta, phi, taup1, taup2, tauq1, tauq2, work []float64, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _x11 *float64 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x12 *float64 + if len(x12) > 0 { + _x12 = &x12[0] + } + var _x21 *float64 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _x22 *float64 + if len(x22) > 0 { + _x22 = &x22[0] + } + var _theta *float64 + if len(theta) > 0 { + _theta = &theta[0] + } + var _phi *float64 + if len(phi) > 0 { + _phi = &phi[0] + } + var _taup1 *float64 + if len(taup1) > 0 { + _taup1 = &taup1[0] + } + var _taup2 *float64 + if len(taup2) > 0 { + _taup2 = &taup2[0] + } + var _tauq1 *float64 + if len(tauq1) > 0 { + _tauq1 = &tauq1[0] + } + var _tauq2 *float64 + if len(tauq2) > 0 { + _tauq2 = &tauq2[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dorbdb_work((C.int)(rowMajor), (C.char)(trans), (C.char)(signs), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.double)(_x11), (C.lapack_int)(ldx11), (*C.double)(_x12), (C.lapack_int)(ldx12), (*C.double)(_x21), (C.lapack_int)(ldx21), (*C.double)(_x22), (C.lapack_int)(ldx22), (*C.double)(_theta), (*C.double)(_phi), (*C.double)(_taup1), (*C.double)(_taup2), (*C.double)(_tauq1), (*C.double)(_tauq2), (*C.double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorcsd.f. +func Dorcsd(jobu1, jobu2, jobv1t, jobv2t lapack.Job, trans blas.Transpose, signs byte, m, p, q int, x11 []float64, ldx11 int, x12 []float64, ldx12 int, x21 []float64, ldx21 int, x22 []float64, ldx22 int, theta, u1 []float64, ldu1 int, u2 []float64, ldu2 int, v1t []float64, ldv1t int, v2t []float64, ldv2t int, work []float64, lwork int, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _x11 *float64 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x12 *float64 + if len(x12) > 0 { + _x12 = &x12[0] + } + var _x21 *float64 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _x22 *float64 + if len(x22) > 0 { + _x22 = &x22[0] + } + var _theta *float64 + if len(theta) > 0 { + _theta = &theta[0] + } + var _u1 *float64 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *float64 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *float64 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _v2t *float64 + if len(v2t) > 0 { + _v2t = &v2t[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dorcsd_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.char)(jobv2t), (C.char)(trans), (C.char)(signs), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.double)(_x11), (C.lapack_int)(ldx11), (*C.double)(_x12), (C.lapack_int)(ldx12), (*C.double)(_x21), (C.lapack_int)(ldx21), (*C.double)(_x22), (C.lapack_int)(ldx22), (*C.double)(_theta), (*C.double)(_u1), (C.lapack_int)(ldu1), (*C.double)(_u2), (C.lapack_int)(ldu2), (*C.double)(_v1t), (C.lapack_int)(ldv1t), (*C.double)(_v2t), (C.lapack_int)(ldv2t), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorcsd2by1.f. +func Dorcsd2by1(jobu1, jobu2, jobv1t lapack.Job, m, p, q int, x11 []float64, ldx11 int, x21 []float64, ldx21 int, theta, u1 []float64, ldu1 int, u2 []float64, ldu2 int, v1t []float64, ldv1t int, work []float64, lwork int, iwork []int32) bool { + var _x11 *float64 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x21 *float64 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _theta *float64 + if len(theta) > 0 { + _theta = &theta[0] + } + var _u1 *float64 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *float64 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *float64 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_dorcsd2by1_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.double)(_x11), (C.lapack_int)(ldx11), (*C.double)(_x21), (C.lapack_int)(ldx21), (*C.double)(_theta), (*C.double)(_u1), (C.lapack_int)(ldu1), (*C.double)(_u2), (C.lapack_int)(ldu2), (*C.double)(_v1t), (C.lapack_int)(ldv1t), (*C.double)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsyconv.f. +func Dsyconv(ul blas.Uplo, way byte, n int, a []float64, lda int, ipiv []int32, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsyconv_work((C.int)(rowMajor), (C.char)(ul), (C.char)(way), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsyswapr.f. +func Dsyswapr(ul blas.Uplo, n int, a []float64, i1, i2 int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_dsyswapr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(i1), (C.lapack_int)(i2))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsytri2.f. +func Dsytri2(ul blas.Uplo, n int, a []float64, lda int, ipiv []int32, work []complex128, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsytri2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsytri2x.f. +func Dsytri2x(ul blas.Uplo, n int, a []float64, lda int, ipiv []int32, work []float64, nb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsytri2x_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_work), (C.lapack_int)(nb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsytrs2.f. +func Dsytrs2(ul blas.Uplo, n, nrhs int, a []float64, lda int, ipiv []int32, b []float64, ldb int, work []float64) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dsytrs2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sbbcsd.f. +func Sbbcsd(jobu1, jobu2, jobv1t, jobv2t lapack.Job, trans blas.Transpose, m, p, q int, theta, phi, u1 []float32, ldu1 int, u2 []float32, ldu2 int, v1t []float32, ldv1t int, v2t []float32, ldv2t int, b11d, b11e, b12d, b12e, b21d, b21e, b22d, b22e, work []float32, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _theta *float32 + if len(theta) > 0 { + _theta = &theta[0] + } + var _phi *float32 + if len(phi) > 0 { + _phi = &phi[0] + } + var _u1 *float32 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *float32 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *float32 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _v2t *float32 + if len(v2t) > 0 { + _v2t = &v2t[0] + } + var _b11d *float32 + if len(b11d) > 0 { + _b11d = &b11d[0] + } + var _b11e *float32 + if len(b11e) > 0 { + _b11e = &b11e[0] + } + var _b12d *float32 + if len(b12d) > 0 { + _b12d = &b12d[0] + } + var _b12e *float32 + if len(b12e) > 0 { + _b12e = &b12e[0] + } + var _b21d *float32 + if len(b21d) > 0 { + _b21d = &b21d[0] + } + var _b21e *float32 + if len(b21e) > 0 { + _b21e = &b21e[0] + } + var _b22d *float32 + if len(b22d) > 0 { + _b22d = &b22d[0] + } + var _b22e *float32 + if len(b22e) > 0 { + _b22e = &b22e[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sbbcsd_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.char)(jobv2t), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.float)(_theta), (*C.float)(_phi), (*C.float)(_u1), (C.lapack_int)(ldu1), (*C.float)(_u2), (C.lapack_int)(ldu2), (*C.float)(_v1t), (C.lapack_int)(ldv1t), (*C.float)(_v2t), (C.lapack_int)(ldv2t), (*C.float)(_b11d), (*C.float)(_b11e), (*C.float)(_b12d), (*C.float)(_b12e), (*C.float)(_b21d), (*C.float)(_b21e), (*C.float)(_b22d), (*C.float)(_b22e), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorbdb.f. +func Sorbdb(trans blas.Transpose, signs byte, m, p, q int, x11 []float32, ldx11 int, x12 []float32, ldx12 int, x21 []float32, ldx21 int, x22 []float32, ldx22 int, theta, phi, taup1, taup2, tauq1, tauq2, work []float32, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _x11 *float32 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x12 *float32 + if len(x12) > 0 { + _x12 = &x12[0] + } + var _x21 *float32 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _x22 *float32 + if len(x22) > 0 { + _x22 = &x22[0] + } + var _theta *float32 + if len(theta) > 0 { + _theta = &theta[0] + } + var _phi *float32 + if len(phi) > 0 { + _phi = &phi[0] + } + var _taup1 *float32 + if len(taup1) > 0 { + _taup1 = &taup1[0] + } + var _taup2 *float32 + if len(taup2) > 0 { + _taup2 = &taup2[0] + } + var _tauq1 *float32 + if len(tauq1) > 0 { + _tauq1 = &tauq1[0] + } + var _tauq2 *float32 + if len(tauq2) > 0 { + _tauq2 = &tauq2[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sorbdb_work((C.int)(rowMajor), (C.char)(trans), (C.char)(signs), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.float)(_x11), (C.lapack_int)(ldx11), (*C.float)(_x12), (C.lapack_int)(ldx12), (*C.float)(_x21), (C.lapack_int)(ldx21), (*C.float)(_x22), (C.lapack_int)(ldx22), (*C.float)(_theta), (*C.float)(_phi), (*C.float)(_taup1), (*C.float)(_taup2), (*C.float)(_tauq1), (*C.float)(_tauq2), (*C.float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorcsd.f. +func Sorcsd(jobu1, jobu2, jobv1t, jobv2t lapack.Job, trans blas.Transpose, signs byte, m, p, q int, x11 []float32, ldx11 int, x12 []float32, ldx12 int, x21 []float32, ldx21 int, x22 []float32, ldx22 int, theta, u1 []float32, ldu1 int, u2 []float32, ldu2 int, v1t []float32, ldv1t int, v2t []float32, ldv2t int, work []float32, lwork int, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _x11 *float32 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x12 *float32 + if len(x12) > 0 { + _x12 = &x12[0] + } + var _x21 *float32 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _x22 *float32 + if len(x22) > 0 { + _x22 = &x22[0] + } + var _theta *float32 + if len(theta) > 0 { + _theta = &theta[0] + } + var _u1 *float32 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *float32 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *float32 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _v2t *float32 + if len(v2t) > 0 { + _v2t = &v2t[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sorcsd_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.char)(jobv2t), (C.char)(trans), (C.char)(signs), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.float)(_x11), (C.lapack_int)(ldx11), (*C.float)(_x12), (C.lapack_int)(ldx12), (*C.float)(_x21), (C.lapack_int)(ldx21), (*C.float)(_x22), (C.lapack_int)(ldx22), (*C.float)(_theta), (*C.float)(_u1), (C.lapack_int)(ldu1), (*C.float)(_u2), (C.lapack_int)(ldu2), (*C.float)(_v1t), (C.lapack_int)(ldv1t), (*C.float)(_v2t), (C.lapack_int)(ldv2t), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sorcsd2by1.f. +func Sorcsd2by1(jobu1, jobu2, jobv1t lapack.Job, m, p, q int, x11 []float32, ldx11 int, x21 []float32, ldx21 int, theta, u1 []float32, ldu1 int, u2 []float32, ldu2 int, v1t []float32, ldv1t int, work []float32, lwork int, iwork []int32) bool { + var _x11 *float32 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x21 *float32 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _theta *float32 + if len(theta) > 0 { + _theta = &theta[0] + } + var _u1 *float32 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *float32 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *float32 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_sorcsd2by1_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.float)(_x11), (C.lapack_int)(ldx11), (*C.float)(_x21), (C.lapack_int)(ldx21), (*C.float)(_theta), (*C.float)(_u1), (C.lapack_int)(ldu1), (*C.float)(_u2), (C.lapack_int)(ldu2), (*C.float)(_v1t), (C.lapack_int)(ldv1t), (*C.float)(_work), (C.lapack_int)(lwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssyconv.f. +func Ssyconv(ul blas.Uplo, way byte, n int, a []float32, lda int, ipiv []int32, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssyconv_work((C.int)(rowMajor), (C.char)(ul), (C.char)(way), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssyswapr.f. +func Ssyswapr(ul blas.Uplo, n int, a []float32, i1, i2 int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_ssyswapr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(i1), (C.lapack_int)(i2))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssytri2.f. +func Ssytri2(ul blas.Uplo, n int, a []float32, lda int, ipiv []int32, work []complex64, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssytri2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_float)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssytri2x.f. +func Ssytri2x(ul blas.Uplo, n int, a []float32, lda int, ipiv []int32, work []float32, nb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssytri2x_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_work), (C.lapack_int)(nb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssytrs2.f. +func Ssytrs2(ul blas.Uplo, n, nrhs int, a []float32, lda int, ipiv []int32, b []float32, ldb int, work []float32) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ssytrs2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.float)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zbbcsd.f. +func Zbbcsd(jobu1, jobu2, jobv1t, jobv2t lapack.Job, trans blas.Transpose, m, p, q int, theta, phi []float64, u1 []complex128, ldu1 int, u2 []complex128, ldu2 int, v1t []complex128, ldv1t int, v2t []complex128, ldv2t int, b11d, b11e, b12d, b12e, b21d, b21e, b22d, b22e, rwork []float64, lrwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _theta *float64 + if len(theta) > 0 { + _theta = &theta[0] + } + var _phi *float64 + if len(phi) > 0 { + _phi = &phi[0] + } + var _u1 *complex128 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *complex128 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *complex128 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _v2t *complex128 + if len(v2t) > 0 { + _v2t = &v2t[0] + } + var _b11d *float64 + if len(b11d) > 0 { + _b11d = &b11d[0] + } + var _b11e *float64 + if len(b11e) > 0 { + _b11e = &b11e[0] + } + var _b12d *float64 + if len(b12d) > 0 { + _b12d = &b12d[0] + } + var _b12e *float64 + if len(b12e) > 0 { + _b12e = &b12e[0] + } + var _b21d *float64 + if len(b21d) > 0 { + _b21d = &b21d[0] + } + var _b21e *float64 + if len(b21e) > 0 { + _b21e = &b21e[0] + } + var _b22d *float64 + if len(b22d) > 0 { + _b22d = &b22d[0] + } + var _b22e *float64 + if len(b22e) > 0 { + _b22e = &b22e[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + return isZero(C.LAPACKE_zbbcsd_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.char)(jobv2t), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.double)(_theta), (*C.double)(_phi), (*C.lapack_complex_double)(_u1), (C.lapack_int)(ldu1), (*C.lapack_complex_double)(_u2), (C.lapack_int)(ldu2), (*C.lapack_complex_double)(_v1t), (C.lapack_int)(ldv1t), (*C.lapack_complex_double)(_v2t), (C.lapack_int)(ldv2t), (*C.double)(_b11d), (*C.double)(_b11e), (*C.double)(_b12d), (*C.double)(_b12e), (*C.double)(_b21d), (*C.double)(_b21e), (*C.double)(_b22d), (*C.double)(_b22e), (*C.double)(_rwork), (C.lapack_int)(lrwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zheswapr.f. +func Zheswapr(ul blas.Uplo, n int, a []complex128, i1, i2 int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zheswapr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(i1), (C.lapack_int)(i2))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetri2.f. +func Zhetri2(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, work []complex128, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhetri2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetri2x.f. +func Zhetri2x(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, work []complex128, nb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhetri2x_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work), (C.lapack_int)(nb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetrs2.f. +func Zhetrs2(ul blas.Uplo, n, nrhs int, a []complex128, lda int, ipiv []int32, b []complex128, ldb int, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zhetrs2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsyconv.f. +func Zsyconv(ul blas.Uplo, way byte, n int, a []complex128, lda int, ipiv []int32, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsyconv_work((C.int)(rowMajor), (C.char)(ul), (C.char)(way), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsyswapr.f. +func Zsyswapr(ul blas.Uplo, n int, a []complex128, i1, i2 int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zsyswapr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(i1), (C.lapack_int)(i2))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsytri2.f. +func Zsytri2(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, work []complex128, lwork int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsytri2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsytri2x.f. +func Zsytri2x(ul blas.Uplo, n int, a []complex128, lda int, ipiv []int32, work []complex128, nb int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsytri2x_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_work), (C.lapack_int)(nb))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsytrs2.f. +func Zsytrs2(ul blas.Uplo, n, nrhs int, a []complex128, lda int, ipiv []int32, b []complex128, ldb int, work []complex128) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _ipiv *int32 + if len(ipiv) > 0 { + _ipiv = &ipiv[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zsytrs2_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_int)(nrhs), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_int)(_ipiv), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zunbdb.f. +func Zunbdb(trans blas.Transpose, signs byte, m, p, q int, x11 []complex128, ldx11 int, x12 []complex128, ldx12 int, x21 []complex128, ldx21 int, x22 []complex128, ldx22 int, theta, phi []float64, taup1, taup2, tauq1, tauq2, work []complex128, lwork int) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _x11 *complex128 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x12 *complex128 + if len(x12) > 0 { + _x12 = &x12[0] + } + var _x21 *complex128 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _x22 *complex128 + if len(x22) > 0 { + _x22 = &x22[0] + } + var _theta *float64 + if len(theta) > 0 { + _theta = &theta[0] + } + var _phi *float64 + if len(phi) > 0 { + _phi = &phi[0] + } + var _taup1 *complex128 + if len(taup1) > 0 { + _taup1 = &taup1[0] + } + var _taup2 *complex128 + if len(taup2) > 0 { + _taup2 = &taup2[0] + } + var _tauq1 *complex128 + if len(tauq1) > 0 { + _tauq1 = &tauq1[0] + } + var _tauq2 *complex128 + if len(tauq2) > 0 { + _tauq2 = &tauq2[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zunbdb_work((C.int)(rowMajor), (C.char)(trans), (C.char)(signs), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.lapack_complex_double)(_x11), (C.lapack_int)(ldx11), (*C.lapack_complex_double)(_x12), (C.lapack_int)(ldx12), (*C.lapack_complex_double)(_x21), (C.lapack_int)(ldx21), (*C.lapack_complex_double)(_x22), (C.lapack_int)(ldx22), (*C.double)(_theta), (*C.double)(_phi), (*C.lapack_complex_double)(_taup1), (*C.lapack_complex_double)(_taup2), (*C.lapack_complex_double)(_tauq1), (*C.lapack_complex_double)(_tauq2), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zuncsd.f. +func Zuncsd(jobu1, jobu2, jobv1t, jobv2t lapack.Job, trans blas.Transpose, signs byte, m, p, q int, x11 []complex128, ldx11 int, x12 []complex128, ldx12 int, x21 []complex128, ldx21 int, x22 []complex128, ldx22 int, theta []float64, u1 []complex128, ldu1 int, u2 []complex128, ldu2 int, v1t []complex128, ldv1t int, v2t []complex128, ldv2t int, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32) bool { + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _x11 *complex128 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x12 *complex128 + if len(x12) > 0 { + _x12 = &x12[0] + } + var _x21 *complex128 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _x22 *complex128 + if len(x22) > 0 { + _x22 = &x22[0] + } + var _theta *float64 + if len(theta) > 0 { + _theta = &theta[0] + } + var _u1 *complex128 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *complex128 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *complex128 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _v2t *complex128 + if len(v2t) > 0 { + _v2t = &v2t[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zuncsd_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.char)(jobv2t), (C.char)(trans), (C.char)(signs), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.lapack_complex_double)(_x11), (C.lapack_int)(ldx11), (*C.lapack_complex_double)(_x12), (C.lapack_int)(ldx12), (*C.lapack_complex_double)(_x21), (C.lapack_int)(ldx21), (*C.lapack_complex_double)(_x22), (C.lapack_int)(ldx22), (*C.double)(_theta), (*C.lapack_complex_double)(_u1), (C.lapack_int)(ldu1), (*C.lapack_complex_double)(_u2), (C.lapack_int)(ldu2), (*C.lapack_complex_double)(_v1t), (C.lapack_int)(ldv1t), (*C.lapack_complex_double)(_v2t), (C.lapack_int)(ldv2t), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zuncsd2by1.f. +func Zuncsd2by1(jobu1, jobu2, jobv1t lapack.Job, m, p, q int, x11 []complex128, ldx11 int, x21 []complex128, ldx21 int, theta, u1 []complex128, ldu1 int, u2 []complex128, ldu2 int, v1t []complex128, ldv1t int, work []complex128, lwork int, rwork []float64, lrwork int, iwork []int32) bool { + var _x11 *complex128 + if len(x11) > 0 { + _x11 = &x11[0] + } + var _x21 *complex128 + if len(x21) > 0 { + _x21 = &x21[0] + } + var _theta *complex128 + if len(theta) > 0 { + _theta = &theta[0] + } + var _u1 *complex128 + if len(u1) > 0 { + _u1 = &u1[0] + } + var _u2 *complex128 + if len(u2) > 0 { + _u2 = &u2[0] + } + var _v1t *complex128 + if len(v1t) > 0 { + _v1t = &v1t[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + var _rwork *float64 + if len(rwork) > 0 { + _rwork = &rwork[0] + } + var _iwork *int32 + if len(iwork) > 0 { + _iwork = &iwork[0] + } + return isZero(C.LAPACKE_zuncsd2by1_work((C.int)(rowMajor), (C.char)(jobu1), (C.char)(jobu2), (C.char)(jobv1t), (C.lapack_int)(m), (C.lapack_int)(p), (C.lapack_int)(q), (*C.lapack_complex_double)(_x11), (C.lapack_int)(ldx11), (*C.lapack_complex_double)(_x21), (C.lapack_int)(ldx21), (*C.lapack_complex_double)(_theta), (*C.lapack_complex_double)(_u1), (C.lapack_int)(ldu1), (*C.lapack_complex_double)(_u2), (C.lapack_int)(ldu2), (*C.lapack_complex_double)(_v1t), (C.lapack_int)(ldv1t), (*C.lapack_complex_double)(_work), (C.lapack_int)(lwork), (*C.double)(_rwork), (C.lapack_int)(lrwork), (*C.lapack_int)(_iwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgemqrt.f. +func Sgemqrt(side blas.Side, trans blas.Transpose, m, n, k, nb int, v []float32, ldv int, t []float32, ldt int, c []float32, ldc int, work []float32) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _c *float32 + if len(c) > 0 { + _c = &c[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgemqrt_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(nb), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_c), (C.lapack_int)(ldc), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgemqrt.f. +func Dgemqrt(side blas.Side, trans blas.Transpose, m, n, k, nb int, v []float64, ldv int, t []float64, ldt int, c []float64, ldc int, work []float64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _c *float64 + if len(c) > 0 { + _c = &c[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgemqrt_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(nb), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_c), (C.lapack_int)(ldc), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgemqrt.f. +func Cgemqrt(side blas.Side, trans blas.Transpose, m, n, k, nb int, v []complex64, ldv int, t []complex64, ldt int, c []complex64, ldc int, work []complex64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _c *complex64 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgemqrt_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(nb), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgemqrt.f. +func Zgemqrt(side blas.Side, trans blas.Transpose, m, n, k, nb int, v []complex128, ldv int, t []complex128, ldt int, c []complex128, ldc int, work []complex128) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _c *complex128 + if len(c) > 0 { + _c = &c[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgemqrt_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(nb), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_c), (C.lapack_int)(ldc), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeqrt.f. +func Sgeqrt(m, n, nb int, a []float32, lda int, t []float32, ldt int, work []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_sgeqrt_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nb), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeqrt.f. +func Dgeqrt(m, n, nb int, a []float64, lda int, t []float64, ldt int, work []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dgeqrt_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nb), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeqrt.f. +func Cgeqrt(m, n, nb int, a []complex64, lda int, t []complex64, ldt int, work []complex64) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_cgeqrt_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nb), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeqrt.f. +func Zgeqrt(m, n, nb int, a []complex128, lda int, t []complex128, ldt int, work []complex128) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_zgeqrt_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(nb), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeqrt2.f. +func Sgeqrt2(m, n int, a []float32, lda int, t []float32, ldt int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_sgeqrt2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeqrt2.f. +func Dgeqrt2(m, n int, a []float64, lda int, t []float64, ldt int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_dgeqrt2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeqrt2.f. +func Cgeqrt2(m, n int, a []complex64, lda int, t []complex64, ldt int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_cgeqrt2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeqrt2.f. +func Zgeqrt2(m, n int, a []complex128, lda int, t []complex128, ldt int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_zgeqrt2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgeqrt3.f. +func Sgeqrt3(m, n int, a []float32, lda int, t []float32, ldt int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_sgeqrt3_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgeqrt3.f. +func Dgeqrt3(m, n int, a []float64, lda int, t []float64, ldt int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_dgeqrt3_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgeqrt3.f. +func Cgeqrt3(m, n int, a []complex64, lda int, t []complex64, ldt int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_cgeqrt3_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgeqrt3.f. +func Zgeqrt3(m, n int, a []complex128, lda int, t []complex128, ldt int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_zgeqrt3_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stpmqrt.f. +func Stpmqrt(side blas.Side, trans blas.Transpose, m, n, k, l, nb int, v []float32, ldv int, t []float32, ldt int, a []float32, lda int, b []float32, ldb int, work []float32) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_stpmqrt_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (C.lapack_int)(nb), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtpmqrt.f. +func Dtpmqrt(side blas.Side, trans blas.Transpose, m, n, k, l, nb int, v []float64, ldv int, t []float64, ldt int, a []float64, lda int, b []float64, ldb int, work []float64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dtpmqrt_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (C.lapack_int)(nb), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctpmqrt.f. +func Ctpmqrt(side blas.Side, trans blas.Transpose, m, n, k, l, nb int, v []complex64, ldv int, t []complex64, ldt int, a []complex64, lda int, b []complex64, ldb int, work []complex64) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ctpmqrt_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (C.lapack_int)(nb), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztpmqrt.f. +func Ztpmqrt(side blas.Side, trans blas.Transpose, m, n, k, l, nb int, v []complex128, ldv int, t []complex128, ldt int, a []complex128, lda int, b []complex128, ldb int, work []complex128) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ztpmqrt_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (C.lapack_int)(nb), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stpqrt.f. +func Stpqrt(m, n, l, nb int, a []float32, lda int, b []float32, ldb int, t []float32, ldt int, work []float32) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_stpqrt_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(l), (C.lapack_int)(nb), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtpqrt.f. +func Dtpqrt(m, n, l, nb int, a []float64, lda int, b []float64, ldb int, t []float64, ldt int, work []float64) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dtpqrt_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(l), (C.lapack_int)(nb), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctpqrt.f. +func Ctpqrt(m, n, l, nb int, a []complex64, lda int, b []complex64, ldb int, t []complex64, ldt int, work []complex64) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ctpqrt_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(l), (C.lapack_int)(nb), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztpqrt.f. +func Ztpqrt(m, n, l, nb int, a []complex128, lda int, b []complex128, ldb int, t []complex128, ldt int, work []complex128) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ztpqrt_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(l), (C.lapack_int)(nb), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_work))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stpqrt2.f. +func Stpqrt2(m, n, l int, a []float32, lda int, b []float32, ldb int, t []float32, ldt int) bool { + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_stpqrt2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(l), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtpqrt2.f. +func Dtpqrt2(m, n, l int, a []float64, lda int, b []float64, ldb int, t []float64, ldt int) bool { + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_dtpqrt2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(l), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctpqrt2.f. +func Ctpqrt2(m, n, l int, a []complex64, lda int, b []complex64, ldb int, t []complex64, ldt int) bool { + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_ctpqrt2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(l), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztpqrt2.f. +func Ztpqrt2(m, n, l int, a []complex128, lda int, b []complex128, ldb int, t []complex128, ldt int) bool { + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + return isZero(C.LAPACKE_ztpqrt2_work((C.int)(rowMajor), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(l), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stprfb.f. +func Stprfb(side blas.Side, trans blas.Transpose, direct, storev byte, m, n, k, l int, v []float32, ldv int, t []float32, ldt int, a []float32, lda int, b []float32, ldb int, work []float32, ldwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *float32 + if len(v) > 0 { + _v = &v[0] + } + var _t *float32 + if len(t) > 0 { + _t = &t[0] + } + var _a *float32 + if len(a) > 0 { + _a = &a[0] + } + var _b *float32 + if len(b) > 0 { + _b = &b[0] + } + var _work *float32 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_stprfb_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.char)(direct), (C.char)(storev), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.float)(_v), (C.lapack_int)(ldv), (*C.float)(_t), (C.lapack_int)(ldt), (*C.float)(_a), (C.lapack_int)(lda), (*C.float)(_b), (C.lapack_int)(ldb), (*C.float)(_work), (C.lapack_int)(ldwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtprfb.f. +func Dtprfb(side blas.Side, trans blas.Transpose, direct, storev byte, m, n, k, l int, v []float64, ldv int, t []float64, ldt int, a []float64, lda int, b []float64, ldb int, work []float64, ldwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *float64 + if len(v) > 0 { + _v = &v[0] + } + var _t *float64 + if len(t) > 0 { + _t = &t[0] + } + var _a *float64 + if len(a) > 0 { + _a = &a[0] + } + var _b *float64 + if len(b) > 0 { + _b = &b[0] + } + var _work *float64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_dtprfb_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.char)(direct), (C.char)(storev), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.double)(_v), (C.lapack_int)(ldv), (*C.double)(_t), (C.lapack_int)(ldt), (*C.double)(_a), (C.lapack_int)(lda), (*C.double)(_b), (C.lapack_int)(ldb), (*C.double)(_work), (C.lapack_int)(ldwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctprfb.f. +func Ctprfb(side blas.Side, trans blas.Transpose, direct, storev byte, m, n, k, l int, v []complex64, ldv int, t []complex64, ldt int, a []complex64, lda int, b []complex64, ldb int, work []complex64, ldwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *complex64 + if len(v) > 0 { + _v = &v[0] + } + var _t *complex64 + if len(t) > 0 { + _t = &t[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex64 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex64 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ctprfb_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.char)(direct), (C.char)(storev), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.lapack_complex_float)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_float)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda), (*C.lapack_complex_float)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_float)(_work), (C.lapack_int)(ldwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztprfb.f. +func Ztprfb(side blas.Side, trans blas.Transpose, direct, storev byte, m, n, k, l int, v []complex128, ldv int, t []complex128, ldt int, a []complex128, lda int, b []complex128, ldb int, work []complex128, ldwork int) bool { + switch side { + case blas.Left: + side = 'L' + case blas.Right: + side = 'R' + default: + panic("lapack: bad side") + } + switch trans { + case blas.NoTrans: + trans = 'N' + case blas.Trans: + trans = 'T' + case blas.ConjTrans: + trans = 'C' + default: + panic("lapack: bad trans") + } + var _v *complex128 + if len(v) > 0 { + _v = &v[0] + } + var _t *complex128 + if len(t) > 0 { + _t = &t[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + var _b *complex128 + if len(b) > 0 { + _b = &b[0] + } + var _work *complex128 + if len(work) > 0 { + _work = &work[0] + } + return isZero(C.LAPACKE_ztprfb_work((C.int)(rowMajor), (C.char)(side), (C.char)(trans), (C.char)(direct), (C.char)(storev), (C.lapack_int)(m), (C.lapack_int)(n), (C.lapack_int)(k), (C.lapack_int)(l), (*C.lapack_complex_double)(_v), (C.lapack_int)(ldv), (*C.lapack_complex_double)(_t), (C.lapack_int)(ldt), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda), (*C.lapack_complex_double)(_b), (C.lapack_int)(ldb), (*C.lapack_complex_double)(_work), (C.lapack_int)(ldwork))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csyr.f. +func Csyr(ul blas.Uplo, n int, alpha complex64, x []complex64, incx int, a []complex64, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _x *complex64 + if len(x) > 0 { + _x = &x[0] + } + var _a *complex64 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_csyr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_complex_float)(alpha), (*C.lapack_complex_float)(_x), (C.lapack_int)(incx), (*C.lapack_complex_float)(_a), (C.lapack_int)(lda))) +} + +// See http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsyr.f. +func Zsyr(ul blas.Uplo, n int, alpha complex128, x []complex128, incx int, a []complex128, lda int) bool { + switch ul { + case blas.Upper: + ul = 'U' + case blas.Lower: + ul = 'L' + default: + panic("lapack: illegal triangle") + } + var _x *complex128 + if len(x) > 0 { + _x = &x[0] + } + var _a *complex128 + if len(a) > 0 { + _a = &a[0] + } + return isZero(C.LAPACKE_zsyr_work((C.int)(rowMajor), (C.char)(ul), (C.lapack_int)(n), (C.lapack_complex_double)(alpha), (*C.lapack_complex_double)(_x), (C.lapack_int)(incx), (*C.lapack_complex_double)(_a), (C.lapack_int)(lda))) +} diff --git a/lapack/cgo/lapacke/lapacke.h b/lapack/cgo/lapacke/lapacke.h new file mode 100644 index 00000000..03c33213 --- /dev/null +++ b/lapack/cgo/lapacke/lapacke.h @@ -0,0 +1,17553 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +****************************************************************************** +* Contents: Native C interface to LAPACK +* Author: Intel Corporation +* Generated August, 2015 +*****************************************************************************/ + +#ifndef _LAPACKE_H_ +#define _LAPACKE_H_ + +/* +* Turn on HAVE_LAPACK_CONFIG_H to redefine C-LAPACK datatypes +*/ +#ifdef HAVE_LAPACK_CONFIG_H +#include "lapacke_config.h" +#endif + +#include + +#ifndef lapack_int +#define lapack_int int +#endif + +#ifndef lapack_logical +#define lapack_logical lapack_int +#endif + +/* Complex types are structures equivalent to the +* Fortran complex types COMPLEX(4) and COMPLEX(8). +* +* One can also redefine the types with his own types +* for example by including in the code definitions like +* +* #define lapack_complex_float std::complex +* #define lapack_complex_double std::complex +* +* or define these types in the command line: +* +* -Dlapack_complex_float="std::complex" +* -Dlapack_complex_double="std::complex" +*/ + +#ifndef LAPACK_COMPLEX_CUSTOM + +/* Complex type (single precision) */ +#ifndef lapack_complex_float +#include +#define lapack_complex_float float _Complex +#endif + +#ifndef lapack_complex_float_real +#define lapack_complex_float_real(z) (creal(z)) +#endif + +#ifndef lapack_complex_float_imag +#define lapack_complex_float_imag(z) (cimag(z)) +#endif + +lapack_complex_float lapack_make_complex_float( float re, float im ); + +/* Complex type (double precision) */ +#ifndef lapack_complex_double +#include +#define lapack_complex_double double _Complex +#endif + +#ifndef lapack_complex_double_real +#define lapack_complex_double_real(z) (creal(z)) +#endif + +#ifndef lapack_complex_double_imag +#define lapack_complex_double_imag(z) (cimag(z)) +#endif + +lapack_complex_double lapack_make_complex_double( double re, double im ); + +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef LAPACKE_malloc +#define LAPACKE_malloc( size ) malloc( size ) +#endif +#ifndef LAPACKE_free +#define LAPACKE_free( p ) free( p ) +#endif + +#define LAPACK_C2INT( x ) (lapack_int)(*((float*)&x )) +#define LAPACK_Z2INT( x ) (lapack_int)(*((double*)&x )) + +#define LAPACK_ROW_MAJOR 101 +#define LAPACK_COL_MAJOR 102 + +#define LAPACK_WORK_MEMORY_ERROR -1010 +#define LAPACK_TRANSPOSE_MEMORY_ERROR -1011 + +/* Callback logical functions of one, two, or three arguments are used +* to select eigenvalues to sort to the top left of the Schur form. +* The value is selected if function returns TRUE (non-zero). */ + +typedef lapack_logical (*LAPACK_S_SELECT2) ( const float*, const float* ); +typedef lapack_logical (*LAPACK_S_SELECT3) + ( const float*, const float*, const float* ); +typedef lapack_logical (*LAPACK_D_SELECT2) ( const double*, const double* ); +typedef lapack_logical (*LAPACK_D_SELECT3) + ( const double*, const double*, const double* ); + +typedef lapack_logical (*LAPACK_C_SELECT1) ( const lapack_complex_float* ); +typedef lapack_logical (*LAPACK_C_SELECT2) + ( const lapack_complex_float*, const lapack_complex_float* ); +typedef lapack_logical (*LAPACK_Z_SELECT1) ( const lapack_complex_double* ); +typedef lapack_logical (*LAPACK_Z_SELECT2) + ( const lapack_complex_double*, const lapack_complex_double* ); + +#include "lapacke_mangling.h" + +#define LAPACK_lsame LAPACK_GLOBAL(lsame,LSAME) +lapack_logical LAPACK_lsame( char* ca, char* cb, + lapack_int lca, lapack_int lcb ); + +/* C-LAPACK function prototypes */ + +lapack_int LAPACKE_sbdsdc( int matrix_layout, char uplo, char compq, + lapack_int n, float* d, float* e, float* u, + lapack_int ldu, float* vt, lapack_int ldvt, float* q, + lapack_int* iq ); +lapack_int LAPACKE_dbdsdc( int matrix_layout, char uplo, char compq, + lapack_int n, double* d, double* e, double* u, + lapack_int ldu, double* vt, lapack_int ldvt, + double* q, lapack_int* iq ); + +lapack_int LAPACKE_sbdsqr( int matrix_layout, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + float* d, float* e, float* vt, lapack_int ldvt, + float* u, lapack_int ldu, float* c, lapack_int ldc ); +lapack_int LAPACKE_dbdsqr( int matrix_layout, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + double* d, double* e, double* vt, lapack_int ldvt, + double* u, lapack_int ldu, double* c, + lapack_int ldc ); +lapack_int LAPACKE_cbdsqr( int matrix_layout, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + float* d, float* e, lapack_complex_float* vt, + lapack_int ldvt, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* c, + lapack_int ldc ); +lapack_int LAPACKE_zbdsqr( int matrix_layout, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + double* d, double* e, lapack_complex_double* vt, + lapack_int ldvt, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* c, + lapack_int ldc ); +lapack_int LAPACKE_sbdsvdx( int matrix_layout, char uplo, char jobz, char range, + lapack_int n, float* d, float* e, + lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + float* s, float* z, lapack_int ldz, + lapack_int* superb ); +lapack_int LAPACKE_dbdsvdx( int matrix_layout, char uplo, char jobz, char range, + lapack_int n, double* d, double* e, + lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + double* s, double* z, lapack_int ldz, + lapack_int* superb ); +lapack_int LAPACKE_sdisna( char job, lapack_int m, lapack_int n, const float* d, + float* sep ); +lapack_int LAPACKE_ddisna( char job, lapack_int m, lapack_int n, + const double* d, double* sep ); + +lapack_int LAPACKE_sgbbrd( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, float* ab, lapack_int ldab, float* d, + float* e, float* q, lapack_int ldq, float* pt, + lapack_int ldpt, float* c, lapack_int ldc ); +lapack_int LAPACKE_dgbbrd( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, double* ab, lapack_int ldab, + double* d, double* e, double* q, lapack_int ldq, + double* pt, lapack_int ldpt, double* c, + lapack_int ldc ); +lapack_int LAPACKE_cgbbrd( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, lapack_complex_float* ab, + lapack_int ldab, float* d, float* e, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* pt, lapack_int ldpt, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zgbbrd( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, lapack_complex_double* ab, + lapack_int ldab, double* d, double* e, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* pt, lapack_int ldpt, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_sgbcon( int matrix_layout, char norm, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, const lapack_int* ipiv, float anorm, + float* rcond ); +lapack_int LAPACKE_dgbcon( int matrix_layout, char norm, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, const lapack_int* ipiv, + double anorm, double* rcond ); +lapack_int LAPACKE_cgbcon( int matrix_layout, char norm, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zgbcon( int matrix_layout, char norm, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_sgbequ( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_dgbequ( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); +lapack_int LAPACKE_cgbequ( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_zgbequ( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, lapack_int ldab, + double* r, double* c, double* rowcnd, double* colcnd, + double* amax ); + +lapack_int LAPACKE_sgbequb( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_dgbequb( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); +lapack_int LAPACKE_cgbequb( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_zgbequb( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, lapack_int ldab, + double* r, double* c, double* rowcnd, + double* colcnd, double* amax ); + +lapack_int LAPACKE_sgbrfs( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const float* ab, lapack_int ldab, const float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dgbrfs( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const double* ab, lapack_int ldab, const double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_cgbrfs( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* afb, lapack_int ldafb, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zgbrfs( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* afb, lapack_int ldafb, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sgbrfsx( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const float* ab, lapack_int ldab, + const float* afb, lapack_int ldafb, + const lapack_int* ipiv, const float* r, + const float* c, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dgbrfsx( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const double* ab, lapack_int ldab, + const double* afb, lapack_int ldafb, + const lapack_int* ipiv, const double* r, + const double* c, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cgbrfsx( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const lapack_complex_float* ab, + lapack_int ldab, const lapack_complex_float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const float* r, const float* c, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zgbrfsx( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const lapack_complex_double* ab, + lapack_int ldab, const lapack_complex_double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const double* r, const double* c, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_sgbsv( int matrix_layout, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, float* ab, + lapack_int ldab, lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgbsv( int matrix_layout, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, double* ab, + lapack_int ldab, lapack_int* ipiv, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgbsv( int matrix_layout, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgbsv( int matrix_layout, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sgbsvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, float* ab, lapack_int ldab, + float* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* rpivot ); +lapack_int LAPACKE_dgbsvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, double* ab, lapack_int ldab, + double* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, double* r, double* c, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* rpivot ); +lapack_int LAPACKE_cgbsvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + float* r, float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, float* rpivot ); +lapack_int LAPACKE_zgbsvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + double* r, double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, double* rpivot ); + +lapack_int LAPACKE_sgbsvxx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, float* ab, lapack_int ldab, + float* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dgbsvxx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, double* ab, lapack_int ldab, + double* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, double* r, double* c, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); +lapack_int LAPACKE_cgbsvxx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + float* r, float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zgbsvxx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + double* r, double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_sgbtrf( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, float* ab, + lapack_int ldab, lapack_int* ipiv ); +lapack_int LAPACKE_dgbtrf( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, double* ab, + lapack_int ldab, lapack_int* ipiv ); +lapack_int LAPACKE_cgbtrf( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + lapack_complex_float* ab, lapack_int ldab, + lapack_int* ipiv ); +lapack_int LAPACKE_zgbtrf( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + lapack_complex_double* ab, lapack_int ldab, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgbtrs( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const float* ab, lapack_int ldab, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dgbtrs( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const double* ab, lapack_int ldab, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_cgbtrs( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgbtrs( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sgebak( int matrix_layout, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const float* scale, + lapack_int m, float* v, lapack_int ldv ); +lapack_int LAPACKE_dgebak( int matrix_layout, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const double* scale, + lapack_int m, double* v, lapack_int ldv ); +lapack_int LAPACKE_cgebak( int matrix_layout, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const float* scale, + lapack_int m, lapack_complex_float* v, + lapack_int ldv ); +lapack_int LAPACKE_zgebak( int matrix_layout, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const double* scale, + lapack_int m, lapack_complex_double* v, + lapack_int ldv ); + +lapack_int LAPACKE_sgebal( int matrix_layout, char job, lapack_int n, float* a, + lapack_int lda, lapack_int* ilo, lapack_int* ihi, + float* scale ); +lapack_int LAPACKE_dgebal( int matrix_layout, char job, lapack_int n, double* a, + lapack_int lda, lapack_int* ilo, lapack_int* ihi, + double* scale ); +lapack_int LAPACKE_cgebal( int matrix_layout, char job, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ilo, lapack_int* ihi, float* scale ); +lapack_int LAPACKE_zgebal( int matrix_layout, char job, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ilo, lapack_int* ihi, double* scale ); + +lapack_int LAPACKE_sgebrd( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* d, float* e, + float* tauq, float* taup ); +lapack_int LAPACKE_dgebrd( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* d, double* e, + double* tauq, double* taup ); +lapack_int LAPACKE_cgebrd( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, float* d, + float* e, lapack_complex_float* tauq, + lapack_complex_float* taup ); +lapack_int LAPACKE_zgebrd( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, double* d, + double* e, lapack_complex_double* tauq, + lapack_complex_double* taup ); + +lapack_int LAPACKE_sgecon( int matrix_layout, char norm, lapack_int n, + const float* a, lapack_int lda, float anorm, + float* rcond ); +lapack_int LAPACKE_dgecon( int matrix_layout, char norm, lapack_int n, + const double* a, lapack_int lda, double anorm, + double* rcond ); +lapack_int LAPACKE_cgecon( int matrix_layout, char norm, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float anorm, float* rcond ); +lapack_int LAPACKE_zgecon( int matrix_layout, char norm, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double anorm, double* rcond ); + +lapack_int LAPACKE_sgeequ( int matrix_layout, lapack_int m, lapack_int n, + const float* a, lapack_int lda, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_dgeequ( int matrix_layout, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* r, + double* c, double* rowcnd, double* colcnd, + double* amax ); +lapack_int LAPACKE_cgeequ( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_zgeequ( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* r, double* c, double* rowcnd, double* colcnd, + double* amax ); + +lapack_int LAPACKE_sgeequb( int matrix_layout, lapack_int m, lapack_int n, + const float* a, lapack_int lda, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_dgeequb( int matrix_layout, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* r, + double* c, double* rowcnd, double* colcnd, + double* amax ); +lapack_int LAPACKE_cgeequb( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_zgeequb( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* r, double* c, double* rowcnd, + double* colcnd, double* amax ); + +lapack_int LAPACKE_sgees( int matrix_layout, char jobvs, char sort, + LAPACK_S_SELECT2 select, lapack_int n, float* a, + lapack_int lda, lapack_int* sdim, float* wr, + float* wi, float* vs, lapack_int ldvs ); +lapack_int LAPACKE_dgees( int matrix_layout, char jobvs, char sort, + LAPACK_D_SELECT2 select, lapack_int n, double* a, + lapack_int lda, lapack_int* sdim, double* wr, + double* wi, double* vs, lapack_int ldvs ); +lapack_int LAPACKE_cgees( int matrix_layout, char jobvs, char sort, + LAPACK_C_SELECT1 select, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int ldvs ); +lapack_int LAPACKE_zgees( int matrix_layout, char jobvs, char sort, + LAPACK_Z_SELECT1 select, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int ldvs ); + +lapack_int LAPACKE_sgeesx( int matrix_layout, char jobvs, char sort, + LAPACK_S_SELECT2 select, char sense, lapack_int n, + float* a, lapack_int lda, lapack_int* sdim, + float* wr, float* wi, float* vs, lapack_int ldvs, + float* rconde, float* rcondv ); +lapack_int LAPACKE_dgeesx( int matrix_layout, char jobvs, char sort, + LAPACK_D_SELECT2 select, char sense, lapack_int n, + double* a, lapack_int lda, lapack_int* sdim, + double* wr, double* wi, double* vs, lapack_int ldvs, + double* rconde, double* rcondv ); +lapack_int LAPACKE_cgeesx( int matrix_layout, char jobvs, char sort, + LAPACK_C_SELECT1 select, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int ldvs, + float* rconde, float* rcondv ); +lapack_int LAPACKE_zgeesx( int matrix_layout, char jobvs, char sort, + LAPACK_Z_SELECT1 select, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int ldvs, + double* rconde, double* rcondv ); + +lapack_int LAPACKE_sgeev( int matrix_layout, char jobvl, char jobvr, + lapack_int n, float* a, lapack_int lda, float* wr, + float* wi, float* vl, lapack_int ldvl, float* vr, + lapack_int ldvr ); +lapack_int LAPACKE_dgeev( int matrix_layout, char jobvl, char jobvr, + lapack_int n, double* a, lapack_int lda, double* wr, + double* wi, double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr ); +lapack_int LAPACKE_cgeev( int matrix_layout, char jobvl, char jobvr, + lapack_int n, lapack_complex_float* a, lapack_int lda, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr ); +lapack_int LAPACKE_zgeev( int matrix_layout, char jobvl, char jobvr, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* w, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr ); + +lapack_int LAPACKE_sgeevx( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, float* a, + lapack_int lda, float* wr, float* wi, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* scale, + float* abnrm, float* rconde, float* rcondv ); +lapack_int LAPACKE_dgeevx( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, double* a, + lapack_int lda, double* wr, double* wi, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, double* scale, + double* abnrm, double* rconde, double* rcondv ); +lapack_int LAPACKE_cgeevx( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr, lapack_int* ilo, lapack_int* ihi, + float* scale, float* abnrm, float* rconde, + float* rcondv ); +lapack_int LAPACKE_zgeevx( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int ldvl, lapack_complex_double* vr, + lapack_int ldvr, lapack_int* ilo, lapack_int* ihi, + double* scale, double* abnrm, double* rconde, + double* rcondv ); + +lapack_int LAPACKE_sgehrd( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, float* a, lapack_int lda, + float* tau ); +lapack_int LAPACKE_dgehrd( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, double* a, lapack_int lda, + double* tau ); +lapack_int LAPACKE_cgehrd( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* tau ); +lapack_int LAPACKE_zgehrd( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* tau ); + +lapack_int LAPACKE_sgejsv( int matrix_layout, char joba, char jobu, char jobv, + char jobr, char jobt, char jobp, lapack_int m, + lapack_int n, float* a, lapack_int lda, float* sva, + float* u, lapack_int ldu, float* v, lapack_int ldv, + float* stat, lapack_int* istat ); +lapack_int LAPACKE_dgejsv( int matrix_layout, char joba, char jobu, char jobv, + char jobr, char jobt, char jobp, lapack_int m, + lapack_int n, double* a, lapack_int lda, double* sva, + double* u, lapack_int ldu, double* v, lapack_int ldv, + double* stat, lapack_int* istat ); +lapack_int LAPACKE_cgejsv( int matrix_layout, char joba, char jobu, char jobv, + char jobr, char jobt, char jobp, lapack_int m, + lapack_int n, lapack_complex_float* a, lapack_int lda, float* sva, + lapack_complex_float* u, lapack_int ldu, lapack_complex_float* v, lapack_int ldv, + float* stat, lapack_int* istat ); +lapack_int LAPACKE_zgejsv( int matrix_layout, char joba, char jobu, char jobv, + char jobr, char jobt, char jobp, lapack_int m, + lapack_int n, lapack_complex_double* a, lapack_int lda, double* sva, + lapack_complex_double* u, lapack_int ldu, lapack_complex_double* v, lapack_int ldv, + double* stat, lapack_int* istat ); + +lapack_int LAPACKE_sgelq2( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgelq2( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgelq2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgelq2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgelqf( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgelqf( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgelqf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgelqf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgels( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* b, lapack_int ldb ); +lapack_int LAPACKE_dgels( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* b, lapack_int ldb ); +lapack_int LAPACKE_cgels( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zgels( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sgelsd( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_dgelsd( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* s, double rcond, + lapack_int* rank ); +lapack_int LAPACKE_cgelsd( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_zgelsd( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* s, double rcond, + lapack_int* rank ); + +lapack_int LAPACKE_sgelss( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_dgelss( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* s, double rcond, + lapack_int* rank ); +lapack_int LAPACKE_cgelss( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_zgelss( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* s, double rcond, + lapack_int* rank ); + +lapack_int LAPACKE_sgelsy( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* b, + lapack_int ldb, lapack_int* jpvt, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_dgelsy( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, lapack_int* jpvt, + double rcond, lapack_int* rank ); +lapack_int LAPACKE_cgelsy( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_int* jpvt, float rcond, + lapack_int* rank ); +lapack_int LAPACKE_zgelsy( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_int* jpvt, double rcond, + lapack_int* rank ); + +lapack_int LAPACKE_sgeqlf( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgeqlf( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgeqlf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqlf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqp3( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* jpvt, + float* tau ); +lapack_int LAPACKE_dgeqp3( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* jpvt, + double* tau ); +lapack_int LAPACKE_cgeqp3( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqp3( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqpf( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* jpvt, + float* tau ); +lapack_int LAPACKE_dgeqpf( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* jpvt, + double* tau ); +lapack_int LAPACKE_cgeqpf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqpf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqr2( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgeqr2( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgeqr2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqr2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqrf( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgeqrf( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgeqrf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqrf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgeqrfp( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgeqrfp( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgeqrfp( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgeqrfp( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgerfs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dgerfs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_cgerfs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zgerfs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sgerfsx( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* r, + const float* c, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dgerfsx( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* r, + const double* c, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cgerfsx( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* r, + const float* c, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zgerfsx( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* r, + const double* c, const lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_sgerqf( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dgerqf( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_cgerqf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_zgerqf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_sgesdd( int matrix_layout, char jobz, lapack_int m, + lapack_int n, float* a, lapack_int lda, float* s, + float* u, lapack_int ldu, float* vt, + lapack_int ldvt ); +lapack_int LAPACKE_dgesdd( int matrix_layout, char jobz, lapack_int m, + lapack_int n, double* a, lapack_int lda, double* s, + double* u, lapack_int ldu, double* vt, + lapack_int ldvt ); +lapack_int LAPACKE_cgesdd( int matrix_layout, char jobz, lapack_int m, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float* s, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* vt, + lapack_int ldvt ); +lapack_int LAPACKE_zgesdd( int matrix_layout, char jobz, lapack_int m, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double* s, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* vt, + lapack_int ldvt ); + +lapack_int LAPACKE_sgesv( int matrix_layout, lapack_int n, lapack_int nrhs, + float* a, lapack_int lda, lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgesv( int matrix_layout, lapack_int n, lapack_int nrhs, + double* a, lapack_int lda, lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cgesv( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgesv( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); +lapack_int LAPACKE_dsgesv( int matrix_layout, lapack_int n, lapack_int nrhs, + double* a, lapack_int lda, lapack_int* ipiv, + double* b, lapack_int ldb, double* x, lapack_int ldx, + lapack_int* iter ); +lapack_int LAPACKE_zcgesv( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, lapack_int* iter ); + +lapack_int LAPACKE_sgesvd( int matrix_layout, char jobu, char jobvt, + lapack_int m, lapack_int n, float* a, lapack_int lda, + float* s, float* u, lapack_int ldu, float* vt, + lapack_int ldvt, float* superb ); +lapack_int LAPACKE_dgesvd( int matrix_layout, char jobu, char jobvt, + lapack_int m, lapack_int n, double* a, + lapack_int lda, double* s, double* u, lapack_int ldu, + double* vt, lapack_int ldvt, double* superb ); +lapack_int LAPACKE_cgesvd( int matrix_layout, char jobu, char jobvt, + lapack_int m, lapack_int n, lapack_complex_float* a, + lapack_int lda, float* s, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* vt, + lapack_int ldvt, float* superb ); +lapack_int LAPACKE_zgesvd( int matrix_layout, char jobu, char jobvt, + lapack_int m, lapack_int n, lapack_complex_double* a, + lapack_int lda, double* s, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* vt, + lapack_int ldvt, double* superb ); + +lapack_int LAPACKE_sgesvdx( int matrix_layout, char jobu, char jobvt, char range, + lapack_int m, lapack_int n, float* a, + lapack_int lda, lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + float* s, float* u, lapack_int ldu, + float* vt, lapack_int ldvt, + lapack_int* superb ); +lapack_int LAPACKE_dgesvdx( int matrix_layout, char jobu, char jobvt, char range, + lapack_int m, lapack_int n, double* a, + lapack_int lda, lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + double* s, double* u, lapack_int ldu, + double* vt, lapack_int ldvt, + lapack_int* superb ); +lapack_int LAPACKE_cgesvdx( int matrix_layout, char jobu, char jobvt, char range, + lapack_int m, lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + float* s, lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* vt, lapack_int ldvt, + lapack_int* superb ); +lapack_int LAPACKE_zgesvdx( int matrix_layout, char jobu, char jobvt, char range, + lapack_int m, lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + double* s, lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* vt, lapack_int ldvt, + lapack_int* superb ); + +lapack_int LAPACKE_sgesvj( int matrix_layout, char joba, char jobu, char jobv, + lapack_int m, lapack_int n, float* a, lapack_int lda, + float* sva, lapack_int mv, float* v, lapack_int ldv, + float* stat ); +lapack_int LAPACKE_dgesvj( int matrix_layout, char joba, char jobu, char jobv, + lapack_int m, lapack_int n, double* a, + lapack_int lda, double* sva, lapack_int mv, + double* v, lapack_int ldv, double* stat ); +lapack_int LAPACKE_cgesvj( int matrix_layout, char joba, char jobu, char jobv, + lapack_int m, lapack_int n, lapack_complex_float* a, + lapack_int lda, float* sva, lapack_int mv, + lapack_complex_float* v, lapack_int ldv, float* stat ); +lapack_int LAPACKE_zgesvj( int matrix_layout, char joba, char jobu, char jobv, + lapack_int m, lapack_int n, lapack_complex_double* a, + lapack_int lda, double* sva, lapack_int mv, + lapack_complex_double* v, lapack_int ldv, double* stat ); + +lapack_int LAPACKE_sgesvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + float* b, lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* rpivot ); +lapack_int LAPACKE_dgesvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* rpivot ); +lapack_int LAPACKE_cgesvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* rpivot ); +lapack_int LAPACKE_zgesvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* rpivot ); + +lapack_int LAPACKE_sgesvxx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + float* b, lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dgesvxx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cgesvxx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zgesvxx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_sgetf2( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetf2( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetf2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetf2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetrf( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetrf( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetrf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetrf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetrf2( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetrf2( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetrf2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetrf2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetri( int matrix_layout, lapack_int n, float* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_dgetri( int matrix_layout, lapack_int n, double* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_cgetri( int matrix_layout, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zgetri( int matrix_layout, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); + +lapack_int LAPACKE_sgetrs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dgetrs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_cgetrs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zgetrs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sggbak( int matrix_layout, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const float* lscale, + const float* rscale, lapack_int m, float* v, + lapack_int ldv ); +lapack_int LAPACKE_dggbak( int matrix_layout, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const double* lscale, + const double* rscale, lapack_int m, double* v, + lapack_int ldv ); +lapack_int LAPACKE_cggbak( int matrix_layout, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const float* lscale, + const float* rscale, lapack_int m, + lapack_complex_float* v, lapack_int ldv ); +lapack_int LAPACKE_zggbak( int matrix_layout, char job, char side, lapack_int n, + lapack_int ilo, lapack_int ihi, const double* lscale, + const double* rscale, lapack_int m, + lapack_complex_double* v, lapack_int ldv ); + +lapack_int LAPACKE_sggbal( int matrix_layout, char job, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale ); +lapack_int LAPACKE_dggbal( int matrix_layout, char job, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale ); +lapack_int LAPACKE_cggbal( int matrix_layout, char job, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale ); +lapack_int LAPACKE_zggbal( int matrix_layout, char job, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale ); + +lapack_int LAPACKE_sgges( int matrix_layout, char jobvsl, char jobvsr, char sort, + LAPACK_S_SELECT3 selctg, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + lapack_int* sdim, float* alphar, float* alphai, + float* beta, float* vsl, lapack_int ldvsl, float* vsr, + lapack_int ldvsr ); +lapack_int LAPACKE_dgges( int matrix_layout, char jobvsl, char jobvsr, char sort, + LAPACK_D_SELECT3 selctg, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + lapack_int* sdim, double* alphar, double* alphai, + double* beta, double* vsl, lapack_int ldvsl, + double* vsr, lapack_int ldvsr ); +lapack_int LAPACKE_cgges( int matrix_layout, char jobvsl, char jobvsr, char sort, + LAPACK_C_SELECT2 selctg, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* vsl, + lapack_int ldvsl, lapack_complex_float* vsr, + lapack_int ldvsr ); +lapack_int LAPACKE_zgges( int matrix_layout, char jobvsl, char jobvsr, char sort, + LAPACK_Z_SELECT2 selctg, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr ); + +lapack_int LAPACKE_sgges3( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_S_SELECT3 selctg, lapack_int n, + float* a, lapack_int lda, float* b, lapack_int ldb, + lapack_int* sdim, float* alphar, float* alphai, + float* beta, float* vsl, lapack_int ldvsl, + float* vsr, lapack_int ldvsr ); +lapack_int LAPACKE_dgges3( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_D_SELECT3 selctg, lapack_int n, + double* a, lapack_int lda, double* b, lapack_int ldb, + lapack_int* sdim, double* alphar, double* alphai, + double* beta, double* vsl, lapack_int ldvsl, + double* vsr, lapack_int ldvsr ); +lapack_int LAPACKE_cgges3( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_C_SELECT2 selctg, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int ldvsl, + lapack_complex_float* vsr, lapack_int ldvsr ); +lapack_int LAPACKE_zgges3( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_Z_SELECT2 selctg, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr ); + +lapack_int LAPACKE_sggesx( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_S_SELECT3 selctg, char sense, + lapack_int n, float* a, lapack_int lda, float* b, + lapack_int ldb, lapack_int* sdim, float* alphar, + float* alphai, float* beta, float* vsl, + lapack_int ldvsl, float* vsr, lapack_int ldvsr, + float* rconde, float* rcondv ); +lapack_int LAPACKE_dggesx( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_D_SELECT3 selctg, char sense, + lapack_int n, double* a, lapack_int lda, double* b, + lapack_int ldb, lapack_int* sdim, double* alphar, + double* alphai, double* beta, double* vsl, + lapack_int ldvsl, double* vsr, lapack_int ldvsr, + double* rconde, double* rcondv ); +lapack_int LAPACKE_cggesx( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_C_SELECT2 selctg, char sense, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_int* sdim, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int ldvsl, + lapack_complex_float* vsr, lapack_int ldvsr, + float* rconde, float* rcondv ); +lapack_int LAPACKE_zggesx( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_Z_SELECT2 selctg, char sense, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_int* sdim, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr, + double* rconde, double* rcondv ); + +lapack_int LAPACKE_sggev( int matrix_layout, char jobvl, char jobvr, + lapack_int n, float* a, lapack_int lda, float* b, + lapack_int ldb, float* alphar, float* alphai, + float* beta, float* vl, lapack_int ldvl, float* vr, + lapack_int ldvr ); +lapack_int LAPACKE_dggev( int matrix_layout, char jobvl, char jobvr, + lapack_int n, double* a, lapack_int lda, double* b, + lapack_int ldb, double* alphar, double* alphai, + double* beta, double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr ); +lapack_int LAPACKE_cggev( int matrix_layout, char jobvl, char jobvr, + lapack_int n, lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr ); +lapack_int LAPACKE_zggev( int matrix_layout, char jobvl, char jobvr, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr ); + +lapack_int LAPACKE_sggev3( int matrix_layout, char jobvl, char jobvr, + lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, + float* alphar, float* alphai, float* beta, + float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr ); +lapack_int LAPACKE_dggev3( int matrix_layout, char jobvl, char jobvr, + lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, + double* alphar, double* alphai, double* beta, + double* vl, lapack_int ldvl, + double* vr, lapack_int ldvr ); +lapack_int LAPACKE_cggev3( int matrix_layout, char jobvl, char jobvr, + lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr ); +lapack_int LAPACKE_zggev3( int matrix_layout, char jobvl, char jobvr, + lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr ); + +lapack_int LAPACKE_sggevx( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* alphar, float* alphai, float* beta, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* abnrm, float* bbnrm, + float* rconde, float* rcondv ); +lapack_int LAPACKE_dggevx( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* alphar, double* alphai, double* beta, + double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr, lapack_int* ilo, lapack_int* ihi, + double* lscale, double* rscale, double* abnrm, + double* bbnrm, double* rconde, double* rcondv ); +lapack_int LAPACKE_cggevx( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr, lapack_int* ilo, lapack_int* ihi, + float* lscale, float* rscale, float* abnrm, + float* bbnrm, float* rconde, float* rcondv ); +lapack_int LAPACKE_zggevx( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale, double* abnrm, double* bbnrm, + double* rconde, double* rcondv ); + +lapack_int LAPACKE_sggglm( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, float* a, lapack_int lda, float* b, + lapack_int ldb, float* d, float* x, float* y ); +lapack_int LAPACKE_dggglm( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, double* a, lapack_int lda, double* b, + lapack_int ldb, double* d, double* x, double* y ); +lapack_int LAPACKE_cggglm( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* d, + lapack_complex_float* x, lapack_complex_float* y ); +lapack_int LAPACKE_zggglm( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* d, + lapack_complex_double* x, lapack_complex_double* y ); + +lapack_int LAPACKE_sgghrd( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* a, lapack_int lda, float* b, lapack_int ldb, + float* q, lapack_int ldq, float* z, lapack_int ldz ); +lapack_int LAPACKE_dgghrd( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* a, lapack_int lda, double* b, lapack_int ldb, + double* q, lapack_int ldq, double* z, + lapack_int ldz ); +lapack_int LAPACKE_cgghrd( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zgghrd( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_sgghd3( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* a, lapack_int lda, float* b, lapack_int ldb, + float* q, lapack_int ldq, float* z, lapack_int ldz ); +lapack_int LAPACKE_dgghd3( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* a, lapack_int lda, double* b, lapack_int ldb, + double* q, lapack_int ldq, double* z, + lapack_int ldz ); +lapack_int LAPACKE_cgghd3( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zgghd3( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_sgglse( int matrix_layout, lapack_int m, lapack_int n, + lapack_int p, float* a, lapack_int lda, float* b, + lapack_int ldb, float* c, float* d, float* x ); +lapack_int LAPACKE_dgglse( int matrix_layout, lapack_int m, lapack_int n, + lapack_int p, double* a, lapack_int lda, double* b, + lapack_int ldb, double* c, double* d, double* x ); +lapack_int LAPACKE_cgglse( int matrix_layout, lapack_int m, lapack_int n, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* c, + lapack_complex_float* d, lapack_complex_float* x ); +lapack_int LAPACKE_zgglse( int matrix_layout, lapack_int m, lapack_int n, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* c, + lapack_complex_double* d, lapack_complex_double* x ); + +lapack_int LAPACKE_sggqrf( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, float* a, lapack_int lda, float* taua, + float* b, lapack_int ldb, float* taub ); +lapack_int LAPACKE_dggqrf( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, double* a, lapack_int lda, + double* taua, double* b, lapack_int ldb, + double* taub ); +lapack_int LAPACKE_cggqrf( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* taua, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* taub ); +lapack_int LAPACKE_zggqrf( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* taua, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* taub ); + +lapack_int LAPACKE_sggrqf( int matrix_layout, lapack_int m, lapack_int p, + lapack_int n, float* a, lapack_int lda, float* taua, + float* b, lapack_int ldb, float* taub ); +lapack_int LAPACKE_dggrqf( int matrix_layout, lapack_int m, lapack_int p, + lapack_int n, double* a, lapack_int lda, + double* taua, double* b, lapack_int ldb, + double* taub ); +lapack_int LAPACKE_cggrqf( int matrix_layout, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* taua, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* taub ); +lapack_int LAPACKE_zggrqf( int matrix_layout, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* taua, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* taub ); + +lapack_int LAPACKE_sggsvd( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* alpha, float* beta, float* u, lapack_int ldu, + float* v, lapack_int ldv, float* q, lapack_int ldq, + lapack_int* iwork ); +lapack_int LAPACKE_dggsvd( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* alpha, double* beta, double* u, + lapack_int ldu, double* v, lapack_int ldv, double* q, + lapack_int ldq, lapack_int* iwork ); +lapack_int LAPACKE_cggsvd( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float* alpha, float* beta, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* v, + lapack_int ldv, lapack_complex_float* q, + lapack_int ldq, lapack_int* iwork ); +lapack_int LAPACKE_zggsvd( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* alpha, double* beta, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_int* iwork ); + +lapack_int LAPACKE_sggsvd3( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* alpha, float* beta, float* u, lapack_int ldu, + float* v, lapack_int ldv, float* q, lapack_int ldq, + lapack_int* iwork ); +lapack_int LAPACKE_dggsvd3( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* alpha, double* beta, double* u, + lapack_int ldu, double* v, lapack_int ldv, double* q, + lapack_int ldq, lapack_int* iwork ); +lapack_int LAPACKE_cggsvd3( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float* alpha, float* beta, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* v, + lapack_int ldv, lapack_complex_float* q, + lapack_int ldq, lapack_int* iwork ); +lapack_int LAPACKE_zggsvd3( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int n, lapack_int p, + lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* alpha, double* beta, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_int* iwork ); + +lapack_int LAPACKE_sggsvp( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, float tola, + float tolb, lapack_int* k, lapack_int* l, float* u, + lapack_int ldu, float* v, lapack_int ldv, float* q, + lapack_int ldq ); +lapack_int LAPACKE_dggsvp( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double tola, double tolb, lapack_int* k, + lapack_int* l, double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq ); +lapack_int LAPACKE_cggsvp( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, float tola, + float tolb, lapack_int* k, lapack_int* l, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq ); +lapack_int LAPACKE_zggsvp( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double tola, double tolb, lapack_int* k, + lapack_int* l, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* v, + lapack_int ldv, lapack_complex_double* q, + lapack_int ldq ); + +lapack_int LAPACKE_sggsvp3( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, float tola, + float tolb, lapack_int* k, lapack_int* l, float* u, + lapack_int ldu, float* v, lapack_int ldv, float* q, + lapack_int ldq ); +lapack_int LAPACKE_dggsvp3( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double tola, double tolb, lapack_int* k, + lapack_int* l, double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq ); +lapack_int LAPACKE_cggsvp3( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, float tola, + float tolb, lapack_int* k, lapack_int* l, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq ); +lapack_int LAPACKE_zggsvp3( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double tola, double tolb, lapack_int* k, + lapack_int* l, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* v, + lapack_int ldv, lapack_complex_double* q, + lapack_int ldq ); + +lapack_int LAPACKE_sgtcon( char norm, lapack_int n, const float* dl, + const float* d, const float* du, const float* du2, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_dgtcon( char norm, lapack_int n, const double* dl, + const double* d, const double* du, const double* du2, + const lapack_int* ipiv, double anorm, + double* rcond ); +lapack_int LAPACKE_cgtcon( char norm, lapack_int n, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zgtcon( char norm, lapack_int n, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_sgtrfs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const float* dl, const float* d, + const float* du, const float* dlf, const float* df, + const float* duf, const float* du2, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dgtrfs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const double* dl, const double* d, + const double* du, const double* dlf, + const double* df, const double* duf, + const double* du2, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_cgtrfs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* dlf, + const lapack_complex_float* df, + const lapack_complex_float* duf, + const lapack_complex_float* du2, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zgtrfs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* dlf, + const lapack_complex_double* df, + const lapack_complex_double* duf, + const lapack_complex_double* du2, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sgtsv( int matrix_layout, lapack_int n, lapack_int nrhs, + float* dl, float* d, float* du, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgtsv( int matrix_layout, lapack_int n, lapack_int nrhs, + double* dl, double* d, double* du, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgtsv( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_float* dl, lapack_complex_float* d, + lapack_complex_float* du, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgtsv( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_double* dl, lapack_complex_double* d, + lapack_complex_double* du, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sgtsvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, const float* dl, + const float* d, const float* du, float* dlf, + float* df, float* duf, float* du2, lapack_int* ipiv, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dgtsvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, const double* dl, + const double* d, const double* du, double* dlf, + double* df, double* duf, double* du2, + lapack_int* ipiv, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* ferr, double* berr ); +lapack_int LAPACKE_cgtsvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + lapack_complex_float* dlf, lapack_complex_float* df, + lapack_complex_float* duf, lapack_complex_float* du2, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_zgtsvx( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + lapack_complex_double* dlf, + lapack_complex_double* df, + lapack_complex_double* duf, + lapack_complex_double* du2, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_sgttrf( lapack_int n, float* dl, float* d, float* du, + float* du2, lapack_int* ipiv ); +lapack_int LAPACKE_dgttrf( lapack_int n, double* dl, double* d, double* du, + double* du2, lapack_int* ipiv ); +lapack_int LAPACKE_cgttrf( lapack_int n, lapack_complex_float* dl, + lapack_complex_float* d, lapack_complex_float* du, + lapack_complex_float* du2, lapack_int* ipiv ); +lapack_int LAPACKE_zgttrf( lapack_int n, lapack_complex_double* dl, + lapack_complex_double* d, lapack_complex_double* du, + lapack_complex_double* du2, lapack_int* ipiv ); + +lapack_int LAPACKE_sgttrs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const float* dl, const float* d, + const float* du, const float* du2, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dgttrs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const double* dl, const double* d, + const double* du, const double* du2, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_cgttrs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgttrs( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chbev( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab, float* w, lapack_complex_float* z, + lapack_int ldz ); +lapack_int LAPACKE_zhbev( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab, double* w, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_chbevd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab, float* w, lapack_complex_float* z, + lapack_int ldz ); +lapack_int LAPACKE_zhbevd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab, double* w, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_chbevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* q, lapack_int ldq, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_zhbevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* q, lapack_int ldq, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chbgst( int matrix_layout, char vect, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* bb, lapack_int ldbb, + lapack_complex_float* x, lapack_int ldx ); +lapack_int LAPACKE_zhbgst( int matrix_layout, char vect, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* bb, lapack_int ldbb, + lapack_complex_double* x, lapack_int ldx ); + +lapack_int LAPACKE_chbgv( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhbgv( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chbgvd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhbgvd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, + double* w, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_chbgvx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, + lapack_complex_float* q, lapack_int ldq, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_zhbgvx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, + lapack_complex_double* q, lapack_int ldq, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chbtrd( int matrix_layout, char vect, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab, float* d, float* e, + lapack_complex_float* q, lapack_int ldq ); +lapack_int LAPACKE_zhbtrd( int matrix_layout, char vect, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab, double* d, double* e, + lapack_complex_double* q, lapack_int ldq ); + +lapack_int LAPACKE_checon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zhecon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_cheequb( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zheequb( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_cheev( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, float* w ); +lapack_int LAPACKE_zheev( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, double* w ); + +lapack_int LAPACKE_cheevd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, float* w ); +lapack_int LAPACKE_zheevd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double* w ); + +lapack_int LAPACKE_cheevr( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int* isuppz ); +lapack_int LAPACKE_zheevr( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, lapack_int ldz, + lapack_int* isuppz ); + +lapack_int LAPACKE_cheevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_zheevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chegst( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhegst( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chegv( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* w ); +lapack_int LAPACKE_zhegv( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* w ); + +lapack_int LAPACKE_chegvd( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* w ); +lapack_int LAPACKE_zhegvd( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* w ); + +lapack_int LAPACKE_chegvx( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_zhegvx( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_cherfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zherfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_cherfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* s, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zherfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_chesv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zhesv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chesvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* af, + lapack_int ldaf, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zhesvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* af, + lapack_int ldaf, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_chesvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zhesvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_chetrd( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, float* d, + float* e, lapack_complex_float* tau ); +lapack_int LAPACKE_zhetrd( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, double* d, + double* e, lapack_complex_double* tau ); + +lapack_int LAPACKE_chetrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zhetrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_chetri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zhetri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); + +lapack_int LAPACKE_chetrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zhetrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chfrk( int matrix_layout, char transr, char uplo, char trans, + lapack_int n, lapack_int k, float alpha, + const lapack_complex_float* a, lapack_int lda, + float beta, lapack_complex_float* c ); +lapack_int LAPACKE_zhfrk( int matrix_layout, char transr, char uplo, char trans, + lapack_int n, lapack_int k, double alpha, + const lapack_complex_double* a, lapack_int lda, + double beta, lapack_complex_double* c ); + +lapack_int LAPACKE_shgeqz( int matrix_layout, char job, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* h, lapack_int ldh, float* t, lapack_int ldt, + float* alphar, float* alphai, float* beta, float* q, + lapack_int ldq, float* z, lapack_int ldz ); +lapack_int LAPACKE_dhgeqz( int matrix_layout, char job, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* h, lapack_int ldh, double* t, lapack_int ldt, + double* alphar, double* alphai, double* beta, + double* q, lapack_int ldq, double* z, + lapack_int ldz ); +lapack_int LAPACKE_chgeqz( int matrix_layout, char job, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* h, lapack_int ldh, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* q, + lapack_int ldq, lapack_complex_float* z, + lapack_int ldz ); +lapack_int LAPACKE_zhgeqz( int matrix_layout, char job, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* h, lapack_int ldh, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpcon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zhpcon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_chpev( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_complex_float* ap, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhpev( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_complex_double* ap, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpevd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_complex_float* ap, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhpevd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_complex_double* ap, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_complex_float* ap, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_zhpevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_complex_double* ap, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chpgst( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, lapack_complex_float* ap, + const lapack_complex_float* bp ); +lapack_int LAPACKE_zhpgst( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, lapack_complex_double* ap, + const lapack_complex_double* bp ); + +lapack_int LAPACKE_chpgv( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* ap, + lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhpgv( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_double* ap, + lapack_complex_double* bp, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpgvd( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* ap, + lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zhpgvd( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_double* ap, + lapack_complex_double* bp, double* w, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_chpgvx( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_complex_float* bp, + float vl, float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_zhpgvx( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_complex_double* bp, + double vl, double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_chprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zhprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_chpsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhpsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chpsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + lapack_complex_float* afp, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zhpsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + lapack_complex_double* afp, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_chptrd( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, float* d, float* e, + lapack_complex_float* tau ); +lapack_int LAPACKE_zhptrd( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, double* d, double* e, + lapack_complex_double* tau ); + +lapack_int LAPACKE_chptrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_zhptrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_int* ipiv ); + +lapack_int LAPACKE_chptri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, const lapack_int* ipiv ); +lapack_int LAPACKE_zhptri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, const lapack_int* ipiv ); + +lapack_int LAPACKE_chptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_shsein( int matrix_layout, char job, char eigsrc, char initv, + lapack_logical* select, lapack_int n, const float* h, + lapack_int ldh, float* wr, const float* wi, + float* vl, lapack_int ldvl, float* vr, + lapack_int ldvr, lapack_int mm, lapack_int* m, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_dhsein( int matrix_layout, char job, char eigsrc, char initv, + lapack_logical* select, lapack_int n, + const double* h, lapack_int ldh, double* wr, + const double* wi, double* vl, lapack_int ldvl, + double* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m, lapack_int* ifaill, + lapack_int* ifailr ); +lapack_int LAPACKE_chsein( int matrix_layout, char job, char eigsrc, char initv, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* h, lapack_int ldh, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int ldvl, lapack_complex_float* vr, + lapack_int ldvr, lapack_int mm, lapack_int* m, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_zhsein( int matrix_layout, char job, char eigsrc, char initv, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* h, lapack_int ldh, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int ldvl, lapack_complex_double* vr, + lapack_int ldvr, lapack_int mm, lapack_int* m, + lapack_int* ifaill, lapack_int* ifailr ); + +lapack_int LAPACKE_shseqr( int matrix_layout, char job, char compz, lapack_int n, + lapack_int ilo, lapack_int ihi, float* h, + lapack_int ldh, float* wr, float* wi, float* z, + lapack_int ldz ); +lapack_int LAPACKE_dhseqr( int matrix_layout, char job, char compz, lapack_int n, + lapack_int ilo, lapack_int ihi, double* h, + lapack_int ldh, double* wr, double* wi, double* z, + lapack_int ldz ); +lapack_int LAPACKE_chseqr( int matrix_layout, char job, char compz, lapack_int n, + lapack_int ilo, lapack_int ihi, + lapack_complex_float* h, lapack_int ldh, + lapack_complex_float* w, lapack_complex_float* z, + lapack_int ldz ); +lapack_int LAPACKE_zhseqr( int matrix_layout, char job, char compz, lapack_int n, + lapack_int ilo, lapack_int ihi, + lapack_complex_double* h, lapack_int ldh, + lapack_complex_double* w, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_clacgv( lapack_int n, lapack_complex_float* x, + lapack_int incx ); +lapack_int LAPACKE_zlacgv( lapack_int n, lapack_complex_double* x, + lapack_int incx ); + +lapack_int LAPACKE_slacn2( lapack_int n, float* v, float* x, lapack_int* isgn, + float* est, lapack_int* kase, lapack_int* isave ); +lapack_int LAPACKE_dlacn2( lapack_int n, double* v, double* x, lapack_int* isgn, + double* est, lapack_int* kase, lapack_int* isave ); +lapack_int LAPACKE_clacn2( lapack_int n, lapack_complex_float* v, + lapack_complex_float* x, + float* est, lapack_int* kase, lapack_int* isave ); +lapack_int LAPACKE_zlacn2( lapack_int n, lapack_complex_double* v, + lapack_complex_double* x, + double* est, lapack_int* kase, lapack_int* isave ); + +lapack_int LAPACKE_slacpy( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const float* a, lapack_int lda, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dlacpy( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const double* a, lapack_int lda, double* b, + lapack_int ldb ); +lapack_int LAPACKE_clacpy( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zlacpy( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_clacp2( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zlacp2( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_zlag2c( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_float* sa, lapack_int ldsa ); + +lapack_int LAPACKE_slag2d( int matrix_layout, lapack_int m, lapack_int n, + const float* sa, lapack_int ldsa, double* a, + lapack_int lda ); + +lapack_int LAPACKE_dlag2s( int matrix_layout, lapack_int m, lapack_int n, + const double* a, lapack_int lda, float* sa, + lapack_int ldsa ); + +lapack_int LAPACKE_clag2z( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_float* sa, lapack_int ldsa, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_slagge( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* d, + float* a, lapack_int lda, lapack_int* iseed ); +lapack_int LAPACKE_dlagge( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* d, + double* a, lapack_int lda, lapack_int* iseed ); +lapack_int LAPACKE_clagge( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* d, + lapack_complex_float* a, lapack_int lda, + lapack_int* iseed ); +lapack_int LAPACKE_zlagge( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* d, + lapack_complex_double* a, lapack_int lda, + lapack_int* iseed ); + +float LAPACKE_slamch( char cmach ); +double LAPACKE_dlamch( char cmach ); + +float LAPACKE_slange( int matrix_layout, char norm, lapack_int m, + lapack_int n, const float* a, lapack_int lda ); +double LAPACKE_dlange( int matrix_layout, char norm, lapack_int m, + lapack_int n, const double* a, lapack_int lda ); +float LAPACKE_clange( int matrix_layout, char norm, lapack_int m, + lapack_int n, const lapack_complex_float* a, + lapack_int lda ); +double LAPACKE_zlange( int matrix_layout, char norm, lapack_int m, + lapack_int n, const lapack_complex_double* a, + lapack_int lda ); + +float LAPACKE_clanhe( int matrix_layout, char norm, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda ); +double LAPACKE_zlanhe( int matrix_layout, char norm, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda ); + +float LAPACKE_slansy( int matrix_layout, char norm, char uplo, lapack_int n, + const float* a, lapack_int lda ); +double LAPACKE_dlansy( int matrix_layout, char norm, char uplo, lapack_int n, + const double* a, lapack_int lda ); +float LAPACKE_clansy( int matrix_layout, char norm, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda ); +double LAPACKE_zlansy( int matrix_layout, char norm, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda ); + +float LAPACKE_slantr( int matrix_layout, char norm, char uplo, char diag, + lapack_int m, lapack_int n, const float* a, + lapack_int lda ); +double LAPACKE_dlantr( int matrix_layout, char norm, char uplo, char diag, + lapack_int m, lapack_int n, const double* a, + lapack_int lda ); +float LAPACKE_clantr( int matrix_layout, char norm, char uplo, char diag, + lapack_int m, lapack_int n, const lapack_complex_float* a, + lapack_int lda ); +double LAPACKE_zlantr( int matrix_layout, char norm, char uplo, char diag, + lapack_int m, lapack_int n, const lapack_complex_double* a, + lapack_int lda ); + + +lapack_int LAPACKE_slarfb( int matrix_layout, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, const float* v, lapack_int ldv, + const float* t, lapack_int ldt, float* c, + lapack_int ldc ); +lapack_int LAPACKE_dlarfb( int matrix_layout, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, const double* v, lapack_int ldv, + const double* t, lapack_int ldt, double* c, + lapack_int ldc ); +lapack_int LAPACKE_clarfb( int matrix_layout, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, const lapack_complex_float* v, + lapack_int ldv, const lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* c, + lapack_int ldc ); +lapack_int LAPACKE_zlarfb( int matrix_layout, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, const lapack_complex_double* v, + lapack_int ldv, const lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* c, + lapack_int ldc ); + +lapack_int LAPACKE_slarfg( lapack_int n, float* alpha, float* x, + lapack_int incx, float* tau ); +lapack_int LAPACKE_dlarfg( lapack_int n, double* alpha, double* x, + lapack_int incx, double* tau ); +lapack_int LAPACKE_clarfg( lapack_int n, lapack_complex_float* alpha, + lapack_complex_float* x, lapack_int incx, + lapack_complex_float* tau ); +lapack_int LAPACKE_zlarfg( lapack_int n, lapack_complex_double* alpha, + lapack_complex_double* x, lapack_int incx, + lapack_complex_double* tau ); + +lapack_int LAPACKE_slarft( int matrix_layout, char direct, char storev, + lapack_int n, lapack_int k, const float* v, + lapack_int ldv, const float* tau, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dlarft( int matrix_layout, char direct, char storev, + lapack_int n, lapack_int k, const double* v, + lapack_int ldv, const double* tau, double* t, + lapack_int ldt ); +lapack_int LAPACKE_clarft( int matrix_layout, char direct, char storev, + lapack_int n, lapack_int k, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* tau, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zlarft( int matrix_layout, char direct, char storev, + lapack_int n, lapack_int k, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* tau, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_slarfx( int matrix_layout, char side, lapack_int m, + lapack_int n, const float* v, float tau, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dlarfx( int matrix_layout, char side, lapack_int m, + lapack_int n, const double* v, double tau, double* c, + lapack_int ldc, double* work ); +lapack_int LAPACKE_clarfx( int matrix_layout, char side, lapack_int m, + lapack_int n, const lapack_complex_float* v, + lapack_complex_float tau, lapack_complex_float* c, + lapack_int ldc, lapack_complex_float* work ); +lapack_int LAPACKE_zlarfx( int matrix_layout, char side, lapack_int m, + lapack_int n, const lapack_complex_double* v, + lapack_complex_double tau, lapack_complex_double* c, + lapack_int ldc, lapack_complex_double* work ); + +lapack_int LAPACKE_slarnv( lapack_int idist, lapack_int* iseed, lapack_int n, + float* x ); +lapack_int LAPACKE_dlarnv( lapack_int idist, lapack_int* iseed, lapack_int n, + double* x ); +lapack_int LAPACKE_clarnv( lapack_int idist, lapack_int* iseed, lapack_int n, + lapack_complex_float* x ); +lapack_int LAPACKE_zlarnv( lapack_int idist, lapack_int* iseed, lapack_int n, + lapack_complex_double* x ); + +lapack_int LAPACKE_slascl( int matrix_layout, char type, lapack_int kl, + lapack_int ku, float cfrom, float cto, + lapack_int m, lapack_int n, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlascl( int matrix_layout, char type, lapack_int kl, + lapack_int ku, double cfrom, double cto, + lapack_int m, lapack_int n, double* a, + lapack_int lda ); +lapack_int LAPACKE_clascl( int matrix_layout, char type, lapack_int kl, + lapack_int ku, float cfrom, float cto, + lapack_int m, lapack_int n, lapack_complex_float* a, + lapack_int lda ); +lapack_int LAPACKE_zlascl( int matrix_layout, char type, lapack_int kl, + lapack_int ku, double cfrom, double cto, + lapack_int m, lapack_int n, lapack_complex_double* a, + lapack_int lda ); + +lapack_int LAPACKE_slaset( int matrix_layout, char uplo, lapack_int m, + lapack_int n, float alpha, float beta, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlaset( int matrix_layout, char uplo, lapack_int m, + lapack_int n, double alpha, double beta, double* a, + lapack_int lda ); +lapack_int LAPACKE_claset( int matrix_layout, char uplo, lapack_int m, + lapack_int n, lapack_complex_float alpha, + lapack_complex_float beta, lapack_complex_float* a, + lapack_int lda ); +lapack_int LAPACKE_zlaset( int matrix_layout, char uplo, lapack_int m, + lapack_int n, lapack_complex_double alpha, + lapack_complex_double beta, lapack_complex_double* a, + lapack_int lda ); + +lapack_int LAPACKE_slasrt( char id, lapack_int n, float* d ); +lapack_int LAPACKE_dlasrt( char id, lapack_int n, double* d ); + +lapack_int LAPACKE_slaswp( int matrix_layout, lapack_int n, float* a, + lapack_int lda, lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_dlaswp( int matrix_layout, lapack_int n, double* a, + lapack_int lda, lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_claswp( int matrix_layout, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int k1, lapack_int k2, const lapack_int* ipiv, + lapack_int incx ); +lapack_int LAPACKE_zlaswp( int matrix_layout, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int k1, lapack_int k2, const lapack_int* ipiv, + lapack_int incx ); + +lapack_int LAPACKE_slatms( int matrix_layout, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, float* d, + lapack_int mode, float cond, float dmax, + lapack_int kl, lapack_int ku, char pack, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlatms( int matrix_layout, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, double* d, + lapack_int mode, double cond, double dmax, + lapack_int kl, lapack_int ku, char pack, double* a, + lapack_int lda ); +lapack_int LAPACKE_clatms( int matrix_layout, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, float* d, + lapack_int mode, float cond, float dmax, + lapack_int kl, lapack_int ku, char pack, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zlatms( int matrix_layout, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, double* d, + lapack_int mode, double cond, double dmax, + lapack_int kl, lapack_int ku, char pack, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_slauum( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlauum( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda ); +lapack_int LAPACKE_clauum( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zlauum( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_sopgtr( int matrix_layout, char uplo, lapack_int n, + const float* ap, const float* tau, float* q, + lapack_int ldq ); +lapack_int LAPACKE_dopgtr( int matrix_layout, char uplo, lapack_int n, + const double* ap, const double* tau, double* q, + lapack_int ldq ); + +lapack_int LAPACKE_sopmtr( int matrix_layout, char side, char uplo, char trans, + lapack_int m, lapack_int n, const float* ap, + const float* tau, float* c, lapack_int ldc ); +lapack_int LAPACKE_dopmtr( int matrix_layout, char side, char uplo, char trans, + lapack_int m, lapack_int n, const double* ap, + const double* tau, double* c, lapack_int ldc ); + +lapack_int LAPACKE_sorgbr( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorgbr( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int k, double* a, + lapack_int lda, const double* tau ); + +lapack_int LAPACKE_sorghr( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorghr( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorglq( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorglq( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorgql( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorgql( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorgqr( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorgqr( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorgrq( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau ); +lapack_int LAPACKE_dorgrq( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau ); + +lapack_int LAPACKE_sorgtr( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda, const float* tau ); +lapack_int LAPACKE_dorgtr( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda, const double* tau ); + +lapack_int LAPACKE_sormbr( int matrix_layout, char vect, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormbr( int matrix_layout, char vect, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormhr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc ); +lapack_int LAPACKE_dormhr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormql( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormql( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormrq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, const float* tau, + float* c, lapack_int ldc ); +lapack_int LAPACKE_dormrq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, const double* tau, + double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormrz( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc ); +lapack_int LAPACKE_dormrz( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc ); + +lapack_int LAPACKE_sormtr( int matrix_layout, char side, char uplo, char trans, + lapack_int m, lapack_int n, const float* a, + lapack_int lda, const float* tau, float* c, + lapack_int ldc ); +lapack_int LAPACKE_dormtr( int matrix_layout, char side, char uplo, char trans, + lapack_int m, lapack_int n, const double* a, + lapack_int lda, const double* tau, double* c, + lapack_int ldc ); + +lapack_int LAPACKE_spbcon( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const float* ab, lapack_int ldab, + float anorm, float* rcond ); +lapack_int LAPACKE_dpbcon( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const double* ab, lapack_int ldab, + double anorm, double* rcond ); +lapack_int LAPACKE_cpbcon( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_float* ab, + lapack_int ldab, float anorm, float* rcond ); +lapack_int LAPACKE_zpbcon( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_double* ab, + lapack_int ldab, double anorm, double* rcond ); + +lapack_int LAPACKE_spbequ( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const float* ab, lapack_int ldab, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_dpbequ( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const double* ab, lapack_int ldab, + double* s, double* scond, double* amax ); +lapack_int LAPACKE_cpbequ( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_float* ab, + lapack_int ldab, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_zpbequ( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_double* ab, + lapack_int ldab, double* s, double* scond, + double* amax ); + +lapack_int LAPACKE_spbrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const float* ab, + lapack_int ldab, const float* afb, lapack_int ldafb, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dpbrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const double* ab, + lapack_int ldab, const double* afb, lapack_int ldafb, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_cpbrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* afb, lapack_int ldafb, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zpbrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* afb, lapack_int ldafb, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_spbstf( int matrix_layout, char uplo, lapack_int n, + lapack_int kb, float* bb, lapack_int ldbb ); +lapack_int LAPACKE_dpbstf( int matrix_layout, char uplo, lapack_int n, + lapack_int kb, double* bb, lapack_int ldbb ); +lapack_int LAPACKE_cpbstf( int matrix_layout, char uplo, lapack_int n, + lapack_int kb, lapack_complex_float* bb, + lapack_int ldbb ); +lapack_int LAPACKE_zpbstf( int matrix_layout, char uplo, lapack_int n, + lapack_int kb, lapack_complex_double* bb, + lapack_int ldbb ); + +lapack_int LAPACKE_spbsv( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dpbsv( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, double* ab, + lapack_int ldab, double* b, lapack_int ldb ); +lapack_int LAPACKE_cpbsv( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpbsv( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spbsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, float* ab, + lapack_int ldab, float* afb, lapack_int ldafb, + char* equed, float* s, float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dpbsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, double* ab, + lapack_int ldab, double* afb, lapack_int ldafb, + char* equed, double* s, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* ferr, double* berr ); +lapack_int LAPACKE_cpbsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* afb, lapack_int ldafb, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_zpbsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* afb, lapack_int ldafb, + char* equed, double* s, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr ); + +lapack_int LAPACKE_spbtrf( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab ); +lapack_int LAPACKE_dpbtrf( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab ); +lapack_int LAPACKE_cpbtrf( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab ); +lapack_int LAPACKE_zpbtrf( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab ); + +lapack_int LAPACKE_spbtrs( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dpbtrs( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const double* ab, + lapack_int ldab, double* b, lapack_int ldb ); +lapack_int LAPACKE_cpbtrs( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpbtrs( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spftrf( int matrix_layout, char transr, char uplo, + lapack_int n, float* a ); +lapack_int LAPACKE_dpftrf( int matrix_layout, char transr, char uplo, + lapack_int n, double* a ); +lapack_int LAPACKE_cpftrf( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_zpftrf( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_spftri( int matrix_layout, char transr, char uplo, + lapack_int n, float* a ); +lapack_int LAPACKE_dpftri( int matrix_layout, char transr, char uplo, + lapack_int n, double* a ); +lapack_int LAPACKE_cpftri( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_zpftri( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_spftrs( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_int nrhs, const float* a, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dpftrs( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_int nrhs, const double* a, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cpftrs( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpftrs( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spocon( int matrix_layout, char uplo, lapack_int n, + const float* a, lapack_int lda, float anorm, + float* rcond ); +lapack_int LAPACKE_dpocon( int matrix_layout, char uplo, lapack_int n, + const double* a, lapack_int lda, double anorm, + double* rcond ); +lapack_int LAPACKE_cpocon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float anorm, float* rcond ); +lapack_int LAPACKE_zpocon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double anorm, double* rcond ); + +lapack_int LAPACKE_spoequ( int matrix_layout, lapack_int n, const float* a, + lapack_int lda, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dpoequ( int matrix_layout, lapack_int n, const double* a, + lapack_int lda, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cpoequ( int matrix_layout, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zpoequ( int matrix_layout, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_spoequb( int matrix_layout, lapack_int n, const float* a, + lapack_int lda, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dpoequb( int matrix_layout, lapack_int n, const double* a, + lapack_int lda, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cpoequb( int matrix_layout, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zpoequb( int matrix_layout, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_sporfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dporfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const double* af, lapack_int ldaf, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_cporfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_zporfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* ferr, double* berr ); + +lapack_int LAPACKE_sporfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, lapack_int ldaf, + const float* s, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dporfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, lapack_int ldaf, + const double* s, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cporfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, lapack_int ldaf, + const float* s, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zporfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, lapack_int ldaf, + const double* s, const lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_sposv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dposv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cposv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zposv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); +lapack_int LAPACKE_dsposv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* x, lapack_int ldx, + lapack_int* iter ); +lapack_int LAPACKE_zcposv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, lapack_int* iter ); + +lapack_int LAPACKE_sposvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, float* af, + lapack_int ldaf, char* equed, float* s, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_dposvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* af, lapack_int ldaf, char* equed, double* s, + double* b, lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); +lapack_int LAPACKE_cposvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* af, + lapack_int ldaf, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zposvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* af, + lapack_int ldaf, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_sposvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + char* equed, float* s, float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_dposvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + char* equed, double* s, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); +lapack_int LAPACKE_cposvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zposvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + char* equed, double* s, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_spotrf2( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda ); +lapack_int LAPACKE_dpotrf2( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda ); +lapack_int LAPACKE_cpotrf2( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotrf2( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotrf( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda ); +lapack_int LAPACKE_dpotrf( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda ); +lapack_int LAPACKE_cpotrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotri( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda ); +lapack_int LAPACKE_dpotri( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda ); +lapack_int LAPACKE_cpotri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dpotrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cpotrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zpotrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sppcon( int matrix_layout, char uplo, lapack_int n, + const float* ap, float anorm, float* rcond ); +lapack_int LAPACKE_dppcon( int matrix_layout, char uplo, lapack_int n, + const double* ap, double anorm, double* rcond ); +lapack_int LAPACKE_cppcon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, float anorm, + float* rcond ); +lapack_int LAPACKE_zppcon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, double anorm, + double* rcond ); + +lapack_int LAPACKE_sppequ( int matrix_layout, char uplo, lapack_int n, + const float* ap, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dppequ( int matrix_layout, char uplo, lapack_int n, + const double* ap, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cppequ( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, float* s, + float* scond, float* amax ); +lapack_int LAPACKE_zppequ( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, double* s, + double* scond, double* amax ); + +lapack_int LAPACKE_spprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, const float* afp, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dpprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, const double* afp, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_cpprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zpprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sppsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* ap, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dppsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* ap, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cppsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zppsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sppsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, float* ap, float* afp, char* equed, + float* s, float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dppsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, double* ap, double* afp, + char* equed, double* s, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* ferr, double* berr ); +lapack_int LAPACKE_cppsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_complex_float* afp, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zppsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_complex_double* afp, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_spptrf( int matrix_layout, char uplo, lapack_int n, + float* ap ); +lapack_int LAPACKE_dpptrf( int matrix_layout, char uplo, lapack_int n, + double* ap ); +lapack_int LAPACKE_cpptrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_zpptrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_spptri( int matrix_layout, char uplo, lapack_int n, + float* ap ); +lapack_int LAPACKE_dpptri( int matrix_layout, char uplo, lapack_int n, + double* ap ); +lapack_int LAPACKE_cpptri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_zpptri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_spptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dpptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spstrf( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda, lapack_int* piv, lapack_int* rank, + float tol ); +lapack_int LAPACKE_dpstrf( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda, lapack_int* piv, lapack_int* rank, + double tol ); +lapack_int LAPACKE_cpstrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* piv, lapack_int* rank, float tol ); +lapack_int LAPACKE_zpstrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* piv, lapack_int* rank, double tol ); + +lapack_int LAPACKE_sptcon( lapack_int n, const float* d, const float* e, + float anorm, float* rcond ); +lapack_int LAPACKE_dptcon( lapack_int n, const double* d, const double* e, + double anorm, double* rcond ); +lapack_int LAPACKE_cptcon( lapack_int n, const float* d, + const lapack_complex_float* e, float anorm, + float* rcond ); +lapack_int LAPACKE_zptcon( lapack_int n, const double* d, + const lapack_complex_double* e, double anorm, + double* rcond ); + +lapack_int LAPACKE_spteqr( int matrix_layout, char compz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dpteqr( int matrix_layout, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz ); +lapack_int LAPACKE_cpteqr( int matrix_layout, char compz, lapack_int n, float* d, + float* e, lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zpteqr( int matrix_layout, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_sptrfs( int matrix_layout, lapack_int n, lapack_int nrhs, + const float* d, const float* e, const float* df, + const float* ef, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dptrfs( int matrix_layout, lapack_int n, lapack_int nrhs, + const double* d, const double* e, const double* df, + const double* ef, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* ferr, + double* berr ); +lapack_int LAPACKE_cptrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, const float* df, + const lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zptrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, const double* df, + const lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sptsv( int matrix_layout, lapack_int n, lapack_int nrhs, + float* d, float* e, float* b, lapack_int ldb ); +lapack_int LAPACKE_dptsv( int matrix_layout, lapack_int n, lapack_int nrhs, + double* d, double* e, double* b, lapack_int ldb ); +lapack_int LAPACKE_cptsv( int matrix_layout, lapack_int n, lapack_int nrhs, + float* d, lapack_complex_float* e, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zptsv( int matrix_layout, lapack_int n, lapack_int nrhs, + double* d, lapack_complex_double* e, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sptsvx( int matrix_layout, char fact, lapack_int n, + lapack_int nrhs, const float* d, const float* e, + float* df, float* ef, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dptsvx( int matrix_layout, char fact, lapack_int n, + lapack_int nrhs, const double* d, const double* e, + double* df, double* ef, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); +lapack_int LAPACKE_cptsvx( int matrix_layout, char fact, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, float* df, + lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zptsvx( int matrix_layout, char fact, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, double* df, + lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_spttrf( lapack_int n, float* d, float* e ); +lapack_int LAPACKE_dpttrf( lapack_int n, double* d, double* e ); +lapack_int LAPACKE_cpttrf( lapack_int n, float* d, lapack_complex_float* e ); +lapack_int LAPACKE_zpttrf( lapack_int n, double* d, lapack_complex_double* e ); + +lapack_int LAPACKE_spttrs( int matrix_layout, lapack_int n, lapack_int nrhs, + const float* d, const float* e, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dpttrs( int matrix_layout, lapack_int n, lapack_int nrhs, + const double* d, const double* e, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpttrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpttrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssbev( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab, float* w, + float* z, lapack_int ldz ); +lapack_int LAPACKE_dsbev( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab, double* w, + double* z, lapack_int ldz ); + +lapack_int LAPACKE_ssbevd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab, float* w, + float* z, lapack_int ldz ); +lapack_int LAPACKE_dsbevd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_ssbevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_int kd, float* ab, + lapack_int ldab, float* q, lapack_int ldq, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dsbevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_int kd, double* ab, + lapack_int ldab, double* q, lapack_int ldq, + double vl, double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssbgst( int matrix_layout, char vect, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, float* ab, + lapack_int ldab, const float* bb, lapack_int ldbb, + float* x, lapack_int ldx ); +lapack_int LAPACKE_dsbgst( int matrix_layout, char vect, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, double* ab, + lapack_int ldab, const double* bb, lapack_int ldbb, + double* x, lapack_int ldx ); + +lapack_int LAPACKE_ssbgv( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, float* ab, + lapack_int ldab, float* bb, lapack_int ldbb, float* w, + float* z, lapack_int ldz ); +lapack_int LAPACKE_dsbgv( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, double* ab, + lapack_int ldab, double* bb, lapack_int ldbb, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_ssbgvd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, float* ab, + lapack_int ldab, float* bb, lapack_int ldbb, + float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dsbgvd( int matrix_layout, char jobz, char uplo, lapack_int n, + lapack_int ka, lapack_int kb, double* ab, + lapack_int ldab, double* bb, lapack_int ldbb, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_ssbgvx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + float* ab, lapack_int ldab, float* bb, + lapack_int ldbb, float* q, lapack_int ldq, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dsbgvx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + double* ab, lapack_int ldab, double* bb, + lapack_int ldbb, double* q, lapack_int ldq, + double vl, double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssbtrd( int matrix_layout, char vect, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab, float* d, + float* e, float* q, lapack_int ldq ); +lapack_int LAPACKE_dsbtrd( int matrix_layout, char vect, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab, + double* d, double* e, double* q, lapack_int ldq ); + +lapack_int LAPACKE_ssfrk( int matrix_layout, char transr, char uplo, char trans, + lapack_int n, lapack_int k, float alpha, + const float* a, lapack_int lda, float beta, + float* c ); +lapack_int LAPACKE_dsfrk( int matrix_layout, char transr, char uplo, char trans, + lapack_int n, lapack_int k, double alpha, + const double* a, lapack_int lda, double beta, + double* c ); + +lapack_int LAPACKE_sspcon( int matrix_layout, char uplo, lapack_int n, + const float* ap, const lapack_int* ipiv, float anorm, + float* rcond ); +lapack_int LAPACKE_dspcon( int matrix_layout, char uplo, lapack_int n, + const double* ap, const lapack_int* ipiv, + double anorm, double* rcond ); +lapack_int LAPACKE_cspcon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zspcon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_sspev( int matrix_layout, char jobz, char uplo, lapack_int n, + float* ap, float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dspev( int matrix_layout, char jobz, char uplo, lapack_int n, + double* ap, double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sspevd( int matrix_layout, char jobz, char uplo, lapack_int n, + float* ap, float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dspevd( int matrix_layout, char jobz, char uplo, lapack_int n, + double* ap, double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sspevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, float* ap, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dspevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, double* ap, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_sspgst( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, float* ap, const float* bp ); +lapack_int LAPACKE_dspgst( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, double* ap, const double* bp ); + +lapack_int LAPACKE_sspgv( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, float* ap, float* bp, + float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dspgv( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, double* ap, double* bp, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sspgvd( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, float* ap, float* bp, + float* w, float* z, lapack_int ldz ); +lapack_int LAPACKE_dspgvd( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, double* ap, double* bp, + double* w, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sspgvx( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, float* ap, + float* bp, float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, float* w, + float* z, lapack_int ldz, lapack_int* ifail ); +lapack_int LAPACKE_dspgvx( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, double* ap, + double* bp, double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, double* z, lapack_int ldz, + lapack_int* ifail ); + +lapack_int LAPACKE_ssprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, const float* afp, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dsprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, const double* afp, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_csprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zsprfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_sspsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* ap, lapack_int* ipiv, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dspsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* ap, lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cspsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zspsv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sspsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, float* afp, + lapack_int* ipiv, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dspsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, double* afp, + lapack_int* ipiv, const double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* ferr, double* berr ); +lapack_int LAPACKE_cspsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + lapack_complex_float* afp, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zspsvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + lapack_complex_double* afp, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_ssptrd( int matrix_layout, char uplo, lapack_int n, float* ap, + float* d, float* e, float* tau ); +lapack_int LAPACKE_dsptrd( int matrix_layout, char uplo, lapack_int n, + double* ap, double* d, double* e, double* tau ); + +lapack_int LAPACKE_ssptrf( int matrix_layout, char uplo, lapack_int n, float* ap, + lapack_int* ipiv ); +lapack_int LAPACKE_dsptrf( int matrix_layout, char uplo, lapack_int n, + double* ap, lapack_int* ipiv ); +lapack_int LAPACKE_csptrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_zsptrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_int* ipiv ); + +lapack_int LAPACKE_ssptri( int matrix_layout, char uplo, lapack_int n, float* ap, + const lapack_int* ipiv ); +lapack_int LAPACKE_dsptri( int matrix_layout, char uplo, lapack_int n, + double* ap, const lapack_int* ipiv ); +lapack_int LAPACKE_csptri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, const lapack_int* ipiv ); +lapack_int LAPACKE_zsptri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, const lapack_int* ipiv ); + +lapack_int LAPACKE_ssptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dsptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_csptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zsptrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* ap, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sstebz( char range, char order, lapack_int n, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + const float* d, const float* e, lapack_int* m, + lapack_int* nsplit, float* w, lapack_int* iblock, + lapack_int* isplit ); +lapack_int LAPACKE_dstebz( char range, char order, lapack_int n, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, const double* d, const double* e, + lapack_int* m, lapack_int* nsplit, double* w, + lapack_int* iblock, lapack_int* isplit ); + +lapack_int LAPACKE_sstedc( int matrix_layout, char compz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dstedc( int matrix_layout, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz ); +lapack_int LAPACKE_cstedc( int matrix_layout, char compz, lapack_int n, float* d, + float* e, lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zstedc( int matrix_layout, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_sstegr( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* isuppz ); +lapack_int LAPACKE_dstegr( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* isuppz ); +lapack_int LAPACKE_cstegr( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* isuppz ); +lapack_int LAPACKE_zstegr( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* isuppz ); + +lapack_int LAPACKE_sstein( int matrix_layout, lapack_int n, const float* d, + const float* e, lapack_int m, const float* w, + const lapack_int* iblock, const lapack_int* isplit, + float* z, lapack_int ldz, lapack_int* ifailv ); +lapack_int LAPACKE_dstein( int matrix_layout, lapack_int n, const double* d, + const double* e, lapack_int m, const double* w, + const lapack_int* iblock, const lapack_int* isplit, + double* z, lapack_int ldz, lapack_int* ifailv ); +lapack_int LAPACKE_cstein( int matrix_layout, lapack_int n, const float* d, + const float* e, lapack_int m, const float* w, + const lapack_int* iblock, const lapack_int* isplit, + lapack_complex_float* z, lapack_int ldz, + lapack_int* ifailv ); +lapack_int LAPACKE_zstein( int matrix_layout, lapack_int n, const double* d, + const double* e, lapack_int m, const double* w, + const lapack_int* iblock, const lapack_int* isplit, + lapack_complex_double* z, lapack_int ldz, + lapack_int* ifailv ); + +lapack_int LAPACKE_sstemr( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, lapack_int* m, + float* w, float* z, lapack_int ldz, lapack_int nzc, + lapack_int* isuppz, lapack_logical* tryrac ); +lapack_int LAPACKE_dstemr( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + lapack_int* m, double* w, double* z, lapack_int ldz, + lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac ); +lapack_int LAPACKE_cstemr( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, lapack_int* m, + float* w, lapack_complex_float* z, lapack_int ldz, + lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac ); +lapack_int LAPACKE_zstemr( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int ldz, lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac ); + +lapack_int LAPACKE_ssteqr( int matrix_layout, char compz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dsteqr( int matrix_layout, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz ); +lapack_int LAPACKE_csteqr( int matrix_layout, char compz, lapack_int n, float* d, + float* e, lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zsteqr( int matrix_layout, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz ); + +lapack_int LAPACKE_ssterf( lapack_int n, float* d, float* e ); +lapack_int LAPACKE_dsterf( lapack_int n, double* d, double* e ); + +lapack_int LAPACKE_sstev( int matrix_layout, char jobz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dstev( int matrix_layout, char jobz, lapack_int n, double* d, + double* e, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sstevd( int matrix_layout, char jobz, lapack_int n, float* d, + float* e, float* z, lapack_int ldz ); +lapack_int LAPACKE_dstevd( int matrix_layout, char jobz, lapack_int n, double* d, + double* e, double* z, lapack_int ldz ); + +lapack_int LAPACKE_sstevr( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* isuppz ); +lapack_int LAPACKE_dstevr( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* isuppz ); + +lapack_int LAPACKE_sstevx( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dstevx( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssycon( int matrix_layout, char uplo, lapack_int n, + const float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_dsycon( int matrix_layout, char uplo, lapack_int n, + const double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond ); +lapack_int LAPACKE_csycon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, float* rcond ); +lapack_int LAPACKE_zsycon( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond ); + +lapack_int LAPACKE_ssyequb( int matrix_layout, char uplo, lapack_int n, + const float* a, lapack_int lda, float* s, + float* scond, float* amax ); +lapack_int LAPACKE_dsyequb( int matrix_layout, char uplo, lapack_int n, + const double* a, lapack_int lda, double* s, + double* scond, double* amax ); +lapack_int LAPACKE_csyequb( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zsyequb( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_ssyev( int matrix_layout, char jobz, char uplo, lapack_int n, + float* a, lapack_int lda, float* w ); +lapack_int LAPACKE_dsyev( int matrix_layout, char jobz, char uplo, lapack_int n, + double* a, lapack_int lda, double* w ); + +lapack_int LAPACKE_ssyevd( int matrix_layout, char jobz, char uplo, lapack_int n, + float* a, lapack_int lda, float* w ); +lapack_int LAPACKE_dsyevd( int matrix_layout, char jobz, char uplo, lapack_int n, + double* a, lapack_int lda, double* w ); + +lapack_int LAPACKE_ssyevr( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, float* a, lapack_int lda, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* isuppz ); +lapack_int LAPACKE_dsyevr( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, double* a, lapack_int lda, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* isuppz ); + +lapack_int LAPACKE_ssyevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, float* a, lapack_int lda, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dsyevx( int matrix_layout, char jobz, char range, char uplo, + lapack_int n, double* a, lapack_int lda, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssygst( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, float* a, lapack_int lda, + const float* b, lapack_int ldb ); +lapack_int LAPACKE_dsygst( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, double* a, lapack_int lda, + const double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssygv( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, float* w ); +lapack_int LAPACKE_dsygv( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, double* w ); + +lapack_int LAPACKE_ssygvd( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, float* w ); +lapack_int LAPACKE_dsygvd( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, double* w ); + +lapack_int LAPACKE_ssygvx( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, float vl, + float vu, lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, lapack_int ldz, + lapack_int* ifail ); +lapack_int LAPACKE_dsygvx( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* ifail ); + +lapack_int LAPACKE_ssyrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dsyrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_csyrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_zsyrfs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_ssyrfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* s, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dsyrfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* s, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); +lapack_int LAPACKE_csyrfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* s, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params ); +lapack_int LAPACKE_zsyrfsx( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, lapack_int ldaf, + const lapack_int* ipiv, const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params ); + +lapack_int LAPACKE_ssysv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dsysv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_csysv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsysv( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssysvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + float* af, lapack_int ldaf, lapack_int* ipiv, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr ); +lapack_int LAPACKE_dsysvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + double* af, lapack_int ldaf, lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr ); +lapack_int LAPACKE_csysvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* af, + lapack_int ldaf, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr ); +lapack_int LAPACKE_zsysvx( int matrix_layout, char fact, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* af, + lapack_int ldaf, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr ); + +lapack_int LAPACKE_ssysvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_dsysvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); +lapack_int LAPACKE_csysvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params ); +lapack_int LAPACKE_zsysvxx( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params ); + +lapack_int LAPACKE_ssytrd( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda, float* d, float* e, float* tau ); +lapack_int LAPACKE_dsytrd( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda, double* d, double* e, double* tau ); + +lapack_int LAPACKE_ssytrf( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dsytrf( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_csytrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zsytrf( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_ssytri( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_dsytri( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_csytri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zsytri( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); + +lapack_int LAPACKE_ssytrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dsytrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_csytrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsytrs( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stbcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, lapack_int kd, const float* ab, + lapack_int ldab, float* rcond ); +lapack_int LAPACKE_dtbcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, lapack_int kd, const double* ab, + lapack_int ldab, double* rcond ); +lapack_int LAPACKE_ctbcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, lapack_int kd, + const lapack_complex_float* ab, lapack_int ldab, + float* rcond ); +lapack_int LAPACKE_ztbcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, lapack_int kd, + const lapack_complex_double* ab, lapack_int ldab, + double* rcond ); + +lapack_int LAPACKE_stbrfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const float* ab, lapack_int ldab, const float* b, + lapack_int ldb, const float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_dtbrfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const double* ab, lapack_int ldab, const double* b, + lapack_int ldb, const double* x, lapack_int ldx, + double* ferr, double* berr ); +lapack_int LAPACKE_ctbrfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_ztbrfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_stbtrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const float* ab, lapack_int ldab, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dtbtrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const double* ab, lapack_int ldab, double* b, + lapack_int ldb ); +lapack_int LAPACKE_ctbtrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztbtrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stfsm( int matrix_layout, char transr, char side, char uplo, + char trans, char diag, lapack_int m, lapack_int n, + float alpha, const float* a, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dtfsm( int matrix_layout, char transr, char side, char uplo, + char trans, char diag, lapack_int m, lapack_int n, + double alpha, const double* a, double* b, + lapack_int ldb ); +lapack_int LAPACKE_ctfsm( int matrix_layout, char transr, char side, char uplo, + char trans, char diag, lapack_int m, lapack_int n, + lapack_complex_float alpha, + const lapack_complex_float* a, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztfsm( int matrix_layout, char transr, char side, char uplo, + char trans, char diag, lapack_int m, lapack_int n, + lapack_complex_double alpha, + const lapack_complex_double* a, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stftri( int matrix_layout, char transr, char uplo, char diag, + lapack_int n, float* a ); +lapack_int LAPACKE_dtftri( int matrix_layout, char transr, char uplo, char diag, + lapack_int n, double* a ); +lapack_int LAPACKE_ctftri( int matrix_layout, char transr, char uplo, char diag, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_ztftri( int matrix_layout, char transr, char uplo, char diag, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_stfttp( int matrix_layout, char transr, char uplo, + lapack_int n, const float* arf, float* ap ); +lapack_int LAPACKE_dtfttp( int matrix_layout, char transr, char uplo, + lapack_int n, const double* arf, double* ap ); +lapack_int LAPACKE_ctfttp( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_float* arf, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztfttp( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_double* arf, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stfttr( int matrix_layout, char transr, char uplo, + lapack_int n, const float* arf, float* a, + lapack_int lda ); +lapack_int LAPACKE_dtfttr( int matrix_layout, char transr, char uplo, + lapack_int n, const double* arf, double* a, + lapack_int lda ); +lapack_int LAPACKE_ctfttr( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_float* arf, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztfttr( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_double* arf, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_stgevc( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + const float* s, lapack_int lds, const float* p, + lapack_int ldp, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m ); +lapack_int LAPACKE_dtgevc( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + const double* s, lapack_int lds, const double* p, + lapack_int ldp, double* vl, lapack_int ldvl, + double* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m ); +lapack_int LAPACKE_ctgevc( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* s, lapack_int lds, + const lapack_complex_float* p, lapack_int ldp, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ztgevc( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* s, lapack_int lds, + const lapack_complex_double* p, lapack_int ldp, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); + +lapack_int LAPACKE_stgexc( int matrix_layout, lapack_logical wantq, + lapack_logical wantz, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, float* q, + lapack_int ldq, float* z, lapack_int ldz, + lapack_int* ifst, lapack_int* ilst ); +lapack_int LAPACKE_dtgexc( int matrix_layout, lapack_logical wantq, + lapack_logical wantz, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, double* q, + lapack_int ldq, double* z, lapack_int ldz, + lapack_int* ifst, lapack_int* ilst ); +lapack_int LAPACKE_ctgexc( int matrix_layout, lapack_logical wantq, + lapack_logical wantz, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz, + lapack_int ifst, lapack_int ilst ); +lapack_int LAPACKE_ztgexc( int matrix_layout, lapack_logical wantq, + lapack_logical wantz, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_int ifst, lapack_int ilst ); + +lapack_int LAPACKE_stgsen( int matrix_layout, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* alphar, float* alphai, float* beta, float* q, + lapack_int ldq, float* z, lapack_int ldz, + lapack_int* m, float* pl, float* pr, float* dif ); +lapack_int LAPACKE_dtgsen( int matrix_layout, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + double* a, lapack_int lda, double* b, lapack_int ldb, + double* alphar, double* alphai, double* beta, + double* q, lapack_int ldq, double* z, lapack_int ldz, + lapack_int* m, double* pl, double* pr, double* dif ); +lapack_int LAPACKE_ctgsen( int matrix_layout, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, lapack_complex_float* q, + lapack_int ldq, lapack_complex_float* z, + lapack_int ldz, lapack_int* m, float* pl, float* pr, + float* dif ); +lapack_int LAPACKE_ztgsen( int matrix_layout, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_int* m, double* pl, double* pr, double* dif ); + +lapack_int LAPACKE_stgsja( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_int k, lapack_int l, float* a, lapack_int lda, + float* b, lapack_int ldb, float tola, float tolb, + float* alpha, float* beta, float* u, lapack_int ldu, + float* v, lapack_int ldv, float* q, lapack_int ldq, + lapack_int* ncycle ); +lapack_int LAPACKE_dtgsja( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_int k, lapack_int l, double* a, + lapack_int lda, double* b, lapack_int ldb, + double tola, double tolb, double* alpha, + double* beta, double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq, + lapack_int* ncycle ); +lapack_int LAPACKE_ctgsja( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_int k, lapack_int l, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float tola, float tolb, float* alpha, + float* beta, lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq, + lapack_int* ncycle ); +lapack_int LAPACKE_ztgsja( int matrix_layout, char jobu, char jobv, char jobq, + lapack_int m, lapack_int p, lapack_int n, + lapack_int k, lapack_int l, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double tola, double tolb, + double* alpha, double* beta, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_int* ncycle ); + +lapack_int LAPACKE_stgsna( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, const float* vl, lapack_int ldvl, + const float* vr, lapack_int ldvr, float* s, + float* dif, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_dtgsna( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const double* a, lapack_int lda, const double* b, + lapack_int ldb, const double* vl, lapack_int ldvl, + const double* vr, lapack_int ldvr, double* s, + double* dif, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ctgsna( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* vl, lapack_int ldvl, + const lapack_complex_float* vr, lapack_int ldvr, + float* s, float* dif, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ztgsna( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* vl, lapack_int ldvl, + const lapack_complex_double* vr, lapack_int ldvr, + double* s, double* dif, lapack_int mm, + lapack_int* m ); + +lapack_int LAPACKE_stgsyl( int matrix_layout, char trans, lapack_int ijob, + lapack_int m, lapack_int n, const float* a, + lapack_int lda, const float* b, lapack_int ldb, + float* c, lapack_int ldc, const float* d, + lapack_int ldd, const float* e, lapack_int lde, + float* f, lapack_int ldf, float* scale, float* dif ); +lapack_int LAPACKE_dtgsyl( int matrix_layout, char trans, lapack_int ijob, + lapack_int m, lapack_int n, const double* a, + lapack_int lda, const double* b, lapack_int ldb, + double* c, lapack_int ldc, const double* d, + lapack_int ldd, const double* e, lapack_int lde, + double* f, lapack_int ldf, double* scale, + double* dif ); +lapack_int LAPACKE_ctgsyl( int matrix_layout, char trans, lapack_int ijob, + lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* c, lapack_int ldc, + const lapack_complex_float* d, lapack_int ldd, + const lapack_complex_float* e, lapack_int lde, + lapack_complex_float* f, lapack_int ldf, + float* scale, float* dif ); +lapack_int LAPACKE_ztgsyl( int matrix_layout, char trans, lapack_int ijob, + lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* c, lapack_int ldc, + const lapack_complex_double* d, lapack_int ldd, + const lapack_complex_double* e, lapack_int lde, + lapack_complex_double* f, lapack_int ldf, + double* scale, double* dif ); + +lapack_int LAPACKE_stpcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, const float* ap, float* rcond ); +lapack_int LAPACKE_dtpcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, const double* ap, double* rcond ); +lapack_int LAPACKE_ctpcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, const lapack_complex_float* ap, + float* rcond ); +lapack_int LAPACKE_ztpcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, const lapack_complex_double* ap, + double* rcond ); + +lapack_int LAPACKE_stprfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const float* ap, + const float* b, lapack_int ldb, const float* x, + lapack_int ldx, float* ferr, float* berr ); +lapack_int LAPACKE_dtprfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const double* ap, + const double* b, lapack_int ldb, const double* x, + lapack_int ldx, double* ferr, double* berr ); +lapack_int LAPACKE_ctprfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_ztprfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_stptri( int matrix_layout, char uplo, char diag, lapack_int n, + float* ap ); +lapack_int LAPACKE_dtptri( int matrix_layout, char uplo, char diag, lapack_int n, + double* ap ); +lapack_int LAPACKE_ctptri( int matrix_layout, char uplo, char diag, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztptri( int matrix_layout, char uplo, char diag, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stptrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const float* ap, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dtptrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const double* ap, + double* b, lapack_int ldb ); +lapack_int LAPACKE_ctptrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztptrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stpttf( int matrix_layout, char transr, char uplo, + lapack_int n, const float* ap, float* arf ); +lapack_int LAPACKE_dtpttf( int matrix_layout, char transr, char uplo, + lapack_int n, const double* ap, double* arf ); +lapack_int LAPACKE_ctpttf( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_float* ap, + lapack_complex_float* arf ); +lapack_int LAPACKE_ztpttf( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_double* ap, + lapack_complex_double* arf ); + +lapack_int LAPACKE_stpttr( int matrix_layout, char uplo, lapack_int n, + const float* ap, float* a, lapack_int lda ); +lapack_int LAPACKE_dtpttr( int matrix_layout, char uplo, lapack_int n, + const double* ap, double* a, lapack_int lda ); +lapack_int LAPACKE_ctpttr( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztpttr( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_strcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, const float* a, lapack_int lda, + float* rcond ); +lapack_int LAPACKE_dtrcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, const double* a, lapack_int lda, + double* rcond ); +lapack_int LAPACKE_ctrcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, float* rcond ); +lapack_int LAPACKE_ztrcon( int matrix_layout, char norm, char uplo, char diag, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, double* rcond ); + +lapack_int LAPACKE_strevc( int matrix_layout, char side, char howmny, + lapack_logical* select, lapack_int n, const float* t, + lapack_int ldt, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m ); +lapack_int LAPACKE_dtrevc( int matrix_layout, char side, char howmny, + lapack_logical* select, lapack_int n, + const double* t, lapack_int ldt, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ctrevc( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ztrevc( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m ); + +lapack_int LAPACKE_strexc( int matrix_layout, char compq, lapack_int n, float* t, + lapack_int ldt, float* q, lapack_int ldq, + lapack_int* ifst, lapack_int* ilst ); +lapack_int LAPACKE_dtrexc( int matrix_layout, char compq, lapack_int n, + double* t, lapack_int ldt, double* q, lapack_int ldq, + lapack_int* ifst, lapack_int* ilst ); +lapack_int LAPACKE_ctrexc( int matrix_layout, char compq, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* q, lapack_int ldq, + lapack_int ifst, lapack_int ilst ); +lapack_int LAPACKE_ztrexc( int matrix_layout, char compq, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* q, lapack_int ldq, + lapack_int ifst, lapack_int ilst ); + +lapack_int LAPACKE_strrfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* b, lapack_int ldb, + const float* x, lapack_int ldx, float* ferr, + float* berr ); +lapack_int LAPACKE_dtrrfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* b, lapack_int ldb, + const double* x, lapack_int ldx, double* ferr, + double* berr ); +lapack_int LAPACKE_ctrrfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr ); +lapack_int LAPACKE_ztrrfs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr ); + +lapack_int LAPACKE_strsen( int matrix_layout, char job, char compq, + const lapack_logical* select, lapack_int n, float* t, + lapack_int ldt, float* q, lapack_int ldq, float* wr, + float* wi, lapack_int* m, float* s, float* sep ); +lapack_int LAPACKE_dtrsen( int matrix_layout, char job, char compq, + const lapack_logical* select, lapack_int n, + double* t, lapack_int ldt, double* q, lapack_int ldq, + double* wr, double* wi, lapack_int* m, double* s, + double* sep ); +lapack_int LAPACKE_ctrsen( int matrix_layout, char job, char compq, + const lapack_logical* select, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* w, lapack_int* m, float* s, + float* sep ); +lapack_int LAPACKE_ztrsen( int matrix_layout, char job, char compq, + const lapack_logical* select, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* w, lapack_int* m, double* s, + double* sep ); + +lapack_int LAPACKE_strsna( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const float* t, lapack_int ldt, const float* vl, + lapack_int ldvl, const float* vr, lapack_int ldvr, + float* s, float* sep, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_dtrsna( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const double* t, lapack_int ldt, const double* vl, + lapack_int ldvl, const double* vr, lapack_int ldvr, + double* s, double* sep, lapack_int mm, + lapack_int* m ); +lapack_int LAPACKE_ctrsna( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* t, lapack_int ldt, + const lapack_complex_float* vl, lapack_int ldvl, + const lapack_complex_float* vr, lapack_int ldvr, + float* s, float* sep, lapack_int mm, lapack_int* m ); +lapack_int LAPACKE_ztrsna( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* t, lapack_int ldt, + const lapack_complex_double* vl, lapack_int ldvl, + const lapack_complex_double* vr, lapack_int ldvr, + double* s, double* sep, lapack_int mm, + lapack_int* m ); + +lapack_int LAPACKE_strsyl( int matrix_layout, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, float* c, lapack_int ldc, + float* scale ); +lapack_int LAPACKE_dtrsyl( int matrix_layout, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const double* a, lapack_int lda, const double* b, + lapack_int ldb, double* c, lapack_int ldc, + double* scale ); +lapack_int LAPACKE_ctrsyl( int matrix_layout, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* c, lapack_int ldc, + float* scale ); +lapack_int LAPACKE_ztrsyl( int matrix_layout, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* c, lapack_int ldc, + double* scale ); + +lapack_int LAPACKE_strtri( int matrix_layout, char uplo, char diag, lapack_int n, + float* a, lapack_int lda ); +lapack_int LAPACKE_dtrtri( int matrix_layout, char uplo, char diag, lapack_int n, + double* a, lapack_int lda ); +lapack_int LAPACKE_ctrtri( int matrix_layout, char uplo, char diag, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztrtri( int matrix_layout, char uplo, char diag, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_strtrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, float* b, lapack_int ldb ); +lapack_int LAPACKE_dtrtrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, double* b, lapack_int ldb ); +lapack_int LAPACKE_ctrtrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztrtrs( int matrix_layout, char uplo, char trans, char diag, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_strttf( int matrix_layout, char transr, char uplo, + lapack_int n, const float* a, lapack_int lda, + float* arf ); +lapack_int LAPACKE_dtrttf( int matrix_layout, char transr, char uplo, + lapack_int n, const double* a, lapack_int lda, + double* arf ); +lapack_int LAPACKE_ctrttf( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* arf ); +lapack_int LAPACKE_ztrttf( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* arf ); + +lapack_int LAPACKE_strttp( int matrix_layout, char uplo, lapack_int n, + const float* a, lapack_int lda, float* ap ); +lapack_int LAPACKE_dtrttp( int matrix_layout, char uplo, lapack_int n, + const double* a, lapack_int lda, double* ap ); +lapack_int LAPACKE_ctrttp( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztrttp( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stzrzf( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau ); +lapack_int LAPACKE_dtzrzf( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau ); +lapack_int LAPACKE_ctzrzf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau ); +lapack_int LAPACKE_ztzrzf( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau ); + +lapack_int LAPACKE_cungbr( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zungbr( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cunghr( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zunghr( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cunglq( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zunglq( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cungql( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zungql( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cungqr( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zungqr( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cungrq( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau ); +lapack_int LAPACKE_zungrq( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau ); + +lapack_int LAPACKE_cungtr( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau ); +lapack_int LAPACKE_zungtr( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau ); + +lapack_int LAPACKE_cunmbr( int matrix_layout, char vect, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmbr( int matrix_layout, char vect, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmhr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmhr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmlq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmql( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmql( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmqr( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmrq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmrq( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmrz( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmrz( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cunmtr( int matrix_layout, char side, char uplo, char trans, + lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zunmtr( int matrix_layout, char side, char uplo, char trans, + lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_cupgtr( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_complex_float* tau, + lapack_complex_float* q, lapack_int ldq ); +lapack_int LAPACKE_zupgtr( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_complex_double* tau, + lapack_complex_double* q, lapack_int ldq ); + +lapack_int LAPACKE_cupmtr( int matrix_layout, char side, char uplo, char trans, + lapack_int m, lapack_int n, + const lapack_complex_float* ap, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc ); +lapack_int LAPACKE_zupmtr( int matrix_layout, char side, char uplo, char trans, + lapack_int m, lapack_int n, + const lapack_complex_double* ap, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc ); + +lapack_int LAPACKE_sbdsdc_work( int matrix_layout, char uplo, char compq, + lapack_int n, float* d, float* e, float* u, + lapack_int ldu, float* vt, lapack_int ldvt, + float* q, lapack_int* iq, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dbdsdc_work( int matrix_layout, char uplo, char compq, + lapack_int n, double* d, double* e, double* u, + lapack_int ldu, double* vt, lapack_int ldvt, + double* q, lapack_int* iq, double* work, + lapack_int* iwork ); + +lapack_int LAPACKE_sbdsvdx_work( int matrix_layout, char uplo, char jobz, char range, + lapack_int n, float* d, float* e, + lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + float* s, float* z, lapack_int ldz, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dbdsvdx_work( int matrix_layout, char uplo, char jobz, char range, + lapack_int n, double* d, double* e, + lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + double* s, double* z, lapack_int ldz, + double* work, lapack_int* iwork ); + +lapack_int LAPACKE_sbdsqr_work( int matrix_layout, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + float* d, float* e, float* vt, lapack_int ldvt, + float* u, lapack_int ldu, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dbdsqr_work( int matrix_layout, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + double* d, double* e, double* vt, + lapack_int ldvt, double* u, lapack_int ldu, + double* c, lapack_int ldc, double* work ); +lapack_int LAPACKE_cbdsqr_work( int matrix_layout, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + float* d, float* e, lapack_complex_float* vt, + lapack_int ldvt, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_zbdsqr_work( int matrix_layout, char uplo, lapack_int n, + lapack_int ncvt, lapack_int nru, lapack_int ncc, + double* d, double* e, lapack_complex_double* vt, + lapack_int ldvt, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* c, + lapack_int ldc, double* work ); + +lapack_int LAPACKE_sdisna_work( char job, lapack_int m, lapack_int n, + const float* d, float* sep ); +lapack_int LAPACKE_ddisna_work( char job, lapack_int m, lapack_int n, + const double* d, double* sep ); + +lapack_int LAPACKE_sgbbrd_work( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, float* ab, lapack_int ldab, + float* d, float* e, float* q, lapack_int ldq, + float* pt, lapack_int ldpt, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dgbbrd_work( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, double* ab, lapack_int ldab, + double* d, double* e, double* q, lapack_int ldq, + double* pt, lapack_int ldpt, double* c, + lapack_int ldc, double* work ); +lapack_int LAPACKE_cgbbrd_work( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, lapack_complex_float* ab, + lapack_int ldab, float* d, float* e, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* pt, lapack_int ldpt, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgbbrd_work( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int ncc, lapack_int kl, + lapack_int ku, lapack_complex_double* ab, + lapack_int ldab, double* d, double* e, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* pt, lapack_int ldpt, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgbcon_work( int matrix_layout, char norm, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, const lapack_int* ipiv, + float anorm, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgbcon_work( int matrix_layout, char norm, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, const lapack_int* ipiv, + double anorm, double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgbcon_work( int matrix_layout, char norm, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgbcon_work( int matrix_layout, char norm, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, + lapack_int ldab, const lapack_int* ipiv, + double anorm, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgbequ_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_dgbequ_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); +lapack_int LAPACKE_cgbequ_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, lapack_int ldab, + float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_zgbequ_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); + +lapack_int LAPACKE_sgbequb_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* ab, + lapack_int ldab, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_dgbequb_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); +lapack_int LAPACKE_cgbequb_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float* ab, + lapack_int ldab, float* r, float* c, + float* rowcnd, float* colcnd, float* amax ); +lapack_int LAPACKE_zgbequb_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double* ab, + lapack_int ldab, double* r, double* c, + double* rowcnd, double* colcnd, double* amax ); + +lapack_int LAPACKE_sgbrfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const float* ab, lapack_int ldab, + const float* afb, lapack_int ldafb, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgbrfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const double* ab, lapack_int ldab, + const double* afb, lapack_int ldafb, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgbrfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgbrfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, + const lapack_complex_double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgbrfsx_work( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const float* ab, + lapack_int ldab, const float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const float* r, const float* c, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgbrfsx_work( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, const double* ab, + lapack_int ldab, const double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const double* r, const double* c, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgbrfsx_work( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, + const lapack_complex_float* ab, + lapack_int ldab, + const lapack_complex_float* afb, + lapack_int ldafb, const lapack_int* ipiv, + const float* r, const float* c, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgbrfsx_work( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, + const lapack_complex_double* afb, + lapack_int ldafb, const lapack_int* ipiv, + const double* r, const double* c, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgbsv_work( int matrix_layout, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, float* ab, + lapack_int ldab, lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgbsv_work( int matrix_layout, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, double* ab, + lapack_int ldab, lapack_int* ipiv, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgbsv_work( int matrix_layout, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgbsv_work( int matrix_layout, lapack_int n, lapack_int kl, + lapack_int ku, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sgbsvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, float* ab, lapack_int ldab, + float* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dgbsvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, double* ab, lapack_int ldab, + double* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, double* r, double* c, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cgbsvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + float* r, float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgbsvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* afb, + lapack_int ldafb, lapack_int* ipiv, char* equed, + double* r, double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgbsvxx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, float* ab, lapack_int ldab, + float* afb, lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgbsvxx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, double* ab, lapack_int ldab, + double* afb, lapack_int ldafb, + lapack_int* ipiv, char* equed, double* r, + double* c, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgbsvxx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* afb, + lapack_int ldafb, lapack_int* ipiv, + char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgbsvxx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int kl, lapack_int ku, + lapack_int nrhs, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* afb, + lapack_int ldafb, lapack_int* ipiv, + char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgbtrf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, float* ab, + lapack_int ldab, lapack_int* ipiv ); +lapack_int LAPACKE_dgbtrf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, double* ab, + lapack_int ldab, lapack_int* ipiv ); +lapack_int LAPACKE_cgbtrf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + lapack_complex_float* ab, lapack_int ldab, + lapack_int* ipiv ); +lapack_int LAPACKE_zgbtrf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + lapack_complex_double* ab, lapack_int ldab, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgbtrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const float* ab, lapack_int ldab, + const lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgbtrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const double* ab, lapack_int ldab, + const lapack_int* ipiv, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgbtrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgbtrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int kl, lapack_int ku, lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sgebak_work( int matrix_layout, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const float* scale, lapack_int m, float* v, + lapack_int ldv ); +lapack_int LAPACKE_dgebak_work( int matrix_layout, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const double* scale, lapack_int m, double* v, + lapack_int ldv ); +lapack_int LAPACKE_cgebak_work( int matrix_layout, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const float* scale, lapack_int m, + lapack_complex_float* v, lapack_int ldv ); +lapack_int LAPACKE_zgebak_work( int matrix_layout, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const double* scale, lapack_int m, + lapack_complex_double* v, lapack_int ldv ); + +lapack_int LAPACKE_sgebal_work( int matrix_layout, char job, lapack_int n, + float* a, lapack_int lda, lapack_int* ilo, + lapack_int* ihi, float* scale ); +lapack_int LAPACKE_dgebal_work( int matrix_layout, char job, lapack_int n, + double* a, lapack_int lda, lapack_int* ilo, + lapack_int* ihi, double* scale ); +lapack_int LAPACKE_cgebal_work( int matrix_layout, char job, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ilo, lapack_int* ihi, + float* scale ); +lapack_int LAPACKE_zgebal_work( int matrix_layout, char job, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ilo, lapack_int* ihi, + double* scale ); + +lapack_int LAPACKE_sgebrd_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* d, float* e, + float* tauq, float* taup, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgebrd_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* d, double* e, + double* tauq, double* taup, double* work, + lapack_int lwork ); +lapack_int LAPACKE_cgebrd_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float* d, float* e, lapack_complex_float* tauq, + lapack_complex_float* taup, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgebrd_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double* d, double* e, + lapack_complex_double* tauq, + lapack_complex_double* taup, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgecon_work( int matrix_layout, char norm, lapack_int n, + const float* a, lapack_int lda, float anorm, + float* rcond, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dgecon_work( int matrix_layout, char norm, lapack_int n, + const double* a, lapack_int lda, double anorm, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgecon_work( int matrix_layout, char norm, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float anorm, float* rcond, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgecon_work( int matrix_layout, char norm, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double anorm, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgeequ_work( int matrix_layout, lapack_int m, lapack_int n, + const float* a, lapack_int lda, float* r, + float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_dgeequ_work( int matrix_layout, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* r, + double* c, double* rowcnd, double* colcnd, + double* amax ); +lapack_int LAPACKE_cgeequ_work( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_zgeequ_work( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* r, double* c, double* rowcnd, + double* colcnd, double* amax ); + +lapack_int LAPACKE_sgeequb_work( int matrix_layout, lapack_int m, lapack_int n, + const float* a, lapack_int lda, float* r, + float* c, float* rowcnd, float* colcnd, + float* amax ); +lapack_int LAPACKE_dgeequb_work( int matrix_layout, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* r, + double* c, double* rowcnd, double* colcnd, + double* amax ); +lapack_int LAPACKE_cgeequb_work( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* r, float* c, float* rowcnd, + float* colcnd, float* amax ); +lapack_int LAPACKE_zgeequb_work( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* r, double* c, double* rowcnd, + double* colcnd, double* amax ); + +lapack_int LAPACKE_sgees_work( int matrix_layout, char jobvs, char sort, + LAPACK_S_SELECT2 select, lapack_int n, float* a, + lapack_int lda, lapack_int* sdim, float* wr, + float* wi, float* vs, lapack_int ldvs, + float* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_dgees_work( int matrix_layout, char jobvs, char sort, + LAPACK_D_SELECT2 select, lapack_int n, double* a, + lapack_int lda, lapack_int* sdim, double* wr, + double* wi, double* vs, lapack_int ldvs, + double* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_cgees_work( int matrix_layout, char jobvs, char sort, + LAPACK_C_SELECT1 select, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int ldvs, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_logical* bwork ); +lapack_int LAPACKE_zgees_work( int matrix_layout, char jobvs, char sort, + LAPACK_Z_SELECT1 select, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int ldvs, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_logical* bwork ); + +lapack_int LAPACKE_sgeesx_work( int matrix_layout, char jobvs, char sort, + LAPACK_S_SELECT2 select, char sense, + lapack_int n, float* a, lapack_int lda, + lapack_int* sdim, float* wr, float* wi, + float* vs, lapack_int ldvs, float* rconde, + float* rcondv, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork, + lapack_logical* bwork ); +lapack_int LAPACKE_dgeesx_work( int matrix_layout, char jobvs, char sort, + LAPACK_D_SELECT2 select, char sense, + lapack_int n, double* a, lapack_int lda, + lapack_int* sdim, double* wr, double* wi, + double* vs, lapack_int ldvs, double* rconde, + double* rcondv, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork, + lapack_logical* bwork ); +lapack_int LAPACKE_cgeesx_work( int matrix_layout, char jobvs, char sort, + LAPACK_C_SELECT1 select, char sense, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_int* sdim, + lapack_complex_float* w, + lapack_complex_float* vs, lapack_int ldvs, + float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_logical* bwork ); +lapack_int LAPACKE_zgeesx_work( int matrix_layout, char jobvs, char sort, + LAPACK_Z_SELECT1 select, char sense, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_int* sdim, + lapack_complex_double* w, + lapack_complex_double* vs, lapack_int ldvs, + double* rconde, double* rcondv, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_logical* bwork ); + +lapack_int LAPACKE_sgeev_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, float* a, lapack_int lda, + float* wr, float* wi, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgeev_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, double* a, lapack_int lda, + double* wr, double* wi, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeev_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* w, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zgeev_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* w, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_sgeevx_work( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, float* a, + lapack_int lda, float* wr, float* wi, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* scale, + float* abnrm, float* rconde, float* rcondv, + float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dgeevx_work( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, double* a, + lapack_int lda, double* wr, double* wi, + double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr, lapack_int* ilo, + lapack_int* ihi, double* scale, double* abnrm, + double* rconde, double* rcondv, double* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_cgeevx_work( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* w, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* scale, + float* abnrm, float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zgeevx_work( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* w, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, double* scale, + double* abnrm, double* rconde, double* rcondv, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_sgehrd_work( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, float* a, lapack_int lda, + float* tau, float* work, lapack_int lwork ); +lapack_int LAPACKE_dgehrd_work( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, double* a, lapack_int lda, + double* tau, double* work, lapack_int lwork ); +lapack_int LAPACKE_cgehrd_work( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgehrd_work( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgejsv_work( int matrix_layout, char joba, char jobu, + char jobv, char jobr, char jobt, char jobp, + lapack_int m, lapack_int n, float* a, + lapack_int lda, float* sva, float* u, + lapack_int ldu, float* v, lapack_int ldv, + float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dgejsv_work( int matrix_layout, char joba, char jobu, + char jobv, char jobr, char jobt, char jobp, + lapack_int m, lapack_int n, double* a, + lapack_int lda, double* sva, double* u, + lapack_int ldu, double* v, lapack_int ldv, + double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_cgejsv_work( int matrix_layout, char joba, char jobu, + char jobv, char jobr, char jobt, char jobp, + lapack_int m, lapack_int n, lapack_complex_float* a, + lapack_int lda, float* sva, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* cwork, lapack_int lwork, + float* work, lapack_int lrwork, + lapack_int* iwork ); +lapack_int LAPACKE_zgejsv_work( int matrix_layout, char joba, char jobu, + char jobv, char jobr, char jobt, char jobp, + lapack_int m, lapack_int n, lapack_complex_double* a, + lapack_int lda, double* sva, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* cwork, lapack_int lwork, + double* work, lapack_int lrwork, + lapack_int* iwork ); + +lapack_int LAPACKE_sgelq2_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work ); +lapack_int LAPACKE_dgelq2_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work ); +lapack_int LAPACKE_cgelq2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work ); +lapack_int LAPACKE_zgelq2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work ); + +lapack_int LAPACKE_sgelqf_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgelqf_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgelqf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgelqf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgels_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgels_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgels_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgels_work( int matrix_layout, char trans, lapack_int m, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgelsd_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + float* b, lapack_int ldb, float* s, float rcond, + lapack_int* rank, float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dgelsd_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* s, + double rcond, lapack_int* rank, double* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_cgelsd_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int* iwork ); +lapack_int LAPACKE_zgelsd_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* s, double rcond, + lapack_int* rank, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int* iwork ); + +lapack_int LAPACKE_sgelss_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + float* b, lapack_int ldb, float* s, float rcond, + lapack_int* rank, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgelss_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* s, + double rcond, lapack_int* rank, double* work, + lapack_int lwork ); +lapack_int LAPACKE_cgelss_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* s, float rcond, + lapack_int* rank, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zgelss_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double* s, double rcond, + lapack_int* rank, lapack_complex_double* work, + lapack_int lwork, double* rwork ); + +lapack_int LAPACKE_sgelsy_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + float* b, lapack_int ldb, lapack_int* jpvt, + float rcond, lapack_int* rank, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgelsy_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, lapack_int* jpvt, + double rcond, lapack_int* rank, double* work, + lapack_int lwork ); +lapack_int LAPACKE_cgelsy_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_int* jpvt, float rcond, + lapack_int* rank, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zgelsy_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_int* jpvt, double rcond, + lapack_int* rank, lapack_complex_double* work, + lapack_int lwork, double* rwork ); + +lapack_int LAPACKE_sgeqlf_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgeqlf_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeqlf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgeqlf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgeqp3_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* jpvt, + float* tau, float* work, lapack_int lwork ); +lapack_int LAPACKE_dgeqp3_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* jpvt, + double* tau, double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeqp3_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zgeqp3_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_sgeqpf_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* jpvt, + float* tau, float* work ); +lapack_int LAPACKE_dgeqpf_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* jpvt, + double* tau, double* work ); +lapack_int LAPACKE_cgeqpf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_float* tau, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgeqpf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* jpvt, lapack_complex_double* tau, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgeqr2_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work ); +lapack_int LAPACKE_dgeqr2_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work ); +lapack_int LAPACKE_cgeqr2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work ); +lapack_int LAPACKE_zgeqr2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work ); + +lapack_int LAPACKE_sgeqrf_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgeqrf_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeqrf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgeqrf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgeqrfp_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgeqrfp_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgeqrfp_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgeqrfp_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sgerfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgerfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cgerfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgerfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgerfsx_work( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* r, const float* c, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgerfsx_work( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* r, const double* c, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgerfsx_work( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* r, const float* c, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgerfsx_work( int matrix_layout, char trans, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* r, const double* c, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgerqf_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgerqf_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgerqf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgerqf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgesdd_work( int matrix_layout, char jobz, lapack_int m, + lapack_int n, float* a, lapack_int lda, + float* s, float* u, lapack_int ldu, float* vt, + lapack_int ldvt, float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dgesdd_work( int matrix_layout, char jobz, lapack_int m, + lapack_int n, double* a, lapack_int lda, + double* s, double* u, lapack_int ldu, + double* vt, lapack_int ldvt, double* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_cgesdd_work( int matrix_layout, char jobz, lapack_int m, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float* s, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* vt, lapack_int ldvt, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int* iwork ); +lapack_int LAPACKE_zgesdd_work( int matrix_layout, char jobz, lapack_int m, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double* s, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* vt, lapack_int ldvt, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int* iwork ); + +lapack_int LAPACKE_sgesv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + float* a, lapack_int lda, lapack_int* ipiv, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dgesv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + double* a, lapack_int lda, lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cgesv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgesv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); +lapack_int LAPACKE_dsgesv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + double* a, lapack_int lda, lapack_int* ipiv, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* work, float* swork, + lapack_int* iter ); +lapack_int LAPACKE_zcgesv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, lapack_complex_double* work, + lapack_complex_float* swork, double* rwork, + lapack_int* iter ); + +lapack_int LAPACKE_sgesvd_work( int matrix_layout, char jobu, char jobvt, + lapack_int m, lapack_int n, float* a, + lapack_int lda, float* s, float* u, + lapack_int ldu, float* vt, lapack_int ldvt, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgesvd_work( int matrix_layout, char jobu, char jobvt, + lapack_int m, lapack_int n, double* a, + lapack_int lda, double* s, double* u, + lapack_int ldu, double* vt, lapack_int ldvt, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgesvd_work( int matrix_layout, char jobu, char jobvt, + lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float* s, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* vt, + lapack_int ldvt, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zgesvd_work( int matrix_layout, char jobu, char jobvt, + lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double* s, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* vt, + lapack_int ldvt, lapack_complex_double* work, + lapack_int lwork, double* rwork ); + +lapack_int LAPACKE_sgesvdx_work( int matrix_layout, char jobu, char jobvt, char range, + lapack_int m, lapack_int n, float* a, + lapack_int lda, lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + float* s, float* u, lapack_int ldu, + float* vt, lapack_int ldvt, + float* work, lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_dgesvdx_work( int matrix_layout, char jobu, char jobvt, char range, + lapack_int m, lapack_int n, double* a, + lapack_int lda, lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + double* s, double* u, lapack_int ldu, + double* vt, lapack_int ldvt, + double* work, lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_cgesvdx_work( int matrix_layout, char jobu, char jobvt, char range, + lapack_int m, lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + float* s, lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* vt, lapack_int ldvt, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int* iwork ); +lapack_int LAPACKE_zgesvdx_work( int matrix_layout, char jobu, char jobvt, char range, + lapack_int m, lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_int vl, lapack_int vu, + lapack_int il, lapack_int iu, lapack_int ns, + double* s, lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* vt, lapack_int ldvt, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int* iwork ); + +lapack_int LAPACKE_sgesvj_work( int matrix_layout, char joba, char jobu, + char jobv, lapack_int m, lapack_int n, float* a, + lapack_int lda, float* sva, lapack_int mv, + float* v, lapack_int ldv, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dgesvj_work( int matrix_layout, char joba, char jobu, + char jobv, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* sva, + lapack_int mv, double* v, lapack_int ldv, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgesvj_work( int matrix_layout, char joba, char jobu, + char jobv, lapack_int m, lapack_int n, lapack_complex_float* a, + lapack_int lda, float* sva, lapack_int mv, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* cwork, lapack_int lwork, + float* rwork,lapack_int lrwork ); +lapack_int LAPACKE_zgesvj_work( int matrix_layout, char joba, char jobu, + char jobv, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, double* sva, + lapack_int mv, lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* cwork, lapack_int lwork, + double* rwork, lapack_int lrwork ); + +lapack_int LAPACKE_sgesvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, + float* c, float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dgesvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, + double* c, double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, double* work, lapack_int* iwork ); +lapack_int LAPACKE_cgesvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, + float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zgesvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, + double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sgesvxx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, + float* c, float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgesvxx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, + double* c, double* b, lapack_int ldb, + double* x, lapack_int ldx, double* rcond, + double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgesvxx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* r, + float* c, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgesvxx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* r, + double* c, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgetf2_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetf2_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetf2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetf2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetrf_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetrf_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetrf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetrf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetrf2_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dgetrf2_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_cgetrf2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zgetrf2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_sgetri_work( int matrix_layout, lapack_int n, float* a, + lapack_int lda, const lapack_int* ipiv, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgetri_work( int matrix_layout, lapack_int n, double* a, + lapack_int lda, const lapack_int* ipiv, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgetri_work( int matrix_layout, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgetri_work( int matrix_layout, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgetrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgetrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cgetrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zgetrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sggbak_work( int matrix_layout, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const float* lscale, const float* rscale, + lapack_int m, float* v, lapack_int ldv ); +lapack_int LAPACKE_dggbak_work( int matrix_layout, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const double* lscale, const double* rscale, + lapack_int m, double* v, lapack_int ldv ); +lapack_int LAPACKE_cggbak_work( int matrix_layout, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const float* lscale, const float* rscale, + lapack_int m, lapack_complex_float* v, + lapack_int ldv ); +lapack_int LAPACKE_zggbak_work( int matrix_layout, char job, char side, + lapack_int n, lapack_int ilo, lapack_int ihi, + const double* lscale, const double* rscale, + lapack_int m, lapack_complex_double* v, + lapack_int ldv ); + +lapack_int LAPACKE_sggbal_work( int matrix_layout, char job, lapack_int n, + float* a, lapack_int lda, float* b, + lapack_int ldb, lapack_int* ilo, + lapack_int* ihi, float* lscale, float* rscale, + float* work ); +lapack_int LAPACKE_dggbal_work( int matrix_layout, char job, lapack_int n, + double* a, lapack_int lda, double* b, + lapack_int ldb, lapack_int* ilo, + lapack_int* ihi, double* lscale, double* rscale, + double* work ); +lapack_int LAPACKE_cggbal_work( int matrix_layout, char job, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* work ); +lapack_int LAPACKE_zggbal_work( int matrix_layout, char job, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* ilo, lapack_int* ihi, + double* lscale, double* rscale, double* work ); + +lapack_int LAPACKE_sgges_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_S_SELECT3 selctg, lapack_int n, + float* a, lapack_int lda, float* b, + lapack_int ldb, lapack_int* sdim, float* alphar, + float* alphai, float* beta, float* vsl, + lapack_int ldvsl, float* vsr, lapack_int ldvsr, + float* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_dgges_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_D_SELECT3 selctg, lapack_int n, + double* a, lapack_int lda, double* b, + lapack_int ldb, lapack_int* sdim, double* alphar, + double* alphai, double* beta, double* vsl, + lapack_int ldvsl, double* vsr, lapack_int ldvsr, + double* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_cgges_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_C_SELECT2 selctg, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int ldvsl, + lapack_complex_float* vsr, lapack_int ldvsr, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_logical* bwork ); +lapack_int LAPACKE_zgges_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_Z_SELECT2 selctg, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_logical* bwork ); + +lapack_int LAPACKE_sgges3_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_S_SELECT3 selctg, + lapack_int n, + float* a, lapack_int lda, + float* b, lapack_int ldb, lapack_int* sdim, + float* alphar, float* alphai, float* beta, + float* vsl, lapack_int ldvsl, + float* vsr, lapack_int ldvsr, + float* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_dgges3_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_D_SELECT3 selctg, + lapack_int n, + double* a, lapack_int lda, + double* b, lapack_int ldb, lapack_int* sdim, + double* alphar, double* alphai, double* beta, + double* vsl, lapack_int ldvsl, + double* vsr, lapack_int ldvsr, + double* work, lapack_int lwork, + lapack_logical* bwork ); +lapack_int LAPACKE_cgges3_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_C_SELECT2 selctg, + lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int ldvsl, + lapack_complex_float* vsr, lapack_int ldvsr, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_logical* bwork ); +lapack_int LAPACKE_zgges3_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_Z_SELECT2 selctg, + lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_int* sdim, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_logical* bwork ); + +lapack_int LAPACKE_sggesx_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_S_SELECT3 selctg, char sense, + lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, lapack_int* sdim, + float* alphar, float* alphai, float* beta, + float* vsl, lapack_int ldvsl, float* vsr, + lapack_int ldvsr, float* rconde, float* rcondv, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork, + lapack_logical* bwork ); +lapack_int LAPACKE_dggesx_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_D_SELECT3 selctg, char sense, + lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, lapack_int* sdim, + double* alphar, double* alphai, double* beta, + double* vsl, lapack_int ldvsl, double* vsr, + lapack_int ldvsr, double* rconde, + double* rcondv, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork, + lapack_logical* bwork ); +lapack_int LAPACKE_cggesx_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_C_SELECT2 selctg, char sense, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_int* sdim, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int ldvsl, + lapack_complex_float* vsr, lapack_int ldvsr, + float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int* iwork, + lapack_int liwork, lapack_logical* bwork ); +lapack_int LAPACKE_zggesx_work( int matrix_layout, char jobvsl, char jobvsr, + char sort, LAPACK_Z_SELECT2 selctg, char sense, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_int* sdim, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int ldvsl, + lapack_complex_double* vsr, lapack_int ldvsr, + double* rconde, double* rcondv, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int* iwork, + lapack_int liwork, lapack_logical* bwork ); + +lapack_int LAPACKE_sggev_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, float* a, lapack_int lda, float* b, + lapack_int ldb, float* alphar, float* alphai, + float* beta, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dggev_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, double* alphar, + double* alphai, double* beta, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cggev_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zggev_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_sggev3_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, + float* a, lapack_int lda, + float* b, lapack_int ldb, + float* alphar, float* alphai, float* beta, + float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dggev3_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, + double* a, lapack_int lda, + double* b, lapack_int ldb, + double* alphar, double* alphai, double* beta, + double* vl, lapack_int ldvl, + double* vr, lapack_int ldvr, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cggev3_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zggev3_work( int matrix_layout, char jobvl, char jobvr, + lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_sggevx_work( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* alphar, float* alphai, float* beta, + float* vl, lapack_int ldvl, float* vr, + lapack_int ldvr, lapack_int* ilo, + lapack_int* ihi, float* lscale, float* rscale, + float* abnrm, float* bbnrm, float* rconde, + float* rcondv, float* work, lapack_int lwork, + lapack_int* iwork, lapack_logical* bwork ); +lapack_int LAPACKE_dggevx_work( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* alphar, double* alphai, double* beta, + double* vl, lapack_int ldvl, double* vr, + lapack_int ldvr, lapack_int* ilo, + lapack_int* ihi, double* lscale, double* rscale, + double* abnrm, double* bbnrm, double* rconde, + double* rcondv, double* work, lapack_int lwork, + lapack_int* iwork, lapack_logical* bwork ); +lapack_int LAPACKE_cggevx_work( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* abnrm, float* bbnrm, + float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int* iwork, + lapack_logical* bwork ); +lapack_int LAPACKE_zggevx_work( int matrix_layout, char balanc, char jobvl, + char jobvr, char sense, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int* ilo, lapack_int* ihi, + double* lscale, double* rscale, double* abnrm, + double* bbnrm, double* rconde, double* rcondv, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int* iwork, + lapack_logical* bwork ); + +lapack_int LAPACKE_sggglm_work( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, float* a, lapack_int lda, + float* b, lapack_int ldb, float* d, float* x, + float* y, float* work, lapack_int lwork ); +lapack_int LAPACKE_dggglm_work( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, double* a, lapack_int lda, + double* b, lapack_int ldb, double* d, double* x, + double* y, double* work, lapack_int lwork ); +lapack_int LAPACKE_cggglm_work( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* d, + lapack_complex_float* x, + lapack_complex_float* y, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zggglm_work( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* d, + lapack_complex_double* x, + lapack_complex_double* y, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgghrd_work( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* a, lapack_int lda, float* b, + lapack_int ldb, float* q, lapack_int ldq, + float* z, lapack_int ldz ); +lapack_int LAPACKE_dgghrd_work( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* a, lapack_int lda, double* b, + lapack_int ldb, double* q, lapack_int ldq, + double* z, lapack_int ldz ); +lapack_int LAPACKE_cgghrd_work( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz ); +lapack_int LAPACKE_zgghrd_work( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz ); + +lapack_int LAPACKE_sgghd3_work( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* a, lapack_int lda, + float* b, lapack_int ldb, + float* q, lapack_int ldq, + float* z, lapack_int ldz, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dgghd3_work( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* a, lapack_int lda, + double* b, lapack_int ldb, + double* q, lapack_int ldq, + double* z, lapack_int ldz, + double* work, lapack_int lwork ); +lapack_int LAPACKE_cgghd3_work( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgghd3_work( int matrix_layout, char compq, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sgglse_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int p, float* a, lapack_int lda, + float* b, lapack_int ldb, float* c, float* d, + float* x, float* work, lapack_int lwork ); +lapack_int LAPACKE_dgglse_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int p, double* a, lapack_int lda, + double* b, lapack_int ldb, double* c, double* d, + double* x, double* work, lapack_int lwork ); +lapack_int LAPACKE_cgglse_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* c, + lapack_complex_float* d, + lapack_complex_float* x, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zgglse_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* c, + lapack_complex_double* d, + lapack_complex_double* x, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sggqrf_work( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, float* a, lapack_int lda, + float* taua, float* b, lapack_int ldb, + float* taub, float* work, lapack_int lwork ); +lapack_int LAPACKE_dggqrf_work( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, double* a, lapack_int lda, + double* taua, double* b, lapack_int ldb, + double* taub, double* work, lapack_int lwork ); +lapack_int LAPACKE_cggqrf_work( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* taua, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* taub, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zggqrf_work( int matrix_layout, lapack_int n, lapack_int m, + lapack_int p, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* taua, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* taub, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sggrqf_work( int matrix_layout, lapack_int m, lapack_int p, + lapack_int n, float* a, lapack_int lda, + float* taua, float* b, lapack_int ldb, + float* taub, float* work, lapack_int lwork ); +lapack_int LAPACKE_dggrqf_work( int matrix_layout, lapack_int m, lapack_int p, + lapack_int n, double* a, lapack_int lda, + double* taua, double* b, lapack_int ldb, + double* taub, double* work, lapack_int lwork ); +lapack_int LAPACKE_cggrqf_work( int matrix_layout, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* taua, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* taub, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zggrqf_work( int matrix_layout, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* taua, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* taub, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sggsvd_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + float* a, lapack_int lda, float* b, + lapack_int ldb, float* alpha, float* beta, + float* u, lapack_int ldu, float* v, + lapack_int ldv, float* q, lapack_int ldq, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dggsvd_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + double* a, lapack_int lda, double* b, + lapack_int ldb, double* alpha, double* beta, + double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cggsvd_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float* alpha, float* beta, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* work, float* rwork, + lapack_int* iwork ); +lapack_int LAPACKE_zggsvd_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* alpha, double* beta, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* work, double* rwork, + lapack_int* iwork ); + +lapack_int LAPACKE_sggsvd3_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + float* a, lapack_int lda, float* b, + lapack_int ldb, float* alpha, float* beta, + float* u, lapack_int ldu, float* v, + lapack_int ldv, float* q, lapack_int ldq, + float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dggsvd3_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + double* a, lapack_int lda, double* b, + lapack_int ldb, double* alpha, double* beta, + double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq, + double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_cggsvd3_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float* alpha, float* beta, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int* iwork ); +lapack_int LAPACKE_zggsvd3_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int n, + lapack_int p, lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* alpha, double* beta, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int* iwork ); + +lapack_int LAPACKE_sggsvp_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, float tola, + float tolb, lapack_int* k, lapack_int* l, + float* u, lapack_int ldu, float* v, + lapack_int ldv, float* q, lapack_int ldq, + lapack_int* iwork, float* tau, float* work ); +lapack_int LAPACKE_dggsvp_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, double tola, + double tolb, lapack_int* k, lapack_int* l, + double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq, + lapack_int* iwork, double* tau, double* work ); +lapack_int LAPACKE_cggsvp_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float tola, float tolb, + lapack_int* k, lapack_int* l, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq, + lapack_int* iwork, float* rwork, + lapack_complex_float* tau, + lapack_complex_float* work ); +lapack_int LAPACKE_zggsvp_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double tola, double tolb, + lapack_int* k, lapack_int* l, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_int* iwork, double* rwork, + lapack_complex_double* tau, + lapack_complex_double* work ); + +lapack_int LAPACKE_sggsvp3_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, float* a, lapack_int lda, + float* b, lapack_int ldb, float tola, + float tolb, lapack_int* k, lapack_int* l, + float* u, lapack_int ldu, float* v, + lapack_int ldv, float* q, lapack_int ldq, + lapack_int* iwork, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dggsvp3_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, double* a, lapack_int lda, + double* b, lapack_int ldb, double tola, + double tolb, lapack_int* k, lapack_int* l, + double* u, lapack_int ldu, double* v, + lapack_int ldv, double* q, lapack_int ldq, + lapack_int* iwork, double* tau, double* work, + lapack_int lwork ); +lapack_int LAPACKE_cggsvp3_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float tola, float tolb, + lapack_int* k, lapack_int* l, + lapack_complex_float* u, lapack_int ldu, + lapack_complex_float* v, lapack_int ldv, + lapack_complex_float* q, lapack_int ldq, + lapack_int* iwork, float* rwork, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zggsvp3_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, double tola, double tolb, + lapack_int* k, lapack_int* l, + lapack_complex_double* u, lapack_int ldu, + lapack_complex_double* v, lapack_int ldv, + lapack_complex_double* q, lapack_int ldq, + lapack_int* iwork, double* rwork, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_sgtcon_work( char norm, lapack_int n, const float* dl, + const float* d, const float* du, + const float* du2, const lapack_int* ipiv, + float anorm, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgtcon_work( char norm, lapack_int n, const double* dl, + const double* d, const double* du, + const double* du2, const lapack_int* ipiv, + double anorm, double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgtcon_work( char norm, lapack_int n, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zgtcon_work( char norm, lapack_int n, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_sgtrfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const float* dl, + const float* d, const float* du, + const float* dlf, const float* df, + const float* duf, const float* du2, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dgtrfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const double* dl, + const double* d, const double* du, + const double* dlf, const double* df, + const double* duf, const double* du2, + const lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cgtrfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* dlf, + const lapack_complex_float* df, + const lapack_complex_float* duf, + const lapack_complex_float* du2, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgtrfs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* dlf, + const lapack_complex_double* df, + const lapack_complex_double* duf, + const lapack_complex_double* du2, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgtsv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + float* dl, float* d, float* du, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dgtsv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + double* dl, double* d, double* du, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cgtsv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_float* dl, + lapack_complex_float* d, + lapack_complex_float* du, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zgtsv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + lapack_complex_double* dl, + lapack_complex_double* d, + lapack_complex_double* du, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sgtsvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, const float* dl, + const float* d, const float* du, float* dlf, + float* df, float* duf, float* du2, + lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dgtsvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, const double* dl, + const double* d, const double* du, double* dlf, + double* df, double* duf, double* du2, + lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cgtsvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + lapack_complex_float* dlf, + lapack_complex_float* df, + lapack_complex_float* duf, + lapack_complex_float* du2, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zgtsvx_work( int matrix_layout, char fact, char trans, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + lapack_complex_double* dlf, + lapack_complex_double* df, + lapack_complex_double* duf, + lapack_complex_double* du2, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sgttrf_work( lapack_int n, float* dl, float* d, float* du, + float* du2, lapack_int* ipiv ); +lapack_int LAPACKE_dgttrf_work( lapack_int n, double* dl, double* d, double* du, + double* du2, lapack_int* ipiv ); +lapack_int LAPACKE_cgttrf_work( lapack_int n, lapack_complex_float* dl, + lapack_complex_float* d, + lapack_complex_float* du, + lapack_complex_float* du2, lapack_int* ipiv ); +lapack_int LAPACKE_zgttrf_work( lapack_int n, lapack_complex_double* dl, + lapack_complex_double* d, + lapack_complex_double* du, + lapack_complex_double* du2, lapack_int* ipiv ); + +lapack_int LAPACKE_sgttrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const float* dl, + const float* d, const float* du, + const float* du2, const lapack_int* ipiv, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dgttrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const double* dl, + const double* d, const double* du, + const double* du2, const lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cgttrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zgttrs_work( int matrix_layout, char trans, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chbev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zhbev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chbevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zhbevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_chbevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* q, lapack_int ldq, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + float* rwork, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_zhbevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* q, lapack_int ldq, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + double* rwork, lapack_int* iwork, + lapack_int* ifail ); + +lapack_int LAPACKE_chbgst_work( int matrix_layout, char vect, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* bb, lapack_int ldbb, + lapack_complex_float* x, lapack_int ldx, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhbgst_work( int matrix_layout, char vect, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + const lapack_complex_double* bb, + lapack_int ldbb, lapack_complex_double* x, + lapack_int ldx, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chbgv_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zhbgv_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chbgvd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* bb, lapack_int ldbb, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zhbgvd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* bb, lapack_int ldbb, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_chbgvx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, lapack_int ka, + lapack_int kb, lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* bb, + lapack_int ldbb, lapack_complex_float* q, + lapack_int ldq, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zhbgvx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, lapack_int ka, + lapack_int kb, lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* bb, + lapack_int ldbb, lapack_complex_double* q, + lapack_int ldq, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_chbtrd_work( int matrix_layout, char vect, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_float* ab, lapack_int ldab, + float* d, float* e, lapack_complex_float* q, + lapack_int ldq, lapack_complex_float* work ); +lapack_int LAPACKE_zhbtrd_work( int matrix_layout, char vect, char uplo, + lapack_int n, lapack_int kd, + lapack_complex_double* ab, lapack_int ldab, + double* d, double* e, lapack_complex_double* q, + lapack_int ldq, lapack_complex_double* work ); + +lapack_int LAPACKE_checon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zhecon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_cheequb_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax, + lapack_complex_float* work ); +lapack_int LAPACKE_zheequb_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax, + lapack_complex_double* work ); + +lapack_int LAPACKE_cheev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float* w, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zheev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double* w, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_cheevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, float* w, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_zheevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, double* w, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_cheevr_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_int* isuppz, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_zheevr_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_int* isuppz, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_cheevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zheevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_chegst_work( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhegst_work( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chegv_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb, float* w, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zhegv_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* w, lapack_complex_double* work, + lapack_int lwork, double* rwork ); + +lapack_int LAPACKE_chegvd_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float* w, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zhegvd_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double* w, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_chegvx_work( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zhegvx_work( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_cherfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zherfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_cherfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* s, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zherfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chesv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zhesv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_chesvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zhesvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_chesvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zhesvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chetrd_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + float* d, float* e, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zhetrd_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + double* d, double* e, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_chetrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* work, + lapack_int lwork ); +lapack_int LAPACKE_zhetrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_chetri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_zhetri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work ); + +lapack_int LAPACKE_chetrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zhetrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chfrk_work( int matrix_layout, char transr, char uplo, + char trans, lapack_int n, lapack_int k, + float alpha, const lapack_complex_float* a, + lapack_int lda, float beta, + lapack_complex_float* c ); +lapack_int LAPACKE_zhfrk_work( int matrix_layout, char transr, char uplo, + char trans, lapack_int n, lapack_int k, + double alpha, const lapack_complex_double* a, + lapack_int lda, double beta, + lapack_complex_double* c ); + +lapack_int LAPACKE_shgeqz_work( int matrix_layout, char job, char compq, + char compz, lapack_int n, lapack_int ilo, + lapack_int ihi, float* h, lapack_int ldh, + float* t, lapack_int ldt, float* alphar, + float* alphai, float* beta, float* q, + lapack_int ldq, float* z, lapack_int ldz, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dhgeqz_work( int matrix_layout, char job, char compq, + char compz, lapack_int n, lapack_int ilo, + lapack_int ihi, double* h, lapack_int ldh, + double* t, lapack_int ldt, double* alphar, + double* alphai, double* beta, double* q, + lapack_int ldq, double* z, lapack_int ldz, + double* work, lapack_int lwork ); +lapack_int LAPACKE_chgeqz_work( int matrix_layout, char job, char compq, + char compz, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* h, + lapack_int ldh, lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, lapack_int lwork, + float* rwork ); +lapack_int LAPACKE_zhgeqz_work( int matrix_layout, char job, char compq, + char compz, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* h, + lapack_int ldh, lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_chpcon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zhpcon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_chpev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_complex_float* ap, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhpev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_complex_double* ap, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_chpevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_complex_float* ap, + float* w, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zhpevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_complex_double* ap, + double* w, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_chpevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_float* ap, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zhpevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, + lapack_complex_double* ap, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_chpgst_work( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, lapack_complex_float* ap, + const lapack_complex_float* bp ); +lapack_int LAPACKE_zhpgst_work( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, lapack_complex_double* ap, + const lapack_complex_double* bp ); + +lapack_int LAPACKE_chpgv_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_float* ap, + lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhpgv_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_double* ap, + lapack_complex_double* bp, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_chpgvd_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_float* ap, + lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_zhpgvd_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, + lapack_complex_double* ap, + lapack_complex_double* bp, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int lrwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_chpgvx_work( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_float* ap, + lapack_complex_float* bp, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_zhpgvx_work( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, + lapack_complex_double* ap, + lapack_complex_double* bp, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_chprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_chpsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhpsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_chpsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + lapack_complex_float* afp, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zhpsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* afp, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_chptrd_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, float* d, float* e, + lapack_complex_float* tau ); +lapack_int LAPACKE_zhptrd_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, double* d, double* e, + lapack_complex_double* tau ); + +lapack_int LAPACKE_chptrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_zhptrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_int* ipiv ); + +lapack_int LAPACKE_chptri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, + const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_zhptri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, + const lapack_int* ipiv, + lapack_complex_double* work ); + +lapack_int LAPACKE_chptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zhptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_shsein_work( int matrix_layout, char job, char eigsrc, + char initv, lapack_logical* select, + lapack_int n, const float* h, lapack_int ldh, + float* wr, const float* wi, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, float* work, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_dhsein_work( int matrix_layout, char job, char eigsrc, + char initv, lapack_logical* select, + lapack_int n, const double* h, lapack_int ldh, + double* wr, const double* wi, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, double* work, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_chsein_work( int matrix_layout, char job, char eigsrc, + char initv, const lapack_logical* select, + lapack_int n, const lapack_complex_float* h, + lapack_int ldh, lapack_complex_float* w, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_float* work, float* rwork, + lapack_int* ifaill, lapack_int* ifailr ); +lapack_int LAPACKE_zhsein_work( int matrix_layout, char job, char eigsrc, + char initv, const lapack_logical* select, + lapack_int n, const lapack_complex_double* h, + lapack_int ldh, lapack_complex_double* w, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, double* rwork, + lapack_int* ifaill, lapack_int* ifailr ); + +lapack_int LAPACKE_shseqr_work( int matrix_layout, char job, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + float* h, lapack_int ldh, float* wr, float* wi, + float* z, lapack_int ldz, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dhseqr_work( int matrix_layout, char job, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + double* h, lapack_int ldh, double* wr, + double* wi, double* z, lapack_int ldz, + double* work, lapack_int lwork ); +lapack_int LAPACKE_chseqr_work( int matrix_layout, char job, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_float* h, lapack_int ldh, + lapack_complex_float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zhseqr_work( int matrix_layout, char job, char compz, + lapack_int n, lapack_int ilo, lapack_int ihi, + lapack_complex_double* h, lapack_int ldh, + lapack_complex_double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_clacgv_work( lapack_int n, lapack_complex_float* x, + lapack_int incx ); +lapack_int LAPACKE_zlacgv_work( lapack_int n, lapack_complex_double* x, + lapack_int incx ); + +lapack_int LAPACKE_slacn2_work( lapack_int n, float* v, float* x, + lapack_int* isgn, float* est, lapack_int* kase, + lapack_int* isave ); +lapack_int LAPACKE_dlacn2_work( lapack_int n, double* v, double* x, + lapack_int* isgn, double* est, lapack_int* kase, + lapack_int* isave ); +lapack_int LAPACKE_clacn2_work( lapack_int n, lapack_complex_float* v, + lapack_complex_float* x, + float* est, lapack_int* kase, + lapack_int* isave ); +lapack_int LAPACKE_zlacn2_work( lapack_int n, lapack_complex_double* v, + lapack_complex_double* x, + double* est, lapack_int* kase, + lapack_int* isave ); + +lapack_int LAPACKE_slacpy_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const float* a, lapack_int lda, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dlacpy_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const double* a, lapack_int lda, + double* b, lapack_int ldb ); +lapack_int LAPACKE_clacpy_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zlacpy_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_clacp2_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zlacp2_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, const double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_zlag2c_work( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_float* sa, lapack_int ldsa ); + +lapack_int LAPACKE_slag2d_work( int matrix_layout, lapack_int m, lapack_int n, + const float* sa, lapack_int ldsa, double* a, + lapack_int lda ); + +lapack_int LAPACKE_dlag2s_work( int matrix_layout, lapack_int m, lapack_int n, + const double* a, lapack_int lda, float* sa, + lapack_int ldsa ); + +lapack_int LAPACKE_clag2z_work( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_float* sa, lapack_int ldsa, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_slagge_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* d, + float* a, lapack_int lda, lapack_int* iseed, + float* work ); +lapack_int LAPACKE_dlagge_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* d, + double* a, lapack_int lda, lapack_int* iseed, + double* work ); +lapack_int LAPACKE_clagge_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const float* d, + lapack_complex_float* a, lapack_int lda, + lapack_int* iseed, lapack_complex_float* work ); +lapack_int LAPACKE_zlagge_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, const double* d, + lapack_complex_double* a, lapack_int lda, + lapack_int* iseed, + lapack_complex_double* work ); + +lapack_int LAPACKE_claghe_work( int matrix_layout, lapack_int n, lapack_int k, + const float* d, lapack_complex_float* a, + lapack_int lda, lapack_int* iseed, + lapack_complex_float* work ); +lapack_int LAPACKE_zlaghe_work( int matrix_layout, lapack_int n, lapack_int k, + const double* d, lapack_complex_double* a, + lapack_int lda, lapack_int* iseed, + lapack_complex_double* work ); + +lapack_int LAPACKE_slagsy_work( int matrix_layout, lapack_int n, lapack_int k, + const float* d, float* a, lapack_int lda, + lapack_int* iseed, float* work ); +lapack_int LAPACKE_dlagsy_work( int matrix_layout, lapack_int n, lapack_int k, + const double* d, double* a, lapack_int lda, + lapack_int* iseed, double* work ); +lapack_int LAPACKE_clagsy_work( int matrix_layout, lapack_int n, lapack_int k, + const float* d, lapack_complex_float* a, + lapack_int lda, lapack_int* iseed, + lapack_complex_float* work ); +lapack_int LAPACKE_zlagsy_work( int matrix_layout, lapack_int n, lapack_int k, + const double* d, lapack_complex_double* a, + lapack_int lda, lapack_int* iseed, + lapack_complex_double* work ); + +lapack_int LAPACKE_slapmr_work( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, float* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_dlapmr_work( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, double* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_clapmr_work( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, + lapack_complex_float* x, lapack_int ldx, + lapack_int* k ); +lapack_int LAPACKE_zlapmr_work( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, + lapack_complex_double* x, lapack_int ldx, + lapack_int* k ); + +lapack_int LAPACKE_slapmt_work( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, float* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_dlapmt_work( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, double* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_clapmt_work( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, + lapack_complex_float* x, lapack_int ldx, + lapack_int* k ); +lapack_int LAPACKE_zlapmt_work( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, + lapack_complex_double* x, lapack_int ldx, + lapack_int* k ); + +lapack_int LAPACKE_slartgp_work( float f, float g, float* cs, float* sn, + float* r ); +lapack_int LAPACKE_dlartgp_work( double f, double g, double* cs, double* sn, + double* r ); + +lapack_int LAPACKE_slartgs_work( float x, float y, float sigma, float* cs, + float* sn ); +lapack_int LAPACKE_dlartgs_work( double x, double y, double sigma, double* cs, + double* sn ); + +float LAPACKE_slapy2_work( float x, float y ); +double LAPACKE_dlapy2_work( double x, double y ); + +float LAPACKE_slapy3_work( float x, float y, float z ); +double LAPACKE_dlapy3_work( double x, double y, double z ); + +float LAPACKE_slamch_work( char cmach ); +double LAPACKE_dlamch_work( char cmach ); + +float LAPACKE_slange_work( int matrix_layout, char norm, lapack_int m, + lapack_int n, const float* a, lapack_int lda, + float* work ); +double LAPACKE_dlange_work( int matrix_layout, char norm, lapack_int m, + lapack_int n, const double* a, lapack_int lda, + double* work ); +float LAPACKE_clange_work( int matrix_layout, char norm, lapack_int m, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, float* work ); +double LAPACKE_zlange_work( int matrix_layout, char norm, lapack_int m, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, double* work ); + +float LAPACKE_clanhe_work( int matrix_layout, char norm, char uplo, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, float* work ); +double LAPACKE_zlanhe_work( int matrix_layout, char norm, char uplo, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, double* work ); + +float LAPACKE_slansy_work( int matrix_layout, char norm, char uplo, + lapack_int n, const float* a, lapack_int lda, + float* work ); +double LAPACKE_dlansy_work( int matrix_layout, char norm, char uplo, + lapack_int n, const double* a, lapack_int lda, + double* work ); +float LAPACKE_clansy_work( int matrix_layout, char norm, char uplo, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, float* work ); +double LAPACKE_zlansy_work( int matrix_layout, char norm, char uplo, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, double* work ); + +float LAPACKE_slantr_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int m, lapack_int n, const float* a, + lapack_int lda, float* work ); +double LAPACKE_dlantr_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int m, lapack_int n, + const double* a, lapack_int lda, double* work ); +float LAPACKE_clantr_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* work ); +double LAPACKE_zlantr_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* work ); + +lapack_int LAPACKE_slarfb_work( int matrix_layout, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, const float* v, + lapack_int ldv, const float* t, lapack_int ldt, + float* c, lapack_int ldc, float* work, + lapack_int ldwork ); +lapack_int LAPACKE_dlarfb_work( int matrix_layout, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, const double* v, + lapack_int ldv, const double* t, lapack_int ldt, + double* c, lapack_int ldc, double* work, + lapack_int ldwork ); +lapack_int LAPACKE_clarfb_work( int matrix_layout, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int ldwork ); +lapack_int LAPACKE_zlarfb_work( int matrix_layout, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, + lapack_int ldwork ); + +lapack_int LAPACKE_slarfg_work( lapack_int n, float* alpha, float* x, + lapack_int incx, float* tau ); +lapack_int LAPACKE_dlarfg_work( lapack_int n, double* alpha, double* x, + lapack_int incx, double* tau ); +lapack_int LAPACKE_clarfg_work( lapack_int n, lapack_complex_float* alpha, + lapack_complex_float* x, lapack_int incx, + lapack_complex_float* tau ); +lapack_int LAPACKE_zlarfg_work( lapack_int n, lapack_complex_double* alpha, + lapack_complex_double* x, lapack_int incx, + lapack_complex_double* tau ); + +lapack_int LAPACKE_slarft_work( int matrix_layout, char direct, char storev, + lapack_int n, lapack_int k, const float* v, + lapack_int ldv, const float* tau, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dlarft_work( int matrix_layout, char direct, char storev, + lapack_int n, lapack_int k, const double* v, + lapack_int ldv, const double* tau, double* t, + lapack_int ldt ); +lapack_int LAPACKE_clarft_work( int matrix_layout, char direct, char storev, + lapack_int n, lapack_int k, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* tau, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zlarft_work( int matrix_layout, char direct, char storev, + lapack_int n, lapack_int k, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* tau, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_slarfx_work( int matrix_layout, char side, lapack_int m, + lapack_int n, const float* v, float tau, + float* c, lapack_int ldc, float* work ); +lapack_int LAPACKE_dlarfx_work( int matrix_layout, char side, lapack_int m, + lapack_int n, const double* v, double tau, + double* c, lapack_int ldc, double* work ); +lapack_int LAPACKE_clarfx_work( int matrix_layout, char side, lapack_int m, + lapack_int n, const lapack_complex_float* v, + lapack_complex_float tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work ); +lapack_int LAPACKE_zlarfx_work( int matrix_layout, char side, lapack_int m, + lapack_int n, const lapack_complex_double* v, + lapack_complex_double tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work ); + +lapack_int LAPACKE_slarnv_work( lapack_int idist, lapack_int* iseed, + lapack_int n, float* x ); +lapack_int LAPACKE_dlarnv_work( lapack_int idist, lapack_int* iseed, + lapack_int n, double* x ); +lapack_int LAPACKE_clarnv_work( lapack_int idist, lapack_int* iseed, + lapack_int n, lapack_complex_float* x ); +lapack_int LAPACKE_zlarnv_work( lapack_int idist, lapack_int* iseed, + lapack_int n, lapack_complex_double* x ); + + +lapack_int LAPACKE_slascl_work( int matrix_layout, char type, lapack_int kl, + lapack_int ku, float cfrom, float cto, + lapack_int m, lapack_int n, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlascl_work( int matrix_layout, char type, lapack_int kl, + lapack_int ku, double cfrom, double cto, + lapack_int m, lapack_int n, double* a, + lapack_int lda ); +lapack_int LAPACKE_clascl_work( int matrix_layout, char type, lapack_int kl, + lapack_int ku, float cfrom, float cto, + lapack_int m, lapack_int n, lapack_complex_float* a, + lapack_int lda ); +lapack_int LAPACKE_zlascl_work( int matrix_layout, char type, lapack_int kl, + lapack_int ku, double cfrom, double cto, + lapack_int m, lapack_int n, lapack_complex_double* a, + lapack_int lda ); + +lapack_int LAPACKE_slaset_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, float alpha, float beta, float* a, + lapack_int lda ); +lapack_int LAPACKE_dlaset_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, double alpha, double beta, + double* a, lapack_int lda ); +lapack_int LAPACKE_claset_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, lapack_complex_float alpha, + lapack_complex_float beta, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zlaset_work( int matrix_layout, char uplo, lapack_int m, + lapack_int n, lapack_complex_double alpha, + lapack_complex_double beta, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_slasrt_work( char id, lapack_int n, float* d ); +lapack_int LAPACKE_dlasrt_work( char id, lapack_int n, double* d ); + +lapack_int LAPACKE_slaswp_work( int matrix_layout, lapack_int n, float* a, + lapack_int lda, lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_dlaswp_work( int matrix_layout, lapack_int n, double* a, + lapack_int lda, lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_claswp_work( int matrix_layout, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); +lapack_int LAPACKE_zlaswp_work( int matrix_layout, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int k1, lapack_int k2, + const lapack_int* ipiv, lapack_int incx ); + +lapack_int LAPACKE_slatms_work( int matrix_layout, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, + float* d, lapack_int mode, float cond, + float dmax, lapack_int kl, lapack_int ku, + char pack, float* a, lapack_int lda, + float* work ); +lapack_int LAPACKE_dlatms_work( int matrix_layout, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, + double* d, lapack_int mode, double cond, + double dmax, lapack_int kl, lapack_int ku, + char pack, double* a, lapack_int lda, + double* work ); +lapack_int LAPACKE_clatms_work( int matrix_layout, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, + float* d, lapack_int mode, float cond, + float dmax, lapack_int kl, lapack_int ku, + char pack, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* work ); +lapack_int LAPACKE_zlatms_work( int matrix_layout, lapack_int m, lapack_int n, + char dist, lapack_int* iseed, char sym, + double* d, lapack_int mode, double cond, + double dmax, lapack_int kl, lapack_int ku, + char pack, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* work ); + +lapack_int LAPACKE_slauum_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda ); +lapack_int LAPACKE_dlauum_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda ); +lapack_int LAPACKE_clauum_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zlauum_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_sopgtr_work( int matrix_layout, char uplo, lapack_int n, + const float* ap, const float* tau, float* q, + lapack_int ldq, float* work ); +lapack_int LAPACKE_dopgtr_work( int matrix_layout, char uplo, lapack_int n, + const double* ap, const double* tau, double* q, + lapack_int ldq, double* work ); + +lapack_int LAPACKE_sopmtr_work( int matrix_layout, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const float* ap, const float* tau, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dopmtr_work( int matrix_layout, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const double* ap, const double* tau, double* c, + lapack_int ldc, double* work ); + +lapack_int LAPACKE_sorgbr_work( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int k, float* a, + lapack_int lda, const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorgbr_work( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int k, double* a, + lapack_int lda, const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorghr_work( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorghr_work( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorglq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorglq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorgql_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorgql_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorgqr_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorgqr_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorgrq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, float* a, lapack_int lda, + const float* tau, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dorgrq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, double* a, lapack_int lda, + const double* tau, double* work, + lapack_int lwork ); + +lapack_int LAPACKE_sorgtr_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda, const float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dorgtr_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, const double* tau, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormbr_work( int matrix_layout, char vect, char side, + char trans, lapack_int m, lapack_int n, + lapack_int k, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormbr_work( int matrix_layout, char vect, char side, + char trans, lapack_int m, lapack_int n, + lapack_int k, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormhr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormhr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormql_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormql_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormrq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormrq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormrz_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormrz_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_sormtr_work( int matrix_layout, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const float* a, lapack_int lda, + const float* tau, float* c, lapack_int ldc, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dormtr_work( int matrix_layout, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const double* a, lapack_int lda, + const double* tau, double* c, lapack_int ldc, + double* work, lapack_int lwork ); + +lapack_int LAPACKE_spbcon_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const float* ab, lapack_int ldab, + float anorm, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dpbcon_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const double* ab, + lapack_int ldab, double anorm, double* rcond, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cpbcon_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_float* ab, + lapack_int ldab, float anorm, float* rcond, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zpbcon_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_double* ab, + lapack_int ldab, double anorm, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spbequ_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const float* ab, lapack_int ldab, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_dpbequ_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const double* ab, + lapack_int ldab, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cpbequ_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_float* ab, + lapack_int ldab, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_zpbequ_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, const lapack_complex_double* ab, + lapack_int ldab, double* s, double* scond, + double* amax ); + +lapack_int LAPACKE_spbrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const float* ab, + lapack_int ldab, const float* afb, + lapack_int ldafb, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dpbrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const double* ab, lapack_int ldab, + const double* afb, lapack_int ldafb, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cpbrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + const lapack_complex_float* afb, + lapack_int ldafb, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zpbrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, + const lapack_complex_double* afb, + lapack_int ldafb, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spbstf_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kb, float* bb, lapack_int ldbb ); +lapack_int LAPACKE_dpbstf_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kb, double* bb, lapack_int ldbb ); +lapack_int LAPACKE_cpbstf_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kb, lapack_complex_float* bb, + lapack_int ldbb ); +lapack_int LAPACKE_zpbstf_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kb, lapack_complex_double* bb, + lapack_int ldbb ); + +lapack_int LAPACKE_spbsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dpbsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, double* ab, + lapack_int ldab, double* b, lapack_int ldb ); +lapack_int LAPACKE_cpbsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpbsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spbsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int kd, lapack_int nrhs, + float* ab, lapack_int ldab, float* afb, + lapack_int ldafb, char* equed, float* s, + float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dpbsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int kd, lapack_int nrhs, + double* ab, lapack_int ldab, double* afb, + lapack_int ldafb, char* equed, double* s, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, double* work, lapack_int* iwork ); +lapack_int LAPACKE_cpbsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int kd, lapack_int nrhs, + lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* afb, lapack_int ldafb, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zpbsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int kd, lapack_int nrhs, + lapack_complex_double* ab, lapack_int ldab, + lapack_complex_double* afb, lapack_int ldafb, + char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spbtrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, float* ab, lapack_int ldab ); +lapack_int LAPACKE_dpbtrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, double* ab, lapack_int ldab ); +lapack_int LAPACKE_cpbtrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_complex_float* ab, + lapack_int ldab ); +lapack_int LAPACKE_zpbtrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_complex_double* ab, + lapack_int ldab ); + +lapack_int LAPACKE_spbtrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, const float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dpbtrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const double* ab, lapack_int ldab, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpbtrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_float* ab, lapack_int ldab, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpbtrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_spftrf_work( int matrix_layout, char transr, char uplo, + lapack_int n, float* a ); +lapack_int LAPACKE_dpftrf_work( int matrix_layout, char transr, char uplo, + lapack_int n, double* a ); +lapack_int LAPACKE_cpftrf_work( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_zpftrf_work( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_spftri_work( int matrix_layout, char transr, char uplo, + lapack_int n, float* a ); +lapack_int LAPACKE_dpftri_work( int matrix_layout, char transr, char uplo, + lapack_int n, double* a ); +lapack_int LAPACKE_cpftri_work( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_complex_float* a ); +lapack_int LAPACKE_zpftri_work( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_complex_double* a ); + +lapack_int LAPACKE_spftrs_work( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_int nrhs, const float* a, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dpftrs_work( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_int nrhs, const double* a, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cpftrs_work( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpftrs_work( int matrix_layout, char transr, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spocon_work( int matrix_layout, char uplo, lapack_int n, + const float* a, lapack_int lda, float anorm, + float* rcond, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dpocon_work( int matrix_layout, char uplo, lapack_int n, + const double* a, lapack_int lda, double anorm, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cpocon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float anorm, float* rcond, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zpocon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double anorm, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spoequ_work( int matrix_layout, lapack_int n, const float* a, + lapack_int lda, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dpoequ_work( int matrix_layout, lapack_int n, const double* a, + lapack_int lda, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cpoequ_work( int matrix_layout, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zpoequ_work( int matrix_layout, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_spoequb_work( int matrix_layout, lapack_int n, const float* a, + lapack_int lda, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dpoequb_work( int matrix_layout, lapack_int n, + const double* a, lapack_int lda, double* s, + double* scond, double* amax ); +lapack_int LAPACKE_cpoequb_work( int matrix_layout, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax ); +lapack_int LAPACKE_zpoequb_work( int matrix_layout, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax ); + +lapack_int LAPACKE_sporfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dporfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cporfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zporfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sporfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, + lapack_int ldaf, const float* s, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dporfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const double* s, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cporfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, + lapack_int ldaf, const float* s, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zporfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, + lapack_int ldaf, const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sposv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dposv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cposv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zposv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); +lapack_int LAPACKE_dsposv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* work, float* swork, + lapack_int* iter ); +lapack_int LAPACKE_zcposv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, lapack_complex_double* work, + lapack_complex_float* swork, double* rwork, + lapack_int* iter ); + +lapack_int LAPACKE_sposvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + char* equed, float* s, float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dposvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + char* equed, double* s, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cposvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zposvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sposvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + char* equed, float* s, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dposvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + char* equed, double* s, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cposvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + char* equed, float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zposvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_spotrf2_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda ); +lapack_int LAPACKE_dpotrf2_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda ); +lapack_int LAPACKE_cpotrf2_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotrf2_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotrf_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda ); +lapack_int LAPACKE_dpotrf_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda ); +lapack_int LAPACKE_cpotrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotri_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda ); +lapack_int LAPACKE_dpotri_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda ); +lapack_int LAPACKE_cpotri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zpotri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_spotrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dpotrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, double* b, lapack_int ldb ); +lapack_int LAPACKE_cpotrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zpotrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sppcon_work( int matrix_layout, char uplo, lapack_int n, + const float* ap, float anorm, float* rcond, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dppcon_work( int matrix_layout, char uplo, lapack_int n, + const double* ap, double anorm, double* rcond, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cppcon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, float anorm, + float* rcond, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zppcon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, double anorm, + double* rcond, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_sppequ_work( int matrix_layout, char uplo, lapack_int n, + const float* ap, float* s, float* scond, + float* amax ); +lapack_int LAPACKE_dppequ_work( int matrix_layout, char uplo, lapack_int n, + const double* ap, double* s, double* scond, + double* amax ); +lapack_int LAPACKE_cppequ_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, float* s, + float* scond, float* amax ); +lapack_int LAPACKE_zppequ_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, double* s, + double* scond, double* amax ); + +lapack_int LAPACKE_spprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, + const float* afp, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dpprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, + const double* afp, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cpprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zpprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sppsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* ap, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dppsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* ap, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cppsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zppsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sppsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* ap, + float* afp, char* equed, float* s, float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dppsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* ap, + double* afp, char* equed, double* s, double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cppsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* ap, + lapack_complex_float* afp, char* equed, + float* s, lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zppsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* ap, + lapack_complex_double* afp, char* equed, + double* s, lapack_complex_double* b, + lapack_int ldb, lapack_complex_double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_spptrf_work( int matrix_layout, char uplo, lapack_int n, + float* ap ); +lapack_int LAPACKE_dpptrf_work( int matrix_layout, char uplo, lapack_int n, + double* ap ); +lapack_int LAPACKE_cpptrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_zpptrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_spptri_work( int matrix_layout, char uplo, lapack_int n, + float* ap ); +lapack_int LAPACKE_dpptri_work( int matrix_layout, char uplo, lapack_int n, + double* ap ); +lapack_int LAPACKE_cpptri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap ); +lapack_int LAPACKE_zpptri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap ); + +lapack_int LAPACKE_spptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dpptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_spstrf_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda, lapack_int* piv, + lapack_int* rank, float tol, float* work ); +lapack_int LAPACKE_dpstrf_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, lapack_int* piv, + lapack_int* rank, double tol, double* work ); +lapack_int LAPACKE_cpstrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* piv, lapack_int* rank, float tol, + float* work ); +lapack_int LAPACKE_zpstrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* piv, lapack_int* rank, double tol, + double* work ); + +lapack_int LAPACKE_sptcon_work( lapack_int n, const float* d, const float* e, + float anorm, float* rcond, float* work ); +lapack_int LAPACKE_dptcon_work( lapack_int n, const double* d, const double* e, + double anorm, double* rcond, double* work ); +lapack_int LAPACKE_cptcon_work( lapack_int n, const float* d, + const lapack_complex_float* e, float anorm, + float* rcond, float* work ); +lapack_int LAPACKE_zptcon_work( lapack_int n, const double* d, + const lapack_complex_double* e, double anorm, + double* rcond, double* work ); + +lapack_int LAPACKE_spteqr_work( int matrix_layout, char compz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work ); +lapack_int LAPACKE_dpteqr_work( int matrix_layout, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work ); +lapack_int LAPACKE_cpteqr_work( int matrix_layout, char compz, lapack_int n, + float* d, float* e, lapack_complex_float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_zpteqr_work( int matrix_layout, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_sptrfs_work( int matrix_layout, lapack_int n, lapack_int nrhs, + const float* d, const float* e, const float* df, + const float* ef, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* ferr, + float* berr, float* work ); +lapack_int LAPACKE_dptrfs_work( int matrix_layout, lapack_int n, lapack_int nrhs, + const double* d, const double* e, + const double* df, const double* ef, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work ); +lapack_int LAPACKE_cptrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, const float* df, + const lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zptrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, + const double* df, + const lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sptsv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + float* d, float* e, float* b, lapack_int ldb ); +lapack_int LAPACKE_dptsv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + double* d, double* e, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cptsv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + float* d, lapack_complex_float* e, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zptsv_work( int matrix_layout, lapack_int n, lapack_int nrhs, + double* d, lapack_complex_double* e, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sptsvx_work( int matrix_layout, char fact, lapack_int n, + lapack_int nrhs, const float* d, const float* e, + float* df, float* ef, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work ); +lapack_int LAPACKE_dptsvx_work( int matrix_layout, char fact, lapack_int n, + lapack_int nrhs, const double* d, + const double* e, double* df, double* ef, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* ferr, + double* berr, double* work ); +lapack_int LAPACKE_cptsvx_work( int matrix_layout, char fact, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, float* df, + lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zptsvx_work( int matrix_layout, char fact, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, double* df, + lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_spttrf_work( lapack_int n, float* d, float* e ); +lapack_int LAPACKE_dpttrf_work( lapack_int n, double* d, double* e ); +lapack_int LAPACKE_cpttrf_work( lapack_int n, float* d, + lapack_complex_float* e ); +lapack_int LAPACKE_zpttrf_work( lapack_int n, double* d, + lapack_complex_double* e ); + +lapack_int LAPACKE_spttrs_work( int matrix_layout, lapack_int n, lapack_int nrhs, + const float* d, const float* e, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dpttrs_work( int matrix_layout, lapack_int n, lapack_int nrhs, + const double* d, const double* e, double* b, + lapack_int ldb ); +lapack_int LAPACKE_cpttrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* d, + const lapack_complex_float* e, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zpttrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* d, + const lapack_complex_double* e, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssbev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int kd, float* ab, + lapack_int ldab, float* w, float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_dsbev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int kd, double* ab, + lapack_int ldab, double* w, double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_ssbevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int kd, float* ab, + lapack_int ldab, float* w, float* z, + lapack_int ldz, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dsbevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int kd, double* ab, + lapack_int ldab, double* w, double* z, + lapack_int ldz, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssbevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, lapack_int kd, + float* ab, lapack_int ldab, float* q, + lapack_int ldq, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dsbevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, lapack_int kd, + double* ab, lapack_int ldab, double* q, + lapack_int ldq, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, + lapack_int ldz, double* work, lapack_int* iwork, + lapack_int* ifail ); + +lapack_int LAPACKE_ssbgst_work( int matrix_layout, char vect, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + float* ab, lapack_int ldab, const float* bb, + lapack_int ldbb, float* x, lapack_int ldx, + float* work ); +lapack_int LAPACKE_dsbgst_work( int matrix_layout, char vect, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + double* ab, lapack_int ldab, const double* bb, + lapack_int ldbb, double* x, lapack_int ldx, + double* work ); + +lapack_int LAPACKE_ssbgv_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + float* ab, lapack_int ldab, float* bb, + lapack_int ldbb, float* w, float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_dsbgv_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + double* ab, lapack_int ldab, double* bb, + lapack_int ldbb, double* w, double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_ssbgvd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + float* ab, lapack_int ldab, float* bb, + lapack_int ldbb, float* w, float* z, + lapack_int ldz, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dsbgvd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, lapack_int ka, lapack_int kb, + double* ab, lapack_int ldab, double* bb, + lapack_int ldbb, double* w, double* z, + lapack_int ldz, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssbgvx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, lapack_int ka, + lapack_int kb, float* ab, lapack_int ldab, + float* bb, lapack_int ldbb, float* q, + lapack_int ldq, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dsbgvx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, lapack_int ka, + lapack_int kb, double* ab, lapack_int ldab, + double* bb, lapack_int ldbb, double* q, + lapack_int ldq, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, + lapack_int ldz, double* work, lapack_int* iwork, + lapack_int* ifail ); + +lapack_int LAPACKE_ssbtrd_work( int matrix_layout, char vect, char uplo, + lapack_int n, lapack_int kd, float* ab, + lapack_int ldab, float* d, float* e, float* q, + lapack_int ldq, float* work ); +lapack_int LAPACKE_dsbtrd_work( int matrix_layout, char vect, char uplo, + lapack_int n, lapack_int kd, double* ab, + lapack_int ldab, double* d, double* e, + double* q, lapack_int ldq, double* work ); + +lapack_int LAPACKE_ssfrk_work( int matrix_layout, char transr, char uplo, + char trans, lapack_int n, lapack_int k, + float alpha, const float* a, lapack_int lda, + float beta, float* c ); +lapack_int LAPACKE_dsfrk_work( int matrix_layout, char transr, char uplo, + char trans, lapack_int n, lapack_int k, + double alpha, const double* a, lapack_int lda, + double beta, double* c ); + +lapack_int LAPACKE_sspcon_work( int matrix_layout, char uplo, lapack_int n, + const float* ap, const lapack_int* ipiv, + float anorm, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dspcon_work( int matrix_layout, char uplo, lapack_int n, + const double* ap, const lapack_int* ipiv, + double anorm, double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_cspcon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zspcon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_sspev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, float* ap, float* w, float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_dspev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, double* ap, double* w, double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_sspevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, float* ap, float* w, float* z, + lapack_int ldz, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dspevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, double* ap, double* w, double* z, + lapack_int ldz, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_sspevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, float* ap, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dspevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, double* ap, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + double* z, lapack_int ldz, double* work, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_sspgst_work( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, float* ap, const float* bp ); +lapack_int LAPACKE_dspgst_work( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, double* ap, const double* bp ); + +lapack_int LAPACKE_sspgv_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, float* ap, float* bp, + float* w, float* z, lapack_int ldz, + float* work ); +lapack_int LAPACKE_dspgv_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, double* ap, double* bp, + double* w, double* z, lapack_int ldz, + double* work ); + +lapack_int LAPACKE_sspgvd_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, float* ap, float* bp, + float* w, float* z, lapack_int ldz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dspgvd_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, double* ap, double* bp, + double* w, double* z, lapack_int ldz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_sspgvx_work( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, float* ap, + float* bp, float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, float* z, lapack_int ldz, float* work, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_dspgvx_work( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, double* ap, + double* bp, double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, double* z, lapack_int ldz, + double* work, lapack_int* iwork, + lapack_int* ifail ); + +lapack_int LAPACKE_ssprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, + const float* afp, const lapack_int* ipiv, + const float* b, lapack_int ldb, float* x, + lapack_int ldx, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dsprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, + const double* afp, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_csprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zsprfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_sspsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* ap, lapack_int* ipiv, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dspsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* ap, lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_cspsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* ap, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zspsv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* ap, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_sspsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, const float* ap, + float* afp, lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dspsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, const double* ap, + double* afp, lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_cspsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + lapack_complex_float* afp, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zspsvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* afp, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_ssptrd_work( int matrix_layout, char uplo, lapack_int n, + float* ap, float* d, float* e, float* tau ); +lapack_int LAPACKE_dsptrd_work( int matrix_layout, char uplo, lapack_int n, + double* ap, double* d, double* e, double* tau ); + +lapack_int LAPACKE_ssptrf_work( int matrix_layout, char uplo, lapack_int n, + float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_dsptrf_work( int matrix_layout, char uplo, lapack_int n, + double* ap, lapack_int* ipiv ); +lapack_int LAPACKE_csptrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, lapack_int* ipiv ); +lapack_int LAPACKE_zsptrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, lapack_int* ipiv ); + +lapack_int LAPACKE_ssptri_work( int matrix_layout, char uplo, lapack_int n, + float* ap, const lapack_int* ipiv, + float* work ); +lapack_int LAPACKE_dsptri_work( int matrix_layout, char uplo, lapack_int n, + double* ap, const lapack_int* ipiv, + double* work ); +lapack_int LAPACKE_csptri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* ap, + const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_zsptri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* ap, + const lapack_int* ipiv, + lapack_complex_double* work ); + +lapack_int LAPACKE_ssptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* ap, + const lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dsptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* ap, + const lapack_int* ipiv, double* b, + lapack_int ldb ); +lapack_int LAPACKE_csptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_zsptrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sstebz_work( char range, char order, lapack_int n, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, const float* d, const float* e, + lapack_int* m, lapack_int* nsplit, float* w, + lapack_int* iblock, lapack_int* isplit, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dstebz_work( char range, char order, lapack_int n, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, const double* d, const double* e, + lapack_int* m, lapack_int* nsplit, double* w, + lapack_int* iblock, lapack_int* isplit, + double* work, lapack_int* iwork ); + +lapack_int LAPACKE_sstedc_work( int matrix_layout, char compz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dstedc_work( int matrix_layout, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_cstedc_work( int matrix_layout, char compz, lapack_int n, + float* d, float* e, lapack_complex_float* z, + lapack_int ldz, lapack_complex_float* work, + lapack_int lwork, float* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zstedc_work( int matrix_layout, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz, lapack_complex_double* work, + lapack_int lwork, double* rwork, + lapack_int lrwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_sstegr_work( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, float* z, + lapack_int ldz, lapack_int* isuppz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dstegr_work( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + double* z, lapack_int ldz, lapack_int* isuppz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_cstegr_work( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int* isuppz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zstegr_work( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int* isuppz, double* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_sstein_work( int matrix_layout, lapack_int n, const float* d, + const float* e, lapack_int m, const float* w, + const lapack_int* iblock, + const lapack_int* isplit, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifailv ); +lapack_int LAPACKE_dstein_work( int matrix_layout, lapack_int n, const double* d, + const double* e, lapack_int m, const double* w, + const lapack_int* iblock, + const lapack_int* isplit, double* z, + lapack_int ldz, double* work, lapack_int* iwork, + lapack_int* ifailv ); +lapack_int LAPACKE_cstein_work( int matrix_layout, lapack_int n, const float* d, + const float* e, lapack_int m, const float* w, + const lapack_int* iblock, + const lapack_int* isplit, + lapack_complex_float* z, lapack_int ldz, + float* work, lapack_int* iwork, + lapack_int* ifailv ); +lapack_int LAPACKE_zstein_work( int matrix_layout, lapack_int n, const double* d, + const double* e, lapack_int m, const double* w, + const lapack_int* iblock, + const lapack_int* isplit, + lapack_complex_double* z, lapack_int ldz, + double* work, lapack_int* iwork, + lapack_int* ifailv ); + +lapack_int LAPACKE_sstemr_work( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + lapack_int* m, float* w, float* z, + lapack_int ldz, lapack_int nzc, + lapack_int* isuppz, lapack_logical* tryrac, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dstemr_work( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int nzc, + lapack_int* isuppz, lapack_logical* tryrac, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_cstemr_work( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + lapack_int* m, float* w, + lapack_complex_float* z, lapack_int ldz, + lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_zstemr_work( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + lapack_int* m, double* w, + lapack_complex_double* z, lapack_int ldz, + lapack_int nzc, lapack_int* isuppz, + lapack_logical* tryrac, double* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_ssteqr_work( int matrix_layout, char compz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work ); +lapack_int LAPACKE_dsteqr_work( int matrix_layout, char compz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work ); +lapack_int LAPACKE_csteqr_work( int matrix_layout, char compz, lapack_int n, + float* d, float* e, lapack_complex_float* z, + lapack_int ldz, float* work ); +lapack_int LAPACKE_zsteqr_work( int matrix_layout, char compz, lapack_int n, + double* d, double* e, lapack_complex_double* z, + lapack_int ldz, double* work ); + +lapack_int LAPACKE_ssterf_work( lapack_int n, float* d, float* e ); +lapack_int LAPACKE_dsterf_work( lapack_int n, double* d, double* e ); + +lapack_int LAPACKE_sstev_work( int matrix_layout, char jobz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work ); +lapack_int LAPACKE_dstev_work( int matrix_layout, char jobz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work ); + +lapack_int LAPACKE_sstevd_work( int matrix_layout, char jobz, lapack_int n, + float* d, float* e, float* z, lapack_int ldz, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dstevd_work( int matrix_layout, char jobz, lapack_int n, + double* d, double* e, double* z, lapack_int ldz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_sstevr_work( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, float* z, + lapack_int ldz, lapack_int* isuppz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dstevr_work( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + double* z, lapack_int ldz, lapack_int* isuppz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_sstevx_work( int matrix_layout, char jobz, char range, + lapack_int n, float* d, float* e, float vl, + float vu, lapack_int il, lapack_int iu, + float abstol, lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dstevx_work( int matrix_layout, char jobz, char range, + lapack_int n, double* d, double* e, double vl, + double vu, lapack_int il, lapack_int iu, + double abstol, lapack_int* m, double* w, + double* z, lapack_int ldz, double* work, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_ssycon_work( int matrix_layout, char uplo, lapack_int n, + const float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, + float* rcond, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dsycon_work( int matrix_layout, char uplo, lapack_int n, + const double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_csycon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, float anorm, + float* rcond, lapack_complex_float* work ); +lapack_int LAPACKE_zsycon_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, double anorm, + double* rcond, lapack_complex_double* work ); + +lapack_int LAPACKE_ssyequb_work( int matrix_layout, char uplo, lapack_int n, + const float* a, lapack_int lda, float* s, + float* scond, float* amax, float* work ); +lapack_int LAPACKE_dsyequb_work( int matrix_layout, char uplo, lapack_int n, + const double* a, lapack_int lda, double* s, + double* scond, double* amax, double* work ); +lapack_int LAPACKE_csyequb_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* s, float* scond, float* amax, + lapack_complex_float* work ); +lapack_int LAPACKE_zsyequb_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* s, double* scond, double* amax, + lapack_complex_double* work ); + +lapack_int LAPACKE_ssyev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, float* a, lapack_int lda, float* w, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsyev_work( int matrix_layout, char jobz, char uplo, + lapack_int n, double* a, lapack_int lda, + double* w, double* work, lapack_int lwork ); + +lapack_int LAPACKE_ssyevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, float* a, lapack_int lda, + float* w, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dsyevd_work( int matrix_layout, char jobz, char uplo, + lapack_int n, double* a, lapack_int lda, + double* w, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssyevr_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, float* a, + lapack_int lda, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, + lapack_int ldz, lapack_int* isuppz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dsyevr_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, double* a, + lapack_int lda, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, + lapack_int ldz, lapack_int* isuppz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssyevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, float* a, + lapack_int lda, float vl, float vu, + lapack_int il, lapack_int iu, float abstol, + lapack_int* m, float* w, float* z, + lapack_int ldz, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int* ifail ); +lapack_int LAPACKE_dsyevx_work( int matrix_layout, char jobz, char range, + char uplo, lapack_int n, double* a, + lapack_int lda, double vl, double vu, + lapack_int il, lapack_int iu, double abstol, + lapack_int* m, double* w, double* z, + lapack_int ldz, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_ssygst_work( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, float* a, lapack_int lda, + const float* b, lapack_int ldb ); +lapack_int LAPACKE_dsygst_work( int matrix_layout, lapack_int itype, char uplo, + lapack_int n, double* a, lapack_int lda, + const double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssygv_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* w, float* work, lapack_int lwork ); +lapack_int LAPACKE_dsygv_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* w, double* work, lapack_int lwork ); + +lapack_int LAPACKE_ssygvd_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* w, float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dsygvd_work( int matrix_layout, lapack_int itype, char jobz, + char uplo, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* w, double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); + +lapack_int LAPACKE_ssygvx_work( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float vl, float vu, lapack_int il, + lapack_int iu, float abstol, lapack_int* m, + float* w, float* z, lapack_int ldz, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int* ifail ); +lapack_int LAPACKE_dsygvx_work( int matrix_layout, lapack_int itype, char jobz, + char range, char uplo, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double vl, double vu, lapack_int il, + lapack_int iu, double abstol, lapack_int* m, + double* w, double* z, lapack_int ldz, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int* ifail ); + +lapack_int LAPACKE_ssyrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const float* af, lapack_int ldaf, + const lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dsyrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* b, lapack_int ldb, double* x, + lapack_int ldx, double* ferr, double* berr, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_csyrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_zsyrfs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_ssyrfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, const float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* s, const float* b, lapack_int ldb, + float* x, lapack_int ldx, float* rcond, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dsyrfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, const double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* s, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_csyrfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* af, + lapack_int ldaf, const lapack_int* ipiv, + const float* s, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zsyrfsx_work( int matrix_layout, char uplo, char equed, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* af, + lapack_int ldaf, const lapack_int* ipiv, + const double* s, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_ssysv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + lapack_int* ipiv, float* b, lapack_int ldb, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsysv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + lapack_int* ipiv, double* b, lapack_int ldb, + double* work, lapack_int lwork ); +lapack_int LAPACKE_csysv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zsysv_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_ssysvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, const float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, const float* b, + lapack_int ldb, float* x, lapack_int ldx, + float* rcond, float* ferr, float* berr, + float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dsysvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, const double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, const double* b, + lapack_int ldb, double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_csysvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int ldb, lapack_complex_float* x, + lapack_int ldx, float* rcond, float* ferr, + float* berr, lapack_complex_float* work, + lapack_int lwork, float* rwork ); +lapack_int LAPACKE_zsysvx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, lapack_int lwork, + double* rwork ); + +lapack_int LAPACKE_ssysvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, float* a, + lapack_int lda, float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + float* b, lapack_int ldb, float* x, + lapack_int ldx, float* rcond, float* rpvgrw, + float* berr, lapack_int n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int nparams, float* params, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dsysvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, double* a, + lapack_int lda, double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + double* b, lapack_int ldb, double* x, + lapack_int ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int nparams, double* params, + double* work, lapack_int* iwork ); +lapack_int LAPACKE_csysvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* x, lapack_int ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int nparams, + float* params, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_zsysvxx_work( int matrix_layout, char fact, char uplo, + lapack_int n, lapack_int nrhs, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* af, lapack_int ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* x, lapack_int ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int nparams, + double* params, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_ssytrd_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda, float* d, float* e, + float* tau, float* work, lapack_int lwork ); +lapack_int LAPACKE_dsytrd_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, double* d, double* e, + double* tau, double* work, lapack_int lwork ); + +lapack_int LAPACKE_ssytrf_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsytrf_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv, + double* work, lapack_int lwork ); +lapack_int LAPACKE_csytrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* work, + lapack_int lwork ); +lapack_int LAPACKE_zsytrf_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_ssytri_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda, + const lapack_int* ipiv, float* work ); +lapack_int LAPACKE_dsytri_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, + const lapack_int* ipiv, double* work ); +lapack_int LAPACKE_csytri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_zsytri_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work ); + +lapack_int LAPACKE_ssytrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dsytrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_csytrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsytrs_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stbcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, lapack_int kd, + const float* ab, lapack_int ldab, float* rcond, + float* work, lapack_int* iwork ); +lapack_int LAPACKE_dtbcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, lapack_int kd, + const double* ab, lapack_int ldab, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctbcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, lapack_int kd, + const lapack_complex_float* ab, lapack_int ldab, + float* rcond, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_ztbcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, lapack_int kd, + const lapack_complex_double* ab, + lapack_int ldab, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stbrfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const float* ab, + lapack_int ldab, const float* b, lapack_int ldb, + const float* x, lapack_int ldx, float* ferr, + float* berr, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dtbrfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const double* ab, + lapack_int ldab, const double* b, + lapack_int ldb, const double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctbrfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const lapack_complex_float* ab, + lapack_int ldab, const lapack_complex_float* b, + lapack_int ldb, const lapack_complex_float* x, + lapack_int ldx, float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztbrfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, const lapack_complex_double* b, + lapack_int ldb, const lapack_complex_double* x, + lapack_int ldx, double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stbtrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const float* ab, + lapack_int ldab, float* b, lapack_int ldb ); +lapack_int LAPACKE_dtbtrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const double* ab, + lapack_int ldab, double* b, lapack_int ldb ); +lapack_int LAPACKE_ctbtrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, const lapack_complex_float* ab, + lapack_int ldab, lapack_complex_float* b, + lapack_int ldb ); +lapack_int LAPACKE_ztbtrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int kd, + lapack_int nrhs, + const lapack_complex_double* ab, + lapack_int ldab, lapack_complex_double* b, + lapack_int ldb ); + +lapack_int LAPACKE_stfsm_work( int matrix_layout, char transr, char side, + char uplo, char trans, char diag, lapack_int m, + lapack_int n, float alpha, const float* a, + float* b, lapack_int ldb ); +lapack_int LAPACKE_dtfsm_work( int matrix_layout, char transr, char side, + char uplo, char trans, char diag, lapack_int m, + lapack_int n, double alpha, const double* a, + double* b, lapack_int ldb ); +lapack_int LAPACKE_ctfsm_work( int matrix_layout, char transr, char side, + char uplo, char trans, char diag, lapack_int m, + lapack_int n, lapack_complex_float alpha, + const lapack_complex_float* a, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztfsm_work( int matrix_layout, char transr, char side, + char uplo, char trans, char diag, lapack_int m, + lapack_int n, lapack_complex_double alpha, + const lapack_complex_double* a, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stftri_work( int matrix_layout, char transr, char uplo, + char diag, lapack_int n, float* a ); +lapack_int LAPACKE_dtftri_work( int matrix_layout, char transr, char uplo, + char diag, lapack_int n, double* a ); +lapack_int LAPACKE_ctftri_work( int matrix_layout, char transr, char uplo, + char diag, lapack_int n, + lapack_complex_float* a ); +lapack_int LAPACKE_ztftri_work( int matrix_layout, char transr, char uplo, + char diag, lapack_int n, + lapack_complex_double* a ); + +lapack_int LAPACKE_stfttp_work( int matrix_layout, char transr, char uplo, + lapack_int n, const float* arf, float* ap ); +lapack_int LAPACKE_dtfttp_work( int matrix_layout, char transr, char uplo, + lapack_int n, const double* arf, double* ap ); +lapack_int LAPACKE_ctfttp_work( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_float* arf, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztfttp_work( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_double* arf, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stfttr_work( int matrix_layout, char transr, char uplo, + lapack_int n, const float* arf, float* a, + lapack_int lda ); +lapack_int LAPACKE_dtfttr_work( int matrix_layout, char transr, char uplo, + lapack_int n, const double* arf, double* a, + lapack_int lda ); +lapack_int LAPACKE_ctfttr_work( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_float* arf, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztfttr_work( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_double* arf, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_stgevc_work( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + const float* s, lapack_int lds, const float* p, + lapack_int ldp, float* vl, lapack_int ldvl, + float* vr, lapack_int ldvr, lapack_int mm, + lapack_int* m, float* work ); +lapack_int LAPACKE_dtgevc_work( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + const double* s, lapack_int lds, + const double* p, lapack_int ldp, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, double* work ); +lapack_int LAPACKE_ctgevc_work( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* s, lapack_int lds, + const lapack_complex_float* p, lapack_int ldp, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztgevc_work( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* s, lapack_int lds, + const lapack_complex_double* p, lapack_int ldp, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stgexc_work( int matrix_layout, lapack_logical wantq, + lapack_logical wantz, lapack_int n, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* q, lapack_int ldq, float* z, + lapack_int ldz, lapack_int* ifst, + lapack_int* ilst, float* work, + lapack_int lwork ); +lapack_int LAPACKE_dtgexc_work( int matrix_layout, lapack_logical wantq, + lapack_logical wantz, lapack_int n, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* q, lapack_int ldq, double* z, + lapack_int ldz, lapack_int* ifst, + lapack_int* ilst, double* work, + lapack_int lwork ); +lapack_int LAPACKE_ctgexc_work( int matrix_layout, lapack_logical wantq, + lapack_logical wantz, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz, + lapack_int ifst, lapack_int ilst ); +lapack_int LAPACKE_ztgexc_work( int matrix_layout, lapack_logical wantq, + lapack_logical wantz, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_int ifst, lapack_int ilst ); + +lapack_int LAPACKE_stgsen_work( int matrix_layout, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + float* a, lapack_int lda, float* b, + lapack_int ldb, float* alphar, float* alphai, + float* beta, float* q, lapack_int ldq, float* z, + lapack_int ldz, lapack_int* m, float* pl, + float* pr, float* dif, float* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); +lapack_int LAPACKE_dtgsen_work( int matrix_layout, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + double* a, lapack_int lda, double* b, + lapack_int ldb, double* alphar, double* alphai, + double* beta, double* q, lapack_int ldq, + double* z, lapack_int ldz, lapack_int* m, + double* pl, double* pr, double* dif, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_ctgsen_work( int matrix_layout, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* alpha, + lapack_complex_float* beta, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* z, lapack_int ldz, + lapack_int* m, float* pl, float* pr, float* dif, + lapack_complex_float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_ztgsen_work( int matrix_layout, lapack_int ijob, + lapack_logical wantq, lapack_logical wantz, + const lapack_logical* select, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* alpha, + lapack_complex_double* beta, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* z, lapack_int ldz, + lapack_int* m, double* pl, double* pr, + double* dif, lapack_complex_double* work, + lapack_int lwork, lapack_int* iwork, + lapack_int liwork ); + +lapack_int LAPACKE_stgsja_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_int k, lapack_int l, + float* a, lapack_int lda, float* b, + lapack_int ldb, float tola, float tolb, + float* alpha, float* beta, float* u, + lapack_int ldu, float* v, lapack_int ldv, + float* q, lapack_int ldq, float* work, + lapack_int* ncycle ); +lapack_int LAPACKE_dtgsja_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_int k, lapack_int l, + double* a, lapack_int lda, double* b, + lapack_int ldb, double tola, double tolb, + double* alpha, double* beta, double* u, + lapack_int ldu, double* v, lapack_int ldv, + double* q, lapack_int ldq, double* work, + lapack_int* ncycle ); +lapack_int LAPACKE_ctgsja_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_int k, lapack_int l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + float tola, float tolb, float* alpha, + float* beta, lapack_complex_float* u, + lapack_int ldu, lapack_complex_float* v, + lapack_int ldv, lapack_complex_float* q, + lapack_int ldq, lapack_complex_float* work, + lapack_int* ncycle ); +lapack_int LAPACKE_ztgsja_work( int matrix_layout, char jobu, char jobv, + char jobq, lapack_int m, lapack_int p, + lapack_int n, lapack_int k, lapack_int l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + double tola, double tolb, double* alpha, + double* beta, lapack_complex_double* u, + lapack_int ldu, lapack_complex_double* v, + lapack_int ldv, lapack_complex_double* q, + lapack_int ldq, lapack_complex_double* work, + lapack_int* ncycle ); + +lapack_int LAPACKE_stgsna_work( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, const float* vl, + lapack_int ldvl, const float* vr, + lapack_int ldvr, float* s, float* dif, + lapack_int mm, lapack_int* m, float* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_dtgsna_work( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const double* a, lapack_int lda, + const double* b, lapack_int ldb, + const double* vl, lapack_int ldvl, + const double* vr, lapack_int ldvr, double* s, + double* dif, lapack_int mm, lapack_int* m, + double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_ctgsna_work( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* vl, lapack_int ldvl, + const lapack_complex_float* vr, lapack_int ldvr, + float* s, float* dif, lapack_int mm, + lapack_int* m, lapack_complex_float* work, + lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_ztgsna_work( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* vl, + lapack_int ldvl, + const lapack_complex_double* vr, + lapack_int ldvr, double* s, double* dif, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, lapack_int lwork, + lapack_int* iwork ); + +lapack_int LAPACKE_stgsyl_work( int matrix_layout, char trans, lapack_int ijob, + lapack_int m, lapack_int n, const float* a, + lapack_int lda, const float* b, lapack_int ldb, + float* c, lapack_int ldc, const float* d, + lapack_int ldd, const float* e, lapack_int lde, + float* f, lapack_int ldf, float* scale, + float* dif, float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dtgsyl_work( int matrix_layout, char trans, lapack_int ijob, + lapack_int m, lapack_int n, const double* a, + lapack_int lda, const double* b, lapack_int ldb, + double* c, lapack_int ldc, const double* d, + lapack_int ldd, const double* e, lapack_int lde, + double* f, lapack_int ldf, double* scale, + double* dif, double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_ctgsyl_work( int matrix_layout, char trans, lapack_int ijob, + lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* c, lapack_int ldc, + const lapack_complex_float* d, lapack_int ldd, + const lapack_complex_float* e, lapack_int lde, + lapack_complex_float* f, lapack_int ldf, + float* scale, float* dif, + lapack_complex_float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_ztgsyl_work( int matrix_layout, char trans, lapack_int ijob, + lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* c, lapack_int ldc, + const lapack_complex_double* d, lapack_int ldd, + const lapack_complex_double* e, lapack_int lde, + lapack_complex_double* f, lapack_int ldf, + double* scale, double* dif, + lapack_complex_double* work, lapack_int lwork, + lapack_int* iwork ); + +lapack_int LAPACKE_stpcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, const float* ap, + float* rcond, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dtpcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, const double* ap, + double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctpcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, + const lapack_complex_float* ap, float* rcond, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztpcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, + const lapack_complex_double* ap, double* rcond, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stprfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const float* ap, const float* b, lapack_int ldb, + const float* x, lapack_int ldx, float* ferr, + float* berr, float* work, lapack_int* iwork ); +lapack_int LAPACKE_dtprfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const double* ap, const double* b, + lapack_int ldb, const double* x, lapack_int ldx, + double* ferr, double* berr, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctprfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztprfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_stptri_work( int matrix_layout, char uplo, char diag, + lapack_int n, float* ap ); +lapack_int LAPACKE_dtptri_work( int matrix_layout, char uplo, char diag, + lapack_int n, double* ap ); +lapack_int LAPACKE_ctptri_work( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_complex_float* ap ); +lapack_int LAPACKE_ztptri_work( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_complex_double* ap ); + +lapack_int LAPACKE_stptrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const float* ap, float* b, lapack_int ldb ); +lapack_int LAPACKE_dtptrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const double* ap, double* b, lapack_int ldb ); +lapack_int LAPACKE_ctptrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztptrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stpttf_work( int matrix_layout, char transr, char uplo, + lapack_int n, const float* ap, float* arf ); +lapack_int LAPACKE_dtpttf_work( int matrix_layout, char transr, char uplo, + lapack_int n, const double* ap, double* arf ); +lapack_int LAPACKE_ctpttf_work( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_float* ap, + lapack_complex_float* arf ); +lapack_int LAPACKE_ztpttf_work( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_double* ap, + lapack_complex_double* arf ); + +lapack_int LAPACKE_stpttr_work( int matrix_layout, char uplo, lapack_int n, + const float* ap, float* a, lapack_int lda ); +lapack_int LAPACKE_dtpttr_work( int matrix_layout, char uplo, lapack_int n, + const double* ap, double* a, lapack_int lda ); +lapack_int LAPACKE_ctpttr_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_ztpttr_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_strcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, const float* a, + lapack_int lda, float* rcond, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dtrcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, const double* a, + lapack_int lda, double* rcond, double* work, + lapack_int* iwork ); +lapack_int LAPACKE_ctrcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + float* rcond, lapack_complex_float* work, + float* rwork ); +lapack_int LAPACKE_ztrcon_work( int matrix_layout, char norm, char uplo, + char diag, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + double* rcond, lapack_complex_double* work, + double* rwork ); + +lapack_int LAPACKE_strevc_work( int matrix_layout, char side, char howmny, + lapack_logical* select, lapack_int n, + const float* t, lapack_int ldt, float* vl, + lapack_int ldvl, float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, float* work ); +lapack_int LAPACKE_dtrevc_work( int matrix_layout, char side, char howmny, + lapack_logical* select, lapack_int n, + const double* t, lapack_int ldt, double* vl, + lapack_int ldvl, double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, double* work ); +lapack_int LAPACKE_ctrevc_work( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* vl, lapack_int ldvl, + lapack_complex_float* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztrevc_work( int matrix_layout, char side, char howmny, + const lapack_logical* select, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* vl, lapack_int ldvl, + lapack_complex_double* vr, lapack_int ldvr, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_strexc_work( int matrix_layout, char compq, lapack_int n, + float* t, lapack_int ldt, float* q, + lapack_int ldq, lapack_int* ifst, + lapack_int* ilst, float* work ); +lapack_int LAPACKE_dtrexc_work( int matrix_layout, char compq, lapack_int n, + double* t, lapack_int ldt, double* q, + lapack_int ldq, lapack_int* ifst, + lapack_int* ilst, double* work ); +lapack_int LAPACKE_ctrexc_work( int matrix_layout, char compq, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* q, lapack_int ldq, + lapack_int ifst, lapack_int ilst ); +lapack_int LAPACKE_ztrexc_work( int matrix_layout, char compq, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* q, lapack_int ldq, + lapack_int ifst, lapack_int ilst ); + +lapack_int LAPACKE_strrfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, const float* x, lapack_int ldx, + float* ferr, float* berr, float* work, + lapack_int* iwork ); +lapack_int LAPACKE_dtrrfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const double* a, lapack_int lda, + const double* b, lapack_int ldb, + const double* x, lapack_int ldx, double* ferr, + double* berr, double* work, lapack_int* iwork ); +lapack_int LAPACKE_ctrrfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + const lapack_complex_float* x, lapack_int ldx, + float* ferr, float* berr, + lapack_complex_float* work, float* rwork ); +lapack_int LAPACKE_ztrrfs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + const lapack_complex_double* x, lapack_int ldx, + double* ferr, double* berr, + lapack_complex_double* work, double* rwork ); + +lapack_int LAPACKE_strsen_work( int matrix_layout, char job, char compq, + const lapack_logical* select, lapack_int n, + float* t, lapack_int ldt, float* q, + lapack_int ldq, float* wr, float* wi, + lapack_int* m, float* s, float* sep, + float* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_dtrsen_work( int matrix_layout, char job, char compq, + const lapack_logical* select, lapack_int n, + double* t, lapack_int ldt, double* q, + lapack_int ldq, double* wr, double* wi, + lapack_int* m, double* s, double* sep, + double* work, lapack_int lwork, + lapack_int* iwork, lapack_int liwork ); +lapack_int LAPACKE_ctrsen_work( int matrix_layout, char job, char compq, + const lapack_logical* select, lapack_int n, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* w, lapack_int* m, + float* s, float* sep, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_ztrsen_work( int matrix_layout, char job, char compq, + const lapack_logical* select, lapack_int n, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* w, lapack_int* m, + double* s, double* sep, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_strsna_work( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const float* t, lapack_int ldt, const float* vl, + lapack_int ldvl, const float* vr, + lapack_int ldvr, float* s, float* sep, + lapack_int mm, lapack_int* m, float* work, + lapack_int ldwork, lapack_int* iwork ); +lapack_int LAPACKE_dtrsna_work( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const double* t, lapack_int ldt, + const double* vl, lapack_int ldvl, + const double* vr, lapack_int ldvr, double* s, + double* sep, lapack_int mm, lapack_int* m, + double* work, lapack_int ldwork, + lapack_int* iwork ); +lapack_int LAPACKE_ctrsna_work( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_float* t, lapack_int ldt, + const lapack_complex_float* vl, lapack_int ldvl, + const lapack_complex_float* vr, lapack_int ldvr, + float* s, float* sep, lapack_int mm, + lapack_int* m, lapack_complex_float* work, + lapack_int ldwork, float* rwork ); +lapack_int LAPACKE_ztrsna_work( int matrix_layout, char job, char howmny, + const lapack_logical* select, lapack_int n, + const lapack_complex_double* t, lapack_int ldt, + const lapack_complex_double* vl, + lapack_int ldvl, + const lapack_complex_double* vr, + lapack_int ldvr, double* s, double* sep, + lapack_int mm, lapack_int* m, + lapack_complex_double* work, lapack_int ldwork, + double* rwork ); + +lapack_int LAPACKE_strsyl_work( int matrix_layout, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const float* a, lapack_int lda, const float* b, + lapack_int ldb, float* c, lapack_int ldc, + float* scale ); +lapack_int LAPACKE_dtrsyl_work( int matrix_layout, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const double* a, lapack_int lda, + const double* b, lapack_int ldb, double* c, + lapack_int ldc, double* scale ); +lapack_int LAPACKE_ctrsyl_work( int matrix_layout, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* c, lapack_int ldc, + float* scale ); +lapack_int LAPACKE_ztrsyl_work( int matrix_layout, char trana, char tranb, + lapack_int isgn, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* c, lapack_int ldc, + double* scale ); + +lapack_int LAPACKE_strtri_work( int matrix_layout, char uplo, char diag, + lapack_int n, float* a, lapack_int lda ); +lapack_int LAPACKE_dtrtri_work( int matrix_layout, char uplo, char diag, + lapack_int n, double* a, lapack_int lda ); +lapack_int LAPACKE_ctrtri_work( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_complex_float* a, + lapack_int lda ); +lapack_int LAPACKE_ztrtri_work( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_complex_double* a, + lapack_int lda ); + +lapack_int LAPACKE_strtrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const float* a, lapack_int lda, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dtrtrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const double* a, lapack_int lda, double* b, + lapack_int ldb ); +lapack_int LAPACKE_ctrtrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztrtrs_work( int matrix_layout, char uplo, char trans, + char diag, lapack_int n, lapack_int nrhs, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_strttf_work( int matrix_layout, char transr, char uplo, + lapack_int n, const float* a, lapack_int lda, + float* arf ); +lapack_int LAPACKE_dtrttf_work( int matrix_layout, char transr, char uplo, + lapack_int n, const double* a, lapack_int lda, + double* arf ); +lapack_int LAPACKE_ctrttf_work( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_float* a, + lapack_int lda, lapack_complex_float* arf ); +lapack_int LAPACKE_ztrttf_work( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_double* a, + lapack_int lda, lapack_complex_double* arf ); + +lapack_int LAPACKE_strttp_work( int matrix_layout, char uplo, lapack_int n, + const float* a, lapack_int lda, float* ap ); +lapack_int LAPACKE_dtrttp_work( int matrix_layout, char uplo, lapack_int n, + const double* a, lapack_int lda, double* ap ); +lapack_int LAPACKE_ctrttp_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + lapack_complex_float* ap ); +lapack_int LAPACKE_ztrttp_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + lapack_complex_double* ap ); + +lapack_int LAPACKE_stzrzf_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* tau, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dtzrzf_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* tau, + double* work, lapack_int lwork ); +lapack_int LAPACKE_ctzrzf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_ztzrzf_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungbr_work( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int k, + lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungbr_work( int matrix_layout, char vect, lapack_int m, + lapack_int n, lapack_int k, + lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunghr_work( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunghr_work( int matrix_layout, lapack_int n, lapack_int ilo, + lapack_int ihi, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunglq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunglq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungql_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungql_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungqr_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungqr_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungrq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungrq_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int k, lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cungtr_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zungtr_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmbr_work( int matrix_layout, char vect, char side, + char trans, lapack_int m, lapack_int n, + lapack_int k, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmbr_work( int matrix_layout, char vect, char side, + char trans, lapack_int m, lapack_int n, + lapack_int k, const lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmhr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmhr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int ilo, + lapack_int ihi, const lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmlq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmql_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmql_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmqr_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmrq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmrq_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmrz_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const lapack_complex_float* a, + lapack_int lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmrz_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, const lapack_complex_double* a, + lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cunmtr_work( int matrix_layout, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const lapack_complex_float* a, lapack_int lda, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_zunmtr_work( int matrix_layout, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const lapack_complex_double* a, lapack_int lda, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work, lapack_int lwork ); + +lapack_int LAPACKE_cupgtr_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float* ap, + const lapack_complex_float* tau, + lapack_complex_float* q, lapack_int ldq, + lapack_complex_float* work ); +lapack_int LAPACKE_zupgtr_work( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double* ap, + const lapack_complex_double* tau, + lapack_complex_double* q, lapack_int ldq, + lapack_complex_double* work ); + +lapack_int LAPACKE_cupmtr_work( int matrix_layout, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const lapack_complex_float* ap, + const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int ldc, + lapack_complex_float* work ); +lapack_int LAPACKE_zupmtr_work( int matrix_layout, char side, char uplo, + char trans, lapack_int m, lapack_int n, + const lapack_complex_double* ap, + const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int ldc, + lapack_complex_double* work ); + +lapack_int LAPACKE_claghe( int matrix_layout, lapack_int n, lapack_int k, + const float* d, lapack_complex_float* a, + lapack_int lda, lapack_int* iseed ); +lapack_int LAPACKE_zlaghe( int matrix_layout, lapack_int n, lapack_int k, + const double* d, lapack_complex_double* a, + lapack_int lda, lapack_int* iseed ); + +lapack_int LAPACKE_slagsy( int matrix_layout, lapack_int n, lapack_int k, + const float* d, float* a, lapack_int lda, + lapack_int* iseed ); +lapack_int LAPACKE_dlagsy( int matrix_layout, lapack_int n, lapack_int k, + const double* d, double* a, lapack_int lda, + lapack_int* iseed ); +lapack_int LAPACKE_clagsy( int matrix_layout, lapack_int n, lapack_int k, + const float* d, lapack_complex_float* a, + lapack_int lda, lapack_int* iseed ); +lapack_int LAPACKE_zlagsy( int matrix_layout, lapack_int n, lapack_int k, + const double* d, lapack_complex_double* a, + lapack_int lda, lapack_int* iseed ); + +lapack_int LAPACKE_slapmr( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, float* x, lapack_int ldx, + lapack_int* k ); +lapack_int LAPACKE_dlapmr( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, double* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_clapmr( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, lapack_complex_float* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_zlapmr( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, lapack_complex_double* x, + lapack_int ldx, lapack_int* k ); + +lapack_int LAPACKE_slapmt( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, float* x, lapack_int ldx, + lapack_int* k ); +lapack_int LAPACKE_dlapmt( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, double* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_clapmt( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, lapack_complex_float* x, + lapack_int ldx, lapack_int* k ); +lapack_int LAPACKE_zlapmt( int matrix_layout, lapack_logical forwrd, + lapack_int m, lapack_int n, lapack_complex_double* x, + lapack_int ldx, lapack_int* k ); + +float LAPACKE_slapy2( float x, float y ); +double LAPACKE_dlapy2( double x, double y ); + +float LAPACKE_slapy3( float x, float y, float z ); +double LAPACKE_dlapy3( double x, double y, double z ); + +lapack_int LAPACKE_slartgp( float f, float g, float* cs, float* sn, float* r ); +lapack_int LAPACKE_dlartgp( double f, double g, double* cs, double* sn, + double* r ); + +lapack_int LAPACKE_slartgs( float x, float y, float sigma, float* cs, + float* sn ); +lapack_int LAPACKE_dlartgs( double x, double y, double sigma, double* cs, + double* sn ); + + +//LAPACK 3.3.0 +lapack_int LAPACKE_cbbcsd( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, lapack_int m, + lapack_int p, lapack_int q, float* theta, float* phi, + lapack_complex_float* u1, lapack_int ldu1, + lapack_complex_float* u2, lapack_int ldu2, + lapack_complex_float* v1t, lapack_int ldv1t, + lapack_complex_float* v2t, lapack_int ldv2t, + float* b11d, float* b11e, float* b12d, float* b12e, + float* b21d, float* b21e, float* b22d, float* b22e ); +lapack_int LAPACKE_cbbcsd_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + lapack_int m, lapack_int p, lapack_int q, + float* theta, float* phi, + lapack_complex_float* u1, lapack_int ldu1, + lapack_complex_float* u2, lapack_int ldu2, + lapack_complex_float* v1t, lapack_int ldv1t, + lapack_complex_float* v2t, lapack_int ldv2t, + float* b11d, float* b11e, float* b12d, + float* b12e, float* b21d, float* b21e, + float* b22d, float* b22e, float* rwork, + lapack_int lrwork ); +lapack_int LAPACKE_cheswapr( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_cheswapr_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_chetri2( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_chetri2_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_chetri2x( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, lapack_int nb ); +lapack_int LAPACKE_chetri2x_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int nb ); +lapack_int LAPACKE_chetrs2( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_chetrs2_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work ); +lapack_int LAPACKE_csyconv( int matrix_layout, char uplo, char way, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, lapack_complex_float* work ); +lapack_int LAPACKE_csyconv_work( int matrix_layout, char uplo, char way, + lapack_int n, lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* work ); +lapack_int LAPACKE_csyswapr( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_csyswapr_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_csytri2( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_csytri2_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_csytri2x( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, lapack_int nb ); +lapack_int LAPACKE_csytri2x_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int nb ); +lapack_int LAPACKE_csytrs2( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_csytrs2_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work ); +lapack_int LAPACKE_cunbdb( int matrix_layout, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_float* x11, lapack_int ldx11, + lapack_complex_float* x12, lapack_int ldx12, + lapack_complex_float* x21, lapack_int ldx21, + lapack_complex_float* x22, lapack_int ldx22, + float* theta, float* phi, + lapack_complex_float* taup1, + lapack_complex_float* taup2, + lapack_complex_float* tauq1, + lapack_complex_float* tauq2 ); +lapack_int LAPACKE_cunbdb_work( int matrix_layout, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_float* x11, lapack_int ldx11, + lapack_complex_float* x12, lapack_int ldx12, + lapack_complex_float* x21, lapack_int ldx21, + lapack_complex_float* x22, lapack_int ldx22, + float* theta, float* phi, + lapack_complex_float* taup1, + lapack_complex_float* taup2, + lapack_complex_float* tauq1, + lapack_complex_float* tauq2, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_cuncsd( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_float* x11, lapack_int ldx11, + lapack_complex_float* x12, lapack_int ldx12, + lapack_complex_float* x21, lapack_int ldx21, + lapack_complex_float* x22, lapack_int ldx22, + float* theta, lapack_complex_float* u1, + lapack_int ldu1, lapack_complex_float* u2, + lapack_int ldu2, lapack_complex_float* v1t, + lapack_int ldv1t, lapack_complex_float* v2t, + lapack_int ldv2t ); +lapack_int LAPACKE_cuncsd_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + char signs, lapack_int m, lapack_int p, + lapack_int q, lapack_complex_float* x11, + lapack_int ldx11, lapack_complex_float* x12, + lapack_int ldx12, lapack_complex_float* x21, + lapack_int ldx21, lapack_complex_float* x22, + lapack_int ldx22, float* theta, + lapack_complex_float* u1, lapack_int ldu1, + lapack_complex_float* u2, lapack_int ldu2, + lapack_complex_float* v1t, lapack_int ldv1t, + lapack_complex_float* v2t, lapack_int ldv2t, + lapack_complex_float* work, lapack_int lwork, + float* rwork, lapack_int lrwork, + lapack_int* iwork ); +lapack_int LAPACKE_cuncsd2by1( int matrix_layout, char jobu1, char jobu2, + char jobv1t, lapack_int m, lapack_int p, lapack_int q, + lapack_complex_float* x11, lapack_int ldx11, + lapack_complex_float* x21, lapack_int ldx21, + lapack_complex_float* theta, lapack_complex_float* u1, + lapack_int ldu1, lapack_complex_float* u2, + lapack_int ldu2, lapack_complex_float* v1t, lapack_int ldv1t ); +lapack_int LAPACKE_cuncsd2by1_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, lapack_int m, lapack_int p, + lapack_int q, lapack_complex_float* x11, lapack_int ldx11, + lapack_complex_float* x21, lapack_int ldx21, + lapack_complex_float* theta, lapack_complex_float* u1, + lapack_int ldu1, lapack_complex_float* u2, + lapack_int ldu2, lapack_complex_float* v1t, + lapack_int ldv1t, lapack_complex_float* work, + lapack_int lwork, float* rwork, lapack_int lrwork, + lapack_int* iwork ); +lapack_int LAPACKE_dbbcsd( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, lapack_int m, + lapack_int p, lapack_int q, double* theta, + double* phi, double* u1, lapack_int ldu1, double* u2, + lapack_int ldu2, double* v1t, lapack_int ldv1t, + double* v2t, lapack_int ldv2t, double* b11d, + double* b11e, double* b12d, double* b12e, + double* b21d, double* b21e, double* b22d, + double* b22e ); +lapack_int LAPACKE_dbbcsd_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + lapack_int m, lapack_int p, lapack_int q, + double* theta, double* phi, double* u1, + lapack_int ldu1, double* u2, lapack_int ldu2, + double* v1t, lapack_int ldv1t, double* v2t, + lapack_int ldv2t, double* b11d, double* b11e, + double* b12d, double* b12e, double* b21d, + double* b21e, double* b22d, double* b22e, + double* work, lapack_int lwork ); +lapack_int LAPACKE_dorbdb( int matrix_layout, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + double* x11, lapack_int ldx11, double* x12, + lapack_int ldx12, double* x21, lapack_int ldx21, + double* x22, lapack_int ldx22, double* theta, + double* phi, double* taup1, double* taup2, + double* tauq1, double* tauq2 ); +lapack_int LAPACKE_dorbdb_work( int matrix_layout, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + double* x11, lapack_int ldx11, double* x12, + lapack_int ldx12, double* x21, lapack_int ldx21, + double* x22, lapack_int ldx22, double* theta, + double* phi, double* taup1, double* taup2, + double* tauq1, double* tauq2, double* work, + lapack_int lwork ); +lapack_int LAPACKE_dorcsd( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + double* x11, lapack_int ldx11, double* x12, + lapack_int ldx12, double* x21, lapack_int ldx21, + double* x22, lapack_int ldx22, double* theta, + double* u1, lapack_int ldu1, double* u2, + lapack_int ldu2, double* v1t, lapack_int ldv1t, + double* v2t, lapack_int ldv2t ); +lapack_int LAPACKE_dorcsd_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + char signs, lapack_int m, lapack_int p, + lapack_int q, double* x11, lapack_int ldx11, + double* x12, lapack_int ldx12, double* x21, + lapack_int ldx21, double* x22, lapack_int ldx22, + double* theta, double* u1, lapack_int ldu1, + double* u2, lapack_int ldu2, double* v1t, + lapack_int ldv1t, double* v2t, lapack_int ldv2t, + double* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_dorcsd2by1( int matrix_layout, char jobu1, char jobu2, + char jobv1t, lapack_int m, lapack_int p, lapack_int q, + double* x11, lapack_int ldx11, double* x21, lapack_int ldx21, + double* theta, double* u1, lapack_int ldu1, double* u2, + lapack_int ldu2, double* v1t, lapack_int ldv1t); +lapack_int LAPACKE_dorcsd2by1_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, lapack_int m, lapack_int p, lapack_int q, + double* x11, lapack_int ldx11, double* x21, lapack_int ldx21, + double* theta, double* u1, lapack_int ldu1, double* u2, + lapack_int ldu2, double* v1t, lapack_int ldv1t, + double* work, lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_dsyconv( int matrix_layout, char uplo, char way, lapack_int n, + double* a, lapack_int lda, const lapack_int* ipiv, double* work); +lapack_int LAPACKE_dsyconv_work( int matrix_layout, char uplo, char way, + lapack_int n, double* a, lapack_int lda, + const lapack_int* ipiv, double* work ); +lapack_int LAPACKE_dsyswapr( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int i1, lapack_int i2 ); +lapack_int LAPACKE_dsyswapr_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int i1, lapack_int i2 ); +lapack_int LAPACKE_dsytri2( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_dsytri2_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int lwork ); +lapack_int LAPACKE_dsytri2x( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, const lapack_int* ipiv, + lapack_int nb ); +lapack_int LAPACKE_dsytri2x_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, + const lapack_int* ipiv, double* work, + lapack_int nb ); +lapack_int LAPACKE_dsytrs2( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_dsytrs2_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const lapack_int* ipiv, + double* b, lapack_int ldb, double* work ); +lapack_int LAPACKE_sbbcsd( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, lapack_int m, + lapack_int p, lapack_int q, float* theta, float* phi, + float* u1, lapack_int ldu1, float* u2, + lapack_int ldu2, float* v1t, lapack_int ldv1t, + float* v2t, lapack_int ldv2t, float* b11d, + float* b11e, float* b12d, float* b12e, float* b21d, + float* b21e, float* b22d, float* b22e ); +lapack_int LAPACKE_sbbcsd_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + lapack_int m, lapack_int p, lapack_int q, + float* theta, float* phi, float* u1, + lapack_int ldu1, float* u2, lapack_int ldu2, + float* v1t, lapack_int ldv1t, float* v2t, + lapack_int ldv2t, float* b11d, float* b11e, + float* b12d, float* b12e, float* b21d, + float* b21e, float* b22d, float* b22e, + float* work, lapack_int lwork ); +lapack_int LAPACKE_sorbdb( int matrix_layout, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, float* x11, + lapack_int ldx11, float* x12, lapack_int ldx12, + float* x21, lapack_int ldx21, float* x22, + lapack_int ldx22, float* theta, float* phi, + float* taup1, float* taup2, float* tauq1, + float* tauq2 ); +lapack_int LAPACKE_sorbdb_work( int matrix_layout, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + float* x11, lapack_int ldx11, float* x12, + lapack_int ldx12, float* x21, lapack_int ldx21, + float* x22, lapack_int ldx22, float* theta, + float* phi, float* taup1, float* taup2, + float* tauq1, float* tauq2, float* work, + lapack_int lwork ); +lapack_int LAPACKE_sorcsd( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, float* x11, + lapack_int ldx11, float* x12, lapack_int ldx12, + float* x21, lapack_int ldx21, float* x22, + lapack_int ldx22, float* theta, float* u1, + lapack_int ldu1, float* u2, lapack_int ldu2, + float* v1t, lapack_int ldv1t, float* v2t, + lapack_int ldv2t ); +lapack_int LAPACKE_sorcsd_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + char signs, lapack_int m, lapack_int p, + lapack_int q, float* x11, lapack_int ldx11, + float* x12, lapack_int ldx12, float* x21, + lapack_int ldx21, float* x22, lapack_int ldx22, + float* theta, float* u1, lapack_int ldu1, + float* u2, lapack_int ldu2, float* v1t, + lapack_int ldv1t, float* v2t, lapack_int ldv2t, + float* work, lapack_int lwork, + lapack_int* iwork ); +lapack_int LAPACKE_sorcsd2by1( int matrix_layout, char jobu1, char jobu2, + char jobv1t, lapack_int m, lapack_int p, lapack_int q, + float* x11, lapack_int ldx11, float* x21, lapack_int ldx21, + float* theta, float* u1, lapack_int ldu1, float* u2, + lapack_int ldu2, float* v1t, lapack_int ldv1t); +lapack_int LAPACKE_sorcsd2by1_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, lapack_int m, lapack_int p, lapack_int q, + float* x11, lapack_int ldx11, float* x21, lapack_int ldx21, + float* theta, float* u1, lapack_int ldu1, float* u2, + lapack_int ldu2, float* v1t, lapack_int ldv1t, + float* work, lapack_int lwork, lapack_int* iwork ); +lapack_int LAPACKE_ssyconv( int matrix_layout, char uplo, char way, lapack_int n, + float* a, lapack_int lda, const lapack_int* ipiv, float* work ); +lapack_int LAPACKE_ssyconv_work( int matrix_layout, char uplo, char way, + lapack_int n, float* a, lapack_int lda, + const lapack_int* ipiv, float* work ); +lapack_int LAPACKE_ssyswapr( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int i1, lapack_int i2 ); +lapack_int LAPACKE_ssyswapr_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int i1, lapack_int i2 ); +lapack_int LAPACKE_ssytri2( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda, const lapack_int* ipiv ); +lapack_int LAPACKE_ssytri2_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int lwork ); +lapack_int LAPACKE_ssytri2x( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda, const lapack_int* ipiv, + lapack_int nb ); +lapack_int LAPACKE_ssytri2x_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda, + const lapack_int* ipiv, float* work, + lapack_int nb ); +lapack_int LAPACKE_ssytrs2( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_ssytrs2_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, + lapack_int lda, const lapack_int* ipiv, + float* b, lapack_int ldb, float* work ); +lapack_int LAPACKE_zbbcsd( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, lapack_int m, + lapack_int p, lapack_int q, double* theta, + double* phi, lapack_complex_double* u1, + lapack_int ldu1, lapack_complex_double* u2, + lapack_int ldu2, lapack_complex_double* v1t, + lapack_int ldv1t, lapack_complex_double* v2t, + lapack_int ldv2t, double* b11d, double* b11e, + double* b12d, double* b12e, double* b21d, + double* b21e, double* b22d, double* b22e ); +lapack_int LAPACKE_zbbcsd_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + lapack_int m, lapack_int p, lapack_int q, + double* theta, double* phi, + lapack_complex_double* u1, lapack_int ldu1, + lapack_complex_double* u2, lapack_int ldu2, + lapack_complex_double* v1t, lapack_int ldv1t, + lapack_complex_double* v2t, lapack_int ldv2t, + double* b11d, double* b11e, double* b12d, + double* b12e, double* b21d, double* b21e, + double* b22d, double* b22e, double* rwork, + lapack_int lrwork ); +lapack_int LAPACKE_zheswapr( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_zheswapr_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_zhetri2( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zhetri2_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int lwork ); +lapack_int LAPACKE_zhetri2x( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, lapack_int nb ); +lapack_int LAPACKE_zhetri2x_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int nb ); +lapack_int LAPACKE_zhetrs2( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); +lapack_int LAPACKE_zhetrs2_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work ); +lapack_int LAPACKE_zsyconv( int matrix_layout, char uplo, char way, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, lapack_complex_double* work ); +lapack_int LAPACKE_zsyconv_work( int matrix_layout, char uplo, char way, + lapack_int n, lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* work ); +lapack_int LAPACKE_zsyswapr( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_zsyswapr_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int i1, + lapack_int i2 ); +lapack_int LAPACKE_zsytri2( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv ); +lapack_int LAPACKE_zsytri2_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int lwork ); +lapack_int LAPACKE_zsytri2x( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, lapack_int nb ); +lapack_int LAPACKE_zsytri2x_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int nb ); +lapack_int LAPACKE_zsytrs2( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); +lapack_int LAPACKE_zsytrs2_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work ); +lapack_int LAPACKE_zunbdb( int matrix_layout, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_double* x11, lapack_int ldx11, + lapack_complex_double* x12, lapack_int ldx12, + lapack_complex_double* x21, lapack_int ldx21, + lapack_complex_double* x22, lapack_int ldx22, + double* theta, double* phi, + lapack_complex_double* taup1, + lapack_complex_double* taup2, + lapack_complex_double* tauq1, + lapack_complex_double* tauq2 ); +lapack_int LAPACKE_zunbdb_work( int matrix_layout, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_double* x11, lapack_int ldx11, + lapack_complex_double* x12, lapack_int ldx12, + lapack_complex_double* x21, lapack_int ldx21, + lapack_complex_double* x22, lapack_int ldx22, + double* theta, double* phi, + lapack_complex_double* taup1, + lapack_complex_double* taup2, + lapack_complex_double* tauq1, + lapack_complex_double* tauq2, + lapack_complex_double* work, lapack_int lwork ); +lapack_int LAPACKE_zuncsd( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, char signs, + lapack_int m, lapack_int p, lapack_int q, + lapack_complex_double* x11, lapack_int ldx11, + lapack_complex_double* x12, lapack_int ldx12, + lapack_complex_double* x21, lapack_int ldx21, + lapack_complex_double* x22, lapack_int ldx22, + double* theta, lapack_complex_double* u1, + lapack_int ldu1, lapack_complex_double* u2, + lapack_int ldu2, lapack_complex_double* v1t, + lapack_int ldv1t, lapack_complex_double* v2t, + lapack_int ldv2t ); +lapack_int LAPACKE_zuncsd_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, char jobv2t, char trans, + char signs, lapack_int m, lapack_int p, + lapack_int q, lapack_complex_double* x11, + lapack_int ldx11, lapack_complex_double* x12, + lapack_int ldx12, lapack_complex_double* x21, + lapack_int ldx21, lapack_complex_double* x22, + lapack_int ldx22, double* theta, + lapack_complex_double* u1, lapack_int ldu1, + lapack_complex_double* u2, lapack_int ldu2, + lapack_complex_double* v1t, lapack_int ldv1t, + lapack_complex_double* v2t, lapack_int ldv2t, + lapack_complex_double* work, lapack_int lwork, + double* rwork, lapack_int lrwork, + lapack_int* iwork ); +lapack_int LAPACKE_zuncsd2by1( int matrix_layout, char jobu1, char jobu2, + char jobv1t, lapack_int m, lapack_int p, lapack_int q, + lapack_complex_double* x11, lapack_int ldx11, + lapack_complex_double* x21, lapack_int ldx21, + lapack_complex_double* theta, lapack_complex_double* u1, + lapack_int ldu1, lapack_complex_double* u2, + lapack_int ldu2, lapack_complex_double* v1t, lapack_int ldv1t ); +lapack_int LAPACKE_zuncsd2by1_work( int matrix_layout, char jobu1, char jobu2, + char jobv1t, lapack_int m, lapack_int p, + lapack_int q, lapack_complex_double* x11, lapack_int ldx11, + lapack_complex_double* x21, lapack_int ldx21, + lapack_complex_double* theta, lapack_complex_double* u1, + lapack_int ldu1, lapack_complex_double* u2, + lapack_int ldu2, lapack_complex_double* v1t, + lapack_int ldv1t, lapack_complex_double* work, + lapack_int lwork, double* rwork, lapack_int lrwork, + lapack_int* iwork ); + +//LAPACK 3.4.0 +lapack_int LAPACKE_sgemqrt( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const float* v, lapack_int ldv, + const float* t, lapack_int ldt, float* c, + lapack_int ldc ); +lapack_int LAPACKE_dgemqrt( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const double* v, lapack_int ldv, + const double* t, lapack_int ldt, double* c, + lapack_int ldc ); +lapack_int LAPACKE_cgemqrt( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const lapack_complex_float* v, + lapack_int ldv, const lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* c, + lapack_int ldc ); +lapack_int LAPACKE_zgemqrt( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const lapack_complex_double* v, + lapack_int ldv, const lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* c, + lapack_int ldc ); + +lapack_int LAPACKE_sgeqrt( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nb, float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nb, double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nb, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* t, + lapack_int ldt ); +lapack_int LAPACKE_zgeqrt( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nb, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* t, + lapack_int ldt ); + +lapack_int LAPACKE_sgeqrt2( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt2( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zgeqrt2( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_sgeqrt3( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt3( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt3( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zgeqrt3( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stpmqrt( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, const float* v, + lapack_int ldv, const float* t, lapack_int ldt, + float* a, lapack_int lda, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dtpmqrt( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, const double* v, + lapack_int ldv, const double* t, lapack_int ldt, + double* a, lapack_int lda, double* b, + lapack_int ldb ); +lapack_int LAPACKE_ctpmqrt( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztpmqrt( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_stpqrt( int matrix_layout, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, float* a, + lapack_int lda, float* b, lapack_int ldb, float* t, + lapack_int ldt ); + +lapack_int LAPACKE_dtpqrt( int matrix_layout, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, double* a, + lapack_int lda, double* b, lapack_int ldb, double* t, + lapack_int ldt ); +lapack_int LAPACKE_ctpqrt( int matrix_layout, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_ztpqrt( int matrix_layout, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stpqrt2( int matrix_layout, + lapack_int m, lapack_int n, lapack_int l, + float* a, lapack_int lda, + float* b, lapack_int ldb, + float* t, lapack_int ldt ); +lapack_int LAPACKE_dtpqrt2( int matrix_layout, + lapack_int m, lapack_int n, lapack_int l, + double* a, lapack_int lda, + double* b, lapack_int ldb, + double* t, lapack_int ldt ); +lapack_int LAPACKE_ctpqrt2( int matrix_layout, + lapack_int m, lapack_int n, lapack_int l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_ztpqrt2( int matrix_layout, + lapack_int m, lapack_int n, lapack_int l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stprfb( int matrix_layout, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, lapack_int l, const float* v, + lapack_int ldv, const float* t, lapack_int ldt, + float* a, lapack_int lda, float* b, lapack_int ldb ); +lapack_int LAPACKE_dtprfb( int matrix_layout, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, lapack_int l, const double* v, + lapack_int ldv, const double* t, lapack_int ldt, + double* a, lapack_int lda, double* b, lapack_int ldb ); +lapack_int LAPACKE_ctprfb( int matrix_layout, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, lapack_int l, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_ztprfb( int matrix_layout, char side, char trans, char direct, + char storev, lapack_int m, lapack_int n, + lapack_int k, lapack_int l, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_sgemqrt_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const float* v, lapack_int ldv, + const float* t, lapack_int ldt, float* c, + lapack_int ldc, float* work ); +lapack_int LAPACKE_dgemqrt_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const double* v, lapack_int ldv, + const double* t, lapack_int ldt, double* c, + lapack_int ldc, double* work ); +lapack_int LAPACKE_cgemqrt_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const lapack_complex_float* v, + lapack_int ldv, const lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* c, + lapack_int ldc, lapack_complex_float* work ); +lapack_int LAPACKE_zgemqrt_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int nb, const lapack_complex_double* v, + lapack_int ldv, const lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* c, + lapack_int ldc, lapack_complex_double* work ); + +lapack_int LAPACKE_sgeqrt_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nb, float* a, lapack_int lda, + float* t, lapack_int ldt, float* work ); +lapack_int LAPACKE_dgeqrt_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nb, double* a, lapack_int lda, + double* t, lapack_int ldt, double* work ); +lapack_int LAPACKE_cgeqrt_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nb, lapack_complex_float* a, + lapack_int lda, lapack_complex_float* t, + lapack_int ldt, lapack_complex_float* work ); +lapack_int LAPACKE_zgeqrt_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int nb, lapack_complex_double* a, + lapack_int lda, lapack_complex_double* t, + lapack_int ldt, lapack_complex_double* work ); + +lapack_int LAPACKE_sgeqrt2_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt2_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zgeqrt2_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_sgeqrt3_work( int matrix_layout, lapack_int m, lapack_int n, + float* a, lapack_int lda, float* t, + lapack_int ldt ); +lapack_int LAPACKE_dgeqrt3_work( int matrix_layout, lapack_int m, lapack_int n, + double* a, lapack_int lda, double* t, + lapack_int ldt ); +lapack_int LAPACKE_cgeqrt3_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_zgeqrt3_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stpmqrt_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, const float* v, + lapack_int ldv, const float* t, lapack_int ldt, + float* a, lapack_int lda, float* b, + lapack_int ldb, float* work ); +lapack_int LAPACKE_dtpmqrt_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, const double* v, + lapack_int ldv, const double* t, + lapack_int ldt, double* a, lapack_int lda, + double* b, lapack_int ldb, double* work ); +lapack_int LAPACKE_ctpmqrt_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work ); +lapack_int LAPACKE_ztpmqrt_work( int matrix_layout, char side, char trans, + lapack_int m, lapack_int n, lapack_int k, + lapack_int l, lapack_int nb, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work ); + +lapack_int LAPACKE_stpqrt_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, float* a, + lapack_int lda, float* b, lapack_int ldb, + float* t, lapack_int ldt, float* work ); +lapack_int LAPACKE_dtpqrt_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, double* a, + lapack_int lda, double* b, lapack_int ldb, + double* t, lapack_int ldt, double* work ); +lapack_int LAPACKE_ctpqrt_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* work ); +lapack_int LAPACKE_ztpqrt_work( int matrix_layout, lapack_int m, lapack_int n, + lapack_int l, lapack_int nb, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* work ); + +lapack_int LAPACKE_stpqrt2_work( int matrix_layout, + lapack_int m, lapack_int n, lapack_int l, + float* a, lapack_int lda, + float* b, lapack_int ldb, + float* t, lapack_int ldt ); +lapack_int LAPACKE_dtpqrt2_work( int matrix_layout, + lapack_int m, lapack_int n, lapack_int l, + double* a, lapack_int lda, + double* b, lapack_int ldb, + double* t, lapack_int ldt ); +lapack_int LAPACKE_ctpqrt2_work( int matrix_layout, + lapack_int m, lapack_int n, lapack_int l, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* t, lapack_int ldt ); +lapack_int LAPACKE_ztpqrt2_work( int matrix_layout, + lapack_int m, lapack_int n, lapack_int l, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* t, lapack_int ldt ); + +lapack_int LAPACKE_stprfb_work( int matrix_layout, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, lapack_int l, + const float* v, lapack_int ldv, const float* t, + lapack_int ldt, float* a, lapack_int lda, + float* b, lapack_int ldb, const float* work, + lapack_int ldwork ); +lapack_int LAPACKE_dtprfb_work( int matrix_layout, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, lapack_int l, + const double* v, lapack_int ldv, + const double* t, lapack_int ldt, double* a, + lapack_int lda, double* b, lapack_int ldb, + const double* work, lapack_int ldwork ); +lapack_int LAPACKE_ctprfb_work( int matrix_layout, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, lapack_int l, + const lapack_complex_float* v, lapack_int ldv, + const lapack_complex_float* t, lapack_int ldt, + lapack_complex_float* a, lapack_int lda, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, lapack_int ldwork ); +lapack_int LAPACKE_ztprfb_work( int matrix_layout, char side, char trans, + char direct, char storev, lapack_int m, + lapack_int n, lapack_int k, lapack_int l, + const lapack_complex_double* v, lapack_int ldv, + const lapack_complex_double* t, lapack_int ldt, + lapack_complex_double* a, lapack_int lda, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, lapack_int ldwork ); +//LAPACK 3.X.X +lapack_int LAPACKE_ssysv_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dsysv_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_csysv_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsysv_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_ssytrf_rook( int matrix_layout, char uplo, lapack_int n, float* a, + lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_dsytrf_rook( int matrix_layout, char uplo, lapack_int n, double* a, + lapack_int lda, lapack_int* ipiv ); +lapack_int LAPACKE_csytrf_rook( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zsytrf_rook( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_ssytrs_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, lapack_int ldb ); +lapack_int LAPACKE_dsytrs_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, lapack_int lda, + const lapack_int* ipiv, double* b, lapack_int ldb ); +lapack_int LAPACKE_csytrs_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsytrs_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chetrf_rook( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv ); +lapack_int LAPACKE_zhetrf_rook( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv ); + +lapack_int LAPACKE_chetrs_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zhetrs_rook( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_csyr( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float alpha, + const lapack_complex_float* x, lapack_int incx, + lapack_complex_float* a, lapack_int lda ); +lapack_int LAPACKE_zsyr( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double alpha, + const lapack_complex_double* x, lapack_int incx, + lapack_complex_double* a, lapack_int lda ); + +lapack_int LAPACKE_ssysv_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, float* a, lapack_int lda, + lapack_int* ipiv, float* b, lapack_int ldb, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsysv_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, double* a, lapack_int lda, + lapack_int* ipiv, double* b, lapack_int ldb, + double* work, lapack_int lwork ); +lapack_int LAPACKE_csysv_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_float* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb, + lapack_complex_float* work, + lapack_int lwork ); +lapack_int LAPACKE_zsysv_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, lapack_complex_double* a, + lapack_int lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb, + lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_ssytrf_rook_work( int matrix_layout, char uplo, lapack_int n, + float* a, lapack_int lda, lapack_int* ipiv, + float* work, lapack_int lwork ); +lapack_int LAPACKE_dsytrf_rook_work( int matrix_layout, char uplo, lapack_int n, + double* a, lapack_int lda, lapack_int* ipiv, + double* work, lapack_int lwork ); +lapack_int LAPACKE_csytrf_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* work, + lapack_int lwork ); +lapack_int LAPACKE_zsytrf_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_ssytrs_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const float* a, lapack_int lda, + const lapack_int* ipiv, float* b, + lapack_int ldb ); +lapack_int LAPACKE_dsytrs_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const double* a, + lapack_int lda, const lapack_int* ipiv, + double* b, lapack_int ldb ); +lapack_int LAPACKE_csytrs_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zsytrs_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + +lapack_int LAPACKE_chetrf_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_float* work, + lapack_int lwork ); +lapack_int LAPACKE_zhetrf_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double* a, lapack_int lda, + lapack_int* ipiv, lapack_complex_double* work, + lapack_int lwork ); + +lapack_int LAPACKE_chetrs_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_float* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int ldb ); +lapack_int LAPACKE_zhetrs_rook_work( int matrix_layout, char uplo, lapack_int n, + lapack_int nrhs, const lapack_complex_double* a, + lapack_int lda, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int ldb ); + + +lapack_int LAPACKE_csyr_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_float alpha, + const lapack_complex_float* x, + lapack_int incx, lapack_complex_float* a, + lapack_int lda ); +lapack_int LAPACKE_zsyr_work( int matrix_layout, char uplo, lapack_int n, + lapack_complex_double alpha, + const lapack_complex_double* x, + lapack_int incx, lapack_complex_double* a, + lapack_int lda ); +void LAPACKE_ilaver( const lapack_int* vers_major, + const lapack_int* vers_minor, + const lapack_int* vers_patch ); + + +#define LAPACK_sgetrf LAPACK_GLOBAL(sgetrf,SGETRF) +#define LAPACK_dgetrf LAPACK_GLOBAL(dgetrf,DGETRF) +#define LAPACK_cgetrf LAPACK_GLOBAL(cgetrf,CGETRF) +#define LAPACK_zgetrf LAPACK_GLOBAL(zgetrf,ZGETRF) +#define LAPACK_sgetrf2 LAPACK_GLOBAL(sgetrf2,SGETRF2) +#define LAPACK_dgetrf2 LAPACK_GLOBAL(dgetrf2,DGETRF2) +#define LAPACK_cgetrf2 LAPACK_GLOBAL(cgetrf2,CGETRF2) +#define LAPACK_zgetrf2 LAPACK_GLOBAL(zgetrf2,ZGETRF2) +#define LAPACK_sgbtrf LAPACK_GLOBAL(sgbtrf,SGBTRF) +#define LAPACK_dgbtrf LAPACK_GLOBAL(dgbtrf,DGBTRF) +#define LAPACK_cgbtrf LAPACK_GLOBAL(cgbtrf,CGBTRF) +#define LAPACK_zgbtrf LAPACK_GLOBAL(zgbtrf,ZGBTRF) +#define LAPACK_sgttrf LAPACK_GLOBAL(sgttrf,SGTTRF) +#define LAPACK_dgttrf LAPACK_GLOBAL(dgttrf,DGTTRF) +#define LAPACK_cgttrf LAPACK_GLOBAL(cgttrf,CGTTRF) +#define LAPACK_zgttrf LAPACK_GLOBAL(zgttrf,ZGTTRF) +#define LAPACK_spotrf LAPACK_GLOBAL(spotrf,SPOTRF) +#define LAPACK_dpotrf LAPACK_GLOBAL(dpotrf,DPOTRF) +#define LAPACK_cpotrf LAPACK_GLOBAL(cpotrf,CPOTRF) +#define LAPACK_zpotrf LAPACK_GLOBAL(zpotrf,ZPOTRF) +#define LAPACK_spotrf2 LAPACK_GLOBAL(spotrf2,SPOTRF2) +#define LAPACK_dpotrf2 LAPACK_GLOBAL(dpotrf2,DPOTRF2) +#define LAPACK_cpotrf2 LAPACK_GLOBAL(cpotrf2,CPOTRF2) +#define LAPACK_zpotrf2 LAPACK_GLOBAL(zpotrf2,ZPOTRF2) +#define LAPACK_dpstrf LAPACK_GLOBAL(dpstrf,DPSTRF) +#define LAPACK_spstrf LAPACK_GLOBAL(spstrf,SPSTRF) +#define LAPACK_zpstrf LAPACK_GLOBAL(zpstrf,ZPSTRF) +#define LAPACK_cpstrf LAPACK_GLOBAL(cpstrf,CPSTRF) +#define LAPACK_dpftrf LAPACK_GLOBAL(dpftrf,DPFTRF) +#define LAPACK_spftrf LAPACK_GLOBAL(spftrf,SPFTRF) +#define LAPACK_zpftrf LAPACK_GLOBAL(zpftrf,ZPFTRF) +#define LAPACK_cpftrf LAPACK_GLOBAL(cpftrf,CPFTRF) +#define LAPACK_spptrf LAPACK_GLOBAL(spptrf,SPPTRF) +#define LAPACK_dpptrf LAPACK_GLOBAL(dpptrf,DPPTRF) +#define LAPACK_cpptrf LAPACK_GLOBAL(cpptrf,CPPTRF) +#define LAPACK_zpptrf LAPACK_GLOBAL(zpptrf,ZPPTRF) +#define LAPACK_spbtrf LAPACK_GLOBAL(spbtrf,SPBTRF) +#define LAPACK_dpbtrf LAPACK_GLOBAL(dpbtrf,DPBTRF) +#define LAPACK_cpbtrf LAPACK_GLOBAL(cpbtrf,CPBTRF) +#define LAPACK_zpbtrf LAPACK_GLOBAL(zpbtrf,ZPBTRF) +#define LAPACK_spttrf LAPACK_GLOBAL(spttrf,SPTTRF) +#define LAPACK_dpttrf LAPACK_GLOBAL(dpttrf,DPTTRF) +#define LAPACK_cpttrf LAPACK_GLOBAL(cpttrf,CPTTRF) +#define LAPACK_zpttrf LAPACK_GLOBAL(zpttrf,ZPTTRF) +#define LAPACK_ssytrf LAPACK_GLOBAL(ssytrf,SSYTRF) +#define LAPACK_ssytrf_rook LAPACK_GLOBAL(ssytrf_rook,SSYTRF_ROOK) +#define LAPACK_dsytrf LAPACK_GLOBAL(dsytrf,DSYTRF) +#define LAPACK_dsytrf_rook LAPACK_GLOBAL(dsytrf_rook,DSYTRF_ROOK) +#define LAPACK_csytrf LAPACK_GLOBAL(csytrf,CSYTRF) +#define LAPACK_csytrf_rook LAPACK_GLOBAL(csytrf_rook,CSYTRF_ROOK) +#define LAPACK_zsytrf LAPACK_GLOBAL(zsytrf,ZSYTRF) +#define LAPACK_zsytrf_rook LAPACK_GLOBAL(zsytrf_rook,ZSYTRF_ROOK) +#define LAPACK_chetrf LAPACK_GLOBAL(chetrf,CHETRF) +#define LAPACK_chetrf_rook LAPACK_GLOBAL(chetrf_rook,CHETRF_ROOK) +#define LAPACK_zhetrf LAPACK_GLOBAL(zhetrf,ZHETRF) +#define LAPACK_zhetrf_rook LAPACK_GLOBAL(zhetrf_rook,ZHETRF_ROOK) +#define LAPACK_ssptrf LAPACK_GLOBAL(ssptrf,SSPTRF) +#define LAPACK_dsptrf LAPACK_GLOBAL(dsptrf,DSPTRF) +#define LAPACK_csptrf LAPACK_GLOBAL(csptrf,CSPTRF) +#define LAPACK_zsptrf LAPACK_GLOBAL(zsptrf,ZSPTRF) +#define LAPACK_chptrf LAPACK_GLOBAL(chptrf,CHPTRF) +#define LAPACK_zhptrf LAPACK_GLOBAL(zhptrf,ZHPTRF) +#define LAPACK_sgetrs LAPACK_GLOBAL(sgetrs,SGETRS) +#define LAPACK_dgetrs LAPACK_GLOBAL(dgetrs,DGETRS) +#define LAPACK_cgetrs LAPACK_GLOBAL(cgetrs,CGETRS) +#define LAPACK_zgetrs LAPACK_GLOBAL(zgetrs,ZGETRS) +#define LAPACK_sgbtrs LAPACK_GLOBAL(sgbtrs,SGBTRS) +#define LAPACK_dgbtrs LAPACK_GLOBAL(dgbtrs,DGBTRS) +#define LAPACK_cgbtrs LAPACK_GLOBAL(cgbtrs,CGBTRS) +#define LAPACK_zgbtrs LAPACK_GLOBAL(zgbtrs,ZGBTRS) +#define LAPACK_sgttrs LAPACK_GLOBAL(sgttrs,SGTTRS) +#define LAPACK_dgttrs LAPACK_GLOBAL(dgttrs,DGTTRS) +#define LAPACK_cgttrs LAPACK_GLOBAL(cgttrs,CGTTRS) +#define LAPACK_zgttrs LAPACK_GLOBAL(zgttrs,ZGTTRS) +#define LAPACK_spotrs LAPACK_GLOBAL(spotrs,SPOTRS) +#define LAPACK_dpotrs LAPACK_GLOBAL(dpotrs,DPOTRS) +#define LAPACK_cpotrs LAPACK_GLOBAL(cpotrs,CPOTRS) +#define LAPACK_zpotrs LAPACK_GLOBAL(zpotrs,ZPOTRS) +#define LAPACK_dpftrs LAPACK_GLOBAL(dpftrs,DPFTRS) +#define LAPACK_spftrs LAPACK_GLOBAL(spftrs,SPFTRS) +#define LAPACK_zpftrs LAPACK_GLOBAL(zpftrs,ZPFTRS) +#define LAPACK_cpftrs LAPACK_GLOBAL(cpftrs,CPFTRS) +#define LAPACK_spptrs LAPACK_GLOBAL(spptrs,SPPTRS) +#define LAPACK_dpptrs LAPACK_GLOBAL(dpptrs,DPPTRS) +#define LAPACK_cpptrs LAPACK_GLOBAL(cpptrs,CPPTRS) +#define LAPACK_zpptrs LAPACK_GLOBAL(zpptrs,ZPPTRS) +#define LAPACK_spbtrs LAPACK_GLOBAL(spbtrs,SPBTRS) +#define LAPACK_dpbtrs LAPACK_GLOBAL(dpbtrs,DPBTRS) +#define LAPACK_cpbtrs LAPACK_GLOBAL(cpbtrs,CPBTRS) +#define LAPACK_zpbtrs LAPACK_GLOBAL(zpbtrs,ZPBTRS) +#define LAPACK_spttrs LAPACK_GLOBAL(spttrs,SPTTRS) +#define LAPACK_dpttrs LAPACK_GLOBAL(dpttrs,DPTTRS) +#define LAPACK_cpttrs LAPACK_GLOBAL(cpttrs,CPTTRS) +#define LAPACK_zpttrs LAPACK_GLOBAL(zpttrs,ZPTTRS) +#define LAPACK_ssytrs LAPACK_GLOBAL(ssytrs,SSYTRS) +#define LAPACK_ssytrs_rook LAPACK_GLOBAL(ssytrs_rook,SSYTRS_ROOK) +#define LAPACK_dsytrs LAPACK_GLOBAL(dsytrs,DSYTRS) +#define LAPACK_dsytrs_rook LAPACK_GLOBAL(dsytrs_rook,DSYTRS_ROOK) +#define LAPACK_csytrs LAPACK_GLOBAL(csytrs,CSYTRS) +#define LAPACK_csytrs_rook LAPACK_GLOBAL(csytrs_rook,CSYTRS_ROOK) +#define LAPACK_zsytrs LAPACK_GLOBAL(zsytrs,ZSYTRS) +#define LAPACK_zsytrs_rook LAPACK_GLOBAL(zsytrs_rook,ZSYTRS_ROOK) +#define LAPACK_chetrs LAPACK_GLOBAL(chetrs,CHETRS) +#define LAPACK_chetrs_rook LAPACK_GLOBAL(chetrs_rook,CHETRS_ROOK) +#define LAPACK_zhetrs LAPACK_GLOBAL(zhetrs,ZHETRS) +#define LAPACK_zhetrs_rook LAPACK_GLOBAL(zhetrs_rook,ZHETRS_ROOK) +#define LAPACK_ssptrs LAPACK_GLOBAL(ssptrs,SSPTRS) +#define LAPACK_dsptrs LAPACK_GLOBAL(dsptrs,DSPTRS) +#define LAPACK_csptrs LAPACK_GLOBAL(csptrs,CSPTRS) +#define LAPACK_zsptrs LAPACK_GLOBAL(zsptrs,ZSPTRS) +#define LAPACK_chptrs LAPACK_GLOBAL(chptrs,CHPTRS) +#define LAPACK_zhptrs LAPACK_GLOBAL(zhptrs,ZHPTRS) +#define LAPACK_strtrs LAPACK_GLOBAL(strtrs,STRTRS) +#define LAPACK_dtrtrs LAPACK_GLOBAL(dtrtrs,DTRTRS) +#define LAPACK_ctrtrs LAPACK_GLOBAL(ctrtrs,CTRTRS) +#define LAPACK_ztrtrs LAPACK_GLOBAL(ztrtrs,ZTRTRS) +#define LAPACK_stptrs LAPACK_GLOBAL(stptrs,STPTRS) +#define LAPACK_dtptrs LAPACK_GLOBAL(dtptrs,DTPTRS) +#define LAPACK_ctptrs LAPACK_GLOBAL(ctptrs,CTPTRS) +#define LAPACK_ztptrs LAPACK_GLOBAL(ztptrs,ZTPTRS) +#define LAPACK_stbtrs LAPACK_GLOBAL(stbtrs,STBTRS) +#define LAPACK_dtbtrs LAPACK_GLOBAL(dtbtrs,DTBTRS) +#define LAPACK_ctbtrs LAPACK_GLOBAL(ctbtrs,CTBTRS) +#define LAPACK_ztbtrs LAPACK_GLOBAL(ztbtrs,ZTBTRS) +#define LAPACK_sgecon LAPACK_GLOBAL(sgecon,SGECON) +#define LAPACK_dgecon LAPACK_GLOBAL(dgecon,DGECON) +#define LAPACK_cgecon LAPACK_GLOBAL(cgecon,CGECON) +#define LAPACK_zgecon LAPACK_GLOBAL(zgecon,ZGECON) +#define LAPACK_sgbcon LAPACK_GLOBAL(sgbcon,SGBCON) +#define LAPACK_dgbcon LAPACK_GLOBAL(dgbcon,DGBCON) +#define LAPACK_cgbcon LAPACK_GLOBAL(cgbcon,CGBCON) +#define LAPACK_zgbcon LAPACK_GLOBAL(zgbcon,ZGBCON) +#define LAPACK_sgtcon LAPACK_GLOBAL(sgtcon,SGTCON) +#define LAPACK_dgtcon LAPACK_GLOBAL(dgtcon,DGTCON) +#define LAPACK_cgtcon LAPACK_GLOBAL(cgtcon,CGTCON) +#define LAPACK_zgtcon LAPACK_GLOBAL(zgtcon,ZGTCON) +#define LAPACK_spocon LAPACK_GLOBAL(spocon,SPOCON) +#define LAPACK_dpocon LAPACK_GLOBAL(dpocon,DPOCON) +#define LAPACK_cpocon LAPACK_GLOBAL(cpocon,CPOCON) +#define LAPACK_zpocon LAPACK_GLOBAL(zpocon,ZPOCON) +#define LAPACK_sppcon LAPACK_GLOBAL(sppcon,SPPCON) +#define LAPACK_dppcon LAPACK_GLOBAL(dppcon,DPPCON) +#define LAPACK_cppcon LAPACK_GLOBAL(cppcon,CPPCON) +#define LAPACK_zppcon LAPACK_GLOBAL(zppcon,ZPPCON) +#define LAPACK_spbcon LAPACK_GLOBAL(spbcon,SPBCON) +#define LAPACK_dpbcon LAPACK_GLOBAL(dpbcon,DPBCON) +#define LAPACK_cpbcon LAPACK_GLOBAL(cpbcon,CPBCON) +#define LAPACK_zpbcon LAPACK_GLOBAL(zpbcon,ZPBCON) +#define LAPACK_sptcon LAPACK_GLOBAL(sptcon,SPTCON) +#define LAPACK_dptcon LAPACK_GLOBAL(dptcon,DPTCON) +#define LAPACK_cptcon LAPACK_GLOBAL(cptcon,CPTCON) +#define LAPACK_zptcon LAPACK_GLOBAL(zptcon,ZPTCON) +#define LAPACK_ssycon LAPACK_GLOBAL(ssycon,SSYCON) +#define LAPACK_dsycon LAPACK_GLOBAL(dsycon,DSYCON) +#define LAPACK_csycon LAPACK_GLOBAL(csycon,CSYCON) +#define LAPACK_zsycon LAPACK_GLOBAL(zsycon,ZSYCON) +#define LAPACK_checon LAPACK_GLOBAL(checon,CHECON) +#define LAPACK_zhecon LAPACK_GLOBAL(zhecon,ZHECON) +#define LAPACK_sspcon LAPACK_GLOBAL(sspcon,SSPCON) +#define LAPACK_dspcon LAPACK_GLOBAL(dspcon,DSPCON) +#define LAPACK_cspcon LAPACK_GLOBAL(cspcon,CSPCON) +#define LAPACK_zspcon LAPACK_GLOBAL(zspcon,ZSPCON) +#define LAPACK_chpcon LAPACK_GLOBAL(chpcon,CHPCON) +#define LAPACK_zhpcon LAPACK_GLOBAL(zhpcon,ZHPCON) +#define LAPACK_strcon LAPACK_GLOBAL(strcon,STRCON) +#define LAPACK_dtrcon LAPACK_GLOBAL(dtrcon,DTRCON) +#define LAPACK_ctrcon LAPACK_GLOBAL(ctrcon,CTRCON) +#define LAPACK_ztrcon LAPACK_GLOBAL(ztrcon,ZTRCON) +#define LAPACK_stpcon LAPACK_GLOBAL(stpcon,STPCON) +#define LAPACK_dtpcon LAPACK_GLOBAL(dtpcon,DTPCON) +#define LAPACK_ctpcon LAPACK_GLOBAL(ctpcon,CTPCON) +#define LAPACK_ztpcon LAPACK_GLOBAL(ztpcon,ZTPCON) +#define LAPACK_stbcon LAPACK_GLOBAL(stbcon,STBCON) +#define LAPACK_dtbcon LAPACK_GLOBAL(dtbcon,DTBCON) +#define LAPACK_ctbcon LAPACK_GLOBAL(ctbcon,CTBCON) +#define LAPACK_ztbcon LAPACK_GLOBAL(ztbcon,ZTBCON) +#define LAPACK_sgerfs LAPACK_GLOBAL(sgerfs,SGERFS) +#define LAPACK_dgerfs LAPACK_GLOBAL(dgerfs,DGERFS) +#define LAPACK_cgerfs LAPACK_GLOBAL(cgerfs,CGERFS) +#define LAPACK_zgerfs LAPACK_GLOBAL(zgerfs,ZGERFS) +#define LAPACK_dgerfsx LAPACK_GLOBAL(dgerfsx,DGERFSX) +#define LAPACK_sgerfsx LAPACK_GLOBAL(sgerfsx,SGERFSX) +#define LAPACK_zgerfsx LAPACK_GLOBAL(zgerfsx,ZGERFSX) +#define LAPACK_cgerfsx LAPACK_GLOBAL(cgerfsx,CGERFSX) +#define LAPACK_sgbrfs LAPACK_GLOBAL(sgbrfs,SGBRFS) +#define LAPACK_dgbrfs LAPACK_GLOBAL(dgbrfs,DGBRFS) +#define LAPACK_cgbrfs LAPACK_GLOBAL(cgbrfs,CGBRFS) +#define LAPACK_zgbrfs LAPACK_GLOBAL(zgbrfs,ZGBRFS) +#define LAPACK_dgbrfsx LAPACK_GLOBAL(dgbrfsx,DGBRFSX) +#define LAPACK_sgbrfsx LAPACK_GLOBAL(sgbrfsx,SGBRFSX) +#define LAPACK_zgbrfsx LAPACK_GLOBAL(zgbrfsx,ZGBRFSX) +#define LAPACK_cgbrfsx LAPACK_GLOBAL(cgbrfsx,CGBRFSX) +#define LAPACK_sgtrfs LAPACK_GLOBAL(sgtrfs,SGTRFS) +#define LAPACK_dgtrfs LAPACK_GLOBAL(dgtrfs,DGTRFS) +#define LAPACK_cgtrfs LAPACK_GLOBAL(cgtrfs,CGTRFS) +#define LAPACK_zgtrfs LAPACK_GLOBAL(zgtrfs,ZGTRFS) +#define LAPACK_sporfs LAPACK_GLOBAL(sporfs,SPORFS) +#define LAPACK_dporfs LAPACK_GLOBAL(dporfs,DPORFS) +#define LAPACK_cporfs LAPACK_GLOBAL(cporfs,CPORFS) +#define LAPACK_zporfs LAPACK_GLOBAL(zporfs,ZPORFS) +#define LAPACK_dporfsx LAPACK_GLOBAL(dporfsx,DPORFSX) +#define LAPACK_sporfsx LAPACK_GLOBAL(sporfsx,SPORFSX) +#define LAPACK_zporfsx LAPACK_GLOBAL(zporfsx,ZPORFSX) +#define LAPACK_cporfsx LAPACK_GLOBAL(cporfsx,CPORFSX) +#define LAPACK_spprfs LAPACK_GLOBAL(spprfs,SPPRFS) +#define LAPACK_dpprfs LAPACK_GLOBAL(dpprfs,DPPRFS) +#define LAPACK_cpprfs LAPACK_GLOBAL(cpprfs,CPPRFS) +#define LAPACK_zpprfs LAPACK_GLOBAL(zpprfs,ZPPRFS) +#define LAPACK_spbrfs LAPACK_GLOBAL(spbrfs,SPBRFS) +#define LAPACK_dpbrfs LAPACK_GLOBAL(dpbrfs,DPBRFS) +#define LAPACK_cpbrfs LAPACK_GLOBAL(cpbrfs,CPBRFS) +#define LAPACK_zpbrfs LAPACK_GLOBAL(zpbrfs,ZPBRFS) +#define LAPACK_sptrfs LAPACK_GLOBAL(sptrfs,SPTRFS) +#define LAPACK_dptrfs LAPACK_GLOBAL(dptrfs,DPTRFS) +#define LAPACK_cptrfs LAPACK_GLOBAL(cptrfs,CPTRFS) +#define LAPACK_zptrfs LAPACK_GLOBAL(zptrfs,ZPTRFS) +#define LAPACK_ssyrfs LAPACK_GLOBAL(ssyrfs,SSYRFS) +#define LAPACK_dsyrfs LAPACK_GLOBAL(dsyrfs,DSYRFS) +#define LAPACK_csyrfs LAPACK_GLOBAL(csyrfs,CSYRFS) +#define LAPACK_zsyrfs LAPACK_GLOBAL(zsyrfs,ZSYRFS) +#define LAPACK_dsyrfsx LAPACK_GLOBAL(dsyrfsx,DSYRFSX) +#define LAPACK_ssyrfsx LAPACK_GLOBAL(ssyrfsx,SSYRFSX) +#define LAPACK_zsyrfsx LAPACK_GLOBAL(zsyrfsx,ZSYRFSX) +#define LAPACK_csyrfsx LAPACK_GLOBAL(csyrfsx,CSYRFSX) +#define LAPACK_cherfs LAPACK_GLOBAL(cherfs,CHERFS) +#define LAPACK_zherfs LAPACK_GLOBAL(zherfs,ZHERFS) +#define LAPACK_zherfsx LAPACK_GLOBAL(zherfsx,ZHERFSX) +#define LAPACK_cherfsx LAPACK_GLOBAL(cherfsx,CHERFSX) +#define LAPACK_ssprfs LAPACK_GLOBAL(ssprfs,SSPRFS) +#define LAPACK_dsprfs LAPACK_GLOBAL(dsprfs,DSPRFS) +#define LAPACK_csprfs LAPACK_GLOBAL(csprfs,CSPRFS) +#define LAPACK_zsprfs LAPACK_GLOBAL(zsprfs,ZSPRFS) +#define LAPACK_chprfs LAPACK_GLOBAL(chprfs,CHPRFS) +#define LAPACK_zhprfs LAPACK_GLOBAL(zhprfs,ZHPRFS) +#define LAPACK_strrfs LAPACK_GLOBAL(strrfs,STRRFS) +#define LAPACK_dtrrfs LAPACK_GLOBAL(dtrrfs,DTRRFS) +#define LAPACK_ctrrfs LAPACK_GLOBAL(ctrrfs,CTRRFS) +#define LAPACK_ztrrfs LAPACK_GLOBAL(ztrrfs,ZTRRFS) +#define LAPACK_stprfs LAPACK_GLOBAL(stprfs,STPRFS) +#define LAPACK_dtprfs LAPACK_GLOBAL(dtprfs,DTPRFS) +#define LAPACK_ctprfs LAPACK_GLOBAL(ctprfs,CTPRFS) +#define LAPACK_ztprfs LAPACK_GLOBAL(ztprfs,ZTPRFS) +#define LAPACK_stbrfs LAPACK_GLOBAL(stbrfs,STBRFS) +#define LAPACK_dtbrfs LAPACK_GLOBAL(dtbrfs,DTBRFS) +#define LAPACK_ctbrfs LAPACK_GLOBAL(ctbrfs,CTBRFS) +#define LAPACK_ztbrfs LAPACK_GLOBAL(ztbrfs,ZTBRFS) +#define LAPACK_sgetri LAPACK_GLOBAL(sgetri,SGETRI) +#define LAPACK_dgetri LAPACK_GLOBAL(dgetri,DGETRI) +#define LAPACK_cgetri LAPACK_GLOBAL(cgetri,CGETRI) +#define LAPACK_zgetri LAPACK_GLOBAL(zgetri,ZGETRI) +#define LAPACK_spotri LAPACK_GLOBAL(spotri,SPOTRI) +#define LAPACK_dpotri LAPACK_GLOBAL(dpotri,DPOTRI) +#define LAPACK_cpotri LAPACK_GLOBAL(cpotri,CPOTRI) +#define LAPACK_zpotri LAPACK_GLOBAL(zpotri,ZPOTRI) +#define LAPACK_dpftri LAPACK_GLOBAL(dpftri,DPFTRI) +#define LAPACK_spftri LAPACK_GLOBAL(spftri,SPFTRI) +#define LAPACK_zpftri LAPACK_GLOBAL(zpftri,ZPFTRI) +#define LAPACK_cpftri LAPACK_GLOBAL(cpftri,CPFTRI) +#define LAPACK_spptri LAPACK_GLOBAL(spptri,SPPTRI) +#define LAPACK_dpptri LAPACK_GLOBAL(dpptri,DPPTRI) +#define LAPACK_cpptri LAPACK_GLOBAL(cpptri,CPPTRI) +#define LAPACK_zpptri LAPACK_GLOBAL(zpptri,ZPPTRI) +#define LAPACK_ssytri LAPACK_GLOBAL(ssytri,SSYTRI) +#define LAPACK_dsytri LAPACK_GLOBAL(dsytri,DSYTRI) +#define LAPACK_csytri LAPACK_GLOBAL(csytri,CSYTRI) +#define LAPACK_zsytri LAPACK_GLOBAL(zsytri,ZSYTRI) +#define LAPACK_chetri LAPACK_GLOBAL(chetri,CHETRI) +#define LAPACK_zhetri LAPACK_GLOBAL(zhetri,ZHETRI) +#define LAPACK_ssptri LAPACK_GLOBAL(ssptri,SSPTRI) +#define LAPACK_dsptri LAPACK_GLOBAL(dsptri,DSPTRI) +#define LAPACK_csptri LAPACK_GLOBAL(csptri,CSPTRI) +#define LAPACK_zsptri LAPACK_GLOBAL(zsptri,ZSPTRI) +#define LAPACK_chptri LAPACK_GLOBAL(chptri,CHPTRI) +#define LAPACK_zhptri LAPACK_GLOBAL(zhptri,ZHPTRI) +#define LAPACK_strtri LAPACK_GLOBAL(strtri,STRTRI) +#define LAPACK_dtrtri LAPACK_GLOBAL(dtrtri,DTRTRI) +#define LAPACK_ctrtri LAPACK_GLOBAL(ctrtri,CTRTRI) +#define LAPACK_ztrtri LAPACK_GLOBAL(ztrtri,ZTRTRI) +#define LAPACK_dtftri LAPACK_GLOBAL(dtftri,DTFTRI) +#define LAPACK_stftri LAPACK_GLOBAL(stftri,STFTRI) +#define LAPACK_ztftri LAPACK_GLOBAL(ztftri,ZTFTRI) +#define LAPACK_ctftri LAPACK_GLOBAL(ctftri,CTFTRI) +#define LAPACK_stptri LAPACK_GLOBAL(stptri,STPTRI) +#define LAPACK_dtptri LAPACK_GLOBAL(dtptri,DTPTRI) +#define LAPACK_ctptri LAPACK_GLOBAL(ctptri,CTPTRI) +#define LAPACK_ztptri LAPACK_GLOBAL(ztptri,ZTPTRI) +#define LAPACK_sgeequ LAPACK_GLOBAL(sgeequ,SGEEQU) +#define LAPACK_dgeequ LAPACK_GLOBAL(dgeequ,DGEEQU) +#define LAPACK_cgeequ LAPACK_GLOBAL(cgeequ,CGEEQU) +#define LAPACK_zgeequ LAPACK_GLOBAL(zgeequ,ZGEEQU) +#define LAPACK_dgeequb LAPACK_GLOBAL(dgeequb,DGEEQUB) +#define LAPACK_sgeequb LAPACK_GLOBAL(sgeequb,SGEEQUB) +#define LAPACK_zgeequb LAPACK_GLOBAL(zgeequb,ZGEEQUB) +#define LAPACK_cgeequb LAPACK_GLOBAL(cgeequb,CGEEQUB) +#define LAPACK_sgbequ LAPACK_GLOBAL(sgbequ,SGBEQU) +#define LAPACK_dgbequ LAPACK_GLOBAL(dgbequ,DGBEQU) +#define LAPACK_cgbequ LAPACK_GLOBAL(cgbequ,CGBEQU) +#define LAPACK_zgbequ LAPACK_GLOBAL(zgbequ,ZGBEQU) +#define LAPACK_dgbequb LAPACK_GLOBAL(dgbequb,DGBEQUB) +#define LAPACK_sgbequb LAPACK_GLOBAL(sgbequb,SGBEQUB) +#define LAPACK_zgbequb LAPACK_GLOBAL(zgbequb,ZGBEQUB) +#define LAPACK_cgbequb LAPACK_GLOBAL(cgbequb,CGBEQUB) +#define LAPACK_spoequ LAPACK_GLOBAL(spoequ,SPOEQU) +#define LAPACK_dpoequ LAPACK_GLOBAL(dpoequ,DPOEQU) +#define LAPACK_cpoequ LAPACK_GLOBAL(cpoequ,CPOEQU) +#define LAPACK_zpoequ LAPACK_GLOBAL(zpoequ,ZPOEQU) +#define LAPACK_dpoequb LAPACK_GLOBAL(dpoequb,DPOEQUB) +#define LAPACK_spoequb LAPACK_GLOBAL(spoequb,SPOEQUB) +#define LAPACK_zpoequb LAPACK_GLOBAL(zpoequb,ZPOEQUB) +#define LAPACK_cpoequb LAPACK_GLOBAL(cpoequb,CPOEQUB) +#define LAPACK_sppequ LAPACK_GLOBAL(sppequ,SPPEQU) +#define LAPACK_dppequ LAPACK_GLOBAL(dppequ,DPPEQU) +#define LAPACK_cppequ LAPACK_GLOBAL(cppequ,CPPEQU) +#define LAPACK_zppequ LAPACK_GLOBAL(zppequ,ZPPEQU) +#define LAPACK_spbequ LAPACK_GLOBAL(spbequ,SPBEQU) +#define LAPACK_dpbequ LAPACK_GLOBAL(dpbequ,DPBEQU) +#define LAPACK_cpbequ LAPACK_GLOBAL(cpbequ,CPBEQU) +#define LAPACK_zpbequ LAPACK_GLOBAL(zpbequ,ZPBEQU) +#define LAPACK_dsyequb LAPACK_GLOBAL(dsyequb,DSYEQUB) +#define LAPACK_ssyequb LAPACK_GLOBAL(ssyequb,SSYEQUB) +#define LAPACK_zsyequb LAPACK_GLOBAL(zsyequb,ZSYEQUB) +#define LAPACK_csyequb LAPACK_GLOBAL(csyequb,CSYEQUB) +#define LAPACK_zheequb LAPACK_GLOBAL(zheequb,ZHEEQUB) +#define LAPACK_cheequb LAPACK_GLOBAL(cheequb,CHEEQUB) +#define LAPACK_sgesv LAPACK_GLOBAL(sgesv,SGESV) +#define LAPACK_dgesv LAPACK_GLOBAL(dgesv,DGESV) +#define LAPACK_cgesv LAPACK_GLOBAL(cgesv,CGESV) +#define LAPACK_zgesv LAPACK_GLOBAL(zgesv,ZGESV) +#define LAPACK_dsgesv LAPACK_GLOBAL(dsgesv,DSGESV) +#define LAPACK_zcgesv LAPACK_GLOBAL(zcgesv,ZCGESV) +#define LAPACK_sgesvx LAPACK_GLOBAL(sgesvx,SGESVX) +#define LAPACK_dgesvx LAPACK_GLOBAL(dgesvx,DGESVX) +#define LAPACK_cgesvx LAPACK_GLOBAL(cgesvx,CGESVX) +#define LAPACK_zgesvx LAPACK_GLOBAL(zgesvx,ZGESVX) +#define LAPACK_dgesvxx LAPACK_GLOBAL(dgesvxx,DGESVXX) +#define LAPACK_sgesvxx LAPACK_GLOBAL(sgesvxx,SGESVXX) +#define LAPACK_zgesvxx LAPACK_GLOBAL(zgesvxx,ZGESVXX) +#define LAPACK_cgesvxx LAPACK_GLOBAL(cgesvxx,CGESVXX) +#define LAPACK_sgbsv LAPACK_GLOBAL(sgbsv,SGBSV) +#define LAPACK_dgbsv LAPACK_GLOBAL(dgbsv,DGBSV) +#define LAPACK_cgbsv LAPACK_GLOBAL(cgbsv,CGBSV) +#define LAPACK_zgbsv LAPACK_GLOBAL(zgbsv,ZGBSV) +#define LAPACK_sgbsvx LAPACK_GLOBAL(sgbsvx,SGBSVX) +#define LAPACK_dgbsvx LAPACK_GLOBAL(dgbsvx,DGBSVX) +#define LAPACK_cgbsvx LAPACK_GLOBAL(cgbsvx,CGBSVX) +#define LAPACK_zgbsvx LAPACK_GLOBAL(zgbsvx,ZGBSVX) +#define LAPACK_dgbsvxx LAPACK_GLOBAL(dgbsvxx,DGBSVXX) +#define LAPACK_sgbsvxx LAPACK_GLOBAL(sgbsvxx,SGBSVXX) +#define LAPACK_zgbsvxx LAPACK_GLOBAL(zgbsvxx,ZGBSVXX) +#define LAPACK_cgbsvxx LAPACK_GLOBAL(cgbsvxx,CGBSVXX) +#define LAPACK_sgtsv LAPACK_GLOBAL(sgtsv,SGTSV) +#define LAPACK_dgtsv LAPACK_GLOBAL(dgtsv,DGTSV) +#define LAPACK_cgtsv LAPACK_GLOBAL(cgtsv,CGTSV) +#define LAPACK_zgtsv LAPACK_GLOBAL(zgtsv,ZGTSV) +#define LAPACK_sgtsvx LAPACK_GLOBAL(sgtsvx,SGTSVX) +#define LAPACK_dgtsvx LAPACK_GLOBAL(dgtsvx,DGTSVX) +#define LAPACK_cgtsvx LAPACK_GLOBAL(cgtsvx,CGTSVX) +#define LAPACK_zgtsvx LAPACK_GLOBAL(zgtsvx,ZGTSVX) +#define LAPACK_sposv LAPACK_GLOBAL(sposv,SPOSV) +#define LAPACK_dposv LAPACK_GLOBAL(dposv,DPOSV) +#define LAPACK_cposv LAPACK_GLOBAL(cposv,CPOSV) +#define LAPACK_zposv LAPACK_GLOBAL(zposv,ZPOSV) +#define LAPACK_dsposv LAPACK_GLOBAL(dsposv,DSPOSV) +#define LAPACK_zcposv LAPACK_GLOBAL(zcposv,ZCPOSV) +#define LAPACK_sposvx LAPACK_GLOBAL(sposvx,SPOSVX) +#define LAPACK_dposvx LAPACK_GLOBAL(dposvx,DPOSVX) +#define LAPACK_cposvx LAPACK_GLOBAL(cposvx,CPOSVX) +#define LAPACK_zposvx LAPACK_GLOBAL(zposvx,ZPOSVX) +#define LAPACK_dposvxx LAPACK_GLOBAL(dposvxx,DPOSVXX) +#define LAPACK_sposvxx LAPACK_GLOBAL(sposvxx,SPOSVXX) +#define LAPACK_zposvxx LAPACK_GLOBAL(zposvxx,ZPOSVXX) +#define LAPACK_cposvxx LAPACK_GLOBAL(cposvxx,CPOSVXX) +#define LAPACK_sppsv LAPACK_GLOBAL(sppsv,SPPSV) +#define LAPACK_dppsv LAPACK_GLOBAL(dppsv,DPPSV) +#define LAPACK_cppsv LAPACK_GLOBAL(cppsv,CPPSV) +#define LAPACK_zppsv LAPACK_GLOBAL(zppsv,ZPPSV) +#define LAPACK_sppsvx LAPACK_GLOBAL(sppsvx,SPPSVX) +#define LAPACK_dppsvx LAPACK_GLOBAL(dppsvx,DPPSVX) +#define LAPACK_cppsvx LAPACK_GLOBAL(cppsvx,CPPSVX) +#define LAPACK_zppsvx LAPACK_GLOBAL(zppsvx,ZPPSVX) +#define LAPACK_spbsv LAPACK_GLOBAL(spbsv,SPBSV) +#define LAPACK_dpbsv LAPACK_GLOBAL(dpbsv,DPBSV) +#define LAPACK_cpbsv LAPACK_GLOBAL(cpbsv,CPBSV) +#define LAPACK_zpbsv LAPACK_GLOBAL(zpbsv,ZPBSV) +#define LAPACK_spbsvx LAPACK_GLOBAL(spbsvx,SPBSVX) +#define LAPACK_dpbsvx LAPACK_GLOBAL(dpbsvx,DPBSVX) +#define LAPACK_cpbsvx LAPACK_GLOBAL(cpbsvx,CPBSVX) +#define LAPACK_zpbsvx LAPACK_GLOBAL(zpbsvx,ZPBSVX) +#define LAPACK_sptsv LAPACK_GLOBAL(sptsv,SPTSV) +#define LAPACK_dptsv LAPACK_GLOBAL(dptsv,DPTSV) +#define LAPACK_cptsv LAPACK_GLOBAL(cptsv,CPTSV) +#define LAPACK_zptsv LAPACK_GLOBAL(zptsv,ZPTSV) +#define LAPACK_sptsvx LAPACK_GLOBAL(sptsvx,SPTSVX) +#define LAPACK_dptsvx LAPACK_GLOBAL(dptsvx,DPTSVX) +#define LAPACK_cptsvx LAPACK_GLOBAL(cptsvx,CPTSVX) +#define LAPACK_zptsvx LAPACK_GLOBAL(zptsvx,ZPTSVX) +#define LAPACK_ssysv LAPACK_GLOBAL(ssysv,SSYSV) +#define LAPACK_dsysv LAPACK_GLOBAL(dsysv,DSYSV) +#define LAPACK_csysv LAPACK_GLOBAL(csysv,CSYSV) +#define LAPACK_zsysv LAPACK_GLOBAL(zsysv,ZSYSV) +#define LAPACK_ssysvx LAPACK_GLOBAL(ssysvx,SSYSVX) +#define LAPACK_dsysvx LAPACK_GLOBAL(dsysvx,DSYSVX) +#define LAPACK_csysvx LAPACK_GLOBAL(csysvx,CSYSVX) +#define LAPACK_zsysvx LAPACK_GLOBAL(zsysvx,ZSYSVX) +#define LAPACK_dsysvxx LAPACK_GLOBAL(dsysvxx,DSYSVXX) +#define LAPACK_ssysvxx LAPACK_GLOBAL(ssysvxx,SSYSVXX) +#define LAPACK_zsysvxx LAPACK_GLOBAL(zsysvxx,ZSYSVXX) +#define LAPACK_csysvxx LAPACK_GLOBAL(csysvxx,CSYSVXX) +#define LAPACK_chesv LAPACK_GLOBAL(chesv,CHESV) +#define LAPACK_zhesv LAPACK_GLOBAL(zhesv,ZHESV) +#define LAPACK_chesvx LAPACK_GLOBAL(chesvx,CHESVX) +#define LAPACK_zhesvx LAPACK_GLOBAL(zhesvx,ZHESVX) +#define LAPACK_zhesvxx LAPACK_GLOBAL(zhesvxx,ZHESVXX) +#define LAPACK_chesvxx LAPACK_GLOBAL(chesvxx,CHESVXX) +#define LAPACK_sspsv LAPACK_GLOBAL(sspsv,SSPSV) +#define LAPACK_dspsv LAPACK_GLOBAL(dspsv,DSPSV) +#define LAPACK_cspsv LAPACK_GLOBAL(cspsv,CSPSV) +#define LAPACK_zspsv LAPACK_GLOBAL(zspsv,ZSPSV) +#define LAPACK_sspsvx LAPACK_GLOBAL(sspsvx,SSPSVX) +#define LAPACK_dspsvx LAPACK_GLOBAL(dspsvx,DSPSVX) +#define LAPACK_cspsvx LAPACK_GLOBAL(cspsvx,CSPSVX) +#define LAPACK_zspsvx LAPACK_GLOBAL(zspsvx,ZSPSVX) +#define LAPACK_chpsv LAPACK_GLOBAL(chpsv,CHPSV) +#define LAPACK_zhpsv LAPACK_GLOBAL(zhpsv,ZHPSV) +#define LAPACK_chpsvx LAPACK_GLOBAL(chpsvx,CHPSVX) +#define LAPACK_zhpsvx LAPACK_GLOBAL(zhpsvx,ZHPSVX) +#define LAPACK_sgeqrf LAPACK_GLOBAL(sgeqrf,SGEQRF) +#define LAPACK_dgeqrf LAPACK_GLOBAL(dgeqrf,DGEQRF) +#define LAPACK_cgeqrf LAPACK_GLOBAL(cgeqrf,CGEQRF) +#define LAPACK_zgeqrf LAPACK_GLOBAL(zgeqrf,ZGEQRF) +#define LAPACK_sgeqpf LAPACK_GLOBAL(sgeqpf,SGEQPF) +#define LAPACK_dgeqpf LAPACK_GLOBAL(dgeqpf,DGEQPF) +#define LAPACK_cgeqpf LAPACK_GLOBAL(cgeqpf,CGEQPF) +#define LAPACK_zgeqpf LAPACK_GLOBAL(zgeqpf,ZGEQPF) +#define LAPACK_sgeqp3 LAPACK_GLOBAL(sgeqp3,SGEQP3) +#define LAPACK_dgeqp3 LAPACK_GLOBAL(dgeqp3,DGEQP3) +#define LAPACK_cgeqp3 LAPACK_GLOBAL(cgeqp3,CGEQP3) +#define LAPACK_zgeqp3 LAPACK_GLOBAL(zgeqp3,ZGEQP3) +#define LAPACK_sorgqr LAPACK_GLOBAL(sorgqr,SORGQR) +#define LAPACK_dorgqr LAPACK_GLOBAL(dorgqr,DORGQR) +#define LAPACK_sormqr LAPACK_GLOBAL(sormqr,SORMQR) +#define LAPACK_dormqr LAPACK_GLOBAL(dormqr,DORMQR) +#define LAPACK_cungqr LAPACK_GLOBAL(cungqr,CUNGQR) +#define LAPACK_zungqr LAPACK_GLOBAL(zungqr,ZUNGQR) +#define LAPACK_cunmqr LAPACK_GLOBAL(cunmqr,CUNMQR) +#define LAPACK_zunmqr LAPACK_GLOBAL(zunmqr,ZUNMQR) +#define LAPACK_sgelqf LAPACK_GLOBAL(sgelqf,SGELQF) +#define LAPACK_dgelqf LAPACK_GLOBAL(dgelqf,DGELQF) +#define LAPACK_cgelqf LAPACK_GLOBAL(cgelqf,CGELQF) +#define LAPACK_zgelqf LAPACK_GLOBAL(zgelqf,ZGELQF) +#define LAPACK_sorglq LAPACK_GLOBAL(sorglq,SORGLQ) +#define LAPACK_dorglq LAPACK_GLOBAL(dorglq,DORGLQ) +#define LAPACK_sormlq LAPACK_GLOBAL(sormlq,SORMLQ) +#define LAPACK_dormlq LAPACK_GLOBAL(dormlq,DORMLQ) +#define LAPACK_cunglq LAPACK_GLOBAL(cunglq,CUNGLQ) +#define LAPACK_zunglq LAPACK_GLOBAL(zunglq,ZUNGLQ) +#define LAPACK_cunmlq LAPACK_GLOBAL(cunmlq,CUNMLQ) +#define LAPACK_zunmlq LAPACK_GLOBAL(zunmlq,ZUNMLQ) +#define LAPACK_sgeqlf LAPACK_GLOBAL(sgeqlf,SGEQLF) +#define LAPACK_dgeqlf LAPACK_GLOBAL(dgeqlf,DGEQLF) +#define LAPACK_cgeqlf LAPACK_GLOBAL(cgeqlf,CGEQLF) +#define LAPACK_zgeqlf LAPACK_GLOBAL(zgeqlf,ZGEQLF) +#define LAPACK_sorgql LAPACK_GLOBAL(sorgql,SORGQL) +#define LAPACK_dorgql LAPACK_GLOBAL(dorgql,DORGQL) +#define LAPACK_cungql LAPACK_GLOBAL(cungql,CUNGQL) +#define LAPACK_zungql LAPACK_GLOBAL(zungql,ZUNGQL) +#define LAPACK_sormql LAPACK_GLOBAL(sormql,SORMQL) +#define LAPACK_dormql LAPACK_GLOBAL(dormql,DORMQL) +#define LAPACK_cunmql LAPACK_GLOBAL(cunmql,CUNMQL) +#define LAPACK_zunmql LAPACK_GLOBAL(zunmql,ZUNMQL) +#define LAPACK_sgerqf LAPACK_GLOBAL(sgerqf,SGERQF) +#define LAPACK_dgerqf LAPACK_GLOBAL(dgerqf,DGERQF) +#define LAPACK_cgerqf LAPACK_GLOBAL(cgerqf,CGERQF) +#define LAPACK_zgerqf LAPACK_GLOBAL(zgerqf,ZGERQF) +#define LAPACK_sorgrq LAPACK_GLOBAL(sorgrq,SORGRQ) +#define LAPACK_dorgrq LAPACK_GLOBAL(dorgrq,DORGRQ) +#define LAPACK_cungrq LAPACK_GLOBAL(cungrq,CUNGRQ) +#define LAPACK_zungrq LAPACK_GLOBAL(zungrq,ZUNGRQ) +#define LAPACK_sormrq LAPACK_GLOBAL(sormrq,SORMRQ) +#define LAPACK_dormrq LAPACK_GLOBAL(dormrq,DORMRQ) +#define LAPACK_cunmrq LAPACK_GLOBAL(cunmrq,CUNMRQ) +#define LAPACK_zunmrq LAPACK_GLOBAL(zunmrq,ZUNMRQ) +#define LAPACK_stzrzf LAPACK_GLOBAL(stzrzf,STZRZF) +#define LAPACK_dtzrzf LAPACK_GLOBAL(dtzrzf,DTZRZF) +#define LAPACK_ctzrzf LAPACK_GLOBAL(ctzrzf,CTZRZF) +#define LAPACK_ztzrzf LAPACK_GLOBAL(ztzrzf,ZTZRZF) +#define LAPACK_sormrz LAPACK_GLOBAL(sormrz,SORMRZ) +#define LAPACK_dormrz LAPACK_GLOBAL(dormrz,DORMRZ) +#define LAPACK_cunmrz LAPACK_GLOBAL(cunmrz,CUNMRZ) +#define LAPACK_zunmrz LAPACK_GLOBAL(zunmrz,ZUNMRZ) +#define LAPACK_sggqrf LAPACK_GLOBAL(sggqrf,SGGQRF) +#define LAPACK_dggqrf LAPACK_GLOBAL(dggqrf,DGGQRF) +#define LAPACK_cggqrf LAPACK_GLOBAL(cggqrf,CGGQRF) +#define LAPACK_zggqrf LAPACK_GLOBAL(zggqrf,ZGGQRF) +#define LAPACK_sggrqf LAPACK_GLOBAL(sggrqf,SGGRQF) +#define LAPACK_dggrqf LAPACK_GLOBAL(dggrqf,DGGRQF) +#define LAPACK_cggrqf LAPACK_GLOBAL(cggrqf,CGGRQF) +#define LAPACK_zggrqf LAPACK_GLOBAL(zggrqf,ZGGRQF) +#define LAPACK_sgebrd LAPACK_GLOBAL(sgebrd,SGEBRD) +#define LAPACK_dgebrd LAPACK_GLOBAL(dgebrd,DGEBRD) +#define LAPACK_cgebrd LAPACK_GLOBAL(cgebrd,CGEBRD) +#define LAPACK_zgebrd LAPACK_GLOBAL(zgebrd,ZGEBRD) +#define LAPACK_sgbbrd LAPACK_GLOBAL(sgbbrd,SGBBRD) +#define LAPACK_dgbbrd LAPACK_GLOBAL(dgbbrd,DGBBRD) +#define LAPACK_cgbbrd LAPACK_GLOBAL(cgbbrd,CGBBRD) +#define LAPACK_zgbbrd LAPACK_GLOBAL(zgbbrd,ZGBBRD) +#define LAPACK_sorgbr LAPACK_GLOBAL(sorgbr,SORGBR) +#define LAPACK_dorgbr LAPACK_GLOBAL(dorgbr,DORGBR) +#define LAPACK_sormbr LAPACK_GLOBAL(sormbr,SORMBR) +#define LAPACK_dormbr LAPACK_GLOBAL(dormbr,DORMBR) +#define LAPACK_cungbr LAPACK_GLOBAL(cungbr,CUNGBR) +#define LAPACK_zungbr LAPACK_GLOBAL(zungbr,ZUNGBR) +#define LAPACK_cunmbr LAPACK_GLOBAL(cunmbr,CUNMBR) +#define LAPACK_zunmbr LAPACK_GLOBAL(zunmbr,ZUNMBR) +#define LAPACK_sbdsqr LAPACK_GLOBAL(sbdsqr,SBDSQR) +#define LAPACK_dbdsqr LAPACK_GLOBAL(dbdsqr,DBDSQR) +#define LAPACK_cbdsqr LAPACK_GLOBAL(cbdsqr,CBDSQR) +#define LAPACK_zbdsqr LAPACK_GLOBAL(zbdsqr,ZBDSQR) +#define LAPACK_sbdsdc LAPACK_GLOBAL(sbdsdc,SBDSDC) +#define LAPACK_dbdsdc LAPACK_GLOBAL(dbdsdc,DBDSDC) +#define LAPACK_sbdsvdx LAPACK_GLOBAL(sbdsvdx,SBDSVDX) +#define LAPACK_dbdsvdx LAPACK_GLOBAL(dbdsvdx,DBDSVDX) +#define LAPACK_ssytrd LAPACK_GLOBAL(ssytrd,SSYTRD) +#define LAPACK_dsytrd LAPACK_GLOBAL(dsytrd,DSYTRD) +#define LAPACK_sorgtr LAPACK_GLOBAL(sorgtr,SORGTR) +#define LAPACK_dorgtr LAPACK_GLOBAL(dorgtr,DORGTR) +#define LAPACK_sormtr LAPACK_GLOBAL(sormtr,SORMTR) +#define LAPACK_dormtr LAPACK_GLOBAL(dormtr,DORMTR) +#define LAPACK_chetrd LAPACK_GLOBAL(chetrd,CHETRD) +#define LAPACK_zhetrd LAPACK_GLOBAL(zhetrd,ZHETRD) +#define LAPACK_cungtr LAPACK_GLOBAL(cungtr,CUNGTR) +#define LAPACK_zungtr LAPACK_GLOBAL(zungtr,ZUNGTR) +#define LAPACK_cunmtr LAPACK_GLOBAL(cunmtr,CUNMTR) +#define LAPACK_zunmtr LAPACK_GLOBAL(zunmtr,ZUNMTR) +#define LAPACK_ssptrd LAPACK_GLOBAL(ssptrd,SSPTRD) +#define LAPACK_dsptrd LAPACK_GLOBAL(dsptrd,DSPTRD) +#define LAPACK_sopgtr LAPACK_GLOBAL(sopgtr,SOPGTR) +#define LAPACK_dopgtr LAPACK_GLOBAL(dopgtr,DOPGTR) +#define LAPACK_sopmtr LAPACK_GLOBAL(sopmtr,SOPMTR) +#define LAPACK_dopmtr LAPACK_GLOBAL(dopmtr,DOPMTR) +#define LAPACK_chptrd LAPACK_GLOBAL(chptrd,CHPTRD) +#define LAPACK_zhptrd LAPACK_GLOBAL(zhptrd,ZHPTRD) +#define LAPACK_cupgtr LAPACK_GLOBAL(cupgtr,CUPGTR) +#define LAPACK_zupgtr LAPACK_GLOBAL(zupgtr,ZUPGTR) +#define LAPACK_cupmtr LAPACK_GLOBAL(cupmtr,CUPMTR) +#define LAPACK_zupmtr LAPACK_GLOBAL(zupmtr,ZUPMTR) +#define LAPACK_ssbtrd LAPACK_GLOBAL(ssbtrd,SSBTRD) +#define LAPACK_dsbtrd LAPACK_GLOBAL(dsbtrd,DSBTRD) +#define LAPACK_chbtrd LAPACK_GLOBAL(chbtrd,CHBTRD) +#define LAPACK_zhbtrd LAPACK_GLOBAL(zhbtrd,ZHBTRD) +#define LAPACK_ssterf LAPACK_GLOBAL(ssterf,SSTERF) +#define LAPACK_dsterf LAPACK_GLOBAL(dsterf,DSTERF) +#define LAPACK_ssteqr LAPACK_GLOBAL(ssteqr,SSTEQR) +#define LAPACK_dsteqr LAPACK_GLOBAL(dsteqr,DSTEQR) +#define LAPACK_csteqr LAPACK_GLOBAL(csteqr,CSTEQR) +#define LAPACK_zsteqr LAPACK_GLOBAL(zsteqr,ZSTEQR) +#define LAPACK_sstemr LAPACK_GLOBAL(sstemr,SSTEMR) +#define LAPACK_dstemr LAPACK_GLOBAL(dstemr,DSTEMR) +#define LAPACK_cstemr LAPACK_GLOBAL(cstemr,CSTEMR) +#define LAPACK_zstemr LAPACK_GLOBAL(zstemr,ZSTEMR) +#define LAPACK_sstedc LAPACK_GLOBAL(sstedc,SSTEDC) +#define LAPACK_dstedc LAPACK_GLOBAL(dstedc,DSTEDC) +#define LAPACK_cstedc LAPACK_GLOBAL(cstedc,CSTEDC) +#define LAPACK_zstedc LAPACK_GLOBAL(zstedc,ZSTEDC) +#define LAPACK_sstegr LAPACK_GLOBAL(sstegr,SSTEGR) +#define LAPACK_dstegr LAPACK_GLOBAL(dstegr,DSTEGR) +#define LAPACK_cstegr LAPACK_GLOBAL(cstegr,CSTEGR) +#define LAPACK_zstegr LAPACK_GLOBAL(zstegr,ZSTEGR) +#define LAPACK_spteqr LAPACK_GLOBAL(spteqr,SPTEQR) +#define LAPACK_dpteqr LAPACK_GLOBAL(dpteqr,DPTEQR) +#define LAPACK_cpteqr LAPACK_GLOBAL(cpteqr,CPTEQR) +#define LAPACK_zpteqr LAPACK_GLOBAL(zpteqr,ZPTEQR) +#define LAPACK_sstebz LAPACK_GLOBAL(sstebz,SSTEBZ) +#define LAPACK_dstebz LAPACK_GLOBAL(dstebz,DSTEBZ) +#define LAPACK_sstein LAPACK_GLOBAL(sstein,SSTEIN) +#define LAPACK_dstein LAPACK_GLOBAL(dstein,DSTEIN) +#define LAPACK_cstein LAPACK_GLOBAL(cstein,CSTEIN) +#define LAPACK_zstein LAPACK_GLOBAL(zstein,ZSTEIN) +#define LAPACK_sdisna LAPACK_GLOBAL(sdisna,SDISNA) +#define LAPACK_ddisna LAPACK_GLOBAL(ddisna,DDISNA) +#define LAPACK_ssygst LAPACK_GLOBAL(ssygst,SSYGST) +#define LAPACK_dsygst LAPACK_GLOBAL(dsygst,DSYGST) +#define LAPACK_chegst LAPACK_GLOBAL(chegst,CHEGST) +#define LAPACK_zhegst LAPACK_GLOBAL(zhegst,ZHEGST) +#define LAPACK_sspgst LAPACK_GLOBAL(sspgst,SSPGST) +#define LAPACK_dspgst LAPACK_GLOBAL(dspgst,DSPGST) +#define LAPACK_chpgst LAPACK_GLOBAL(chpgst,CHPGST) +#define LAPACK_zhpgst LAPACK_GLOBAL(zhpgst,ZHPGST) +#define LAPACK_ssbgst LAPACK_GLOBAL(ssbgst,SSBGST) +#define LAPACK_dsbgst LAPACK_GLOBAL(dsbgst,DSBGST) +#define LAPACK_chbgst LAPACK_GLOBAL(chbgst,CHBGST) +#define LAPACK_zhbgst LAPACK_GLOBAL(zhbgst,ZHBGST) +#define LAPACK_spbstf LAPACK_GLOBAL(spbstf,SPBSTF) +#define LAPACK_dpbstf LAPACK_GLOBAL(dpbstf,DPBSTF) +#define LAPACK_cpbstf LAPACK_GLOBAL(cpbstf,CPBSTF) +#define LAPACK_zpbstf LAPACK_GLOBAL(zpbstf,ZPBSTF) +#define LAPACK_sgehrd LAPACK_GLOBAL(sgehrd,SGEHRD) +#define LAPACK_dgehrd LAPACK_GLOBAL(dgehrd,DGEHRD) +#define LAPACK_cgehrd LAPACK_GLOBAL(cgehrd,CGEHRD) +#define LAPACK_zgehrd LAPACK_GLOBAL(zgehrd,ZGEHRD) +#define LAPACK_sorghr LAPACK_GLOBAL(sorghr,SORGHR) +#define LAPACK_dorghr LAPACK_GLOBAL(dorghr,DORGHR) +#define LAPACK_sormhr LAPACK_GLOBAL(sormhr,SORMHR) +#define LAPACK_dormhr LAPACK_GLOBAL(dormhr,DORMHR) +#define LAPACK_cunghr LAPACK_GLOBAL(cunghr,CUNGHR) +#define LAPACK_zunghr LAPACK_GLOBAL(zunghr,ZUNGHR) +#define LAPACK_cunmhr LAPACK_GLOBAL(cunmhr,CUNMHR) +#define LAPACK_zunmhr LAPACK_GLOBAL(zunmhr,ZUNMHR) +#define LAPACK_sgebal LAPACK_GLOBAL(sgebal,SGEBAL) +#define LAPACK_dgebal LAPACK_GLOBAL(dgebal,DGEBAL) +#define LAPACK_cgebal LAPACK_GLOBAL(cgebal,CGEBAL) +#define LAPACK_zgebal LAPACK_GLOBAL(zgebal,ZGEBAL) +#define LAPACK_sgebak LAPACK_GLOBAL(sgebak,SGEBAK) +#define LAPACK_dgebak LAPACK_GLOBAL(dgebak,DGEBAK) +#define LAPACK_cgebak LAPACK_GLOBAL(cgebak,CGEBAK) +#define LAPACK_zgebak LAPACK_GLOBAL(zgebak,ZGEBAK) +#define LAPACK_shseqr LAPACK_GLOBAL(shseqr,SHSEQR) +#define LAPACK_dhseqr LAPACK_GLOBAL(dhseqr,DHSEQR) +#define LAPACK_chseqr LAPACK_GLOBAL(chseqr,CHSEQR) +#define LAPACK_zhseqr LAPACK_GLOBAL(zhseqr,ZHSEQR) +#define LAPACK_shsein LAPACK_GLOBAL(shsein,SHSEIN) +#define LAPACK_dhsein LAPACK_GLOBAL(dhsein,DHSEIN) +#define LAPACK_chsein LAPACK_GLOBAL(chsein,CHSEIN) +#define LAPACK_zhsein LAPACK_GLOBAL(zhsein,ZHSEIN) +#define LAPACK_strevc LAPACK_GLOBAL(strevc,STREVC) +#define LAPACK_dtrevc LAPACK_GLOBAL(dtrevc,DTREVC) +#define LAPACK_ctrevc LAPACK_GLOBAL(ctrevc,CTREVC) +#define LAPACK_ztrevc LAPACK_GLOBAL(ztrevc,ZTREVC) +#define LAPACK_strsna LAPACK_GLOBAL(strsna,STRSNA) +#define LAPACK_dtrsna LAPACK_GLOBAL(dtrsna,DTRSNA) +#define LAPACK_ctrsna LAPACK_GLOBAL(ctrsna,CTRSNA) +#define LAPACK_ztrsna LAPACK_GLOBAL(ztrsna,ZTRSNA) +#define LAPACK_strexc LAPACK_GLOBAL(strexc,STREXC) +#define LAPACK_dtrexc LAPACK_GLOBAL(dtrexc,DTREXC) +#define LAPACK_ctrexc LAPACK_GLOBAL(ctrexc,CTREXC) +#define LAPACK_ztrexc LAPACK_GLOBAL(ztrexc,ZTREXC) +#define LAPACK_strsen LAPACK_GLOBAL(strsen,STRSEN) +#define LAPACK_dtrsen LAPACK_GLOBAL(dtrsen,DTRSEN) +#define LAPACK_ctrsen LAPACK_GLOBAL(ctrsen,CTRSEN) +#define LAPACK_ztrsen LAPACK_GLOBAL(ztrsen,ZTRSEN) +#define LAPACK_strsyl LAPACK_GLOBAL(strsyl,STRSYL) +#define LAPACK_dtrsyl LAPACK_GLOBAL(dtrsyl,DTRSYL) +#define LAPACK_ctrsyl LAPACK_GLOBAL(ctrsyl,CTRSYL) +#define LAPACK_ztrsyl LAPACK_GLOBAL(ztrsyl,ZTRSYL) +#define LAPACK_sgghrd LAPACK_GLOBAL(sgghrd,SGGHRD) +#define LAPACK_dgghrd LAPACK_GLOBAL(dgghrd,DGGHRD) +#define LAPACK_cgghrd LAPACK_GLOBAL(cgghrd,CGGHRD) +#define LAPACK_zgghrd LAPACK_GLOBAL(zgghrd,ZGGHRD) +#define LAPACK_sgghd3 LAPACK_GLOBAL(sgghd3,SGGHD3) +#define LAPACK_dgghd3 LAPACK_GLOBAL(dgghd3,DGGHD3) +#define LAPACK_cgghd3 LAPACK_GLOBAL(cgghd3,CGGHD3) +#define LAPACK_zgghd3 LAPACK_GLOBAL(zgghd3,ZGGHD3) +#define LAPACK_sggbal LAPACK_GLOBAL(sggbal,SGGBAL) +#define LAPACK_dggbal LAPACK_GLOBAL(dggbal,DGGBAL) +#define LAPACK_cggbal LAPACK_GLOBAL(cggbal,CGGBAL) +#define LAPACK_zggbal LAPACK_GLOBAL(zggbal,ZGGBAL) +#define LAPACK_sggbak LAPACK_GLOBAL(sggbak,SGGBAK) +#define LAPACK_dggbak LAPACK_GLOBAL(dggbak,DGGBAK) +#define LAPACK_cggbak LAPACK_GLOBAL(cggbak,CGGBAK) +#define LAPACK_zggbak LAPACK_GLOBAL(zggbak,ZGGBAK) +#define LAPACK_shgeqz LAPACK_GLOBAL(shgeqz,SHGEQZ) +#define LAPACK_dhgeqz LAPACK_GLOBAL(dhgeqz,DHGEQZ) +#define LAPACK_chgeqz LAPACK_GLOBAL(chgeqz,CHGEQZ) +#define LAPACK_zhgeqz LAPACK_GLOBAL(zhgeqz,ZHGEQZ) +#define LAPACK_stgevc LAPACK_GLOBAL(stgevc,STGEVC) +#define LAPACK_dtgevc LAPACK_GLOBAL(dtgevc,DTGEVC) +#define LAPACK_ctgevc LAPACK_GLOBAL(ctgevc,CTGEVC) +#define LAPACK_ztgevc LAPACK_GLOBAL(ztgevc,ZTGEVC) +#define LAPACK_stgexc LAPACK_GLOBAL(stgexc,STGEXC) +#define LAPACK_dtgexc LAPACK_GLOBAL(dtgexc,DTGEXC) +#define LAPACK_ctgexc LAPACK_GLOBAL(ctgexc,CTGEXC) +#define LAPACK_ztgexc LAPACK_GLOBAL(ztgexc,ZTGEXC) +#define LAPACK_stgsen LAPACK_GLOBAL(stgsen,STGSEN) +#define LAPACK_dtgsen LAPACK_GLOBAL(dtgsen,DTGSEN) +#define LAPACK_ctgsen LAPACK_GLOBAL(ctgsen,CTGSEN) +#define LAPACK_ztgsen LAPACK_GLOBAL(ztgsen,ZTGSEN) +#define LAPACK_stgsyl LAPACK_GLOBAL(stgsyl,STGSYL) +#define LAPACK_dtgsyl LAPACK_GLOBAL(dtgsyl,DTGSYL) +#define LAPACK_ctgsyl LAPACK_GLOBAL(ctgsyl,CTGSYL) +#define LAPACK_ztgsyl LAPACK_GLOBAL(ztgsyl,ZTGSYL) +#define LAPACK_stgsna LAPACK_GLOBAL(stgsna,STGSNA) +#define LAPACK_dtgsna LAPACK_GLOBAL(dtgsna,DTGSNA) +#define LAPACK_ctgsna LAPACK_GLOBAL(ctgsna,CTGSNA) +#define LAPACK_ztgsna LAPACK_GLOBAL(ztgsna,ZTGSNA) +#define LAPACK_sggsvp LAPACK_GLOBAL(sggsvp,SGGSVP) +#define LAPACK_dggsvp LAPACK_GLOBAL(dggsvp,DGGSVP) +#define LAPACK_cggsvp LAPACK_GLOBAL(cggsvp,CGGSVP) +#define LAPACK_zggsvp LAPACK_GLOBAL(zggsvp,ZGGSVP) +#define LAPACK_sggsvp3 LAPACK_GLOBAL(sggsvp3,SGGSVP3) +#define LAPACK_dggsvp3 LAPACK_GLOBAL(dggsvp3,DGGSVP3) +#define LAPACK_cggsvp3 LAPACK_GLOBAL(cggsvp3,CGGSVP3) +#define LAPACK_zggsvp3 LAPACK_GLOBAL(zggsvp3,ZGGSVP3) +#define LAPACK_stgsja LAPACK_GLOBAL(stgsja,STGSJA) +#define LAPACK_dtgsja LAPACK_GLOBAL(dtgsja,DTGSJA) +#define LAPACK_ctgsja LAPACK_GLOBAL(ctgsja,CTGSJA) +#define LAPACK_ztgsja LAPACK_GLOBAL(ztgsja,ZTGSJA) +#define LAPACK_sgels LAPACK_GLOBAL(sgels,SGELS) +#define LAPACK_dgels LAPACK_GLOBAL(dgels,DGELS) +#define LAPACK_cgels LAPACK_GLOBAL(cgels,CGELS) +#define LAPACK_zgels LAPACK_GLOBAL(zgels,ZGELS) +#define LAPACK_sgelsy LAPACK_GLOBAL(sgelsy,SGELSY) +#define LAPACK_dgelsy LAPACK_GLOBAL(dgelsy,DGELSY) +#define LAPACK_cgelsy LAPACK_GLOBAL(cgelsy,CGELSY) +#define LAPACK_zgelsy LAPACK_GLOBAL(zgelsy,ZGELSY) +#define LAPACK_sgelss LAPACK_GLOBAL(sgelss,SGELSS) +#define LAPACK_dgelss LAPACK_GLOBAL(dgelss,DGELSS) +#define LAPACK_cgelss LAPACK_GLOBAL(cgelss,CGELSS) +#define LAPACK_zgelss LAPACK_GLOBAL(zgelss,ZGELSS) +#define LAPACK_sgelsd LAPACK_GLOBAL(sgelsd,SGELSD) +#define LAPACK_dgelsd LAPACK_GLOBAL(dgelsd,DGELSD) +#define LAPACK_cgelsd LAPACK_GLOBAL(cgelsd,CGELSD) +#define LAPACK_zgelsd LAPACK_GLOBAL(zgelsd,ZGELSD) +#define LAPACK_sgglse LAPACK_GLOBAL(sgglse,SGGLSE) +#define LAPACK_dgglse LAPACK_GLOBAL(dgglse,DGGLSE) +#define LAPACK_cgglse LAPACK_GLOBAL(cgglse,CGGLSE) +#define LAPACK_zgglse LAPACK_GLOBAL(zgglse,ZGGLSE) +#define LAPACK_sggglm LAPACK_GLOBAL(sggglm,SGGGLM) +#define LAPACK_dggglm LAPACK_GLOBAL(dggglm,DGGGLM) +#define LAPACK_cggglm LAPACK_GLOBAL(cggglm,CGGGLM) +#define LAPACK_zggglm LAPACK_GLOBAL(zggglm,ZGGGLM) +#define LAPACK_ssyev LAPACK_GLOBAL(ssyev,SSYEV) +#define LAPACK_dsyev LAPACK_GLOBAL(dsyev,DSYEV) +#define LAPACK_cheev LAPACK_GLOBAL(cheev,CHEEV) +#define LAPACK_zheev LAPACK_GLOBAL(zheev,ZHEEV) +#define LAPACK_ssyevd LAPACK_GLOBAL(ssyevd,SSYEVD) +#define LAPACK_dsyevd LAPACK_GLOBAL(dsyevd,DSYEVD) +#define LAPACK_cheevd LAPACK_GLOBAL(cheevd,CHEEVD) +#define LAPACK_zheevd LAPACK_GLOBAL(zheevd,ZHEEVD) +#define LAPACK_ssyevx LAPACK_GLOBAL(ssyevx,SSYEVX) +#define LAPACK_dsyevx LAPACK_GLOBAL(dsyevx,DSYEVX) +#define LAPACK_cheevx LAPACK_GLOBAL(cheevx,CHEEVX) +#define LAPACK_zheevx LAPACK_GLOBAL(zheevx,ZHEEVX) +#define LAPACK_ssyevr LAPACK_GLOBAL(ssyevr,SSYEVR) +#define LAPACK_dsyevr LAPACK_GLOBAL(dsyevr,DSYEVR) +#define LAPACK_cheevr LAPACK_GLOBAL(cheevr,CHEEVR) +#define LAPACK_zheevr LAPACK_GLOBAL(zheevr,ZHEEVR) +#define LAPACK_sspev LAPACK_GLOBAL(sspev,SSPEV) +#define LAPACK_dspev LAPACK_GLOBAL(dspev,DSPEV) +#define LAPACK_chpev LAPACK_GLOBAL(chpev,CHPEV) +#define LAPACK_zhpev LAPACK_GLOBAL(zhpev,ZHPEV) +#define LAPACK_sspevd LAPACK_GLOBAL(sspevd,SSPEVD) +#define LAPACK_dspevd LAPACK_GLOBAL(dspevd,DSPEVD) +#define LAPACK_chpevd LAPACK_GLOBAL(chpevd,CHPEVD) +#define LAPACK_zhpevd LAPACK_GLOBAL(zhpevd,ZHPEVD) +#define LAPACK_sspevx LAPACK_GLOBAL(sspevx,SSPEVX) +#define LAPACK_dspevx LAPACK_GLOBAL(dspevx,DSPEVX) +#define LAPACK_chpevx LAPACK_GLOBAL(chpevx,CHPEVX) +#define LAPACK_zhpevx LAPACK_GLOBAL(zhpevx,ZHPEVX) +#define LAPACK_ssbev LAPACK_GLOBAL(ssbev,SSBEV) +#define LAPACK_dsbev LAPACK_GLOBAL(dsbev,DSBEV) +#define LAPACK_chbev LAPACK_GLOBAL(chbev,CHBEV) +#define LAPACK_zhbev LAPACK_GLOBAL(zhbev,ZHBEV) +#define LAPACK_ssbevd LAPACK_GLOBAL(ssbevd,SSBEVD) +#define LAPACK_dsbevd LAPACK_GLOBAL(dsbevd,DSBEVD) +#define LAPACK_chbevd LAPACK_GLOBAL(chbevd,CHBEVD) +#define LAPACK_zhbevd LAPACK_GLOBAL(zhbevd,ZHBEVD) +#define LAPACK_ssbevx LAPACK_GLOBAL(ssbevx,SSBEVX) +#define LAPACK_dsbevx LAPACK_GLOBAL(dsbevx,DSBEVX) +#define LAPACK_chbevx LAPACK_GLOBAL(chbevx,CHBEVX) +#define LAPACK_zhbevx LAPACK_GLOBAL(zhbevx,ZHBEVX) +#define LAPACK_sstev LAPACK_GLOBAL(sstev,SSTEV) +#define LAPACK_dstev LAPACK_GLOBAL(dstev,DSTEV) +#define LAPACK_sstevd LAPACK_GLOBAL(sstevd,SSTEVD) +#define LAPACK_dstevd LAPACK_GLOBAL(dstevd,DSTEVD) +#define LAPACK_sstevx LAPACK_GLOBAL(sstevx,SSTEVX) +#define LAPACK_dstevx LAPACK_GLOBAL(dstevx,DSTEVX) +#define LAPACK_sstevr LAPACK_GLOBAL(sstevr,SSTEVR) +#define LAPACK_dstevr LAPACK_GLOBAL(dstevr,DSTEVR) +#define LAPACK_sgees LAPACK_GLOBAL(sgees,SGEES) +#define LAPACK_dgees LAPACK_GLOBAL(dgees,DGEES) +#define LAPACK_cgees LAPACK_GLOBAL(cgees,CGEES) +#define LAPACK_zgees LAPACK_GLOBAL(zgees,ZGEES) +#define LAPACK_sgeesx LAPACK_GLOBAL(sgeesx,SGEESX) +#define LAPACK_dgeesx LAPACK_GLOBAL(dgeesx,DGEESX) +#define LAPACK_cgeesx LAPACK_GLOBAL(cgeesx,CGEESX) +#define LAPACK_zgeesx LAPACK_GLOBAL(zgeesx,ZGEESX) +#define LAPACK_sgeev LAPACK_GLOBAL(sgeev,SGEEV) +#define LAPACK_dgeev LAPACK_GLOBAL(dgeev,DGEEV) +#define LAPACK_cgeev LAPACK_GLOBAL(cgeev,CGEEV) +#define LAPACK_zgeev LAPACK_GLOBAL(zgeev,ZGEEV) +#define LAPACK_sgeevx LAPACK_GLOBAL(sgeevx,SGEEVX) +#define LAPACK_dgeevx LAPACK_GLOBAL(dgeevx,DGEEVX) +#define LAPACK_cgeevx LAPACK_GLOBAL(cgeevx,CGEEVX) +#define LAPACK_zgeevx LAPACK_GLOBAL(zgeevx,ZGEEVX) +#define LAPACK_sgesvd LAPACK_GLOBAL(sgesvd,SGESVD) +#define LAPACK_dgesvd LAPACK_GLOBAL(dgesvd,DGESVD) +#define LAPACK_cgesvd LAPACK_GLOBAL(cgesvd,CGESVD) +#define LAPACK_zgesvd LAPACK_GLOBAL(zgesvd,ZGESVD) +#define LAPACK_sgesvdx LAPACK_GLOBAL(sgesvdx,SGESVDX) +#define LAPACK_dgesvdx LAPACK_GLOBAL(dgesvdx,DGESVDX) +#define LAPACK_cgesvdx LAPACK_GLOBAL(cgesvdx,CGESVDX) +#define LAPACK_zgesvdx LAPACK_GLOBAL(zgesvdx,ZGESVDX) +#define LAPACK_sgesdd LAPACK_GLOBAL(sgesdd,SGESDD) +#define LAPACK_dgesdd LAPACK_GLOBAL(dgesdd,DGESDD) +#define LAPACK_cgesdd LAPACK_GLOBAL(cgesdd,CGESDD) +#define LAPACK_zgesdd LAPACK_GLOBAL(zgesdd,ZGESDD) +#define LAPACK_sgejsv LAPACK_GLOBAL(sgejsv,SGEJSV) +#define LAPACK_dgejsv LAPACK_GLOBAL(dgejsv,DGEJSV) +#define LAPACK_cgejsv LAPACK_GLOBAL(cgejsv,CGEJSV) +#define LAPACK_zgejsv LAPACK_GLOBAL(zgejsv,ZGEJSV) +#define LAPACK_sgesvj LAPACK_GLOBAL(sgesvj,SGESVJ) +#define LAPACK_dgesvj LAPACK_GLOBAL(dgesvj,DGESVJ) +#define LAPACK_cgesvj LAPACK_GLOBAL(cgesvj,CGESVJ) +#define LAPACK_zgesvj LAPACK_GLOBAL(zgesvj,ZGESVJ) +#define LAPACK_sggsvd LAPACK_GLOBAL(sggsvd,SGGSVD) +#define LAPACK_dggsvd LAPACK_GLOBAL(dggsvd,DGGSVD) +#define LAPACK_cggsvd LAPACK_GLOBAL(cggsvd,CGGSVD) +#define LAPACK_zggsvd LAPACK_GLOBAL(zggsvd,ZGGSVD) +#define LAPACK_ssygv LAPACK_GLOBAL(ssygv,SSYGV) +#define LAPACK_dsygv LAPACK_GLOBAL(dsygv,DSYGV) +#define LAPACK_chegv LAPACK_GLOBAL(chegv,CHEGV) +#define LAPACK_zhegv LAPACK_GLOBAL(zhegv,ZHEGV) +#define LAPACK_ssygvd LAPACK_GLOBAL(ssygvd,SSYGVD) +#define LAPACK_dsygvd LAPACK_GLOBAL(dsygvd,DSYGVD) +#define LAPACK_chegvd LAPACK_GLOBAL(chegvd,CHEGVD) +#define LAPACK_zhegvd LAPACK_GLOBAL(zhegvd,ZHEGVD) +#define LAPACK_ssygvx LAPACK_GLOBAL(ssygvx,SSYGVX) +#define LAPACK_dsygvx LAPACK_GLOBAL(dsygvx,DSYGVX) +#define LAPACK_chegvx LAPACK_GLOBAL(chegvx,CHEGVX) +#define LAPACK_zhegvx LAPACK_GLOBAL(zhegvx,ZHEGVX) +#define LAPACK_sspgv LAPACK_GLOBAL(sspgv,SSPGV) +#define LAPACK_dspgv LAPACK_GLOBAL(dspgv,DSPGV) +#define LAPACK_chpgv LAPACK_GLOBAL(chpgv,CHPGV) +#define LAPACK_zhpgv LAPACK_GLOBAL(zhpgv,ZHPGV) +#define LAPACK_sspgvd LAPACK_GLOBAL(sspgvd,SSPGVD) +#define LAPACK_dspgvd LAPACK_GLOBAL(dspgvd,DSPGVD) +#define LAPACK_chpgvd LAPACK_GLOBAL(chpgvd,CHPGVD) +#define LAPACK_zhpgvd LAPACK_GLOBAL(zhpgvd,ZHPGVD) +#define LAPACK_sspgvx LAPACK_GLOBAL(sspgvx,SSPGVX) +#define LAPACK_dspgvx LAPACK_GLOBAL(dspgvx,DSPGVX) +#define LAPACK_chpgvx LAPACK_GLOBAL(chpgvx,CHPGVX) +#define LAPACK_zhpgvx LAPACK_GLOBAL(zhpgvx,ZHPGVX) +#define LAPACK_ssbgv LAPACK_GLOBAL(ssbgv,SSBGV) +#define LAPACK_dsbgv LAPACK_GLOBAL(dsbgv,DSBGV) +#define LAPACK_chbgv LAPACK_GLOBAL(chbgv,CHBGV) +#define LAPACK_zhbgv LAPACK_GLOBAL(zhbgv,ZHBGV) +#define LAPACK_ssbgvd LAPACK_GLOBAL(ssbgvd,SSBGVD) +#define LAPACK_dsbgvd LAPACK_GLOBAL(dsbgvd,DSBGVD) +#define LAPACK_chbgvd LAPACK_GLOBAL(chbgvd,CHBGVD) +#define LAPACK_zhbgvd LAPACK_GLOBAL(zhbgvd,ZHBGVD) +#define LAPACK_ssbgvx LAPACK_GLOBAL(ssbgvx,SSBGVX) +#define LAPACK_dsbgvx LAPACK_GLOBAL(dsbgvx,DSBGVX) +#define LAPACK_chbgvx LAPACK_GLOBAL(chbgvx,CHBGVX) +#define LAPACK_zhbgvx LAPACK_GLOBAL(zhbgvx,ZHBGVX) +#define LAPACK_sgges LAPACK_GLOBAL(sgges,SGGES) +#define LAPACK_dgges LAPACK_GLOBAL(dgges,DGGES) +#define LAPACK_cgges LAPACK_GLOBAL(cgges,CGGES) +#define LAPACK_zgges LAPACK_GLOBAL(zgges,ZGGES) +#define LAPACK_sgges3 LAPACK_GLOBAL(sgges3,SGGES3) +#define LAPACK_dgges3 LAPACK_GLOBAL(dgges3,DGGES3) +#define LAPACK_cgges3 LAPACK_GLOBAL(cgges3,CGGES3) +#define LAPACK_zgges3 LAPACK_GLOBAL(zgges3,ZGGES3) +#define LAPACK_sggesx LAPACK_GLOBAL(sggesx,SGGESX) +#define LAPACK_dggesx LAPACK_GLOBAL(dggesx,DGGESX) +#define LAPACK_cggesx LAPACK_GLOBAL(cggesx,CGGESX) +#define LAPACK_zggesx LAPACK_GLOBAL(zggesx,ZGGESX) +#define LAPACK_sggev LAPACK_GLOBAL(sggev,SGGEV) +#define LAPACK_dggev LAPACK_GLOBAL(dggev,DGGEV) +#define LAPACK_cggev LAPACK_GLOBAL(cggev,CGGEV) +#define LAPACK_zggev LAPACK_GLOBAL(zggev,ZGGEV) +#define LAPACK_sggev3 LAPACK_GLOBAL(sggev3,SGGEV3) +#define LAPACK_dggev3 LAPACK_GLOBAL(dggev3,DGGEV3) +#define LAPACK_cggev3 LAPACK_GLOBAL(cggev3,CGGEV3) +#define LAPACK_zggev3 LAPACK_GLOBAL(zggev3,ZGGEV3) +#define LAPACK_sggevx LAPACK_GLOBAL(sggevx,SGGEVX) +#define LAPACK_dggevx LAPACK_GLOBAL(dggevx,DGGEVX) +#define LAPACK_cggevx LAPACK_GLOBAL(cggevx,CGGEVX) +#define LAPACK_zggevx LAPACK_GLOBAL(zggevx,ZGGEVX) +#define LAPACK_dsfrk LAPACK_GLOBAL(dsfrk,DSFRK) +#define LAPACK_ssfrk LAPACK_GLOBAL(ssfrk,SSFRK) +#define LAPACK_zhfrk LAPACK_GLOBAL(zhfrk,ZHFRK) +#define LAPACK_chfrk LAPACK_GLOBAL(chfrk,CHFRK) +#define LAPACK_dtfsm LAPACK_GLOBAL(dtfsm,DTFSM) +#define LAPACK_stfsm LAPACK_GLOBAL(stfsm,STFSM) +#define LAPACK_ztfsm LAPACK_GLOBAL(ztfsm,ZTFSM) +#define LAPACK_ctfsm LAPACK_GLOBAL(ctfsm,CTFSM) +#define LAPACK_dtfttp LAPACK_GLOBAL(dtfttp,DTFTTP) +#define LAPACK_stfttp LAPACK_GLOBAL(stfttp,STFTTP) +#define LAPACK_ztfttp LAPACK_GLOBAL(ztfttp,ZTFTTP) +#define LAPACK_ctfttp LAPACK_GLOBAL(ctfttp,CTFTTP) +#define LAPACK_dtfttr LAPACK_GLOBAL(dtfttr,DTFTTR) +#define LAPACK_stfttr LAPACK_GLOBAL(stfttr,STFTTR) +#define LAPACK_ztfttr LAPACK_GLOBAL(ztfttr,ZTFTTR) +#define LAPACK_ctfttr LAPACK_GLOBAL(ctfttr,CTFTTR) +#define LAPACK_dtpttf LAPACK_GLOBAL(dtpttf,DTPTTF) +#define LAPACK_stpttf LAPACK_GLOBAL(stpttf,STPTTF) +#define LAPACK_ztpttf LAPACK_GLOBAL(ztpttf,ZTPTTF) +#define LAPACK_ctpttf LAPACK_GLOBAL(ctpttf,CTPTTF) +#define LAPACK_dtpttr LAPACK_GLOBAL(dtpttr,DTPTTR) +#define LAPACK_stpttr LAPACK_GLOBAL(stpttr,STPTTR) +#define LAPACK_ztpttr LAPACK_GLOBAL(ztpttr,ZTPTTR) +#define LAPACK_ctpttr LAPACK_GLOBAL(ctpttr,CTPTTR) +#define LAPACK_dtrttf LAPACK_GLOBAL(dtrttf,DTRTTF) +#define LAPACK_strttf LAPACK_GLOBAL(strttf,STRTTF) +#define LAPACK_ztrttf LAPACK_GLOBAL(ztrttf,ZTRTTF) +#define LAPACK_ctrttf LAPACK_GLOBAL(ctrttf,CTRTTF) +#define LAPACK_dtrttp LAPACK_GLOBAL(dtrttp,DTRTTP) +#define LAPACK_strttp LAPACK_GLOBAL(strttp,STRTTP) +#define LAPACK_ztrttp LAPACK_GLOBAL(ztrttp,ZTRTTP) +#define LAPACK_ctrttp LAPACK_GLOBAL(ctrttp,CTRTTP) +#define LAPACK_sgeqrfp LAPACK_GLOBAL(sgeqrfp,SGEQRFP) +#define LAPACK_dgeqrfp LAPACK_GLOBAL(dgeqrfp,DGEQRFP) +#define LAPACK_cgeqrfp LAPACK_GLOBAL(cgeqrfp,CGEQRFP) +#define LAPACK_zgeqrfp LAPACK_GLOBAL(zgeqrfp,ZGEQRFP) +#define LAPACK_clacgv LAPACK_GLOBAL(clacgv,CLACGV) +#define LAPACK_zlacgv LAPACK_GLOBAL(zlacgv,ZLACGV) +#define LAPACK_slarnv LAPACK_GLOBAL(slarnv,SLARNV) +#define LAPACK_dlarnv LAPACK_GLOBAL(dlarnv,DLARNV) +#define LAPACK_clarnv LAPACK_GLOBAL(clarnv,CLARNV) +#define LAPACK_zlarnv LAPACK_GLOBAL(zlarnv,ZLARNV) +#define LAPACK_sgeqr2 LAPACK_GLOBAL(sgeqr2,SGEQR2) +#define LAPACK_dgeqr2 LAPACK_GLOBAL(dgeqr2,DGEQR2) +#define LAPACK_cgeqr2 LAPACK_GLOBAL(cgeqr2,CGEQR2) +#define LAPACK_zgeqr2 LAPACK_GLOBAL(zgeqr2,ZGEQR2) +#define LAPACK_slacn2 LAPACK_GLOBAL(slacn2,SLACN2) +#define LAPACK_dlacn2 LAPACK_GLOBAL(dlacn2,DLACN2) +#define LAPACK_clacn2 LAPACK_GLOBAL(clacn2,CLACN2) +#define LAPACK_zlacn2 LAPACK_GLOBAL(zlacn2,ZLACN2) +#define LAPACK_slacpy LAPACK_GLOBAL(slacpy,SLACPY) +#define LAPACK_dlacpy LAPACK_GLOBAL(dlacpy,DLACPY) +#define LAPACK_clacpy LAPACK_GLOBAL(clacpy,CLACPY) +#define LAPACK_zlacpy LAPACK_GLOBAL(zlacpy,ZLACPY) +#define LAPACK_clacp2 LAPACK_GLOBAL(clacp2,CLACP2) +#define LAPACK_zlacp2 LAPACK_GLOBAL(zlacp2,ZLACP2) +#define LAPACK_sgetf2 LAPACK_GLOBAL(sgetf2,SGETF2) +#define LAPACK_dgetf2 LAPACK_GLOBAL(dgetf2,DGETF2) +#define LAPACK_cgetf2 LAPACK_GLOBAL(cgetf2,CGETF2) +#define LAPACK_zgetf2 LAPACK_GLOBAL(zgetf2,ZGETF2) +#define LAPACK_slaswp LAPACK_GLOBAL(slaswp,SLASWP) +#define LAPACK_dlaswp LAPACK_GLOBAL(dlaswp,DLASWP) +#define LAPACK_claswp LAPACK_GLOBAL(claswp,CLASWP) +#define LAPACK_zlaswp LAPACK_GLOBAL(zlaswp,ZLASWP) +#define LAPACK_slange LAPACK_GLOBAL(slange,SLANGE) +#define LAPACK_dlange LAPACK_GLOBAL(dlange,DLANGE) +#define LAPACK_clange LAPACK_GLOBAL(clange,CLANGE) +#define LAPACK_zlange LAPACK_GLOBAL(zlange,ZLANGE) +#define LAPACK_clanhe LAPACK_GLOBAL(clanhe,CLANHE) +#define LAPACK_zlanhe LAPACK_GLOBAL(zlanhe,ZLANHE) +#define LAPACK_slansy LAPACK_GLOBAL(slansy,SLANSY) +#define LAPACK_dlansy LAPACK_GLOBAL(dlansy,DLANSY) +#define LAPACK_clansy LAPACK_GLOBAL(clansy,CLANSY) +#define LAPACK_zlansy LAPACK_GLOBAL(zlansy,ZLANSY) +#define LAPACK_slantr LAPACK_GLOBAL(slantr,SLANTR) +#define LAPACK_dlantr LAPACK_GLOBAL(dlantr,DLANTR) +#define LAPACK_clantr LAPACK_GLOBAL(clantr,CLANTR) +#define LAPACK_zlantr LAPACK_GLOBAL(zlantr,ZLANTR) +#define LAPACK_slamch LAPACK_GLOBAL(slamch,SLAMCH) +#define LAPACK_dlamch LAPACK_GLOBAL(dlamch,DLAMCH) +#define LAPACK_sgelq2 LAPACK_GLOBAL(sgelq2,SGELQ2) +#define LAPACK_dgelq2 LAPACK_GLOBAL(dgelq2,DGELQ2) +#define LAPACK_cgelq2 LAPACK_GLOBAL(cgelq2,CGELQ2) +#define LAPACK_zgelq2 LAPACK_GLOBAL(zgelq2,ZGELQ2) +#define LAPACK_slarfb LAPACK_GLOBAL(slarfb,SLARFB) +#define LAPACK_dlarfb LAPACK_GLOBAL(dlarfb,DLARFB) +#define LAPACK_clarfb LAPACK_GLOBAL(clarfb,CLARFB) +#define LAPACK_zlarfb LAPACK_GLOBAL(zlarfb,ZLARFB) +#define LAPACK_slarfg LAPACK_GLOBAL(slarfg,SLARFG) +#define LAPACK_dlarfg LAPACK_GLOBAL(dlarfg,DLARFG) +#define LAPACK_clarfg LAPACK_GLOBAL(clarfg,CLARFG) +#define LAPACK_zlarfg LAPACK_GLOBAL(zlarfg,ZLARFG) +#define LAPACK_slarft LAPACK_GLOBAL(slarft,SLARFT) +#define LAPACK_dlarft LAPACK_GLOBAL(dlarft,DLARFT) +#define LAPACK_clarft LAPACK_GLOBAL(clarft,CLARFT) +#define LAPACK_zlarft LAPACK_GLOBAL(zlarft,ZLARFT) +#define LAPACK_slarfx LAPACK_GLOBAL(slarfx,SLARFX) +#define LAPACK_dlarfx LAPACK_GLOBAL(dlarfx,DLARFX) +#define LAPACK_clarfx LAPACK_GLOBAL(clarfx,CLARFX) +#define LAPACK_zlarfx LAPACK_GLOBAL(zlarfx,ZLARFX) +#define LAPACK_slatms LAPACK_GLOBAL(slatms,SLATMS) +#define LAPACK_dlatms LAPACK_GLOBAL(dlatms,DLATMS) +#define LAPACK_clatms LAPACK_GLOBAL(clatms,CLATMS) +#define LAPACK_zlatms LAPACK_GLOBAL(zlatms,ZLATMS) +#define LAPACK_slag2d LAPACK_GLOBAL(slag2d,SLAG2D) +#define LAPACK_dlag2s LAPACK_GLOBAL(dlag2s,DLAG2S) +#define LAPACK_clag2z LAPACK_GLOBAL(clag2z,CLAG2Z) +#define LAPACK_zlag2c LAPACK_GLOBAL(zlag2c,ZLAG2C) +#define LAPACK_slauum LAPACK_GLOBAL(slauum,SLAUUM) +#define LAPACK_dlauum LAPACK_GLOBAL(dlauum,DLAUUM) +#define LAPACK_clauum LAPACK_GLOBAL(clauum,CLAUUM) +#define LAPACK_zlauum LAPACK_GLOBAL(zlauum,ZLAUUM) +#define LAPACK_slagge LAPACK_GLOBAL(slagge,SLAGGE) +#define LAPACK_dlagge LAPACK_GLOBAL(dlagge,DLAGGE) +#define LAPACK_clagge LAPACK_GLOBAL(clagge,CLAGGE) +#define LAPACK_zlagge LAPACK_GLOBAL(zlagge,ZLAGGE) +#define LAPACK_slascl LAPACK_GLOBAL(slascl,SLASCL) +#define LAPACK_dlascl LAPACK_GLOBAL(dlascl,DLASCL) +#define LAPACK_clascl LAPACK_GLOBAL(clascl,CLASCL) +#define LAPACK_zlascl LAPACK_GLOBAL(zlascl,ZLASCL) +#define LAPACK_slaset LAPACK_GLOBAL(slaset,SLASET) +#define LAPACK_dlaset LAPACK_GLOBAL(dlaset,DLASET) +#define LAPACK_claset LAPACK_GLOBAL(claset,CLASET) +#define LAPACK_zlaset LAPACK_GLOBAL(zlaset,ZLASET) +#define LAPACK_slasrt LAPACK_GLOBAL(slasrt,SLASRT) +#define LAPACK_dlasrt LAPACK_GLOBAL(dlasrt,DLASRT) +#define LAPACK_slagsy LAPACK_GLOBAL(slagsy,SLAGSY) +#define LAPACK_dlagsy LAPACK_GLOBAL(dlagsy,DLAGSY) +#define LAPACK_clagsy LAPACK_GLOBAL(clagsy,CLAGSY) +#define LAPACK_zlagsy LAPACK_GLOBAL(zlagsy,ZLAGSY) +#define LAPACK_claghe LAPACK_GLOBAL(claghe,CLAGHE) +#define LAPACK_zlaghe LAPACK_GLOBAL(zlaghe,ZLAGHE) +#define LAPACK_slapmr LAPACK_GLOBAL(slapmr,SLAPMR) +#define LAPACK_dlapmr LAPACK_GLOBAL(dlapmr,DLAPMR) +#define LAPACK_clapmr LAPACK_GLOBAL(clapmr,CLAPMR) +#define LAPACK_zlapmr LAPACK_GLOBAL(zlapmr,ZLAPMR) +#define LAPACK_slapmt LAPACK_GLOBAL(slapmt,SLAPMT) +#define LAPACK_dlapmt LAPACK_GLOBAL(dlapmt,DLAPMT) +#define LAPACK_clapmt LAPACK_GLOBAL(clapmt,CLAPMT) +#define LAPACK_zlapmt LAPACK_GLOBAL(zlapmt,ZLAPMT) +#define LAPACK_slapy2 LAPACK_GLOBAL(slapy2,SLAPY2) +#define LAPACK_dlapy2 LAPACK_GLOBAL(dlapy2,DLAPY2) +#define LAPACK_slapy3 LAPACK_GLOBAL(slapy3,SLAPY3) +#define LAPACK_dlapy3 LAPACK_GLOBAL(dlapy3,DLAPY3) +#define LAPACK_slartgp LAPACK_GLOBAL(slartgp,SLARTGP) +#define LAPACK_dlartgp LAPACK_GLOBAL(dlartgp,DLARTGP) +#define LAPACK_slartgs LAPACK_GLOBAL(slartgs,SLARTGS) +#define LAPACK_dlartgs LAPACK_GLOBAL(dlartgs,DLARTGS) +// LAPACK 3.3.0 +#define LAPACK_cbbcsd LAPACK_GLOBAL(cbbcsd,CBBCSD) +#define LAPACK_cheswapr LAPACK_GLOBAL(cheswapr,CHESWAPR) +#define LAPACK_chetri2 LAPACK_GLOBAL(chetri2,CHETRI2) +#define LAPACK_chetri2x LAPACK_GLOBAL(chetri2x,CHETRI2X) +#define LAPACK_chetrs2 LAPACK_GLOBAL(chetrs2,CHETRS2) +#define LAPACK_csyconv LAPACK_GLOBAL(csyconv,CSYCONV) +#define LAPACK_csyswapr LAPACK_GLOBAL(csyswapr,CSYSWAPR) +#define LAPACK_csytri2 LAPACK_GLOBAL(csytri2,CSYTRI2) +#define LAPACK_csytri2x LAPACK_GLOBAL(csytri2x,CSYTRI2X) +#define LAPACK_csytrs2 LAPACK_GLOBAL(csytrs2,CSYTRS2) +#define LAPACK_cunbdb LAPACK_GLOBAL(cunbdb,CUNBDB) +#define LAPACK_cuncsd LAPACK_GLOBAL(cuncsd,CUNCSD) +#define LAPACK_cuncsd2by1 LAPACK_GLOBAL(cuncsd2by1,CUNCSD2BY1) +#define LAPACK_dbbcsd LAPACK_GLOBAL(dbbcsd,DBBCSD) +#define LAPACK_dorbdb LAPACK_GLOBAL(dorbdb,DORBDB) +#define LAPACK_dorcsd LAPACK_GLOBAL(dorcsd,DORCSD) +#define LAPACK_dorcsd2by1 LAPACK_GLOBAL(dorcsd2by1,DORCSD2BY1) +#define LAPACK_dsyconv LAPACK_GLOBAL(dsyconv,DSYCONV) +#define LAPACK_dsyswapr LAPACK_GLOBAL(dsyswapr,DSYSWAPR) +#define LAPACK_dsytri2 LAPACK_GLOBAL(dsytri2,DSYTRI2) +#define LAPACK_dsytri2x LAPACK_GLOBAL(dsytri2x,DSYTRI2X) +#define LAPACK_dsytrs2 LAPACK_GLOBAL(dsytrs2,DSYTRS2) +#define LAPACK_sbbcsd LAPACK_GLOBAL(sbbcsd,SBBCSD) +#define LAPACK_sorbdb LAPACK_GLOBAL(sorbdb,SORBDB) +#define LAPACK_sorcsd LAPACK_GLOBAL(sorcsd,SORCSD) +#define LAPACK_sorcsd2by1 LAPACK_GLOBAL(sorcsd2by1,SORCSD2BY1) +#define LAPACK_ssyconv LAPACK_GLOBAL(ssyconv,SSYCONV) +#define LAPACK_ssyswapr LAPACK_GLOBAL(ssyswapr,SSYSWAPR) +#define LAPACK_ssytri2 LAPACK_GLOBAL(ssytri2,SSYTRI2) +#define LAPACK_ssytri2x LAPACK_GLOBAL(ssytri2x,SSYTRI2X) +#define LAPACK_ssytrs2 LAPACK_GLOBAL(ssytrs2,SSYTRS2) +#define LAPACK_zbbcsd LAPACK_GLOBAL(zbbcsd,ZBBCSD) +#define LAPACK_zheswapr LAPACK_GLOBAL(zheswapr,ZHESWAPR) +#define LAPACK_zhetri2 LAPACK_GLOBAL(zhetri2,ZHETRI2) +#define LAPACK_zhetri2x LAPACK_GLOBAL(zhetri2x,ZHETRI2X) +#define LAPACK_zhetrs2 LAPACK_GLOBAL(zhetrs2,ZHETRS2) +#define LAPACK_zsyconv LAPACK_GLOBAL(zsyconv,ZSYCONV) +#define LAPACK_zsyswapr LAPACK_GLOBAL(zsyswapr,ZSYSWAPR) +#define LAPACK_zsytri2 LAPACK_GLOBAL(zsytri2,ZSYTRI2) +#define LAPACK_zsytri2x LAPACK_GLOBAL(zsytri2x,ZSYTRI2X) +#define LAPACK_zsytrs2 LAPACK_GLOBAL(zsytrs2,ZSYTRS2) +#define LAPACK_zunbdb LAPACK_GLOBAL(zunbdb,ZUNBDB) +#define LAPACK_zuncsd LAPACK_GLOBAL(zuncsd,ZUNCSD) +#define LAPACK_zuncsd2by1 LAPACK_GLOBAL(zuncsd2by1,ZUNCSD2BY1) +// LAPACK 3.4.0 +#define LAPACK_sgemqrt LAPACK_GLOBAL(sgemqrt,SGEMQRT) +#define LAPACK_dgemqrt LAPACK_GLOBAL(dgemqrt,DGEMQRT) +#define LAPACK_cgemqrt LAPACK_GLOBAL(cgemqrt,CGEMQRT) +#define LAPACK_zgemqrt LAPACK_GLOBAL(zgemqrt,ZGEMQRT) +#define LAPACK_sgeqrt LAPACK_GLOBAL(sgeqrt,SGEQRT) +#define LAPACK_dgeqrt LAPACK_GLOBAL(dgeqrt,DGEQRT) +#define LAPACK_cgeqrt LAPACK_GLOBAL(cgeqrt,CGEQRT) +#define LAPACK_zgeqrt LAPACK_GLOBAL(zgeqrt,ZGEQRT) +#define LAPACK_sgeqrt2 LAPACK_GLOBAL(sgeqrt2,SGEQRT2) +#define LAPACK_dgeqrt2 LAPACK_GLOBAL(dgeqrt2,DGEQRT2) +#define LAPACK_cgeqrt2 LAPACK_GLOBAL(cgeqrt2,CGEQRT2) +#define LAPACK_zgeqrt2 LAPACK_GLOBAL(zgeqrt2,ZGEQRT2) +#define LAPACK_sgeqrt3 LAPACK_GLOBAL(sgeqrt3,SGEQRT3) +#define LAPACK_dgeqrt3 LAPACK_GLOBAL(dgeqrt3,DGEQRT3) +#define LAPACK_cgeqrt3 LAPACK_GLOBAL(cgeqrt3,CGEQRT3) +#define LAPACK_zgeqrt3 LAPACK_GLOBAL(zgeqrt3,ZGEQRT3) +#define LAPACK_stpmqrt LAPACK_GLOBAL(stpmqrt,STPMQRT) +#define LAPACK_dtpmqrt LAPACK_GLOBAL(dtpmqrt,DTPMQRT) +#define LAPACK_ctpmqrt LAPACK_GLOBAL(ctpmqrt,CTPMQRT) +#define LAPACK_ztpmqrt LAPACK_GLOBAL(ztpmqrt,ZTPMQRT) +#define LAPACK_stpqrt LAPACK_GLOBAL(stpqrt,STPQRT) +#define LAPACK_dtpqrt LAPACK_GLOBAL(dtpqrt,DTPQRT) +#define LAPACK_ctpqrt LAPACK_GLOBAL(ctpqrt,CTPQRT) +#define LAPACK_ztpqrt LAPACK_GLOBAL(ztpqrt,ZTPQRT) +#define LAPACK_stpqrt2 LAPACK_GLOBAL(stpqrt2,STPQRT2) +#define LAPACK_dtpqrt2 LAPACK_GLOBAL(dtpqrt2,DTPQRT2) +#define LAPACK_ctpqrt2 LAPACK_GLOBAL(ctpqrt2,CTPQRT2) +#define LAPACK_ztpqrt2 LAPACK_GLOBAL(ztpqrt2,ZTPQRT2) +#define LAPACK_stprfb LAPACK_GLOBAL(stprfb,STPRFB) +#define LAPACK_dtprfb LAPACK_GLOBAL(dtprfb,DTPRFB) +#define LAPACK_ctprfb LAPACK_GLOBAL(ctprfb,CTPRFB) +#define LAPACK_ztprfb LAPACK_GLOBAL(ztprfb,ZTPRFB) +// LAPACK 3.5.0 +#define LAPACK_ssysv_rook LAPACK_GLOBAL(ssysv_rook,SSYSV_ROOK) +#define LAPACK_dsysv_rook LAPACK_GLOBAL(dsysv_rook,DSYSV_ROOK) +#define LAPACK_csysv_rook LAPACK_GLOBAL(csysv_rook,CSYSV_ROOK) +#define LAPACK_zsysv_rook LAPACK_GLOBAL(zsysv_rook,ZSYSV_ROOK) +#define LAPACK_csyr LAPACK_GLOBAL(csyr,CSYR) +#define LAPACK_zsyr LAPACK_GLOBAL(zsyr,ZSYR) +#define LAPACK_ilaver LAPACK_GLOBAL(ilaver,ILAVER) +// LAPACK 3.6.0 +#define LAPACK_sggsvd3 LAPACK_GLOBAL(sggsvd3,SGGSVD3) +#define LAPACK_dggsvd3 LAPACK_GLOBAL(dggsvd3,DGGSVD3) +#define LAPACK_cggsvd3 LAPACK_GLOBAL(cggsvd3,CGGSVD3) +#define LAPACK_zggsvd3 LAPACK_GLOBAL(zggsvd3,ZGGSVD3) + + + +void LAPACK_sgetrf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_dgetrf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_cgetrf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_zgetrf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_sgetrf2( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_dgetrf2( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_cgetrf2( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_zgetrf2( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_sgbtrf( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, float* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_dgbtrf( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, double* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_cgbtrf( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_complex_float* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_zgbtrf( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_complex_double* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_sgttrf( lapack_int* n, float* dl, float* d, float* du, float* du2, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_dgttrf( lapack_int* n, double* dl, double* d, double* du, + double* du2, lapack_int* ipiv, lapack_int *info ); +void LAPACK_cgttrf( lapack_int* n, lapack_complex_float* dl, + lapack_complex_float* d, lapack_complex_float* du, + lapack_complex_float* du2, lapack_int* ipiv, + lapack_int *info ); +void LAPACK_zgttrf( lapack_int* n, lapack_complex_double* dl, + lapack_complex_double* d, lapack_complex_double* du, + lapack_complex_double* du2, lapack_int* ipiv, + lapack_int *info ); +void LAPACK_spotrf2( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dpotrf2( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_cpotrf2( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_zpotrf2( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_spotrf( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dpotrf( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_cpotrf( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_zpotrf( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_dpstrf( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int* piv, lapack_int* rank, double* tol, + double* work, lapack_int *info ); +void LAPACK_spstrf( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int* piv, lapack_int* rank, float* tol, float* work, + lapack_int *info ); +void LAPACK_zpstrf( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* piv, lapack_int* rank, + double* tol, double* work, lapack_int *info ); +void LAPACK_cpstrf( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* piv, lapack_int* rank, + float* tol, float* work, lapack_int *info ); +void LAPACK_dpftrf( char* transr, char* uplo, lapack_int* n, double* a, + lapack_int *info ); +void LAPACK_spftrf( char* transr, char* uplo, lapack_int* n, float* a, + lapack_int *info ); +void LAPACK_zpftrf( char* transr, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int *info ); +void LAPACK_cpftrf( char* transr, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int *info ); +void LAPACK_spptrf( char* uplo, lapack_int* n, float* ap, lapack_int *info ); +void LAPACK_dpptrf( char* uplo, lapack_int* n, double* ap, lapack_int *info ); +void LAPACK_cpptrf( char* uplo, lapack_int* n, lapack_complex_float* ap, + lapack_int *info ); +void LAPACK_zpptrf( char* uplo, lapack_int* n, lapack_complex_double* ap, + lapack_int *info ); +void LAPACK_spbtrf( char* uplo, lapack_int* n, lapack_int* kd, float* ab, + lapack_int* ldab, lapack_int *info ); +void LAPACK_dpbtrf( char* uplo, lapack_int* n, lapack_int* kd, double* ab, + lapack_int* ldab, lapack_int *info ); +void LAPACK_cpbtrf( char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_float* ab, lapack_int* ldab, + lapack_int *info ); +void LAPACK_zpbtrf( char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_double* ab, lapack_int* ldab, + lapack_int *info ); +void LAPACK_spttrf( lapack_int* n, float* d, float* e, lapack_int *info ); +void LAPACK_dpttrf( lapack_int* n, double* d, double* e, lapack_int *info ); +void LAPACK_cpttrf( lapack_int* n, float* d, lapack_complex_float* e, + lapack_int *info ); +void LAPACK_zpttrf( lapack_int* n, double* d, lapack_complex_double* e, + lapack_int *info ); +void LAPACK_ssytrf( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ipiv, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dsytrf( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ipiv, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_csytrf( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zsytrf( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_chetrf( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zhetrf( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ssptrf( char* uplo, lapack_int* n, float* ap, lapack_int* ipiv, + lapack_int *info ); +void LAPACK_dsptrf( char* uplo, lapack_int* n, double* ap, lapack_int* ipiv, + lapack_int *info ); +void LAPACK_csptrf( char* uplo, lapack_int* n, lapack_complex_float* ap, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_zsptrf( char* uplo, lapack_int* n, lapack_complex_double* ap, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_chptrf( char* uplo, lapack_int* n, lapack_complex_float* ap, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_zhptrf( char* uplo, lapack_int* n, lapack_complex_double* ap, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_sgetrs( char* trans, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const lapack_int* ipiv, + float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_dgetrs( char* trans, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const lapack_int* ipiv, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_cgetrs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zgetrs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_sgbtrs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const float* ab, lapack_int* ldab, + const lapack_int* ipiv, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dgbtrs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const double* ab, lapack_int* ldab, + const lapack_int* ipiv, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cgbtrs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const lapack_complex_float* ab, + lapack_int* ldab, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zgbtrs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const lapack_complex_double* ab, + lapack_int* ldab, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sgttrs( char* trans, lapack_int* n, lapack_int* nrhs, + const float* dl, const float* d, const float* du, + const float* du2, const lapack_int* ipiv, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dgttrs( char* trans, lapack_int* n, lapack_int* nrhs, + const double* dl, const double* d, const double* du, + const double* du2, const lapack_int* ipiv, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_cgttrs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zgttrs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_spotrs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* a, + lapack_int* lda, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpotrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_cpotrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zpotrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpftrs( char* transr, char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_spftrs( char* transr, char* uplo, lapack_int* n, lapack_int* nrhs, + const float* a, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zpftrs( char* transr, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_cpftrs( char* transr, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_spptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cpptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zpptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_spbtrs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const float* ab, lapack_int* ldab, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dpbtrs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const double* ab, lapack_int* ldab, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_cpbtrs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zpbtrs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_spttrs( lapack_int* n, lapack_int* nrhs, const float* d, + const float* e, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpttrs( lapack_int* n, lapack_int* nrhs, const double* d, + const double* e, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cpttrs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* d, + const lapack_complex_float* e, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zpttrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* d, const lapack_complex_double* e, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ssytrs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* a, + lapack_int* lda, const lapack_int* ipiv, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dsytrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const lapack_int* ipiv, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_csytrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zsytrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_chetrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zhetrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_ssptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, const lapack_int* ipiv, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dsptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, const lapack_int* ipiv, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_csptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zsptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_chptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zhptrs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_strtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const float* a, lapack_int* lda, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dtrtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const double* a, lapack_int* lda, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_ctrtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ztrtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_stptrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const float* ap, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dtptrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const double* ap, double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_ctptrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* ap, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ztptrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_double* ap, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_stbtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, const float* ab, + lapack_int* ldab, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dtbtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, const double* ab, + lapack_int* ldab, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ctbtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_ztbtrs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sgecon( char* norm, lapack_int* n, const float* a, lapack_int* lda, + float* anorm, float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgecon( char* norm, lapack_int* n, const double* a, lapack_int* lda, + double* anorm, double* rcond, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgecon( char* norm, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* anorm, float* rcond, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgecon( char* norm, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* anorm, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sgbcon( char* norm, lapack_int* n, lapack_int* kl, lapack_int* ku, + const float* ab, lapack_int* ldab, const lapack_int* ipiv, + float* anorm, float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgbcon( char* norm, lapack_int* n, lapack_int* kl, lapack_int* ku, + const double* ab, lapack_int* ldab, const lapack_int* ipiv, + double* anorm, double* rcond, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgbcon( char* norm, lapack_int* n, lapack_int* kl, lapack_int* ku, + const lapack_complex_float* ab, lapack_int* ldab, + const lapack_int* ipiv, float* anorm, float* rcond, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgbcon( char* norm, lapack_int* n, lapack_int* kl, lapack_int* ku, + const lapack_complex_double* ab, lapack_int* ldab, + const lapack_int* ipiv, double* anorm, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sgtcon( char* norm, lapack_int* n, const float* dl, const float* d, + const float* du, const float* du2, const lapack_int* ipiv, + float* anorm, float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgtcon( char* norm, lapack_int* n, const double* dl, + const double* d, const double* du, const double* du2, + const lapack_int* ipiv, double* anorm, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cgtcon( char* norm, lapack_int* n, const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* du2, const lapack_int* ipiv, + float* anorm, float* rcond, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zgtcon( char* norm, lapack_int* n, const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* du2, const lapack_int* ipiv, + double* anorm, double* rcond, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_spocon( char* uplo, lapack_int* n, const float* a, lapack_int* lda, + float* anorm, float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dpocon( char* uplo, lapack_int* n, const double* a, lapack_int* lda, + double* anorm, double* rcond, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cpocon( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* anorm, float* rcond, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zpocon( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* anorm, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sppcon( char* uplo, lapack_int* n, const float* ap, float* anorm, + float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dppcon( char* uplo, lapack_int* n, const double* ap, double* anorm, + double* rcond, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cppcon( char* uplo, lapack_int* n, const lapack_complex_float* ap, + float* anorm, float* rcond, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zppcon( char* uplo, lapack_int* n, const lapack_complex_double* ap, + double* anorm, double* rcond, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_spbcon( char* uplo, lapack_int* n, lapack_int* kd, const float* ab, + lapack_int* ldab, float* anorm, float* rcond, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dpbcon( char* uplo, lapack_int* n, lapack_int* kd, const double* ab, + lapack_int* ldab, double* anorm, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cpbcon( char* uplo, lapack_int* n, lapack_int* kd, + const lapack_complex_float* ab, lapack_int* ldab, + float* anorm, float* rcond, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zpbcon( char* uplo, lapack_int* n, lapack_int* kd, + const lapack_complex_double* ab, lapack_int* ldab, + double* anorm, double* rcond, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sptcon( lapack_int* n, const float* d, const float* e, float* anorm, + float* rcond, float* work, lapack_int *info ); +void LAPACK_dptcon( lapack_int* n, const double* d, const double* e, + double* anorm, double* rcond, double* work, + lapack_int *info ); +void LAPACK_cptcon( lapack_int* n, const float* d, + const lapack_complex_float* e, float* anorm, float* rcond, + float* work, lapack_int *info ); +void LAPACK_zptcon( lapack_int* n, const double* d, + const lapack_complex_double* e, double* anorm, + double* rcond, double* work, lapack_int *info ); +void LAPACK_ssycon( char* uplo, lapack_int* n, const float* a, lapack_int* lda, + const lapack_int* ipiv, float* anorm, float* rcond, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dsycon( char* uplo, lapack_int* n, const double* a, lapack_int* lda, + const lapack_int* ipiv, double* anorm, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_csycon( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, float* anorm, + float* rcond, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zsycon( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, double* anorm, + double* rcond, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_checon( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, float* anorm, + float* rcond, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zhecon( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, double* anorm, + double* rcond, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_sspcon( char* uplo, lapack_int* n, const float* ap, + const lapack_int* ipiv, float* anorm, float* rcond, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dspcon( char* uplo, lapack_int* n, const double* ap, + const lapack_int* ipiv, double* anorm, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cspcon( char* uplo, lapack_int* n, const lapack_complex_float* ap, + const lapack_int* ipiv, float* anorm, float* rcond, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zspcon( char* uplo, lapack_int* n, const lapack_complex_double* ap, + const lapack_int* ipiv, double* anorm, double* rcond, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_chpcon( char* uplo, lapack_int* n, const lapack_complex_float* ap, + const lapack_int* ipiv, float* anorm, float* rcond, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zhpcon( char* uplo, lapack_int* n, const lapack_complex_double* ap, + const lapack_int* ipiv, double* anorm, double* rcond, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_strcon( char* norm, char* uplo, char* diag, lapack_int* n, + const float* a, lapack_int* lda, float* rcond, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dtrcon( char* norm, char* uplo, char* diag, lapack_int* n, + const double* a, lapack_int* lda, double* rcond, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_ctrcon( char* norm, char* uplo, char* diag, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, + float* rcond, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztrcon( char* norm, char* uplo, char* diag, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + double* rcond, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_stpcon( char* norm, char* uplo, char* diag, lapack_int* n, + const float* ap, float* rcond, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dtpcon( char* norm, char* uplo, char* diag, lapack_int* n, + const double* ap, double* rcond, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ctpcon( char* norm, char* uplo, char* diag, lapack_int* n, + const lapack_complex_float* ap, float* rcond, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztpcon( char* norm, char* uplo, char* diag, lapack_int* n, + const lapack_complex_double* ap, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_stbcon( char* norm, char* uplo, char* diag, lapack_int* n, + lapack_int* kd, const float* ab, lapack_int* ldab, + float* rcond, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dtbcon( char* norm, char* uplo, char* diag, lapack_int* n, + lapack_int* kd, const double* ab, lapack_int* ldab, + double* rcond, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_ctbcon( char* norm, char* uplo, char* diag, lapack_int* n, + lapack_int* kd, const lapack_complex_float* ab, + lapack_int* ldab, float* rcond, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_ztbcon( char* norm, char* uplo, char* diag, lapack_int* n, + lapack_int* kd, const lapack_complex_double* ab, + lapack_int* ldab, double* rcond, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sgerfs( char* trans, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const float* af, + lapack_int* ldaf, const lapack_int* ipiv, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* ferr, + float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgerfs( char* trans, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const lapack_int* ipiv, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cgerfs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgerfs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dgerfsx( char* trans, char* equed, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const lapack_int* ipiv, const double* r, + const double* c, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* rcond, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgerfsx( char* trans, char* equed, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const float* af, + lapack_int* ldaf, const lapack_int* ipiv, const float* r, + const float* c, const float* b, lapack_int* ldb, float* x, + lapack_int* ldx, float* rcond, float* berr, + lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zgerfsx( char* trans, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const double* r, const double* c, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cgerfsx( char* trans, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const float* r, const float* c, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sgbrfs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const float* ab, lapack_int* ldab, + const float* afb, lapack_int* ldafb, const lapack_int* ipiv, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgbrfs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const double* ab, lapack_int* ldab, + const double* afb, lapack_int* ldafb, + const lapack_int* ipiv, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* ferr, double* berr, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cgbrfs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const lapack_complex_float* ab, + lapack_int* ldab, const lapack_complex_float* afb, + lapack_int* ldafb, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgbrfs( char* trans, lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, const lapack_complex_double* ab, + lapack_int* ldab, const lapack_complex_double* afb, + lapack_int* ldafb, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_dgbrfsx( char* trans, char* equed, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, const double* ab, + lapack_int* ldab, const double* afb, lapack_int* ldafb, + const lapack_int* ipiv, const double* r, const double* c, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* rcond, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgbrfsx( char* trans, char* equed, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, const float* ab, + lapack_int* ldab, const float* afb, lapack_int* ldafb, + const lapack_int* ipiv, const float* r, const float* c, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zgbrfsx( char* trans, char* equed, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + const lapack_complex_double* afb, lapack_int* ldafb, + const lapack_int* ipiv, const double* r, const double* c, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cgbrfsx( char* trans, char* equed, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + const lapack_complex_float* afb, lapack_int* ldafb, + const lapack_int* ipiv, const float* r, const float* c, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sgtrfs( char* trans, lapack_int* n, lapack_int* nrhs, + const float* dl, const float* d, const float* du, + const float* dlf, const float* df, const float* duf, + const float* du2, const lapack_int* ipiv, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* ferr, + float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgtrfs( char* trans, lapack_int* n, lapack_int* nrhs, + const double* dl, const double* d, const double* du, + const double* dlf, const double* df, const double* duf, + const double* du2, const lapack_int* ipiv, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cgtrfs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, + const lapack_complex_float* dlf, + const lapack_complex_float* df, + const lapack_complex_float* duf, + const lapack_complex_float* du2, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgtrfs( char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, + const lapack_complex_double* dlf, + const lapack_complex_double* df, + const lapack_complex_double* duf, + const lapack_complex_double* du2, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sporfs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* a, + lapack_int* lda, const float* af, lapack_int* ldaf, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dporfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* ferr, double* berr, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cporfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zporfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_dporfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const double* s, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_sporfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const float* af, + lapack_int* ldaf, const float* s, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zporfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const double* s, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cporfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const float* s, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_spprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, const float* afp, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* ferr, + float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dpprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, const double* afp, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cpprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* afp, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zpprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_spbrfs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const float* ab, lapack_int* ldab, const float* afb, + lapack_int* ldafb, const float* b, lapack_int* ldb, + float* x, lapack_int* ldx, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dpbrfs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const double* ab, lapack_int* ldab, const double* afb, + lapack_int* ldafb, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* ferr, double* berr, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cpbrfs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + const lapack_complex_float* afb, lapack_int* ldafb, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zpbrfs( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + const lapack_complex_double* afb, lapack_int* ldafb, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sptrfs( lapack_int* n, lapack_int* nrhs, const float* d, + const float* e, const float* df, const float* ef, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int *info ); +void LAPACK_dptrfs( lapack_int* n, lapack_int* nrhs, const double* d, + const double* e, const double* df, const double* ef, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* ferr, double* berr, double* work, + lapack_int *info ); +void LAPACK_cptrfs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* d, + const lapack_complex_float* e, const float* df, + const lapack_complex_float* ef, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zptrfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* d, const lapack_complex_double* e, + const double* df, const lapack_complex_double* ef, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_ssyrfs( char* uplo, lapack_int* n, lapack_int* nrhs, const float* a, + lapack_int* lda, const float* af, lapack_int* ldaf, + const lapack_int* ipiv, const float* b, lapack_int* ldb, + float* x, lapack_int* ldx, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dsyrfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const lapack_int* ipiv, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_csyrfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zsyrfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dsyrfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const double* af, + lapack_int* ldaf, const lapack_int* ipiv, const double* s, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* rcond, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_ssyrfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, const float* af, + lapack_int* ldaf, const lapack_int* ipiv, const float* s, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zsyrfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const double* s, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_csyrfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const float* s, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_cherfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zherfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_zherfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* af, lapack_int* ldaf, + const lapack_int* ipiv, const double* s, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cherfsx( char* uplo, char* equed, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* af, lapack_int* ldaf, + const lapack_int* ipiv, const float* s, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* berr, lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ssprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, const float* afp, const lapack_int* ipiv, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dsprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, const double* afp, const lapack_int* ipiv, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* ferr, double* berr, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_csprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* afp, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zsprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_chprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, + const lapack_complex_float* afp, const lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zhprfs( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, + const lapack_complex_double* afp, const lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* ferr, + double* berr, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_strrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const float* a, lapack_int* lda, + const float* b, lapack_int* ldb, const float* x, + lapack_int* ldx, float* ferr, float* berr, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dtrrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const double* a, lapack_int* lda, + const double* b, lapack_int* ldb, const double* x, + lapack_int* ldx, double* ferr, double* berr, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ctrrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* b, + lapack_int* ldb, const lapack_complex_float* x, + lapack_int* ldx, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztrrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* b, + lapack_int* ldb, const lapack_complex_double* x, + lapack_int* ldx, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_stprfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const float* ap, const float* b, + lapack_int* ldb, const float* x, lapack_int* ldx, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dtprfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const double* ap, const double* b, + lapack_int* ldb, const double* x, lapack_int* ldx, + double* ferr, double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_ctprfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* ap, + const lapack_complex_float* b, lapack_int* ldb, + const lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztprfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* nrhs, const lapack_complex_double* ap, + const lapack_complex_double* b, lapack_int* ldb, + const lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_stbrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, const float* ab, + lapack_int* ldab, const float* b, lapack_int* ldb, + const float* x, lapack_int* ldx, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dtbrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, const double* ab, + lapack_int* ldab, const double* b, lapack_int* ldb, + const double* x, lapack_int* ldx, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_ctbrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, + const lapack_complex_float* ab, lapack_int* ldab, + const lapack_complex_float* b, lapack_int* ldb, + const lapack_complex_float* x, lapack_int* ldx, float* ferr, + float* berr, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztbrfs( char* uplo, char* trans, char* diag, lapack_int* n, + lapack_int* kd, lapack_int* nrhs, + const lapack_complex_double* ab, lapack_int* ldab, + const lapack_complex_double* b, lapack_int* ldb, + const lapack_complex_double* x, lapack_int* ldx, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sgetri( lapack_int* n, float* a, lapack_int* lda, + const lapack_int* ipiv, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgetri( lapack_int* n, double* a, lapack_int* lda, + const lapack_int* ipiv, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgetri( lapack_int* n, lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zgetri( lapack_int* n, lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_spotri( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dpotri( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_cpotri( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_zpotri( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_dpftri( char* transr, char* uplo, lapack_int* n, double* a, + lapack_int *info ); +void LAPACK_spftri( char* transr, char* uplo, lapack_int* n, float* a, + lapack_int *info ); +void LAPACK_zpftri( char* transr, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int *info ); +void LAPACK_cpftri( char* transr, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int *info ); +void LAPACK_spptri( char* uplo, lapack_int* n, float* ap, lapack_int *info ); +void LAPACK_dpptri( char* uplo, lapack_int* n, double* ap, lapack_int *info ); +void LAPACK_cpptri( char* uplo, lapack_int* n, lapack_complex_float* ap, + lapack_int *info ); +void LAPACK_zpptri( char* uplo, lapack_int* n, lapack_complex_double* ap, + lapack_int *info ); +void LAPACK_ssytri( char* uplo, lapack_int* n, float* a, lapack_int* lda, + const lapack_int* ipiv, float* work, lapack_int *info ); +void LAPACK_dsytri( char* uplo, lapack_int* n, double* a, lapack_int* lda, + const lapack_int* ipiv, double* work, lapack_int *info ); +void LAPACK_csytri( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zsytri( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_chetri( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zhetri( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_ssptri( char* uplo, lapack_int* n, float* ap, + const lapack_int* ipiv, float* work, lapack_int *info ); +void LAPACK_dsptri( char* uplo, lapack_int* n, double* ap, + const lapack_int* ipiv, double* work, lapack_int *info ); +void LAPACK_csptri( char* uplo, lapack_int* n, lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zsptri( char* uplo, lapack_int* n, lapack_complex_double* ap, + const lapack_int* ipiv, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_chptri( char* uplo, lapack_int* n, lapack_complex_float* ap, + const lapack_int* ipiv, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zhptri( char* uplo, lapack_int* n, lapack_complex_double* ap, + const lapack_int* ipiv, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_strtri( char* uplo, char* diag, lapack_int* n, float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_dtrtri( char* uplo, char* diag, lapack_int* n, double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_ctrtri( char* uplo, char* diag, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_ztrtri( char* uplo, char* diag, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dtftri( char* transr, char* uplo, char* diag, lapack_int* n, + double* a, lapack_int *info ); +void LAPACK_stftri( char* transr, char* uplo, char* diag, lapack_int* n, + float* a, lapack_int *info ); +void LAPACK_ztftri( char* transr, char* uplo, char* diag, lapack_int* n, + lapack_complex_double* a, lapack_int *info ); +void LAPACK_ctftri( char* transr, char* uplo, char* diag, lapack_int* n, + lapack_complex_float* a, lapack_int *info ); +void LAPACK_stptri( char* uplo, char* diag, lapack_int* n, float* ap, + lapack_int *info ); +void LAPACK_dtptri( char* uplo, char* diag, lapack_int* n, double* ap, + lapack_int *info ); +void LAPACK_ctptri( char* uplo, char* diag, lapack_int* n, + lapack_complex_float* ap, lapack_int *info ); +void LAPACK_ztptri( char* uplo, char* diag, lapack_int* n, + lapack_complex_double* ap, lapack_int *info ); +void LAPACK_sgeequ( lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_dgeequ( lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, double* r, double* c, double* rowcnd, + double* colcnd, double* amax, lapack_int *info ); +void LAPACK_cgeequ( lapack_int* m, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_zgeequ( lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* r, + double* c, double* rowcnd, double* colcnd, double* amax, + lapack_int *info ); +void LAPACK_dgeequb( lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, double* r, double* c, double* rowcnd, + double* colcnd, double* amax, lapack_int *info ); +void LAPACK_sgeequb( lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_zgeequb( lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* r, + double* c, double* rowcnd, double* colcnd, double* amax, + lapack_int *info ); +void LAPACK_cgeequb( lapack_int* m, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, float* r, + float* c, float* rowcnd, float* colcnd, float* amax, + lapack_int *info ); +void LAPACK_sgbequ( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const float* ab, lapack_int* ldab, float* r, + float* c, float* rowcnd, float* colcnd, float* amax, + lapack_int *info ); +void LAPACK_dgbequ( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const double* ab, lapack_int* ldab, + double* r, double* c, double* rowcnd, double* colcnd, + double* amax, lapack_int *info ); +void LAPACK_cgbequ( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const lapack_complex_float* ab, + lapack_int* ldab, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_zgbequ( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const lapack_complex_double* ab, + lapack_int* ldab, double* r, double* c, double* rowcnd, + double* colcnd, double* amax, lapack_int *info ); +void LAPACK_dgbequb( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const double* ab, lapack_int* ldab, + double* r, double* c, double* rowcnd, double* colcnd, + double* amax, lapack_int *info ); +void LAPACK_sgbequb( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const float* ab, lapack_int* ldab, + float* r, float* c, float* rowcnd, float* colcnd, + float* amax, lapack_int *info ); +void LAPACK_zgbequb( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const lapack_complex_double* ab, + lapack_int* ldab, double* r, double* c, double* rowcnd, + double* colcnd, double* amax, lapack_int *info ); +void LAPACK_cgbequb( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const lapack_complex_float* ab, + lapack_int* ldab, float* r, float* c, float* rowcnd, + float* colcnd, float* amax, lapack_int *info ); +void LAPACK_spoequ( lapack_int* n, const float* a, lapack_int* lda, float* s, + float* scond, float* amax, lapack_int *info ); +void LAPACK_dpoequ( lapack_int* n, const double* a, lapack_int* lda, double* s, + double* scond, double* amax, lapack_int *info ); +void LAPACK_cpoequ( lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* s, float* scond, float* amax, + lapack_int *info ); +void LAPACK_zpoequ( lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* s, double* scond, double* amax, + lapack_int *info ); +void LAPACK_dpoequb( lapack_int* n, const double* a, lapack_int* lda, double* s, + double* scond, double* amax, lapack_int *info ); +void LAPACK_spoequb( lapack_int* n, const float* a, lapack_int* lda, float* s, + float* scond, float* amax, lapack_int *info ); +void LAPACK_zpoequb( lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* s, double* scond, double* amax, + lapack_int *info ); +void LAPACK_cpoequb( lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* s, float* scond, float* amax, + lapack_int *info ); +void LAPACK_sppequ( char* uplo, lapack_int* n, const float* ap, float* s, + float* scond, float* amax, lapack_int *info ); +void LAPACK_dppequ( char* uplo, lapack_int* n, const double* ap, double* s, + double* scond, double* amax, lapack_int *info ); +void LAPACK_cppequ( char* uplo, lapack_int* n, const lapack_complex_float* ap, + float* s, float* scond, float* amax, lapack_int *info ); +void LAPACK_zppequ( char* uplo, lapack_int* n, const lapack_complex_double* ap, + double* s, double* scond, double* amax, lapack_int *info ); +void LAPACK_spbequ( char* uplo, lapack_int* n, lapack_int* kd, const float* ab, + lapack_int* ldab, float* s, float* scond, float* amax, + lapack_int *info ); +void LAPACK_dpbequ( char* uplo, lapack_int* n, lapack_int* kd, const double* ab, + lapack_int* ldab, double* s, double* scond, double* amax, + lapack_int *info ); +void LAPACK_cpbequ( char* uplo, lapack_int* n, lapack_int* kd, + const lapack_complex_float* ab, lapack_int* ldab, float* s, + float* scond, float* amax, lapack_int *info ); +void LAPACK_zpbequ( char* uplo, lapack_int* n, lapack_int* kd, + const lapack_complex_double* ab, lapack_int* ldab, + double* s, double* scond, double* amax, lapack_int *info ); +void LAPACK_dsyequb( char* uplo, lapack_int* n, const double* a, + lapack_int* lda, double* s, double* scond, double* amax, + double* work, lapack_int *info ); +void LAPACK_ssyequb( char* uplo, lapack_int* n, const float* a, lapack_int* lda, + float* s, float* scond, float* amax, float* work, + lapack_int *info ); +void LAPACK_zsyequb( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* s, double* scond, double* amax, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_csyequb( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* s, float* scond, float* amax, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zheequb( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, double* s, double* scond, double* amax, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_cheequb( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, float* s, float* scond, float* amax, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_sgesv( lapack_int* n, lapack_int* nrhs, float* a, lapack_int* lda, + lapack_int* ipiv, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dgesv( lapack_int* n, lapack_int* nrhs, double* a, lapack_int* lda, + lapack_int* ipiv, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cgesv( lapack_int* n, lapack_int* nrhs, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zgesv( lapack_int* n, lapack_int* nrhs, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dsgesv( lapack_int* n, lapack_int* nrhs, double* a, lapack_int* lda, + lapack_int* ipiv, double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* work, float* swork, + lapack_int* iter, lapack_int *info ); +void LAPACK_zcgesv( lapack_int* n, lapack_int* nrhs, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + lapack_complex_double* work, lapack_complex_float* swork, + double* rwork, lapack_int* iter, lapack_int *info ); +void LAPACK_sgesvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgesvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int* ldb, double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgesvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgesvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dgesvxx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int* ldb, double* x, lapack_int* ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgesvxx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zgesvxx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cgesvxx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* r, float* c, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sgbsv( lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, float* ab, lapack_int* ldab, + lapack_int* ipiv, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dgbsv( lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, double* ab, lapack_int* ldab, + lapack_int* ipiv, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cgbsv( lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, lapack_complex_float* ab, lapack_int* ldab, + lapack_int* ipiv, lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zgbsv( lapack_int* n, lapack_int* kl, lapack_int* ku, + lapack_int* nrhs, lapack_complex_double* ab, + lapack_int* ldab, lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_sgbsvx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, float* ab, + lapack_int* ldab, float* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, float* r, float* c, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgbsvx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, double* ab, + lapack_int* ldab, double* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int* ldb, double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgbsvx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, lapack_complex_float* ab, + lapack_int* ldab, lapack_complex_float* afb, + lapack_int* ldafb, lapack_int* ipiv, char* equed, float* r, + float* c, lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgbsvx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, lapack_complex_double* ab, + lapack_int* ldab, lapack_complex_double* afb, + lapack_int* ldafb, lapack_int* ipiv, char* equed, double* r, + double* c, lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dgbsvxx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, double* ab, + lapack_int* ldab, double* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, double* r, double* c, + double* b, lapack_int* ldb, double* x, lapack_int* ldx, + double* rcond, double* rpvgrw, double* berr, + lapack_int* n_err_bnds, double* err_bnds_norm, + double* err_bnds_comp, lapack_int* nparams, double* params, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgbsvxx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, float* ab, + lapack_int* ldab, float* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, float* r, float* c, + float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* rpvgrw, float* berr, + lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zgbsvxx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, + lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* afb, lapack_int* ldafb, + lapack_int* ipiv, char* equed, double* r, double* c, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cgbsvxx( char* fact, char* trans, lapack_int* n, lapack_int* kl, + lapack_int* ku, lapack_int* nrhs, lapack_complex_float* ab, + lapack_int* ldab, lapack_complex_float* afb, + lapack_int* ldafb, lapack_int* ipiv, char* equed, float* r, + float* c, lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sgtsv( lapack_int* n, lapack_int* nrhs, float* dl, float* d, + float* du, float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_dgtsv( lapack_int* n, lapack_int* nrhs, double* dl, double* d, + double* du, double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_cgtsv( lapack_int* n, lapack_int* nrhs, lapack_complex_float* dl, + lapack_complex_float* d, lapack_complex_float* du, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zgtsv( lapack_int* n, lapack_int* nrhs, lapack_complex_double* dl, + lapack_complex_double* d, lapack_complex_double* du, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sgtsvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + const float* dl, const float* d, const float* du, + float* dlf, float* df, float* duf, float* du2, + lapack_int* ipiv, const float* b, lapack_int* ldb, float* x, + lapack_int* ldx, float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dgtsvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + const double* dl, const double* d, const double* du, + double* dlf, double* df, double* duf, double* du2, + lapack_int* ipiv, const double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* rcond, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cgtsvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* dl, + const lapack_complex_float* d, + const lapack_complex_float* du, lapack_complex_float* dlf, + lapack_complex_float* df, lapack_complex_float* duf, + lapack_complex_float* du2, lapack_int* ipiv, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgtsvx( char* fact, char* trans, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* dl, + const lapack_complex_double* d, + const lapack_complex_double* du, lapack_complex_double* dlf, + lapack_complex_double* df, lapack_complex_double* duf, + lapack_complex_double* du2, lapack_int* ipiv, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sposv( char* uplo, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dposv( char* uplo, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cposv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zposv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dsposv( char* uplo, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* work, float* swork, + lapack_int* iter, lapack_int *info ); +void LAPACK_zcposv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, + lapack_complex_double* work, lapack_complex_float* swork, + double* rwork, lapack_int* iter, lapack_int *info ); +void LAPACK_sposvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + char* equed, float* s, float* b, lapack_int* ldb, float* x, + lapack_int* ldx, float* rcond, float* ferr, float* berr, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dposvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + char* equed, double* s, double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* rcond, double* ferr, + double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cposvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, char* equed, + float* s, lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zposvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, char* equed, + double* s, lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_dposvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + char* equed, double* s, double* b, lapack_int* ldb, + double* x, lapack_int* ldx, double* rcond, double* rpvgrw, + double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_sposvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + char* equed, float* s, float* b, lapack_int* ldb, float* x, + lapack_int* ldx, float* rcond, float* rpvgrw, float* berr, + lapack_int* n_err_bnds, float* err_bnds_norm, + float* err_bnds_comp, lapack_int* nparams, float* params, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_zposvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, char* equed, + double* s, lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_cposvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, char* equed, + float* s, lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sppsv( char* uplo, lapack_int* n, lapack_int* nrhs, float* ap, + float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_dppsv( char* uplo, lapack_int* n, lapack_int* nrhs, double* ap, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_cppsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* ap, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zppsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* ap, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_sppsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + float* ap, float* afp, char* equed, float* s, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dppsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + double* ap, double* afp, char* equed, double* s, double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cppsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* ap, lapack_complex_float* afp, + char* equed, float* s, lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zppsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* ap, lapack_complex_double* afp, + char* equed, double* s, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_spbsv( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + float* ab, lapack_int* ldab, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dpbsv( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + double* ab, lapack_int* ldab, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cpbsv( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zpbsv( char* uplo, lapack_int* n, lapack_int* kd, lapack_int* nrhs, + lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_spbsvx( char* fact, char* uplo, lapack_int* n, lapack_int* kd, + lapack_int* nrhs, float* ab, lapack_int* ldab, float* afb, + lapack_int* ldafb, char* equed, float* s, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dpbsvx( char* fact, char* uplo, lapack_int* n, lapack_int* kd, + lapack_int* nrhs, double* ab, lapack_int* ldab, double* afb, + lapack_int* ldafb, char* equed, double* s, double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cpbsvx( char* fact, char* uplo, lapack_int* n, lapack_int* kd, + lapack_int* nrhs, lapack_complex_float* ab, + lapack_int* ldab, lapack_complex_float* afb, + lapack_int* ldafb, char* equed, float* s, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zpbsvx( char* fact, char* uplo, lapack_int* n, lapack_int* kd, + lapack_int* nrhs, lapack_complex_double* ab, + lapack_int* ldab, lapack_complex_double* afb, + lapack_int* ldafb, char* equed, double* s, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sptsv( lapack_int* n, lapack_int* nrhs, float* d, float* e, + float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_dptsv( lapack_int* n, lapack_int* nrhs, double* d, double* e, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_cptsv( lapack_int* n, lapack_int* nrhs, float* d, + lapack_complex_float* e, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zptsv( lapack_int* n, lapack_int* nrhs, double* d, + lapack_complex_double* e, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_sptsvx( char* fact, lapack_int* n, lapack_int* nrhs, const float* d, + const float* e, float* df, float* ef, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int *info ); +void LAPACK_dptsvx( char* fact, lapack_int* n, lapack_int* nrhs, + const double* d, const double* e, double* df, double* ef, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* rcond, double* ferr, double* berr, + double* work, lapack_int *info ); +void LAPACK_cptsvx( char* fact, lapack_int* n, lapack_int* nrhs, const float* d, + const lapack_complex_float* e, float* df, + lapack_complex_float* ef, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zptsvx( char* fact, lapack_int* n, lapack_int* nrhs, + const double* d, const lapack_complex_double* e, double* df, + lapack_complex_double* ef, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_ssysv( char* uplo, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, lapack_int* ipiv, float* b, lapack_int* ldb, + float* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_dsysv( char* uplo, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, lapack_int* ipiv, double* b, + lapack_int* ldb, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_csysv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zsysv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ssysvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const float* a, lapack_int* lda, float* af, + lapack_int* ldaf, lapack_int* ipiv, const float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* ferr, float* berr, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dsysvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, double* af, + lapack_int* ldaf, lapack_int* ipiv, const double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* ferr, double* berr, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_csysvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zsysvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_dsysvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* s, double* b, + lapack_int* ldb, double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ssysvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* s, float* b, + lapack_int* ldb, float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zsysvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_csysvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_chesv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zhesv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_chesvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zhesvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_zhesvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, double* s, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* x, lapack_int* ldx, double* rcond, + double* rpvgrw, double* berr, lapack_int* n_err_bnds, + double* err_bnds_norm, double* err_bnds_comp, + lapack_int* nparams, double* params, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_chesvxx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* af, lapack_int* ldaf, + lapack_int* ipiv, char* equed, float* s, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* x, lapack_int* ldx, float* rcond, + float* rpvgrw, float* berr, lapack_int* n_err_bnds, + float* err_bnds_norm, float* err_bnds_comp, + lapack_int* nparams, float* params, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_sspsv( char* uplo, lapack_int* n, lapack_int* nrhs, float* ap, + lapack_int* ipiv, float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dspsv( char* uplo, lapack_int* n, lapack_int* nrhs, double* ap, + lapack_int* ipiv, double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_cspsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* ap, lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zspsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* ap, lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sspsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const float* ap, float* afp, lapack_int* ipiv, + const float* b, lapack_int* ldb, float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, float* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dspsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const double* ap, double* afp, lapack_int* ipiv, + const double* b, lapack_int* ldb, double* x, + lapack_int* ldx, double* rcond, double* ferr, double* berr, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cspsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, lapack_complex_float* afp, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zspsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, lapack_complex_double* afp, + lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_chpsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* ap, lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_zhpsv( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* ap, lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_chpsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* ap, lapack_complex_float* afp, + lapack_int* ipiv, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* x, lapack_int* ldx, + float* rcond, float* ferr, float* berr, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zhpsvx( char* fact, char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* ap, lapack_complex_double* afp, + lapack_int* ipiv, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* x, lapack_int* ldx, + double* rcond, double* ferr, double* berr, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sgeqrf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgeqrf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgeqrf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgeqrf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgeqpf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + lapack_int* jpvt, float* tau, float* work, + lapack_int *info ); +void LAPACK_dgeqpf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + lapack_int* jpvt, double* tau, double* work, + lapack_int *info ); +void LAPACK_cgeqpf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* jpvt, + lapack_complex_float* tau, lapack_complex_float* work, + float* rwork, lapack_int *info ); +void LAPACK_zgeqpf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* jpvt, + lapack_complex_double* tau, lapack_complex_double* work, + double* rwork, lapack_int *info ); +void LAPACK_sgeqp3( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + lapack_int* jpvt, float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgeqp3( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + lapack_int* jpvt, double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgeqp3( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* jpvt, + lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int *info ); +void LAPACK_zgeqp3( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* jpvt, + lapack_complex_double* tau, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int *info ); +void LAPACK_sorgqr( lapack_int* m, lapack_int* n, lapack_int* k, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorgqr( lapack_int* m, lapack_int* n, lapack_int* k, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sormqr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormqr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cungqr( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zungqr( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmqr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmqr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgelqf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgelqf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgelqf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgelqf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sorglq( lapack_int* m, lapack_int* n, lapack_int* k, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorglq( lapack_int* m, lapack_int* n, lapack_int* k, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sormlq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormlq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cunglq( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zunglq( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmlq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmlq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgeqlf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgeqlf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgeqlf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgeqlf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sorgql( lapack_int* m, lapack_int* n, lapack_int* k, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorgql( lapack_int* m, lapack_int* n, lapack_int* k, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cungql( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zungql( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sormql( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormql( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cunmql( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmql( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgerqf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgerqf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgerqf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgerqf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sorgrq( lapack_int* m, lapack_int* n, lapack_int* k, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorgrq( lapack_int* m, lapack_int* n, lapack_int* k, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cungrq( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zungrq( lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sormrq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormrq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cunmrq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmrq( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_stzrzf( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dtzrzf( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ctzrzf( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ztzrzf( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sormrz( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, const float* a, + lapack_int* lda, const float* tau, float* c, + lapack_int* ldc, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dormrz( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, const double* a, + lapack_int* lda, const double* tau, double* c, + lapack_int* ldc, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmrz( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmrz( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, lapack_complex_double* c, + lapack_int* ldc, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sggqrf( lapack_int* n, lapack_int* m, lapack_int* p, float* a, + lapack_int* lda, float* taua, float* b, lapack_int* ldb, + float* taub, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dggqrf( lapack_int* n, lapack_int* m, lapack_int* p, double* a, + lapack_int* lda, double* taua, double* b, lapack_int* ldb, + double* taub, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cggqrf( lapack_int* n, lapack_int* m, lapack_int* p, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* taua, lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* taub, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zggqrf( lapack_int* n, lapack_int* m, lapack_int* p, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* taua, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* taub, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sggrqf( lapack_int* m, lapack_int* p, lapack_int* n, float* a, + lapack_int* lda, float* taua, float* b, lapack_int* ldb, + float* taub, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dggrqf( lapack_int* m, lapack_int* p, lapack_int* n, double* a, + lapack_int* lda, double* taua, double* b, lapack_int* ldb, + double* taub, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cggrqf( lapack_int* m, lapack_int* p, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* taua, lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* taub, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zggrqf( lapack_int* m, lapack_int* p, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* taua, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* taub, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgebrd( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* d, float* e, float* tauq, float* taup, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgebrd( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* d, double* e, double* tauq, double* taup, + double* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_cgebrd( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, float* d, float* e, + lapack_complex_float* tauq, lapack_complex_float* taup, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgebrd( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, double* d, double* e, + lapack_complex_double* tauq, lapack_complex_double* taup, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgbbrd( char* vect, lapack_int* m, lapack_int* n, lapack_int* ncc, + lapack_int* kl, lapack_int* ku, float* ab, lapack_int* ldab, + float* d, float* e, float* q, lapack_int* ldq, float* pt, + lapack_int* ldpt, float* c, lapack_int* ldc, float* work, + lapack_int *info ); +void LAPACK_dgbbrd( char* vect, lapack_int* m, lapack_int* n, lapack_int* ncc, + lapack_int* kl, lapack_int* ku, double* ab, + lapack_int* ldab, double* d, double* e, double* q, + lapack_int* ldq, double* pt, lapack_int* ldpt, double* c, + lapack_int* ldc, double* work, lapack_int *info ); +void LAPACK_cgbbrd( char* vect, lapack_int* m, lapack_int* n, lapack_int* ncc, + lapack_int* kl, lapack_int* ku, lapack_complex_float* ab, + lapack_int* ldab, float* d, float* e, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* pt, lapack_int* ldpt, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zgbbrd( char* vect, lapack_int* m, lapack_int* n, lapack_int* ncc, + lapack_int* kl, lapack_int* ku, lapack_complex_double* ab, + lapack_int* ldab, double* d, double* e, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* pt, lapack_int* ldpt, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sorgbr( char* vect, lapack_int* m, lapack_int* n, lapack_int* k, + float* a, lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorgbr( char* vect, lapack_int* m, lapack_int* n, lapack_int* k, + double* a, lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sormbr( char* vect, char* side, char* trans, lapack_int* m, + lapack_int* n, lapack_int* k, const float* a, + lapack_int* lda, const float* tau, float* c, + lapack_int* ldc, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dormbr( char* vect, char* side, char* trans, lapack_int* m, + lapack_int* n, lapack_int* k, const double* a, + lapack_int* lda, const double* tau, double* c, + lapack_int* ldc, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cungbr( char* vect, lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zungbr( char* vect, lapack_int* m, lapack_int* n, lapack_int* k, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmbr( char* vect, char* side, char* trans, lapack_int* m, + lapack_int* n, lapack_int* k, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmbr( char* vect, char* side, char* trans, lapack_int* m, + lapack_int* n, lapack_int* k, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, lapack_complex_double* c, + lapack_int* ldc, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sbdsqr( char* uplo, lapack_int* n, lapack_int* ncvt, + lapack_int* nru, lapack_int* ncc, float* d, float* e, + float* vt, lapack_int* ldvt, float* u, lapack_int* ldu, + float* c, lapack_int* ldc, float* work, lapack_int *info ); +void LAPACK_dbdsqr( char* uplo, lapack_int* n, lapack_int* ncvt, + lapack_int* nru, lapack_int* ncc, double* d, double* e, + double* vt, lapack_int* ldvt, double* u, lapack_int* ldu, + double* c, lapack_int* ldc, double* work, + lapack_int *info ); +void LAPACK_cbdsqr( char* uplo, lapack_int* n, lapack_int* ncvt, + lapack_int* nru, lapack_int* ncc, float* d, float* e, + lapack_complex_float* vt, lapack_int* ldvt, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* c, lapack_int* ldc, float* work, + lapack_int *info ); +void LAPACK_zbdsqr( char* uplo, lapack_int* n, lapack_int* ncvt, + lapack_int* nru, lapack_int* ncc, double* d, double* e, + lapack_complex_double* vt, lapack_int* ldvt, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* c, lapack_int* ldc, double* work, + lapack_int *info ); +void LAPACK_sbdsdc( char* uplo, char* compq, lapack_int* n, float* d, float* e, + float* u, lapack_int* ldu, float* vt, lapack_int* ldvt, + float* q, lapack_int* iq, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dbdsdc( char* uplo, char* compq, lapack_int* n, double* d, + double* e, double* u, lapack_int* ldu, double* vt, + lapack_int* ldvt, double* q, lapack_int* iq, double* work, + lapack_int* iwork, lapack_int *info ); +void LAPACK_sbdsvdx( char* uplo, char* jobz, char* range, + lapack_int* n, float* d, float* e, + lapack_int* vl, lapack_int* vu, + lapack_int* il, lapack_int* iu, lapack_int* ns, + float* s, float* z, lapack_int* ldz, + float* work, lapack_int *iwork, lapack_int *info ); +void LAPACK_dbdsvdx( char* uplo, char* jobz, char* range, + lapack_int* n, double* d, double* e, + lapack_int* vl, lapack_int* vu, + lapack_int* il, lapack_int* iu, lapack_int* ns, + double* s, double* z, lapack_int* ldz, + double* work, lapack_int *iwork, lapack_int *info ); +void LAPACK_ssytrd( char* uplo, lapack_int* n, float* a, lapack_int* lda, + float* d, float* e, float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dsytrd( char* uplo, lapack_int* n, double* a, lapack_int* lda, + double* d, double* e, double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sorgtr( char* uplo, lapack_int* n, float* a, lapack_int* lda, + const float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dorgtr( char* uplo, lapack_int* n, double* a, lapack_int* lda, + const double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sormtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const float* a, lapack_int* lda, + const float* tau, float* c, lapack_int* ldc, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dormtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const double* a, lapack_int* lda, + const double* tau, double* c, lapack_int* ldc, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_chetrd( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, float* d, float* e, + lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zhetrd( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, double* d, double* e, + lapack_complex_double* tau, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cungtr( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zungtr( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zunmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ssptrd( char* uplo, lapack_int* n, float* ap, float* d, float* e, + float* tau, lapack_int *info ); +void LAPACK_dsptrd( char* uplo, lapack_int* n, double* ap, double* d, double* e, + double* tau, lapack_int *info ); +void LAPACK_sopgtr( char* uplo, lapack_int* n, const float* ap, + const float* tau, float* q, lapack_int* ldq, float* work, + lapack_int *info ); +void LAPACK_dopgtr( char* uplo, lapack_int* n, const double* ap, + const double* tau, double* q, lapack_int* ldq, double* work, + lapack_int *info ); +void LAPACK_sopmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const float* ap, const float* tau, float* c, + lapack_int* ldc, float* work, lapack_int *info ); +void LAPACK_dopmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const double* ap, const double* tau, + double* c, lapack_int* ldc, double* work, + lapack_int *info ); +void LAPACK_chptrd( char* uplo, lapack_int* n, lapack_complex_float* ap, + float* d, float* e, lapack_complex_float* tau, + lapack_int *info ); +void LAPACK_zhptrd( char* uplo, lapack_int* n, lapack_complex_double* ap, + double* d, double* e, lapack_complex_double* tau, + lapack_int *info ); +void LAPACK_cupgtr( char* uplo, lapack_int* n, const lapack_complex_float* ap, + const lapack_complex_float* tau, lapack_complex_float* q, + lapack_int* ldq, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zupgtr( char* uplo, lapack_int* n, const lapack_complex_double* ap, + const lapack_complex_double* tau, lapack_complex_double* q, + lapack_int* ldq, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_cupmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const lapack_complex_float* ap, + const lapack_complex_float* tau, lapack_complex_float* c, + lapack_int* ldc, lapack_complex_float* work, + lapack_int *info ); +void LAPACK_zupmtr( char* side, char* uplo, char* trans, lapack_int* m, + lapack_int* n, const lapack_complex_double* ap, + const lapack_complex_double* tau, lapack_complex_double* c, + lapack_int* ldc, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_ssbtrd( char* vect, char* uplo, lapack_int* n, lapack_int* kd, + float* ab, lapack_int* ldab, float* d, float* e, float* q, + lapack_int* ldq, float* work, lapack_int *info ); +void LAPACK_dsbtrd( char* vect, char* uplo, lapack_int* n, lapack_int* kd, + double* ab, lapack_int* ldab, double* d, double* e, + double* q, lapack_int* ldq, double* work, + lapack_int *info ); +void LAPACK_chbtrd( char* vect, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_float* ab, lapack_int* ldab, float* d, + float* e, lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zhbtrd( char* vect, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_double* ab, lapack_int* ldab, double* d, + double* e, lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_ssterf( lapack_int* n, float* d, float* e, lapack_int *info ); +void LAPACK_dsterf( lapack_int* n, double* d, double* e, lapack_int *info ); +void LAPACK_ssteqr( char* compz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dsteqr( char* compz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_csteqr( char* compz, lapack_int* n, float* d, float* e, + lapack_complex_float* z, lapack_int* ldz, float* work, + lapack_int *info ); +void LAPACK_zsteqr( char* compz, lapack_int* n, double* d, double* e, + lapack_complex_double* z, lapack_int* ldz, double* work, + lapack_int *info ); +void LAPACK_sstemr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + lapack_int* m, float* w, float* z, lapack_int* ldz, + lapack_int* nzc, lapack_int* isuppz, lapack_logical* tryrac, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dstemr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, lapack_int* m, double* w, double* z, + lapack_int* ldz, lapack_int* nzc, lapack_int* isuppz, + lapack_logical* tryrac, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_cstemr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_int* nzc, lapack_int* isuppz, + lapack_logical* tryrac, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_zstemr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int* ldz, lapack_int* nzc, + lapack_int* isuppz, lapack_logical* tryrac, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_sstedc( char* compz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dstedc( char* compz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_cstedc( char* compz, lapack_int* n, float* d, float* e, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zstedc( char* compz, lapack_int* n, double* d, double* e, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sstegr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, float* z, + lapack_int* ldz, lapack_int* isuppz, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_dstegr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, lapack_int* isuppz, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_cstegr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_int* isuppz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_zstegr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_int* isuppz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_spteqr( char* compz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dpteqr( char* compz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_cpteqr( char* compz, lapack_int* n, float* d, float* e, + lapack_complex_float* z, lapack_int* ldz, float* work, + lapack_int *info ); +void LAPACK_zpteqr( char* compz, lapack_int* n, double* d, double* e, + lapack_complex_double* z, lapack_int* ldz, double* work, + lapack_int *info ); +void LAPACK_sstebz( char* range, char* order, lapack_int* n, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + const float* d, const float* e, lapack_int* m, + lapack_int* nsplit, float* w, lapack_int* iblock, + lapack_int* isplit, float* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dstebz( char* range, char* order, lapack_int* n, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + const double* d, const double* e, lapack_int* m, + lapack_int* nsplit, double* w, lapack_int* iblock, + lapack_int* isplit, double* work, lapack_int* iwork, + lapack_int *info ); +void LAPACK_sstein( lapack_int* n, const float* d, const float* e, + lapack_int* m, const float* w, const lapack_int* iblock, + const lapack_int* isplit, float* z, lapack_int* ldz, + float* work, lapack_int* iwork, lapack_int* ifailv, + lapack_int *info ); +void LAPACK_dstein( lapack_int* n, const double* d, const double* e, + lapack_int* m, const double* w, const lapack_int* iblock, + const lapack_int* isplit, double* z, lapack_int* ldz, + double* work, lapack_int* iwork, lapack_int* ifailv, + lapack_int *info ); +void LAPACK_cstein( lapack_int* n, const float* d, const float* e, + lapack_int* m, const float* w, const lapack_int* iblock, + const lapack_int* isplit, lapack_complex_float* z, + lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifailv, lapack_int *info ); +void LAPACK_zstein( lapack_int* n, const double* d, const double* e, + lapack_int* m, const double* w, const lapack_int* iblock, + const lapack_int* isplit, lapack_complex_double* z, + lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifailv, lapack_int *info ); +void LAPACK_sdisna( char* job, lapack_int* m, lapack_int* n, const float* d, + float* sep, lapack_int *info ); +void LAPACK_ddisna( char* job, lapack_int* m, lapack_int* n, const double* d, + double* sep, lapack_int *info ); +void LAPACK_ssygst( lapack_int* itype, char* uplo, lapack_int* n, float* a, + lapack_int* lda, const float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_dsygst( lapack_int* itype, char* uplo, lapack_int* n, double* a, + lapack_int* lda, const double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_chegst( lapack_int* itype, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_zhegst( lapack_int* itype, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* b, lapack_int* ldb, + lapack_int *info ); +void LAPACK_sspgst( lapack_int* itype, char* uplo, lapack_int* n, float* ap, + const float* bp, lapack_int *info ); +void LAPACK_dspgst( lapack_int* itype, char* uplo, lapack_int* n, double* ap, + const double* bp, lapack_int *info ); +void LAPACK_chpgst( lapack_int* itype, char* uplo, lapack_int* n, + lapack_complex_float* ap, const lapack_complex_float* bp, + lapack_int *info ); +void LAPACK_zhpgst( lapack_int* itype, char* uplo, lapack_int* n, + lapack_complex_double* ap, const lapack_complex_double* bp, + lapack_int *info ); +void LAPACK_ssbgst( char* vect, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, float* ab, lapack_int* ldab, + const float* bb, lapack_int* ldbb, float* x, + lapack_int* ldx, float* work, lapack_int *info ); +void LAPACK_dsbgst( char* vect, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, double* ab, lapack_int* ldab, + const double* bb, lapack_int* ldbb, double* x, + lapack_int* ldx, double* work, lapack_int *info ); +void LAPACK_chbgst( char* vect, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_float* ab, lapack_int* ldab, + const lapack_complex_float* bb, lapack_int* ldbb, + lapack_complex_float* x, lapack_int* ldx, + lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zhbgst( char* vect, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_double* ab, lapack_int* ldab, + const lapack_complex_double* bb, lapack_int* ldbb, + lapack_complex_double* x, lapack_int* ldx, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_spbstf( char* uplo, lapack_int* n, lapack_int* kb, float* bb, + lapack_int* ldbb, lapack_int *info ); +void LAPACK_dpbstf( char* uplo, lapack_int* n, lapack_int* kb, double* bb, + lapack_int* ldbb, lapack_int *info ); +void LAPACK_cpbstf( char* uplo, lapack_int* n, lapack_int* kb, + lapack_complex_float* bb, lapack_int* ldbb, + lapack_int *info ); +void LAPACK_zpbstf( char* uplo, lapack_int* n, lapack_int* kb, + lapack_complex_double* bb, lapack_int* ldbb, + lapack_int *info ); +void LAPACK_sgehrd( lapack_int* n, lapack_int* ilo, lapack_int* ihi, float* a, + lapack_int* lda, float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgehrd( lapack_int* n, lapack_int* ilo, lapack_int* ihi, double* a, + lapack_int* lda, double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgehrd( lapack_int* n, lapack_int* ilo, lapack_int* ihi, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zgehrd( lapack_int* n, lapack_int* ilo, lapack_int* ihi, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* tau, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sorghr( lapack_int* n, lapack_int* ilo, lapack_int* ihi, float* a, + lapack_int* lda, const float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dorghr( lapack_int* n, lapack_int* ilo, lapack_int* ihi, double* a, + lapack_int* lda, const double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sormhr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, const float* a, + lapack_int* lda, const float* tau, float* c, + lapack_int* ldc, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dormhr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, const double* a, + lapack_int* lda, const double* tau, double* c, + lapack_int* ldc, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunghr( lapack_int* n, lapack_int* ilo, lapack_int* ihi, + lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zunghr( lapack_int* n, lapack_int* ilo, lapack_int* ihi, + lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cunmhr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* tau, lapack_complex_float* c, + lapack_int* ldc, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zunmhr( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* tau, lapack_complex_double* c, + lapack_int* ldc, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sgebal( char* job, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ilo, lapack_int* ihi, float* scale, + lapack_int *info ); +void LAPACK_dgebal( char* job, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ilo, lapack_int* ihi, double* scale, + lapack_int *info ); +void LAPACK_cgebal( char* job, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ilo, lapack_int* ihi, + float* scale, lapack_int *info ); +void LAPACK_zgebal( char* job, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ilo, lapack_int* ihi, + double* scale, lapack_int *info ); +void LAPACK_sgebak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const float* scale, lapack_int* m, + float* v, lapack_int* ldv, lapack_int *info ); +void LAPACK_dgebak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const double* scale, lapack_int* m, + double* v, lapack_int* ldv, lapack_int *info ); +void LAPACK_cgebak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const float* scale, lapack_int* m, + lapack_complex_float* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_zgebak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const double* scale, lapack_int* m, + lapack_complex_double* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_shseqr( char* job, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, float* h, lapack_int* ldh, float* wr, + float* wi, float* z, lapack_int* ldz, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dhseqr( char* job, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, double* h, lapack_int* ldh, double* wr, + double* wi, double* z, lapack_int* ldz, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_chseqr( char* job, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, lapack_complex_float* h, lapack_int* ldh, + lapack_complex_float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zhseqr( char* job, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, lapack_complex_double* h, lapack_int* ldh, + lapack_complex_double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_shsein( char* job, char* eigsrc, char* initv, + lapack_logical* select, lapack_int* n, const float* h, + lapack_int* ldh, float* wr, const float* wi, float* vl, + lapack_int* ldvl, float* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, float* work, + lapack_int* ifaill, lapack_int* ifailr, lapack_int *info ); +void LAPACK_dhsein( char* job, char* eigsrc, char* initv, + lapack_logical* select, lapack_int* n, const double* h, + lapack_int* ldh, double* wr, const double* wi, double* vl, + lapack_int* ldvl, double* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, double* work, + lapack_int* ifaill, lapack_int* ifailr, lapack_int *info ); +void LAPACK_chsein( char* job, char* eigsrc, char* initv, + const lapack_logical* select, lapack_int* n, + const lapack_complex_float* h, lapack_int* ldh, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int* ldvl, lapack_complex_float* vr, + lapack_int* ldvr, lapack_int* mm, lapack_int* m, + lapack_complex_float* work, float* rwork, + lapack_int* ifaill, lapack_int* ifailr, lapack_int *info ); +void LAPACK_zhsein( char* job, char* eigsrc, char* initv, + const lapack_logical* select, lapack_int* n, + const lapack_complex_double* h, lapack_int* ldh, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int* ldvl, lapack_complex_double* vr, + lapack_int* ldvr, lapack_int* mm, lapack_int* m, + lapack_complex_double* work, double* rwork, + lapack_int* ifaill, lapack_int* ifailr, lapack_int *info ); +void LAPACK_strevc( char* side, char* howmny, lapack_logical* select, + lapack_int* n, const float* t, lapack_int* ldt, float* vl, + lapack_int* ldvl, float* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, float* work, + lapack_int *info ); +void LAPACK_dtrevc( char* side, char* howmny, lapack_logical* select, + lapack_int* n, const double* t, lapack_int* ldt, double* vl, + lapack_int* ldvl, double* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, double* work, + lapack_int *info ); +void LAPACK_ctrevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* vl, lapack_int* ldvl, + lapack_complex_float* vr, lapack_int* ldvr, lapack_int* mm, + lapack_int* m, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztrevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* vl, lapack_int* ldvl, + lapack_complex_double* vr, lapack_int* ldvr, lapack_int* mm, + lapack_int* m, lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_strsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const float* t, lapack_int* ldt, + const float* vl, lapack_int* ldvl, const float* vr, + lapack_int* ldvr, float* s, float* sep, lapack_int* mm, + lapack_int* m, float* work, lapack_int* ldwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dtrsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const double* t, lapack_int* ldt, + const double* vl, lapack_int* ldvl, const double* vr, + lapack_int* ldvr, double* s, double* sep, lapack_int* mm, + lapack_int* m, double* work, lapack_int* ldwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ctrsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_float* t, + lapack_int* ldt, const lapack_complex_float* vl, + lapack_int* ldvl, const lapack_complex_float* vr, + lapack_int* ldvr, float* s, float* sep, lapack_int* mm, + lapack_int* m, lapack_complex_float* work, + lapack_int* ldwork, float* rwork, lapack_int *info ); +void LAPACK_ztrsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_double* t, + lapack_int* ldt, const lapack_complex_double* vl, + lapack_int* ldvl, const lapack_complex_double* vr, + lapack_int* ldvr, double* s, double* sep, lapack_int* mm, + lapack_int* m, lapack_complex_double* work, + lapack_int* ldwork, double* rwork, lapack_int *info ); +void LAPACK_strexc( char* compq, lapack_int* n, float* t, lapack_int* ldt, + float* q, lapack_int* ldq, lapack_int* ifst, + lapack_int* ilst, float* work, lapack_int *info ); +void LAPACK_dtrexc( char* compq, lapack_int* n, double* t, lapack_int* ldt, + double* q, lapack_int* ldq, lapack_int* ifst, + lapack_int* ilst, double* work, lapack_int *info ); +void LAPACK_ctrexc( char* compq, lapack_int* n, lapack_complex_float* t, + lapack_int* ldt, lapack_complex_float* q, lapack_int* ldq, + lapack_int* ifst, lapack_int* ilst, lapack_int *info ); +void LAPACK_ztrexc( char* compq, lapack_int* n, lapack_complex_double* t, + lapack_int* ldt, lapack_complex_double* q, lapack_int* ldq, + lapack_int* ifst, lapack_int* ilst, lapack_int *info ); +void LAPACK_strsen( char* job, char* compq, const lapack_logical* select, + lapack_int* n, float* t, lapack_int* ldt, float* q, + lapack_int* ldq, float* wr, float* wi, lapack_int* m, + float* s, float* sep, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dtrsen( char* job, char* compq, const lapack_logical* select, + lapack_int* n, double* t, lapack_int* ldt, double* q, + lapack_int* ldq, double* wr, double* wi, lapack_int* m, + double* s, double* sep, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_ctrsen( char* job, char* compq, const lapack_logical* select, + lapack_int* n, lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* w, lapack_int* m, float* s, + float* sep, lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ztrsen( char* job, char* compq, const lapack_logical* select, + lapack_int* n, lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* w, lapack_int* m, double* s, + double* sep, lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_strsyl( char* trana, char* tranb, lapack_int* isgn, lapack_int* m, + lapack_int* n, const float* a, lapack_int* lda, + const float* b, lapack_int* ldb, float* c, lapack_int* ldc, + float* scale, lapack_int *info ); +void LAPACK_dtrsyl( char* trana, char* tranb, lapack_int* isgn, lapack_int* m, + lapack_int* n, const double* a, lapack_int* lda, + const double* b, lapack_int* ldb, double* c, + lapack_int* ldc, double* scale, lapack_int *info ); +void LAPACK_ctrsyl( char* trana, char* tranb, lapack_int* isgn, lapack_int* m, + lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* c, lapack_int* ldc, + float* scale, lapack_int *info ); +void LAPACK_ztrsyl( char* trana, char* tranb, lapack_int* isgn, lapack_int* m, + lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* c, lapack_int* ldc, + double* scale, lapack_int *info ); +void LAPACK_sgghrd( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* q, lapack_int* ldq, float* z, + lapack_int* ldz, lapack_int *info ); +void LAPACK_dgghrd( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* q, lapack_int* ldq, double* z, + lapack_int* ldz, lapack_int *info ); +void LAPACK_cgghrd( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* z, lapack_int* ldz, + lapack_int *info ); +void LAPACK_zgghrd( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* z, lapack_int* ldz, + lapack_int *info ); +void LAPACK_sgghd3( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* q, lapack_int* ldq, float* z, + lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgghd3( char* compq, char* compz, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* q, lapack_int* ldq, double* z, + lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgghd3( char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgghd3( char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sggbal( char* job, lapack_int* n, float* a, lapack_int* lda, + float* b, lapack_int* ldb, lapack_int* ilo, lapack_int* ihi, + float* lscale, float* rscale, float* work, + lapack_int *info ); +void LAPACK_dggbal( char* job, lapack_int* n, double* a, lapack_int* lda, + double* b, lapack_int* ldb, lapack_int* ilo, + lapack_int* ihi, double* lscale, double* rscale, + double* work, lapack_int *info ); +void LAPACK_cggbal( char* job, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* b, lapack_int* ldb, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* work, lapack_int *info ); +void LAPACK_zggbal( char* job, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* b, lapack_int* ldb, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale, double* work, lapack_int *info ); +void LAPACK_sggbak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const float* lscale, const float* rscale, + lapack_int* m, float* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_dggbak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const double* lscale, const double* rscale, + lapack_int* m, double* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_cggbak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const float* lscale, const float* rscale, + lapack_int* m, lapack_complex_float* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_zggbak( char* job, char* side, lapack_int* n, lapack_int* ilo, + lapack_int* ihi, const double* lscale, const double* rscale, + lapack_int* m, lapack_complex_double* v, lapack_int* ldv, + lapack_int *info ); +void LAPACK_shgeqz( char* job, char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, float* h, lapack_int* ldh, + float* t, lapack_int* ldt, float* alphar, float* alphai, + float* beta, float* q, lapack_int* ldq, float* z, + lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dhgeqz( char* job, char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, double* h, + lapack_int* ldh, double* t, lapack_int* ldt, double* alphar, + double* alphai, double* beta, double* q, lapack_int* ldq, + double* z, lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_chgeqz( char* job, char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, lapack_complex_float* h, + lapack_int* ldh, lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zhgeqz( char* job, char* compq, char* compz, lapack_int* n, + lapack_int* ilo, lapack_int* ihi, lapack_complex_double* h, + lapack_int* ldh, lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_stgevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, const float* s, lapack_int* lds, + const float* p, lapack_int* ldp, float* vl, + lapack_int* ldvl, float* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, float* work, + lapack_int *info ); +void LAPACK_dtgevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, const double* s, lapack_int* lds, + const double* p, lapack_int* ldp, double* vl, + lapack_int* ldvl, double* vr, lapack_int* ldvr, + lapack_int* mm, lapack_int* m, double* work, + lapack_int *info ); +void LAPACK_ctgevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_float* s, + lapack_int* lds, const lapack_complex_float* p, + lapack_int* ldp, lapack_complex_float* vl, lapack_int* ldvl, + lapack_complex_float* vr, lapack_int* ldvr, lapack_int* mm, + lapack_int* m, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_ztgevc( char* side, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_double* s, + lapack_int* lds, const lapack_complex_double* p, + lapack_int* ldp, lapack_complex_double* vl, + lapack_int* ldvl, lapack_complex_double* vr, + lapack_int* ldvr, lapack_int* mm, lapack_int* m, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_stgexc( lapack_logical* wantq, lapack_logical* wantz, lapack_int* n, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* q, lapack_int* ldq, float* z, lapack_int* ldz, + lapack_int* ifst, lapack_int* ilst, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dtgexc( lapack_logical* wantq, lapack_logical* wantz, lapack_int* n, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* q, lapack_int* ldq, double* z, lapack_int* ldz, + lapack_int* ifst, lapack_int* ilst, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_ctgexc( lapack_logical* wantq, lapack_logical* wantz, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* z, lapack_int* ldz, lapack_int* ifst, + lapack_int* ilst, lapack_int *info ); +void LAPACK_ztgexc( lapack_logical* wantq, lapack_logical* wantz, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* z, lapack_int* ldz, lapack_int* ifst, + lapack_int* ilst, lapack_int *info ); +void LAPACK_stgsen( lapack_int* ijob, lapack_logical* wantq, + lapack_logical* wantz, const lapack_logical* select, + lapack_int* n, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* alphar, float* alphai, float* beta, + float* q, lapack_int* ldq, float* z, lapack_int* ldz, + lapack_int* m, float* pl, float* pr, float* dif, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dtgsen( lapack_int* ijob, lapack_logical* wantq, + lapack_logical* wantz, const lapack_logical* select, + lapack_int* n, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* alphar, double* alphai, + double* beta, double* q, lapack_int* ldq, double* z, + lapack_int* ldz, lapack_int* m, double* pl, double* pr, + double* dif, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_ctgsen( lapack_int* ijob, lapack_logical* wantq, + lapack_logical* wantz, const lapack_logical* select, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* z, lapack_int* ldz, lapack_int* m, + float* pl, float* pr, float* dif, + lapack_complex_float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_ztgsen( lapack_int* ijob, lapack_logical* wantq, + lapack_logical* wantz, const lapack_logical* select, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* z, lapack_int* ldz, lapack_int* m, + double* pl, double* pr, double* dif, + lapack_complex_double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_stgsyl( char* trans, lapack_int* ijob, lapack_int* m, lapack_int* n, + const float* a, lapack_int* lda, const float* b, + lapack_int* ldb, float* c, lapack_int* ldc, const float* d, + lapack_int* ldd, const float* e, lapack_int* lde, float* f, + lapack_int* ldf, float* scale, float* dif, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_dtgsyl( char* trans, lapack_int* ijob, lapack_int* m, lapack_int* n, + const double* a, lapack_int* lda, const double* b, + lapack_int* ldb, double* c, lapack_int* ldc, + const double* d, lapack_int* ldd, const double* e, + lapack_int* lde, double* f, lapack_int* ldf, double* scale, + double* dif, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ctgsyl( char* trans, lapack_int* ijob, lapack_int* m, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, + const lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* c, lapack_int* ldc, + const lapack_complex_float* d, lapack_int* ldd, + const lapack_complex_float* e, lapack_int* lde, + lapack_complex_float* f, lapack_int* ldf, float* scale, + float* dif, lapack_complex_float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_ztgsyl( char* trans, lapack_int* ijob, lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + const lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* c, lapack_int* ldc, + const lapack_complex_double* d, lapack_int* ldd, + const lapack_complex_double* e, lapack_int* lde, + lapack_complex_double* f, lapack_int* ldf, double* scale, + double* dif, lapack_complex_double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_stgsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const float* a, lapack_int* lda, + const float* b, lapack_int* ldb, const float* vl, + lapack_int* ldvl, const float* vr, lapack_int* ldvr, + float* s, float* dif, lapack_int* mm, lapack_int* m, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dtgsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const double* a, lapack_int* lda, + const double* b, lapack_int* ldb, const double* vl, + lapack_int* ldvl, const double* vr, lapack_int* ldvr, + double* s, double* dif, lapack_int* mm, lapack_int* m, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_ctgsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, const lapack_complex_float* b, + lapack_int* ldb, const lapack_complex_float* vl, + lapack_int* ldvl, const lapack_complex_float* vr, + lapack_int* ldvr, float* s, float* dif, lapack_int* mm, + lapack_int* m, lapack_complex_float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_ztgsna( char* job, char* howmny, const lapack_logical* select, + lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, const lapack_complex_double* b, + lapack_int* ldb, const lapack_complex_double* vl, + lapack_int* ldvl, const lapack_complex_double* vr, + lapack_int* ldvr, double* s, double* dif, lapack_int* mm, + lapack_int* m, lapack_complex_double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_sggsvp( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, float* a, lapack_int* lda, + float* b, lapack_int* ldb, float* tola, float* tolb, + lapack_int* k, lapack_int* l, float* u, lapack_int* ldu, + float* v, lapack_int* ldv, float* q, lapack_int* ldq, + lapack_int* iwork, float* tau, float* work, + lapack_int *info ); +void LAPACK_dggsvp( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, double* a, lapack_int* lda, + double* b, lapack_int* ldb, double* tola, double* tolb, + lapack_int* k, lapack_int* l, double* u, lapack_int* ldu, + double* v, lapack_int* ldv, double* q, lapack_int* ldq, + lapack_int* iwork, double* tau, double* work, + lapack_int *info ); +void LAPACK_cggsvp( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* b, lapack_int* ldb, + float* tola, float* tolb, lapack_int* k, lapack_int* l, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* v, lapack_int* ldv, + lapack_complex_float* q, lapack_int* ldq, lapack_int* iwork, + float* rwork, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zggsvp( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* b, lapack_int* ldb, + double* tola, double* tolb, lapack_int* k, lapack_int* l, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* v, lapack_int* ldv, + lapack_complex_double* q, lapack_int* ldq, + lapack_int* iwork, double* rwork, + lapack_complex_double* tau, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_sggsvp3( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, float* a, lapack_int* lda, + float* b, lapack_int* ldb, float* tola, float* tolb, + lapack_int* k, lapack_int* l, float* u, lapack_int* ldu, + float* v, lapack_int* ldv, float* q, lapack_int* ldq, + lapack_int* iwork, float* tau, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dggsvp3( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, double* a, lapack_int* lda, + double* b, lapack_int* ldb, double* tola, double* tolb, + lapack_int* k, lapack_int* l, double* u, lapack_int* ldu, + double* v, lapack_int* ldv, double* q, lapack_int* ldq, + lapack_int* iwork, double* tau, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cggsvp3( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* b, lapack_int* ldb, + float* tola, float* tolb, lapack_int* k, lapack_int* l, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* v, lapack_int* ldv, + lapack_complex_float* q, lapack_int* ldq, lapack_int* iwork, + float* rwork, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zggsvp3( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* b, lapack_int* ldb, + double* tola, double* tolb, lapack_int* k, lapack_int* l, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* v, lapack_int* ldv, + lapack_complex_double* q, lapack_int* ldq, + lapack_int* iwork, double* rwork, + lapack_complex_double* tau, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_stgsja( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_int* k, lapack_int* l, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* tola, float* tolb, float* alpha, float* beta, + float* u, lapack_int* ldu, float* v, lapack_int* ldv, + float* q, lapack_int* ldq, float* work, lapack_int* ncycle, + lapack_int *info ); +void LAPACK_dtgsja( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_int* k, lapack_int* l, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* tola, double* tolb, double* alpha, double* beta, + double* u, lapack_int* ldu, double* v, lapack_int* ldv, + double* q, lapack_int* ldq, double* work, + lapack_int* ncycle, lapack_int *info ); +void LAPACK_ctgsja( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* tola, + float* tolb, float* alpha, float* beta, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* v, lapack_int* ldv, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* work, lapack_int* ncycle, + lapack_int *info ); +void LAPACK_ztgsja( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* p, lapack_int* n, lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* tola, + double* tolb, double* alpha, double* beta, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* v, lapack_int* ldv, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* work, lapack_int* ncycle, + lapack_int *info ); +void LAPACK_sgels( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_dgels( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_cgels( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgels( char* trans, lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_sgelsy( lapack_int* m, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, float* b, lapack_int* ldb, + lapack_int* jpvt, float* rcond, lapack_int* rank, + float* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_dgelsy( lapack_int* m, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, + lapack_int* jpvt, double* rcond, lapack_int* rank, + double* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_cgelsy( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, lapack_int* jpvt, + float* rcond, lapack_int* rank, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int *info ); +void LAPACK_zgelsy( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, lapack_int* jpvt, + double* rcond, lapack_int* rank, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_sgelss( lapack_int* m, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* s, + float* rcond, lapack_int* rank, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgelss( lapack_int* m, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* s, + double* rcond, lapack_int* rank, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgelss( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* s, + float* rcond, lapack_int* rank, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int *info ); +void LAPACK_zgelss( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* s, + double* rcond, lapack_int* rank, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_sgelsd( lapack_int* m, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* s, + float* rcond, lapack_int* rank, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_dgelsd( lapack_int* m, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* s, + double* rcond, lapack_int* rank, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_cgelsd( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* s, + float* rcond, lapack_int* rank, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_zgelsd( lapack_int* m, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* s, + double* rcond, lapack_int* rank, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_sgglse( lapack_int* m, lapack_int* n, lapack_int* p, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* c, + float* d, float* x, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgglse( lapack_int* m, lapack_int* n, lapack_int* p, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* c, + double* d, double* x, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgglse( lapack_int* m, lapack_int* n, lapack_int* p, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* c, lapack_complex_float* d, + lapack_complex_float* x, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zgglse( lapack_int* m, lapack_int* n, lapack_int* p, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* c, lapack_complex_double* d, + lapack_complex_double* x, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sggglm( lapack_int* n, lapack_int* m, lapack_int* p, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* d, + float* x, float* y, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dggglm( lapack_int* n, lapack_int* m, lapack_int* p, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* d, + double* x, double* y, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cggglm( lapack_int* n, lapack_int* m, lapack_int* p, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* d, lapack_complex_float* x, + lapack_complex_float* y, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zggglm( lapack_int* n, lapack_int* m, lapack_int* p, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* d, lapack_complex_double* x, + lapack_complex_double* y, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_ssyev( char* jobz, char* uplo, lapack_int* n, float* a, + lapack_int* lda, float* w, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dsyev( char* jobz, char* uplo, lapack_int* n, double* a, + lapack_int* lda, double* w, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cheev( char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* w, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zheev( char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* w, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_ssyevd( char* jobz, char* uplo, lapack_int* n, float* a, + lapack_int* lda, float* w, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dsyevd( char* jobz, char* uplo, lapack_int* n, double* a, + lapack_int* lda, double* w, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_cheevd( char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* w, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zheevd( char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* w, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_ssyevx( char* jobz, char* range, char* uplo, lapack_int* n, + float* a, lapack_int* lda, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, float* z, lapack_int* ldz, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dsyevx( char* jobz, char* range, char* uplo, lapack_int* n, + double* a, lapack_int* lda, double* vl, double* vu, + lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, double* z, lapack_int* ldz, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_cheevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_zheevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_ssyevr( char* jobz, char* range, char* uplo, lapack_int* n, + float* a, lapack_int* lda, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, float* z, lapack_int* ldz, + lapack_int* isuppz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dsyevr( char* jobz, char* range, char* uplo, lapack_int* n, + double* a, lapack_int* lda, double* vl, double* vu, + lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, double* z, lapack_int* ldz, + lapack_int* isuppz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_cheevr( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_int* isuppz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zheevr( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_int* isuppz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sspev( char* jobz, char* uplo, lapack_int* n, float* ap, float* w, + float* z, lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dspev( char* jobz, char* uplo, lapack_int* n, double* ap, double* w, + double* z, lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_chpev( char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* ap, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, float* rwork, + lapack_int *info ); +void LAPACK_zhpev( char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* ap, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sspevd( char* jobz, char* uplo, lapack_int* n, float* ap, float* w, + float* z, lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dspevd( char* jobz, char* uplo, lapack_int* n, double* ap, + double* w, double* z, lapack_int* ldz, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_chpevd( char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* ap, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* lrwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_zhpevd( char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* ap, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sspevx( char* jobz, char* range, char* uplo, lapack_int* n, + float* ap, float* vl, float* vu, lapack_int* il, + lapack_int* iu, float* abstol, lapack_int* m, float* w, + float* z, lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dspevx( char* jobz, char* range, char* uplo, lapack_int* n, + double* ap, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_chpevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_float* ap, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_zhpevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_complex_double* ap, double* vl, double* vu, + lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_ssbev( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + float* ab, lapack_int* ldab, float* w, float* z, + lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dsbev( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + double* ab, lapack_int* ldab, double* w, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_chbev( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_float* ab, lapack_int* ldab, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, float* rwork, lapack_int *info ); +void LAPACK_zhbev( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_double* ab, lapack_int* ldab, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_ssbevd( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + float* ab, lapack_int* ldab, float* w, float* z, + lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dsbevd( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + double* ab, lapack_int* ldab, double* w, double* z, + lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_chbevd( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_float* ab, lapack_int* ldab, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zhbevd( char* jobz, char* uplo, lapack_int* n, lapack_int* kd, + lapack_complex_double* ab, lapack_int* ldab, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_ssbevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* kd, float* ab, lapack_int* ldab, float* q, + lapack_int* ldq, float* vl, float* vu, lapack_int* il, + lapack_int* iu, float* abstol, lapack_int* m, float* w, + float* z, lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dsbevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* kd, double* ab, lapack_int* ldab, double* q, + lapack_int* ldq, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_chbevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* kd, lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* q, lapack_int* ldq, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_zhbevx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* kd, lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* q, lapack_int* ldq, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_sstev( char* jobz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int *info ); +void LAPACK_dstev( char* jobz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_sstevd( char* jobz, lapack_int* n, float* d, float* e, float* z, + lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_dstevd( char* jobz, lapack_int* n, double* d, double* e, double* z, + lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_sstevx( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, float* z, + lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dstevx( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_sstevr( char* jobz, char* range, lapack_int* n, float* d, float* e, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, float* z, + lapack_int* ldz, lapack_int* isuppz, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_dstevr( char* jobz, char* range, lapack_int* n, double* d, + double* e, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, lapack_int* isuppz, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sgees( char* jobvs, char* sort, LAPACK_S_SELECT2 select, + lapack_int* n, float* a, lapack_int* lda, lapack_int* sdim, + float* wr, float* wi, float* vs, lapack_int* ldvs, + float* work, lapack_int* lwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_dgees( char* jobvs, char* sort, LAPACK_D_SELECT2 select, + lapack_int* n, double* a, lapack_int* lda, lapack_int* sdim, + double* wr, double* wi, double* vs, lapack_int* ldvs, + double* work, lapack_int* lwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_cgees( char* jobvs, char* sort, LAPACK_C_SELECT1 select, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int* ldvs, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_zgees( char* jobvs, char* sort, LAPACK_Z_SELECT1 select, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int* ldvs, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_logical* bwork, lapack_int *info ); +void LAPACK_sgeesx( char* jobvs, char* sort, LAPACK_S_SELECT2 select, + char* sense, lapack_int* n, float* a, lapack_int* lda, + lapack_int* sdim, float* wr, float* wi, float* vs, + lapack_int* ldvs, float* rconde, float* rcondv, float* work, + lapack_int* lwork, lapack_int* iwork, lapack_int* liwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_dgeesx( char* jobvs, char* sort, LAPACK_D_SELECT2 select, + char* sense, lapack_int* n, double* a, lapack_int* lda, + lapack_int* sdim, double* wr, double* wi, double* vs, + lapack_int* ldvs, double* rconde, double* rcondv, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_cgeesx( char* jobvs, char* sort, LAPACK_C_SELECT1 select, + char* sense, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* sdim, lapack_complex_float* w, + lapack_complex_float* vs, lapack_int* ldvs, float* rconde, + float* rcondv, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_zgeesx( char* jobvs, char* sort, LAPACK_Z_SELECT1 select, + char* sense, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* sdim, lapack_complex_double* w, + lapack_complex_double* vs, lapack_int* ldvs, double* rconde, + double* rcondv, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_sgeev( char* jobvl, char* jobvr, lapack_int* n, float* a, + lapack_int* lda, float* wr, float* wi, float* vl, + lapack_int* ldvl, float* vr, lapack_int* ldvr, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgeev( char* jobvl, char* jobvr, lapack_int* n, double* a, + lapack_int* lda, double* wr, double* wi, double* vl, + lapack_int* ldvl, double* vr, lapack_int* ldvr, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgeev( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int* ldvl, lapack_complex_float* vr, lapack_int* ldvr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zgeev( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int* ldvl, lapack_complex_double* vr, + lapack_int* ldvr, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int *info ); +void LAPACK_sgeevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, float* a, lapack_int* lda, float* wr, + float* wi, float* vl, lapack_int* ldvl, float* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + float* scale, float* abnrm, float* rconde, float* rcondv, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dgeevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, double* a, lapack_int* lda, double* wr, + double* wi, double* vl, lapack_int* ldvl, double* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + double* scale, double* abnrm, double* rconde, + double* rcondv, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgeevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* w, lapack_complex_float* vl, + lapack_int* ldvl, lapack_complex_float* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + float* scale, float* abnrm, float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zgeevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* w, lapack_complex_double* vl, + lapack_int* ldvl, lapack_complex_double* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + double* scale, double* abnrm, double* rconde, + double* rcondv, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int *info ); +void LAPACK_sgesvd( char* jobu, char* jobvt, lapack_int* m, lapack_int* n, + float* a, lapack_int* lda, float* s, float* u, + lapack_int* ldu, float* vt, lapack_int* ldvt, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_dgesvd( char* jobu, char* jobvt, lapack_int* m, lapack_int* n, + double* a, lapack_int* lda, double* s, double* u, + lapack_int* ldu, double* vt, lapack_int* ldvt, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgesvd( char* jobu, char* jobvt, lapack_int* m, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* s, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* vt, lapack_int* ldvt, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zgesvd( char* jobu, char* jobvt, lapack_int* m, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* s, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* vt, lapack_int* ldvt, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_sgesvdx( char* jobu, char* jobvt, char* range, lapack_int* m, lapack_int* n, + float* a, lapack_int* lda, lapack_int* vl, lapack_int* vu, + lapack_int* il, lapack_int* iu, lapack_int* ns, float* s, float* u, + lapack_int* ldu, float* vt, lapack_int* ldvt, float* work, + lapack_int* lwork, lapack_int *iwork, lapack_int *info ); +void LAPACK_dgesvdx( char* jobu, char* jobvt, char* range, lapack_int* m, lapack_int* n, + double* a, lapack_int* lda, lapack_int* vl, lapack_int* vu, + lapack_int* il, lapack_int* iu, lapack_int* ns, double* s, double* u, + lapack_int* ldu, double* vt, lapack_int* ldvt, double* work, + lapack_int* lwork, lapack_int *iwork, lapack_int *info ); +void LAPACK_cgesvdx( char* jobu, char* jobvt, char* range, lapack_int* m, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, lapack_int* vl, lapack_int* vu, + lapack_int* il, lapack_int* iu, lapack_int* ns, float* s, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* vt, lapack_int* ldvt, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *iwork, lapack_int *info ); +void LAPACK_zgesvdx( char* jobu, char* jobvt, char* range, lapack_int* m, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, lapack_int* vl, lapack_int* vu, + lapack_int* il, lapack_int* iu, lapack_int* ns, double* s, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* vt, lapack_int* ldvt, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *iwork, lapack_int *info ); +void LAPACK_sgesdd( char* jobz, lapack_int* m, lapack_int* n, float* a, + lapack_int* lda, float* s, float* u, lapack_int* ldu, + float* vt, lapack_int* ldvt, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dgesdd( char* jobz, lapack_int* m, lapack_int* n, double* a, + lapack_int* lda, double* s, double* u, lapack_int* ldu, + double* vt, lapack_int* ldvt, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_cgesdd( char* jobz, lapack_int* m, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, float* s, + lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* vt, lapack_int* ldvt, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zgesdd( char* jobz, lapack_int* m, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, double* s, + lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* vt, lapack_int* ldvt, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_dgejsv( char* joba, char* jobu, char* jobv, char* jobr, char* jobt, + char* jobp, lapack_int* m, lapack_int* n, double* a, + lapack_int* lda, double* sva, double* u, lapack_int* ldu, + double* v, lapack_int* ldv, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_sgejsv( char* joba, char* jobu, char* jobv, char* jobr, char* jobt, + char* jobp, lapack_int* m, lapack_int* n, float* a, + lapack_int* lda, float* sva, float* u, lapack_int* ldu, + float* v, lapack_int* ldv, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_cgejsv( char* joba, char* jobu, char* jobv, char* jobr, char* jobt, + char* jobp, lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, float* sva, lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* v, lapack_int* ldv, lapack_complex_float* cwork, + lapack_int* lwork, float* work, lapack_int* lrwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zgejsv( char* joba, char* jobu, char* jobv, char* jobr, char* jobt, + char* jobp, lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, double* sva, lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* v, lapack_int* ldv, lapack_complex_double* cwork, + lapack_int* lwork, double* work, lapack_int* lrwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_dgesvj( char* joba, char* jobu, char* jobv, lapack_int* m, + lapack_int* n, double* a, lapack_int* lda, double* sva, + lapack_int* mv, double* v, lapack_int* ldv, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_sgesvj( char* joba, char* jobu, char* jobv, lapack_int* m, + lapack_int* n, float* a, lapack_int* lda, float* sva, + lapack_int* mv, float* v, lapack_int* ldv, float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cgesvj( char* joba, char* jobu, char* jobv, lapack_int* m, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, float* sva, + lapack_int* mv, lapack_complex_float* v, lapack_int* ldv, + lapack_complex_float* cwork, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int *info ); +void LAPACK_zgesvj( char* joba, char* jobu, char* jobv, lapack_int* m, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, double* sva, + lapack_int* mv, lapack_complex_double* v, lapack_int* ldv, + lapack_complex_double* cwork, lapack_int* lwork, double* rwork, + lapack_int* lrwork, lapack_int *info ); +void LAPACK_sggsvd( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* alpha, float* beta, float* u, lapack_int* ldu, + float* v, lapack_int* ldv, float* q, lapack_int* ldq, + float* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_dggsvd( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* alpha, double* beta, double* u, lapack_int* ldu, + double* v, lapack_int* ldv, double* q, lapack_int* ldq, + double* work, lapack_int* iwork, lapack_int *info ); +void LAPACK_cggsvd( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* alpha, + float* beta, lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* v, lapack_int* ldv, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* work, float* rwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_zggsvd( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* alpha, + double* beta, lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* v, lapack_int* ldv, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_sggsvd3( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* alpha, float* beta, float* u, lapack_int* ldu, + float* v, lapack_int* ldv, float* q, lapack_int* ldq, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_dggsvd3( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* alpha, double* beta, double* u, lapack_int* ldu, + double* v, lapack_int* ldv, double* q, lapack_int* ldq, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int *info ); +void LAPACK_cggsvd3( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* alpha, + float* beta, lapack_complex_float* u, lapack_int* ldu, + lapack_complex_float* v, lapack_int* ldv, + lapack_complex_float* q, lapack_int* ldq, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* iwork, lapack_int *info ); +void LAPACK_zggsvd3( char* jobu, char* jobv, char* jobq, lapack_int* m, + lapack_int* n, lapack_int* p, lapack_int* k, lapack_int* l, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* alpha, + double* beta, lapack_complex_double* u, lapack_int* ldu, + lapack_complex_double* v, lapack_int* ldv, + lapack_complex_double* q, lapack_int* ldq, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* iwork, lapack_int *info ); +void LAPACK_ssygv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* w, float* work, lapack_int* lwork, lapack_int *info ); +void LAPACK_dsygv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* w, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_chegv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* w, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zhegv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* w, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_ssygvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* w, float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dsygvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* w, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_chegvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* w, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zhegvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* w, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_ssygvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* vl, float* vu, lapack_int* il, + lapack_int* iu, float* abstol, lapack_int* m, float* w, + float* z, lapack_int* ldz, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_dsygvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_chegvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, float* vl, + float* vu, lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_zhegvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_sspgv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + float* ap, float* bp, float* w, float* z, lapack_int* ldz, + float* work, lapack_int *info ); +void LAPACK_dspgv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + double* ap, double* bp, double* w, double* z, + lapack_int* ldz, double* work, lapack_int *info ); +void LAPACK_chpgv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* ap, lapack_complex_float* bp, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, float* rwork, lapack_int *info ); +void LAPACK_zhpgv( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* ap, lapack_complex_double* bp, + double* w, lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_sspgvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + float* ap, float* bp, float* w, float* z, lapack_int* ldz, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dspgvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + double* ap, double* bp, double* w, double* z, + lapack_int* ldz, double* work, lapack_int* lwork, + lapack_int* iwork, lapack_int* liwork, lapack_int *info ); +void LAPACK_chpgvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_float* ap, lapack_complex_float* bp, + float* w, lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zhpgvd( lapack_int* itype, char* jobz, char* uplo, lapack_int* n, + lapack_complex_double* ap, lapack_complex_double* bp, + double* w, lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_sspgvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, float* ap, float* bp, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, float* z, lapack_int* ldz, + float* work, lapack_int* iwork, lapack_int* ifail, + lapack_int *info ); +void LAPACK_dspgvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, double* ap, double* bp, double* vl, + double* vu, lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, double* z, lapack_int* ldz, + double* work, lapack_int* iwork, lapack_int* ifail, + lapack_int *info ); +void LAPACK_chpgvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, lapack_complex_float* ap, + lapack_complex_float* bp, float* vl, float* vu, + lapack_int* il, lapack_int* iu, float* abstol, + lapack_int* m, float* w, lapack_complex_float* z, + lapack_int* ldz, lapack_complex_float* work, float* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_zhpgvx( lapack_int* itype, char* jobz, char* range, char* uplo, + lapack_int* n, lapack_complex_double* ap, + lapack_complex_double* bp, double* vl, double* vu, + lapack_int* il, lapack_int* iu, double* abstol, + lapack_int* m, double* w, lapack_complex_double* z, + lapack_int* ldz, lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_ssbgv( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, float* ab, lapack_int* ldab, float* bb, + lapack_int* ldbb, float* w, float* z, lapack_int* ldz, + float* work, lapack_int *info ); +void LAPACK_dsbgv( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, double* ab, lapack_int* ldab, double* bb, + lapack_int* ldbb, double* w, double* z, lapack_int* ldz, + double* work, lapack_int *info ); +void LAPACK_chbgv( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* bb, lapack_int* ldbb, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, float* rwork, lapack_int *info ); +void LAPACK_zhbgv( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* bb, lapack_int* ldbb, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int *info ); +void LAPACK_ssbgvd( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, float* ab, lapack_int* ldab, float* bb, + lapack_int* ldbb, float* w, float* z, lapack_int* ldz, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_dsbgvd( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, double* ab, lapack_int* ldab, double* bb, + lapack_int* ldbb, double* w, double* z, lapack_int* ldz, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_chbgvd( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_float* ab, lapack_int* ldab, + lapack_complex_float* bb, lapack_int* ldbb, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* lrwork, lapack_int* iwork, lapack_int* liwork, + lapack_int *info ); +void LAPACK_zhbgvd( char* jobz, char* uplo, lapack_int* n, lapack_int* ka, + lapack_int* kb, lapack_complex_double* ab, lapack_int* ldab, + lapack_complex_double* bb, lapack_int* ldbb, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, lapack_int* iwork, + lapack_int* liwork, lapack_int *info ); +void LAPACK_ssbgvx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* ka, lapack_int* kb, float* ab, lapack_int* ldab, + float* bb, lapack_int* ldbb, float* q, lapack_int* ldq, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, float* z, + lapack_int* ldz, float* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_dsbgvx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* ka, lapack_int* kb, double* ab, + lapack_int* ldab, double* bb, lapack_int* ldbb, double* q, + lapack_int* ldq, double* vl, double* vu, lapack_int* il, + lapack_int* iu, double* abstol, lapack_int* m, double* w, + double* z, lapack_int* ldz, double* work, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_chbgvx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* ka, lapack_int* kb, lapack_complex_float* ab, + lapack_int* ldab, lapack_complex_float* bb, + lapack_int* ldbb, lapack_complex_float* q, lapack_int* ldq, + float* vl, float* vu, lapack_int* il, lapack_int* iu, + float* abstol, lapack_int* m, float* w, + lapack_complex_float* z, lapack_int* ldz, + lapack_complex_float* work, float* rwork, lapack_int* iwork, + lapack_int* ifail, lapack_int *info ); +void LAPACK_zhbgvx( char* jobz, char* range, char* uplo, lapack_int* n, + lapack_int* ka, lapack_int* kb, lapack_complex_double* ab, + lapack_int* ldab, lapack_complex_double* bb, + lapack_int* ldbb, lapack_complex_double* q, lapack_int* ldq, + double* vl, double* vu, lapack_int* il, lapack_int* iu, + double* abstol, lapack_int* m, double* w, + lapack_complex_double* z, lapack_int* ldz, + lapack_complex_double* work, double* rwork, + lapack_int* iwork, lapack_int* ifail, lapack_int *info ); +void LAPACK_sgges( char* jobvsl, char* jobvsr, char* sort, + LAPACK_S_SELECT3 selctg, lapack_int* n, float* a, + lapack_int* lda, float* b, lapack_int* ldb, lapack_int* sdim, + float* alphar, float* alphai, float* beta, float* vsl, + lapack_int* ldvsl, float* vsr, lapack_int* ldvsr, + float* work, lapack_int* lwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_dgges( char* jobvsl, char* jobvsr, char* sort, + LAPACK_D_SELECT3 selctg, lapack_int* n, double* a, + lapack_int* lda, double* b, lapack_int* ldb, + lapack_int* sdim, double* alphar, double* alphai, + double* beta, double* vsl, lapack_int* ldvsl, double* vsr, + lapack_int* ldvsr, double* work, lapack_int* lwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_cgges( char* jobvsl, char* jobvsr, char* sort, + LAPACK_C_SELECT2 selctg, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, lapack_int* sdim, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int* ldvsl, + lapack_complex_float* vsr, lapack_int* ldvsr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_zgges( char* jobvsl, char* jobvsr, char* sort, + LAPACK_Z_SELECT2 selctg, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, lapack_int* sdim, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int* ldvsl, + lapack_complex_double* vsr, lapack_int* ldvsr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_logical* bwork, lapack_int *info ); +void LAPACK_sgges3( char* jobvsl, char* jobvsr, char* sort, + LAPACK_S_SELECT3 selctg, lapack_int* n, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + lapack_int* sdim, float* alphar, float* alphai, + float* beta, float* vsl, lapack_int* ldvsl, + float* vsr, lapack_int* ldvsr, + float* work, lapack_int* lwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_dgges3( char* jobvsl, char* jobvsr, char* sort, + LAPACK_D_SELECT3 selctg, lapack_int* n, double* a, + lapack_int* lda, double* b, lapack_int* ldb, + lapack_int* sdim, double* alphar, double* alphai, + double* beta, double* vsl, lapack_int* ldvsl, double* vsr, + lapack_int* ldvsr, double* work, lapack_int* lwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_cgges3( char* jobvsl, char* jobvsr, char* sort, + LAPACK_C_SELECT2 selctg, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_int* sdim, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int* ldvsl, + lapack_complex_float* vsr, lapack_int* ldvsr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_zgges3( char* jobvsl, char* jobvsr, char* sort, + LAPACK_Z_SELECT2 selctg, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, lapack_int* sdim, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int* ldvsl, + lapack_complex_double* vsr, lapack_int* ldvsr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_logical* bwork, lapack_int *info ); +void LAPACK_sggesx( char* jobvsl, char* jobvsr, char* sort, + LAPACK_S_SELECT3 selctg, char* sense, lapack_int* n, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + lapack_int* sdim, float* alphar, float* alphai, float* beta, + float* vsl, lapack_int* ldvsl, float* vsr, + lapack_int* ldvsr, float* rconde, float* rcondv, + float* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_dggesx( char* jobvsl, char* jobvsr, char* sort, + LAPACK_D_SELECT3 selctg, char* sense, lapack_int* n, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + lapack_int* sdim, double* alphar, double* alphai, + double* beta, double* vsl, lapack_int* ldvsl, double* vsr, + lapack_int* ldvsr, double* rconde, double* rcondv, + double* work, lapack_int* lwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_cggesx( char* jobvsl, char* jobvsr, char* sort, + LAPACK_C_SELECT2 selctg, char* sense, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, lapack_int* sdim, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vsl, lapack_int* ldvsl, + lapack_complex_float* vsr, lapack_int* ldvsr, float* rconde, + float* rcondv, lapack_complex_float* work, + lapack_int* lwork, float* rwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_zggesx( char* jobvsl, char* jobvsr, char* sort, + LAPACK_Z_SELECT2 selctg, char* sense, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, lapack_int* sdim, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vsl, lapack_int* ldvsl, + lapack_complex_double* vsr, lapack_int* ldvsr, + double* rconde, double* rcondv, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int* iwork, + lapack_int* liwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_sggev( char* jobvl, char* jobvr, lapack_int* n, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* alphar, + float* alphai, float* beta, float* vl, lapack_int* ldvl, + float* vr, lapack_int* ldvr, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dggev( char* jobvl, char* jobvr, lapack_int* n, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* alphar, + double* alphai, double* beta, double* vl, lapack_int* ldvl, + double* vr, lapack_int* ldvr, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cggev( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int* ldvl, + lapack_complex_float* vr, lapack_int* ldvr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zggev( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int* ldvl, + lapack_complex_double* vr, lapack_int* ldvr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_sggev3( char* jobvl, char* jobvr, lapack_int* n, float* a, + lapack_int* lda, float* b, lapack_int* ldb, float* alphar, + float* alphai, float* beta, float* vl, lapack_int* ldvl, + float* vr, lapack_int* ldvr, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dggev3( char* jobvl, char* jobvr, lapack_int* n, double* a, + lapack_int* lda, double* b, lapack_int* ldb, double* alphar, + double* alphai, double* beta, double* vl, lapack_int* ldvl, + double* vr, lapack_int* ldvr, double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_cggev3( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int* ldvl, + lapack_complex_float* vr, lapack_int* ldvr, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int *info ); +void LAPACK_zggev3( char* jobvl, char* jobvr, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int* ldvl, + lapack_complex_double* vr, lapack_int* ldvr, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int *info ); +void LAPACK_sggevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* alphar, float* alphai, float* beta, + float* vl, lapack_int* ldvl, float* vr, lapack_int* ldvr, + lapack_int* ilo, lapack_int* ihi, float* lscale, + float* rscale, float* abnrm, float* bbnrm, float* rconde, + float* rcondv, float* work, lapack_int* lwork, + lapack_int* iwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_dggevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* alphar, double* alphai, + double* beta, double* vl, lapack_int* ldvl, double* vr, + lapack_int* ldvr, lapack_int* ilo, lapack_int* ihi, + double* lscale, double* rscale, double* abnrm, + double* bbnrm, double* rconde, double* rcondv, double* work, + lapack_int* lwork, lapack_int* iwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_cggevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* vl, lapack_int* ldvl, + lapack_complex_float* vr, lapack_int* ldvr, lapack_int* ilo, + lapack_int* ihi, float* lscale, float* rscale, float* abnrm, + float* bbnrm, float* rconde, float* rcondv, + lapack_complex_float* work, lapack_int* lwork, float* rwork, + lapack_int* iwork, lapack_logical* bwork, + lapack_int *info ); +void LAPACK_zggevx( char* balanc, char* jobvl, char* jobvr, char* sense, + lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* vl, lapack_int* ldvl, + lapack_complex_double* vr, lapack_int* ldvr, + lapack_int* ilo, lapack_int* ihi, double* lscale, + double* rscale, double* abnrm, double* bbnrm, + double* rconde, double* rcondv, lapack_complex_double* work, + lapack_int* lwork, double* rwork, lapack_int* iwork, + lapack_logical* bwork, lapack_int *info ); +void LAPACK_dsfrk( char* transr, char* uplo, char* trans, lapack_int* n, + lapack_int* k, double* alpha, const double* a, + lapack_int* lda, double* beta, double* c ); +void LAPACK_ssfrk( char* transr, char* uplo, char* trans, lapack_int* n, + lapack_int* k, float* alpha, const float* a, lapack_int* lda, + float* beta, float* c ); +void LAPACK_zhfrk( char* transr, char* uplo, char* trans, lapack_int* n, + lapack_int* k, double* alpha, const lapack_complex_double* a, + lapack_int* lda, double* beta, lapack_complex_double* c ); +void LAPACK_chfrk( char* transr, char* uplo, char* trans, lapack_int* n, + lapack_int* k, float* alpha, const lapack_complex_float* a, + lapack_int* lda, float* beta, lapack_complex_float* c ); +void LAPACK_dtfsm( char* transr, char* side, char* uplo, char* trans, + char* diag, lapack_int* m, lapack_int* n, double* alpha, + const double* a, double* b, lapack_int* ldb ); +void LAPACK_stfsm( char* transr, char* side, char* uplo, char* trans, + char* diag, lapack_int* m, lapack_int* n, float* alpha, + const float* a, float* b, lapack_int* ldb ); +void LAPACK_ztfsm( char* transr, char* side, char* uplo, char* trans, + char* diag, lapack_int* m, lapack_int* n, + lapack_complex_double* alpha, const lapack_complex_double* a, + lapack_complex_double* b, lapack_int* ldb ); +void LAPACK_ctfsm( char* transr, char* side, char* uplo, char* trans, + char* diag, lapack_int* m, lapack_int* n, + lapack_complex_float* alpha, const lapack_complex_float* a, + lapack_complex_float* b, lapack_int* ldb ); +void LAPACK_dtfttp( char* transr, char* uplo, lapack_int* n, const double* arf, + double* ap, lapack_int *info ); +void LAPACK_stfttp( char* transr, char* uplo, lapack_int* n, const float* arf, + float* ap, lapack_int *info ); +void LAPACK_ztfttp( char* transr, char* uplo, lapack_int* n, + const lapack_complex_double* arf, lapack_complex_double* ap, + lapack_int *info ); +void LAPACK_ctfttp( char* transr, char* uplo, lapack_int* n, + const lapack_complex_float* arf, lapack_complex_float* ap, + lapack_int *info ); +void LAPACK_dtfttr( char* transr, char* uplo, lapack_int* n, const double* arf, + double* a, lapack_int* lda, lapack_int *info ); +void LAPACK_stfttr( char* transr, char* uplo, lapack_int* n, const float* arf, + float* a, lapack_int* lda, lapack_int *info ); +void LAPACK_ztfttr( char* transr, char* uplo, lapack_int* n, + const lapack_complex_double* arf, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_ctfttr( char* transr, char* uplo, lapack_int* n, + const lapack_complex_float* arf, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_dtpttf( char* transr, char* uplo, lapack_int* n, const double* ap, + double* arf, lapack_int *info ); +void LAPACK_stpttf( char* transr, char* uplo, lapack_int* n, const float* ap, + float* arf, lapack_int *info ); +void LAPACK_ztpttf( char* transr, char* uplo, lapack_int* n, + const lapack_complex_double* ap, lapack_complex_double* arf, + lapack_int *info ); +void LAPACK_ctpttf( char* transr, char* uplo, lapack_int* n, + const lapack_complex_float* ap, lapack_complex_float* arf, + lapack_int *info ); +void LAPACK_dtpttr( char* uplo, lapack_int* n, const double* ap, double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_stpttr( char* uplo, lapack_int* n, const float* ap, float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_ztpttr( char* uplo, lapack_int* n, const lapack_complex_double* ap, + lapack_complex_double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_ctpttr( char* uplo, lapack_int* n, const lapack_complex_float* ap, + lapack_complex_float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dtrttf( char* transr, char* uplo, lapack_int* n, const double* a, + lapack_int* lda, double* arf, lapack_int *info ); +void LAPACK_strttf( char* transr, char* uplo, lapack_int* n, const float* a, + lapack_int* lda, float* arf, lapack_int *info ); +void LAPACK_ztrttf( char* transr, char* uplo, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* arf, lapack_int *info ); +void LAPACK_ctrttf( char* transr, char* uplo, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* arf, lapack_int *info ); +void LAPACK_dtrttp( char* uplo, lapack_int* n, const double* a, lapack_int* lda, + double* ap, lapack_int *info ); +void LAPACK_strttp( char* uplo, lapack_int* n, const float* a, lapack_int* lda, + float* ap, lapack_int *info ); +void LAPACK_ztrttp( char* uplo, lapack_int* n, const lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* ap, + lapack_int *info ); +void LAPACK_ctrttp( char* uplo, lapack_int* n, const lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* ap, + lapack_int *info ); +void LAPACK_sgeqrfp( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dgeqrfp( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_cgeqrfp( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zgeqrfp( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_clacgv( lapack_int* n, lapack_complex_float* x, lapack_int* incx ); +void LAPACK_zlacgv( lapack_int* n, lapack_complex_double* x, lapack_int* incx ); +void LAPACK_slarnv( lapack_int* idist, lapack_int* iseed, lapack_int* n, + float* x ); +void LAPACK_dlarnv( lapack_int* idist, lapack_int* iseed, lapack_int* n, + double* x ); +void LAPACK_clarnv( lapack_int* idist, lapack_int* iseed, lapack_int* n, + lapack_complex_float* x ); +void LAPACK_zlarnv( lapack_int* idist, lapack_int* iseed, lapack_int* n, + lapack_complex_double* x ); +void LAPACK_sgeqr2( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int *info ); +void LAPACK_dgeqr2( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int *info ); +void LAPACK_cgeqr2( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zgeqr2( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_slacn2( lapack_int* n, float* v, float* x, lapack_int* isgn, + float* est, lapack_int* kase, lapack_int* isave ); +void LAPACK_dlacn2( lapack_int* n, double* v, double* x, lapack_int* isgn, + double* est, lapack_int* kase, lapack_int* isave ); +void LAPACK_clacn2( lapack_int* n, lapack_complex_float* v, + lapack_complex_float* x, float* est, + lapack_int* kase, lapack_int* isave ); +void LAPACK_zlacn2( lapack_int* n, lapack_complex_double* v, + lapack_complex_double* x, double* est, + lapack_int* kase, lapack_int* isave ); +void LAPACK_slacpy( char* uplo, lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, float* b, lapack_int* ldb ); +void LAPACK_dlacpy( char* uplo, lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, double* b, lapack_int* ldb ); +void LAPACK_clacpy( char* uplo, lapack_int* m, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb ); +void LAPACK_zlacpy( char* uplo, lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb ); + +void LAPACK_clacp2( char* uplo, lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, lapack_complex_float* b, lapack_int* ldb ); +void LAPACK_zlacp2( char* uplo, lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, lapack_complex_double* b, + lapack_int* ldb ); + +void LAPACK_sgetf2( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_dgetf2( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ipiv, lapack_int *info ); +void LAPACK_cgetf2( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_zgetf2( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, lapack_int *info ); +void LAPACK_slaswp( lapack_int* n, float* a, lapack_int* lda, lapack_int* k1, + lapack_int* k2, const lapack_int* ipiv, lapack_int* incx ); +void LAPACK_dlaswp( lapack_int* n, double* a, lapack_int* lda, lapack_int* k1, + lapack_int* k2, const lapack_int* ipiv, lapack_int* incx ); +void LAPACK_claswp( lapack_int* n, lapack_complex_float* a, lapack_int* lda, + lapack_int* k1, lapack_int* k2, const lapack_int* ipiv, + lapack_int* incx ); +void LAPACK_zlaswp( lapack_int* n, lapack_complex_double* a, lapack_int* lda, + lapack_int* k1, lapack_int* k2, const lapack_int* ipiv, + lapack_int* incx ); +float LAPACK_slange( char* norm, lapack_int* m, lapack_int* n, const float* a, + lapack_int* lda, float* work ); +double LAPACK_dlange( char* norm, lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, double* work ); +float LAPACK_clange( char* norm, lapack_int* m, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, float* work ); +double LAPACK_zlange( char* norm, lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* work ); +float LAPACK_clanhe( char* norm, char* uplo, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, float* work ); +double LAPACK_zlanhe( char* norm, char* uplo, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* work ); +float LAPACK_slansy( char* norm, char* uplo, lapack_int* n, const float* a, + lapack_int* lda, float* work ); +double LAPACK_dlansy( char* norm, char* uplo, lapack_int* n, const double* a, + lapack_int* lda, double* work ); +float LAPACK_clansy( char* norm, char* uplo, lapack_int* n, + const lapack_complex_float* a, lapack_int* lda, float* work ); +double LAPACK_zlansy( char* norm, char* uplo, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, double* work ); +float LAPACK_slantr( char* norm, char* uplo, char* diag, lapack_int* m, + lapack_int* n, const float* a, lapack_int* lda, float* work ); +double LAPACK_dlantr( char* norm, char* uplo, char* diag, lapack_int* m, + lapack_int* n, const double* a, lapack_int* lda, double* work ); +float LAPACK_clantr( char* norm, char* uplo, char* diag, lapack_int* m, + lapack_int* n, const lapack_complex_float* a, lapack_int* lda, + float* work ); +double LAPACK_zlantr( char* norm, char* uplo, char* diag, lapack_int* m, + lapack_int* n, const lapack_complex_double* a, lapack_int* lda, + double* work ); +float LAPACK_slamch( char* cmach ); +double LAPACK_dlamch( char* cmach ); +void LAPACK_sgelq2( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* tau, float* work, lapack_int *info ); +void LAPACK_dgelq2( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* tau, double* work, lapack_int *info ); +void LAPACK_cgelq2( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* tau, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zgelq2( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* tau, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_slarfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, const float* v, + lapack_int* ldv, const float* t, lapack_int* ldt, float* c, + lapack_int* ldc, float* work, lapack_int* ldwork ); +void LAPACK_dlarfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, + const double* v, lapack_int* ldv, const double* t, + lapack_int* ldt, double* c, lapack_int* ldc, double* work, + lapack_int* ldwork ); +void LAPACK_clarfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int* ldwork ); +void LAPACK_zlarfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int* ldwork ); +void LAPACK_slarfg( lapack_int* n, float* alpha, float* x, lapack_int* incx, + float* tau ); +void LAPACK_dlarfg( lapack_int* n, double* alpha, double* x, lapack_int* incx, + double* tau ); +void LAPACK_clarfg( lapack_int* n, lapack_complex_float* alpha, + lapack_complex_float* x, lapack_int* incx, + lapack_complex_float* tau ); +void LAPACK_zlarfg( lapack_int* n, lapack_complex_double* alpha, + lapack_complex_double* x, lapack_int* incx, + lapack_complex_double* tau ); +void LAPACK_slarft( char* direct, char* storev, lapack_int* n, lapack_int* k, + const float* v, lapack_int* ldv, const float* tau, float* t, + lapack_int* ldt ); +void LAPACK_dlarft( char* direct, char* storev, lapack_int* n, lapack_int* k, + const double* v, lapack_int* ldv, const double* tau, + double* t, lapack_int* ldt ); +void LAPACK_clarft( char* direct, char* storev, lapack_int* n, lapack_int* k, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* tau, lapack_complex_float* t, + lapack_int* ldt ); +void LAPACK_zlarft( char* direct, char* storev, lapack_int* n, lapack_int* k, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* tau, lapack_complex_double* t, + lapack_int* ldt ); +void LAPACK_slarfx( char* side, lapack_int* m, lapack_int* n, const float* v, + float* tau, float* c, lapack_int* ldc, float* work ); +void LAPACK_dlarfx( char* side, lapack_int* m, lapack_int* n, const double* v, + double* tau, double* c, lapack_int* ldc, double* work ); +void LAPACK_clarfx( char* side, lapack_int* m, lapack_int* n, + const lapack_complex_float* v, lapack_complex_float* tau, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work ); +void LAPACK_zlarfx( char* side, lapack_int* m, lapack_int* n, + const lapack_complex_double* v, lapack_complex_double* tau, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work ); +void LAPACK_slatms( lapack_int* m, lapack_int* n, char* dist, lapack_int* iseed, + char* sym, float* d, lapack_int* mode, float* cond, + float* dmax, lapack_int* kl, lapack_int* ku, char* pack, + float* a, lapack_int* lda, float* work, lapack_int *info ); +void LAPACK_dlatms( lapack_int* m, lapack_int* n, char* dist, lapack_int* iseed, + char* sym, double* d, lapack_int* mode, double* cond, + double* dmax, lapack_int* kl, lapack_int* ku, char* pack, + double* a, lapack_int* lda, double* work, + lapack_int *info ); +void LAPACK_clatms( lapack_int* m, lapack_int* n, char* dist, lapack_int* iseed, + char* sym, float* d, lapack_int* mode, float* cond, + float* dmax, lapack_int* kl, lapack_int* ku, char* pack, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zlatms( lapack_int* m, lapack_int* n, char* dist, lapack_int* iseed, + char* sym, double* d, lapack_int* mode, double* cond, + double* dmax, lapack_int* kl, lapack_int* ku, char* pack, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_slag2d( lapack_int* m, lapack_int* n, const float* sa, + lapack_int* ldsa, double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dlag2s( lapack_int* m, lapack_int* n, const double* a, + lapack_int* lda, float* sa, lapack_int* ldsa, + lapack_int *info ); +void LAPACK_clag2z( lapack_int* m, lapack_int* n, + const lapack_complex_float* sa, lapack_int* ldsa, + lapack_complex_double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_zlag2c( lapack_int* m, lapack_int* n, + const lapack_complex_double* a, lapack_int* lda, + lapack_complex_float* sa, lapack_int* ldsa, + lapack_int *info ); +void LAPACK_slauum( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_dlauum( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int *info ); +void LAPACK_clauum( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_zlauum( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_slagge( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const float* d, float* a, lapack_int* lda, + lapack_int* iseed, float* work, lapack_int *info ); +void LAPACK_dlagge( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const double* d, double* a, lapack_int* lda, + lapack_int* iseed, double* work, lapack_int *info ); +void LAPACK_clagge( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const float* d, lapack_complex_float* a, + lapack_int* lda, lapack_int* iseed, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zlagge( lapack_int* m, lapack_int* n, lapack_int* kl, + lapack_int* ku, const double* d, lapack_complex_double* a, + lapack_int* lda, lapack_int* iseed, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_slascl( char* type, lapack_int* kl, lapack_int* ku, float* cfrom, + float* cto, lapack_int* m, lapack_int* n, float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_dlascl( char* type, lapack_int* kl, lapack_int* ku, double* cfrom, + double* cto, lapack_int* m, lapack_int* n, double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_clascl( char* type, lapack_int* kl, lapack_int* ku, float* cfrom, + float* cto, lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_zlascl( char* type, lapack_int* kl, lapack_int* ku, double* cfrom, + double* cto, lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int *info ); +void LAPACK_slaset( char* uplo, lapack_int* m, lapack_int* n, float* alpha, + float* beta, float* a, lapack_int* lda ); +void LAPACK_dlaset( char* uplo, lapack_int* m, lapack_int* n, double* alpha, + double* beta, double* a, lapack_int* lda ); +void LAPACK_claset( char* uplo, lapack_int* m, lapack_int* n, + lapack_complex_float* alpha, lapack_complex_float* beta, + lapack_complex_float* a, lapack_int* lda ); +void LAPACK_zlaset( char* uplo, lapack_int* m, lapack_int* n, + lapack_complex_double* alpha, lapack_complex_double* beta, + lapack_complex_double* a, lapack_int* lda ); +void LAPACK_slasrt( char* id, lapack_int* n, float* d, lapack_int *info ); +void LAPACK_dlasrt( char* id, lapack_int* n, double* d, lapack_int *info ); +void LAPACK_claghe( lapack_int* n, lapack_int* k, const float* d, + lapack_complex_float* a, lapack_int* lda, lapack_int* iseed, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zlaghe( lapack_int* n, lapack_int* k, const double* d, + lapack_complex_double* a, lapack_int* lda, + lapack_int* iseed, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_slagsy( lapack_int* n, lapack_int* k, const float* d, float* a, + lapack_int* lda, lapack_int* iseed, float* work, + lapack_int *info ); +void LAPACK_dlagsy( lapack_int* n, lapack_int* k, const double* d, double* a, + lapack_int* lda, lapack_int* iseed, double* work, + lapack_int *info ); +void LAPACK_clagsy( lapack_int* n, lapack_int* k, const float* d, + lapack_complex_float* a, lapack_int* lda, lapack_int* iseed, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zlagsy( lapack_int* n, lapack_int* k, const double* d, + lapack_complex_double* a, lapack_int* lda, + lapack_int* iseed, lapack_complex_double* work, + lapack_int *info ); +void LAPACK_slapmr( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + float* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_dlapmr( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + double* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_clapmr( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + lapack_complex_float* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_zlapmr( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + lapack_complex_double* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_slapmt( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + float* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_dlapmt( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + double* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_clapmt( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + lapack_complex_float* x, lapack_int* ldx, lapack_int* k ); +void LAPACK_zlapmt( lapack_logical* forwrd, lapack_int* m, lapack_int* n, + lapack_complex_double* x, lapack_int* ldx, lapack_int* k ); +float LAPACK_slapy2( float* x, float* y ); +double LAPACK_dlapy2( double* x, double* y ); +float LAPACK_slapy3( float* x, float* y, float* z ); +double LAPACK_dlapy3( double* x, double* y, double* z ); +void LAPACK_slartgp( float* f, float* g, float* cs, float* sn, float* r ); +void LAPACK_dlartgp( double* f, double* g, double* cs, double* sn, double* r ); +void LAPACK_slartgs( float* x, float* y, float* sigma, float* cs, float* sn ); +void LAPACK_dlartgs( double* x, double* y, double* sigma, double* cs, + double* sn ); +// LAPACK 3.3.0 +void LAPACK_cbbcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + lapack_int* m, lapack_int* p, lapack_int* q, + float* theta, float* phi, + lapack_complex_float* u1, lapack_int* ldu1, + lapack_complex_float* u2, lapack_int* ldu2, + lapack_complex_float* v1t, lapack_int* ldv1t, + lapack_complex_float* v2t, lapack_int* ldv2t, + float* b11d, float* b11e, float* b12d, + float* b12e, float* b21d, float* b21e, + float* b22d, float* b22e, float* rwork, + lapack_int* lrwork , lapack_int *info ); +void LAPACK_cheswapr( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* i1, + lapack_int* i2 ); +void LAPACK_chetri2( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_chetri2x( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* nb , lapack_int *info ); +void LAPACK_chetrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work , lapack_int *info ); +void LAPACK_csyconv( char* uplo, char* way, + lapack_int* n, lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* work , lapack_int *info ); +void LAPACK_csyswapr( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* i1, + lapack_int* i2 ); +void LAPACK_csytri2( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_csytri2x( char* uplo, lapack_int* n, + lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* nb , lapack_int *info ); +void LAPACK_csytrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, const lapack_complex_float* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work , lapack_int *info ); +void LAPACK_cunbdb( char* trans, char* signs, + lapack_int* m, lapack_int* p, lapack_int* q, + lapack_complex_float* x11, lapack_int* ldx11, + lapack_complex_float* x12, lapack_int* ldx12, + lapack_complex_float* x21, lapack_int* ldx21, + lapack_complex_float* x22, lapack_int* ldx22, + float* theta, float* phi, + lapack_complex_float* taup1, + lapack_complex_float* taup2, + lapack_complex_float* tauq1, + lapack_complex_float* tauq2, + lapack_complex_float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_cuncsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + char* signs, lapack_int* m, lapack_int* p, + lapack_int* q, lapack_complex_float* x11, + lapack_int* ldx11, lapack_complex_float* x12, + lapack_int* ldx12, lapack_complex_float* x21, + lapack_int* ldx21, lapack_complex_float* x22, + lapack_int* ldx22, float* theta, + lapack_complex_float* u1, lapack_int* ldu1, + lapack_complex_float* u2, lapack_int* ldu2, + lapack_complex_float* v1t, lapack_int* ldv1t, + lapack_complex_float* v2t, lapack_int* ldv2t, + lapack_complex_float* work, lapack_int* lwork, + float* rwork, lapack_int* lrwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_cuncsd2by1( char* jobu1, char* jobu2, + char* jobv1t, lapack_int* m, lapack_int* p, + lapack_int* q, lapack_complex_float* x11, + lapack_int* ldx11, lapack_complex_float* x21, + lapack_int* ldx21, lapack_complex_float* theta, + lapack_complex_float* u1, lapack_int* ldu1, + lapack_complex_float* u2, lapack_int* ldu2, + lapack_complex_float* v1t, lapack_int* ldv1t, + lapack_complex_float* work, lapack_int* lwork, + float* rwork, lapack_int* lrwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_dbbcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + lapack_int* m, lapack_int* p, lapack_int* q, + double* theta, double* phi, double* u1, + lapack_int* ldu1, double* u2, lapack_int* ldu2, + double* v1t, lapack_int* ldv1t, double* v2t, + lapack_int* ldv2t, double* b11d, double* b11e, + double* b12d, double* b12e, double* b21d, + double* b21e, double* b22d, double* b22e, + double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_dorbdb( char* trans, char* signs, + lapack_int* m, lapack_int* p, lapack_int* q, + double* x11, lapack_int* ldx11, double* x12, + lapack_int* ldx12, double* x21, lapack_int* ldx21, + double* x22, lapack_int* ldx22, double* theta, + double* phi, double* taup1, double* taup2, + double* tauq1, double* tauq2, double* work, + lapack_int* lwork , lapack_int *info ); +void LAPACK_dorcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + char* signs, lapack_int* m, lapack_int* p, + lapack_int* q, double* x11, lapack_int* ldx11, + double* x12, lapack_int* ldx12, double* x21, + lapack_int* ldx21, double* x22, lapack_int* ldx22, + double* theta, double* u1, lapack_int* ldu1, + double* u2, lapack_int* ldu2, double* v1t, + lapack_int* ldv1t, double* v2t, lapack_int* ldv2t, + double* work, lapack_int* lwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_dorcsd2by1( char* jobu1, char* jobu2, + char* jobv1t, lapack_int* m, lapack_int* p, + lapack_int* q, double* x11, lapack_int* ldx11, + double* x21, lapack_int* ldx21, + double* theta, double* u1, lapack_int* ldu1, + double* u2, lapack_int* ldu2, double* v1t, + lapack_int* ldv1t, double* work, lapack_int* lwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_dsyconv( char* uplo, char* way, + lapack_int* n, double* a, lapack_int* lda, + const lapack_int* ipiv, double* work , lapack_int *info ); +void LAPACK_dsyswapr( char* uplo, lapack_int* n, + double* a, lapack_int* i1, lapack_int* i2 ); +void LAPACK_dsytri2( char* uplo, lapack_int* n, + double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_dsytri2x( char* uplo, lapack_int* n, + double* a, lapack_int* lda, + const lapack_int* ipiv, double* work, + lapack_int* nb , lapack_int *info ); +void LAPACK_dsytrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, const double* a, + lapack_int* lda, const lapack_int* ipiv, + double* b, lapack_int* ldb, double* work , lapack_int *info ); +void LAPACK_sbbcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + lapack_int* m, lapack_int* p, lapack_int* q, + float* theta, float* phi, float* u1, + lapack_int* ldu1, float* u2, lapack_int* ldu2, + float* v1t, lapack_int* ldv1t, float* v2t, + lapack_int* ldv2t, float* b11d, float* b11e, + float* b12d, float* b12e, float* b21d, + float* b21e, float* b22d, float* b22e, + float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_sorbdb( char* trans, char* signs, + lapack_int* m, lapack_int* p, lapack_int* q, + float* x11, lapack_int* ldx11, float* x12, + lapack_int* ldx12, float* x21, lapack_int* ldx21, + float* x22, lapack_int* ldx22, float* theta, + float* phi, float* taup1, float* taup2, + float* tauq1, float* tauq2, float* work, + lapack_int* lwork , lapack_int *info ); +void LAPACK_sorcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + char* signs, lapack_int* m, lapack_int* p, + lapack_int* q, float* x11, lapack_int* ldx11, + float* x12, lapack_int* ldx12, float* x21, + lapack_int* ldx21, float* x22, lapack_int* ldx22, + float* theta, float* u1, lapack_int* ldu1, + float* u2, lapack_int* ldu2, float* v1t, + lapack_int* ldv1t, float* v2t, lapack_int* ldv2t, + float* work, lapack_int* lwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_sorcsd2by1( char* jobu1, char* jobu2, + char* jobv1t, lapack_int* m, lapack_int* p, + lapack_int* q, float* x11, lapack_int* ldx11, + float* x21, lapack_int* ldx21, + float* theta, float* u1, lapack_int* ldu1, + float* u2, lapack_int* ldu2, float* v1t, + lapack_int* ldv1t, float* work, lapack_int* lwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_ssyconv( char* uplo, char* way, + lapack_int* n, float* a, lapack_int* lda, + const lapack_int* ipiv, float* work , lapack_int *info ); +void LAPACK_ssyswapr( char* uplo, lapack_int* n, + float* a, lapack_int* i1, lapack_int* i2 ); +void LAPACK_ssytri2( char* uplo, lapack_int* n, + float* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_ssytri2x( char* uplo, lapack_int* n, + float* a, lapack_int* lda, + const lapack_int* ipiv, float* work, + lapack_int* nb , lapack_int *info ); +void LAPACK_ssytrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, const float* a, + lapack_int* lda, const lapack_int* ipiv, + float* b, lapack_int* ldb, float* work , lapack_int *info ); +void LAPACK_zbbcsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + lapack_int* m, lapack_int* p, lapack_int* q, + double* theta, double* phi, + lapack_complex_double* u1, lapack_int* ldu1, + lapack_complex_double* u2, lapack_int* ldu2, + lapack_complex_double* v1t, lapack_int* ldv1t, + lapack_complex_double* v2t, lapack_int* ldv2t, + double* b11d, double* b11e, double* b12d, + double* b12e, double* b21d, double* b21e, + double* b22d, double* b22e, double* rwork, + lapack_int* lrwork , lapack_int *info ); +void LAPACK_zheswapr( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* i1, + lapack_int* i2 ); +void LAPACK_zhetri2( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_zhetri2x( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* nb , lapack_int *info ); +void LAPACK_zhetrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work , lapack_int *info ); +void LAPACK_zsyconv( char* uplo, char* way, + lapack_int* n, lapack_complex_double* a, + lapack_int* lda, const lapack_int* ipiv, + lapack_complex_double* work , lapack_int *info ); +void LAPACK_zsyswapr( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* i1, + lapack_int* i2 ); +void LAPACK_zsytri2( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_zsytri2x( char* uplo, lapack_int* n, + lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* work, lapack_int* nb , lapack_int *info ); +void LAPACK_zsytrs2( char* uplo, lapack_int* n, + lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work , lapack_int *info ); +void LAPACK_zunbdb( char* trans, char* signs, + lapack_int* m, lapack_int* p, lapack_int* q, + lapack_complex_double* x11, lapack_int* ldx11, + lapack_complex_double* x12, lapack_int* ldx12, + lapack_complex_double* x21, lapack_int* ldx21, + lapack_complex_double* x22, lapack_int* ldx22, + double* theta, double* phi, + lapack_complex_double* taup1, + lapack_complex_double* taup2, + lapack_complex_double* tauq1, + lapack_complex_double* tauq2, + lapack_complex_double* work, lapack_int* lwork , lapack_int *info ); +void LAPACK_zuncsd( char* jobu1, char* jobu2, + char* jobv1t, char* jobv2t, char* trans, + char* signs, lapack_int* m, lapack_int* p, + lapack_int* q, lapack_complex_double* x11, + lapack_int* ldx11, lapack_complex_double* x12, + lapack_int* ldx12, lapack_complex_double* x21, + lapack_int* ldx21, lapack_complex_double* x22, + lapack_int* ldx22, double* theta, + lapack_complex_double* u1, lapack_int* ldu1, + lapack_complex_double* u2, lapack_int* ldu2, + lapack_complex_double* v1t, lapack_int* ldv1t, + lapack_complex_double* v2t, lapack_int* ldv2t, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, + lapack_int* iwork , lapack_int *info ); +void LAPACK_zuncsd2by1( char* jobu1, char* jobu2, + char* jobv1t, lapack_int* m, lapack_int* p, + lapack_int* q, lapack_complex_double* x11, + lapack_int* ldx11, lapack_complex_double* x21, + lapack_int* ldx21, lapack_complex_double* theta, + lapack_complex_double* u1, lapack_int* ldu1, + lapack_complex_double* u2, lapack_int* ldu2, + lapack_complex_double* v1t, lapack_int* ldv1t, + lapack_complex_double* work, lapack_int* lwork, + double* rwork, lapack_int* lrwork, + lapack_int* iwork , lapack_int *info ); +// LAPACK 3.4.0 +void LAPACK_sgemqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* nb, const float* v, + lapack_int* ldv, const float* t, lapack_int* ldt, float* c, + lapack_int* ldc, float* work, lapack_int *info ); +void LAPACK_dgemqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* nb, const double* v, + lapack_int* ldv, const double* t, lapack_int* ldt, + double* c, lapack_int* ldc, double* work, + lapack_int *info ); +void LAPACK_cgemqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* nb, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* c, lapack_int* ldc, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zgemqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* nb, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* c, lapack_int* ldc, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_sgeqrt( lapack_int* m, lapack_int* n, lapack_int* nb, float* a, + lapack_int* lda, float* t, lapack_int* ldt, float* work, + lapack_int *info ); +void LAPACK_dgeqrt( lapack_int* m, lapack_int* n, lapack_int* nb, double* a, + lapack_int* lda, double* t, lapack_int* ldt, double* work, + lapack_int *info ); +void LAPACK_cgeqrt( lapack_int* m, lapack_int* n, lapack_int* nb, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_zgeqrt( lapack_int* m, lapack_int* n, lapack_int* nb, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_sgeqrt2( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* t, lapack_int* ldt, lapack_int *info ); +void LAPACK_dgeqrt2( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* t, lapack_int* ldt, lapack_int *info ); +void LAPACK_cgeqrt2( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_zgeqrt2( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_sgeqrt3( lapack_int* m, lapack_int* n, float* a, lapack_int* lda, + float* t, lapack_int* ldt, lapack_int *info ); +void LAPACK_dgeqrt3( lapack_int* m, lapack_int* n, double* a, lapack_int* lda, + double* t, lapack_int* ldt, lapack_int *info ); +void LAPACK_cgeqrt3( lapack_int* m, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_complex_float* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_zgeqrt3( lapack_int* m, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_complex_double* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_stpmqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, lapack_int* nb, + const float* v, lapack_int* ldv, const float* t, + lapack_int* ldt, float* a, lapack_int* lda, float* b, + lapack_int* ldb, float* work, lapack_int *info ); +void LAPACK_dtpmqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, lapack_int* nb, + const double* v, lapack_int* ldv, const double* t, + lapack_int* ldt, double* a, lapack_int* lda, double* b, + lapack_int* ldb, double* work, lapack_int *info ); +void LAPACK_ctpmqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, lapack_int* nb, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_ztpmqrt( char* side, char* trans, lapack_int* m, lapack_int* n, + lapack_int* k, lapack_int* l, lapack_int* nb, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_stpqrt( lapack_int* m, lapack_int* n, lapack_int* l, lapack_int* nb, + float* a, lapack_int* lda, float* b, lapack_int* ldb, + float* t, lapack_int* ldt, float* work, lapack_int *info ); +void LAPACK_dtpqrt( lapack_int* m, lapack_int* n, lapack_int* l, lapack_int* nb, + double* a, lapack_int* lda, double* b, lapack_int* ldb, + double* t, lapack_int* ldt, double* work, + lapack_int *info ); +void LAPACK_ctpqrt( lapack_int* m, lapack_int* n, lapack_int* l, lapack_int* nb, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* work, lapack_int *info ); +void LAPACK_ztpqrt( lapack_int* m, lapack_int* n, lapack_int* l, lapack_int* nb, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* work, lapack_int *info ); +void LAPACK_stpqrt2( lapack_int* m, lapack_int* n, lapack_int* l, + float* a, lapack_int* lda, + float* b, lapack_int* ldb, + float* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_dtpqrt2( lapack_int* m, lapack_int* n, lapack_int* l, + double* a, lapack_int* lda, + double* b, lapack_int* ldb, + double* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_ctpqrt2( lapack_int* m, lapack_int* n, lapack_int* l, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_ztpqrt2( lapack_int* m, lapack_int* n, lapack_int* l, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* t, lapack_int* ldt, + lapack_int *info ); +void LAPACK_stprfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, lapack_int* l, + const float* v, lapack_int* ldv, const float* t, + lapack_int* ldt, float* a, lapack_int* lda, float* b, + lapack_int* ldb, const float* work, + lapack_int* ldwork ); +void LAPACK_dtprfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, lapack_int* l, + const double* v, lapack_int* ldv, const double* t, + lapack_int* ldt, double* a, lapack_int* lda, double* b, + lapack_int* ldb, const double* work, + lapack_int* ldwork ); +void LAPACK_ctprfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, lapack_int* l, + const lapack_complex_float* v, lapack_int* ldv, + const lapack_complex_float* t, lapack_int* ldt, + lapack_complex_float* a, lapack_int* lda, + lapack_complex_float* b, lapack_int* ldb, + lapack_complex_float* work, lapack_int* ldwork ); +void LAPACK_ztprfb( char* side, char* trans, char* direct, char* storev, + lapack_int* m, lapack_int* n, lapack_int* k, lapack_int* l, + const lapack_complex_double* v, lapack_int* ldv, + const lapack_complex_double* t, lapack_int* ldt, + lapack_complex_double* a, lapack_int* lda, + lapack_complex_double* b, lapack_int* ldb, + lapack_complex_double* work, lapack_int* ldwork ); +// LAPACK 3.5.0 +void LAPACK_ssysv_rook( char* uplo, lapack_int* n, lapack_int* nrhs, float* a, + lapack_int* lda, lapack_int* ipiv, float* b, + lapack_int* ldb, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ssytrf_rook( char* uplo, lapack_int* n, float* a, lapack_int* lda, + lapack_int* ipiv, float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dsysv_rook( char* uplo, lapack_int* n, lapack_int* nrhs, double* a, + lapack_int* lda, lapack_int* ipiv, double* b, + lapack_int* ldb, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_dsytrf_rook( char* uplo, lapack_int* n, double* a, lapack_int* lda, + lapack_int* ipiv, double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_csysv_rook( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_float* a, lapack_int* lda, + lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_complex_float* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_csytrf_rook( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zsysv_rook( char* uplo, lapack_int* n, lapack_int* nrhs, + lapack_complex_double* a, lapack_int* lda, + lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_complex_double* work, + lapack_int* lwork, lapack_int *info ); +void LAPACK_zsytrf_rook( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_ssytrs_rook( char* uplo, lapack_int* n, lapack_int* nrhs, const float* a, + lapack_int* lda, const lapack_int* ipiv, float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_dsytrs_rook( char* uplo, lapack_int* n, lapack_int* nrhs, + const double* a, lapack_int* lda, const lapack_int* ipiv, + double* b, lapack_int* ldb, lapack_int *info ); +void LAPACK_csytrs_rook( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zsytrs_rook( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_chetrf_rook( char* uplo, lapack_int* n, lapack_complex_float* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_float* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_zhetrf_rook( char* uplo, lapack_int* n, lapack_complex_double* a, + lapack_int* lda, lapack_int* ipiv, + lapack_complex_double* work, lapack_int* lwork, + lapack_int *info ); +void LAPACK_chetrs_rook( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_float* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_float* b, + lapack_int* ldb, lapack_int *info ); +void LAPACK_zhetrs_rook( char* uplo, lapack_int* n, lapack_int* nrhs, + const lapack_complex_double* a, lapack_int* lda, + const lapack_int* ipiv, lapack_complex_double* b, + lapack_int* ldb, lapack_int *info ); + +void LAPACK_csyr( char* uplo, lapack_int* n, lapack_complex_float* alpha, + const lapack_complex_float* x, lapack_int* incx, + lapack_complex_float* a, lapack_int* lda ); +void LAPACK_zsyr( char* uplo, lapack_int* n, lapack_complex_double* alpha, + const lapack_complex_double* x, lapack_int* incx, + lapack_complex_double* a, lapack_int* lda ); +void LAPACK_ilaver( const lapack_int* vers_major, const lapack_int* vers_minor, + const lapack_int* vers_patch ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _LAPACKE_H_ */ diff --git a/lapack/cgo/lapacke/lapacke_config.h b/lapack/cgo/lapacke/lapacke_config.h new file mode 100644 index 00000000..1e2509bf --- /dev/null +++ b/lapack/cgo/lapacke/lapacke_config.h @@ -0,0 +1,119 @@ +/***************************************************************************** + Copyright (c) 2010, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +****************************************************************************** +* Contents: Native C interface to LAPACK +* Author: Intel Corporation +* Generated May, 2011 +*****************************************************************************/ + +#ifndef _LAPACKE_CONFIG_H_ +#define _LAPACKE_CONFIG_H_ + +#ifdef __cplusplus +#if defined(LAPACK_COMPLEX_CPP) +#include +#endif +extern "C" { +#endif /* __cplusplus */ + +#include + +#ifndef lapack_int +#if defined(LAPACK_ILP64) +#define lapack_int long +#else +#define lapack_int int +#endif +#endif + +#ifndef lapack_logical +#define lapack_logical lapack_int +#endif + +#ifndef LAPACK_COMPLEX_CUSTOM + +#if defined(LAPACK_COMPLEX_STRUCTURE) + +typedef struct { float real, imag; } _lapack_complex_float; +typedef struct { double real, imag; } _lapack_complex_double; +#define lapack_complex_float _lapack_complex_float +#define lapack_complex_double _lapack_complex_double +#define lapack_complex_float_real(z) ((z).real) +#define lapack_complex_float_imag(z) ((z).imag) +#define lapack_complex_double_real(z) ((z).real) +#define lapack_complex_double_imag(z) ((z).imag) + +#elif defined(LAPACK_COMPLEX_C99) + +#include +#define lapack_complex_float float _Complex +#define lapack_complex_double double _Complex +#define lapack_complex_float_real(z) (creal(z)) +#define lapack_complex_float_imag(z) (cimag(z)) +#define lapack_complex_double_real(z) (creal(z)) +#define lapack_complex_double_imag(z) (cimag(z)) + +#elif defined(LAPACK_COMPLEX_CPP) + +#define lapack_complex_float std::complex +#define lapack_complex_double std::complex +#define lapack_complex_float_real(z) ((z).real()) +#define lapack_complex_float_imag(z) ((z).imag()) +#define lapack_complex_double_real(z) ((z).real()) +#define lapack_complex_double_imag(z) ((z).imag()) + +#else + +#include +#define lapack_complex_float float _Complex +#define lapack_complex_double double _Complex +#define lapack_complex_float_real(z) (creal(z)) +#define lapack_complex_float_imag(z) (cimag(z)) +#define lapack_complex_double_real(z) (creal(z)) +#define lapack_complex_double_imag(z) (cimag(z)) + +#endif + +lapack_complex_float lapack_make_complex_float( float re, float im ); +lapack_complex_double lapack_make_complex_double( double re, double im ); + +#endif + +#ifndef LAPACK_malloc +#define LAPACK_malloc( size ) malloc( size ) +#endif + +#ifndef LAPACK_free +#define LAPACK_free( p ) free( p ) +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _LAPACKE_CONFIG_H_ */ diff --git a/lapack/cgo/lapacke/lapacke_mangling.h b/lapack/cgo/lapacke/lapacke_mangling.h new file mode 100644 index 00000000..6211fd14 --- /dev/null +++ b/lapack/cgo/lapacke/lapacke_mangling.h @@ -0,0 +1,17 @@ +#ifndef LAPACK_HEADER_INCLUDED +#define LAPACK_HEADER_INCLUDED + +#ifndef LAPACK_GLOBAL +#if defined(LAPACK_GLOBAL_PATTERN_LC) || defined(ADD_) +#define LAPACK_GLOBAL(lcname,UCNAME) lcname##_ +#elif defined(LAPACK_GLOBAL_PATTERN_UC) || defined(UPPER) +#define LAPACK_GLOBAL(lcname,UCNAME) UCNAME +#elif defined(LAPACK_GLOBAL_PATTERN_MC) || defined(NOCHANGE) +#define LAPACK_GLOBAL(lcname,UCNAME) lcname +#else +#define LAPACK_GLOBAL(lcname,UCNAME) lcname##_ +#endif +#endif + +#endif + diff --git a/lapack/cgo/lapacke/lapacke_utils.h b/lapack/cgo/lapacke/lapacke_utils.h new file mode 100644 index 00000000..a9236d23 --- /dev/null +++ b/lapack/cgo/lapacke/lapacke_utils.h @@ -0,0 +1,579 @@ +/***************************************************************************** + Copyright (c) 2014, Intel Corp. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. +****************************************************************************** +* Contents: Native C interface to LAPACK utility functions +* Author: Intel Corporation +* Created in January, 2010 +*****************************************************************************/ + +#ifndef _LAPACKE_UTILS_H_ +#define _LAPACKE_UTILS_H_ + +#include "lapacke.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef ABS +#define ABS(x) (((x) < 0) ? -(x) : (x)) +#endif +#ifndef MAX +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#endif +#ifndef MIN +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#endif +#ifndef MAX3 +#define MAX3(x,y,z) (((x) > MAX(y,z)) ? (x) : MAX(y,z)) +#endif +#ifndef MIN3 +#define MIN3(x,y,z) (((x) < MIN(y,z)) ? (x) : MIN(y,z)) +#endif + +#define IS_S_NONZERO(x) ( (x) < 0 || (x) > 0 ) +#define IS_D_NONZERO(x) ( (x) < 0 || (x) > 0 ) +#define IS_C_NONZERO(x) ( IS_S_NONZERO(*((float*)&x)) || \ + IS_S_NONZERO(*(((float*)&x)+1)) ) +#define IS_Z_NONZERO(x) ( IS_D_NONZERO(*((double*)&x)) || \ + IS_D_NONZERO(*(((double*)&x)+1)) ) + +/* Error handler */ +void LAPACKE_xerbla( const char *name, lapack_int info ); + +/* Compare two chars (case-insensitive) */ +lapack_logical LAPACKE_lsame( char ca, char cb ); + +/* Functions to convert column-major to row-major 2d arrays and vice versa. */ +void LAPACKE_cgb_trans( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_float *in, lapack_int ldin, + lapack_complex_float *out, lapack_int ldout ); +void LAPACKE_cge_trans( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_float* in, lapack_int ldin, + lapack_complex_float* out, lapack_int ldout ); +void LAPACKE_cgg_trans( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_float* in, lapack_int ldin, + lapack_complex_float* out, lapack_int ldout ); +void LAPACKE_chb_trans( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, + const lapack_complex_float *in, lapack_int ldin, + lapack_complex_float *out, lapack_int ldout ); +void LAPACKE_che_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float *in, lapack_int ldin, + lapack_complex_float *out, lapack_int ldout ); +void LAPACKE_chp_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float *in, + lapack_complex_float *out ); +void LAPACKE_chs_trans( int matrix_layout, lapack_int n, + const lapack_complex_float *in, lapack_int ldin, + lapack_complex_float *out, lapack_int ldout ); +void LAPACKE_cpb_trans( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, + const lapack_complex_float *in, lapack_int ldin, + lapack_complex_float *out, lapack_int ldout ); +void LAPACKE_cpf_trans( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_float *in, + lapack_complex_float *out ); +void LAPACKE_cpo_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float *in, lapack_int ldin, + lapack_complex_float *out, lapack_int ldout ); +void LAPACKE_cpp_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float *in, + lapack_complex_float *out ); +void LAPACKE_csp_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float *in, + lapack_complex_float *out ); +void LAPACKE_csy_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_float *in, lapack_int ldin, + lapack_complex_float *out, lapack_int ldout ); +void LAPACKE_ctb_trans( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_int kd, + const lapack_complex_float *in, lapack_int ldin, + lapack_complex_float *out, lapack_int ldout ); +void LAPACKE_ctf_trans( int matrix_layout, char transr, char uplo, char diag, + lapack_int n, const lapack_complex_float *in, + lapack_complex_float *out ); +void LAPACKE_ctp_trans( int matrix_layout, char uplo, char diag, + lapack_int n, const lapack_complex_float *in, + lapack_complex_float *out ); +void LAPACKE_ctr_trans( int matrix_layout, char uplo, char diag, lapack_int n, + const lapack_complex_float *in, lapack_int ldin, + lapack_complex_float *out, lapack_int ldout ); + +void LAPACKE_dgb_trans( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const double *in, lapack_int ldin, + double *out, lapack_int ldout ); +void LAPACKE_dge_trans( int matrix_layout, lapack_int m, lapack_int n, + const double* in, lapack_int ldin, + double* out, lapack_int ldout ); +void LAPACKE_dgg_trans( int matrix_layout, lapack_int m, lapack_int n, + const double* in, lapack_int ldin, + double* out, lapack_int ldout ); +void LAPACKE_dhs_trans( int matrix_layout, lapack_int n, + const double *in, lapack_int ldin, + double *out, lapack_int ldout ); +void LAPACKE_dpb_trans( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, + const double *in, lapack_int ldin, + double *out, lapack_int ldout ); +void LAPACKE_dpf_trans( int matrix_layout, char transr, char uplo, + lapack_int n, const double *in, + double *out ); +void LAPACKE_dpo_trans( int matrix_layout, char uplo, lapack_int n, + const double *in, lapack_int ldin, + double *out, lapack_int ldout ); +void LAPACKE_dpp_trans( int matrix_layout, char uplo, lapack_int n, + const double *in, + double *out ); +void LAPACKE_dsb_trans( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, + const double *in, lapack_int ldin, + double *out, lapack_int ldout ); +void LAPACKE_dsp_trans( int matrix_layout, char uplo, lapack_int n, + const double *in, + double *out ); +void LAPACKE_dsy_trans( int matrix_layout, char uplo, lapack_int n, + const double *in, lapack_int ldin, + double *out, lapack_int ldout ); +void LAPACKE_dtb_trans( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_int kd, + const double *in, lapack_int ldin, + double *out, lapack_int ldout ); +void LAPACKE_dtf_trans( int matrix_layout, char transr, char uplo, char diag, + lapack_int n, const double *in, + double *out ); +void LAPACKE_dtp_trans( int matrix_layout, char uplo, char diag, + lapack_int n, const double *in, + double *out ); +void LAPACKE_dtr_trans( int matrix_layout, char uplo, char diag, lapack_int n, + const double *in, lapack_int ldin, + double *out, lapack_int ldout ); + +void LAPACKE_sgb_trans( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const float *in, lapack_int ldin, + float *out, lapack_int ldout ); +void LAPACKE_sge_trans( int matrix_layout, lapack_int m, lapack_int n, + const float* in, lapack_int ldin, + float* out, lapack_int ldout ); +void LAPACKE_sgg_trans( int matrix_layout, lapack_int m, lapack_int n, + const float* in, lapack_int ldin, + float* out, lapack_int ldout ); +void LAPACKE_shs_trans( int matrix_layout, lapack_int n, + const float *in, lapack_int ldin, + float *out, lapack_int ldout ); +void LAPACKE_spb_trans( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, + const float *in, lapack_int ldin, + float *out, lapack_int ldout ); +void LAPACKE_spf_trans( int matrix_layout, char transr, char uplo, + lapack_int n, const float *in, + float *out ); +void LAPACKE_spo_trans( int matrix_layout, char uplo, lapack_int n, + const float *in, lapack_int ldin, + float *out, lapack_int ldout ); +void LAPACKE_spp_trans( int matrix_layout, char uplo, lapack_int n, + const float *in, + float *out ); +void LAPACKE_ssb_trans( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, + const float *in, lapack_int ldin, + float *out, lapack_int ldout ); +void LAPACKE_ssp_trans( int matrix_layout, char uplo, lapack_int n, + const float *in, + float *out ); +void LAPACKE_ssy_trans( int matrix_layout, char uplo, lapack_int n, + const float *in, lapack_int ldin, + float *out, lapack_int ldout ); +void LAPACKE_stb_trans( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_int kd, + const float *in, lapack_int ldin, + float *out, lapack_int ldout ); +void LAPACKE_stf_trans( int matrix_layout, char transr, char uplo, char diag, + lapack_int n, const float *in, + float *out ); +void LAPACKE_stp_trans( int matrix_layout, char uplo, char diag, + lapack_int n, const float *in, + float *out ); +void LAPACKE_str_trans( int matrix_layout, char uplo, char diag, lapack_int n, + const float *in, lapack_int ldin, + float *out, lapack_int ldout ); + +void LAPACKE_zgb_trans( int matrix_layout, lapack_int m, lapack_int n, + lapack_int kl, lapack_int ku, + const lapack_complex_double *in, lapack_int ldin, + lapack_complex_double *out, lapack_int ldout ); +void LAPACKE_zge_trans( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_double* in, lapack_int ldin, + lapack_complex_double* out, lapack_int ldout ); +void LAPACKE_zgg_trans( int matrix_layout, lapack_int m, lapack_int n, + const lapack_complex_double* in, lapack_int ldin, + lapack_complex_double* out, lapack_int ldout ); +void LAPACKE_zhb_trans( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, + const lapack_complex_double *in, lapack_int ldin, + lapack_complex_double *out, lapack_int ldout ); +void LAPACKE_zhe_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double *in, lapack_int ldin, + lapack_complex_double *out, lapack_int ldout ); +void LAPACKE_zhp_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double *in, + lapack_complex_double *out ); +void LAPACKE_zhs_trans( int matrix_layout, lapack_int n, + const lapack_complex_double *in, lapack_int ldin, + lapack_complex_double *out, lapack_int ldout ); +void LAPACKE_zpb_trans( int matrix_layout, char uplo, lapack_int n, + lapack_int kd, + const lapack_complex_double *in, lapack_int ldin, + lapack_complex_double *out, lapack_int ldout ); +void LAPACKE_zpf_trans( int matrix_layout, char transr, char uplo, + lapack_int n, const lapack_complex_double *in, + lapack_complex_double *out ); +void LAPACKE_zpo_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double *in, lapack_int ldin, + lapack_complex_double *out, lapack_int ldout ); +void LAPACKE_zpp_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double *in, + lapack_complex_double *out ); +void LAPACKE_zsp_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double *in, + lapack_complex_double *out ); +void LAPACKE_zsy_trans( int matrix_layout, char uplo, lapack_int n, + const lapack_complex_double *in, lapack_int ldin, + lapack_complex_double *out, lapack_int ldout ); +void LAPACKE_ztb_trans( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_int kd, + const lapack_complex_double *in, lapack_int ldin, + lapack_complex_double *out, lapack_int ldout ); +void LAPACKE_ztf_trans( int matrix_layout, char transr, char uplo, char diag, + lapack_int n, const lapack_complex_double *in, + lapack_complex_double *out ); +void LAPACKE_ztp_trans( int matrix_layout, char uplo, char diag, + lapack_int n, const lapack_complex_double *in, + lapack_complex_double *out ); +void LAPACKE_ztr_trans( int matrix_layout, char uplo, char diag, lapack_int n, + const lapack_complex_double *in, lapack_int ldin, + lapack_complex_double *out, lapack_int ldout ); + +/* NaN checkers */ +#define LAPACK_SISNAN( x ) ( x != x ) +#define LAPACK_DISNAN( x ) ( x != x ) +#define LAPACK_CISNAN( x ) ( LAPACK_SISNAN(*((float*) &x)) || \ + LAPACK_SISNAN(*(((float*) &x)+1)) ) +#define LAPACK_ZISNAN( x ) ( LAPACK_DISNAN(*((double*)&x)) || \ + LAPACK_DISNAN(*(((double*)&x)+1)) ) + +/* NaN checkers for vectors */ +lapack_logical LAPACKE_c_nancheck( lapack_int n, + const lapack_complex_float *x, + lapack_int incx ); +lapack_logical LAPACKE_d_nancheck( lapack_int n, + const double *x, + lapack_int incx ); +lapack_logical LAPACKE_s_nancheck( lapack_int n, + const float *x, + lapack_int incx ); +lapack_logical LAPACKE_z_nancheck( lapack_int n, + const lapack_complex_double *x, + lapack_int incx ); +/* NaN checkers for matrices */ +lapack_logical LAPACKE_cgb_nancheck( int matrix_layout, lapack_int m, + lapack_int n, lapack_int kl, + lapack_int ku, + const lapack_complex_float *ab, + lapack_int ldab ); +lapack_logical LAPACKE_cge_nancheck( int matrix_layout, lapack_int m, + lapack_int n, + const lapack_complex_float *a, + lapack_int lda ); +lapack_logical LAPACKE_cgg_nancheck( int matrix_layout, lapack_int m, + lapack_int n, + const lapack_complex_float *a, + lapack_int lda ); +lapack_logical LAPACKE_cgt_nancheck( lapack_int n, + const lapack_complex_float *dl, + const lapack_complex_float *d, + const lapack_complex_float *du ); +lapack_logical LAPACKE_chb_nancheck( int matrix_layout, char uplo, + lapack_int n, lapack_int kd, + const lapack_complex_float* ab, + lapack_int ldab ); +lapack_logical LAPACKE_che_nancheck( int matrix_layout, char uplo, + lapack_int n, + const lapack_complex_float *a, + lapack_int lda ); +lapack_logical LAPACKE_chp_nancheck( lapack_int n, + const lapack_complex_float *ap ); +lapack_logical LAPACKE_chs_nancheck( int matrix_layout, lapack_int n, + const lapack_complex_float *a, + lapack_int lda ); +lapack_logical LAPACKE_cpb_nancheck( int matrix_layout, char uplo, + lapack_int n, lapack_int kd, + const lapack_complex_float* ab, + lapack_int ldab ); +lapack_logical LAPACKE_cpf_nancheck( lapack_int n, + const lapack_complex_float *a ); +lapack_logical LAPACKE_cpo_nancheck( int matrix_layout, char uplo, + lapack_int n, + const lapack_complex_float *a, + lapack_int lda ); +lapack_logical LAPACKE_cpp_nancheck( lapack_int n, + const lapack_complex_float *ap ); +lapack_logical LAPACKE_cpt_nancheck( lapack_int n, + const float *d, + const lapack_complex_float *e ); +lapack_logical LAPACKE_csp_nancheck( lapack_int n, + const lapack_complex_float *ap ); +lapack_logical LAPACKE_cst_nancheck( lapack_int n, + const lapack_complex_float *d, + const lapack_complex_float *e ); +lapack_logical LAPACKE_csy_nancheck( int matrix_layout, char uplo, + lapack_int n, + const lapack_complex_float *a, + lapack_int lda ); +lapack_logical LAPACKE_ctb_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_int kd, + const lapack_complex_float* ab, + lapack_int ldab ); +lapack_logical LAPACKE_ctf_nancheck( int matrix_layout, char transr, + char uplo, char diag, + lapack_int n, + const lapack_complex_float *a ); +lapack_logical LAPACKE_ctp_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, + const lapack_complex_float *ap ); +lapack_logical LAPACKE_ctr_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, + const lapack_complex_float *a, + lapack_int lda ); + +lapack_logical LAPACKE_dgb_nancheck( int matrix_layout, lapack_int m, + lapack_int n, lapack_int kl, + lapack_int ku, + const double *ab, + lapack_int ldab ); +lapack_logical LAPACKE_dge_nancheck( int matrix_layout, lapack_int m, + lapack_int n, + const double *a, + lapack_int lda ); +lapack_logical LAPACKE_dgg_nancheck( int matrix_layout, lapack_int m, + lapack_int n, + const double *a, + lapack_int lda ); +lapack_logical LAPACKE_dgt_nancheck( lapack_int n, + const double *dl, + const double *d, + const double *du ); +lapack_logical LAPACKE_dhs_nancheck( int matrix_layout, lapack_int n, + const double *a, + lapack_int lda ); +lapack_logical LAPACKE_dpb_nancheck( int matrix_layout, char uplo, + lapack_int n, lapack_int kd, + const double* ab, + lapack_int ldab ); +lapack_logical LAPACKE_dpf_nancheck( lapack_int n, + const double *a ); +lapack_logical LAPACKE_dpo_nancheck( int matrix_layout, char uplo, + lapack_int n, + const double *a, + lapack_int lda ); +lapack_logical LAPACKE_dpp_nancheck( lapack_int n, + const double *ap ); +lapack_logical LAPACKE_dpt_nancheck( lapack_int n, + const double *d, + const double *e ); +lapack_logical LAPACKE_dsb_nancheck( int matrix_layout, char uplo, + lapack_int n, lapack_int kd, + const double* ab, + lapack_int ldab ); +lapack_logical LAPACKE_dsp_nancheck( lapack_int n, + const double *ap ); +lapack_logical LAPACKE_dst_nancheck( lapack_int n, + const double *d, + const double *e ); +lapack_logical LAPACKE_dsy_nancheck( int matrix_layout, char uplo, + lapack_int n, + const double *a, + lapack_int lda ); +lapack_logical LAPACKE_dtb_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_int kd, + const double* ab, + lapack_int ldab ); +lapack_logical LAPACKE_dtf_nancheck( int matrix_layout, char transr, + char uplo, char diag, + lapack_int n, + const double *a ); +lapack_logical LAPACKE_dtp_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, + const double *ap ); +lapack_logical LAPACKE_dtr_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, + const double *a, + lapack_int lda ); + +lapack_logical LAPACKE_sgb_nancheck( int matrix_layout, lapack_int m, + lapack_int n, lapack_int kl, + lapack_int ku, + const float *ab, + lapack_int ldab ); +lapack_logical LAPACKE_sge_nancheck( int matrix_layout, lapack_int m, + lapack_int n, + const float *a, + lapack_int lda ); +lapack_logical LAPACKE_sgg_nancheck( int matrix_layout, lapack_int m, + lapack_int n, + const float *a, + lapack_int lda ); +lapack_logical LAPACKE_sgt_nancheck( lapack_int n, + const float *dl, + const float *d, + const float *du ); +lapack_logical LAPACKE_shs_nancheck( int matrix_layout, lapack_int n, + const float *a, + lapack_int lda ); +lapack_logical LAPACKE_spb_nancheck( int matrix_layout, char uplo, + lapack_int n, lapack_int kd, + const float* ab, + lapack_int ldab ); +lapack_logical LAPACKE_spf_nancheck( lapack_int n, + const float *a ); +lapack_logical LAPACKE_spo_nancheck( int matrix_layout, char uplo, + lapack_int n, + const float *a, + lapack_int lda ); +lapack_logical LAPACKE_spp_nancheck( lapack_int n, + const float *ap ); +lapack_logical LAPACKE_spt_nancheck( lapack_int n, + const float *d, + const float *e ); +lapack_logical LAPACKE_ssb_nancheck( int matrix_layout, char uplo, + lapack_int n, lapack_int kd, + const float* ab, + lapack_int ldab ); +lapack_logical LAPACKE_ssp_nancheck( lapack_int n, + const float *ap ); +lapack_logical LAPACKE_sst_nancheck( lapack_int n, + const float *d, + const float *e ); +lapack_logical LAPACKE_ssy_nancheck( int matrix_layout, char uplo, + lapack_int n, + const float *a, + lapack_int lda ); +lapack_logical LAPACKE_stb_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_int kd, + const float* ab, + lapack_int ldab ); +lapack_logical LAPACKE_stf_nancheck( int matrix_layout, char transr, + char uplo, char diag, + lapack_int n, + const float *a ); +lapack_logical LAPACKE_stp_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, + const float *ap ); +lapack_logical LAPACKE_str_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, + const float *a, + lapack_int lda ); + +lapack_logical LAPACKE_zgb_nancheck( int matrix_layout, lapack_int m, + lapack_int n, lapack_int kl, + lapack_int ku, + const lapack_complex_double *ab, + lapack_int ldab ); +lapack_logical LAPACKE_zge_nancheck( int matrix_layout, lapack_int m, + lapack_int n, + const lapack_complex_double *a, + lapack_int lda ); +lapack_logical LAPACKE_zgg_nancheck( int matrix_layout, lapack_int m, + lapack_int n, + const lapack_complex_double *a, + lapack_int lda ); +lapack_logical LAPACKE_zgt_nancheck( lapack_int n, + const lapack_complex_double *dl, + const lapack_complex_double *d, + const lapack_complex_double *du ); +lapack_logical LAPACKE_zhb_nancheck( int matrix_layout, char uplo, + lapack_int n, lapack_int kd, + const lapack_complex_double* ab, + lapack_int ldab ); +lapack_logical LAPACKE_zhe_nancheck( int matrix_layout, char uplo, + lapack_int n, + const lapack_complex_double *a, + lapack_int lda ); +lapack_logical LAPACKE_zhp_nancheck( lapack_int n, + const lapack_complex_double *ap ); +lapack_logical LAPACKE_zhs_nancheck( int matrix_layout, lapack_int n, + const lapack_complex_double *a, + lapack_int lda ); +lapack_logical LAPACKE_zpb_nancheck( int matrix_layout, char uplo, + lapack_int n, lapack_int kd, + const lapack_complex_double* ab, + lapack_int ldab ); +lapack_logical LAPACKE_zpf_nancheck( lapack_int n, + const lapack_complex_double *a ); +lapack_logical LAPACKE_zpo_nancheck( int matrix_layout, char uplo, + lapack_int n, + const lapack_complex_double *a, + lapack_int lda ); +lapack_logical LAPACKE_zpp_nancheck( lapack_int n, + const lapack_complex_double *ap ); +lapack_logical LAPACKE_zpt_nancheck( lapack_int n, + const double *d, + const lapack_complex_double *e ); +lapack_logical LAPACKE_zsp_nancheck( lapack_int n, + const lapack_complex_double *ap ); +lapack_logical LAPACKE_zst_nancheck( lapack_int n, + const lapack_complex_double *d, + const lapack_complex_double *e ); +lapack_logical LAPACKE_zsy_nancheck( int matrix_layout, char uplo, + lapack_int n, + const lapack_complex_double *a, + lapack_int lda ); +lapack_logical LAPACKE_ztb_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, lapack_int kd, + const lapack_complex_double* ab, + lapack_int ldab ); +lapack_logical LAPACKE_ztf_nancheck( int matrix_layout, char transr, + char uplo, char diag, + lapack_int n, + const lapack_complex_double *a ); +lapack_logical LAPACKE_ztp_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, + const lapack_complex_double *ap ); +lapack_logical LAPACKE_ztr_nancheck( int matrix_layout, char uplo, char diag, + lapack_int n, + const lapack_complex_double *a, + lapack_int lda ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _LAPACKE_UTILS_H_ */ diff --git a/lapack/internal/testdata/dlahr2test/main.go b/lapack/internal/testdata/dlahr2test/main.go new file mode 100644 index 00000000..2b146f83 --- /dev/null +++ b/lapack/internal/testdata/dlahr2test/main.go @@ -0,0 +1,101 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// dlahr2test generates test data for Dlahr2. Test cases are stored in +// gzip-compressed JSON file testlapack/testdata/dlahr2data.json.gz which is +// read during testing by testlapack/dlahr2.go. +// +// This program uses cgo to call Fortran version of DLAHR2. Therefore, matrices +// passed to the Fortran routine are in column-major format but are written into +// the output file in row-major format. +package main + +import ( + "compress/gzip" + "encoding/json" + "log" + "math/rand" + "os" + "path/filepath" + + "github.com/gonum/lapack/internal/testdata/netlib" +) + +type Dlahr2Test struct { + N, K, NB int + A []float64 + + AWant []float64 + TWant []float64 + YWant []float64 + TauWant []float64 +} + +func main() { + file, err := os.Create(filepath.FromSlash("../../../testlapack/testdata/dlahr2data.json.gz")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + w := gzip.NewWriter(file) + + rnd := rand.New(rand.NewSource(1)) + + var tests []Dlahr2Test + for _, n := range []int{4, 5, 6, 7, 11} { + for k := 0; k <= n/2; k++ { + for nb := 1; nb <= k; nb++ { + ain := genrand(n, n-k+1, rnd) + a := make([]float64, len(ain)) + copy(a, ain) + + t := genrand(nb, nb, rnd) + y := genrand(n, nb, rnd) + tau := genrand(nb, 1, rnd) + + netlib.Dlahr2(n, k, nb, a, n, tau, t, nb, y, n) + + tests = append(tests, Dlahr2Test{ + N: n, + K: k, + NB: nb, + A: rowMajor(n, n-k+1, ain), + AWant: rowMajor(n, n-k+1, a), + TWant: rowMajor(nb, nb, t), + YWant: rowMajor(n, nb, y), + TauWant: tau, + }) + } + } + } + json.NewEncoder(w).Encode(tests) + + err = w.Close() + if err != nil { + log.Fatal(err) + } +} + +// genrand returns a general r×c matrix with random entries. +func genrand(r, c int, rnd *rand.Rand) []float64 { + m := make([]float64, r*c) + for i := range m { + m[i] = rnd.NormFloat64() + } + return m +} + +// rowMajor returns the given r×c column-major matrix a in row-major format. +func rowMajor(r, c int, a []float64) []float64 { + if len(a) != r*c { + panic("testdata: slice length mismatch") + } + m := make([]float64, len(a)) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + m[i*c+j] = a[i+j*r] + } + } + return m +} diff --git a/lapack/internal/testdata/dlaqr5test/main.go b/lapack/internal/testdata/dlaqr5test/main.go new file mode 100644 index 00000000..1ef02faf --- /dev/null +++ b/lapack/internal/testdata/dlaqr5test/main.go @@ -0,0 +1,185 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This program generates test data for Dlaqr5. Test cases are stored in +// gzip-compressed JSON file testlapack/testdata/dlaqr5data.json.gz which is +// read during testing by testlapack/dlaqr5.go. +// +// This program uses cgo to call Fortran version of DLAQR5. Therefore, matrices +// passed to the Fortran routine are in column-major format but are written into +// the output file in row-major format. +package main + +import ( + "compress/gzip" + "encoding/json" + "log" + "math/rand" + "os" + "path/filepath" + + "github.com/gonum/lapack/internal/testdata/netlib" +) + +type Dlaqr5Test struct { + WantT bool + N int + NShifts int + KTop, KBot int + ShiftR, ShiftI []float64 + H []float64 + + HWant []float64 + ZWant []float64 +} + +func main() { + file, err := os.Create(filepath.FromSlash("../../../testlapack/testdata/dlaqr5data.json.gz")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + w := gzip.NewWriter(file) + + rnd := rand.New(rand.NewSource(1)) + + var tests []Dlaqr5Test + for _, wantt := range []bool{true, false} { + for _, n := range []int{2, 3, 4, 5, 6, 7, 11} { + for k := 0; k <= min(5, n); k++ { + npairs := k + if npairs == 0 { + npairs = 2 * n + } + for ktop := 0; ktop < n-1; ktop++ { + for kbot := ktop + 1; kbot < n; kbot++ { + sr, si := shiftpairs(npairs, rnd) + nshfts := len(sr) + + v := genrand(nshfts/2, 3, rnd) + u := genrand(3*nshfts-3, 3*nshfts-3, rnd) + wh := genrand(3*nshfts-3, n, rnd) + nh := n + wv := genrand(n, 3*nshfts-3, rnd) + nv := n + + h := hessrand(n, rnd) + if ktop > 0 { + h[ktop+(ktop-1)*n] = 0 + } + if kbot < n-1 { + h[kbot+1+kbot*n] = 0 + } + hin := make([]float64, len(h)) + copy(hin, h) + z := eye(n) + + netlib.Dlaqr5(wantt, true, 2, + n, ktop+1, kbot+1, + nshfts, sr, si, + h, n, + 1, n, z, n, + v, 3, + u, 3*nshfts-3, + nh, wh, nh, + nv, wv, 3*nshfts-3) + + tests = append(tests, Dlaqr5Test{ + WantT: wantt, + N: n, + NShifts: nshfts, + KTop: ktop, + KBot: kbot, + ShiftR: sr, + ShiftI: si, + H: rowMajor(n, n, hin), + HWant: rowMajor(n, n, h), + ZWant: rowMajor(n, n, z), + }) + } + } + } + } + } + json.NewEncoder(w).Encode(tests) + + err = w.Close() + if err != nil { + log.Fatal(err) + } +} + +// genrand returns a general r×c matrix with random entries. +func genrand(r, c int, rnd *rand.Rand) []float64 { + m := make([]float64, r*c) + for i := range m { + m[i] = rnd.NormFloat64() + } + return m +} + +// eye returns an identity matrix of order n. +func eye(n int) []float64 { + m := make([]float64, n*n) + for i := 0; i < n*n; i += n + 1 { + m[i] = 1 + } + return m +} + +// hessrand returns a Hessenberg matrix of order n with random non-zero entries +// in column-major format. +func hessrand(n int, rnd *rand.Rand) []float64 { + h := make([]float64, n*n) + for j := 0; j < n; j++ { + for i := 0; i <= min(j+1, n-1); i++ { + h[i+j*n] = rnd.NormFloat64() + } + } + return h +} + +// shiftpairs generates k real and complex conjugate shift pairs. That is, the +// length of sr and si is 2*k. +func shiftpairs(k int, rnd *rand.Rand) (sr, si []float64) { + sr = make([]float64, 2*k) + si = make([]float64, 2*k) + for i := 0; i < len(sr); { + if rnd.Float64() < 0.5 || i == len(sr)-1 { + sr[i] = rnd.NormFloat64() + i++ + continue + } + // Generate a complex conjugate pair. + r := rnd.NormFloat64() + c := rnd.NormFloat64() + sr[i] = r + si[i] = c + sr[i+1] = r + si[i+1] = -c + i += 2 + } + return sr, si +} + +// rowMajor returns the given r×c column-major matrix a in row-major format. +func rowMajor(r, c int, a []float64) []float64 { + if len(a) != r*c { + panic("testdata: slice length mismatch") + } + m := make([]float64, len(a)) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + m[i*c+j] = a[i+j*r] + } + } + return m +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/lapack/internal/testdata/dlasqtest/Makefile b/lapack/internal/testdata/dlasqtest/Makefile new file mode 100644 index 00000000..f9f94446 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/Makefile @@ -0,0 +1,27 @@ +FC = gfortran +FFLAGS = -O2 + +targets = testdlasq1 testdlasq2 testdlasq3 testdlasq4 +objects = dlamch.o lsame.o xerbla.o ieeeck.o iparmq.o ilaenv.o dlasrt.o \ + dlaisnan.o disnan.o dlasq6.o dlasq5.o dlasq4.o dlasq3.o dlasq2.o + +default : $(targets) +.PHONY : default + +testdlasq1 : testdlasq1.o $(objects) dcopy.o dlas2.o dlascl.o dlasq1.o + +testdlasq2 : testdlasq2.o $(objects) + +testdlasq3 : testdlasq3.o $(objects) + +testdlasq4 : testdlasq4.o $(objects) + +% : %.o + $(FC) $(FFLAGS) $^ -o $@ + +%.o : %.f90 + $(FC) $(FFLAGS) -c -o $@ $< + +clean : + rm -f *.o $(targets) *.txt +.PHONY : clean \ No newline at end of file diff --git a/lapack/internal/testdata/dlasqtest/Readme.md b/lapack/internal/testdata/dlasqtest/Readme.md new file mode 100644 index 00000000..65c47448 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/Readme.md @@ -0,0 +1,23 @@ +This set of codes generates tests for the dlasq* routines. + +The high level routines are testdlasq*.f90. The testdlasq*.f90 routines are intended in combination with the routines in gonum/lapack/testlapack. +During execution, these high-level routines record the inputs and outputs +to the executed subroutines. For example, testdlasq3, when executed, +generates files gen4tests.txt and gen5tests.txt that record the inputs +and outputs to the evaluation of dlasq4 and dlasq5 respectively. The output +format in gen*tests.txt is the struct literal that matches the respective test +in gonum/lapack/testlapack/dlasq*.go. Thus, these generated tests can be copied +into the testing routine to test the native implementation. + +The testing routines in testlapack have code for generating inputs for these +fortran routines. Typically, one would isolate the particular failing test, +and modify the testlapack routine to print it to the terminal, for example +in testlapack/dlasq3.go one might add + + printDlasq3FortranInput(test) + os.Exit(1) + +This prints variable initialization for dlasq3 routine to the terminal, which +can be copied and pasted into testdlasq3.f90. Please note that this process +is not completely automated. Some of the other initialization may need to +change, particularly the size allocation of the data array(s). \ No newline at end of file diff --git a/lapack/internal/testdata/dlasqtest/dcopy.f b/lapack/internal/testdata/dlasqtest/dcopy.f new file mode 100644 index 00000000..d9d5ac7a --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dcopy.f @@ -0,0 +1,115 @@ +*> \brief \b DCOPY +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) +* +* .. Scalar Arguments .. +* INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION DX(*),DY(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DCOPY copies a vector, x, to a vector, y. +*> uses unrolled loops for increments equal to one. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> jack dongarra, linpack, 3/11/78. +*> modified 12/3/93, array(1) declarations changed to array(*) +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION DX(*),DY(*) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I,IX,IY,M,MP1 +* .. +* .. Intrinsic Functions .. + INTRINSIC MOD +* .. + IF (N.LE.0) RETURN + IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN +* +* code for both increments equal to 1 +* +* +* clean-up loop +* + M = MOD(N,7) + IF (M.NE.0) THEN + DO I = 1,M + DY(I) = DX(I) + END DO + IF (N.LT.7) RETURN + END IF + MP1 = M + 1 + DO I = MP1,N,7 + DY(I) = DX(I) + DY(I+1) = DX(I+1) + DY(I+2) = DX(I+2) + DY(I+3) = DX(I+3) + DY(I+4) = DX(I+4) + DY(I+5) = DX(I+5) + DY(I+6) = DX(I+6) + END DO + ELSE +* +* code for unequal increments or equal increments +* not equal to 1 +* + IX = 1 + IY = 1 + IF (INCX.LT.0) IX = (-N+1)*INCX + 1 + IF (INCY.LT.0) IY = (-N+1)*INCY + 1 + DO I = 1,N + DY(IY) = DX(IX) + IX = IX + INCX + IY = IY + INCY + END DO + END IF + RETURN + END diff --git a/lapack/internal/testdata/dlasqtest/disnan.f b/lapack/internal/testdata/dlasqtest/disnan.f new file mode 100644 index 00000000..355b8279 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/disnan.f @@ -0,0 +1,80 @@ +*> \brief \b DISNAN tests input for NaN. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DISNAN + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* LOGICAL FUNCTION DISNAN( DIN ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DIN +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DISNAN returns .TRUE. if its argument is NaN, and .FALSE. +*> otherwise. To be replaced by the Fortran 2003 intrinsic in the +*> future. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] DIN +*> \verbatim +*> DIN is DOUBLE PRECISION +*> Input to test for NaN. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION DISNAN( DIN ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN +* .. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL DLAISNAN + EXTERNAL DLAISNAN +* .. +* .. Executable Statements .. + DISNAN = DLAISNAN(DIN,DIN) + RETURN + END diff --git a/lapack/internal/testdata/dlasqtest/dlaisnan.f b/lapack/internal/testdata/dlasqtest/dlaisnan.f new file mode 100644 index 00000000..58595c5c --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlaisnan.f @@ -0,0 +1,91 @@ +*> \brief \b DLAISNAN tests input for NaN by comparing two arguments for inequality. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAISNAN + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DIN1, DIN2 +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> This routine is not for general use. It exists solely to avoid +*> over-optimization in DISNAN. +*> +*> DLAISNAN checks for NaNs by comparing its two arguments for +*> inequality. NaN is the only floating-point value where NaN != NaN +*> returns .TRUE. To check for NaNs, pass the same variable as both +*> arguments. +*> +*> A compiler must assume that the two arguments are +*> not the same variable, and the test will not be optimized away. +*> Interprocedural or whole-program optimization may delete this +*> test. The ISNAN functions will be replaced by the correct +*> Fortran 03 intrinsic once the intrinsic is widely available. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] DIN1 +*> \verbatim +*> DIN1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] DIN2 +*> \verbatim +*> DIN2 is DOUBLE PRECISION +*> Two numbers to compare for inequality. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN1, DIN2 +* .. +* +* ===================================================================== +* +* .. Executable Statements .. + DLAISNAN = (DIN1.NE.DIN2) + RETURN + END diff --git a/lapack/internal/testdata/dlasqtest/dlamch.f b/lapack/internal/testdata/dlasqtest/dlamch.f new file mode 100644 index 00000000..25c2c8e6 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlamch.f @@ -0,0 +1,193 @@ +*> \brief \b DLAMCH +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAMCH determines double precision machine parameters. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CMACH +*> \verbatim +*> Specifies the value to be returned by DLAMCH: +*> = 'E' or 'e', DLAMCH := eps +*> = 'S' or 's , DLAMCH := sfmin +*> = 'B' or 'b', DLAMCH := base +*> = 'P' or 'p', DLAMCH := eps*base +*> = 'N' or 'n', DLAMCH := t +*> = 'R' or 'r', DLAMCH := rnd +*> = 'M' or 'm', DLAMCH := emin +*> = 'U' or 'u', DLAMCH := rmin +*> = 'L' or 'l', DLAMCH := emax +*> = 'O' or 'o', DLAMCH := rmax +*> where +*> eps = relative machine precision +*> sfmin = safe minimum, such that 1/sfmin does not overflow +*> base = base of the machine +*> prec = eps*base +*> t = number of (base) digits in the mantissa +*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise +*> emin = minimum exponent before (gradual) underflow +*> rmin = underflow threshold - base**(emin-1) +*> emax = largest exponent before overflow +*> rmax = overflow threshold - (base**emax)*(1-eps) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CMACH +* .. +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION RND, EPS, SFMIN, SMALL, RMACH +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT, + $ MINEXPONENT, RADIX, TINY +* .. +* .. Executable Statements .. +* +* +* Assume rounding, not chopping. Always. +* + RND = ONE +* + IF( ONE.EQ.RND ) THEN + EPS = EPSILON(ZERO) * 0.5 + ELSE + EPS = EPSILON(ZERO) + END IF +* + IF( LSAME( CMACH, 'E' ) ) THEN + RMACH = EPS + ELSE IF( LSAME( CMACH, 'S' ) ) THEN + SFMIN = TINY(ZERO) + SMALL = ONE / HUGE(ZERO) + IF( SMALL.GE.SFMIN ) THEN +* +* Use SMALL plus a bit, to avoid the possibility of rounding +* causing overflow when computing 1/sfmin. +* + SFMIN = SMALL*( ONE+EPS ) + END IF + RMACH = SFMIN + ELSE IF( LSAME( CMACH, 'B' ) ) THEN + RMACH = RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'P' ) ) THEN + RMACH = EPS * RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'N' ) ) THEN + RMACH = DIGITS(ZERO) + ELSE IF( LSAME( CMACH, 'R' ) ) THEN + RMACH = RND + ELSE IF( LSAME( CMACH, 'M' ) ) THEN + RMACH = MINEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'U' ) ) THEN + RMACH = tiny(zero) + ELSE IF( LSAME( CMACH, 'L' ) ) THEN + RMACH = MAXEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'O' ) ) THEN + RMACH = HUGE(ZERO) + ELSE + RMACH = ZERO + END IF +* + DLAMCH = RMACH + RETURN +* +* End of DLAMCH +* + END +************************************************************************ +*> \brief \b DLAMC3 +*> \details +*> \b Purpose: +*> \verbatim +*> DLAMC3 is intended to force A and B to be stored prior to doing +*> the addition of A and B , for use in situations where optimizers +*> might hold one of these in a register. +*> \endverbatim +*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +*> \date November 2011 +*> \ingroup auxOTHERauxiliary +*> +*> \param[in] A +*> \verbatim +*> A is a DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is a DOUBLE PRECISION +*> The values A and B. +*> \endverbatim +*> + DOUBLE PRECISION FUNCTION DLAMC3( A, B ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2010 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* ===================================================================== +* +* .. Executable Statements .. +* + DLAMC3 = A + B +* + RETURN +* +* End of DLAMC3 +* + END +* +************************************************************************ diff --git a/lapack/internal/testdata/dlasqtest/dlas2.f b/lapack/internal/testdata/dlasqtest/dlas2.f new file mode 100644 index 00000000..81077f94 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlas2.f @@ -0,0 +1,183 @@ +*> \brief \b DLAS2 computes singular values of a 2-by-2 triangular matrix. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAS2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAS2( F, G, H, SSMIN, SSMAX ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION F, G, H, SSMAX, SSMIN +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAS2 computes the singular values of the 2-by-2 matrix +*> [ F G ] +*> [ 0 H ]. +*> On return, SSMIN is the smaller singular value and SSMAX is the +*> larger singular value. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] F +*> \verbatim +*> F is DOUBLE PRECISION +*> The (1,1) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[in] G +*> \verbatim +*> G is DOUBLE PRECISION +*> The (1,2) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[in] H +*> \verbatim +*> H is DOUBLE PRECISION +*> The (2,2) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[out] SSMIN +*> \verbatim +*> SSMIN is DOUBLE PRECISION +*> The smaller singular value. +*> \endverbatim +*> +*> \param[out] SSMAX +*> \verbatim +*> SSMAX is DOUBLE PRECISION +*> The larger singular value. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Barring over/underflow, all output quantities are correct to within +*> a few units in the last place (ulps), even in the absence of a guard +*> digit in addition/subtraction. +*> +*> In IEEE arithmetic, the code works correctly if one matrix element is +*> infinite. +*> +*> Overflow will not occur unless the largest singular value itself +*> overflows, or is within a few ulps of overflow. (On machines with +*> partial overflow, like the Cray, overflow may occur if the largest +*> singular value is within a factor of 2 of overflow.) +*> +*> Underflow is harmless if underflow is gradual. Otherwise, results +*> may correspond to a matrix modified by perturbations of size near +*> the underflow threshold. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DLAS2( F, G, H, SSMIN, SSMAX ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION F, G, H, SSMAX, SSMIN +* .. +* +* ==================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AS, AT, AU, C, FA, FHMN, FHMX, GA, HA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + FA = ABS( F ) + GA = ABS( G ) + HA = ABS( H ) + FHMN = MIN( FA, HA ) + FHMX = MAX( FA, HA ) + IF( FHMN.EQ.ZERO ) THEN + SSMIN = ZERO + IF( FHMX.EQ.ZERO ) THEN + SSMAX = GA + ELSE + SSMAX = MAX( FHMX, GA )*SQRT( ONE+ + $ ( MIN( FHMX, GA ) / MAX( FHMX, GA ) )**2 ) + END IF + ELSE + IF( GA.LT.FHMX ) THEN + AS = ONE + FHMN / FHMX + AT = ( FHMX-FHMN ) / FHMX + AU = ( GA / FHMX )**2 + C = TWO / ( SQRT( AS*AS+AU )+SQRT( AT*AT+AU ) ) + SSMIN = FHMN*C + SSMAX = FHMX / C + ELSE + AU = FHMX / GA + IF( AU.EQ.ZERO ) THEN +* +* Avoid possible harmful underflow if exponent range +* asymmetric (true SSMIN may not underflow even if +* AU underflows) +* + SSMIN = ( FHMN*FHMX ) / GA + SSMAX = GA + ELSE + AS = ONE + FHMN / FHMX + AT = ( FHMX-FHMN ) / FHMX + C = ONE / ( SQRT( ONE+( AS*AU )**2 )+ + $ SQRT( ONE+( AT*AU )**2 ) ) + SSMIN = ( FHMN*C )*AU + SSMIN = SSMIN + SSMIN + SSMAX = GA / ( C+C ) + END IF + END IF + END IF + RETURN +* +* End of DLAS2 +* + END diff --git a/lapack/internal/testdata/dlasqtest/dlascl.f b/lapack/internal/testdata/dlasqtest/dlascl.f new file mode 100644 index 00000000..9b9b33c0 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlascl.f @@ -0,0 +1,364 @@ +*> \brief \b DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASCL + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER TYPE +* INTEGER INFO, KL, KU, LDA, M, N +* DOUBLE PRECISION CFROM, CTO +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASCL multiplies the M by N real matrix A by the real scalar +*> CTO/CFROM. This is done without over/underflow as long as the final +*> result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that +*> A may be full, upper triangular, lower triangular, upper Hessenberg, +*> or banded. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] TYPE +*> \verbatim +*> TYPE is CHARACTER*1 +*> TYPE indices the storage type of the input matrix. +*> = 'G': A is a full matrix. +*> = 'L': A is a lower triangular matrix. +*> = 'U': A is an upper triangular matrix. +*> = 'H': A is an upper Hessenberg matrix. +*> = 'B': A is a symmetric band matrix with lower bandwidth KL +*> and upper bandwidth KU and with the only the lower +*> half stored. +*> = 'Q': A is a symmetric band matrix with lower bandwidth KL +*> and upper bandwidth KU and with the only the upper +*> half stored. +*> = 'Z': A is a band matrix with lower bandwidth KL and upper +*> bandwidth KU. See DGBTRF for storage details. +*> \endverbatim +*> +*> \param[in] KL +*> \verbatim +*> KL is INTEGER +*> The lower bandwidth of A. Referenced only if TYPE = 'B', +*> 'Q' or 'Z'. +*> \endverbatim +*> +*> \param[in] KU +*> \verbatim +*> KU is INTEGER +*> The upper bandwidth of A. Referenced only if TYPE = 'B', +*> 'Q' or 'Z'. +*> \endverbatim +*> +*> \param[in] CFROM +*> \verbatim +*> CFROM is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] CTO +*> \verbatim +*> CTO is DOUBLE PRECISION +*> +*> The matrix A is multiplied by CTO/CFROM. A(I,J) is computed +*> without over/underflow if the final result CTO*A(I,J)/CFROM +*> can be represented without over/underflow. CFROM must be +*> nonzero. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. M >= 0. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in,out] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> The matrix to be multiplied by CTO/CFROM. See TYPE for the +*> storage type. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> 0 - successful exit +*> <0 - if INFO = -i, the i-th argument had an illegal value. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER TYPE + INTEGER INFO, KL, KU, LDA, M, N + DOUBLE PRECISION CFROM, CTO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL DONE + INTEGER I, ITYPE, J, K1, K2, K3, K4 + DOUBLE PRECISION BIGNUM, CFROM1, CFROMC, CTO1, CTOC, MUL, SMLNUM +* .. +* .. External Functions .. + LOGICAL LSAME, DISNAN + DOUBLE PRECISION DLAMCH + EXTERNAL LSAME, DLAMCH, DISNAN +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 +* + IF( LSAME( TYPE, 'G' ) ) THEN + ITYPE = 0 + ELSE IF( LSAME( TYPE, 'L' ) ) THEN + ITYPE = 1 + ELSE IF( LSAME( TYPE, 'U' ) ) THEN + ITYPE = 2 + ELSE IF( LSAME( TYPE, 'H' ) ) THEN + ITYPE = 3 + ELSE IF( LSAME( TYPE, 'B' ) ) THEN + ITYPE = 4 + ELSE IF( LSAME( TYPE, 'Q' ) ) THEN + ITYPE = 5 + ELSE IF( LSAME( TYPE, 'Z' ) ) THEN + ITYPE = 6 + ELSE + ITYPE = -1 + END IF +* + IF( ITYPE.EQ.-1 ) THEN + INFO = -1 + ELSE IF( CFROM.EQ.ZERO .OR. DISNAN(CFROM) ) THEN + INFO = -4 + ELSE IF( DISNAN(CTO) ) THEN + INFO = -5 + ELSE IF( M.LT.0 ) THEN + INFO = -6 + ELSE IF( N.LT.0 .OR. ( ITYPE.EQ.4 .AND. N.NE.M ) .OR. + $ ( ITYPE.EQ.5 .AND. N.NE.M ) ) THEN + INFO = -7 + ELSE IF( ITYPE.LE.3 .AND. LDA.LT.MAX( 1, M ) ) THEN + INFO = -9 + ELSE IF( ITYPE.GE.4 ) THEN + IF( KL.LT.0 .OR. KL.GT.MAX( M-1, 0 ) ) THEN + INFO = -2 + ELSE IF( KU.LT.0 .OR. KU.GT.MAX( N-1, 0 ) .OR. + $ ( ( ITYPE.EQ.4 .OR. ITYPE.EQ.5 ) .AND. KL.NE.KU ) ) + $ THEN + INFO = -3 + ELSE IF( ( ITYPE.EQ.4 .AND. LDA.LT.KL+1 ) .OR. + $ ( ITYPE.EQ.5 .AND. LDA.LT.KU+1 ) .OR. + $ ( ITYPE.EQ.6 .AND. LDA.LT.2*KL+KU+1 ) ) THEN + INFO = -9 + END IF + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASCL', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. M.EQ.0 ) + $ RETURN +* +* Get machine parameters +* + SMLNUM = DLAMCH( 'S' ) + BIGNUM = ONE / SMLNUM +* + CFROMC = CFROM + CTOC = CTO +* + 10 CONTINUE + CFROM1 = CFROMC*SMLNUM + IF( CFROM1.EQ.CFROMC ) THEN +! CFROMC is an inf. Multiply by a correctly signed zero for +! finite CTOC, or a NaN if CTOC is infinite. + MUL = CTOC / CFROMC + DONE = .TRUE. + CTO1 = CTOC + ELSE + CTO1 = CTOC / BIGNUM + IF( CTO1.EQ.CTOC ) THEN +! CTOC is either 0 or an inf. In both cases, CTOC itself +! serves as the correct multiplication factor. + MUL = CTOC + DONE = .TRUE. + CFROMC = ONE + ELSE IF( ABS( CFROM1 ).GT.ABS( CTOC ) .AND. CTOC.NE.ZERO ) THEN + MUL = SMLNUM + DONE = .FALSE. + CFROMC = CFROM1 + ELSE IF( ABS( CTO1 ).GT.ABS( CFROMC ) ) THEN + MUL = BIGNUM + DONE = .FALSE. + CTOC = CTO1 + ELSE + MUL = CTOC / CFROMC + DONE = .TRUE. + END IF + END IF +* + IF( ITYPE.EQ.0 ) THEN +* +* Full matrix +* + DO 30 J = 1, N + DO 20 I = 1, M + A( I, J ) = A( I, J )*MUL + 20 CONTINUE + 30 CONTINUE +* + ELSE IF( ITYPE.EQ.1 ) THEN +* +* Lower triangular matrix +* + DO 50 J = 1, N + DO 40 I = J, M + A( I, J ) = A( I, J )*MUL + 40 CONTINUE + 50 CONTINUE +* + ELSE IF( ITYPE.EQ.2 ) THEN +* +* Upper triangular matrix +* + DO 70 J = 1, N + DO 60 I = 1, MIN( J, M ) + A( I, J ) = A( I, J )*MUL + 60 CONTINUE + 70 CONTINUE +* + ELSE IF( ITYPE.EQ.3 ) THEN +* +* Upper Hessenberg matrix +* + DO 90 J = 1, N + DO 80 I = 1, MIN( J+1, M ) + A( I, J ) = A( I, J )*MUL + 80 CONTINUE + 90 CONTINUE +* + ELSE IF( ITYPE.EQ.4 ) THEN +* +* Lower half of a symmetric band matrix +* + K3 = KL + 1 + K4 = N + 1 + DO 110 J = 1, N + DO 100 I = 1, MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 100 CONTINUE + 110 CONTINUE +* + ELSE IF( ITYPE.EQ.5 ) THEN +* +* Upper half of a symmetric band matrix +* + K1 = KU + 2 + K3 = KU + 1 + DO 130 J = 1, N + DO 120 I = MAX( K1-J, 1 ), K3 + A( I, J ) = A( I, J )*MUL + 120 CONTINUE + 130 CONTINUE +* + ELSE IF( ITYPE.EQ.6 ) THEN +* +* Band matrix +* + K1 = KL + KU + 2 + K2 = KL + 1 + K3 = 2*KL + KU + 1 + K4 = KL + KU + 1 + M + DO 150 J = 1, N + DO 140 I = MAX( K1-J, K2 ), MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 140 CONTINUE + 150 CONTINUE +* + END IF +* + IF( .NOT.DONE ) + $ GO TO 10 +* + RETURN +* +* End of DLASCL +* + END diff --git a/lapack/internal/testdata/dlasqtest/dlasq1.f b/lapack/internal/testdata/dlasqtest/dlasq1.f new file mode 100644 index 00000000..f0847781 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlasq1.f @@ -0,0 +1,226 @@ +*> \brief \b DLASQ1 computes the singular values of a real square bidiagonal matrix. Used by sbdsqr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ1 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ1( N, D, E, WORK, INFO ) +* +* .. Scalar Arguments .. +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ), E( * ), WORK( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ1 computes the singular values of a real N-by-N bidiagonal +*> matrix with diagonal D and off-diagonal E. The singular values +*> are computed to high relative accuracy, in the absence of +*> denormalization, underflow and overflow. The algorithm was first +*> presented in +*> +*> "Accurate singular values and differential qd algorithms" by K. V. +*> Fernando and B. N. Parlett, Numer. Math., Vol-67, No. 2, pp. 191-230, +*> 1994, +*> +*> and the present implementation is described in "An implementation of +*> the dqds Algorithm (Positive Case)", LAPACK Working Note. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of rows and columns in the matrix. N >= 0. +*> \endverbatim +*> +*> \param[in,out] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> On entry, D contains the diagonal elements of the +*> bidiagonal matrix whose SVD is desired. On normal exit, +*> D contains the singular values in decreasing order. +*> \endverbatim +*> +*> \param[in,out] E +*> \verbatim +*> E is DOUBLE PRECISION array, dimension (N) +*> On entry, elements E(1:N-1) contain the off-diagonal elements +*> of the bidiagonal matrix whose SVD is desired. +*> On exit, E is overwritten. +*> \endverbatim +*> +*> \param[out] WORK +*> \verbatim +*> WORK is DOUBLE PRECISION array, dimension (4*N) +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> > 0: the algorithm failed +*> = 1, a split was marked by a positive value in E +*> = 2, current block of Z not diagonalized after 100*N +*> iterations (in inner while loop) On exit D and E +*> represent a matrix with the same singular values +*> which the calling subroutine could use to finish the +*> computation, or even feed back into DLASQ1 +*> = 3, termination criterion of outer while loop not met +*> (program created more than N unreduced blocks) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASQ1( N, D, E, WORK, INFO ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ), WORK( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) +* .. +* .. Local Scalars .. + INTEGER I, IINFO + DOUBLE PRECISION EPS, SCALE, SAFMIN, SIGMN, SIGMX +* .. +* .. External Subroutines .. + EXTERNAL DCOPY, DLAS2, DLASCL, DLASQ2, DLASRT, XERBLA +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, SQRT +* .. +* .. Executable Statements .. +* + INFO = 0 + IF( N.LT.0 ) THEN + INFO = -2 + CALL XERBLA( 'DLASQ1', -INFO ) + RETURN + ELSE IF( N.EQ.0 ) THEN + RETURN + ELSE IF( N.EQ.1 ) THEN + D( 1 ) = ABS( D( 1 ) ) + RETURN + ELSE IF( N.EQ.2 ) THEN + CALL DLAS2( D( 1 ), E( 1 ), D( 2 ), SIGMN, SIGMX ) + D( 1 ) = SIGMX + D( 2 ) = SIGMN + RETURN + END IF +* +* Estimate the largest singular value. +* + SIGMX = ZERO + DO 10 I = 1, N - 1 + D( I ) = ABS( D( I ) ) + SIGMX = MAX( SIGMX, ABS( E( I ) ) ) + 10 CONTINUE + D( N ) = ABS( D( N ) ) +* +* Early return if SIGMX is zero (matrix is already diagonal). +* + IF( SIGMX.EQ.ZERO ) THEN + CALL DLASRT( 'D', N, D, IINFO ) + RETURN + END IF +* + DO 20 I = 1, N + SIGMX = MAX( SIGMX, D( I ) ) + 20 CONTINUE +* +* Copy D and E into WORK (in the Z format) and scale (squaring the +* input data makes scaling by a power of the radix pointless). +* + EPS = DLAMCH( 'Precision' ) + SAFMIN = DLAMCH( 'Safe minimum' ) + SCALE = SQRT( EPS / SAFMIN ) + + CALL DCOPY( N, D, 1, WORK( 1 ), 2 ) + CALL DCOPY( N-1, E, 1, WORK( 2 ), 2 ) + CALL DLASCL( 'G', 0, 0, SIGMX, SCALE, 2*N-1, 1, WORK, 2*N-1, + $ IINFO ) +* +* Compute the q's and e's. +* + DO 30 I = 1, 2*N - 1 + WORK( I ) = WORK( I )**2 + 30 CONTINUE + WORK( 2*N ) = ZERO +* + + CALL DLASQ2( N, WORK, INFO ) +* + IF( INFO.EQ.0 ) THEN + DO 40 I = 1, N + D( I ) = SQRT( WORK( I ) ) + 40 CONTINUE + CALL DLASCL( 'G', 0, 0, SCALE, SIGMX, N, 1, D, N, IINFO ) + ELSE IF( INFO.EQ.2 ) THEN +* +* Maximum number of iterations exceeded. Move data from WORK +* into D and E so the calling subroutine can try to finish +* + DO I = 1, N + D( I ) = SQRT( WORK( 2*I-1 ) ) + E( I ) = SQRT( WORK( 2*I ) ) + END DO + CALL DLASCL( 'G', 0, 0, SCALE, SIGMX, N, 1, D, N, IINFO ) + CALL DLASCL( 'G', 0, 0, SCALE, SIGMX, N, 1, E, N, IINFO ) + END IF +* + RETURN +* +* End of DLASQ1 +* + END diff --git a/lapack/internal/testdata/dlasqtest/dlasq2.f b/lapack/internal/testdata/dlasqtest/dlasq2.f new file mode 100644 index 00000000..602dffc9 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlasq2.f @@ -0,0 +1,652 @@ +*> \brief \b DLASQ2 computes all the eigenvalues of the symmetric positive definite tridiagonal matrix associated with the qd Array Z to high relative accuracy. Used by sbdsqr and sstegr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ2( N, Z, INFO ) +* +* .. Scalar Arguments .. +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ2 computes all the eigenvalues of the symmetric positive +*> definite tridiagonal matrix associated with the qd array Z to high +*> relative accuracy are computed to high relative accuracy, in the +*> absence of denormalization, underflow and overflow. +*> +*> To see the relation of Z to the tridiagonal matrix, let L be a +*> unit lower bidiagonal matrix with subdiagonals Z(2,4,6,,..) and +*> let U be an upper bidiagonal matrix with 1's above and diagonal +*> Z(1,3,5,,..). The tridiagonal is L*U or, if you prefer, the +*> symmetric tridiagonal to which it is similar. +*> +*> Note : DLASQ2 defines a logical variable, IEEE, which is true +*> on machines which follow ieee-754 floating-point standard in their +*> handling of infinities and NaNs, and false otherwise. This variable +*> is passed to DLASQ3. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of rows and columns in the matrix. N >= 0. +*> \endverbatim +*> +*> \param[in,out] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> On entry Z holds the qd array. On exit, entries 1 to N hold +*> the eigenvalues in decreasing order, Z( 2*N+1 ) holds the +*> trace, and Z( 2*N+2 ) holds the sum of the eigenvalues. If +*> N > 2, then Z( 2*N+3 ) holds the iteration count, Z( 2*N+4 ) +*> holds NDIVS/NIN^2, and Z( 2*N+5 ) holds the percentage of +*> shifts that failed. +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if the i-th argument is a scalar and had an illegal +*> value, then INFO = -i, if the i-th argument is an +*> array and the j-entry had an illegal value, then +*> INFO = -(i*100+j) +*> > 0: the algorithm failed +*> = 1, a split was marked by a positive value in E +*> = 2, current block of Z not diagonalized after 100*N +*> iterations (in inner while loop). On exit Z holds +*> a qd array with the same eigenvalues as the given Z. +*> = 3, termination criterion of outer while loop not met +*> (program created more than N unreduced blocks) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Local Variables: I0:N0 defines a current unreduced segment of Z. +*> The shifts are accumulated in SIGMA. Iteration count is in ITER. +*> Ping-pong is controlled by PP (alternates between 0 and 1). +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DLASQ2( N, Z, INFO ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION CBIAS + PARAMETER ( CBIAS = 1.50D0 ) + DOUBLE PRECISION ZERO, HALF, ONE, TWO, FOUR, HUNDRD + PARAMETER ( ZERO = 0.0D0, HALF = 0.5D0, ONE = 1.0D0, + $ TWO = 2.0D0, FOUR = 4.0D0, HUNDRD = 100.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL IEEE + INTEGER I0, I1, I4, IINFO, IPN4, ITER, IWHILA, IWHILB, + $ K, KMIN, N0, N1, NBIG, NDIV, NFAIL, PP, SPLT, + $ TTYPE + DOUBLE PRECISION D, DEE, DEEMIN, DESIG, DMIN, DMIN1, DMIN2, DN, + $ DN1, DN2, E, EMAX, EMIN, EPS, G, OLDEMN, QMAX, + $ QMIN, S, SAFMIN, SIGMA, T, TAU, TEMP, TOL, + $ TOL2, TRACE, ZMAX, TEMPE, TEMPQ +* .. +* .. External Subroutines .. + EXTERNAL DLASQ3, DLASRT, XERBLA +* .. +* .. External Functions .. + INTEGER ILAENV + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH, ILAENV +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, DBLE, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input arguments. +* (in case DLASQ2 is not called by DLASQ1) +* + INFO = 0 + EPS = DLAMCH( 'Precision' ) + SAFMIN = DLAMCH( 'Safe minimum' ) + TOL = EPS*HUNDRD + TOL2 = TOL**2 +* + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DLASQ2', 1 ) + RETURN + ELSE IF( N.EQ.0 ) THEN + RETURN + ELSE IF( N.EQ.1 ) THEN +* +* 1-by-1 case. +* + IF( Z( 1 ).LT.ZERO ) THEN + INFO = -201 + CALL XERBLA( 'DLASQ2', 2 ) + END IF + RETURN + ELSE IF( N.EQ.2 ) THEN +* +* 2-by-2 case. +* + IF( Z( 2 ).LT.ZERO .OR. Z( 3 ).LT.ZERO ) THEN + INFO = -2 + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + ELSE IF( Z( 3 ).GT.Z( 1 ) ) THEN + D = Z( 3 ) + Z( 3 ) = Z( 1 ) + Z( 1 ) = D + END IF + Z( 5 ) = Z( 1 ) + Z( 2 ) + Z( 3 ) + IF( Z( 2 ).GT.Z( 3 )*TOL2 ) THEN + T = HALF*( ( Z( 1 )-Z( 3 ) )+Z( 2 ) ) + S = Z( 3 )*( Z( 2 ) / T ) + IF( S.LE.T ) THEN + S = Z( 3 )*( Z( 2 ) / ( T*( ONE+SQRT( ONE+S / T ) ) ) ) + ELSE + S = Z( 3 )*( Z( 2 ) / ( T+SQRT( T )*SQRT( T+S ) ) ) + END IF + T = Z( 1 ) + ( S+Z( 2 ) ) + Z( 3 ) = Z( 3 )*( Z( 1 ) / T ) + Z( 1 ) = T + END IF + Z( 2 ) = Z( 3 ) + Z( 6 ) = Z( 2 ) + Z( 1 ) + RETURN + END IF +* +* Check for negative data and compute sums of q's and e's. +* + Z( 2*N ) = ZERO + EMIN = Z( 2 ) + QMAX = ZERO + ZMAX = ZERO + D = ZERO + E = ZERO +* + DO 10 K = 1, 2*( N-1 ), 2 + IF( Z( K ).LT.ZERO ) THEN + INFO = -( 200+K ) + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + ELSE IF( Z( K+1 ).LT.ZERO ) THEN + INFO = -( 200+K+1 ) + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + END IF + D = D + Z( K ) + E = E + Z( K+1 ) + QMAX = MAX( QMAX, Z( K ) ) + EMIN = MIN( EMIN, Z( K+1 ) ) + ZMAX = MAX( QMAX, ZMAX, Z( K+1 ) ) + 10 CONTINUE + IF( Z( 2*N-1 ).LT.ZERO ) THEN + INFO = -( 200+2*N-1 ) + CALL XERBLA( 'DLASQ2', 2 ) + RETURN + END IF + D = D + Z( 2*N-1 ) + QMAX = MAX( QMAX, Z( 2*N-1 ) ) + ZMAX = MAX( QMAX, ZMAX ) +* +* Check for diagonality. +* + IF( E.EQ.ZERO ) THEN + DO 20 K = 2, N + Z( K ) = Z( 2*K-1 ) + 20 CONTINUE + CALL DLASRT( 'D', N, Z, IINFO ) + Z( 2*N-1 ) = D + RETURN + END IF +* + TRACE = D + E +* +* Check for zero data. +* + IF( TRACE.EQ.ZERO ) THEN + Z( 2*N-1 ) = ZERO + RETURN + END IF +* +* Check whether the machine is IEEE conformable. +* + IEEE = ILAENV( 10, 'DLASQ2', 'N', 1, 2, 3, 4 ).EQ.1 .AND. + $ ILAENV( 11, 'DLASQ2', 'N', 1, 2, 3, 4 ).EQ.1 +* +* Rearrange data for locality: Z=(q1,qq1,e1,ee1,q2,qq2,e2,ee2,...). +* + DO 30 K = 2*N, 2, -2 + Z( 2*K ) = ZERO + Z( 2*K-1 ) = Z( K ) + Z( 2*K-2 ) = ZERO + Z( 2*K-3 ) = Z( K-1 ) + 30 CONTINUE +* + I0 = 1 + N0 = N +* +* Reverse the qd-array, if warranted. +* + IF( CBIAS*Z( 4*I0-3 ).LT.Z( 4*N0-3 ) ) THEN + IPN4 = 4*( I0+N0 ) + DO 40 I4 = 4*I0, 2*( I0+N0-1 ), 4 + + TEMP = Z( I4-3 ) + Z( I4-3 ) = Z( IPN4-I4-3 ) + Z( IPN4-I4-3 ) = TEMP + TEMP = Z( I4-1 ) + Z( I4-1 ) = Z( IPN4-I4-5 ) + Z( IPN4-I4-5 ) = TEMP + 40 CONTINUE + END IF +* +* Initial split checking via dqd and Li's test. +* + PP = 0 +* + DO 80 K = 1, 2 +* + D = Z( 4*N0+PP-3 ) + DO 50 I4 = 4*( N0-1 ) + PP, 4*I0 + PP, -4 + IF( Z( I4-1 ).LE.TOL2*D ) THEN + Z( I4-1 ) = -ZERO + D = Z( I4-3 ) + ELSE + D = Z( I4-3 )*( D / ( D+Z( I4-1 ) ) ) + END IF + 50 CONTINUE +* +* dqd maps Z to ZZ plus Li's test. +* + EMIN = Z( 4*I0+PP+1 ) + D = Z( 4*I0+PP-3 ) + DO 60 I4 = 4*I0 + PP, 4*( N0-1 ) + PP, 4 + Z( I4-2*PP-2 ) = D + Z( I4-1 ) + IF( Z( I4-1 ).LE.TOL2*D ) THEN + Z( I4-1 ) = -ZERO + Z( I4-2*PP-2 ) = D + Z( I4-2*PP ) = ZERO + D = Z( I4+1 ) + ELSE IF( SAFMIN*Z( I4+1 ).LT.Z( I4-2*PP-2 ) .AND. + $ SAFMIN*Z( I4-2*PP-2 ).LT.Z( I4+1 ) ) THEN + TEMP = Z( I4+1 ) / Z( I4-2*PP-2 ) + Z( I4-2*PP ) = Z( I4-1 )*TEMP + D = D*TEMP + ELSE + Z( I4-2*PP ) = Z( I4+1 )*( Z( I4-1 ) / Z( I4-2*PP-2 ) ) + D = Z( I4+1 )*( D / Z( I4-2*PP-2 ) ) + END IF + EMIN = MIN( EMIN, Z( I4-2*PP ) ) + 60 CONTINUE + Z( 4*N0-PP-2 ) = D +* +* Now find qmax. +* + QMAX = Z( 4*I0-PP-2 ) + DO 70 I4 = 4*I0 - PP + 2, 4*N0 - PP - 2, 4 + QMAX = MAX( QMAX, Z( I4 ) ) + 70 CONTINUE +* +* Prepare for the next iteration on K. +* + PP = 1 - PP + 80 CONTINUE + +* +* Initialise variables to pass to DLASQ3. +* + TTYPE = 0 + DMIN1 = ZERO + DMIN2 = ZERO + DN = ZERO + DN1 = ZERO + DN2 = ZERO + G = ZERO + TAU = ZERO +* + ITER = 2 + NFAIL = 0 + NDIV = 2*( N0-I0 ) +* + DO 160 IWHILA = 1, N + 1 + + IF( N0.LT.1 ) THEN + GO TO 170 + END IF +* +* While array unfinished do +* +* E(N0) holds the value of SIGMA when submatrix in I0:N0 +* splits from the rest of the array, but is negated. +* + DESIG = ZERO + IF( N0.EQ.N ) THEN + SIGMA = ZERO + ELSE + SIGMA = -Z( 4*N0-1 ) + END IF + IF( SIGMA.LT.ZERO ) THEN + INFO = 1 + RETURN + END IF +* +* Find last unreduced submatrix's top index I0, find QMAX and +* EMIN. Find Gershgorin-type bound if Q's much greater than E's. +* + EMAX = ZERO + IF( N0.GT.I0 ) THEN + EMIN = ABS( Z( 4*N0-5 ) ) + ELSE + EMIN = ZERO + END IF + QMIN = Z( 4*N0-3 ) + QMAX = QMIN + DO 90 I4 = 4*N0, 8, -4 + IF( Z( I4-5 ).LE.ZERO ) + $ GO TO 100 + IF( QMIN.GE.FOUR*EMAX ) THEN + QMIN = MIN( QMIN, Z( I4-3 ) ) + EMAX = MAX( EMAX, Z( I4-5 ) ) + END IF + QMAX = MAX( QMAX, Z( I4-7 )+Z( I4-5 ) ) + EMIN = MIN( EMIN, Z( I4-5 ) ) + 90 CONTINUE + I4 = 4 +* + 100 CONTINUE + I0 = I4 / 4 + + PP = 0 +* + IF( N0-I0.GT.1 ) THEN + DEE = Z( 4*I0-3 ) + DEEMIN = DEE + KMIN = I0 + DO 110 I4 = 4*I0+1, 4*N0-3, 4 + DEE = Z( I4 )*( DEE /( DEE+Z( I4-2 ) ) ) + IF( DEE.LE.DEEMIN ) THEN + DEEMIN = DEE + KMIN = ( I4+3 )/4 + END IF + 110 CONTINUE + IF( (KMIN-I0)*2.LT.N0-KMIN .AND. + $ DEEMIN.LE.HALF*Z(4*N0-3) ) THEN + IPN4 = 4*( I0+N0 ) + PP = 2 + DO 120 I4 = 4*I0, 2*( I0+N0-1 ), 4 + TEMP = Z( I4-3 ) + Z( I4-3 ) = Z( IPN4-I4-3 ) + Z( IPN4-I4-3 ) = TEMP + TEMP = Z( I4-2 ) + Z( I4-2 ) = Z( IPN4-I4-2 ) + Z( IPN4-I4-2 ) = TEMP + TEMP = Z( I4-1 ) + Z( I4-1 ) = Z( IPN4-I4-5 ) + Z( IPN4-I4-5 ) = TEMP + TEMP = Z( I4 ) + Z( I4 ) = Z( IPN4-I4-4 ) + Z( IPN4-I4-4 ) = TEMP + 120 CONTINUE + END IF + END IF +* +* Put -(initial shift) into DMIN. +* + DMIN = -MAX( ZERO, QMIN-TWO*SQRT( QMIN )*SQRT( EMAX ) ) +* +* Now I0:N0 is unreduced. +* PP = 0 for ping, PP = 1 for pong. +* PP = 2 indicates that flipping was applied to the Z array and +* and that the tests for deflation upon entry in DLASQ3 +* should not be performed. +* + NBIG = 100*( N0-I0+1 ) + DO 140 IWHILB = 1, NBIG + + IF( I0.GT.N0 ) + $ GO TO 150 +* + + ! Print out test cases + + write(3,*) "{" + write(3,*) "i0: ", I0, "," + write(3,*) "n0: ", N0, "," + write(3,'(9999(g0))',advance="no") "z: []float64{" + do i = 1, 4*n + write (3,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (3,*) "}," + write (3,*) "pp: ", PP, "," + write (3,*) "dmin: ", DMIN, "," + write (3,*) "desig:", DESIG, "," + write (3,*) "qmax: ", QMAX, "," + write (3,*) "ttype:", TTYPE, "," + write (3,*) "dmin1:", DMIN1, "," + write (3,*) "dmin2:", DMIN2, "," + write (3,*) "dn: ", DN, "," + write (3,*) "dn1: ", DN1, "," + write (3,*) "dn2: ", DN2, "," + write (3,*) "g: ", G, "," + write (3,*) "tau: ", TAU, "," + write (3,*) "nFail:", NFAIL, "," + write (3,*) "iter: ", ITER, "," + write (3,*) "sigma:", SIGMA, "," + write (3,*) "nDiv: ", NDIV, "," + +* While submatrix unfinished take a good dqds step. +* + + + CALL DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL, + $ ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1, + $ DN2, G, TAU ) + + + ! Write the outputs + write(3,'(9999(g0))',advance="no") "zOut: []float64{" + do i = 1, 4*n + write (3,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (3,*) "}," + write (3,*) "i0Out:",I0, "," + write (3,*) "n0Out:", N0, "," + write (3,*) "ppOut:", PP, "," + write (3,*) "dminOut:", DMIN, "," + write (3,*) "desigOut:", DESIG, "," + write (3,*) "sigmaOut:", SIGMA, "," + write (3,*) "qmaxOut:", QMAX, "," + write (3,*) "nFailOut:", NFAIL, "," + write (3,*) "iterOut:", ITER, "," + write (3,*) "nDivOut:", NDIV, "," + write (3,*) "ttypeOut:", TTYPE, "," + write (3,*) "dmin1Out:", DMIN1, "," + write (3,*) "dmin2Out:", DMIN2, "," + write (3,*) "dnOut:", DN, "," + write (3,*) "dn1Out:", DN1, "," + write (3,*) "dn2Out:", DN2, "," + write (3,*) "gOut:", G, "," + write (3,*) "tauOut:", TAU, "," + + write (3,*) "}," + + + PP = 1 - PP +* +* When EMIN is very small check for splits. +* + IF( PP.EQ.0 .AND. N0-I0.GE.3 ) THEN + IF( Z( 4*N0 ).LE.TOL2*QMAX .OR. + $ Z( 4*N0-1 ).LE.TOL2*SIGMA ) THEN + SPLT = I0 - 1 + QMAX = Z( 4*I0-3 ) + EMIN = Z( 4*I0-1 ) + OLDEMN = Z( 4*I0 ) + DO 130 I4 = 4*I0, 4*( N0-3 ), 4 + IF( Z( I4 ).LE.TOL2*Z( I4-3 ) .OR. + $ Z( I4-1 ).LE.TOL2*SIGMA ) THEN + Z( I4-1 ) = -SIGMA + SPLT = I4 / 4 + QMAX = ZERO + EMIN = Z( I4+3 ) + OLDEMN = Z( I4+4 ) + ELSE + QMAX = MAX( QMAX, Z( I4+1 ) ) + EMIN = MIN( EMIN, Z( I4-1 ) ) + OLDEMN = MIN( OLDEMN, Z( I4 ) ) + END IF + 130 CONTINUE + Z( 4*N0-1 ) = EMIN + Z( 4*N0 ) = OLDEMN + I0 = SPLT + 1 + END IF + END IF +* + 140 CONTINUE +* + INFO = 2 +* +* Maximum number of iterations exceeded, restore the shift +* SIGMA and place the new d's and e's in a qd array. +* This might need to be done for several blocks +* + I1 = I0 + N1 = N0 + 145 CONTINUE + + TEMPQ = Z( 4*I0-3 ) + Z( 4*I0-3 ) = Z( 4*I0-3 ) + SIGMA + DO K = I0+1, N0 + TEMPE = Z( 4*K-5 ) + Z( 4*K-5 ) = Z( 4*K-5 ) * (TEMPQ / Z( 4*K-7 )) + TEMPQ = Z( 4*K-3 ) + Z( 4*K-3 ) = Z( 4*K-3 ) + SIGMA + TEMPE - Z( 4*K-5 ) + END DO +* +* Prepare to do this on the previous block if there is one +* + IF( I1.GT.1 ) THEN + N1 = I1-1 + DO WHILE( ( I1.GE.2 ) .AND. ( Z(4*I1-5).GE.ZERO ) ) + I1 = I1 - 1 + END DO + SIGMA = -Z(4*N1-1) + GO TO 145 + END IF + + DO K = 1, N + Z( 2*K-1 ) = Z( 4*K-3 ) +* +* Only the block 1..N0 is unfinished. The rest of the e's +* must be essentially zero, although sometimes other data +* has been stored in them. +* + IF( K.LT.N0 ) THEN + Z( 2*K ) = Z( 4*K-1 ) + ELSE + Z( 2*K ) = 0 + END IF + END DO + RETURN +* +* end IWHILB +* + 150 CONTINUE +* + 160 CONTINUE +* + INFO = 3 + RETURN +* +* end IWHILA +* + 170 CONTINUE +* + +* Move q's to the front. +* + DO 180 K = 2, N + Z( K ) = Z( 4*K-3 ) + 180 CONTINUE +* +* Sort and compute sum of eigenvalues. +* + CALL DLASRT( 'D', N, Z, IINFO ) +* + + E = ZERO + DO 190 K = N, 1, -1 + E = E + Z( K ) + 190 CONTINUE +* +* Store trace, sum(eigenvalues) and information on performance. +* + + Z( 2*N+1 ) = TRACE + Z( 2*N+2 ) = E + Z( 2*N+3 ) = DBLE( ITER ) + Z( 2*N+4 ) = DBLE( NDIV ) / DBLE( N**2 ) + Z( 2*N+5 ) = HUNDRD*NFAIL / DBLE( ITER ) + + RETURN +* +* End of DLASQ2 +* + END diff --git a/lapack/internal/testdata/dlasqtest/dlasq3.f b/lapack/internal/testdata/dlasqtest/dlasq3.f new file mode 100644 index 00000000..1c4e8ecf --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlasq3.f @@ -0,0 +1,498 @@ +*> \brief \b DLASQ3 checks for deflation, computes a shift and calls dqds. Used by sbdsqr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ3 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL, +* ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1, +* DN2, G, TAU ) +* +* .. Scalar Arguments .. +* LOGICAL IEEE +* INTEGER I0, ITER, N0, NDIV, NFAIL, PP +* DOUBLE PRECISION DESIG, DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, +* $ QMAX, SIGMA, TAU +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ3 checks for deflation, computes a shift (TAU) and calls dqds. +*> In case of failure it changes shifts, and tries again until output +*> is positive. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] I0 +*> \verbatim +*> I0 is INTEGER +*> First index. +*> \endverbatim +*> +*> \param[in,out] N0 +*> \verbatim +*> N0 is INTEGER +*> Last index. +*> \endverbatim +*> +*> \param[in] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> Z holds the qd array. +*> \endverbatim +*> +*> \param[in,out] PP +*> \verbatim +*> PP is INTEGER +*> PP=0 for ping, PP=1 for pong. +*> PP=2 indicates that flipping was applied to the Z array +*> and that the initial tests for deflation should not be +*> performed. +*> \endverbatim +*> +*> \param[out] DMIN +*> \verbatim +*> DMIN is DOUBLE PRECISION +*> Minimum value of d. +*> \endverbatim +*> +*> \param[out] SIGMA +*> \verbatim +*> SIGMA is DOUBLE PRECISION +*> Sum of shifts used in current segment. +*> \endverbatim +*> +*> \param[in,out] DESIG +*> \verbatim +*> DESIG is DOUBLE PRECISION +*> Lower order part of SIGMA +*> \endverbatim +*> +*> \param[in] QMAX +*> \verbatim +*> QMAX is DOUBLE PRECISION +*> Maximum value of q. +*> \endverbatim +*> +*> \param[out] NFAIL +*> \verbatim +*> NFAIL is INTEGER +*> Number of times shift was too big. +*> \endverbatim +*> +*> \param[out] ITER +*> \verbatim +*> ITER is INTEGER +*> Number of iterations. +*> \endverbatim +*> +*> \param[out] NDIV +*> \verbatim +*> NDIV is INTEGER +*> Number of divisions. +*> \endverbatim +*> +*> \param[in] IEEE +*> \verbatim +*> IEEE is LOGICAL +*> Flag for IEEE or non IEEE arithmetic (passed to DLASQ5). +*> \endverbatim +*> +*> \param[in,out] TTYPE +*> \verbatim +*> TTYPE is INTEGER +*> Shift type. +*> \endverbatim +*> +*> \param[in,out] DMIN1 +*> \verbatim +*> DMIN1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] DMIN2 +*> \verbatim +*> DMIN2 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] DN +*> \verbatim +*> DN is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] DN1 +*> \verbatim +*> DN1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] DN2 +*> \verbatim +*> DN2 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] G +*> \verbatim +*> G is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in,out] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION +*> +*> These are passed as arguments in order to save their values +*> between calls to DLASQ3. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASQ3( I0, N0, Z, PP, DMIN, SIGMA, DESIG, QMAX, NFAIL, + $ ITER, NDIV, IEEE, TTYPE, DMIN1, DMIN2, DN, DN1, + $ DN2, G, TAU ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + LOGICAL IEEE + INTEGER I0, ITER, N0, NDIV, NFAIL, PP + DOUBLE PRECISION DESIG, DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, + $ QMAX, SIGMA, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION CBIAS + PARAMETER ( CBIAS = 1.50D0 ) + DOUBLE PRECISION ZERO, QURTR, HALF, ONE, TWO, HUNDRD + PARAMETER ( ZERO = 0.0D0, QURTR = 0.250D0, HALF = 0.5D0, + $ ONE = 1.0D0, TWO = 2.0D0, HUNDRD = 100.0D0 ) +* .. +* .. Local Scalars .. + INTEGER IPN4, J4, N0IN, NN, TTYPE + DOUBLE PRECISION EPS, S, T, TEMP, TOL, TOL2 +* .. +* .. External Subroutines .. + EXTERNAL DLASQ4, DLASQ5, DLASQ6 +* .. +* .. External Function .. + DOUBLE PRECISION DLAMCH + LOGICAL DISNAN + EXTERNAL DISNAN, DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + + N0IN = N0 + EPS = DLAMCH( 'Precision' ) + TOL = EPS*HUNDRD + TOL2 = TOL**2 +* +* Check for deflation. +* + 10 CONTINUE +* + IF( N0.LT.I0 ) + $ RETURN + IF( N0.EQ.I0 ) + $ GO TO 20 + NN = 4*N0 + PP + IF( N0.EQ.( I0+1 ) ) + $ GO TO 40 +* +* Check whether E(N0-1) is negligible, 1 eigenvalue. +* + IF( Z( NN-5 ).GT.TOL2*( SIGMA+Z( NN-3 ) ) .AND. + $ Z( NN-2*PP-4 ).GT.TOL2*Z( NN-7 ) ) + $ GO TO 30 +* + 20 CONTINUE +* + Z( 4*N0-3 ) = Z( 4*N0+PP-3 ) + SIGMA + N0 = N0 - 1 + GO TO 10 +* +* Check whether E(N0-2) is negligible, 2 eigenvalues. +* + 30 CONTINUE +* + IF( Z( NN-9 ).GT.TOL2*SIGMA .AND. + $ Z( NN-2*PP-8 ).GT.TOL2*Z( NN-11 ) ) + $ GO TO 50 +* + 40 CONTINUE +* + IF( Z( NN-3 ).GT.Z( NN-7 ) ) THEN + S = Z( NN-3 ) + Z( NN-3 ) = Z( NN-7 ) + Z( NN-7 ) = S + END IF + T = HALF*( ( Z( NN-7 )-Z( NN-3 ) )+Z( NN-5 ) ) + IF( Z( NN-5 ).GT.Z( NN-3 )*TOL2.AND.T.NE.ZERO ) THEN + S = Z( NN-3 )*( Z( NN-5 ) / T ) + IF( S.LE.T ) THEN + S = Z( NN-3 )*( Z( NN-5 ) / + $ ( T*( ONE+SQRT( ONE+S / T ) ) ) ) + ELSE + S = Z( NN-3 )*( Z( NN-5 ) / ( T+SQRT( T )*SQRT( T+S ) ) ) + END IF + T = Z( NN-7 ) + ( S+Z( NN-5 ) ) + Z( NN-3 ) = Z( NN-3 )*( Z( NN-7 ) / T ) + Z( NN-7 ) = T + END IF + Z( 4*N0-7 ) = Z( NN-7 ) + SIGMA + Z( 4*N0-3 ) = Z( NN-3 ) + SIGMA + N0 = N0 - 2 + GO TO 10 +* + 50 CONTINUE + IF( PP.EQ.2 ) + $ PP = 0 +* +* Reverse the qd-array, if warranted. +* + + IF( DMIN.LE.ZERO .OR. N0.LT.N0IN ) THEN + IF( CBIAS*Z( 4*I0+PP-3 ).LT.Z( 4*N0+PP-3 ) ) THEN + IPN4 = 4*( I0+N0 ) + DO 60 J4 = 4*I0, 2*( I0+N0-1 ), 4 + TEMP = Z( J4-3 ) + Z( J4-3 ) = Z( IPN4-J4-3 ) + Z( IPN4-J4-3 ) = TEMP + TEMP = Z( J4-2 ) + Z( J4-2 ) = Z( IPN4-J4-2 ) + Z( IPN4-J4-2 ) = TEMP + TEMP = Z( J4-1 ) + Z( J4-1 ) = Z( IPN4-J4-5 ) + Z( IPN4-J4-5 ) = TEMP + TEMP = Z( J4 ) + Z( J4 ) = Z( IPN4-J4-4 ) + Z( IPN4-J4-4 ) = TEMP + 60 CONTINUE + IF( N0-I0.LE.4 ) THEN + Z( 4*N0+PP-1 ) = Z( 4*I0+PP-1 ) + Z( 4*N0-PP ) = Z( 4*I0-PP ) + END IF + DMIN2 = MIN( DMIN2, Z( 4*N0+PP-1 ) ) + Z( 4*N0+PP-1 ) = MIN( Z( 4*N0+PP-1 ), Z( 4*I0+PP-1 ), + $ Z( 4*I0+PP+3 ) ) + Z( 4*N0-PP ) = MIN( Z( 4*N0-PP ), Z( 4*I0-PP ), + $ Z( 4*I0-PP+4 ) ) + QMAX = MAX( QMAX, Z( 4*I0+PP-3 ), Z( 4*I0+PP+1 ) ) + DMIN = -ZERO + END IF + END IF +* +* Choose a shift. +* + ! Print out DLASQ4 test cases + write(4,*) "{" + write(4,'(9999(g0))',advance="no") "z: []float64{" + do i = 1, NN + write (4,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (4,*) "}," + write (4,*) "i0: ", I0, "," + write (4,*) "n0: ", N0, "," + write (4,*) "pp: ", PP, "," + write (4,*) "n0in: ", N0IN, "," + write (4,*) "dmin: ", DMIN, "," + write (4,*) "dmin1:", DMIN1, "," + write (4,*) "dmin2:", DMIN2, "," + write (4,*) "dn: ", DN, "," + write (4,*) "dn1: ", DN1, "," + write (4,*) "dn2: ", DN2, "," + write (4,*) "tau: ", TAU, "," + write (4,*) "ttype: ", TTYPE, "," + write (4,*) "g: ", G, "," + CALL DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, DN1, + $ DN2, TAU, TTYPE, G ) + + write(4,'(9999(g0))',advance="no") "zOut: []float64{" + do i = 1, NN + write (4,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (4,*) "}," + write (4,*) "tauOut: ", TAU, "," + write (4,*) "ttypeOut: ", TTYPE, "," + write (4,*) "gOut: ", G, "," + write (4,*) "}," + +* +* Call dqds until DMIN > 0. +* + 70 CONTINUE +* + + write(5,*) "{" + write(5,'(9999(g0))',advance="no") "z: []float64{" + do i = 1, NN + write (5,'(99999(e24.16,a))',advance="no") z(i), "," + end do + write (5,*) "}," + write (5,*) "i0: ", I0, "," + write (5,*) "n0: ", N0, "," + write (5,*) "pp: ", PP, "," + write (5,*) "tau: ", TAU, "," + write (5,*) "sigma: ", SIGMA, "," + write (5,*) "dmin: ", DMIN, "," + write (5,*) "dmin1:", DMIN1, "," + write (5,*) "dmin2:", DMIN2, "," + write (5,*) "dn: ", DN, "," + write (5,*) "dnm1: ", DN1, "," + write (5,*) "dnm2: ", DN2, "," + + + CALL DLASQ5( I0, N0, Z, PP, TAU, SIGMA, DMIN, DMIN1, DMIN2, DN, + $ DN1, DN2, IEEE, EPS ) + + + + write (5,*) "i0Out: ", I0, "," + write (5,*) "n0Out: ", N0, "," + write (5,*) "ppOut: ", PP, "," + write (5,*) "tauOut: ", TAU, "," + write (5,*) "sigmaOut: ", SIGMA, "," + write (5,*) "dminOut: ", DMIN, "," + write (5,*) "dmin1Out:", DMIN1, "," + write (5,*) "dmin2Out:", DMIN2, "," + write (5,*) "dnOut: ", DN, "," + write (5,*) "dnm1Out: ", DN1, "," + write (5,*) "dnm2Out: ", DN2, "," + write (5,*) "}," + +* + NDIV = NDIV + ( N0-I0+2 ) + + ITER = ITER + 1 +* +* Check status. +* + + IF( DMIN.GE.ZERO .AND. DMIN1.GE.ZERO ) THEN +* +* Success. +* + GO TO 90 +* + ELSE IF( DMIN.LT.ZERO .AND. DMIN1.GT.ZERO .AND. + $ Z( 4*( N0-1 )-PP ).LT.TOL*( SIGMA+DN1 ) .AND. + $ ABS( DN ).LT.TOL*SIGMA ) THEN + +* +* Convergence hidden by negative DN. +* + Z( 4*( N0-1 )-PP+2 ) = ZERO + DMIN = ZERO + GO TO 90 + ELSE IF( DMIN.LT.ZERO ) THEN + +* +* TAU too big. Select new TAU and try again. +* + NFAIL = NFAIL + 1 + IF( TTYPE.LT.-22 ) THEN +* +* Failed twice. Play it safe. +* + TAU = ZERO + ELSE IF( DMIN1.GT.ZERO ) THEN +* +* Late failure. Gives excellent shift. +* + TAU = ( TAU+DMIN )*( ONE-TWO*EPS ) + TTYPE = TTYPE - 11 + ELSE +* +* Early failure. Divide by 4. +* + TAU = QURTR*TAU + TTYPE = TTYPE - 12 + END IF + GO TO 70 + ELSE IF( DISNAN( DMIN ) ) THEN +* +* NaN. +* + IF( TAU.EQ.ZERO ) THEN + GO TO 80 + ELSE + TAU = ZERO + GO TO 70 + END IF + ELSE +* +* Possible underflow. Play it safe. +* + GO TO 80 + END IF +* +* Risk of underflow. +* + 80 CONTINUE + + CALL DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, DN1, DN2 ) + + + NDIV = NDIV + ( N0-I0+2 ) + ITER = ITER + 1 + TAU = ZERO +* + 90 CONTINUE + + IF( TAU.LT.SIGMA ) THEN + DESIG = DESIG + TAU + T = SIGMA + DESIG + DESIG = DESIG - ( T-SIGMA ) + ELSE + T = SIGMA + TAU + DESIG = SIGMA - ( T-TAU ) + DESIG + END IF + SIGMA = T +* + RETURN +* +* End of DLASQ3 +* + END diff --git a/lapack/internal/testdata/dlasqtest/dlasq4.f b/lapack/internal/testdata/dlasqtest/dlasq4.f new file mode 100644 index 00000000..f60f775b --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlasq4.f @@ -0,0 +1,427 @@ +*> \brief \b DLASQ4 computes an approximation to the smallest eigenvalue using values of d from the previous transform. Used by sbdsqr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ4 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, +* DN1, DN2, TAU, TTYPE, G ) +* +* .. Scalar Arguments .. +* INTEGER I0, N0, N0IN, PP, TTYPE +* DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, TAU +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ4 computes an approximation TAU to the smallest eigenvalue +*> using values of d from the previous transform. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] I0 +*> \verbatim +*> I0 is INTEGER +*> First index. +*> \endverbatim +*> +*> \param[in] N0 +*> \verbatim +*> N0 is INTEGER +*> Last index. +*> \endverbatim +*> +*> \param[in] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> Z holds the qd array. +*> \endverbatim +*> +*> \param[in] PP +*> \verbatim +*> PP is INTEGER +*> PP=0 for ping, PP=1 for pong. +*> \endverbatim +*> +*> \param[in] N0IN +*> \verbatim +*> N0IN is INTEGER +*> The value of N0 at start of EIGTEST. +*> \endverbatim +*> +*> \param[in] DMIN +*> \verbatim +*> DMIN is DOUBLE PRECISION +*> Minimum value of d. +*> \endverbatim +*> +*> \param[in] DMIN1 +*> \verbatim +*> DMIN1 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ). +*> \endverbatim +*> +*> \param[in] DMIN2 +*> \verbatim +*> DMIN2 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ) and D( N0-1 ). +*> \endverbatim +*> +*> \param[in] DN +*> \verbatim +*> DN is DOUBLE PRECISION +*> d(N) +*> \endverbatim +*> +*> \param[in] DN1 +*> \verbatim +*> DN1 is DOUBLE PRECISION +*> d(N-1) +*> \endverbatim +*> +*> \param[in] DN2 +*> \verbatim +*> DN2 is DOUBLE PRECISION +*> d(N-2) +*> \endverbatim +*> +*> \param[out] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION +*> This is the shift. +*> \endverbatim +*> +*> \param[out] TTYPE +*> \verbatim +*> TTYPE is INTEGER +*> Shift type. +*> \endverbatim +*> +*> \param[in,out] G +*> \verbatim +*> G is REAL +*> G is passed as an argument in order to save its value between +*> calls to DLASQ4. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> CNST1 = 9/16 +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DLASQ4( I0, N0, Z, PP, N0IN, DMIN, DMIN1, DMIN2, DN, + $ DN1, DN2, TAU, TTYPE, G ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER I0, N0, N0IN, PP, TTYPE + DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DN1, DN2, G, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION CNST1, CNST2, CNST3 + PARAMETER ( CNST1 = 0.5630D0, CNST2 = 1.010D0, + $ CNST3 = 1.050D0 ) + DOUBLE PRECISION QURTR, THIRD, HALF, ZERO, ONE, TWO, HUNDRD + PARAMETER ( QURTR = 0.250D0, THIRD = 0.3330D0, + $ HALF = 0.50D0, ZERO = 0.0D0, ONE = 1.0D0, + $ TWO = 2.0D0, HUNDRD = 100.0D0 ) +* .. +* .. Local Scalars .. + INTEGER I4, NN, NP + DOUBLE PRECISION A2, B1, B2, GAM, GAP1, GAP2, S +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* +* A negative DMIN forces the shift to take that absolute value +* TTYPE records the type of shift. +* + + IF( DMIN.LE.ZERO ) THEN + TAU = -DMIN + TTYPE = -1 + RETURN + END IF +* + NN = 4*N0 + PP + IF( N0IN.EQ.N0 ) THEN +* +* No eigenvalues deflated. +* + IF( DMIN.EQ.DN .OR. DMIN.EQ.DN1 ) THEN +* + B1 = SQRT( Z( NN-3 ) )*SQRT( Z( NN-5 ) ) + B2 = SQRT( Z( NN-7 ) )*SQRT( Z( NN-9 ) ) + A2 = Z( NN-7 ) + Z( NN-5 ) +* +* Cases 2 and 3. +* + IF( DMIN.EQ.DN .AND. DMIN1.EQ.DN1 ) THEN + + GAP2 = DMIN2 - A2 - DMIN2*QURTR + IF( GAP2.GT.ZERO .AND. GAP2.GT.B2 ) THEN + GAP1 = A2 - DN - ( B2 / GAP2 )*B2 + ELSE + GAP1 = A2 - DN - ( B1+B2 ) + END IF + IF( GAP1.GT.ZERO .AND. GAP1.GT.B1 ) THEN + S = MAX( DN-( B1 / GAP1 )*B1, HALF*DMIN ) + TTYPE = -2 + ELSE + S = ZERO + IF( DN.GT.B1 ) + $ S = DN - B1 + IF( A2.GT.( B1+B2 ) ) + $ S = MIN( S, A2-( B1+B2 ) ) + S = MAX( S, THIRD*DMIN ) + TTYPE = -3 + END IF + ELSE +* +* Case 4. +* + TTYPE = -4 + S = QURTR*DMIN + IF( DMIN.EQ.DN ) THEN + GAM = DN + A2 = ZERO + IF( Z( NN-5 ) .GT. Z( NN-7 ) ) + $ RETURN + B2 = Z( NN-5 ) / Z( NN-7 ) + NP = NN - 9 + ELSE + NP = NN - 2*PP + B2 = Z( NP-2 ) + GAM = DN1 + IF( Z( NP-4 ) .GT. Z( NP-2 ) ) + $ RETURN + A2 = Z( NP-4 ) / Z( NP-2 ) + IF( Z( NN-9 ) .GT. Z( NN-11 ) ) + $ RETURN + B2 = Z( NN-9 ) / Z( NN-11 ) + NP = NN - 13 + END IF +* +* Approximate contribution to norm squared from I < NN-1. +* + A2 = A2 + B2 + DO 10 I4 = NP, 4*I0 - 1 + PP, -4 + IF( B2.EQ.ZERO ) + $ GO TO 20 + B1 = B2 + IF( Z( I4 ) .GT. Z( I4-2 ) ) + $ RETURN + B2 = B2*( Z( I4 ) / Z( I4-2 ) ) + A2 = A2 + B2 + IF( HUNDRD*MAX( B2, B1 ).LT.A2 .OR. CNST1.LT.A2 ) + $ GO TO 20 + 10 CONTINUE + 20 CONTINUE + A2 = CNST3*A2 +* +* Rayleigh quotient residual bound. +* + IF( A2.LT.CNST1 ) + $ S = GAM*( ONE-SQRT( A2 ) ) / ( ONE+A2 ) + END IF + ELSE IF( DMIN.EQ.DN2 ) THEN +* +* Case 5. +* + TTYPE = -5 + S = QURTR*DMIN +* +* Compute contribution to norm squared from I > NN-2. +* + NP = NN - 2*PP + B1 = Z( NP-2 ) + B2 = Z( NP-6 ) + GAM = DN2 + IF( Z( NP-8 ).GT.B2 .OR. Z( NP-4 ).GT.B1 ) + $ RETURN + A2 = ( Z( NP-8 ) / B2 )*( ONE+Z( NP-4 ) / B1 ) +* +* Approximate contribution to norm squared from I < NN-2. +* + IF( N0-I0.GT.2 ) THEN + B2 = Z( NN-13 ) / Z( NN-15 ) + A2 = A2 + B2 + DO 30 I4 = NN - 17, 4*I0 - 1 + PP, -4 + IF( B2.EQ.ZERO ) + $ GO TO 40 + B1 = B2 + IF( Z( I4 ) .GT. Z( I4-2 ) ) + $ RETURN + B2 = B2*( Z( I4 ) / Z( I4-2 ) ) + A2 = A2 + B2 + IF( HUNDRD*MAX( B2, B1 ).LT.A2 .OR. CNST1.LT.A2 ) + $ GO TO 40 + 30 CONTINUE + 40 CONTINUE + A2 = CNST3*A2 + END IF +* + IF( A2.LT.CNST1 ) + $ S = GAM*( ONE-SQRT( A2 ) ) / ( ONE+A2 ) + ELSE +* +* Case 6, no information to guide us. +* + IF( TTYPE.EQ.-6 ) THEN + G = G + THIRD*( ONE-G ) + ELSE IF( TTYPE.EQ.-18 ) THEN + G = QURTR*THIRD + ELSE + G = QURTR + END IF + S = G*DMIN + TTYPE = -6 + END IF +* + ELSE IF( N0IN.EQ.( N0+1 ) ) THEN +* +* One eigenvalue just deflated. Use DMIN1, DN1 for DMIN and DN. +* + IF( DMIN1.EQ.DN1 .AND. DMIN2.EQ.DN2 ) THEN +* +* Cases 7 and 8. +* + TTYPE = -7 + S = THIRD*DMIN1 + IF( Z( NN-5 ).GT.Z( NN-7 ) ) + $ RETURN + B1 = Z( NN-5 ) / Z( NN-7 ) + B2 = B1 + IF( B2.EQ.ZERO ) + $ GO TO 60 + DO 50 I4 = 4*N0 - 9 + PP, 4*I0 - 1 + PP, -4 + A2 = B1 + IF( Z( I4 ).GT.Z( I4-2 ) ) + $ RETURN + B1 = B1*( Z( I4 ) / Z( I4-2 ) ) + B2 = B2 + B1 + IF( HUNDRD*MAX( B1, A2 ).LT.B2 ) + $ GO TO 60 + 50 CONTINUE + 60 CONTINUE + B2 = SQRT( CNST3*B2 ) + A2 = DMIN1 / ( ONE+B2**2 ) + GAP2 = HALF*DMIN2 - A2 + IF( GAP2.GT.ZERO .AND. GAP2.GT.B2*A2 ) THEN + S = MAX( S, A2*( ONE-CNST2*A2*( B2 / GAP2 )*B2 ) ) + ELSE + S = MAX( S, A2*( ONE-CNST2*B2 ) ) + TTYPE = -8 + END IF + ELSE +* +* Case 9. +* + S = QURTR*DMIN1 + IF( DMIN1.EQ.DN1 ) + $ S = HALF*DMIN1 + TTYPE = -9 + END IF +* + ELSE IF( N0IN.EQ.( N0+2 ) ) THEN +* +* Two eigenvalues deflated. Use DMIN2, DN2 for DMIN and DN. +* +* Cases 10 and 11. +* + IF( DMIN2.EQ.DN2 .AND. TWO*Z( NN-5 ).LT.Z( NN-7 ) ) THEN + TTYPE = -10 + S = THIRD*DMIN2 + IF( Z( NN-5 ).GT.Z( NN-7 ) ) + $ RETURN + B1 = Z( NN-5 ) / Z( NN-7 ) + B2 = B1 + IF( B2.EQ.ZERO ) + $ GO TO 80 + DO 70 I4 = 4*N0 - 9 + PP, 4*I0 - 1 + PP, -4 + IF( Z( I4 ).GT.Z( I4-2 ) ) + $ RETURN + B1 = B1*( Z( I4 ) / Z( I4-2 ) ) + B2 = B2 + B1 + IF( HUNDRD*B1.LT.B2 ) + $ GO TO 80 + 70 CONTINUE + 80 CONTINUE + B2 = SQRT( CNST3*B2 ) + A2 = DMIN2 / ( ONE+B2**2 ) + GAP2 = Z( NN-7 ) + Z( NN-9 ) - + $ SQRT( Z( NN-11 ) )*SQRT( Z( NN-9 ) ) - A2 + IF( GAP2.GT.ZERO .AND. GAP2.GT.B2*A2 ) THEN + S = MAX( S, A2*( ONE-CNST2*A2*( B2 / GAP2 )*B2 ) ) + ELSE + S = MAX( S, A2*( ONE-CNST2*B2 ) ) + END IF + ELSE + S = QURTR*DMIN2 + TTYPE = -11 + END IF + ELSE IF( N0IN.GT.( N0+2 ) ) THEN +* +* Case 12, more than two eigenvalues deflated. No information. +* + S = ZERO + TTYPE = -12 + END IF +* + TAU = S + RETURN +* +* End of DLASQ4 +* + END diff --git a/lapack/internal/testdata/dlasqtest/dlasq5.f b/lapack/internal/testdata/dlasqtest/dlasq5.f new file mode 100644 index 00000000..19470447 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlasq5.f @@ -0,0 +1,413 @@ +*> \brief \b DLASQ5 computes one dqds transform in ping-pong form. Used by sbdsqr and sstegr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ5 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ5( I0, N0, Z, PP, TAU, SIGMA, DMIN, DMIN1, DMIN2, DN, +* DNM1, DNM2, IEEE, EPS ) +* +* .. Scalar Arguments .. +* LOGICAL IEEE +* INTEGER I0, N0, PP +* DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2, TAU, SIGMA, EPS +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ5 computes one dqds transform in ping-pong form, one +*> version for IEEE machines another for non IEEE machines. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] I0 +*> \verbatim +*> I0 is INTEGER +*> First index. +*> \endverbatim +*> +*> \param[in] N0 +*> \verbatim +*> N0 is INTEGER +*> Last index. +*> \endverbatim +*> +*> \param[in] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> Z holds the qd array. EMIN is stored in Z(4*N0) to avoid +*> an extra argument. +*> \endverbatim +*> +*> \param[in] PP +*> \verbatim +*> PP is INTEGER +*> PP=0 for ping, PP=1 for pong. +*> \endverbatim +*> +*> \param[in] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION +*> This is the shift. +*> \endverbatim +*> +*> \param[in] SIGMA +*> \verbatim +*> SIGMA is DOUBLE PRECISION +*> This is the accumulated shift up to this step. +*> \endverbatim +*> +*> \param[out] DMIN +*> \verbatim +*> DMIN is DOUBLE PRECISION +*> Minimum value of d. +*> \endverbatim +*> +*> \param[out] DMIN1 +*> \verbatim +*> DMIN1 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ). +*> \endverbatim +*> +*> \param[out] DMIN2 +*> \verbatim +*> DMIN2 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ) and D( N0-1 ). +*> \endverbatim +*> +*> \param[out] DN +*> \verbatim +*> DN is DOUBLE PRECISION +*> d(N0), the last value of d. +*> \endverbatim +*> +*> \param[out] DNM1 +*> \verbatim +*> DNM1 is DOUBLE PRECISION +*> d(N0-1). +*> \endverbatim +*> +*> \param[out] DNM2 +*> \verbatim +*> DNM2 is DOUBLE PRECISION +*> d(N0-2). +*> \endverbatim +*> +*> \param[in] IEEE +*> \verbatim +*> IEEE is LOGICAL +*> Flag for IEEE or non IEEE arithmetic. +*> \endverbatim +* +*> \param[in] EPS +*> \verbatim +*> EPS is DOUBLE PRECISION +*> This is the value of epsilon used. +*> \endverbatim +*> +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASQ5( I0, N0, Z, PP, TAU, SIGMA, DMIN, DMIN1, DMIN2, + $ DN, DNM1, DNM2, IEEE, EPS ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + LOGICAL IEEE + INTEGER I0, N0, PP + DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2, TAU, + $ SIGMA, EPS +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameter .. + DOUBLE PRECISION ZERO, HALF + PARAMETER ( ZERO = 0.0D0, HALF = 0.5 ) +* .. +* .. Local Scalars .. + INTEGER J4, J4P2 + DOUBLE PRECISION D, EMIN, TEMP, DTHRESH +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + + IF( ( N0-I0-1 ).LE.0 ) + $ RETURN +* + DTHRESH = EPS*(SIGMA+TAU) + IF( TAU.LT.DTHRESH*HALF ) TAU = ZERO + IF( TAU.NE.ZERO ) THEN + J4 = 4*I0 + PP - 3 + EMIN = Z( J4+4 ) + D = Z( J4 ) - TAU + DMIN = D + DMIN1 = -Z( J4 ) +* + IF( IEEE ) THEN +* +* Code for IEEE arithmetic. +* + IF( PP.EQ.0 ) THEN + DO 10 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + TEMP = Z( J4+1 ) / Z( J4-2 ) + D = D*TEMP - TAU + DMIN = MIN( DMIN, D ) + Z( J4 ) = Z( J4-1 )*TEMP + EMIN = MIN( Z( J4 ), EMIN ) + 10 CONTINUE + ELSE + DO 20 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + TEMP = Z( J4+2 ) / Z( J4-3 ) + D = D*TEMP - TAU + DMIN = MIN( DMIN, D ) + Z( J4-1 ) = Z( J4 )*TEMP + EMIN = MIN( Z( J4-1 ), EMIN ) + 20 CONTINUE + END IF + +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DN ) +* + ELSE +* +* Code for non IEEE arithmetic. +* + IF( PP.EQ.0 ) THEN + DO 30 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4+1 )*( Z( J4-1 ) / Z( J4-2 ) ) + D = Z( J4+1 )*( D / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4 ) ) + 30 CONTINUE + ELSE + DO 40 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4-1 ) = Z( J4+2 )*( Z( J4 ) / Z( J4-3 ) ) + D = Z( J4+2 )*( D / Z( J4-3 ) ) - TAU + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4-1 ) ) + 40 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + IF( DNM2.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + IF( DNM1.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DN ) +* + END IF + ELSE +* This is the version that sets d's to zero if they are small enough + J4 = 4*I0 + PP - 3 + EMIN = Z( J4+4 ) + D = Z( J4 ) - TAU + DMIN = D + DMIN1 = -Z( J4 ) + IF( IEEE ) THEN +* +* Code for IEEE arithmetic. +* + + IF( PP.EQ.0 ) THEN + DO 50 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + TEMP = Z( J4+1 ) / Z( J4-2 ) + D = D*TEMP - TAU + IF( D.LT.DTHRESH ) D = ZERO + DMIN = MIN( DMIN, D ) + Z( J4 ) = Z( J4-1 )*TEMP + EMIN = MIN( Z( J4 ), EMIN ) + 50 CONTINUE + ELSE + DO 60 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + TEMP = Z( J4+2 ) / Z( J4-3 ) + D = D*TEMP - TAU + IF( D.LT.DTHRESH ) D = ZERO + DMIN = MIN( DMIN, D ) + Z( J4-1 ) = Z( J4 )*TEMP + EMIN = MIN( Z( J4-1 ), EMIN ) + 60 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + DMIN = MIN( DMIN, DN ) +* + ELSE +* +* Code for non IEEE arithmetic. +* + IF( PP.EQ.0 ) THEN + DO 70 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4+1 )*( Z( J4-1 ) / Z( J4-2 ) ) + D = Z( J4+1 )*( D / Z( J4-2 ) ) - TAU + END IF + IF( D.LT.DTHRESH) D = ZERO + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4 ) ) + 70 CONTINUE + ELSE + DO 80 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + IF( D.LT.ZERO ) THEN + RETURN + ELSE + Z( J4-1 ) = Z( J4+2 )*( Z( J4 ) / Z( J4-3 ) ) + D = Z( J4+2 )*( D / Z( J4-3 ) ) - TAU + END IF + IF( D.LT.DTHRESH) D = ZERO + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4-1 ) ) + 80 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + IF( DNM2.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + IF( DNM1.LT.ZERO ) THEN + RETURN + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) - TAU + END IF + DMIN = MIN( DMIN, DN ) +* + END IF + END IF +* + Z( J4+2 ) = DN + Z( 4*N0-PP ) = EMIN + RETURN +* +* End of DLASQ5 +* + END diff --git a/lapack/internal/testdata/dlasqtest/dlasq6.f b/lapack/internal/testdata/dlasqtest/dlasq6.f new file mode 100644 index 00000000..bcd61f35 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlasq6.f @@ -0,0 +1,258 @@ +*> \brief \b DLASQ6 computes one dqd transform in ping-pong form. Used by sbdsqr and sstegr. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASQ6 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, +* DNM1, DNM2 ) +* +* .. Scalar Arguments .. +* INTEGER I0, N0, PP +* DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2 +* .. +* .. Array Arguments .. +* DOUBLE PRECISION Z( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASQ6 computes one dqd (shift equal to zero) transform in +*> ping-pong form, with protection against underflow and overflow. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] I0 +*> \verbatim +*> I0 is INTEGER +*> First index. +*> \endverbatim +*> +*> \param[in] N0 +*> \verbatim +*> N0 is INTEGER +*> Last index. +*> \endverbatim +*> +*> \param[in] Z +*> \verbatim +*> Z is DOUBLE PRECISION array, dimension ( 4*N ) +*> Z holds the qd array. EMIN is stored in Z(4*N0) to avoid +*> an extra argument. +*> \endverbatim +*> +*> \param[in] PP +*> \verbatim +*> PP is INTEGER +*> PP=0 for ping, PP=1 for pong. +*> \endverbatim +*> +*> \param[out] DMIN +*> \verbatim +*> DMIN is DOUBLE PRECISION +*> Minimum value of d. +*> \endverbatim +*> +*> \param[out] DMIN1 +*> \verbatim +*> DMIN1 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ). +*> \endverbatim +*> +*> \param[out] DMIN2 +*> \verbatim +*> DMIN2 is DOUBLE PRECISION +*> Minimum value of d, excluding D( N0 ) and D( N0-1 ). +*> \endverbatim +*> +*> \param[out] DN +*> \verbatim +*> DN is DOUBLE PRECISION +*> d(N0), the last value of d. +*> \endverbatim +*> +*> \param[out] DNM1 +*> \verbatim +*> DNM1 is DOUBLE PRECISION +*> d(N0-1). +*> \endverbatim +*> +*> \param[out] DNM2 +*> \verbatim +*> DNM2 is DOUBLE PRECISION +*> d(N0-2). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASQ6( I0, N0, Z, PP, DMIN, DMIN1, DMIN2, DN, + $ DNM1, DNM2 ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER I0, N0, PP + DOUBLE PRECISION DMIN, DMIN1, DMIN2, DN, DNM1, DNM2 +* .. +* .. Array Arguments .. + DOUBLE PRECISION Z( * ) +* .. +* +* ===================================================================== +* +* .. Parameter .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) +* .. +* .. Local Scalars .. + INTEGER J4, J4P2 + DOUBLE PRECISION D, EMIN, SAFMIN, TEMP +* .. +* .. External Function .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( ( N0-I0-1 ).LE.0 ) + $ RETURN +* + + print *, "In dlasq6" + STOP + + SAFMIN = DLAMCH( 'Safe minimum' ) + J4 = 4*I0 + PP - 3 + EMIN = Z( J4+4 ) + D = Z( J4 ) + DMIN = D +* + IF( PP.EQ.0 ) THEN + DO 10 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-2 ) = D + Z( J4-1 ) + IF( Z( J4-2 ).EQ.ZERO ) THEN + Z( J4 ) = ZERO + D = Z( J4+1 ) + DMIN = D + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4+1 ).LT.Z( J4-2 ) .AND. + $ SAFMIN*Z( J4-2 ).LT.Z( J4+1 ) ) THEN + TEMP = Z( J4+1 ) / Z( J4-2 ) + Z( J4 ) = Z( J4-1 )*TEMP + D = D*TEMP + ELSE + Z( J4 ) = Z( J4+1 )*( Z( J4-1 ) / Z( J4-2 ) ) + D = Z( J4+1 )*( D / Z( J4-2 ) ) + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4 ) ) + 10 CONTINUE + ELSE + DO 20 J4 = 4*I0, 4*( N0-3 ), 4 + Z( J4-3 ) = D + Z( J4 ) + IF( Z( J4-3 ).EQ.ZERO ) THEN + Z( J4-1 ) = ZERO + D = Z( J4+2 ) + DMIN = D + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4+2 ).LT.Z( J4-3 ) .AND. + $ SAFMIN*Z( J4-3 ).LT.Z( J4+2 ) ) THEN + TEMP = Z( J4+2 ) / Z( J4-3 ) + Z( J4-1 ) = Z( J4 )*TEMP + D = D*TEMP + ELSE + Z( J4-1 ) = Z( J4+2 )*( Z( J4 ) / Z( J4-3 ) ) + D = Z( J4+2 )*( D / Z( J4-3 ) ) + END IF + DMIN = MIN( DMIN, D ) + EMIN = MIN( EMIN, Z( J4-1 ) ) + 20 CONTINUE + END IF +* +* Unroll last two steps. +* + DNM2 = D + DMIN2 = DMIN + J4 = 4*( N0-2 ) - PP + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM2 + Z( J4P2 ) + IF( Z( J4-2 ).EQ.ZERO ) THEN + Z( J4 ) = ZERO + DNM1 = Z( J4P2+2 ) + DMIN = DNM1 + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4P2+2 ).LT.Z( J4-2 ) .AND. + $ SAFMIN*Z( J4-2 ).LT.Z( J4P2+2 ) ) THEN + TEMP = Z( J4P2+2 ) / Z( J4-2 ) + Z( J4 ) = Z( J4P2 )*TEMP + DNM1 = DNM2*TEMP + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DNM1 = Z( J4P2+2 )*( DNM2 / Z( J4-2 ) ) + END IF + DMIN = MIN( DMIN, DNM1 ) +* + DMIN1 = DMIN + J4 = J4 + 4 + J4P2 = J4 + 2*PP - 1 + Z( J4-2 ) = DNM1 + Z( J4P2 ) + IF( Z( J4-2 ).EQ.ZERO ) THEN + Z( J4 ) = ZERO + DN = Z( J4P2+2 ) + DMIN = DN + EMIN = ZERO + ELSE IF( SAFMIN*Z( J4P2+2 ).LT.Z( J4-2 ) .AND. + $ SAFMIN*Z( J4-2 ).LT.Z( J4P2+2 ) ) THEN + TEMP = Z( J4P2+2 ) / Z( J4-2 ) + Z( J4 ) = Z( J4P2 )*TEMP + DN = DNM1*TEMP + ELSE + Z( J4 ) = Z( J4P2+2 )*( Z( J4P2 ) / Z( J4-2 ) ) + DN = Z( J4P2+2 )*( DNM1 / Z( J4-2 ) ) + END IF + DMIN = MIN( DMIN, DN ) +* + Z( J4+2 ) = DN + Z( 4*N0-PP ) = EMIN + RETURN +* +* End of DLASQ6 +* + END diff --git a/lapack/internal/testdata/dlasqtest/dlasrt.f b/lapack/internal/testdata/dlasqtest/dlasrt.f new file mode 100644 index 00000000..f5d0e6cd --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/dlasrt.f @@ -0,0 +1,303 @@ +*> \brief \b DLASRT sorts numbers in increasing or decreasing order. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASRT + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASRT( ID, N, D, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER ID +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> Sort the numbers in D in increasing order (if ID = 'I') or +*> in decreasing order (if ID = 'D' ). +*> +*> Use Quick Sort, reverting to Insertion sort on arrays of +*> size <= 20. Dimension of STACK limits N to about 2**32. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ID +*> \verbatim +*> ID is CHARACTER*1 +*> = 'I': sort D in increasing order; +*> = 'D': sort D in decreasing order. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The length of the array D. +*> \endverbatim +*> +*> \param[in,out] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> On entry, the array to be sorted. +*> On exit, D has been sorted into increasing order +*> (D(1) <= ... <= D(N) ) or into decreasing order +*> (D(1) >= ... >= D(N) ), depending on ID. +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASRT( ID, N, D, INFO ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER ID + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + INTEGER SELECT + PARAMETER ( SELECT = 20 ) +* .. +* .. Local Scalars .. + INTEGER DIR, ENDD, I, J, START, STKPNT + DOUBLE PRECISION D1, D2, D3, DMNMX, TMP +* .. +* .. Local Arrays .. + INTEGER STACK( 2, 32 ) +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input paramters. +* + INFO = 0 + DIR = -1 + IF( LSAME( ID, 'D' ) ) THEN + DIR = 0 + ELSE IF( LSAME( ID, 'I' ) ) THEN + DIR = 1 + END IF + IF( DIR.EQ.-1 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASRT', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + STKPNT = 1 + STACK( 1, 1 ) = 1 + STACK( 2, 1 ) = N + 10 CONTINUE + START = STACK( 1, STKPNT ) + ENDD = STACK( 2, STKPNT ) + STKPNT = STKPNT - 1 + IF( ENDD-START.LE.SELECT .AND. ENDD-START.GT.0 ) THEN +* +* Do Insertion sort on D( START:ENDD ) +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + DO 30 I = START + 1, ENDD + DO 20 J = I, START + 1, -1 + IF( D( J ).GT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 30 + END IF + 20 CONTINUE + 30 CONTINUE +* + ELSE +* +* Sort into increasing order +* + DO 50 I = START + 1, ENDD + DO 40 J = I, START + 1, -1 + IF( D( J ).LT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 50 + END IF + 40 CONTINUE + 50 CONTINUE +* + END IF +* + ELSE IF( ENDD-START.GT.SELECT ) THEN +* +* Partition D( START:ENDD ) and stack parts, largest one first +* +* Choose partition entry as median of 3 +* + D1 = D( START ) + D2 = D( ENDD ) + I = ( START+ENDD ) / 2 + D3 = D( I ) + IF( D1.LT.D2 ) THEN + IF( D3.LT.D1 ) THEN + DMNMX = D1 + ELSE IF( D3.LT.D2 ) THEN + DMNMX = D3 + ELSE + DMNMX = D2 + END IF + ELSE + IF( D3.LT.D2 ) THEN + DMNMX = D2 + ELSE IF( D3.LT.D1 ) THEN + DMNMX = D3 + ELSE + DMNMX = D1 + END IF + END IF +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + I = START - 1 + J = ENDD + 1 + 60 CONTINUE + 70 CONTINUE + J = J - 1 + IF( D( J ).LT.DMNMX ) + $ GO TO 70 + 80 CONTINUE + I = I + 1 + IF( D( I ).GT.DMNMX ) + $ GO TO 80 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 60 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + ELSE +* +* Sort into increasing order +* + I = START - 1 + J = ENDD + 1 + 90 CONTINUE + 100 CONTINUE + J = J - 1 + IF( D( J ).GT.DMNMX ) + $ GO TO 100 + 110 CONTINUE + I = I + 1 + IF( D( I ).LT.DMNMX ) + $ GO TO 110 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 90 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + END IF + END IF + IF( STKPNT.GT.0 ) + $ GO TO 10 + RETURN +* +* End of DLASRT +* + END diff --git a/lapack/internal/testdata/dlasqtest/ieeeck.f b/lapack/internal/testdata/dlasqtest/ieeeck.f new file mode 100644 index 00000000..132e4367 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/ieeeck.f @@ -0,0 +1,203 @@ +*> \brief \b IEEECK +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download IEEECK + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION IEEECK( ISPEC, ZERO, ONE ) +* +* .. Scalar Arguments .. +* INTEGER ISPEC +* REAL ONE, ZERO +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> IEEECK is called from the ILAENV to verify that Infinity and +*> possibly NaN arithmetic is safe (i.e. will not trap). +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ISPEC +*> \verbatim +*> ISPEC is INTEGER +*> Specifies whether to test just for inifinity arithmetic +*> or whether to test for infinity and NaN arithmetic. +*> = 0: Verify infinity arithmetic only. +*> = 1: Verify infinity and NaN arithmetic. +*> \endverbatim +*> +*> \param[in] ZERO +*> \verbatim +*> ZERO is REAL +*> Must contain the value 0.0 +*> This is passed to prevent the compiler from optimizing +*> away this code. +*> \endverbatim +*> +*> \param[in] ONE +*> \verbatim +*> ONE is REAL +*> Must contain the value 1.0 +*> This is passed to prevent the compiler from optimizing +*> away this code. +*> +*> RETURN VALUE: INTEGER +*> = 0: Arithmetic failed to produce the correct answers +*> = 1: Arithmetic produced the correct answers +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + INTEGER FUNCTION IEEECK( ISPEC, ZERO, ONE ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER ISPEC + REAL ONE, ZERO +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + REAL NAN1, NAN2, NAN3, NAN4, NAN5, NAN6, NEGINF, + $ NEGZRO, NEWZRO, POSINF +* .. +* .. Executable Statements .. + IEEECK = 1 +* + POSINF = ONE / ZERO + IF( POSINF.LE.ONE ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGINF = -ONE / ZERO + IF( NEGINF.GE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGZRO = ONE / ( NEGINF+ONE ) + IF( NEGZRO.NE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGINF = ONE / NEGZRO + IF( NEGINF.GE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + NEWZRO = NEGZRO + ZERO + IF( NEWZRO.NE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + POSINF = ONE / NEWZRO + IF( POSINF.LE.ONE ) THEN + IEEECK = 0 + RETURN + END IF +* + NEGINF = NEGINF*POSINF + IF( NEGINF.GE.ZERO ) THEN + IEEECK = 0 + RETURN + END IF +* + POSINF = POSINF*POSINF + IF( POSINF.LE.ONE ) THEN + IEEECK = 0 + RETURN + END IF +* +* +* +* +* Return if we were only asked to check infinity arithmetic +* + IF( ISPEC.EQ.0 ) + $ RETURN +* + NAN1 = POSINF + NEGINF +* + NAN2 = POSINF / NEGINF +* + NAN3 = POSINF / POSINF +* + NAN4 = POSINF*ZERO +* + NAN5 = NEGINF*NEGZRO +* + NAN6 = NAN5*ZERO +* + IF( NAN1.EQ.NAN1 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN2.EQ.NAN2 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN3.EQ.NAN3 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN4.EQ.NAN4 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN5.EQ.NAN5 ) THEN + IEEECK = 0 + RETURN + END IF +* + IF( NAN6.EQ.NAN6 ) THEN + IEEECK = 0 + RETURN + END IF +* + RETURN + END diff --git a/lapack/internal/testdata/dlasqtest/ilaenv.f b/lapack/internal/testdata/dlasqtest/ilaenv.f new file mode 100644 index 00000000..867464de --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/ilaenv.f @@ -0,0 +1,624 @@ +*> \brief \b ILAENV +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download ILAENV + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) +* +* .. Scalar Arguments .. +* CHARACTER*( * ) NAME, OPTS +* INTEGER ISPEC, N1, N2, N3, N4 +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> ILAENV is called from the LAPACK routines to choose problem-dependent +*> parameters for the local environment. See ISPEC for a description of +*> the parameters. +*> +*> ILAENV returns an INTEGER +*> if ILAENV >= 0: ILAENV returns the value of the parameter specified by ISPEC +*> if ILAENV < 0: if ILAENV = -k, the k-th argument had an illegal value. +*> +*> This version provides a set of parameters which should give good, +*> but not optimal, performance on many of the currently available +*> computers. Users are encouraged to modify this subroutine to set +*> the tuning parameters for their particular machine using the option +*> and problem size information in the arguments. +*> +*> This routine will not function correctly if it is converted to all +*> lower case. Converting it to all upper case is allowed. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ISPEC +*> \verbatim +*> ISPEC is INTEGER +*> Specifies the parameter to be returned as the value of +*> ILAENV. +*> = 1: the optimal blocksize; if this value is 1, an unblocked +*> algorithm will give the best performance. +*> = 2: the minimum block size for which the block routine +*> should be used; if the usable block size is less than +*> this value, an unblocked routine should be used. +*> = 3: the crossover point (in a block routine, for N less +*> than this value, an unblocked routine should be used) +*> = 4: the number of shifts, used in the nonsymmetric +*> eigenvalue routines (DEPRECATED) +*> = 5: the minimum column dimension for blocking to be used; +*> rectangular blocks must have dimension at least k by m, +*> where k is given by ILAENV(2,...) and m by ILAENV(5,...) +*> = 6: the crossover point for the SVD (when reducing an m by n +*> matrix to bidiagonal form, if max(m,n)/min(m,n) exceeds +*> this value, a QR factorization is used first to reduce +*> the matrix to a triangular form.) +*> = 7: the number of processors +*> = 8: the crossover point for the multishift QR method +*> for nonsymmetric eigenvalue problems (DEPRECATED) +*> = 9: maximum size of the subproblems at the bottom of the +*> computation tree in the divide-and-conquer algorithm +*> (used by xGELSD and xGESDD) +*> =10: ieee NaN arithmetic can be trusted not to trap +*> =11: infinity arithmetic can be trusted not to trap +*> 12 <= ISPEC <= 16: +*> xHSEQR or one of its subroutines, +*> see IPARMQ for detailed explanation +*> \endverbatim +*> +*> \param[in] NAME +*> \verbatim +*> NAME is CHARACTER*(*) +*> The name of the calling subroutine, in either upper case or +*> lower case. +*> \endverbatim +*> +*> \param[in] OPTS +*> \verbatim +*> OPTS is CHARACTER*(*) +*> The character options to the subroutine NAME, concatenated +*> into a single character string. For example, UPLO = 'U', +*> TRANS = 'T', and DIAG = 'N' for a triangular routine would +*> be specified as OPTS = 'UTN'. +*> \endverbatim +*> +*> \param[in] N1 +*> \verbatim +*> N1 is INTEGER +*> \endverbatim +*> +*> \param[in] N2 +*> \verbatim +*> N2 is INTEGER +*> \endverbatim +*> +*> \param[in] N3 +*> \verbatim +*> N3 is INTEGER +*> \endverbatim +*> +*> \param[in] N4 +*> \verbatim +*> N4 is INTEGER +*> Problem dimensions for the subroutine NAME; these may not all +*> be required. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> The following conventions have been used when calling ILAENV from the +*> LAPACK routines: +*> 1) OPTS is a concatenation of all of the character options to +*> subroutine NAME, in the same order that they appear in the +*> argument list for NAME, even if they are not used in determining +*> the value of the parameter specified by ISPEC. +*> 2) The problem dimensions N1, N2, N3, N4 are specified in the order +*> that they appear in the argument list for NAME. N1 is used +*> first, N2 second, and so on, and unused problem dimensions are +*> passed a value of -1. +*> 3) The parameter value returned by ILAENV is checked for validity in +*> the calling subroutine. For example, ILAENV is used to retrieve +*> the optimal blocksize for STRTRI as follows: +*> +*> NB = ILAENV( 1, 'STRTRI', UPLO // DIAG, N, -1, -1, -1 ) +*> IF( NB.LE.1 ) NB = MAX( 1, N ) +*> \endverbatim +*> +* ===================================================================== + INTEGER FUNCTION ILAENV( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER*( * ) NAME, OPTS + INTEGER ISPEC, N1, N2, N3, N4 +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, IC, IZ, NB, NBMIN, NX + LOGICAL CNAME, SNAME + CHARACTER C1*1, C2*2, C4*2, C3*3, SUBNAM*6 +* .. +* .. Intrinsic Functions .. + INTRINSIC CHAR, ICHAR, INT, MIN, REAL +* .. +* .. External Functions .. + INTEGER IEEECK, IPARMQ + EXTERNAL IEEECK, IPARMQ +* .. +* .. Executable Statements .. +* + GO TO ( 10, 10, 10, 80, 90, 100, 110, 120, + $ 130, 140, 150, 160, 160, 160, 160, 160 )ISPEC +* +* Invalid value for ISPEC +* + ILAENV = -1 + RETURN +* + 10 CONTINUE +* +* Convert NAME to upper case if the first character is lower case. +* + ILAENV = 1 + SUBNAM = NAME + IC = ICHAR( SUBNAM( 1: 1 ) ) + IZ = ICHAR( 'Z' ) + IF( IZ.EQ.90 .OR. IZ.EQ.122 ) THEN +* +* ASCII character set +* + IF( IC.GE.97 .AND. IC.LE.122 ) THEN + SUBNAM( 1: 1 ) = CHAR( IC-32 ) + DO 20 I = 2, 6 + IC = ICHAR( SUBNAM( I: I ) ) + IF( IC.GE.97 .AND. IC.LE.122 ) + $ SUBNAM( I: I ) = CHAR( IC-32 ) + 20 CONTINUE + END IF +* + ELSE IF( IZ.EQ.233 .OR. IZ.EQ.169 ) THEN +* +* EBCDIC character set +* + IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR. + $ ( IC.GE.145 .AND. IC.LE.153 ) .OR. + $ ( IC.GE.162 .AND. IC.LE.169 ) ) THEN + SUBNAM( 1: 1 ) = CHAR( IC+64 ) + DO 30 I = 2, 6 + IC = ICHAR( SUBNAM( I: I ) ) + IF( ( IC.GE.129 .AND. IC.LE.137 ) .OR. + $ ( IC.GE.145 .AND. IC.LE.153 ) .OR. + $ ( IC.GE.162 .AND. IC.LE.169 ) )SUBNAM( I: + $ I ) = CHAR( IC+64 ) + 30 CONTINUE + END IF +* + ELSE IF( IZ.EQ.218 .OR. IZ.EQ.250 ) THEN +* +* Prime machines: ASCII+128 +* + IF( IC.GE.225 .AND. IC.LE.250 ) THEN + SUBNAM( 1: 1 ) = CHAR( IC-32 ) + DO 40 I = 2, 6 + IC = ICHAR( SUBNAM( I: I ) ) + IF( IC.GE.225 .AND. IC.LE.250 ) + $ SUBNAM( I: I ) = CHAR( IC-32 ) + 40 CONTINUE + END IF + END IF +* + C1 = SUBNAM( 1: 1 ) + SNAME = C1.EQ.'S' .OR. C1.EQ.'D' + CNAME = C1.EQ.'C' .OR. C1.EQ.'Z' + IF( .NOT.( CNAME .OR. SNAME ) ) + $ RETURN + C2 = SUBNAM( 2: 3 ) + C3 = SUBNAM( 4: 6 ) + C4 = C3( 2: 3 ) +* + GO TO ( 50, 60, 70 )ISPEC +* + 50 CONTINUE +* +* ISPEC = 1: block size +* +* In these examples, separate code is provided for setting NB for +* real and complex. We assume that NB will take the same value in +* single or double precision. +* + NB = 1 +* + IF( C2.EQ.'GE' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + ELSE IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. + $ C3.EQ.'QLF' ) THEN + IF( SNAME ) THEN + NB = 32 + ELSE + NB = 32 + END IF + ELSE IF( C3.EQ.'HRD' ) THEN + IF( SNAME ) THEN + NB = 32 + ELSE + NB = 32 + END IF + ELSE IF( C3.EQ.'BRD' ) THEN + IF( SNAME ) THEN + NB = 32 + ELSE + NB = 32 + END IF + ELSE IF( C3.EQ.'TRI' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( C2.EQ.'PO' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( C2.EQ.'SY' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN + NB = 32 + ELSE IF( SNAME .AND. C3.EQ.'GST' ) THEN + NB = 64 + END IF + ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN + IF( C3.EQ.'TRF' ) THEN + NB = 64 + ELSE IF( C3.EQ.'TRD' ) THEN + NB = 32 + ELSE IF( C3.EQ.'GST' ) THEN + NB = 64 + END IF + ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + END IF + ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NB = 32 + END IF + END IF + ELSE IF( C2.EQ.'GB' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + IF( N4.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + ELSE + IF( N4.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + END IF + END IF + ELSE IF( C2.EQ.'PB' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + IF( N2.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + ELSE + IF( N2.LE.64 ) THEN + NB = 1 + ELSE + NB = 32 + END IF + END IF + END IF + ELSE IF( C2.EQ.'TR' ) THEN + IF( C3.EQ.'TRI' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( C2.EQ.'LA' ) THEN + IF( C3.EQ.'UUM' ) THEN + IF( SNAME ) THEN + NB = 64 + ELSE + NB = 64 + END IF + END IF + ELSE IF( SNAME .AND. C2.EQ.'ST' ) THEN + IF( C3.EQ.'EBZ' ) THEN + NB = 1 + END IF + END IF + ILAENV = NB + RETURN +* + 60 CONTINUE +* +* ISPEC = 2: minimum block size +* + NBMIN = 2 + IF( C2.EQ.'GE' ) THEN + IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. C3.EQ. + $ 'QLF' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + ELSE IF( C3.EQ.'HRD' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + ELSE IF( C3.EQ.'BRD' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + ELSE IF( C3.EQ.'TRI' ) THEN + IF( SNAME ) THEN + NBMIN = 2 + ELSE + NBMIN = 2 + END IF + END IF + ELSE IF( C2.EQ.'SY' ) THEN + IF( C3.EQ.'TRF' ) THEN + IF( SNAME ) THEN + NBMIN = 8 + ELSE + NBMIN = 8 + END IF + ELSE IF( SNAME .AND. C3.EQ.'TRD' ) THEN + NBMIN = 2 + END IF + ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN + IF( C3.EQ.'TRD' ) THEN + NBMIN = 2 + END IF + ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + END IF + ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + ELSE IF( C3( 1: 1 ).EQ.'M' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NBMIN = 2 + END IF + END IF + END IF + ILAENV = NBMIN + RETURN +* + 70 CONTINUE +* +* ISPEC = 3: crossover point +* + NX = 0 + IF( C2.EQ.'GE' ) THEN + IF( C3.EQ.'QRF' .OR. C3.EQ.'RQF' .OR. C3.EQ.'LQF' .OR. C3.EQ. + $ 'QLF' ) THEN + IF( SNAME ) THEN + NX = 128 + ELSE + NX = 128 + END IF + ELSE IF( C3.EQ.'HRD' ) THEN + IF( SNAME ) THEN + NX = 128 + ELSE + NX = 128 + END IF + ELSE IF( C3.EQ.'BRD' ) THEN + IF( SNAME ) THEN + NX = 128 + ELSE + NX = 128 + END IF + END IF + ELSE IF( C2.EQ.'SY' ) THEN + IF( SNAME .AND. C3.EQ.'TRD' ) THEN + NX = 32 + END IF + ELSE IF( CNAME .AND. C2.EQ.'HE' ) THEN + IF( C3.EQ.'TRD' ) THEN + NX = 32 + END IF + ELSE IF( SNAME .AND. C2.EQ.'OR' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NX = 128 + END IF + END IF + ELSE IF( CNAME .AND. C2.EQ.'UN' ) THEN + IF( C3( 1: 1 ).EQ.'G' ) THEN + IF( C4.EQ.'QR' .OR. C4.EQ.'RQ' .OR. C4.EQ.'LQ' .OR. C4.EQ. + $ 'QL' .OR. C4.EQ.'HR' .OR. C4.EQ.'TR' .OR. C4.EQ.'BR' ) + $ THEN + NX = 128 + END IF + END IF + END IF + ILAENV = NX + RETURN +* + 80 CONTINUE +* +* ISPEC = 4: number of shifts (used by xHSEQR) +* + ILAENV = 6 + RETURN +* + 90 CONTINUE +* +* ISPEC = 5: minimum column dimension (not used) +* + ILAENV = 2 + RETURN +* + 100 CONTINUE +* +* ISPEC = 6: crossover point for SVD (used by xGELSS and xGESVD) +* + ILAENV = INT( REAL( MIN( N1, N2 ) )*1.6E0 ) + RETURN +* + 110 CONTINUE +* +* ISPEC = 7: number of processors (not used) +* + ILAENV = 1 + RETURN +* + 120 CONTINUE +* +* ISPEC = 8: crossover point for multishift (used by xHSEQR) +* + ILAENV = 50 + RETURN +* + 130 CONTINUE +* +* ISPEC = 9: maximum size of the subproblems at the bottom of the +* computation tree in the divide-and-conquer algorithm +* (used by xGELSD and xGESDD) +* + ILAENV = 25 + RETURN +* + 140 CONTINUE +* +* ISPEC = 10: ieee NaN arithmetic can be trusted not to trap +* +* ILAENV = 0 + ILAENV = 1 + IF( ILAENV.EQ.1 ) THEN + ILAENV = IEEECK( 1, 0.0, 1.0 ) + END IF + RETURN +* + 150 CONTINUE +* +* ISPEC = 11: infinity arithmetic can be trusted not to trap +* +* ILAENV = 0 + ILAENV = 1 + IF( ILAENV.EQ.1 ) THEN + ILAENV = IEEECK( 0, 0.0, 1.0 ) + END IF + RETURN +* + 160 CONTINUE +* +* 12 <= ISPEC <= 16: xHSEQR or one of its subroutines. +* + ILAENV = IPARMQ( ISPEC, NAME, OPTS, N1, N2, N3, N4 ) + RETURN +* +* End of ILAENV +* + END diff --git a/lapack/internal/testdata/dlasqtest/iparmq.f b/lapack/internal/testdata/dlasqtest/iparmq.f new file mode 100644 index 00000000..bd5bd7a0 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/iparmq.f @@ -0,0 +1,322 @@ +*> \brief \b IPARMQ +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download IPARMQ + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* INTEGER FUNCTION IPARMQ( ISPEC, NAME, OPTS, N, ILO, IHI, LWORK ) +* +* .. Scalar Arguments .. +* INTEGER IHI, ILO, ISPEC, LWORK, N +* CHARACTER NAME*( * ), OPTS*( * ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> This program sets problem and machine dependent parameters +*> useful for xHSEQR and its subroutines. It is called whenever +*> ILAENV is called with 12 <= ISPEC <= 16 +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ISPEC +*> \verbatim +*> ISPEC is integer scalar +*> ISPEC specifies which tunable parameter IPARMQ should +*> return. +*> +*> ISPEC=12: (INMIN) Matrices of order nmin or less +*> are sent directly to xLAHQR, the implicit +*> double shift QR algorithm. NMIN must be +*> at least 11. +*> +*> ISPEC=13: (INWIN) Size of the deflation window. +*> This is best set greater than or equal to +*> the number of simultaneous shifts NS. +*> Larger matrices benefit from larger deflation +*> windows. +*> +*> ISPEC=14: (INIBL) Determines when to stop nibbling and +*> invest in an (expensive) multi-shift QR sweep. +*> If the aggressive early deflation subroutine +*> finds LD converged eigenvalues from an order +*> NW deflation window and LD.GT.(NW*NIBBLE)/100, +*> then the next QR sweep is skipped and early +*> deflation is applied immediately to the +*> remaining active diagonal block. Setting +*> IPARMQ(ISPEC=14) = 0 causes TTQRE to skip a +*> multi-shift QR sweep whenever early deflation +*> finds a converged eigenvalue. Setting +*> IPARMQ(ISPEC=14) greater than or equal to 100 +*> prevents TTQRE from skipping a multi-shift +*> QR sweep. +*> +*> ISPEC=15: (NSHFTS) The number of simultaneous shifts in +*> a multi-shift QR iteration. +*> +*> ISPEC=16: (IACC22) IPARMQ is set to 0, 1 or 2 with the +*> following meanings. +*> 0: During the multi-shift QR sweep, +*> xLAQR5 does not accumulate reflections and +*> does not use matrix-matrix multiply to +*> update the far-from-diagonal matrix +*> entries. +*> 1: During the multi-shift QR sweep, +*> xLAQR5 and/or xLAQRaccumulates reflections and uses +*> matrix-matrix multiply to update the +*> far-from-diagonal matrix entries. +*> 2: During the multi-shift QR sweep. +*> xLAQR5 accumulates reflections and takes +*> advantage of 2-by-2 block structure during +*> matrix-matrix multiplies. +*> (If xTRMM is slower than xGEMM, then +*> IPARMQ(ISPEC=16)=1 may be more efficient than +*> IPARMQ(ISPEC=16)=2 despite the greater level of +*> arithmetic work implied by the latter choice.) +*> \endverbatim +*> +*> \param[in] NAME +*> \verbatim +*> NAME is character string +*> Name of the calling subroutine +*> \endverbatim +*> +*> \param[in] OPTS +*> \verbatim +*> OPTS is character string +*> This is a concatenation of the string arguments to +*> TTQRE. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is integer scalar +*> N is the order of the Hessenberg matrix H. +*> \endverbatim +*> +*> \param[in] ILO +*> \verbatim +*> ILO is INTEGER +*> \endverbatim +*> +*> \param[in] IHI +*> \verbatim +*> IHI is INTEGER +*> It is assumed that H is already upper triangular +*> in rows and columns 1:ILO-1 and IHI+1:N. +*> \endverbatim +*> +*> \param[in] LWORK +*> \verbatim +*> LWORK is integer scalar +*> The amount of workspace available. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Little is known about how best to choose these parameters. +*> It is possible to use different values of the parameters +*> for each of CHSEQR, DHSEQR, SHSEQR and ZHSEQR. +*> +*> It is probably best to choose different parameters for +*> different matrices and different parameters at different +*> times during the iteration, but this has not been +*> implemented --- yet. +*> +*> +*> The best choices of most of the parameters depend +*> in an ill-understood way on the relative execution +*> rate of xLAQR3 and xLAQR5 and on the nature of each +*> particular eigenvalue problem. Experiment may be the +*> only practical way to determine which choices are most +*> effective. +*> +*> Following is a list of default values supplied by IPARMQ. +*> These defaults may be adjusted in order to attain better +*> performance in any particular computational environment. +*> +*> IPARMQ(ISPEC=12) The xLAHQR vs xLAQR0 crossover point. +*> Default: 75. (Must be at least 11.) +*> +*> IPARMQ(ISPEC=13) Recommended deflation window size. +*> This depends on ILO, IHI and NS, the +*> number of simultaneous shifts returned +*> by IPARMQ(ISPEC=15). The default for +*> (IHI-ILO+1).LE.500 is NS. The default +*> for (IHI-ILO+1).GT.500 is 3*NS/2. +*> +*> IPARMQ(ISPEC=14) Nibble crossover point. Default: 14. +*> +*> IPARMQ(ISPEC=15) Number of simultaneous shifts, NS. +*> a multi-shift QR iteration. +*> +*> If IHI-ILO+1 is ... +*> +*> greater than ...but less ... the +*> or equal to ... than default is +*> +*> 0 30 NS = 2+ +*> 30 60 NS = 4+ +*> 60 150 NS = 10 +*> 150 590 NS = ** +*> 590 3000 NS = 64 +*> 3000 6000 NS = 128 +*> 6000 infinity NS = 256 +*> +*> (+) By default matrices of this order are +*> passed to the implicit double shift routine +*> xLAHQR. See IPARMQ(ISPEC=12) above. These +*> values of NS are used only in case of a rare +*> xLAHQR failure. +*> +*> (**) The asterisks (**) indicate an ad-hoc +*> function increasing from 10 to 64. +*> +*> IPARMQ(ISPEC=16) Select structured matrix multiply. +*> (See ISPEC=16 above for details.) +*> Default: 3. +*> \endverbatim +*> +* ===================================================================== + INTEGER FUNCTION IPARMQ( ISPEC, NAME, OPTS, N, ILO, IHI, LWORK ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER IHI, ILO, ISPEC, LWORK, N + CHARACTER NAME*( * ), OPTS*( * ) +* +* ================================================================ +* .. Parameters .. + INTEGER INMIN, INWIN, INIBL, ISHFTS, IACC22 + PARAMETER ( INMIN = 12, INWIN = 13, INIBL = 14, + $ ISHFTS = 15, IACC22 = 16 ) + INTEGER NMIN, K22MIN, KACMIN, NIBBLE, KNWSWP + PARAMETER ( NMIN = 75, K22MIN = 14, KACMIN = 14, + $ NIBBLE = 14, KNWSWP = 500 ) + REAL TWO + PARAMETER ( TWO = 2.0 ) +* .. +* .. Local Scalars .. + INTEGER NH, NS +* .. +* .. Intrinsic Functions .. + INTRINSIC LOG, MAX, MOD, NINT, REAL +* .. +* .. Executable Statements .. + IF( ( ISPEC.EQ.ISHFTS ) .OR. ( ISPEC.EQ.INWIN ) .OR. + $ ( ISPEC.EQ.IACC22 ) ) THEN +* +* ==== Set the number simultaneous shifts ==== +* + NH = IHI - ILO + 1 + NS = 2 + IF( NH.GE.30 ) + $ NS = 4 + IF( NH.GE.60 ) + $ NS = 10 + IF( NH.GE.150 ) + $ NS = MAX( 10, NH / NINT( LOG( REAL( NH ) ) / LOG( TWO ) ) ) + IF( NH.GE.590 ) + $ NS = 64 + IF( NH.GE.3000 ) + $ NS = 128 + IF( NH.GE.6000 ) + $ NS = 256 + NS = MAX( 2, NS-MOD( NS, 2 ) ) + END IF +* + IF( ISPEC.EQ.INMIN ) THEN +* +* +* ===== Matrices of order smaller than NMIN get sent +* . to xLAHQR, the classic double shift algorithm. +* . This must be at least 11. ==== +* + IPARMQ = NMIN +* + ELSE IF( ISPEC.EQ.INIBL ) THEN +* +* ==== INIBL: skip a multi-shift qr iteration and +* . whenever aggressive early deflation finds +* . at least (NIBBLE*(window size)/100) deflations. ==== +* + IPARMQ = NIBBLE +* + ELSE IF( ISPEC.EQ.ISHFTS ) THEN +* +* ==== NSHFTS: The number of simultaneous shifts ===== +* + IPARMQ = NS +* + ELSE IF( ISPEC.EQ.INWIN ) THEN +* +* ==== NW: deflation window size. ==== +* + IF( NH.LE.KNWSWP ) THEN + IPARMQ = NS + ELSE + IPARMQ = 3*NS / 2 + END IF +* + ELSE IF( ISPEC.EQ.IACC22 ) THEN +* +* ==== IACC22: Whether to accumulate reflections +* . before updating the far-from-diagonal elements +* . and whether to use 2-by-2 block structure while +* . doing it. A small amount of work could be saved +* . by making this choice dependent also upon the +* . NH=IHI-ILO+1. +* + IPARMQ = 0 + IF( NS.GE.KACMIN ) + $ IPARMQ = 1 + IF( NS.GE.K22MIN ) + $ IPARMQ = 2 +* + ELSE +* ===== invalid value of ispec ===== + IPARMQ = -1 +* + END IF +* +* ==== End of IPARMQ ==== +* + END diff --git a/lapack/internal/testdata/dlasqtest/lsame.f b/lapack/internal/testdata/dlasqtest/lsame.f new file mode 100644 index 00000000..315304c3 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/lsame.f @@ -0,0 +1,125 @@ +*> \brief \b LSAME +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* LOGICAL FUNCTION LSAME( CA, CB ) +* +* .. Scalar Arguments .. +* CHARACTER CA, CB +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> LSAME returns .TRUE. if CA is the same letter as CB regardless of +*> case. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CA +*> \verbatim +*> \endverbatim +*> +*> \param[in] CB +*> \verbatim +*> CA and CB specify the single characters to be compared. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION LSAME( CA, CB ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CA, CB +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC ICHAR +* .. +* .. Local Scalars .. + INTEGER INTA, INTB, ZCODE +* .. +* .. Executable Statements .. +* +* Test if the characters are equal +* + LSAME = CA.EQ.CB + IF( LSAME ) + $ RETURN +* +* Now test for equivalence if both characters are alphabetic. +* + ZCODE = ICHAR( 'Z' ) +* +* Use 'Z' rather than 'A' so that ASCII can be detected on Prime +* machines, on which ICHAR returns a value with bit 8 set. +* ICHAR('A') on Prime machines returns 193 which is the same as +* ICHAR('A') on an EBCDIC machine. +* + INTA = ICHAR( CA ) + INTB = ICHAR( CB ) +* + IF( ZCODE.EQ.90 .OR. ZCODE.EQ.122 ) THEN +* +* ASCII is assumed - ZCODE is the ASCII code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.97 .AND. INTA.LE.122 ) INTA = INTA - 32 + IF( INTB.GE.97 .AND. INTB.LE.122 ) INTB = INTB - 32 +* + ELSE IF( ZCODE.EQ.233 .OR. ZCODE.EQ.169 ) THEN +* +* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.129 .AND. INTA.LE.137 .OR. + $ INTA.GE.145 .AND. INTA.LE.153 .OR. + $ INTA.GE.162 .AND. INTA.LE.169 ) INTA = INTA + 64 + IF( INTB.GE.129 .AND. INTB.LE.137 .OR. + $ INTB.GE.145 .AND. INTB.LE.153 .OR. + $ INTB.GE.162 .AND. INTB.LE.169 ) INTB = INTB + 64 +* + ELSE IF( ZCODE.EQ.218 .OR. ZCODE.EQ.250 ) THEN +* +* ASCII is assumed, on Prime machines - ZCODE is the ASCII code +* plus 128 of either lower or upper case 'Z'. +* + IF( INTA.GE.225 .AND. INTA.LE.250 ) INTA = INTA - 32 + IF( INTB.GE.225 .AND. INTB.LE.250 ) INTB = INTB - 32 + END IF + LSAME = INTA.EQ.INTB +* +* RETURN +* +* End of LSAME +* + END diff --git a/lapack/internal/testdata/dlasqtest/testdlasq1.f90 b/lapack/internal/testdata/dlasqtest/testdlasq1.f90 new file mode 100644 index 00000000..5ee8878d --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/testdlasq1.f90 @@ -0,0 +1,626 @@ +program randomsys1 +implicit none +integer, parameter :: nmax=1000 +real(kind=8), dimension(nmax) :: b, x +real(kind=8), dimension(nmax,nmax) :: a +real(kind=8) :: err +integer :: i, info, lda, ldb, nrhs, n,iter +integer, dimension(nmax) :: ipiv + +real(kind=8), dimension(100) :: d +real(kind=8), dimension(99) :: e +real(kind=8), dimension(400) :: work + +d(1:100) = (/1.8334043365537367D+00, & +1.4451749896846686D+00, & +1.0018566447551758D-01, & +-7.2143260438744417D-01, & +-3.7864653015502087D-01, & +-9.0270111568850808D-01, & +1.2204305489831029D+00, & +-9.7628177811136485D-01, & +8.4199233511256721D-01, & +-2.7938817329922050D-01, & +3.6157779599908046D-01, & +-1.8563411313998144D+00, & +-5.7930081140992240D-01, & +7.4080550463379169D-01, & +1.7021409147402005D+00, & +-5.7992035328196923D-01, & +4.0877426434579855D-01, & +-7.1297236049446144D-01, & +-1.2214095798914903D+00, & +2.9037983248746674D-01, & +7.4685018821608473D-01, & +3.0213735481316539D-01, & +-1.5207207136907624D-01, & +-2.1332671668411556D+00, & +6.8744661834930676D-01, & +-2.0946670404018297D-01, & +-1.5221059713957628D+00, & +1.1117190383859539D+00, & +-6.1175948159744020D-01, & +-4.4149212620857964D-01, & +-5.5702632609947533D-01, & +1.4071858950692646D+00, & +-3.2329881667362437D-01, & +-3.1958092104323499D-01, & +9.0934520529412111D-01, & +9.7881421364746712D-01, & +-5.1202970940327841D-01, & +1.5040024724520102D+00, & +-7.1993831181468571D-01, & +-7.1819661000094503D-01, & +-1.3481185445933910D+00, & +-1.4984426192966893D+00, & +1.1356626654278745D+00, & +1.6427417967661164D+00, & +-1.4184643787388000D+00, & +2.9811560271518989D-01, & +7.8630022575860559D-01, & +-1.8262830018047089D+00, & +6.3058255632564841D-01, & +-2.0692752940382309D-02, & +-7.2726648905906033D-01, & +-1.0461446937034022D+00, & +1.2530345094987356D+00, & +-2.3583665341168443D+00, & +1.9177654334479410D-01, & +-1.3563410975095058D+00, & +-1.0669710425337906D+00, & +1.4840245472507219D+00, & +-6.9185935518981789D-01, & +1.6813910559942205D-01, & +-7.1255209442204559D-01, & +-1.0112797453604008D+00, & +2.8591746998403011D-01, & +-1.9403039239509563D+00, & +-8.1434141084858885D-02, & +1.3873918713367210D+00, & +-8.8212258376548647D-01, & +-1.2253510598547583D+00, & +-3.8677386127356073D-01, & +-1.0262656526479850D+00, & +2.9468734022014376D-01, & +2.3442965677966704D-01, & +1.2219251054024911D+00, & +2.6066505150099868D+00, & +-7.8543147636303856D-01, & +-9.8126277325503253D-01, & +1.1722358680271947D+00, & +-8.1477749181289072D-01, & +1.3437777060446568D-01, & +3.4626341297821356D-01, & +-4.5672026157532375D-01, & +3.0496975959999184D-01, & +3.4636683737604146D-01, & +1.5114807806635011D-01, & +-1.1376177393945328D+00, & +9.3419670621891793D-01, & +7.9186416310239138D-01, & +6.7230421440462595D-01, & +-2.3236847424852280D-01, & +-1.0927137499922757D+00, & +9.8562766620822340D-01, & +-1.1382935431007701D-01, & +-9.2072237463768225D-01, & +6.1142850054965170D-01, & +8.2752057022739134D-03, & +6.7197122515126417D-01, & +-1.1007816668204429D+00, & +-1.2196829073430047D+00, & +-6.1428585523321222D-01, & +6.4599803465517280D-01/) +e(1:99) = (/-9.6393084631802151D-01, & +2.5532567563781607D+00, & +8.2492664240014357D-01, & +8.2628261757058474D-01, & +7.3021658879350859D-01, & +3.4014431785419519D-02, & +3.2121571974900542D-01, & +2.5987166374572213D-02, & +-3.1150206355945814D-01, & +1.3429094629249927D+00, & +8.6246434952180806D-01, & +-8.3756967113851388D-01, & +9.5277237959592009D-01, & +1.1717152179539618D+00, & +2.5980977671460709D-01, & +-6.4468162556415265D-01, & +-1.3751364204170078D+00, & +2.9677172586579936D-01, & +-3.7071376979215720D-01, & +8.2912690407496381D-01, & +-8.6820437618589197D-01, & +5.2500961173269689D-01, & +1.0657701704030644D+00, & +-4.6621502244820201D-03, & +-1.9013997092621748D-01, & +1.5098985741543924D-01, & +1.0102557493909003D+00, & +8.8830298507891103D-01, & +2.0464938169302065D+00, & +4.7910192662606277D-01, & +1.4155288808120892D+00, & +-5.8169388172737679D-01, & +-9.8007278321065916D-01, & +2.4369633027015425D-01, & +1.6173163491335715D-01, & +6.6887624704464499D-01, & +-1.6500999383869115D+00, & +1.4380895281962367D+00, & +4.7508565250807777D-01, & +-3.1332991280327299D-01, & +3.1402552392574451D-01, & +5.6246373170551534D-01, & +2.5944662334710866D-01, & +4.8101648688789655D-01, & +1.7823376751423265D+00, & +3.0160656491545923D-01, & +-8.8915960863742050D-01, & +-4.4783548340444157D-01, & +8.9985836172311440D-01, & +-1.5626460660617920D+00, & +8.9972644535054036D-01, & +2.4456452268563592D-01, & +-3.1377944726557985D+00, & +1.6874136691232020D+00, & +2.4791290942030142D-01, & +1.7055713617986679D+00, & +1.7027580566127303D+00, & +-5.2969836953828042D-01, & +-8.6858804294195124D-01, & +7.6588136514601834D-01, & +8.6161822555855139D-01, & +6.5387844189250555D-01, & +7.0164941351276944D-01, & +4.1171318512873312D-01, & +7.6075070364872455D-01, & +8.5708035578209718D-02, & +-4.3558500874018535D-01, & +-6.2302104134015979D-01, & +8.4912051051824700D-01, & +-1.7120108380813925D-01, & +-9.7880552224113848D-01, & +1.1904436348486702D+00, & +7.0273864977367972D-01, & +-1.0213785672492079D+00, & +4.8392839864322634D-02, & +1.2611184618297511D-01, & +5.3330169134056482D-01, & +1.8070298106837654D+00, & +-2.8022831541922144D-01, & +8.0235047640662738D-01, & +-1.2615220404695868D+00, & +1.1878769364434660D+00, & +-2.1059219864297674D-01, & +3.2897539618854971D-01, & +-5.8928028913554642D-01, & +1.9164347352074701D-02, & +2.8035162764822374D-01, & +-9.6622429734784299D-02, & +3.4216241143907045D-01, & +-2.2358052317750254D+00, & +6.6284070879481805D-01, & +7.4316074303777269D-01, & +1.0280848437626724D+00, & +-2.0939898252763922D-01, & +-1.0268515265064981D+00, & +-1.2648527910628871D-01, & +4.8663846308033204D-01, & +1.2270171407392749D+00, & +-1.6189022502021406D+00/) +work(1:400) = (/6.0466028797961957D-01, & +9.4050908804501243D-01, & +6.6456005321849043D-01, & +4.3771418718698019D-01, & +4.2463749707126569D-01, & +6.8682307286710942D-01, & +6.5637019217476222D-02, & +1.5651925473279124D-01, & +9.6969518914484562D-02, & +3.0091186058528707D-01, & +5.1521262850206540D-01, & +8.1363996099009683D-01, & +2.1426387258237492D-01, & +3.8065718929968601D-01, & +3.1805817433032985D-01, & +4.6888984490242319D-01, & +2.8303415118044517D-01, & +2.9310185733681576D-01, & +6.7908467592021626D-01, & +2.1855305259276428D-01, & +2.0318687664732285D-01, & +3.6087141685690599D-01, & +5.7067327607102258D-01, & +8.6249143744788637D-01, & +2.9311424455385804D-01, & +2.9708256355629153D-01, & +7.5257303555161192D-01, & +2.0658266191369859D-01, & +8.6533501300156102D-01, & +6.9671916574663473D-01, & +5.2382030605000085D-01, & +2.8303083325889995D-02, & +1.5832827774512764D-01, & +6.0725343954551536D-01, & +9.7524161886057836D-01, & +7.9453623373871976D-02, & +5.9480859768306260D-01, & +5.9120651313875290D-02, & +6.9202458735311201D-01, & +3.0152268100655999D-01, & +1.7326623818270528D-01, & +5.4109985500873525D-01, & +5.4415557300088502D-01, & +2.7850762181610883D-01, & +4.2315220157182809D-01, & +5.3058571535070520D-01, & +2.5354050051506050D-01, & +2.8208099496492467D-01, & +7.8860491501934493D-01, & +3.6180548048031691D-01, & +8.8054312274161706D-01, & +2.9711226063977081D-01, & +8.9436172933045366D-01, & +9.7454618399116566D-02, & +9.7691686858626237D-01, & +7.4290998949843021D-02, & +2.2228941700678773D-01, & +6.8107831239257088D-01, & +2.4151508854715265D-01, & +3.1152244431052484D-01, & +9.3284642851843402D-01, & +7.4184895999182299D-01, & +8.0105504265266125D-01, & +7.3023147729480831D-01, & +1.8292491645390843D-01, & +4.2835708180680782D-01, & +8.9699195756187267D-01, & +6.8265348801324377D-01, & +9.7892935557668759D-01, & +9.2221225892172687D-01, & +9.0837275353887081D-02, & +4.9314199770488037D-01, & +9.2698680357441421D-01, & +9.5494544041678175D-01, & +3.4795396362822290D-01, & +6.9083883150567893D-01, & +7.1090719529999513D-01, & +5.6377959581526438D-01, & +6.4948946059294044D-01, & +5.5176504901277490D-01, & +7.5582350749159777D-01, & +4.0380328579570035D-01, & +1.3065111702897217D-01, & +9.8596472934024670D-01, & +8.9634174539621614D-01, & +3.2208397052088172D-01, & +7.2114776519267410D-01, & +6.4453978250932942D-01, & +8.5520507541911234D-02, & +6.6957529769977453D-01, & +6.2272831736370449D-01, & +3.6969284363982191D-01, & +2.3682254680548520D-01, & +5.3528189063440612D-01, & +1.8724610140105305D-01, & +2.3884070280531861D-01, & +6.2809817121836331D-01, & +1.2675292937260130D-01, & +2.8133029380535923D-01, & +4.1032284435628247D-01, & +4.3491247389145765D-01, & +6.2509502830053043D-01, & +5.5014692050772329D-01, & +6.2360882645293014D-01, & +7.2918072673429812D-01, & +8.3053391899480622D-01, & +5.1381551612136129D-04, & +7.3606860149543141D-01, & +3.9998376285699544D-01, & +4.9786811334270198D-01, & +6.0397810228292748D-01, & +4.0961827788499267D-01, & +2.9671281274886468D-02, & +1.9038945142366389D-03, & +2.8430411748625642D-03, & +9.1582131461295702D-01, & +5.8983418500491935D-01, & +5.5939244907101404D-01, & +8.1540517093336062D-01, & +8.7801175865240000D-01, & +4.5844247857565062D-01, & +6.0016559532333080D-01, & +2.6265150609689439D-02, & +8.4583278724804167D-01, & +2.4969320116349378D-01, & +6.4178429079958299D-01, & +2.4746660783662855D-01, & +1.7365584472313275D-01, & +5.9262375321244554D-01, & +8.1439455096702107D-01, & +6.9383813651720949D-01, & +3.0322547833006870D-02, & +5.3921010589094598D-01, & +9.7567481498731645D-01, & +7.5076305647959851D-01, & +2.9400631279501488D-01, & +7.5316127773675856D-01, & +1.5096404497960700D-01, & +3.5576726540923664D-01, & +8.3193085296981628D-01, & +2.3183004193767690D-01, & +6.2783460500002275D-01, & +4.9839430127597562D-01, & +8.9836089260366833D-02, & +2.5193959794895041D-02, & +3.9221618315402479D-01, & +5.8938308640079917D-01, & +9.2961163544903025D-01, & +5.7208680144308399D-01, & +5.8857634514348212D-01, & +4.1176268834501623D-01, & +5.5258038981424384D-01, & +4.9160739613162047D-01, & +9.5795391353751358D-01, & +7.9720854091080284D-01, & +1.0738111282075208D-01, & +7.8303497339600214D-01, & +3.9325099922888668D-01, & +1.3041384617379179D-01, & +1.9003276633920804D-01, & +7.3982578101583363D-01, & +6.5404140923127974D-01, & +9.8383788985732593D-02, & +5.2038028571222783D-01, & +9.9729663719935122D-02, & +1.5184340208190175D-01, & +7.6190262303755044D-02, & +3.1520808532012451D-01, & +1.5965092146489504D-01, & +1.3780406161952607D-01, & +3.2261068286779754D-01, & +5.3907451703947940D-01, & +5.7085162734549566D-01, & +5.1278175811108151D-01, & +6.8417513009745512D-01, & +6.5304020513536076D-01, & +5.2449975954986505D-01, & +6.5427013442414605D-01, & +7.1636837490167116D-01, & +6.3664421403817983D-01, & +1.2825909106361078D-02, & +3.0682195787138565D-02, & +9.8030874806304999D-02, & +3.6911170916434483D-01, & +8.2645412563474197D-01, & +3.4768170859156955D-01, & +3.4431501772636058D-01, & +2.5299982364784412D-01, & +2.1647114665497036D-01, & +5.5500213563479417D-01, & +4.0207084527183062D-01, & +5.0649706367641834D-01, & +1.6867966833433606D-01, & +3.3136826030698385D-01, & +8.2792809615055885D-01, & +7.0028787314581509D-01, & +5.7926259664335768D-02, & +9.9915949022033324D-01, & +4.1154036322047599D-01, & +1.1167463676480495D-01, & +7.8075408455849260D-01, & +9.2117624440742188D-02, & +5.3494624494407637D-02, & +7.1469581589162956D-01, & +2.5076227542918023D-01, & +8.4863292090315690D-01, & +9.7388187407067284D-01, & +2.1256094905031958D-01, & +2.1533783325605065D-02, & +9.4519476038882588D-01, & +9.2970155499924934D-02, & +6.4583337452397671D-01, & +3.1188554282705405D-01, & +4.4846436394045647D-01, & +4.8723924858036949D-01, & +8.2479676511350006D-02, & +6.7182910623463954D-01, & +4.0018828942364343D-01, & +9.0027514726431157D-01, & +9.4988320610125321D-01, & +3.1933126760711733D-01, & +4.9938549375241320D-01, & +4.0043231714181288D-01, & +1.9808670325451940D-02, & +6.4503886601944815D-01, & +4.2868843006993296D-01, & +3.3959675138730994D-01, & +8.8744750085050050D-01, & +2.3632747430436052D-01, & +7.6500821493327975D-01, & +3.5754647436084384D-02, & +7.2757725604152290D-01, & +6.2583662695812525D-01, & +5.1308750608785669D-01, & +7.2448356792351315D-02, & +7.2422905845916841D-01, & +8.7984484630570914D-01, & +9.7776347735771851D-01, & +8.4750026226468134D-01, & +8.3219793814993315D-01, & +2.4784452318699535D-01, & +9.1339906293647088D-01, & +7.5037210134653420D-02, & +8.3510380115435290D-01, & +6.2933169164530067D-01, & +7.5174057889673473D-01, & +6.3200343378879975D-01, & +9.6934213238731665D-02, & +1.4827369494876504D-02, & +5.8383474186253115D-01, & +6.8756195202154743D-02, & +9.9827381100849455D-01, & +6.4918841659842363D-01, & +9.8546557863324791D-01, & +8.3480576021921249D-01, & +3.3205608571906026D-01, & +6.6139318058334262D-01, & +9.5602062659660969D-01, & +3.1051027622482125D-01, & +1.8439069400202679D-01, & +9.6709434137177297D-01, & +8.3324181552815457D-01, & +3.0954845052732810D-01, & +8.0587176753764456D-01, & +4.1732584219038238D-01, & +7.1853044935277477D-01, & +4.0673677545039083D-01, & +8.9580326774414576D-01, & +9.5817636260259365D-01, & +1.8713221139656417D-02, & +7.9167230908208319D-01, & +4.2355315388584103D-01, & +1.5181277223073395D-02, & +4.3269824007906393D-01, & +9.0477623706573340D-01, & +8.5570441457488644D-01, & +4.2921642176334200D-02, & +6.5903053300775438D-01, & +3.4785904313005395D-01, & +5.0348679004869112D-01, & +8.3994742117055976D-01, & +2.3109568410543832D-02, & +1.2436351859954159D-01, & +2.6117561918821841D-01, & +8.3494750649349414D-01, & +3.1480479595597533D-01, & +7.6812064740880894D-03, & +8.9975012571752733D-01, & +3.7026753645051064D-01, & +1.0019940926941497D-01, & +6.4320402657020315D-01, & +7.6988908998308336D-01, & +7.9112533566198451D-01, & +2.6238190747072776D-01, & +3.4686388037925503D-01, & +2.1465371537694145D-01, & +8.2209289717657175D-01, & +3.5113429966521320D-01, & +5.9919425250588099D-01, & +5.7835125693111211D-01, & +4.1358098797631293D-01, & +1.1985050890286310D-01, & +9.1161370679159903D-01, & +5.3785580105748208D-02, & +2.2891758676059876D-01, & +3.2417396306138829D-01, & +3.5076512764716117D-01, & +3.4928874777426255D-01, & +3.0380212985436572D-01, & +9.6874615996581170D-01, & +6.7152655046083776D-01, & +2.0794312837315651D-01, & +9.6313940120247044D-01, & +3.0220237504213365D-01, & +8.0794108095480799D-01, & +1.3408416275024179D-01, & +9.4776028919455635D-01, & +6.4086482116825383D-01, & +9.5325875425035178D-01, & +8.0987422593395209D-01, & +1.8159084675756379D-01, & +9.4275737153737327D-01, & +8.3124103554376771D-01, & +4.9468043578205978D-01, & +8.5531034647693982D-01, & +7.1074391181909824D-01, & +2.7349475629159786D-01, & +4.0763287189198161D-01, & +9.0976128251911847D-01, & +9.4439713870030451D-01, & +4.9863245185560190D-01, & +2.8863831012730923D-01, & +9.7589525649963815D-01, & +4.5258447627808124D-01, & +4.4990698677957075D-02, & +3.1536198151820755D-01, & +9.5190614812037189D-01, & +7.5156308247423609D-01, & +5.3579099898961424D-01, & +6.6971458883510748D-01, & +8.6517499748328641D-01, & +4.5888445390388938D-01, & +5.7855090249582031D-01, & +4.8152982184966137D-01, & +5.5061576198318274D-01, & +9.5062324380815433D-01, & +5.0986542047295536D-01, & +7.4251472966182985D-01, & +4.9079401441435533D-01, & +6.6151414870689360D-02, & +2.6249066264989940D-01, & +9.2546794407799982D-01, & +3.7148665165822231D-01, & +4.0941940003107308D-01, & +4.1575196973399631D-01, & +9.7261599736539445D-02, & +9.0162762447969347D-01, & +4.4446597981328932D-03, & +2.7392454335102678D-01, & +1.0930666111680035D-01, & +8.5544841289295426D-01, & +2.5705535663902546D-01, & +9.8913209203202213D-01, & +9.2641142236812712D-01, & +1.7094603208839290D-01, & +3.0388712489325242D-01, & +5.3345144978115477D-01, & +1.7648961347647024D-01, & +8.1359077477652830D-01, & +7.0513712380125892D-01, & +2.5720755742139950D-01, & +2.5036892046498466D-01, & +3.3509436689927874D-01, & +7.5124063162526056D-01, & +4.8797826077860845D-03, & +8.4099320643626019D-01, & +2.2957358869665739D-01, & +1.3285547727582237D-02, & +9.4993740716879371D-01, & +8.9937146465701423D-01, & +9.6262420114388625D-01, & +4.3000361954927006D-02, & +7.1266261216467264D-01, & +5.1094098258212241D-02, & +4.0753210485857738D-01, & +4.7569737399615403D-01, & +3.4746838606940983D-01, & +4.0719938711096422D-02, & +5.9756620514440806D-01, & +2.6012467360309705D-01, & +8.3285585557738717D-01, & +9.6049750529821787D-01, & +9.3670756890653750D-01, & +2.2932023844733959D-01, & +7.2031310018914962D-01, & +7.5648232426876405D-01, & +4.5015392507594826D-01, & +3.3897738839543617D-01, & +4.7249205225111501D-01, & +9.8599436000817042D-01/) +n = 100 +info = 0 + +open(unit = 4, STATUS='REPLACE', file = "gen4tests.txt") +open(unit = 3, STATUS='REPLACE', file = "gen3tests.txt") +open(unit = 5, STATUS='REPLACE', file = "gen5tests.txt") + +call dlasq1(n, d, e, work, info) + +close(5) +close(3) +close(4) + +end \ No newline at end of file diff --git a/lapack/internal/testdata/dlasqtest/testdlasq2.f90 b/lapack/internal/testdata/dlasqtest/testdlasq2.f90 new file mode 100644 index 00000000..c908f7d6 --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/testdlasq2.f90 @@ -0,0 +1,171 @@ +! $CLASSHG/codes/lapack/random/randomsys1.f90 + +program randomsys1 +implicit none +integer, parameter :: nmax=1000 +real(kind=8), dimension(nmax) :: b, x +real(kind=8), dimension(nmax,nmax) :: a +real(kind=8) :: err +integer :: i, info, lda, ldb, nrhs, n,iter +integer, dimension(nmax) :: ipiv + +real(kind=8), dimension(84) :: z + +z(1:84) = (/2.3962280929192509D-01, & +6.4346010490580374D-01, & +5.4886677265274941D-01, & +1.8435046456575191D-01, & +4.2690013698472401D-01, & +6.2760930131666248D-01, & +8.7243363936287288D-02, & +5.3710399529030350D-01, & +8.4474604576675638D-01, & +4.0947669295022632D-01, & +2.0315141244999760D-01, & +8.2714283129979482D-01, & +9.6582843029739029D-01, & +3.7773539690481128D-01, & +6.4713340225873406D-01, & +6.7774351756798612D-01, & +4.4568905572928591D-01, & +1.7208265726837521D-01, & +3.5202074329011412D-01, & +3.2913965083413110D-01, & +7.4682622623737438D-01, & +2.7151044969605542D-01, & +5.6129178633962351D-01, & +1.3244294692867761D-01, & +7.9837660640147112D-01, & +2.0595995860196409D-01, & +2.6555102564257749D-02, & +1.9623902644848701D-01, & +7.8452468963715605D-03, & +8.2177375597112101D-01, & +9.4444982187044924D-01, & +4.6799576958310329D-01, & +1.1359180530395520D-01, & +1.6049482525711320D-01, & +8.4523811016138373D-01, & +8.5370708147160490D-01, & +3.0139325968162661D-01, & +2.5117154067021252D-01, & +2.0086476380364379D-01, & +2.6078975734443288D-01, & +2.5710509100784901D-01, & +6.2861740244633146D-01, & +4.7397018497236110D-01, & +8.6989475348440182D-01, & +6.4860795895959611D-01, & +8.8943219043019872D-01, & +7.9524758401855578D-01, & +8.8016617212154102D-01, & +2.1472721943810300D-01, & +9.5183566464760194D-01, & +7.1911522894148772D-01, & +1.1065249711733080D-01, & +9.5745872307341484D-01, & +6.4694742306793951D-01, & +5.8182607574435841D-01, & +1.2922028370755401D-02, & +2.7617229134380777D-01, & +8.0045359255855852D-01, & +3.2789738555900377D-01, & +5.7940374386642890D-01, & +2.3961554431041750D-02, & +6.6990484757537938D-01, & +1.8144929371280860D-01, & +2.8661849362222419D-01, & +6.5845572125062690D-01, & +5.8896512277754309D-01, & +6.3697665190607378D-02, & +1.3281935295985961D-01, & +7.4166314172628711D-01, & +5.0033182787066932D-01, & +3.1440772963953763D-02, & +9.9073931564031925D-01, & +3.4236965949145941D-03, & +6.9929220728508257D-01, & +7.5905196170645428D-01, & +2.5421825141163590D-01, & +3.3146571845550887D-01, & +5.7286596840196446D-01, & +9.9158547964144228D-01, & +4.8967497301052382D-01, & +5.6113697207961410D-01, & +6.0641422150435165D-01, & +8.5675901647669139D-02, & +2.5817319326781851D-01/) +n = 21 +info = 0 + +open(unit = 2,STATUS='REPLACE', file = "gen2tests.txt") +open(unit = 4, STATUS='REPLACE', file = "gen4tests.txt") +open(unit = 3,STATUS='REPLACE', file = "gen3tests.txt") +open(unit = 5,STATUS='REPLACE', file = "gen5tests.txt") + +write(2,*) "{" +write(2,'(9999(g0))',advance="no") "z: []float64{" +do i = 1, 4*n +write (2,'(99999(e24.16,a))',advance="no") z(i), "," +end do +write (2,*) "}," +write(2,*) "n: " ,n,"," + + +call dlasq2(n, z, info) + +write(2,'(9999(g0))', advance="no") "zOut: []float64{" +do i = 1, 4*n +write (2,'(99999(e24.16,a))', advance="no") z(i), "," +end do +write (2,*) "}," +write(2,*) "info:", info, "," +write(2,*) "}," + +print *, "Done fixed dlasq2" + +close(5) +close(3) +close(4) +close(2) + +! For random tests +n = 21 + +open(unit = 2, STATUS='REPLACE', file = "gen2tests.txt") +open(unit = 4, STATUS='REPLACE', file = "gen4tests.txt") +open(unit = 3, STATUS='REPLACE', file = "gen3tests.txt") +open(unit = 5, STATUS='REPLACE', file = "gen5tests.txt") + +do iter = 1, 2 + +call random_number(z(1:4*n)) + +write(2,*) "{" +write(2,'(9999(g0))', advance="no") "z: []float64{" +do i = 1, 4*n +write (2,'(99999(e24.16,a))', advance="no") z(i), "," +end do +write (2,*) "}," +write(2,*) "n: " ,n,"," + +call dlasq2(n, z, info) + +write(2,'(9999(g0))', advance="no") "zOut: []float64{" +do i = 1, 4*n + write (2,'(99999(e24.16,a))', advance="no") z(i), "," +end do +write (2,*) "}," +write(2,*) "info:", info, "," +write(2,*) "}," + +print *, "Done with dlasq2" + +end do + +close(5) +close(3) +close(4) +close(2) + +end program randomsys1 \ No newline at end of file diff --git a/lapack/internal/testdata/dlasqtest/testdlasq3.f90 b/lapack/internal/testdata/dlasqtest/testdlasq3.f90 new file mode 100644 index 00000000..8cc5cf0f --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/testdlasq3.f90 @@ -0,0 +1,132 @@ +program testdlasq3 +implicit none + +! Dlasq3 tests +integer :: i0, n0, pp,ttype, nFail,iter,nDiv,n +real(kind=8), dimension(84) :: z +real(kind=8) :: dmin,desig,qmax,dmin1,dmin2,dn,dn1,dn2,g,tau,sigma +logical :: ieee + +n = 84 + +ieee = .True. + +z(1:84) = (/1.9143652461808209D+00, & +1.5643842977038900D+00, & +2.4933891621438989D-01, & +3.4998094847693051D-01, & +1.3159965131315450D+00, & +1.3638621124906269D+00, & +9.8984666119707590D-02, & +2.0147331685530781D-01, & +6.0239739795872871D-01, & +6.4655447927417942D-01, & +2.2100334106387809D-03, & +5.4827584804256833D-02, & +9.8618572336789667D-02, & +2.4281908107454921D-02, & +4.7563214844548191D-01, & +7.6546697639973529D-02, & +2.5887481436771148D-01, & +6.1277840695087704D-01, & +1.0786113766900041D-01, & +1.2172855586231640D-01, & +6.4428964922552456D-01, & +2.2938358048981550D-01, & +6.2032304866397048D-01, & +5.2276720640470942D-01, & +3.6956606786075852D-01, & +7.6452331847458654D-01, & +5.3788380542522651D-01, & +2.2536579805014259D-01, & +3.5625331812646233D-01, & +8.8204867223354833D-01, & +2.2221324964361449D-02, & +1.2088451318140349D-02, & +1.2750943030216850D+00, & +6.5487468521633574D-01, & +1.6473243548212180D-01, & +6.4244094276971109D-01, & +1.0075305765438660D+00, & +3.2695517365467008D-01, & +3.4538816017831181D-01, & +8.4530783837131718D-01, & +2.6793917191534039D-01, & +4.1167148387782809D-01, & +7.3286777366837230D-01, & +2.0165584821582411D-01, & +8.3608281383074101D-01, & +9.7375794521953263D-01, & +4.8136607095928219D-01, & +5.9519264227958080D-01, & +6.4953705136764595D-01, & +6.7618762481481709D-01, & +2.3254758802226480D-01, & +4.5471549751211121D-01, & +1.9936248028938069D-01, & +3.3218193673422552D-01, & +3.7823189169112570D-01, & +9.9728131577419957D-02, & +9.8304494035037460D-01, & +7.5610809968448423D-01, & +4.4297338640403672D-01, & +6.0516873235701607D-01, & +1.1732795506024030D+00, & +7.1957244803166864D-01, & +5.0355240691445868D-01, & +8.9668048897477137D-01, & +3.0589803950585209D-01, & +6.5888323539286620D-01, & +3.0146344334154529D-01, & +1.5056721102744461D-01, & +1.2894222375675779D+00, & +6.1246453109936005D-01, & +7.5833643057994404D-01, & +9.7842114980976291D-01, & +4.9778147794615712D-01, & +9.9938135774918690D-01, & +2.8414688478625982D-01, & +2.5673655077691432D-01, & +9.2575397942057647D-01, & +5.5092683856146663D-01, & +5.2313556054509897D-05, & +6.5897402564536967D-01, & +2.1178692213810329D-05, & +7.3492248268320243D-05, & +0.0000000000000000D+00, & +0.0000000000000000D+00/) +i0 = 1 +n0 = 21 +pp = 0 +dmin = -0.0000000000000000D+00 +sigma = 0.0000000000000000D+00 +desig = 0.0000000000000000D+00 +qmax = 2.1637041623952107D+00 +nFail = 0 +iter = 2 +nDiv = 40 +ttype = 0 +dmin1 = 0.0000000000000000D+00 +dmin2 = 0.0000000000000000D+00 +dn = 0.0000000000000000D+00 +dn1 = 0.0000000000000000D+00 +dn2 = 0.0000000000000000D+00 +g = 0.0000000000000000D+00 +tau = 0.0000000000000000D+00 + +print *, "Starting Dlasq3" +open(unit = 4, file = "gen4tests.txt") +open(unit = 5, file = "gen5tests.txt") +call Dlasq3(i0, n0, z, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ieee, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau) +close(4) +close(5) + +print *, "Done calling dlasq3" +print *, Z(1:n) + +print *, I0, N0, PP +print *, DMIN, DESIG, SIGMA, QMAX +print *, NFAIL, ITER, NDIV, TTYPE +print *, DMIN1, DMIN2, DN, DN1, DN2, G, TAU + +end \ No newline at end of file diff --git a/lapack/internal/testdata/dlasqtest/testdlasq4.f90 b/lapack/internal/testdata/dlasqtest/testdlasq4.f90 new file mode 100644 index 00000000..3c84983a --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/testdlasq4.f90 @@ -0,0 +1,435 @@ +program testdlasq4 +implicit none + +! Dlasq4 tests +integer :: i0, n0, pp, ttype, iter, nDiv, n, n0in +real(kind=8), dimension(401) :: z +real(kind=8) :: dmin, desig, qmax, dmin1, dmin2, dn, dn1, dn2, g, tau, sigma +logical :: ieee + +z(1:401) = (/2.9266499599402414D+02, & +2.9276699640004830D+02, & +2.9210200041216615D+02, & +2.9171973344922628D+02, & +2.9254120660184350D+02, & +2.9246923723528141D+02, & +2.8739845025761718D+02, & +2.8713781898215319D+02, & +2.9216230331620721D+02, & +2.9216609319427272D+02, & +2.9037912623973870D+02, & +2.9019341222762625D+02, & +2.9184732870824223D+02, & +2.9211597271231784D+02, & +2.9133173969911888D+02, & +2.9116703928303986D+02, & +2.9158395177813247D+02, & +2.9142053084921997D+02, & +2.8936184155474774D+02, & +2.9014388604362898D+02, & +2.9216722380092682D+02, & +2.9216917065163557D+02, & +2.9033857172870131D+02, & +2.9017428768626024D+02, & +2.9187084534700494D+02, & +2.9185392666684271D+02, & +2.8851014988393416D+02, & +2.8849290783118727D+02, & +2.9182506564169046D+02, & +2.9184679532940385D+02, & +2.9022222656964715D+02, & +2.9051820223150668D+02, & +2.9219746119018231D+02, & +2.9219997046052623D+02, & +2.9076912988009974D+02, & +2.9110108536012547D+02, & +2.9226281758828725D+02, & +2.9246883105892533D+02, & +2.9221612201279271D+02, & +2.9059157967819368D+02, & +2.9112833071623868D+02, & +2.9210680427275844D+02, & +2.9199887004058536D+02, & +2.9151030826460186D+02, & +2.9154564759046622D+02, & +2.9212462005167004D+02, & +2.9212108612522559D+02, & +2.9225720737270348D+02, & +2.9226471402909704D+02, & +2.9186949422820902D+02, & +2.9179442772569342D+02, & +2.9025839700680774D+02, & +2.9028281327393216D+02, & +2.9168280284451140D+02, & +2.9168036127921908D+02, & +2.9115346030764749D+02, & +2.9115401102000044D+02, & +2.9212282665919003D+02, & +2.9212277159409672D+02, & +2.9212554020600300D+02, & +2.9212559651286460D+02, & +2.9050907549403615D+02, & +2.9050344542208029D+02, & +2.9211004769628386D+02, & +2.9211127836880860D+02, & +2.9159257985266015D+02, & +2.9158027318883302D+02, & +2.9042716308833894D+02, & +2.9043622253245718D+02, & +2.9134221002346220D+02, & +2.9134130414047053D+02, & +2.9193179671375327D+02, & +2.9193426987096007D+02, & +2.9145366956406895D+02, & +2.9145119646828226D+02, & +2.9144876630819033D+02, & +2.9145122608379586D+02, & +2.9058395601500280D+02, & +2.9055935887314877D+02, & +2.9123982459393329D+02, & +2.9125037059550806D+02, & +2.9111624624209884D+02, & +2.9110570030194424D+02, & +2.9250004994137356D+02, & +2.9254994096967755D+02, & +2.9166071282413282D+02, & +2.9116180260251298D+02, & +2.8862845048087325D+02, & +2.8925662460652461D+02, & +2.9012609983518610D+02, & +2.9010672249354360D+02, & +2.9142999275190090D+02, & +2.9150806548221971D+02, & +2.9078477842534176D+02, & +2.8840517363552317D+02, & +2.8946267131307206D+02, & +2.9189614533792309D+02, & +2.9232617409967031D+02, & +2.9223702224333306D+02, & +2.9149978725880743D+02, & +2.9168777367421643D+02, & +2.9213296087125275D+02, & +2.9211416223585388D+02, & +2.9151431726536367D+02, & +2.9159900781717892D+02, & +2.9215362494632291D+02, & +2.9214515589728342D+02, & +2.9229900293632022D+02, & +2.9231644811476662D+02, & +2.9119079594655176D+02, & +2.9016344223508082D+02, & +2.9040052826233938D+02, & +2.9146756071890462D+02, & +2.9216592215429023D+02, & +2.9212317137116514D+02, & +2.9220217331561315D+02, & +2.9227234439098311D+02, & +2.9210931773273273D+02, & +2.9139146663504778D+02, & +2.9047426145779627D+02, & +2.9113243832972501D+02, & +2.9163901100086372D+02, & +2.9155399887833846D+02, & +2.9145039523229758D+02, & +2.9151950918932886D+02, & +2.9116352441156198D+02, & +2.9094410515950784D+02, & +2.9056083843332891D+02, & +2.9097140423254604D+02, & +2.9185385310744653D+02, & +2.9181279658894493D+02, & +2.9031697123096876D+02, & +2.9033298229128292D+02, & +2.9212507489852788D+02, & +2.9212491479406674D+02, & +2.9123248207180859D+02, & +2.9123278004625678D+02, & +2.9210890357464513D+02, & +2.9210887378334229D+02, & +2.9240010366769212D+02, & +2.9240021314868147D+02, & +2.9212046105624000D+02, & +2.9212035158139264D+02, & +2.9215242607939217D+02, & +2.9215256473001551D+02, & +2.9086373488934720D+02, & +2.9084987044121846D+02, & +2.9162085042968522D+02, & +2.9163097873649599D+02, & +2.9113228736441005D+02, & +2.9112215911901944D+02, & +2.9210393504686402D+02, & +2.9211255232953414D+02, & +2.9191445519642213D+02, & +2.9182828243114074D+02, & +2.9127013482394887D+02, & +2.9129823908392501D+02, & +2.9220880435635905D+02, & +2.9220599393650343D+02, & +2.9144676491963560D+02, & +2.9145286023012017D+02, & +2.9148058174349006D+02, & +2.9147448649442555D+02, & +2.9186619188590822D+02, & +2.9187731897876392D+02, & +2.9151148084374620D+02, & +2.9150035381231066D+02, & +2.9224292392669071D+02, & +2.9224832614828313D+02, & +2.9140236136264468D+02, & +2.9134833920814032D+02, & +2.9241531971951883D+02, & +2.9247972954055604D+02, & +2.9164613863843044D+02, & +2.8920404894780614D+02, & +2.8913485112658549D+02, & +2.9142701775363003D+02, & +2.9213449277295280D+02, & +2.9191925854858397D+02, & +2.9217029610406047D+02, & +2.9224915292105180D+02, & +2.9220325626287905D+02, & +2.9212439945202976D+02, & +2.9057154227612733D+02, & +2.9093384291672965D+02, & +2.9183595231931184D+02, & +2.9179972231667176D+02, & +2.9133916987034183D+02, & +2.9135453536038978D+02, & +2.9047085843212886D+02, & +2.9031720414585078D+02, & +2.9113106705127024D+02, & +2.9119455617800747D+02, & +2.9230127009862616D+02, & +2.9229492119209442D+02, & +2.9098170102485551D+02, & +2.9110028345622749D+02, & +2.9215236246918653D+02, & +2.9215215113995436D+02, & +2.9124650182241129D+02, & +2.9124684419934567D+02, & +2.9216244260160767D+02, & +2.9216240837005626D+02, & +2.9314769094184447D+02, & +2.9314772207133655D+02, & +2.9212215646682506D+02, & +2.9212184517804621D+02, & +2.9224739389310008D+02, & +2.9224802593241526D+02, & +2.8978611958992855D+02, & +2.8915408641678846D+02, & +2.9118533307571403D+02, & +2.9194553410039072D+02, & +2.9244688594134544D+02, & +2.9237086584501975D+02, & +2.9189894464487475D+02, & +2.9210832103555418D+02, & +2.9227685116407457D+02, & +2.9225842459914986D+02, & +2.9224821267514392D+02, & +2.9226591109467802D+02, & +2.9158625025645608D+02, & +2.9140926612253548D+02, & +2.9125298964526195D+02, & +2.9136239316241648D+02, & +2.9182040805585694D+02, & +2.9171100460012258D+02, & +2.9126693393315793D+02, & +2.9130800749967943D+02, & +2.9084722625682167D+02, & +2.9043649120580767D+02, & +2.9153791610078673D+02, & +2.9210440912405335D+02, & +2.9188686486416555D+02, & +2.9138068978583891D+02, & +2.9158124399039616D+02, & +2.9213540811751852D+02, & +2.9211624446790427D+02, & +2.9138960755567365D+02, & +2.9060415959100914D+02, & +2.9118025885063923D+02, & +2.9132902926505932D+02, & +2.9120918643494110D+02, & +2.9222955158764825D+02, & +2.9236106160611405D+02, & +2.9219941546106151D+02, & +2.9167905448737707D+02, & +2.8956733560159137D+02, & +2.9016660738228080D+02, & +2.9069372888915495D+02, & +2.9058385568123452D+02, & +2.9219861470697771D+02, & +2.9223599112669444D+02, & +2.9150234673408067D+02, & +2.9112858259833354D+02, & +2.9011809831967531D+02, & +2.9046138673473865D+02, & +2.9176526297220903D+02, & +2.9173093419212285D+02, & +2.9150067445343569D+02, & +2.9152418894132262D+02, & +2.9197021328944544D+02, & +2.9194669886297868D+02, & +2.9168012546172463D+02, & +2.9169701864791432D+02, & +2.9061916960844030D+02, & +2.9045023836074438D+02, & +2.9212529304266053D+02, & +2.9217230349727680D+02, & +2.9156357220873417D+02, & +2.9093467723991887D+02, & +2.9015918793416472D+02, & +2.9095983823965622D+02, & +2.9124303667219704D+02, & +2.9116297170306802D+02, & +2.9162557939634507D+02, & +2.9193291492830070D+02, & +2.9138731414547760D+02, & +2.9079978674942083D+02, & +2.9159254111122891D+02, & +2.9228695093326087D+02, & +2.9225423965335352D+02, & +2.9126542837357596D+02, & +2.9173807466948557D+02, & +2.9270696227984581D+02, & +2.9274075480094893D+02, & +2.9210759999419366D+02, & +2.9091701924155882D+02, & +2.9163130710260498D+02, & +2.9157158980248664D+02, & +2.9031984685457667D+02, & +2.8939239820067894D+02, & +2.9070124438246870D+02, & +2.9196350995833507D+02, & +2.9189730956351508D+02, & +2.9047434516138509D+02, & +2.9050934070611282D+02, & +2.9179387236503283D+02, & +2.9179037287198020D+02, & +2.9197909575321057D+02, & +2.9198343084479546D+02, & +2.9146450345905629D+02, & +2.9146016842889151D+02, & +2.9233889755268928D+02, & +2.9234209014701219D+02, & +2.9032302536354865D+02, & +2.8837665454569191D+02, & +2.8923259893670223D+02, & +2.9119948081590582D+02, & +2.9158422265927129D+02, & +2.9138706789415261D+02, & +2.9131767302238063D+02, & +2.9147948119882238D+02, & +2.9186937598758146D+02, & +2.9170756787255982D+02, & +2.9181460198203825D+02, & +2.9210008868832023D+02, & +2.9132088639794199D+02, & +2.9113460155819826D+02, & +2.9159448593680958D+02, & +2.9214172380575934D+02, & +2.9182660907964311D+02, & +2.8938570202792107D+02, & +2.8829979954353007D+02, & +2.9064250900128923D+02, & +2.9110347860364448D+02, & +2.9039527564479215D+02, & +2.9152783923893156D+02, & +2.9213818222324863D+02, & +2.9211881276563861D+02, & +2.9133414472425187D+02, & +2.9125375097531855D+02, & +2.9190226937530139D+02, & +2.9164903795105636D+02, & +2.8851961249369930D+02, & +2.8835729910731652D+02, & +2.9144629542849515D+02, & +2.9171485796658368D+02, & +2.9126891989861593D+02, & +2.9051052150188838D+02, & +2.9113570969073521D+02, & +2.9141652614094619D+02, & +2.9133186866181995D+02, & +2.8912484642922516D+02, & +2.8915669391948876D+02, & +2.9117142770169869D+02, & +2.9117110928821620D+02, & +2.9183490795481288D+02, & +2.9183646161652371D+02, & +2.9254379194824975D+02, & +2.9254363658822064D+02, & +2.9192127768678108D+02, & +2.9192154096878102D+02, & +2.9151073810022524D+02, & +2.9151047487964541D+02, & +2.9013993357169915D+02, & +2.9014000572685774D+02, & +2.9145714571416084D+02, & +2.9145713856006512D+02, & +2.9196091751473017D+02, & +2.9196093255283131D+02, & +2.9195731369267685D+02, & +2.9195729871599588D+02, & +2.9149460806187619D+02, & +2.9149461579988633D+02, & +2.9034687539457741D+02, & +2.9034679862867739D+02, & +2.9010765498373922D+02, & +2.9010767881379803D+02, & +2.8967492890608241D+02, & +2.8967469674750663D+02, & +2.9215189060671338D+02, & +2.9215194287124120D+02, & +2.8956132995364590D+02, & +2.8950907156783751D+02, & +2.9210783379750950D+02, & +2.9211890340058585D+02, & +2.9139896954309916D+02, & +2.9128827357375536D+02, & +2.9190012628763964D+02, & +2.9212457714005234D+02, & +2.9221336158434212D+02, & +2.9217879707919576D+02, & +2.9127472708852724D+02, & +2.9132783649002283D+02, & +2.9227509889951233D+02, & +2.9226978796550475D+02, & +2.9142078378447616D+02, & +2.9142906715955786D+02, & +2.9017517054475991D+02, & +2.8992337408144391D+02, & +2.8477362931531121D+02, & +2.8514676291150971D+02, & +2.8393423954726200D+02, & +2.8313625395453965D+02, & +2.8449999402409759D+02, & +2.8534282615303522D+02, & +2.8523140662657408D+02, & +2.8739845025761718D+02, & +2.8713781898215319D+02, & +0.0000000000000000D+00/) +i0 = 1 +n0 = 100 +pp = 1 +n0in = 100 +dmin = 7.9798559272231942D+282 +dmin1 = 7.9798559272231942D+282 +dmin2 = 2.3215857579138407D+285 +dn = 2.3140662657409930D+284 +dn1 = 7.9798559272231942D+282 +dn2 = 8.2833136615500372D+288 +g = 2.5000000000000000D-01 +tau = 6.1420124051338430D+283 +ttype = -4 + +ieee = .True. + +print *, "Starting Dlasq4" + +call Dlasq4(i0, n0, z, pp, n0in, dmin, dmin1, dmin2, dn, dn1, dn2, tau, ttype, g) + +print *, "Done calling dlasq4" +print *, "tau = ", tau +print *, tau, ttype, g + +end \ No newline at end of file diff --git a/lapack/internal/testdata/dlasqtest/xerbla.f b/lapack/internal/testdata/dlasqtest/xerbla.f new file mode 100644 index 00000000..3e93bc4e --- /dev/null +++ b/lapack/internal/testdata/dlasqtest/xerbla.f @@ -0,0 +1,99 @@ +*> \brief \b XERBLA +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download XERBLA + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE XERBLA( SRNAME, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER*(*) SRNAME +* INTEGER INFO +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> XERBLA is an error handler for the LAPACK routines. +*> It is called by an LAPACK routine if an input parameter has an +*> invalid value. A message is printed and execution stops. +*> +*> Installers may consider modifying the STOP statement in order to +*> call system-specific exception-handling facilities. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] SRNAME +*> \verbatim +*> SRNAME is CHARACTER*(*) +*> The name of the routine which called XERBLA. +*> \endverbatim +*> +*> \param[in] INFO +*> \verbatim +*> INFO is INTEGER +*> The position of the invalid parameter in the parameter list +*> of the calling routine. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE XERBLA( SRNAME, INFO ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER*(*) SRNAME + INTEGER INFO +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LEN_TRIM +* .. +* .. Executable Statements .. +* + WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO +* + STOP +* + 9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ', + $ 'an illegal value' ) +* +* End of XERBLA +* + END diff --git a/lapack/internal/testdata/dsterftest/Makefile b/lapack/internal/testdata/dsterftest/Makefile new file mode 100644 index 00000000..7d22727a --- /dev/null +++ b/lapack/internal/testdata/dsterftest/Makefile @@ -0,0 +1,20 @@ +FC = gfortran +FFLAGS = -O2 + +targets = testdsterf +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 + +default : $(targets) +.PHONY : default + +testdsterf : testdsterf.o $(objects) + +% : %.o + $(FC) $(FFLAGS) $^ -o $@ + +%.o : %.f90 + $(FC) $(FFLAGS) -c -o $@ $< + +clean : + rm -f *.o $(targets) *.txt +.PHONY : clean \ No newline at end of file diff --git a/lapack/internal/testdata/dsterftest/disnan.f b/lapack/internal/testdata/dsterftest/disnan.f new file mode 100644 index 00000000..355b8279 --- /dev/null +++ b/lapack/internal/testdata/dsterftest/disnan.f @@ -0,0 +1,80 @@ +*> \brief \b DISNAN tests input for NaN. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DISNAN + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* LOGICAL FUNCTION DISNAN( DIN ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DIN +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DISNAN returns .TRUE. if its argument is NaN, and .FALSE. +*> otherwise. To be replaced by the Fortran 2003 intrinsic in the +*> future. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] DIN +*> \verbatim +*> DIN is DOUBLE PRECISION +*> Input to test for NaN. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION DISNAN( DIN ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN +* .. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL DLAISNAN + EXTERNAL DLAISNAN +* .. +* .. Executable Statements .. + DISNAN = DLAISNAN(DIN,DIN) + RETURN + END diff --git a/lapack/internal/testdata/dsterftest/dlae2.f b/lapack/internal/testdata/dsterftest/dlae2.f new file mode 100644 index 00000000..302eeaa1 --- /dev/null +++ b/lapack/internal/testdata/dsterftest/dlae2.f @@ -0,0 +1,185 @@ +*> \brief \b DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAE2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAE2( A, B, C, RT1, RT2 ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION A, B, C, RT1, RT2 +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix +*> [ A B ] +*> [ B C ]. +*> On return, RT1 is the eigenvalue of larger absolute value, and RT2 +*> is the eigenvalue of smaller absolute value. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION +*> The (1,1) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is DOUBLE PRECISION +*> The (1,2) and (2,1) elements of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[in] C +*> \verbatim +*> C is DOUBLE PRECISION +*> The (2,2) element of the 2-by-2 matrix. +*> \endverbatim +*> +*> \param[out] RT1 +*> \verbatim +*> RT1 is DOUBLE PRECISION +*> The eigenvalue of larger absolute value. +*> \endverbatim +*> +*> \param[out] RT2 +*> \verbatim +*> RT2 is DOUBLE PRECISION +*> The eigenvalue of smaller absolute value. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> RT1 is accurate to a few ulps barring over/underflow. +*> +*> RT2 may be inaccurate if there is massive cancellation in the +*> determinant A*C-B*B; higher precision or correctly rounded or +*> correctly truncated arithmetic would be needed to compute RT2 +*> accurately in all cases. +*> +*> Overflow is possible only if RT1 is within a factor of 5 of overflow. +*> Underflow is harmless if the input data is 0 or exceeds +*> underflow_threshold / macheps. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DLAE2( A, B, C, RT1, RT2 ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B, C, RT1, RT2 +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) + DOUBLE PRECISION TWO + PARAMETER ( TWO = 2.0D0 ) + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION HALF + PARAMETER ( HALF = 0.5D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION AB, ACMN, ACMX, ADF, DF, RT, SM, TB +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SQRT +* .. +* .. Executable Statements .. +* +* Compute the eigenvalues +* + SM = A + C + DF = A - C + ADF = ABS( DF ) + TB = B + B + AB = ABS( TB ) + IF( ABS( A ).GT.ABS( C ) ) THEN + ACMX = A + ACMN = C + ELSE + ACMX = C + ACMN = A + END IF + IF( ADF.GT.AB ) THEN + RT = ADF*SQRT( ONE+( AB / ADF )**2 ) + ELSE IF( ADF.LT.AB ) THEN + RT = AB*SQRT( ONE+( ADF / AB )**2 ) + ELSE +* +* Includes case AB=ADF=0 +* + RT = AB*SQRT( TWO ) + END IF + IF( SM.LT.ZERO ) THEN + RT1 = HALF*( SM-RT ) +* +* Order of execution important. +* To get fully accurate smaller eigenvalue, +* next line needs to be executed in higher precision. +* + RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B + ELSE IF( SM.GT.ZERO ) THEN + RT1 = HALF*( SM+RT ) +* +* Order of execution important. +* To get fully accurate smaller eigenvalue, +* next line needs to be executed in higher precision. +* + RT2 = ( ACMX / RT1 )*ACMN - ( B / RT1 )*B + ELSE +* +* Includes case RT1 = RT2 = 0 +* + RT1 = HALF*RT + RT2 = -HALF*RT + END IF + RETURN +* +* End of DLAE2 +* + END diff --git a/lapack/internal/testdata/dsterftest/dlaisnan.f b/lapack/internal/testdata/dsterftest/dlaisnan.f new file mode 100644 index 00000000..58595c5c --- /dev/null +++ b/lapack/internal/testdata/dsterftest/dlaisnan.f @@ -0,0 +1,91 @@ +*> \brief \b DLAISNAN tests input for NaN by comparing two arguments for inequality. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAISNAN + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DIN1, DIN2 +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> This routine is not for general use. It exists solely to avoid +*> over-optimization in DISNAN. +*> +*> DLAISNAN checks for NaNs by comparing its two arguments for +*> inequality. NaN is the only floating-point value where NaN != NaN +*> returns .TRUE. To check for NaNs, pass the same variable as both +*> arguments. +*> +*> A compiler must assume that the two arguments are +*> not the same variable, and the test will not be optimized away. +*> Interprocedural or whole-program optimization may delete this +*> test. The ISNAN functions will be replaced by the correct +*> Fortran 03 intrinsic once the intrinsic is widely available. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] DIN1 +*> \verbatim +*> DIN1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] DIN2 +*> \verbatim +*> DIN2 is DOUBLE PRECISION +*> Two numbers to compare for inequality. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DIN1, DIN2 +* .. +* +* ===================================================================== +* +* .. Executable Statements .. + DLAISNAN = (DIN1.NE.DIN2) + RETURN + END diff --git a/lapack/internal/testdata/dsterftest/dlamch.f b/lapack/internal/testdata/dsterftest/dlamch.f new file mode 100644 index 00000000..25c2c8e6 --- /dev/null +++ b/lapack/internal/testdata/dsterftest/dlamch.f @@ -0,0 +1,193 @@ +*> \brief \b DLAMCH +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAMCH determines double precision machine parameters. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CMACH +*> \verbatim +*> Specifies the value to be returned by DLAMCH: +*> = 'E' or 'e', DLAMCH := eps +*> = 'S' or 's , DLAMCH := sfmin +*> = 'B' or 'b', DLAMCH := base +*> = 'P' or 'p', DLAMCH := eps*base +*> = 'N' or 'n', DLAMCH := t +*> = 'R' or 'r', DLAMCH := rnd +*> = 'M' or 'm', DLAMCH := emin +*> = 'U' or 'u', DLAMCH := rmin +*> = 'L' or 'l', DLAMCH := emax +*> = 'O' or 'o', DLAMCH := rmax +*> where +*> eps = relative machine precision +*> sfmin = safe minimum, such that 1/sfmin does not overflow +*> base = base of the machine +*> prec = eps*base +*> t = number of (base) digits in the mantissa +*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise +*> emin = minimum exponent before (gradual) underflow +*> rmin = underflow threshold - base**(emin-1) +*> emax = largest exponent before overflow +*> rmax = overflow threshold - (base**emax)*(1-eps) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CMACH +* .. +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION RND, EPS, SFMIN, SMALL, RMACH +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT, + $ MINEXPONENT, RADIX, TINY +* .. +* .. Executable Statements .. +* +* +* Assume rounding, not chopping. Always. +* + RND = ONE +* + IF( ONE.EQ.RND ) THEN + EPS = EPSILON(ZERO) * 0.5 + ELSE + EPS = EPSILON(ZERO) + END IF +* + IF( LSAME( CMACH, 'E' ) ) THEN + RMACH = EPS + ELSE IF( LSAME( CMACH, 'S' ) ) THEN + SFMIN = TINY(ZERO) + SMALL = ONE / HUGE(ZERO) + IF( SMALL.GE.SFMIN ) THEN +* +* Use SMALL plus a bit, to avoid the possibility of rounding +* causing overflow when computing 1/sfmin. +* + SFMIN = SMALL*( ONE+EPS ) + END IF + RMACH = SFMIN + ELSE IF( LSAME( CMACH, 'B' ) ) THEN + RMACH = RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'P' ) ) THEN + RMACH = EPS * RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'N' ) ) THEN + RMACH = DIGITS(ZERO) + ELSE IF( LSAME( CMACH, 'R' ) ) THEN + RMACH = RND + ELSE IF( LSAME( CMACH, 'M' ) ) THEN + RMACH = MINEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'U' ) ) THEN + RMACH = tiny(zero) + ELSE IF( LSAME( CMACH, 'L' ) ) THEN + RMACH = MAXEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'O' ) ) THEN + RMACH = HUGE(ZERO) + ELSE + RMACH = ZERO + END IF +* + DLAMCH = RMACH + RETURN +* +* End of DLAMCH +* + END +************************************************************************ +*> \brief \b DLAMC3 +*> \details +*> \b Purpose: +*> \verbatim +*> DLAMC3 is intended to force A and B to be stored prior to doing +*> the addition of A and B , for use in situations where optimizers +*> might hold one of these in a register. +*> \endverbatim +*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +*> \date November 2011 +*> \ingroup auxOTHERauxiliary +*> +*> \param[in] A +*> \verbatim +*> A is a DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is a DOUBLE PRECISION +*> The values A and B. +*> \endverbatim +*> + DOUBLE PRECISION FUNCTION DLAMC3( A, B ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2010 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* ===================================================================== +* +* .. Executable Statements .. +* + DLAMC3 = A + B +* + RETURN +* +* End of DLAMC3 +* + END +* +************************************************************************ diff --git a/lapack/internal/testdata/dsterftest/dlanst.f b/lapack/internal/testdata/dsterftest/dlanst.f new file mode 100644 index 00000000..213b06ad --- /dev/null +++ b/lapack/internal/testdata/dsterftest/dlanst.f @@ -0,0 +1,186 @@ +*> \brief \b DLANST returns the value of the 1-norm, or the Frobenius norm, or the infinity norm, or the element of largest absolute value of a real symmetric tridiagonal matrix. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLANST + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLANST( NORM, N, D, E ) +* +* .. Scalar Arguments .. +* CHARACTER NORM +* INTEGER N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ), E( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLANST returns the value of the one norm, or the Frobenius norm, or +*> the infinity norm, or the element of largest absolute value of a +*> real symmetric tridiagonal matrix A. +*> \endverbatim +*> +*> \return DLANST +*> \verbatim +*> +*> DLANST = ( max(abs(A(i,j))), NORM = 'M' or 'm' +*> ( +*> ( norm1(A), NORM = '1', 'O' or 'o' +*> ( +*> ( normI(A), NORM = 'I' or 'i' +*> ( +*> ( normF(A), NORM = 'F', 'f', 'E' or 'e' +*> +*> where norm1 denotes the one norm of a matrix (maximum column sum), +*> normI denotes the infinity norm of a matrix (maximum row sum) and +*> normF denotes the Frobenius norm of a matrix (square root of sum of +*> squares). Note that max(abs(A(i,j))) is not a consistent matrix norm. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] NORM +*> \verbatim +*> NORM is CHARACTER*1 +*> Specifies the value to be returned in DLANST as described +*> above. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The order of the matrix A. N >= 0. When N = 0, DLANST is +*> set to zero. +*> \endverbatim +*> +*> \param[in] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> The diagonal elements of A. +*> \endverbatim +*> +*> \param[in] E +*> \verbatim +*> E is DOUBLE PRECISION array, dimension (N-1) +*> The (n-1) sub-diagonal or super-diagonal elements of A. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLANST( NORM, N, D, E ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER NORM + INTEGER N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION ANORM, SCALE, SUM +* .. +* .. External Functions .. + LOGICAL LSAME, DISNAN + EXTERNAL LSAME, DISNAN +* .. +* .. External Subroutines .. + EXTERNAL DLASSQ +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SQRT +* .. +* .. Executable Statements .. +* + IF( N.LE.0 ) THEN + ANORM = ZERO + ELSE IF( LSAME( NORM, 'M' ) ) THEN +* +* Find max(abs(A(i,j))). +* + ANORM = ABS( D( N ) ) + DO 10 I = 1, N - 1 + SUM = ABS( D( I ) ) + IF( ANORM .LT. SUM .OR. DISNAN( SUM ) ) ANORM = SUM + SUM = ABS( E( I ) ) + IF( ANORM .LT. SUM .OR. DISNAN( SUM ) ) ANORM = SUM + 10 CONTINUE + ELSE IF( LSAME( NORM, 'O' ) .OR. NORM.EQ.'1' .OR. + $ LSAME( NORM, 'I' ) ) THEN +* +* Find norm1(A). +* + IF( N.EQ.1 ) THEN + ANORM = ABS( D( 1 ) ) + ELSE + ANORM = ABS( D( 1 ) )+ABS( E( 1 ) ) + SUM = ABS( E( N-1 ) )+ABS( D( N ) ) + IF( ANORM .LT. SUM .OR. DISNAN( SUM ) ) ANORM = SUM + DO 20 I = 2, N - 1 + SUM = ABS( D( I ) )+ABS( E( I ) )+ABS( E( I-1 ) ) + IF( ANORM .LT. SUM .OR. DISNAN( SUM ) ) ANORM = SUM + 20 CONTINUE + END IF + ELSE IF( ( LSAME( NORM, 'F' ) ) .OR. ( LSAME( NORM, 'E' ) ) ) THEN +* +* Find normF(A). +* + SCALE = ZERO + SUM = ONE + IF( N.GT.1 ) THEN + CALL DLASSQ( N-1, E, 1, SCALE, SUM ) + SUM = 2*SUM + END IF + CALL DLASSQ( N, D, 1, SCALE, SUM ) + ANORM = SCALE*SQRT( SUM ) + END IF +* + DLANST = ANORM + RETURN +* +* End of DLANST +* + END diff --git a/lapack/internal/testdata/dsterftest/dlapy2.f b/lapack/internal/testdata/dsterftest/dlapy2.f new file mode 100644 index 00000000..d43b0d5d --- /dev/null +++ b/lapack/internal/testdata/dsterftest/dlapy2.f @@ -0,0 +1,104 @@ +*> \brief \b DLAPY2 returns sqrt(x2+y2). +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAPY2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAPY2( X, Y ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION X, Y +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary +*> overflow. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] X +*> \verbatim +*> X is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] Y +*> \verbatim +*> Y is DOUBLE PRECISION +*> X and Y specify the values x and y. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAPY2( X, Y ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION X, Y +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION W, XABS, YABS, Z +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + XABS = ABS( X ) + YABS = ABS( Y ) + W = MAX( XABS, YABS ) + Z = MIN( XABS, YABS ) + IF( Z.EQ.ZERO ) THEN + DLAPY2 = W + ELSE + DLAPY2 = W*SQRT( ONE+( Z / W )**2 ) + END IF + RETURN +* +* End of DLAPY2 +* + END diff --git a/lapack/internal/testdata/dsterftest/dlascl.f b/lapack/internal/testdata/dsterftest/dlascl.f new file mode 100644 index 00000000..9b9b33c0 --- /dev/null +++ b/lapack/internal/testdata/dsterftest/dlascl.f @@ -0,0 +1,364 @@ +*> \brief \b DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASCL + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER TYPE +* INTEGER INFO, KL, KU, LDA, M, N +* DOUBLE PRECISION CFROM, CTO +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASCL multiplies the M by N real matrix A by the real scalar +*> CTO/CFROM. This is done without over/underflow as long as the final +*> result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that +*> A may be full, upper triangular, lower triangular, upper Hessenberg, +*> or banded. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] TYPE +*> \verbatim +*> TYPE is CHARACTER*1 +*> TYPE indices the storage type of the input matrix. +*> = 'G': A is a full matrix. +*> = 'L': A is a lower triangular matrix. +*> = 'U': A is an upper triangular matrix. +*> = 'H': A is an upper Hessenberg matrix. +*> = 'B': A is a symmetric band matrix with lower bandwidth KL +*> and upper bandwidth KU and with the only the lower +*> half stored. +*> = 'Q': A is a symmetric band matrix with lower bandwidth KL +*> and upper bandwidth KU and with the only the upper +*> half stored. +*> = 'Z': A is a band matrix with lower bandwidth KL and upper +*> bandwidth KU. See DGBTRF for storage details. +*> \endverbatim +*> +*> \param[in] KL +*> \verbatim +*> KL is INTEGER +*> The lower bandwidth of A. Referenced only if TYPE = 'B', +*> 'Q' or 'Z'. +*> \endverbatim +*> +*> \param[in] KU +*> \verbatim +*> KU is INTEGER +*> The upper bandwidth of A. Referenced only if TYPE = 'B', +*> 'Q' or 'Z'. +*> \endverbatim +*> +*> \param[in] CFROM +*> \verbatim +*> CFROM is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] CTO +*> \verbatim +*> CTO is DOUBLE PRECISION +*> +*> The matrix A is multiplied by CTO/CFROM. A(I,J) is computed +*> without over/underflow if the final result CTO*A(I,J)/CFROM +*> can be represented without over/underflow. CFROM must be +*> nonzero. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. M >= 0. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in,out] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> The matrix to be multiplied by CTO/CFROM. See TYPE for the +*> storage type. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> 0 - successful exit +*> <0 - if INFO = -i, the i-th argument had an illegal value. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER TYPE + INTEGER INFO, KL, KU, LDA, M, N + DOUBLE PRECISION CFROM, CTO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + LOGICAL DONE + INTEGER I, ITYPE, J, K1, K2, K3, K4 + DOUBLE PRECISION BIGNUM, CFROM1, CFROMC, CTO1, CTOC, MUL, SMLNUM +* .. +* .. External Functions .. + LOGICAL LSAME, DISNAN + DOUBLE PRECISION DLAMCH + EXTERNAL LSAME, DLAMCH, DISNAN +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input arguments +* + INFO = 0 +* + IF( LSAME( TYPE, 'G' ) ) THEN + ITYPE = 0 + ELSE IF( LSAME( TYPE, 'L' ) ) THEN + ITYPE = 1 + ELSE IF( LSAME( TYPE, 'U' ) ) THEN + ITYPE = 2 + ELSE IF( LSAME( TYPE, 'H' ) ) THEN + ITYPE = 3 + ELSE IF( LSAME( TYPE, 'B' ) ) THEN + ITYPE = 4 + ELSE IF( LSAME( TYPE, 'Q' ) ) THEN + ITYPE = 5 + ELSE IF( LSAME( TYPE, 'Z' ) ) THEN + ITYPE = 6 + ELSE + ITYPE = -1 + END IF +* + IF( ITYPE.EQ.-1 ) THEN + INFO = -1 + ELSE IF( CFROM.EQ.ZERO .OR. DISNAN(CFROM) ) THEN + INFO = -4 + ELSE IF( DISNAN(CTO) ) THEN + INFO = -5 + ELSE IF( M.LT.0 ) THEN + INFO = -6 + ELSE IF( N.LT.0 .OR. ( ITYPE.EQ.4 .AND. N.NE.M ) .OR. + $ ( ITYPE.EQ.5 .AND. N.NE.M ) ) THEN + INFO = -7 + ELSE IF( ITYPE.LE.3 .AND. LDA.LT.MAX( 1, M ) ) THEN + INFO = -9 + ELSE IF( ITYPE.GE.4 ) THEN + IF( KL.LT.0 .OR. KL.GT.MAX( M-1, 0 ) ) THEN + INFO = -2 + ELSE IF( KU.LT.0 .OR. KU.GT.MAX( N-1, 0 ) .OR. + $ ( ( ITYPE.EQ.4 .OR. ITYPE.EQ.5 ) .AND. KL.NE.KU ) ) + $ THEN + INFO = -3 + ELSE IF( ( ITYPE.EQ.4 .AND. LDA.LT.KL+1 ) .OR. + $ ( ITYPE.EQ.5 .AND. LDA.LT.KU+1 ) .OR. + $ ( ITYPE.EQ.6 .AND. LDA.LT.2*KL+KU+1 ) ) THEN + INFO = -9 + END IF + END IF +* + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASCL', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.EQ.0 .OR. M.EQ.0 ) + $ RETURN +* +* Get machine parameters +* + SMLNUM = DLAMCH( 'S' ) + BIGNUM = ONE / SMLNUM +* + CFROMC = CFROM + CTOC = CTO +* + 10 CONTINUE + CFROM1 = CFROMC*SMLNUM + IF( CFROM1.EQ.CFROMC ) THEN +! CFROMC is an inf. Multiply by a correctly signed zero for +! finite CTOC, or a NaN if CTOC is infinite. + MUL = CTOC / CFROMC + DONE = .TRUE. + CTO1 = CTOC + ELSE + CTO1 = CTOC / BIGNUM + IF( CTO1.EQ.CTOC ) THEN +! CTOC is either 0 or an inf. In both cases, CTOC itself +! serves as the correct multiplication factor. + MUL = CTOC + DONE = .TRUE. + CFROMC = ONE + ELSE IF( ABS( CFROM1 ).GT.ABS( CTOC ) .AND. CTOC.NE.ZERO ) THEN + MUL = SMLNUM + DONE = .FALSE. + CFROMC = CFROM1 + ELSE IF( ABS( CTO1 ).GT.ABS( CFROMC ) ) THEN + MUL = BIGNUM + DONE = .FALSE. + CTOC = CTO1 + ELSE + MUL = CTOC / CFROMC + DONE = .TRUE. + END IF + END IF +* + IF( ITYPE.EQ.0 ) THEN +* +* Full matrix +* + DO 30 J = 1, N + DO 20 I = 1, M + A( I, J ) = A( I, J )*MUL + 20 CONTINUE + 30 CONTINUE +* + ELSE IF( ITYPE.EQ.1 ) THEN +* +* Lower triangular matrix +* + DO 50 J = 1, N + DO 40 I = J, M + A( I, J ) = A( I, J )*MUL + 40 CONTINUE + 50 CONTINUE +* + ELSE IF( ITYPE.EQ.2 ) THEN +* +* Upper triangular matrix +* + DO 70 J = 1, N + DO 60 I = 1, MIN( J, M ) + A( I, J ) = A( I, J )*MUL + 60 CONTINUE + 70 CONTINUE +* + ELSE IF( ITYPE.EQ.3 ) THEN +* +* Upper Hessenberg matrix +* + DO 90 J = 1, N + DO 80 I = 1, MIN( J+1, M ) + A( I, J ) = A( I, J )*MUL + 80 CONTINUE + 90 CONTINUE +* + ELSE IF( ITYPE.EQ.4 ) THEN +* +* Lower half of a symmetric band matrix +* + K3 = KL + 1 + K4 = N + 1 + DO 110 J = 1, N + DO 100 I = 1, MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 100 CONTINUE + 110 CONTINUE +* + ELSE IF( ITYPE.EQ.5 ) THEN +* +* Upper half of a symmetric band matrix +* + K1 = KU + 2 + K3 = KU + 1 + DO 130 J = 1, N + DO 120 I = MAX( K1-J, 1 ), K3 + A( I, J ) = A( I, J )*MUL + 120 CONTINUE + 130 CONTINUE +* + ELSE IF( ITYPE.EQ.6 ) THEN +* +* Band matrix +* + K1 = KL + KU + 2 + K2 = KL + 1 + K3 = 2*KL + KU + 1 + K4 = KL + KU + 1 + M + DO 150 J = 1, N + DO 140 I = MAX( K1-J, K2 ), MIN( K3, K4-J ) + A( I, J ) = A( I, J )*MUL + 140 CONTINUE + 150 CONTINUE +* + END IF +* + IF( .NOT.DONE ) + $ GO TO 10 +* + RETURN +* +* End of DLASCL +* + END diff --git a/lapack/internal/testdata/dsterftest/dlasrt.f b/lapack/internal/testdata/dsterftest/dlasrt.f new file mode 100644 index 00000000..f5d0e6cd --- /dev/null +++ b/lapack/internal/testdata/dsterftest/dlasrt.f @@ -0,0 +1,303 @@ +*> \brief \b DLASRT sorts numbers in increasing or decreasing order. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASRT + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASRT( ID, N, D, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER ID +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> Sort the numbers in D in increasing order (if ID = 'I') or +*> in decreasing order (if ID = 'D' ). +*> +*> Use Quick Sort, reverting to Insertion sort on arrays of +*> size <= 20. Dimension of STACK limits N to about 2**32. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] ID +*> \verbatim +*> ID is CHARACTER*1 +*> = 'I': sort D in increasing order; +*> = 'D': sort D in decreasing order. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The length of the array D. +*> \endverbatim +*> +*> \param[in,out] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> On entry, the array to be sorted. +*> On exit, D has been sorted into increasing order +*> (D(1) <= ... <= D(N) ) or into decreasing order +*> (D(1) >= ... >= D(N) ), depending on ID. +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DLASRT( ID, N, D, INFO ) +* +* -- LAPACK computational routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER ID + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + INTEGER SELECT + PARAMETER ( SELECT = 20 ) +* .. +* .. Local Scalars .. + INTEGER DIR, ENDD, I, J, START, STKPNT + DOUBLE PRECISION D1, D2, D3, DMNMX, TMP +* .. +* .. Local Arrays .. + INTEGER STACK( 2, 32 ) +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Executable Statements .. +* +* Test the input paramters. +* + INFO = 0 + DIR = -1 + IF( LSAME( ID, 'D' ) ) THEN + DIR = 0 + ELSE IF( LSAME( ID, 'I' ) ) THEN + DIR = 1 + END IF + IF( DIR.EQ.-1 ) THEN + INFO = -1 + ELSE IF( N.LT.0 ) THEN + INFO = -2 + END IF + IF( INFO.NE.0 ) THEN + CALL XERBLA( 'DLASRT', -INFO ) + RETURN + END IF +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + STKPNT = 1 + STACK( 1, 1 ) = 1 + STACK( 2, 1 ) = N + 10 CONTINUE + START = STACK( 1, STKPNT ) + ENDD = STACK( 2, STKPNT ) + STKPNT = STKPNT - 1 + IF( ENDD-START.LE.SELECT .AND. ENDD-START.GT.0 ) THEN +* +* Do Insertion sort on D( START:ENDD ) +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + DO 30 I = START + 1, ENDD + DO 20 J = I, START + 1, -1 + IF( D( J ).GT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 30 + END IF + 20 CONTINUE + 30 CONTINUE +* + ELSE +* +* Sort into increasing order +* + DO 50 I = START + 1, ENDD + DO 40 J = I, START + 1, -1 + IF( D( J ).LT.D( J-1 ) ) THEN + DMNMX = D( J ) + D( J ) = D( J-1 ) + D( J-1 ) = DMNMX + ELSE + GO TO 50 + END IF + 40 CONTINUE + 50 CONTINUE +* + END IF +* + ELSE IF( ENDD-START.GT.SELECT ) THEN +* +* Partition D( START:ENDD ) and stack parts, largest one first +* +* Choose partition entry as median of 3 +* + D1 = D( START ) + D2 = D( ENDD ) + I = ( START+ENDD ) / 2 + D3 = D( I ) + IF( D1.LT.D2 ) THEN + IF( D3.LT.D1 ) THEN + DMNMX = D1 + ELSE IF( D3.LT.D2 ) THEN + DMNMX = D3 + ELSE + DMNMX = D2 + END IF + ELSE + IF( D3.LT.D2 ) THEN + DMNMX = D2 + ELSE IF( D3.LT.D1 ) THEN + DMNMX = D3 + ELSE + DMNMX = D1 + END IF + END IF +* + IF( DIR.EQ.0 ) THEN +* +* Sort into decreasing order +* + I = START - 1 + J = ENDD + 1 + 60 CONTINUE + 70 CONTINUE + J = J - 1 + IF( D( J ).LT.DMNMX ) + $ GO TO 70 + 80 CONTINUE + I = I + 1 + IF( D( I ).GT.DMNMX ) + $ GO TO 80 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 60 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + ELSE +* +* Sort into increasing order +* + I = START - 1 + J = ENDD + 1 + 90 CONTINUE + 100 CONTINUE + J = J - 1 + IF( D( J ).GT.DMNMX ) + $ GO TO 100 + 110 CONTINUE + I = I + 1 + IF( D( I ).LT.DMNMX ) + $ GO TO 110 + IF( I.LT.J ) THEN + TMP = D( I ) + D( I ) = D( J ) + D( J ) = TMP + GO TO 90 + END IF + IF( J-START.GT.ENDD-J-1 ) THEN + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + ELSE + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = J + 1 + STACK( 2, STKPNT ) = ENDD + STKPNT = STKPNT + 1 + STACK( 1, STKPNT ) = START + STACK( 2, STKPNT ) = J + END IF + END IF + END IF + IF( STKPNT.GT.0 ) + $ GO TO 10 + RETURN +* +* End of DLASRT +* + END diff --git a/lapack/internal/testdata/dsterftest/dlassq.f b/lapack/internal/testdata/dsterftest/dlassq.f new file mode 100644 index 00000000..c7c4087e --- /dev/null +++ b/lapack/internal/testdata/dsterftest/dlassq.f @@ -0,0 +1,155 @@ +*> \brief \b DLASSQ updates a sum of squares represented in scaled form. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASSQ + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ ) +* +* .. Scalar Arguments .. +* INTEGER INCX, N +* DOUBLE PRECISION SCALE, SUMSQ +* .. +* .. Array Arguments .. +* DOUBLE PRECISION X( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASSQ returns the values scl and smsq such that +*> +*> ( scl**2 )*smsq = x( 1 )**2 +...+ x( n )**2 + ( scale**2 )*sumsq, +*> +*> where x( i ) = X( 1 + ( i - 1 )*INCX ). The value of sumsq is +*> assumed to be non-negative and scl returns the value +*> +*> scl = max( scale, abs( x( i ) ) ). +*> +*> scale and sumsq must be supplied in SCALE and SUMSQ and +*> scl and smsq are overwritten on SCALE and SUMSQ respectively. +*> +*> The routine makes only one pass through the vector x. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of elements to be used from the vector X. +*> \endverbatim +*> +*> \param[in] X +*> \verbatim +*> X is DOUBLE PRECISION array, dimension (N) +*> The vector for which a scaled sum of squares is computed. +*> x( i ) = X( 1 + ( i - 1 )*INCX ), 1 <= i <= n. +*> \endverbatim +*> +*> \param[in] INCX +*> \verbatim +*> INCX is INTEGER +*> The increment between successive values of the vector X. +*> INCX > 0. +*> \endverbatim +*> +*> \param[in,out] SCALE +*> \verbatim +*> SCALE is DOUBLE PRECISION +*> On entry, the value scale in the equation above. +*> On exit, SCALE is overwritten with scl , the scaling factor +*> for the sum of squares. +*> \endverbatim +*> +*> \param[in,out] SUMSQ +*> \verbatim +*> SUMSQ is DOUBLE PRECISION +*> On entry, the value sumsq in the equation above. +*> On exit, SUMSQ is overwritten with smsq , the basic sum of +*> squares from which scl has been factored out. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER INCX, N + DOUBLE PRECISION SCALE, SUMSQ +* .. +* .. Array Arguments .. + DOUBLE PRECISION X( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER IX + DOUBLE PRECISION ABSXI +* .. +* .. External Functions .. + LOGICAL DISNAN + EXTERNAL DISNAN +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. Executable Statements .. +* + IF( N.GT.0 ) THEN + DO 10 IX = 1, 1 + ( N-1 )*INCX, INCX + ABSXI = ABS( X( IX ) ) + IF( ABSXI.GT.ZERO.OR.DISNAN( ABSXI ) ) THEN + IF( SCALE.LT.ABSXI ) THEN + SUMSQ = 1 + SUMSQ*( SCALE / ABSXI )**2 + SCALE = ABSXI + ELSE + SUMSQ = SUMSQ + ( ABSXI / SCALE )**2 + END IF + END IF + 10 CONTINUE + END IF + RETURN +* +* End of DLASSQ +* + END diff --git a/lapack/internal/testdata/dsterftest/dsterf.f b/lapack/internal/testdata/dsterftest/dsterf.f new file mode 100644 index 00000000..43395cc7 --- /dev/null +++ b/lapack/internal/testdata/dsterftest/dsterf.f @@ -0,0 +1,448 @@ +*> \brief \b DSTERF +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DSTERF + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DSTERF( N, D, E, INFO ) +* +* .. Scalar Arguments .. +* INTEGER INFO, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION D( * ), E( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DSTERF computes all eigenvalues of a symmetric tridiagonal matrix +*> using the Pal-Walker-Kahan variant of the QL or QR algorithm. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The order of the matrix. N >= 0. +*> \endverbatim +*> +*> \param[in,out] D +*> \verbatim +*> D is DOUBLE PRECISION array, dimension (N) +*> On entry, the n diagonal elements of the tridiagonal matrix. +*> On exit, if INFO = 0, the eigenvalues in ascending order. +*> \endverbatim +*> +*> \param[in,out] E +*> \verbatim +*> E is DOUBLE PRECISION array, dimension (N-1) +*> On entry, the (n-1) subdiagonal elements of the tridiagonal +*> matrix. +*> On exit, E has been destroyed. +*> \endverbatim +*> +*> \param[out] INFO +*> \verbatim +*> INFO is INTEGER +*> = 0: successful exit +*> < 0: if INFO = -i, the i-th argument had an illegal value +*> > 0: the algorithm failed to find all of the eigenvalues in +*> a total of 30*N iterations; if INFO = i, then i +*> elements of E have not converged to zero. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERcomputational +* +* ===================================================================== + SUBROUTINE DSTERF( N, D, E, INFO ) +* +* -- LAPACK computational routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INFO, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION D( * ), E( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE, TWO, THREE + PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0, + $ THREE = 3.0D0 ) + INTEGER MAXIT + PARAMETER ( MAXIT = 30 ) +* .. +* .. Local Scalars .. + INTEGER I, ISCALE, JTOT, L, L1, LEND, LENDSV, LSV, M, + $ NMAXIT + DOUBLE PRECISION ALPHA, ANORM, BB, C, EPS, EPS2, GAMMA, OLDC, + $ OLDGAM, P, R, RT1, RT2, RTE, S, SAFMAX, SAFMIN, + $ SIGMA, SSFMAX, SSFMIN, RMAX +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH, DLANST, DLAPY2 + EXTERNAL DLAMCH, DLANST, DLAPY2 +* .. +* .. External Subroutines .. + EXTERNAL DLAE2, DLASCL, DLASRT, XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SIGN, SQRT +* .. +* .. Executable Statements .. +* +* Test the input parameters. +* + INFO = 0 +* +* Quick return if possible +* + IF( N.LT.0 ) THEN + INFO = -1 + CALL XERBLA( 'DSTERF', -INFO ) + RETURN + END IF + IF( N.LE.1 ) + $ RETURN +* +* Determine the unit roundoff for this environment. +* + EPS = DLAMCH( 'E' ) + EPS2 = EPS**2 + SAFMIN = DLAMCH( 'S' ) + SAFMAX = ONE / SAFMIN + SSFMAX = SQRT( SAFMAX ) / THREE + SSFMIN = SQRT( SAFMIN ) / EPS2 + RMAX = DLAMCH( 'O' ) +* +* Compute the eigenvalues of the tridiagonal matrix. +* + NMAXIT = N*MAXIT + SIGMA = ZERO + JTOT = 0 +* +* Determine where the matrix splits and choose QL or QR iteration +* for each block, according to whether top or bottom diagonal +* element is smaller. +* + L1 = 1 +* + 10 CONTINUE + print *, "l1 = ", l1 + IF( L1.GT.N ) THEN + print *, "going to 170" + GO TO 170 + end if + IF( L1.GT.1 ) + $ E( L1-1 ) = ZERO + DO 20 M = L1, N - 1 + IF( ABS( E( M ) ).LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+ + $ 1 ) ) ) )*EPS ) THEN + E( M ) = ZERO + GO TO 30 + END IF + 20 CONTINUE + M = N +* + 30 CONTINUE + print *, "30, d" + print *, d(1:n) + L = L1 + LSV = L + LEND = M + LENDSV = LEND + L1 = M + 1 + IF( LEND.EQ.L ) + $ GO TO 10 +* +* Scale submatrix in rows and columns L to LEND +* + ANORM = DLANST( 'M', LEND-L+1, D( L ), E( L ) ) + ISCALE = 0 + IF( ANORM.EQ.ZERO ) + $ GO TO 10 + IF( (ANORM.GT.SSFMAX) ) THEN + ISCALE = 1 + CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N, + $ INFO ) + CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N, + $ INFO ) + ELSE IF( ANORM.LT.SSFMIN ) THEN + ISCALE = 2 + CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N, + $ INFO ) + CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N, + $ INFO ) + END IF +* + DO 40 I = L, LEND - 1 + E( I ) = E( I )**2 + 40 CONTINUE +* +* Choose between QL and QR iteration +* + IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN + LEND = LSV + L = LENDSV + END IF +* + IF( LEND.GE.L ) THEN + print *, "ql, d" + print *, d(1:n) +* +* QL Iteration +* +* Look for small subdiagonal element. +* + 50 CONTINUE + IF( L.NE.LEND ) THEN + DO 60 M = L, LEND - 1 + IF( ABS( E( M ) ).LE.EPS2*ABS( D( M )*D( M+1 ) ) ) + $ GO TO 70 + 60 CONTINUE + END IF + M = LEND +* + 70 CONTINUE + IF( M.LT.LEND ) + $ E( M ) = ZERO + P = D( L ) + IF( M.EQ.L ) + $ GO TO 90 +* +* If remaining matrix is 2 by 2, use DLAE2 to compute its +* eigenvalues. +* + IF( M.EQ.L+1 ) THEN + RTE = SQRT( E( L ) ) + CALL DLAE2( D( L ), RTE, D( L+1 ), RT1, RT2 ) + D( L ) = RT1 + D( L+1 ) = RT2 + E( L ) = ZERO + L = L + 2 + IF( L.LE.LEND ) + $ GO TO 50 + GO TO 150 + END IF +* + IF( JTOT.EQ.NMAXIT ) + $ GO TO 150 + JTOT = JTOT + 1 +* +* Form shift. +* + RTE = SQRT( E( L ) ) + SIGMA = ( D( L+1 )-P ) / ( TWO*RTE ) + R = DLAPY2( SIGMA, ONE ) + SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) ) +* + C = ONE + S = ZERO + GAMMA = D( M ) - SIGMA + P = GAMMA*GAMMA +* +* Inner loop +* + print *, "inner loop d before" + print *, d(1:n) + + DO 80 I = M - 1, L, -1 + print *, "inner loop" + print *, "ei", e(i) + BB = E( I ) + R = P + BB + print *, "bb,p,r" + print *, bb,p,r + IF( I.NE.M-1 ) THEN + print *, s,r + E( I+1 ) = S*R + end if + OLDC = C + C = P / R + S = BB / R + OLDGAM = GAMMA + print *, "di", d(i) + ALPHA = D( I ) + GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM + print *,"og, a, ga", OLDGAM, ALPHA, GAMMA + D( I+1 ) = OLDGAM + ( ALPHA-GAMMA ) + IF( C.NE.ZERO ) THEN + P = ( GAMMA*GAMMA ) / C + ELSE + P = OLDC*BB + END IF + print *, "p, gamma = ", p,GAMMA + 80 CONTINUE +* + E( L ) = S*P + D( L ) = SIGMA + GAMMA + + print *, "inner loop d after" + print *, d(1:n) + GO TO 50 +* +* Eigenvalue found. +* + 90 CONTINUE + D( L ) = P +* + L = L + 1 + IF( L.LE.LEND ) + $ GO TO 50 + GO TO 150 +* + ELSE +* +* QR Iteration +* +* Look for small superdiagonal element. +* + 100 CONTINUE + DO 110 M = L, LEND + 1, -1 + IF( ABS( E( M-1 ) ).LE.EPS2*ABS( D( M )*D( M-1 ) ) ) + $ GO TO 120 + 110 CONTINUE + M = LEND +* + 120 CONTINUE + IF( M.GT.LEND ) + $ E( M-1 ) = ZERO + P = D( L ) + IF( M.EQ.L ) + $ GO TO 140 +* +* If remaining matrix is 2 by 2, use DLAE2 to compute its +* eigenvalues. +* + IF( M.EQ.L-1 ) THEN + RTE = SQRT( E( L-1 ) ) + CALL DLAE2( D( L ), RTE, D( L-1 ), RT1, RT2 ) + D( L ) = RT1 + D( L-1 ) = RT2 + E( L-1 ) = ZERO + L = L - 2 + IF( L.GE.LEND ) + $ GO TO 100 + GO TO 150 + END IF +* + IF( JTOT.EQ.NMAXIT ) + $ GO TO 150 + JTOT = JTOT + 1 +* +* Form shift. +* + RTE = SQRT( E( L-1 ) ) + SIGMA = ( D( L-1 )-P ) / ( TWO*RTE ) + R = DLAPY2( SIGMA, ONE ) + SIGMA = P - ( RTE / ( SIGMA+SIGN( R, SIGMA ) ) ) +* + C = ONE + S = ZERO + GAMMA = D( M ) - SIGMA + P = GAMMA*GAMMA +* +* Inner loop +* + DO 130 I = M, L - 1 + BB = E( I ) + R = P + BB + IF( I.NE.M ) + $ E( I-1 ) = S*R + OLDC = C + C = P / R + S = BB / R + OLDGAM = GAMMA + ALPHA = D( I+1 ) + GAMMA = C*( ALPHA-SIGMA ) - S*OLDGAM + D( I ) = OLDGAM + ( ALPHA-GAMMA ) + IF( C.NE.ZERO ) THEN + P = ( GAMMA*GAMMA ) / C + ELSE + P = OLDC*BB + END IF + 130 CONTINUE +* + E( L-1 ) = S*P + D( L ) = SIGMA + GAMMA + GO TO 100 +* +* Eigenvalue found. +* + 140 CONTINUE + D( L ) = P +* + L = L - 1 + IF( L.GE.LEND ) + $ GO TO 100 + GO TO 150 +* + END IF +* +* Undo scaling if necessary +* + 150 CONTINUE + IF( ISCALE.EQ.1 ) + $ CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1, + $ D( LSV ), N, INFO ) + IF( ISCALE.EQ.2 ) + $ CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1, + $ D( LSV ), N, INFO ) +* +* Check for no convergence to an eigenvalue after a total +* of N*MAXIT iterations. +* + IF( JTOT.LT.NMAXIT ) + $ GO TO 10 + DO 160 I = 1, N - 1 + IF( E( I ).NE.ZERO ) + $ INFO = INFO + 1 + 160 CONTINUE + GO TO 180 +* +* Sort eigenvalues in increasing order. +* + 170 CONTINUE + CALL DLASRT( 'I', N, D, INFO ) +* + 180 CONTINUE + RETURN +* +* End of DSTERF +* + END diff --git a/lapack/internal/testdata/dsterftest/lsame.f b/lapack/internal/testdata/dsterftest/lsame.f new file mode 100644 index 00000000..315304c3 --- /dev/null +++ b/lapack/internal/testdata/dsterftest/lsame.f @@ -0,0 +1,125 @@ +*> \brief \b LSAME +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* LOGICAL FUNCTION LSAME( CA, CB ) +* +* .. Scalar Arguments .. +* CHARACTER CA, CB +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> LSAME returns .TRUE. if CA is the same letter as CB regardless of +*> case. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CA +*> \verbatim +*> \endverbatim +*> +*> \param[in] CB +*> \verbatim +*> CA and CB specify the single characters to be compared. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION LSAME( CA, CB ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CA, CB +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC ICHAR +* .. +* .. Local Scalars .. + INTEGER INTA, INTB, ZCODE +* .. +* .. Executable Statements .. +* +* Test if the characters are equal +* + LSAME = CA.EQ.CB + IF( LSAME ) + $ RETURN +* +* Now test for equivalence if both characters are alphabetic. +* + ZCODE = ICHAR( 'Z' ) +* +* Use 'Z' rather than 'A' so that ASCII can be detected on Prime +* machines, on which ICHAR returns a value with bit 8 set. +* ICHAR('A') on Prime machines returns 193 which is the same as +* ICHAR('A') on an EBCDIC machine. +* + INTA = ICHAR( CA ) + INTB = ICHAR( CB ) +* + IF( ZCODE.EQ.90 .OR. ZCODE.EQ.122 ) THEN +* +* ASCII is assumed - ZCODE is the ASCII code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.97 .AND. INTA.LE.122 ) INTA = INTA - 32 + IF( INTB.GE.97 .AND. INTB.LE.122 ) INTB = INTB - 32 +* + ELSE IF( ZCODE.EQ.233 .OR. ZCODE.EQ.169 ) THEN +* +* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.129 .AND. INTA.LE.137 .OR. + $ INTA.GE.145 .AND. INTA.LE.153 .OR. + $ INTA.GE.162 .AND. INTA.LE.169 ) INTA = INTA + 64 + IF( INTB.GE.129 .AND. INTB.LE.137 .OR. + $ INTB.GE.145 .AND. INTB.LE.153 .OR. + $ INTB.GE.162 .AND. INTB.LE.169 ) INTB = INTB + 64 +* + ELSE IF( ZCODE.EQ.218 .OR. ZCODE.EQ.250 ) THEN +* +* ASCII is assumed, on Prime machines - ZCODE is the ASCII code +* plus 128 of either lower or upper case 'Z'. +* + IF( INTA.GE.225 .AND. INTA.LE.250 ) INTA = INTA - 32 + IF( INTB.GE.225 .AND. INTB.LE.250 ) INTB = INTB - 32 + END IF + LSAME = INTA.EQ.INTB +* +* RETURN +* +* End of LSAME +* + END diff --git a/lapack/internal/testdata/dsterftest/testdsterf.f90 b/lapack/internal/testdata/dsterftest/testdsterf.f90 new file mode 100644 index 00000000..8373f512 --- /dev/null +++ b/lapack/internal/testdata/dsterftest/testdsterf.f90 @@ -0,0 +1,15 @@ +program testdsterf +implicit none +integer, parameter :: n = 4 +real(kind=8), dimension(n) :: d +real(kind=8), dimension(n-1) :: e +integer :: info,i + +d(1:4) = (/1D+00, 3D+00, 4D+00, 6D+00/) +e(1:3) = (/2D+00, 4D+00, 5D+00/) + +call dsterf(n,d,e,info) +DO i = 1, n + print *, d(i) +end do +end \ No newline at end of file diff --git a/lapack/internal/testdata/dsterftest/xerbla.f b/lapack/internal/testdata/dsterftest/xerbla.f new file mode 100644 index 00000000..3e93bc4e --- /dev/null +++ b/lapack/internal/testdata/dsterftest/xerbla.f @@ -0,0 +1,99 @@ +*> \brief \b XERBLA +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download XERBLA + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE XERBLA( SRNAME, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER*(*) SRNAME +* INTEGER INFO +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> XERBLA is an error handler for the LAPACK routines. +*> It is called by an LAPACK routine if an input parameter has an +*> invalid value. A message is printed and execution stops. +*> +*> Installers may consider modifying the STOP statement in order to +*> call system-specific exception-handling facilities. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] SRNAME +*> \verbatim +*> SRNAME is CHARACTER*(*) +*> The name of the routine which called XERBLA. +*> \endverbatim +*> +*> \param[in] INFO +*> \verbatim +*> INFO is INTEGER +*> The position of the invalid parameter in the parameter list +*> of the calling routine. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE XERBLA( SRNAME, INFO ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER*(*) SRNAME + INTEGER INFO +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LEN_TRIM +* .. +* .. Executable Statements .. +* + WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO +* + STOP +* + 9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ', + $ 'an illegal value' ) +* +* End of XERBLA +* + END diff --git a/lapack/internal/testdata/netlib/daxpy.f b/lapack/internal/testdata/netlib/daxpy.f new file mode 100644 index 00000000..64a02d68 --- /dev/null +++ b/lapack/internal/testdata/netlib/daxpy.f @@ -0,0 +1,115 @@ +*> \brief \b DAXPY +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DA +* INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION DX(*),DY(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DAXPY constant times a vector plus a vector. +*> uses unrolled loops for increments equal to one. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> jack dongarra, linpack, 3/11/78. +*> modified 12/3/93, array(1) declarations changed to array(*) +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DAXPY(N,DA,DX,INCX,DY,INCY) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DA + INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION DX(*),DY(*) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I,IX,IY,M,MP1 +* .. +* .. Intrinsic Functions .. + INTRINSIC MOD +* .. + IF (N.LE.0) RETURN + IF (DA.EQ.0.0d0) RETURN + IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN +* +* code for both increments equal to 1 +* +* +* clean-up loop +* + M = MOD(N,4) + IF (M.NE.0) THEN + DO I = 1,M + DY(I) = DY(I) + DA*DX(I) + END DO + END IF + IF (N.LT.4) RETURN + MP1 = M + 1 + DO I = MP1,N,4 + DY(I) = DY(I) + DA*DX(I) + DY(I+1) = DY(I+1) + DA*DX(I+1) + DY(I+2) = DY(I+2) + DA*DX(I+2) + DY(I+3) = DY(I+3) + DA*DX(I+3) + END DO + ELSE +* +* code for unequal increments or equal increments +* not equal to 1 +* + IX = 1 + IY = 1 + IF (INCX.LT.0) IX = (-N+1)*INCX + 1 + IF (INCY.LT.0) IY = (-N+1)*INCY + 1 + DO I = 1,N + DY(IY) = DY(IY) + DA*DX(IX) + IX = IX + INCX + IY = IY + INCY + END DO + END IF + RETURN + END diff --git a/lapack/internal/testdata/netlib/dcopy.f b/lapack/internal/testdata/netlib/dcopy.f new file mode 100644 index 00000000..d9d5ac7a --- /dev/null +++ b/lapack/internal/testdata/netlib/dcopy.f @@ -0,0 +1,115 @@ +*> \brief \b DCOPY +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) +* +* .. Scalar Arguments .. +* INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION DX(*),DY(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DCOPY copies a vector, x, to a vector, y. +*> uses unrolled loops for increments equal to one. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> jack dongarra, linpack, 3/11/78. +*> modified 12/3/93, array(1) declarations changed to array(*) +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INCX,INCY,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION DX(*),DY(*) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I,IX,IY,M,MP1 +* .. +* .. Intrinsic Functions .. + INTRINSIC MOD +* .. + IF (N.LE.0) RETURN + IF (INCX.EQ.1 .AND. INCY.EQ.1) THEN +* +* code for both increments equal to 1 +* +* +* clean-up loop +* + M = MOD(N,7) + IF (M.NE.0) THEN + DO I = 1,M + DY(I) = DX(I) + END DO + IF (N.LT.7) RETURN + END IF + MP1 = M + 1 + DO I = MP1,N,7 + DY(I) = DX(I) + DY(I+1) = DX(I+1) + DY(I+2) = DX(I+2) + DY(I+3) = DX(I+3) + DY(I+4) = DX(I+4) + DY(I+5) = DX(I+5) + DY(I+6) = DX(I+6) + END DO + ELSE +* +* code for unequal increments or equal increments +* not equal to 1 +* + IX = 1 + IY = 1 + IF (INCX.LT.0) IX = (-N+1)*INCX + 1 + IF (INCY.LT.0) IY = (-N+1)*INCY + 1 + DO I = 1,N + DY(IY) = DX(IX) + IX = IX + INCX + IY = IY + INCY + END DO + END IF + RETURN + END diff --git a/lapack/internal/testdata/netlib/dgemm.f b/lapack/internal/testdata/netlib/dgemm.f new file mode 100644 index 00000000..4bae243a --- /dev/null +++ b/lapack/internal/testdata/netlib/dgemm.f @@ -0,0 +1,384 @@ +*> \brief \b DGEMM +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION ALPHA,BETA +* INTEGER K,LDA,LDB,LDC,M,N +* CHARACTER TRANSA,TRANSB +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DGEMM performs one of the matrix-matrix operations +*> +*> C := alpha*op( A )*op( B ) + beta*C, +*> +*> where op( X ) is one of +*> +*> op( X ) = X or op( X ) = X**T, +*> +*> alpha and beta are scalars, and A, B and C are matrices, with op( A ) +*> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] TRANSA +*> \verbatim +*> TRANSA is CHARACTER*1 +*> On entry, TRANSA specifies the form of op( A ) to be used in +*> the matrix multiplication as follows: +*> +*> TRANSA = 'N' or 'n', op( A ) = A. +*> +*> TRANSA = 'T' or 't', op( A ) = A**T. +*> +*> TRANSA = 'C' or 'c', op( A ) = A**T. +*> \endverbatim +*> +*> \param[in] TRANSB +*> \verbatim +*> TRANSB is CHARACTER*1 +*> On entry, TRANSB specifies the form of op( B ) to be used in +*> the matrix multiplication as follows: +*> +*> TRANSB = 'N' or 'n', op( B ) = B. +*> +*> TRANSB = 'T' or 't', op( B ) = B**T. +*> +*> TRANSB = 'C' or 'c', op( B ) = B**T. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> On entry, M specifies the number of rows of the matrix +*> op( A ) and of the matrix C. M must be at least zero. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> On entry, N specifies the number of columns of the matrix +*> op( B ) and the number of columns of the matrix C. N must be +*> at least zero. +*> \endverbatim +*> +*> \param[in] K +*> \verbatim +*> K is INTEGER +*> On entry, K specifies the number of columns of the matrix +*> op( A ) and the number of rows of the matrix op( B ). K must +*> be at least zero. +*> \endverbatim +*> +*> \param[in] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION. +*> On entry, ALPHA specifies the scalar alpha. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array of DIMENSION ( LDA, ka ), where ka is +*> k when TRANSA = 'N' or 'n', and is m otherwise. +*> Before entry with TRANSA = 'N' or 'n', the leading m by k +*> part of the array A must contain the matrix A, otherwise +*> the leading k by m part of the array A must contain the +*> matrix A. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> On entry, LDA specifies the first dimension of A as declared +*> in the calling (sub) program. When TRANSA = 'N' or 'n' then +*> LDA must be at least max( 1, m ), otherwise LDA must be at +*> least max( 1, k ). +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is DOUBLE PRECISION array of DIMENSION ( LDB, kb ), where kb is +*> n when TRANSB = 'N' or 'n', and is k otherwise. +*> Before entry with TRANSB = 'N' or 'n', the leading k by n +*> part of the array B must contain the matrix B, otherwise +*> the leading n by k part of the array B must contain the +*> matrix B. +*> \endverbatim +*> +*> \param[in] LDB +*> \verbatim +*> LDB is INTEGER +*> On entry, LDB specifies the first dimension of B as declared +*> in the calling (sub) program. When TRANSB = 'N' or 'n' then +*> LDB must be at least max( 1, k ), otherwise LDB must be at +*> least max( 1, n ). +*> \endverbatim +*> +*> \param[in] BETA +*> \verbatim +*> BETA is DOUBLE PRECISION. +*> On entry, BETA specifies the scalar beta. When BETA is +*> supplied as zero then C need not be set on input. +*> \endverbatim +*> +*> \param[in,out] C +*> \verbatim +*> C is DOUBLE PRECISION array of DIMENSION ( LDC, n ). +*> Before entry, the leading m by n part of the array C must +*> contain the matrix C, except when beta is zero, in which +*> case C need not be set on entry. +*> On exit, the array C is overwritten by the m by n matrix +*> ( alpha*op( A )*op( B ) + beta*C ). +*> \endverbatim +*> +*> \param[in] LDC +*> \verbatim +*> LDC is INTEGER +*> On entry, LDC specifies the first dimension of C as declared +*> in the calling (sub) program. LDC must be at least +*> max( 1, m ). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2015 +* +*> \ingroup double_blas_level3 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Level 3 Blas routine. +*> +*> -- Written on 8-February-1989. +*> Jack Dongarra, Argonne National Laboratory. +*> Iain Duff, AERE Harwell. +*> Jeremy Du Croz, Numerical Algorithms Group Ltd. +*> Sven Hammarling, Numerical Algorithms Group Ltd. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC) +* +* -- Reference BLAS level3 routine (version 3.6.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2015 +* +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA,BETA + INTEGER K,LDA,LDB,LDC,M,N + CHARACTER TRANSA,TRANSB +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*) +* .. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,J,L,NCOLA,NROWA,NROWB + LOGICAL NOTA,NOTB +* .. +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* +* Set NOTA and NOTB as true if A and B respectively are not +* transposed and set NROWA, NCOLA and NROWB as the number of rows +* and columns of A and the number of rows of B respectively. +* + NOTA = LSAME(TRANSA,'N') + NOTB = LSAME(TRANSB,'N') + IF (NOTA) THEN + NROWA = M + NCOLA = K + ELSE + NROWA = K + NCOLA = M + END IF + IF (NOTB) THEN + NROWB = K + ELSE + NROWB = N + END IF +* +* Test the input parameters. +* + INFO = 0 + IF ((.NOT.NOTA) .AND. (.NOT.LSAME(TRANSA,'C')) .AND. + + (.NOT.LSAME(TRANSA,'T'))) THEN + INFO = 1 + ELSE IF ((.NOT.NOTB) .AND. (.NOT.LSAME(TRANSB,'C')) .AND. + + (.NOT.LSAME(TRANSB,'T'))) THEN + INFO = 2 + ELSE IF (M.LT.0) THEN + INFO = 3 + ELSE IF (N.LT.0) THEN + INFO = 4 + ELSE IF (K.LT.0) THEN + INFO = 5 + ELSE IF (LDA.LT.MAX(1,NROWA)) THEN + INFO = 8 + ELSE IF (LDB.LT.MAX(1,NROWB)) THEN + INFO = 10 + ELSE IF (LDC.LT.MAX(1,M)) THEN + INFO = 13 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DGEMM ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF ((M.EQ.0) .OR. (N.EQ.0) .OR. + + (((ALPHA.EQ.ZERO).OR. (K.EQ.0)).AND. (BETA.EQ.ONE))) RETURN +* +* And if alpha.eq.zero. +* + IF (ALPHA.EQ.ZERO) THEN + IF (BETA.EQ.ZERO) THEN + DO 20 J = 1,N + DO 10 I = 1,M + C(I,J) = ZERO + 10 CONTINUE + 20 CONTINUE + ELSE + DO 40 J = 1,N + DO 30 I = 1,M + C(I,J) = BETA*C(I,J) + 30 CONTINUE + 40 CONTINUE + END IF + RETURN + END IF +* +* Start the operations. +* + IF (NOTB) THEN + IF (NOTA) THEN +* +* Form C := alpha*A*B + beta*C. +* + DO 90 J = 1,N + IF (BETA.EQ.ZERO) THEN + DO 50 I = 1,M + C(I,J) = ZERO + 50 CONTINUE + ELSE IF (BETA.NE.ONE) THEN + DO 60 I = 1,M + C(I,J) = BETA*C(I,J) + 60 CONTINUE + END IF + DO 80 L = 1,K + TEMP = ALPHA*B(L,J) + DO 70 I = 1,M + C(I,J) = C(I,J) + TEMP*A(I,L) + 70 CONTINUE + 80 CONTINUE + 90 CONTINUE + ELSE +* +* Form C := alpha*A**T*B + beta*C +* + DO 120 J = 1,N + DO 110 I = 1,M + TEMP = ZERO + DO 100 L = 1,K + TEMP = TEMP + A(L,I)*B(L,J) + 100 CONTINUE + IF (BETA.EQ.ZERO) THEN + C(I,J) = ALPHA*TEMP + ELSE + C(I,J) = ALPHA*TEMP + BETA*C(I,J) + END IF + 110 CONTINUE + 120 CONTINUE + END IF + ELSE + IF (NOTA) THEN +* +* Form C := alpha*A*B**T + beta*C +* + DO 170 J = 1,N + IF (BETA.EQ.ZERO) THEN + DO 130 I = 1,M + C(I,J) = ZERO + 130 CONTINUE + ELSE IF (BETA.NE.ONE) THEN + DO 140 I = 1,M + C(I,J) = BETA*C(I,J) + 140 CONTINUE + END IF + DO 160 L = 1,K + TEMP = ALPHA*B(J,L) + DO 150 I = 1,M + C(I,J) = C(I,J) + TEMP*A(I,L) + 150 CONTINUE + 160 CONTINUE + 170 CONTINUE + ELSE +* +* Form C := alpha*A**T*B**T + beta*C +* + DO 200 J = 1,N + DO 190 I = 1,M + TEMP = ZERO + DO 180 L = 1,K + TEMP = TEMP + A(L,I)*B(J,L) + 180 CONTINUE + IF (BETA.EQ.ZERO) THEN + C(I,J) = ALPHA*TEMP + ELSE + C(I,J) = ALPHA*TEMP + BETA*C(I,J) + END IF + 190 CONTINUE + 200 CONTINUE + END IF + END IF +* + RETURN +* +* End of DGEMM . +* + END diff --git a/lapack/internal/testdata/netlib/dgemv.f b/lapack/internal/testdata/netlib/dgemv.f new file mode 100644 index 00000000..e04cc07c --- /dev/null +++ b/lapack/internal/testdata/netlib/dgemv.f @@ -0,0 +1,330 @@ +*> \brief \b DGEMV +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION ALPHA,BETA +* INTEGER INCX,INCY,LDA,M,N +* CHARACTER TRANS +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A(LDA,*),X(*),Y(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DGEMV performs one of the matrix-vector operations +*> +*> y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y, +*> +*> where alpha and beta are scalars, x and y are vectors and A is an +*> m by n matrix. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] TRANS +*> \verbatim +*> TRANS is CHARACTER*1 +*> On entry, TRANS specifies the operation to be performed as +*> follows: +*> +*> TRANS = 'N' or 'n' y := alpha*A*x + beta*y. +*> +*> TRANS = 'T' or 't' y := alpha*A**T*x + beta*y. +*> +*> TRANS = 'C' or 'c' y := alpha*A**T*x + beta*y. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> On entry, M specifies the number of rows of the matrix A. +*> M must be at least zero. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> On entry, N specifies the number of columns of the matrix A. +*> N must be at least zero. +*> \endverbatim +*> +*> \param[in] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION. +*> On entry, ALPHA specifies the scalar alpha. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array of DIMENSION ( LDA, n ). +*> Before entry, the leading m by n part of the array A must +*> contain the matrix of coefficients. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> On entry, LDA specifies the first dimension of A as declared +*> in the calling (sub) program. LDA must be at least +*> max( 1, m ). +*> \endverbatim +*> +*> \param[in] X +*> \verbatim +*> X is DOUBLE PRECISION array of DIMENSION at least +*> ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n' +*> and at least +*> ( 1 + ( m - 1 )*abs( INCX ) ) otherwise. +*> Before entry, the incremented array X must contain the +*> vector x. +*> \endverbatim +*> +*> \param[in] INCX +*> \verbatim +*> INCX is INTEGER +*> On entry, INCX specifies the increment for the elements of +*> X. INCX must not be zero. +*> \endverbatim +*> +*> \param[in] BETA +*> \verbatim +*> BETA is DOUBLE PRECISION. +*> On entry, BETA specifies the scalar beta. When BETA is +*> supplied as zero then Y need not be set on input. +*> \endverbatim +*> +*> \param[in,out] Y +*> \verbatim +*> Y is DOUBLE PRECISION array of DIMENSION at least +*> ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n' +*> and at least +*> ( 1 + ( n - 1 )*abs( INCY ) ) otherwise. +*> Before entry with BETA non-zero, the incremented array Y +*> must contain the vector y. On exit, Y is overwritten by the +*> updated vector y. +*> \endverbatim +*> +*> \param[in] INCY +*> \verbatim +*> INCY is INTEGER +*> On entry, INCY specifies the increment for the elements of +*> Y. INCY must not be zero. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2015 +* +*> \ingroup double_blas_level2 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Level 2 Blas routine. +*> The vector and matrix arguments are not referenced when N = 0, or M = 0 +*> +*> -- Written on 22-October-1986. +*> Jack Dongarra, Argonne National Lab. +*> Jeremy Du Croz, Nag Central Office. +*> Sven Hammarling, Nag Central Office. +*> Richard Hanson, Sandia National Labs. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) +* +* -- Reference BLAS level2 routine (version 3.6.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2015 +* +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA,BETA + INTEGER INCX,INCY,LDA,M,N + CHARACTER TRANS +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),X(*),Y(*) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,IX,IY,J,JX,JY,KX,KY,LENX,LENY +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* +* Test the input parameters. +* + INFO = 0 + IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND. + + .NOT.LSAME(TRANS,'C')) THEN + INFO = 1 + ELSE IF (M.LT.0) THEN + INFO = 2 + ELSE IF (N.LT.0) THEN + INFO = 3 + ELSE IF (LDA.LT.MAX(1,M)) THEN + INFO = 6 + ELSE IF (INCX.EQ.0) THEN + INFO = 8 + ELSE IF (INCY.EQ.0) THEN + INFO = 11 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DGEMV ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF ((M.EQ.0) .OR. (N.EQ.0) .OR. + + ((ALPHA.EQ.ZERO).AND. (BETA.EQ.ONE))) RETURN +* +* Set LENX and LENY, the lengths of the vectors x and y, and set +* up the start points in X and Y. +* + IF (LSAME(TRANS,'N')) THEN + LENX = N + LENY = M + ELSE + LENX = M + LENY = N + END IF + IF (INCX.GT.0) THEN + KX = 1 + ELSE + KX = 1 - (LENX-1)*INCX + END IF + IF (INCY.GT.0) THEN + KY = 1 + ELSE + KY = 1 - (LENY-1)*INCY + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* +* First form y := beta*y. +* + IF (BETA.NE.ONE) THEN + IF (INCY.EQ.1) THEN + IF (BETA.EQ.ZERO) THEN + DO 10 I = 1,LENY + Y(I) = ZERO + 10 CONTINUE + ELSE + DO 20 I = 1,LENY + Y(I) = BETA*Y(I) + 20 CONTINUE + END IF + ELSE + IY = KY + IF (BETA.EQ.ZERO) THEN + DO 30 I = 1,LENY + Y(IY) = ZERO + IY = IY + INCY + 30 CONTINUE + ELSE + DO 40 I = 1,LENY + Y(IY) = BETA*Y(IY) + IY = IY + INCY + 40 CONTINUE + END IF + END IF + END IF + IF (ALPHA.EQ.ZERO) RETURN + IF (LSAME(TRANS,'N')) THEN +* +* Form y := alpha*A*x + y. +* + JX = KX + IF (INCY.EQ.1) THEN + DO 60 J = 1,N + TEMP = ALPHA*X(JX) + DO 50 I = 1,M + Y(I) = Y(I) + TEMP*A(I,J) + 50 CONTINUE + JX = JX + INCX + 60 CONTINUE + ELSE + DO 80 J = 1,N + TEMP = ALPHA*X(JX) + IY = KY + DO 70 I = 1,M + Y(IY) = Y(IY) + TEMP*A(I,J) + IY = IY + INCY + 70 CONTINUE + JX = JX + INCX + 80 CONTINUE + END IF + ELSE +* +* Form y := alpha*A**T*x + y. +* + JY = KY + IF (INCX.EQ.1) THEN + DO 100 J = 1,N + TEMP = ZERO + DO 90 I = 1,M + TEMP = TEMP + A(I,J)*X(I) + 90 CONTINUE + Y(JY) = Y(JY) + ALPHA*TEMP + JY = JY + INCY + 100 CONTINUE + ELSE + DO 120 J = 1,N + TEMP = ZERO + IX = KX + DO 110 I = 1,M + TEMP = TEMP + A(I,J)*X(IX) + IX = IX + INCX + 110 CONTINUE + Y(JY) = Y(JY) + ALPHA*TEMP + JY = JY + INCY + 120 CONTINUE + END IF + END IF +* + RETURN +* +* End of DGEMV . +* + END diff --git a/lapack/internal/testdata/netlib/dlabad.f b/lapack/internal/testdata/netlib/dlabad.f new file mode 100644 index 00000000..da412633 --- /dev/null +++ b/lapack/internal/testdata/netlib/dlabad.f @@ -0,0 +1,105 @@ +*> \brief \b DLABAD +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLABAD + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLABAD( SMALL, LARGE ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION LARGE, SMALL +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLABAD takes as input the values computed by DLAMCH for underflow and +*> overflow, and returns the square root of each of these values if the +*> log of LARGE is sufficiently large. This subroutine is intended to +*> identify machines with a large exponent range, such as the Crays, and +*> redefine the underflow and overflow limits to be the square roots of +*> the values computed by DLAMCH. This subroutine is needed because +*> DLAMCH does not compensate for poor arithmetic in the upper half of +*> the exponent range, as is found on a Cray. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in,out] SMALL +*> \verbatim +*> SMALL is DOUBLE PRECISION +*> On entry, the underflow threshold as computed by DLAMCH. +*> On exit, if LOG10(LARGE) is sufficiently large, the square +*> root of SMALL, otherwise unchanged. +*> \endverbatim +*> +*> \param[in,out] LARGE +*> \verbatim +*> LARGE is DOUBLE PRECISION +*> On entry, the overflow threshold as computed by DLAMCH. +*> On exit, if LOG10(LARGE) is sufficiently large, the square +*> root of LARGE, otherwise unchanged. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLABAD( SMALL, LARGE ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + DOUBLE PRECISION LARGE, SMALL +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LOG10, SQRT +* .. +* .. Executable Statements .. +* +* If it looks like we're on a Cray, take the square root of +* SMALL and LARGE to avoid overflow and underflow problems. +* +* IF( LOG10( LARGE ).GT.2000.D0 ) THEN +* SMALL = SQRT( SMALL ) +* LARGE = SQRT( LARGE ) +* END IF +* + RETURN +* +* End of DLABAD +* + END diff --git a/lapack/internal/testdata/netlib/dlacpy.f b/lapack/internal/testdata/netlib/dlacpy.f new file mode 100644 index 00000000..a9a23c94 --- /dev/null +++ b/lapack/internal/testdata/netlib/dlacpy.f @@ -0,0 +1,156 @@ +*> \brief \b DLACPY copies all or part of one two-dimensional array to another. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLACPY + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLACPY( UPLO, M, N, A, LDA, B, LDB ) +* +* .. Scalar Arguments .. +* CHARACTER UPLO +* INTEGER LDA, LDB, M, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLACPY copies all or part of a two-dimensional matrix A to another +*> matrix B. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> Specifies the part of the matrix A to be copied to B. +*> = 'U': Upper triangular part +*> = 'L': Lower triangular part +*> Otherwise: All of the matrix A +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. M >= 0. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> The m by n matrix A. If UPLO = 'U', only the upper triangle +*> or trapezoid is accessed; if UPLO = 'L', only the lower +*> triangle or trapezoid is accessed. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +*> +*> \param[out] B +*> \verbatim +*> B is DOUBLE PRECISION array, dimension (LDB,N) +*> On exit, B = A in the locations specified by UPLO. +*> \endverbatim +*> +*> \param[in] LDB +*> \verbatim +*> LDB is INTEGER +*> The leading dimension of the array B. LDB >= max(1,M). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLACPY( UPLO, M, N, A, LDA, B, LDB ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER LDA, LDB, M, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), B( LDB, * ) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( LSAME( UPLO, 'U' ) ) THEN + DO 20 J = 1, N + DO 10 I = 1, MIN( J, M ) + B( I, J ) = A( I, J ) + 10 CONTINUE + 20 CONTINUE + ELSE IF( LSAME( UPLO, 'L' ) ) THEN + DO 40 J = 1, N + DO 30 I = J, M + B( I, J ) = A( I, J ) + 30 CONTINUE + 40 CONTINUE + ELSE + DO 60 J = 1, N + DO 50 I = 1, M + B( I, J ) = A( I, J ) + 50 CONTINUE + 60 CONTINUE + END IF + RETURN +* +* End of DLACPY +* + END diff --git a/lapack/internal/testdata/netlib/dlahr2.f b/lapack/internal/testdata/netlib/dlahr2.f new file mode 100644 index 00000000..9d15979c --- /dev/null +++ b/lapack/internal/testdata/netlib/dlahr2.f @@ -0,0 +1,326 @@ +*> \brief \b DLAHR2 reduces the specified number of first columns of a general rectangular matrix A so that elements below the specified subdiagonal are zero, and returns auxiliary matrices which are needed to apply the transformation to the unreduced part of A. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAHR2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAHR2( N, K, NB, A, LDA, TAU, T, LDT, Y, LDY ) +* +* .. Scalar Arguments .. +* INTEGER K, LDA, LDT, LDY, N, NB +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ), T( LDT, NB ), TAU( NB ), +* $ Y( LDY, NB ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAHR2 reduces the first NB columns of A real general n-BY-(n-k+1) +*> matrix A so that elements below the k-th subdiagonal are zero. The +*> reduction is performed by an orthogonal similarity transformation +*> Q**T * A * Q. The routine returns the matrices V and T which determine +*> Q as a block reflector I - V*T*V**T, and also the matrix Y = A * V * T. +*> +*> This is an auxiliary routine called by DGEHRD. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The order of the matrix A. +*> \endverbatim +*> +*> \param[in] K +*> \verbatim +*> K is INTEGER +*> The offset for the reduction. Elements below the k-th +*> subdiagonal in the first NB columns are reduced to zero. +*> K < N. +*> \endverbatim +*> +*> \param[in] NB +*> \verbatim +*> NB is INTEGER +*> The number of columns to be reduced. +*> \endverbatim +*> +*> \param[in,out] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N-K+1) +*> On entry, the n-by-(n-k+1) general matrix A. +*> On exit, the elements on and above the k-th subdiagonal in +*> the first NB columns are overwritten with the corresponding +*> elements of the reduced matrix; the elements below the k-th +*> subdiagonal, with the array TAU, represent the matrix Q as a +*> product of elementary reflectors. The other columns of A are +*> unchanged. See Further Details. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,N). +*> \endverbatim +*> +*> \param[out] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION array, dimension (NB) +*> The scalar factors of the elementary reflectors. See Further +*> Details. +*> \endverbatim +*> +*> \param[out] T +*> \verbatim +*> T is DOUBLE PRECISION array, dimension (LDT,NB) +*> The upper triangular matrix T. +*> \endverbatim +*> +*> \param[in] LDT +*> \verbatim +*> LDT is INTEGER +*> The leading dimension of the array T. LDT >= NB. +*> \endverbatim +*> +*> \param[out] Y +*> \verbatim +*> Y is DOUBLE PRECISION array, dimension (LDY,NB) +*> The n-by-nb matrix Y. +*> \endverbatim +*> +*> \param[in] LDY +*> \verbatim +*> LDY is INTEGER +*> The leading dimension of the array Y. LDY >= N. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup doubleOTHERauxiliary +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> The matrix Q is represented as a product of nb elementary reflectors +*> +*> Q = H(1) H(2) . . . H(nb). +*> +*> Each H(i) has the form +*> +*> H(i) = I - tau * v * v**T +*> +*> where tau is a real scalar, and v is a real vector with +*> v(1:i+k-1) = 0, v(i+k) = 1; v(i+k+1:n) is stored on exit in +*> A(i+k+1:n,i), and tau in TAU(i). +*> +*> The elements of the vectors v together form the (n-k+1)-by-nb matrix +*> V which is needed, with T and Y, to apply the transformation to the +*> unreduced part of the matrix, using an update of the form: +*> A := (I - V*T*V**T) * (A - Y*V**T). +*> +*> The contents of A on exit are illustrated by the following example +*> with n = 7, k = 3 and nb = 2: +*> +*> ( a a a a a ) +*> ( a a a a a ) +*> ( a a a a a ) +*> ( h h a a a ) +*> ( v1 h a a a ) +*> ( v1 v2 a a a ) +*> ( v1 v2 a a a ) +*> +*> where a denotes an element of the original matrix A, h denotes a +*> modified element of the upper Hessenberg matrix H, and vi denotes an +*> element of the vector defining H(i). +*> +*> This subroutine is a slight modification of LAPACK-3.0's DLAHRD +*> incorporating improvements proposed by Quintana-Orti and Van de +*> Gejin. Note that the entries of A(1:K,2:NB) differ from those +*> returned by the original LAPACK-3.0's DLAHRD routine. (This +*> subroutine is not backward compatible with LAPACK-3.0's DLAHRD.) +*> \endverbatim +* +*> \par References: +* ================ +*> +*> Gregorio Quintana-Orti and Robert van de Geijn, "Improving the +*> performance of reduction to Hessenberg form," ACM Transactions on +*> Mathematical Software, 32(2):180-194, June 2006. +*> +* ===================================================================== + SUBROUTINE DLAHR2( N, K, NB, A, LDA, TAU, T, LDT, Y, LDY ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER K, LDA, LDT, LDY, N, NB +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ), T( LDT, NB ), TAU( NB ), + $ Y( LDY, NB ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0D+0, + $ ONE = 1.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER I + DOUBLE PRECISION EI +* .. +* .. External Subroutines .. + EXTERNAL DAXPY, DCOPY, DGEMM, DGEMV, DLACPY, + $ DLARFG, DSCAL, DTRMM, DTRMV +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* +* Quick return if possible +* + IF( N.LE.1 ) + $ RETURN +* + DO 10 I = 1, NB + IF( I.GT.1 ) THEN +* +* Update A(K+1:N,I) +* +* Update I-th column of A - Y * V**T +* + CALL DGEMV( 'NO TRANSPOSE', N-K, I-1, -ONE, Y(K+1,1), LDY, + $ A( K+I-1, 1 ), LDA, ONE, A( K+1, I ), 1 ) +* +* Apply I - V * T**T * V**T to this column (call it b) from the +* left, using the last column of T as workspace +* +* Let V = ( V1 ) and b = ( b1 ) (first I-1 rows) +* ( V2 ) ( b2 ) +* +* where V1 is unit lower triangular +* +* w := V1**T * b1 +* + CALL DCOPY( I-1, A( K+1, I ), 1, T( 1, NB ), 1 ) + CALL DTRMV( 'Lower', 'Transpose', 'UNIT', + $ I-1, A( K+1, 1 ), + $ LDA, T( 1, NB ), 1 ) +* +* w := w + V2**T * b2 +* + CALL DGEMV( 'Transpose', N-K-I+1, I-1, + $ ONE, A( K+I, 1 ), + $ LDA, A( K+I, I ), 1, ONE, T( 1, NB ), 1 ) +* +* w := T**T * w +* + CALL DTRMV( 'Upper', 'Transpose', 'NON-UNIT', + $ I-1, T, LDT, + $ T( 1, NB ), 1 ) +* +* b2 := b2 - V2*w +* + CALL DGEMV( 'NO TRANSPOSE', N-K-I+1, I-1, -ONE, + $ A( K+I, 1 ), + $ LDA, T( 1, NB ), 1, ONE, A( K+I, I ), 1 ) +* +* b1 := b1 - V1*w +* + CALL DTRMV( 'Lower', 'NO TRANSPOSE', + $ 'UNIT', I-1, + $ A( K+1, 1 ), LDA, T( 1, NB ), 1 ) + CALL DAXPY( I-1, -ONE, T( 1, NB ), 1, A( K+1, I ), 1 ) +* + A( K+I-1, I-1 ) = EI + END IF +* +* Generate the elementary reflector H(I) to annihilate +* A(K+I+1:N,I) +* + CALL DLARFG( N-K-I+1, A( K+I, I ), A( MIN( K+I+1, N ), I ), 1, + $ TAU( I ) ) + EI = A( K+I, I ) + A( K+I, I ) = ONE +* +* Compute Y(K+1:N,I) +* + CALL DGEMV( 'NO TRANSPOSE', N-K, N-K-I+1, + $ ONE, A( K+1, I+1 ), + $ LDA, A( K+I, I ), 1, ZERO, Y( K+1, I ), 1 ) + CALL DGEMV( 'Transpose', N-K-I+1, I-1, + $ ONE, A( K+I, 1 ), LDA, + $ A( K+I, I ), 1, ZERO, T( 1, I ), 1 ) + CALL DGEMV( 'NO TRANSPOSE', N-K, I-1, -ONE, + $ Y( K+1, 1 ), LDY, + $ T( 1, I ), 1, ONE, Y( K+1, I ), 1 ) + CALL DSCAL( N-K, TAU( I ), Y( K+1, I ), 1 ) +* +* Compute T(1:I,I) +* + CALL DSCAL( I-1, -TAU( I ), T( 1, I ), 1 ) + CALL DTRMV( 'Upper', 'No Transpose', 'NON-UNIT', + $ I-1, T, LDT, + $ T( 1, I ), 1 ) + T( I, I ) = TAU( I ) +* + 10 CONTINUE + A( K+NB, NB ) = EI +* +* Compute Y(1:K,1:NB) +* + CALL DLACPY( 'ALL', K, NB, A( 1, 2 ), LDA, Y, LDY ) + CALL DTRMM( 'RIGHT', 'Lower', 'NO TRANSPOSE', + $ 'UNIT', K, NB, + $ ONE, A( K+1, 1 ), LDA, Y, LDY ) + IF( N.GT.K+NB ) + $ CALL DGEMM( 'NO TRANSPOSE', 'NO TRANSPOSE', K, + $ NB, N-K-NB, ONE, + $ A( 1, 2+NB ), LDA, A( K+1+NB, 1 ), LDA, ONE, Y, + $ LDY ) + CALL DTRMM( 'RIGHT', 'Upper', 'NO TRANSPOSE', + $ 'NON-UNIT', K, NB, + $ ONE, T, LDT, Y, LDY ) +* + RETURN +* +* End of DLAHR2 +* + END diff --git a/lapack/internal/testdata/netlib/dlamch.f b/lapack/internal/testdata/netlib/dlamch.f new file mode 100644 index 00000000..22a16218 --- /dev/null +++ b/lapack/internal/testdata/netlib/dlamch.f @@ -0,0 +1,189 @@ +*> \brief \b DLAMCH +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAMCH determines double precision machine parameters. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CMACH +*> \verbatim +*> Specifies the value to be returned by DLAMCH: +*> = 'E' or 'e', DLAMCH := eps +*> = 'S' or 's , DLAMCH := sfmin +*> = 'B' or 'b', DLAMCH := base +*> = 'P' or 'p', DLAMCH := eps*base +*> = 'N' or 'n', DLAMCH := t +*> = 'R' or 'r', DLAMCH := rnd +*> = 'M' or 'm', DLAMCH := emin +*> = 'U' or 'u', DLAMCH := rmin +*> = 'L' or 'l', DLAMCH := emax +*> = 'O' or 'o', DLAMCH := rmax +*> where +*> eps = relative machine precision +*> sfmin = safe minimum, such that 1/sfmin does not overflow +*> base = base of the machine +*> prec = eps*base +*> t = number of (base) digits in the mantissa +*> rnd = 1.0 when rounding occurs in addition, 0.0 otherwise +*> emin = minimum exponent before (gradual) underflow +*> rmin = underflow threshold - base**(emin-1) +*> emax = largest exponent before overflow +*> rmax = overflow threshold - (base**emax)*(1-eps) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2015 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAMCH( CMACH ) +* +* -- LAPACK auxiliary routine (version 3.6.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2015 +* +* .. Scalar Arguments .. + CHARACTER CMACH +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION RND, EPS, SFMIN, SMALL, RMACH +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC DIGITS, EPSILON, HUGE, MAXEXPONENT, + $ MINEXPONENT, RADIX, TINY +* .. +* .. Executable Statements .. +* +* +* Assume rounding, not chopping. Always. +* + RND = ONE +* + IF( ONE.EQ.RND ) THEN + EPS = EPSILON(ZERO) * 0.5 + ELSE + EPS = EPSILON(ZERO) + END IF +* + IF( LSAME( CMACH, 'E' ) ) THEN + RMACH = EPS + ELSE IF( LSAME( CMACH, 'S' ) ) THEN + SFMIN = TINY(ZERO) + SMALL = ONE / HUGE(ZERO) + IF( SMALL.GE.SFMIN ) THEN +* +* Use SMALL plus a bit, to avoid the possibility of rounding +* causing overflow when computing 1/sfmin. +* + SFMIN = SMALL*( ONE+EPS ) + END IF + RMACH = SFMIN + ELSE IF( LSAME( CMACH, 'B' ) ) THEN + RMACH = RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'P' ) ) THEN + RMACH = EPS * RADIX(ZERO) + ELSE IF( LSAME( CMACH, 'N' ) ) THEN + RMACH = DIGITS(ZERO) + ELSE IF( LSAME( CMACH, 'R' ) ) THEN + RMACH = RND + ELSE IF( LSAME( CMACH, 'M' ) ) THEN + RMACH = MINEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'U' ) ) THEN + RMACH = tiny(zero) + ELSE IF( LSAME( CMACH, 'L' ) ) THEN + RMACH = MAXEXPONENT(ZERO) + ELSE IF( LSAME( CMACH, 'O' ) ) THEN + RMACH = HUGE(ZERO) + ELSE + RMACH = ZERO + END IF +* + DLAMCH = RMACH + RETURN +* +* End of DLAMCH +* + END +************************************************************************ +*> \brief \b DLAMC3 +*> \details +*> \b Purpose: +*> \verbatim +*> DLAMC3 is intended to force A and B to be stored prior to doing +*> the addition of A and B , for use in situations where optimizers +*> might hold one of these in a register. +*> \endverbatim +*> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.. +*> \date November 2015 +*> \ingroup auxOTHERauxiliary +*> +*> \param[in] A +*> \verbatim +*> A is a DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] B +*> \verbatim +*> B is a DOUBLE PRECISION +*> The values A and B. +*> \endverbatim +*> + DOUBLE PRECISION FUNCTION DLAMC3( A, B ) +* +* -- LAPACK auxiliary routine (version 3.6.0) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2010 +* +* .. Scalar Arguments .. + DOUBLE PRECISION A, B +* .. +* ===================================================================== +* +* .. Executable Statements .. +* + DLAMC3 = A + B +* + RETURN +* +* End of DLAMC3 +* + END +* +************************************************************************ diff --git a/lapack/internal/testdata/netlib/dlapy2.f b/lapack/internal/testdata/netlib/dlapy2.f new file mode 100644 index 00000000..d43b0d5d --- /dev/null +++ b/lapack/internal/testdata/netlib/dlapy2.f @@ -0,0 +1,104 @@ +*> \brief \b DLAPY2 returns sqrt(x2+y2). +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAPY2 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DLAPY2( X, Y ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION X, Y +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary +*> overflow. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] X +*> \verbatim +*> X is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] Y +*> \verbatim +*> Y is DOUBLE PRECISION +*> X and Y specify the values x and y. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + DOUBLE PRECISION FUNCTION DLAPY2( X, Y ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION X, Y +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0D0 ) + DOUBLE PRECISION ONE + PARAMETER ( ONE = 1.0D0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION W, XABS, YABS, Z +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, MAX, MIN, SQRT +* .. +* .. Executable Statements .. +* + XABS = ABS( X ) + YABS = ABS( Y ) + W = MAX( XABS, YABS ) + Z = MIN( XABS, YABS ) + IF( Z.EQ.ZERO ) THEN + DLAPY2 = W + ELSE + DLAPY2 = W*SQRT( ONE+( Z / W )**2 ) + END IF + RETURN +* +* End of DLAPY2 +* + END diff --git a/lapack/internal/testdata/netlib/dlaqr1.f b/lapack/internal/testdata/netlib/dlaqr1.f new file mode 100644 index 00000000..df4fb68b --- /dev/null +++ b/lapack/internal/testdata/netlib/dlaqr1.f @@ -0,0 +1,179 @@ +*> \brief \b DLAQR1 sets a scalar multiple of the first column of the product of 2-by-2 or 3-by-3 matrix H and specified shifts. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAQR1 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAQR1( N, H, LDH, SR1, SI1, SR2, SI2, V ) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION SI1, SI2, SR1, SR2 +* INTEGER LDH, N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION H( LDH, * ), V( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> Given a 2-by-2 or 3-by-3 matrix H, DLAQR1 sets v to a +*> scalar multiple of the first column of the product +*> +*> (*) K = (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) +*> +*> scaling to avoid overflows and most underflows. It +*> is assumed that either +*> +*> 1) sr1 = sr2 and si1 = -si2 +*> or +*> 2) si1 = si2 = 0. +*> +*> This is useful for starting double implicit shift bulges +*> in the QR algorithm. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is integer +*> Order of the matrix H. N must be either 2 or 3. +*> \endverbatim +*> +*> \param[in] H +*> \verbatim +*> H is DOUBLE PRECISION array of dimension (LDH,N) +*> The 2-by-2 or 3-by-3 matrix H in (*). +*> \endverbatim +*> +*> \param[in] LDH +*> \verbatim +*> LDH is integer +*> The leading dimension of H as declared in +*> the calling procedure. LDH.GE.N +*> \endverbatim +*> +*> \param[in] SR1 +*> \verbatim +*> SR1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] SI1 +*> \verbatim +*> SI1 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] SR2 +*> \verbatim +*> SR2 is DOUBLE PRECISION +*> \endverbatim +*> +*> \param[in] SI2 +*> \verbatim +*> SI2 is DOUBLE PRECISION +*> The shifts in (*). +*> \endverbatim +*> +*> \param[out] V +*> \verbatim +*> V is DOUBLE PRECISION array of dimension N +*> A scalar multiple of the first column of the +*> matrix K in (*). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup doubleOTHERauxiliary +* +*> \par Contributors: +* ================== +*> +*> Karen Braman and Ralph Byers, Department of Mathematics, +*> University of Kansas, USA +*> +* ===================================================================== + SUBROUTINE DLAQR1( N, H, LDH, SR1, SI1, SR2, SI2, V ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + DOUBLE PRECISION SI1, SI2, SR1, SR2 + INTEGER LDH, N +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), V( * ) +* .. +* +* ================================================================ +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER ( ZERO = 0.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION H21S, H31S, S +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS +* .. +* .. Executable Statements .. + IF( N.EQ.2 ) THEN + S = ABS( H( 1, 1 )-SR2 ) + ABS( SI2 ) + ABS( H( 2, 1 ) ) + IF( S.EQ.ZERO ) THEN + V( 1 ) = ZERO + V( 2 ) = ZERO + ELSE + H21S = H( 2, 1 ) / S + V( 1 ) = H21S*H( 1, 2 ) + ( H( 1, 1 )-SR1 )* + $ ( ( H( 1, 1 )-SR2 ) / S ) - SI1*( SI2 / S ) + V( 2 ) = H21S*( H( 1, 1 )+H( 2, 2 )-SR1-SR2 ) + END IF + ELSE + S = ABS( H( 1, 1 )-SR2 ) + ABS( SI2 ) + ABS( H( 2, 1 ) ) + + $ ABS( H( 3, 1 ) ) + IF( S.EQ.ZERO ) THEN + V( 1 ) = ZERO + V( 2 ) = ZERO + V( 3 ) = ZERO + ELSE + H21S = H( 2, 1 ) / S + H31S = H( 3, 1 ) / S + V( 1 ) = ( H( 1, 1 )-SR1 )*( ( H( 1, 1 )-SR2 ) / S ) - + $ SI1*( SI2 / S ) + H( 1, 2 )*H21S + H( 1, 3 )*H31S + V( 2 ) = H21S*( H( 1, 1 )+H( 2, 2 )-SR1-SR2 ) + + $ H( 2, 3 )*H31S + V( 3 ) = H31S*( H( 1, 1 )+H( 3, 3 )-SR1-SR2 ) + + $ H21S*H( 3, 2 ) + END IF + END IF + END diff --git a/lapack/internal/testdata/netlib/dlaqr5.f b/lapack/internal/testdata/netlib/dlaqr5.f new file mode 100644 index 00000000..37ce6f6b --- /dev/null +++ b/lapack/internal/testdata/netlib/dlaqr5.f @@ -0,0 +1,921 @@ +*> \brief \b DLAQR5 performs a single small-bulge multi-shift QR sweep. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLAQR5 + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NSHFTS, +* SR, SI, H, LDH, ILOZ, IHIZ, Z, LDZ, V, LDV, U, +* LDU, NV, WV, LDWV, NH, WH, LDWH ) +* +* .. Scalar Arguments .. +* INTEGER IHIZ, ILOZ, KACC22, KBOT, KTOP, LDH, LDU, LDV, +* $ LDWH, LDWV, LDZ, N, NH, NSHFTS, NV +* LOGICAL WANTT, WANTZ +* .. +* .. Array Arguments .. +* DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), U( LDU, * ), +* $ V( LDV, * ), WH( LDWH, * ), WV( LDWV, * ), +* $ Z( LDZ, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLAQR5, called by DLAQR0, performs a +*> single small-bulge multi-shift QR sweep. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] WANTT +*> \verbatim +*> WANTT is logical scalar +*> WANTT = .true. if the quasi-triangular Schur factor +*> is being computed. WANTT is set to .false. otherwise. +*> \endverbatim +*> +*> \param[in] WANTZ +*> \verbatim +*> WANTZ is logical scalar +*> WANTZ = .true. if the orthogonal Schur factor is being +*> computed. WANTZ is set to .false. otherwise. +*> \endverbatim +*> +*> \param[in] KACC22 +*> \verbatim +*> KACC22 is integer with value 0, 1, or 2. +*> Specifies the computation mode of far-from-diagonal +*> orthogonal updates. +*> = 0: DLAQR5 does not accumulate reflections and does not +*> use matrix-matrix multiply to update far-from-diagonal +*> matrix entries. +*> = 1: DLAQR5 accumulates reflections and uses matrix-matrix +*> multiply to update the far-from-diagonal matrix entries. +*> = 2: DLAQR5 accumulates reflections, uses matrix-matrix +*> multiply to update the far-from-diagonal matrix entries, +*> and takes advantage of 2-by-2 block structure during +*> matrix multiplies. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is integer scalar +*> N is the order of the Hessenberg matrix H upon which this +*> subroutine operates. +*> \endverbatim +*> +*> \param[in] KTOP +*> \verbatim +*> KTOP is integer scalar +*> \endverbatim +*> +*> \param[in] KBOT +*> \verbatim +*> KBOT is integer scalar +*> These are the first and last rows and columns of an +*> isolated diagonal block upon which the QR sweep is to be +*> applied. It is assumed without a check that +*> either KTOP = 1 or H(KTOP,KTOP-1) = 0 +*> and +*> either KBOT = N or H(KBOT+1,KBOT) = 0. +*> \endverbatim +*> +*> \param[in] NSHFTS +*> \verbatim +*> NSHFTS is integer scalar +*> NSHFTS gives the number of simultaneous shifts. NSHFTS +*> must be positive and even. +*> \endverbatim +*> +*> \param[in,out] SR +*> \verbatim +*> SR is DOUBLE PRECISION array of size (NSHFTS) +*> \endverbatim +*> +*> \param[in,out] SI +*> \verbatim +*> SI is DOUBLE PRECISION array of size (NSHFTS) +*> SR contains the real parts and SI contains the imaginary +*> parts of the NSHFTS shifts of origin that define the +*> multi-shift QR sweep. On output SR and SI may be +*> reordered. +*> \endverbatim +*> +*> \param[in,out] H +*> \verbatim +*> H is DOUBLE PRECISION array of size (LDH,N) +*> On input H contains a Hessenberg matrix. On output a +*> multi-shift QR sweep with shifts SR(J)+i*SI(J) is applied +*> to the isolated diagonal block in rows and columns KTOP +*> through KBOT. +*> \endverbatim +*> +*> \param[in] LDH +*> \verbatim +*> LDH is integer scalar +*> LDH is the leading dimension of H just as declared in the +*> calling procedure. LDH.GE.MAX(1,N). +*> \endverbatim +*> +*> \param[in] ILOZ +*> \verbatim +*> ILOZ is INTEGER +*> \endverbatim +*> +*> \param[in] IHIZ +*> \verbatim +*> IHIZ is INTEGER +*> Specify the rows of Z to which transformations must be +*> applied if WANTZ is .TRUE.. 1 .LE. ILOZ .LE. IHIZ .LE. N +*> \endverbatim +*> +*> \param[in,out] Z +*> \verbatim +*> Z is DOUBLE PRECISION array of size (LDZ,IHI) +*> If WANTZ = .TRUE., then the QR Sweep orthogonal +*> similarity transformation is accumulated into +*> Z(ILOZ:IHIZ,ILO:IHI) from the right. +*> If WANTZ = .FALSE., then Z is unreferenced. +*> \endverbatim +*> +*> \param[in] LDZ +*> \verbatim +*> LDZ is integer scalar +*> LDA is the leading dimension of Z just as declared in +*> the calling procedure. LDZ.GE.N. +*> \endverbatim +*> +*> \param[out] V +*> \verbatim +*> V is DOUBLE PRECISION array of size (LDV,NSHFTS/2) +*> \endverbatim +*> +*> \param[in] LDV +*> \verbatim +*> LDV is integer scalar +*> LDV is the leading dimension of V as declared in the +*> calling procedure. LDV.GE.3. +*> \endverbatim +*> +*> \param[out] U +*> \verbatim +*> U is DOUBLE PRECISION array of size +*> (LDU,3*NSHFTS-3) +*> \endverbatim +*> +*> \param[in] LDU +*> \verbatim +*> LDU is integer scalar +*> LDU is the leading dimension of U just as declared in the +*> in the calling subroutine. LDU.GE.3*NSHFTS-3. +*> \endverbatim +*> +*> \param[in] NH +*> \verbatim +*> NH is integer scalar +*> NH is the number of columns in array WH available for +*> workspace. NH.GE.1. +*> \endverbatim +*> +*> \param[out] WH +*> \verbatim +*> WH is DOUBLE PRECISION array of size (LDWH,NH) +*> \endverbatim +*> +*> \param[in] LDWH +*> \verbatim +*> LDWH is integer scalar +*> Leading dimension of WH just as declared in the +*> calling procedure. LDWH.GE.3*NSHFTS-3. +*> \endverbatim +*> +*> \param[in] NV +*> \verbatim +*> NV is integer scalar +*> NV is the number of rows in WV agailable for workspace. +*> NV.GE.1. +*> \endverbatim +*> +*> \param[out] WV +*> \verbatim +*> WV is DOUBLE PRECISION array of size +*> (LDWV,3*NSHFTS-3) +*> \endverbatim +*> +*> \param[in] LDWV +*> \verbatim +*> LDWV is integer scalar +*> LDWV is the leading dimension of WV as declared in the +*> in the calling subroutine. LDWV.GE.NV. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup doubleOTHERauxiliary +* +*> \par Contributors: +* ================== +*> +*> Karen Braman and Ralph Byers, Department of Mathematics, +*> University of Kansas, USA +* +*> \par References: +* ================ +*> +*> K. Braman, R. Byers and R. Mathias, The Multi-Shift QR +*> Algorithm Part I: Maintaining Well Focused Shifts, and Level 3 +*> Performance, SIAM Journal of Matrix Analysis, volume 23, pages +*> 929--947, 2002. +*> +* ===================================================================== + SUBROUTINE DLAQR5( WANTT, WANTZ, KACC22, N, KTOP, KBOT, NSHFTS, + $ SR, SI, H, LDH, ILOZ, IHIZ, Z, LDZ, V, LDV, U, + $ LDU, NV, WV, LDWV, NH, WH, LDWH ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER IHIZ, ILOZ, KACC22, KBOT, KTOP, LDH, LDU, LDV, + $ LDWH, LDWV, LDZ, N, NH, NSHFTS, NV + LOGICAL WANTT, WANTZ +* .. +* .. Array Arguments .. + DOUBLE PRECISION H( LDH, * ), SI( * ), SR( * ), U( LDU, * ), + $ V( LDV, * ), WH( LDWH, * ), WV( LDWV, * ), + $ Z( LDZ, * ) +* .. +* +* ================================================================ +* .. Parameters .. + DOUBLE PRECISION ZERO, ONE + PARAMETER ( ZERO = 0.0d0, ONE = 1.0d0 ) +* .. +* .. Local Scalars .. + DOUBLE PRECISION ALPHA, BETA, H11, H12, H21, H22, REFSUM, + $ SAFMAX, SAFMIN, SCL, SMLNUM, SWAP, TST1, TST2, + $ ULP + INTEGER I, I2, I4, INCOL, J, J2, J4, JBOT, JCOL, JLEN, + $ JROW, JTOP, K, K1, KDU, KMS, KNZ, KRCOL, KZS, + $ M, M22, MBOT, MEND, MSTART, MTOP, NBMPS, NDCOL, + $ NS, NU + LOGICAL ACCUM, BLK22, BMP22 +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH + EXTERNAL DLAMCH +* .. +* .. Intrinsic Functions .. +* + INTRINSIC ABS, DBLE, MAX, MIN, MOD +* .. +* .. Local Arrays .. + DOUBLE PRECISION VT( 3 ) +* .. +* .. External Subroutines .. + EXTERNAL DGEMM, DLABAD, DLACPY, DLAQR1, DLARFG, DLASET, + $ DTRMM +* .. +* .. Executable Statements .. +* +* ==== If there are no shifts, then there is nothing to do. ==== +* + IF( NSHFTS.LT.2 ) + $ RETURN +* +* ==== If the active block is empty or 1-by-1, then there +* . is nothing to do. ==== +* + IF( KTOP.GE.KBOT ) + $ RETURN +* +* ==== Shuffle shifts into pairs of real shifts and pairs +* . of complex conjugate shifts assuming complex +* . conjugate shifts are already adjacent to one +* . another. ==== +* + DO 10 I = 1, NSHFTS - 2, 2 + IF( SI( I ).NE.-SI( I+1 ) ) THEN +* + SWAP = SR( I ) + SR( I ) = SR( I+1 ) + SR( I+1 ) = SR( I+2 ) + SR( I+2 ) = SWAP +* + SWAP = SI( I ) + SI( I ) = SI( I+1 ) + SI( I+1 ) = SI( I+2 ) + SI( I+2 ) = SWAP + END IF + 10 CONTINUE +* +* ==== NSHFTS is supposed to be even, but if it is odd, +* . then simply reduce it by one. The shuffle above +* . ensures that the dropped shift is real and that +* . the remaining shifts are paired. ==== +* + NS = NSHFTS - MOD( NSHFTS, 2 ) +* +* ==== Machine constants for deflation ==== +* + SAFMIN = DLAMCH( 'SAFE MINIMUM' ) + SAFMAX = ONE / SAFMIN + CALL DLABAD( SAFMIN, SAFMAX ) + ULP = DLAMCH( 'PRECISION' ) + SMLNUM = SAFMIN*( DBLE( N ) / ULP ) +* +* ==== Use accumulated reflections to update far-from-diagonal +* . entries ? ==== +* + ACCUM = ( KACC22.EQ.1 ) .OR. ( KACC22.EQ.2 ) +* +* ==== If so, exploit the 2-by-2 block structure? ==== +* + BLK22 = ( NS.GT.2 ) .AND. ( KACC22.EQ.2 ) +* +* ==== clear trash ==== +* + IF( KTOP+2.LE.KBOT ) + $ H( KTOP+2, KTOP ) = ZERO +* +* ==== NBMPS = number of 2-shift bulges in the chain ==== +* + NBMPS = NS / 2 +* +* ==== KDU = width of slab ==== +* + KDU = 6*NBMPS - 3 +* +* ==== Create and chase chains of NBMPS bulges ==== +* + DO 220 INCOL = 3*( 1-NBMPS ) + KTOP - 1, KBOT - 2, 3*NBMPS - 2 + NDCOL = INCOL + KDU + IF( ACCUM ) + $ CALL DLASET( 'ALL', KDU, KDU, ZERO, ONE, U, LDU ) +* +* ==== Near-the-diagonal bulge chase. The following loop +* . performs the near-the-diagonal part of a small bulge +* . multi-shift QR sweep. Each 6*NBMPS-2 column diagonal +* . chunk extends from column INCOL to column NDCOL +* . (including both column INCOL and column NDCOL). The +* . following loop chases a 3*NBMPS column long chain of +* . NBMPS bulges 3*NBMPS-2 columns to the right. (INCOL +* . may be less than KTOP and and NDCOL may be greater than +* . KBOT indicating phantom columns from which to chase +* . bulges before they are actually introduced or to which +* . to chase bulges beyond column KBOT.) ==== +* + DO 150 KRCOL = INCOL, MIN( INCOL+3*NBMPS-3, KBOT-2 ) +* +* ==== Bulges number MTOP to MBOT are active double implicit +* . shift bulges. There may or may not also be small +* . 2-by-2 bulge, if there is room. The inactive bulges +* . (if any) must wait until the active bulges have moved +* . down the diagonal to make room. The phantom matrix +* . paradigm described above helps keep track. ==== +* + MTOP = MAX( 1, ( ( KTOP-1 )-KRCOL+2 ) / 3+1 ) + MBOT = MIN( NBMPS, ( KBOT-KRCOL ) / 3 ) + M22 = MBOT + 1 + BMP22 = ( MBOT.LT.NBMPS ) .AND. ( KRCOL+3*( M22-1 ) ).EQ. + $ ( KBOT-2 ) +* +* ==== Generate reflections to chase the chain right +* . one column. (The minimum value of K is KTOP-1.) ==== +* + DO 20 M = MTOP, MBOT + K = KRCOL + 3*( M-1 ) + IF( K.EQ.KTOP-1 ) THEN + CALL DLAQR1( 3, H( KTOP, KTOP ), LDH, SR( 2*M-1 ), + $ SI( 2*M-1 ), SR( 2*M ), SI( 2*M ), + $ V( 1, M ) ) + ALPHA = V( 1, M ) + CALL DLARFG( 3, ALPHA, V( 2, M ), 1, V( 1, M ) ) + ELSE + BETA = H( K+1, K ) + V( 2, M ) = H( K+2, K ) + V( 3, M ) = H( K+3, K ) + CALL DLARFG( 3, BETA, V( 2, M ), 1, V( 1, M ) ) +* +* ==== A Bulge may collapse because of vigilant +* . deflation or destructive underflow. In the +* . underflow case, try the two-small-subdiagonals +* . trick to try to reinflate the bulge. ==== +* + IF( H( K+3, K ).NE.ZERO .OR. H( K+3, K+1 ).NE. + $ ZERO .OR. H( K+3, K+2 ).EQ.ZERO ) THEN +* +* ==== Typical case: not collapsed (yet). ==== +* + H( K+1, K ) = BETA + H( K+2, K ) = ZERO + H( K+3, K ) = ZERO + ELSE +* +* ==== Atypical case: collapsed. Attempt to +* . reintroduce ignoring H(K+1,K) and H(K+2,K). +* . If the fill resulting from the new +* . reflector is too large, then abandon it. +* . Otherwise, use the new one. ==== +* + CALL DLAQR1( 3, H( K+1, K+1 ), LDH, SR( 2*M-1 ), + $ SI( 2*M-1 ), SR( 2*M ), SI( 2*M ), + $ VT ) + ALPHA = VT( 1 ) + CALL DLARFG( 3, ALPHA, VT( 2 ), 1, VT( 1 ) ) + REFSUM = VT( 1 )*( H( K+1, K )+VT( 2 )* + $ H( K+2, K ) ) +* + IF( ABS( H( K+2, K )-REFSUM*VT( 2 ) )+ + $ ABS( REFSUM*VT( 3 ) ).GT.ULP* + $ ( ABS( H( K, K ) )+ABS( H( K+1, + $ K+1 ) )+ABS( H( K+2, K+2 ) ) ) ) THEN +* +* ==== Starting a new bulge here would +* . create non-negligible fill. Use +* . the old one with trepidation. ==== +* + H( K+1, K ) = BETA + H( K+2, K ) = ZERO + H( K+3, K ) = ZERO + ELSE +* +* ==== Stating a new bulge here would +* . create only negligible fill. +* . Replace the old reflector with +* . the new one. ==== +* + H( K+1, K ) = H( K+1, K ) - REFSUM + H( K+2, K ) = ZERO + H( K+3, K ) = ZERO + V( 1, M ) = VT( 1 ) + V( 2, M ) = VT( 2 ) + V( 3, M ) = VT( 3 ) + END IF + END IF + END IF + 20 CONTINUE +* +* ==== Generate a 2-by-2 reflection, if needed. ==== +* + K = KRCOL + 3*( M22-1 ) + IF( BMP22 ) THEN + IF( K.EQ.KTOP-1 ) THEN + CALL DLAQR1( 2, H( K+1, K+1 ), LDH, SR( 2*M22-1 ), + $ SI( 2*M22-1 ), SR( 2*M22 ), SI( 2*M22 ), + $ V( 1, M22 ) ) + BETA = V( 1, M22 ) + CALL DLARFG( 2, BETA, V( 2, M22 ), 1, V( 1, M22 ) ) + ELSE + BETA = H( K+1, K ) + V( 2, M22 ) = H( K+2, K ) + CALL DLARFG( 2, BETA, V( 2, M22 ), 1, V( 1, M22 ) ) + H( K+1, K ) = BETA + H( K+2, K ) = ZERO + END IF + END IF +* +* ==== Multiply H by reflections from the left ==== +* + IF( ACCUM ) THEN + JBOT = MIN( NDCOL, KBOT ) + ELSE IF( WANTT ) THEN + JBOT = N + ELSE + JBOT = KBOT + END IF + DO 40 J = MAX( KTOP, KRCOL ), JBOT + MEND = MIN( MBOT, ( J-KRCOL+2 ) / 3 ) + DO 30 M = MTOP, MEND + K = KRCOL + 3*( M-1 ) + REFSUM = V( 1, M )*( H( K+1, J )+V( 2, M )* + $ H( K+2, J )+V( 3, M )*H( K+3, J ) ) + H( K+1, J ) = H( K+1, J ) - REFSUM + H( K+2, J ) = H( K+2, J ) - REFSUM*V( 2, M ) + H( K+3, J ) = H( K+3, J ) - REFSUM*V( 3, M ) + 30 CONTINUE + 40 CONTINUE + IF( BMP22 ) THEN + K = KRCOL + 3*( M22-1 ) + DO 50 J = MAX( K+1, KTOP ), JBOT + REFSUM = V( 1, M22 )*( H( K+1, J )+V( 2, M22 )* + $ H( K+2, J ) ) + H( K+1, J ) = H( K+1, J ) - REFSUM + H( K+2, J ) = H( K+2, J ) - REFSUM*V( 2, M22 ) + 50 CONTINUE + END IF +* +* ==== Multiply H by reflections from the right. +* . Delay filling in the last row until the +* . vigilant deflation check is complete. ==== +* + IF( ACCUM ) THEN + JTOP = MAX( KTOP, INCOL ) + ELSE IF( WANTT ) THEN + JTOP = 1 + ELSE + JTOP = KTOP + END IF + DO 90 M = MTOP, MBOT + IF( V( 1, M ).NE.ZERO ) THEN + K = KRCOL + 3*( M-1 ) + DO 60 J = JTOP, MIN( KBOT, K+3 ) + REFSUM = V( 1, M )*( H( J, K+1 )+V( 2, M )* + $ H( J, K+2 )+V( 3, M )*H( J, K+3 ) ) + H( J, K+1 ) = H( J, K+1 ) - REFSUM + H( J, K+2 ) = H( J, K+2 ) - REFSUM*V( 2, M ) + H( J, K+3 ) = H( J, K+3 ) - REFSUM*V( 3, M ) + 60 CONTINUE +* + IF( ACCUM ) THEN +* +* ==== Accumulate U. (If necessary, update Z later +* . with with an efficient matrix-matrix +* . multiply.) ==== +* + KMS = K - INCOL + DO 70 J = MAX( 1, KTOP-INCOL ), KDU + REFSUM = V( 1, M )*( U( J, KMS+1 )+V( 2, M )* + $ U( J, KMS+2 )+V( 3, M )*U( J, KMS+3 ) ) + U( J, KMS+1 ) = U( J, KMS+1 ) - REFSUM + U( J, KMS+2 ) = U( J, KMS+2 ) - REFSUM*V( 2, M ) + U( J, KMS+3 ) = U( J, KMS+3 ) - REFSUM*V( 3, M ) + 70 CONTINUE + ELSE IF( WANTZ ) THEN +* +* ==== U is not accumulated, so update Z +* . now by multiplying by reflections +* . from the right. ==== +* + DO 80 J = ILOZ, IHIZ + REFSUM = V( 1, M )*( Z( J, K+1 )+V( 2, M )* + $ Z( J, K+2 )+V( 3, M )*Z( J, K+3 ) ) + Z( J, K+1 ) = Z( J, K+1 ) - REFSUM + Z( J, K+2 ) = Z( J, K+2 ) - REFSUM*V( 2, M ) + Z( J, K+3 ) = Z( J, K+3 ) - REFSUM*V( 3, M ) + 80 CONTINUE + END IF + END IF + 90 CONTINUE +* +* ==== Special case: 2-by-2 reflection (if needed) ==== +* + K = KRCOL + 3*( M22-1 ) + IF( BMP22 ) THEN + IF ( V( 1, M22 ).NE.ZERO ) THEN + DO 100 J = JTOP, MIN( KBOT, K+3 ) + REFSUM = V( 1, M22 )*( H( J, K+1 )+V( 2, M22 )* + $ H( J, K+2 ) ) + H( J, K+1 ) = H( J, K+1 ) - REFSUM + H( J, K+2 ) = H( J, K+2 ) - REFSUM*V( 2, M22 ) + 100 CONTINUE +* + IF( ACCUM ) THEN + KMS = K - INCOL + DO 110 J = MAX( 1, KTOP-INCOL ), KDU + REFSUM = V( 1, M22 )*( U( J, KMS+1 )+ + $ V( 2, M22 )*U( J, KMS+2 ) ) + U( J, KMS+1 ) = U( J, KMS+1 ) - REFSUM + U( J, KMS+2 ) = U( J, KMS+2 ) - + $ REFSUM*V( 2, M22 ) + 110 CONTINUE + ELSE IF( WANTZ ) THEN + DO 120 J = ILOZ, IHIZ + REFSUM = V( 1, M22 )*( Z( J, K+1 )+V( 2, M22 )* + $ Z( J, K+2 ) ) + Z( J, K+1 ) = Z( J, K+1 ) - REFSUM + Z( J, K+2 ) = Z( J, K+2 ) - REFSUM*V( 2, M22 ) + 120 CONTINUE + END IF + END IF + END IF +* +* ==== Vigilant deflation check ==== +* + MSTART = MTOP + IF( KRCOL+3*( MSTART-1 ).LT.KTOP ) + $ MSTART = MSTART + 1 + MEND = MBOT + IF( BMP22 ) + $ MEND = MEND + 1 + IF( KRCOL.EQ.KBOT-2 ) + $ MEND = MEND + 1 + DO 130 M = MSTART, MEND + K = MIN( KBOT-1, KRCOL+3*( M-1 ) ) +* +* ==== The following convergence test requires that +* . the tradition small-compared-to-nearby-diagonals +* . criterion and the Ahues & Tisseur (LAWN 122, 1997) +* . criteria both be satisfied. The latter improves +* . accuracy in some examples. Falling back on an +* . alternate convergence criterion when TST1 or TST2 +* . is zero (as done here) is traditional but probably +* . unnecessary. ==== +* + IF( H( K+1, K ).NE.ZERO ) THEN + TST1 = ABS( H( K, K ) ) + ABS( H( K+1, K+1 ) ) + IF( TST1.EQ.ZERO ) THEN + IF( K.GE.KTOP+1 ) + $ TST1 = TST1 + ABS( H( K, K-1 ) ) + IF( K.GE.KTOP+2 ) + $ TST1 = TST1 + ABS( H( K, K-2 ) ) + IF( K.GE.KTOP+3 ) + $ TST1 = TST1 + ABS( H( K, K-3 ) ) + IF( K.LE.KBOT-2 ) + $ TST1 = TST1 + ABS( H( K+2, K+1 ) ) + IF( K.LE.KBOT-3 ) + $ TST1 = TST1 + ABS( H( K+3, K+1 ) ) + IF( K.LE.KBOT-4 ) + $ TST1 = TST1 + ABS( H( K+4, K+1 ) ) + END IF + IF( ABS( H( K+1, K ) ).LE.MAX( SMLNUM, ULP*TST1 ) ) + $ THEN + H12 = MAX( ABS( H( K+1, K ) ), ABS( H( K, K+1 ) ) ) + H21 = MIN( ABS( H( K+1, K ) ), ABS( H( K, K+1 ) ) ) + H11 = MAX( ABS( H( K+1, K+1 ) ), + $ ABS( H( K, K )-H( K+1, K+1 ) ) ) + H22 = MIN( ABS( H( K+1, K+1 ) ), + $ ABS( H( K, K )-H( K+1, K+1 ) ) ) + SCL = H11 + H12 + TST2 = H22*( H11 / SCL ) +* + IF( TST2.EQ.ZERO .OR. H21*( H12 / SCL ).LE. + $ MAX( SMLNUM, ULP*TST2 ) )H( K+1, K ) = ZERO + END IF + END IF + 130 CONTINUE +* +* ==== Fill in the last row of each bulge. ==== +* + MEND = MIN( NBMPS, ( KBOT-KRCOL-1 ) / 3 ) + DO 140 M = MTOP, MEND + K = KRCOL + 3*( M-1 ) + REFSUM = V( 1, M )*V( 3, M )*H( K+4, K+3 ) + H( K+4, K+1 ) = -REFSUM + H( K+4, K+2 ) = -REFSUM*V( 2, M ) + H( K+4, K+3 ) = H( K+4, K+3 ) - REFSUM*V( 3, M ) + 140 CONTINUE +* +* ==== End of near-the-diagonal bulge chase. ==== +* + 150 CONTINUE +* +* ==== Use U (if accumulated) to update far-from-diagonal +* . entries in H. If required, use U to update Z as +* . well. ==== +* + IF( ACCUM ) THEN + IF( WANTT ) THEN + JTOP = 1 + JBOT = N + ELSE + JTOP = KTOP + JBOT = KBOT + END IF + IF( ( .NOT.BLK22 ) .OR. ( INCOL.LT.KTOP ) .OR. + $ ( NDCOL.GT.KBOT ) .OR. ( NS.LE.2 ) ) THEN +* +* ==== Updates not exploiting the 2-by-2 block +* . structure of U. K1 and NU keep track of +* . the location and size of U in the special +* . cases of introducing bulges and chasing +* . bulges off the bottom. In these special +* . cases and in case the number of shifts +* . is NS = 2, there is no 2-by-2 block +* . structure to exploit. ==== +* + K1 = MAX( 1, KTOP-INCOL ) + NU = ( KDU-MAX( 0, NDCOL-KBOT ) ) - K1 + 1 +* +* ==== Horizontal Multiply ==== +* + DO 160 JCOL = MIN( NDCOL, KBOT ) + 1, JBOT, NH + JLEN = MIN( NH, JBOT-JCOL+1 ) + CALL DGEMM( 'C', 'N', NU, JLEN, NU, ONE, U( K1, K1 ), + $ LDU, H( INCOL+K1, JCOL ), LDH, ZERO, WH, + $ LDWH ) + CALL DLACPY( 'ALL', NU, JLEN, WH, LDWH, + $ H( INCOL+K1, JCOL ), LDH ) + 160 CONTINUE +* +* ==== Vertical multiply ==== +* + DO 170 JROW = JTOP, MAX( KTOP, INCOL ) - 1, NV + JLEN = MIN( NV, MAX( KTOP, INCOL )-JROW ) + CALL DGEMM( 'N', 'N', JLEN, NU, NU, ONE, + $ H( JROW, INCOL+K1 ), LDH, U( K1, K1 ), + $ LDU, ZERO, WV, LDWV ) + CALL DLACPY( 'ALL', JLEN, NU, WV, LDWV, + $ H( JROW, INCOL+K1 ), LDH ) + 170 CONTINUE +* +* ==== Z multiply (also vertical) ==== +* + IF( WANTZ ) THEN + DO 180 JROW = ILOZ, IHIZ, NV + JLEN = MIN( NV, IHIZ-JROW+1 ) + CALL DGEMM( 'N', 'N', JLEN, NU, NU, ONE, + $ Z( JROW, INCOL+K1 ), LDZ, U( K1, K1 ), + $ LDU, ZERO, WV, LDWV ) + CALL DLACPY( 'ALL', JLEN, NU, WV, LDWV, + $ Z( JROW, INCOL+K1 ), LDZ ) + 180 CONTINUE + END IF + ELSE +* +* ==== Updates exploiting U's 2-by-2 block structure. +* . (I2, I4, J2, J4 are the last rows and columns +* . of the blocks.) ==== +* + I2 = ( KDU+1 ) / 2 + I4 = KDU + J2 = I4 - I2 + J4 = KDU +* +* ==== KZS and KNZ deal with the band of zeros +* . along the diagonal of one of the triangular +* . blocks. ==== +* + KZS = ( J4-J2 ) - ( NS+1 ) + KNZ = NS + 1 +* +* ==== Horizontal multiply ==== +* + DO 190 JCOL = MIN( NDCOL, KBOT ) + 1, JBOT, NH + JLEN = MIN( NH, JBOT-JCOL+1 ) +* +* ==== Copy bottom of H to top+KZS of scratch ==== +* (The first KZS rows get multiplied by zero.) ==== +* + CALL DLACPY( 'ALL', KNZ, JLEN, H( INCOL+1+J2, JCOL ), + $ LDH, WH( KZS+1, 1 ), LDWH ) +* +* ==== Multiply by U21**T ==== +* + CALL DLASET( 'ALL', KZS, JLEN, ZERO, ZERO, WH, LDWH ) + CALL DTRMM( 'L', 'U', 'C', 'N', KNZ, JLEN, ONE, + $ U( J2+1, 1+KZS ), LDU, WH( KZS+1, 1 ), + $ LDWH ) +* +* ==== Multiply top of H by U11**T ==== +* + CALL DGEMM( 'C', 'N', I2, JLEN, J2, ONE, U, LDU, + $ H( INCOL+1, JCOL ), LDH, ONE, WH, LDWH ) +* +* ==== Copy top of H to bottom of WH ==== +* + CALL DLACPY( 'ALL', J2, JLEN, H( INCOL+1, JCOL ), LDH, + $ WH( I2+1, 1 ), LDWH ) +* +* ==== Multiply by U21**T ==== +* + CALL DTRMM( 'L', 'L', 'C', 'N', J2, JLEN, ONE, + $ U( 1, I2+1 ), LDU, WH( I2+1, 1 ), LDWH ) +* +* ==== Multiply by U22 ==== +* + CALL DGEMM( 'C', 'N', I4-I2, JLEN, J4-J2, ONE, + $ U( J2+1, I2+1 ), LDU, + $ H( INCOL+1+J2, JCOL ), LDH, ONE, + $ WH( I2+1, 1 ), LDWH ) +* +* ==== Copy it back ==== +* + CALL DLACPY( 'ALL', KDU, JLEN, WH, LDWH, + $ H( INCOL+1, JCOL ), LDH ) + 190 CONTINUE +* +* ==== Vertical multiply ==== +* + DO 200 JROW = JTOP, MAX( INCOL, KTOP ) - 1, NV + JLEN = MIN( NV, MAX( INCOL, KTOP )-JROW ) +* +* ==== Copy right of H to scratch (the first KZS +* . columns get multiplied by zero) ==== +* + CALL DLACPY( 'ALL', JLEN, KNZ, H( JROW, INCOL+1+J2 ), + $ LDH, WV( 1, 1+KZS ), LDWV ) +* +* ==== Multiply by U21 ==== +* + CALL DLASET( 'ALL', JLEN, KZS, ZERO, ZERO, WV, LDWV ) + CALL DTRMM( 'R', 'U', 'N', 'N', JLEN, KNZ, ONE, + $ U( J2+1, 1+KZS ), LDU, WV( 1, 1+KZS ), + $ LDWV ) +* +* ==== Multiply by U11 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I2, J2, ONE, + $ H( JROW, INCOL+1 ), LDH, U, LDU, ONE, WV, + $ LDWV ) +* +* ==== Copy left of H to right of scratch ==== +* + CALL DLACPY( 'ALL', JLEN, J2, H( JROW, INCOL+1 ), LDH, + $ WV( 1, 1+I2 ), LDWV ) +* +* ==== Multiply by U21 ==== +* + CALL DTRMM( 'R', 'L', 'N', 'N', JLEN, I4-I2, ONE, + $ U( 1, I2+1 ), LDU, WV( 1, 1+I2 ), LDWV ) +* +* ==== Multiply by U22 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I4-I2, J4-J2, ONE, + $ H( JROW, INCOL+1+J2 ), LDH, + $ U( J2+1, I2+1 ), LDU, ONE, WV( 1, 1+I2 ), + $ LDWV ) +* +* ==== Copy it back ==== +* + CALL DLACPY( 'ALL', JLEN, KDU, WV, LDWV, + $ H( JROW, INCOL+1 ), LDH ) + 200 CONTINUE +* +* ==== Multiply Z (also vertical) ==== +* + IF( WANTZ ) THEN + DO 210 JROW = ILOZ, IHIZ, NV + JLEN = MIN( NV, IHIZ-JROW+1 ) +* +* ==== Copy right of Z to left of scratch (first +* . KZS columns get multiplied by zero) ==== +* + CALL DLACPY( 'ALL', JLEN, KNZ, + $ Z( JROW, INCOL+1+J2 ), LDZ, + $ WV( 1, 1+KZS ), LDWV ) +* +* ==== Multiply by U12 ==== +* + CALL DLASET( 'ALL', JLEN, KZS, ZERO, ZERO, WV, + $ LDWV ) + CALL DTRMM( 'R', 'U', 'N', 'N', JLEN, KNZ, ONE, + $ U( J2+1, 1+KZS ), LDU, WV( 1, 1+KZS ), + $ LDWV ) +* +* ==== Multiply by U11 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I2, J2, ONE, + $ Z( JROW, INCOL+1 ), LDZ, U, LDU, ONE, + $ WV, LDWV ) +* +* ==== Copy left of Z to right of scratch ==== +* + CALL DLACPY( 'ALL', JLEN, J2, Z( JROW, INCOL+1 ), + $ LDZ, WV( 1, 1+I2 ), LDWV ) +* +* ==== Multiply by U21 ==== +* + CALL DTRMM( 'R', 'L', 'N', 'N', JLEN, I4-I2, ONE, + $ U( 1, I2+1 ), LDU, WV( 1, 1+I2 ), + $ LDWV ) +* +* ==== Multiply by U22 ==== +* + CALL DGEMM( 'N', 'N', JLEN, I4-I2, J4-J2, ONE, + $ Z( JROW, INCOL+1+J2 ), LDZ, + $ U( J2+1, I2+1 ), LDU, ONE, + $ WV( 1, 1+I2 ), LDWV ) +* +* ==== Copy the result back to Z ==== +* + CALL DLACPY( 'ALL', JLEN, KDU, WV, LDWV, + $ Z( JROW, INCOL+1 ), LDZ ) + 210 CONTINUE + END IF + END IF + END IF + 220 CONTINUE +* +* ==== End of DLAQR5 ==== +* + END diff --git a/lapack/internal/testdata/netlib/dlarfg.f b/lapack/internal/testdata/netlib/dlarfg.f new file mode 100644 index 00000000..ce91d33c --- /dev/null +++ b/lapack/internal/testdata/netlib/dlarfg.f @@ -0,0 +1,196 @@ +*> \brief \b DLARFG generates an elementary reflector (Householder matrix). +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLARFG + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU ) +* +* .. Scalar Arguments .. +* INTEGER INCX, N +* DOUBLE PRECISION ALPHA, TAU +* .. +* .. Array Arguments .. +* DOUBLE PRECISION X( * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLARFG generates a real elementary reflector H of order n, such +*> that +*> +*> H * ( alpha ) = ( beta ), H**T * H = I. +*> ( x ) ( 0 ) +*> +*> where alpha and beta are scalars, and x is an (n-1)-element real +*> vector. H is represented in the form +*> +*> H = I - tau * ( 1 ) * ( 1 v**T ) , +*> ( v ) +*> +*> where tau is a real scalar and v is a real (n-1)-element +*> vector. +*> +*> If the elements of x are all zero, then tau = 0 and H is taken to be +*> the unit matrix. +*> +*> Otherwise 1 <= tau <= 2. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The order of the elementary reflector. +*> \endverbatim +*> +*> \param[in,out] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION +*> On entry, the value alpha. +*> On exit, it is overwritten with the value beta. +*> \endverbatim +*> +*> \param[in,out] X +*> \verbatim +*> X is DOUBLE PRECISION array, dimension +*> (1+(N-2)*abs(INCX)) +*> On entry, the vector x. +*> On exit, it is overwritten with the vector v. +*> \endverbatim +*> +*> \param[in] INCX +*> \verbatim +*> INCX is INTEGER +*> The increment between elements of X. INCX > 0. +*> \endverbatim +*> +*> \param[out] TAU +*> \verbatim +*> TAU is DOUBLE PRECISION +*> The value tau. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date September 2012 +* +*> \ingroup doubleOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU ) +* +* -- LAPACK auxiliary routine (version 3.4.2) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* September 2012 +* +* .. Scalar Arguments .. + INTEGER INCX, N + DOUBLE PRECISION ALPHA, TAU +* .. +* .. Array Arguments .. + DOUBLE PRECISION X( * ) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE, ZERO + PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 ) +* .. +* .. Local Scalars .. + INTEGER J, KNT + DOUBLE PRECISION BETA, RSAFMN, SAFMIN, XNORM +* .. +* .. External Functions .. + DOUBLE PRECISION DLAMCH, DLAPY2, DNRM2 + EXTERNAL DLAMCH, DLAPY2, DNRM2 +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS, SIGN +* .. +* .. External Subroutines .. + EXTERNAL DSCAL +* .. +* .. Executable Statements .. +* + IF( N.LE.1 ) THEN + TAU = ZERO + RETURN + END IF +* + XNORM = DNRM2( N-1, X, INCX ) +* + IF( XNORM.EQ.ZERO ) THEN +* +* H = I +* + TAU = ZERO + ELSE +* +* general case +* + BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA ) + SAFMIN = DLAMCH( 'S' ) / DLAMCH( 'E' ) + KNT = 0 + IF( ABS( BETA ).LT.SAFMIN ) THEN +* +* XNORM, BETA may be inaccurate; scale X and recompute them +* + RSAFMN = ONE / SAFMIN + 10 CONTINUE + KNT = KNT + 1 + CALL DSCAL( N-1, RSAFMN, X, INCX ) + BETA = BETA*RSAFMN + ALPHA = ALPHA*RSAFMN + IF( ABS( BETA ).LT.SAFMIN ) + $ GO TO 10 +* +* New BETA is at most 1, at least SAFMIN +* + XNORM = DNRM2( N-1, X, INCX ) + BETA = -SIGN( DLAPY2( ALPHA, XNORM ), ALPHA ) + END IF + TAU = ( BETA-ALPHA ) / BETA + CALL DSCAL( N-1, ONE / ( ALPHA-BETA ), X, INCX ) +* +* If ALPHA is subnormal, it may lose relative accuracy +* + DO 20 J = 1, KNT + BETA = BETA*SAFMIN + 20 CONTINUE + ALPHA = BETA + END IF +* + RETURN +* +* End of DLARFG +* + END diff --git a/lapack/internal/testdata/netlib/dlaset.f b/lapack/internal/testdata/netlib/dlaset.f new file mode 100644 index 00000000..d3bb9456 --- /dev/null +++ b/lapack/internal/testdata/netlib/dlaset.f @@ -0,0 +1,184 @@ +*> \brief \b DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values. +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +*> \htmlonly +*> Download DLASET + dependencies +*> +*> [TGZ] +*> +*> [ZIP] +*> +*> [TXT] +*> \endhtmlonly +* +* Definition: +* =========== +* +* SUBROUTINE DLASET( UPLO, M, N, ALPHA, BETA, A, LDA ) +* +* .. Scalar Arguments .. +* CHARACTER UPLO +* INTEGER LDA, M, N +* DOUBLE PRECISION ALPHA, BETA +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A( LDA, * ) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DLASET initializes an m-by-n matrix A to BETA on the diagonal and +*> ALPHA on the offdiagonals. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> Specifies the part of the matrix A to be set. +*> = 'U': Upper triangular part is set; the strictly lower +*> triangular part of A is not changed. +*> = 'L': Lower triangular part is set; the strictly upper +*> triangular part of A is not changed. +*> Otherwise: All of the matrix A is set. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> The number of rows of the matrix A. M >= 0. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> The number of columns of the matrix A. N >= 0. +*> \endverbatim +*> +*> \param[in] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION +*> The constant to which the offdiagonal elements are to be set. +*> \endverbatim +*> +*> \param[in] BETA +*> \verbatim +*> BETA is DOUBLE PRECISION +*> The constant to which the diagonal elements are to be set. +*> \endverbatim +*> +*> \param[out] A +*> \verbatim +*> A is DOUBLE PRECISION array, dimension (LDA,N) +*> On exit, the leading m-by-n submatrix of A is set as follows: +*> +*> if UPLO = 'U', A(i,j) = ALPHA, 1<=i<=j-1, 1<=j<=n, +*> if UPLO = 'L', A(i,j) = ALPHA, j+1<=i<=m, 1<=j<=n, +*> otherwise, A(i,j) = ALPHA, 1<=i<=m, 1<=j<=n, i.ne.j, +*> +*> and, for all UPLO, A(i,i) = BETA, 1<=i<=min(m,n). +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> The leading dimension of the array A. LDA >= max(1,M). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2015 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + SUBROUTINE DLASET( UPLO, M, N, ALPHA, BETA, A, LDA ) +* +* -- LAPACK auxiliary routine (version 3.6.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2015 +* +* .. Scalar Arguments .. + CHARACTER UPLO + INTEGER LDA, M, N + DOUBLE PRECISION ALPHA, BETA +* .. +* .. Array Arguments .. + DOUBLE PRECISION A( LDA, * ) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I, J +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. Intrinsic Functions .. + INTRINSIC MIN +* .. +* .. Executable Statements .. +* + IF( LSAME( UPLO, 'U' ) ) THEN +* +* Set the strictly upper triangular or trapezoidal part of the +* array to ALPHA. +* + DO 20 J = 2, N + DO 10 I = 1, MIN( J-1, M ) + A( I, J ) = ALPHA + 10 CONTINUE + 20 CONTINUE +* + ELSE IF( LSAME( UPLO, 'L' ) ) THEN +* +* Set the strictly lower triangular or trapezoidal part of the +* array to ALPHA. +* + DO 40 J = 1, MIN( M, N ) + DO 30 I = J + 1, M + A( I, J ) = ALPHA + 30 CONTINUE + 40 CONTINUE +* + ELSE +* +* Set the leading m-by-n submatrix to ALPHA. +* + DO 60 J = 1, N + DO 50 I = 1, M + A( I, J ) = ALPHA + 50 CONTINUE + 60 CONTINUE + END IF +* +* Set the first min(M,N) diagonal elements to BETA. +* + DO 70 I = 1, MIN( M, N ) + A( I, I ) = BETA + 70 CONTINUE +* + RETURN +* +* End of DLASET +* + END diff --git a/lapack/internal/testdata/netlib/dnrm2.f b/lapack/internal/testdata/netlib/dnrm2.f new file mode 100644 index 00000000..5ea257a2 --- /dev/null +++ b/lapack/internal/testdata/netlib/dnrm2.f @@ -0,0 +1,112 @@ +*> \brief \b DNRM2 +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* DOUBLE PRECISION FUNCTION DNRM2(N,X,INCX) +* +* .. Scalar Arguments .. +* INTEGER INCX,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION X(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DNRM2 returns the euclidean norm of a vector via the function +*> name, so that +*> +*> DNRM2 := sqrt( x'*x ) +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> -- This version written on 25-October-1982. +*> Modified on 14-October-1993 to inline the call to DLASSQ. +*> Sven Hammarling, Nag Ltd. +*> \endverbatim +*> +* ===================================================================== + DOUBLE PRECISION FUNCTION DNRM2(N,X,INCX) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INCX,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION X(*) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* .. Local Scalars .. + DOUBLE PRECISION ABSXI,NORM,SCALE,SSQ + INTEGER IX +* .. +* .. Intrinsic Functions .. + INTRINSIC ABS,SQRT +* .. + IF (N.LT.1 .OR. INCX.LT.1) THEN + NORM = ZERO + ELSE IF (N.EQ.1) THEN + NORM = ABS(X(1)) + ELSE + SCALE = ZERO + SSQ = ONE +* The following loop is equivalent to this call to the LAPACK +* auxiliary routine: +* CALL DLASSQ( N, X, INCX, SCALE, SSQ ) +* + DO 10 IX = 1,1 + (N-1)*INCX,INCX + IF (X(IX).NE.ZERO) THEN + ABSXI = ABS(X(IX)) + IF (SCALE.LT.ABSXI) THEN + SSQ = ONE + SSQ* (SCALE/ABSXI)**2 + SCALE = ABSXI + ELSE + SSQ = SSQ + (ABSXI/SCALE)**2 + END IF + END IF + 10 CONTINUE + NORM = SCALE*SQRT(SSQ) + END IF +* + DNRM2 = NORM + RETURN +* +* End of DNRM2. +* + END diff --git a/lapack/internal/testdata/netlib/dscal.f b/lapack/internal/testdata/netlib/dscal.f new file mode 100644 index 00000000..3337de8e --- /dev/null +++ b/lapack/internal/testdata/netlib/dscal.f @@ -0,0 +1,110 @@ +*> \brief \b DSCAL +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DSCAL(N,DA,DX,INCX) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION DA +* INTEGER INCX,N +* .. +* .. Array Arguments .. +* DOUBLE PRECISION DX(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DSCAL scales a vector by a constant. +*> uses unrolled loops for increment equal to one. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level1 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> jack dongarra, linpack, 3/11/78. +*> modified 3/93 to return if incx .le. 0. +*> modified 12/3/93, array(1) declarations changed to array(*) +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DSCAL(N,DA,DX,INCX) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + DOUBLE PRECISION DA + INTEGER INCX,N +* .. +* .. Array Arguments .. + DOUBLE PRECISION DX(*) +* .. +* +* ===================================================================== +* +* .. Local Scalars .. + INTEGER I,M,MP1,NINCX +* .. +* .. Intrinsic Functions .. + INTRINSIC MOD +* .. + IF (N.LE.0 .OR. INCX.LE.0) RETURN + IF (INCX.EQ.1) THEN +* +* code for increment equal to 1 +* +* +* clean-up loop +* + M = MOD(N,5) + IF (M.NE.0) THEN + DO I = 1,M + DX(I) = DA*DX(I) + END DO + IF (N.LT.5) RETURN + END IF + MP1 = M + 1 + DO I = MP1,N,5 + DX(I) = DA*DX(I) + DX(I+1) = DA*DX(I+1) + DX(I+2) = DA*DX(I+2) + DX(I+3) = DA*DX(I+3) + DX(I+4) = DA*DX(I+4) + END DO + ELSE +* +* code for increment not equal to 1 +* + NINCX = N*INCX + DO I = 1,NINCX,INCX + DX(I) = DA*DX(I) + END DO + END IF + RETURN + END diff --git a/lapack/internal/testdata/netlib/dtrmm.f b/lapack/internal/testdata/netlib/dtrmm.f new file mode 100644 index 00000000..cbd5ce70 --- /dev/null +++ b/lapack/internal/testdata/netlib/dtrmm.f @@ -0,0 +1,415 @@ +*> \brief \b DTRMM +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DTRMM(SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB) +* +* .. Scalar Arguments .. +* DOUBLE PRECISION ALPHA +* INTEGER LDA,LDB,M,N +* CHARACTER DIAG,SIDE,TRANSA,UPLO +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A(LDA,*),B(LDB,*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DTRMM performs one of the matrix-matrix operations +*> +*> B := alpha*op( A )*B, or B := alpha*B*op( A ), +*> +*> where alpha is a scalar, B is an m by n matrix, A is a unit, or +*> non-unit, upper or lower triangular matrix and op( A ) is one of +*> +*> op( A ) = A or op( A ) = A**T. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] SIDE +*> \verbatim +*> SIDE is CHARACTER*1 +*> On entry, SIDE specifies whether op( A ) multiplies B from +*> the left or right as follows: +*> +*> SIDE = 'L' or 'l' B := alpha*op( A )*B. +*> +*> SIDE = 'R' or 'r' B := alpha*B*op( A ). +*> \endverbatim +*> +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> On entry, UPLO specifies whether the matrix A is an upper or +*> lower triangular matrix as follows: +*> +*> UPLO = 'U' or 'u' A is an upper triangular matrix. +*> +*> UPLO = 'L' or 'l' A is a lower triangular matrix. +*> \endverbatim +*> +*> \param[in] TRANSA +*> \verbatim +*> TRANSA is CHARACTER*1 +*> On entry, TRANSA specifies the form of op( A ) to be used in +*> the matrix multiplication as follows: +*> +*> TRANSA = 'N' or 'n' op( A ) = A. +*> +*> TRANSA = 'T' or 't' op( A ) = A**T. +*> +*> TRANSA = 'C' or 'c' op( A ) = A**T. +*> \endverbatim +*> +*> \param[in] DIAG +*> \verbatim +*> DIAG is CHARACTER*1 +*> On entry, DIAG specifies whether or not A is unit triangular +*> as follows: +*> +*> DIAG = 'U' or 'u' A is assumed to be unit triangular. +*> +*> DIAG = 'N' or 'n' A is not assumed to be unit +*> triangular. +*> \endverbatim +*> +*> \param[in] M +*> \verbatim +*> M is INTEGER +*> On entry, M specifies the number of rows of B. M must be at +*> least zero. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> On entry, N specifies the number of columns of B. N must be +*> at least zero. +*> \endverbatim +*> +*> \param[in] ALPHA +*> \verbatim +*> ALPHA is DOUBLE PRECISION. +*> On entry, ALPHA specifies the scalar alpha. When alpha is +*> zero then A is not referenced and B need not be set before +*> entry. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m +*> when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. +*> Before entry with UPLO = 'U' or 'u', the leading k by k +*> upper triangular part of the array A must contain the upper +*> triangular matrix and the strictly lower triangular part of +*> A is not referenced. +*> Before entry with UPLO = 'L' or 'l', the leading k by k +*> lower triangular part of the array A must contain the lower +*> triangular matrix and the strictly upper triangular part of +*> A is not referenced. +*> Note that when DIAG = 'U' or 'u', the diagonal elements of +*> A are not referenced either, but are assumed to be unity. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> On entry, LDA specifies the first dimension of A as declared +*> in the calling (sub) program. When SIDE = 'L' or 'l' then +*> LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' +*> then LDA must be at least max( 1, n ). +*> \endverbatim +*> +*> \param[in,out] B +*> \verbatim +*> B is DOUBLE PRECISION array of DIMENSION ( LDB, n ). +*> Before entry, the leading m by n part of the array B must +*> contain the matrix B, and on exit is overwritten by the +*> transformed matrix. +*> \endverbatim +*> +*> \param[in] LDB +*> \verbatim +*> LDB is INTEGER +*> On entry, LDB specifies the first dimension of B as declared +*> in the calling (sub) program. LDB must be at least +*> max( 1, m ). +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level3 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Level 3 Blas routine. +*> +*> -- Written on 8-February-1989. +*> Jack Dongarra, Argonne National Laboratory. +*> Iain Duff, AERE Harwell. +*> Jeremy Du Croz, Numerical Algorithms Group Ltd. +*> Sven Hammarling, Numerical Algorithms Group Ltd. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DTRMM(SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB) +* +* -- Reference BLAS level3 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + DOUBLE PRECISION ALPHA + INTEGER LDA,LDB,M,N + CHARACTER DIAG,SIDE,TRANSA,UPLO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),B(LDB,*) +* .. +* +* ===================================================================== +* +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,J,K,NROWA + LOGICAL LSIDE,NOUNIT,UPPER +* .. +* .. Parameters .. + DOUBLE PRECISION ONE,ZERO + PARAMETER (ONE=1.0D+0,ZERO=0.0D+0) +* .. +* +* Test the input parameters. +* + LSIDE = LSAME(SIDE,'L') + IF (LSIDE) THEN + NROWA = M + ELSE + NROWA = N + END IF + NOUNIT = LSAME(DIAG,'N') + UPPER = LSAME(UPLO,'U') +* + INFO = 0 + IF ((.NOT.LSIDE) .AND. (.NOT.LSAME(SIDE,'R'))) THEN + INFO = 1 + ELSE IF ((.NOT.UPPER) .AND. (.NOT.LSAME(UPLO,'L'))) THEN + INFO = 2 + ELSE IF ((.NOT.LSAME(TRANSA,'N')) .AND. + + (.NOT.LSAME(TRANSA,'T')) .AND. + + (.NOT.LSAME(TRANSA,'C'))) THEN + INFO = 3 + ELSE IF ((.NOT.LSAME(DIAG,'U')) .AND. (.NOT.LSAME(DIAG,'N'))) THEN + INFO = 4 + ELSE IF (M.LT.0) THEN + INFO = 5 + ELSE IF (N.LT.0) THEN + INFO = 6 + ELSE IF (LDA.LT.MAX(1,NROWA)) THEN + INFO = 9 + ELSE IF (LDB.LT.MAX(1,M)) THEN + INFO = 11 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DTRMM ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF (M.EQ.0 .OR. N.EQ.0) RETURN +* +* And when alpha.eq.zero. +* + IF (ALPHA.EQ.ZERO) THEN + DO 20 J = 1,N + DO 10 I = 1,M + B(I,J) = ZERO + 10 CONTINUE + 20 CONTINUE + RETURN + END IF +* +* Start the operations. +* + IF (LSIDE) THEN + IF (LSAME(TRANSA,'N')) THEN +* +* Form B := alpha*A*B. +* + IF (UPPER) THEN + DO 50 J = 1,N + DO 40 K = 1,M + IF (B(K,J).NE.ZERO) THEN + TEMP = ALPHA*B(K,J) + DO 30 I = 1,K - 1 + B(I,J) = B(I,J) + TEMP*A(I,K) + 30 CONTINUE + IF (NOUNIT) TEMP = TEMP*A(K,K) + B(K,J) = TEMP + END IF + 40 CONTINUE + 50 CONTINUE + ELSE + DO 80 J = 1,N + DO 70 K = M,1,-1 + IF (B(K,J).NE.ZERO) THEN + TEMP = ALPHA*B(K,J) + B(K,J) = TEMP + IF (NOUNIT) B(K,J) = B(K,J)*A(K,K) + DO 60 I = K + 1,M + B(I,J) = B(I,J) + TEMP*A(I,K) + 60 CONTINUE + END IF + 70 CONTINUE + 80 CONTINUE + END IF + ELSE +* +* Form B := alpha*A**T*B. +* + IF (UPPER) THEN + DO 110 J = 1,N + DO 100 I = M,1,-1 + TEMP = B(I,J) + IF (NOUNIT) TEMP = TEMP*A(I,I) + DO 90 K = 1,I - 1 + TEMP = TEMP + A(K,I)*B(K,J) + 90 CONTINUE + B(I,J) = ALPHA*TEMP + 100 CONTINUE + 110 CONTINUE + ELSE + DO 140 J = 1,N + DO 130 I = 1,M + TEMP = B(I,J) + IF (NOUNIT) TEMP = TEMP*A(I,I) + DO 120 K = I + 1,M + TEMP = TEMP + A(K,I)*B(K,J) + 120 CONTINUE + B(I,J) = ALPHA*TEMP + 130 CONTINUE + 140 CONTINUE + END IF + END IF + ELSE + IF (LSAME(TRANSA,'N')) THEN +* +* Form B := alpha*B*A. +* + IF (UPPER) THEN + DO 180 J = N,1,-1 + TEMP = ALPHA + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 150 I = 1,M + B(I,J) = TEMP*B(I,J) + 150 CONTINUE + DO 170 K = 1,J - 1 + IF (A(K,J).NE.ZERO) THEN + TEMP = ALPHA*A(K,J) + DO 160 I = 1,M + B(I,J) = B(I,J) + TEMP*B(I,K) + 160 CONTINUE + END IF + 170 CONTINUE + 180 CONTINUE + ELSE + DO 220 J = 1,N + TEMP = ALPHA + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 190 I = 1,M + B(I,J) = TEMP*B(I,J) + 190 CONTINUE + DO 210 K = J + 1,N + IF (A(K,J).NE.ZERO) THEN + TEMP = ALPHA*A(K,J) + DO 200 I = 1,M + B(I,J) = B(I,J) + TEMP*B(I,K) + 200 CONTINUE + END IF + 210 CONTINUE + 220 CONTINUE + END IF + ELSE +* +* Form B := alpha*B*A**T. +* + IF (UPPER) THEN + DO 260 K = 1,N + DO 240 J = 1,K - 1 + IF (A(J,K).NE.ZERO) THEN + TEMP = ALPHA*A(J,K) + DO 230 I = 1,M + B(I,J) = B(I,J) + TEMP*B(I,K) + 230 CONTINUE + END IF + 240 CONTINUE + TEMP = ALPHA + IF (NOUNIT) TEMP = TEMP*A(K,K) + IF (TEMP.NE.ONE) THEN + DO 250 I = 1,M + B(I,K) = TEMP*B(I,K) + 250 CONTINUE + END IF + 260 CONTINUE + ELSE + DO 300 K = N,1,-1 + DO 280 J = K + 1,N + IF (A(J,K).NE.ZERO) THEN + TEMP = ALPHA*A(J,K) + DO 270 I = 1,M + B(I,J) = B(I,J) + TEMP*B(I,K) + 270 CONTINUE + END IF + 280 CONTINUE + TEMP = ALPHA + IF (NOUNIT) TEMP = TEMP*A(K,K) + IF (TEMP.NE.ONE) THEN + DO 290 I = 1,M + B(I,K) = TEMP*B(I,K) + 290 CONTINUE + END IF + 300 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of DTRMM . +* + END diff --git a/lapack/internal/testdata/netlib/dtrmv.f b/lapack/internal/testdata/netlib/dtrmv.f new file mode 100644 index 00000000..71459fe7 --- /dev/null +++ b/lapack/internal/testdata/netlib/dtrmv.f @@ -0,0 +1,342 @@ +*> \brief \b DTRMV +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE DTRMV(UPLO,TRANS,DIAG,N,A,LDA,X,INCX) +* +* .. Scalar Arguments .. +* INTEGER INCX,LDA,N +* CHARACTER DIAG,TRANS,UPLO +* .. +* .. Array Arguments .. +* DOUBLE PRECISION A(LDA,*),X(*) +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> DTRMV performs one of the matrix-vector operations +*> +*> x := A*x, or x := A**T*x, +*> +*> where x is an n element vector and A is an n by n unit, or non-unit, +*> upper or lower triangular matrix. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] UPLO +*> \verbatim +*> UPLO is CHARACTER*1 +*> On entry, UPLO specifies whether the matrix is an upper or +*> lower triangular matrix as follows: +*> +*> UPLO = 'U' or 'u' A is an upper triangular matrix. +*> +*> UPLO = 'L' or 'l' A is a lower triangular matrix. +*> \endverbatim +*> +*> \param[in] TRANS +*> \verbatim +*> TRANS is CHARACTER*1 +*> On entry, TRANS specifies the operation to be performed as +*> follows: +*> +*> TRANS = 'N' or 'n' x := A*x. +*> +*> TRANS = 'T' or 't' x := A**T*x. +*> +*> TRANS = 'C' or 'c' x := A**T*x. +*> \endverbatim +*> +*> \param[in] DIAG +*> \verbatim +*> DIAG is CHARACTER*1 +*> On entry, DIAG specifies whether or not A is unit +*> triangular as follows: +*> +*> DIAG = 'U' or 'u' A is assumed to be unit triangular. +*> +*> DIAG = 'N' or 'n' A is not assumed to be unit +*> triangular. +*> \endverbatim +*> +*> \param[in] N +*> \verbatim +*> N is INTEGER +*> On entry, N specifies the order of the matrix A. +*> N must be at least zero. +*> \endverbatim +*> +*> \param[in] A +*> \verbatim +*> A is DOUBLE PRECISION array of DIMENSION ( LDA, n ). +*> Before entry with UPLO = 'U' or 'u', the leading n by n +*> upper triangular part of the array A must contain the upper +*> triangular matrix and the strictly lower triangular part of +*> A is not referenced. +*> Before entry with UPLO = 'L' or 'l', the leading n by n +*> lower triangular part of the array A must contain the lower +*> triangular matrix and the strictly upper triangular part of +*> A is not referenced. +*> Note that when DIAG = 'U' or 'u', the diagonal elements of +*> A are not referenced either, but are assumed to be unity. +*> \endverbatim +*> +*> \param[in] LDA +*> \verbatim +*> LDA is INTEGER +*> On entry, LDA specifies the first dimension of A as declared +*> in the calling (sub) program. LDA must be at least +*> max( 1, n ). +*> \endverbatim +*> +*> \param[in,out] X +*> \verbatim +*> X is DOUBLE PRECISION array of dimension at least +*> ( 1 + ( n - 1 )*abs( INCX ) ). +*> Before entry, the incremented array X must contain the n +*> element vector x. On exit, X is overwritten with the +*> tranformed vector x. +*> \endverbatim +*> +*> \param[in] INCX +*> \verbatim +*> INCX is INTEGER +*> On entry, INCX specifies the increment for the elements of +*> X. INCX must not be zero. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup double_blas_level2 +* +*> \par Further Details: +* ===================== +*> +*> \verbatim +*> +*> Level 2 Blas routine. +*> The vector and matrix arguments are not referenced when N = 0, or M = 0 +*> +*> -- Written on 22-October-1986. +*> Jack Dongarra, Argonne National Lab. +*> Jeremy Du Croz, Nag Central Office. +*> Sven Hammarling, Nag Central Office. +*> Richard Hanson, Sandia National Labs. +*> \endverbatim +*> +* ===================================================================== + SUBROUTINE DTRMV(UPLO,TRANS,DIAG,N,A,LDA,X,INCX) +* +* -- Reference BLAS level2 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + INTEGER INCX,LDA,N + CHARACTER DIAG,TRANS,UPLO +* .. +* .. Array Arguments .. + DOUBLE PRECISION A(LDA,*),X(*) +* .. +* +* ===================================================================== +* +* .. Parameters .. + DOUBLE PRECISION ZERO + PARAMETER (ZERO=0.0D+0) +* .. +* .. Local Scalars .. + DOUBLE PRECISION TEMP + INTEGER I,INFO,IX,J,JX,KX + LOGICAL NOUNIT +* .. +* .. External Functions .. + LOGICAL LSAME + EXTERNAL LSAME +* .. +* .. External Subroutines .. + EXTERNAL XERBLA +* .. +* .. Intrinsic Functions .. + INTRINSIC MAX +* .. +* +* Test the input parameters. +* + INFO = 0 + IF (.NOT.LSAME(UPLO,'U') .AND. .NOT.LSAME(UPLO,'L')) THEN + INFO = 1 + ELSE IF (.NOT.LSAME(TRANS,'N') .AND. .NOT.LSAME(TRANS,'T') .AND. + + .NOT.LSAME(TRANS,'C')) THEN + INFO = 2 + ELSE IF (.NOT.LSAME(DIAG,'U') .AND. .NOT.LSAME(DIAG,'N')) THEN + INFO = 3 + ELSE IF (N.LT.0) THEN + INFO = 4 + ELSE IF (LDA.LT.MAX(1,N)) THEN + INFO = 6 + ELSE IF (INCX.EQ.0) THEN + INFO = 8 + END IF + IF (INFO.NE.0) THEN + CALL XERBLA('DTRMV ',INFO) + RETURN + END IF +* +* Quick return if possible. +* + IF (N.EQ.0) RETURN +* + NOUNIT = LSAME(DIAG,'N') +* +* Set up the start point in X if the increment is not unity. This +* will be ( N - 1 )*INCX too small for descending loops. +* + IF (INCX.LE.0) THEN + KX = 1 - (N-1)*INCX + ELSE IF (INCX.NE.1) THEN + KX = 1 + END IF +* +* Start the operations. In this version the elements of A are +* accessed sequentially with one pass through A. +* + IF (LSAME(TRANS,'N')) THEN +* +* Form x := A*x. +* + IF (LSAME(UPLO,'U')) THEN + IF (INCX.EQ.1) THEN + DO 20 J = 1,N + IF (X(J).NE.ZERO) THEN + TEMP = X(J) + DO 10 I = 1,J - 1 + X(I) = X(I) + TEMP*A(I,J) + 10 CONTINUE + IF (NOUNIT) X(J) = X(J)*A(J,J) + END IF + 20 CONTINUE + ELSE + JX = KX + DO 40 J = 1,N + IF (X(JX).NE.ZERO) THEN + TEMP = X(JX) + IX = KX + DO 30 I = 1,J - 1 + X(IX) = X(IX) + TEMP*A(I,J) + IX = IX + INCX + 30 CONTINUE + IF (NOUNIT) X(JX) = X(JX)*A(J,J) + END IF + JX = JX + INCX + 40 CONTINUE + END IF + ELSE + IF (INCX.EQ.1) THEN + DO 60 J = N,1,-1 + IF (X(J).NE.ZERO) THEN + TEMP = X(J) + DO 50 I = N,J + 1,-1 + X(I) = X(I) + TEMP*A(I,J) + 50 CONTINUE + IF (NOUNIT) X(J) = X(J)*A(J,J) + END IF + 60 CONTINUE + ELSE + KX = KX + (N-1)*INCX + JX = KX + DO 80 J = N,1,-1 + IF (X(JX).NE.ZERO) THEN + TEMP = X(JX) + IX = KX + DO 70 I = N,J + 1,-1 + X(IX) = X(IX) + TEMP*A(I,J) + IX = IX - INCX + 70 CONTINUE + IF (NOUNIT) X(JX) = X(JX)*A(J,J) + END IF + JX = JX - INCX + 80 CONTINUE + END IF + END IF + ELSE +* +* Form x := A**T*x. +* + IF (LSAME(UPLO,'U')) THEN + IF (INCX.EQ.1) THEN + DO 100 J = N,1,-1 + TEMP = X(J) + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 90 I = J - 1,1,-1 + TEMP = TEMP + A(I,J)*X(I) + 90 CONTINUE + X(J) = TEMP + 100 CONTINUE + ELSE + JX = KX + (N-1)*INCX + DO 120 J = N,1,-1 + TEMP = X(JX) + IX = JX + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 110 I = J - 1,1,-1 + IX = IX - INCX + TEMP = TEMP + A(I,J)*X(IX) + 110 CONTINUE + X(JX) = TEMP + JX = JX - INCX + 120 CONTINUE + END IF + ELSE + IF (INCX.EQ.1) THEN + DO 140 J = 1,N + TEMP = X(J) + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 130 I = J + 1,N + TEMP = TEMP + A(I,J)*X(I) + 130 CONTINUE + X(J) = TEMP + 140 CONTINUE + ELSE + JX = KX + DO 160 J = 1,N + TEMP = X(JX) + IX = JX + IF (NOUNIT) TEMP = TEMP*A(J,J) + DO 150 I = J + 1,N + IX = IX + INCX + TEMP = TEMP + A(I,J)*X(IX) + 150 CONTINUE + X(JX) = TEMP + JX = JX + INCX + 160 CONTINUE + END IF + END IF + END IF +* + RETURN +* +* End of DTRMV . +* + END diff --git a/lapack/internal/testdata/netlib/lsame.f b/lapack/internal/testdata/netlib/lsame.f new file mode 100644 index 00000000..315304c3 --- /dev/null +++ b/lapack/internal/testdata/netlib/lsame.f @@ -0,0 +1,125 @@ +*> \brief \b LSAME +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* LOGICAL FUNCTION LSAME( CA, CB ) +* +* .. Scalar Arguments .. +* CHARACTER CA, CB +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> LSAME returns .TRUE. if CA is the same letter as CB regardless of +*> case. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] CA +*> \verbatim +*> \endverbatim +*> +*> \param[in] CB +*> \verbatim +*> CA and CB specify the single characters to be compared. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup auxOTHERauxiliary +* +* ===================================================================== + LOGICAL FUNCTION LSAME( CA, CB ) +* +* -- LAPACK auxiliary routine (version 3.4.0) -- +* -- LAPACK is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER CA, CB +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC ICHAR +* .. +* .. Local Scalars .. + INTEGER INTA, INTB, ZCODE +* .. +* .. Executable Statements .. +* +* Test if the characters are equal +* + LSAME = CA.EQ.CB + IF( LSAME ) + $ RETURN +* +* Now test for equivalence if both characters are alphabetic. +* + ZCODE = ICHAR( 'Z' ) +* +* Use 'Z' rather than 'A' so that ASCII can be detected on Prime +* machines, on which ICHAR returns a value with bit 8 set. +* ICHAR('A') on Prime machines returns 193 which is the same as +* ICHAR('A') on an EBCDIC machine. +* + INTA = ICHAR( CA ) + INTB = ICHAR( CB ) +* + IF( ZCODE.EQ.90 .OR. ZCODE.EQ.122 ) THEN +* +* ASCII is assumed - ZCODE is the ASCII code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.97 .AND. INTA.LE.122 ) INTA = INTA - 32 + IF( INTB.GE.97 .AND. INTB.LE.122 ) INTB = INTB - 32 +* + ELSE IF( ZCODE.EQ.233 .OR. ZCODE.EQ.169 ) THEN +* +* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower or +* upper case 'Z'. +* + IF( INTA.GE.129 .AND. INTA.LE.137 .OR. + $ INTA.GE.145 .AND. INTA.LE.153 .OR. + $ INTA.GE.162 .AND. INTA.LE.169 ) INTA = INTA + 64 + IF( INTB.GE.129 .AND. INTB.LE.137 .OR. + $ INTB.GE.145 .AND. INTB.LE.153 .OR. + $ INTB.GE.162 .AND. INTB.LE.169 ) INTB = INTB + 64 +* + ELSE IF( ZCODE.EQ.218 .OR. ZCODE.EQ.250 ) THEN +* +* ASCII is assumed, on Prime machines - ZCODE is the ASCII code +* plus 128 of either lower or upper case 'Z'. +* + IF( INTA.GE.225 .AND. INTA.LE.250 ) INTA = INTA - 32 + IF( INTB.GE.225 .AND. INTB.LE.250 ) INTB = INTB - 32 + END IF + LSAME = INTA.EQ.INTB +* +* RETURN +* +* End of LSAME +* + END diff --git a/lapack/internal/testdata/netlib/netlib.go b/lapack/internal/testdata/netlib/netlib.go new file mode 100644 index 00000000..182e074a --- /dev/null +++ b/lapack/internal/testdata/netlib/netlib.go @@ -0,0 +1,68 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package netlib + +// void dlahr2_(int* n, int* k, int* nb, double* a, int* lda, double* tau, double* t, int* ldt, double* y, int* ldy); +// +// void dlaqr5_(int* wantt, int* wantz, int* kacc22, int* n, int* ktop, int* kbot, int* nshfts, +// double* sr, double* si, double* h, int* ldh, int* iloz, int* ihiz, +// double* z, int* ldz, double* v, int* ldv, double* u, int* ldu, +// int* nv, double* wv, int* ldwv, int* nh, double* wh, int* ldwh); +import "C" + +func Dlahr2(n, k, nb int, a []float64, lda int, tau, t []float64, ldt int, y []float64, ldy int) { + func() { + n := C.int(n) + k := C.int(k) + nb := C.int(nb) + lda := C.int(lda) + ldt := C.int(ldt) + ldy := C.int(ldy) + C.dlahr2_((*C.int)(&n), (*C.int)(&k), (*C.int)(&nb), + (*C.double)(&a[0]), (*C.int)(&lda), + (*C.double)(&tau[0]), + (*C.double)(&t[0]), (*C.int)(&ldt), + (*C.double)(&y[0]), (*C.int)(&ldy)) + }() +} + +func Dlaqr5(wantt, wantz bool, kacc22 int, n, ktop, kbot int, nshfts int, sr, si []float64, h []float64, + ldh int, iloz, ihiz int, z []float64, ldz int, v []float64, ldv int, + u []float64, ldu int, nh int, wh []float64, ldwh int, nv int, wv []float64, ldwv int) { + func() { + wt := C.int(0) + if wantt { + wt = 1 + } + wz := C.int(0) + if wantz { + wz = 1 + } + kacc22 := C.int(kacc22) + n := C.int(n) + ktop := C.int(ktop) + kbot := C.int(kbot) + nshfts := C.int(nshfts) + ldh := C.int(ldh) + iloz := C.int(iloz) + ihiz := C.int(ihiz) + ldz := C.int(ldz) + ldv := C.int(ldv) + ldu := C.int(ldu) + nh := C.int(nh) + ldwh := C.int(ldwh) + nv := C.int(nv) + ldwv := C.int(ldwv) + C.dlaqr5_((*C.int)(&wt), (*C.int)(&wz), (*C.int)(&kacc22), + (*C.int)(&n), (*C.int)(&ktop), (*C.int)(&kbot), + (*C.int)(&nshfts), (*C.double)(&sr[0]), (*C.double)(&si[0]), + (*C.double)(&h[0]), (*C.int)(&ldh), + (*C.int)(&iloz), (*C.int)(&ihiz), (*C.double)(&z[0]), (*C.int)(&ldz), + (*C.double)(&v[0]), (*C.int)(&ldv), + (*C.double)(&u[0]), (*C.int)(&ldu), + (*C.int)(&nh), (*C.double)(&wh[0]), (*C.int)(&ldwh), + (*C.int)(&nv), (*C.double)(&wv[0]), (*C.int)(&ldwv)) + }() +} diff --git a/lapack/internal/testdata/netlib/xerbla.f b/lapack/internal/testdata/netlib/xerbla.f new file mode 100644 index 00000000..eb1c037d --- /dev/null +++ b/lapack/internal/testdata/netlib/xerbla.f @@ -0,0 +1,89 @@ +*> \brief \b XERBLA +* +* =========== DOCUMENTATION =========== +* +* Online html documentation available at +* http://www.netlib.org/lapack/explore-html/ +* +* Definition: +* =========== +* +* SUBROUTINE XERBLA( SRNAME, INFO ) +* +* .. Scalar Arguments .. +* CHARACTER*(*) SRNAME +* INTEGER INFO +* .. +* +* +*> \par Purpose: +* ============= +*> +*> \verbatim +*> +*> XERBLA is an error handler for the LAPACK routines. +*> It is called by an LAPACK routine if an input parameter has an +*> invalid value. A message is printed and execution stops. +*> +*> Installers may consider modifying the STOP statement in order to +*> call system-specific exception-handling facilities. +*> \endverbatim +* +* Arguments: +* ========== +* +*> \param[in] SRNAME +*> \verbatim +*> SRNAME is CHARACTER*(*) +*> The name of the routine which called XERBLA. +*> \endverbatim +*> +*> \param[in] INFO +*> \verbatim +*> INFO is INTEGER +*> The position of the invalid parameter in the parameter list +*> of the calling routine. +*> \endverbatim +* +* Authors: +* ======== +* +*> \author Univ. of Tennessee +*> \author Univ. of California Berkeley +*> \author Univ. of Colorado Denver +*> \author NAG Ltd. +* +*> \date November 2011 +* +*> \ingroup aux_blas +* +* ===================================================================== + SUBROUTINE XERBLA( SRNAME, INFO ) +* +* -- Reference BLAS level1 routine (version 3.4.0) -- +* -- Reference BLAS is a software package provided by Univ. of Tennessee, -- +* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- +* November 2011 +* +* .. Scalar Arguments .. + CHARACTER*(*) SRNAME + INTEGER INFO +* .. +* +* ===================================================================== +* +* .. Intrinsic Functions .. + INTRINSIC LEN_TRIM +* .. +* .. Executable Statements .. +* + WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO +* + STOP +* + 9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ', + $ 'an illegal value' ) +* +* End of XERBLA +* + END diff --git a/lapack/lapack.go b/lapack/lapack.go new file mode 100644 index 00000000..7f64a7a9 --- /dev/null +++ b/lapack/lapack.go @@ -0,0 +1,188 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package lapack + +import "gonum.org/v1/gonum/blas" + +const None = 'N' + +type Job byte + +type Comp byte + +// Complex128 defines the public complex128 LAPACK API supported by gonum/lapack. +type Complex128 interface{} + +// Float64 defines the public float64 LAPACK API supported by gonum/lapack. +type Float64 interface { + Dgecon(norm MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 + Dgeev(jobvl LeftEVJob, jobvr RightEVJob, n int, a []float64, lda int, wr, wi []float64, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) (first int) + Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool + Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) + Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) + Dgesvd(jobU, jobVT SVDJob, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) (ok bool) + Dgetrf(m, n int, a []float64, lda int, ipiv []int) (ok bool) + Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) (ok bool) + Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) + Dggsvd3(jobU, jobV, jobQ GSVDJob, m, n, p int, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int) (k, l int, ok bool) + Dlantr(norm MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 + Dlange(norm MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 + Dlansy(norm MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 + Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) + Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) + Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) + Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 + Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) + Dsyev(jobz EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) + Dtrcon(norm MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 + Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) (ok bool) + Dtrtrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, nrhs int, a []float64, lda int, b []float64, ldb int) (ok bool) +} + +// Direct specifies the direction of the multiplication for the Householder matrix. +type Direct byte + +const ( + Forward Direct = 'F' // Reflectors are right-multiplied, H_0 * H_1 * ... * H_{k-1}. + Backward Direct = 'B' // Reflectors are left-multiplied, H_{k-1} * ... * H_1 * H_0. +) + +// Sort is the sorting order. +type Sort byte + +const ( + SortIncreasing Sort = 'I' + SortDecreasing Sort = 'D' +) + +// StoreV indicates the storage direction of elementary reflectors. +type StoreV byte + +const ( + ColumnWise StoreV = 'C' // Reflector stored in a column of the matrix. + RowWise StoreV = 'R' // Reflector stored in a row of the matrix. +) + +// MatrixNorm represents the kind of matrix norm to compute. +type MatrixNorm byte + +const ( + MaxAbs MatrixNorm = 'M' // max(abs(A(i,j))) ('M') + MaxColumnSum MatrixNorm = 'O' // Maximum column sum (one norm) ('1', 'O') + MaxRowSum MatrixNorm = 'I' // Maximum row sum (infinity norm) ('I', 'i') + NormFrob MatrixNorm = 'F' // Frobenius norm (sqrt of sum of squares) ('F', 'f', E, 'e') +) + +// MatrixType represents the kind of matrix represented in the data. +type MatrixType byte + +const ( + General MatrixType = 'G' // A dense matrix (like blas64.General). + UpperTri MatrixType = 'U' // An upper triangular matrix. + LowerTri MatrixType = 'L' // A lower triangular matrix. +) + +// Pivot specifies the pivot type for plane rotations +type Pivot byte + +const ( + Variable Pivot = 'V' + Top Pivot = 'T' + Bottom Pivot = 'B' +) + +type DecompUpdate byte + +const ( + ApplyP DecompUpdate = 'P' + ApplyQ DecompUpdate = 'Q' +) + +// SVDJob specifies the singular vector computation type for SVD. +type SVDJob byte + +const ( + SVDAll SVDJob = 'A' // Compute all singular vectors + SVDInPlace SVDJob = 'S' // Compute the first singular vectors and store them in provided storage. + SVDOverwrite SVDJob = 'O' // Compute the singular vectors and store them in input matrix + SVDNone SVDJob = 'N' // Do not compute singular vectors +) + +// GSVDJob specifies the singular vector computation type for Generalized SVD. +type GSVDJob byte + +const ( + GSVDU GSVDJob = 'U' // Compute orthogonal matrix U + GSVDV GSVDJob = 'V' // Compute orthogonal matrix V + GSVDQ GSVDJob = 'Q' // Compute orthogonal matrix Q + GSVDUnit GSVDJob = 'I' // Use unit-initialized matrix + GSVDNone GSVDJob = 'N' // Do not compute orthogonal matrix +) + +// EVComp specifies how eigenvectors are computed. +type EVComp byte + +const ( + // OriginalEV specifies to compute the eigenvectors of the original + // matrix. + OriginalEV EVComp = 'V' + // TridiagEV specifies to compute both the eigenvectors of the input + // tridiagonal matrix. + TridiagEV EVComp = 'I' + // HessEV specifies to compute both the eigenvectors of the input upper + // Hessenberg matrix. + HessEV EVComp = 'I' + + // UpdateSchur specifies that the matrix of Schur vectors will be + // updated by Dtrexc. + UpdateSchur EVComp = 'V' +) + +// Job types for computation of eigenvectors. +type ( + EVJob byte + LeftEVJob byte + RightEVJob byte +) + +// Job constants for computation of eigenvectors. +const ( + ComputeEV EVJob = 'V' // Compute eigenvectors in Dsyev. + ComputeLeftEV LeftEVJob = 'V' // Compute left eigenvectors. + ComputeRightEV RightEVJob = 'V' // Compute right eigenvectors. +) + +// Jobs for Dgebal. +const ( + Permute Job = 'P' + Scale Job = 'S' + PermuteScale Job = 'B' +) + +// Job constants for Dhseqr. +const ( + EigenvaluesOnly EVJob = 'E' + EigenvaluesAndSchur EVJob = 'S' +) + +// EVSide specifies what eigenvectors will be computed. +type EVSide byte + +// EVSide constants for Dtrevc3. +const ( + RightEV EVSide = 'R' // Compute right eigenvectors only. + LeftEV EVSide = 'L' // Compute left eigenvectors only. + RightLeftEV EVSide = 'B' // Compute both right and left eigenvectors. +) + +// HowMany specifies which eigenvectors will be computed. +type HowMany byte + +// HowMany constants for Dhseqr. +const ( + AllEV HowMany = 'A' // Compute all right and/or left eigenvectors. + AllEVMulQ HowMany = 'B' // Compute all right and/or left eigenvectors multiplied by an input matrix. + SelectedEV HowMany = 'S' // Compute selected right and/or left eigenvectors. +) diff --git a/lapack/lapack64/lapack64.go b/lapack/lapack64/lapack64.go new file mode 100644 index 00000000..095de163 --- /dev/null +++ b/lapack/lapack64/lapack64.go @@ -0,0 +1,560 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package lapack64 provides a set of convenient wrapper functions for LAPACK +// calls, as specified in the netlib standard (www.netlib.org). +// +// The native Go routines are used by default, and the Use function can be used +// to set an alternative implementation. +// +// If the type of matrix (General, Symmetric, etc.) is known and fixed, it is +// used in the wrapper signature. In many cases, however, the type of the matrix +// changes during the call to the routine, for example the matrix is symmetric on +// entry and is triangular on exit. In these cases the correct types should be checked +// in the documentation. +// +// The full set of Lapack functions is very large, and it is not clear that a +// full implementation is desirable, let alone feasible. Please open up an issue +// if there is a specific function you need and/or are willing to implement. +package lapack64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/native" +) + +var lapack64 lapack.Float64 = native.Implementation{} + +// Use sets the LAPACK float64 implementation to be used by subsequent BLAS calls. +// The default implementation is native.Implementation. +func Use(l lapack.Float64) { + lapack64 = l +} + +// Potrf computes the Cholesky factorization of a. +// The factorization has the form +// A = U^T * U if a.Uplo == blas.Upper, or +// A = L * L^T if a.Uplo == blas.Lower, +// where U is an upper triangular matrix and L is lower triangular. +// The triangular matrix is returned in t, and the underlying data between +// a and t is shared. The returned bool indicates whether a is positive +// definite and the factorization could be finished. +func Potrf(a blas64.Symmetric) (t blas64.Triangular, ok bool) { + ok = lapack64.Dpotrf(a.Uplo, a.N, a.Data, a.Stride) + t.Uplo = a.Uplo + t.N = a.N + t.Data = a.Data + t.Stride = a.Stride + t.Diag = blas.NonUnit + return +} + +// Gecon estimates the reciprocal of the condition number of the n×n matrix A +// given the LU decomposition of the matrix. The condition number computed may +// be based on the 1-norm or the ∞-norm. +// +// a contains the result of the LU decomposition of A as computed by Getrf. +// +// anorm is the corresponding 1-norm or ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 4*n and Gecon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Gecon will panic otherwise. +func Gecon(norm lapack.MatrixNorm, a blas64.General, anorm float64, work []float64, iwork []int) float64 { + return lapack64.Dgecon(norm, a.Cols, a.Data, a.Stride, anorm, work, iwork) +} + +// Gels finds a minimum-norm solution based on the matrices A and B using the +// QR or LQ factorization. Gels returns false if the matrix +// A is singular, and true if this solution was successfully found. +// +// The minimization problem solved depends on the input parameters. +// +// 1. If m >= n and trans == blas.NoTrans, Gels finds X such that || A*X - B||_2 +// is minimized. +// 2. If m < n and trans == blas.NoTrans, Gels finds the minimum norm solution of +// A * X = B. +// 3. If m >= n and trans == blas.Trans, Gels finds the minimum norm solution of +// A^T * X = B. +// 4. If m < n and trans == blas.Trans, Gels finds X such that || A*X - B||_2 +// is minimized. +// Note that the least-squares solutions (cases 1 and 3) perform the minimization +// per column of B. This is not the same as finding the minimum-norm matrix. +// +// The matrix A is a general matrix of size m×n and is modified during this call. +// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry, +// the elements of b specify the input matrix B. B has size m×nrhs if +// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the +// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans, +// this submatrix is of size n×nrhs, and of size m×nrhs otherwise. +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic +// otherwise. A longer work will enable blocked algorithms to be called. +// In the special case that lwork == -1, work[0] will be set to the optimal working +// length. +func Gels(trans blas.Transpose, a blas64.General, b blas64.General, work []float64, lwork int) bool { + return lapack64.Dgels(trans, a.Rows, a.Cols, b.Cols, a.Data, a.Stride, b.Data, b.Stride, work, lwork) +} + +// Geqrf computes the QR factorization of the m×n matrix A using a blocked +// algorithm. A is modified to contain the information to construct Q and R. +// The upper triangle of a contains the matrix R. The lower triangular elements +// (not including the diagonal) contain the elementary reflectors. tau is modified +// to contain the reflector scales. tau must have length at least min(m,n), and +// this function will panic otherwise. +// +// The ith elementary reflector can be explicitly constructed by first extracting +// the +// v[j] = 0 j < i +// v[j] = 1 j == i +// v[j] = a[j*lda+i] j > i +// and computing H_i = I - tau[i] * v * v^T. +// +// The orthonormal matrix Q can be constucted from a product of these elementary +// reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m and this function will panic otherwise. +// Geqrf is a blocked QR factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Geqrf, +// the optimal work length will be stored into work[0]. +func Geqrf(a blas64.General, tau, work []float64, lwork int) { + lapack64.Dgeqrf(a.Rows, a.Cols, a.Data, a.Stride, tau, work, lwork) +} + +// Gelqf computes the LQ factorization of the m×n matrix A using a blocked +// algorithm. A is modified to contain the information to construct L and Q. The +// lower triangle of a contains the matrix L. The elements above the diagonal +// and the slice tau represent the matrix Q. tau is modified to contain the +// reflector scales. tau must have length at least min(m,n), and this function +// will panic otherwise. +// +// See Geqrf for a description of the elementary reflectors and orthonormal +// matrix Q. Q is constructed as a product of these elementary reflectors, +// Q = H_{k-1} * ... * H_1 * H_0. +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m and this function will panic otherwise. +// Gelqf is a blocked LQ factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Gelqf, +// the optimal work length will be stored into work[0]. +func Gelqf(a blas64.General, tau, work []float64, lwork int) { + lapack64.Dgelqf(a.Rows, a.Cols, a.Data, a.Stride, tau, work, lwork) +} + +// Gesvd computes the singular value decomposition of the input matrix A. +// +// The singular value decomposition is +// A = U * Sigma * V^T +// where Sigma is an m×n diagonal matrix containing the singular values of A, +// U is an m×m orthogonal matrix and V is an n×n orthogonal matrix. The first +// min(m,n) columns of U and V are the left and right singular vectors of A +// respectively. +// +// jobU and jobVT are options for computing the singular vectors. The behavior +// is as follows +// jobU == lapack.SVDAll All m columns of U are returned in u +// jobU == lapack.SVDInPlace The first min(m,n) columns are returned in u +// jobU == lapack.SVDOverwrite The first min(m,n) columns of U are written into a +// jobU == lapack.SVDNone The columns of U are not computed. +// The behavior is the same for jobVT and the rows of V^T. At most one of jobU +// and jobVT can equal lapack.SVDOverwrite, and Gesvd will panic otherwise. +// +// On entry, a contains the data for the m×n matrix A. During the call to Gesvd +// the data is overwritten. On exit, A contains the appropriate singular vectors +// if either job is lapack.SVDOverwrite. +// +// s is a slice of length at least min(m,n) and on exit contains the singular +// values in decreasing order. +// +// u contains the left singular vectors on exit, stored columnwise. If +// jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDInPlace u is +// of size m×min(m,n). If jobU == lapack.SVDOverwrite or lapack.SVDNone, u is +// not used. +// +// vt contains the left singular vectors on exit, stored rowwise. If +// jobV == lapack.SVDAll, vt is of size n×m. If jobVT == lapack.SVDInPlace vt is +// of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is +// not used. +// +// work is a slice for storing temporary memory, and lwork is the usable size of +// the slice. lwork must be at least max(5*min(m,n), 3*min(m,n)+max(m,n)). +// If lwork == -1, instead of performing Gesvd, the optimal work length will be +// stored into work[0]. Gesvd will panic if the working memory has insufficient +// storage. +// +// Gesvd returns whether the decomposition successfully completed. +func Gesvd(jobU, jobVT lapack.SVDJob, a, u, vt blas64.General, s, work []float64, lwork int) (ok bool) { + return lapack64.Dgesvd(jobU, jobVT, a.Rows, a.Cols, a.Data, a.Stride, s, u.Data, u.Stride, vt.Data, vt.Stride, work, lwork) +} + +// Getrf computes the LU decomposition of the m×n matrix A. +// The LU decomposition is a factorization of A into +// A = P * L * U +// where P is a permutation matrix, L is a unit lower triangular matrix, and +// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored +// in place into a. +// +// ipiv is a permutation vector. It indicates that row i of the matrix was +// changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic +// otherwise. ipiv is zero-indexed. +// +// Getrf is the blocked version of the algorithm. +// +// Getrf returns whether the matrix A is singular. The LU decomposition will +// be computed regardless of the singularity of A, but division by zero +// will occur if the false is returned and the result is used to solve a +// system of equations. +func Getrf(a blas64.General, ipiv []int) bool { + return lapack64.Dgetrf(a.Rows, a.Cols, a.Data, a.Stride, ipiv) +} + +// Getri computes the inverse of the matrix A using the LU factorization computed +// by Getrf. On entry, a contains the PLU decomposition of A as computed by +// Getrf and on exit contains the reciprocal of the original matrix. +// +// Getri will not perform the inversion if the matrix is singular, and returns +// a boolean indicating whether the inversion was successful. +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= n and this function will panic otherwise. +// Getri is a blocked inversion, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Getri, +// the optimal work length will be stored into work[0]. +func Getri(a blas64.General, ipiv []int, work []float64, lwork int) (ok bool) { + return lapack64.Dgetri(a.Cols, a.Data, a.Stride, ipiv, work, lwork) +} + +// Getrs solves a system of equations using an LU factorization. +// The system of equations solved is +// A * X = B if trans == blas.Trans +// A^T * X = B if trans == blas.NoTrans +// A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs. +// +// On entry b contains the elements of the matrix B. On exit, b contains the +// elements of X, the solution to the system of equations. +// +// a and ipiv contain the LU factorization of A and the permutation indices as +// computed by Getrf. ipiv is zero-indexed. +func Getrs(trans blas.Transpose, a blas64.General, b blas64.General, ipiv []int) { + lapack64.Dgetrs(trans, a.Cols, b.Cols, a.Data, a.Stride, ipiv, b.Data, b.Stride) +} + +// Ggsvd3 computes the generalized singular value decomposition (GSVD) +// of an m×n matrix A and p×n matrix B: +// U^T*A*Q = D1*[ 0 R ] +// +// V^T*B*Q = D2*[ 0 R ] +// where U, V and Q are orthogonal matrices. +// +// Ggsvd3 returns k and l, the dimensions of the sub-blocks. k+l +// is the effective numerical rank of the (m+p)×n matrix [ A^T B^T ]^T. +// R is a (k+l)×(k+l) nonsingular upper triangular matrix, D1 and +// D2 are m×(k+l) and p×(k+l) diagonal matrices and of the following +// structures, respectively: +// +// If m-k-l >= 0, +// +// k l +// D1 = k [ I 0 ] +// l [ 0 C ] +// m-k-l [ 0 0 ] +// +// k l +// D2 = l [ 0 S ] +// p-l [ 0 0 ] +// +// n-k-l k l +// [ 0 R ] = k [ 0 R11 R12 ] k +// l [ 0 0 R22 ] l +// +// where +// +// C = diag( alpha_k, ... , alpha_{k+l} ), +// S = diag( beta_k, ... , beta_{k+l} ), +// C^2 + S^2 = I. +// +// R is stored in +// A[0:k+l, n-k-l:n] +// on exit. +// +// If m-k-l < 0, +// +// k m-k k+l-m +// D1 = k [ I 0 0 ] +// m-k [ 0 C 0 ] +// +// k m-k k+l-m +// D2 = m-k [ 0 S 0 ] +// k+l-m [ 0 0 I ] +// p-l [ 0 0 0 ] +// +// n-k-l k m-k k+l-m +// [ 0 R ] = k [ 0 R11 R12 R13 ] +// m-k [ 0 0 R22 R23 ] +// k+l-m [ 0 0 0 R33 ] +// +// where +// C = diag( alpha_k, ... , alpha_m ), +// S = diag( beta_k, ... , beta_m ), +// C^2 + S^2 = I. +// +// R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n] +// [ 0 R22 R23 ] +// and R33 is stored in +// B[m-k:l, n+m-k-l:n] on exit. +// +// Ggsvd3 computes C, S, R, and optionally the orthogonal transformation +// matrices U, V and Q. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// alpha and beta must have length n or Ggsvd3 will panic. On exit, alpha and +// beta contain the generalized singular value pairs of A and B +// alpha[0:k] = 1, +// beta[0:k] = 0, +// if m-k-l >= 0, +// alpha[k:k+l] = diag(C), +// beta[k:k+l] = diag(S), +// if m-k-l < 0, +// alpha[k:m]= C, alpha[m:k+l]= 0 +// beta[k:m] = S, beta[m:k+l] = 1. +// if k+l < n, +// alpha[k+l:n] = 0 and +// beta[k+l:n] = 0. +// +// On exit, iwork contains the permutation required to sort alpha descending. +// +// iwork must have length n, work must have length at least max(1, lwork), and +// lwork must be -1 or greater than n, otherwise Ggsvd3 will panic. If +// lwork is -1, work[0] holds the optimal lwork on return, but Ggsvd3 does +// not perform the GSVD. +func Ggsvd3(jobU, jobV, jobQ lapack.GSVDJob, a, b blas64.General, alpha, beta []float64, u, v, q blas64.General, work []float64, lwork int, iwork []int) (k, l int, ok bool) { + return lapack64.Dggsvd3(jobU, jobV, jobQ, a.Rows, a.Cols, b.Rows, a.Data, a.Stride, b.Data, b.Stride, alpha, beta, u.Data, u.Stride, v.Data, v.Stride, q.Data, q.Stride, work, lwork, iwork) +} + +// Lange computes the matrix norm of the general m×n matrix A. The input norm +// specifies the norm computed. +// lapack.MaxAbs: the maximum absolute value of an element. +// lapack.MaxColumnSum: the maximum column sum of the absolute values of the entries. +// lapack.MaxRowSum: the maximum row sum of the absolute values of the entries. +// lapack.Frobenius: the square root of the sum of the squares of the entries. +// If norm == lapack.MaxColumnSum, work must be of length n, and this function will panic otherwise. +// There are no restrictions on work for the other matrix norms. +func Lange(norm lapack.MatrixNorm, a blas64.General, work []float64) float64 { + return lapack64.Dlange(norm, a.Rows, a.Cols, a.Data, a.Stride, work) +} + +// Lansy computes the specified norm of an n×n symmetric matrix. If +// norm == lapack.MaxColumnSum or norm == lapackMaxRowSum work must have length +// at least n and this function will panic otherwise. +// There are no restrictions on work for the other matrix norms. +func Lansy(norm lapack.MatrixNorm, a blas64.Symmetric, work []float64) float64 { + return lapack64.Dlansy(norm, a.Uplo, a.N, a.Data, a.Stride, work) +} + +// Lantr computes the specified norm of an m×n trapezoidal matrix A. If +// norm == lapack.MaxColumnSum work must have length at least n and this function +// will panic otherwise. There are no restrictions on work for the other matrix norms. +func Lantr(norm lapack.MatrixNorm, a blas64.Triangular, work []float64) float64 { + return lapack64.Dlantr(norm, a.Uplo, a.Diag, a.N, a.N, a.Data, a.Stride, work) +} + +// Lapmt rearranges the columns of the m×n matrix X as specified by the +// permutation k_0, k_1, ..., k_{n-1} of the integers 0, ..., n-1. +// +// If forward is true a forward permutation is performed: +// +// X[0:m, k[j]] is moved to X[0:m, j] for j = 0, 1, ..., n-1. +// +// otherwise a backward permutation is performed: +// +// X[0:m, j] is moved to X[0:m, k[j]] for j = 0, 1, ..., n-1. +// +// k must have length n, otherwise Lapmt will panic. k is zero-indexed. +func Lapmt(forward bool, x blas64.General, k []int) { + lapack64.Dlapmt(forward, x.Rows, x.Cols, x.Data, x.Stride, k) +} + +// Ormlq multiplies the matrix C by the othogonal matrix Q defined by +// A and tau. A and tau are as returned from Gelqf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, A is a matrix of side k×m, and if side == blas.Right +// A is of size k×n. This uses a blocked algorithm. +// +// Work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right, +// and this function will panic otherwise. +// Ormlq uses a block algorithm, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Ormlq, +// the optimal work length will be stored into work[0]. +// +// Tau contains the Householder scales and must have length at least k, and +// this function will panic otherwise. +func Ormlq(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) { + lapack64.Dormlq(side, trans, c.Rows, c.Cols, a.Rows, a.Data, a.Stride, tau, c.Data, c.Stride, work, lwork) +} + +// Ormqr multiplies an m×n matrix C by an orthogonal matrix Q as +// C = Q * C, if side == blas.Left and trans == blas.NoTrans, +// C = Q^T * C, if side == blas.Left and trans == blas.Trans, +// C = C * Q, if side == blas.Right and trans == blas.NoTrans, +// C = C * Q^T, if side == blas.Right and trans == blas.Trans, +// where Q is defined as the product of k elementary reflectors +// Q = H_0 * H_1 * ... * H_{k-1}. +// +// If side == blas.Left, A is an m×k matrix and 0 <= k <= m. +// If side == blas.Right, A is an n×k matrix and 0 <= k <= n. +// The ith column of A contains the vector which defines the elementary +// reflector H_i and tau[i] contains its scalar factor. tau must have length k +// and Ormqr will panic otherwise. Geqrf returns A and tau in the required +// form. +// +// work must have length at least max(1,lwork), and lwork must be at least n if +// side == blas.Left and at least m if side == blas.Right, otherwise Ormqr will +// panic. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= m if side == blas.Left and lwork >= n if side == +// blas.Right, and this function will panic otherwise. Larger values of lwork +// will generally give better performance. On return, work[0] will contain the +// optimal value of lwork. +// +// If lwork is -1, instead of performing Ormqr, the optimal workspace size will +// be stored into work[0]. +func Ormqr(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) { + lapack64.Dormqr(side, trans, c.Rows, c.Cols, a.Cols, a.Data, a.Stride, tau, c.Data, c.Stride, work, lwork) +} + +// Pocon estimates the reciprocal of the condition number of a positive-definite +// matrix A given the Cholesky decmposition of A. The condition number computed +// is based on the 1-norm and the ∞-norm. +// +// anorm is the 1-norm and the ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 3*n and Pocon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Pocon will panic otherwise. +func Pocon(a blas64.Symmetric, anorm float64, work []float64, iwork []int) float64 { + return lapack64.Dpocon(a.Uplo, a.N, a.Data, a.Stride, anorm, work, iwork) +} + +// Syev computes all eigenvalues and, optionally, the eigenvectors of a real +// symmetric matrix A. +// +// w contains the eigenvalues in ascending order upon return. w must have length +// at least n, and Syev will panic otherwise. +// +// On entry, a contains the elements of the symmetric matrix A in the triangular +// portion specified by uplo. If jobz == lapack.ComputeEV a contains the +// orthonormal eigenvectors of A on exit, otherwise on exit the specified +// triangular region is overwritten. +// +// Work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= 3*n-1, and Syev will panic otherwise. The amount of blocking is +// limited by the usable length. If lwork == -1, instead of computing Syev the +// optimal work length is stored into work[0]. +func Syev(jobz lapack.EVJob, a blas64.Symmetric, w, work []float64, lwork int) (ok bool) { + return lapack64.Dsyev(jobz, a.Uplo, a.N, a.Data, a.Stride, w, work, lwork) +} + +// Trcon estimates the reciprocal of the condition number of a triangular matrix A. +// The condition number computed may be based on the 1-norm or the ∞-norm. +// +// work is a temporary data slice of length at least 3*n and Trcon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Trcon will panic otherwise. +func Trcon(norm lapack.MatrixNorm, a blas64.Triangular, work []float64, iwork []int) float64 { + return lapack64.Dtrcon(norm, a.Uplo, a.Diag, a.N, a.Data, a.Stride, work, iwork) +} + +// Trtri computes the inverse of a triangular matrix, storing the result in place +// into a. +// +// Trtri will not perform the inversion if the matrix is singular, and returns +// a boolean indicating whether the inversion was successful. +func Trtri(a blas64.Triangular) (ok bool) { + return lapack64.Dtrtri(a.Uplo, a.Diag, a.N, a.Data, a.Stride) +} + +// Trtrs solves a triangular system of the form A * X = B or A^T * X = B. Trtrs +// returns whether the solve completed successfully. If A is singular, no solve is performed. +func Trtrs(trans blas.Transpose, a blas64.Triangular, b blas64.General) (ok bool) { + return lapack64.Dtrtrs(a.Uplo, trans, a.Diag, a.N, b.Cols, a.Data, a.Stride, b.Data, b.Stride) +} + +// Geev computes the eigenvalues and, optionally, the left and/or right +// eigenvectors for an n×n real nonsymmetric matrix A. +// +// The right eigenvector v_j of A corresponding to an eigenvalue λ_j +// is defined by +// A v_j = λ_j v_j, +// and the left eigenvector u_j corresponding to an eigenvalue λ_j is defined by +// u_j^H A = λ_j u_j^H, +// where u_j^H is the conjugate transpose of u_j. +// +// On return, A will be overwritten and the left and right eigenvectors will be +// stored, respectively, in the columns of the n×n matrices VL and VR in the +// same order as their eigenvalues. If the j-th eigenvalue is real, then +// u_j = VL[:,j], +// v_j = VR[:,j], +// and if it is not real, then j and j+1 form a complex conjugate pair and the +// eigenvectors can be recovered as +// u_j = VL[:,j] + i*VL[:,j+1], +// u_{j+1} = VL[:,j] - i*VL[:,j+1], +// v_j = VR[:,j] + i*VR[:,j+1], +// v_{j+1} = VR[:,j] - i*VR[:,j+1], +// where i is the imaginary unit. The computed eigenvectors are normalized to +// have Euclidean norm equal to 1 and largest component real. +// +// Left eigenvectors will be computed only if jobvl == lapack.ComputeLeftEV, +// otherwise jobvl must be lapack.None. +// Right eigenvectors will be computed only if jobvr == lapack.ComputeRightEV, +// otherwise jobvr must be lapack.None. +// For other values of jobvl and jobvr Geev will panic. +// +// On return, wr and wi will contain the real and imaginary parts, respectively, +// of the computed eigenvalues. Complex conjugate pairs of eigenvalues appear +// consecutively with the eigenvalue having the positive imaginary part first. +// wr and wi must have length n, and Geev will panic otherwise. +// +// work must have length at least lwork and lwork must be at least max(1,4*n) if +// the left or right eigenvectors are computed, and at least max(1,3*n) if no +// eigenvectors are computed. For good performance, lwork must generally be +// larger. On return, optimal value of lwork will be stored in work[0]. +// +// If lwork == -1, instead of performing Geev, the function only calculates the +// optimal vaule of lwork and stores it into work[0]. +// +// On return, first will be the index of the first valid eigenvalue. +// If first == 0, all eigenvalues and eigenvectors have been computed. +// If first is positive, Geev failed to compute all the eigenvalues, no +// eigenvectors have been computed and wr[first:] and wi[first:] contain those +// eigenvalues which have converged. +func Geev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, a blas64.General, wr, wi []float64, vl, vr blas64.General, work []float64, lwork int) (first int) { + n := a.Rows + if a.Cols != n { + panic("lapack64: matrix not square") + } + if jobvl == lapack.ComputeLeftEV && (vl.Rows != n || vl.Cols != n) { + panic("lapack64: bad size of VL") + } + if jobvr == lapack.ComputeRightEV && (vr.Rows != n || vr.Cols != n) { + panic("lapack64: bad size of VR") + } + return lapack64.Dgeev(jobvl, jobvr, n, a.Data, a.Stride, wr, wi, vl.Data, vl.Stride, vr.Data, vr.Stride, work, lwork) +} diff --git a/lapack/native/bench_test.go b/lapack/native/bench_test.go new file mode 100644 index 00000000..35fa9369 --- /dev/null +++ b/lapack/native/bench_test.go @@ -0,0 +1,15 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package native + +import ( + "testing" + + "gonum.org/v1/gonum/lapack/testlapack" +) + +func BenchmarkDgeev(b *testing.B) { testlapack.DgeevBenchmark(b, impl) } diff --git a/lapack/native/dbdsqr.go b/lapack/native/dbdsqr.go new file mode 100644 index 00000000..7b4ecd98 --- /dev/null +++ b/lapack/native/dbdsqr.go @@ -0,0 +1,488 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dbdsqr performs a singular value decomposition of a real n×n bidiagonal matrix. +// +// The SVD of the bidiagonal matrix B is +// B = Q * S * P^T +// where S is a diagonal matrix of singular values, Q is an orthogonal matrix of +// left singular vectors, and P is an orthogonal matrix of right singular vectors. +// +// Q and P are only computed if requested. If left singular vectors are requested, +// this routine returns U * Q instead of Q, and if right singular vectors are +// requested P^T * VT is returned instead of P^T. +// +// Frequently Dbdsqr is used in conjunction with Dgebrd which reduces a general +// matrix A into bidiagonal form. In this case, the SVD of A is +// A = (U * Q) * S * (P^T * VT) +// +// This routine may also compute Q^T * C. +// +// d and e contain the elements of the bidiagonal matrix b. d must have length at +// least n, and e must have length at least n-1. Dbdsqr will panic if there is +// insufficient length. On exit, D contains the singular values of B in decreasing +// order. +// +// VT is a matrix of size n×ncvt whose elements are stored in vt. The elements +// of vt are modified to contain P^T * VT on exit. VT is not used if ncvt == 0. +// +// U is a matrix of size nru×n whose elements are stored in u. The elements +// of u are modified to contain U * Q on exit. U is not used if nru == 0. +// +// C is a matrix of size n×ncc whose elements are stored in c. The elements +// of c are modified to contain Q^T * C on exit. C is not used if ncc == 0. +// +// work contains temporary storage and must have length at least 4*n. Dbdsqr +// will panic if there is insufficient working memory. +// +// Dbdsqr returns whether the decomposition was successful. +// +// Dbdsqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dbdsqr(uplo blas.Uplo, n, ncvt, nru, ncc int, d, e, vt []float64, ldvt int, u []float64, ldu int, c []float64, ldc int, work []float64) (ok bool) { + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if ncvt != 0 { + checkMatrix(n, ncvt, vt, ldvt) + } + if nru != 0 { + checkMatrix(nru, n, u, ldu) + } + if ncc != 0 { + checkMatrix(n, ncc, c, ldc) + } + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if len(work) < 4*n { + panic(badWork) + } + var info int + bi := blas64.Implementation() + const ( + maxIter = 6 + ) + if n == 0 { + return true + } + if n != 1 { + // If the singular vectors do not need to be computed, use qd algorithm. + if !(ncvt > 0 || nru > 0 || ncc > 0) { + info = impl.Dlasq1(n, d, e, work) + // If info is 2 dqds didn't finish, and so try to. + if info != 2 { + return info == 0 + } + info = 0 + } + nm1 := n - 1 + nm12 := nm1 + nm1 + nm13 := nm12 + nm1 + idir := 0 + + eps := dlamchE + unfl := dlamchS + lower := uplo == blas.Lower + var cs, sn, r float64 + if lower { + for i := 0; i < n-1; i++ { + cs, sn, r = impl.Dlartg(d[i], e[i]) + d[i] = r + e[i] = sn * d[i+1] + d[i+1] *= cs + work[i] = cs + work[nm1+i] = sn + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, nru, n, work, work[n-1:], u, ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, n, ncc, work, work[n-1:], c, ldc) + } + } + // Compute singular values to a relative accuracy of tol. If tol is negative + // the values will be computed to an absolute accuracy of math.Abs(tol) * norm(b) + tolmul := math.Max(10, math.Min(100, math.Pow(eps, -1.0/8))) + tol := tolmul * eps + var smax float64 + for i := 0; i < n; i++ { + smax = math.Max(smax, math.Abs(d[i])) + } + for i := 0; i < n-1; i++ { + smax = math.Max(smax, math.Abs(e[i])) + } + + var sminl float64 + var thresh float64 + if tol >= 0 { + sminoa := math.Abs(d[0]) + if sminoa != 0 { + mu := sminoa + for i := 1; i < n; i++ { + mu = math.Abs(d[i]) * (mu / (mu + math.Abs(e[i-1]))) + sminoa = math.Min(sminoa, mu) + if sminoa == 0 { + break + } + } + } + sminoa = sminoa / math.Sqrt(float64(n)) + thresh = math.Max(tol*sminoa, float64(maxIter*n*n)*unfl) + } else { + thresh = math.Max(math.Abs(tol)*smax, float64(maxIter*n*n)*unfl) + } + // Prepare for the main iteration loop for the singular values. + maxIt := maxIter * n * n + iter := 0 + oldl2 := -1 + oldm := -1 + // m points to the last element of unconverged part of matrix. + m := n + + Outer: + for m > 1 { + if iter > maxIt { + info = 0 + for i := 0; i < n-1; i++ { + if e[i] != 0 { + info++ + } + } + return info == 0 + } + // Find diagonal block of matrix to work on. + if tol < 0 && math.Abs(d[m-1]) <= thresh { + d[m-1] = 0 + } + smax = math.Abs(d[m-1]) + smin := smax + var l2 int + var broke bool + for l3 := 0; l3 < m-1; l3++ { + l2 = m - l3 - 2 + abss := math.Abs(d[l2]) + abse := math.Abs(e[l2]) + if tol < 0 && abss <= thresh { + d[l2] = 0 + } + if abse <= thresh { + broke = true + break + } + smin = math.Min(smin, abss) + smax = math.Max(math.Max(smax, abss), abse) + } + if broke { + e[l2] = 0 + if l2 == m-2 { + // Convergence of bottom singular value, return to top. + m-- + continue + } + l2++ + } else { + l2 = 0 + } + // e[ll] through e[m-2] are nonzero, e[ll-1] is zero + if l2 == m-2 { + // Handle 2×2 block separately. + var sinr, cosr, sinl, cosl float64 + d[m-1], d[m-2], sinr, cosr, sinl, cosl = impl.Dlasv2(d[m-2], e[m-2], d[m-1]) + e[m-2] = 0 + if ncvt > 0 { + bi.Drot(ncvt, vt[(m-2)*ldvt:], 1, vt[(m-1)*ldvt:], 1, cosr, sinr) + } + if nru > 0 { + bi.Drot(nru, u[m-2:], ldu, u[m-1:], ldu, cosl, sinl) + } + if ncc > 0 { + bi.Drot(ncc, c[(m-2)*ldc:], 1, c[(m-1)*ldc:], 1, cosl, sinl) + } + m -= 2 + continue + } + // If working on a new submatrix, choose shift direction from larger end + // diagonal element toward smaller. + if l2 > oldm-1 || m-1 < oldl2 { + if math.Abs(d[l2]) >= math.Abs(d[m-1]) { + idir = 1 + } else { + idir = 2 + } + } + // Apply convergence tests. + // TODO(btracey): There is a lot of similar looking code here. See + // if there is a better way to de-duplicate. + if idir == 1 { + // Run convergence test in forward direction. + // First apply standard test to bottom of matrix. + if math.Abs(e[m-2]) <= math.Abs(tol)*math.Abs(d[m-1]) || (tol < 0 && math.Abs(e[m-2]) <= thresh) { + e[m-2] = 0 + continue + } + if tol >= 0 { + // If relative accuracy desired, apply convergence criterion forward. + mu := math.Abs(d[l2]) + sminl = mu + for l3 := l2; l3 < m-1; l3++ { + if math.Abs(e[l3]) <= tol*mu { + e[l3] = 0 + continue Outer + } + mu = math.Abs(d[l3+1]) * (mu / (mu + math.Abs(e[l3]))) + sminl = math.Min(sminl, mu) + } + } + } else { + // Run convergence test in backward direction. + // First apply standard test to top of matrix. + if math.Abs(e[l2]) <= math.Abs(tol)*math.Abs(d[l2]) || (tol < 0 && math.Abs(e[l2]) <= thresh) { + e[l2] = 0 + continue + } + if tol >= 0 { + // If relative accuracy desired, apply convergence criterion backward. + mu := math.Abs(d[m-1]) + sminl = mu + for l3 := m - 2; l3 >= l2; l3-- { + if math.Abs(e[l3]) <= tol*mu { + e[l3] = 0 + continue Outer + } + mu = math.Abs(d[l3]) * (mu / (mu + math.Abs(e[l3]))) + sminl = math.Min(sminl, mu) + } + } + } + oldl2 = l2 + oldm = m + // Compute shift. First, test if shifting would ruin relative accuracy, + // and if so set the shift to zero. + var shift float64 + if tol >= 0 && float64(n)*tol*(sminl/smax) <= math.Max(eps, (1.0/100)*tol) { + shift = 0 + } else { + var sl2 float64 + if idir == 1 { + sl2 = math.Abs(d[l2]) + shift, _ = impl.Dlas2(d[m-2], e[m-2], d[m-1]) + } else { + sl2 = math.Abs(d[m-1]) + shift, _ = impl.Dlas2(d[l2], e[l2], d[l2+1]) + } + // Test if shift is negligible + if sl2 > 0 { + if (shift/sl2)*(shift/sl2) < eps { + shift = 0 + } + } + } + iter += m - l2 + 1 + // If no shift, do simplified QR iteration. + if shift == 0 { + if idir == 1 { + cs := 1.0 + oldcs := 1.0 + var sn, r, oldsn float64 + for i := l2; i < m-1; i++ { + cs, sn, r = impl.Dlartg(d[i]*cs, e[i]) + if i > l2 { + e[i-1] = oldsn * r + } + oldcs, oldsn, d[i] = impl.Dlartg(oldcs*r, d[i+1]*sn) + work[i-l2] = cs + work[i-l2+nm1] = sn + work[i-l2+nm12] = oldcs + work[i-l2+nm13] = oldsn + } + h := d[m-1] * cs + d[m-1] = h * oldcs + e[m-2] = h * oldsn + if ncvt > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncvt, work, work[n-1:], vt[l2*ldvt:], ldvt) + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, nru, m-l2, work[nm12:], work[nm13:], u[l2:], ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncc, work[nm12:], work[nm13:], c[l2*ldc:], ldc) + } + if math.Abs(e[m-2]) < thresh { + e[m-2] = 0 + } + } else { + cs := 1.0 + oldcs := 1.0 + var sn, r, oldsn float64 + for i := m - 1; i >= l2+1; i-- { + cs, sn, r = impl.Dlartg(d[i]*cs, e[i-1]) + if i < m-1 { + e[i] = oldsn * r + } + oldcs, oldsn, d[i] = impl.Dlartg(oldcs*r, d[i-1]*sn) + work[i-l2-1] = cs + work[i-l2+nm1-1] = -sn + work[i-l2+nm12-1] = oldcs + work[i-l2+nm13-1] = -oldsn + } + h := d[l2] * cs + d[l2] = h * oldcs + e[l2] = h * oldsn + if ncvt > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncvt, work[nm12:], work[nm13:], vt[l2*ldvt:], ldvt) + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, nru, m-l2, work, work[n-1:], u[l2:], ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncc, work, work[n-1:], c[l2*ldc:], ldc) + } + if math.Abs(e[l2]) <= thresh { + e[l2] = 0 + } + } + } else { + // Use nonzero shift. + if idir == 1 { + // Chase bulge from top to bottom. Save cosines and sines for + // later singular vector updates. + f := (math.Abs(d[l2]) - shift) * (math.Copysign(1, d[l2]) + shift/d[l2]) + g := e[l2] + var cosl, sinl float64 + for i := l2; i < m-1; i++ { + cosr, sinr, r := impl.Dlartg(f, g) + if i > l2 { + e[i-1] = r + } + f = cosr*d[i] + sinr*e[i] + e[i] = cosr*e[i] - sinr*d[i] + g = sinr * d[i+1] + d[i+1] *= cosr + cosl, sinl, r = impl.Dlartg(f, g) + d[i] = r + f = cosl*e[i] + sinl*d[i+1] + d[i+1] = cosl*d[i+1] - sinl*e[i] + if i < m-2 { + g = sinl * e[i+1] + e[i+1] = cosl * e[i+1] + } + work[i-l2] = cosr + work[i-l2+nm1] = sinr + work[i-l2+nm12] = cosl + work[i-l2+nm13] = sinl + } + e[m-2] = f + if ncvt > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncvt, work, work[n-1:], vt[l2*ldvt:], ldvt) + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, nru, m-l2, work[nm12:], work[nm13:], u[l2:], ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Forward, m-l2, ncc, work[nm12:], work[nm13:], c[l2*ldc:], ldc) + } + if math.Abs(e[m-2]) <= thresh { + e[m-2] = 0 + } + } else { + // Chase bulge from top to bottom. Save cosines and sines for + // later singular vector updates. + f := (math.Abs(d[m-1]) - shift) * (math.Copysign(1, d[m-1]) + shift/d[m-1]) + g := e[m-2] + for i := m - 1; i > l2; i-- { + cosr, sinr, r := impl.Dlartg(f, g) + if i < m-1 { + e[i] = r + } + f = cosr*d[i] + sinr*e[i-1] + e[i-1] = cosr*e[i-1] - sinr*d[i] + g = sinr * d[i-1] + d[i-1] *= cosr + cosl, sinl, r := impl.Dlartg(f, g) + d[i] = r + f = cosl*e[i-1] + sinl*d[i-1] + d[i-1] = cosl*d[i-1] - sinl*e[i-1] + if i > l2+1 { + g = sinl * e[i-2] + e[i-2] *= cosl + } + work[i-l2-1] = cosr + work[i-l2+nm1-1] = -sinr + work[i-l2+nm12-1] = cosl + work[i-l2+nm13-1] = -sinl + } + e[l2] = f + if math.Abs(e[l2]) <= thresh { + e[l2] = 0 + } + if ncvt > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncvt, work[nm12:], work[nm13:], vt[l2*ldvt:], ldvt) + } + if nru > 0 { + impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, nru, m-l2, work, work[n-1:], u[l2:], ldu) + } + if ncc > 0 { + impl.Dlasr(blas.Left, lapack.Variable, lapack.Backward, m-l2, ncc, work, work[n-1:], c[l2*ldc:], ldc) + } + } + } + } + } + + // All singular values converged, make them positive. + for i := 0; i < n; i++ { + if d[i] < 0 { + d[i] *= -1 + if ncvt > 0 { + bi.Dscal(ncvt, -1, vt[i*ldvt:], 1) + } + } + } + + // Sort the singular values in decreasing order. + for i := 0; i < n-1; i++ { + isub := 0 + smin := d[0] + for j := 1; j < n-i; j++ { + if d[j] <= smin { + isub = j + smin = d[j] + } + } + if isub != n-i { + // Swap singular values and vectors. + d[isub] = d[n-i-1] + d[n-i-1] = smin + if ncvt > 0 { + bi.Dswap(ncvt, vt[isub*ldvt:], 1, vt[(n-i-1)*ldvt:], 1) + } + if nru > 0 { + bi.Dswap(nru, u[isub:], ldu, u[n-i-1:], ldu) + } + if ncc > 0 { + bi.Dswap(ncc, c[isub*ldc:], 1, c[(n-i-1)*ldc:], 1) + } + } + } + info = 0 + for i := 0; i < n-1; i++ { + if e[i] != 0 { + info++ + } + } + return info == 0 +} diff --git a/lapack/native/dgebak.go b/lapack/native/dgebak.go new file mode 100644 index 00000000..096c21c3 --- /dev/null +++ b/lapack/native/dgebak.go @@ -0,0 +1,78 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgebak updates an n×m matrix V as +// V = P D V, if side == lapack.RightEV, +// V = P D^{-1} V, if side == lapack.LeftEV, +// where P and D are n×n permutation and scaling matrices, respectively, +// implicitly represented by job, scale, ilo and ihi as returned by Dgebal. +// +// Typically, columns of the matrix V contain the right or left (determined by +// side) eigenvectors of the balanced matrix output by Dgebal, and Dgebak forms +// the eigenvectors of the original matrix. +// +// Dgebak is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebak(job lapack.Job, side lapack.EVSide, n, ilo, ihi int, scale []float64, m int, v []float64, ldv int) { + switch job { + default: + panic(badJob) + case lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale: + } + switch side { + default: + panic(badSide) + case lapack.LeftEV, lapack.RightEV: + } + checkMatrix(n, m, v, ldv) + switch { + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + } + + // Quick return if possible. + if n == 0 || m == 0 || job == lapack.None { + return + } + + bi := blas64.Implementation() + if ilo != ihi && job != lapack.Permute { + // Backward balance. + if side == lapack.RightEV { + for i := ilo; i <= ihi; i++ { + bi.Dscal(m, scale[i], v[i*ldv:], 1) + } + } else { + for i := ilo; i <= ihi; i++ { + bi.Dscal(m, 1/scale[i], v[i*ldv:], 1) + } + } + } + if job == lapack.Scale { + return + } + // Backward permutation. + for i := ilo - 1; i >= 0; i-- { + k := int(scale[i]) + if k == i { + continue + } + bi.Dswap(m, v[i*ldv:], 1, v[k*ldv:], 1) + } + for i := ihi + 1; i < n; i++ { + k := int(scale[i]) + if k == i { + continue + } + bi.Dswap(m, v[i*ldv:], 1, v[k*ldv:], 1) + } +} diff --git a/lapack/native/dgebal.go b/lapack/native/dgebal.go new file mode 100644 index 00000000..6b986fa2 --- /dev/null +++ b/lapack/native/dgebal.go @@ -0,0 +1,228 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgebal balances an n×n matrix A. Balancing consists of two stages, permuting +// and scaling. Both steps are optional and depend on the value of job. +// +// Permuting consists of applying a permutation matrix P such that the matrix +// that results from P^T*A*P takes the upper block triangular form +// [ T1 X Y ] +// P^T A P = [ 0 B Z ], +// [ 0 0 T2 ] +// where T1 and T2 are upper triangular matrices and B contains at least one +// nonzero off-diagonal element in each row and column. The indices ilo and ihi +// mark the starting and ending columns of the submatrix B. The eigenvalues of A +// isolated in the first 0 to ilo-1 and last ihi+1 to n-1 elements on the +// diagonal can be read off without any roundoff error. +// +// Scaling consists of applying a diagonal similarity transformation D such that +// D^{-1}*B*D has the 1-norm of each row and its corresponding column nearly +// equal. The output matrix is +// [ T1 X*D Y ] +// [ 0 inv(D)*B*D inv(D)*Z ]. +// [ 0 0 T2 ] +// Scaling may reduce the 1-norm of the matrix, and improve the accuracy of +// the computed eigenvalues and/or eigenvectors. +// +// job specifies the operations that will be performed on A. +// If job is lapack.None, Dgebal sets scale[i] = 1 for all i and returns ilo=0, ihi=n-1. +// If job is lapack.Permute, only permuting will be done. +// If job is lapack.Scale, only scaling will be done. +// If job is lapack.PermuteScale, both permuting and scaling will be done. +// +// On return, if job is lapack.Permute or lapack.PermuteScale, it will hold that +// A[i,j] == 0, for i > j and j ∈ {0, ..., ilo-1, ihi+1, ..., n-1}. +// If job is lapack.None or lapack.Scale, or if n == 0, it will hold that +// ilo == 0 and ihi == n-1. +// +// On return, scale will contain information about the permutations and scaling +// factors applied to A. If π(j) denotes the index of the column interchanged +// with column j, and D[j,j] denotes the scaling factor applied to column j, +// then +// scale[j] == π(j), for j ∈ {0, ..., ilo-1, ihi+1, ..., n-1}, +// == D[j,j], for j ∈ {ilo, ..., ihi}. +// scale must have length equal to n, otherwise Dgebal will panic. +// +// Dgebal is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebal(job lapack.Job, n int, a []float64, lda int, scale []float64) (ilo, ihi int) { + switch job { + default: + panic(badJob) + case lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale: + } + checkMatrix(n, n, a, lda) + if len(scale) != n { + panic("lapack: bad length of scale") + } + + ilo = 0 + ihi = n - 1 + + if n == 0 || job == lapack.None { + for i := range scale { + scale[i] = 1 + } + return ilo, ihi + } + + bi := blas64.Implementation() + swapped := true + + if job == lapack.Scale { + goto scaling + } + + // Permutation to isolate eigenvalues if possible. + // + // Search for rows isolating an eigenvalue and push them down. + for swapped { + swapped = false + rows: + for i := ihi; i >= 0; i-- { + for j := 0; j <= ihi; j++ { + if i == j { + continue + } + if a[i*lda+j] != 0 { + continue rows + } + } + // Row i has only zero off-diagonal elements in the + // block A[ilo:ihi+1,ilo:ihi+1]. + scale[ihi] = float64(i) + if i != ihi { + bi.Dswap(ihi+1, a[i:], lda, a[ihi:], lda) + bi.Dswap(n, a[i*lda:], 1, a[ihi*lda:], 1) + } + if ihi == 0 { + scale[0] = 1 + return ilo, ihi + } + ihi-- + swapped = true + break + } + } + // Search for columns isolating an eigenvalue and push them left. + swapped = true + for swapped { + swapped = false + columns: + for j := ilo; j <= ihi; j++ { + for i := ilo; i <= ihi; i++ { + if i == j { + continue + } + if a[i*lda+j] != 0 { + continue columns + } + } + // Column j has only zero off-diagonal elements in the + // block A[ilo:ihi+1,ilo:ihi+1]. + scale[ilo] = float64(j) + if j != ilo { + bi.Dswap(ihi+1, a[j:], lda, a[ilo:], lda) + bi.Dswap(n-ilo, a[j*lda+ilo:], 1, a[ilo*lda+ilo:], 1) + } + swapped = true + ilo++ + break + } + } + +scaling: + for i := ilo; i <= ihi; i++ { + scale[i] = 1 + } + + if job == lapack.Permute { + return ilo, ihi + } + + // Balance the submatrix in rows ilo to ihi. + + const ( + // sclfac should be a power of 2 to avoid roundoff errors. + // Elements of scale are restricted to powers of sclfac, + // therefore the matrix will be only nearly balanced. + sclfac = 2 + // factor determines the minimum reduction of the row and column + // norms that is considered non-negligible. It must be less than 1. + factor = 0.95 + ) + sfmin1 := dlamchS / dlamchP + sfmax1 := 1 / sfmin1 + sfmin2 := sfmin1 * sclfac + sfmax2 := 1 / sfmin2 + + // Iterative loop for norm reduction. + var conv bool + for !conv { + conv = true + for i := ilo; i <= ihi; i++ { + c := bi.Dnrm2(ihi-ilo+1, a[ilo*lda+i:], lda) + r := bi.Dnrm2(ihi-ilo+1, a[i*lda+ilo:], 1) + ica := bi.Idamax(ihi+1, a[i:], lda) + ca := math.Abs(a[ica*lda+i]) + ira := bi.Idamax(n-ilo, a[i*lda+ilo:], 1) + ra := math.Abs(a[i*lda+ilo+ira]) + + // Guard against zero c or r due to underflow. + if c == 0 || r == 0 { + continue + } + g := r / sclfac + f := 1.0 + s := c + r + for c < g && math.Max(f, math.Max(c, ca)) < sfmax2 && math.Min(r, math.Min(g, ra)) > sfmin2 { + if math.IsNaN(c + f + ca + r + g + ra) { + // Panic if NaN to avoid infinite loop. + panic("lapack: NaN") + } + f *= sclfac + c *= sclfac + ca *= sclfac + g /= sclfac + r /= sclfac + ra /= sclfac + } + g = c / sclfac + for r <= g && math.Max(r, ra) < sfmax2 && math.Min(math.Min(f, c), math.Min(g, ca)) > sfmin2 { + f /= sclfac + c /= sclfac + ca /= sclfac + g /= sclfac + r *= sclfac + ra *= sclfac + } + + if c+r >= factor*s { + // Reduction would be negligible. + continue + } + if f < 1 && scale[i] < 1 && f*scale[i] <= sfmin1 { + continue + } + if f > 1 && scale[i] > 1 && scale[i] >= sfmax1/f { + continue + } + + // Now balance. + scale[i] *= f + bi.Dscal(n-ilo, 1/f, a[i*lda+ilo:], 1) + bi.Dscal(ihi+1, f, a[i:], lda) + conv = false + } + } + return ilo, ihi +} diff --git a/lapack/native/dgebd2.go b/lapack/native/dgebd2.go new file mode 100644 index 00000000..3eea59de --- /dev/null +++ b/lapack/native/dgebd2.go @@ -0,0 +1,74 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dgebd2 reduces an m×n matrix A to upper or lower bidiagonal form by an orthogonal +// transformation. +// Q^T * A * P = B +// if m >= n, B is upper diagonal, otherwise B is lower bidiagonal. +// d is the diagonal, len = min(m,n) +// e is the off-diagonal len = min(m,n)-1 +// +// Dgebd2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebd2(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64) { + checkMatrix(m, n, a, lda) + if len(d) < min(m, n) { + panic(badD) + } + if len(e) < min(m, n)-1 { + panic(badE) + } + if len(tauQ) < min(m, n) { + panic(badTauQ) + } + if len(tauP) < min(m, n) { + panic(badTauP) + } + if len(work) < max(m, n) { + panic(badWork) + } + if m >= n { + for i := 0; i < n; i++ { + a[i*lda+i], tauQ[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min(i+1, m-1)*lda+i:], lda) + d[i] = a[i*lda+i] + a[i*lda+i] = 1 + // Apply H_i to A[i:m, i+1:n] from the left. + if i < n-1 { + impl.Dlarf(blas.Left, m-i, n-i-1, a[i*lda+i:], lda, tauQ[i], a[i*lda+i+1:], lda, work) + } + a[i*lda+i] = d[i] + if i < n-1 { + 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) + e[i] = a[i*lda+i+1] + a[i*lda+i+1] = 1 + 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) + a[i*lda+i+1] = e[i] + } else { + tauP[i] = 0 + } + } + return + } + for i := 0; i < m; i++ { + a[i*lda+i], tauP[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) + d[i] = a[i*lda+i] + a[i*lda+i] = 1 + if i < m-1 { + impl.Dlarf(blas.Right, m-i-1, n-i, a[i*lda+i:], 1, tauP[i], a[(i+1)*lda+i:], lda, work) + } + a[i*lda+i] = d[i] + if i < m-1 { + 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) + e[i] = a[(i+1)*lda+i] + a[(i+1)*lda+i] = 1 + 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) + a[(i+1)*lda+i] = e[i] + } else { + tauQ[i] = 0 + } + } +} diff --git a/lapack/native/dgebrd.go b/lapack/native/dgebrd.go new file mode 100644 index 00000000..446566fa --- /dev/null +++ b/lapack/native/dgebrd.go @@ -0,0 +1,150 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgebrd reduces a general m×n matrix A to upper or lower bidiagonal form B by +// an orthogonal transformation: +// Q^T * A * P = B. +// The diagonal elements of B are stored in d and the off-diagonal elements are stored +// in e. These are additionally stored along the diagonal of A and the off-diagonal +// of A. If m >= n B is an upper-bidiagonal matrix, and if m < n B is a +// lower-bidiagonal matrix. +// +// The remaining elements of A store the data needed to construct Q and P. +// The matrices Q and P are products of elementary reflectors +// if m >= n, Q = H_0 * H_1 * ... * H_{n-1}, +// P = G_0 * G_1 * ... * G_{n-2}, +// if m < n, Q = H_0 * H_1 * ... * H_{m-2}, +// P = G_0 * G_1 * ... * G_{m-1}, +// where +// H_i = I - tauQ[i] * v_i * v_i^T, +// G_i = I - tauP[i] * u_i * u_i^T. +// +// As an example, on exit the entries of A when m = 6, and n = 5 +// [ d e u1 u1 u1] +// [v1 d e u2 u2] +// [v1 v2 d e u3] +// [v1 v2 v3 d e] +// [v1 v2 v3 v4 d] +// [v1 v2 v3 v4 v5] +// and when m = 5, n = 6 +// [ d u1 u1 u1 u1 u1] +// [ e d u2 u2 u2 u2] +// [v1 e d u3 u3 u3] +// [v1 v2 e d u4 u4] +// [v1 v2 v3 e d u5] +// +// d, tauQ, and tauP must all have length at least min(m,n), and e must have +// length min(m,n) - 1, unless lwork is -1 when there is no check except for +// work which must have a length of at least one. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= max(1,m,n) or be -1 and this function will panic otherwise. +// Dgebrd is blocked decomposition, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgebrd, +// the optimal work length will be stored into work[0]. +// +// Dgebrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64, lwork int) { + checkMatrix(m, n, a, lda) + // Calculate optimal work. + nb := impl.Ilaenv(1, "DGEBRD", " ", m, n, -1, -1) + var lworkOpt int + if lwork == -1 { + if len(work) < 1 { + panic(badWork) + } + lworkOpt = ((m + n) * nb) + work[0] = float64(max(1, lworkOpt)) + return + } + minmn := min(m, n) + if len(d) < minmn { + panic(badD) + } + if len(e) < minmn-1 { + panic(badE) + } + if len(tauQ) < minmn { + panic(badTauQ) + } + if len(tauP) < minmn { + panic(badTauP) + } + ws := max(m, n) + if lwork < max(1, ws) { + panic(badWork) + } + if len(work) < lwork { + panic(badWork) + } + var nx int + if nb > 1 && nb < minmn { + nx = max(nb, impl.Ilaenv(3, "DGEBRD", " ", m, n, -1, -1)) + if nx < minmn { + ws = (m + n) * nb + if lwork < ws { + nbmin := impl.Ilaenv(2, "DGEBRD", " ", m, n, -1, -1) + if lwork >= (m+n)*nbmin { + nb = lwork / (m + n) + } else { + nb = minmn + nx = minmn + } + } + } + } else { + nx = minmn + } + bi := blas64.Implementation() + ldworkx := nb + ldworky := nb + var i int + // Netlib lapack has minmn - nx, but this makes the last nx rows (which by + // default is large) be unblocked. As written here, the blocking is more + // consistent. + for i = 0; i < minmn-nb; i += nb { + // Reduce rows and columns i:i+nb to bidiagonal form and return + // the matrices X and Y which are needed to update the unreduced + // part of the matrix. + // X is stored in the first m rows of work, y in the next rows. + x := work[:m*ldworkx] + y := work[m*ldworkx:] + impl.Dlabrd(m-i, n-i, nb, a[i*lda+i:], lda, + d[i:], e[i:], tauQ[i:], tauP[i:], + x, ldworkx, y, ldworky) + + // Update the trailing submatrix A[i+nb:m,i+nb:n], using an update + // of the form A := A - V*Y**T - X*U**T + bi.Dgemm(blas.NoTrans, blas.Trans, m-i-nb, n-i-nb, nb, + -1, a[(i+nb)*lda+i:], lda, y[nb*ldworky:], ldworky, + 1, a[(i+nb)*lda+i+nb:], lda) + + bi.Dgemm(blas.NoTrans, blas.NoTrans, m-i-nb, n-i-nb, nb, + -1, x[nb*ldworkx:], ldworkx, a[i*lda+i+nb:], lda, + 1, a[(i+nb)*lda+i+nb:], lda) + + // Copy diagonal and off-diagonal elements of B back into A. + if m >= n { + for j := i; j < i+nb; j++ { + a[j*lda+j] = d[j] + a[j*lda+j+1] = e[j] + } + } else { + for j := i; j < i+nb; j++ { + a[j*lda+j] = d[j] + a[(j+1)*lda+j] = e[j] + } + } + } + // Use unblocked code to reduce the remainder of the matrix. + impl.Dgebd2(m-i, n-i, a[i*lda+i:], lda, d[i:], e[i:], tauQ[i:], tauP[i:], work) + work[0] = float64(lworkOpt) +} diff --git a/lapack/native/dgecon.go b/lapack/native/dgecon.go new file mode 100644 index 00000000..588cd39c --- /dev/null +++ b/lapack/native/dgecon.go @@ -0,0 +1,81 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgecon estimates the reciprocal of the condition number of the n×n matrix A +// given the LU decomposition of the matrix. The condition number computed may +// be based on the 1-norm or the ∞-norm. +// +// The slice a contains the result of the LU decomposition of A as computed by Dgetrf. +// +// anorm is the corresponding 1-norm or ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 4*n and Dgecon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Dgecon will panic otherwise. +func (impl Implementation) Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { + checkMatrix(n, n, a, lda) + if norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum { + panic(badNorm) + } + if len(work) < 4*n { + panic(badWork) + } + if len(iwork) < n { + panic(badWork) + } + + if n == 0 { + return 1 + } else if anorm == 0 { + return 0 + } + + bi := blas64.Implementation() + var rcond, ainvnm float64 + var kase int + var normin bool + isave := new([3]int) + onenrm := norm == lapack.MaxColumnSum + smlnum := dlamchS + kase1 := 2 + if onenrm { + kase1 = 1 + } + for { + ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) + if kase == 0 { + if ainvnm != 0 { + rcond = (1 / ainvnm) / anorm + } + return rcond + } + var sl, su float64 + if kase == kase1 { + sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.Unit, normin, n, a, lda, work, work[2*n:]) + su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) + } else { + su = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) + sl = impl.Dlatrs(blas.Lower, blas.Trans, blas.Unit, normin, n, a, lda, work, work[2*n:]) + } + scale := sl * su + normin = true + if scale != 1 { + ix := bi.Idamax(n, work, 1) + if scale == 0 || scale < math.Abs(work[ix])*smlnum { + return rcond + } + impl.Drscl(n, scale, work, 1) + } + } +} diff --git a/lapack/native/dgeev.go b/lapack/native/dgeev.go new file mode 100644 index 00000000..63182fa9 --- /dev/null +++ b/lapack/native/dgeev.go @@ -0,0 +1,284 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgeev computes the eigenvalues and, optionally, the left and/or right +// eigenvectors for an n×n real nonsymmetric matrix A. +// +// The right eigenvector v_j of A corresponding to an eigenvalue λ_j +// is defined by +// A v_j = λ_j v_j, +// and the left eigenvector u_j corresponding to an eigenvalue λ_j is defined by +// u_j^H A = λ_j u_j^H, +// where u_j^H is the conjugate transpose of u_j. +// +// On return, A will be overwritten and the left and right eigenvectors will be +// stored, respectively, in the columns of the n×n matrices VL and VR in the +// same order as their eigenvalues. If the j-th eigenvalue is real, then +// u_j = VL[:,j], +// v_j = VR[:,j], +// and if it is not real, then j and j+1 form a complex conjugate pair and the +// eigenvectors can be recovered as +// u_j = VL[:,j] + i*VL[:,j+1], +// u_{j+1} = VL[:,j] - i*VL[:,j+1], +// v_j = VR[:,j] + i*VR[:,j+1], +// v_{j+1} = VR[:,j] - i*VR[:,j+1], +// where i is the imaginary unit. The computed eigenvectors are normalized to +// have Euclidean norm equal to 1 and largest component real. +// +// Left eigenvectors will be computed only if jobvl == lapack.ComputeLeftEV, +// otherwise jobvl must be lapack.None. Right eigenvectors will be computed +// only if jobvr == lapack.ComputeRightEV, otherwise jobvr must be lapack.None. +// For other values of jobvl and jobvr Dgeev will panic. +// +// wr and wi contain the real and imaginary parts, respectively, of the computed +// eigenvalues. Complex conjugate pairs of eigenvalues appear consecutively with +// the eigenvalue having the positive imaginary part first. +// wr and wi must have length n, and Dgeev will panic otherwise. +// +// work must have length at least lwork and lwork must be at least max(1,4*n) if +// the left or right eigenvectors are computed, and at least max(1,3*n) if no +// eigenvectors are computed. For good performance, lwork must generally be +// larger. On return, optimal value of lwork will be stored in work[0]. +// +// If lwork == -1, instead of performing Dgeev, the function only calculates the +// optimal vaule of lwork and stores it into work[0]. +// +// On return, first is the index of the first valid eigenvalue. If first == 0, +// all eigenvalues and eigenvectors have been computed. If first is positive, +// Dgeev failed to compute all the eigenvalues, no eigenvectors have been +// computed and wr[first:] and wi[first:] contain those eigenvalues which have +// converged. +func (impl Implementation) Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, n int, a []float64, lda int, wr, wi []float64, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) (first int) { + var wantvl bool + switch jobvl { + default: + panic("lapack: invalid LeftEVJob") + case lapack.ComputeLeftEV: + wantvl = true + case lapack.None: + } + var wantvr bool + switch jobvr { + default: + panic("lapack: invalid RightEVJob") + case lapack.ComputeRightEV: + wantvr = true + case lapack.None: + } + switch { + case n < 0: + panic(nLT0) + case len(work) < lwork: + panic(shortWork) + } + var minwrk int + if wantvl || wantvr { + minwrk = max(1, 4*n) + } else { + minwrk = max(1, 3*n) + } + if lwork != -1 { + checkMatrix(n, n, a, lda) + if wantvl { + checkMatrix(n, n, vl, ldvl) + } + if wantvr { + checkMatrix(n, n, vr, ldvr) + } + switch { + case len(wr) != n: + panic("lapack: bad length of wr") + case len(wi) != n: + panic("lapack: bad length of wi") + case lwork < minwrk: + panic(badWork) + } + } + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return 0 + } + + maxwrk := 2*n + n*impl.Ilaenv(1, "DGEHRD", " ", n, 1, n, 0) + if wantvl || wantvr { + maxwrk = max(maxwrk, 2*n+(n-1)*impl.Ilaenv(1, "DORGHR", " ", n, 1, n, -1)) + impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.OriginalEV, n, 0, n-1, + nil, 1, nil, nil, nil, 1, work, -1) + maxwrk = max(maxwrk, max(n+1, n+int(work[0]))) + side := lapack.LeftEV + if wantvr { + side = lapack.RightEV + } + impl.Dtrevc3(side, lapack.AllEVMulQ, nil, n, nil, 1, nil, 1, nil, 1, + n, work, -1) + maxwrk = max(maxwrk, n+int(work[0])) + maxwrk = max(maxwrk, 4*n) + } else { + impl.Dhseqr(lapack.EigenvaluesOnly, lapack.None, n, 0, n-1, + nil, 1, nil, nil, nil, 1, work, -1) + maxwrk = max(maxwrk, max(n+1, n+int(work[0]))) + } + maxwrk = max(maxwrk, minwrk) + + if lwork == -1 { + work[0] = float64(maxwrk) + return 0 + } + + // Get machine constants. + smlnum := math.Sqrt(dlamchS) / dlamchP + bignum := 1 / smlnum + + // Scale A if max element outside range [smlnum,bignum]. + anrm := impl.Dlange(lapack.MaxAbs, n, n, a, lda, nil) + var scalea bool + var cscale float64 + if 0 < anrm && anrm < smlnum { + scalea = true + cscale = smlnum + } else if anrm > bignum { + scalea = true + cscale = bignum + } + if scalea { + impl.Dlascl(lapack.General, 0, 0, anrm, cscale, n, n, a, lda) + } + + // Balance the matrix. + workbal := work[:n] + ilo, ihi := impl.Dgebal(lapack.PermuteScale, n, a, lda, workbal) + + // Reduce to upper Hessenberg form. + iwrk := 2 * n + tau := work[n : iwrk-1] + impl.Dgehrd(n, ilo, ihi, a, lda, tau, work[iwrk:], lwork-iwrk) + + var side lapack.EVSide + if wantvl { + side = lapack.LeftEV + // Copy Householder vectors to VL. + impl.Dlacpy(blas.Lower, n, n, a, lda, vl, ldvl) + // Generate orthogonal matrix in VL. + impl.Dorghr(n, ilo, ihi, vl, ldvl, tau, work[iwrk:], lwork-iwrk) + // Perform QR iteration, accumulating Schur vectors in VL. + iwrk = n + first = impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.OriginalEV, n, ilo, ihi, + a, lda, wr, wi, vl, ldvl, work[iwrk:], lwork-iwrk) + if wantvr { + // Want left and right eigenvectors. + // Copy Schur vectors to VR. + side = lapack.RightLeftEV + impl.Dlacpy(blas.All, n, n, vl, ldvl, vr, ldvr) + } + } else if wantvr { + side = lapack.RightEV + // Copy Householder vectors to VR. + impl.Dlacpy(blas.Lower, n, n, a, lda, vr, ldvr) + // Generate orthogonal matrix in VR. + impl.Dorghr(n, ilo, ihi, vr, ldvr, tau, work[iwrk:], lwork-iwrk) + // Perform QR iteration, accumulating Schur vectors in VR. + iwrk = n + first = impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.OriginalEV, n, ilo, ihi, + a, lda, wr, wi, vr, ldvr, work[iwrk:], lwork-iwrk) + } else { + // Compute eigenvalues only. + iwrk = n + first = impl.Dhseqr(lapack.EigenvaluesOnly, lapack.None, n, ilo, ihi, + a, lda, wr, wi, nil, 1, work[iwrk:], lwork-iwrk) + } + + if first > 0 { + if scalea { + // Undo scaling. + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wr[first:], 1) + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wi[first:], 1) + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, ilo, 1, wr, 1) + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, ilo, 1, wi, 1) + } + work[0] = float64(maxwrk) + return first + } + + if wantvl || wantvr { + // Compute left and/or right eigenvectors. + impl.Dtrevc3(side, lapack.AllEVMulQ, nil, n, + a, lda, vl, ldvl, vr, ldvr, n, work[iwrk:], lwork-iwrk) + } + bi := blas64.Implementation() + if wantvl { + // Undo balancing of left eigenvectors. + impl.Dgebak(lapack.PermuteScale, lapack.LeftEV, n, ilo, ihi, workbal, n, vl, ldvl) + // Normalize left eigenvectors and make largest component real. + for i, wii := range wi { + if wii < 0 { + continue + } + if wii == 0 { + scl := 1 / bi.Dnrm2(n, vl[i:], ldvl) + bi.Dscal(n, scl, vl[i:], ldvl) + continue + } + scl := 1 / impl.Dlapy2(bi.Dnrm2(n, vl[i:], ldvl), bi.Dnrm2(n, vl[i+1:], ldvl)) + bi.Dscal(n, scl, vl[i:], ldvl) + bi.Dscal(n, scl, vl[i+1:], ldvl) + for k := 0; k < n; k++ { + vi := vl[k*ldvl+i] + vi1 := vl[k*ldvl+i+1] + work[iwrk+k] = vi*vi + vi1*vi1 + } + k := bi.Idamax(n, work[iwrk:iwrk+n], 1) + cs, sn, _ := impl.Dlartg(vl[k*ldvl+i], vl[k*ldvl+i+1]) + bi.Drot(n, vl[i:], ldvl, vl[i+1:], ldvl, cs, sn) + vl[k*ldvl+i+1] = 0 + } + } + if wantvr { + // Undo balancing of right eigenvectors. + impl.Dgebak(lapack.PermuteScale, lapack.RightEV, n, ilo, ihi, workbal, n, vr, ldvr) + // Normalize right eigenvectors and make largest component real. + for i, wii := range wi { + if wii < 0 { + continue + } + if wii == 0 { + scl := 1 / bi.Dnrm2(n, vr[i:], ldvr) + bi.Dscal(n, scl, vr[i:], ldvr) + continue + } + scl := 1 / impl.Dlapy2(bi.Dnrm2(n, vr[i:], ldvr), bi.Dnrm2(n, vr[i+1:], ldvr)) + bi.Dscal(n, scl, vr[i:], ldvr) + bi.Dscal(n, scl, vr[i+1:], ldvr) + for k := 0; k < n; k++ { + vi := vr[k*ldvr+i] + vi1 := vr[k*ldvr+i+1] + work[iwrk+k] = vi*vi + vi1*vi1 + } + k := bi.Idamax(n, work[iwrk:iwrk+n], 1) + cs, sn, _ := impl.Dlartg(vr[k*ldvr+i], vr[k*ldvr+i+1]) + bi.Drot(n, vr[i:], ldvr, vr[i+1:], ldvr, cs, sn) + vr[k*ldvr+i+1] = 0 + } + } + + if scalea { + // Undo scaling. + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wr[first:], 1) + impl.Dlascl(lapack.General, 0, 0, cscale, anrm, n-first, 1, wi[first:], 1) + } + + work[0] = float64(maxwrk) + return first +} diff --git a/lapack/native/dgehd2.go b/lapack/native/dgehd2.go new file mode 100644 index 00000000..946d2ec1 --- /dev/null +++ b/lapack/native/dgehd2.go @@ -0,0 +1,84 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dgehd2 reduces a block of a general n×n matrix A to upper Hessenberg form H +// by an orthogonal similarity transformation Q^T * A * Q = H. +// +// The matrix Q is represented as a product of (ihi-ilo) elementary +// reflectors +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// Each H_i has the form +// H_i = I - tau[i] * v * v^T +// where v is a real vector with v[0:i+1] = 0, v[i+1] = 1 and v[ihi+1:n] = 0. +// v[i+2:ihi+1] is stored on exit in A[i+2:ihi+1,i]. +// +// On entry, a contains the n×n general matrix to be reduced. On return, the +// upper triangle and the first subdiagonal of A are overwritten with the upper +// Hessenberg matrix H, and the elements below the first subdiagonal, with the +// slice tau, represent the orthogonal matrix Q as a product of elementary +// reflectors. +// +// The contents of A are illustrated by the following example, with n = 7, ilo = +// 1 and ihi = 5. +// On entry, +// [ a a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a ] +// on return, +// [ a a h h h h a ] +// [ a h h h h a ] +// [ h h h h h h ] +// [ v1 h h h h h ] +// [ v1 v2 h h h h ] +// [ v1 v2 v3 h h h ] +// [ a ] +// where a denotes an element of the original matrix A, h denotes a +// modified element of the upper Hessenberg matrix H, and vi denotes an +// element of the vector defining H_i. +// +// ilo and ihi determine the block of A that will be reduced to upper Hessenberg +// form. It must hold that 0 <= ilo <= ihi <= max(0, n-1), otherwise Dgehd2 will +// panic. +// +// On return, tau will contain the scalar factors of the elementary reflectors. +// It must have length equal to n-1, otherwise Dgehd2 will panic. +// +// work must have length at least n, otherwise Dgehd2 will panic. +// +// Dgehd2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgehd2(n, ilo, ihi int, a []float64, lda int, tau, work []float64) { + checkMatrix(n, n, a, lda) + switch { + case ilo < 0 || ilo > max(0, n-1): + panic(badIlo) + case ihi < min(ilo, n-1) || ihi >= n: + panic(badIhi) + case len(tau) != n-1: + panic(badTau) + case len(work) < n: + panic(badWork) + } + + for i := ilo; i < ihi; i++ { + // Compute elementary reflector H_i to annihilate A[i+2:ihi+1,i]. + var aii float64 + aii, tau[i] = impl.Dlarfg(ihi-i, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) + a[(i+1)*lda+i] = 1 + + // Apply H_i to A[0:ihi+1,i+1:ihi+1] from the right. + impl.Dlarf(blas.Right, ihi+1, ihi-i, a[(i+1)*lda+i:], lda, tau[i], a[i+1:], lda, work) + + // Apply H_i to A[i+1:ihi+1,i+1:n] from the left. + impl.Dlarf(blas.Left, ihi-i, n-i-1, a[(i+1)*lda+i:], lda, tau[i], a[(i+1)*lda+i+1:], lda, work) + a[(i+1)*lda+i] = aii + } +} diff --git a/lapack/native/dgehrd.go b/lapack/native/dgehrd.go new file mode 100644 index 00000000..e388d2b6 --- /dev/null +++ b/lapack/native/dgehrd.go @@ -0,0 +1,183 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dgehrd reduces a block of a real n×n general matrix A to upper Hessenberg +// form H by an orthogonal similarity transformation Q^T * A * Q = H. +// +// The matrix Q is represented as a product of (ihi-ilo) elementary +// reflectors +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// Each H_i has the form +// H_i = I - tau[i] * v * v^T +// where v is a real vector with v[0:i+1] = 0, v[i+1] = 1 and v[ihi+1:n] = 0. +// v[i+2:ihi+1] is stored on exit in A[i+2:ihi+1,i]. +// +// On entry, a contains the n×n general matrix to be reduced. On return, the +// upper triangle and the first subdiagonal of A will be overwritten with the +// upper Hessenberg matrix H, and the elements below the first subdiagonal, with +// the slice tau, represent the orthogonal matrix Q as a product of elementary +// reflectors. +// +// The contents of a are illustrated by the following example, with n = 7, ilo = +// 1 and ihi = 5. +// On entry, +// [ a a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a a a a a a ] +// [ a ] +// on return, +// [ a a h h h h a ] +// [ a h h h h a ] +// [ h h h h h h ] +// [ v1 h h h h h ] +// [ v1 v2 h h h h ] +// [ v1 v2 v3 h h h ] +// [ a ] +// where a denotes an element of the original matrix A, h denotes a +// modified element of the upper Hessenberg matrix H, and vi denotes an +// element of the vector defining H_i. +// +// ilo and ihi determine the block of A that will be reduced to upper Hessenberg +// form. It must hold that 0 <= ilo <= ihi < n if n > 0, and ilo == 0 and ihi == +// -1 if n == 0, otherwise Dgehrd will panic. +// +// On return, tau will contain the scalar factors of the elementary reflectors. +// Elements tau[:ilo] and tau[ihi:] will be set to zero. tau must have length +// equal to n-1 if n > 0, otherwise Dgehrd will panic. +// +// work must have length at least lwork and lwork must be at least max(1,n), +// otherwise Dgehrd will panic. On return, work[0] contains the optimal value of +// lwork. +// +// If lwork == -1, instead of performing Dgehrd, only the optimal value of lwork +// will be stored in work[0]. +// +// Dgehrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgehrd(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) { + switch { + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case lwork < max(1, n) && lwork != -1: + panic(badWork) + case len(work) < lwork: + panic(shortWork) + } + if lwork != -1 { + checkMatrix(n, n, a, lda) + if len(tau) != n-1 && n > 0 { + panic(badTau) + } + } + + const ( + nbmax = 64 + ldt = nbmax + 1 + tsize = ldt * nbmax + ) + // Compute the workspace requirements. + nb := min(nbmax, impl.Ilaenv(1, "DGEHRD", " ", n, ilo, ihi, -1)) + lwkopt := n*nb + tsize + if lwork == -1 { + work[0] = float64(lwkopt) + return + } + + // Set tau[:ilo] and tau[ihi:] to zero. + for i := 0; i < ilo; i++ { + tau[i] = 0 + } + for i := ihi; i < n-1; i++ { + tau[i] = 0 + } + + // Quick return if possible. + nh := ihi - ilo + 1 + if nh <= 1 { + work[0] = 1 + return + } + + // Determine the block size. + nbmin := 2 + var nx int + if 1 < nb && nb < nh { + // Determine when to cross over from blocked to unblocked code + // (last block is always handled by unblocked code). + nx = max(nb, impl.Ilaenv(3, "DGEHRD", " ", n, ilo, ihi, -1)) + if nx < nh { + // Determine if workspace is large enough for blocked code. + if lwork < n*nb+tsize { + // Not enough workspace to use optimal nb: + // determine the minimum value of nb, and reduce + // nb or force use of unblocked code. + nbmin = max(2, impl.Ilaenv(2, "DGEHRD", " ", n, ilo, ihi, -1)) + if lwork >= n*nbmin+tsize { + nb = (lwork - tsize) / n + } else { + nb = 1 + } + } + } + } + ldwork := nb // work is used as an n×nb matrix. + + var i int + if nb < nbmin || nh <= nb { + // Use unblocked code below. + i = ilo + } else { + // Use blocked code. + bi := blas64.Implementation() + iwt := n * nb // Size of the matrix Y and index where the matrix T starts in work. + for i = ilo; i < ihi-nx; i += nb { + ib := min(nb, ihi-i) + + // Reduce columns [i:i+ib] to Hessenberg form, returning the + // matrices V and T of the block reflector H = I - V*T*V^T + // which performs the reduction, and also the matrix Y = A*V*T. + impl.Dlahr2(ihi+1, i+1, ib, a[i:], lda, tau[i:], work[iwt:], ldt, work, ldwork) + + // Apply the block reflector H to A[:ihi+1,i+ib:ihi+1] from the + // right, computing A := A - Y * V^T. V[i+ib,i+ib-1] must be set + // to 1. + ei := a[(i+ib)*lda+i+ib-1] + a[(i+ib)*lda+i+ib-1] = 1 + bi.Dgemm(blas.NoTrans, blas.Trans, ihi+1, ihi-i-ib+1, ib, + -1, work, ldwork, + a[(i+ib)*lda+i:], lda, + 1, a[i+ib:], lda) + a[(i+ib)*lda+i+ib-1] = ei + + // Apply the block reflector H to A[0:i+1,i+1:i+ib-1] from the + // right. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, i+1, ib-1, + 1, a[(i+1)*lda+i:], lda, work, ldwork) + for j := 0; j <= ib-2; j++ { + bi.Daxpy(i+1, -1, work[j:], ldwork, a[i+j+1:], lda) + } + + // Apply the block reflector H to A[i+1:ihi+1,i+ib:n] from the + // left. + impl.Dlarfb(blas.Left, blas.Trans, lapack.Forward, lapack.ColumnWise, + ihi-i, n-i-ib, ib, + a[(i+1)*lda+i:], lda, work[iwt:], ldt, a[(i+1)*lda+i+ib:], lda, work, ldwork) + } + } + // Use unblocked code to reduce the rest of the matrix. + impl.Dgehd2(n, i, ihi, a, lda, tau, work) + work[0] = float64(lwkopt) +} diff --git a/lapack/native/dgelq2.go b/lapack/native/dgelq2.go new file mode 100644 index 00000000..9e735e81 --- /dev/null +++ b/lapack/native/dgelq2.go @@ -0,0 +1,49 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dgelq2 computes the LQ factorization of the m×n matrix A. +// +// In an LQ factorization, L is a lower triangular m×n matrix, and Q is an n×n +// orthonormal matrix. +// +// a is modified to contain the information to construct L and Q. +// The lower triangle of a contains the matrix L. The upper triangular elements +// (not including the diagonal) contain the elementary reflectors. tau is modified +// to contain the reflector scales. tau must have length of at least k = min(m,n) +// and this function will panic otherwise. +// +// See Dgeqr2 for a description of the elementary reflectors and orthonormal +// matrix Q. Q is constructed as a product of these elementary reflectors, +// Q = H_{k-1} * ... * H_1 * H_0. +// +// work is temporary storage of length at least m and this function will panic otherwise. +// +// Dgelq2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgelq2(m, n int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + if len(work) < m { + panic(badWork) + } + for i := 0; i < k; i++ { + a[i*lda+i], tau[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) + if i < m-1 { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(blas.Right, m-i-1, n-i, + a[i*lda+i:], 1, + tau[i], + a[(i+1)*lda+i:], lda, + work) + a[i*lda+i] = aii + } + } +} diff --git a/lapack/native/dgelqf.go b/lapack/native/dgelqf.go new file mode 100644 index 00000000..ad97cf25 --- /dev/null +++ b/lapack/native/dgelqf.go @@ -0,0 +1,84 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dgelqf computes the LQ factorization of the m×n matrix A using a blocked +// algorithm. See the documentation for Dgelq2 for a description of the +// parameters at entry and exit. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m, and this function will panic otherwise. +// Dgelqf is a blocked LQ factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgelqf, +// the optimal work length will be stored into work[0]. +// +// tau must have length at least min(m,n), and this function will panic otherwise. +func (impl Implementation) Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { + nb := impl.Ilaenv(1, "DGELQF", " ", m, n, -1, -1) + lworkopt := m * max(nb, 1) + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + checkMatrix(m, n, a, lda) + if len(work) < lwork { + panic(shortWork) + } + if lwork < m { + panic(badWork) + } + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + if k == 0 { + return + } + // Find the optimal blocking size based on the size of available memory + // and optimal machine parameters. + nbmin := 2 + var nx int + iws := m + ldwork := nb + if nb > 1 && k > nb { + nx = max(0, impl.Ilaenv(3, "DGELQF", " ", m, n, -1, -1)) + if nx < k { + iws = m * nb + if lwork < iws { + nb = lwork / m + nbmin = max(2, impl.Ilaenv(2, "DGELQF", " ", m, n, -1, -1)) + } + } + } + // Computed blocked LQ factorization. + var i int + if nb >= nbmin && nb < k && nx < k { + for i = 0; i < k-nx; i += nb { + ib := min(k-i, nb) + impl.Dgelq2(ib, n-i, a[i*lda+i:], lda, tau[i:], work) + if i+ib < m { + impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + work, ldwork) + impl.Dlarfb(blas.Right, blas.NoTrans, lapack.Forward, lapack.RowWise, + m-i-ib, n-i, ib, + a[i*lda+i:], lda, + work, ldwork, + a[(i+ib)*lda+i:], lda, + work[ib*ldwork:], ldwork) + } + } + } + // Perform unblocked LQ factorization on the remainder. + if i < k { + impl.Dgelq2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work) + } +} diff --git a/lapack/native/dgels.go b/lapack/native/dgels.go new file mode 100644 index 00000000..75bad43d --- /dev/null +++ b/lapack/native/dgels.go @@ -0,0 +1,200 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dgels finds a minimum-norm solution based on the matrices A and B using the +// QR or LQ factorization. Dgels returns false if the matrix +// A is singular, and true if this solution was successfully found. +// +// The minimization problem solved depends on the input parameters. +// +// 1. If m >= n and trans == blas.NoTrans, Dgels finds X such that || A*X - B||_2 +// is minimized. +// 2. If m < n and trans == blas.NoTrans, Dgels finds the minimum norm solution of +// A * X = B. +// 3. If m >= n and trans == blas.Trans, Dgels finds the minimum norm solution of +// A^T * X = B. +// 4. If m < n and trans == blas.Trans, Dgels finds X such that || A*X - B||_2 +// is minimized. +// Note that the least-squares solutions (cases 1 and 3) perform the minimization +// per column of B. This is not the same as finding the minimum-norm matrix. +// +// The matrix A is a general matrix of size m×n and is modified during this call. +// The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry, +// the elements of b specify the input matrix B. B has size m×nrhs if +// trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the +// leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans, +// this submatrix is of size n×nrhs, and of size m×nrhs otherwise. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic +// otherwise. A longer work will enable blocked algorithms to be called. +// In the special case that lwork == -1, work[0] will be set to the optimal working +// length. +func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool { + notran := trans == blas.NoTrans + checkMatrix(m, n, a, lda) + mn := min(m, n) + checkMatrix(max(m, n), nrhs, b, ldb) + + // Find optimal block size. + tpsd := true + if notran { + tpsd = false + } + var nb int + if m >= n { + nb = impl.Ilaenv(1, "DGEQRF", " ", m, n, -1, -1) + if tpsd { + nb = max(nb, impl.Ilaenv(1, "DORMQR", "LN", m, nrhs, n, -1)) + } else { + nb = max(nb, impl.Ilaenv(1, "DORMQR", "LT", m, nrhs, n, -1)) + } + } else { + nb = impl.Ilaenv(1, "DGELQF", " ", m, n, -1, -1) + if tpsd { + nb = max(nb, impl.Ilaenv(1, "DORMLQ", "LT", n, nrhs, m, -1)) + } else { + nb = max(nb, impl.Ilaenv(1, "DORMLQ", "LN", n, nrhs, m, -1)) + } + } + if lwork == -1 { + work[0] = float64(max(1, mn+max(mn, nrhs)*nb)) + return true + } + + if len(work) < lwork { + panic(shortWork) + } + if lwork < mn+max(mn, nrhs) { + panic(badWork) + } + if m == 0 || n == 0 || nrhs == 0 { + impl.Dlaset(blas.All, max(m, n), nrhs, 0, 0, b, ldb) + return true + } + + // Scale the input matrices if they contain extreme values. + smlnum := dlamchS / dlamchP + bignum := 1 / smlnum + anrm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, nil) + var iascl int + if anrm > 0 && anrm < smlnum { + impl.Dlascl(lapack.General, 0, 0, anrm, smlnum, m, n, a, lda) + iascl = 1 + } else if anrm > bignum { + impl.Dlascl(lapack.General, 0, 0, anrm, bignum, m, n, a, lda) + } else if anrm == 0 { + // Matrix is all zeros. + impl.Dlaset(blas.All, max(m, n), nrhs, 0, 0, b, ldb) + return true + } + brow := m + if tpsd { + brow = n + } + bnrm := impl.Dlange(lapack.MaxAbs, brow, nrhs, b, ldb, nil) + ibscl := 0 + if bnrm > 0 && bnrm < smlnum { + impl.Dlascl(lapack.General, 0, 0, bnrm, smlnum, brow, nrhs, b, ldb) + ibscl = 1 + } else if bnrm > bignum { + impl.Dlascl(lapack.General, 0, 0, bnrm, bignum, brow, nrhs, b, ldb) + ibscl = 2 + } + + // Solve the minimization problem using a QR or an LQ decomposition. + var scllen int + if m >= n { + impl.Dgeqrf(m, n, a, lda, work, work[mn:], lwork-mn) + if !tpsd { + impl.Dormqr(blas.Left, blas.Trans, m, nrhs, n, + a, lda, + work[:n], + b, ldb, + work[mn:], lwork-mn) + ok := impl.Dtrtrs(blas.Upper, blas.NoTrans, blas.NonUnit, n, nrhs, + a, lda, + b, ldb) + if !ok { + return false + } + scllen = n + } else { + ok := impl.Dtrtrs(blas.Upper, blas.Trans, blas.NonUnit, n, nrhs, + a, lda, + b, ldb) + if !ok { + return false + } + for i := n; i < m; i++ { + for j := 0; j < nrhs; j++ { + b[i*ldb+j] = 0 + } + } + impl.Dormqr(blas.Left, blas.NoTrans, m, nrhs, n, + a, lda, + work[:n], + b, ldb, + work[mn:], lwork-mn) + scllen = m + } + } else { + impl.Dgelqf(m, n, a, lda, work, work[mn:], lwork-mn) + if !tpsd { + ok := impl.Dtrtrs(blas.Lower, blas.NoTrans, blas.NonUnit, + m, nrhs, + a, lda, + b, ldb) + if !ok { + return false + } + for i := m; i < n; i++ { + for j := 0; j < nrhs; j++ { + b[i*ldb+j] = 0 + } + } + impl.Dormlq(blas.Left, blas.Trans, n, nrhs, m, + a, lda, + work, + b, ldb, + work[mn:], lwork-mn) + scllen = n + } else { + impl.Dormlq(blas.Left, blas.NoTrans, n, nrhs, m, + a, lda, + work, + b, ldb, + work[mn:], lwork-mn) + ok := impl.Dtrtrs(blas.Lower, blas.Trans, blas.NonUnit, + m, nrhs, + a, lda, + b, ldb) + if !ok { + return false + } + } + } + + // Adjust answer vector based on scaling. + if iascl == 1 { + impl.Dlascl(lapack.General, 0, 0, anrm, smlnum, scllen, nrhs, b, ldb) + } + if iascl == 2 { + impl.Dlascl(lapack.General, 0, 0, anrm, bignum, scllen, nrhs, b, ldb) + } + if ibscl == 1 { + impl.Dlascl(lapack.General, 0, 0, smlnum, bnrm, scllen, nrhs, b, ldb) + } + if ibscl == 2 { + impl.Dlascl(lapack.General, 0, 0, bignum, bnrm, scllen, nrhs, b, ldb) + } + return true +} diff --git a/lapack/native/dgeql2.go b/lapack/native/dgeql2.go new file mode 100644 index 00000000..c29dd2f0 --- /dev/null +++ b/lapack/native/dgeql2.go @@ -0,0 +1,45 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dgeql2 computes the QL factorization of the m×n matrix A. That is, Dgeql2 +// computes Q and L such that +// A = Q * L +// where Q is an m×m orthonormal matrix and L is a lower trapezoidal matrix. +// +// Q is represented as a product of elementary reflectors, +// Q = H_{k-1} * ... * H_1 * H_0 +// where k = min(m,n) and each H_i has the form +// H_i = I - tau[i] * v_i * v_i^T +// 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 +// exit in A[0:m-k+i-1, n-k+i]. +// +// tau must have length at least min(m,n), and Dgeql2 will panic otherwise. +// +// work is temporary memory storage and must have length at least n. +// +// Dgeql2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgeql2(m, n int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + if len(tau) < min(m, n) { + panic(badTau) + } + if len(work) < n { + panic(badWork) + } + k := min(m, n) + var aii float64 + for i := k - 1; i >= 0; i-- { + // Generate elementary reflector H_i to annihilate A[0:m-k+i-1, n-k+i]. + aii, tau[i] = impl.Dlarfg(m-k+i+1, a[(m-k+i)*lda+n-k+i], a[n-k+i:], lda) + + // Apply H_i to A[0:m-k+i, 0:n-k+i-1] from the left. + a[(m-k+i)*lda+n-k+i] = 1 + impl.Dlarf(blas.Left, m-k+i+1, n-k+i, a[n-k+i:], lda, tau[i], a, lda, work) + a[(m-k+i)*lda+n-k+i] = aii + } +} diff --git a/lapack/native/dgeqp3.go b/lapack/native/dgeqp3.go new file mode 100644 index 00000000..39ce7d4e --- /dev/null +++ b/lapack/native/dgeqp3.go @@ -0,0 +1,174 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgeqp3 computes a QR factorization with column pivoting of the +// m×n matrix A: A*P = Q*R using Level 3 BLAS. +// +// The matrix Q is represented as a product of elementary reflectors +// Q = H_0 H_1 . . . H_{k-1}, where k = min(m,n). +// Each H_i has the form +// H_i = I - tau * v * v^T +// where tau and v are real vectors with v[0:i-1] = 0 and v[i] = 1; +// v[i:m] is stored on exit in A[i:m, i], and tau in tau[i]. +// +// jpvt specifies a column pivot to be applied to A. If +// jpvt[j] is at least zero, the jth column of A is permuted +// to the front of A*P (a leading column), if jpvt[j] is -1 +// the jth column of A is a free column. If jpvt[j] < -1, Dgeqp3 +// will panic. On return, jpvt holds the permutation that was +// applied; the jth column of A*P was the jpvt[j] column of A. +// jpvt must have length n or Dgeqp3 will panic. +// +// tau holds the scalar factors of the elementary reflectors. +// It must have length min(m, n), otherwise Dgeqp3 will panic. +// +// work must have length at least max(1,lwork), and lwork must be at least +// 3*n+1, otherwise Dgeqp3 will panic. For optimal performance lwork must +// be at least 2*n+(n+1)*nb, where nb is the optimal blocksize. On return, +// work[0] will contain the optimal value of lwork. +// +// If lwork == -1, instead of performing Dgeqp3, only the optimal value of lwork +// will be stored in work[0]. +// +// Dgeqp3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgeqp3(m, n int, a []float64, lda int, jpvt []int, tau, work []float64, lwork int) { + const ( + inb = 1 + inbmin = 2 + ixover = 3 + ) + checkMatrix(m, n, a, lda) + + if len(jpvt) != n { + panic(badIpiv) + } + for _, v := range jpvt { + if v < -1 || n <= v { + panic("lapack: jpvt element out of range") + } + } + minmn := min(m, n) + if len(work) < max(1, lwork) { + panic(badWork) + } + + var iws, lwkopt, nb int + if minmn == 0 { + iws = 1 + lwkopt = 1 + } else { + iws = 3*n + 1 + nb = impl.Ilaenv(inb, "DGEQRF", " ", m, n, -1, -1) + lwkopt = 2*n + (n+1)*nb + } + work[0] = float64(lwkopt) + + if lwork == -1 { + return + } + + if len(tau) < minmn { + panic(badTau) + } + + bi := blas64.Implementation() + + // Move initial columns up front. + var nfxd int + for j := 0; j < n; j++ { + if jpvt[j] == -1 { + jpvt[j] = j + continue + } + if j != nfxd { + bi.Dswap(m, a[j:], lda, a[nfxd:], lda) + jpvt[j], jpvt[nfxd] = jpvt[nfxd], j + } else { + jpvt[j] = j + } + nfxd++ + } + + // Factorize nfxd columns. + // + // Compute the QR factorization of nfxd columns and update remaining columns. + if nfxd > 0 { + na := min(m, nfxd) + impl.Dgeqrf(m, na, a, lda, tau, work, lwork) + iws = max(iws, int(work[0])) + if na < n { + impl.Dormqr(blas.Left, blas.Trans, m, n-na, na, a, lda, tau[:na], a[na:], lda, + work, lwork) + iws = max(iws, int(work[0])) + } + } + + if nfxd >= minmn { + work[0] = float64(iws) + return + } + + // Factorize free columns. + sm := m - nfxd + sn := n - nfxd + sminmn := minmn - nfxd + + // Determine the block size. + nb = impl.Ilaenv(inb, "DGEQRF", " ", sm, sn, -1, -1) + nbmin := 2 + nx := 0 + + if 1 < nb && nb < sminmn { + // Determine when to cross over from blocked to unblocked code. + nx = max(0, impl.Ilaenv(ixover, "DGEQRF", " ", sm, sn, -1, -1)) + + if nx < sminmn { + // Determine if workspace is large enough for blocked code. + minws := 2*sn + (sn+1)*nb + iws = max(iws, minws) + if lwork < minws { + // Not enough workspace to use optimal nb. Reduce + // nb and determine the minimum value of nb. + nb = (lwork - 2*sn) / (sn + 1) + nbmin = max(2, impl.Ilaenv(inbmin, "DGEQRF", " ", sm, sn, -1, -1)) + } + } + } + + // Initialize partial column norms. + // The first n elements of work store the exact column norms. + for j := nfxd; j < n; j++ { + work[j] = bi.Dnrm2(sm, a[nfxd*lda+j:], lda) + work[n+j] = work[j] + } + j := nfxd + if nbmin <= nb && nb < sminmn && nx < sminmn { + // Use blocked code initially. + + // Compute factorization. + var fjb int + for topbmn := minmn - nx; j < topbmn; j += fjb { + jb := min(nb, topbmn-j) + + // Factorize jb columns among columns j:n. + fjb = impl.Dlaqps(m, n-j, j, jb, a[j:], lda, jpvt[j:], tau[j:], + work[j:n], work[j+n:2*n], work[2*n:2*n+jb], work[2*n+jb:], jb) + } + } + + // Use unblocked code to factor the last or only block. + if j < minmn { + impl.Dlaqp2(m, n-j, j, a[j:], lda, jpvt[j:], tau[j:], + work[j:n], work[j+n:2*n], work[2*n:]) + } + + work[0] = float64(iws) +} diff --git a/lapack/native/dgeqr2.go b/lapack/native/dgeqr2.go new file mode 100644 index 00000000..646350cd --- /dev/null +++ b/lapack/native/dgeqr2.go @@ -0,0 +1,59 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dgeqr2 computes a QR factorization of the m×n matrix A. +// +// In a QR factorization, Q is an m×m orthonormal matrix, and R is an +// upper triangular m×n matrix. +// +// A is modified to contain the information to construct Q and R. +// The upper triangle of a contains the matrix R. The lower triangular elements +// (not including the diagonal) contain the elementary reflectors. tau is modified +// to contain the reflector scales. tau must have length at least min(m,n), and +// this function will panic otherwise. +// +// The ith elementary reflector can be explicitly constructed by first extracting +// the +// v[j] = 0 j < i +// v[j] = 1 j == i +// v[j] = a[j*lda+i] j > i +// and computing H_i = I - tau[i] * v * v^T. +// +// The orthonormal matrix Q can be constructed from a product of these elementary +// reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). +// +// work is temporary storage of length at least n and this function will panic otherwise. +// +// Dgeqr2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgeqr2(m, n int, a []float64, lda int, tau, work []float64) { + // TODO(btracey): This is oriented such that columns of a are eliminated. + // This likely could be re-arranged to take better advantage of row-major + // storage. + checkMatrix(m, n, a, lda) + if len(work) < n { + panic(badWork) + } + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + for i := 0; i < k; i++ { + // Generate elementary reflector H_i. + a[i*lda+i], tau[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min((i+1), m-1)*lda+i:], lda) + if i < n-1 { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(blas.Left, m-i, n-i-1, + a[i*lda+i:], lda, + tau[i], + a[i*lda+i+1:], lda, + work) + a[i*lda+i] = aii + } + } +} diff --git a/lapack/native/dgeqrf.go b/lapack/native/dgeqrf.go new file mode 100644 index 00000000..aeb1afad --- /dev/null +++ b/lapack/native/dgeqrf.go @@ -0,0 +1,99 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dgeqrf computes the QR factorization of the m×n matrix A using a blocked +// algorithm. See the documentation for Dgeqr2 for a description of the +// parameters at entry and exit. +// +// work is temporary storage, and lwork specifies the usable memory length. +// The length of work must be at least max(1, lwork) and lwork must be -1 +// or at least n, otherwise this function will panic. +// Dgeqrf is a blocked QR factorization, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgeqrf, +// the optimal work length will be stored into work[0]. +// +// tau must have length at least min(m,n), and this function will panic otherwise. +func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { + if len(work) < max(1, lwork) { + panic(shortWork) + } + // nb is the optimal blocksize, i.e. the number of columns transformed at a time. + nb := impl.Ilaenv(1, "DGEQRF", " ", m, n, -1, -1) + lworkopt := n * max(nb, 1) + lworkopt = max(n, lworkopt) + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + checkMatrix(m, n, a, lda) + if lwork < n { + panic(badWork) + } + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + if k == 0 { + work[0] = float64(lworkopt) + return + } + nbmin := 2 // Minimal block size. + var nx int // Use unblocked (unless changed in the next for loop) + iws := n + ldwork := nb + // Only consider blocked if the suggested block size is > 1 and the + // number of rows or columns is sufficiently large. + if 1 < nb && nb < k { + // nx is the block size at which the code switches from blocked + // to unblocked. + nx = max(0, impl.Ilaenv(3, "DGEQRF", " ", m, n, -1, -1)) + if k > nx { + iws = ldwork * n + if lwork < iws { + // Not enough workspace to use the optimal block + // size. Get the minimum block size instead. + nb = lwork / n + nbmin = max(2, impl.Ilaenv(2, "DGEQRF", " ", m, n, -1, -1)) + } + } + } + for i := range work { + work[i] = 0 + } + // Compute QR using a blocked algorithm. + var i int + if nbmin <= nb && nb < k && nx < k { + for i = 0; i < k-nx; i += nb { + ib := min(k-i, nb) + // Compute the QR factorization of the current block. + impl.Dgeqr2(m-i, ib, a[i*lda+i:], lda, tau[i:], work) + if i+ib < n { + // Form the triangular factor of the block reflector and apply H^T + // In Dlarft, work becomes the T matrix. + impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + work, ldwork) + impl.Dlarfb(blas.Left, blas.Trans, lapack.Forward, lapack.ColumnWise, + m-i, n-i-ib, ib, + a[i*lda+i:], lda, + work, ldwork, + a[i*lda+i+ib:], lda, + work[ib*ldwork:], ldwork) + } + } + } + // Call unblocked code on the remaining columns. + if i < k { + impl.Dgeqr2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work) + } + work[0] = float64(lworkopt) +} diff --git a/lapack/native/dgerq2.go b/lapack/native/dgerq2.go new file mode 100644 index 00000000..19f5bd03 --- /dev/null +++ b/lapack/native/dgerq2.go @@ -0,0 +1,53 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dgerq2 computes an RQ factorization of the m×n matrix A, +// A = R * Q. +// On exit, if m <= n, the upper triangle of the subarray +// A[0:m, n-m:n] contains the m×m upper triangular matrix R. +// If m >= n, the elements on and above the (m-n)-th subdiagonal +// contain the m×n upper trapezoidal matrix R. +// The remaining elements, with tau, represent the +// orthogonal matrix Q as a product of min(m,n) elementary +// reflectors. +// +// The matrix Q is represented as a product of elementary reflectors +// Q = H_0 H_1 . . . H_{min(m,n)-1}. +// Each H(i) has the form +// H_i = I - tau_i * v * v^T +// where v is a vector with v[0:n-k+i-1] stored in A[m-k+i, 0:n-k+i-1], +// v[n-k+i:n] = 0 and v[n-k+i] = 1. +// +// tau must have length min(m,n) and work must have length m, otherwise +// Dgerq2 will panic. +// +// Dgerq2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgerq2(m, n int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + k := min(m, n) + if len(tau) < k { + panic(badTau) + } + if len(work) < m { + panic(badWork) + } + + for i := k - 1; i >= 0; i-- { + // Generate elementary reflector H[i] to annihilate + // A[m-k+i, 0:n-k+i-1]. + mki := m - k + i + nki := n - k + i + var aii float64 + aii, tau[i] = impl.Dlarfg(nki+1, a[mki*lda+nki], a[mki*lda:], 1) + + // Apply H[i] to A[0:m-k+i-1, 0:n-k+i] from the right. + a[mki*lda+nki] = 1 + impl.Dlarf(blas.Right, mki, nki+1, a[mki*lda:], 1, tau[i], a, lda, work) + a[mki*lda+nki] = aii + } +} diff --git a/lapack/native/dgerqf.go b/lapack/native/dgerqf.go new file mode 100644 index 00000000..48a7f743 --- /dev/null +++ b/lapack/native/dgerqf.go @@ -0,0 +1,128 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dgerqf computes an RQ factorization of the m×n matrix A, +// A = R * Q. +// On exit, if m <= n, the upper triangle of the subarray +// A[0:m, n-m:n] contains the m×m upper triangular matrix R. +// If m >= n, the elements on and above the (m-n)-th subdiagonal +// contain the m×n upper trapezoidal matrix R. +// The remaining elements, with tau, represent the +// orthogonal matrix Q as a product of min(m,n) elementary +// reflectors. +// +// The matrix Q is represented as a product of elementary reflectors +// Q = H_0 H_1 . . . H_{min(m,n)-1}. +// Each H(i) has the form +// H_i = I - tau_i * v * v^T +// where v is a vector with v[0:n-k+i-1] stored in A[m-k+i, 0:n-k+i-1], +// v[n-k+i:n] = 0 and v[n-k+i] = 1. +// +// tau must have length min(m,n), work must have length max(1, lwork), +// and lwork must be -1 or at least max(1, m), otherwise Dgerqf will panic. +// On exit, work[0] will contain the optimal length for work. +// +// Dgerqf is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { + checkMatrix(m, n, a, lda) + + if len(work) < max(1, lwork) { + panic(shortWork) + } + if lwork != -1 && lwork < max(1, m) { + panic(badWork) + } + + k := min(m, n) + if len(tau) != k { + panic(badTau) + } + + var nb, lwkopt int + if k == 0 { + lwkopt = 1 + } else { + nb = impl.Ilaenv(1, "DGERQF", " ", m, n, -1, -1) + lwkopt = m * nb + } + work[0] = float64(lwkopt) + + if lwork == -1 { + return + } + + // Return quickly if possible. + if k == 0 { + return + } + + nbmin := 2 + nx := 1 + iws := m + var ldwork int + if 1 < nb && nb < k { + // Determine when to cross over from blocked to unblocked code. + nx = max(0, impl.Ilaenv(3, "DGERQF", " ", m, n, -1, -1)) + if nx < k { + // Determine whether workspace is large enough for blocked code. + iws = m * nb + if lwork < iws { + // Not enough workspace to use optimal nb. Reduce + // nb and determine the minimum value of nb. + nb = lwork / m + nbmin = max(2, impl.Ilaenv(2, "DGERQF", " ", m, n, -1, -1)) + } + ldwork = nb + } + } + + var mu, nu int + if nbmin <= nb && nb < k && nx < k { + // Use blocked code initially. + // The last kk rows are handled by the block method. + ki := ((k - nx - 1) / nb) * nb + kk := min(k, ki+nb) + + var i int + for i = k - kk + ki; i >= k-kk; i -= nb { + ib := min(k-i, nb) + + // Compute the RQ factorization of the current block + // A[m-k+i:m-k+i+ib-1, 0:n-k+i+ib-1]. + impl.Dgerq2(ib, n-k+i+ib, a[(m-k+i)*lda:], lda, tau[i:], work) + if m-k+i > 0 { + // Form the triangular factor of the block reflector + // H = H_{i+ib-1} . . . H_{i+1} H_i. + impl.Dlarft(lapack.Backward, lapack.RowWise, + n-k+i+ib, ib, a[(m-k+i)*lda:], lda, tau[i:], + work, ldwork) + + // Apply H to A[0:m-k+i-1, 0:n-k+i+ib-1] from the right. + impl.Dlarfb(blas.Right, blas.NoTrans, lapack.Backward, lapack.RowWise, + m-k+i, n-k+i+ib, ib, a[(m-k+i)*lda:], lda, + work, ldwork, + a, lda, + work[ib*ldwork:], ldwork) + } + } + mu = m - k + i + nb + nu = n - k + i + nb + } else { + mu = m + nu = n + } + + // Use unblocked code to factor the last or only block. + if mu > 0 && nu > 0 { + impl.Dgerq2(mu, nu, a, lda, tau, work) + } + work[0] = float64(iws) +} diff --git a/lapack/native/dgesvd.go b/lapack/native/dgesvd.go new file mode 100644 index 00000000..d38ef2af --- /dev/null +++ b/lapack/native/dgesvd.go @@ -0,0 +1,1356 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +const noSVDO = "dgesvd: not coded for overwrite" + +// Dgesvd computes the singular value decomposition of the input matrix A. +// +// The singular value decomposition is +// A = U * Sigma * V^T +// where Sigma is an m×n diagonal matrix containing the singular values of A, +// U is an m×m orthogonal matrix and V is an n×n orthogonal matrix. The first +// min(m,n) columns of U and V are the left and right singular vectors of A +// respectively. +// +// jobU and jobVT are options for computing the singular vectors. The behavior +// is as follows +// jobU == lapack.SVDAll All m columns of U are returned in u +// jobU == lapack.SVDInPlace The first min(m,n) columns are returned in u +// jobU == lapack.SVDOverwrite The first min(m,n) columns of U are written into a +// jobU == lapack.SVDNone The columns of U are not computed. +// The behavior is the same for jobVT and the rows of V^T. At most one of jobU +// and jobVT can equal lapack.SVDOverwrite, and Dgesvd will panic otherwise. +// +// On entry, a contains the data for the m×n matrix A. During the call to Dgesvd +// the data is overwritten. On exit, A contains the appropriate singular vectors +// if either job is lapack.SVDOverwrite. +// +// s is a slice of length at least min(m,n) and on exit contains the singular +// values in decreasing order. +// +// u contains the left singular vectors on exit, stored column-wise. If +// jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDInPlace u is +// of size m×min(m,n). If jobU == lapack.SVDOverwrite or lapack.SVDNone, u is +// not used. +// +// vt contains the left singular vectors on exit, stored row-wise. If +// jobV == lapack.SVDAll, vt is of size n×m. If jobVT == lapack.SVDInPlace vt is +// of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is +// not used. +// +// work is a slice for storing temporary memory, and lwork is the usable size of +// the slice. lwork must be at least max(5*min(m,n), 3*min(m,n)+max(m,n)). +// If lwork == -1, instead of performing Dgesvd, the optimal work length will be +// stored into work[0]. Dgesvd will panic if the working memory has insufficient +// storage. +// +// Dgesvd returns whether the decomposition successfully completed. +func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) (ok bool) { + minmn := min(m, n) + checkMatrix(m, n, a, lda) + if jobU == lapack.SVDAll { + checkMatrix(m, m, u, ldu) + } else if jobU == lapack.SVDInPlace { + checkMatrix(m, minmn, u, ldu) + } + if jobVT == lapack.SVDAll { + checkMatrix(n, n, vt, ldvt) + } else if jobVT == lapack.SVDInPlace { + checkMatrix(minmn, n, vt, ldvt) + } + if jobU == lapack.SVDOverwrite && jobVT == lapack.SVDOverwrite { + panic("lapack: both jobU and jobVT are lapack.SVDOverwrite") + } + if len(s) < minmn { + panic(badS) + } + if jobU == lapack.SVDOverwrite || jobVT == lapack.SVDOverwrite { + panic(noSVDO) + } + if m == 0 || n == 0 { + return true + } + + wantua := jobU == lapack.SVDAll + wantus := jobU == lapack.SVDInPlace + wantuas := wantua || wantus + wantuo := jobU == lapack.SVDOverwrite + wantun := jobU == lapack.None + + wantva := jobVT == lapack.SVDAll + wantvs := jobVT == lapack.SVDInPlace + wantvas := wantva || wantvs + wantvo := jobVT == lapack.SVDOverwrite + wantvn := jobVT == lapack.None + + bi := blas64.Implementation() + var mnthr int + + // Compute optimal space for subroutines. + maxwrk := 1 + opts := string(jobU) + string(jobVT) + var wrkbl, bdspac int + if m >= n { + mnthr = impl.Ilaenv(6, "DGESVD", opts, m, n, 0, 0) + bdspac = 5 * n + impl.Dgeqrf(m, n, a, lda, nil, work, -1) + lwork_dgeqrf := int(work[0]) + impl.Dorgqr(m, n, n, a, lda, nil, work, -1) + lwork_dorgqr_n := int(work[0]) + impl.Dorgqr(m, m, n, a, lda, nil, work, -1) + lwork_dorgqr_m := int(work[0]) + impl.Dgebrd(n, n, a, lda, s, nil, nil, nil, work, -1) + lwork_dgebrd := int(work[0]) + impl.Dorgbr(lapack.ApplyP, n, n, n, a, lda, nil, work, -1) + lwork_dorgbr_p := int(work[0]) + impl.Dorgbr(lapack.ApplyQ, n, n, n, a, lda, nil, work, -1) + lwork_dorgbr_q := int(work[0]) + + if m >= mnthr { + // m >> n + if wantun { + // Path 1 + maxwrk = n + lwork_dgeqrf + maxwrk = max(maxwrk, 3*n+lwork_dgebrd) + if wantvo || wantvas { + maxwrk = max(maxwrk, 3*n+lwork_dorgbr_p) + } + maxwrk = max(maxwrk, bdspac) + } else if wantuo && wantvn { + // Path 2 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = max(n*n+wrkbl, n*n+m*n+n) + } else if wantuo && wantvs { + // Path 3 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = max(n*n+wrkbl, n*n+m*n+n) + } else if wantus && wantvn { + // Path 4 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = n*n + wrkbl + } else if wantus && wantvo { + // Path 5 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = 2*n*n + wrkbl + } else if wantus && wantvas { + // Path 6 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_n) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = n*n + wrkbl + } else if wantua && wantvn { + // Path 7 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_m) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = n*n + wrkbl + } else if wantua && wantvo { + // Path 8 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_m) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = 2*n*n + wrkbl + } else if wantua && wantvas { + // Path 9 + wrkbl = n + lwork_dgeqrf + wrkbl = max(wrkbl, n+lwork_dorgqr_m) + wrkbl = max(wrkbl, 3*n+lwork_dgebrd) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_q) + wrkbl = max(wrkbl, 3*n+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = n*n + wrkbl + } + } else { + // Path 10: m > n + impl.Dgebrd(m, n, a, lda, s, nil, nil, nil, work, -1) + lwork_dgebrd := int(work[0]) + maxwrk = 3*n + lwork_dgebrd + if wantus || wantuo { + impl.Dorgbr(lapack.ApplyQ, m, n, n, a, lda, nil, work, -1) + lwork_dorgbr_q = int(work[0]) + maxwrk = max(maxwrk, 3*n+lwork_dorgbr_q) + } + if wantua { + impl.Dorgbr(lapack.ApplyQ, m, m, n, a, lda, nil, work, -1) + lwork_dorgbr_q := int(work[0]) + maxwrk = max(maxwrk, 3*n+lwork_dorgbr_q) + } + if !wantvn { + maxwrk = max(maxwrk, 3*n+lwork_dorgbr_p) + } + maxwrk = max(maxwrk, bdspac) + } + } else { + mnthr = impl.Ilaenv(6, "DGESVD", opts, m, n, 0, 0) + + bdspac = 5 * m + impl.Dgelqf(m, n, a, lda, nil, work, -1) + lwork_dgelqf := int(work[0]) + impl.Dorglq(n, n, m, nil, n, nil, work, -1) + lwork_dorglq_n := int(work[0]) + impl.Dorglq(m, n, m, a, lda, nil, work, -1) + lwork_dorglq_m := int(work[0]) + impl.Dgebrd(m, m, a, lda, s, nil, nil, nil, work, -1) + lwork_dgebrd := int(work[0]) + impl.Dorgbr(lapack.ApplyP, m, m, m, a, n, nil, work, -1) + lwork_dorgbr_p := int(work[0]) + impl.Dorgbr(lapack.ApplyQ, m, m, m, a, n, nil, work, -1) + lwork_dorgbr_q := int(work[0]) + if n >= mnthr { + // n >> m + if wantvn { + // Path 1t + maxwrk = m + lwork_dgelqf + maxwrk = max(maxwrk, 3*m+lwork_dgebrd) + if wantuo || wantuas { + maxwrk = max(maxwrk, 3*m+lwork_dorgbr_q) + } + maxwrk = max(maxwrk, bdspac) + } else if wantvo && wantun { + // Path 2t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = max(m*m+wrkbl, m*m+m*n+m) + } else if wantvo && wantuas { + // Path 3t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = max(m*m+wrkbl, m*m+m*n+m) + } else if wantvs && wantun { + // Path 4t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = m*m + wrkbl + } else if wantvs && wantuo { + // Path 5t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = 2*m*m + wrkbl + } else if wantvs && wantuas { + // Path 6t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_m) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = m*m + wrkbl + } else if wantva && wantun { + // Path 7t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_n) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, bdspac) + maxwrk = m*m + wrkbl + } else if wantva && wantuo { + // Path 8t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_n) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = 2*m*m + wrkbl + } else if wantva && wantuas { + // Path 9t + wrkbl = m + lwork_dgelqf + wrkbl = max(wrkbl, m+lwork_dorglq_n) + wrkbl = max(wrkbl, 3*m+lwork_dgebrd) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_p) + wrkbl = max(wrkbl, 3*m+lwork_dorgbr_q) + wrkbl = max(wrkbl, bdspac) + maxwrk = m*m + wrkbl + } + } else { + // Path 10t, n > m + impl.Dgebrd(m, n, a, lda, s, nil, nil, nil, work, -1) + lwork_dgebrd = int(work[0]) + maxwrk := 3*m + lwork_dgebrd + if wantvs || wantvo { + impl.Dorgbr(lapack.ApplyP, m, n, m, a, n, nil, work, -1) + lwork_dorgbr_p = int(work[0]) + maxwrk = max(maxwrk, 3*m+lwork_dorgbr_p) + } + if wantva { + impl.Dorgbr(lapack.ApplyP, n, n, m, a, n, nil, work, -1) + lwork_dorgbr_p = int(work[0]) + maxwrk = max(maxwrk, 3*m+lwork_dorgbr_p) + } + if !wantun { + maxwrk = max(maxwrk, 3*m+lwork_dorgbr_q) + } + maxwrk = max(maxwrk, bdspac) + } + } + + minWork := max(1, 5*minmn) + if !((wantun && m >= mnthr) || (wantvn && n >= mnthr)) { + minWork = max(minWork, 3*minmn+max(m, n)) + } + + if lwork != -1 { + if len(work) < lwork { + panic(badWork) + } + if lwork < minWork { + panic(badWork) + } + } + if m == 0 || n == 0 { + return true + } + + maxwrk = max(maxwrk, minWork) + work[0] = float64(maxwrk) + if lwork == -1 { + return true + } + + // Perform decomposition. + eps := dlamchE + smlnum := math.Sqrt(dlamchS) / eps + bignum := 1 / smlnum + + // Scale A if max element outside range [smlnum, bignum]. + anrm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, nil) + var iscl bool + if anrm > 0 && anrm < smlnum { + iscl = true + impl.Dlascl(lapack.General, 0, 0, anrm, smlnum, m, n, a, lda) + } else if anrm > bignum { + iscl = true + impl.Dlascl(lapack.General, 0, 0, anrm, bignum, m, n, a, lda) + } + + var ie int + if m >= n { + // If A has sufficiently more rows than columns, use the QR decomposition. + if m >= mnthr { + // m >> n + if wantun { + // Path 1. + itau := 0 + iwork := itau + n + + // Compute A = Q * R. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Zero out below R. + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda) + ie = 0 + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + // Bidiagonalize R in A. + impl.Dgebrd(n, n, a, lda, s, work[ie:], work[itauq:], + work[itaup:], work[iwork:], lwork-iwork) + ncvt := 0 + if wantvo || wantvas { + // Generate P^T. + impl.Dorgbr(lapack.ApplyP, n, n, n, a, lda, work[itaup:], + work[iwork:], lwork-iwork) + ncvt = n + } + iwork = ie + n + + // Perform bidiagonal QR iteration computing right singular vectors + // of A in A if desired. + ok = impl.Dbdsqr(blas.Upper, n, ncvt, 0, 0, s, work[ie:], + a, lda, work, 1, work, 1, work[iwork:]) + + // If right singular vectors desired in VT, copy them there. + if wantvas { + impl.Dlacpy(blas.All, n, n, a, lda, vt, ldvt) + } + } else if wantuo && wantvn { + // Path 2 + panic(noSVDO) + } else if wantuo && wantvas { + // Path 3 + panic(noSVDO) + } else if wantus { + if wantvn { + // Path 4 + if lwork >= n*n+max(4*n, bdspac) { + // Sufficient workspace for a fast algorithm. + ir := 0 + var ldworkr int + if lwork >= wrkbl+lda*n { + ldworkr = lda + } else { + ldworkr = n + } + itau := ir + ldworkr*n + iwork := itau + n + // Compute A = Q * R. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Copy R to work[ir:], zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, work[ir:], ldworkr) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr) + + // Generate Q in A. + impl.Dorgqr(m, n, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in work[ir:]. + impl.Dgebrd(n, n, work[ir:], ldworkr, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Generate left vectors bidiagonalizing R in work[ir:]. + impl.Dorgbr(lapack.ApplyQ, n, n, n, work[ir:], ldworkr, + work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, compuing left singular + // vectors of R in work[ir:]. + ok = impl.Dbdsqr(blas.Upper, n, 0, n, 0, s, work[ie:], work, 1, + work[ir:], ldworkr, work, 1, work[iwork:]) + + // Multiply Q in A by left singular vectors of R in + // work[ir:], storing result in U. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, a, lda, + work[ir:], ldworkr, 0, u, ldu) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + n + + // Compute A = Q*R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, n, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Zero out below R in A. + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda) + + // Bidiagonalize R in A. + impl.Dgebrd(n, n, a, lda, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left vectors bidiagonalizing R. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, m, n, n, + a, lda, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left + // singular vectors of A in U. + ok = impl.Dbdsqr(blas.Upper, n, 0, m, 0, s, work[ie:], work, 1, + u, ldu, work, 1, work[iwork:]) + } + } else if wantvo { + // Path 5 + panic(noSVDO) + } else if wantvas { + // Path 6 + if lwork >= n*n+max(4*n, bdspac) { + // Sufficient workspace for a fast algorithm. + iu := 0 + var ldworku int + if lwork >= wrkbl+lda*n { + ldworku = lda + } else { + ldworku = n + } + itau := iu + ldworku*n + iwork := itau + n + + // Compute A = Q * R. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + // Copy R to work[iu:], zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[iu+ldworku:], ldworku) + + // Generate Q in A. + impl.Dorgqr(m, n, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in work[iu:], copying result to VT. + impl.Dgebrd(n, n, work[iu:], ldworku, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, n, n, work[iu:], ldworku, vt, ldvt) + + // Generate left bidiagonalizing vectors in work[iu:]. + impl.Dorgbr(lapack.ApplyQ, n, n, n, work[iu:], ldworku, + work[itauq:], work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of R in work[iu:], and computing right singular + // vectors of R in VT. + ok = impl.Dbdsqr(blas.Upper, n, n, n, 0, s, work[ie:], + vt, ldvt, work[iu:], ldworku, work, 1, work[iwork:]) + + // Multiply Q in A by left singular vectors of R in + // work[iu:], storing result in U. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, a, lda, + work[iu:], ldworku, 0, u, ldu) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + n + + // Compute A = Q * R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, n, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + + // Copy R to VT, zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, vt[ldvt:], ldvt) + + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in VT. + impl.Dgebrd(n, n, vt, ldvt, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left bidiagonalizing vectors in VT. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, m, n, n, + vt, ldvt, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + ok = impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } + } + } else if wantua { + if wantvn { + // Path 7 + if lwork >= n*n+max(max(n+m, 4*n), bdspac) { + // Sufficient workspace for a fast algorithm. + ir := 0 + var ldworkr int + if lwork >= wrkbl+lda*n { + ldworkr = lda + } else { + ldworkr = n + } + itau := ir + ldworkr*n + iwork := itau + n + + // Compute A = Q*R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Copy R to work[ir:], zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, work[ir:], ldworkr) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[ir+ldworkr:], ldworkr) + + // Generate Q in U. + impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in work[ir:]. + impl.Dgebrd(n, n, work[ir:], ldworkr, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in work[ir:]. + impl.Dorgbr(lapack.ApplyQ, n, n, n, work[ir:], ldworkr, + work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of R in work[ir:]. + ok = impl.Dbdsqr(blas.Upper, n, 0, n, 0, s, work[ie:], work, 1, + work[ir:], ldworkr, work, 1, work[iwork:]) + + // Multiply Q in U by left singular vectors of R in + // work[ir:], storing result in A. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, u, ldu, + work[ir:], ldworkr, 0, a, lda) + + // Copy left singular vectors of A from A to U. + impl.Dlacpy(blas.All, m, n, a, lda, u, ldu) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + n + + // Compute A = Q*R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Zero out below R in A. + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, a[lda:], lda) + + // Bidiagonalize R in A. + impl.Dgebrd(n, n, a, lda, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left bidiagonalizing vectors in A. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, m, n, n, + a, lda, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left + // singular vectors of A in U. + ok = impl.Dbdsqr(blas.Upper, n, 0, m, 0, s, work[ie:], + work, 1, u, ldu, work, 1, work[iwork:]) + } + } else if wantvo { + // Path 8. + panic(noSVDO) + } else if wantvas { + // Path 9. + if lwork >= n*n+max(max(n+m, 4*n), bdspac) { + // Sufficient workspace for a fast algorithm. + iu := 0 + var ldworku int + if lwork >= wrkbl+lda*n { + ldworku = lda + } else { + ldworku = n + } + itau := iu + ldworku*n + iwork := itau + n + + // Compute A = Q * R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + + // Copy R to work[iu:], zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, work[iu:], ldworku) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, work[iu+ldworku:], ldworku) + + ie = itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in work[iu:], copying result to VT. + impl.Dgebrd(n, n, work[iu:], ldworku, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, n, n, work[iu:], ldworku, vt, ldvt) + + // Generate left bidiagonalizing vectors in work[iu:]. + impl.Dorgbr(lapack.ApplyQ, n, n, n, work[iu:], ldworku, + work[itauq:], work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of R in work[iu:] and computing right + // singular vectors of R in VT. + ok = impl.Dbdsqr(blas.Upper, n, n, n, 0, s, work[ie:], + vt, ldvt, work[iu:], ldworku, work, 1, work[iwork:]) + + // Multiply Q in U by left singular vectors of R in + // work[iu:], storing result in A. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, n, 1, + u, ldu, work[iu:], ldworku, 0, a, lda) + + // Copy left singular vectors of A from A to U. + impl.Dlacpy(blas.All, m, n, a, lda, u, ldu) + + /* + // Bidiagonalize R in VT. + impl.Dgebrd(n, n, vt, ldvt, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left bidiagonalizing vectors in VT. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, + m, n, n, vt, ldvt, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + ok = impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + */ + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + n + + // Compute A = Q*R, copying result to U. + impl.Dgeqrf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + + // Generate Q in U. + impl.Dorgqr(m, m, n, u, ldu, work[itau:], work[iwork:], lwork-iwork) + + // Copy R from A to VT, zeroing out below it. + impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt) + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, vt[ldvt:], ldvt) + + ie := itau + itauq := ie + n + itaup := itauq + n + iwork = itaup + n + + // Bidiagonalize R in VT. + impl.Dgebrd(n, n, vt, ldvt, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply Q in U by left bidiagonalizing vectors in VT. + impl.Dormbr(lapack.ApplyQ, blas.Right, blas.NoTrans, + m, n, n, vt, ldvt, work[itauq:], u, ldu, work[iwork:], lwork-iwork) + + // Generate right bidiagonizing vectors in VT. + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + n + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } + } + } + } else { + // Path 10. + // M at least N, but not much larger. + ie = 0 + itauq := ie + n + itaup := itauq + n + iwork := itaup + n + + // Bidiagonalize A. + impl.Dgebrd(m, n, a, lda, s, work[ie:], work[itauq:], + work[itaup:], work[iwork:], lwork-iwork) + if wantuas { + // Left singular vectors are desired in U. Copy result to U and + // generate left biadiagonalizing vectors in U. + impl.Dlacpy(blas.Lower, m, n, a, lda, u, ldu) + var ncu int + if wantus { + ncu = n + } + if wantua { + ncu = m + } + impl.Dorgbr(lapack.ApplyQ, m, ncu, n, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + } + if wantvas { + // Right singular vectors are desired in VT. Copy result to VT and + // generate left biadiagonalizing vectors in VT. + impl.Dlacpy(blas.Upper, n, n, a, lda, vt, ldvt) + impl.Dorgbr(lapack.ApplyP, n, n, n, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) + } + if wantuo { + panic(noSVDO) + } + if wantvo { + panic(noSVDO) + } + iwork = ie + n + var nru, ncvt int + if wantuas || wantuo { + nru = m + } + if wantun { + nru = 0 + } + if wantvas || wantvo { + ncvt = n + } + if wantvn { + ncvt = 0 + } + if !wantuo && !wantvo { + // Perform bidiagonal QR iteration, if desired, computing left + // singular vectors in U and right singular vectors in VT. + ok = impl.Dbdsqr(blas.Upper, n, ncvt, nru, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } else { + // There will be two branches when the implementation is complete. + panic(noSVDO) + } + } + } else { + // A has more columns than rows. If A has sufficiently more columns than + // rows, first reduce using the LQ decomposition. + if n >= mnthr { + // n >> m. + if wantvn { + // Path 1t. + itau := 0 + iwork := itau + m + + // Compute A = L*Q. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Zero out above L. + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, a[1:], lda) + ie := 0 + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in A. + impl.Dgebrd(m, m, a, lda, s, work[ie:itauq], + work[itauq:itaup], work[itaup:iwork], work[iwork:], lwork-iwork) + if wantuo || wantuas { + impl.Dorgbr(lapack.ApplyQ, m, m, m, a, lda, + work[itauq:], work[iwork:], lwork-iwork) + } + iwork = ie + m + nru := 0 + if wantuo || wantuas { + nru = m + } + + // Perform bidiagonal QR iteration, computing left singular vectors + // of A in A if desired. + ok = impl.Dbdsqr(blas.Upper, m, 0, nru, 0, s, work[ie:], + work, 1, a, lda, work, 1, work[iwork:]) + + // If left singular vectors desired in U, copy them there. + if wantuas { + impl.Dlacpy(blas.All, m, m, a, lda, u, ldu) + } + } else if wantvo && wantun { + // Path 2t. + panic(noSVDO) + } else if wantvo && wantuas { + // Path 3t. + panic(noSVDO) + } else if wantvs { + if wantun { + // Path 4t. + if lwork >= m*m+max(4*m, bdspac) { + // Sufficient workspace for a fast algorithm. + ir := 0 + var ldworkr int + if lwork >= wrkbl+lda*m { + ldworkr = lda + } else { + ldworkr = m + } + itau := ir + ldworkr*m + iwork := itau + m + + // Compute A = L*Q. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to work[ir:], zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, work[ir:], ldworkr) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[ir+1:], ldworkr) + + // Generate Q in A. + impl.Dorglq(m, n, m, a, lda, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in work[ir:]. + impl.Dgebrd(m, m, work[ir:], ldworkr, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Generate right vectors bidiagonalizing L in work[ir:]. + impl.Dorgbr(lapack.ApplyP, m, m, m, work[ir:], ldworkr, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing right singular + // vectors of L in work[ir:]. + ok = impl.Dbdsqr(blas.Upper, m, m, 0, 0, s, work[ie:], + work[ir:], ldworkr, work, 1, work, 1, work[iwork:]) + + // Multiply right singular vectors of L in work[ir:] by + // Q in A, storing result in VT. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, + work[ir:], ldworkr, a, lda, 0, vt, ldvt) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + m + + // Compute A = L*Q. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Copy result to VT. + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(m, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Zero out above L in A. + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, a[1:], lda) + + // Bidiagonalize L in A. + impl.Dgebrd(m, m, a, lda, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply right vectors bidiagonalizing L by Q in VT. + impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, + a, lda, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing right + // singular vectors of A in VT. + ok = impl.Dbdsqr(blas.Upper, m, n, 0, 0, s, work[ie:], + vt, ldvt, work, 1, work, 1, work[iwork:]) + } + } else if wantuo { + // Path 5t. + panic(noSVDO) + } else if wantuas { + // Path 6t. + if lwork >= m*m+max(4*m, bdspac) { + // Sufficient workspace for a fast algorithm. + iu := 0 + var ldworku int + if lwork >= wrkbl+lda*m { + ldworku = lda + } else { + ldworku = m + } + itau := iu + ldworku*m + iwork := itau + m + + // Compute A = L*Q. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to work[iu:], zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, work[iu:], ldworku) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[iu+1:], ldworku) + + // Generate Q in A. + impl.Dorglq(m, n, m, a, lda, work[itau:], work[iwork:], lwork-iwork) + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in work[iu:], copying result to U. + impl.Dgebrd(m, m, work[iu:], ldworku, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, m, work[iu:], ldworku, u, ldu) + + // Generate right bidiagionalizing vectors in work[iu:]. + impl.Dorgbr(lapack.ApplyP, m, m, m, work[iu:], ldworku, + work[itaup:], work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in U. + impl.Dorgbr(lapack.ApplyQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing left singular + // vectors of L in U and computing right singular vectors of + // L in work[iu:]. + ok = impl.Dbdsqr(blas.Upper, m, m, m, 0, s, work[ie:], + work[iu:], ldworku, u, ldu, work, 1, work[iwork:]) + + // Multiply right singular vectors of L in work[iu:] by + // Q in A, storing result in VT. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, + work[iu:], ldworku, a, lda, 0, vt, ldvt) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + m + + // Compute A = L*Q, copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(m, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to U, zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, u, ldu) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, u[1:], ldu) + + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in U. + impl.Dgebrd(m, m, u, ldu, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Multiply right bidiagonalizing vectors in U by Q in VT. + impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, + u, ldu, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in U. + impl.Dorgbr(lapack.ApplyQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + impl.Dbdsqr(blas.Upper, m, n, m, 0, s, work[ie:], vt, ldvt, + u, ldu, work, 1, work[iwork:]) + } + } + } else if wantva { + if wantun { + // Path 7t. + if lwork >= m*m+max(max(n+m, 4*m), bdspac) { + // Sufficient workspace for a fast algorithm. + ir := 0 + var ldworkr int + if lwork >= wrkbl+lda*m { + ldworkr = lda + } else { + ldworkr = m + } + itau := ir + ldworkr*m + iwork := itau + m + + // Compute A = L*Q, copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Copy L to work[ir:], zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, work[ir:], ldworkr) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[ir+1:], ldworkr) + + // Generate Q in VT. + impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in work[ir:]. + impl.Dgebrd(m, m, work[ir:], ldworkr, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + + // Generate right bidiagonalizing vectors in work[ir:]. + impl.Dorgbr(lapack.ApplyP, m, m, m, work[ir:], ldworkr, + work[itaup:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing right + // singular vectors of L in work[ir:]. + ok = impl.Dbdsqr(blas.Upper, m, m, 0, 0, s, work[ie:], + work[ir:], ldworkr, work, 1, work, 1, work[iwork:]) + + // Multiply right singular vectors of L in work[ir:] by + // Q in VT, storing result in A. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, + work[ir:], ldworkr, vt, ldvt, 0, a, lda) + + // Copy right singular vectors of A from A to VT. + impl.Dlacpy(blas.All, m, n, a, lda, vt, ldvt) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + m + // Compute A = L * Q, copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + ie := itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Zero out above L in A. + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, a[1:], lda) + + // Bidiagonalize L in A. + impl.Dgebrd(m, m, a, lda, s, work[ie:], work[itauq:], + work[itaup:], work[iwork:], lwork-iwork) + + // Multiply right bidiagonalizing vectors in A by Q in VT. + impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, + a, lda, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing right singular + // vectors of A in VT. + ok = impl.Dbdsqr(blas.Upper, m, n, 0, 0, s, work[ie:], + vt, ldvt, work, 1, work, 1, work[iwork:]) + } + } else if wantuo { + panic(noSVDO) + } else if wantuas { + // Path 9t. + if lwork >= m*m+max(max(m+n, 4*m), bdspac) { + // Sufficient workspace for a fast algorithm. + iu := 0 + + var ldworku int + if lwork >= wrkbl+lda*m { + ldworku = lda + } else { + ldworku = m + } + itau := iu + ldworku*m + iwork := itau + m + + // Generate A = L * Q copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to work[iu:], zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, work[iu:], ldworku) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, work[iu+1:], ldworku) + ie = itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in work[iu:], copying result to U. + impl.Dgebrd(m, m, work[iu:], ldworku, s, work[ie:], + work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Lower, m, m, work[iu:], ldworku, u, ldu) + + // Generate right bidiagonalizing vectors in work[iu:]. + impl.Dorgbr(lapack.ApplyP, m, m, m, work[iu:], ldworku, + work[itaup:], work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in U. + impl.Dorgbr(lapack.ApplyQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing left singular + // vectors of L in U and computing right singular vectors + // of L in work[iu:]. + ok = impl.Dbdsqr(blas.Upper, m, m, m, 0, s, work[ie:], + work[iu:], ldworku, u, ldu, work, 1, work[iwork:]) + + // Multiply right singular vectors of L in work[iu:] + // Q in VT, storing result in A. + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n, m, 1, + work[iu:], ldworku, vt, ldvt, 0, a, lda) + + // Copy right singular vectors of A from A to VT. + impl.Dlacpy(blas.All, m, n, a, lda, vt, ldvt) + } else { + // Insufficient workspace for a fast algorithm. + itau := 0 + iwork := itau + m + + // Compute A = L * Q, copying result to VT. + impl.Dgelqf(m, n, a, lda, work[itau:], work[iwork:], lwork-iwork) + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + + // Generate Q in VT. + impl.Dorglq(n, n, m, vt, ldvt, work[itau:], work[iwork:], lwork-iwork) + + // Copy L to U, zeroing out above it. + impl.Dlacpy(blas.Lower, m, m, a, lda, u, ldu) + impl.Dlaset(blas.Upper, m-1, m-1, 0, 0, u[1:], ldu) + + ie = itau + itauq := ie + m + itaup := itauq + m + iwork = itaup + m + + // Bidiagonalize L in U. + impl.Dgebrd(m, m, u, ldu, s, work[ie:], work[itauq:], + work[itaup:], work[iwork:], lwork-iwork) + + // Multiply right bidiagonalizing vectors in U by Q in VT. + impl.Dormbr(lapack.ApplyP, blas.Left, blas.Trans, m, n, m, + u, ldu, work[itaup:], vt, ldvt, work[iwork:], lwork-iwork) + + // Generate left bidiagonalizing vectors in U. + impl.Dorgbr(lapack.ApplyQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + iwork = ie + m + + // Perform bidiagonal QR iteration, computing left singular + // vectors of A in U and computing right singular vectors + // of A in VT. + ok = impl.Dbdsqr(blas.Upper, m, n, m, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } + } + } + } else { + // Path 10t. + // N at least M, but not much larger. + ie = 0 + itauq := ie + m + itaup := itauq + m + iwork := itaup + m + + // Bidiagonalize A. + impl.Dgebrd(m, n, a, lda, s, work[ie:], work[itauq:], work[itaup:], work[iwork:], lwork-iwork) + if wantuas { + // If left singular vectors desired in U, copy result to U and + // generate left bidiagonalizing vectors in U. + impl.Dlacpy(blas.Lower, m, m, a, lda, u, ldu) + impl.Dorgbr(lapack.ApplyQ, m, m, n, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + } + if wantvas { + // If right singular vectors desired in VT, copy result to VT + // and generate right bidiagonalizing vectors in VT. + impl.Dlacpy(blas.Upper, m, n, a, lda, vt, ldvt) + var nrvt int + if wantva { + nrvt = n + } else { + nrvt = m + } + impl.Dorgbr(lapack.ApplyP, nrvt, n, m, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) + } + if wantuo { + panic(noSVDO) + } + if wantvo { + panic(noSVDO) + } + iwork = ie + m + var nru, ncvt int + if wantuas || wantuo { + nru = m + } + if wantvas || wantvo { + ncvt = n + } + if !wantuo && !wantvo { + // Perform bidiagonal QR iteration, if desired, computing left + // singular vectors in U and computing right singular vectors in + // VT. + ok = impl.Dbdsqr(blas.Lower, m, ncvt, nru, 0, s, work[ie:], + vt, ldvt, u, ldu, work, 1, work[iwork:]) + } else { + // There will be two branches when the implementation is complete. + panic(noSVDO) + } + } + } + if !ok { + if ie > 1 { + for i := 0; i < minmn-1; i++ { + work[i+1] = work[i+ie] + } + } + if ie < 1 { + for i := minmn - 2; i >= 0; i-- { + work[i+1] = work[i+ie] + } + } + } + // Undo scaling if necessary. + if iscl { + if anrm > bignum { + impl.Dlascl(lapack.General, 0, 0, bignum, anrm, minmn, 1, s, minmn) + } + if !ok && anrm > bignum { + impl.Dlascl(lapack.General, 0, 0, bignum, anrm, minmn-1, 1, work[minmn:], minmn) + } + if anrm < smlnum { + impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, minmn, 1, s, minmn) + } + if !ok && anrm < smlnum { + impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, minmn-1, 1, work[minmn:], minmn) + } + } + work[0] = float64(maxwrk) + return ok +} diff --git a/lapack/native/dgetf2.go b/lapack/native/dgetf2.go new file mode 100644 index 00000000..357068fc --- /dev/null +++ b/lapack/native/dgetf2.go @@ -0,0 +1,69 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgetf2 computes the LU decomposition of the m×n matrix A. +// The LU decomposition is a factorization of a into +// A = P * L * U +// where P is a permutation matrix, L is a unit lower triangular matrix, and +// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored +// in place into a. +// +// ipiv is a permutation vector. It indicates that row i of the matrix was +// changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic +// otherwise. ipiv is zero-indexed. +// +// Dgetf2 returns whether the matrix A is singular. The LU decomposition will +// be computed regardless of the singularity of A, but division by zero +// will occur if the false is returned and the result is used to solve a +// system of equations. +// +// Dgetf2 is an internal routine. It is exported for testing purposes. +func (Implementation) Dgetf2(m, n int, a []float64, lda int, ipiv []int) (ok bool) { + mn := min(m, n) + checkMatrix(m, n, a, lda) + if len(ipiv) < mn { + panic(badIpiv) + } + if m == 0 || n == 0 { + return true + } + bi := blas64.Implementation() + sfmin := dlamchS + ok = true + for j := 0; j < mn; j++ { + // Find a pivot and test for singularity. + jp := j + bi.Idamax(m-j, a[j*lda+j:], lda) + ipiv[j] = jp + if a[jp*lda+j] == 0 { + ok = false + } else { + // Swap the rows if necessary. + if jp != j { + bi.Dswap(n, a[j*lda:], 1, a[jp*lda:], 1) + } + if j < m-1 { + aj := a[j*lda+j] + if math.Abs(aj) >= sfmin { + bi.Dscal(m-j-1, 1/aj, a[(j+1)*lda+j:], lda) + } else { + for i := 0; i < m-j-1; i++ { + a[(j+1)*lda+j] = a[(j+1)*lda+j] / a[lda*j+j] + } + } + } + } + if j < mn-1 { + 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) + } + } + return ok +} diff --git a/lapack/native/dgetrf.go b/lapack/native/dgetrf.go new file mode 100644 index 00000000..74aa4249 --- /dev/null +++ b/lapack/native/dgetrf.go @@ -0,0 +1,70 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgetrf computes the LU decomposition of the m×n matrix A. +// The LU decomposition is a factorization of A into +// A = P * L * U +// where P is a permutation matrix, L is a unit lower triangular matrix, and +// U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored +// in place into a. +// +// ipiv is a permutation vector. It indicates that row i of the matrix was +// changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic +// otherwise. ipiv is zero-indexed. +// +// Dgetrf is the blocked version of the algorithm. +// +// Dgetrf returns whether the matrix A is singular. The LU decomposition will +// be computed regardless of the singularity of A, but division by zero +// will occur if the false is returned and the result is used to solve a +// system of equations. +func (impl Implementation) Dgetrf(m, n int, a []float64, lda int, ipiv []int) (ok bool) { + mn := min(m, n) + checkMatrix(m, n, a, lda) + if len(ipiv) < mn { + panic(badIpiv) + } + if m == 0 || n == 0 { + return false + } + bi := blas64.Implementation() + nb := impl.Ilaenv(1, "DGETRF", " ", m, n, -1, -1) + if nb <= 1 || nb >= min(m, n) { + // Use the unblocked algorithm. + return impl.Dgetf2(m, n, a, lda, ipiv) + } + ok = true + for j := 0; j < mn; j += nb { + jb := min(mn-j, nb) + blockOk := impl.Dgetf2(m-j, jb, a[j*lda+j:], lda, ipiv[j:]) + if !blockOk { + ok = false + } + for i := j; i <= min(m-1, j+jb-1); i++ { + ipiv[i] = j + ipiv[i] + } + impl.Dlaswp(j, a, lda, j, j+jb-1, ipiv[:j+jb], 1) + if j+jb < n { + impl.Dlaswp(n-j-jb, a[j+jb:], lda, j, j+jb-1, ipiv[:j+jb], 1) + bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.Unit, + jb, n-j-jb, 1, + a[j*lda+j:], lda, + a[j*lda+j+jb:], lda) + if j+jb < m { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m-j-jb, n-j-jb, jb, -1, + a[(j+jb)*lda+j:], lda, + a[j*lda+j+jb:], lda, + 1, a[(j+jb)*lda+j+jb:], lda) + } + } + } + return ok +} diff --git a/lapack/native/dgetri.go b/lapack/native/dgetri.go new file mode 100644 index 00000000..55ef1e84 --- /dev/null +++ b/lapack/native/dgetri.go @@ -0,0 +1,92 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgetri computes the inverse of the matrix A using the LU factorization computed +// by Dgetrf. On entry, a contains the PLU decomposition of A as computed by +// Dgetrf and on exit contains the reciprocal of the original matrix. +// +// Dgetri will not perform the inversion if the matrix is singular, and returns +// a boolean indicating whether the inversion was successful. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= n and this function will panic otherwise. +// Dgetri is a blocked inversion, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dgetri, +// the optimal work length will be stored into work[0]. +func (impl Implementation) Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) (ok bool) { + checkMatrix(n, n, a, lda) + if len(ipiv) < n { + panic(badIpiv) + } + nb := impl.Ilaenv(1, "DGETRI", " ", n, -1, -1, -1) + if lwork == -1 { + work[0] = float64(n * nb) + return true + } + if lwork < n { + panic(badWork) + } + if len(work) < lwork { + panic(badWork) + } + if n == 0 { + return true + } + ok = impl.Dtrtri(blas.Upper, blas.NonUnit, n, a, lda) + if !ok { + return false + } + nbmin := 2 + ldwork := nb + if nb > 1 && nb < n { + iws := max(ldwork*n, 1) + if lwork < iws { + nb = lwork / ldwork + nbmin = max(2, impl.Ilaenv(2, "DGETRI", " ", n, -1, -1, -1)) + } + } + bi := blas64.Implementation() + // TODO(btracey): Replace this with a more row-major oriented algorithm. + if nb < nbmin || nb >= n { + // Unblocked code. + for j := n - 1; j >= 0; j-- { + for i := j + 1; i < n; i++ { + work[i*ldwork] = a[i*lda+j] + a[i*lda+j] = 0 + } + if j < n { + bi.Dgemv(blas.NoTrans, n, n-j-1, -1, a[(j+1):], lda, work[(j+1)*ldwork:], ldwork, 1, a[j:], lda) + } + } + } else { + nn := ((n - 1) / nb) * nb + for j := nn; j >= 0; j -= nb { + jb := min(nb, n-j) + for jj := j; jj < j+jb-1; jj++ { + for i := jj + 1; i < n; i++ { + work[i*ldwork+(jj-j)] = a[i*lda+jj] + a[i*lda+jj] = 0 + } + } + if j+jb < n { + 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) + bi.Dtrsm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, n, jb, 1, work[j*ldwork:], ldwork, a[j:], lda) + } + } + } + for j := n - 2; j >= 0; j-- { + jp := ipiv[j] + if jp != j { + bi.Dswap(n, a[j:], lda, a[jp:], lda) + } + } + return true +} diff --git a/lapack/native/dgetrs.go b/lapack/native/dgetrs.go new file mode 100644 index 00000000..17a6ade8 --- /dev/null +++ b/lapack/native/dgetrs.go @@ -0,0 +1,55 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dgetrs solves a system of equations using an LU factorization. +// The system of equations solved is +// A * X = B if trans == blas.Trans +// A^T * X = B if trans == blas.NoTrans +// A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs. +// +// On entry b contains the elements of the matrix B. On exit, b contains the +// elements of X, the solution to the system of equations. +// +// a and ipiv contain the LU factorization of A and the permutation indices as +// computed by Dgetrf. ipiv is zero-indexed. +func (impl Implementation) Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) { + checkMatrix(n, n, a, lda) + checkMatrix(n, nrhs, b, ldb) + if len(ipiv) < n { + panic(badIpiv) + } + if n == 0 || nrhs == 0 { + return + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + bi := blas64.Implementation() + if trans == blas.NoTrans { + // Solve A * X = B. + impl.Dlaswp(nrhs, b, ldb, 0, n-1, ipiv, 1) + // Solve L * X = B, updating b. + bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.Unit, + n, nrhs, 1, a, lda, b, ldb) + // Solve U * X = B, updating b. + bi.Dtrsm(blas.Left, blas.Upper, blas.NoTrans, blas.NonUnit, + n, nrhs, 1, a, lda, b, ldb) + return + } + // Solve A^T * X = B. + // Solve U^T * X = B, updating b. + bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, + n, nrhs, 1, a, lda, b, ldb) + // Solve L^T * X = B, updating b. + bi.Dtrsm(blas.Left, blas.Lower, blas.Trans, blas.Unit, + n, nrhs, 1, a, lda, b, ldb) + impl.Dlaswp(nrhs, b, ldb, 0, n-1, ipiv, -1) +} diff --git a/lapack/native/dggsvd3.go b/lapack/native/dggsvd3.go new file mode 100644 index 00000000..0ec8bbb3 --- /dev/null +++ b/lapack/native/dggsvd3.go @@ -0,0 +1,230 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dggsvd3 computes the generalized singular value decomposition (GSVD) +// of an m×n matrix A and p×n matrix B: +// U^T*A*Q = D1*[ 0 R ] +// +// V^T*B*Q = D2*[ 0 R ] +// where U, V and Q are orthogonal matrices. +// +// Dggsvd3 returns k and l, the dimensions of the sub-blocks. k+l +// is the effective numerical rank of the (m+p)×n matrix [ A^T B^T ]^T. +// R is a (k+l)×(k+l) nonsingular upper triangular matrix, D1 and +// D2 are m×(k+l) and p×(k+l) diagonal matrices and of the following +// structures, respectively: +// +// If m-k-l >= 0, +// +// k l +// D1 = k [ I 0 ] +// l [ 0 C ] +// m-k-l [ 0 0 ] +// +// k l +// D2 = l [ 0 S ] +// p-l [ 0 0 ] +// +// n-k-l k l +// [ 0 R ] = k [ 0 R11 R12 ] k +// l [ 0 0 R22 ] l +// +// where +// +// C = diag( alpha_k, ... , alpha_{k+l} ), +// S = diag( beta_k, ... , beta_{k+l} ), +// C^2 + S^2 = I. +// +// R is stored in +// A[0:k+l, n-k-l:n] +// on exit. +// +// If m-k-l < 0, +// +// k m-k k+l-m +// D1 = k [ I 0 0 ] +// m-k [ 0 C 0 ] +// +// k m-k k+l-m +// D2 = m-k [ 0 S 0 ] +// k+l-m [ 0 0 I ] +// p-l [ 0 0 0 ] +// +// n-k-l k m-k k+l-m +// [ 0 R ] = k [ 0 R11 R12 R13 ] +// m-k [ 0 0 R22 R23 ] +// k+l-m [ 0 0 0 R33 ] +// +// where +// C = diag( alpha_k, ... , alpha_m ), +// S = diag( beta_k, ... , beta_m ), +// C^2 + S^2 = I. +// +// R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n] +// [ 0 R22 R23 ] +// and R33 is stored in +// B[m-k:l, n+m-k-l:n] on exit. +// +// Dggsvd3 computes C, S, R, and optionally the orthogonal transformation +// matrices U, V and Q. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// alpha and beta must have length n or Dggsvd3 will panic. On exit, alpha and +// beta contain the generalized singular value pairs of A and B +// alpha[0:k] = 1, +// beta[0:k] = 0, +// if m-k-l >= 0, +// alpha[k:k+l] = diag(C), +// beta[k:k+l] = diag(S), +// if m-k-l < 0, +// alpha[k:m]= C, alpha[m:k+l]= 0 +// beta[k:m] = S, beta[m:k+l] = 1. +// if k+l < n, +// alpha[k+l:n] = 0 and +// beta[k+l:n] = 0. +// +// On exit, iwork contains the permutation required to sort alpha descending. +// +// iwork must have length n, work must have length at least max(1, lwork), and +// lwork must be -1 or greater than n, otherwise Dggsvd3 will panic. If +// lwork is -1, work[0] holds the optimal lwork on return, but Dggsvd3 does +// not perform the GSVD. +func (impl Implementation) Dggsvd3(jobU, jobV, jobQ lapack.GSVDJob, m, n, p int, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int) (k, l int, ok bool) { + checkMatrix(m, n, a, lda) + checkMatrix(p, n, b, ldb) + + wantu := jobU == lapack.GSVDU + if wantu { + checkMatrix(m, m, u, ldu) + } else if jobU != lapack.GSVDNone { + panic(badGSVDJob + "U") + } + wantv := jobV == lapack.GSVDV + if wantv { + checkMatrix(p, p, v, ldv) + } else if jobV != lapack.GSVDNone { + panic(badGSVDJob + "V") + } + wantq := jobQ == lapack.GSVDQ + if wantq { + checkMatrix(n, n, q, ldq) + } else if jobQ != lapack.GSVDNone { + panic(badGSVDJob + "Q") + } + + if len(alpha) != n { + panic(badAlpha) + } + if len(beta) != n { + panic(badBeta) + } + + if lwork != -1 && lwork <= n { + panic(badWork) + } + if len(work) < max(1, lwork) { + panic(shortWork) + } + if len(iwork) < n { + panic(badWork) + } + + // Determine optimal work length. + impl.Dggsvp3(jobU, jobV, jobQ, + m, p, n, + a, lda, + b, ldb, + 0, 0, + u, ldu, + v, ldv, + q, ldq, + iwork, + work, work, -1) + lwkopt := n + int(work[0]) + lwkopt = max(lwkopt, 2*n) + lwkopt = max(lwkopt, 1) + work[0] = float64(lwkopt) + if lwork == -1 { + return 0, 0, true + } + + // Compute the Frobenius norm of matrices A and B. + anorm := impl.Dlange(lapack.NormFrob, m, n, a, lda, nil) + bnorm := impl.Dlange(lapack.NormFrob, p, n, b, ldb, nil) + + // Get machine precision and set up threshold for determining + // the effective numerical rank of the matrices A and B. + tola := float64(max(m, n)) * math.Max(anorm, dlamchS) * dlamchP + tolb := float64(max(p, n)) * math.Max(bnorm, dlamchS) * dlamchP + + // Preprocessing. + k, l = impl.Dggsvp3(jobU, jobV, jobQ, + m, p, n, + a, lda, + b, ldb, + tola, tolb, + u, ldu, + v, ldv, + q, ldq, + iwork, + work[:n], work[n:], lwork-n) + + // Compute the GSVD of two upper "triangular" matrices. + _, ok = impl.Dtgsja(jobU, jobV, jobQ, + m, p, n, + k, l, + a, lda, + b, ldb, + tola, tolb, + alpha, beta, + u, ldu, + v, ldv, + q, ldq, + work) + + // Sort the singular values and store the pivot indices in iwork + // Copy alpha to work, then sort alpha in work. + bi := blas64.Implementation() + bi.Dcopy(n, alpha, 1, work[:n], 1) + ibnd := min(l, m-k) + for i := 0; i < ibnd; i++ { + // Scan for largest alpha_{k+i}. + isub := i + smax := work[k+i] + for j := i + 1; j < ibnd; j++ { + if v := work[k+j]; v > smax { + isub = j + smax = v + } + } + if isub != i { + work[k+isub] = work[k+i] + work[k+i] = smax + iwork[k+i] = k + isub + } else { + iwork[k+i] = k + i + } + } + + work[0] = float64(lwkopt) + + return k, l, ok +} diff --git a/lapack/native/dggsvp3.go b/lapack/native/dggsvp3.go new file mode 100644 index 00000000..2821895e --- /dev/null +++ b/lapack/native/dggsvp3.go @@ -0,0 +1,273 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dggsvp3 computes orthogonal matrices U, V and Q such that +// +// n-k-l k l +// U^T*A*Q = k [ 0 A12 A13 ] if m-k-l >= 0; +// l [ 0 0 A23 ] +// m-k-l [ 0 0 0 ] +// +// n-k-l k l +// U^T*A*Q = k [ 0 A12 A13 ] if m-k-l < 0; +// m-k [ 0 0 A23 ] +// +// n-k-l k l +// V^T*B*Q = l [ 0 0 B13 ] +// p-l [ 0 0 0 ] +// +// where the k×k matrix A12 and l×l matrix B13 are non-singular +// upper triangular. A23 is l×l upper triangular if m-k-l >= 0, +// otherwise A23 is (m-k)×l upper trapezoidal. +// +// Dggsvp3 returns k and l, the dimensions of the sub-blocks. k+l +// is the effective numerical rank of the (m+p)×n matrix [ A^T B^T ]^T. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// tola and tolb are the convergence criteria for the Jacobi-Kogbetliantz +// iteration procedure. Generally, they are the same as used in the preprocessing +// step, for example, +// tola = max(m, n)*norm(A)*eps, +// tolb = max(p, n)*norm(B)*eps. +// Where eps is the machine epsilon. +// +// iwork must have length n, work must have length at least max(1, lwork), and +// lwork must be -1 or greater than zero, otherwise Dggsvp3 will panic. +// +// Dggsvp3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, iwork []int, tau, work []float64, lwork int) (k, l int) { + const forward = true + + checkMatrix(m, n, a, lda) + checkMatrix(p, n, b, ldb) + + wantu := jobU == lapack.GSVDU + if !wantu && jobU != lapack.GSVDNone { + panic(badGSVDJob + "U") + } + if jobU != lapack.GSVDNone { + checkMatrix(m, m, u, ldu) + } + + wantv := jobV == lapack.GSVDV + if !wantv && jobV != lapack.GSVDNone { + panic(badGSVDJob + "V") + } + if jobV != lapack.GSVDNone { + checkMatrix(p, p, v, ldv) + } + + wantq := jobQ == lapack.GSVDQ + if !wantq && jobQ != lapack.GSVDNone { + panic(badGSVDJob + "Q") + } + if jobQ != lapack.GSVDNone { + checkMatrix(n, n, q, ldq) + } + + if len(iwork) != n { + panic(badWork) + } + if lwork != -1 && lwork < 1 { + panic(badWork) + } + if len(work) < max(1, lwork) { + panic(badWork) + } + + var lwkopt int + impl.Dgeqp3(p, n, b, ldb, iwork, tau, work, -1) + lwkopt = int(work[0]) + if wantv { + lwkopt = max(lwkopt, p) + } + lwkopt = max(lwkopt, min(n, p)) + lwkopt = max(lwkopt, m) + if wantq { + lwkopt = max(lwkopt, n) + } + impl.Dgeqp3(m, n, a, lda, iwork, tau, work, -1) + lwkopt = max(lwkopt, int(work[0])) + lwkopt = max(1, lwkopt) + if lwork == -1 { + work[0] = float64(lwkopt) + return 0, 0 + } + + // tau check must come after lwkopt query since + // the Dggsvd3 call for lwkopt query may have + // lwork == -1, and tau is provided by work. + if len(tau) < n { + panic(badTau) + } + + // QR with column pivoting of B: B*P = V*[ S11 S12 ]. + // [ 0 0 ] + for i := range iwork[:n] { + iwork[i] = 0 + } + impl.Dgeqp3(p, n, b, ldb, iwork, tau, work, lwork) + + // Update A := A*P. + impl.Dlapmt(forward, m, n, a, lda, iwork) + + // Determine the effective rank of matrix B. + for i := 0; i < min(p, n); i++ { + if math.Abs(b[i*ldb+i]) > tolb { + l++ + } + } + + if wantv { + // Copy the details of V, and form V. + impl.Dlaset(blas.All, p, p, 0, 0, v, ldv) + if p > 1 { + impl.Dlacpy(blas.Lower, p-1, min(p, n), b[ldb:], ldb, v[ldv:], ldv) + } + impl.Dorg2r(p, p, min(p, n), v, ldv, tau, work) + } + + // Clean up B. + for i := 1; i < l; i++ { + r := b[i*ldb : i*ldb+i] + for j := range r { + r[j] = 0 + } + } + if p > l { + impl.Dlaset(blas.All, p-l, n, 0, 0, b[l*ldb:], ldb) + } + + if wantq { + // Set Q = I and update Q := Q*P. + impl.Dlaset(blas.All, n, n, 0, 1, q, ldq) + impl.Dlapmt(forward, n, n, q, ldq, iwork) + } + + if p >= l && n != l { + // RQ factorization of [ S11 S12 ]: [ S11 S12 ] = [ 0 S12 ]*Z. + impl.Dgerq2(l, n, b, ldb, tau, work) + + // Update A := A*Z^T. + impl.Dormr2(blas.Right, blas.Trans, m, n, l, b, ldb, tau, a, lda, work) + + if wantq { + // Update Q := Q*Z^T. + impl.Dormr2(blas.Right, blas.Trans, n, n, l, b, ldb, tau, q, ldq, work) + } + + // Clean up B. + impl.Dlaset(blas.All, l, n-l, 0, 0, b, ldb) + for i := 1; i < l; i++ { + r := b[i*ldb+n-l : i*ldb+i+n-l] + for j := range r { + r[j] = 0 + } + } + } + + // Let N-L L + // A = [ A11 A12 ] M, + // + // then the following does the complete QR decomposition of A11: + // + // A11 = U*[ 0 T12 ]*P1^T. + // [ 0 0 ] + for i := range iwork[:n-l] { + iwork[i] = 0 + } + impl.Dgeqp3(m, n-l, a, lda, iwork[:n-l], tau, work, lwork) + + // Determine the effective rank of A11. + for i := 0; i < min(m, n-l); i++ { + if math.Abs(a[i*lda+i]) > tola { + k++ + } + } + + // Update A12 := U^T*A12, where A12 = A[0:m, n-l:n]. + impl.Dorm2r(blas.Left, blas.Trans, m, l, min(m, n-l), a, lda, tau, a[n-l:], lda, work) + + if wantu { + // Copy the details of U, and form U. + impl.Dlaset(blas.All, m, m, 0, 0, u, ldu) + if m > 1 { + impl.Dlacpy(blas.Lower, m-1, min(m, n-l), a[lda:], lda, u[ldu:], ldu) + } + impl.Dorg2r(m, m, min(m, n-l), u, ldu, tau, work) + } + + if wantq { + // Update Q[0:n, 0:n-l] := Q[0:n, 0:n-l]*P1. + impl.Dlapmt(forward, n, n-l, q, ldq, iwork[:n-l]) + } + + // Clean up A: set the strictly lower triangular part of + // A[0:k, 0:k] = 0, and A[k:m, 0:n-l] = 0. + for i := 1; i < k; i++ { + r := a[i*lda : i*lda+i] + for j := range r { + r[j] = 0 + } + } + if m > k { + impl.Dlaset(blas.All, m-k, n-l, 0, 0, a[k*lda:], lda) + } + + if n-l > k { + // RQ factorization of [ T11 T12 ] = [ 0 T12 ]*Z1. + impl.Dgerq2(k, n-l, a, lda, tau, work) + + if wantq { + // Update Q[0:n, 0:n-l] := Q[0:n, 0:n-l]*Z1^T. + impl.Dorm2r(blas.Right, blas.Trans, n, n-l, k, a, lda, tau, q, ldq, work) + } + + // Clean up A. + impl.Dlaset(blas.All, k, n-l-k, 0, 0, a, lda) + for i := 1; i < k; i++ { + r := a[i*lda+n-k-l : i*lda+i+n-k-l] + for j := range r { + a[j] = 0 + } + } + } + + if m > k { + // QR factorization of A[k:m, n-l:n]. + impl.Dgeqr2(m-k, l, a[k*lda+n-l:], lda, tau, work) + if wantu { + // Update U[:, k:m) := U[:, k:m]*U1. + impl.Dorm2r(blas.Right, blas.NoTrans, m, m-k, min(m-k, l), a[k*lda+n-l:], lda, tau, u[k:], ldu, work) + } + + // Clean up A. + for i := k + 1; i < m; i++ { + r := a[i*lda+n-l : i*lda+min(n-l+i-k, n)] + for j := range r { + r[j] = 0 + } + } + } + + work[0] = float64(lwkopt) + return k, l +} diff --git a/lapack/native/dhseqr.go b/lapack/native/dhseqr.go new file mode 100644 index 00000000..60ae61f5 --- /dev/null +++ b/lapack/native/dhseqr.go @@ -0,0 +1,257 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dhseqr computes the eigenvalues of an n×n Hessenberg matrix H and, +// optionally, the matrices T and Z from the Schur decomposition +// H = Z T Z^T, +// where T is an n×n upper quasi-triangular matrix (the Schur form), and Z is +// the n×n orthogonal matrix of Schur vectors. +// +// Optionally Z may be postmultiplied into an input orthogonal matrix Q so that +// this routine can give the Schur factorization of a matrix A which has been +// reduced to the Hessenberg form H by the orthogonal matrix Q: +// A = Q H Q^T = (QZ) T (QZ)^T. +// +// If job == lapack.EigenvaluesOnly, only the eigenvalues will be computed. +// If job == lapack.EigenvaluesAndSchur, the eigenvalues and the Schur form T will +// be computed. +// For other values of job Dhseqr will panic. +// +// If compz == lapack.None, no Schur vectors will be computed and Z will not be +// referenced. +// If compz == lapack.HessEV, on return Z will contain the matrix of Schur +// vectors of H. +// If compz == lapack.OriginalEV, on entry z is assumed to contain the orthogonal +// matrix Q that is the identity except for the submatrix +// Q[ilo:ihi+1,ilo:ihi+1]. On return z will be updated to the product Q*Z. +// +// ilo and ihi determine the block of H on which Dhseqr operates. It is assumed +// that H is already upper triangular in rows and columns [0:ilo] and [ihi+1:n], +// although it will be only checked that the block is isolated, that is, +// ilo == 0 or H[ilo,ilo-1] == 0, +// ihi == n-1 or H[ihi+1,ihi] == 0, +// and Dhseqr will panic otherwise. ilo and ihi are typically set by a previous +// call to Dgebal, otherwise they should be set to 0 and n-1, respectively. It +// must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo == 0 and ihi == -1, if n == 0. +// +// wr and wi must have length n. +// +// work must have length at least lwork and lwork must be at least max(1,n) +// otherwise Dhseqr will panic. The minimum lwork delivers very good and +// sometimes optimal performance, although lwork as large as 11*n may be +// required. On return, work[0] will contain the optimal value of lwork. +// +// If lwork is -1, instead of performing Dhseqr, the function only estimates the +// optimal workspace size and stores it into work[0]. Neither h nor z are +// accessed. +// +// unconverged indicates whether Dhseqr computed all the eigenvalues. +// +// If unconverged == 0, all the eigenvalues have been computed and their real +// and imaginary parts will be stored on return in wr and wi, respectively. If +// two eigenvalues are computed as a complex conjugate pair, they are stored in +// consecutive elements of wr and wi, say the i-th and (i+1)th, with wi[i] > 0 +// and wi[i+1] < 0. +// +// If unconverged == 0 and job == lapack.EigenvaluesAndSchur, on return H will +// contain the upper quasi-triangular matrix T from the Schur decomposition (the +// Schur form). 2×2 diagonal blocks (corresponding to complex conjugate pairs of +// eigenvalues) will be returned in standard form, with +// H[i,i] == H[i+1,i+1], +// and +// H[i+1,i]*H[i,i+1] < 0. +// The eigenvalues will be stored in wr and wi in the same order as on the +// diagonal of the Schur form returned in H, with +// wr[i] = H[i,i], +// and, if H[i:i+2,i:i+2] is a 2×2 diagonal block, +// wi[i] = sqrt(-H[i+1,i]*H[i,i+1]), +// wi[i+1] = -wi[i]. +// +// If unconverged == 0 and job == lapack.EigenvaluesOnly, the contents of h +// on return is unspecified. +// +// If unconverged > 0, some eigenvalues have not converged, and the blocks +// [0:ilo] and [unconverged:n] of wr and wi will contain those eigenvalues which +// have been successfully computed. Failures are rare. +// +// If unconverged > 0 and job == lapack.EigenvaluesOnly, on return the +// remaining unconverged eigenvalues are the eigenvalues of the upper Hessenberg +// matrix H[ilo:unconverged,ilo:unconverged]. +// +// If unconverged > 0 and job == lapack.EigenvaluesAndSchur, then on +// return +// (initial H) U = U (final H), (*) +// where U is an orthogonal matrix. The final H is upper Hessenberg and +// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. +// +// If unconverged > 0 and compz == lapack.OriginalEV, then on return +// (final Z) = (initial Z) U, +// where U is the orthogonal matrix in (*) regardless of the value of job. +// +// If unconverged > 0 and compz == lapack.HessEV, then on return +// (final Z) = U, +// where U is the orthogonal matrix in (*) regardless of the value of job. +// +// References: +// [1] R. Byers. LAPACK 3.1 xHSEQR: Tuning and Implementation Notes on the +// Small Bulge Multi-Shift QR Algorithm with Aggressive Early Deflation. +// LAPACK Working Note 187 (2007) +// URL: http://www.netlib.org/lapack/lawnspdf/lawn187.pdf +// [2] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part I: +// Maintaining Well-Focused Shifts and Level 3 Performance. SIAM J. Matrix +// Anal. Appl. 23(4) (2002), pp. 929—947 +// URL: http://dx.doi.org/10.1137/S0895479801384573 +// [3] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: +// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl. 23(4) (2002), pp. 948—973 +// URL: http://dx.doi.org/10.1137/S0895479801384585 +// +// Dhseqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dhseqr(job lapack.EVJob, compz lapack.EVComp, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, z []float64, ldz int, work []float64, lwork int) (unconverged int) { + var wantt bool + switch job { + default: + panic(badEVJob) + case lapack.EigenvaluesOnly: + case lapack.EigenvaluesAndSchur: + wantt = true + } + var wantz bool + switch compz { + default: + panic(badEVComp) + case lapack.None: + case lapack.HessEV, lapack.OriginalEV: + wantz = true + } + switch { + case n < 0: + panic(nLT0) + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case len(work) < lwork: + panic(shortWork) + case lwork < max(1, n) && lwork != -1: + panic(badWork) + } + if lwork != -1 { + checkMatrix(n, n, h, ldh) + switch { + case wantz: + checkMatrix(n, n, z, ldz) + case len(wr) < n: + panic("lapack: wr has insufficient length") + case len(wi) < n: + panic("lapack: wi has insufficient length") + } + } + + const ( + // Matrices of order ntiny or smaller must be processed by + // Dlahqr because of insufficient subdiagonal scratch space. + // This is a hard limit. + ntiny = 11 + + // nl is the size of a local workspace to help small matrices + // through a rare Dlahqr failure. nl > ntiny is required and + // nl <= nmin = Ilaenv(ispec=12,...) is recommended (the default + // value of nmin is 75). Using nl = 49 allows up to six + // simultaneous shifts and a 16×16 deflation window. + nl = 49 + ) + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return 0 + } + + // Quick return in case of a workspace query. + if lwork == -1 { + impl.Dlaqr04(wantt, wantz, n, ilo, ihi, nil, 0, nil, nil, ilo, ihi, nil, 0, work, -1, 1) + work[0] = math.Max(float64(n), work[0]) + return 0 + } + + // Copy eigenvalues isolated by Dgebal. + for i := 0; i < ilo; i++ { + wr[i] = h[i*ldh+i] + wi[i] = 0 + } + for i := ihi + 1; i < n; i++ { + wr[i] = h[i*ldh+i] + wi[i] = 0 + } + + // Initialize Z to identity matrix if requested. + if compz == lapack.HessEV { + impl.Dlaset(blas.All, n, n, 0, 1, z, ldz) + } + + // Quick return if possible. + if ilo == ihi { + wr[ilo] = h[ilo*ldh+ilo] + wi[ilo] = 0 + return 0 + } + + // Dlahqr/Dlaqr04 crossover point. + nmin := impl.Ilaenv(12, "DHSEQR", string(job)+string(compz), n, ilo, ihi, lwork) + nmin = max(ntiny, nmin) + + if n > nmin { + // Dlaqr0 for big matrices. + unconverged = impl.Dlaqr04(wantt, wantz, n, ilo, ihi, h, ldh, wr[:ihi+1], wi[:ihi+1], + ilo, ihi, z, ldz, work, lwork, 1) + } else { + // Dlahqr for small matrices. + unconverged = impl.Dlahqr(wantt, wantz, n, ilo, ihi, h, ldh, wr[:ihi+1], wi[:ihi+1], + ilo, ihi, z, ldz) + if unconverged > 0 { + // A rare Dlahqr failure! Dlaqr04 sometimes succeeds + // when Dlahqr fails. + kbot := unconverged + if n >= nl { + // Larger matrices have enough subdiagonal + // scratch space to call Dlaqr04 directly. + unconverged = impl.Dlaqr04(wantt, wantz, n, ilo, kbot, h, ldh, + wr[:ihi+1], wi[:ihi+1], ilo, ihi, z, ldz, work, lwork, 1) + } else { + // Tiny matrices don't have enough subdiagonal + // scratch space to benefit from Dlaqr04. Hence, + // tiny matrices must be copied into a larger + // array before calling Dlaqr04. + var hl [nl * nl]float64 + impl.Dlacpy(blas.All, n, n, h, ldh, hl[:], nl) + impl.Dlaset(blas.All, nl, nl-n, 0, 0, hl[n:], nl) + var workl [nl]float64 + unconverged = impl.Dlaqr04(wantt, wantz, nl, ilo, kbot, hl[:], nl, + wr[:ihi+1], wi[:ihi+1], ilo, ihi, z, ldz, workl[:], nl, 1) + work[0] = workl[0] + if wantt || unconverged > 0 { + impl.Dlacpy(blas.All, n, n, hl[:], nl, h, ldh) + } + } + } + } + // Zero out under the first subdiagonal, if necessary. + if (wantt || unconverged > 0) && n > 2 { + impl.Dlaset(blas.Lower, n-2, n-2, 0, 0, h[2*ldh:], ldh) + } + + work[0] = math.Max(float64(n), work[0]) + return unconverged +} diff --git a/lapack/native/dlabrd.go b/lapack/native/dlabrd.go new file mode 100644 index 00000000..967c45b7 --- /dev/null +++ b/lapack/native/dlabrd.go @@ -0,0 +1,150 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlabrd reduces the first NB rows and columns of a real general m×n matrix +// A to upper or lower bidiagonal form by an orthogonal transformation +// Q**T * A * P +// If m >= n, A is reduced to upper bidiagonal form and upon exit the elements +// on and below the diagonal in the first nb columns represent the elementary +// reflectors, and the elements above the diagonal in the first nb rows represent +// the matrix P. If m < n, A is reduced to lower bidiagonal form and the elements +// P is instead stored above the diagonal. +// +// The reduction to bidiagonal form is stored in d and e, where d are the diagonal +// elements, and e are the off-diagonal elements. +// +// The matrices Q and P are products of elementary reflectors +// Q = H_0 * H_1 * ... * H_{nb-1} +// P = G_0 * G_1 * ... * G_{nb-1} +// where +// H_i = I - tauQ[i] * v_i * v_i^T +// G_i = I - tauP[i] * u_i * u_i^T +// +// As an example, on exit the entries of A when m = 6, n = 5, and nb = 2 +// [ 1 1 u1 u1 u1] +// [v1 1 1 u2 u2] +// [v1 v2 a a a] +// [v1 v2 a a a] +// [v1 v2 a a a] +// [v1 v2 a a a] +// and when m = 5, n = 6, and nb = 2 +// [ 1 u1 u1 u1 u1 u1] +// [ 1 1 u2 u2 u2 u2] +// [v1 1 a a a a] +// [v1 v2 a a a a] +// [v1 v2 a a a a] +// +// Dlabrd also returns the matrices X and Y which are used with U and V to +// apply the transformation to the unreduced part of the matrix +// A := A - V*Y^T - X*U^T +// and returns the matrices X and Y which are needed to apply the +// transformation to the unreduced part of A. +// +// X is an m×nb matrix, Y is an n×nb matrix. d, e, taup, and tauq must all have +// length at least nb. Dlabrd will panic if these size constraints are violated. +// +// Dlabrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlabrd(m, n, nb int, a []float64, lda int, d, e, tauQ, tauP, x []float64, ldx int, y []float64, ldy int) { + checkMatrix(m, n, a, lda) + checkMatrix(m, nb, x, ldx) + checkMatrix(n, nb, y, ldy) + if len(d) < nb { + panic(badD) + } + if len(e) < nb { + panic(badE) + } + if len(tauQ) < nb { + panic(badTauQ) + } + if len(tauP) < nb { + panic(badTauP) + } + if m <= 0 || n <= 0 { + return + } + bi := blas64.Implementation() + if m >= n { + // Reduce to upper bidiagonal form. + for i := 0; i < nb; i++ { + bi.Dgemv(blas.NoTrans, m-i, i, -1, a[i*lda:], lda, y[i*ldy:], 1, 1, a[i*lda+i:], lda) + bi.Dgemv(blas.NoTrans, m-i, i, -1, x[i*ldx:], ldx, a[i:], lda, 1, a[i*lda+i:], lda) + + a[i*lda+i], tauQ[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min(i+1, m-1)*lda+i:], lda) + d[i] = a[i*lda+i] + if i < n-1 { + // Compute Y[i+1:n, i]. + a[i*lda+i] = 1 + bi.Dgemv(blas.Trans, m-i, n-i-1, 1, a[i*lda+i+1:], lda, a[i*lda+i:], lda, 0, y[(i+1)*ldy+i:], ldy) + bi.Dgemv(blas.Trans, m-i, i, 1, a[i*lda:], lda, a[i*lda+i:], lda, 0, y[i:], ldy) + bi.Dgemv(blas.NoTrans, n-i-1, i, -1, y[(i+1)*ldy:], ldy, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) + bi.Dgemv(blas.Trans, m-i, i, 1, x[i*ldx:], ldx, a[i*lda+i:], lda, 0, y[i:], ldy) + bi.Dgemv(blas.Trans, i, n-i-1, -1, a[i+1:], lda, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) + bi.Dscal(n-i-1, tauQ[i], y[(i+1)*ldy+i:], ldy) + + // Update A[i, i+1:n]. + bi.Dgemv(blas.NoTrans, n-i-1, i+1, -1, y[(i+1)*ldy:], ldy, a[i*lda:], 1, 1, a[i*lda+i+1:], 1) + bi.Dgemv(blas.Trans, i, n-i-1, -1, a[i+1:], lda, x[i*ldx:], 1, 1, a[i*lda+i+1:], 1) + + // Generate reflection P[i] to annihilate A[i, i+2:n]. + 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) + e[i] = a[i*lda+i+1] + a[i*lda+i+1] = 1 + + // Compute X[i+1:m, i]. + bi.Dgemv(blas.NoTrans, m-i-1, n-i-1, 1, a[(i+1)*lda+i+1:], lda, a[i*lda+i+1:], 1, 0, x[(i+1)*ldx+i:], ldx) + bi.Dgemv(blas.Trans, n-i-1, i+1, 1, y[(i+1)*ldy:], ldy, a[i*lda+i+1:], 1, 0, x[i:], ldx) + bi.Dgemv(blas.NoTrans, m-i-1, i+1, -1, a[(i+1)*lda:], lda, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) + bi.Dgemv(blas.NoTrans, i, n-i-1, 1, a[i+1:], lda, a[i*lda+i+1:], 1, 0, x[i:], ldx) + bi.Dgemv(blas.NoTrans, m-i-1, i, -1, x[(i+1)*ldx:], ldx, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) + bi.Dscal(m-i-1, tauP[i], x[(i+1)*ldx+i:], ldx) + } + } + return + } + // Reduce to lower bidiagonal form. + for i := 0; i < nb; i++ { + // Update A[i,i:n] + bi.Dgemv(blas.NoTrans, n-i, i, -1, y[i*ldy:], ldy, a[i*lda:], 1, 1, a[i*lda+i:], 1) + bi.Dgemv(blas.Trans, i, n-i, -1, a[i:], lda, x[i*ldx:], 1, 1, a[i*lda+i:], 1) + + // Generate reflection P[i] to annihilate A[i, i+1:n] + a[i*lda+i], tauP[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) + d[i] = a[i*lda+i] + if i < m-1 { + a[i*lda+i] = 1 + // Compute X[i+1:m, i]. + bi.Dgemv(blas.NoTrans, m-i-1, n-i, 1, a[(i+1)*lda+i:], lda, a[i*lda+i:], 1, 0, x[(i+1)*ldx+i:], ldx) + bi.Dgemv(blas.Trans, n-i, i, 1, y[i*ldy:], ldy, a[i*lda+i:], 1, 0, x[i:], ldx) + bi.Dgemv(blas.NoTrans, m-i-1, i, -1, a[(i+1)*lda:], lda, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) + bi.Dgemv(blas.NoTrans, i, n-i, 1, a[i:], lda, a[i*lda+i:], 1, 0, x[i:], ldx) + bi.Dgemv(blas.NoTrans, m-i-1, i, -1, x[(i+1)*ldx:], ldx, x[i:], ldx, 1, x[(i+1)*ldx+i:], ldx) + bi.Dscal(m-i-1, tauP[i], x[(i+1)*ldx+i:], ldx) + + // Update A[i+1:m, i]. + bi.Dgemv(blas.NoTrans, m-i-1, i, -1, a[(i+1)*lda:], lda, y[i*ldy:], 1, 1, a[(i+1)*lda+i:], lda) + bi.Dgemv(blas.NoTrans, m-i-1, i+1, -1, x[(i+1)*ldx:], ldx, a[i:], lda, 1, a[(i+1)*lda+i:], lda) + + // Generate reflection Q[i] to annihilate A[i+2:m, i]. + 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) + e[i] = a[(i+1)*lda+i] + a[(i+1)*lda+i] = 1 + + // Compute Y[i+1:n, i]. + bi.Dgemv(blas.Trans, m-i-1, n-i-1, 1, a[(i+1)*lda+i+1:], lda, a[(i+1)*lda+i:], lda, 0, y[(i+1)*ldy+i:], ldy) + bi.Dgemv(blas.Trans, m-i-1, i, 1, a[(i+1)*lda:], lda, a[(i+1)*lda+i:], lda, 0, y[i:], ldy) + bi.Dgemv(blas.NoTrans, n-i-1, i, -1, y[(i+1)*ldy:], ldy, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) + bi.Dgemv(blas.Trans, m-i-1, i+1, 1, x[(i+1)*ldx:], ldx, a[(i+1)*lda+i:], lda, 0, y[i:], ldy) + bi.Dgemv(blas.Trans, i+1, n-i-1, -1, a[i+1:], lda, y[i:], ldy, 1, y[(i+1)*ldy+i:], ldy) + bi.Dscal(n-i-1, tauQ[i], y[(i+1)*ldy+i:], ldy) + } + } +} diff --git a/lapack/native/dlacn2.go b/lapack/native/dlacn2.go new file mode 100644 index 00000000..4918eadb --- /dev/null +++ b/lapack/native/dlacn2.go @@ -0,0 +1,134 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlacn2 estimates the 1-norm of an n×n matrix A using sequential updates with +// matrix-vector products provided externally. +// +// Dlacn2 is called sequentially and it returns the value of est and kase to be +// used on the next call. +// On the initial call, kase must be 0. +// In between calls, x must be overwritten by +// A * X if kase was returned as 1, +// A^T * X if kase was returned as 2, +// and all other parameters must not be changed. +// On the final return, kase is returned as 0, v contains A*W where W is a +// vector, and est = norm(V)/norm(W) is a lower bound for 1-norm of A. +// +// v, x, and isgn must all have length n and n must be at least 1, otherwise +// Dlacn2 will panic. isave is used for temporary storage. +// +// Dlacn2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlacn2(n int, v, x []float64, isgn []int, est float64, kase int, isave *[3]int) (float64, int) { + if n < 1 { + panic("lapack: non-positive n") + } + checkVector(n, x, 1) + checkVector(n, v, 1) + if len(isgn) < n { + panic("lapack: insufficient isgn length") + } + if isave[0] < 0 || isave[0] > 5 { + panic("lapack: bad isave value") + } + if isave[0] == 0 && kase != 0 { + panic("lapack: bad isave value") + } + itmax := 5 + bi := blas64.Implementation() + if kase == 0 { + for i := 0; i < n; i++ { + x[i] = 1 / float64(n) + } + kase = 1 + isave[0] = 1 + return est, kase + } + switch isave[0] { + default: + panic("unreachable") + case 1: + if n == 1 { + v[0] = x[0] + est = math.Abs(v[0]) + kase = 0 + return est, kase + } + est = bi.Dasum(n, x, 1) + for i := 0; i < n; i++ { + x[i] = math.Copysign(1, x[i]) + isgn[i] = int(x[i]) + } + kase = 2 + isave[0] = 2 + return est, kase + case 2: + isave[1] = bi.Idamax(n, x, 1) + isave[2] = 2 + for i := 0; i < n; i++ { + x[i] = 0 + } + x[isave[1]] = 1 + kase = 1 + isave[0] = 3 + return est, kase + case 3: + bi.Dcopy(n, x, 1, v, 1) + estold := est + est = bi.Dasum(n, v, 1) + sameSigns := true + for i := 0; i < n; i++ { + if int(math.Copysign(1, x[i])) != isgn[i] { + sameSigns = false + break + } + } + if !sameSigns && est > estold { + for i := 0; i < n; i++ { + x[i] = math.Copysign(1, x[i]) + isgn[i] = int(x[i]) + } + kase = 2 + isave[0] = 4 + return est, kase + } + case 4: + jlast := isave[1] + isave[1] = bi.Idamax(n, x, 1) + if x[jlast] != math.Abs(x[isave[1]]) && isave[2] < itmax { + isave[2] += 1 + for i := 0; i < n; i++ { + x[i] = 0 + } + x[isave[1]] = 1 + kase = 1 + isave[0] = 3 + return est, kase + } + case 5: + tmp := 2 * (bi.Dasum(n, x, 1)) / float64(3*n) + if tmp > est { + bi.Dcopy(n, x, 1, v, 1) + est = tmp + } + kase = 0 + return est, kase + } + // Iteration complete. Final stage + altsgn := 1.0 + for i := 0; i < n; i++ { + x[i] = altsgn * (1 + float64(i)/float64(n-1)) + altsgn *= -1 + } + kase = 1 + isave[0] = 5 + return est, kase +} diff --git a/lapack/native/dlacpy.go b/lapack/native/dlacpy.go new file mode 100644 index 00000000..f37be7fd --- /dev/null +++ b/lapack/native/dlacpy.go @@ -0,0 +1,40 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dlacpy copies the elements of A specified by uplo into B. Uplo can specify +// a triangular portion with blas.Upper or blas.Lower, or can specify all of the +// elemest with blas.All. +// +// Dlacpy is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) { + checkMatrix(m, n, a, lda) + checkMatrix(m, n, b, ldb) + switch uplo { + default: + panic(badUplo) + case blas.Upper: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + b[i*ldb+j] = a[i*lda+j] + } + } + + case blas.Lower: + for i := 0; i < m; i++ { + for j := 0; j < min(i+1, n); j++ { + b[i*ldb+j] = a[i*lda+j] + } + } + case blas.All: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + b[i*ldb+j] = a[i*lda+j] + } + } + } +} diff --git a/lapack/native/dlae2.go b/lapack/native/dlae2.go new file mode 100644 index 00000000..c2fb96ce --- /dev/null +++ b/lapack/native/dlae2.go @@ -0,0 +1,49 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlae2 computes the eigenvalues of a 2×2 symmetric matrix +// [a b] +// [b c] +// and returns the eigenvalue with the larger absolute value as rt1 and the +// smaller as rt2. +// +// Dlae2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlae2(a, b, c float64) (rt1, rt2 float64) { + sm := a + c + df := a - c + adf := math.Abs(df) + tb := b + b + ab := math.Abs(tb) + acmx := c + acmn := a + if math.Abs(a) > math.Abs(c) { + acmx = a + acmn = c + } + var rt float64 + if adf > ab { + rt = adf * math.Sqrt(1+(ab/adf)*(ab/adf)) + } else if adf < ab { + rt = ab * math.Sqrt(1+(adf/ab)*(adf/ab)) + } else { + rt = ab * math.Sqrt2 + } + if sm < 0 { + rt1 = 0.5 * (sm - rt) + rt2 = (acmx/rt1)*acmn - (b/rt1)*b + return rt1, rt2 + } + if sm > 0 { + rt1 = 0.5 * (sm + rt) + rt2 = (acmx/rt1)*acmn - (b/rt1)*b + return rt1, rt2 + } + rt1 = 0.5 * rt + rt2 = -0.5 * rt + return rt1, rt2 +} diff --git a/lapack/native/dlaev2.go b/lapack/native/dlaev2.go new file mode 100644 index 00000000..7cae50d7 --- /dev/null +++ b/lapack/native/dlaev2.go @@ -0,0 +1,82 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlaev2 computes the Eigen decomposition of a symmetric 2×2 matrix. +// The matrix is given by +// [a b] +// [b c] +// Dlaev2 returns rt1 and rt2, the eigenvalues of the matrix where |RT1| > |RT2|, +// and [cs1, sn1] which is the unit right eigenvalue for RT1. +// [ cs1 sn1] [a b] [cs1 -sn1] = [rt1 0] +// [-sn1 cs1] [b c] [sn1 cs1] [ 0 rt2] +// +// Dlaev2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaev2(a, b, c float64) (rt1, rt2, cs1, sn1 float64) { + sm := a + c + df := a - c + adf := math.Abs(df) + tb := b + b + ab := math.Abs(tb) + acmx := c + acmn := a + if math.Abs(a) > math.Abs(c) { + acmx = a + acmn = c + } + var rt float64 + if adf > ab { + rt = adf * math.Sqrt(1+(ab/adf)*(ab/adf)) + } else if adf < ab { + rt = ab * math.Sqrt(1+(adf/ab)*(adf/ab)) + } else { + rt = ab * math.Sqrt(2) + } + var sgn1 float64 + if sm < 0 { + rt1 = 0.5 * (sm - rt) + sgn1 = -1 + rt2 = (acmx/rt1)*acmn - (b/rt1)*b + } else if sm > 0 { + rt1 = 0.5 * (sm + rt) + sgn1 = 1 + rt2 = (acmx/rt1)*acmn - (b/rt1)*b + } else { + rt1 = 0.5 * rt + rt2 = -0.5 * rt + sgn1 = 1 + } + var cs, sgn2 float64 + if df >= 0 { + cs = df + rt + sgn2 = 1 + } else { + cs = df - rt + sgn2 = -1 + } + acs := math.Abs(cs) + if acs > ab { + ct := -tb / cs + sn1 = 1 / math.Sqrt(1+ct*ct) + cs1 = ct * sn1 + } else { + if ab == 0 { + cs1 = 1 + sn1 = 0 + } else { + tn := -cs / tb + cs1 = 1 / math.Sqrt(1+tn*tn) + sn1 = tn * cs1 + } + } + if sgn1 == sgn2 { + tn := cs1 + cs1 = -sn1 + sn1 = tn + } + return rt1, rt2, cs1, sn1 +} diff --git a/lapack/native/dlaexc.go b/lapack/native/dlaexc.go new file mode 100644 index 00000000..d4ab2274 --- /dev/null +++ b/lapack/native/dlaexc.go @@ -0,0 +1,261 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlaexc swaps two adjacent diagonal blocks of order 1 or 2 in an n×n upper +// quasi-triangular matrix T by an orthogonal similarity transformation. +// +// T must be in Schur canonical form, that is, block upper triangular with 1×1 +// and 2×2 diagonal blocks; each 2×2 diagonal block has its diagonal elements +// equal and its off-diagonal elements of opposite sign. On return, T will +// contain the updated matrix again in Schur canonical form. +// +// If wantq is true, the transformation is accumulated in the n×n matrix Q, +// otherwise Q is not referenced. +// +// j1 is the index of the first row of the first block. n1 and n2 are the order +// of the first and second block, respectively. +// +// work must have length at least n, otherwise Dlaexc will panic. +// +// If ok is false, the transformed matrix T would be too far from Schur form. +// The blocks are not swapped, and T and Q are not modified. +// +// If n1 and n2 are both equal to 1, Dlaexc will always return true. +// +// Dlaexc is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaexc(wantq bool, n int, t []float64, ldt int, q []float64, ldq int, j1, n1, n2 int, work []float64) (ok bool) { + checkMatrix(n, n, t, ldt) + if wantq { + checkMatrix(n, n, q, ldq) + } + if j1 < 0 || n <= j1 { + panic("lapack: index j1 out of range") + } + if len(work) < n { + panic(badWork) + } + if n1 < 0 || 2 < n1 { + panic("lapack: invalid value of n1") + } + if n2 < 0 || 2 < n2 { + panic("lapack: invalid value of n2") + } + + if n == 0 || n1 == 0 || n2 == 0 { + return true + } + if j1+n1 >= n { + // TODO(vladimir-ch): Reference LAPACK does this check whether + // the start of the second block is in the matrix T. It returns + // true if it is not and moreover it does not check whether the + // whole second block fits into T. This does not feel + // satisfactory. The only caller of Dlaexc is Dtrexc, so if the + // caller makes sure that this does not happen, we could be + // stricter here. + return true + } + + j2 := j1 + 1 + j3 := j1 + 2 + + bi := blas64.Implementation() + + if n1 == 1 && n2 == 1 { + // Swap two 1×1 blocks. + t11 := t[j1*ldt+j1] + t22 := t[j2*ldt+j2] + + // Determine the transformation to perform the interchange. + cs, sn, _ := impl.Dlartg(t[j1*ldt+j2], t22-t11) + + // Apply transformation to the matrix T. + if n-j3 > 0 { + bi.Drot(n-j3, t[j1*ldt+j3:], 1, t[j2*ldt+j3:], 1, cs, sn) + } + if j1 > 0 { + bi.Drot(j1, t[j1:], ldt, t[j2:], ldt, cs, sn) + } + + t[j1*ldt+j1] = t22 + t[j2*ldt+j2] = t11 + + if wantq { + // Accumulate transformation in the matrix Q. + bi.Drot(n, q[j1:], ldq, q[j2:], ldq, cs, sn) + } + + return true + } + + // Swapping involves at least one 2×2 block. + // + // Copy the diagonal block of order n1+n2 to the local array d and + // compute its norm. + nd := n1 + n2 + var d [16]float64 + const ldd = 4 + impl.Dlacpy(blas.All, nd, nd, t[j1*ldt+j1:], ldt, d[:], ldd) + dnorm := impl.Dlange(lapack.MaxAbs, nd, nd, d[:], ldd, work) + + // Compute machine-dependent threshold for test for accepting swap. + eps := dlamchP + thresh := math.Max(10*eps*dnorm, dlamchS/eps) + + // Solve T11*X - X*T22 = scale*T12 for X. + var x [4]float64 + const ldx = 2 + scale, _, _ := impl.Dlasy2(false, false, -1, n1, n2, d[:], ldd, d[n1*ldd+n1:], ldd, d[n1:], ldd, x[:], ldx) + + // Swap the adjacent diagonal blocks. + switch { + case n1 == 1 && n2 == 2: + // Generate elementary reflector H so that + // ( scale, X11, X12 ) H = ( 0, 0, * ) + u := [3]float64{scale, x[0], 1} + _, tau := impl.Dlarfg(3, x[1], u[:2], 1) + t11 := t[j1*ldt+j1] + + // Perform swap provisionally on diagonal block in d. + impl.Dlarfx(blas.Left, 3, 3, u[:], tau, d[:], ldd, work) + impl.Dlarfx(blas.Right, 3, 3, u[:], tau, d[:], ldd, work) + + // Test whether to reject swap. + if math.Max(math.Abs(d[2*ldd]), math.Max(math.Abs(d[2*ldd+1]), math.Abs(d[2*ldd+2]-t11))) > thresh { + return false + } + + // Accept swap: apply transformation to the entire matrix T. + impl.Dlarfx(blas.Left, 3, n-j1, u[:], tau, t[j1*ldt+j1:], ldt, work) + impl.Dlarfx(blas.Right, j2+1, 3, u[:], tau, t[j1:], ldt, work) + + t[j3*ldt+j1] = 0 + t[j3*ldt+j2] = 0 + t[j3*ldt+j3] = t11 + + if wantq { + // Accumulate transformation in the matrix Q. + impl.Dlarfx(blas.Right, n, 3, u[:], tau, q[j1:], ldq, work) + } + + case n1 == 2 && n2 == 1: + // Generate elementary reflector H so that: + // H ( -X11 ) = ( * ) + // ( -X21 ) = ( 0 ) + // ( scale ) = ( 0 ) + u := [3]float64{1, -x[ldx], scale} + _, tau := impl.Dlarfg(3, -x[0], u[1:], 1) + t33 := t[j3*ldt+j3] + + // Perform swap provisionally on diagonal block in D. + impl.Dlarfx(blas.Left, 3, 3, u[:], tau, d[:], ldd, work) + impl.Dlarfx(blas.Right, 3, 3, u[:], tau, d[:], ldd, work) + + // Test whether to reject swap. + if math.Max(math.Abs(d[ldd]), math.Max(math.Abs(d[2*ldd]), math.Abs(d[0]-t33))) > thresh { + return false + } + + // Accept swap: apply transformation to the entire matrix T. + impl.Dlarfx(blas.Right, j3+1, 3, u[:], tau, t[j1:], ldt, work) + impl.Dlarfx(blas.Left, 3, n-j1-1, u[:], tau, t[j1*ldt+j2:], ldt, work) + + t[j1*ldt+j1] = t33 + t[j2*ldt+j1] = 0 + t[j3*ldt+j1] = 0 + + if wantq { + // Accumulate transformation in the matrix Q. + impl.Dlarfx(blas.Right, n, 3, u[:], tau, q[j1:], ldq, work) + } + + default: // n1 == 2 && n2 == 2 + // Generate elementary reflectors H_1 and H_2 so that: + // H_2 H_1 ( -X11 -X12 ) = ( * * ) + // ( -X21 -X22 ) ( 0 * ) + // ( scale 0 ) ( 0 0 ) + // ( 0 scale ) ( 0 0 ) + u1 := [3]float64{1, -x[ldx], scale} + _, tau1 := impl.Dlarfg(3, -x[0], u1[1:], 1) + + temp := -tau1 * (x[1] + u1[1]*x[ldx+1]) + u2 := [3]float64{1, -temp * u1[2], scale} + _, tau2 := impl.Dlarfg(3, -temp*u1[1]-x[ldx+1], u2[1:], 1) + + // Perform swap provisionally on diagonal block in D. + impl.Dlarfx(blas.Left, 3, 4, u1[:], tau1, d[:], ldd, work) + impl.Dlarfx(blas.Right, 4, 3, u1[:], tau1, d[:], ldd, work) + impl.Dlarfx(blas.Left, 3, 4, u2[:], tau2, d[ldd:], ldd, work) + impl.Dlarfx(blas.Right, 4, 3, u2[:], tau2, d[1:], ldd, work) + + // Test whether to reject swap. + m1 := math.Max(math.Abs(d[2*ldd]), math.Abs(d[2*ldd+1])) + m2 := math.Max(math.Abs(d[3*ldd]), math.Abs(d[3*ldd+1])) + if math.Max(m1, m2) > thresh { + return false + } + + // Accept swap: apply transformation to the entire matrix T. + j4 := j1 + 3 + impl.Dlarfx(blas.Left, 3, n-j1, u1[:], tau1, t[j1*ldt+j1:], ldt, work) + impl.Dlarfx(blas.Right, j4+1, 3, u1[:], tau1, t[j1:], ldt, work) + impl.Dlarfx(blas.Left, 3, n-j1, u2[:], tau2, t[j2*ldt+j1:], ldt, work) + impl.Dlarfx(blas.Right, j4+1, 3, u2[:], tau2, t[j2:], ldt, work) + + t[j3*ldt+j1] = 0 + t[j3*ldt+j2] = 0 + t[j4*ldt+j1] = 0 + t[j4*ldt+j2] = 0 + + if wantq { + // Accumulate transformation in the matrix Q. + impl.Dlarfx(blas.Right, n, 3, u1[:], tau1, q[j1:], ldq, work) + impl.Dlarfx(blas.Right, n, 3, u2[:], tau2, q[j2:], ldq, work) + } + } + + if n2 == 2 { + // Standardize new 2×2 block T11. + a, b := t[j1*ldt+j1], t[j1*ldt+j2] + c, d := t[j2*ldt+j1], t[j2*ldt+j2] + var cs, sn float64 + t[j1*ldt+j1], t[j1*ldt+j2], t[j2*ldt+j1], t[j2*ldt+j2], _, _, _, _, cs, sn = impl.Dlanv2(a, b, c, d) + if n-j1-2 > 0 { + bi.Drot(n-j1-2, t[j1*ldt+j1+2:], 1, t[j2*ldt+j1+2:], 1, cs, sn) + } + if j1 > 0 { + bi.Drot(j1, t[j1:], ldt, t[j2:], ldt, cs, sn) + } + if wantq { + bi.Drot(n, q[j1:], ldq, q[j2:], ldq, cs, sn) + } + } + if n1 == 2 { + // Standardize new 2×2 block T22. + j3 := j1 + n2 + j4 := j3 + 1 + a, b := t[j3*ldt+j3], t[j3*ldt+j4] + c, d := t[j4*ldt+j3], t[j4*ldt+j4] + var cs, sn float64 + t[j3*ldt+j3], t[j3*ldt+j4], t[j4*ldt+j3], t[j4*ldt+j4], _, _, _, _, cs, sn = impl.Dlanv2(a, b, c, d) + if n-j3-2 > 0 { + bi.Drot(n-j3-2, t[j3*ldt+j3+2:], 1, t[j4*ldt+j3+2:], 1, cs, sn) + } + bi.Drot(j3, t[j3:], ldt, t[j4:], ldt, cs, sn) + if wantq { + bi.Drot(n, q[j3:], ldq, q[j4:], ldq, cs, sn) + } + } + + return true +} diff --git a/lapack/native/dlags2.go b/lapack/native/dlags2.go new file mode 100644 index 00000000..66fac9b9 --- /dev/null +++ b/lapack/native/dlags2.go @@ -0,0 +1,182 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlags2 computes 2-by-2 orthogonal matrices U, V and Q with the +// triangles of A and B specified by upper. +// +// If upper is true +// +// U^T*A*Q = U^T*[ a1 a2 ]*Q = [ x 0 ] +// [ 0 a3 ] [ x x ] +// and +// V^T*B*Q = V^T*[ b1 b2 ]*Q = [ x 0 ] +// [ 0 b3 ] [ x x ] +// +// otherwise +// +// U^T*A*Q = U^T*[ a1 0 ]*Q = [ x x ] +// [ a2 a3 ] [ 0 x ] +// and +// V^T*B*Q = V^T*[ b1 0 ]*Q = [ x x ] +// [ b2 b3 ] [ 0 x ]. +// +// The rows of the transformed A and B are parallel, where +// +// U = [ csu snu ], V = [ csv snv ], Q = [ csq snq ] +// [ -snu csu ] [ -snv csv ] [ -snq csq ] +// +// Dlags2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlags2(upper bool, a1, a2, a3, b1, b2, b3 float64) (csu, snu, csv, snv, csq, snq float64) { + if upper { + // Input matrices A and B are upper triangular matrices. + // + // Form matrix C = A*adj(B) = [ a b ] + // [ 0 d ] + a := a1 * b3 + d := a3 * b1 + b := a2*b1 - a1*b2 + + // The SVD of real 2-by-2 triangular C. + // + // [ csl -snl ]*[ a b ]*[ csr snr ] = [ r 0 ] + // [ snl csl ] [ 0 d ] [ -snr csr ] [ 0 t ] + _, _, snr, csr, snl, csl := impl.Dlasv2(a, b, d) + + if math.Abs(csl) >= math.Abs(snl) || math.Abs(csr) >= math.Abs(snr) { + // Compute the [0, 0] and [0, 1] elements of U^T*A and V^T*B, + // and [0, 1] element of |U|^T*|A| and |V|^T*|B|. + + ua11r := csl * a1 + ua12 := csl*a2 + snl*a3 + + vb11r := csr * b1 + vb12 := csr*b2 + snr*b3 + + aua12 := math.Abs(csl)*math.Abs(a2) + math.Abs(snl)*math.Abs(a3) + avb12 := math.Abs(csr)*math.Abs(b2) + math.Abs(snr)*math.Abs(b3) + + // Zero [0, 1] elements of U^T*A and V^T*B. + if math.Abs(ua11r)+math.Abs(ua12) != 0 { + if aua12/(math.Abs(ua11r)+math.Abs(ua12)) <= avb12/(math.Abs(vb11r)+math.Abs(vb12)) { + csq, snq, _ = impl.Dlartg(-ua11r, ua12) + } else { + csq, snq, _ = impl.Dlartg(-vb11r, vb12) + } + } else { + csq, snq, _ = impl.Dlartg(-vb11r, vb12) + } + + csu = csl + snu = -snl + csv = csr + snv = -snr + } else { + // Compute the [1, 0] and [1, 1] elements of U^T*A and V^T*B, + // and [1, 1] element of |U|^T*|A| and |V|^T*|B|. + + ua21 := -snl * a1 + ua22 := -snl*a2 + csl*a3 + + vb21 := -snr * b1 + vb22 := -snr*b2 + csr*b3 + + aua22 := math.Abs(snl)*math.Abs(a2) + math.Abs(csl)*math.Abs(a3) + avb22 := math.Abs(snr)*math.Abs(b2) + math.Abs(csr)*math.Abs(b3) + + // Zero [1, 1] elements of U^T*A and V^T*B, and then swap. + if math.Abs(ua21)+math.Abs(ua22) != 0 { + if aua22/(math.Abs(ua21)+math.Abs(ua22)) <= avb22/(math.Abs(vb21)+math.Abs(vb22)) { + csq, snq, _ = impl.Dlartg(-ua21, ua22) + } else { + csq, snq, _ = impl.Dlartg(-vb21, vb22) + } + } else { + csq, snq, _ = impl.Dlartg(-vb21, vb22) + } + + csu = snl + snu = csl + csv = snr + snv = csr + } + } else { + // Input matrices A and B are lower triangular matrices + // + // Form matrix C = A*adj(B) = [ a 0 ] + // [ c d ] + a := a1 * b3 + d := a3 * b1 + c := a2*b3 - a3*b2 + + // The SVD of real 2-by-2 triangular C + // + // [ csl -snl ]*[ a 0 ]*[ csr snr ] = [ r 0 ] + // [ snl csl ] [ c d ] [ -snr csr ] [ 0 t ] + _, _, snr, csr, snl, csl := impl.Dlasv2(a, c, d) + + if math.Abs(csr) >= math.Abs(snr) || math.Abs(csl) >= math.Abs(snl) { + // Compute the [1, 0] and [1, 1] elements of U^T*A and V^T*B, + // and [1, 0] element of |U|^T*|A| and |V|^T*|B|. + + ua21 := -snr*a1 + csr*a2 + ua22r := csr * a3 + + vb21 := -snl*b1 + csl*b2 + vb22r := csl * b3 + + aua21 := math.Abs(snr)*math.Abs(a1) + math.Abs(csr)*math.Abs(a2) + avb21 := math.Abs(snl)*math.Abs(b1) + math.Abs(csl)*math.Abs(b2) + + // Zero [1, 0] elements of U^T*A and V^T*B. + if (math.Abs(ua21) + math.Abs(ua22r)) != 0 { + if aua21/(math.Abs(ua21)+math.Abs(ua22r)) <= avb21/(math.Abs(vb21)+math.Abs(vb22r)) { + csq, snq, _ = impl.Dlartg(ua22r, ua21) + } else { + csq, snq, _ = impl.Dlartg(vb22r, vb21) + } + } else { + csq, snq, _ = impl.Dlartg(vb22r, vb21) + } + + csu = csr + snu = -snr + csv = csl + snv = -snl + } else { + // Compute the [0, 0] and [0, 1] elements of U^T *A and V^T *B, + // and [0, 0] element of |U|^T*|A| and |V|^T*|B|. + + ua11 := csr*a1 + snr*a2 + ua12 := snr * a3 + + vb11 := csl*b1 + snl*b2 + vb12 := snl * b3 + + aua11 := math.Abs(csr)*math.Abs(a1) + math.Abs(snr)*math.Abs(a2) + avb11 := math.Abs(csl)*math.Abs(b1) + math.Abs(snl)*math.Abs(b2) + + // Zero [0, 0] elements of U^T*A and V^T*B, and then swap. + if (math.Abs(ua11) + math.Abs(ua12)) != 0 { + if aua11/(math.Abs(ua11)+math.Abs(ua12)) <= avb11/(math.Abs(vb11)+math.Abs(vb12)) { + csq, snq, _ = impl.Dlartg(ua12, ua11) + } else { + csq, snq, _ = impl.Dlartg(vb12, vb11) + } + } else { + csq, snq, _ = impl.Dlartg(vb12, vb11) + } + + csu = snr + snu = csr + csv = snl + snv = csl + } + } + + return csu, snu, csv, snv, csq, snq +} diff --git a/lapack/native/dlahqr.go b/lapack/native/dlahqr.go new file mode 100644 index 00000000..9097d26b --- /dev/null +++ b/lapack/native/dlahqr.go @@ -0,0 +1,423 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlahqr computes the eigenvalues and Schur factorization of a block of an n×n +// upper Hessenberg matrix H, using the double-shift/single-shift QR algorithm. +// +// h and ldh represent the matrix H. Dlahqr works primarily with the Hessenberg +// submatrix H[ilo:ihi+1,ilo:ihi+1], but applies transformations to all of H if +// wantt is true. It is assumed that H[ihi+1:n,ihi+1:n] is already upper +// quasi-triangular, although this is not checked. +// +// It must hold that +// 0 <= ilo <= max(0,ihi), and ihi < n, +// and that +// H[ilo,ilo-1] == 0, if ilo > 0, +// otherwise Dlahqr will panic. +// +// If unconverged is zero on return, wr[ilo:ihi+1] and wi[ilo:ihi+1] will contain +// respectively the real and imaginary parts of the computed eigenvalues ilo +// to ihi. If two eigenvalues are computed as a complex conjugate pair, they are +// stored in consecutive elements of wr and wi, say the i-th and (i+1)th, with +// wi[i] > 0 and wi[i+1] < 0. If wantt is true, the eigenvalues are stored in +// the same order as on the diagonal of the Schur form returned in H, with +// wr[i] = H[i,i], and, if H[i:i+2,i:i+2] is a 2×2 diagonal block, +// wi[i] = sqrt(abs(H[i+1,i]*H[i,i+1])) and wi[i+1] = -wi[i]. +// +// wr and wi must have length ihi+1. +// +// z and ldz represent an n×n matrix Z. If wantz is true, the transformations +// will be applied to the submatrix Z[iloz:ihiz+1,ilo:ihi+1] and it must hold that +// 0 <= iloz <= ilo, and ihi <= ihiz < n. +// If wantz is false, z is not referenced. +// +// unconverged indicates whether Dlahqr computed all the eigenvalues ilo to ihi +// in a total of 30 iterations per eigenvalue. +// +// If unconverged is zero, all the eigenvalues ilo to ihi have been computed and +// will be stored on return in wr[ilo:ihi+1] and wi[ilo:ihi+1]. +// +// If unconverged is zero and wantt is true, H[ilo:ihi+1,ilo:ihi+1] will be +// overwritten on return by upper quasi-triangular full Schur form with any +// 2×2 diagonal blocks in standard form. +// +// If unconverged is zero and if wantt is false, the contents of h on return is +// unspecified. +// +// If unconverged is positive, some eigenvalues have not converged, and +// wr[unconverged:ihi+1] and wi[unconverged:ihi+1] contain those eigenvalues +// which have been successfully computed. +// +// If unconverged is positive and wantt is true, then on return +// (initial H)*U = U*(final H), (*) +// where U is an orthogonal matrix. The final H is upper Hessenberg and +// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. +// +// If unconverged is positive and wantt is false, on return the remaining +// unconverged eigenvalues are the eigenvalues of the upper Hessenberg matrix +// H[ilo:unconverged,ilo:unconverged]. +// +// If unconverged is positive and wantz is true, then on return +// (final Z) = (initial Z)*U, +// where U is the orthogonal matrix in (*) regardless of the value of wantt. +// +// Dlahqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlahqr(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int) (unconverged int) { + checkMatrix(n, n, h, ldh) + switch { + case ilo < 0 || max(0, ihi) < ilo: + panic(badIlo) + case n <= ihi: + panic(badIhi) + case len(wr) != ihi+1: + panic("lapack: bad length of wr") + case len(wi) != ihi+1: + panic("lapack: bad length of wi") + case ilo > 0 && h[ilo*ldh+ilo-1] != 0: + panic("lapack: block is not isolated") + } + if wantz { + checkMatrix(n, n, z, ldz) + switch { + case iloz < 0 || ilo < iloz: + panic("lapack: iloz out of range") + case ihiz < ihi || n <= ihiz: + panic("lapack: ihiz out of range") + } + } + + // Quick return if possible. + if n == 0 { + return 0 + } + if ilo == ihi { + wr[ilo] = h[ilo*ldh+ilo] + wi[ilo] = 0 + return 0 + } + + // Clear out the trash. + for j := ilo; j < ihi-2; j++ { + h[(j+2)*ldh+j] = 0 + h[(j+3)*ldh+j] = 0 + } + if ilo <= ihi-2 { + h[ihi*ldh+ihi-2] = 0 + } + + nh := ihi - ilo + 1 + nz := ihiz - iloz + 1 + + // Set machine-dependent constants for the stopping criterion. + ulp := dlamchP + smlnum := float64(nh) / ulp * dlamchS + + // i1 and i2 are the indices of the first row and last column of H to + // which transformations must be applied. If eigenvalues only are being + // computed, i1 and i2 are set inside the main loop. + var i1, i2 int + if wantt { + i1 = 0 + i2 = n - 1 + } + + itmax := 30 * max(10, nh) // Total number of QR iterations allowed. + + // The main loop begins here. i is the loop index and decreases from ihi + // to ilo in steps of 1 or 2. Each iteration of the loop works with the + // active submatrix in rows and columns l to i. Eigenvalues i+1 to ihi + // have already converged. Either l = ilo or H[l,l-1] is negligible so + // that the matrix splits. + bi := blas64.Implementation() + i := ihi + for i >= ilo { + l := ilo + + // Perform QR iterations on rows and columns ilo to i until a + // submatrix of order 1 or 2 splits off at the bottom because a + // subdiagonal element has become negligible. + converged := false + for its := 0; its <= itmax; its++ { + // Look for a single small subdiagonal element. + var k int + for k = i; k > l; k-- { + if math.Abs(h[k*ldh+k-1]) <= smlnum { + break + } + tst := math.Abs(h[(k-1)*ldh+k-1]) + math.Abs(h[k*ldh+k]) + if tst == 0 { + if k-2 >= ilo { + tst += math.Abs(h[(k-1)*ldh+k-2]) + } + if k+1 <= ihi { + tst += math.Abs(h[(k+1)*ldh+k]) + } + } + // The following is a conservative small + // subdiagonal deflation criterion due to Ahues + // & Tisseur (LAWN 122, 1997). It has better + // mathematical foundation and improves accuracy + // in some cases. + if math.Abs(h[k*ldh+k-1]) <= ulp*tst { + ab := math.Max(math.Abs(h[k*ldh+k-1]), math.Abs(h[(k-1)*ldh+k])) + ba := math.Min(math.Abs(h[k*ldh+k-1]), math.Abs(h[(k-1)*ldh+k])) + aa := math.Max(math.Abs(h[k*ldh+k]), math.Abs(h[(k-1)*ldh+k-1]-h[k*ldh+k])) + bb := math.Min(math.Abs(h[k*ldh+k]), math.Abs(h[(k-1)*ldh+k-1]-h[k*ldh+k])) + s := aa + ab + if ab/s*ba <= math.Max(smlnum, aa/s*bb*ulp) { + break + } + } + } + l = k + if l > ilo { + // H[l,l-1] is negligible. + h[l*ldh+l-1] = 0 + } + if l >= i-1 { + // Break the loop because a submatrix of order 1 + // or 2 has split off. + converged = true + break + } + + // Now the active submatrix is in rows and columns l to + // i. If eigenvalues only are being computed, only the + // active submatrix need be transformed. + if !wantt { + i1 = l + i2 = i + } + + const ( + dat1 = 3.0 + dat2 = -0.4375 + ) + var h11, h21, h12, h22 float64 + switch its { + case 10: // Exceptional shift. + s := math.Abs(h[(l+1)*ldh+l]) + math.Abs(h[(l+2)*ldh+l+1]) + h11 = dat1*s + h[l*ldh+l] + h12 = dat2 * s + h21 = s + h22 = h11 + case 20: // Exceptional shift. + s := math.Abs(h[i*ldh+i-1]) + math.Abs(h[(i-1)*ldh+i-2]) + h11 = dat1*s + h[i*ldh+i] + h12 = dat2 * s + h21 = s + h22 = h11 + default: // Prepare to use Francis' double shift (i.e., + // 2nd degree generalized Rayleigh quotient). + h11 = h[(i-1)*ldh+i-1] + h21 = h[i*ldh+i-1] + h12 = h[(i-1)*ldh+i] + h22 = h[i*ldh+i] + } + s := math.Abs(h11) + math.Abs(h12) + math.Abs(h21) + math.Abs(h22) + var ( + rt1r, rt1i float64 + rt2r, rt2i float64 + ) + if s != 0 { + h11 /= s + h21 /= s + h12 /= s + h22 /= s + tr := (h11 + h22) / 2 + det := (h11-tr)*(h22-tr) - h12*h21 + rtdisc := math.Sqrt(math.Abs(det)) + if det >= 0 { + // Complex conjugate shifts. + rt1r = tr * s + rt2r = rt1r + rt1i = rtdisc * s + rt2i = -rt1i + } else { + // Real shifts (use only one of them). + rt1r = tr + rtdisc + rt2r = tr - rtdisc + if math.Abs(rt1r-h22) <= math.Abs(rt2r-h22) { + rt1r *= s + rt2r = rt1r + } else { + rt2r *= s + rt1r = rt2r + } + rt1i = 0 + rt2i = 0 + } + } + + // Look for two consecutive small subdiagonal elements. + var m int + var v [3]float64 + for m = i - 2; m >= l; m-- { + // Determine the effect of starting the + // double-shift QR iteration at row m, and see + // if this would make H[m,m-1] negligible. The + // following uses scaling to avoid overflows and + // most underflows. + h21s := h[(m+1)*ldh+m] + s := math.Abs(h[m*ldh+m]-rt2r) + math.Abs(rt2i) + math.Abs(h21s) + h21s /= s + v[0] = h21s*h[m*ldh+m+1] + (h[m*ldh+m]-rt1r)*((h[m*ldh+m]-rt2r)/s) - rt2i/s*rt1i + v[1] = h21s * (h[m*ldh+m] + h[(m+1)*ldh+m+1] - rt1r - rt2r) + v[2] = h21s * h[(m+2)*ldh+m+1] + s = math.Abs(v[0]) + math.Abs(v[1]) + math.Abs(v[2]) + v[0] /= s + v[1] /= s + v[2] /= s + if m == l { + break + } + dsum := math.Abs(h[(m-1)*ldh+m-1]) + math.Abs(h[m*ldh+m]) + math.Abs(h[(m+1)*ldh+m+1]) + if math.Abs(h[m*ldh+m-1])*(math.Abs(v[1])+math.Abs(v[2])) <= ulp*math.Abs(v[0])*dsum { + break + } + } + + // Double-shift QR step. + for k := m; k < i; k++ { + // The first iteration of this loop determines a + // reflection G from the vector V and applies it + // from left and right to H, thus creating a + // non-zero bulge below the subdiagonal. + // + // Each subsequent iteration determines a + // reflection G to restore the Hessenberg form + // in the (k-1)th column, and thus chases the + // bulge one step toward the bottom of the + // active submatrix. nr is the order of G. + + nr := min(3, i-k+1) + if k > m { + bi.Dcopy(nr, h[k*ldh+k-1:], ldh, v[:], 1) + } + var t0 float64 + v[0], t0 = impl.Dlarfg(nr, v[0], v[1:], 1) + if k > m { + h[k*ldh+k-1] = v[0] + h[(k+1)*ldh+k-1] = 0 + if k < i-1 { + h[(k+2)*ldh+k-1] = 0 + } + } else if m > l { + // Use the following instead of H[k,k-1] = -H[k,k-1] + // to avoid a bug when v[1] and v[2] underflow. + h[k*ldh+k-1] *= 1 - t0 + } + t1 := t0 * v[1] + if nr == 3 { + t2 := t0 * v[2] + + // Apply G from the left to transform + // the rows of the matrix in columns k + // to i2. + for j := k; j <= i2; j++ { + sum := h[k*ldh+j] + v[1]*h[(k+1)*ldh+j] + v[2]*h[(k+2)*ldh+j] + h[k*ldh+j] -= sum * t0 + h[(k+1)*ldh+j] -= sum * t1 + h[(k+2)*ldh+j] -= sum * t2 + } + + // Apply G from the right to transform + // the columns of the matrix in rows i1 + // to min(k+3,i). + for j := i1; j <= min(k+3, i); j++ { + sum := h[j*ldh+k] + v[1]*h[j*ldh+k+1] + v[2]*h[j*ldh+k+2] + h[j*ldh+k] -= sum * t0 + h[j*ldh+k+1] -= sum * t1 + h[j*ldh+k+2] -= sum * t2 + } + + if wantz { + // Accumulate transformations in the matrix Z. + for j := iloz; j <= ihiz; j++ { + sum := z[j*ldz+k] + v[1]*z[j*ldz+k+1] + v[2]*z[j*ldz+k+2] + z[j*ldz+k] -= sum * t0 + z[j*ldz+k+1] -= sum * t1 + z[j*ldz+k+2] -= sum * t2 + } + } + } else if nr == 2 { + // Apply G from the left to transform + // the rows of the matrix in columns k + // to i2. + for j := k; j <= i2; j++ { + sum := h[k*ldh+j] + v[1]*h[(k+1)*ldh+j] + h[k*ldh+j] -= sum * t0 + h[(k+1)*ldh+j] -= sum * t1 + } + + // Apply G from the right to transform + // the columns of the matrix in rows i1 + // to min(k+3,i). + for j := i1; j <= i; j++ { + sum := h[j*ldh+k] + v[1]*h[j*ldh+k+1] + h[j*ldh+k] -= sum * t0 + h[j*ldh+k+1] -= sum * t1 + } + + if wantz { + // Accumulate transformations in the matrix Z. + for j := iloz; j <= ihiz; j++ { + sum := z[j*ldz+k] + v[1]*z[j*ldz+k+1] + z[j*ldz+k] -= sum * t0 + z[j*ldz+k+1] -= sum * t1 + } + } + } + } + } + + if converged == false { + // The QR iteration finished without splitting off a + // submatrix of order 1 or 2. + return i + 1 + } + + if l == i { + // H[i,i-1] is negligible: one eigenvalue has converged. + wr[i] = h[i*ldh+i] + wi[i] = 0 + } else if l == i-1 { + // H[i-1,i-2] is negligible: a pair of eigenvalues have converged. + + // Transform the 2×2 submatrix to standard Schur form, + // and compute and store the eigenvalues. + var cs, sn float64 + a, b := h[(i-1)*ldh+i-1], h[(i-1)*ldh+i] + c, d := h[i*ldh+i-1], h[i*ldh+i] + a, b, c, d, wr[i-1], wi[i-1], wr[i], wi[i], cs, sn = impl.Dlanv2(a, b, c, d) + h[(i-1)*ldh+i-1], h[(i-1)*ldh+i] = a, b + h[i*ldh+i-1], h[i*ldh+i] = c, d + + if wantt { + // Apply the transformation to the rest of H. + if i2 > i { + bi.Drot(i2-i, h[(i-1)*ldh+i+1:], 1, h[i*ldh+i+1:], 1, cs, sn) + } + bi.Drot(i-i1-1, h[i1*ldh+i-1:], ldh, h[i1*ldh+i:], ldh, cs, sn) + } + + if wantz { + // Apply the transformation to Z. + bi.Drot(nz, z[iloz*ldz+i-1:], ldz, z[iloz*ldz+i:], ldz, cs, sn) + } + } + + // Return to start of the main loop with new value of i. + i = l - 1 + } + return 0 +} diff --git a/lapack/native/dlahr2.go b/lapack/native/dlahr2.go new file mode 100644 index 00000000..2e1e54bc --- /dev/null +++ b/lapack/native/dlahr2.go @@ -0,0 +1,169 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlahr2 reduces the first nb columns of a real general n×(n-k+1) matrix A so +// that elements below the k-th subdiagonal are zero. The reduction is performed +// by an orthogonal similarity transformation Q^T * A * Q. Dlahr2 returns the +// matrices V and T which determine Q as a block reflector I - V*T*V^T, and +// also the matrix Y = A * V * T. +// +// The matrix Q is represented as a product of nb elementary reflectors +// Q = H_0 * H_1 * ... * H_{nb-1}. +// Each H_i has the form +// H_i = I - tau[i] * v * v^T, +// where v is a real vector with v[0:i+k-1] = 0 and v[i+k-1] = 1. v[i+k:n] is +// stored on exit in A[i+k+1:n,i]. +// +// The elements of the vectors v together form the (n-k+1)×nb matrix +// V which is needed, with T and Y, to apply the transformation to the +// unreduced part of the matrix, using an update of the form +// A = (I - V*T*V^T) * (A - Y*V^T). +// +// On entry, a contains the n×(n-k+1) general matrix A. On return, the elements +// on and above the k-th subdiagonal in the first nb columns are overwritten +// with the corresponding elements of the reduced matrix; the elements below the +// k-th subdiagonal, with the slice tau, represent the matrix Q as a product of +// elementary reflectors. The other columns of A are unchanged. +// +// The contents of A on exit are illustrated by the following example +// with n = 7, k = 3 and nb = 2: +// [ a a a a a ] +// [ a a a a a ] +// [ a a a a a ] +// [ h h a a a ] +// [ v0 h a a a ] +// [ v0 v1 a a a ] +// [ v0 v1 a a a ] +// where a denotes an element of the original matrix A, h denotes a +// modified element of the upper Hessenberg matrix H, and vi denotes an +// element of the vector defining H_i. +// +// k is the offset for the reduction. Elements below the k-th subdiagonal in the +// first nb columns are reduced to zero. +// +// nb is the number of columns to be reduced. +// +// On entry, a represents the n×(n-k+1) matrix A. On return, the elements on and +// above the k-th subdiagonal in the first nb columns are overwritten with the +// corresponding elements of the reduced matrix. The elements below the k-th +// subdiagonal, with the slice tau, represent the matrix Q as a product of +// elementary reflectors. The other columns of A are unchanged. +// +// tau will contain the scalar factors of the elementary reflectors. It must +// have length at least nb. +// +// t and ldt represent the nb×nb upper triangular matrix T, and y and ldy +// represent the n×nb matrix Y. +// +// Dlahr2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlahr2(n, k, nb int, a []float64, lda int, tau, t []float64, ldt int, y []float64, ldy int) { + checkMatrix(n, n-k+1, a, lda) + if len(tau) < nb { + panic(badTau) + } + checkMatrix(nb, nb, t, ldt) + checkMatrix(n, nb, y, ldy) + + // Quick return if possible. + if n <= 1 { + return + } + + bi := blas64.Implementation() + var ei float64 + for i := 0; i < nb; i++ { + if i > 0 { + // Update A[k:n,i]. + + // Update i-th column of A - Y * V^T. + bi.Dgemv(blas.NoTrans, n-k, i, + -1, y[k*ldy:], ldy, + a[(k+i-1)*lda:], 1, + 1, a[k*lda+i:], lda) + + // Apply I - V * T^T * V^T to this column (call it b) + // from the left, using the last column of T as + // workspace. + // Let V = [ V1 ] and b = [ b1 ] (first i rows) + // [ V2 ] [ b2 ] + // where V1 is unit lower triangular. + // + // w := V1^T * b1. + bi.Dcopy(i, a[k*lda+i:], lda, t[nb-1:], ldt) + bi.Dtrmv(blas.Lower, blas.Trans, blas.Unit, i, + a[k*lda:], lda, t[nb-1:], ldt) + + // w := w + V2^T * b2. + bi.Dgemv(blas.Trans, n-k-i, i, + 1, a[(k+i)*lda:], lda, + a[(k+i)*lda+i:], lda, + 1, t[nb-1:], ldt) + + // w := T^T * w. + bi.Dtrmv(blas.Upper, blas.Trans, blas.NonUnit, i, + t, ldt, t[nb-1:], ldt) + + // b2 := b2 - V2*w. + bi.Dgemv(blas.NoTrans, n-k-i, i, + -1, a[(k+i)*lda:], lda, + t[nb-1:], ldt, + 1, a[(k+i)*lda+i:], lda) + + // b1 := b1 - V1*w. + bi.Dtrmv(blas.Lower, blas.NoTrans, blas.Unit, i, + a[k*lda:], lda, t[nb-1:], ldt) + bi.Daxpy(i, -1, t[nb-1:], ldt, a[k*lda+i:], lda) + + a[(k+i-1)*lda+i-1] = ei + } + + // Generate the elementary reflector H_i to annihilate + // A[k+i+1:n,i]. + ei, tau[i] = impl.Dlarfg(n-k-i, a[(k+i)*lda+i], a[min(k+i+1, n-1)*lda+i:], lda) + a[(k+i)*lda+i] = 1 + + // Compute Y[k:n,i]. + bi.Dgemv(blas.NoTrans, n-k, n-k-i, + 1, a[k*lda+i+1:], lda, + a[(k+i)*lda+i:], lda, + 0, y[k*ldy+i:], ldy) + bi.Dgemv(blas.Trans, n-k-i, i, + 1, a[(k+i)*lda:], lda, + a[(k+i)*lda+i:], lda, + 0, t[i:], ldt) + bi.Dgemv(blas.NoTrans, n-k, i, + -1, y[k*ldy:], ldy, + t[i:], ldt, + 1, y[k*ldy+i:], ldy) + bi.Dscal(n-k, tau[i], y[k*ldy+i:], ldy) + + // Compute T[0:i,i]. + bi.Dscal(i, -tau[i], t[i:], ldt) + bi.Dtrmv(blas.Upper, blas.NoTrans, blas.NonUnit, i, + t, ldt, t[i:], ldt) + + t[i*ldt+i] = tau[i] + } + a[(k+nb-1)*lda+nb-1] = ei + + // Compute Y[0:k,0:nb]. + impl.Dlacpy(blas.All, k, nb, a[1:], lda, y, ldy) + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, k, nb, + 1, a[k*lda:], lda, y, ldy) + if n > k+nb { + bi.Dgemm(blas.NoTrans, blas.NoTrans, k, nb, n-k-nb, + 1, a[1+nb:], lda, + a[(k+nb)*lda:], lda, + 1, y, ldy) + } + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.NonUnit, k, nb, + 1, t, ldt, y, ldy) +} diff --git a/lapack/native/dlaln2.go b/lapack/native/dlaln2.go new file mode 100644 index 00000000..29925cfb --- /dev/null +++ b/lapack/native/dlaln2.go @@ -0,0 +1,396 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlaln2 solves a linear equation or a system of 2 linear equations of the form +// (ca A - w D) X = scale B, if trans == false, +// (ca A^T - w D) X = scale B, if trans == true, +// where A is a na×na real matrix, ca is a real scalar, D is a na×na diagonal +// real matrix, w is a scalar, real if nw == 1, complex if nw == 2, and X and B +// are na×1 matrices, real if w is real, complex if w is complex. +// +// If w is complex, X and B are represented as na×2 matrices, the first column +// of each being the real part and the second being the imaginary part. +// +// na and nw must be 1 or 2, otherwise Dlaln2 will panic. +// +// d1 and d2 are the diagonal elements of D. d2 is not used if na == 1. +// +// wr and wi represent the real and imaginary part, respectively, of the scalar +// w. wi is not used if nw == 1. +// +// smin is the desired lower bound on the singular values of A. This should be +// a safe distance away from underflow or overflow, say, between +// (underflow/machine precision) and (overflow*machine precision). +// +// If both singular values of (ca A - w D) are less than smin, smin*identity +// will be used instead of (ca A - w D). If only one singular value is less than +// smin, one element of (ca A - w D) will be perturbed enough to make the +// smallest singular value roughly smin. If both singular values are at least +// smin, (ca A - w D) will not be perturbed. In any case, the perturbation will +// be at most some small multiple of max(smin, ulp*norm(ca A - w D)). The +// singular values are computed by infinity-norm approximations, and thus will +// only be correct to a factor of 2 or so. +// +// All input quantities are assumed to be smaller than overflow by a reasonable +// factor. +// +// scale is a scaling factor less than or equal to 1 which is chosen so that X +// can be computed without overflow. X is further scaled if necessary to assure +// that norm(ca A - w D)*norm(X) is less than overflow. +// +// xnorm contains the infinity-norm of X when X is regarded as a na×nw real +// matrix. +// +// ok will be false if (ca A - w D) had to be perturbed to make its smallest +// singular value greater than smin, otherwise ok will be true. +// +// Dlaln2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaln2(trans bool, na, nw int, smin, ca float64, a []float64, lda int, d1, d2 float64, b []float64, ldb int, wr, wi float64, x []float64, ldx int) (scale, xnorm float64, ok bool) { + // TODO(vladimir-ch): Consider splitting this function into two, one + // handling the real case (nw == 1) and the other handling the complex + // case (nw == 2). Given that Go has complex types, their signatures + // would be simpler and more natural, and the implementation not as + // convoluted. + + if na != 1 && na != 2 { + panic("lapack: invalid value of na") + } + if nw != 1 && nw != 2 { + panic("lapack: invalid value of nw") + } + checkMatrix(na, na, a, lda) + checkMatrix(na, nw, b, ldb) + checkMatrix(na, nw, x, ldx) + + smlnum := 2 * dlamchS + bignum := 1 / smlnum + smini := math.Max(smin, smlnum) + + ok = true + scale = 1 + + if na == 1 { + // 1×1 (i.e., scalar) system C X = B. + + if nw == 1 { + // Real 1×1 system. + + // C = ca A - w D. + csr := ca*a[0] - wr*d1 + cnorm := math.Abs(csr) + + // If |C| < smini, use C = smini. + if cnorm < smini { + csr = smini + cnorm = smini + ok = false + } + + // Check scaling for X = B / C. + bnorm := math.Abs(b[0]) + if cnorm < 1 && bnorm > math.Max(1, bignum*cnorm) { + scale = 1 / bnorm + } + + // Compute X. + x[0] = b[0] * scale / csr + xnorm = math.Abs(x[0]) + + return scale, xnorm, ok + } + + // Complex 1×1 system (w is complex). + + // C = ca A - w D. + csr := ca*a[0] - wr*d1 + csi := -wi * d1 + cnorm := math.Abs(csr) + math.Abs(csi) + + // If |C| < smini, use C = smini. + if cnorm < smini { + csr = smini + csi = 0 + cnorm = smini + ok = false + } + + // Check scaling for X = B / C. + bnorm := math.Abs(b[0]) + math.Abs(b[1]) + if cnorm < 1 && bnorm > math.Max(1, bignum*cnorm) { + scale = 1 / bnorm + } + + // Compute X. + cx := complex(scale*b[0], scale*b[1]) / complex(csr, csi) + x[0], x[1] = real(cx), imag(cx) + xnorm = math.Abs(x[0]) + math.Abs(x[1]) + + return scale, xnorm, ok + } + + // 2×2 system. + + // Compute the real part of + // C = ca A - w D + // or + // C = ca A^T - w D. + crv := [4]float64{ + ca*a[0] - wr*d1, + ca * a[1], + ca * a[lda], + ca*a[lda+1] - wr*d2, + } + if trans { + crv[1] = ca * a[lda] + crv[2] = ca * a[1] + } + + pivot := [4][4]int{ + {0, 1, 2, 3}, + {1, 0, 3, 2}, + {2, 3, 0, 1}, + {3, 2, 1, 0}, + } + + if nw == 1 { + // Real 2×2 system (w is real). + + // Find the largest element in C. + var cmax float64 + var icmax int + for j, v := range crv { + v = math.Abs(v) + if v > cmax { + cmax = v + icmax = j + } + } + + // If norm(C) < smini, use smini*identity. + if cmax < smini { + bnorm := math.Max(math.Abs(b[0]), math.Abs(b[ldb])) + if smini < 1 && bnorm > math.Max(1, bignum*smini) { + scale = 1 / bnorm + } + temp := scale / smini + x[0] = temp * b[0] + x[ldx] = temp * b[ldb] + xnorm = temp * bnorm + ok = false + + return scale, xnorm, ok + } + + // Gaussian elimination with complete pivoting. + // Form upper triangular matrix + // [ur11 ur12] + // [ 0 ur22] + ur11 := crv[icmax] + ur12 := crv[pivot[icmax][1]] + cr21 := crv[pivot[icmax][2]] + cr22 := crv[pivot[icmax][3]] + ur11r := 1 / ur11 + lr21 := ur11r * cr21 + ur22 := cr22 - ur12*lr21 + + // If smaller pivot < smini, use smini. + if math.Abs(ur22) < smini { + ur22 = smini + ok = false + } + + var br1, br2 float64 + if icmax > 1 { + // If the pivot lies in the second row, swap the rows. + br1 = b[ldb] + br2 = b[0] + } else { + br1 = b[0] + br2 = b[ldb] + } + br2 -= lr21 * br1 // Apply the Gaussian elimination step to the right-hand side. + + bbnd := math.Max(math.Abs(ur22*ur11r*br1), math.Abs(br2)) + if bbnd > 1 && math.Abs(ur22) < 1 && bbnd >= bignum*math.Abs(ur22) { + scale = 1 / bbnd + } + + // Solve the linear system ur*xr=br. + xr2 := br2 * scale / ur22 + xr1 := scale*br1*ur11r - ur11r*ur12*xr2 + if icmax&0x1 != 0 { + // If the pivot lies in the second column, swap the components of the solution. + x[0] = xr2 + x[ldx] = xr1 + } else { + x[0] = xr1 + x[ldx] = xr2 + } + xnorm = math.Max(math.Abs(xr1), math.Abs(xr2)) + + // Further scaling if norm(A)*norm(X) > overflow. + if xnorm > 1 && cmax > 1 && xnorm > bignum/cmax { + temp := cmax / bignum + x[0] *= temp + x[ldx] *= temp + xnorm *= temp + scale *= temp + } + + return scale, xnorm, ok + } + + // Complex 2×2 system (w is complex). + + // Find the largest element in C. + civ := [4]float64{ + -wi * d1, + 0, + 0, + -wi * d2, + } + var cmax float64 + var icmax int + for j, v := range crv { + v := math.Abs(v) + if v+math.Abs(civ[j]) > cmax { + cmax = v + math.Abs(civ[j]) + icmax = j + } + } + + // If norm(C) < smini, use smini*identity. + if cmax < smini { + br1 := math.Abs(b[0]) + math.Abs(b[1]) + br2 := math.Abs(b[ldb]) + math.Abs(b[ldb+1]) + bnorm := math.Max(br1, br2) + if smini < 1 && bnorm > 1 && bnorm > bignum*smini { + scale = 1 / bnorm + } + temp := scale / smini + x[0] = temp * b[0] + x[1] = temp * b[1] + x[ldb] = temp * b[ldb] + x[ldb+1] = temp * b[ldb+1] + xnorm = temp * bnorm + ok = false + + return scale, xnorm, ok + } + + // Gaussian elimination with complete pivoting. + ur11 := crv[icmax] + ui11 := civ[icmax] + ur12 := crv[pivot[icmax][1]] + ui12 := civ[pivot[icmax][1]] + cr21 := crv[pivot[icmax][2]] + ci21 := civ[pivot[icmax][2]] + cr22 := crv[pivot[icmax][3]] + ci22 := civ[pivot[icmax][3]] + var ( + ur11r, ui11r float64 + lr21, li21 float64 + ur12s, ui12s float64 + ur22, ui22 float64 + ) + if icmax == 0 || icmax == 3 { + // Off-diagonals of pivoted C are real. + if math.Abs(ur11) > math.Abs(ui11) { + temp := ui11 / ur11 + ur11r = 1 / (ur11 * (1 + temp*temp)) + ui11r = -temp * ur11r + } else { + temp := ur11 / ui11 + ui11r = -1 / (ui11 * (1 + temp*temp)) + ur11r = -temp * ui11r + } + lr21 = cr21 * ur11r + li21 = cr21 * ui11r + ur12s = ur12 * ur11r + ui12s = ur12 * ui11r + ur22 = cr22 - ur12*lr21 + ui22 = ci22 - ur12*li21 + } else { + // Diagonals of pivoted C are real. + ur11r = 1 / ur11 + // ui11r is already 0. + lr21 = cr21 * ur11r + li21 = ci21 * ur11r + ur12s = ur12 * ur11r + ui12s = ui12 * ur11r + ur22 = cr22 - ur12*lr21 + ui12*li21 + ui22 = -ur12*li21 - ui12*lr21 + } + u22abs := math.Abs(ur22) + math.Abs(ui22) + + // If smaller pivot < smini, use smini. + if u22abs < smini { + ur22 = smini + ui22 = 0 + ok = false + } + + var br1, bi1 float64 + var br2, bi2 float64 + if icmax > 1 { + // If the pivot lies in the second row, swap the rows. + br1 = b[ldb] + bi1 = b[ldb+1] + br2 = b[0] + bi2 = b[1] + } else { + br1 = b[0] + bi1 = b[1] + br2 = b[ldb] + bi2 = b[ldb+1] + } + br2 += -lr21*br1 + li21*bi1 + bi2 += -li21*br1 - lr21*bi1 + + bbnd1 := u22abs * (math.Abs(ur11r) + math.Abs(ui11r)) * (math.Abs(br1) + math.Abs(bi1)) + bbnd2 := math.Abs(br2) + math.Abs(bi2) + bbnd := math.Max(bbnd1, bbnd2) + if bbnd > 1 && u22abs < 1 && bbnd >= bignum*u22abs { + scale = 1 / bbnd + br1 *= scale + bi1 *= scale + br2 *= scale + bi2 *= scale + } + + cx2 := complex(br2, bi2) / complex(ur22, ui22) + xr2, xi2 := real(cx2), imag(cx2) + xr1 := ur11r*br1 - ui11r*bi1 - ur12s*xr2 + ui12s*xi2 + xi1 := ui11r*br1 + ur11r*bi1 - ui12s*xr2 - ur12s*xi2 + if icmax&0x1 != 0 { + // If the pivot lies in the second column, swap the components of the solution. + x[0] = xr2 + x[1] = xi2 + x[ldx] = xr1 + x[ldx+1] = xi1 + } else { + x[0] = xr1 + x[1] = xi1 + x[ldx] = xr2 + x[ldx+1] = xi2 + } + xnorm = math.Max(math.Abs(xr1)+math.Abs(xi1), math.Abs(xr2)+math.Abs(xi2)) + + // Further scaling if norm(A)*norm(X) > overflow. + if xnorm > 1 && cmax > 1 && xnorm > bignum/cmax { + temp := cmax / bignum + x[0] *= temp + x[1] *= temp + x[ldx] *= temp + x[ldx+1] *= temp + xnorm *= temp + scale *= temp + } + + return scale, xnorm, ok +} diff --git a/lapack/native/dlange.go b/lapack/native/dlange.go new file mode 100644 index 00000000..aa924aa0 --- /dev/null +++ b/lapack/native/dlange.go @@ -0,0 +1,84 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dlange computes the matrix norm of the general m×n matrix a. The input norm +// specifies the norm computed. +// lapack.MaxAbs: the maximum absolute value of an element. +// lapack.MaxColumnSum: the maximum column sum of the absolute values of the entries. +// lapack.MaxRowSum: the maximum row sum of the absolute values of the entries. +// lapack.NormFrob: the square root of the sum of the squares of the entries. +// If norm == lapack.MaxColumnSum, work must be of length n, and this function will panic otherwise. +// There are no restrictions on work for the other matrix norms. +func (impl Implementation) Dlange(norm lapack.MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 { + // TODO(btracey): These should probably be refactored to use BLAS calls. + checkMatrix(m, n, a, lda) + switch norm { + case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: + default: + panic(badNorm) + } + if norm == lapack.MaxColumnSum && len(work) < n { + panic(badWork) + } + if m == 0 && n == 0 { + return 0 + } + if norm == lapack.MaxAbs { + var value float64 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + value = math.Max(value, math.Abs(a[i*lda+j])) + } + } + return value + } + if norm == lapack.MaxColumnSum { + if len(work) < n { + panic(badWork) + } + for i := 0; i < n; i++ { + work[i] = 0 + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + var value float64 + for i := 0; i < n; i++ { + value = math.Max(value, work[i]) + } + return value + } + if norm == lapack.MaxRowSum { + var value float64 + for i := 0; i < m; i++ { + var sum float64 + for j := 0; j < n; j++ { + sum += math.Abs(a[i*lda+j]) + } + value = math.Max(value, sum) + } + return value + } + if norm == lapack.NormFrob { + var value float64 + scale := 0.0 + sum := 1.0 + for i := 0; i < m; i++ { + scale, sum = impl.Dlassq(n, a[i*lda:], 1, scale, sum) + } + value = scale * math.Sqrt(sum) + return value + } + panic("lapack: bad matrix norm") +} diff --git a/lapack/native/dlanst.go b/lapack/native/dlanst.go new file mode 100644 index 00000000..2987d3ba --- /dev/null +++ b/lapack/native/dlanst.go @@ -0,0 +1,68 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dlanst computes the specified norm of a symmetric tridiagonal matrix A. +// The diagonal elements of A are stored in d and the off-diagonal elements +// are stored in e. +func (impl Implementation) Dlanst(norm lapack.MatrixNorm, n int, d, e []float64) float64 { + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if n <= 0 { + return 0 + } + switch norm { + default: + panic(badNorm) + case lapack.MaxAbs: + anorm := math.Abs(d[n-1]) + for i := 0; i < n-1; i++ { + sum := math.Abs(d[i]) + if anorm < sum || math.IsNaN(sum) { + anorm = sum + } + sum = math.Abs(e[i]) + if anorm < sum || math.IsNaN(sum) { + anorm = sum + } + } + return anorm + case lapack.MaxColumnSum, lapack.MaxRowSum: + if n == 1 { + return math.Abs(d[0]) + } + anorm := math.Abs(d[0]) + math.Abs(e[0]) + sum := math.Abs(e[n-2]) + math.Abs(d[n-1]) + if anorm < sum || math.IsNaN(sum) { + anorm = sum + } + for i := 1; i < n-1; i++ { + sum := math.Abs(d[i]) + math.Abs(e[i]) + math.Abs(e[i-1]) + if anorm < sum || math.IsNaN(sum) { + anorm = sum + } + } + return anorm + case lapack.NormFrob: + var scale float64 + sum := 1.0 + if n > 1 { + scale, sum = impl.Dlassq(n-1, e, 1, scale, sum) + sum = 2 * sum + } + scale, sum = impl.Dlassq(n, d, 1, scale, sum) + return scale * math.Sqrt(sum) + } +} diff --git a/lapack/native/dlansy.go b/lapack/native/dlansy.go new file mode 100644 index 00000000..bb5a7f22 --- /dev/null +++ b/lapack/native/dlansy.go @@ -0,0 +1,125 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dlansy computes the specified norm of an n×n symmetric matrix. If +// norm == lapack.MaxColumnSum or norm == lapackMaxRowSum work must have length +// at least n, otherwise work is unused. +func (impl Implementation) Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 { + checkMatrix(n, n, a, lda) + switch norm { + case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: + default: + panic(badNorm) + } + if (norm == lapack.MaxColumnSum || norm == lapack.MaxRowSum) && len(work) < n { + panic(badWork) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + + if n == 0 { + return 0 + } + switch norm { + default: + panic("unreachable") + case lapack.MaxAbs: + if uplo == blas.Upper { + var max float64 + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := math.Abs(a[i*lda+j]) + if math.IsNaN(v) { + return math.NaN() + } + if v > max { + max = v + } + } + } + return max + } + var max float64 + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := math.Abs(a[i*lda+j]) + if math.IsNaN(v) { + return math.NaN() + } + if v > max { + max = v + } + } + } + return max + case lapack.MaxRowSum, lapack.MaxColumnSum: + // A symmetric matrix has the same 1-norm and ∞-norm. + for i := 0; i < n; i++ { + work[i] = 0 + } + if uplo == blas.Upper { + for i := 0; i < n; i++ { + work[i] += math.Abs(a[i*lda+i]) + for j := i + 1; j < n; j++ { + v := math.Abs(a[i*lda+j]) + work[i] += v + work[j] += v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + v := math.Abs(a[i*lda+j]) + work[i] += v + work[j] += v + } + work[i] += math.Abs(a[i*lda+i]) + } + } + var max float64 + for i := 0; i < n; i++ { + v := work[i] + if math.IsNaN(v) { + return math.NaN() + } + if v > max { + max = v + } + } + return max + case lapack.NormFrob: + if uplo == blas.Upper { + var sum float64 + for i := 0; i < n; i++ { + v := a[i*lda+i] + sum += v * v + for j := i + 1; j < n; j++ { + v := a[i*lda+j] + sum += 2 * v * v + } + } + return math.Sqrt(sum) + } + var sum float64 + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + v := a[i*lda+j] + sum += 2 * v * v + } + v := a[i*lda+i] + sum += v * v + } + return math.Sqrt(sum) + } +} diff --git a/lapack/native/dlantr.go b/lapack/native/dlantr.go new file mode 100644 index 00000000..7cb77d49 --- /dev/null +++ b/lapack/native/dlantr.go @@ -0,0 +1,252 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dlantr computes the specified norm of an m×n trapezoidal matrix A. If +// norm == lapack.MaxColumnSum work must have length at least n, otherwise work +// is unused. +func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 { + checkMatrix(m, n, a, lda) + switch norm { + case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: + default: + panic(badNorm) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.Unit && diag != blas.NonUnit { + panic(badDiag) + } + if norm == lapack.MaxColumnSum && len(work) < n { + panic(badWork) + } + if min(m, n) == 0 { + return 0 + } + switch norm { + default: + panic("unreachable") + case lapack.MaxAbs: + if diag == blas.Unit { + value := 1.0 + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + tmp := math.Abs(a[i*lda+j]) + if math.IsNaN(tmp) { + return tmp + } + if tmp > value { + value = tmp + } + } + } + return value + } + for i := 1; i < m; i++ { + for j := 0; j < min(i, n); j++ { + tmp := math.Abs(a[i*lda+j]) + if math.IsNaN(tmp) { + return tmp + } + if tmp > value { + value = tmp + } + } + } + return value + } + var value float64 + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + tmp := math.Abs(a[i*lda+j]) + if math.IsNaN(tmp) { + return tmp + } + if tmp > value { + value = tmp + } + } + } + return value + } + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + tmp := math.Abs(a[i*lda+j]) + if math.IsNaN(tmp) { + return tmp + } + if tmp > value { + value = tmp + } + } + } + return value + case lapack.MaxColumnSum: + if diag == blas.Unit { + for i := 0; i < min(m, n); i++ { + work[i] = 1 + } + for i := min(m, n); i < n; i++ { + work[i] = 0 + } + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + } else { + for i := 1; i < m; i++ { + for j := 0; j < min(i, n); j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + } + } else { + for i := 0; i < n; i++ { + work[i] = 0 + } + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + work[j] += math.Abs(a[i*lda+j]) + } + } + } + } + var max float64 + for _, v := range work[:n] { + if math.IsNaN(v) { + return math.NaN() + } + if v > max { + max = v + } + } + return max + case lapack.MaxRowSum: + var maxsum float64 + if diag == blas.Unit { + if uplo == blas.Upper { + for i := 0; i < m; i++ { + var sum float64 + if i < min(m, n) { + sum = 1 + } + for j := i + 1; j < n; j++ { + sum += math.Abs(a[i*lda+j]) + } + if math.IsNaN(sum) { + return math.NaN() + } + if sum > maxsum { + maxsum = sum + } + } + return maxsum + } else { + for i := 1; i < m; i++ { + var sum float64 + if i < min(m, n) { + sum = 1 + } + for j := 0; j < min(i, n); j++ { + sum += math.Abs(a[i*lda+j]) + } + if math.IsNaN(sum) { + return math.NaN() + } + if sum > maxsum { + maxsum = sum + } + } + return maxsum + } + } else { + if uplo == blas.Upper { + for i := 0; i < m; i++ { + var sum float64 + for j := i; j < n; j++ { + sum += math.Abs(a[i*lda+j]) + } + if math.IsNaN(sum) { + return sum + } + if sum > maxsum { + maxsum = sum + } + } + return maxsum + } else { + for i := 0; i < m; i++ { + var sum float64 + for j := 0; j <= min(i, n-1); j++ { + sum += math.Abs(a[i*lda+j]) + } + if math.IsNaN(sum) { + return sum + } + if sum > maxsum { + maxsum = sum + } + } + return maxsum + } + } + case lapack.NormFrob: + var nrm float64 + if diag == blas.Unit { + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + tmp := a[i*lda+j] + nrm += tmp * tmp + } + } + } else { + for i := 1; i < m; i++ { + for j := 0; j < min(i, n); j++ { + tmp := a[i*lda+j] + nrm += tmp * tmp + } + } + } + nrm += float64(min(m, n)) + } else { + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + tmp := math.Abs(a[i*lda+j]) + nrm += tmp * tmp + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + tmp := math.Abs(a[i*lda+j]) + nrm += tmp * tmp + } + } + } + } + return math.Sqrt(nrm) + } +} diff --git a/lapack/native/dlanv2.go b/lapack/native/dlanv2.go new file mode 100644 index 00000000..d462f6ed --- /dev/null +++ b/lapack/native/dlanv2.go @@ -0,0 +1,132 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlanv2 computes the Schur factorization of a real 2×2 matrix: +// [ a b ] = [ cs -sn ] * [ aa bb ] * [ cs sn ] +// [ c d ] [ sn cs ] [ cc dd ] * [-sn cs ] +// If cc is zero, aa and dd are real eigenvalues of the matrix. Otherwise it +// holds that aa = dd and bb*cc < 0, and aa ± sqrt(bb*cc) are complex conjugate +// eigenvalues. The real and imaginary parts of the eigenvalues are returned in +// (rt1r,rt1i) and (rt2r,rt2i). +func (impl Implementation) Dlanv2(a, b, c, d float64) (aa, bb, cc, dd float64, rt1r, rt1i, rt2r, rt2i float64, cs, sn float64) { + switch { + case c == 0: // Matrix is already upper triangular. + aa = a + bb = b + cc = 0 + dd = d + cs = 1 + sn = 0 + case b == 0: // Matrix is lower triangular, swap rows and columns. + aa = d + bb = -c + cc = 0 + dd = a + cs = 0 + sn = 1 + case a == d && math.Signbit(b) != math.Signbit(c): // Matrix is already in the standard Schur form. + aa = a + bb = b + cc = c + dd = d + cs = 1 + sn = 0 + default: + temp := a - d + p := temp / 2 + bcmax := math.Max(math.Abs(b), math.Abs(c)) + bcmis := math.Min(math.Abs(b), math.Abs(c)) + if b*c < 0 { + bcmis *= -1 + } + scale := math.Max(math.Abs(p), bcmax) + z := p/scale*p + bcmax/scale*bcmis + eps := dlamchP + + if z >= 4*eps { + // Real eigenvalues. Compute aa and dd. + if p > 0 { + z = p + math.Sqrt(scale)*math.Sqrt(z) + } else { + z = p - math.Sqrt(scale)*math.Sqrt(z) + } + aa = d + z + dd = d - bcmax/z*bcmis + // Compute bb and the rotation matrix. + tau := impl.Dlapy2(c, z) + cs = z / tau + sn = c / tau + bb = b - c + cc = 0 + } else { + // Complex eigenvalues, or real (almost) equal eigenvalues. + // Make diagonal elements equal. + sigma := b + c + tau := impl.Dlapy2(sigma, temp) + cs = math.Sqrt((1 + math.Abs(sigma)/tau) / 2) + sn = -p / (tau * cs) + if sigma < 0 { + sn *= -1 + } + // Compute [ aa bb ] = [ a b ] [ cs -sn ] + // [ cc dd ] [ c d ] [ sn cs ] + aa = a*cs + b*sn + bb = -a*sn + b*cs + cc = c*cs + d*sn + dd = -c*sn + d*cs + // Compute [ a b ] = [ cs sn ] [ aa bb ] + // [ c d ] [-sn cs ] [ cc dd ] + a = aa*cs + cc*sn + b = bb*cs + dd*sn + c = -aa*sn + cc*cs + d = -bb*sn + dd*cs + + temp = (a + d) / 2 + aa = temp + bb = b + cc = c + dd = temp + + if cc != 0 { + if bb != 0 { + if math.Signbit(bb) == math.Signbit(cc) { + // Real eigenvalues, reduce to + // upper triangular form. + sab := math.Sqrt(math.Abs(bb)) + sac := math.Sqrt(math.Abs(cc)) + p = sab * sac + if cc < 0 { + p *= -1 + } + tau = 1 / math.Sqrt(math.Abs(bb+cc)) + aa = temp + p + bb = bb - cc + cc = 0 + dd = temp - p + cs1 := sab * tau + sn1 := sac * tau + cs, sn = cs*cs1-sn*sn1, cs*sn1+sn+cs1 + } + } else { + bb = -cc + cc = 0 + cs, sn = -sn, cs + } + } + } + } + + // Store eigenvalues in (rt1r,rt1i) and (rt2r,rt2i). + rt1r = aa + rt2r = dd + if cc != 0 { + rt1i = math.Sqrt(math.Abs(bb)) * math.Sqrt(math.Abs(cc)) + rt2i = -rt1i + } + return +} diff --git a/lapack/native/dlapll.go b/lapack/native/dlapll.go new file mode 100644 index 00000000..f424e280 --- /dev/null +++ b/lapack/native/dlapll.go @@ -0,0 +1,36 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas/blas64" + +// Dlapll returns the smallest singular value of the n×2 matrix A = [ x y ]. +// The function first computes the QR factorization of A = Q*R, and then computes +// the SVD of the 2-by-2 upper triangular matrix r. +// +// The contents of x and y are overwritten during the call. +// +// Dlapll is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlapll(n int, x []float64, incX int, y []float64, incY int) float64 { + checkVector(n, x, incX) + checkVector(n, y, incY) + + if n <= 1 { + return 0 + } + + // Compute the QR factorization of the N-by-2 matrix [ X Y ]. + a00, tau := impl.Dlarfg(n, x[0], x[incX:], incX) + x[0] = 1 + + bi := blas64.Implementation() + c := -tau * bi.Ddot(n, x, incX, y, incY) + bi.Daxpy(n, c, x, incX, y, incY) + a11, _ := impl.Dlarfg(n-1, y[incY], y[2*incY:], incY) + + // Compute the SVD of 2-by-2 upper triangular matrix. + ssmin, _ := impl.Dlas2(a00, y[0], a11) + return ssmin +} diff --git a/lapack/native/dlapmt.go b/lapack/native/dlapmt.go new file mode 100644 index 00000000..0496902d --- /dev/null +++ b/lapack/native/dlapmt.go @@ -0,0 +1,72 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas/blas64" + +// Dlapmt rearranges the columns of the m×n matrix X as specified by the +// permutation k_0, k_1, ..., k_n-1 of the integers 0, ..., n-1. +// +// If forward is true a forward permutation is performed: +// +// X[0:m, k[j]] is moved to X[0:m, j] for j = 0, 1, ..., n-1. +// +// otherwise a backward permutation is performed: +// +// X[0:m, j] is moved to X[0:m, k[j]] for j = 0, 1, ..., n-1. +// +// k must have length n, otherwise Dlapmt will panic. k is zero-indexed. +func (impl Implementation) Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) { + checkMatrix(m, n, x, ldx) + if len(k) != n { + panic(badKperm) + } + + if n <= 1 { + return + } + + for i, v := range k { + v++ + k[i] = -v + } + + bi := blas64.Implementation() + + if forward { + for j, v := range k { + if v >= 0 { + continue + } + k[j] = -v + i := -v - 1 + for k[i] < 0 { + bi.Dswap(m, x[j:], ldx, x[i:], ldx) + + k[i] = -k[i] + j = i + i = k[i] - 1 + } + } + } else { + for i, v := range k { + if v >= 0 { + continue + } + k[i] = -v + j := -v - 1 + for j != i { + bi.Dswap(m, x[j:], ldx, x[i:], ldx) + + k[j] = -k[j] + j = k[j] - 1 + } + } + } + + for i := range k { + k[i]-- + } +} diff --git a/lapack/native/dlapy2.go b/lapack/native/dlapy2.go new file mode 100644 index 00000000..052a73a9 --- /dev/null +++ b/lapack/native/dlapy2.go @@ -0,0 +1,14 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlapy2 is the LAPACK version of math.Hypot. +// +// Dlapy2 is an internal routine. It is exported for testing purposes. +func (Implementation) Dlapy2(x, y float64) float64 { + return math.Hypot(x, y) +} diff --git a/lapack/native/dlaqp2.go b/lapack/native/dlaqp2.go new file mode 100644 index 00000000..2ef72461 --- /dev/null +++ b/lapack/native/dlaqp2.go @@ -0,0 +1,111 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlaqp2 computes a QR factorization with column pivoting of the block A[offset:m, 0:n] +// of the m×n matrix A. The block A[0:offset, 0:n] is accordingly pivoted, but not factorized. +// +// On exit, the upper triangle of block A[offset:m, 0:n] is the triangular factor obtained. +// The elements in block A[offset:m, 0:n] below the diagonal, together with tau, represent +// the orthogonal matrix Q as a product of elementary reflectors. +// +// offset is number of rows of the matrix A that must be pivoted but not factorized. +// offset must not be negative otherwise Dlaqp2 will panic. +// +// On exit, jpvt holds the permutation that was applied; the jth column of A*P was the +// jpvt[j] column of A. jpvt must have length n, otherwise Dlaqp2 will panic. +// +// On exit tau holds the scalar factors of the elementary reflectors. It must have length +// at least min(m-offset, n) otherwise Dlaqp2 will panic. +// +// vn1 and vn2 hold the partial and complete column norms respectively. They must have length n, +// otherwise Dlaqp2 will panic. +// +// work must have length n, otherwise Dlaqp2 will panic. +// +// Dlaqp2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqp2(m, n, offset int, a []float64, lda int, jpvt []int, tau, vn1, vn2, work []float64) { + checkMatrix(m, n, a, lda) + if len(jpvt) != n { + panic(badIpiv) + } + mn := min(m-offset, n) + if len(tau) < mn { + panic(badTau) + } + if len(vn1) < n { + panic(badVn1) + } + if len(vn2) < n { + panic(badVn2) + } + if len(work) < n { + panic(badWork) + } + + tol3z := math.Sqrt(dlamchE) + + bi := blas64.Implementation() + + // Compute factorization. + for i := 0; i < mn; i++ { + offpi := offset + i + + // Determine ith pivot column and swap if necessary. + p := i + bi.Idamax(n-i, vn1[i:], 1) + if p != i { + bi.Dswap(m, a[p:], lda, a[i:], lda) + jpvt[p], jpvt[i] = jpvt[i], jpvt[p] + vn1[p] = vn1[i] + vn2[p] = vn2[i] + } + + // Generate elementary reflector H_i. + if offpi < m-1 { + a[offpi*lda+i], tau[i] = impl.Dlarfg(m-offpi, a[offpi*lda+i], a[(offpi+1)*lda+i:], lda) + } else { + tau[i] = 0 + } + + if i < n-1 { + // Apply H_i^T to A[offset+i:m, i:n] from the left. + aii := a[offpi*lda+i] + a[offpi*lda+i] = 1 + impl.Dlarf(blas.Left, m-offpi, n-i-1, a[offpi*lda+i:], lda, tau[i], a[offpi*lda+i+1:], lda, work) + a[offpi*lda+i] = aii + } + + // Update partial column norms. + for j := i + 1; j < n; j++ { + if vn1[j] == 0 { + continue + } + + // The following marked lines follow from the + // analysis in Lapack Working Note 176. + r := math.Abs(a[offpi*lda+j]) / vn1[j] // * + temp := math.Max(0, 1-r*r) // * + r = vn1[j] / vn2[j] // * + temp2 := temp * r * r // * + if temp2 < tol3z { + var v float64 + if offpi < m-1 { + v = bi.Dnrm2(m-offpi-1, a[(offpi+1)*lda+j:], lda) + } + vn1[j] = v + vn2[j] = v + } else { + vn1[j] *= math.Sqrt(temp) // * + } + } + } +} diff --git a/lapack/native/dlaqps.go b/lapack/native/dlaqps.go new file mode 100644 index 00000000..6b2a47a3 --- /dev/null +++ b/lapack/native/dlaqps.go @@ -0,0 +1,217 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlaqps computes a step of QR factorization with column pivoting +// of an m×n matrix A by using Blas-3. It tries to factorize nb +// columns from A starting from the row offset, and updates all +// of the matrix with Dgemm. +// +// In some cases, due to catastrophic cancellations, it cannot +// factorize nb columns. Hence, the actual number of factorized +// columns is returned in kb. +// +// Dlaqps computes a QR factorization with column pivoting of the +// block A[offset:m, 0:nb] of the m×n matrix A. The block +// A[0:offset, 0:n] is accordingly pivoted, but not factorized. +// +// On exit, the upper triangle of block A[offset:m, 0:kb] is the +// triangular factor obtained. The elements in block A[offset:m, 0:n] +// below the diagonal, together with tau, represent the orthogonal +// matrix Q as a product of elementary reflectors. +// +// offset is number of rows of the matrix A that must be pivoted but +// not factorized. offset must not be negative otherwise Dlaqps will panic. +// +// On exit, jpvt holds the permutation that was applied; the jth column +// of A*P was the jpvt[j] column of A. jpvt must have length n, +// otherwise Dlapqs will panic. +// +// On exit tau holds the scalar factors of the elementary reflectors. +// It must have length nb, otherwise Dlapqs will panic. +// +// vn1 and vn2 hold the partial and complete column norms respectively. +// They must have length n, otherwise Dlapqs will panic. +// +// auxv must have length nb, otherwise Dlaqps will panic. +// +// f and ldf represent an n×nb matrix F that is overwritten during the +// call. +// +// Dlaqps is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqps(m, n, offset, nb int, a []float64, lda int, jpvt []int, tau, vn1, vn2, auxv, f []float64, ldf int) (kb int) { + checkMatrix(m, n, a, lda) + checkMatrix(n, nb, f, ldf) + if offset > m { + panic(offsetGTM) + } + if n < 0 || nb > n { + panic(badNb) + } + if len(jpvt) != n { + panic(badIpiv) + } + if len(tau) < nb { + panic(badTau) + } + if len(vn1) < n { + panic(badVn1) + } + if len(vn2) < n { + panic(badVn2) + } + if len(auxv) < nb { + panic(badAuxv) + } + + lastrk := min(m, n+offset) + lsticc := -1 + tol3z := math.Sqrt(dlamchE) + + bi := blas64.Implementation() + + var k, rk int + for ; k < nb && lsticc == -1; k++ { + rk = offset + k + + // Determine kth pivot column and swap if necessary. + p := k + bi.Idamax(n-k, vn1[k:], 1) + if p != k { + bi.Dswap(m, a[p:], lda, a[k:], lda) + bi.Dswap(k, f[p*ldf:], 1, f[k*ldf:], 1) + jpvt[p], jpvt[k] = jpvt[k], jpvt[p] + vn1[p] = vn1[k] + vn2[p] = vn2[k] + } + + // Apply previous Householder reflectors to column K: + // + // A[rk:m, k] = A[rk:m, k] - A[rk:m, 0:k-1]*F[k, 0:k-1]^T. + if k > 0 { + bi.Dgemv(blas.NoTrans, m-rk, k, -1, + a[rk*lda:], lda, + f[k*ldf:], 1, + 1, + a[rk*lda+k:], lda) + } + + // Generate elementary reflector H_k. + if rk < m-1 { + a[rk*lda+k], tau[k] = impl.Dlarfg(m-rk, a[rk*lda+k], a[(rk+1)*lda+k:], lda) + } else { + tau[k] = 0 + } + + akk := a[rk*lda+k] + a[rk*lda+k] = 1 + + // Compute kth column of F: + // + // Compute F[k+1:n, k] = tau[k]*A[rk:m, k+1:n]^T*A[rk:m, k]. + if k < n-1 { + bi.Dgemv(blas.Trans, m-rk, n-k-1, tau[k], + a[rk*lda+k+1:], lda, + a[rk*lda+k:], lda, + 0, + f[(k+1)*ldf+k:], ldf) + } + + // Padding F[0:k, k] with zeros. + for j := 0; j < k; j++ { + f[j*ldf+k] = 0 + } + + // Incremental updating of F: + // + // F[0:n, k] := F[0:n, k] - tau[k]*F[0:n, 0:k-1]*A[rk:m, 0:k-1]^T*A[rk:m,k]. + if k > 0 { + bi.Dgemv(blas.Trans, m-rk, k, -tau[k], + a[rk*lda:], lda, + a[rk*lda+k:], lda, + 0, + auxv, 1) + bi.Dgemv(blas.NoTrans, n, k, 1, + f, ldf, + auxv, 1, + 1, + f[k:], ldf) + } + + // Update the current row of A: + // + // A[rk, k+1:n] = A[rk, k+1:n] - A[rk, 0:k]*F[k+1:n, 0:k]^T. + if k < n-1 { + bi.Dgemv(blas.NoTrans, n-k-1, k+1, -1, + f[(k+1)*ldf:], ldf, + a[rk*lda:], 1, + 1, + a[rk*lda+k+1:], 1) + } + + // Update partial column norms. + if rk < lastrk-1 { + for j := k + 1; j < n; j++ { + if vn1[j] == 0 { + continue + } + + // The following marked lines follow from the + // analysis in Lapack Working Note 176. + r := math.Abs(a[rk*lda+j]) / vn1[j] // * + temp := math.Max(0, 1-r*r) // * + r = vn1[j] / vn2[j] // * + temp2 := temp * r * r // * + if temp2 < tol3z { + // vn2 is used here as a collection of + // indices into vn2 and also a collection + // of column norms. + vn2[j] = float64(lsticc) + lsticc = j + } else { + vn1[j] *= math.Sqrt(temp) // * + } + } + } + + a[rk*lda+k] = akk + } + kb = k + rk = offset + kb + + // Apply the block reflector to the rest of the matrix: + // + // A[offset+kb+1:m, kb+1:n] := A[offset+kb+1:m, kb+1:n] - A[offset+kb+1:m, 1:kb]*F[kb+1:n, 1:kb]^T. + if kb < min(n, m-offset) { + bi.Dgemm(blas.NoTrans, blas.Trans, + m-rk, n-kb, kb, -1, + a[rk*lda:], lda, + f[kb*ldf:], ldf, + 1, + a[rk*lda+kb:], lda) + } + + // Recomputation of difficult columns. + for lsticc >= 0 { + itemp := int(vn2[lsticc]) + + // NOTE: The computation of vn1[lsticc] relies on the fact that + // Dnrm2 does not fail on vectors with norm below the value of + // sqrt(dlamchS) + v := bi.Dnrm2(m-rk, a[rk*lda+lsticc:], lda) + vn1[lsticc] = v + vn2[lsticc] = v + + lsticc = itemp + } + + return kb +} diff --git a/lapack/native/dlaqr04.go b/lapack/native/dlaqr04.go new file mode 100644 index 00000000..d1506074 --- /dev/null +++ b/lapack/native/dlaqr04.go @@ -0,0 +1,475 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" +) + +// Dlaqr04 computes the eigenvalues of a block of an n×n upper Hessenberg matrix +// H, and optionally the matrices T and Z from the Schur decomposition +// H = Z T Z^T +// where T is an upper quasi-triangular matrix (the Schur form), and Z is the +// orthogonal matrix of Schur vectors. +// +// wantt indicates whether the full Schur form T is required. If wantt is false, +// then only enough of H will be updated to preserve the eigenvalues. +// +// wantz indicates whether the n×n matrix of Schur vectors Z is required. If it +// is true, the orthogonal similarity transformation will be accumulated into +// Z[iloz:ihiz+1,ilo:ihi+1], otherwise Z will not be referenced. +// +// ilo and ihi determine the block of H on which Dlaqr04 operates. It must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo == 0 and ihi == -1, if n == 0, +// and the block must be isolated, that is, +// ilo == 0 or H[ilo,ilo-1] == 0, +// ihi == n-1 or H[ihi+1,ihi] == 0, +// otherwise Dlaqr04 will panic. +// +// wr and wi must have length ihi+1. +// +// iloz and ihiz specify the rows of Z to which transformations will be applied +// if wantz is true. It must hold that +// 0 <= iloz <= ilo, and ihi <= ihiz < n, +// otherwise Dlaqr04 will panic. +// +// work must have length at least lwork and lwork must be +// lwork >= 1, if n <= 11, +// lwork >= n, if n > 11, +// otherwise Dlaqr04 will panic. lwork as large as 6*n may be required for +// optimal performance. On return, work[0] will contain the optimal value of +// lwork. +// +// If lwork is -1, instead of performing Dlaqr04, the function only estimates the +// optimal workspace size and stores it into work[0]. Neither h nor z are +// accessed. +// +// recur is the non-negative recursion depth. For recur > 0, Dlaqr04 behaves +// as DLAQR0, for recur == 0 it behaves as DLAQR4. +// +// unconverged indicates whether Dlaqr04 computed all the eigenvalues of H[ilo:ihi+1,ilo:ihi+1]. +// +// If unconverged is zero and wantt is true, H will contain on return the upper +// quasi-triangular matrix T from the Schur decomposition. 2×2 diagonal blocks +// (corresponding to complex conjugate pairs of eigenvalues) will be returned in +// standard form, with H[i,i] == H[i+1,i+1] and H[i+1,i]*H[i,i+1] < 0. +// +// If unconverged is zero and if wantt is false, the contents of h on return is +// unspecified. +// +// If unconverged is zero, all the eigenvalues have been computed and their real +// and imaginary parts will be stored on return in wr[ilo:ihi+1] and +// wi[ilo:ihi+1], respectively. If two eigenvalues are computed as a complex +// conjugate pair, they are stored in consecutive elements of wr and wi, say the +// i-th and (i+1)th, with wi[i] > 0 and wi[i+1] < 0. If wantt is true, then the +// eigenvalues are stored in the same order as on the diagonal of the Schur form +// returned in H, with wr[i] = H[i,i] and, if H[i:i+2,i:i+2] is a 2×2 diagonal +// block, wi[i] = sqrt(-H[i+1,i]*H[i,i+1]) and wi[i+1] = -wi[i]. +// +// If unconverged is positive, some eigenvalues have not converged, and +// wr[unconverged:ihi+1] and wi[unconverged:ihi+1] will contain those +// eigenvalues which have been successfully computed. Failures are rare. +// +// If unconverged is positive and wantt is true, then on return +// (initial H)*U = U*(final H), (*) +// where U is an orthogonal matrix. The final H is upper Hessenberg and +// H[unconverged:ihi+1,unconverged:ihi+1] is upper quasi-triangular. +// +// If unconverged is positive and wantt is false, on return the remaining +// unconverged eigenvalues are the eigenvalues of the upper Hessenberg matrix +// H[ilo:unconverged,ilo:unconverged]. +// +// If unconverged is positive and wantz is true, then on return +// (final Z) = (initial Z)*U, +// where U is the orthogonal matrix in (*) regardless of the value of wantt. +// +// References: +// [1] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part I: +// Maintaining Well-Focused Shifts and Level 3 Performance. SIAM J. Matrix +// Anal. Appl. 23(4) (2002), pp. 929—947 +// URL: http://dx.doi.org/10.1137/S0895479801384573 +// [2] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: +// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl. 23(4) (2002), pp. 948—973 +// URL: http://dx.doi.org/10.1137/S0895479801384585 +// +// Dlaqr04 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int, work []float64, lwork int, recur int) (unconverged int) { + const ( + // Matrices of order ntiny or smaller must be processed by + // Dlahqr because of insufficient subdiagonal scratch space. + // This is a hard limit. + ntiny = 11 + // Exceptional deflation windows: try to cure rare slow + // convergence by varying the size of the deflation window after + // kexnw iterations. + kexnw = 5 + // Exceptional shifts: try to cure rare slow convergence with + // ad-hoc exceptional shifts every kexsh iterations. + kexsh = 6 + + // See https://github.com/gonum/lapack/pull/151#discussion_r68162802 + // and the surrounding discussion for an explanation where these + // constants come from. + // TODO(vladimir-ch): Similar constants for exceptional shifts + // are used also in dlahqr.go. The first constant is different + // there, it is equal to 3. Why? And does it matter? + wilk1 = 0.75 + wilk2 = -0.4375 + ) + + switch { + case ilo < 0 || max(0, n-1) < ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case lwork < 1 && n <= ntiny && lwork != -1: + panic(badWork) + // TODO(vladimir-ch): Enable if and when we figure out what the minimum + // necessary lwork value is. Dlaqr04 says that the minimum is n which + // clashes with Dlaqr23's opinion about optimal work when nw <= 2 + // (independent of n). + // case lwork < n && n > ntiny && lwork != -1: + // panic(badWork) + case len(work) < lwork: + panic(shortWork) + case recur < 0: + panic("lapack: recur is negative") + } + if wantz { + if iloz < 0 || ilo < iloz { + panic("lapack: invalid value of iloz") + } + if ihiz < ihi || n <= ihiz { + panic("lapack: invalid value of ihiz") + } + } + if lwork != -1 { + checkMatrix(n, n, h, ldh) + if wantz { + checkMatrix(n, n, z, ldz) + } + switch { + case ilo > 0 && h[ilo*ldh+ilo-1] != 0: + panic("lapack: block not isolated") + case ihi+1 < n && h[(ihi+1)*ldh+ihi] != 0: + panic("lapack: block not isolated") + case len(wr) != ihi+1: + panic("lapack: bad length of wr") + case len(wi) != ihi+1: + panic("lapack: bad length of wi") + } + } + + // Quick return. + if n == 0 { + work[0] = 1 + return 0 + } + + if n <= ntiny { + // Tiny matrices must use Dlahqr. + work[0] = 1 + if lwork == -1 { + return 0 + } + return impl.Dlahqr(wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, iloz, ihiz, z, ldz) + } + + // Use small bulge multi-shift QR with aggressive early deflation on + // larger-than-tiny matrices. + var jbcmpz string + if wantt { + jbcmpz = "S" + } else { + jbcmpz = "E" + } + if wantz { + jbcmpz += "V" + } else { + jbcmpz += "N" + } + + var fname string + if recur > 0 { + fname = "DLAQR0" + } else { + fname = "DLAQR4" + } + // nwr is the recommended deflation window size. n is greater than 11, + // so there is enough subdiagonal workspace for nwr >= 2 as required. + // (In fact, there is enough subdiagonal space for nwr >= 3.) + // TODO(vladimir-ch): If there is enough space for nwr >= 3, should we + // use it? + nwr := impl.Ilaenv(13, fname, jbcmpz, n, ilo, ihi, lwork) + nwr = max(2, nwr) + nwr = min(ihi-ilo+1, min((n-1)/3, nwr)) + + // nsr is the recommended number of simultaneous shifts. n is greater + // than 11, so there is enough subdiagonal workspace for nsr to be even + // and greater than or equal to two as required. + nsr := impl.Ilaenv(15, fname, jbcmpz, n, ilo, ihi, lwork) + nsr = min(nsr, min((n+6)/9, ihi-ilo)) + nsr = max(2, nsr&^1) + + // Workspace query call to Dlaqr23. + impl.Dlaqr23(wantt, wantz, n, ilo, ihi, nwr+1, nil, 0, iloz, ihiz, nil, 0, + nil, nil, nil, 0, n, nil, 0, n, nil, 0, work, -1, recur) + // Optimal workspace is max(Dlaqr5, Dlaqr23). + lwkopt := max(3*nsr/2, int(work[0])) + // Quick return in case of workspace query. + if lwork == -1 { + work[0] = float64(lwkopt) + return 0 + } + + // Dlahqr/Dlaqr04 crossover point. + nmin := impl.Ilaenv(12, fname, jbcmpz, n, ilo, ihi, lwork) + nmin = max(ntiny, nmin) + + // Nibble determines when to skip a multi-shift QR sweep (Dlaqr5). + nibble := impl.Ilaenv(14, fname, jbcmpz, n, ilo, ihi, lwork) + nibble = max(0, nibble) + + // Computation mode of far-from-diagonal orthogonal updates in Dlaqr5. + kacc22 := impl.Ilaenv(16, fname, jbcmpz, n, ilo, ihi, lwork) + kacc22 = max(0, min(kacc22, 2)) + + // nwmax is the largest possible deflation window for which there is + // sufficient workspace. + nwmax := min((n-1)/3, lwork/2) + nw := nwmax // Start with maximum deflation window size. + + // nsmax is the largest number of simultaneous shifts for which there is + // sufficient workspace. + nsmax := min((n+6)/9, 2*lwork/3) &^ 1 + + ndfl := 1 // Number of iterations since last deflation. + ndec := 0 // Deflation window size decrement. + + // Main loop. + var ( + itmax = max(30, 2*kexsh) * max(10, (ihi-ilo+1)) + it = 0 + ) + for kbot := ihi; kbot >= ilo; { + if it == itmax { + unconverged = kbot + 1 + break + } + it++ + + // Locate active block. + ktop := ilo + for k := kbot; k >= ilo+1; k-- { + if h[k*ldh+k-1] == 0 { + ktop = k + break + } + } + + // Select deflation window size nw. + // + // Typical Case: + // If possible and advisable, nibble the entire active block. + // If not, use size min(nwr,nwmax) or min(nwr+1,nwmax) + // depending upon which has the smaller corresponding + // subdiagonal entry (a heuristic). + // + // Exceptional Case: + // If there have been no deflations in kexnw or more + // iterations, then vary the deflation window size. At first, + // because larger windows are, in general, more powerful than + // smaller ones, rapidly increase the window to the maximum + // possible. Then, gradually reduce the window size. + nh := kbot - ktop + 1 + nwupbd := min(nh, nwmax) + if ndfl < kexnw { + nw = min(nwupbd, nwr) + } else { + nw = min(nwupbd, 2*nw) + } + if nw < nwmax { + if nw >= nh-1 { + nw = nh + } else { + kwtop := kbot - nw + 1 + if math.Abs(h[kwtop*ldh+kwtop-1]) > math.Abs(h[(kwtop-1)*ldh+kwtop-2]) { + nw++ + } + } + } + if ndfl < kexnw { + ndec = -1 + } else if ndec >= 0 || nw >= nwupbd { + ndec++ + if nw-ndec < 2 { + ndec = 0 + } + nw -= ndec + } + + // Split workspace under the subdiagonal of H into: + // - an nw×nw work array V in the lower left-hand corner, + // - an nw×nhv horizontal work array along the bottom edge (nhv + // must be at least nw but more is better), + // - an nve×nw vertical work array along the left-hand-edge + // (nhv can be any positive integer but more is better). + kv := n - nw + kt := nw + kwv := nw + 1 + nhv := n - kwv - kt + // Aggressive early deflation. + ls, ld := impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, + h, ldh, iloz, ihiz, z, ldz, wr[:kbot+1], wi[:kbot+1], + h[kv*ldh:], ldh, nhv, h[kv*ldh+kt:], ldh, nhv, h[kwv*ldh:], ldh, work, lwork, recur) + + // Adjust kbot accounting for new deflations. + kbot -= ld + // ks points to the shifts. + ks := kbot - ls + 1 + + // Skip an expensive QR sweep if there is a (partly heuristic) + // reason to expect that many eigenvalues will deflate without + // it. Here, the QR sweep is skipped if many eigenvalues have + // just been deflated or if the remaining active block is small. + if ld > 0 && (100*ld > nw*nibble || kbot-ktop+1 <= min(nmin, nwmax)) { + // ld is positive, note progress. + ndfl = 1 + continue + } + + // ns is the nominal number of simultaneous shifts. This may be + // lowered (slightly) if Dlaqr23 did not provide that many + // shifts. + ns := min(min(nsmax, nsr), max(2, kbot-ktop)) &^ 1 + + // If there have been no deflations in a multiple of kexsh + // iterations, then try exceptional shifts. Otherwise use shifts + // provided by Dlaqr23 above or from the eigenvalues of a + // trailing principal submatrix. + if ndfl%kexsh == 0 { + ks = kbot - ns + 1 + for i := kbot; i > max(ks, ktop+1); i -= 2 { + ss := math.Abs(h[i*ldh+i-1]) + math.Abs(h[(i-1)*ldh+i-2]) + aa := wilk1*ss + h[i*ldh+i] + _, _, _, _, wr[i-1], wi[i-1], wr[i], wi[i], _, _ = + impl.Dlanv2(aa, ss, wilk2*ss, aa) + } + if ks == ktop { + wr[ks+1] = h[(ks+1)*ldh+ks+1] + wi[ks+1] = 0 + wr[ks] = wr[ks+1] + wi[ks] = wi[ks+1] + } + } else { + // If we got ns/2 or fewer shifts, use Dlahqr or recur + // into Dlaqr04 on a trailing principal submatrix to get + // more. Since ns <= nsmax <=(n+6)/9, there is enough + // space below the subdiagonal to fit an ns×ns scratch + // array. + if kbot-ks+1 <= ns/2 { + ks = kbot - ns + 1 + kt = n - ns + impl.Dlacpy(blas.All, ns, ns, h[ks*ldh+ks:], ldh, h[kt*ldh:], ldh) + if ns > nmin && recur > 0 { + ks += impl.Dlaqr04(false, false, ns, 1, ns-1, h[kt*ldh:], ldh, + wr[ks:ks+ns], wi[ks:ks+ns], 0, 0, nil, 0, work, lwork, recur-1) + } else { + ks += impl.Dlahqr(false, false, ns, 0, ns-1, h[kt*ldh:], ldh, + wr[ks:ks+ns], wi[ks:ks+ns], 0, 0, nil, 0) + } + // In case of a rare QR failure use eigenvalues + // of the trailing 2×2 principal submatrix. + if ks >= kbot { + aa := h[(kbot-1)*ldh+kbot-1] + bb := h[(kbot-1)*ldh+kbot] + cc := h[kbot*ldh+kbot-1] + dd := h[kbot*ldh+kbot] + _, _, _, _, wr[kbot-1], wi[kbot-1], wr[kbot], wi[kbot], _, _ = + impl.Dlanv2(aa, bb, cc, dd) + ks = kbot - 1 + } + } + + if kbot-ks+1 > ns { + // Sorting the shifts helps a little. Bubble + // sort keeps complex conjugate pairs together. + sorted := false + for k := kbot; k > ks; k-- { + if sorted { + break + } + sorted = true + for i := ks; i < k; i++ { + if math.Abs(wr[i])+math.Abs(wi[i]) >= math.Abs(wr[i+1])+math.Abs(wi[i+1]) { + continue + } + sorted = false + wr[i], wr[i+1] = wr[i+1], wr[i] + wi[i], wi[i+1] = wi[i+1], wi[i] + } + } + } + + // Shuffle shifts into pairs of real shifts and pairs of + // complex conjugate shifts using the fact that complex + // conjugate shifts are already adjacent to one another. + // TODO(vladimir-ch): The shuffling here could probably + // be removed but I'm not sure right now and it's safer + // to leave it. + for i := kbot; i > ks+1; i -= 2 { + if wi[i] == -wi[i-1] { + continue + } + wr[i], wr[i-1], wr[i-2] = wr[i-1], wr[i-2], wr[i] + wi[i], wi[i-1], wi[i-2] = wi[i-1], wi[i-2], wi[i] + } + } + + // If there are only two shifts and both are real, then use only one. + if kbot-ks+1 == 2 && wi[kbot] == 0 { + if math.Abs(wr[kbot]-h[kbot*ldh+kbot]) < math.Abs(wr[kbot-1]-h[kbot*ldh+kbot]) { + wr[kbot-1] = wr[kbot] + } else { + wr[kbot] = wr[kbot-1] + } + } + + // Use up to ns of the the smallest magnitude shifts. If there + // aren't ns shifts available, then use them all, possibly + // dropping one to make the number of shifts even. + ns = min(ns, kbot-ks+1) &^ 1 + ks = kbot - ns + 1 + + // Split workspace under the subdiagonal into: + // - a kdu×kdu work array U in the lower left-hand-corner, + // - a kdu×nhv horizontal work array WH along the bottom edge + // (nhv must be at least kdu but more is better), + // - an nhv×kdu vertical work array WV along the left-hand-edge + // (nhv must be at least kdu but more is better). + kdu := 3*ns - 3 + ku := n - kdu + kwh := kdu + kwv = kdu + 3 + nhv = n - kwv - kdu + // Small-bulge multi-shift QR sweep. + impl.Dlaqr5(wantt, wantz, kacc22, n, ktop, kbot, ns, + wr[ks:ks+ns], wi[ks:ks+ns], h, ldh, iloz, ihiz, z, ldz, + work, 3, h[ku*ldh:], ldh, nhv, h[kwv*ldh:], ldh, nhv, h[ku*ldh+kwh:], ldh) + + // Note progress (or the lack of it). + if ld > 0 { + ndfl = 1 + } else { + ndfl++ + } + } + + work[0] = float64(lwkopt) + return unconverged +} diff --git a/lapack/native/dlaqr1.go b/lapack/native/dlaqr1.go new file mode 100644 index 00000000..4d482a5d --- /dev/null +++ b/lapack/native/dlaqr1.go @@ -0,0 +1,57 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlaqr1 sets v to a scalar multiple of the first column of the product +// (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) +// where H is a 2×2 or 3×3 matrix, I is the identity matrix of the same size, +// and i is the imaginary unit. Scaling is done to avoid overflows and most +// underflows. +// +// n is the order of H and must be either 2 or 3. It must hold that either sr1 = +// sr2 and si1 = -si2, or si1 = si2 = 0. The length of v must be equal to n. If +// any of these conditions is not met, Dlaqr1 will panic. +// +// Dlaqr1 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqr1(n int, h []float64, ldh int, sr1, si1, sr2, si2 float64, v []float64) { + if n != 2 && n != 3 { + panic(badDims) + } + checkMatrix(n, n, h, ldh) + if len(v) != n { + panic(badSlice) + } + if !((sr1 == sr2 && si1 == -si2) || (si1 == 0 && si2 == 0)) { + panic(badShifts) + } + + if n == 2 { + s := math.Abs(h[0]-sr2) + math.Abs(si2) + math.Abs(h[ldh]) + if s == 0 { + v[0] = 0 + v[1] = 0 + } else { + h21s := h[ldh] / s + v[0] = h21s*h[1] + (h[0]-sr1)*((h[0]-sr2)/s) - si1*(si2/s) + v[1] = h21s * (h[0] + h[ldh+1] - sr1 - sr2) + } + return + } + + s := math.Abs(h[0]-sr2) + math.Abs(si2) + math.Abs(h[ldh]) + math.Abs(h[2*ldh]) + if s == 0 { + v[0] = 0 + v[1] = 0 + v[2] = 0 + } else { + h21s := h[ldh] / s + h31s := h[2*ldh] / s + v[0] = (h[0]-sr1)*((h[0]-sr2)/s) - si1*(si2/s) + h[1]*h21s + h[2]*h31s + v[1] = h21s*(h[0]+h[ldh+1]-sr1-sr2) + h[ldh+2]*h31s + v[2] = h31s*(h[0]+h[2*ldh+2]-sr1-sr2) + h21s*h[2*ldh+1] + } +} diff --git a/lapack/native/dlaqr23.go b/lapack/native/dlaqr23.go new file mode 100644 index 00000000..70abf9f0 --- /dev/null +++ b/lapack/native/dlaqr23.go @@ -0,0 +1,403 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlaqr23 performs the orthogonal similarity transformation of an n×n upper +// Hessenberg matrix to detect and deflate fully converged eigenvalues from a +// trailing principal submatrix using aggressive early deflation [1]. +// +// On return, H will be overwritten by a new Hessenberg matrix that is a +// perturbation of an orthogonal similarity transformation of H. It is hoped +// that on output H will have many zero subdiagonal entries. +// +// If wantt is true, the matrix H will be fully updated so that the +// quasi-triangular Schur factor can be computed. If wantt is false, then only +// enough of H will be updated to preserve the eigenvalues. +// +// If wantz is true, the orthogonal similarity transformation will be +// accumulated into Z[iloz:ihiz+1,ktop:kbot+1], otherwise Z is not referenced. +// +// ktop and kbot determine a block [ktop:kbot+1,ktop:kbot+1] along the diagonal +// of H. It must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo == 0 and ihi == -1, if n == 0, +// and the block must be isolated, that is, it must hold that +// ktop == 0 or H[ktop,ktop-1] == 0, +// kbot == n-1 or H[kbot+1,kbot] == 0, +// otherwise Dlaqr23 will panic. +// +// nw is the deflation window size. It must hold that +// 0 <= nw <= kbot-ktop+1, +// otherwise Dlaqr23 will panic. +// +// iloz and ihiz specify the rows of the n×n matrix Z to which transformations +// will be applied if wantz is true. It must hold that +// 0 <= iloz <= ktop, and kbot <= ihiz < n, +// otherwise Dlaqr23 will panic. +// +// sr and si must have length kbot+1, otherwise Dlaqr23 will panic. +// +// v and ldv represent an nw×nw work matrix. +// t and ldt represent an nw×nh work matrix, and nh must be at least nw. +// wv and ldwv represent an nv×nw work matrix. +// +// work must have length at least lwork and lwork must be at least max(1,2*nw), +// otherwise Dlaqr23 will panic. Larger values of lwork may result in greater +// efficiency. On return, work[0] will contain the optimal value of lwork. +// +// If lwork is -1, instead of performing Dlaqr23, the function only estimates the +// optimal workspace size and stores it into work[0]. Neither h nor z are +// accessed. +// +// recur is the non-negative recursion depth. For recur > 0, Dlaqr23 behaves +// as DLAQR3, for recur == 0 it behaves as DLAQR2. +// +// On return, ns and nd will contain respectively the number of unconverged +// (i.e., approximate) eigenvalues and converged eigenvalues that are stored in +// sr and si. +// +// On return, the real and imaginary parts of approximate eigenvalues that may +// be used for shifts will be stored respectively in sr[kbot-nd-ns+1:kbot-nd+1] +// and si[kbot-nd-ns+1:kbot-nd+1]. +// +// On return, the real and imaginary parts of converged eigenvalues will be +// stored respectively in sr[kbot-nd+1:kbot+1] and si[kbot-nd+1:kbot+1]. +// +// References: +// [1] K. Braman, R. Byers, R. Mathias. The Multishift QR Algorithm. Part II: +// Aggressive Early Deflation. SIAM J. Matrix Anal. Appl 23(4) (2002), pp. 948—973 +// URL: http://dx.doi.org/10.1137/S0895479801384585 +// +func (impl Implementation) Dlaqr23(wantt, wantz bool, n, ktop, kbot, nw int, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, sr, si []float64, v []float64, ldv int, nh int, t []float64, ldt int, nv int, wv []float64, ldwv int, work []float64, lwork int, recur int) (ns, nd int) { + switch { + case ktop < 0 || max(0, n-1) < ktop: + panic("lapack: invalid value of ktop") + case kbot < min(ktop, n-1) || n <= kbot: + panic("lapack: invalid value of kbot") + case (nw < 0 || kbot-ktop+1 < nw) && lwork != -1: + panic("lapack: invalid value of nw") + case nh < nw: + panic("lapack: invalid value of nh") + case lwork < max(1, 2*nw) && lwork != -1: + panic(badWork) + case len(work) < lwork: + panic(shortWork) + case recur < 0: + panic("lapack: recur is negative") + } + if wantz { + switch { + case iloz < 0 || ktop < iloz: + panic("lapack: invalid value of iloz") + case ihiz < kbot || n <= ihiz: + panic("lapack: invalid value of ihiz") + } + } + if lwork != -1 { + // Check input slices only if not doing workspace query. + checkMatrix(n, n, h, ldh) + checkMatrix(nw, nw, v, ldv) + checkMatrix(nw, nh, t, ldt) + checkMatrix(nv, nw, wv, ldwv) + if wantz { + checkMatrix(n, n, z, ldz) + } + switch { + case ktop > 0 && h[ktop*ldh+ktop-1] != 0: + panic("lapack: block not isolated") + case kbot+1 < n && h[(kbot+1)*ldh+kbot] != 0: + panic("lapack: block not isolated") + case len(sr) != kbot+1: + panic("lapack: bad length of sr") + case len(si) != kbot+1: + panic("lapack: bad length of si") + } + } + + // Quick return for zero window size. + if nw == 0 { + work[0] = 1 + return 0, 0 + } + + // LAPACK code does not enforce the documented behavior + // nw <= kbot-ktop+1 + // but we do (we panic above). + jw := nw + lwkopt := max(1, 2*nw) + if jw > 2 { + // Workspace query call to Dgehrd. + impl.Dgehrd(jw, 0, jw-2, nil, 0, nil, work, -1) + lwk1 := int(work[0]) + // Workspace query call to Dormhr. + impl.Dormhr(blas.Right, blas.NoTrans, jw, jw, 0, jw-2, nil, 0, nil, nil, 0, work, -1) + lwk2 := int(work[0]) + if recur > 0 { + // Workspace query call to Dlaqr04. + impl.Dlaqr04(true, true, jw, 0, jw-1, nil, 0, nil, nil, 0, jw-1, nil, 0, work, -1, recur-1) + lwk3 := int(work[0]) + // Optimal workspace. + lwkopt = max(jw+max(lwk1, lwk2), lwk3) + } else { + // Optimal workspace. + lwkopt = jw + max(lwk1, lwk2) + } + } + // Quick return in case of workspace query. + if lwork == -1 { + work[0] = float64(lwkopt) + return 0, 0 + } + + // Machine constants. + ulp := dlamchP + smlnum := float64(n) / ulp * dlamchS + + // Setup deflation window. + var s float64 + kwtop := kbot - jw + 1 + if kwtop != ktop { + s = h[kwtop*ldh+kwtop-1] + } + if kwtop == kbot { + // 1×1 deflation window. + sr[kwtop] = h[kwtop*ldh+kwtop] + si[kwtop] = 0 + ns = 1 + nd = 0 + if math.Abs(s) <= math.Max(smlnum, ulp*math.Abs(h[kwtop*ldh+kwtop])) { + ns = 0 + nd = 1 + if kwtop > ktop { + h[kwtop*ldh+kwtop-1] = 0 + } + } + work[0] = 1 + return ns, nd + } + + // Convert to spike-triangular form. In case of a rare QR failure, this + // routine continues to do aggressive early deflation using that part of + // the deflation window that converged using infqr here and there to + // keep track. + impl.Dlacpy(blas.Upper, jw, jw, h[kwtop*ldh+kwtop:], ldh, t, ldt) + bi := blas64.Implementation() + bi.Dcopy(jw-1, h[(kwtop+1)*ldh+kwtop:], ldh+1, t[ldt:], ldt+1) + impl.Dlaset(blas.All, jw, jw, 0, 1, v, ldv) + nmin := impl.Ilaenv(12, "DLAQR3", "SV", jw, 0, jw-1, lwork) + var infqr int + if recur > 0 && jw > nmin { + infqr = impl.Dlaqr04(true, true, jw, 0, jw-1, t, ldt, sr[kwtop:], si[kwtop:], 0, jw-1, v, ldv, work, lwork, recur-1) + } else { + infqr = impl.Dlahqr(true, true, jw, 0, jw-1, t, ldt, sr[kwtop:], si[kwtop:], 0, jw-1, v, ldv) + } + // Note that ilo == 0 which conveniently coincides with the success + // value of infqr, that is, infqr as an index always points to the first + // converged eigenvalue. + + // Dtrexc needs a clean margin near the diagonal. + for j := 0; j < jw-3; j++ { + t[(j+2)*ldt+j] = 0 + t[(j+3)*ldt+j] = 0 + } + if jw >= 3 { + t[(jw-1)*ldt+jw-3] = 0 + } + + ns = jw + ilst := infqr + // Deflation detection loop. + for ilst < ns { + bulge := false + if ns >= 2 { + bulge = t[(ns-1)*ldt+ns-2] != 0 + } + if !bulge { + // Real eigenvalue. + abst := math.Abs(t[(ns-1)*ldt+ns-1]) + if abst == 0 { + abst = math.Abs(s) + } + if math.Abs(s*v[ns-1]) <= math.Max(smlnum, ulp*abst) { + // Deflatable. + ns-- + } else { + // Undeflatable, move it up out of the way. + // Dtrexc can not fail in this case. + _, ilst, _ = impl.Dtrexc(lapack.UpdateSchur, jw, t, ldt, v, ldv, ns-1, ilst, work) + ilst++ + } + continue + } + // Complex conjugate pair. + abst := math.Abs(t[(ns-1)*ldt+ns-1]) + math.Sqrt(math.Abs(t[(ns-1)*ldt+ns-2]))*math.Sqrt(math.Abs(t[(ns-2)*ldt+ns-1])) + if abst == 0 { + abst = math.Abs(s) + } + if math.Max(math.Abs(s*v[ns-1]), math.Abs(s*v[ns-2])) <= math.Max(smlnum, ulp*abst) { + // Deflatable. + ns -= 2 + } else { + // Undeflatable, move them up out of the way. + // Dtrexc does the right thing with ilst in case of a + // rare exchange failure. + _, ilst, _ = impl.Dtrexc(lapack.UpdateSchur, jw, t, ldt, v, ldv, ns-1, ilst, work) + ilst += 2 + } + } + + // Return to Hessenberg form. + if ns == 0 { + s = 0 + } + if ns < jw { + // Sorting diagonal blocks of T improves accuracy for graded + // matrices. Bubble sort deals well with exchange failures. + sorted := false + i := ns + for !sorted { + sorted = true + kend := i - 1 + i = infqr + var k int + if i == ns-1 || t[(i+1)*ldt+i] == 0 { + k = i + 1 + } else { + k = i + 2 + } + for k <= kend { + var evi float64 + if k == i+1 { + evi = math.Abs(t[i*ldt+i]) + } else { + evi = math.Abs(t[i*ldt+i]) + math.Sqrt(math.Abs(t[(i+1)*ldt+i]))*math.Sqrt(math.Abs(t[i*ldt+i+1])) + } + + var evk float64 + if k == kend || t[(k+1)*ldt+k] == 0 { + evk = math.Abs(t[k*ldt+k]) + } else { + evk = math.Abs(t[k*ldt+k]) + math.Sqrt(math.Abs(t[(k+1)*ldt+k]))*math.Sqrt(math.Abs(t[k*ldt+k+1])) + } + + if evi >= evk { + i = k + } else { + sorted = false + _, ilst, ok := impl.Dtrexc(lapack.UpdateSchur, jw, t, ldt, v, ldv, i, k, work) + if ok { + i = ilst + } else { + i = k + } + } + if i == kend || t[(i+1)*ldt+i] == 0 { + k = i + 1 + } else { + k = i + 2 + } + } + } + } + + // Restore shift/eigenvalue array from T. + for i := jw - 1; i >= infqr; { + if i == infqr || t[i*ldt+i-1] == 0 { + sr[kwtop+i] = t[i*ldt+i] + si[kwtop+i] = 0 + i-- + continue + } + aa := t[(i-1)*ldt+i-1] + bb := t[(i-1)*ldt+i] + cc := t[i*ldt+i-1] + dd := t[i*ldt+i] + _, _, _, _, sr[kwtop+i-1], si[kwtop+i-1], sr[kwtop+i], si[kwtop+i], _, _ = impl.Dlanv2(aa, bb, cc, dd) + i -= 2 + } + + if ns < jw || s == 0 { + if ns > 1 && s != 0 { + // Reflect spike back into lower triangle. + bi.Dcopy(ns, v[:ns], 1, work[:ns], 1) + _, tau := impl.Dlarfg(ns, work[0], work[1:ns], 1) + work[0] = 1 + impl.Dlaset(blas.Lower, jw-2, jw-2, 0, 0, t[2*ldt:], ldt) + impl.Dlarf(blas.Left, ns, jw, work[:ns], 1, tau, t, ldt, work[jw:]) + impl.Dlarf(blas.Right, ns, ns, work[:ns], 1, tau, t, ldt, work[jw:]) + impl.Dlarf(blas.Right, jw, ns, work[:ns], 1, tau, v, ldv, work[jw:]) + impl.Dgehrd(jw, 0, ns-1, t, ldt, work[:jw-1], work[jw:], lwork-jw) + } + + // Copy updated reduced window into place. + if kwtop > 0 { + h[kwtop*ldh+kwtop-1] = s * v[0] + } + impl.Dlacpy(blas.Upper, jw, jw, t, ldt, h[kwtop*ldh+kwtop:], ldh) + bi.Dcopy(jw-1, t[ldt:], ldt+1, h[(kwtop+1)*ldh+kwtop:], ldh+1) + + // Accumulate orthogonal matrix in order to update H and Z, if + // requested. + if ns > 1 && s != 0 { + // work[:ns-1] contains the elementary reflectors stored + // by a call to Dgehrd above. + impl.Dormhr(blas.Right, blas.NoTrans, jw, ns, 0, ns-1, + t, ldt, work[:ns-1], v, ldv, work[jw:], lwork-jw) + } + + // Update vertical slab in H. + var ltop int + if !wantt { + ltop = ktop + } + for krow := ltop; krow < kwtop; krow += nv { + kln := min(nv, kwtop-krow) + bi.Dgemm(blas.NoTrans, blas.NoTrans, kln, jw, jw, + 1, h[krow*ldh+kwtop:], ldh, v, ldv, + 0, wv, ldwv) + impl.Dlacpy(blas.All, kln, jw, wv, ldwv, h[krow*ldh+kwtop:], ldh) + } + + // Update horizontal slab in H. + if wantt { + for kcol := kbot + 1; kcol < n; kcol += nh { + kln := min(nh, n-kcol) + bi.Dgemm(blas.Trans, blas.NoTrans, jw, kln, jw, + 1, v, ldv, h[kwtop*ldh+kcol:], ldh, + 0, t, ldt) + impl.Dlacpy(blas.All, jw, kln, t, ldt, h[kwtop*ldh+kcol:], ldh) + } + } + + // Update vertical slab in Z. + if wantz { + for krow := iloz; krow <= ihiz; krow += nv { + kln := min(nv, ihiz-krow+1) + bi.Dgemm(blas.NoTrans, blas.NoTrans, kln, jw, jw, + 1, z[krow*ldz+kwtop:], ldz, v, ldv, + 0, wv, ldwv) + impl.Dlacpy(blas.All, kln, jw, wv, ldwv, z[krow*ldz+kwtop:], ldz) + } + } + } + + // The number of deflations. + nd = jw - ns + // Shifts are converged eigenvalues that could not be deflated. + // Subtracting infqr from the spike length takes care of the case of a + // rare QR failure while calculating eigenvalues of the deflation + // window. + ns -= infqr + work[0] = float64(lwkopt) + return ns, nd +} diff --git a/lapack/native/dlaqr5.go b/lapack/native/dlaqr5.go new file mode 100644 index 00000000..358fda7a --- /dev/null +++ b/lapack/native/dlaqr5.go @@ -0,0 +1,616 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlaqr5 performs a single small-bulge multi-shift QR sweep on an isolated +// block of a Hessenberg matrix. +// +// wantt and wantz determine whether the quasi-triangular Schur factor and the +// orthogonal Schur factor, respectively, will be computed. +// +// kacc22 specifies the computation mode of far-from-diagonal orthogonal +// updates. Permitted values are: +// 0: Dlaqr5 will not accumulate reflections and will not use matrix-matrix +// multiply to update far-from-diagonal matrix entries. +// 1: Dlaqr5 will accumulate reflections and use matrix-matrix multiply to +// update far-from-diagonal matrix entries. +// 2: Dlaqr5 will accumulate reflections, use matrix-matrix multiply to update +// far-from-diagonal matrix entries, and take advantage of 2×2 block +// structure during matrix multiplies. +// For other values of kacc2 Dlaqr5 will panic. +// +// n is the order of the Hessenberg matrix H. +// +// ktop and kbot are indices of the first and last row and column of an isolated +// diagonal block upon which the QR sweep will be applied. It must hold that +// ktop == 0, or 0 < ktop <= n-1 and H[ktop, ktop-1] == 0, and +// kbot == n-1, or 0 <= kbot < n-1 and H[kbot+1, kbot] == 0, +// otherwise Dlaqr5 will panic. +// +// nshfts is the number of simultaneous shifts. It must be positive and even, +// otherwise Dlaqr5 will panic. +// +// sr and si contain the real and imaginary parts, respectively, of the shifts +// of origin that define the multi-shift QR sweep. On return both slices may be +// reordered by Dlaqr5. Their length must be equal to nshfts, otherwise Dlaqr5 +// will panic. +// +// h and ldh represent the Hessenberg matrix H of size n×n. On return +// multi-shift QR sweep with shifts sr+i*si has been applied to the isolated +// diagonal block in rows and columns ktop through kbot, inclusive. +// +// iloz and ihiz specify the rows of Z to which transformations will be applied +// if wantz is true. It must hold that 0 <= iloz <= ihiz < n, otherwise Dlaqr5 +// will panic. +// +// z and ldz represent the matrix Z of size n×n. If wantz is true, the QR sweep +// orthogonal similarity transformation is accumulated into +// z[iloz:ihiz,iloz:ihiz] from the right, otherwise z not referenced. +// +// v and ldv represent an auxiliary matrix V of size (nshfts/2)×3. Note that V +// is transposed with respect to the reference netlib implementation. +// +// u and ldu represent an auxiliary matrix of size (3*nshfts-3)×(3*nshfts-3). +// +// wh and ldwh represent an auxiliary matrix of size (3*nshfts-3)×nh. +// +// wv and ldwv represent an auxiliary matrix of size nv×(3*nshfts-3). +// +// Dlaqr5 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaqr5(wantt, wantz bool, kacc22 int, n, ktop, kbot, nshfts int, sr, si []float64, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, v []float64, ldv int, u []float64, ldu int, nv int, wv []float64, ldwv int, nh int, wh []float64, ldwh int) { + checkMatrix(n, n, h, ldh) + if ktop < 0 || n <= ktop { + panic("lapack: invalid value of ktop") + } + if ktop > 0 && h[ktop*ldh+ktop-1] != 0 { + panic("lapack: diagonal block is not isolated") + } + if kbot < 0 || n <= kbot { + panic("lapack: invalid value of kbot") + } + if kbot < n-1 && h[(kbot+1)*ldh+kbot] != 0 { + panic("lapack: diagonal block is not isolated") + } + if nshfts < 0 || nshfts&0x1 != 0 { + panic("lapack: invalid number of shifts") + } + if len(sr) != nshfts || len(si) != nshfts { + panic(badSlice) // TODO(vladimir-ch) Another message? + } + if wantz { + if ihiz >= n { + panic("lapack: invalid value of ihiz") + } + if iloz < 0 || ihiz < iloz { + panic("lapack: invalid value of iloz") + } + checkMatrix(n, n, z, ldz) + } + checkMatrix(nshfts/2, 3, v, ldv) // Transposed w.r.t. lapack. + checkMatrix(3*nshfts-3, 3*nshfts-3, u, ldu) + checkMatrix(nv, 3*nshfts-3, wv, ldwv) + checkMatrix(3*nshfts-3, nh, wh, ldwh) + if kacc22 != 0 && kacc22 != 1 && kacc22 != 2 { + panic("lapack: invalid value of kacc22") + } + + // If there are no shifts, then there is nothing to do. + if nshfts < 2 { + return + } + // If the active block is empty or 1×1, then there is nothing to do. + if ktop >= kbot { + return + } + + // Shuffle shifts into pairs of real shifts and pairs of complex + // conjugate shifts assuming complex conjugate shifts are already + // adjacent to one another. + for i := 0; i < nshfts-2; i += 2 { + if si[i] == -si[i+1] { + continue + } + sr[i], sr[i+1], sr[i+2] = sr[i+1], sr[i+2], sr[i] + si[i], si[i+1], si[i+2] = si[i+1], si[i+2], si[i] + } + + // Note: lapack says that nshfts must be even but allows it to be odd + // anyway. We panic above if nshfts is not even, so reducing it by one + // is unnecessary. The only caller Dlaqr04 uses only even nshfts. + // + // The original comment and code from lapack-3.6.0/SRC/dlaqr5.f:341: + // * ==== NSHFTS is supposed to be even, but if it is odd, + // * . then simply reduce it by one. The shuffle above + // * . ensures that the dropped shift is real and that + // * . the remaining shifts are paired. ==== + // * + // NS = NSHFTS - MOD( NSHFTS, 2 ) + ns := nshfts + + safmin := dlamchS + ulp := dlamchP + smlnum := safmin * float64(n) / ulp + + // Use accumulated reflections to update far-from-diagonal entries? + accum := kacc22 == 1 || kacc22 == 2 + // If so, exploit the 2×2 block structure? + blk22 := ns > 2 && kacc22 == 2 + + // Clear trash. + if ktop+2 <= kbot { + h[(ktop+2)*ldh+ktop] = 0 + } + + // nbmps = number of 2-shift bulges in the chain. + nbmps := ns / 2 + + // kdu = width of slab. + kdu := 6*nbmps - 3 + + // Create and chase chains of nbmps bulges. + for incol := 3*(1-nbmps) + ktop - 1; incol <= kbot-2; incol += 3*nbmps - 2 { + ndcol := incol + kdu + if accum { + impl.Dlaset(blas.All, kdu, kdu, 0, 1, u, ldu) + } + + // Near-the-diagonal bulge chase. The following loop performs + // the near-the-diagonal part of a small bulge multi-shift QR + // sweep. Each 6*nbmps-2 column diagonal chunk extends from + // column incol to column ndcol (including both column incol and + // column ndcol). The following loop chases a 3*nbmps column + // long chain of nbmps bulges 3*nbmps-2 columns to the right. + // (incol may be less than ktop and ndcol may be greater than + // kbot indicating phantom columns from which to chase bulges + // before they are actually introduced or to which to chase + // bulges beyond column kbot.) + for krcol := incol; krcol <= min(incol+3*nbmps-3, kbot-2); krcol++ { + // Bulges number mtop to mbot are active double implicit + // shift bulges. There may or may not also be small 2×2 + // bulge, if there is room. The inactive bulges (if any) + // must wait until the active bulges have moved down the + // diagonal to make room. The phantom matrix paradigm + // described above helps keep track. + + mtop := max(0, ((ktop-1)-krcol+2)/3) + mbot := min(nbmps, (kbot-krcol)/3) - 1 + m22 := mbot + 1 + bmp22 := (mbot < nbmps-1) && (krcol+3*m22 == kbot-2) + + // Generate reflections to chase the chain right one + // column. (The minimum value of k is ktop-1.) + for m := mtop; m <= mbot; m++ { + k := krcol + 3*m + if k == ktop-1 { + impl.Dlaqr1(3, h[ktop*ldh+ktop:], ldh, + sr[2*m], si[2*m], sr[2*m+1], si[2*m+1], + v[m*ldv:m*ldv+3]) + alpha := v[m*ldv] + _, v[m*ldv] = impl.Dlarfg(3, alpha, v[m*ldv+1:m*ldv+3], 1) + continue + } + beta := h[(k+1)*ldh+k] + v[m*ldv+1] = h[(k+2)*ldh+k] + v[m*ldv+2] = h[(k+3)*ldh+k] + beta, v[m*ldv] = impl.Dlarfg(3, beta, v[m*ldv+1:m*ldv+3], 1) + + // A bulge may collapse because of vigilant deflation or + // destructive underflow. In the underflow case, try the + // two-small-subdiagonals trick to try to reinflate the + // bulge. + if h[(k+3)*ldh+k] != 0 || h[(k+3)*ldh+k+1] != 0 || h[(k+3)*ldh+k+2] == 0 { + // Typical case: not collapsed (yet). + h[(k+1)*ldh+k] = beta + h[(k+2)*ldh+k] = 0 + h[(k+3)*ldh+k] = 0 + continue + } + + // Atypical case: collapsed. Attempt to reintroduce + // ignoring H[k+1,k] and H[k+2,k]. If the fill + // resulting from the new reflector is too large, + // then abandon it. Otherwise, use the new one. + var vt [3]float64 + impl.Dlaqr1(3, h[(k+1)*ldh+k+1:], ldh, sr[2*m], + si[2*m], sr[2*m+1], si[2*m+1], vt[:]) + alpha := vt[0] + _, vt[0] = impl.Dlarfg(3, alpha, vt[1:3], 1) + refsum := vt[0] * (h[(k+1)*ldh+k] + vt[1]*h[(k+2)*ldh+k]) + + dsum := math.Abs(h[k*ldh+k]) + math.Abs(h[(k+1)*ldh+k+1]) + math.Abs(h[(k+2)*ldh+k+2]) + if math.Abs(h[(k+2)*ldh+k]-refsum*vt[1])+math.Abs(refsum*vt[2]) > ulp*dsum { + // Starting a new bulge here would create + // non-negligible fill. Use the old one with + // trepidation. + h[(k+1)*ldh+k] = beta + h[(k+2)*ldh+k] = 0 + h[(k+3)*ldh+k] = 0 + continue + } else { + // Starting a new bulge here would create + // only negligible fill. Replace the old + // reflector with the new one. + h[(k+1)*ldh+k] -= refsum + h[(k+2)*ldh+k] = 0 + h[(k+3)*ldh+k] = 0 + v[m*ldv] = vt[0] + v[m*ldv+1] = vt[1] + v[m*ldv+2] = vt[2] + } + } + + // Generate a 2×2 reflection, if needed. + if bmp22 { + k := krcol + 3*m22 + if k == ktop-1 { + impl.Dlaqr1(2, h[(k+1)*ldh+k+1:], ldh, + sr[2*m22], si[2*m22], sr[2*m22+1], si[2*m22+1], + v[m22*ldv:m22*ldv+2]) + beta := v[m22*ldv] + _, v[m22*ldv] = impl.Dlarfg(2, beta, v[m22*ldv+1:m22*ldv+2], 1) + } else { + beta := h[(k+1)*ldh+k] + v[m22*ldv+1] = h[(k+2)*ldh+k] + beta, v[m22*ldv] = impl.Dlarfg(2, beta, v[m22*ldv+1:m22*ldv+2], 1) + h[(k+1)*ldh+k] = beta + h[(k+2)*ldh+k] = 0 + } + } + + // Multiply H by reflections from the left. + var jbot int + switch { + case accum: + jbot = min(ndcol, kbot) + case wantt: + jbot = n - 1 + default: + jbot = kbot + } + for j := max(ktop, krcol); j <= jbot; j++ { + mend := min(mbot+1, (j-krcol+2)/3) - 1 + for m := mtop; m <= mend; m++ { + k := krcol + 3*m + refsum := v[m*ldv] * (h[(k+1)*ldh+j] + + v[m*ldv+1]*h[(k+2)*ldh+j] + v[m*ldv+2]*h[(k+3)*ldh+j]) + h[(k+1)*ldh+j] -= refsum + h[(k+2)*ldh+j] -= refsum * v[m*ldv+1] + h[(k+3)*ldh+j] -= refsum * v[m*ldv+2] + } + } + if bmp22 { + k := krcol + 3*m22 + for j := max(k+1, ktop); j <= jbot; j++ { + refsum := v[m22*ldv] * (h[(k+1)*ldh+j] + v[m22*ldv+1]*h[(k+2)*ldh+j]) + h[(k+1)*ldh+j] -= refsum + h[(k+2)*ldh+j] -= refsum * v[m22*ldv+1] + } + } + + // Multiply H by reflections from the right. Delay filling in the last row + // until the vigilant deflation check is complete. + var jtop int + switch { + case accum: + jtop = max(ktop, incol) + case wantt: + jtop = 0 + default: + jtop = ktop + } + for m := mtop; m <= mbot; m++ { + if v[m*ldv] == 0 { + continue + } + k := krcol + 3*m + for j := jtop; j <= min(kbot, k+3); j++ { + refsum := v[m*ldv] * (h[j*ldh+k+1] + + v[m*ldv+1]*h[j*ldh+k+2] + v[m*ldv+2]*h[j*ldh+k+3]) + h[j*ldh+k+1] -= refsum + h[j*ldh+k+2] -= refsum * v[m*ldv+1] + h[j*ldh+k+3] -= refsum * v[m*ldv+2] + } + if accum { + // Accumulate U. (If necessary, update Z later with with an + // efficient matrix-matrix multiply.) + kms := k - incol + for j := max(0, ktop-incol-1); j < kdu; j++ { + refsum := v[m*ldv] * (u[j*ldu+kms] + + v[m*ldv+1]*u[j*ldu+kms+1] + v[m*ldv+2]*u[j*ldu+kms+2]) + u[j*ldu+kms] -= refsum + u[j*ldu+kms+1] -= refsum * v[m*ldv+1] + u[j*ldu+kms+2] -= refsum * v[m*ldv+2] + } + } else if wantz { + // U is not accumulated, so update Z now by multiplying by + // reflections from the right. + for j := iloz; j <= ihiz; j++ { + refsum := v[m*ldv] * (z[j*ldz+k+1] + + v[m*ldv+1]*z[j*ldz+k+2] + v[m*ldv+2]*z[j*ldz+k+3]) + z[j*ldz+k+1] -= refsum + z[j*ldz+k+2] -= refsum * v[m*ldv+1] + z[j*ldz+k+3] -= refsum * v[m*ldv+2] + } + } + } + + // Special case: 2×2 reflection (if needed). + if bmp22 && v[m22*ldv] != 0 { + k := krcol + 3*m22 + for j := jtop; j <= min(kbot, k+3); j++ { + refsum := v[m22*ldv] * (h[j*ldh+k+1] + v[m22*ldv+1]*h[j*ldh+k+2]) + h[j*ldh+k+1] -= refsum + h[j*ldh+k+2] -= refsum * v[m22*ldv+1] + } + if accum { + kms := k - incol + for j := max(0, ktop-incol-1); j < kdu; j++ { + refsum := v[m22*ldv] * (u[j*ldu+kms] + v[m22*ldv+1]*u[j*ldu+kms+1]) + u[j*ldu+kms] -= refsum + u[j*ldu+kms+1] -= refsum * v[m22*ldv+1] + } + } else if wantz { + for j := iloz; j <= ihiz; j++ { + refsum := v[m22*ldv] * (z[j*ldz+k+1] + v[m22*ldv+1]*z[j*ldz+k+2]) + z[j*ldz+k+1] -= refsum + z[j*ldz+k+2] -= refsum * v[m22*ldv+1] + } + } + } + + // Vigilant deflation check. + mstart := mtop + if krcol+3*mstart < ktop { + mstart++ + } + mend := mbot + if bmp22 { + mend++ + } + if krcol == kbot-2 { + mend++ + } + for m := mstart; m <= mend; m++ { + k := min(kbot-1, krcol+3*m) + + // The following convergence test requires that the tradition + // small-compared-to-nearby-diagonals criterion and the Ahues & + // Tisseur (LAWN 122, 1997) criteria both be satisfied. The latter + // improves accuracy in some examples. Falling back on an alternate + // convergence criterion when tst1 or tst2 is zero (as done here) is + // traditional but probably unnecessary. + + if h[(k+1)*ldh+k] == 0 { + continue + } + tst1 := math.Abs(h[k*ldh+k]) + math.Abs(h[(k+1)*ldh+k+1]) + if tst1 == 0 { + if k >= ktop+1 { + tst1 += math.Abs(h[k*ldh+k-1]) + } + if k >= ktop+2 { + tst1 += math.Abs(h[k*ldh+k-2]) + } + if k >= ktop+3 { + tst1 += math.Abs(h[k*ldh+k-3]) + } + if k <= kbot-2 { + tst1 += math.Abs(h[(k+2)*ldh+k+1]) + } + if k <= kbot-3 { + tst1 += math.Abs(h[(k+3)*ldh+k+1]) + } + if k <= kbot-4 { + tst1 += math.Abs(h[(k+4)*ldh+k+1]) + } + } + if math.Abs(h[(k+1)*ldh+k]) <= math.Max(smlnum, ulp*tst1) { + h12 := math.Max(math.Abs(h[(k+1)*ldh+k]), math.Abs(h[k*ldh+k+1])) + h21 := math.Min(math.Abs(h[(k+1)*ldh+k]), math.Abs(h[k*ldh+k+1])) + h11 := math.Max(math.Abs(h[(k+1)*ldh+k+1]), math.Abs(h[k*ldh+k]-h[(k+1)*ldh+k+1])) + h22 := math.Min(math.Abs(h[(k+1)*ldh+k+1]), math.Abs(h[k*ldh+k]-h[(k+1)*ldh+k+1])) + scl := h11 + h12 + tst2 := h22 * (h11 / scl) + if tst2 == 0 || h21*(h12/scl) <= math.Max(smlnum, ulp*tst2) { + h[(k+1)*ldh+k] = 0 + } + } + } + + // Fill in the last row of each bulge. + mend = min(nbmps, (kbot-krcol-1)/3) - 1 + for m := mtop; m <= mend; m++ { + k := krcol + 3*m + refsum := v[m*ldv] * v[m*ldv+2] * h[(k+4)*ldh+k+3] + h[(k+4)*ldh+k+1] = -refsum + h[(k+4)*ldh+k+2] = -refsum * v[m*ldv+1] + h[(k+4)*ldh+k+3] -= refsum * v[m*ldv+2] + } + } + + // Use U (if accumulated) to update far-from-diagonal entries in H. + // If required, use U to update Z as well. + if !accum { + continue + } + var jtop, jbot int + if wantt { + jtop = 0 + jbot = n - 1 + } else { + jtop = ktop + jbot = kbot + } + bi := blas64.Implementation() + if !blk22 || incol < ktop || kbot < ndcol || ns <= 2 { + // Updates not exploiting the 2×2 block structure of U. k0 and nu keep track + // of the location and size of U in the special cases of introducing bulges + // and chasing bulges off the bottom. In these special cases and in case the + // number of shifts is ns = 2, there is no 2×2 block structure to exploit. + + k0 := max(0, ktop-incol-1) + nu := kdu - max(0, ndcol-kbot) - k0 + + // Horizontal multiply. + for jcol := min(ndcol, kbot) + 1; jcol <= jbot; jcol += nh { + jlen := min(nh, jbot-jcol+1) + bi.Dgemm(blas.Trans, blas.NoTrans, nu, jlen, nu, + 1, u[k0*ldu+k0:], ldu, + h[(incol+k0+1)*ldh+jcol:], ldh, + 0, wh, ldwh) + impl.Dlacpy(blas.All, nu, jlen, wh, ldwh, h[(incol+k0+1)*ldh+jcol:], ldh) + } + + // Vertical multiply. + for jrow := jtop; jrow <= max(ktop, incol)-1; jrow += nv { + jlen := min(nv, max(ktop, incol)-jrow) + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, nu, nu, + 1, h[jrow*ldh+incol+k0+1:], ldh, + u[k0*ldu+k0:], ldu, + 0, wv, ldwv) + impl.Dlacpy(blas.All, jlen, nu, wv, ldwv, h[jrow*ldh+incol+k0+1:], ldh) + } + + // Z multiply (also vertical). + if wantz { + for jrow := iloz; jrow <= ihiz; jrow += nv { + jlen := min(nv, ihiz-jrow+1) + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, nu, nu, + 1, z[jrow*ldz+incol+k0+1:], ldz, + u[k0*ldu+k0:], ldu, + 0, wv, ldwv) + impl.Dlacpy(blas.All, jlen, nu, wv, ldwv, z[jrow*ldz+incol+k0+1:], ldz) + } + } + + continue + } + + // Updates exploiting U's 2×2 block structure. + + // i2, i4, j2, j4 are the last rows and columns of the blocks. + i2 := (kdu + 1) / 2 + i4 := kdu + j2 := i4 - i2 + j4 := kdu + + // kzs and knz deal with the band of zeros along the diagonal of one of the + // triangular blocks. + kzs := (j4 - j2) - (ns + 1) + knz := ns + 1 + + // Horizontal multiply. + for jcol := min(ndcol, kbot) + 1; jcol <= jbot; jcol += nh { + jlen := min(nh, jbot-jcol+1) + + // Copy bottom of H to top+kzs of scratch (the first kzs + // rows get multiplied by zero). + impl.Dlacpy(blas.All, knz, jlen, h[(incol+1+j2)*ldh+jcol:], ldh, wh[kzs*ldwh:], ldwh) + + // Multiply by U21^T. + impl.Dlaset(blas.All, kzs, jlen, 0, 0, wh, ldwh) + bi.Dtrmm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, knz, jlen, + 1, u[j2*ldu+kzs:], ldu, wh[kzs*ldwh:], ldwh) + + // Multiply top of H by U11^T. + bi.Dgemm(blas.Trans, blas.NoTrans, i2, jlen, j2, + 1, u, ldu, h[(incol+1)*ldh+jcol:], ldh, + 1, wh, ldwh) + + // Copy top of H to bottom of WH. + impl.Dlacpy(blas.All, j2, jlen, h[(incol+1)*ldh+jcol:], ldh, wh[i2*ldwh:], ldwh) + + // Multiply by U21^T. + bi.Dtrmm(blas.Left, blas.Lower, blas.Trans, blas.NonUnit, j2, jlen, + 1, u[i2:], ldu, wh[i2*ldwh:], ldwh) + + // Multiply by U22. + bi.Dgemm(blas.Trans, blas.NoTrans, i4-i2, jlen, j4-j2, + 1, u[j2*ldu+i2:], ldu, h[(incol+1+j2)*ldh+jcol:], ldh, + 1, wh[i2*ldwh:], ldwh) + + // Copy it back. + impl.Dlacpy(blas.All, kdu, jlen, wh, ldwh, h[(incol+1)*ldh+jcol:], ldh) + } + + // Vertical multiply. + for jrow := jtop; jrow <= max(incol, ktop)-1; jrow += nv { + jlen := min(nv, max(incol, ktop)-jrow) + + // Copy right of H to scratch (the first kzs columns get multiplied + // by zero). + impl.Dlacpy(blas.All, jlen, knz, h[jrow*ldh+incol+1+j2:], ldh, wv[kzs:], ldwv) + + // Multiply by U21. + impl.Dlaset(blas.All, jlen, kzs, 0, 0, wv, ldwv) + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.NonUnit, jlen, knz, + 1, u[j2*ldu+kzs:], ldu, wv[kzs:], ldwv) + + // Multiply by U11. + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, i2, j2, + 1, h[jrow*ldh+incol+1:], ldh, u, ldu, + 1, wv, ldwv) + + // Copy left of H to right of scratch. + impl.Dlacpy(blas.All, jlen, j2, h[jrow*ldh+incol+1:], ldh, wv[i2:], ldwv) + + // Multiply by U21. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.NonUnit, jlen, i4-i2, + 1, u[i2:], ldu, wv[i2:], ldwv) + + // Multiply by U22. + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, i4-i2, j4-j2, + 1, h[jrow*ldh+incol+1+j2:], ldh, u[j2*ldu+i2:], ldu, + 1, wv[i2:], ldwv) + + // Copy it back. + impl.Dlacpy(blas.All, jlen, kdu, wv, ldwv, h[jrow*ldh+incol+1:], ldh) + } + + if !wantz { + continue + } + // Multiply Z (also vertical). + for jrow := iloz; jrow <= ihiz; jrow += nv { + jlen := min(nv, ihiz-jrow+1) + + // Copy right of Z to left of scratch (first kzs columns get + // multiplied by zero). + impl.Dlacpy(blas.All, jlen, knz, z[jrow*ldz+incol+1+j2:], ldz, wv[kzs:], ldwv) + + // Multiply by U12. + impl.Dlaset(blas.All, jlen, kzs, 0, 0, wv, ldwv) + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.NonUnit, jlen, knz, + 1, u[j2*ldu+kzs:], ldu, wv[kzs:], ldwv) + + // Multiply by U11. + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, i2, j2, + 1, z[jrow*ldz+incol+1:], ldz, u, ldu, + 1, wv, ldwv) + + // Copy left of Z to right of scratch. + impl.Dlacpy(blas.All, jlen, j2, z[jrow*ldz+incol+1:], ldz, wv[i2:], ldwv) + + // Multiply by U21. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.NonUnit, jlen, i4-i2, + 1, u[i2:], ldu, wv[i2:], ldwv) + + // Multiply by U22. + bi.Dgemm(blas.NoTrans, blas.NoTrans, jlen, i4-i2, j4-j2, + 1, z[jrow*ldz+incol+1+j2:], ldz, u[j2*ldu+i2:], ldu, + 1, wv[i2:], ldwv) + + // Copy the result back to Z. + impl.Dlacpy(blas.All, jlen, kdu, wv, ldwv, z[jrow*ldz+incol+1:], ldz) + } + } +} diff --git a/lapack/native/dlarf.go b/lapack/native/dlarf.go new file mode 100644 index 00000000..7bbf9a25 --- /dev/null +++ b/lapack/native/dlarf.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlarf applies an elementary reflector to a general rectangular matrix c. +// This computes +// c = h * c if side == Left +// c = c * h if side == right +// where +// h = 1 - tau * v * v^T +// and c is an m * n matrix. +// +// work is temporary storage of length at least m if side == Left and at least +// n if side == Right. This function will panic if this length requirement is not met. +// +// Dlarf is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlarf(side blas.Side, m, n int, v []float64, incv int, tau float64, c []float64, ldc int, work []float64) { + applyleft := side == blas.Left + if (applyleft && len(work) < n) || (!applyleft && len(work) < m) { + panic(badWork) + } + checkMatrix(m, n, c, ldc) + + // v has length m if applyleft and n otherwise. + lenV := n + if applyleft { + lenV = m + } + + checkVector(lenV, v, incv) + + lastv := 0 // last non-zero element of v + lastc := 0 // last non-zero row/column of c + if tau != 0 { + var i int + if applyleft { + lastv = m - 1 + } else { + lastv = n - 1 + } + if incv > 0 { + i = lastv * incv + } + + // Look for the last non-zero row in v. + for lastv >= 0 && v[i] == 0 { + lastv-- + i -= incv + } + if applyleft { + // Scan for the last non-zero column in C[0:lastv, :] + lastc = impl.Iladlc(lastv+1, n, c, ldc) + } else { + // Scan for the last non-zero row in C[:, 0:lastv] + lastc = impl.Iladlr(m, lastv+1, c, ldc) + } + } + if lastv == -1 || lastc == -1 { + return + } + // Sometimes 1-indexing is nicer ... + bi := blas64.Implementation() + if applyleft { + // Form H * C + // w[0:lastc+1] = c[1:lastv+1, 1:lastc+1]^T * v[1:lastv+1,1] + bi.Dgemv(blas.Trans, lastv+1, lastc+1, 1, c, ldc, v, incv, 0, work, 1) + // c[0: lastv, 0: lastc] = c[...] - w[0:lastv, 1] * v[1:lastc, 1]^T + bi.Dger(lastv+1, lastc+1, -tau, v, incv, work, 1, c, ldc) + return + } + // Form C*H + // w[0:lastc+1,1] := c[0:lastc+1,0:lastv+1] * v[0:lastv+1,1] + bi.Dgemv(blas.NoTrans, lastc+1, lastv+1, 1, c, ldc, v, incv, 0, work, 1) + // c[0:lastc+1,0:lastv+1] = c[...] - w[0:lastc+1,0] * v[0:lastv+1,0]^T + bi.Dger(lastc+1, lastv+1, -tau, work, 1, v, incv, c, ldc) +} diff --git a/lapack/native/dlarfb.go b/lapack/native/dlarfb.go new file mode 100644 index 00000000..b79f6b90 --- /dev/null +++ b/lapack/native/dlarfb.go @@ -0,0 +1,431 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlarfb applies a block reflector to a matrix. +// +// In the call to Dlarfb, the mxn c is multiplied by the implicitly defined matrix h as follows: +// c = h * c if side == Left and trans == NoTrans +// c = c * h if side == Right and trans == NoTrans +// c = h^T * c if side == Left and trans == Trans +// c = c * h^T if side == Right and trans == Trans +// h is a product of elementary reflectors. direct sets the direction of multiplication +// h = h_1 * h_2 * ... * h_k if direct == Forward +// h = h_k * h_k-1 * ... * h_1 if direct == Backward +// The combination of direct and store defines the orientation of the elementary +// reflectors. In all cases the ones on the diagonal are implicitly represented. +// +// If direct == lapack.Forward and store == lapack.ColumnWise +// V = [ 1 ] +// [v1 1 ] +// [v1 v2 1] +// [v1 v2 v3] +// [v1 v2 v3] +// If direct == lapack.Forward and store == lapack.RowWise +// V = [ 1 v1 v1 v1 v1] +// [ 1 v2 v2 v2] +// [ 1 v3 v3] +// If direct == lapack.Backward and store == lapack.ColumnWise +// V = [v1 v2 v3] +// [v1 v2 v3] +// [ 1 v2 v3] +// [ 1 v3] +// [ 1] +// If direct == lapack.Backward and store == lapack.RowWise +// V = [v1 v1 1 ] +// [v2 v2 v2 1 ] +// [v3 v3 v3 v3 1] +// An elementary reflector can be explicitly constructed by extracting the +// corresponding elements of v, placing a 1 where the diagonal would be, and +// placing zeros in the remaining elements. +// +// t is a k×k matrix containing the block reflector, and this function will panic +// if t is not of sufficient size. See Dlarft for more information. +// +// work is a temporary storage matrix with stride ldwork. +// work must be of size at least n×k side == Left and m×k if side == Right, and +// this function will panic if this size is not met. +// +// Dlarfb is an internal routine. It is exported for testing purposes. +func (Implementation) Dlarfb(side blas.Side, trans blas.Transpose, direct lapack.Direct, store lapack.StoreV, m, n, k int, v []float64, ldv int, t []float64, ldt int, c []float64, ldc int, work []float64, ldwork int) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + if direct != lapack.Forward && direct != lapack.Backward { + panic(badDirect) + } + if store != lapack.ColumnWise && store != lapack.RowWise { + panic(badStore) + } + checkMatrix(m, n, c, ldc) + if k < 0 { + panic(kLT0) + } + checkMatrix(k, k, t, ldt) + nv := m + nw := n + if side == blas.Right { + nv = n + nw = m + } + if store == lapack.ColumnWise { + checkMatrix(nv, k, v, ldv) + } else { + checkMatrix(k, nv, v, ldv) + } + checkMatrix(nw, k, work, ldwork) + + if m == 0 || n == 0 { + return + } + + bi := blas64.Implementation() + + transt := blas.Trans + if trans == blas.Trans { + transt = blas.NoTrans + } + // TODO(btracey): This follows the original Lapack code where the + // elements are copied into the columns of the working array. The + // loops should go in the other direction so the data is written + // into the rows of work so the copy is not strided. A bigger change + // would be to replace work with work^T, but benchmarks would be + // needed to see if the change is merited. + if store == lapack.ColumnWise { + if direct == lapack.Forward { + // V1 is the first k rows of C. V2 is the remaining rows. + if side == blas.Left { + // W = C^T V = C1^T V1 + C2^T V2 (stored in work). + + // W = C1. + for j := 0; j < k; j++ { + bi.Dcopy(n, c[j*ldc:], 1, work[j:], ldwork) + } + // W = W * V1. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, + n, k, 1, + v, ldv, + work, ldwork) + if m > k { + // W = W + C2^T V2. + bi.Dgemm(blas.Trans, blas.NoTrans, n, k, m-k, + 1, c[k*ldc:], ldc, v[k*ldv:], ldv, + 1, work, ldwork) + } + // W = W * T^T or W * T. + bi.Dtrmm(blas.Right, blas.Upper, transt, blas.NonUnit, n, k, + 1, t, ldt, + work, ldwork) + // C -= V * W^T. + if m > k { + // C2 -= V2 * W^T. + bi.Dgemm(blas.NoTrans, blas.Trans, m-k, n, k, + -1, v[k*ldv:], ldv, work, ldwork, + 1, c[k*ldc:], ldc) + } + // W *= V1^T. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, n, k, + 1, v, ldv, + work, ldwork) + // C1 -= W^T. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < n; i++ { + for j := 0; j < k; j++ { + c[j*ldc+i] -= work[i*ldwork+j] + } + } + return + } + // Form C = C * H or C * H^T, where C = (C1 C2). + + // W = C1. + for i := 0; i < k; i++ { + bi.Dcopy(m, c[i:], ldc, work[i:], ldwork) + } + // W *= V1. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, m, k, + 1, v, ldv, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, k, n-k, + 1, c[k:], ldc, v[k*ldv:], ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Upper, trans, blas.NonUnit, m, k, + 1, t, ldt, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.Trans, m, n-k, k, + -1, work, ldwork, v[k*ldv:], ldv, + 1, c[k:], ldc) + } + // C -= W * V^T. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, m, k, + 1, v, ldv, + work, ldwork) + // C -= W. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + c[i*ldc+j] -= work[i*ldwork+j] + } + } + return + } + // V = (V1) + // = (V2) (last k rows) + // Where V2 is unit upper triangular. + if side == blas.Left { + // Form H * C or + // W = C^T V. + + // W = C2^T. + for j := 0; j < k; j++ { + bi.Dcopy(n, c[(m-k+j)*ldc:], 1, work[j:], ldwork) + } + // W *= V2. + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, n, k, + 1, v[(m-k)*ldv:], ldv, + work, ldwork) + if m > k { + // W += C1^T * V1. + bi.Dgemm(blas.Trans, blas.NoTrans, n, k, m-k, + 1, c, ldc, v, ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Lower, transt, blas.NonUnit, n, k, + 1, t, ldt, + work, ldwork) + // C -= V * W^T. + if m > k { + bi.Dgemm(blas.NoTrans, blas.Trans, m-k, n, k, + -1, v, ldv, work, ldwork, + 1, c, ldc) + } + // W *= V2^T. + bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, n, k, + 1, v[(m-k)*ldv:], ldv, + work, ldwork) + // C2 -= W^T. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < n; i++ { + for j := 0; j < k; j++ { + c[(m-k+j)*ldc+i] -= work[i*ldwork+j] + } + } + return + } + // Form C * H or C * H^T where C = (C1 C2). + // W = C * V. + + // W = C2. + for j := 0; j < k; j++ { + bi.Dcopy(m, c[n-k+j:], ldc, work[j:], ldwork) + } + + // W = W * V2. + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, m, k, + 1, v[(n-k)*ldv:], ldv, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, k, n-k, + 1, c, ldc, v, ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Lower, trans, blas.NonUnit, m, k, + 1, t, ldt, + work, ldwork) + // C -= W * V^T. + if n > k { + // C1 -= W * V1^T. + bi.Dgemm(blas.NoTrans, blas.Trans, m, n-k, k, + -1, work, ldwork, v, ldv, + 1, c, ldc) + } + // W *= V2^T. + bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, m, k, + 1, v[(n-k)*ldv:], ldv, + work, ldwork) + // C2 -= W. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + c[i*ldc+n-k+j] -= work[i*ldwork+j] + } + } + return + } + // Store = Rowwise. + if direct == lapack.Forward { + // V = (V1 V2) where v1 is unit upper triangular. + if side == blas.Left { + // Form H * C or H^T * C where C = (C1; C2). + // W = C^T * V^T. + + // W = C1^T. + for j := 0; j < k; j++ { + bi.Dcopy(n, c[j*ldc:], 1, work[j:], ldwork) + } + // W *= V1^T. + bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, n, k, + 1, v, ldv, + work, ldwork) + if m > k { + bi.Dgemm(blas.Trans, blas.Trans, n, k, m-k, + 1, c[k*ldc:], ldc, v[k:], ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Upper, transt, blas.NonUnit, n, k, + 1, t, ldt, + work, ldwork) + // C -= V^T * W^T. + if m > k { + bi.Dgemm(blas.Trans, blas.Trans, m-k, n, k, + -1, v[k:], ldv, work, ldwork, + 1, c[k*ldc:], ldc) + } + // W *= V1. + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, n, k, + 1, v, ldv, + work, ldwork) + // C1 -= W^T. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < n; i++ { + for j := 0; j < k; j++ { + c[j*ldc+i] -= work[i*ldwork+j] + } + } + return + } + // Form C * H or C * H^T where C = (C1 C2). + // W = C * V^T. + + // W = C1. + for j := 0; j < k; j++ { + bi.Dcopy(m, c[j:], ldc, work[j:], ldwork) + } + // W *= V1^T. + bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.Unit, m, k, + 1, v, ldv, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.Trans, m, k, n-k, + 1, c[k:], ldc, v[k:], ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Upper, trans, blas.NonUnit, m, k, + 1, t, ldt, + work, ldwork) + // C -= W * V. + if n > k { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n-k, k, + -1, work, ldwork, v[k:], ldv, + 1, c[k:], ldc) + } + // W *= V1. + bi.Dtrmm(blas.Right, blas.Upper, blas.NoTrans, blas.Unit, m, k, + 1, v, ldv, + work, ldwork) + // C1 -= W. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + c[i*ldc+j] -= work[i*ldwork+j] + } + } + return + } + // V = (V1 V2) where V2 is the last k columns and is lower unit triangular. + if side == blas.Left { + // Form H * C or H^T C where C = (C1 ; C2). + // W = C^T * V^T. + + // W = C2^T. + for j := 0; j < k; j++ { + bi.Dcopy(n, c[(m-k+j)*ldc:], 1, work[j:], ldwork) + } + // W *= V2^T. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, n, k, + 1, v[m-k:], ldv, + work, ldwork) + if m > k { + bi.Dgemm(blas.Trans, blas.Trans, n, k, m-k, + 1, c, ldc, v, ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Lower, transt, blas.NonUnit, n, k, + 1, t, ldt, + work, ldwork) + // C -= V^T * W^T. + if m > k { + bi.Dgemm(blas.Trans, blas.Trans, m-k, n, k, + -1, v, ldv, work, ldwork, + 1, c, ldc) + } + // W *= V2. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, n, k, + 1, v[m-k:], ldv, + work, ldwork) + // C2 -= W^T. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < n; i++ { + for j := 0; j < k; j++ { + c[(m-k+j)*ldc+i] -= work[i*ldwork+j] + } + } + return + } + // Form C * H or C * H^T where C = (C1 C2). + // W = C * V^T. + // W = C2. + for j := 0; j < k; j++ { + bi.Dcopy(m, c[n-k+j:], ldc, work[j:], ldwork) + } + // W *= V2^T. + bi.Dtrmm(blas.Right, blas.Lower, blas.Trans, blas.Unit, m, k, + 1, v[n-k:], ldv, + work, ldwork) + if n > k { + bi.Dgemm(blas.NoTrans, blas.Trans, m, k, n-k, + 1, c, ldc, v, ldv, + 1, work, ldwork) + } + // W *= T or T^T. + bi.Dtrmm(blas.Right, blas.Lower, trans, blas.NonUnit, m, k, + 1, t, ldt, + work, ldwork) + // C -= W * V. + if n > k { + bi.Dgemm(blas.NoTrans, blas.NoTrans, m, n-k, k, + -1, work, ldwork, v, ldv, + 1, c, ldc) + } + // W *= V2. + bi.Dtrmm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, m, k, + 1, v[n-k:], ldv, + work, ldwork) + // C1 -= W. + // TODO(btracey): This should use blas.Axpy. + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + c[i*ldc+n-k+j] -= work[i*ldwork+j] + } + } +} diff --git a/lapack/native/dlarfg.go b/lapack/native/dlarfg.go new file mode 100644 index 00000000..9230b532 --- /dev/null +++ b/lapack/native/dlarfg.go @@ -0,0 +1,62 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlarfg generates an elementary reflector for a Householder matrix. It creates +// a real elementary reflector of order n such that +// H * (alpha) = (beta) +// ( x) ( 0) +// H^T * H = I +// H is represented in the form +// H = 1 - tau * (1; v) * (1 v^T) +// where tau is a real scalar. +// +// On entry, x contains the vector x, on exit it contains v. +// +// Dlarfg is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlarfg(n int, alpha float64, x []float64, incX int) (beta, tau float64) { + if n < 0 { + panic(nLT0) + } + if n <= 1 { + return alpha, 0 + } + checkVector(n-1, x, incX) + bi := blas64.Implementation() + xnorm := bi.Dnrm2(n-1, x, incX) + if xnorm == 0 { + return alpha, 0 + } + beta = -math.Copysign(impl.Dlapy2(alpha, xnorm), alpha) + safmin := dlamchS / dlamchE + knt := 0 + if math.Abs(beta) < safmin { + // xnorm and beta may be inaccurate, scale x and recompute. + rsafmn := 1 / safmin + for { + knt++ + bi.Dscal(n-1, rsafmn, x, incX) + beta *= rsafmn + alpha *= rsafmn + if math.Abs(beta) >= safmin { + break + } + } + xnorm = bi.Dnrm2(n-1, x, incX) + beta = -math.Copysign(impl.Dlapy2(alpha, xnorm), alpha) + } + tau = (beta - alpha) / beta + bi.Dscal(n-1, 1/(alpha-beta), x, incX) + for j := 0; j < knt; j++ { + beta *= safmin + } + return beta, tau +} diff --git a/lapack/native/dlarft.go b/lapack/native/dlarft.go new file mode 100644 index 00000000..1b42b3d5 --- /dev/null +++ b/lapack/native/dlarft.go @@ -0,0 +1,150 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlarft forms the triangular factor T of a block reflector H, storing the answer +// in t. +// H = I - V * T * V^T if store == lapack.ColumnWise +// H = I - V^T * T * V if store == lapack.RowWise +// H is defined by a product of the elementary reflectors where +// H = H_0 * H_1 * ... * H_{k-1} if direct == lapack.Forward +// H = H_{k-1} * ... * H_1 * H_0 if direct == lapack.Backward +// +// t is a k×k triangular matrix. t is upper triangular if direct = lapack.Forward +// and lower triangular otherwise. This function will panic if t is not of +// sufficient size. +// +// store describes the storage of the elementary reflectors in v. Please see +// Dlarfb for a description of layout. +// +// tau contains the scalar factors of the elementary reflectors H_i. +// +// Dlarft is an internal routine. It is exported for testing purposes. +func (Implementation) Dlarft(direct lapack.Direct, store lapack.StoreV, n, k int, + v []float64, ldv int, tau []float64, t []float64, ldt int) { + if n == 0 { + return + } + if n < 0 || k < 0 { + panic(negDimension) + } + if direct != lapack.Forward && direct != lapack.Backward { + panic(badDirect) + } + if store != lapack.RowWise && store != lapack.ColumnWise { + panic(badStore) + } + if len(tau) < k { + panic(badTau) + } + checkMatrix(k, k, t, ldt) + bi := blas64.Implementation() + // TODO(btracey): There are a number of minor obvious loop optimizations here. + // TODO(btracey): It may be possible to rearrange some of the code so that + // index of 1 is more common in the Dgemv. + if direct == lapack.Forward { + prevlastv := n - 1 + for i := 0; i < k; i++ { + prevlastv = max(i, prevlastv) + if tau[i] == 0 { + for j := 0; j <= i; j++ { + t[j*ldt+i] = 0 + } + continue + } + var lastv int + if store == lapack.ColumnWise { + // skip trailing zeros + for lastv = n - 1; lastv >= i+1; lastv-- { + if v[lastv*ldv+i] != 0 { + break + } + } + for j := 0; j < i; j++ { + t[j*ldt+i] = -tau[i] * v[i*ldv+j] + } + j := min(lastv, prevlastv) + bi.Dgemv(blas.Trans, j-i, i, + -tau[i], v[(i+1)*ldv:], ldv, v[(i+1)*ldv+i:], ldv, + 1, t[i:], ldt) + } else { + for lastv = n - 1; lastv >= i+1; lastv-- { + if v[i*ldv+lastv] != 0 { + break + } + } + for j := 0; j < i; j++ { + t[j*ldt+i] = -tau[i] * v[j*ldv+i] + } + j := min(lastv, prevlastv) + bi.Dgemv(blas.NoTrans, i, j-i, + -tau[i], v[i+1:], ldv, v[i*ldv+i+1:], 1, + 1, t[i:], ldt) + } + bi.Dtrmv(blas.Upper, blas.NoTrans, blas.NonUnit, i, t, ldt, t[i:], ldt) + t[i*ldt+i] = tau[i] + if i > 1 { + prevlastv = max(prevlastv, lastv) + } else { + prevlastv = lastv + } + } + return + } + prevlastv := 0 + for i := k - 1; i >= 0; i-- { + if tau[i] == 0 { + for j := i; j < k; j++ { + t[j*ldt+i] = 0 + } + continue + } + var lastv int + if i < k-1 { + if store == lapack.ColumnWise { + for lastv = 0; lastv < i; lastv++ { + if v[lastv*ldv+i] != 0 { + break + } + } + for j := i + 1; j < k; j++ { + t[j*ldt+i] = -tau[i] * v[(n-k+i)*ldv+j] + } + j := max(lastv, prevlastv) + bi.Dgemv(blas.Trans, n-k+i-j, k-i-1, + -tau[i], v[j*ldv+i+1:], ldv, v[j*ldv+i:], ldv, + 1, t[(i+1)*ldt+i:], ldt) + } else { + for lastv = 0; lastv < i; lastv++ { + if v[i*ldv+lastv] != 0 { + break + } + } + for j := i + 1; j < k; j++ { + t[j*ldt+i] = -tau[i] * v[j*ldv+n-k+i] + } + j := max(lastv, prevlastv) + bi.Dgemv(blas.NoTrans, k-i-1, n-k+i-j, + -tau[i], v[(i+1)*ldv+j:], ldv, v[i*ldv+j:], 1, + 1, t[(i+1)*ldt+i:], ldt) + } + bi.Dtrmv(blas.Lower, blas.NoTrans, blas.NonUnit, k-i-1, + t[(i+1)*ldt+i+1:], ldt, + t[(i+1)*ldt+i:], ldt) + if i > 0 { + prevlastv = min(prevlastv, lastv) + } else { + prevlastv = lastv + } + } + t[i*ldt+i] = tau[i] + } +} diff --git a/lapack/native/dlarfx.go b/lapack/native/dlarfx.go new file mode 100644 index 00000000..8e2b1b8c --- /dev/null +++ b/lapack/native/dlarfx.go @@ -0,0 +1,535 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dlarfx applies an elementary reflector H to a real m×n matrix C, from either +// the left or the right, with loop unrolling when the reflector has order less +// than 11. +// +// H is represented in the form +// H = I - tau * v * v^T, +// where tau is a real scalar and v is a real vector. If tau = 0, then H is +// taken to be the identity matrix. +// +// v must have length equal to m if side == blas.Left, and equal to n if side == +// blas.Right, otherwise Dlarfx will panic. +// +// c and ldc represent the m×n matrix C. On return, C is overwritten by the +// matrix H * C if side == blas.Left, or C * H if side == blas.Right. +// +// work must have length at least n if side == blas.Left, and at least m if side +// == blas.Right, otherwise Dlarfx will panic. work is not referenced if H has +// order < 11. +// +// Dlarfx is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) { + checkMatrix(m, n, c, ldc) + switch side { + case blas.Left: + checkVector(m, v, 1) + if m > 10 && len(work) < n { + panic(badWork) + } + case blas.Right: + checkVector(n, v, 1) + if n > 10 && len(work) < m { + panic(badWork) + } + default: + panic(badSide) + } + + if tau == 0 { + return + } + + if side == blas.Left { + // Form H * C, where H has order m. + switch m { + default: // Code for general m. + impl.Dlarf(side, m, n, v, 1, tau, c, ldc, work) + return + + case 0: // No-op for zero size matrix. + return + + case 1: // Special code for 1×1 Householder matrix. + t0 := 1 - tau*v[0]*v[0] + for j := 0; j < n; j++ { + c[j] *= t0 + } + return + + case 2: // Special code for 2×2 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + } + return + + case 3: // Special code for 3×3 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + } + return + + case 4: // Special code for 4×4 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + } + return + + case 5: // Special code for 5×5 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + } + return + + case 6: // Special code for 6×6 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + } + return + + case 7: // Special code for 7×7 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + v6*c[6*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + c[6*ldc+j] -= sum * t6 + } + return + + case 8: // Special code for 8×8 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + c[6*ldc+j] -= sum * t6 + c[7*ldc+j] -= sum * t7 + } + return + + case 9: // Special code for 9×9 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + v8 := v[8] + t8 := tau * v8 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + v8*c[8*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + c[6*ldc+j] -= sum * t6 + c[7*ldc+j] -= sum * t7 + c[8*ldc+j] -= sum * t8 + } + return + + case 10: // Special code for 10×10 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + v8 := v[8] + t8 := tau * v8 + v9 := v[9] + t9 := tau * v9 + for j := 0; j < n; j++ { + sum := v0*c[j] + v1*c[ldc+j] + v2*c[2*ldc+j] + v3*c[3*ldc+j] + v4*c[4*ldc+j] + + v5*c[5*ldc+j] + v6*c[6*ldc+j] + v7*c[7*ldc+j] + v8*c[8*ldc+j] + v9*c[9*ldc+j] + c[j] -= sum * t0 + c[ldc+j] -= sum * t1 + c[2*ldc+j] -= sum * t2 + c[3*ldc+j] -= sum * t3 + c[4*ldc+j] -= sum * t4 + c[5*ldc+j] -= sum * t5 + c[6*ldc+j] -= sum * t6 + c[7*ldc+j] -= sum * t7 + c[8*ldc+j] -= sum * t8 + c[9*ldc+j] -= sum * t9 + } + return + } + } + + // Form C * H, where H has order n. + switch n { + default: // Code for general n. + impl.Dlarf(side, m, n, v, 1, tau, c, ldc, work) + return + + case 0: // No-op for zero size matrix. + return + + case 1: // Special code for 1×1 Householder matrix. + t0 := 1 - tau*v[0]*v[0] + for j := 0; j < m; j++ { + c[j*ldc] *= t0 + } + return + + case 2: // Special code for 2×2 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + } + return + + case 3: // Special code for 3×3 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + } + return + + case 4: // Special code for 4×4 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + } + return + + case 5: // Special code for 5×5 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + } + return + + case 6: // Special code for 6×6 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + v5*cs[5] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + } + return + + case 7: // Special code for 7×7 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + + v5*cs[5] + v6*cs[6] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + cs[6] -= sum * t6 + } + return + + case 8: // Special code for 8×8 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + + v5*cs[5] + v6*cs[6] + v7*cs[7] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + cs[6] -= sum * t6 + cs[7] -= sum * t7 + } + return + + case 9: // Special code for 9×9 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + v8 := v[8] + t8 := tau * v8 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + + v5*cs[5] + v6*cs[6] + v7*cs[7] + v8*cs[8] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + cs[6] -= sum * t6 + cs[7] -= sum * t7 + cs[8] -= sum * t8 + } + return + + case 10: // Special code for 10×10 Householder matrix. + v0 := v[0] + t0 := tau * v0 + v1 := v[1] + t1 := tau * v1 + v2 := v[2] + t2 := tau * v2 + v3 := v[3] + t3 := tau * v3 + v4 := v[4] + t4 := tau * v4 + v5 := v[5] + t5 := tau * v5 + v6 := v[6] + t6 := tau * v6 + v7 := v[7] + t7 := tau * v7 + v8 := v[8] + t8 := tau * v8 + v9 := v[9] + t9 := tau * v9 + for j := 0; j < m; j++ { + cs := c[j*ldc:] + sum := v0*cs[0] + v1*cs[1] + v2*cs[2] + v3*cs[3] + v4*cs[4] + + v5*cs[5] + v6*cs[6] + v7*cs[7] + v8*cs[8] + v9*cs[9] + cs[0] -= sum * t0 + cs[1] -= sum * t1 + cs[2] -= sum * t2 + cs[3] -= sum * t3 + cs[4] -= sum * t4 + cs[5] -= sum * t5 + cs[6] -= sum * t6 + cs[7] -= sum * t7 + cs[8] -= sum * t8 + cs[9] -= sum * t9 + } + return + } +} diff --git a/lapack/native/dlartg.go b/lapack/native/dlartg.go new file mode 100644 index 00000000..2b0e324d --- /dev/null +++ b/lapack/native/dlartg.go @@ -0,0 +1,80 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlartg generates a plane rotation so that +// [ cs sn] * [f] = [r] +// [-sn cs] [g] = [0] +// This is a more accurate version of BLAS drotg, with the other differences that +// if g = 0, then cs = 1 and sn = 0, and if f = 0 and g != 0, then cs = 0 and sn = 1. +// If abs(f) > abs(g), cs will be positive. +// +// Dlartg is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlartg(f, g float64) (cs, sn, r float64) { + safmn2 := math.Pow(dlamchB, math.Trunc(math.Log(dlamchS/dlamchE)/math.Log(dlamchB)/2)) + safmx2 := 1 / safmn2 + if g == 0 { + cs = 1 + sn = 0 + r = f + return cs, sn, r + } + if f == 0 { + cs = 0 + sn = 1 + r = g + return cs, sn, r + } + f1 := f + g1 := g + scale := math.Max(math.Abs(f1), math.Abs(g1)) + if scale >= safmx2 { + var count int + for { + count++ + f1 *= safmn2 + g1 *= safmn2 + scale = math.Max(math.Abs(f1), math.Abs(g1)) + if scale < safmx2 { + break + } + } + r = math.Sqrt(f1*f1 + g1*g1) + cs = f1 / r + sn = g1 / r + for i := 0; i < count; i++ { + r *= safmx2 + } + } else if scale <= safmn2 { + var count int + for { + count++ + f1 *= safmx2 + g1 *= safmx2 + scale = math.Max(math.Abs(f1), math.Abs(g1)) + if scale >= safmn2 { + break + } + } + r = math.Sqrt(f1*f1 + g1*g1) + cs = f1 / r + sn = g1 / r + for i := 0; i < count; i++ { + r *= safmn2 + } + } else { + r = math.Sqrt(f1*f1 + g1*g1) + cs = f1 / r + sn = g1 / r + } + if math.Abs(f) > math.Abs(g) && cs < 0 { + cs *= -1 + sn *= -1 + r *= -1 + } + return cs, sn, r +} diff --git a/lapack/native/dlas2.go b/lapack/native/dlas2.go new file mode 100644 index 00000000..ee37bec1 --- /dev/null +++ b/lapack/native/dlas2.go @@ -0,0 +1,43 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlas2 computes the singular values of the 2×2 matrix defined by +// [F G] +// [0 H] +// The smaller and larger singular values are returned in that order. +// +// Dlas2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlas2(f, g, h float64) (ssmin, ssmax float64) { + fa := math.Abs(f) + ga := math.Abs(g) + ha := math.Abs(h) + fhmin := math.Min(fa, ha) + fhmax := math.Max(fa, ha) + if fhmin == 0 { + if fhmax == 0 { + return 0, ga + } + v := math.Min(fhmax, ga) / math.Max(fhmax, ga) + return 0, math.Max(fhmax, ga) * math.Sqrt(1+v*v) + } + if ga < fhmax { + as := 1 + fhmin/fhmax + at := (fhmax - fhmin) / fhmax + au := (ga / fhmax) * (ga / fhmax) + c := 2 / (math.Sqrt(as*as+au) + math.Sqrt(at*at+au)) + return fhmin * c, fhmax / c + } + au := fhmax / ga + if au == 0 { + return fhmin * fhmax / ga, ga + } + as := 1 + fhmin/fhmax + at := (fhmax - fhmin) / fhmax + c := 1 / (math.Sqrt(1+(as*au)*(as*au)) + math.Sqrt(1+(at*au)*(at*au))) + return 2 * (fhmin * c) * au, ga / (c + c) +} diff --git a/lapack/native/dlascl.go b/lapack/native/dlascl.go new file mode 100644 index 00000000..4dacc80a --- /dev/null +++ b/lapack/native/dlascl.go @@ -0,0 +1,89 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dlascl multiplies an m×n matrix by the scalar cto/cfrom. +// +// cfrom must not be zero, and cto and cfrom must not be NaN, otherwise Dlascl +// will panic. +// +// Dlascl is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlascl(kind lapack.MatrixType, kl, ku int, cfrom, cto float64, m, n int, a []float64, lda int) { + checkMatrix(m, n, a, lda) + if cfrom == 0 { + panic(zeroDiv) + } + if math.IsNaN(cfrom) || math.IsNaN(cto) { + panic(nanScale) + } + if n == 0 || m == 0 { + return + } + smlnum := dlamchS + bignum := 1 / smlnum + cfromc := cfrom + ctoc := cto + cfrom1 := cfromc * smlnum + for { + var done bool + var mul, ctol float64 + if cfrom1 == cfromc { + // cfromc is inf. + mul = ctoc / cfromc + done = true + ctol = ctoc + } else { + ctol = ctoc / bignum + if ctol == ctoc { + // ctoc is either 0 or inf. + mul = ctoc + done = true + cfromc = 1 + } else if math.Abs(cfrom1) > math.Abs(ctoc) && ctoc != 0 { + mul = smlnum + done = false + cfromc = cfrom1 + } else if math.Abs(ctol) > math.Abs(cfromc) { + mul = bignum + done = false + ctoc = ctol + } else { + mul = ctoc / cfromc + done = true + } + } + switch kind { + default: + panic("lapack: not implemented") + case lapack.General: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = a[i*lda+j] * mul + } + } + case lapack.UpperTri: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + a[i*lda+j] = a[i*lda+j] * mul + } + } + case lapack.LowerTri: + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + a[i*lda+j] = a[i*lda+j] * mul + } + } + } + if done { + break + } + } +} diff --git a/lapack/native/dlaset.go b/lapack/native/dlaset.go new file mode 100644 index 00000000..ad9fb7af --- /dev/null +++ b/lapack/native/dlaset.go @@ -0,0 +1,40 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dlaset sets the off-diagonal elements of A to alpha, and the diagonal +// elements to beta. If uplo == blas.Upper, only the elements in the upper +// triangular part are set. If uplo == blas.Lower, only the elements in the +// lower triangular part are set. If uplo is otherwise, all of the elements of A +// are set. +// +// Dlaset is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaset(uplo blas.Uplo, m, n int, alpha, beta float64, a []float64, lda int) { + checkMatrix(m, n, a, lda) + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + a[i*lda+j] = alpha + } + } + } else if uplo == blas.Lower { + for i := 0; i < m; i++ { + for j := 0; j < min(i+1, n); j++ { + a[i*lda+j] = alpha + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = alpha + } + } + } + for i := 0; i < min(m, n); i++ { + a[i*lda+i] = beta + } +} diff --git a/lapack/native/dlasq1.go b/lapack/native/dlasq1.go new file mode 100644 index 00000000..e2bbce3c --- /dev/null +++ b/lapack/native/dlasq1.go @@ -0,0 +1,97 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dlasq1 computes the singular values of an n×n bidiagonal matrix with diagonal +// d and off-diagonal e. On exit, d contains the singular values in decreasing +// order, and e is overwritten. d must have length at least n, e must have +// length at least n-1, and the input work must have length at least 4*n. Dlasq1 +// will panic if these conditions are not met. +// +// Dlasq1 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq1(n int, d, e, work []float64) (info int) { + // TODO(btracey): replace info with an error. + if n < 0 { + panic(nLT0) + } + if len(work) < 4*n { + panic(badWork) + } + if len(d) < n { + panic("lapack: length of d less than n") + } + if len(e) < n-1 { + panic("lapack: length of e less than n-1") + } + if n == 0 { + return info + } + if n == 1 { + d[0] = math.Abs(d[0]) + return info + } + if n == 2 { + d[1], d[0] = impl.Dlas2(d[0], e[0], d[1]) + return info + } + // Estimate the largest singular value. + var sigmx float64 + for i := 0; i < n-1; i++ { + d[i] = math.Abs(d[i]) + sigmx = math.Max(sigmx, math.Abs(e[i])) + } + d[n-1] = math.Abs(d[n-1]) + // Early return if sigmx is zero (matrix is already diagonal). + if sigmx == 0 { + impl.Dlasrt(lapack.SortDecreasing, n, d) + return info + } + + for i := 0; i < n; i++ { + sigmx = math.Max(sigmx, d[i]) + } + + // Copy D and E into WORK (in the Z format) and scale (squaring the + // input data makes scaling by a power of the radix pointless). + + eps := dlamchP + safmin := dlamchS + scale := math.Sqrt(eps / safmin) + bi := blas64.Implementation() + bi.Dcopy(n, d, 1, work, 2) + bi.Dcopy(n-1, e, 1, work[1:], 2) + impl.Dlascl(lapack.General, 0, 0, sigmx, scale, 2*n-1, 1, work, 1) + + // Compute the q's and e's. + for i := 0; i < 2*n-1; i++ { + work[i] *= work[i] + } + work[2*n-1] = 0 + + info = impl.Dlasq2(n, work) + if info == 0 { + for i := 0; i < n; i++ { + d[i] = math.Sqrt(work[i]) + } + impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, d, 1) + } else if info == 2 { + // Maximum number of iterations exceeded. Move data from work + // into D and E so the calling subroutine can try to finish. + for i := 0; i < n; i++ { + d[i] = math.Sqrt(work[2*i]) + e[i] = math.Sqrt(work[2*i+1]) + } + impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, d, 1) + impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, e, 1) + } + return info +} diff --git a/lapack/native/dlasq2.go b/lapack/native/dlasq2.go new file mode 100644 index 00000000..3570e734 --- /dev/null +++ b/lapack/native/dlasq2.go @@ -0,0 +1,370 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dlasq2 computes all the eigenvalues of the symmetric positive +// definite tridiagonal matrix associated with the qd array Z. Eigevalues +// are computed to high relative accuracy avoiding denormalization, underflow +// and overflow. +// +// To see the relation of Z to the tridiagonal matrix, let L be a +// unit lower bidiagonal matrix with sub-diagonals Z(2,4,6,,..) and +// let U be an upper bidiagonal matrix with 1's above and diagonal +// Z(1,3,5,,..). The tridiagonal is L*U or, if you prefer, the +// symmetric tridiagonal to which it is similar. +// +// info returns a status error. The return codes mean as follows: +// 0: The algorithm completed successfully. +// 1: A split was marked by a positive value in e. +// 2: Current block of Z not diagonalized after 100*n iterations (in inner +// while loop). On exit Z holds a qd array with the same eigenvalues as +// the given Z. +// 3: Termination criterion of outer while loop not met (program created more +// than N unreduced blocks). +// +// z must have length at least 4*n, and must not contain any negative elements. +// Dlasq2 will panic otherwise. +// +// Dlasq2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq2(n int, z []float64) (info int) { + // TODO(btracey): make info an error. + if len(z) < 4*n { + panic(badZ) + } + const cbias = 1.5 + + eps := dlamchP + safmin := dlamchS + tol := eps * 100 + tol2 := tol * tol + if n < 0 { + panic(nLT0) + } + if n == 0 { + return info + } + if n == 1 { + if z[0] < 0 { + panic(negZ) + } + return info + } + if n == 2 { + if z[1] < 0 || z[2] < 0 { + panic("lapack: bad z value") + } else if z[2] > z[0] { + z[0], z[2] = z[2], z[0] + } + z[4] = z[0] + z[1] + z[2] + if z[1] > z[2]*tol2 { + t := 0.5 * (z[0] - z[2] + z[1]) + s := z[2] * (z[1] / t) + if s <= t { + s = z[2] * (z[1] / (t * (1 + math.Sqrt(1+s/t)))) + } else { + s = z[2] * (z[1] / (t + math.Sqrt(t)*math.Sqrt(t+s))) + } + t = z[0] + s + z[1] + z[2] *= z[0] / t + z[0] = t + } + z[1] = z[2] + z[5] = z[1] + z[0] + return info + } + // Check for negative data and compute sums of q's and e's. + z[2*n-1] = 0 + emin := z[1] + var d, e, qmax, zmax float64 + var i1, n1 int + for k := 0; k < 2*(n-1); k += 2 { + if z[k] < 0 || z[k+1] < 0 { + panic("lapack: bad z value") + } + d += z[k] + e += z[k+1] + qmax = math.Max(qmax, z[k]) + emin = math.Min(emin, z[k+1]) + zmax = math.Max(math.Max(qmax, zmax), z[k+1]) + } + if z[2*(n-1)] < 0 { + panic("lapack: bad z value") + } + d += z[2*(n-1)] + qmax = math.Max(qmax, z[2*(n-1)]) + zmax = math.Max(qmax, zmax) + // Check for diagonality. + if e == 0 { + for k := 1; k < n; k++ { + z[k] = z[2*k] + } + impl.Dlasrt(lapack.SortDecreasing, n, z) + z[2*(n-1)] = d + return info + } + trace := d + e + // Check for zero data. + if trace == 0 { + z[2*(n-1)] = 0 + return info + } + // Rearrange data for locality: Z=(q1,qq1,e1,ee1,q2,qq2,e2,ee2,...). + for k := 2 * n; k >= 2; k -= 2 { + z[2*k-1] = 0 + z[2*k-2] = z[k-1] + z[2*k-3] = 0 + z[2*k-4] = z[k-2] + } + i0 := 0 + n0 := n - 1 + + // Reverse the qd-array, if warranted. + // z[4*i0-3] --> z[4*(i0+1)-3-1] --> z[4*i0] + if cbias*z[4*i0] < z[4*n0] { + ipn4Out := 4 * (i0 + n0 + 2) + for i4loop := 4 * (i0 + 1); i4loop <= 2*(i0+n0+1); i4loop += 4 { + i4 := i4loop - 1 + ipn4 := ipn4Out - 1 + z[i4-3], z[ipn4-i4-4] = z[ipn4-i4-4], z[i4-3] + z[i4-1], z[ipn4-i4-6] = z[ipn4-i4-6], z[i4-1] + } + } + + // Initial split checking via dqd and Li's test. + pp := 0 + for k := 0; k < 2; k++ { + d = z[4*n0+pp] + for i4loop := 4*n0 + pp; i4loop >= 4*(i0+1)+pp; i4loop -= 4 { + i4 := i4loop - 1 + if z[i4-1] <= tol2*d { + z[i4-1] = math.Copysign(0, -1) + d = z[i4-3] + } else { + d = z[i4-3] * (d / (d + z[i4-1])) + } + } + // dqd maps Z to ZZ plus Li's test. + emin = z[4*(i0+1)+pp] + d = z[4*i0+pp] + for i4loop := 4*(i0+1) + pp; i4loop <= 4*n0+pp; i4loop += 4 { + i4 := i4loop - 1 + z[i4-2*pp-2] = d + z[i4-1] + if z[i4-1] <= tol2*d { + z[i4-1] = math.Copysign(0, -1) + z[i4-2*pp-2] = d + z[i4-2*pp] = 0 + d = z[i4+1] + } else if safmin*z[i4+1] < z[i4-2*pp-2] && safmin*z[i4-2*pp-2] < z[i4+1] { + tmp := z[i4+1] / z[i4-2*pp-2] + z[i4-2*pp] = z[i4-1] * tmp + d *= tmp + } else { + z[i4-2*pp] = z[i4+1] * (z[i4-1] / z[i4-2*pp-2]) + d = z[i4+1] * (d / z[i4-2*pp-2]) + } + emin = math.Min(emin, z[i4-2*pp]) + } + z[4*(n0+1)-pp-3] = d + + // Now find qmax. + qmax = z[4*(i0+1)-pp-3] + for i4loop := 4*(i0+1) - pp + 2; i4loop <= 4*(n0+1)+pp-2; i4loop += 4 { + i4 := i4loop - 1 + qmax = math.Max(qmax, z[i4]) + } + // Prepare for the next iteration on K. + pp = 1 - pp + } + + // Initialise variables to pass to DLASQ3. + var ttype int + var dmin1, dmin2, dn, dn1, dn2, g, tau float64 + var tempq float64 + iter := 2 + var nFail int + nDiv := 2 * (n0 - i0) + var i4 int +outer: + for iwhila := 1; iwhila <= n+1; iwhila++ { + // Test for completion. + if n0 < 0 { + // Move q's to the front. + for k := 1; k < n; k++ { + z[k] = z[4*k] + } + // Sort and compute sum of eigenvalues. + impl.Dlasrt(lapack.SortDecreasing, n, z) + e = 0 + for k := n - 1; k >= 0; k-- { + e += z[k] + } + // Store trace, sum(eigenvalues) and information on performance. + z[2*n] = trace + z[2*n+1] = e + z[2*n+2] = float64(iter) + z[2*n+3] = float64(nDiv) / float64(n*n) + z[2*n+4] = 100 * float64(nFail) / float64(iter) + return info + } + + // While array unfinished do + // e[n0] holds the value of sigma when submatrix in i0:n0 + // splits from the rest of the array, but is negated. + var desig float64 + var sigma float64 + if n0 != n-1 { + sigma = -z[4*(n0+1)-2] + } + if sigma < 0 { + info = 1 + return info + } + // Find last unreduced submatrix's top index i0, find qmax and + // emin. Find Gershgorin-type bound if Q's much greater than E's. + var emax float64 + if n0 > i0 { + emin = math.Abs(z[4*(n0+1)-6]) + } else { + emin = 0 + } + qmin := z[4*(n0+1)-4] + qmax = qmin + zSmall := false + for i4loop := 4 * (n0 + 1); i4loop >= 8; i4loop -= 4 { + i4 = i4loop - 1 + if z[i4-5] <= 0 { + zSmall = true + break + } + if qmin >= 4*emax { + qmin = math.Min(qmin, z[i4-3]) + emax = math.Max(emax, z[i4-5]) + } + qmax = math.Max(qmax, z[i4-7]+z[i4-5]) + emin = math.Min(emin, z[i4-5]) + } + if !zSmall { + i4 = 3 + } + i0 = (i4+1)/4 - 1 + pp = 0 + if n0-i0 > 1 { + dee := z[4*i0] + deemin := dee + kmin := i0 + for i4loop := 4*(i0+1) + 1; i4loop <= 4*(n0+1)-3; i4loop += 4 { + i4 := i4loop - 1 + dee = z[i4] * (dee / (dee + z[i4-2])) + if dee <= deemin { + deemin = dee + kmin = (i4+4)/4 - 1 + } + } + if (kmin-i0)*2 < n0-kmin && deemin <= 0.5*z[4*n0] { + ipn4Out := 4 * (i0 + n0 + 2) + pp = 2 + for i4loop := 4 * (i0 + 1); i4loop <= 2*(i0+n0+1); i4loop += 4 { + i4 := i4loop - 1 + ipn4 := ipn4Out - 1 + z[i4-3], z[ipn4-i4-4] = z[ipn4-i4-4], z[i4-3] + z[i4-2], z[ipn4-i4-3] = z[ipn4-i4-3], z[i4-2] + z[i4-1], z[ipn4-i4-6] = z[ipn4-i4-6], z[i4-1] + z[i4], z[ipn4-i4-5] = z[ipn4-i4-5], z[i4] + } + } + } + // Put -(initial shift) into DMIN. + dmin := -math.Max(0, qmin-2*math.Sqrt(qmin)*math.Sqrt(emax)) + + // Now i0:n0 is unreduced. + // PP = 0 for ping, PP = 1 for pong. + // PP = 2 indicates that flipping was applied to the Z array and + // and that the tests for deflation upon entry in Dlasq3 + // should not be performed. + nbig := 100 * (n0 - i0 + 1) + for iwhilb := 0; iwhilb < nbig; iwhilb++ { + if i0 > n0 { + continue outer + } + + // While submatrix unfinished take a good dqds step. + i0, n0, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau = + impl.Dlasq3(i0, n0, z, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau) + + pp = 1 - pp + // When emin is very small check for splits. + if pp == 0 && n0-i0 >= 3 { + if z[4*(n0+1)-1] <= tol2*qmax || z[4*(n0+1)-2] <= tol2*sigma { + splt := i0 - 1 + qmax = z[4*i0] + emin = z[4*(i0+1)-2] + oldemn := z[4*(i0+1)-1] + for i4loop := 4 * (i0 + 1); i4loop <= 4*(n0-2); i4loop += 4 { + i4 := i4loop - 1 + if z[i4] <= tol2*z[i4-3] || z[i4-1] <= tol2*sigma { + z[i4-1] = -sigma + splt = i4 / 4 + qmax = 0 + emin = z[i4+3] + oldemn = z[i4+4] + } else { + qmax = math.Max(qmax, z[i4+1]) + emin = math.Min(emin, z[i4-1]) + oldemn = math.Min(oldemn, z[i4]) + } + } + z[4*(n0+1)-2] = emin + z[4*(n0+1)-1] = oldemn + i0 = splt + 1 + } + } + } + // Maximum number of iterations exceeded, restore the shift + // sigma and place the new d's and e's in a qd array. + // This might need to be done for several blocks. + info = 2 + i1 = i0 + n1 = n0 + for { + tempq = z[4*i0] + z[4*i0] += sigma + for k := i0 + 1; k <= n0; k++ { + tempe := z[4*(k+1)-6] + z[4*(k+1)-6] *= tempq / z[4*(k+1)-8] + tempq = z[4*k] + z[4*k] += sigma + tempe - z[4*(k+1)-6] + } + // Prepare to do this on the previous block if there is one. + if i1 <= 0 { + break + } + n1 = i1 - 1 + for i1 >= 1 && z[4*(i1+1)-6] >= 0 { + i1 -= 1 + } + sigma = -z[4*(n1+1)-2] + } + for k := 0; k < n; k++ { + z[2*k] = z[4*k] + // Only the block 1..N0 is unfinished. The rest of the e's + // must be essentially zero, although sometimes other data + // has been stored in them. + if k < n0 { + z[2*(k+1)-1] = z[4*(k+1)-1] + } else { + z[2*(k+1)] = 0 + } + } + return info + } + info = 3 + return info +} diff --git a/lapack/native/dlasq3.go b/lapack/native/dlasq3.go new file mode 100644 index 00000000..236671f2 --- /dev/null +++ b/lapack/native/dlasq3.go @@ -0,0 +1,161 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlasq3 checks for deflation, computes a shift (tau) and calls dqds. +// In case of failure it changes shifts, and tries again until output +// is positive. +// +// Dlasq3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq3(i0, n0 int, z []float64, pp int, dmin, sigma, desig, qmax float64, nFail, iter, nDiv int, ttype int, dmin1, dmin2, dn, dn1, dn2, g, tau float64) ( + i0Out, n0Out, ppOut int, dminOut, sigmaOut, desigOut, qmaxOut float64, nFailOut, iterOut, nDivOut, ttypeOut int, dmin1Out, dmin2Out, dnOut, dn1Out, dn2Out, gOut, tauOut float64) { + const cbias = 1.5 + + n0in := n0 + eps := dlamchP + tol := eps * 100 + tol2 := tol * tol + var nn int + var t float64 + for { + if n0 < i0 { + return i0, n0, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau + } + if n0 == i0 { + z[4*(n0+1)-4] = z[4*(n0+1)+pp-4] + sigma + n0-- + continue + } + nn = 4*(n0+1) + pp - 1 + if n0 != i0+1 { + // Check whether e[n0-1] is negligible, 1 eigenvalue. + if z[nn-5] > tol2*(sigma+z[nn-3]) && z[nn-2*pp-4] > tol2*z[nn-7] { + // Check whether e[n0-2] is negligible, 2 eigenvalues. + if z[nn-9] > tol2*sigma && z[nn-2*pp-8] > tol2*z[nn-11] { + break + } + } else { + z[4*(n0+1)-4] = z[4*(n0+1)+pp-4] + sigma + n0-- + continue + } + } + if z[nn-3] > z[nn-7] { + z[nn-3], z[nn-7] = z[nn-7], z[nn-3] + } + t = 0.5 * (z[nn-7] - z[nn-3] + z[nn-5]) + if z[nn-5] > z[nn-3]*tol2 && t != 0 { + s := z[nn-3] * (z[nn-5] / t) + if s <= t { + s = z[nn-3] * (z[nn-5] / (t * (1 + math.Sqrt(1+s/t)))) + } else { + s = z[nn-3] * (z[nn-5] / (t + math.Sqrt(t)*math.Sqrt(t+s))) + } + t = z[nn-7] + (s + z[nn-5]) + z[nn-3] *= z[nn-7] / t + z[nn-7] = t + } + z[4*(n0+1)-8] = z[nn-7] + sigma + z[4*(n0+1)-4] = z[nn-3] + sigma + n0 -= 2 + } + if pp == 2 { + pp = 0 + } + + // Reverse the qd-array, if warranted. + if dmin <= 0 || n0 < n0in { + if cbias*z[4*(i0+1)+pp-4] < z[4*(n0+1)+pp-4] { + ipn4Out := 4 * (i0 + n0 + 2) + for j4loop := 4 * (i0 + 1); j4loop <= 2*((i0+1)+(n0+1)-1); j4loop += 4 { + ipn4 := ipn4Out - 1 + j4 := j4loop - 1 + + z[j4-3], z[ipn4-j4-4] = z[ipn4-j4-4], z[j4-3] + z[j4-2], z[ipn4-j4-3] = z[ipn4-j4-3], z[j4-2] + z[j4-1], z[ipn4-j4-6] = z[ipn4-j4-6], z[j4-1] + z[j4], z[ipn4-j4-5] = z[ipn4-j4-5], z[j4] + } + if n0-i0 <= 4 { + z[4*(n0+1)+pp-2] = z[4*(i0+1)+pp-2] + z[4*(n0+1)-pp-1] = z[4*(i0+1)-pp-1] + } + dmin2 = math.Min(dmin2, z[4*(i0+1)-pp-2]) + z[4*(n0+1)+pp-2] = math.Min(math.Min(z[4*(n0+1)+pp-2], z[4*(i0+1)+pp-2]), z[4*(i0+1)+pp+2]) + z[4*(n0+1)-pp-1] = math.Min(math.Min(z[4*(n0+1)-pp-1], z[4*(i0+1)-pp-1]), z[4*(i0+1)-pp+3]) + qmax = math.Max(math.Max(qmax, z[4*(i0+1)+pp-4]), z[4*(i0+1)+pp]) + dmin = math.Copysign(0, -1) // Fortran code has -zero, but -0 in go is 0 + } + } + + // Choose a shift. + tau, ttype, g = impl.Dlasq4(i0, n0, z, pp, n0in, dmin, dmin1, dmin2, dn, dn1, dn2, tau, ttype, g) + + // Call dqds until dmin > 0. +loop: + for { + i0, n0, pp, tau, sigma, dmin, dmin1, dmin2, dn, dn1, dn2 = impl.Dlasq5(i0, n0, z, pp, tau, sigma) + + nDiv += n0 - i0 + 2 + iter++ + switch { + case dmin >= 0 && dmin1 >= 0: + // Success. + goto done + + case dmin < 0 && dmin1 > 0 && z[4*n0-pp-1] < tol*(sigma+dn1) && math.Abs(dn) < tol*sigma: + // Convergence hidden by negative dn. + z[4*n0-pp+1] = 0 + dmin = 0 + goto done + + case dmin < 0: + // Tau too big. Select new Tau and try again. + nFail++ + if ttype < -22 { + // Failed twice. Play it safe. + tau = 0 + } else if dmin1 > 0 { + // Late failure. Gives excellent shift. + tau = (tau + dmin) * (1 - 2*eps) + ttype -= 11 + } else { + // Early failure. Divide by 4. + tau = tau / 4 + ttype -= 12 + } + + case math.IsNaN(dmin): + if tau == 0 { + break loop + } + tau = 0 + + default: + // Possible underflow. Play it safe. + break loop + } + } + + // Risk of underflow. + dmin, dmin1, dmin2, dn, dn1, dn2 = impl.Dlasq6(i0, n0, z, pp) + nDiv += n0 - i0 + 2 + iter++ + tau = 0 + +done: + if tau < sigma { + desig += tau + t = sigma + desig + desig -= t - sigma + } else { + t = sigma + tau + desig += sigma - (t - tau) + } + sigma = t + return i0, n0, pp, dmin, sigma, desig, qmax, nFail, iter, nDiv, ttype, dmin1, dmin2, dn, dn1, dn2, g, tau +} diff --git a/lapack/native/dlasq4.go b/lapack/native/dlasq4.go new file mode 100644 index 00000000..20aa4612 --- /dev/null +++ b/lapack/native/dlasq4.go @@ -0,0 +1,239 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlasq4 computes an approximation to the smallest eigenvalue using values of d +// from the previous transform. +// i0, n0, and n0in are zero-indexed. +// +// Dlasq4 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq4(i0, n0 int, z []float64, pp int, n0in int, dmin, dmin1, dmin2, dn, dn1, dn2, tau float64, ttype int, g float64) (tauOut float64, ttypeOut int, gOut float64) { + const ( + cnst1 = 0.563 + cnst2 = 1.01 + cnst3 = 1.05 + + cnstthird = 0.333 // TODO(btracey): Fix? + ) + // A negative dmin forces the shift to take that absolute value + // ttype records the type of shift. + if dmin <= 0 { + tau = -dmin + ttype = -1 + return tau, ttype, g + } + nn := 4*(n0+1) + pp - 1 // -1 for zero indexing + s := math.NaN() // Poison s so that failure to take a path below is obvious + if n0in == n0 { + // No eigenvalues deflated. + if dmin == dn || dmin == dn1 { + b1 := math.Sqrt(z[nn-3]) * math.Sqrt(z[nn-5]) + b2 := math.Sqrt(z[nn-7]) * math.Sqrt(z[nn-9]) + a2 := z[nn-7] + z[nn-5] + if dmin == dn && dmin1 == dn1 { + gap2 := dmin2 - a2 - dmin2/4 + var gap1 float64 + if gap2 > 0 && gap2 > b2 { + gap1 = a2 - dn - (b2/gap2)*b2 + } else { + gap1 = a2 - dn - (b1 + b2) + } + if gap1 > 0 && gap1 > b1 { + s = math.Max(dn-(b1/gap1)*b1, 0.5*dmin) + ttype = -2 + } else { + s = 0 + if dn > b1 { + s = dn - b1 + } + if a2 > b1+b2 { + s = math.Min(s, a2-(b1+b2)) + } + s = math.Max(s, cnstthird*dmin) + ttype = -3 + } + } else { + ttype = -4 + s = dmin / 4 + var gam float64 + var np int + if dmin == dn { + gam = dn + a2 = 0 + if z[nn-5] > z[nn-7] { + return tau, ttype, g + } + b2 = z[nn-5] / z[nn-7] + np = nn - 9 + } else { + np = nn - 2*pp + b2 = z[np-2] + gam = dn1 + if z[np-4] > z[np-2] { + return tau, ttype, g + } + a2 = z[np-4] / z[np-2] + if z[nn-9] > z[nn-11] { + return tau, ttype, g + } + b2 = z[nn-9] / z[nn-11] + np = nn - 13 + } + // Approximate contribution to norm squared from i < nn-1. + a2 += b2 + for i4loop := np + 1; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { + i4 := i4loop - 1 + if b2 == 0 { + break + } + b1 = b2 + if z[i4] > z[i4-2] { + return tau, ttype, g + } + b2 *= z[i4] / z[i4-2] + a2 += b2 + if 100*math.Max(b2, b1) < a2 || cnst1 < a2 { + break + } + } + a2 *= cnst3 + // Rayleigh quotient residual bound. + if a2 < cnst1 { + s = gam * (1 - math.Sqrt(a2)) / (1 + a2) + } + } + } else if dmin == dn2 { + ttype = -5 + s = dmin / 4 + // Compute contribution to norm squared from i > nn-2. + np := nn - 2*pp + b1 := z[np-2] + b2 := z[np-6] + gam := dn2 + if z[np-8] > b2 || z[np-4] > b1 { + return tau, ttype, g + } + a2 := (z[np-8] / b2) * (1 + z[np-4]/b1) + // Approximate contribution to norm squared from i < nn-2. + if n0-i0 > 2 { + b2 = z[nn-13] / z[nn-15] + a2 += b2 + for i4loop := (nn + 1) - 17; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { + i4 := i4loop - 1 + if b2 == 0 { + break + } + b1 = b2 + if z[i4] > z[i4-2] { + return tau, ttype, g + } + b2 *= z[i4] / z[i4-2] + a2 += b2 + if 100*math.Max(b2, b1) < a2 || cnst1 < a2 { + break + } + } + a2 *= cnst3 + } + if a2 < cnst1 { + s = gam * (1 - math.Sqrt(a2)) / (1 + a2) + } + } else { + // Case 6, no information to guide us. + if ttype == -6 { + g += cnstthird * (1 - g) + } else if ttype == -18 { + g = cnstthird / 4 + } else { + g = 1.0 / 4 + } + s = g * dmin + ttype = -6 + } + } else if n0in == (n0 + 1) { + // One eigenvalue just deflated. Use DMIN1, DN1 for DMIN and DN. + if dmin1 == dn1 && dmin2 == dn2 { + ttype = -7 + s = cnstthird * dmin1 + if z[nn-5] > z[nn-7] { + return tau, ttype, g + } + b1 := z[nn-5] / z[nn-7] + b2 := b1 + if b2 != 0 { + for i4loop := 4*(n0+1) - 9 + pp; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { + i4 := i4loop - 1 + a2 := b1 + if z[i4] > z[i4-2] { + return tau, ttype, g + } + b1 *= z[i4] / z[i4-2] + b2 += b1 + if 100*math.Max(b1, a2) < b2 { + break + } + } + } + b2 = math.Sqrt(cnst3 * b2) + a2 := dmin1 / (1 + b2*b2) + gap2 := 0.5*dmin2 - a2 + if gap2 > 0 && gap2 > b2*a2 { + s = math.Max(s, a2*(1-cnst2*a2*(b2/gap2)*b2)) + } else { + s = math.Max(s, a2*(1-cnst2*b2)) + ttype = -8 + } + } else { + s = dmin1 / 4 + if dmin1 == dn1 { + s = 0.5 * dmin1 + } + ttype = -9 + } + } else if n0in == (n0 + 2) { + // Two eigenvalues deflated. Use DMIN2, DN2 for DMIN and DN. + if dmin2 == dn2 && 2*z[nn-5] < z[nn-7] { + ttype = -10 + s = cnstthird * dmin2 + if z[nn-5] > z[nn-7] { + return tau, ttype, g + } + b1 := z[nn-5] / z[nn-7] + b2 := b1 + if b2 != 0 { + for i4loop := 4*(n0+1) - 9 + pp; i4loop >= 4*(i0+1)-1+pp; i4loop -= 4 { + i4 := i4loop - 1 + if z[i4] > z[i4-2] { + return tau, ttype, g + } + b1 *= z[i4] / z[i4-2] + b2 += b1 + if 100*b1 < b2 { + break + } + } + } + b2 = math.Sqrt(cnst3 * b2) + a2 := dmin2 / (1 + b2*b2) + gap2 := z[nn-7] + z[nn-9] - math.Sqrt(z[nn-11])*math.Sqrt(z[nn-9]) - a2 + if gap2 > 0 && gap2 > b2*a2 { + s = math.Max(s, a2*(1-cnst2*a2*(b2/gap2)*b2)) + } else { + s = math.Max(s, a2*(1-cnst2*b2)) + } + } else { + s = dmin2 / 4 + ttype = -11 + } + } else if n0in > n0+2 { + // Case 12, more than two eigenvalues deflated. No information. + s = 0 + ttype = -12 + } + tau = s + return tau, ttype, g +} diff --git a/lapack/native/dlasq5.go b/lapack/native/dlasq5.go new file mode 100644 index 00000000..3be3fc9b --- /dev/null +++ b/lapack/native/dlasq5.go @@ -0,0 +1,125 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlasq5 computes one dqds transform in ping-pong form. +// i0 and n0 are zero-indexed. +// +// Dlasq5 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq5(i0, n0 int, z []float64, pp int, tau, sigma float64) (i0Out, n0Out, ppOut int, tauOut, sigmaOut, dmin, dmin1, dmin2, dn, dnm1, dnm2 float64) { + // The lapack function has inputs for ieee and eps, but Go requires ieee so + // these are unnecessary. + if n0-i0-1 <= 0 { + return i0, n0, pp, tau, sigma, dmin, dmin1, dmin2, dn, dnm1, dnm2 + } + eps := dlamchP + dthresh := eps * (sigma + tau) + if tau < dthresh*0.5 { + tau = 0 + } + var j4 int + var emin float64 + if tau != 0 { + j4 = 4*i0 + pp + emin = z[j4+4] + d := z[j4] - tau + dmin = d + dmin1 = -z[j4] + if pp == 0 { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-2] = d + z[j4-1] + tmp := z[j4+1] / z[j4-2] + d = d*tmp - tau + dmin = math.Min(dmin, d) + z[j4] = z[j4-1] * tmp + emin = math.Min(z[j4], emin) + } + } else { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-3] = d + z[j4] + tmp := z[j4+2] / z[j4-3] + d = d*tmp - tau + dmin = math.Min(dmin, d) + z[j4-1] = z[j4] * tmp + emin = math.Min(z[j4-1], emin) + } + } + // Unroll the last two steps. + dnm2 = d + dmin2 = dmin + j4 = 4*((n0+1)-2) - pp - 1 + j4p2 := j4 + 2*pp - 1 + z[j4-2] = dnm2 + z[j4p2] + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dnm1 = z[j4p2+2]*(dnm2/z[j4-2]) - tau + dmin = math.Min(dmin, dnm1) + + dmin1 = dmin + j4 += 4 + j4p2 = j4 + 2*pp - 1 + z[j4-2] = dnm1 + z[j4p2] + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dn = z[j4p2+2]*(dnm1/z[j4-2]) - tau + dmin = math.Min(dmin, dn) + } else { + // This is the version that sets d's to zero if they are small enough. + j4 = 4*(i0+1) + pp - 4 + emin = z[j4+4] + d := z[j4] - tau + dmin = d + dmin1 = -z[j4] + if pp == 0 { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-2] = d + z[j4-1] + tmp := z[j4+1] / z[j4-2] + d = d*tmp - tau + if d < dthresh { + d = 0 + } + dmin = math.Min(dmin, d) + z[j4] = z[j4-1] * tmp + emin = math.Min(z[j4], emin) + } + } else { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-3] = d + z[j4] + tmp := z[j4+2] / z[j4-3] + d = d*tmp - tau + if d < dthresh { + d = 0 + } + dmin = math.Min(dmin, d) + z[j4-1] = z[j4] * tmp + emin = math.Min(z[j4-1], emin) + } + } + // Unroll the last two steps. + dnm2 = d + dmin2 = dmin + j4 = 4*((n0+1)-2) - pp - 1 + j4p2 := j4 + 2*pp - 1 + z[j4-2] = dnm2 + z[j4p2] + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dnm1 = z[j4p2+2]*(dnm2/z[j4-2]) - tau + dmin = math.Min(dmin, dnm1) + + dmin1 = dmin + j4 += 4 + j4p2 = j4 + 2*pp - 1 + z[j4-2] = dnm1 + z[j4p2] + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dn = z[j4p2+2]*(dnm1/z[j4-2]) - tau + dmin = math.Min(dmin, dn) + } + z[j4+2] = dn + z[4*(n0+1)-pp-1] = emin + return i0, n0, pp, tau, sigma, dmin, dmin1, dmin2, dn, dnm1, dnm2 +} diff --git a/lapack/native/dlasq6.go b/lapack/native/dlasq6.go new file mode 100644 index 00000000..456b6cae --- /dev/null +++ b/lapack/native/dlasq6.go @@ -0,0 +1,109 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlasq6 computes one dqd transform in ping-pong form with protection against +// overflow and underflow. z has length at least 4*(n0+1) and holds the qd array. +// i0 is the zero-based first index. +// n0 is the zero-based last index. +// +// Dlasq6 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasq6(i0, n0 int, z []float64, pp int) (dmin, dmin1, dmin2, dn, dnm1, dnm2 float64) { + if len(z) < 4*(n0+1) { + panic(badZ) + } + if n0-i0-1 <= 0 { + return dmin, dmin1, dmin2, dn, dnm1, dnm2 + } + safmin := dlamchS + j4 := 4*(i0+1) + pp - 4 // -4 rather than -3 for zero indexing + emin := z[j4+4] + d := z[j4] + dmin = d + if pp == 0 { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 // Translate back to zero-indexed. + z[j4-2] = d + z[j4-1] + if z[j4-2] == 0 { + z[j4] = 0 + d = z[j4+1] + dmin = d + emin = 0 + } else if safmin*z[j4+1] < z[j4-2] && safmin*z[j4-2] < z[j4+1] { + tmp := z[j4+1] / z[j4-2] + z[j4] = z[j4-1] * tmp + d *= tmp + } else { + z[j4] = z[j4+1] * (z[j4-1] / z[j4-2]) + d = z[j4+1] * (d / z[j4-2]) + } + dmin = math.Min(dmin, d) + emin = math.Min(emin, z[j4]) + } + } else { + for j4loop := 4 * (i0 + 1); j4loop <= 4*((n0+1)-3); j4loop += 4 { + j4 := j4loop - 1 + z[j4-3] = d + z[j4] + if z[j4-3] == 0 { + z[j4-1] = 0 + d = z[j4+2] + dmin = d + emin = 0 + } else if safmin*z[j4+2] < z[j4-3] && safmin*z[j4-3] < z[j4+2] { + tmp := z[j4+2] / z[j4-3] + z[j4-1] = z[j4] * tmp + d *= tmp + } else { + z[j4-1] = z[j4+2] * (z[j4] / z[j4-3]) + d = z[j4+2] * (d / z[j4-3]) + } + dmin = math.Min(dmin, d) + emin = math.Min(emin, z[j4-1]) + } + } + // Unroll last two steps. + dnm2 = d + dmin2 = dmin + j4 = 4*(n0-1) - pp - 1 + j4p2 := j4 + 2*pp - 1 + z[j4-2] = dnm2 + z[j4p2] + if z[j4-2] == 0 { + z[j4] = 0 + dnm1 = z[j4p2+2] + dmin = dnm1 + emin = 0 + } else if safmin*z[j4p2+2] < z[j4-2] && safmin*z[j4-2] < z[j4p2+2] { + tmp := z[j4p2+2] / z[j4-2] + z[j4] = z[j4p2] * tmp + dnm1 = dnm2 * tmp + } else { + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dnm1 = z[j4p2+2] * (dnm2 / z[j4-2]) + } + dmin = math.Min(dmin, dnm1) + dmin1 = dmin + j4 += 4 + j4p2 = j4 + 2*pp - 1 + z[j4-2] = dnm1 + z[j4p2] + if z[j4-2] == 0 { + z[j4] = 0 + dn = z[j4p2+2] + dmin = dn + emin = 0 + } else if safmin*z[j4p2+2] < z[j4-2] && safmin*z[j4-2] < z[j4p2+2] { + tmp := z[j4p2+2] / z[j4-2] + z[j4] = z[j4p2] * tmp + dn = dnm1 * tmp + } else { + z[j4] = z[j4p2+2] * (z[j4p2] / z[j4-2]) + dn = z[j4p2+2] * (dnm1 / z[j4-2]) + } + dmin = math.Min(dmin, dn) + z[j4+2] = dn + z[4*(n0+1)-pp-1] = emin + return dmin, dmin1, dmin2, dn, dnm1, dnm2 +} diff --git a/lapack/native/dlasr.go b/lapack/native/dlasr.go new file mode 100644 index 00000000..773754fc --- /dev/null +++ b/lapack/native/dlasr.go @@ -0,0 +1,268 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dlasr applies a sequence of plane rotations to the m×n matrix A. This series +// of plane rotations is implicitly represented by a matrix P. P is multiplied +// by a depending on the value of side -- A = P * A if side == lapack.Left, +// A = A * P^T if side == lapack.Right. +// +//The exact value of P depends on the value of pivot, but in all cases P is +// implicitly represented by a series of 2×2 rotation matrices. The entries of +// rotation matrix k are defined by s[k] and c[k] +// R(k) = [ c[k] s[k]] +// [-s[k] s[k]] +// If direct == lapack.Forward, the rotation matrices are applied as +// P = P(z-1) * ... * P(2) * P(1), while if direct == lapack.Backward they are +// applied as P = P(1) * P(2) * ... * P(n). +// +// pivot defines the mapping of the elements in R(k) to P(k). +// If pivot == lapack.Variable, the rotation is performed for the (k, k+1) plane. +// P(k) = [1 ] +// [ ... ] +// [ 1 ] +// [ c[k] s[k] ] +// [ -s[k] c[k] ] +// [ 1 ] +// [ ... ] +// [ 1] +// if pivot == lapack.Top, the rotation is performed for the (1, k+1) plane, +// P(k) = [c[k] s[k] ] +// [ 1 ] +// [ ... ] +// [ 1 ] +// [-s[k] c[k] ] +// [ 1 ] +// [ ... ] +// [ 1] +// and if pivot == lapack.Bottom, the rotation is performed for the (k, z) plane. +// P(k) = [1 ] +// [ ... ] +// [ 1 ] +// [ c[k] s[k]] +// [ 1 ] +// [ ... ] +// [ 1 ] +// [ -s[k] c[k]] +// s and c have length m - 1 if side == blas.Left, and n - 1 if side == blas.Right. +// +// Dlasr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasr(side blas.Side, pivot lapack.Pivot, direct lapack.Direct, m, n int, c, s, a []float64, lda int) { + checkMatrix(m, n, a, lda) + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if pivot != lapack.Variable && pivot != lapack.Top && pivot != lapack.Bottom { + panic(badPivot) + } + if direct != lapack.Forward && direct != lapack.Backward { + panic(badDirect) + } + if side == blas.Left { + if len(c) < m-1 { + panic(badSlice) + } + if len(s) < m-1 { + panic(badSlice) + } + } else { + if len(c) < n-1 { + panic(badSlice) + } + if len(s) < n-1 { + panic(badSlice) + } + } + if m == 0 || n == 0 { + return + } + if side == blas.Left { + if pivot == lapack.Variable { + if direct == lapack.Forward { + for j := 0; j < m-1; j++ { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp2 := a[j*lda+i] + tmp := a[(j+1)*lda+i] + a[(j+1)*lda+i] = ctmp*tmp - stmp*tmp2 + a[j*lda+i] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + for j := m - 2; j >= 0; j-- { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp2 := a[j*lda+i] + tmp := a[(j+1)*lda+i] + a[(j+1)*lda+i] = ctmp*tmp - stmp*tmp2 + a[j*lda+i] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } else if pivot == lapack.Top { + if direct == lapack.Forward { + for j := 1; j < m; j++ { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp := a[j*lda+i] + tmp2 := a[i] + a[j*lda+i] = ctmp*tmp - stmp*tmp2 + a[i] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + for j := m - 1; j >= 1; j-- { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp := a[j*lda+i] + tmp2 := a[i] + a[j*lda+i] = ctmp*tmp - stmp*tmp2 + a[i] = stmp*tmp + ctmp*tmp2 + } + } + } + } + } + return + } + if direct == lapack.Forward { + for j := 0; j < m-1; j++ { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp := a[j*lda+i] + tmp2 := a[(m-1)*lda+i] + a[j*lda+i] = stmp*tmp2 + ctmp*tmp + a[(m-1)*lda+i] = ctmp*tmp2 - stmp*tmp + } + } + } + return + } + for j := m - 2; j >= 0; j-- { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < n; i++ { + tmp := a[j*lda+i] + tmp2 := a[(m-1)*lda+i] + a[j*lda+i] = stmp*tmp2 + ctmp*tmp + a[(m-1)*lda+i] = ctmp*tmp2 - stmp*tmp + } + } + } + return + } + if pivot == lapack.Variable { + if direct == lapack.Forward { + for j := 0; j < n-1; j++ { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j+1] + tmp2 := a[i*lda+j] + a[i*lda+j+1] = ctmp*tmp - stmp*tmp2 + a[i*lda+j] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + for j := n - 2; j >= 0; j-- { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j+1] + tmp2 := a[i*lda+j] + a[i*lda+j+1] = ctmp*tmp - stmp*tmp2 + a[i*lda+j] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } else if pivot == lapack.Top { + if direct == lapack.Forward { + for j := 1; j < n; j++ { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j] + tmp2 := a[i*lda] + a[i*lda+j] = ctmp*tmp - stmp*tmp2 + a[i*lda] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + for j := n - 1; j >= 1; j-- { + ctmp := c[j-1] + stmp := s[j-1] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j] + tmp2 := a[i*lda] + a[i*lda+j] = ctmp*tmp - stmp*tmp2 + a[i*lda] = stmp*tmp + ctmp*tmp2 + } + } + } + return + } + if direct == lapack.Forward { + for j := 0; j < n-1; j++ { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j] + tmp2 := a[i*lda+n-1] + a[i*lda+j] = stmp*tmp2 + ctmp*tmp + a[i*lda+n-1] = ctmp*tmp2 - stmp*tmp + } + + } + } + return + } + for j := n - 2; j >= 0; j-- { + ctmp := c[j] + stmp := s[j] + if ctmp != 1 || stmp != 0 { + for i := 0; i < m; i++ { + tmp := a[i*lda+j] + tmp2 := a[i*lda+n-1] + a[i*lda+j] = stmp*tmp2 + ctmp*tmp + a[i*lda+n-1] = ctmp*tmp2 - stmp*tmp + } + } + } +} diff --git a/lapack/native/dlasrt.go b/lapack/native/dlasrt.go new file mode 100644 index 00000000..f2d65fa6 --- /dev/null +++ b/lapack/native/dlasrt.go @@ -0,0 +1,30 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "sort" + + "gonum.org/v1/gonum/lapack" +) + +// Dlasrt sorts the numbers in the input slice d. If s == lapack.SortIncreasing, +// the elements are sorted in increasing order. If s == lapack.SortDecreasing, +// the elements are sorted in decreasing order. For other values of s Dlasrt +// will panic. +// +// Dlasrt is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasrt(s lapack.Sort, n int, d []float64) { + checkVector(n, d, 1) + d = d[:n] + switch s { + default: + panic(badSort) + case lapack.SortIncreasing: + sort.Float64s(d) + case lapack.SortDecreasing: + sort.Sort(sort.Reverse(sort.Float64Slice(d))) + } +} diff --git a/lapack/native/dlassq.go b/lapack/native/dlassq.go new file mode 100644 index 00000000..24f60365 --- /dev/null +++ b/lapack/native/dlassq.go @@ -0,0 +1,31 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlassq updates a sum of squares in scaled form. The input parameters scale and +// sumsq represent the current scale and total sum of squares. These values are +// updated with the information in the first n elements of the vector specified +// by x and incX. +// +// Dlassq is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlassq(n int, x []float64, incx int, scale float64, sumsq float64) (scl, smsq float64) { + if n <= 0 { + return scale, sumsq + } + for ix := 0; ix <= (n-1)*incx; ix += incx { + absxi := math.Abs(x[ix]) + if absxi > 0 || math.IsNaN(absxi) { + if scale < absxi { + sumsq = 1 + sumsq*(scale/absxi)*(scale/absxi) + scale = absxi + } else { + sumsq += (absxi / scale) * (absxi / scale) + } + } + } + return scale, sumsq +} diff --git a/lapack/native/dlasv2.go b/lapack/native/dlasv2.go new file mode 100644 index 00000000..bfae9ecf --- /dev/null +++ b/lapack/native/dlasv2.go @@ -0,0 +1,115 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Dlasv2 computes the singular value decomposition of a 2×2 matrix. +// [ csl snl] [f g] [csr -snr] = [ssmax 0] +// [-snl csl] [0 h] [snr csr] = [ 0 ssmin] +// ssmax is the larger absolute singular value, and ssmin is the smaller absolute +// singular value. [cls, snl] and [csr, snr] are the left and right singular vectors. +// +// Dlasv2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasv2(f, g, h float64) (ssmin, ssmax, snr, csr, snl, csl float64) { + ft := f + fa := math.Abs(ft) + ht := h + ha := math.Abs(h) + // pmax points to the largest element of the matrix in terms of absolute value. + // 1 if F, 2 if G, 3 if H. + pmax := 1 + swap := ha > fa + if swap { + pmax = 3 + ft, ht = ht, ft + fa, ha = ha, fa + } + gt := g + ga := math.Abs(gt) + var clt, crt, slt, srt float64 + if ga == 0 { + ssmin = ha + ssmax = fa + clt = 1 + crt = 1 + slt = 0 + srt = 0 + } else { + gasmall := true + if ga > fa { + pmax = 2 + if (fa / ga) < dlamchE { + gasmall = false + ssmax = ga + if ha > 1 { + ssmin = fa / (ga / ha) + } else { + ssmin = (fa / ga) * ha + } + clt = 1 + slt = ht / gt + srt = 1 + crt = ft / gt + } + } + if gasmall { + d := fa - ha + l := d / fa + if d == fa { // deal with inf + l = 1 + } + m := gt / ft + t := 2 - l + s := math.Hypot(t, m) + var r float64 + if l == 0 { + r = math.Abs(m) + } else { + r = math.Hypot(l, m) + } + a := 0.5 * (s + r) + ssmin = ha / a + ssmax = fa * a + if m == 0 { + if l == 0 { + t = math.Copysign(2, ft) * math.Copysign(1, gt) + } else { + t = gt/math.Copysign(d, ft) + m/t + } + } else { + t = (m/(s+t) + m/(r+l)) * (1 + a) + } + l = math.Hypot(t, 2) + crt = 2 / l + srt = t / l + clt = (crt + srt*m) / a + slt = (ht / ft) * srt / a + } + } + if swap { + csl = srt + snl = crt + csr = slt + snr = clt + } else { + csl = clt + snl = slt + csr = crt + snr = srt + } + var tsign float64 + switch pmax { + case 1: + tsign = math.Copysign(1, csr) * math.Copysign(1, csl) * math.Copysign(1, f) + case 2: + tsign = math.Copysign(1, snr) * math.Copysign(1, csl) * math.Copysign(1, g) + case 3: + tsign = math.Copysign(1, snr) * math.Copysign(1, snl) * math.Copysign(1, h) + } + ssmax = math.Copysign(ssmax, tsign) + ssmin = math.Copysign(ssmin, tsign*math.Copysign(1, f)*math.Copysign(1, h)) + return ssmin, ssmax, snr, csr, snl, csl +} diff --git a/lapack/native/dlaswp.go b/lapack/native/dlaswp.go new file mode 100644 index 00000000..12239c2d --- /dev/null +++ b/lapack/native/dlaswp.go @@ -0,0 +1,47 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas/blas64" + +// Dlaswp swaps the rows k1 to k2 of a rectangular matrix A according to the +// indices in ipiv so that row k is swapped with ipiv[k]. +// +// n is the number of columns of A and incX is the increment for ipiv. If incX +// is 1, the swaps are applied from k1 to k2. If incX is -1, the swaps are +// applied in reverse order from k2 to k1. For other values of incX Dlaswp will +// panic. ipiv must have length k2+1, otherwise Dlaswp will panic. +// +// The indices k1, k2, and the elements of ipiv are zero-based. +// +// Dlaswp is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlaswp(n int, a []float64, lda int, k1, k2 int, ipiv []int, incX int) { + switch { + case n < 0: + panic(nLT0) + case k2 < 0: + panic(badK2) + case k1 < 0 || k2 < k1: + panic(badK1) + case len(ipiv) != k2+1: + panic(badIpiv) + case incX != 1 && incX != -1: + panic(absIncNotOne) + } + + if n == 0 { + return + } + bi := blas64.Implementation() + if incX == 1 { + for k := k1; k <= k2; k++ { + bi.Dswap(n, a[k*lda:], 1, a[ipiv[k]*lda:], 1) + } + return + } + for k := k2; k >= k1; k-- { + bi.Dswap(n, a[k*lda:], 1, a[ipiv[k]*lda:], 1) + } +} diff --git a/lapack/native/dlasy2.go b/lapack/native/dlasy2.go new file mode 100644 index 00000000..af06e312 --- /dev/null +++ b/lapack/native/dlasy2.go @@ -0,0 +1,290 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlasy2 solves the Sylvester matrix equation where the matrices are of order 1 +// or 2. It computes the unknown n1×n2 matrix X so that +// TL*X + sgn*X*TR = scale*B, if tranl == false and tranr == false, +// TL^T*X + sgn*X*TR = scale*B, if tranl == true and tranr == false, +// TL*X + sgn*X*TR^T = scale*B, if tranl == false and tranr == true, +// TL^T*X + sgn*X*TR^T = scale*B, if tranl == true and tranr == true, +// where TL is n1×n1, TR is n2×n2, B is n1×n2, and 1 <= n1,n2 <= 2. +// +// isgn must be 1 or -1, and n1 and n2 must be 0, 1, or 2, but these conditions +// are not checked. +// +// Dlasy2 returns three values, a scale factor that is chosen less than or equal +// to 1 to prevent the solution overflowing, the infinity norm of the solution, +// and an indicator of success. If ok is false, TL and TR have eigenvalues that +// are too close, so TL or TR is perturbed to get a non-singular equation. +// +// Dlasy2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlasy2(tranl, tranr bool, isgn, n1, n2 int, tl []float64, ldtl int, tr []float64, ldtr int, b []float64, ldb int, x []float64, ldx int) (scale, xnorm float64, ok bool) { + // TODO(vladimir-ch): Add input validation checks conditionally skipped + // using the build tag mechanism. + + ok = true + // Quick return if possible. + if n1 == 0 || n2 == 0 { + return scale, xnorm, ok + } + + // Set constants to control overflow. + eps := dlamchP + smlnum := dlamchS / eps + sgn := float64(isgn) + + if n1 == 1 && n2 == 1 { + // 1×1 case: TL11*X + sgn*X*TR11 = B11. + tau1 := tl[0] + sgn*tr[0] + bet := math.Abs(tau1) + if bet <= smlnum { + tau1 = smlnum + bet = smlnum + ok = false + } + scale = 1 + gam := math.Abs(b[0]) + if smlnum*gam > bet { + scale = 1 / gam + } + x[0] = b[0] * scale / tau1 + xnorm = math.Abs(x[0]) + return scale, xnorm, ok + } + + if n1+n2 == 3 { + // 1×2 or 2×1 case. + var ( + smin float64 + tmp [4]float64 // tmp is used as a 2×2 row-major matrix. + btmp [2]float64 + ) + if n1 == 1 && n2 == 2 { + // 1×2 case: TL11*[X11 X12] + sgn*[X11 X12]*op[TR11 TR12] = [B11 B12]. + // [TR21 TR22] + smin = math.Abs(tl[0]) + smin = math.Max(smin, math.Max(math.Abs(tr[0]), math.Abs(tr[1]))) + smin = math.Max(smin, math.Max(math.Abs(tr[ldtr]), math.Abs(tr[ldtr+1]))) + smin = math.Max(eps*smin, smlnum) + tmp[0] = tl[0] + sgn*tr[0] + tmp[3] = tl[0] + sgn*tr[ldtr+1] + if tranr { + tmp[1] = sgn * tr[1] + tmp[2] = sgn * tr[ldtr] + } else { + tmp[1] = sgn * tr[ldtr] + tmp[2] = sgn * tr[1] + } + btmp[0] = b[0] + btmp[1] = b[1] + } else { + // 2×1 case: op[TL11 TL12]*[X11] + sgn*[X11]*TR11 = [B11]. + // [TL21 TL22]*[X21] [X21] [B21] + smin = math.Abs(tr[0]) + smin = math.Max(smin, math.Max(math.Abs(tl[0]), math.Abs(tl[1]))) + smin = math.Max(smin, math.Max(math.Abs(tl[ldtl]), math.Abs(tl[ldtl+1]))) + smin = math.Max(eps*smin, smlnum) + tmp[0] = tl[0] + sgn*tr[0] + tmp[3] = tl[ldtl+1] + sgn*tr[0] + if tranl { + tmp[1] = tl[ldtl] + tmp[2] = tl[1] + } else { + tmp[1] = tl[1] + tmp[2] = tl[ldtl] + } + btmp[0] = b[0] + btmp[1] = b[ldb] + } + + // Solve 2×2 system using complete pivoting. + // Set pivots less than smin to smin. + + bi := blas64.Implementation() + ipiv := bi.Idamax(len(tmp), tmp[:], 1) + // Compute the upper triangular matrix [u11 u12]. + // [ 0 u22] + u11 := tmp[ipiv] + if math.Abs(u11) <= smin { + ok = false + u11 = smin + } + locu12 := [4]int{1, 0, 3, 2} // Index in tmp of the element on the same row as the pivot. + u12 := tmp[locu12[ipiv]] + locl21 := [4]int{2, 3, 0, 1} // Index in tmp of the element on the same column as the pivot. + l21 := tmp[locl21[ipiv]] / u11 + locu22 := [4]int{3, 2, 1, 0} // Index in tmp of the remaining element. + u22 := tmp[locu22[ipiv]] - l21*u12 + if math.Abs(u22) <= smin { + ok = false + u22 = smin + } + if ipiv&0x2 != 0 { // true for ipiv equal to 2 and 3. + // The pivot was in the second row, swap the elements of + // the right-hand side. + btmp[0], btmp[1] = btmp[1], btmp[0]-l21*btmp[1] + } else { + btmp[1] -= l21 * btmp[0] + } + scale = 1 + if 2*smlnum*math.Abs(btmp[1]) > math.Abs(u22) || 2*smlnum*math.Abs(btmp[0]) > math.Abs(u11) { + scale = 0.5 / math.Max(math.Abs(btmp[0]), math.Abs(btmp[1])) + btmp[0] *= scale + btmp[1] *= scale + } + // Solve the system [u11 u12] [x21] = [ btmp[0] ]. + // [ 0 u22] [x22] [ btmp[1] ] + x22 := btmp[1] / u22 + x21 := btmp[0]/u11 - (u12/u11)*x22 + if ipiv&0x1 != 0 { // true for ipiv equal to 1 and 3. + // The pivot was in the second column, swap the elements + // of the solution. + x21, x22 = x22, x21 + } + x[0] = x21 + if n1 == 1 { + x[1] = x22 + xnorm = math.Abs(x[0]) + math.Abs(x[1]) + } else { + x[ldx] = x22 + xnorm = math.Max(math.Abs(x[0]), math.Abs(x[ldx])) + } + return scale, xnorm, ok + } + + // 2×2 case: op[TL11 TL12]*[X11 X12] + SGN*[X11 X12]*op[TR11 TR12] = [B11 B12]. + // [TL21 TL22] [X21 X22] [X21 X22] [TR21 TR22] [B21 B22] + // + // Solve equivalent 4×4 system using complete pivoting. + // Set pivots less than smin to smin. + + smin := math.Max(math.Abs(tr[0]), math.Abs(tr[1])) + smin = math.Max(smin, math.Max(math.Abs(tr[ldtr]), math.Abs(tr[ldtr+1]))) + smin = math.Max(smin, math.Max(math.Abs(tl[0]), math.Abs(tl[1]))) + smin = math.Max(smin, math.Max(math.Abs(tl[ldtl]), math.Abs(tl[ldtl+1]))) + smin = math.Max(eps*smin, smlnum) + + var t [4][4]float64 + t[0][0] = tl[0] + sgn*tr[0] + t[1][1] = tl[0] + sgn*tr[ldtr+1] + t[2][2] = tl[ldtl+1] + sgn*tr[0] + t[3][3] = tl[ldtl+1] + sgn*tr[ldtr+1] + if tranl { + t[0][2] = tl[ldtl] + t[1][3] = tl[ldtl] + t[2][0] = tl[1] + t[3][1] = tl[1] + } else { + t[0][2] = tl[1] + t[1][3] = tl[1] + t[2][0] = tl[ldtl] + t[3][1] = tl[ldtl] + } + if tranr { + t[0][1] = sgn * tr[1] + t[1][0] = sgn * tr[ldtr] + t[2][3] = sgn * tr[1] + t[3][2] = sgn * tr[ldtr] + } else { + t[0][1] = sgn * tr[ldtr] + t[1][0] = sgn * tr[1] + t[2][3] = sgn * tr[ldtr] + t[3][2] = sgn * tr[1] + } + + var btmp [4]float64 + btmp[0] = b[0] + btmp[1] = b[1] + btmp[2] = b[ldb] + btmp[3] = b[ldb+1] + + // Perform elimination. + var jpiv [4]int // jpiv records any column swaps for pivoting. + for i := 0; i < 3; i++ { + var ( + xmax float64 + ipsv, jpsv int + ) + for ip := i; ip < 4; ip++ { + for jp := i; jp < 4; jp++ { + if math.Abs(t[ip][jp]) >= xmax { + xmax = math.Abs(t[ip][jp]) + ipsv = ip + jpsv = jp + } + } + } + if ipsv != i { + // The pivot is not in the top row of the unprocessed + // block, swap rows ipsv and i of t and btmp. + t[ipsv], t[i] = t[i], t[ipsv] + btmp[ipsv], btmp[i] = btmp[i], btmp[ipsv] + } + if jpsv != i { + // The pivot is not in the left column of the + // unprocessed block, swap columns jpsv and i of t. + for k := 0; k < 4; k++ { + t[k][jpsv], t[k][i] = t[k][i], t[k][jpsv] + } + } + jpiv[i] = jpsv + if math.Abs(t[i][i]) < smin { + ok = false + t[i][i] = smin + } + for k := i + 1; k < 4; k++ { + t[k][i] /= t[i][i] + btmp[k] -= t[k][i] * btmp[i] + for j := i + 1; j < 4; j++ { + t[k][j] -= t[k][i] * t[i][j] + } + } + } + if math.Abs(t[3][3]) < smin { + ok = false + t[3][3] = smin + } + scale = 1 + if 8*smlnum*math.Abs(btmp[0]) > math.Abs(t[0][0]) || + 8*smlnum*math.Abs(btmp[1]) > math.Abs(t[1][1]) || + 8*smlnum*math.Abs(btmp[2]) > math.Abs(t[2][2]) || + 8*smlnum*math.Abs(btmp[3]) > math.Abs(t[3][3]) { + + maxbtmp := math.Max(math.Abs(btmp[0]), math.Abs(btmp[1])) + maxbtmp = math.Max(maxbtmp, math.Max(math.Abs(btmp[2]), math.Abs(btmp[3]))) + scale = 1 / 8 / maxbtmp + btmp[0] *= scale + btmp[1] *= scale + btmp[2] *= scale + btmp[3] *= scale + } + // Compute the solution of the upper triangular system t * tmp = btmp. + var tmp [4]float64 + for i := 3; i >= 0; i-- { + temp := 1 / t[i][i] + tmp[i] = btmp[i] * temp + for j := i + 1; j < 4; j++ { + tmp[i] -= temp * t[i][j] * tmp[j] + } + } + for i := 2; i >= 0; i-- { + if jpiv[i] != i { + tmp[i], tmp[jpiv[i]] = tmp[jpiv[i]], tmp[i] + } + } + x[0] = tmp[0] + x[1] = tmp[1] + x[ldx] = tmp[2] + x[ldx+1] = tmp[3] + xnorm = math.Max(math.Abs(tmp[0])+math.Abs(tmp[1]), math.Abs(tmp[2])+math.Abs(tmp[3])) + return scale, xnorm, ok +} diff --git a/lapack/native/dlatrd.go b/lapack/native/dlatrd.go new file mode 100644 index 00000000..e032c8d6 --- /dev/null +++ b/lapack/native/dlatrd.go @@ -0,0 +1,145 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlatrd reduces nb rows and columns of a real n×n symmetric matrix A to symmetric +// tridiagonal form. It computes the orthonormal similarity transformation +// Q^T * A * Q +// and returns the matrices V and W to apply to the unreduced part of A. If +// uplo == blas.Upper, the upper triangle is supplied and the last nb rows are +// reduced. If uplo == blas.Lower, the lower triangle is supplied and the first +// nb rows are reduced. +// +// a contains the symmetric matrix on entry with active triangular half specified +// by uplo. On exit, the nb columns have been reduced to tridiagonal form. The +// diagonal contains the diagonal of the reduced matrix, the off-diagonal is +// set to 1, and the remaining elements contain the data to construct Q. +// +// If uplo == blas.Upper, with n = 5 and nb = 2 on exit a is +// [ a a a v4 v5] +// [ a a v4 v5] +// [ a 1 v5] +// [ d 1] +// [ d] +// +// If uplo == blas.Lower, with n = 5 and nb = 2, on exit a is +// [ d ] +// [ 1 d ] +// [v1 1 a ] +// [v1 v2 a a ] +// [v1 v2 a a a] +// +// e contains the superdiagonal elements of the reduced matrix. If uplo == blas.Upper, +// e[n-nb:n-1] contains the last nb columns of the reduced matrix, while if +// uplo == blas.Lower, e[:nb] contains the first nb columns of the reduced matrix. +// e must have length at least n-1, and Dlatrd will panic otherwise. +// +// tau contains the scalar factors of the elementary reflectors needed to construct Q. +// The reflectors are stored in tau[n-nb:n-1] if uplo == blas.Upper, and in +// tau[:nb] if uplo == blas.Lower. tau must have length n-1, and Dlatrd will panic +// otherwise. +// +// w is an n×nb matrix. On exit it contains the data to update the unreduced part +// of A. +// +// The matrix Q is represented as a product of elementary reflectors. Each reflector +// H has the form +// I - tau * v * v^T +// If uplo == blas.Upper, +// Q = H_{n-1} * H_{n-2} * ... * H_{n-nb} +// where v[:i-1] is stored in A[:i-1,i], v[i-1] = 1, and v[i:n] = 0. +// +// If uplo == blas.Lower, +// Q = H_0 * H_1 * ... * H_{nb-1} +// where v[:i+1] = 0, v[i+1] = 1, and v[i+2:n] is stored in A[i+2:n,i]. +// +// The vectors v form the n×nb matrix V which is used with W to apply a +// symmetric rank-2 update to the unreduced part of A +// A = A - V * W^T - W * V^T +// +// Dlatrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlatrd(uplo blas.Uplo, n, nb int, a []float64, lda int, e, tau, w []float64, ldw int) { + checkMatrix(n, n, a, lda) + checkMatrix(n, nb, w, ldw) + if len(e) < n-1 { + panic(badE) + } + if len(tau) < n-1 { + panic(badTau) + } + if n <= 0 { + return + } + bi := blas64.Implementation() + if uplo == blas.Upper { + for i := n - 1; i >= n-nb; i-- { + iw := i - n + nb + if i < n-1 { + // Update A(0:i, i). + bi.Dgemv(blas.NoTrans, i+1, n-i-1, -1, a[i+1:], lda, + w[i*ldw+iw+1:], 1, 1, a[i:], lda) + bi.Dgemv(blas.NoTrans, i+1, n-i-1, -1, w[iw+1:], ldw, + a[i*lda+i+1:], 1, 1, a[i:], lda) + } + if i > 0 { + // Generate elementary reflector H_i to annihilate A(0:i-2,i). + e[i-1], tau[i-1] = impl.Dlarfg(i, a[(i-1)*lda+i], a[i:], lda) + a[(i-1)*lda+i] = 1 + + // Compute W(0:i-1, i). + bi.Dsymv(blas.Upper, i, 1, a, lda, a[i:], lda, 0, w[iw:], ldw) + if i < n-1 { + bi.Dgemv(blas.Trans, i, n-i-1, 1, w[iw+1:], ldw, + a[i:], lda, 0, w[(i+1)*ldw+iw:], ldw) + bi.Dgemv(blas.NoTrans, i, n-i-1, -1, a[i+1:], lda, + w[(i+1)*ldw+iw:], ldw, 1, w[iw:], ldw) + bi.Dgemv(blas.Trans, i, n-i-1, 1, a[i+1:], lda, + a[i:], lda, 0, w[(i+1)*ldw+iw:], ldw) + bi.Dgemv(blas.NoTrans, i, n-i-1, -1, w[iw+1:], ldw, + w[(i+1)*ldw+iw:], ldw, 1, w[iw:], ldw) + } + bi.Dscal(i, tau[i-1], w[iw:], ldw) + alpha := -0.5 * tau[i-1] * bi.Ddot(i, w[iw:], ldw, a[i:], lda) + bi.Daxpy(i, alpha, a[i:], lda, w[iw:], ldw) + } + } + } else { + // Reduce first nb columns of lower triangle. + for i := 0; i < nb; i++ { + // Update A(i:n, i) + bi.Dgemv(blas.NoTrans, n-i, i, -1, a[i*lda:], lda, + w[i*ldw:], 1, 1, a[i*lda+i:], lda) + bi.Dgemv(blas.NoTrans, n-i, i, -1, w[i*ldw:], ldw, + a[i*lda:], 1, 1, a[i*lda+i:], lda) + if i < n-1 { + // Generate elementary reflector H_i to annihilate A(i+2:n,i). + e[i], tau[i] = impl.Dlarfg(n-i-1, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) + a[(i+1)*lda+i] = 1 + + // Compute W(i+1:n,i). + bi.Dsymv(blas.Lower, n-i-1, 1, a[(i+1)*lda+i+1:], lda, + a[(i+1)*lda+i:], lda, 0, w[(i+1)*ldw+i:], ldw) + bi.Dgemv(blas.Trans, n-i-1, i, 1, w[(i+1)*ldw:], ldw, + a[(i+1)*lda+i:], lda, 0, w[i:], ldw) + bi.Dgemv(blas.NoTrans, n-i-1, i, -1, a[(i+1)*lda:], lda, + w[i:], ldw, 1, w[(i+1)*ldw+i:], ldw) + bi.Dgemv(blas.Trans, n-i-1, i, 1, a[(i+1)*lda:], lda, + a[(i+1)*lda+i:], lda, 0, w[i:], ldw) + bi.Dgemv(blas.NoTrans, n-i-1, i, -1, w[(i+1)*ldw:], ldw, + w[i:], ldw, 1, w[(i+1)*ldw+i:], ldw) + bi.Dscal(n-i-1, tau[i], w[(i+1)*ldw+i:], ldw) + alpha := -0.5 * tau[i] * bi.Ddot(n-i-1, w[(i+1)*ldw+i:], ldw, + a[(i+1)*lda+i:], lda) + bi.Daxpy(n-i-1, alpha, a[(i+1)*lda+i:], lda, + w[(i+1)*ldw+i:], ldw) + } + } + } +} diff --git a/lapack/native/dlatrs.go b/lapack/native/dlatrs.go new file mode 100644 index 00000000..2a86c4f4 --- /dev/null +++ b/lapack/native/dlatrs.go @@ -0,0 +1,350 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlatrs solves a triangular system of equations scaled to prevent overflow. It +// solves +// A * x = scale * b if trans == blas.NoTrans +// A^T * x = scale * b if trans == blas.Trans +// where the scale s is set for numeric stability. +// +// A is an n×n triangular matrix. On entry, the slice x contains the values of +// of b, and on exit it contains the solution vector x. +// +// If normin == true, cnorm is an input and cnorm[j] contains the norm of the off-diagonal +// part of the j^th column of A. If trans == blas.NoTrans, cnorm[j] must be greater +// than or equal to the infinity norm, and greater than or equal to the one-norm +// otherwise. If normin == false, then cnorm is treated as an output, and is set +// to contain the 1-norm of the off-diagonal part of the j^th column of A. +// +// Dlatrs is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dlatrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, normin bool, n int, a []float64, lda int, x []float64, cnorm []float64) (scale float64) { + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + if diag != blas.Unit && diag != blas.NonUnit { + panic(badDiag) + } + upper := uplo == blas.Upper + noTrans := trans == blas.NoTrans + nonUnit := diag == blas.NonUnit + + if n < 0 { + panic(nLT0) + } + checkMatrix(n, n, a, lda) + checkVector(n, x, 1) + checkVector(n, cnorm, 1) + + if n == 0 { + return 0 + } + smlnum := dlamchS / dlamchP + bignum := 1 / smlnum + scale = 1 + bi := blas64.Implementation() + if !normin { + if upper { + cnorm[0] = 0 + for j := 1; j < n; j++ { + cnorm[j] = bi.Dasum(j, a[j:], lda) + } + } else { + for j := 0; j < n-1; j++ { + cnorm[j] = bi.Dasum(n-j-1, a[(j+1)*lda+j:], lda) + } + cnorm[n-1] = 0 + } + } + // Scale the column norms by tscal if the maximum element in cnorm is greater than bignum. + imax := bi.Idamax(n, cnorm, 1) + tmax := cnorm[imax] + var tscal float64 + if tmax <= bignum { + tscal = 1 + } else { + tscal = 1 / (smlnum * tmax) + bi.Dscal(n, tscal, cnorm, 1) + } + + // Compute a bound on the computed solution vector to see if bi.Dtrsv can be used. + j := bi.Idamax(n, x, 1) + xmax := math.Abs(x[j]) + xbnd := xmax + var grow float64 + var jfirst, jlast, jinc int + if noTrans { + if upper { + jfirst = n - 1 + jlast = -1 + jinc = -1 + } else { + jfirst = 0 + jlast = n + jinc = 1 + } + // Compute the growth in A * x = b. + if tscal != 1 { + grow = 0 + goto Solve + } + if nonUnit { + grow = 1 / math.Max(xbnd, smlnum) + xbnd = grow + for j := jfirst; j != jlast; j += jinc { + if grow <= smlnum { + goto Solve + } + tjj := math.Abs(a[j*lda+j]) + xbnd = math.Min(xbnd, math.Min(1, tjj)*grow) + if tjj+cnorm[j] >= smlnum { + grow *= tjj / (tjj + cnorm[j]) + } else { + grow = 0 + } + } + grow = xbnd + } else { + grow = math.Min(1, 1/math.Max(xbnd, smlnum)) + for j := jfirst; j != jlast; j += jinc { + if grow <= smlnum { + goto Solve + } + grow *= 1 / (1 + cnorm[j]) + } + } + } else { + if upper { + jfirst = 0 + jlast = n + jinc = 1 + } else { + jfirst = n - 1 + jlast = -1 + jinc = -1 + } + if tscal != 1 { + grow = 0 + goto Solve + } + if nonUnit { + grow = 1 / (math.Max(xbnd, smlnum)) + xbnd = grow + for j := jfirst; j != jlast; j += jinc { + if grow <= smlnum { + goto Solve + } + xj := 1 + cnorm[j] + grow = math.Min(grow, xbnd/xj) + tjj := math.Abs(a[j*lda+j]) + if xj > tjj { + xbnd *= tjj / xj + } + } + grow = math.Min(grow, xbnd) + } else { + grow = math.Min(1, 1/math.Max(xbnd, smlnum)) + for j := jfirst; j != jlast; j += jinc { + if grow <= smlnum { + goto Solve + } + xj := 1 + cnorm[j] + grow /= xj + } + } + } + +Solve: + if grow*tscal > smlnum { + // Use the Level 2 BLAS solve if the reciprocal of the bound on + // elements of X is not too small. + bi.Dtrsv(uplo, trans, diag, n, a, lda, x, 1) + if tscal != 1 { + bi.Dscal(n, 1/tscal, cnorm, 1) + } + return scale + } + + // Use a Level 1 BLAS solve, scaling intermediate results. + if xmax > bignum { + scale = bignum / xmax + bi.Dscal(n, scale, x, 1) + xmax = bignum + } + if noTrans { + for j := jfirst; j != jlast; j += jinc { + xj := math.Abs(x[j]) + var tjj, tjjs float64 + if nonUnit { + tjjs = a[j*lda+j] * tscal + } else { + tjjs = tscal + if tscal == 1 { + goto Skip1 + } + } + tjj = math.Abs(tjjs) + if tjj > smlnum { + if tjj < 1 { + if xj > tjj*bignum { + rec := 1 / xj + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + } + x[j] /= tjjs + xj = math.Abs(x[j]) + } else if tjj > 0 { + if xj > tjj*bignum { + rec := (tjj * bignum) / xj + if cnorm[j] > 1 { + rec /= cnorm[j] + } + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + x[j] /= tjjs + xj = math.Abs(x[j]) + } else { + for i := 0; i < n; i++ { + x[i] = 0 + } + x[j] = 1 + xj = 1 + scale = 0 + xmax = 0 + } + Skip1: + if xj > 1 { + rec := 1 / xj + if cnorm[j] > (bignum-xmax)*rec { + rec *= 0.5 + bi.Dscal(n, rec, x, 1) + scale *= rec + } + } else if xj*cnorm[j] > bignum-xmax { + bi.Dscal(n, 0.5, x, 1) + scale *= 0.5 + } + if upper { + if j > 0 { + bi.Daxpy(j, -x[j]*tscal, a[j:], lda, x, 1) + i := bi.Idamax(j, x, 1) + xmax = math.Abs(x[i]) + } + } else { + if j < n-1 { + bi.Daxpy(n-j-1, -x[j]*tscal, a[(j+1)*lda+j:], lda, x[j+1:], 1) + i := j + bi.Idamax(n-j-1, x[j+1:], 1) + xmax = math.Abs(x[i]) + } + } + } + } else { + for j := jfirst; j != jlast; j += jinc { + xj := math.Abs(x[j]) + uscal := tscal + rec := 1 / math.Max(xmax, 1) + var tjjs float64 + if cnorm[j] > (bignum-xj)*rec { + rec *= 0.5 + if nonUnit { + tjjs = a[j*lda+j] * tscal + } else { + tjjs = tscal + } + tjj := math.Abs(tjjs) + if tjj > 1 { + rec = math.Min(1, rec*tjj) + uscal /= tjjs + } + if rec < 1 { + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + } + var sumj float64 + if uscal == 1 { + if upper { + sumj = bi.Ddot(j, a[j:], lda, x, 1) + } else if j < n-1 { + sumj = bi.Ddot(n-j-1, a[(j+1)*lda+j:], lda, x[j+1:], 1) + } + } else { + if upper { + for i := 0; i < j; i++ { + sumj += (a[i*lda+j] * uscal) * x[i] + } + } else if j < n { + for i := j + 1; i < n; i++ { + sumj += (a[i*lda+j] * uscal) * x[i] + } + } + } + if uscal == tscal { + x[j] -= sumj + xj := math.Abs(x[j]) + var tjjs float64 + if nonUnit { + tjjs = a[j*lda+j] * tscal + } else { + tjjs = tscal + if tscal == 1 { + goto Skip2 + } + } + tjj := math.Abs(tjjs) + if tjj > smlnum { + if tjj < 1 { + if xj > tjj*bignum { + rec = 1 / xj + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + } + x[j] /= tjjs + } else if tjj > 0 { + if xj > tjj*bignum { + rec = (tjj * bignum) / xj + bi.Dscal(n, rec, x, 1) + scale *= rec + xmax *= rec + } + x[j] /= tjjs + } else { + for i := 0; i < n; i++ { + x[i] = 0 + } + x[j] = 1 + scale = 0 + xmax = 0 + } + } else { + x[j] = x[j]/tjjs - sumj + } + Skip2: + xmax = math.Max(xmax, math.Abs(x[j])) + } + } + scale /= tscal + if tscal != 1 { + bi.Dscal(n, 1/tscal, cnorm, 1) + } + return scale +} diff --git a/lapack/native/doc.go b/lapack/native/doc.go new file mode 100644 index 00000000..d622dc50 --- /dev/null +++ b/lapack/native/doc.go @@ -0,0 +1,28 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package native is a pure-go implementation of the LAPACK API. The LAPACK API defines +// a set of algorithms for advanced matrix operations. +// +// The function definitions and implementations follow that of the netlib reference +// implementation. Please see http://www.netlib.org/lapack/explore-html/ for more +// information, and http://www.netlib.org/lapack/explore-html/d4/de1/_l_i_c_e_n_s_e_source.html +// for more license information. +// +// Slice function arguments frequently represent vectors and matrices. The data +// layout is identical to that found in https://godoc.org/github.com/gonum/blas/native. +// +// Most LAPACK functions are built on top the routines defined in the BLAS API, +// and as such the computation time for many LAPACK functions is +// dominated by BLAS calls. Here, BLAS is accessed through the +// the blas64 package (https://godoc.org/github.com/gonum/blas/blas64). In particular, +// this implies that an external BLAS library will be used if it is +// registered in blas64. +// +// The full LAPACK capability has not been implemented at present. The full +// API is very large, containing approximately 200 functions for double precision +// alone. Future additions will be focused on supporting the gonum matrix +// package (https://godoc.org/github.com/gonum/matrix/mat64), though pull requests +// with implementations and tests for LAPACK function are encouraged. +package native diff --git a/lapack/native/dorg2l.go b/lapack/native/dorg2l.go new file mode 100644 index 00000000..63510d19 --- /dev/null +++ b/lapack/native/dorg2l.go @@ -0,0 +1,65 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dorg2l generates an m×n matrix Q with orthonormal columns which is defined +// as the last n columns of a product of k elementary reflectors of order m. +// Q = H_{k-1} * ... * H_1 * H_0 +// See Dgelqf for more information. It must be that m >= n >= k. +// +// tau contains the scalar reflectors computed by Dgeqlf. tau must have length +// at least k, and Dorg2l will panic otherwise. +// +// work contains temporary memory, and must have length at least n. Dorg2l will +// panic otherwise. +// +// Dorg2l is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorg2l(m, n, k int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + if len(tau) < k { + panic(badTau) + } + if len(work) < n { + panic(badWork) + } + if m < n { + panic(mLTN) + } + if k > n { + panic(kGTN) + } + if n == 0 { + return + } + + // Initialize columns 0:n-k to columns of the unit matrix. + for j := 0; j < n-k; j++ { + for l := 0; l < m; l++ { + a[l*lda+j] = 0 + } + a[(m-n+j)*lda+j] = 1 + } + + bi := blas64.Implementation() + for i := 0; i < k; i++ { + ii := n - k + i + + // Apply H_i to A[0:m-k+i, 0:n-k+i] from the left. + a[(m-n+ii)*lda+ii] = 1 + impl.Dlarf(blas.Left, m-n+ii+1, ii, a[ii:], lda, tau[i], a, lda, work) + bi.Dscal(m-n+ii, -tau[i], a[ii:], lda) + a[(m-n+ii)*lda+ii] = 1 - tau[i] + + // Set A[m-k+i:m, n-k+i+1] to zero. + for l := m - n + ii + 1; l < m; l++ { + a[l*lda+ii] = 0 + } + } +} diff --git a/lapack/native/dorg2r.go b/lapack/native/dorg2r.go new file mode 100644 index 00000000..6bc69647 --- /dev/null +++ b/lapack/native/dorg2r.go @@ -0,0 +1,65 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dorg2r generates an m×n matrix Q with orthonormal columns defined by the +// product of elementary reflectors as computed by Dgeqrf. +// Q = H_0 * H_1 * ... * H_{k-1} +// len(tau) >= k, 0 <= k <= n, 0 <= n <= m, len(work) >= n. +// Dorg2r will panic if these conditions are not met. +// +// Dorg2r is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorg2r(m, n, k int, a []float64, lda int, tau []float64, work []float64) { + checkMatrix(m, n, a, lda) + if len(tau) < k { + panic(badTau) + } + if len(work) < n { + panic(badWork) + } + if k > n { + panic(kGTN) + } + if n > m { + panic(mLTN) + } + if len(work) < n { + panic(badWork) + } + if n == 0 { + return + } + bi := blas64.Implementation() + // Initialize columns k+1:n to columns of the unit matrix. + for l := 0; l < m; l++ { + for j := k; j < n; j++ { + a[l*lda+j] = 0 + } + } + for j := k; j < n; j++ { + a[j*lda+j] = 1 + } + for i := k - 1; i >= 0; i-- { + for i := range work { + work[i] = 0 + } + if i < n-1 { + a[i*lda+i] = 1 + impl.Dlarf(blas.Left, m-i, n-i-1, a[i*lda+i:], lda, tau[i], a[i*lda+i+1:], lda, work) + } + if i < m-1 { + bi.Dscal(m-i-1, -tau[i], a[(i+1)*lda+i:], lda) + } + a[i*lda+i] = 1 - tau[i] + for l := 0; l < i; l++ { + a[l*lda+i] = 0 + } + } +} diff --git a/lapack/native/dorgbr.go b/lapack/native/dorgbr.go new file mode 100644 index 00000000..62b6b3b8 --- /dev/null +++ b/lapack/native/dorgbr.go @@ -0,0 +1,124 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/lapack" + +// Dorgbr generates one of the matrices Q or P^T computed by Dgebrd +// computed from the decomposition Dgebrd. See Dgebd2 for the description of +// Q and P^T. +// +// If vect == lapack.ApplyQ, then a is assumed to have been an m×k matrix and +// Q is of order m. If m >= k, then Dorgbr returns the first n columns of Q +// where m >= n >= k. If m < k, then Dorgbr returns Q as an m×m matrix. +// +// If vect == lapack.ApplyP, then A is assumed to have been a k×n matrix, and +// P^T is of order n. If k < n, then Dorgbr returns the first m rows of P^T, +// where n >= m >= k. If k >= n, then Dorgbr returns P^T as an n×n matrix. +// +// Dorgbr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgbr(vect lapack.DecompUpdate, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + mn := min(m, n) + wantq := vect == lapack.ApplyQ + if wantq { + if m < n || n < min(m, k) || m < min(m, k) { + panic(badDims) + } + } else { + if n < m || m < min(n, k) || n < min(n, k) { + panic(badDims) + } + } + if wantq { + if m >= k { + checkMatrix(m, k, a, lda) + } else { + checkMatrix(m, m, a, lda) + } + } else { + if n >= k { + checkMatrix(k, n, a, lda) + } else { + checkMatrix(n, n, a, lda) + } + } + work[0] = 1 + if wantq { + if m >= k { + impl.Dorgqr(m, n, k, a, lda, tau, work, -1) + } else if m > 1 { + impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau, work, -1) + } + } else { + if k < n { + impl.Dorglq(m, n, k, a, lda, tau, work, -1) + } else if n > 1 { + impl.Dorglq(n-1, n-1, n-1, a[lda+1:], lda, tau, work, -1) + } + } + lworkopt := int(work[0]) + lworkopt = max(lworkopt, mn) + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + if len(work) < lwork { + panic(badWork) + } + if lwork < mn { + panic(badWork) + } + if m == 0 || n == 0 { + work[0] = 1 + return + } + if wantq { + // Form Q, determined by a call to Dgebrd to reduce an m×k matrix. + if m >= k { + impl.Dorgqr(m, n, k, a, lda, tau, work, lwork) + } else { + // Shift the vectors which define the elementary reflectors one + // column to the right, and set the first row and column of Q to + // those of the unit matrix. + for j := m - 1; j >= 1; j-- { + a[j] = 0 + for i := j + 1; i < m; i++ { + a[i*lda+j] = a[i*lda+j-1] + } + } + a[0] = 1 + for i := 1; i < m; i++ { + a[i*lda] = 0 + } + if m > 1 { + // Form Q[1:m-1, 1:m-1] + impl.Dorgqr(m-1, m-1, m-1, a[lda+1:], lda, tau, work, lwork) + } + } + } else { + // Form P^T, determined by a call to Dgebrd to reduce a k×n matrix. + if k < n { + impl.Dorglq(m, n, k, a, lda, tau, work, lwork) + } else { + // Shift the vectors which define the elementary reflectors one + // row downward, and set the first row and column of P^T to + // those of the unit matrix. + a[0] = 1 + for i := 1; i < n; i++ { + a[i*lda] = 0 + } + for j := 1; j < n; j++ { + for i := j - 1; i >= 1; i-- { + a[i*lda+j] = a[(i-1)*lda+j] + } + a[j] = 0 + } + if n > 1 { + impl.Dorglq(n-1, n-1, n-1, a[lda+1:], lda, tau, work, lwork) + } + } + } + work[0] = float64(lworkopt) +} diff --git a/lapack/native/dorghr.go b/lapack/native/dorghr.go new file mode 100644 index 00000000..fb4d57f2 --- /dev/null +++ b/lapack/native/dorghr.go @@ -0,0 +1,93 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +// Dorghr generates an n×n orthogonal matrix Q which is defined as the product +// of ihi-ilo elementary reflectors: +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// +// a and lda represent an n×n matrix that contains the elementary reflectors, as +// returned by Dgehrd. On return, a is overwritten by the n×n orthogonal matrix +// Q. Q will be equal to the identity matrix except in the submatrix +// Q[ilo+1:ihi+1,ilo+1:ihi+1]. +// +// ilo and ihi must have the same values as in the previous call of Dgehrd. It +// must hold that +// 0 <= ilo <= ihi < n, if n > 0, +// ilo = 0, ihi = -1, if n == 0. +// +// tau contains the scalar factors of the elementary reflectors, as returned by +// Dgehrd. tau must have length n-1. +// +// work must have length at least max(1,lwork) and lwork must be at least +// ihi-ilo. For optimum performance lwork must be at least (ihi-ilo)*nb where nb +// is the optimal blocksize. On return, work[0] will contain the optimal value +// of lwork. +// +// If lwork == -1, instead of performing Dorghr, only the optimal value of lwork +// will be stored into work[0]. +// +// If any requirement on input sizes is not met, Dorghr will panic. +// +// Dorghr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorghr(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) { + checkMatrix(n, n, a, lda) + nh := ihi - ilo + switch { + case ilo < 0 || max(1, n) <= ilo: + panic(badIlo) + case ihi < min(ilo, n-1) || n <= ihi: + panic(badIhi) + case lwork < max(1, nh) && lwork != -1: + panic(badWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + + lwkopt := max(1, nh) * impl.Ilaenv(1, "DORGQR", " ", nh, nh, nh, -1) + if lwork == -1 { + work[0] = float64(lwkopt) + return + } + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return + } + + // Shift the vectors which define the elementary reflectors one column + // to the right. + for i := ilo + 2; i < ihi+1; i++ { + copy(a[i*lda+ilo+1:i*lda+i], a[i*lda+ilo:i*lda+i-1]) + } + // Set the first ilo+1 and the last n-ihi-1 rows and columns to those of + // the identity matrix. + for i := 0; i < ilo+1; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + } + a[i*lda+i] = 1 + } + for i := ilo + 1; i < ihi+1; i++ { + for j := 0; j <= ilo; j++ { + a[i*lda+j] = 0 + } + for j := i; j < n; j++ { + a[i*lda+j] = 0 + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + } + a[i*lda+i] = 1 + } + if nh > 0 { + // Generate Q[ilo+1:ihi+1,ilo+1:ihi+1]. + impl.Dorgqr(nh, nh, nh, a[(ilo+1)*lda+ilo+1:], lda, tau[ilo:ihi], work, lwork) + } + work[0] = float64(lwkopt) +} diff --git a/lapack/native/dorgl2.go b/lapack/native/dorgl2.go new file mode 100644 index 00000000..760ebd71 --- /dev/null +++ b/lapack/native/dorgl2.go @@ -0,0 +1,63 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dorgl2 generates an m×n matrix Q with orthonormal rows defined by the +// first m rows product of elementary reflectors as computed by Dgelqf. +// Q = H_0 * H_1 * ... * H_{k-1} +// len(tau) >= k, 0 <= k <= m, 0 <= m <= n, len(work) >= m. +// Dorgl2 will panic if these conditions are not met. +// +// Dorgl2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgl2(m, n, k int, a []float64, lda int, tau, work []float64) { + checkMatrix(m, n, a, lda) + if len(tau) < k { + panic(badTau) + } + if k > m { + panic(kGTM) + } + if k > m { + panic(kGTM) + } + if m > n { + panic(nLTM) + } + if len(work) < m { + panic(badWork) + } + if m == 0 { + return + } + bi := blas64.Implementation() + if k < m { + for i := k; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + } + } + for j := k; j < m; j++ { + a[j*lda+j] = 1 + } + } + for i := k - 1; i >= 0; i-- { + if i < n-1 { + if i < m-1 { + a[i*lda+i] = 1 + impl.Dlarf(blas.Right, m-i-1, n-i, a[i*lda+i:], 1, tau[i], a[(i+1)*lda+i:], lda, work) + } + bi.Dscal(n-i-1, -tau[i], a[i*lda+i+1:], 1) + } + a[i*lda+i] = 1 - tau[i] + for l := 0; l < i; l++ { + a[i*lda+l] = 0 + } + } +} diff --git a/lapack/native/dorglq.go b/lapack/native/dorglq.go new file mode 100644 index 00000000..3f5639d6 --- /dev/null +++ b/lapack/native/dorglq.go @@ -0,0 +1,117 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dorglq generates an m×n matrix Q with orthonormal columns defined by the +// product of elementary reflectors as computed by Dgelqf. +// Q = H_0 * H_1 * ... * H_{k-1} +// Dorglq is the blocked version of Dorgl2 that makes greater use of level-3 BLAS +// routines. +// +// len(tau) >= k, 0 <= k <= n, and 0 <= n <= m. +// +// work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= m, and the amount of blocking is limited by the usable length. +// If lwork == -1, instead of computing Dorglq the optimal work length is stored +// into work[0]. +// +// Dorglq will panic if the conditions on input values are not met. +// +// Dorglq is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + nb := impl.Ilaenv(1, "DORGLQ", " ", m, n, k, -1) + // work is treated as an n×nb matrix + if lwork == -1 { + work[0] = float64(max(1, m) * nb) + return + } + checkMatrix(m, n, a, lda) + if k < 0 { + panic(kLT0) + } + if k > m { + panic(kGTM) + } + if m > n { + panic(nLTM) + } + if len(tau) < k { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + if lwork < m { + panic(badWork) + } + if m == 0 { + return + } + nbmin := 2 // Minimum number of blocks + var nx int // Minimum number of rows + iws := m // Length of work needed + var ldwork int + if nb > 1 && nb < k { + nx = max(0, impl.Ilaenv(3, "DORGLQ", " ", m, n, k, -1)) + if nx < k { + ldwork = nb + iws = m * ldwork + if lwork < iws { + nb = lwork / m + ldwork = nb + nbmin = max(2, impl.Ilaenv(2, "DORGLQ", " ", m, n, k, -1)) + } + } + } + var ki, kk int + if nb >= nbmin && nb < k && nx < k { + // The first kk rows are handled by the blocked method. + // Note: lapack has nx here, but this means the last nx rows are handled + // serially which could be quite different than nb. + ki = ((k - nb - 1) / nb) * nb + kk = min(k, ki+nb) + for i := kk; i < m; i++ { + for j := 0; j < kk; j++ { + a[i*lda+j] = 0 + } + } + } + if kk < m { + // Perform the operation on colums kk to the end. + impl.Dorgl2(m-kk, n-kk, k-kk, a[kk*lda+kk:], lda, tau[kk:], work) + } + if kk == 0 { + return + } + // Perform the operation on column-blocks + for i := ki; i >= 0; i -= nb { + ib := min(nb, k-i) + if i+ib < m { + impl.Dlarft(lapack.Forward, lapack.RowWise, + n-i, ib, + a[i*lda+i:], lda, + tau[i:], + work, ldwork) + + impl.Dlarfb(blas.Right, blas.Trans, lapack.Forward, lapack.RowWise, + m-i-ib, n-i, ib, + a[i*lda+i:], lda, + work, ldwork, + a[(i+ib)*lda+i:], lda, + work[ib*ldwork:], ldwork) + } + impl.Dorgl2(ib, n-i, ib, a[i*lda+i:], lda, tau[i:], work) + for l := i; l < i+ib; l++ { + for j := 0; j < i; j++ { + a[l*lda+j] = 0 + } + } + } +} diff --git a/lapack/native/dorgql.go b/lapack/native/dorgql.go new file mode 100644 index 00000000..d1b69418 --- /dev/null +++ b/lapack/native/dorgql.go @@ -0,0 +1,130 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dorgql generates the m×n matrix Q with orthonormal columns defined as the +// last n columns of a product of k elementary reflectors of order m +// Q = H_{k-1} * ... * H_1 * H_0. +// +// It must hold that +// 0 <= k <= n <= m, +// and Dorgql will panic otherwise. +// +// On entry, the (n-k+i)-th column of A must contain the vector which defines +// the elementary reflector H_i, for i=0,...,k-1, and tau[i] must contain its +// scalar factor. On return, a contains the m×n matrix Q. +// +// tau must have length at least k, and Dorgql will panic otherwise. +// +// work must have length at least max(1,lwork), and lwork must be at least +// max(1,n), otherwise Dorgql will panic. For optimum performance lwork must +// be a sufficiently large multiple of n. +// +// If lwork == -1, instead of computing Dorgql the optimal work length is stored +// into work[0]. +// +// Dorgql is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgql(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + switch { + case n < 0: + panic(nLT0) + case m < n: + panic(mLTN) + case k < 0: + panic(kLT0) + case k > n: + panic(kGTN) + case lwork < max(1, n) && lwork != -1: + panic(badWork) + case len(work) < lwork: + panic(shortWork) + } + if lwork != -1 { + checkMatrix(m, n, a, lda) + if len(tau) < k { + panic(badTau) + } + } + + if n == 0 { + work[0] = 1 + return + } + + nb := impl.Ilaenv(1, "DORGQL", " ", m, n, k, -1) + if lwork == -1 { + work[0] = float64(n * nb) + return + } + + nbmin := 2 + var nx, ldwork int + iws := n + if nb > 1 && nb < k { + // Determine when to cross over from blocked to unblocked code. + nx = max(0, impl.Ilaenv(3, "DORGQL", " ", m, n, k, -1)) + if nx < k { + // Determine if workspace is large enough for blocked code. + iws = n * nb + if lwork < iws { + // Not enough workspace to use optimal nb: reduce nb and determine + // the minimum value of nb. + nb = lwork / n + nbmin = max(2, impl.Ilaenv(2, "DORGQL", " ", m, n, k, -1)) + } + ldwork = nb + } + } + + var kk int + if nb >= nbmin && nb < k && nx < k { + // Use blocked code after the first block. The last kk columns are handled + // by the block method. + kk = min(k, ((k-nx+nb-1)/nb)*nb) + + // Set A(m-kk:m, 0:n-kk) to zero. + for i := m - kk; i < m; i++ { + for j := 0; j < n-kk; j++ { + a[i*lda+j] = 0 + } + } + } + + // Use unblocked code for the first or only block. + impl.Dorg2l(m-kk, n-kk, k-kk, a, lda, tau, work) + if kk > 0 { + // Use blocked code. + for i := k - kk; i < k; i += nb { + ib := min(nb, k-i) + if n-k+i > 0 { + // Form the triangular factor of the block reflector + // H = H_{i+ib-1} * ... * H_{i+1} * H_i. + impl.Dlarft(lapack.Backward, lapack.ColumnWise, m-k+i+ib, ib, + a[n-k+i:], lda, tau[i:], work, ldwork) + + // Apply H to A[0:m-k+i+ib, 0:n-k+i] from the left. + impl.Dlarfb(blas.Left, blas.NoTrans, lapack.Backward, lapack.ColumnWise, + m-k+i+ib, n-k+i, ib, a[n-k+i:], lda, work, ldwork, + a, lda, work[ib*ldwork:], ldwork) + } + + // Apply H to rows 0:m-k+i+ib of current block. + impl.Dorg2l(m-k+i+ib, ib, ib, a[n-k+i:], lda, tau[i:], work) + + // Set rows m-k+i+ib:m of current block to zero. + for j := n - k + i; j < n-k+i+ib; j++ { + for l := m - k + i + ib; l < m; l++ { + a[l*lda+j] = 0 + } + } + } + } + work[0] = float64(iws) +} diff --git a/lapack/native/dorgqr.go b/lapack/native/dorgqr.go new file mode 100644 index 00000000..28822d03 --- /dev/null +++ b/lapack/native/dorgqr.go @@ -0,0 +1,120 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dorgqr generates an m×n matrix Q with orthonormal columns defined by the +// product of elementary reflectors +// Q = H_0 * H_1 * ... * H_{k-1} +// as computed by Dgeqrf. +// Dorgqr is the blocked version of Dorg2r that makes greater use of level-3 BLAS +// routines. +// +// The length of tau must be at least k, and the length of work must be at least n. +// It also must be that 0 <= k <= n and 0 <= n <= m. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= n, and the amount of blocking is limited by the usable +// length. If lwork == -1, instead of computing Dorgqr the optimal work length +// is stored into work[0]. +// +// Dorgqr will panic if the conditions on input values are not met. +// +// Dorgqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + nb := impl.Ilaenv(1, "DORGQR", " ", m, n, k, -1) + // work is treated as an n×nb matrix + if lwork == -1 { + work[0] = float64(max(1, n) * nb) + return + } + checkMatrix(m, n, a, lda) + if k < 0 { + panic(kLT0) + } + if k > n { + panic(kGTN) + } + if n > m { + panic(mLTN) + } + if len(tau) < k { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + if lwork < n { + panic(badWork) + } + if n == 0 { + return + } + nbmin := 2 // Minimum number of blocks + var nx int // Minimum number of rows + iws := n // Length of work needed + var ldwork int + if nb > 1 && nb < k { + nx = max(0, impl.Ilaenv(3, "DORGQR", " ", m, n, k, -1)) + if nx < k { + ldwork = nb + iws = n * ldwork + if lwork < iws { + nb = lwork / n + ldwork = nb + nbmin = max(2, impl.Ilaenv(2, "DORGQR", " ", m, n, k, -1)) + } + } + } + var ki, kk int + if nb >= nbmin && nb < k && nx < k { + // The first kk columns are handled by the blocked method. + // Note: lapack has nx here, but this means the last nx rows are handled + // serially which could be quite different than nb. + ki = ((k - nb - 1) / nb) * nb + kk = min(k, ki+nb) + for j := kk; j < n; j++ { + for i := 0; i < kk; i++ { + a[i*lda+j] = 0 + } + } + } + if kk < n { + // Perform the operation on colums kk to the end. + impl.Dorg2r(m-kk, n-kk, k-kk, a[kk*lda+kk:], lda, tau[kk:], work) + } + if kk == 0 { + return + } + // Perform the operation on column-blocks + for i := ki; i >= 0; i -= nb { + ib := min(nb, k-i) + if i+ib < n { + impl.Dlarft(lapack.Forward, lapack.ColumnWise, + m-i, ib, + a[i*lda+i:], lda, + tau[i:], + work, ldwork) + + impl.Dlarfb(blas.Left, blas.NoTrans, lapack.Forward, lapack.ColumnWise, + m-i, n-i-ib, ib, + a[i*lda+i:], lda, + work, ldwork, + a[i*lda+i+ib:], lda, + work[ib*ldwork:], ldwork) + } + impl.Dorg2r(m-i, ib, ib, a[i*lda+i:], lda, tau[i:], work) + // Set rows 0:i-1 of current block to zero + for j := i; j < i+ib; j++ { + for l := 0; l < i; l++ { + a[l*lda+j] = 0 + } + } + } +} diff --git a/lapack/native/dorgtr.go b/lapack/native/dorgtr.go new file mode 100644 index 00000000..c5c3b756 --- /dev/null +++ b/lapack/native/dorgtr.go @@ -0,0 +1,99 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dorgtr generates a real orthogonal matrix Q which is defined as the product +// of n-1 elementary reflectors of order n as returned by Dsytrd. +// +// The construction of Q depends on the value of uplo: +// Q = H_{n-1} * ... * H_1 * H_0 if uplo == blas.Upper +// Q = H_0 * H_1 * ... * H_{n-1} if uplo == blas.Lower +// where H_i is constructed from the elementary reflectors as computed by Dsytrd. +// See the documentation for Dsytrd for more information. +// +// tau must have length at least n-1, and Dorgtr will panic otherwise. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= max(1,n-1), and Dorgtr will panic otherwise. The amount of blocking +// is limited by the usable length. +// If lwork == -1, instead of computing Dorgtr the optimal work length is stored +// into work[0]. +// +// Dorgtr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, tau, work []float64, lwork int) { + checkMatrix(n, n, a, lda) + if len(tau) < n-1 { + panic(badTau) + } + if len(work) < lwork { + panic(badWork) + } + if lwork < n-1 && lwork != -1 { + panic(badWork) + } + upper := uplo == blas.Upper + if !upper && uplo != blas.Lower { + panic(badUplo) + } + + if n == 0 { + work[0] = 1 + return + } + + var nb int + if upper { + nb = impl.Ilaenv(1, "DORGQL", " ", n-1, n-1, n-1, -1) + } else { + nb = impl.Ilaenv(1, "DORGQR", " ", n-1, n-1, n-1, -1) + } + lworkopt := max(1, n-1) * nb + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + + if upper { + // Q was determined by a call to Dsytrd with uplo == blas.Upper. + // Shift the vectors which define the elementary reflectors one column + // to the left, and set the last row and column of Q to those of the unit + // matrix. + for j := 0; j < n-1; j++ { + for i := 0; i < j; i++ { + a[i*lda+j] = a[i*lda+j+1] + } + a[(n-1)*lda+j] = 0 + } + for i := 0; i < n-1; i++ { + a[i*lda+n-1] = 0 + } + a[(n-1)*lda+n-1] = 1 + + // Generate Q[0:n-1, 0:n-1]. + impl.Dorgql(n-1, n-1, n-1, a, lda, tau, work, lwork) + } else { + // Q was determined by a call to Dsytrd with uplo == blas.Upper. + // Shift the vectors which define the elementary reflectors one column + // to the right, and set the first row and column of Q to those of the unit + // matrix. + for j := n - 1; j > 0; j-- { + a[j] = 0 + for i := j + 1; i < n; i++ { + a[i*lda+j] = a[i*lda+j-1] + } + } + a[0] = 1 + for i := 1; i < n; i++ { + a[i*lda] = 0 + } + if n > 1 { + // Generate Q[1:n, 1:n]. + impl.Dorgqr(n-1, n-1, n-1, a[lda+1:], lda, tau, work, lwork) + } + } + work[0] = float64(lworkopt) +} diff --git a/lapack/native/dorm2r.go b/lapack/native/dorm2r.go new file mode 100644 index 00000000..dae265f6 --- /dev/null +++ b/lapack/native/dorm2r.go @@ -0,0 +1,88 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dorm2r multiplies a general matrix C by an orthogonal matrix from a QR factorization +// determined by Dgeqrf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, a is a matrix of size m×k, and if side == blas.Right +// a is of size n×k. +// +// tau contains the Householder factors and is of length at least k and this function +// will panic otherwise. +// +// work is temporary storage of length at least n if side == blas.Left +// and at least m if side == blas.Right and this function will panic otherwise. +// +// Dorm2r is an internal routine. It is exported for testing purposes. +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) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + + left := side == blas.Left + notran := trans == blas.NoTrans + if left { + // Q is m x m + checkMatrix(m, k, a, lda) + if len(work) < n { + panic(badWork) + } + } else { + // Q is n x n + checkMatrix(n, k, a, lda) + if len(work) < m { + panic(badWork) + } + } + checkMatrix(m, n, c, ldc) + if m == 0 || n == 0 || k == 0 { + return + } + if len(tau) < k { + panic(badTau) + } + if left { + if notran { + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) + a[i*lda+i] = aii + } + return + } + for i := 0; i < k; i++ { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) + a[i*lda+i] = aii + } + return + } + if notran { + for i := 0; i < k; i++ { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) + a[i*lda+i] = aii + } + return + } + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) + a[i*lda+i] = aii + } +} diff --git a/lapack/native/dormbr.go b/lapack/native/dormbr.go new file mode 100644 index 00000000..eef130ad --- /dev/null +++ b/lapack/native/dormbr.go @@ -0,0 +1,158 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dormbr applies a multiplicative update to the matrix C based on a +// decomposition computed by Dgebrd. +// +// Dormbr overwrites the m×n matrix C with +// Q * C if vect == lapack.ApplyQ, side == blas.Left, and trans == blas.NoTrans +// C * Q if vect == lapack.ApplyQ, side == blas.Right, and trans == blas.NoTrans +// Q^T * C if vect == lapack.ApplyQ, side == blas.Left, and trans == blas.Trans +// C * Q^T if vect == lapack.ApplyQ, side == blas.Right, and trans == blas.Trans +// +// P * C if vect == lapack.ApplyP, side == blas.Left, and trans == blas.NoTrans +// C * P if vect == lapack.ApplyP, side == blas.Right, and trans == blas.NoTrans +// P^T * C if vect == lapack.ApplyP, side == blas.Left, and trans == blas.Trans +// C * P^T if vect == lapack.ApplyP, side == blas.Right, and trans == blas.Trans +// where P and Q are the orthogonal matrices determined by Dgebrd when reducing +// a matrix A to bidiagonal form: A = Q * B * P^T. See Dgebrd for the +// definitions of Q and P. +// +// If vect == lapack.ApplyQ, A is assumed to have been an nq×k matrix, while if +// vect == lapack.ApplyP, A is assumed to have been a k×nq matrix. nq = m if +// side == blas.Left, while nq = n if side == blas.Right. +// +// tau must have length min(nq,k), and Dormbr will panic otherwise. tau contains +// the elementary reflectors to construct Q or P depending on the value of +// vect. +// +// work must have length at least max(1,lwork), and lwork must be either -1 or +// at least max(1,n) if side == blas.Left, and at least max(1,m) if side == +// blas.Right. For optimum performance lwork should be at least n*nb if side == +// blas.Left, and at least m*nb if side == blas.Right, where nb is the optimal +// block size. On return, work[0] will contain the optimal value of lwork. +// +// If lwork == -1, the function only calculates the optimal value of lwork and +// returns it in work[0]. +// +// Dormbr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dormbr(vect lapack.DecompUpdate, side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.NoTrans && trans != blas.Trans { + panic(badTrans) + } + if vect != lapack.ApplyP && vect != lapack.ApplyQ { + panic(badDecompUpdate) + } + nq := n + nw := m + if side == blas.Left { + nq = m + nw = n + } + if vect == lapack.ApplyQ { + checkMatrix(nq, min(nq, k), a, lda) + } else { + checkMatrix(min(nq, k), nq, a, lda) + } + if len(tau) < min(nq, k) { + panic(badTau) + } + checkMatrix(m, n, c, ldc) + if len(work) < lwork { + panic(shortWork) + } + if lwork < max(1, nw) && lwork != -1 { + panic(badWork) + } + + applyQ := vect == lapack.ApplyQ + left := side == blas.Left + var nb int + + // The current implementation does not use opts, but a future change may + // use these options so construct them. + var opts string + if side == blas.Left { + opts = "L" + } else { + opts = "R" + } + if trans == blas.Trans { + opts += "T" + } else { + opts += "N" + } + if applyQ { + if left { + nb = impl.Ilaenv(1, "DORMQR", opts, m-1, n, m-1, -1) + } else { + nb = impl.Ilaenv(1, "DORMQR", opts, m, n-1, n-1, -1) + } + } else { + if left { + nb = impl.Ilaenv(1, "DORMLQ", opts, m-1, n, m-1, -1) + } else { + nb = impl.Ilaenv(1, "DORMLQ", opts, m, n-1, n-1, -1) + } + } + lworkopt := max(1, nw) * nb + if lwork == -1 { + work[0] = float64(lworkopt) + } + if applyQ { + // Change the operation to get Q depending on the size of the initial + // matrix to Dgebrd. The size matters due to the storage location of + // the off-diagonal elements. + if nq >= k { + impl.Dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork) + } else if nq > 1 { + mi := m + ni := n - 1 + i1 := 0 + i2 := 1 + if left { + mi = m - 1 + ni = n + i1 = 1 + i2 = 0 + } + impl.Dormqr(side, trans, mi, ni, nq-1, a[1*lda:], lda, tau[:nq-1], c[i1*ldc+i2:], ldc, work, lwork) + } + work[0] = float64(lworkopt) + return + } + transt := blas.Trans + if trans == blas.Trans { + transt = blas.NoTrans + } + // Change the operation to get P depending on the size of the initial + // matrix to Dgebrd. The size matters due to the storage location of + // the off-diagonal elements. + if nq > k { + impl.Dormlq(side, transt, m, n, k, a, lda, tau, c, ldc, work, lwork) + } else if nq > 1 { + mi := m + ni := n - 1 + i1 := 0 + i2 := 1 + if left { + mi = m - 1 + ni = n + i1 = 1 + i2 = 0 + } + impl.Dormlq(side, transt, mi, ni, nq-1, a[1:], lda, tau, c[i1*ldc+i2:], ldc, work, lwork) + } + work[0] = float64(lworkopt) +} diff --git a/lapack/native/dormhr.go b/lapack/native/dormhr.go new file mode 100644 index 00000000..7349a873 --- /dev/null +++ b/lapack/native/dormhr.go @@ -0,0 +1,121 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dormhr multiplies an m×n general matrix C with an nq×nq orthogonal matrix Q +// Q * C, if side == blas.Left and trans == blas.NoTrans, +// Q^T * C, if side == blas.Left and trans == blas.Trans, +// C * Q, if side == blas.Right and trans == blas.NoTrans, +// C * Q^T, if side == blas.Right and trans == blas.Trans, +// where nq == m if side == blas.Left and nq == n if side == blas.Right. +// +// Q is defined implicitly as the product of ihi-ilo elementary reflectors, as +// returned by Dgehrd: +// Q = H_{ilo} H_{ilo+1} ... H_{ihi-1}. +// Q is equal to the identity matrix except in the submatrix +// Q[ilo+1:ihi+1,ilo+1:ihi+1]. +// +// ilo and ihi must have the same values as in the previous call of Dgehrd. It +// must hold that +// 0 <= ilo <= ihi < m, if m > 0 and side == blas.Left, +// ilo = 0 and ihi = -1, if m = 0 and side == blas.Left, +// 0 <= ilo <= ihi < n, if n > 0 and side == blas.Right, +// ilo = 0 and ihi = -1, if n = 0 and side == blas.Right. +// +// a and lda represent an m×m matrix if side == blas.Left and an n×n matrix if +// side == blas.Right. The matrix contains vectors which define the elementary +// reflectors, as returned by Dgehrd. +// +// tau contains the scalar factors of the elementary reflectors, as returned by +// Dgehrd. tau must have length m-1 if side == blas.Left and n-1 if side == +// blas.Right. +// +// c and ldc represent the m×n matrix C. On return, c is overwritten by the +// product with Q. +// +// work must have length at least max(1,lwork), and lwork must be at least +// max(1,n), if side == blas.Left, and max(1,m), if side == blas.Right. For +// optimum performance lwork should be at least n*nb if side == blas.Left and +// m*nb if side == blas.Right, where nb is the optimal block size. On return, +// work[0] will contain the optimal value of lwork. +// +// If lwork == -1, instead of performing Dormhr, only the optimal value of lwork +// will be stored in work[0]. +// +// If any requirement on input sizes is not met, Dormhr will panic. +// +// Dormhr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dormhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + var ( + nq int // The order of Q. + nw int // The minimum length of work. + ) + switch side { + case blas.Left: + nq = m + nw = n + case blas.Right: + nq = n + nw = m + default: + panic(badSide) + } + switch { + case trans != blas.NoTrans && trans != blas.Trans: + panic(badTrans) + case ilo < 0 || max(1, nq) <= ilo: + panic(badIlo) + case ihi < min(ilo, nq-1) || nq <= ihi: + panic(badIhi) + case lwork < max(1, nw) && lwork != -1: + panic(badWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + if lwork != -1 { + checkMatrix(m, n, c, ldc) + checkMatrix(nq, nq, a, lda) + if len(tau) != nq-1 && nq > 0 { + panic(badTau) + } + + } + + nh := ihi - ilo + var nb int + if side == blas.Left { + opts := "LN" + if trans == blas.Trans { + opts = "LT" + } + nb = impl.Ilaenv(1, "DORMQR", opts, nh, n, nh, -1) + } else { + opts := "RN" + if trans == blas.Trans { + opts = "RT" + } + nb = impl.Ilaenv(1, "DORMQR", opts, m, nh, nh, -1) + } + lwkopt := max(1, nw) * nb + if lwork == -1 { + work[0] = float64(lwkopt) + return + } + + if m == 0 || n == 0 || nh == 0 { + work[0] = 1 + return + } + if side == blas.Left { + impl.Dormqr(side, trans, nh, n, nh, a[(ilo+1)*lda+ilo:], lda, + tau[ilo:ihi], c[(ilo+1)*ldc:], ldc, work, lwork) + } else { + impl.Dormqr(side, trans, m, nh, nh, a[(ilo+1)*lda+ilo:], lda, + tau[ilo:ihi], c[ilo+1:], ldc, work, lwork) + } + work[0] = float64(lwkopt) +} diff --git a/lapack/native/dorml2.go b/lapack/native/dorml2.go new file mode 100644 index 00000000..1cfde1ab --- /dev/null +++ b/lapack/native/dorml2.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dorml2 multiplies a general matrix C by an orthogonal matrix from an LQ factorization +// determined by Dgelqf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, a is a matrix of side k×m, and if side == blas.Right +// a is of size k×n. +// +// tau contains the Householder factors and is of length at least k and this function will +// panic otherwise. +// +// work is temporary storage of length at least n if side == blas.Left +// and at least m if side == blas.Right and this function will panic otherwise. +// +// Dorml2 is an internal routine. It is exported for testing purposes. +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) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + + left := side == blas.Left + notran := trans == blas.NoTrans + if left { + checkMatrix(k, m, a, lda) + if len(work) < n { + panic(badWork) + } + } else { + checkMatrix(k, n, a, lda) + if len(work) < m { + panic(badWork) + } + } + checkMatrix(m, n, c, ldc) + if m == 0 || n == 0 || k == 0 { + return + } + switch { + case left && notran: + for i := 0; i < k; i++ { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work) + a[i*lda+i] = aii + } + + case left && !notran: + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work) + a[i*lda+i] = aii + } + + case !left && notran: + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work) + a[i*lda+i] = aii + } + + case !left && !notran: + for i := 0; i < k; i++ { + aii := a[i*lda+i] + a[i*lda+i] = 1 + impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work) + a[i*lda+i] = aii + } + } +} diff --git a/lapack/native/dormlq.go b/lapack/native/dormlq.go new file mode 100644 index 00000000..d69f517d --- /dev/null +++ b/lapack/native/dormlq.go @@ -0,0 +1,159 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dormlq multiplies the matrix C by the orthogonal matrix Q defined by the +// slices a and tau. A and tau are as returned from Dgelqf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, A is a matrix of side k×m, and if side == blas.Right +// A is of size k×n. This uses a blocked algorithm. +// +// work is temporary storage, and lwork specifies the usable memory length. +// At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right, +// and this function will panic otherwise. +// Dormlq uses a block algorithm, but the block size is limited +// by the temporary space available. If lwork == -1, instead of performing Dormlq, +// the optimal work length will be stored into work[0]. +// +// tau contains the Householder scales and must have length at least k, and +// this function will panic otherwise. +func (impl Implementation) Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + left := side == blas.Left + if left { + checkMatrix(k, m, a, lda) + } else { + checkMatrix(k, n, a, lda) + } + checkMatrix(m, n, c, ldc) + if len(tau) < k { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + nw := m + if left { + nw = n + } + if lwork < max(1, nw) && lwork != -1 { + panic(badWork) + } + + if m == 0 || n == 0 || k == 0 { + work[0] = 1 + return + } + + const ( + nbmax = 64 + ldt = nbmax + tsize = nbmax * ldt + ) + opts := string(side) + string(trans) + nb := min(nbmax, impl.Ilaenv(1, "DORMLQ", opts, m, n, k, -1)) + lworkopt := max(1, nw)*nb + tsize + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + + nbmin := 2 + if 1 < nb && nb < k { + iws := nw*nb + tsize + if lwork < iws { + nb = (lwork - tsize) / nw + nbmin = max(2, impl.Ilaenv(2, "DORMLQ", opts, m, n, k, -1)) + } + } + if nb < nbmin || k <= nb { + // Call unblocked code. + impl.Dorml2(side, trans, m, n, k, a, lda, tau, c, ldc, work) + work[0] = float64(lworkopt) + return + } + + t := work[:tsize] + wrk := work[tsize:] + ldwrk := nb + + notran := trans == blas.NoTrans + transt := blas.NoTrans + if notran { + transt = blas.Trans + } + + switch { + case left && notran: + for i := 0; i < k; i += nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.RowWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + t, ldt) + impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m-i, n, ib, + a[i*lda+i:], lda, + t, ldt, + c[i*ldc:], ldc, + wrk, ldwrk) + } + + case left && !notran: + for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.RowWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + t, ldt) + impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m-i, n, ib, + a[i*lda+i:], lda, + t, ldt, + c[i*ldc:], ldc, + wrk, ldwrk) + } + + case !left && notran: + for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + t, ldt) + impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m, n-i, ib, + a[i*lda+i:], lda, + t, ldt, + c[i:], ldc, + wrk, ldwrk) + } + + case !left && !notran: + for i := 0; i < k; i += nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + t, ldt) + impl.Dlarfb(side, transt, lapack.Forward, lapack.RowWise, m, n-i, ib, + a[i*lda+i:], lda, + t, ldt, + c[i:], ldc, + wrk, ldwrk) + } + } + work[0] = float64(lworkopt) +} diff --git a/lapack/native/dormqr.go b/lapack/native/dormqr.go new file mode 100644 index 00000000..2f0c2316 --- /dev/null +++ b/lapack/native/dormqr.go @@ -0,0 +1,167 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +// Dormqr multiplies an m×n matrix C by an orthogonal matrix Q as +// C = Q * C, if side == blas.Left and trans == blas.NoTrans, +// C = Q^T * C, if side == blas.Left and trans == blas.Trans, +// C = C * Q, if side == blas.Right and trans == blas.NoTrans, +// C = C * Q^T, if side == blas.Right and trans == blas.Trans, +// where Q is defined as the product of k elementary reflectors +// Q = H_0 * H_1 * ... * H_{k-1}. +// +// If side == blas.Left, A is an m×k matrix and 0 <= k <= m. +// If side == blas.Right, A is an n×k matrix and 0 <= k <= n. +// The ith column of A contains the vector which defines the elementary +// reflector H_i and tau[i] contains its scalar factor. tau must have length k +// and Dormqr will panic otherwise. Dgeqrf returns A and tau in the required +// form. +// +// work must have length at least max(1,lwork), and lwork must be at least n if +// side == blas.Left and at least m if side == blas.Right, otherwise Dormqr will +// panic. +// +// work is temporary storage, and lwork specifies the usable memory length. At +// minimum, lwork >= m if side == blas.Left and lwork >= n if side == +// blas.Right, and this function will panic otherwise. Larger values of lwork +// will generally give better performance. On return, work[0] will contain the +// optimal value of lwork. +// +// If lwork is -1, instead of performing Dormqr, the optimal workspace size will +// be stored into work[0]. +func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { + var nq, nw int + switch side { + default: + panic(badSide) + case blas.Left: + nq = m + nw = n + case blas.Right: + nq = n + nw = m + } + switch { + case trans != blas.NoTrans && trans != blas.Trans: + panic(badTrans) + case m < 0 || n < 0: + panic(negDimension) + case k < 0 || nq < k: + panic("lapack: invalid value of k") + case len(work) < lwork: + panic(shortWork) + case lwork < max(1, nw) && lwork != -1: + panic(badWork) + } + if lwork != -1 { + checkMatrix(nq, k, a, lda) + checkMatrix(m, n, c, ldc) + if len(tau) != k { + panic(badTau) + } + } + + if m == 0 || n == 0 || k == 0 { + work[0] = 1 + return + } + + const ( + nbmax = 64 + ldt = nbmax + tsize = nbmax * ldt + ) + opts := string(side) + string(trans) + nb := min(nbmax, impl.Ilaenv(1, "DORMQR", opts, m, n, k, -1)) + lworkopt := max(1, nw)*nb + tsize + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + + nbmin := 2 + if 1 < nb && nb < k { + if lwork < nw*nb+tsize { + nb = (lwork - tsize) / nw + nbmin = max(2, impl.Ilaenv(2, "DORMQR", opts, m, n, k, -1)) + } + } + + if nb < nbmin || k <= nb { + // Call unblocked code. + impl.Dorm2r(side, trans, m, n, k, a, lda, tau, c, ldc, work) + work[0] = float64(lworkopt) + return + } + + var ( + ldwork = nb + left = side == blas.Left + notran = trans == blas.NoTrans + ) + switch { + case left && notran: + for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + work[:tsize], ldt) + impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m-i, n, ib, + a[i*lda+i:], lda, + work[:tsize], ldt, + c[i*ldc:], ldc, + work[tsize:], ldwork) + } + + case left && !notran: + for i := 0; i < k; i += nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, + a[i*lda+i:], lda, + tau[i:], + work[:tsize], ldt) + impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m-i, n, ib, + a[i*lda+i:], lda, + work[:tsize], ldt, + c[i*ldc:], ldc, + work[tsize:], ldwork) + } + + case !left && notran: + for i := 0; i < k; i += nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + work[:tsize], ldt) + impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m, n-i, ib, + a[i*lda+i:], lda, + work[:tsize], ldt, + c[i:], ldc, + work[tsize:], ldwork) + } + + case !left && !notran: + for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { + ib := min(nb, k-i) + impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib, + a[i*lda+i:], lda, + tau[i:], + work[:tsize], ldt) + impl.Dlarfb(side, trans, lapack.Forward, lapack.ColumnWise, m, n-i, ib, + a[i*lda+i:], lda, + work[:tsize], ldt, + c[i:], ldc, + work[tsize:], ldwork) + } + } + work[0] = float64(lworkopt) +} diff --git a/lapack/native/dormr2.go b/lapack/native/dormr2.go new file mode 100644 index 00000000..a4e97c20 --- /dev/null +++ b/lapack/native/dormr2.go @@ -0,0 +1,93 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/blas" + +// Dormr2 multiplies a general matrix C by an orthogonal matrix from a RQ factorization +// determined by Dgerqf. +// C = Q * C if side == blas.Left and trans == blas.NoTrans +// C = Q^T * C if side == blas.Left and trans == blas.Trans +// C = C * Q if side == blas.Right and trans == blas.NoTrans +// C = C * Q^T if side == blas.Right and trans == blas.Trans +// If side == blas.Left, a is a matrix of size k×m, and if side == blas.Right +// a is of size k×n. +// +// tau contains the Householder factors and is of length at least k and this function +// will panic otherwise. +// +// work is temporary storage of length at least n if side == blas.Left +// and at least m if side == blas.Right and this function will panic otherwise. +// +// Dormr2 is an internal routine. It is exported for testing purposes. +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) { + if side != blas.Left && side != blas.Right { + panic(badSide) + } + if trans != blas.Trans && trans != blas.NoTrans { + panic(badTrans) + } + + left := side == blas.Left + notran := trans == blas.NoTrans + if left { + if k > m { + panic(kGTM) + } + checkMatrix(k, m, a, lda) + if len(work) < n { + panic(badWork) + } + } else { + if k > n { + panic(kGTN) + } + checkMatrix(k, n, a, lda) + if len(work) < m { + panic(badWork) + } + } + if len(tau) < k { + panic(badTau) + } + checkMatrix(m, n, c, ldc) + + if m == 0 || n == 0 || k == 0 { + return + } + if left { + if notran { + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+(m-k+i)] + a[i*lda+(m-k+i)] = 1 + impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work) + a[i*lda+(m-k+i)] = aii + } + return + } + for i := 0; i < k; i++ { + aii := a[i*lda+(m-k+i)] + a[i*lda+(m-k+i)] = 1 + impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work) + a[i*lda+(m-k+i)] = aii + } + return + } + if notran { + for i := 0; i < k; i++ { + aii := a[i*lda+(n-k+i)] + a[i*lda+(n-k+i)] = 1 + impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work) + a[i*lda+(n-k+i)] = aii + } + return + } + for i := k - 1; i >= 0; i-- { + aii := a[i*lda+(n-k+i)] + a[i*lda+(n-k+i)] = 1 + impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work) + a[i*lda+(n-k+i)] = aii + } +} diff --git a/lapack/native/dpocon.go b/lapack/native/dpocon.go new file mode 100644 index 00000000..b0e0b407 --- /dev/null +++ b/lapack/native/dpocon.go @@ -0,0 +1,76 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dpocon estimates the reciprocal of the condition number of a positive-definite +// matrix A given the Cholesky decomposition of A. The condition number computed +// is based on the 1-norm and the ∞-norm. +// +// anorm is the 1-norm and the ∞-norm of the original matrix A. +// +// work is a temporary data slice of length at least 3*n and Dpocon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Dpocon will panic otherwise. +func (impl Implementation) Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { + checkMatrix(n, n, a, lda) + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if len(work) < 3*n { + panic(badWork) + } + if len(iwork) < n { + panic(badWork) + } + var rcond float64 + if n == 0 { + return 1 + } + if anorm == 0 { + return rcond + } + + bi := blas64.Implementation() + var ainvnm float64 + smlnum := dlamchS + upper := uplo == blas.Upper + var kase int + var normin bool + isave := new([3]int) + var sl, su float64 + for { + ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) + if kase == 0 { + if ainvnm != 0 { + rcond = (1 / ainvnm) / anorm + } + return rcond + } + if upper { + sl = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) + normin = true + su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) + } else { + sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) + normin = true + su = impl.Dlatrs(blas.Lower, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) + } + scale := sl * su + if scale != 1 { + ix := bi.Idamax(n, work, 1) + if scale == 0 || scale < math.Abs(work[ix])*smlnum { + return rcond + } + impl.Drscl(n, scale, work, 1) + } + } +} diff --git a/lapack/native/dpotf2.go b/lapack/native/dpotf2.go new file mode 100644 index 00000000..bf923665 --- /dev/null +++ b/lapack/native/dpotf2.go @@ -0,0 +1,72 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dpotf2 computes the Cholesky decomposition of the symmetric positive definite +// matrix a. If ul == blas.Upper, then a is stored as an upper-triangular matrix, +// and a = U^T U is stored in place into a. If ul == blas.Lower, then a = L L^T +// is computed and stored in-place into a. If a is not positive definite, false +// is returned. This is the unblocked version of the algorithm. +// +// Dpotf2 is an internal routine. It is exported for testing purposes. +func (Implementation) Dpotf2(ul blas.Uplo, n int, a []float64, lda int) (ok bool) { + if ul != blas.Upper && ul != blas.Lower { + panic(badUplo) + } + checkMatrix(n, n, a, lda) + + if n == 0 { + return true + } + + bi := blas64.Implementation() + if ul == blas.Upper { + for j := 0; j < n; j++ { + ajj := a[j*lda+j] + if j != 0 { + ajj -= bi.Ddot(j, a[j:], lda, a[j:], lda) + } + if ajj <= 0 || math.IsNaN(ajj) { + a[j*lda+j] = ajj + return false + } + ajj = math.Sqrt(ajj) + a[j*lda+j] = ajj + if j < n-1 { + bi.Dgemv(blas.Trans, j, n-j-1, + -1, a[j+1:], lda, a[j:], lda, + 1, a[j*lda+j+1:], 1) + bi.Dscal(n-j-1, 1/ajj, a[j*lda+j+1:], 1) + } + } + return true + } + for j := 0; j < n; j++ { + ajj := a[j*lda+j] + if j != 0 { + ajj -= bi.Ddot(j, a[j*lda:], 1, a[j*lda:], 1) + } + if ajj <= 0 || math.IsNaN(ajj) { + a[j*lda+j] = ajj + return false + } + ajj = math.Sqrt(ajj) + a[j*lda+j] = ajj + if j < n-1 { + bi.Dgemv(blas.NoTrans, n-j-1, j, + -1, a[(j+1)*lda:], lda, a[j*lda:], 1, + 1, a[(j+1)*lda+j:], lda) + bi.Dscal(n-j-1, 1/ajj, a[(j+1)*lda+j:], lda) + } + } + return true +} diff --git a/lapack/native/dpotrf.go b/lapack/native/dpotrf.go new file mode 100644 index 00000000..32259dea --- /dev/null +++ b/lapack/native/dpotrf.go @@ -0,0 +1,72 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dpotrf computes the Cholesky decomposition of the symmetric positive definite +// matrix a. If ul == blas.Upper, then a is stored as an upper-triangular matrix, +// and a = U^T U is stored in place into a. If ul == blas.Lower, then a = L L^T +// is computed and stored in-place into a. If a is not positive definite, false +// is returned. This is the blocked version of the algorithm. +func (impl Implementation) Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) { + if ul != blas.Upper && ul != blas.Lower { + panic(badUplo) + } + checkMatrix(n, n, a, lda) + + if n == 0 { + return true + } + + nb := impl.Ilaenv(1, "DPOTRF", string(ul), n, -1, -1, -1) + if nb <= 1 || n <= nb { + return impl.Dpotf2(ul, n, a, lda) + } + bi := blas64.Implementation() + if ul == blas.Upper { + for j := 0; j < n; j += nb { + jb := min(nb, n-j) + bi.Dsyrk(blas.Upper, blas.Trans, jb, j, + -1, a[j:], lda, + 1, a[j*lda+j:], lda) + ok = impl.Dpotf2(blas.Upper, jb, a[j*lda+j:], lda) + if !ok { + return ok + } + if j+jb < n { + bi.Dgemm(blas.Trans, blas.NoTrans, jb, n-j-jb, j, + -1, a[j:], lda, a[j+jb:], lda, + 1, a[j*lda+j+jb:], lda) + bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, jb, n-j-jb, + 1, a[j*lda+j:], lda, + a[j*lda+j+jb:], lda) + } + } + return true + } + for j := 0; j < n; j += nb { + jb := min(nb, n-j) + bi.Dsyrk(blas.Lower, blas.NoTrans, jb, j, + -1, a[j*lda:], lda, + 1, a[j*lda+j:], lda) + ok := impl.Dpotf2(blas.Lower, jb, a[j*lda+j:], lda) + if !ok { + return ok + } + if j+jb < n { + bi.Dgemm(blas.NoTrans, blas.Trans, n-j-jb, jb, j, + -1, a[(j+jb)*lda:], lda, a[j*lda:], lda, + 1, a[(j+jb)*lda+j:], lda) + bi.Dtrsm(blas.Right, blas.Lower, blas.Trans, blas.NonUnit, n-j-jb, jb, + 1, a[j*lda+j:], lda, + a[(j+jb)*lda+j:], lda) + } + } + return true +} diff --git a/lapack/native/drscl.go b/lapack/native/drscl.go new file mode 100644 index 00000000..a10b52db --- /dev/null +++ b/lapack/native/drscl.go @@ -0,0 +1,47 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas/blas64" +) + +// Drscl multiplies the vector x by 1/a being careful to avoid overflow or +// underflow where possible. +// +// Drscl is an internal routine. It is exported for testing purposes. +func (impl Implementation) Drscl(n int, a float64, x []float64, incX int) { + checkVector(n, x, incX) + bi := blas64.Implementation() + cden := a + cnum := 1.0 + smlnum := dlamchS + bignum := 1 / smlnum + for { + cden1 := cden * smlnum + cnum1 := cnum / bignum + var mul float64 + var done bool + switch { + case cnum != 0 && math.Abs(cden1) > math.Abs(cnum): + mul = smlnum + done = false + cden = cden1 + case math.Abs(cnum1) > math.Abs(cden): + mul = bignum + done = false + cnum = cnum1 + default: + mul = cnum / cden + done = true + } + bi.Dscal(n, mul, x, incX) + if done { + break + } + } +} diff --git a/lapack/native/dsteqr.go b/lapack/native/dsteqr.go new file mode 100644 index 00000000..3b31d547 --- /dev/null +++ b/lapack/native/dsteqr.go @@ -0,0 +1,374 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dsteqr computes the eigenvalues and optionally the eigenvectors of a symmetric +// tridiagonal matrix using the implicit QL or QR method. The eigenvectors of a +// full or band symmetric matrix can also be found if Dsytrd, Dsptrd, or Dsbtrd +// have been used to reduce this matrix to tridiagonal form. +// +// d, on entry, contains the diagonal elements of the tridiagonal matrix. On exit, +// d contains the eigenvalues in ascending order. d must have length n and +// Dsteqr will panic otherwise. +// +// e, on entry, contains the off-diagonal elements of the tridiagonal matrix on +// entry, and is overwritten during the call to Dsteqr. e must have length n-1 and +// Dsteqr will panic otherwise. +// +// z, on entry, contains the n×n orthogonal matrix used in the reduction to +// tridiagonal form if compz == lapack.OriginalEV. On exit, if +// compz == lapack.OriginalEV, z contains the orthonormal eigenvectors of the +// original symmetric matrix, and if compz == lapack.TridiagEV, z contains the +// orthonormal eigenvectors of the symmetric tridiagonal matrix. z is not used +// if compz == lapack.None. +// +// work must have length at least max(1, 2*n-2) if the eigenvectors are computed, +// and Dsteqr will panic otherwise. +// +// Dsteqr is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsteqr(compz lapack.EVComp, n int, d, e, z []float64, ldz int, work []float64) (ok bool) { + if n < 0 { + panic(nLT0) + } + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if compz != lapack.None && compz != lapack.TridiagEV && compz != lapack.OriginalEV { + panic(badEVComp) + } + if compz != lapack.None { + if len(work) < max(1, 2*n-2) { + panic(badWork) + } + checkMatrix(n, n, z, ldz) + } + + var icompz int + if compz == lapack.OriginalEV { + icompz = 1 + } else if compz == lapack.TridiagEV { + icompz = 2 + } + + if n == 0 { + return true + } + if n == 1 { + if icompz == 2 { + z[0] = 1 + } + return true + } + + bi := blas64.Implementation() + + eps := dlamchE + eps2 := eps * eps + safmin := dlamchS + safmax := 1 / safmin + ssfmax := math.Sqrt(safmax) / 3 + ssfmin := math.Sqrt(safmin) / eps2 + + // Compute the eigenvalues and eigenvectors of the tridiagonal matrix. + if icompz == 2 { + impl.Dlaset(blas.All, n, n, 0, 1, z, ldz) + } + const maxit = 30 + nmaxit := n * maxit + + jtot := 0 + + // Determine where the matrix splits and choose QL or QR iteration for each + // block, according to whether top or bottom diagonal element is smaller. + l1 := 0 + nm1 := n - 1 + + type scaletype int + const ( + none scaletype = iota + down + up + ) + var iscale scaletype + + for { + if l1 > n-1 { + // Order eigenvalues and eigenvectors. + if icompz == 0 { + impl.Dlasrt(lapack.SortIncreasing, n, d) + } else { + // TODO(btracey): Consider replacing this sort with a call to sort.Sort. + for ii := 1; ii < n; ii++ { + i := ii - 1 + k := i + p := d[i] + for j := ii; j < n; j++ { + if d[j] < p { + k = j + p = d[j] + } + } + if k != i { + d[k] = d[i] + d[i] = p + bi.Dswap(n, z[i:], ldz, z[k:], ldz) + } + } + } + return true + } + if l1 > 0 { + e[l1-1] = 0 + } + var m int + if l1 <= nm1 { + for m = l1; m < nm1; m++ { + test := math.Abs(e[m]) + if test == 0 { + break + } + if test <= (math.Sqrt(math.Abs(d[m]))*math.Sqrt(math.Abs(d[m+1])))*eps { + e[m] = 0 + break + } + } + } + l := l1 + lsv := l + lend := m + lendsv := lend + l1 = m + 1 + if lend == l { + continue + } + + // Scale submatrix in rows and columns L to Lend + anorm := impl.Dlanst(lapack.MaxAbs, lend-l+1, d[l:], e[l:]) + switch { + case anorm == 0: + continue + case anorm > ssfmax: + iscale = down + // Pretend that d and e are matrices with 1 column. + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l+1, 1, d[l:], 1) + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l, 1, e[l:], 1) + case anorm < ssfmin: + iscale = up + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l+1, 1, d[l:], 1) + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l, 1, e[l:], 1) + } + + // Choose between QL and QR. + if math.Abs(d[lend]) < math.Abs(d[l]) { + lend = lsv + l = lendsv + } + if lend > l { + // QL Iteration. Look for small subdiagonal element. + for { + if l != lend { + for m = l; m < lend; m++ { + v := math.Abs(e[m]) + if v*v <= (eps2*math.Abs(d[m]))*math.Abs(d[m+1])+safmin { + break + } + } + } else { + m = lend + } + if m < lend { + e[m] = 0 + } + p := d[l] + if m == l { + // Eigenvalue found. + l++ + if l > lend { + break + } + continue + } + + // If remaining matrix is 2×2, use Dlae2 to compute its eigensystem. + if m == l+1 { + if icompz > 0 { + d[l], d[l+1], work[l], work[n-1+l] = impl.Dlaev2(d[l], e[l], d[l+1]) + impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, + n, 2, work[l:], work[n-1+l:], z[l:], ldz) + } else { + d[l], d[l+1] = impl.Dlae2(d[l], e[l], d[l+1]) + } + e[l] = 0 + l += 2 + if l > lend { + break + } + continue + } + + if jtot == nmaxit { + break + } + jtot++ + + // Form shift + g := (d[l+1] - p) / (2 * e[l]) + r := impl.Dlapy2(g, 1) + g = d[m] - p + e[l]/(g+math.Copysign(r, g)) + s := 1.0 + c := 1.0 + p = 0.0 + + // Inner loop + for i := m - 1; i >= l; i-- { + f := s * e[i] + b := c * e[i] + c, s, r = impl.Dlartg(g, f) + if i != m-1 { + e[i+1] = r + } + g = d[i+1] - p + r = (d[i]-g)*s + 2*c*b + p = s * r + d[i+1] = g + p + g = c*r - b + + // If eigenvectors are desired, then save rotations. + if icompz > 0 { + work[i] = c + work[n-1+i] = -s + } + } + // If eigenvectors are desired, then apply saved rotations. + if icompz > 0 { + mm := m - l + 1 + impl.Dlasr(blas.Right, lapack.Variable, lapack.Backward, + n, mm, work[l:], work[n-1+l:], z[l:], ldz) + } + d[l] -= p + e[l] = g + } + } else { + // QR Iteration. + // Look for small superdiagonal element. + for { + if l != lend { + for m = l; m > lend; m-- { + v := math.Abs(e[m-1]) + if v*v <= (eps2*math.Abs(d[m])*math.Abs(d[m-1]) + safmin) { + break + } + } + } else { + m = lend + } + if m > lend { + e[m-1] = 0 + } + p := d[l] + if m == l { + // Eigenvalue found + l-- + if l < lend { + break + } + continue + } + + // If remaining matrix is 2×2, use Dlae2 to compute its eigenvalues. + if m == l-1 { + if icompz > 0 { + d[l-1], d[l], work[m], work[n-1+m] = impl.Dlaev2(d[l-1], e[l-1], d[l]) + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, + n, 2, work[m:], work[n-1+m:], z[l-1:], ldz) + } else { + d[l-1], d[l] = impl.Dlae2(d[l-1], e[l-1], d[l]) + } + e[l-1] = 0 + l -= 2 + if l < lend { + break + } + continue + } + if jtot == nmaxit { + break + } + jtot++ + + // Form shift. + g := (d[l-1] - p) / (2 * e[l-1]) + r := impl.Dlapy2(g, 1) + g = d[m] - p + (e[l-1])/(g+math.Copysign(r, g)) + s := 1.0 + c := 1.0 + p = 0.0 + + // Inner loop. + for i := m; i < l; i++ { + f := s * e[i] + b := c * e[i] + c, s, r = impl.Dlartg(g, f) + if i != m { + e[i-1] = r + } + g = d[i] - p + r = (d[i+1]-g)*s + 2*c*b + p = s * r + d[i] = g + p + g = c*r - b + + // If eigenvectors are desired, then save rotations. + if icompz > 0 { + work[i] = c + work[n-1+i] = s + } + } + + // If eigenvectors are desired, then apply saved rotations. + if icompz > 0 { + mm := l - m + 1 + impl.Dlasr(blas.Right, lapack.Variable, lapack.Forward, + n, mm, work[m:], work[n-1+m:], z[m:], ldz) + } + d[l] -= p + e[l-1] = g + } + } + + // Undo scaling if necessary. + switch iscale { + case down: + // Pretend that d and e are matrices with 1 column. + impl.Dlascl(lapack.General, 0, 0, ssfmax, anorm, lendsv-lsv+1, 1, d[lsv:], 1) + impl.Dlascl(lapack.General, 0, 0, ssfmax, anorm, lendsv-lsv, 1, e[lsv:], 1) + case up: + impl.Dlascl(lapack.General, 0, 0, ssfmin, anorm, lendsv-lsv+1, 1, d[lsv:], 1) + impl.Dlascl(lapack.General, 0, 0, ssfmin, anorm, lendsv-lsv, 1, e[lsv:], 1) + } + + // Check for no convergence to an eigenvalue after a total of n*maxit iterations. + if jtot >= nmaxit { + break + } + } + for i := 0; i < n-1; i++ { + if e[i] != 0 { + return false + } + } + return true +} diff --git a/lapack/native/dsterf.go b/lapack/native/dsterf.go new file mode 100644 index 00000000..860b969f --- /dev/null +++ b/lapack/native/dsterf.go @@ -0,0 +1,278 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/lapack" +) + +// Dsterf computes all eigenvalues of a symmetric tridiagonal matrix using the +// Pal-Walker-Kahan variant of the QL or QR algorithm. +// +// d contains the diagonal elements of the tridiagonal matrix on entry, and +// contains the eigenvalues in ascending order on exit. d must have length at +// least n, or Dsterf will panic. +// +// e contains the off-diagonal elements of the tridiagonal matrix on entry, and is +// overwritten during the call to Dsterf. e must have length of at least n-1 or +// Dsterf will panic. +// +// Dsterf is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsterf(n int, d, e []float64) (ok bool) { + if n < 0 { + panic(nLT0) + } + if n == 0 { + return true + } + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + + const ( + none = 0 // The values are not scaled. + down = 1 // The values are scaled below ssfmax threshold. + up = 2 // The values are scaled below ssfmin threshold. + ) + + // Determine the unit roundoff for this environment. + eps := dlamchE + eps2 := eps * eps + safmin := dlamchS + safmax := 1 / safmin + ssfmax := math.Sqrt(safmax) / 3 + ssfmin := math.Sqrt(safmin) / eps2 + + // Compute the eigenvalues of the tridiagonal matrix. + maxit := 30 + nmaxit := n * maxit + jtot := 0 + + l1 := 0 + + for { + if l1 > n-1 { + impl.Dlasrt(lapack.SortIncreasing, n, d) + return true + } + if l1 > 0 { + e[l1-1] = 0 + } + var m int + for m = l1; m < n-1; m++ { + if math.Abs(e[m]) <= math.Sqrt(math.Abs(d[m]))*math.Sqrt(math.Abs(d[m+1]))*eps { + e[m] = 0 + break + } + } + + l := l1 + lsv := l + lend := m + lendsv := lend + l1 = m + 1 + if lend == 0 { + continue + } + + // Scale submatrix in rows and columns l to lend. + anorm := impl.Dlanst(lapack.MaxAbs, lend-l+1, d[l:], e[l:]) + iscale := none + if anorm == 0 { + continue + } + if anorm > ssfmax { + iscale = down + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l+1, 1, d[l:], n) + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmax, lend-l, 1, e[l:], n) + } else if anorm < ssfmin { + iscale = up + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l+1, 1, d[l:], n) + impl.Dlascl(lapack.General, 0, 0, anorm, ssfmin, lend-l, 1, e[l:], n) + } + + el := e[l:lend] + for i, v := range el { + el[i] *= v + } + + // Choose between QL and QR iteration. + if math.Abs(d[lend]) < math.Abs(d[l]) { + lend = lsv + l = lendsv + } + if lend >= l { + // QL Iteration. + // Look for small sub-diagonal element. + for { + if l != lend { + for m = l; m < lend; m++ { + if math.Abs(e[m]) <= eps2*(math.Abs(d[m]*d[m+1])) { + break + } + } + } else { + m = lend + } + if m < lend { + e[m] = 0 + } + p := d[l] + if m == l { + // Eigenvalue found. + l++ + if l > lend { + break + } + continue + } + // If remaining matrix is 2 by 2, use Dlae2 to compute its eigenvalues. + if m == l+1 { + d[l], d[l+1] = impl.Dlae2(d[l], math.Sqrt(e[l]), d[l+1]) + e[l] = 0 + l += 2 + if l > lend { + break + } + continue + } + if jtot == nmaxit { + break + } + jtot++ + + // Form shift. + rte := math.Sqrt(e[l]) + sigma := (d[l+1] - p) / (2 * rte) + r := impl.Dlapy2(sigma, 1) + sigma = p - (rte / (sigma + math.Copysign(r, sigma))) + + c := 1.0 + s := 0.0 + gamma := d[m] - sigma + p = gamma * gamma + + // Inner loop. + for i := m - 1; i >= l; i-- { + bb := e[i] + r := p + bb + if i != m-1 { + e[i+1] = s * r + } + oldc := c + c = p / r + s = bb / r + oldgam := gamma + alpha := d[i] + gamma = c*(alpha-sigma) - s*oldgam + d[i+1] = oldgam + (alpha - gamma) + if c != 0 { + p = (gamma * gamma) / c + } else { + p = oldc * bb + } + } + e[l] = s * p + d[l] = sigma + gamma + } + } else { + for { + // QR Iteration. + // Look for small super-diagonal element. + for m = l; m > lend; m-- { + if math.Abs(e[m-1]) <= eps2*math.Abs(d[m]*d[m-1]) { + break + } + } + if m > lend { + e[m-1] = 0 + } + p := d[l] + if m == l { + // Eigenvalue found. + l-- + if l < lend { + break + } + continue + } + + // If remaining matrix is 2 by 2, use Dlae2 to compute its eigenvalues. + if m == l-1 { + d[l], d[l-1] = impl.Dlae2(d[l], math.Sqrt(e[l-1]), d[l-1]) + e[l-1] = 0 + l -= 2 + if l < lend { + break + } + continue + } + if jtot == nmaxit { + break + } + jtot++ + + // Form shift. + rte := math.Sqrt(e[l-1]) + sigma := (d[l-1] - p) / (2 * rte) + r := impl.Dlapy2(sigma, 1) + sigma = p - (rte / (sigma + math.Copysign(r, sigma))) + + c := 1.0 + s := 0.0 + gamma := d[m] - sigma + p = gamma * gamma + + // Inner loop. + for i := m; i < l; i++ { + bb := e[i] + r := p + bb + if i != m { + e[i-1] = s * r + } + oldc := c + c = p / r + s = bb / r + oldgam := gamma + alpha := d[i+1] + gamma = c*(alpha-sigma) - s*oldgam + d[i] = oldgam + alpha - gamma + if c != 0 { + p = (gamma * gamma) / c + } else { + p = oldc * bb + } + } + e[l-1] = s * p + d[l] = sigma + gamma + } + } + + // Undo scaling if necessary + switch iscale { + case down: + impl.Dlascl(lapack.General, 0, 0, ssfmax, anorm, lendsv-lsv+1, 1, d[lsv:], n) + case up: + impl.Dlascl(lapack.General, 0, 0, ssfmin, anorm, lendsv-lsv+1, 1, d[lsv:], n) + } + + // Check for no convergence to an eigenvalue after a total of n*maxit iterations. + if jtot >= nmaxit { + break + } + } + for _, v := range e[:n-1] { + if v != 0 { + return false + } + } + impl.Dlasrt(lapack.SortIncreasing, n, d) + return true +} diff --git a/lapack/native/dsyev.go b/lapack/native/dsyev.go new file mode 100644 index 00000000..3eee8a04 --- /dev/null +++ b/lapack/native/dsyev.go @@ -0,0 +1,113 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dsyev computes all eigenvalues and, optionally, the eigenvectors of a real +// symmetric matrix A. +// +// w contains the eigenvalues in ascending order upon return. w must have length +// at least n, and Dsyev will panic otherwise. +// +// On entry, a contains the elements of the symmetric matrix A in the triangular +// portion specified by uplo. If jobz == lapack.ComputeEV a contains the +// orthonormal eigenvectors of A on exit, otherwise on exit the specified +// triangular region is overwritten. +// +// work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= 3*n-1, and Dsyev will panic otherwise. The amount of blocking is +// limited by the usable length. If lwork == -1, instead of computing Dsyev the +// optimal work length is stored into work[0]. +func (impl Implementation) Dsyev(jobz lapack.EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) { + checkMatrix(n, n, a, lda) + upper := uplo == blas.Upper + wantz := jobz == lapack.ComputeEV + var opts string + if upper { + opts = "U" + } else { + opts = "L" + } + nb := impl.Ilaenv(1, "DSYTRD", opts, n, -1, -1, -1) + lworkopt := max(1, (nb+2)*n) + work[0] = float64(lworkopt) + if lwork == -1 { + return + } + if len(work) < lwork { + panic(badWork) + } + if lwork < 3*n-1 { + panic(badWork) + } + if n == 0 { + return true + } + if n == 1 { + w[0] = a[0] + work[0] = 2 + if wantz { + a[0] = 1 + } + return true + } + safmin := dlamchS + eps := dlamchP + smlnum := safmin / eps + bignum := 1 / smlnum + rmin := math.Sqrt(smlnum) + rmax := math.Sqrt(bignum) + + // Scale matrix to allowable range, if necessary. + anrm := impl.Dlansy(lapack.MaxAbs, uplo, n, a, lda, work) + scaled := false + var sigma float64 + if anrm > 0 && anrm < rmin { + scaled = true + sigma = rmin / anrm + } else if anrm > rmax { + scaled = true + sigma = rmax / anrm + } + if scaled { + kind := lapack.LowerTri + if upper { + kind = lapack.UpperTri + } + impl.Dlascl(kind, 0, 0, 1, sigma, n, n, a, lda) + } + var inde int + indtau := inde + n + indwork := indtau + n + llwork := lwork - indwork + impl.Dsytrd(uplo, n, a, lda, w, work[inde:], work[indtau:], work[indwork:], llwork) + + // For eigenvalues only, call Dsterf. For eigenvectors, first call Dorgtr + // to generate the orthogonal matrix, then call Dsteqr. + if !wantz { + ok = impl.Dsterf(n, w, work[inde:]) + } else { + impl.Dorgtr(uplo, n, a, lda, work[indtau:], work[indwork:], llwork) + ok = impl.Dsteqr(lapack.EVComp(jobz), n, w, work[inde:], a, lda, work[indtau:]) + } + if !ok { + return false + } + + // If the matrix was scaled, then rescale eigenvalues appropriately. + if scaled { + bi := blas64.Implementation() + bi.Dscal(n, 1/sigma, w, 1) + } + work[0] = float64(lworkopt) + return true +} diff --git a/lapack/native/dsytd2.go b/lapack/native/dsytd2.go new file mode 100644 index 00000000..4f0d84d1 --- /dev/null +++ b/lapack/native/dsytd2.go @@ -0,0 +1,123 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dsytd2 reduces a symmetric n×n matrix A to symmetric tridiagonal form T by an +// orthogonal similarity transformation +// Q^T * A * Q = T +// On entry, the matrix is contained in the specified triangle of a. On exit, +// if uplo == blas.Upper, the diagonal and first super-diagonal of a are +// overwritten with the elements of T. The elements above the first super-diagonal +// are overwritten with the the elementary reflectors that are used with the +// elements written to tau in order to construct Q. If uplo == blas.Lower, the +// elements are written in the lower triangular region. +// +// d must have length at least n. e and tau must have length at least n-1. Dsytd2 +// will panic if these sizes are not met. +// +// Q is represented as a product of elementary reflectors. +// If uplo == blas.Upper +// Q = H_{n-2} * ... * H_1 * H_0 +// and if uplo == blas.Lower +// Q = H_0 * H_1 * ... * H_{n-2} +// where +// H_i = I - tau * v * v^T +// where tau is stored in tau[i], and v is stored in a. +// +// If uplo == blas.Upper, v[0:i-1] is stored in A[0:i-1,i+1], v[i] = 1, and +// v[i+1:] = 0. The elements of a are +// [ d e v2 v3 v4] +// [ d e v3 v4] +// [ d e v4] +// [ d e] +// [ d] +// If uplo == blas.Lower, v[0:i+1] = 0, v[i+1] = 1, and v[i+2:] is stored in +// A[i+2:n,i]. +// The elements of a are +// [ d ] +// [ e d ] +// [v1 e d ] +// [v1 v2 e d ] +// [v1 v2 v3 e d] +// +// Dsytd2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsytd2(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau []float64) { + checkMatrix(n, n, a, lda) + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if len(tau) < n-1 { + panic(badTau) + } + if n <= 0 { + return + } + bi := blas64.Implementation() + if uplo == blas.Upper { + // Reduce the upper triangle of A. + for i := n - 2; i >= 0; i-- { + // Generate elementary reflector H_i = I - tau * v * v^T to + // annihilate A[i:i-1, i+1]. + var taui float64 + a[i*lda+i+1], taui = impl.Dlarfg(i+1, a[i*lda+i+1], a[i+1:], lda) + e[i] = a[i*lda+i+1] + if taui != 0 { + // Apply H_i from both sides to A[0:i,0:i]. + a[i*lda+i+1] = 1 + + // Compute x := tau * A * v storing x in tau[0:i]. + bi.Dsymv(uplo, i+1, taui, a, lda, a[i+1:], lda, 0, tau, 1) + + // Compute w := x - 1/2 * tau * (x^T * v) * v. + alpha := -0.5 * taui * bi.Ddot(i+1, tau, 1, a[i+1:], lda) + bi.Daxpy(i+1, alpha, a[i+1:], lda, tau, 1) + + // Apply the transformation as a rank-2 update + // A = A - v * w^T - w * v^T. + bi.Dsyr2(uplo, i+1, -1, a[i+1:], lda, tau, 1, a, lda) + a[i*lda+i+1] = e[i] + } + d[i+1] = a[(i+1)*lda+i+1] + tau[i] = taui + } + d[0] = a[0] + return + } + // Reduce the lower triangle of A. + for i := 0; i < n-1; i++ { + // Generate elementary reflector H_i = I - tau * v * v^T to + // annihilate A[i+2:n, i]. + var taui float64 + a[(i+1)*lda+i], taui = impl.Dlarfg(n-i-1, a[(i+1)*lda+i], a[min(i+2, n-1)*lda+i:], lda) + e[i] = a[(i+1)*lda+i] + if taui != 0 { + // Apply H_i from both sides to A[i+1:n, i+1:n]. + a[(i+1)*lda+i] = 1 + + // Compute x := tau * A * v, storing y in tau[i:n-1]. + bi.Dsymv(uplo, n-i-1, taui, a[(i+1)*lda+i+1:], lda, a[(i+1)*lda+i:], lda, 0, tau[i:], 1) + + // Compute w := x - 1/2 * tau * (x^T * v) * v. + alpha := -0.5 * taui * bi.Ddot(n-i-1, tau[i:], 1, a[(i+1)*lda+i:], lda) + bi.Daxpy(n-i-1, alpha, a[(i+1)*lda+i:], lda, tau[i:], 1) + + // Apply the transformation as a rank-2 update + // A = A - v * w^T - w * v^T. + bi.Dsyr2(uplo, n-i-1, -1, a[(i+1)*lda+i:], lda, tau[i:], 1, a[(i+1)*lda+i+1:], lda) + a[(i+1)*lda+i] = e[i] + } + d[i] = a[i*lda+i] + tau[i] = taui + } + d[n-1] = a[(n-1)*lda+n-1] +} diff --git a/lapack/native/dsytrd.go b/lapack/native/dsytrd.go new file mode 100644 index 00000000..88e74f12 --- /dev/null +++ b/lapack/native/dsytrd.go @@ -0,0 +1,178 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dsytrd reduces a symmetric n×n matrix A to symmetric tridiagonal form by an +// orthogonal similarity transformation +// Q^T * A * Q = T +// where Q is an orthonormal matrix and T is symmetric and tridiagonal. +// +// On entry, a contains the elements of the input matrix in the triangle specified +// by uplo. On exit, the diagonal and sub/super-diagonal are overwritten by the +// corresponding elements of the tridiagonal matrix T. The remaining elements in +// the triangle, along with the array tau, contain the data to construct Q as +// the product of elementary reflectors. +// +// If uplo == blas.Upper, Q is constructed with +// Q = H_{n-2} * ... * H_1 * H_0 +// where +// H_i = I - tau_i * v * v^T +// v is constructed as v[i+1:n] = 0, v[i] = 1, v[0:i-1] is stored in A[0:i-1, i+1]. +// The elements of A are +// [ d e v1 v2 v3] +// [ d e v2 v3] +// [ d e v3] +// [ d e] +// [ e] +// +// If uplo == blas.Lower, Q is constructed with +// Q = H_0 * H_1 * ... * H_{n-2} +// where +// H_i = I - tau_i * v * v^T +// v is constructed as v[0:i+1] = 0, v[i+1] = 1, v[i+2:n] is stored in A[i+2:n, i]. +// The elements of A are +// [ d ] +// [ e d ] +// [v0 e d ] +// [v0 v1 e d ] +// [v0 v1 v2 e d] +// +// d must have length n, and e and tau must have length n-1. Dsytrd will panic if +// these conditions are not met. +// +// work is temporary storage, and lwork specifies the usable memory length. At minimum, +// lwork >= 1, and Dsytrd will panic otherwise. The amount of blocking is +// limited by the usable length. +// If lwork == -1, instead of computing Dsytrd the optimal work length is stored +// into work[0]. +// +// Dsytrd is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dsytrd(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau, work []float64, lwork int) { + checkMatrix(n, n, a, lda) + if len(d) < n { + panic(badD) + } + if len(e) < n-1 { + panic(badE) + } + if len(tau) < n-1 { + panic(badTau) + } + if len(work) < lwork { + panic(shortWork) + } + if lwork != -1 && lwork < 1 { + panic(badWork) + } + + var upper bool + var opts string + switch uplo { + case blas.Upper: + upper = true + opts = "U" + case blas.Lower: + opts = "L" + default: + panic(badUplo) + } + + if n == 0 { + work[0] = 1 + return + } + + nb := impl.Ilaenv(1, "DSYTRD", opts, n, -1, -1, -1) + lworkopt := n * nb + if lwork == -1 { + work[0] = float64(lworkopt) + return + } + + nx := n + bi := blas64.Implementation() + var ldwork int + if 1 < nb && nb < n { + // Determine when to cross over from blocked to unblocked code. The last + // block is always handled by unblocked code. + opts := "L" + if upper { + opts = "U" + } + nx = max(nb, impl.Ilaenv(3, "DSYTRD", opts, n, -1, -1, -1)) + if nx < n { + // Determine if workspace is large enough for blocked code. + ldwork = nb + iws := n * ldwork + if lwork < iws { + // Not enough workspace to use optimal nb: determine the minimum + // value of nb and reduce nb or force use of unblocked code by + // setting nx = n. + nb = max(lwork/n, 1) + nbmin := impl.Ilaenv(2, "DSYTRD", opts, n, -1, -1, -1) + if nb < nbmin { + nx = n + } + } + } else { + nx = n + } + } else { + nb = 1 + } + ldwork = nb + + if upper { + // Reduce the upper triangle of A. Columns 0:kk are handled by the + // unblocked method. + var i int + kk := n - ((n-nx+nb-1)/nb)*nb + for i = n - nb; i >= kk; i -= nb { + // Reduce columns i:i+nb to tridiagonal form and form the matrix W + // which is needed to update the unreduced part of the matrix. + impl.Dlatrd(uplo, i+nb, nb, a, lda, e, tau, work, ldwork) + + // Update the unreduced submatrix A[0:i-1,0:i-1], using an update + // of the form A = A - V*W^T - W*V^T. + bi.Dsyr2k(uplo, blas.NoTrans, i, nb, -1, a[i:], lda, work, ldwork, 1, a, lda) + + // Copy superdiagonal elements back into A, and diagonal elements into D. + for j := i; j < i+nb; j++ { + a[(j-1)*lda+j] = e[j-1] + d[j] = a[j*lda+j] + } + } + // Use unblocked code to reduce the last or only block + // check that i == kk. + impl.Dsytd2(uplo, kk, a, lda, d, e, tau) + } else { + var i int + // Reduce the lower triangle of A. + for i = 0; i < n-nx; i += nb { + // Reduce columns 0:i+nb to tridiagonal form and form the matrix W + // which is needed to update the unreduced part of the matrix. + impl.Dlatrd(uplo, n-i, nb, a[i*lda+i:], lda, e[i:], tau[i:], work, ldwork) + + // Update the unreduced submatrix A[i+ib:n, i+ib:n], using an update + // of the form A = A + V*W^T - W*V^T. + bi.Dsyr2k(uplo, blas.NoTrans, n-i-nb, nb, -1, a[(i+nb)*lda+i:], lda, + work[nb*ldwork:], ldwork, 1, a[(i+nb)*lda+i+nb:], lda) + + // Copy subdiagonal elements back into A, and diagonal elements into D. + for j := i; j < i+nb; j++ { + a[(j+1)*lda+j] = e[j] + d[j] = a[j*lda+j] + } + } + // Use unblocked code to reduce the last or only block. + impl.Dsytd2(uplo, n-i, a[i*lda+i:], lda, d[i:], e[i:], tau[i:]) + } + work[0] = float64(lworkopt) +} diff --git a/lapack/native/dtgsja.go b/lapack/native/dtgsja.go new file mode 100644 index 00000000..7eb1dc6e --- /dev/null +++ b/lapack/native/dtgsja.go @@ -0,0 +1,357 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dtgsja computes the generalized singular value decomposition (GSVD) +// of two real upper triangular or trapezoidal matrices A and B. +// +// A and B have the following forms, which may be obtained by the +// preprocessing subroutine Dggsvp from a general m×n matrix A and p×n +// matrix B: +// +// n-k-l k l +// A = k [ 0 A12 A13 ] if m-k-l >= 0; +// l [ 0 0 A23 ] +// m-k-l [ 0 0 0 ] +// +// n-k-l k l +// A = k [ 0 A12 A13 ] if m-k-l < 0; +// m-k [ 0 0 A23 ] +// +// n-k-l k l +// B = l [ 0 0 B13 ] +// p-l [ 0 0 0 ] +// +// where the k×k matrix A12 and l×l matrix B13 are non-singular +// upper triangular. A23 is l×l upper triangular if m-k-l >= 0, +// otherwise A23 is (m-k)×l upper trapezoidal. +// +// On exit, +// +// U^T*A*Q = D1*[ 0 R ], V^T*B*Q = D2*[ 0 R ], +// +// where U, V and Q are orthogonal matrices. +// R is a non-singular upper triangular matrix, and D1 and D2 are +// diagonal matrices, which are of the following structures: +// +// If m-k-l >= 0, +// +// k l +// D1 = k [ I 0 ] +// l [ 0 C ] +// m-k-l [ 0 0 ] +// +// k l +// D2 = l [ 0 S ] +// p-l [ 0 0 ] +// +// n-k-l k l +// [ 0 R ] = k [ 0 R11 R12 ] k +// l [ 0 0 R22 ] l +// +// where +// +// C = diag( alpha_k, ... , alpha_{k+l} ), +// S = diag( beta_k, ... , beta_{k+l} ), +// C^2 + S^2 = I. +// +// R is stored in +// A[0:k+l, n-k-l:n] +// on exit. +// +// If m-k-l < 0, +// +// k m-k k+l-m +// D1 = k [ I 0 0 ] +// m-k [ 0 C 0 ] +// +// k m-k k+l-m +// D2 = m-k [ 0 S 0 ] +// k+l-m [ 0 0 I ] +// p-l [ 0 0 0 ] +// +// n-k-l k m-k k+l-m +// [ 0 R ] = k [ 0 R11 R12 R13 ] +// m-k [ 0 0 R22 R23 ] +// k+l-m [ 0 0 0 R33 ] +// +// where +// C = diag( alpha_k, ... , alpha_m ), +// S = diag( beta_k, ... , beta_m ), +// C^2 + S^2 = I. +// +// R = [ R11 R12 R13 ] is stored in A[0:m, n-k-l:n] +// [ 0 R22 R23 ] +// and R33 is stored in +// B[m-k:l, n+m-k-l:n] on exit. +// +// The computation of the orthogonal transformation matrices U, V or Q +// is optional. These matrices may either be formed explicitly, or they +// may be post-multiplied into input matrices U1, V1, or Q1. +// +// Dtgsja essentially uses a variant of Kogbetliantz algorithm to reduce +// min(l,m-k)×l triangular or trapezoidal matrix A23 and l×l +// matrix B13 to the form: +// +// U1^T*A13*Q1 = C1*R1; V1^T*B13*Q1 = S1*R1, +// +// where U1, V1 and Q1 are orthogonal matrices. C1 and S1 are diagonal +// matrices satisfying +// +// C1^2 + S1^2 = I, +// +// and R1 is an l×l non-singular upper triangular matrix. +// +// jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior +// is as follows +// jobU == lapack.GSVDU Compute orthogonal matrix U +// jobU == lapack.GSVDUnit Use unit-initialized matrix +// jobU == lapack.GSVDNone Do not compute orthogonal matrix. +// The behavior is the same for jobV and jobQ with the exception that instead of +// lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively. +// The matrices U, V and Q must be m×m, p×p and n×n respectively unless the +// relevant job parameter is lapack.GSVDNone. +// +// k and l specify the sub-blocks in the input matrices A and B: +// A23 = A[k:min(k+l,m), n-l:n) and B13 = B[0:l, n-l:n] +// of A and B, whose GSVD is going to be computed by Dtgsja. +// +// tola and tolb are the convergence criteria for the Jacobi-Kogbetliantz +// iteration procedure. Generally, they are the same as used in the preprocessing +// step, for example, +// tola = max(m, n)*norm(A)*eps, +// tolb = max(p, n)*norm(B)*eps, +// where eps is the machine epsilon. +// +// work must have length at least 2*n, otherwise Dtgsja will panic. +// +// alpha and beta must have length n or Dtgsja will panic. On exit, alpha and +// beta contain the generalized singular value pairs of A and B +// alpha[0:k] = 1, +// beta[0:k] = 0, +// if m-k-l >= 0, +// alpha[k:k+l] = diag(C), +// beta[k:k+l] = diag(S), +// if m-k-l < 0, +// alpha[k:m]= C, alpha[m:k+l]= 0 +// beta[k:m] = S, beta[m:k+l] = 1. +// if k+l < n, +// alpha[k+l:n] = 0 and +// beta[k+l:n] = 0. +// +// On exit, A[n-k:n, 0:min(k+l,m)] contains the triangular matrix R or part of R +// and if necessary, B[m-k:l, n+m-k-l:n] contains a part of R. +// +// Dtgsja returns whether the routine converged and the number of iteration cycles +// that were run. +// +// Dtgsja is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtgsja(jobU, jobV, jobQ lapack.GSVDJob, m, p, n, k, l int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64) (cycles int, ok bool) { + const maxit = 40 + + checkMatrix(m, n, a, lda) + checkMatrix(p, n, b, ldb) + + if len(alpha) != n { + panic(badAlpha) + } + if len(beta) != n { + panic(badBeta) + } + + initu := jobU == lapack.GSVDUnit + wantu := initu || jobU == lapack.GSVDU + if !initu && !wantu && jobU != lapack.GSVDNone { + panic(badGSVDJob + "U") + } + if jobU != lapack.GSVDNone { + checkMatrix(m, m, u, ldu) + } + + initv := jobV == lapack.GSVDUnit + wantv := initv || jobV == lapack.GSVDV + if !initv && !wantv && jobV != lapack.GSVDNone { + panic(badGSVDJob + "V") + } + if jobV != lapack.GSVDNone { + checkMatrix(p, p, v, ldv) + } + + initq := jobQ == lapack.GSVDUnit + wantq := initq || jobQ == lapack.GSVDQ + if !initq && !wantq && jobQ != lapack.GSVDNone { + panic(badGSVDJob + "Q") + } + if jobQ != lapack.GSVDNone { + checkMatrix(n, n, q, ldq) + } + + if len(work) < 2*n { + panic(badWork) + } + + // Initialize U, V and Q, if necessary + if initu { + impl.Dlaset(blas.All, m, m, 0, 1, u, ldu) + } + if initv { + impl.Dlaset(blas.All, p, p, 0, 1, v, ldv) + } + if initq { + impl.Dlaset(blas.All, n, n, 0, 1, q, ldq) + } + + bi := blas64.Implementation() + minTol := math.Min(tola, tolb) + + // Loop until convergence. + upper := false + for cycles = 1; cycles <= maxit; cycles++ { + upper = !upper + + for i := 0; i < l-1; i++ { + for j := i + 1; j < l; j++ { + var a1, a2, a3 float64 + if k+i < m { + a1 = a[(k+i)*lda+n-l+i] + } + if k+j < m { + a3 = a[(k+j)*lda+n-l+j] + } + + b1 := b[i*ldb+n-l+i] + b3 := b[j*ldb+n-l+j] + + var b2 float64 + if upper { + if k+i < m { + a2 = a[(k+i)*lda+n-l+j] + } + b2 = b[i*ldb+n-l+j] + } else { + if k+j < m { + a2 = a[(k+j)*lda+n-l+i] + } + b2 = b[j*ldb+n-l+i] + } + + csu, snu, csv, snv, csq, snq := impl.Dlags2(upper, a1, a2, a3, b1, b2, b3) + + // Update (k+i)-th and (k+j)-th rows of matrix A: U^T*A. + if k+j < m { + bi.Drot(l, a[(k+j)*lda+n-l:], 1, a[(k+i)*lda+n-l:], 1, csu, snu) + } + + // Update i-th and j-th rows of matrix B: V^T*B. + bi.Drot(l, b[j*ldb+n-l:], 1, b[i*ldb+n-l:], 1, csv, snv) + + // Update (n-l+i)-th and (n-l+j)-th columns of matrices + // A and B: A*Q and B*Q. + bi.Drot(min(k+l, m), a[n-l+j:], lda, a[n-l+i:], lda, csq, snq) + bi.Drot(l, b[n-l+j:], ldb, b[n-l+i:], ldb, csq, snq) + + if upper { + if k+i < m { + a[(k+i)*lda+n-l+j] = 0 + } + b[i*ldb+n-l+j] = 0 + } else { + if k+j < m { + a[(k+j)*lda+n-l+i] = 0 + } + b[j*ldb+n-l+i] = 0 + } + + // Update orthogonal matrices U, V, Q, if desired. + if wantu && k+j < m { + bi.Drot(m, u[k+j:], ldu, u[k+i:], ldu, csu, snu) + } + if wantv { + bi.Drot(p, v[j:], ldv, v[i:], ldv, csv, snv) + } + if wantq { + bi.Drot(n, q[n-l+j:], ldq, q[n-l+i:], ldq, csq, snq) + } + } + } + + if !upper { + // The matrices A13 and B13 were lower triangular at the start + // of the cycle, and are now upper triangular. + // + // Convergence test: test the parallelism of the corresponding + // rows of A and B. + var error float64 + for i := 0; i < min(l, m-k); i++ { + bi.Dcopy(l-i, a[(k+i)*lda+n-l+i:], 1, work, 1) + bi.Dcopy(l-i, b[i*ldb+n-l+i:], 1, work[l:], 1) + ssmin := impl.Dlapll(l-i, work, 1, work[l:], 1) + error = math.Max(error, ssmin) + } + if math.Abs(error) <= minTol { + // The algorithm has converged. + // Compute the generalized singular value pairs (alpha, beta) + // and set the triangular matrix R to array A. + for i := 0; i < k; i++ { + alpha[i] = 1 + beta[i] = 0 + } + + for i := 0; i < min(l, m-k); i++ { + a1 := a[(k+i)*lda+n-l+i] + b1 := b[i*ldb+n-l+i] + + if a1 != 0 { + gamma := b1 / a1 + + // Change sign if necessary. + if gamma < 0 { + bi.Dscal(l-i, -1, b[i*ldb+n-l+i:], 1) + if wantv { + bi.Dscal(p, -1, v[i:], ldv) + } + } + beta[k+i], alpha[k+i], _ = impl.Dlartg(math.Abs(gamma), 1) + + if alpha[k+i] >= beta[k+i] { + bi.Dscal(l-i, 1/alpha[k+i], a[(k+i)*lda+n-l+i:], 1) + } else { + bi.Dscal(l-i, 1/beta[k+i], b[i*ldb+n-l+i:], 1) + bi.Dcopy(l-i, b[i*ldb+n-l+i:], 1, a[(k+i)*lda+n-l+i:], 1) + } + } else { + alpha[k+i] = 0 + beta[k+i] = 1 + bi.Dcopy(l-i, b[i*ldb+n-l+i:], 1, a[(k+i)*lda+n-l+i:], 1) + } + } + + for i := m; i < k+l; i++ { + alpha[i] = 0 + beta[i] = 1 + } + if k+l < n { + for i := k + l; i < n; i++ { + alpha[i] = 0 + beta[i] = 0 + } + } + + return cycles, true + } + } + } + + // The algorithm has not converged after maxit cycles. + return cycles, false +} diff --git a/lapack/native/dtrcon.go b/lapack/native/dtrcon.go new file mode 100644 index 00000000..ffa9cc71 --- /dev/null +++ b/lapack/native/dtrcon.go @@ -0,0 +1,82 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dtrcon estimates the reciprocal of the condition number of a triangular matrix A. +// The condition number computed may be based on the 1-norm or the ∞-norm. +// +// work is a temporary data slice of length at least 3*n and Dtrcon will panic otherwise. +// +// iwork is a temporary data slice of length at least n and Dtrcon will panic otherwise. +func (impl Implementation) Dtrcon(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 { + if norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum { + panic(badNorm) + } + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.NonUnit && diag != blas.Unit { + panic(badDiag) + } + if len(work) < 3*n { + panic(badWork) + } + if len(iwork) < n { + panic(badWork) + } + if n == 0 { + return 1 + } + bi := blas64.Implementation() + + var rcond float64 + smlnum := dlamchS * float64(n) + + anorm := impl.Dlantr(norm, uplo, diag, n, n, a, lda, work) + + if anorm <= 0 { + return rcond + } + var ainvnm float64 + var normin bool + kase1 := 2 + if norm == lapack.MaxColumnSum { + kase1 = 1 + } + var kase int + isave := new([3]int) + var scale float64 + for { + ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) + if kase == 0 { + if ainvnm != 0 { + rcond = (1 / anorm) / ainvnm + } + return rcond + } + if kase == kase1 { + scale = impl.Dlatrs(uplo, blas.NoTrans, diag, normin, n, a, lda, work, work[2*n:]) + } else { + scale = impl.Dlatrs(uplo, blas.Trans, diag, normin, n, a, lda, work, work[2*n:]) + } + normin = true + if scale != 1 { + ix := bi.Idamax(n, work, 1) + xnorm := math.Abs(work[ix]) + if scale == 0 || scale < xnorm*smlnum { + return rcond + } + impl.Drscl(n, scale, work, 1) + } + } +} diff --git a/lapack/native/dtrevc3.go b/lapack/native/dtrevc3.go new file mode 100644 index 00000000..034b19ee --- /dev/null +++ b/lapack/native/dtrevc3.go @@ -0,0 +1,866 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +// Dtrevc3 computes some or all of the right and/or left eigenvectors of an n×n +// upper quasi-triangular matrix T in Schur canonical form. Matrices of this +// type are produced by the Schur factorization of a real general matrix A +// A = Q T Q^T, +// as computed by Dhseqr. +// +// The right eigenvector x of T corresponding to an +// eigenvalue λ is defined by +// T x = λ x, +// and the left eigenvector is defined by +// y^H T = λ y^H, +// where y^H is the conjugate transpose of y. +// +// The eigenvalues are read directly from the diagonal blocks of T. +// +// This routine returns the matrices X and/or Y of right and left eigenvectors +// of T, or the products Q*X and/or Q*Y, where Q is an input matrix. If Q is the +// orthogonal factor that reduces a matrix A to Schur form T, then Q*X and Q*Y +// are the matrices of right and left eigenvectors of A. +// +// If side == lapack.RightEV, only right eigenvectors will be computed. +// If side == lapack.LeftEV, only left eigenvectors will be computed. +// If side == lapack.RightLeftEV, both right and left eigenvectors will be computed. +// For other values of side, Dtrevc3 will panic. +// +// If howmny == lapack.AllEV, all right and/or left eigenvectors will be +// computed. +// If howmny == lapack.AllEVMulQ, all right and/or left eigenvectors will be +// computed and multiplied from left by the matrices in VR and/or VL. +// If howmny == lapack.SelectedEV, right and/or left eigenvectors will be +// computed as indicated by selected. +// For other values of howmny, Dtrevc3 will panic. +// +// selected specifies which eigenvectors will be computed. It must have length n +// if howmny == lapack.SelectedEV, and it is not referenced otherwise. +// If w_j is a real eigenvalue, the corresponding real eigenvector will be +// computed if selected[j] is true. +// If w_j and w_{j+1} are the real and imaginary parts of a complex eigenvalue, +// the corresponding complex eigenvector is computed if either selected[j] or +// selected[j+1] is true, and on return selected[j] will be set to true and +// selected[j+1] will be set to false. +// +// VL and VR are n×mm matrices. If howmny is lapack.AllEV or +// lapack.AllEVMulQ, mm must be at least n. If howmny == +// lapack.SelectedEV, mm must be large enough to store the selected +// eigenvectors. Each selected real eigenvector occupies one column and each +// selected complex eigenvector occupies two columns. If mm is not sufficiently +// large, Dtrevc3 will panic. +// +// On entry, if howmny == lapack.AllEVMulQ, it is assumed that VL (if side +// is lapack.LeftEV or lapack.RightLeftEV) contains an n×n matrix QL, +// and that VR (if side is lapack.LeftEV or lapack.RightLeftEV) contains +// an n×n matrix QR. QL and QR are typically the orthogonal matrix Q of Schur +// vectors returned by Dhseqr. +// +// On return, if side is lapack.LeftEV or lapack.RightLeftEV, +// VL will contain: +// if howmny == lapack.AllEV, the matrix Y of left eigenvectors of T, +// if howmny == lapack.AllEVMulQ, the matrix Q*Y, +// if howmny == lapack.SelectedEV, the left eigenvectors of T specified by +// selected, stored consecutively in the +// columns of VL, in the same order as their +// eigenvalues. +// VL is not referenced if side == lapack.RightEV. +// +// On return, if side is lapack.RightEV or lapack.RightLeftEV, +// VR will contain: +// if howmny == lapack.AllEV, the matrix X of right eigenvectors of T, +// if howmny == lapack.AllEVMulQ, the matrix Q*X, +// if howmny == lapack.SelectedEV, the left eigenvectors of T specified by +// selected, stored consecutively in the +// columns of VR, in the same order as their +// eigenvalues. +// VR is not referenced if side == lapack.LeftEV. +// +// Complex eigenvectors corresponding to a complex eigenvalue are stored in VL +// and VR in two consecutive columns, the first holding the real part, and the +// second the imaginary part. +// +// Each eigenvector will be normalized so that the element of largest magnitude +// has magnitude 1. Here the magnitude of a complex number (x,y) is taken to be +// |x| + |y|. +// +// work must have length at least lwork and lwork must be at least max(1,3*n), +// otherwise Dtrevc3 will panic. For optimum performance, lwork should be at +// least n+2*n*nb, where nb is the optimal blocksize. +// +// If lwork == -1, instead of performing Dtrevc3, the function only estimates +// the optimal workspace size based on n and stores it into work[0]. +// +// Dtrevc3 returns the number of columns in VL and/or VR actually used to store +// the eigenvectors. +// +// Dtrevc3 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, selected []bool, n int, t []float64, ldt int, vl []float64, ldvl int, vr []float64, ldvr int, mm int, work []float64, lwork int) (m int) { + switch side { + default: + panic(badSide) + case lapack.RightEV, lapack.LeftEV, lapack.RightLeftEV: + } + switch howmny { + default: + panic(badHowMany) + case lapack.AllEV, lapack.AllEVMulQ, lapack.SelectedEV: + } + switch { + case n < 0: + panic(nLT0) + case len(work) < lwork: + panic(shortWork) + case lwork < max(1, 3*n) && lwork != -1: + panic(badWork) + } + if lwork != -1 { + if howmny == lapack.SelectedEV { + if len(selected) != n { + panic("lapack: bad selected length") + } + // Set m to the number of columns required to store the + // selected eigenvectors, and standardize the slice + // selected. + for j := 0; j < n; { + if j == n-1 || t[(j+1)*ldt+j] == 0 { + // Diagonal 1×1 block corresponding to a + // real eigenvalue. + if selected[j] { + m++ + } + j++ + } else { + // Diagonal 2×2 block corresponding to a + // complex eigenvalue. + if selected[j] || selected[j+1] { + selected[j] = true + selected[j+1] = false + m += 2 + } + j += 2 + } + } + } else { + m = n + } + if m > mm { + panic("lapack: insufficient number of columns") + } + checkMatrix(n, n, t, ldt) + if (side == lapack.RightEV || side == lapack.RightLeftEV) && m > 0 { + checkMatrix(n, m, vr, ldvr) + } + if (side == lapack.LeftEV || side == lapack.RightLeftEV) && m > 0 { + checkMatrix(n, m, vl, ldvl) + } + } + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return m + } + + const ( + nbmin = 8 + nbmax = 128 + ) + nb := impl.Ilaenv(1, "DTREVC", string(side)+string(howmny), n, -1, -1, -1) + + // Quick return in case of a workspace query. + if lwork == -1 { + work[0] = float64(n + 2*n*nb) + return m + } + + // Use blocked version of back-transformation if sufficient workspace. + // Zero-out the workspace to avoid potential NaN propagation. + if howmny == lapack.AllEVMulQ && lwork >= n+2*n*nbmin { + nb = min((lwork-n)/(2*n), nbmax) + impl.Dlaset(blas.All, n, 1+2*nb, 0, 0, work[:n+2*nb*n], 1+2*nb) + } else { + nb = 1 + } + + // Set the constants to control overflow. + ulp := dlamchP + smlnum := float64(n) / ulp * dlamchS + bignum := (1 - ulp) / smlnum + + // Split work into a vector of column norms and an n×2*nb matrix b. + norms := work[:n] + ldb := 2 * nb + b := work[n : n+n*ldb] + + // Compute 1-norm of each column of strictly upper triangular part of T + // to control overflow in triangular solver. + norms[0] = 0 + for j := 1; j < n; j++ { + var cn float64 + for i := 0; i < j; i++ { + cn += math.Abs(t[i*ldt+j]) + } + norms[j] = cn + } + + bi := blas64.Implementation() + + var ( + x [4]float64 + + iv int // Index of column in current block. + is int + + // ip is used below to specify the real or complex eigenvalue: + // ip == 0, real eigenvalue, + // 1, first of conjugate complex pair (wr,wi), + // -1, second of conjugate complex pair (wr,wi). + ip int + iscomplex [nbmax]int // Stores ip for each column in current block. + ) + + if side == lapack.LeftEV { + goto leftev + } + + // Compute right eigenvectors. + + // For complex right vector, iv-1 is for real part and iv for complex + // part. Non-blocked version always uses iv=1, blocked version starts + // with iv=nb-1 and goes down to 0 or 1. + iv = max(2, nb) - 1 + ip = 0 + is = m - 1 + for ki := n - 1; ki >= 0; ki-- { + if ip == -1 { + // Previous iteration (ki+1) was second of + // conjugate pair, so this ki is first of + // conjugate pair. + ip = 1 + continue + } + + if ki == 0 || t[ki*ldt+ki-1] == 0 { + // Last column or zero on sub-diagonal, so this + // ki must be real eigenvalue. + ip = 0 + } else { + // Non-zero on sub-diagonal, so this ki is + // second of conjugate pair. + ip = -1 + } + + if howmny == lapack.SelectedEV { + if ip == 0 { + if !selected[ki] { + continue + } + } else if !selected[ki-1] { + continue + } + } + + // Compute the ki-th eigenvalue (wr,wi). + wr := t[ki*ldt+ki] + var wi float64 + if ip != 0 { + wi = math.Sqrt(math.Abs(t[ki*ldt+ki-1])) * math.Sqrt(math.Abs(t[(ki-1)*ldt+ki])) + } + smin := math.Max(ulp*(math.Abs(wr)+math.Abs(wi)), smlnum) + + if ip == 0 { + // Real right eigenvector. + + b[ki*ldb+iv] = 1 + // Form right-hand side. + for k := 0; k < ki; k++ { + b[k*ldb+iv] = -t[k*ldt+ki] + } + // Solve upper quasi-triangular system: + // [ T[0:ki,0:ki] - wr ]*X = scale*b. + for j := ki - 1; j >= 0; { + if j == 0 || t[j*ldt+j-1] == 0 { + // 1×1 diagonal block. + scale, xnorm, _ := impl.Dlaln2(false, 1, 1, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:1], 2) + // Scale X[0,0] to avoid overflow when updating the + // right-hand side. + if xnorm > 1 && norms[j] > bignum/xnorm { + x[0] /= xnorm + scale /= xnorm + } + // Scale if necessary. + if scale != 1 { + bi.Dscal(ki+1, scale, b[iv:], ldb) + } + b[j*ldb+iv] = x[0] + // Update right-hand side. + bi.Daxpy(j, -x[0], t[j:], ldt, b[iv:], ldb) + j-- + } else { + // 2×2 diagonal block. + scale, xnorm, _ := impl.Dlaln2(false, 2, 1, smin, 1, t[(j-1)*ldt+j-1:], ldt, + 1, 1, b[(j-1)*ldb+iv:], ldb, wr, 0, x[:3], 2) + // Scale X[0,0] and X[1,0] to avoid overflow + // when updating the right-hand side. + if xnorm > 1 { + beta := math.Max(norms[j-1], norms[j]) + if beta > bignum/xnorm { + x[0] /= xnorm + x[2] /= xnorm + scale /= xnorm + } + } + // Scale if necessary. + if scale != 1 { + bi.Dscal(ki+1, scale, b[iv:], ldb) + } + b[(j-1)*ldb+iv] = x[0] + b[j*ldb+iv] = x[2] + // Update right-hand side. + bi.Daxpy(j-1, -x[0], t[j-1:], ldt, b[iv:], ldb) + bi.Daxpy(j-1, -x[2], t[j:], ldt, b[iv:], ldb) + j -= 2 + } + } + // Copy the vector x or Q*x to VR and normalize. + switch { + case howmny != lapack.AllEVMulQ: + // No back-transform: copy x to VR and normalize. + bi.Dcopy(ki+1, b[iv:], ldb, vr[is:], ldvr) + ii := bi.Idamax(ki+1, vr[is:], ldvr) + remax := 1 / math.Abs(vr[ii*ldvr+is]) + bi.Dscal(ki+1, remax, vr[is:], ldvr) + for k := ki + 1; k < n; k++ { + vr[k*ldvr+is] = 0 + } + case nb == 1: + // Version 1: back-transform each vector with GEMV, Q*x. + if ki > 0 { + bi.Dgemv(blas.NoTrans, n, ki, 1, vr, ldvr, b[iv:], ldb, + b[ki*ldb+iv], vr[ki:], ldvr) + } + ii := bi.Idamax(n, vr[ki:], ldvr) + remax := 1 / math.Abs(vr[ii*ldvr+ki]) + bi.Dscal(n, remax, vr[ki:], ldvr) + default: + // Version 2: back-transform block of vectors with GEMM. + // Zero out below vector. + for k := ki + 1; k < n; k++ { + b[k*ldb+iv] = 0 + } + iscomplex[iv] = ip + // Back-transform and normalization is done below. + } + } else { + // Complex right eigenvector. + + // Initial solve + // [ ( T[ki-1,ki-1] T[ki-1,ki] ) - (wr + i*wi) ]*X = 0. + // [ ( T[ki, ki-1] T[ki, ki] ) ] + if math.Abs(t[(ki-1)*ldt+ki]) >= math.Abs(t[ki*ldt+ki-1]) { + b[(ki-1)*ldb+iv-1] = 1 + b[ki*ldb+iv] = wi / t[(ki-1)*ldt+ki] + } else { + b[(ki-1)*ldb+iv-1] = -wi / t[ki*ldt+ki-1] + b[ki*ldb+iv] = 1 + } + b[ki*ldb+iv-1] = 0 + b[(ki-1)*ldb+iv] = 0 + // Form right-hand side. + for k := 0; k < ki-1; k++ { + b[k*ldb+iv-1] = -b[(ki-1)*ldb+iv-1] * t[k*ldt+ki-1] + b[k*ldb+iv] = -b[ki*ldb+iv] * t[k*ldt+ki] + } + // Solve upper quasi-triangular system: + // [ T[0:ki-1,0:ki-1] - (wr+i*wi) ]*X = scale*(b1+i*b2) + for j := ki - 2; j >= 0; { + if j == 0 || t[j*ldt+j-1] == 0 { + // 1×1 diagonal block. + + scale, xnorm, _ := impl.Dlaln2(false, 1, 2, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv-1:], ldb, wr, wi, x[:2], 2) + // Scale X[0,0] and X[0,1] to avoid + // overflow when updating the right-hand side. + if xnorm > 1 && norms[j] > bignum/xnorm { + x[0] /= xnorm + x[1] /= xnorm + scale /= xnorm + } + // Scale if necessary. + if scale != 1 { + bi.Dscal(ki+1, scale, b[iv-1:], ldb) + bi.Dscal(ki+1, scale, b[iv:], ldb) + } + b[j*ldb+iv-1] = x[0] + b[j*ldb+iv] = x[1] + // Update the right-hand side. + bi.Daxpy(j, -x[0], t[j:], ldt, b[iv-1:], ldb) + bi.Daxpy(j, -x[1], t[j:], ldt, b[iv:], ldb) + j-- + } else { + // 2×2 diagonal block. + + scale, xnorm, _ := impl.Dlaln2(false, 2, 2, smin, 1, t[(j-1)*ldt+j-1:], ldt, + 1, 1, b[(j-1)*ldb+iv-1:], ldb, wr, wi, x[:], 2) + // Scale X to avoid overflow when updating + // the right-hand side. + if xnorm > 1 { + beta := math.Max(norms[j-1], norms[j]) + if beta > bignum/xnorm { + rec := 1 / xnorm + x[0] *= rec + x[1] *= rec + x[2] *= rec + x[3] *= rec + scale *= rec + } + } + // Scale if necessary. + if scale != 1 { + bi.Dscal(ki+1, scale, b[iv-1:], ldb) + bi.Dscal(ki+1, scale, b[iv:], ldb) + } + b[(j-1)*ldb+iv-1] = x[0] + b[(j-1)*ldb+iv] = x[1] + b[j*ldb+iv-1] = x[2] + b[j*ldb+iv] = x[3] + // Update the right-hand side. + bi.Daxpy(j-1, -x[0], t[j-1:], ldt, b[iv-1:], ldb) + bi.Daxpy(j-1, -x[1], t[j-1:], ldt, b[iv:], ldb) + bi.Daxpy(j-1, -x[2], t[j:], ldt, b[iv-1:], ldb) + bi.Daxpy(j-1, -x[3], t[j:], ldt, b[iv:], ldb) + j -= 2 + } + } + + // Copy the vector x or Q*x to VR and normalize. + switch { + case howmny != lapack.AllEVMulQ: + // No back-transform: copy x to VR and normalize. + bi.Dcopy(ki+1, b[iv-1:], ldb, vr[is-1:], ldvr) + bi.Dcopy(ki+1, b[iv:], ldb, vr[is:], ldvr) + emax := 0.0 + for k := 0; k <= ki; k++ { + emax = math.Max(emax, math.Abs(vr[k*ldvr+is-1])+math.Abs(vr[k*ldvr+is])) + } + remax := 1 / emax + bi.Dscal(ki+1, remax, vr[is-1:], ldvr) + bi.Dscal(ki+1, remax, vr[is:], ldvr) + for k := ki + 1; k < n; k++ { + vr[k*ldvr+is-1] = 0 + vr[k*ldvr+is] = 0 + } + case nb == 1: + // Version 1: back-transform each vector with GEMV, Q*x. + if ki-1 > 0 { + bi.Dgemv(blas.NoTrans, n, ki-1, 1, vr, ldvr, b[iv-1:], ldb, + b[(ki-1)*ldb+iv-1], vr[ki-1:], ldvr) + bi.Dgemv(blas.NoTrans, n, ki-1, 1, vr, ldvr, b[iv:], ldb, + b[ki*ldb+iv], vr[ki:], ldvr) + } else { + bi.Dscal(n, b[(ki-1)*ldb+iv-1], vr[ki-1:], ldvr) + bi.Dscal(n, b[ki*ldb+iv], vr[ki:], ldvr) + } + emax := 0.0 + for k := 0; k < n; k++ { + emax = math.Max(emax, math.Abs(vr[k*ldvr+ki-1])+math.Abs(vr[k*ldvr+ki])) + } + remax := 1 / emax + bi.Dscal(n, remax, vr[ki-1:], ldvr) + bi.Dscal(n, remax, vr[ki:], ldvr) + default: + // Version 2: back-transform block of vectors with GEMM. + // Zero out below vector. + for k := ki + 1; k < n; k++ { + b[k*ldb+iv-1] = 0 + b[k*ldb+iv] = 0 + } + iscomplex[iv-1] = -ip + iscomplex[iv] = ip + iv-- + // Back-transform and normalization is done below. + } + } + if nb > 1 { + // Blocked version of back-transform. + + // For complex case, ki2 includes both vectors (ki-1 and ki). + ki2 := ki + if ip != 0 { + ki2-- + } + // Columns iv:nb of b are valid vectors. + // When the number of vectors stored reaches nb-1 or nb, + // or if this was last vector, do the Gemm. + if iv < 2 || ki2 == 0 { + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, nb-iv, ki2+nb-iv, + 1, vr, ldvr, b[iv:], ldb, + 0, b[nb+iv:], ldb) + // Normalize vectors. + var remax float64 + for k := iv; k < nb; k++ { + if iscomplex[k] == 0 { + // Real eigenvector. + ii := bi.Idamax(n, b[nb+k:], ldb) + remax = 1 / math.Abs(b[ii*ldb+nb+k]) + } else if iscomplex[k] == 1 { + // First eigenvector of conjugate pair. + emax := 0.0 + for ii := 0; ii < n; ii++ { + emax = math.Max(emax, math.Abs(b[ii*ldb+nb+k])+math.Abs(b[ii*ldb+nb+k+1])) + } + remax = 1 / emax + // Second eigenvector of conjugate pair + // will reuse this value of remax. + } + bi.Dscal(n, remax, b[nb+k:], ldb) + } + impl.Dlacpy(blas.All, n, nb-iv, b[nb+iv:], ldb, vr[ki2:], ldvr) + iv = nb - 1 + } else { + iv-- + } + } + is-- + if ip != 0 { + is-- + } + } + + if side == lapack.RightEV { + return m + } + +leftev: + // Compute left eigenvectors. + + // For complex left vector, iv is for real part and iv+1 for complex + // part. Non-blocked version always uses iv=0. Blocked version starts + // with iv=0, goes up to nb-2 or nb-1. + iv = 0 + ip = 0 + is = 0 + for ki := 0; ki < n; ki++ { + if ip == 1 { + // Previous iteration ki-1 was first of conjugate pair, + // so this ki is second of conjugate pair. + ip = -1 + continue + } + + if ki == n-1 || t[(ki+1)*ldt+ki] == 0 { + // Last column or zero on sub-diagonal, so this ki must + // be real eigenvalue. + ip = 0 + } else { + // Non-zero on sub-diagonal, so this ki is first of + // conjugate pair. + ip = 1 + } + if howmny == lapack.SelectedEV && !selected[ki] { + continue + } + + // Compute the ki-th eigenvalue (wr,wi). + wr := t[ki*ldt+ki] + var wi float64 + if ip != 0 { + wi = math.Sqrt(math.Abs(t[ki*ldt+ki+1])) * math.Sqrt(math.Abs(t[(ki+1)*ldt+ki])) + } + smin := math.Max(ulp*(math.Abs(wr)+math.Abs(wi)), smlnum) + + if ip == 0 { + // Real left eigenvector. + + b[ki*ldb+iv] = 1 + // Form right-hand side. + for k := ki + 1; k < n; k++ { + b[k*ldb+iv] = -t[ki*ldt+k] + } + // Solve transposed quasi-triangular system: + // [ T[ki+1:n,ki+1:n] - wr ]^T * X = scale*b + vmax := 1.0 + vcrit := bignum + for j := ki + 1; j < n; { + if j == n-1 || t[(j+1)*ldt+j] == 0 { + // 1×1 diagonal block. + + // Scale if necessary to avoid overflow + // when forming the right-hand side. + if norms[j] > vcrit { + rec := 1 / vmax + bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb) + vmax = 1 + vcrit = bignum + } + b[j*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j:], ldt, b[(ki+1)*ldb+iv:], ldb) + // Solve [ T[j,j] - wr ]^T * X = b. + scale, _, _ := impl.Dlaln2(false, 1, 1, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:1], 2) + // Scale if necessary. + if scale != 1 { + bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) + } + b[j*ldb+iv] = x[0] + vmax = math.Max(math.Abs(b[j*ldb+iv]), vmax) + vcrit = bignum / vmax + j++ + } else { + // 2×2 diagonal block. + + // Scale if necessary to avoid overflow + // when forming the right-hand side. + beta := math.Max(norms[j], norms[j+1]) + if beta > vcrit { + bi.Dscal(n-ki+1, 1/vmax, b[ki*ldb+iv:], 1) + vmax = 1 + vcrit = bignum + } + b[j*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j:], ldt, b[(ki+1)*ldb+iv:], ldb) + b[(j+1)*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j+1:], ldt, b[(ki+1)*ldb+iv:], ldb) + // Solve + // [ T[j,j]-wr T[j,j+1] ]^T * X = scale*[ b1 ] + // [ T[j+1,j] T[j+1,j+1]-wr ] [ b2 ] + scale, _, _ := impl.Dlaln2(true, 2, 1, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:3], 2) + // Scale if necessary. + if scale != 1 { + bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) + } + b[j*ldb+iv] = x[0] + b[(j+1)*ldb+iv] = x[2] + vmax = math.Max(vmax, math.Max(math.Abs(b[j*ldb+iv]), math.Abs(b[(j+1)*ldb+iv]))) + vcrit = bignum / vmax + j += 2 + } + } + // Copy the vector x or Q*x to VL and normalize. + switch { + case howmny != lapack.AllEVMulQ: + // No back-transform: copy x to VL and normalize. + bi.Dcopy(n-ki, b[ki*ldb+iv:], ldb, vl[ki*ldvl+is:], ldvl) + ii := bi.Idamax(n-ki, vl[ki*ldvl+is:], ldvl) + ki + remax := 1 / math.Abs(vl[ii*ldvl+is]) + bi.Dscal(n-ki, remax, vl[ki*ldvl+is:], ldvl) + for k := 0; k < ki; k++ { + vl[k*ldvl+is] = 0 + } + case nb == 1: + // Version 1: back-transform each vector with Gemv, Q*x. + if n-ki-1 > 0 { + bi.Dgemv(blas.NoTrans, n, n-ki-1, + 1, vl[ki+1:], ldvl, b[(ki+1)*ldb+iv:], ldb, + b[ki*ldb+iv], vl[ki:], ldvl) + } + ii := bi.Idamax(n, vl[ki:], ldvl) + remax := 1 / math.Abs(vl[ii*ldvl+ki]) + bi.Dscal(n, remax, vl[ki:], ldvl) + default: + // Version 2: back-transform block of vectors with Gemm + // zero out above vector. + for k := 0; k < ki; k++ { + b[k*ldb+iv] = 0 + } + iscomplex[iv] = ip + // Back-transform and normalization is done below. + } + } else { + // Complex left eigenvector. + + // Initial solve: + // [ [ T[ki,ki] T[ki,ki+1] ]^T - (wr - i* wi) ]*X = 0. + // [ [ T[ki+1,ki] T[ki+1,ki+1] ] ] + if math.Abs(t[ki*ldt+ki+1]) >= math.Abs(t[(ki+1)*ldt+ki]) { + b[ki*ldb+iv] = wi / t[ki*ldt+ki+1] + b[(ki+1)*ldb+iv+1] = 1 + } else { + b[ki*ldb+iv] = 1 + b[(ki+1)*ldb+iv+1] = -wi / t[(ki+1)*ldt+ki] + } + b[(ki+1)*ldb+iv] = 0 + b[ki*ldb+iv+1] = 0 + // Form right-hand side. + for k := ki + 2; k < n; k++ { + b[k*ldb+iv] = -b[ki*ldb+iv] * t[ki*ldt+k] + b[k*ldb+iv+1] = -b[(ki+1)*ldb+iv+1] * t[(ki+1)*ldt+k] + } + // Solve transposed quasi-triangular system: + // [ T[ki+2:n,ki+2:n]^T - (wr-i*wi) ]*X = b1+i*b2 + vmax := 1.0 + vcrit := bignum + for j := ki + 2; j < n; { + if j == n-1 || t[(j+1)*ldt+j] == 0 { + // 1×1 diagonal block. + + // Scale if necessary to avoid overflow + // when forming the right-hand side elements. + if norms[j] > vcrit { + rec := 1 / vmax + bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb) + bi.Dscal(n-ki, rec, b[ki*ldb+iv+1:], ldb) + vmax = 1 + vcrit = bignum + } + b[j*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv:], ldb) + b[j*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv+1:], ldb) + // Solve [ T[j,j]-(wr-i*wi) ]*(X11+i*X12) = b1+i*b2. + scale, _, _ := impl.Dlaln2(false, 1, 2, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, -wi, x[:2], 2) + // Scale if necessary. + if scale != 1 { + bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) + bi.Dscal(n-ki, scale, b[ki*ldb+iv+1:], ldb) + } + b[j*ldb+iv] = x[0] + b[j*ldb+iv+1] = x[1] + vmax = math.Max(vmax, math.Max(math.Abs(b[j*ldb+iv]), math.Abs(b[j*ldb+iv+1]))) + vcrit = bignum / vmax + j++ + } else { + // 2×2 diagonal block. + + // Scale if necessary to avoid overflow + // when forming the right-hand side elements. + if math.Max(norms[j], norms[j+1]) > vcrit { + rec := 1 / vmax + bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb) + bi.Dscal(n-ki, rec, b[ki*ldb+iv+1:], ldb) + vmax = 1 + vcrit = bignum + } + b[j*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv:], ldb) + b[j*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv+1:], ldb) + b[(j+1)*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j+1:], ldt, b[(ki+2)*ldb+iv:], ldb) + b[(j+1)*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j+1:], ldt, b[(ki+2)*ldb+iv+1:], ldb) + // Solve 2×2 complex linear equation + // [ [T[j,j] T[j,j+1] ]^T - (wr-i*wi)*I ]*X = scale*b + // [ [T[j+1,j] T[j+1,j+1]] ] + scale, _, _ := impl.Dlaln2(true, 2, 2, smin, 1, t[j*ldt+j:], ldt, + 1, 1, b[j*ldb+iv:], ldb, wr, -wi, x[:], 2) + // Scale if necessary. + if scale != 1 { + bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb) + bi.Dscal(n-ki, scale, b[ki*ldb+iv+1:], ldb) + } + b[j*ldb+iv] = x[0] + b[j*ldb+iv+1] = x[1] + b[(j+1)*ldb+iv] = x[2] + b[(j+1)*ldb+iv+1] = x[3] + vmax01 := math.Max(math.Abs(x[0]), math.Abs(x[1])) + vmax23 := math.Max(math.Abs(x[2]), math.Abs(x[3])) + vmax = math.Max(vmax, math.Max(vmax01, vmax23)) + vcrit = bignum / vmax + j += 2 + } + } + // Copy the vector x or Q*x to VL and normalize. + switch { + case howmny != lapack.AllEVMulQ: + // No back-transform: copy x to VL and normalize. + bi.Dcopy(n-ki, b[ki*ldb+iv:], ldb, vl[ki*ldvl+is:], ldvl) + bi.Dcopy(n-ki, b[ki*ldb+iv+1:], ldb, vl[ki*ldvl+is+1:], ldvl) + emax := 0.0 + for k := ki; k < n; k++ { + emax = math.Max(emax, math.Abs(vl[k*ldvl+is])+math.Abs(vl[k*ldvl+is+1])) + } + remax := 1 / emax + bi.Dscal(n-ki, remax, vl[ki*ldvl+is:], ldvl) + bi.Dscal(n-ki, remax, vl[ki*ldvl+is+1:], ldvl) + for k := 0; k < ki; k++ { + vl[k*ldvl+is] = 0 + vl[k*ldvl+is+1] = 0 + } + case nb == 1: + // Version 1: back-transform each vector with GEMV, Q*x. + if n-ki-2 > 0 { + bi.Dgemv(blas.NoTrans, n, n-ki-2, + 1, vl[ki+2:], ldvl, b[(ki+2)*ldb+iv:], ldb, + b[ki*ldb+iv], vl[ki:], ldvl) + bi.Dgemv(blas.NoTrans, n, n-ki-2, + 1, vl[ki+2:], ldvl, b[(ki+2)*ldb+iv+1:], ldb, + b[(ki+1)*ldb+iv+1], vl[ki+1:], ldvl) + } else { + bi.Dscal(n, b[ki*ldb+iv], vl[ki:], ldvl) + bi.Dscal(n, b[(ki+1)*ldb+iv+1], vl[ki+1:], ldvl) + } + emax := 0.0 + for k := 0; k < n; k++ { + emax = math.Max(emax, math.Abs(vl[k*ldvl+ki])+math.Abs(vl[k*ldvl+ki+1])) + } + remax := 1 / emax + bi.Dscal(n, remax, vl[ki:], ldvl) + bi.Dscal(n, remax, vl[ki+1:], ldvl) + default: + // Version 2: back-transform block of vectors with GEMM. + // Zero out above vector. + // Could go from ki-nv+1 to ki-1. + for k := 0; k < ki; k++ { + b[k*ldb+iv] = 0 + b[k*ldb+iv+1] = 0 + } + iscomplex[iv] = ip + iscomplex[iv+1] = -ip + iv++ + // Back-transform and normalization is done below. + } + } + if nb > 1 { + // Blocked version of back-transform. + // For complex case, ki2 includes both vectors ki and ki+1. + ki2 := ki + if ip != 0 { + ki2++ + } + // Columns [0:iv] of work are valid vectors. When the + // number of vectors stored reaches nb-1 or nb, or if + // this was last vector, do the Gemm. + if iv >= nb-2 || ki2 == n-1 { + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, iv+1, n-ki2+iv, + 1, vl[ki2-iv:], ldvl, b[(ki2-iv)*ldb:], ldb, + 0, b[nb:], ldb) + // Normalize vectors. + var remax float64 + for k := 0; k <= iv; k++ { + if iscomplex[k] == 0 { + // Real eigenvector. + ii := bi.Idamax(n, b[nb+k:], ldb) + remax = 1 / math.Abs(b[ii*ldb+nb+k]) + } else if iscomplex[k] == 1 { + // First eigenvector of conjugate pair. + emax := 0.0 + for ii := 0; ii < n; ii++ { + emax = math.Max(emax, math.Abs(b[ii*ldb+nb+k])+math.Abs(b[ii*ldb+nb+k+1])) + } + remax = 1 / emax + // Second eigenvector of conjugate pair + // will reuse this value of remax. + } + bi.Dscal(n, remax, b[nb+k:], ldb) + } + impl.Dlacpy(blas.All, n, iv+1, b[nb:], ldb, vl[ki2-iv:], ldvl) + iv = 0 + } else { + iv++ + } + } + is++ + if ip != 0 { + is++ + } + } + + return m +} diff --git a/lapack/native/dtrexc.go b/lapack/native/dtrexc.go new file mode 100644 index 00000000..ab4b4837 --- /dev/null +++ b/lapack/native/dtrexc.go @@ -0,0 +1,221 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "gonum.org/v1/gonum/lapack" + +// Dtrexc reorders the real Schur factorization of a n×n real matrix +// A = Q*T*Q^T +// so that the diagonal block of T with row index ifst is moved to row ilst. +// +// On entry, T must be in Schur canonical form, that is, block upper triangular +// with 1×1 and 2×2 diagonal blocks; each 2×2 diagonal block has its diagonal +// elements equal and its off-diagonal elements of opposite sign. +// +// On return, T will be reordered by an orthogonal similarity transformation Z +// as Z^T*T*Z, and will be again in Schur canonical form. +// +// If compq is lapack.UpdateSchur, on return the matrix Q of Schur vectors will be +// updated by postmultiplying it with Z. +// If compq is lapack.None, the matrix Q is not referenced and will not be +// updated. +// For other values of compq Dtrexc will panic. +// +// ifst and ilst specify the reordering of the diagonal blocks of T. The block +// with row index ifst is moved to row ilst, by a sequence of transpositions +// between adjacent blocks. +// +// If ifst points to the second row of a 2×2 block, ifstOut will point to the +// first row, otherwise it will be equal to ifst. +// +// ilstOut will point to the first row of the block in its final position. If ok +// is true, ilstOut may differ from ilst by +1 or -1. +// +// It must hold that +// 0 <= ifst < n, and 0 <= ilst < n, +// otherwise Dtrexc will panic. +// +// If ok is false, two adjacent blocks were too close to swap because the +// problem is very ill-conditioned. T may have been partially reordered, and +// ilstOut will point to the first row of the block at the position to which it +// has been moved. +// +// work must have length at least n, otherwise Dtrexc will panic. +// +// Dtrexc is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtrexc(compq lapack.EVComp, n int, t []float64, ldt int, q []float64, ldq int, ifst, ilst int, work []float64) (ifstOut, ilstOut int, ok bool) { + checkMatrix(n, n, t, ldt) + var wantq bool + switch compq { + default: + panic("lapack: bad value of compq") + case lapack.None: + // Nothing to do because wantq is already false. + case lapack.UpdateSchur: + wantq = true + checkMatrix(n, n, q, ldq) + } + if (ifst < 0 || n <= ifst) && n > 0 { + panic("lapack: ifst out of range") + } + if (ilst < 0 || n <= ilst) && n > 0 { + panic("lapack: ilst out of range") + } + if len(work) < n { + panic(badWork) + } + + ok = true + + // Quick return if possible. + if n <= 1 { + return ifst, ilst, true + } + + // Determine the first row of specified block + // and find out it is 1×1 or 2×2. + if ifst > 0 && t[ifst*ldt+ifst-1] != 0 { + ifst-- + } + nbf := 1 // Size of the first block. + if ifst+1 < n && t[(ifst+1)*ldt+ifst] != 0 { + nbf = 2 + } + // Determine the first row of the final block + // and find out it is 1×1 or 2×2. + if ilst > 0 && t[ilst*ldt+ilst-1] != 0 { + ilst-- + } + nbl := 1 // Size of the last block. + if ilst+1 < n && t[(ilst+1)*ldt+ilst] != 0 { + nbl = 2 + } + + switch { + case ifst == ilst: + return ifst, ilst, true + + case ifst < ilst: + // Update ilst. + switch { + case nbf == 2 && nbl == 1: + ilst-- + case nbf == 1 && nbl == 2: + ilst++ + } + here := ifst + for here < ilst { + // Swap block with next one below. + if nbf == 1 || nbf == 2 { + // Current block either 1×1 or 2×2. + nbnext := 1 // Size of the next block. + if here+nbf+1 < n && t[(here+nbf+1)*ldt+here+nbf] != 0 { + nbnext = 2 + } + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, nbf, nbnext, work) + if !ok { + return ifst, here, false + } + here += nbnext + // Test if 2×2 block breaks into two 1×1 blocks. + if nbf == 2 && t[(here+1)*ldt+here] == 0 { + nbf = 3 + } + continue + } + + // Current block consists of two 1×1 blocks each of + // which must be swapped individually. + nbnext := 1 // Size of the next block. + if here+3 < n && t[(here+3)*ldt+here+2] != 0 { + nbnext = 2 + } + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here+1, 1, nbnext, work) + if !ok { + return ifst, here, false + } + if nbnext == 1 { + // Swap two 1×1 blocks, no problems possible. + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, nbnext, work) + here++ + continue + } + // Recompute nbnext in case 2×2 split. + if t[(here+2)*ldt+here+1] == 0 { + nbnext = 1 + } + if nbnext == 2 { + // 2×2 block did not split. + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, nbnext, work) + if !ok { + return ifst, here, false + } + } else { + // 2×2 block did split. + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, 1, work) + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here+1, 1, 1, work) + } + here += 2 + } + return ifst, here, true + + default: // ifst > ilst + here := ifst + for here > ilst { + // Swap block with next one above. + if nbf == 1 || nbf == 2 { + // Current block either 1×1 or 2×2. + nbnext := 1 + if here-2 >= 0 && t[(here-1)*ldt+here-2] != 0 { + nbnext = 2 + } + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-nbnext, nbnext, nbf, work) + if !ok { + return ifst, here, false + } + here -= nbnext + // Test if 2×2 block breaks into two 1×1 blocks. + if nbf == 2 && t[(here+1)*ldt+here] == 0 { + nbf = 3 + } + continue + } + + // Current block consists of two 1×1 blocks each of + // which must be swapped individually. + nbnext := 1 + if here-2 >= 0 && t[(here-1)*ldt+here-2] != 0 { + nbnext = 2 + } + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-nbnext, nbnext, 1, work) + if !ok { + return ifst, here, false + } + if nbnext == 1 { + // Swap two 1×1 blocks, no problems possible. + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, nbnext, 1, work) + here-- + continue + } + // Recompute nbnext in case 2×2 split. + if t[here*ldt+here-1] == 0 { + nbnext = 1 + } + if nbnext == 2 { + // 2×2 block did not split. + ok = impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-1, 2, 1, work) + if !ok { + return ifst, here, false + } + } else { + // 2×2 block did split. + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here, 1, 1, work) + impl.Dlaexc(wantq, n, t, ldt, q, ldq, here-1, 1, 1, work) + } + here -= 2 + } + return ifst, here, true + } +} diff --git a/lapack/native/dtrti2.go b/lapack/native/dtrti2.go new file mode 100644 index 00000000..49ae9e1c --- /dev/null +++ b/lapack/native/dtrti2.go @@ -0,0 +1,57 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dtrti2 computes the inverse of a triangular matrix, storing the result in place +// into a. This is the BLAS level 2 version of the algorithm. +// +// Dtrti2 is an internal routine. It is exported for testing purposes. +func (impl Implementation) Dtrti2(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) { + checkMatrix(n, n, a, lda) + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.NonUnit && diag != blas.Unit { + panic(badDiag) + } + bi := blas64.Implementation() + + nonUnit := diag == blas.NonUnit + // TODO(btracey): Replace this with a row-major ordering. + if uplo == blas.Upper { + for j := 0; j < n; j++ { + var ajj float64 + if nonUnit { + ajj = 1 / a[j*lda+j] + a[j*lda+j] = ajj + ajj *= -1 + } else { + ajj = -1 + } + bi.Dtrmv(blas.Upper, blas.NoTrans, diag, j, a, lda, a[j:], lda) + bi.Dscal(j, ajj, a[j:], lda) + } + return + } + for j := n - 1; j >= 0; j-- { + var ajj float64 + if nonUnit { + ajj = 1 / a[j*lda+j] + a[j*lda+j] = ajj + ajj *= -1 + } else { + ajj = -1 + } + if j < n-1 { + bi.Dtrmv(blas.Lower, blas.NoTrans, diag, n-j-1, a[(j+1)*lda+j+1:], lda, a[(j+1)*lda+j:], lda) + bi.Dscal(n-j-1, ajj, a[(j+1)*lda+j:], lda) + } + } +} diff --git a/lapack/native/dtrtri.go b/lapack/native/dtrtri.go new file mode 100644 index 00000000..5bc2cc0a --- /dev/null +++ b/lapack/native/dtrtri.go @@ -0,0 +1,64 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dtrtri computes the inverse of a triangular matrix, storing the result in place +// into a. This is the BLAS level 3 version of the algorithm which builds upon +// Dtrti2 to operate on matrix blocks instead of only individual columns. +// +// Dtrtri will not perform the inversion if the matrix is singular, and returns +// a boolean indicating whether the inversion was successful. +func (impl Implementation) Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) (ok bool) { + checkMatrix(n, n, a, lda) + if uplo != blas.Upper && uplo != blas.Lower { + panic(badUplo) + } + if diag != blas.NonUnit && diag != blas.Unit { + panic(badDiag) + } + if n == 0 { + return false + } + nonUnit := diag == blas.NonUnit + if nonUnit { + for i := 0; i < n; i++ { + if a[i*lda+i] == 0 { + return false + } + } + } + + bi := blas64.Implementation() + + nb := impl.Ilaenv(1, "DTRTRI", "UD", n, -1, -1, -1) + if nb <= 1 || nb > n { + impl.Dtrti2(uplo, diag, n, a, lda) + return true + } + if uplo == blas.Upper { + for j := 0; j < n; j += nb { + jb := min(nb, n-j) + bi.Dtrmm(blas.Left, blas.Upper, blas.NoTrans, diag, j, jb, 1, a, lda, a[j:], lda) + bi.Dtrsm(blas.Right, blas.Upper, blas.NoTrans, diag, j, jb, -1, a[j*lda+j:], lda, a[j:], lda) + impl.Dtrti2(blas.Upper, diag, jb, a[j*lda+j:], lda) + } + return true + } + nn := ((n - 1) / nb) * nb + for j := nn; j >= 0; j -= nb { + jb := min(nb, n-j) + if j+jb <= n-1 { + 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) + 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) + } + impl.Dtrti2(blas.Lower, diag, jb, a[j*lda+j:], lda) + } + return true +} diff --git a/lapack/native/dtrtrs.go b/lapack/native/dtrtrs.go new file mode 100644 index 00000000..8f4e2322 --- /dev/null +++ b/lapack/native/dtrtrs.go @@ -0,0 +1,30 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dtrtrs solves a triangular system of the form A * X = B or A^T * X = B. Dtrtrs +// returns whether the solve completed successfully. If A is singular, no solve is performed. +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) { + nounit := diag == blas.NonUnit + if n == 0 { + return false + } + // Check for singularity. + if nounit { + for i := 0; i < n; i++ { + if a[i*lda+i] == 0 { + return false + } + } + } + bi := blas64.Implementation() + bi.Dtrsm(blas.Left, uplo, trans, diag, n, nrhs, 1, a, lda, b, ldb) + return true +} diff --git a/lapack/native/general.go b/lapack/native/general.go new file mode 100644 index 00000000..0b2a1a65 --- /dev/null +++ b/lapack/native/general.go @@ -0,0 +1,130 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "gonum.org/v1/gonum/lapack" +) + +// Implementation is the native Go implementation of LAPACK routines. It +// is built on top of calls to the return of blas64.Implementation(), so while +// this code is in pure Go, the underlying BLAS implementation may not be. +type Implementation struct{} + +var _ lapack.Float64 = Implementation{} + +// This list is duplicated in lapack/cgo. Keep in sync. +const ( + absIncNotOne = "lapack: increment not one or negative one" + badAlpha = "lapack: bad alpha length" + badAuxv = "lapack: auxv has insufficient length" + badBeta = "lapack: bad beta length" + badD = "lapack: d has insufficient length" + badDecompUpdate = "lapack: bad decomp update" + badDiag = "lapack: bad diag" + badDims = "lapack: bad input dimensions" + badDirect = "lapack: bad direct" + badE = "lapack: e has insufficient length" + badEVComp = "lapack: bad EVComp" + badEVJob = "lapack: bad EVJob" + badEVSide = "lapack: bad EVSide" + badGSVDJob = "lapack: bad GSVDJob" + badHowMany = "lapack: bad HowMany" + badIlo = "lapack: ilo out of range" + badIhi = "lapack: ihi out of range" + badIpiv = "lapack: bad permutation length" + badJob = "lapack: bad Job" + badK1 = "lapack: k1 out of range" + badK2 = "lapack: k2 out of range" + badKperm = "lapack: incorrect permutation length" + badLdA = "lapack: index of a out of range" + badNb = "lapack: nb out of range" + badNorm = "lapack: bad norm" + badPivot = "lapack: bad pivot" + badS = "lapack: s has insufficient length" + badShifts = "lapack: bad shifts" + badSide = "lapack: bad side" + badSlice = "lapack: bad input slice length" + badSort = "lapack: bad Sort" + badStore = "lapack: bad store" + badTau = "lapack: tau has insufficient length" + badTauQ = "lapack: tauQ has insufficient length" + badTauP = "lapack: tauP has insufficient length" + badTrans = "lapack: bad trans" + badVn1 = "lapack: vn1 has insufficient length" + badVn2 = "lapack: vn2 has insufficient length" + badUplo = "lapack: illegal triangle" + badWork = "lapack: insufficient working memory" + badWorkStride = "lapack: insufficient working array stride" + badZ = "lapack: insufficient z length" + kGTM = "lapack: k > m" + kGTN = "lapack: k > n" + kLT0 = "lapack: k < 0" + mLT0 = "lapack: m < 0" + mLTN = "lapack: m < n" + nanScale = "lapack: NaN scale factor" + negDimension = "lapack: negative matrix dimension" + negZ = "lapack: negative z value" + nLT0 = "lapack: n < 0" + nLTM = "lapack: n < m" + offsetGTM = "lapack: offset > m" + shortWork = "lapack: working array shorter than declared" + zeroDiv = "lapack: zero divisor" +) + +// checkMatrix verifies the parameters of a matrix input. +func checkMatrix(m, n int, a []float64, lda int) { + if m < 0 { + panic("lapack: has negative number of rows") + } + if n < 0 { + panic("lapack: has negative number of columns") + } + if lda < n { + panic("lapack: stride less than number of columns") + } + if len(a) < (m-1)*lda+n { + panic("lapack: insufficient matrix slice length") + } +} + +func checkVector(n int, v []float64, inc int) { + if n < 0 { + panic("lapack: negative vector length") + } + if (inc > 0 && (n-1)*inc >= len(v)) || (inc < 0 && (1-n)*inc >= len(v)) { + panic("lapack: insufficient vector slice length") + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +const ( + // dlamchE is the machine epsilon. For IEEE this is 2^{-53}. + dlamchE = 1.0 / (1 << 53) + + // dlamchB is the radix of the machine (the base of the number system). + dlamchB = 2 + + // dlamchP is base * eps. + dlamchP = dlamchB * dlamchE + + // dlamchS is the "safe minimum", that is, the lowest number such that + // 1/dlamchS does not overflow, or also the smallest normal number. + // For IEEE this is 2^{-1022}. + dlamchS = 1.0 / (1 << 256) / (1 << 256) / (1 << 256) / (1 << 254) +) diff --git a/lapack/native/iladlc.go b/lapack/native/iladlc.go new file mode 100644 index 00000000..c7f06489 --- /dev/null +++ b/lapack/native/iladlc.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +// Iladlc scans a matrix for its last non-zero column. Returns -1 if the matrix +// is all zeros. +// +// Iladlc is an internal routine. It is exported for testing purposes. +func (Implementation) Iladlc(m, n int, a []float64, lda int) int { + if n == 0 || m == 0 { + return n - 1 + } + checkMatrix(m, n, a, lda) + + // Test common case where corner is non-zero. + if a[n-1] != 0 || a[(m-1)*lda+(n-1)] != 0 { + return n - 1 + } + + // Scan each row tracking the highest column seen. + highest := -1 + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + if a[i*lda+j] != 0 { + highest = max(highest, j) + break + } + } + } + return highest +} diff --git a/lapack/native/iladlr.go b/lapack/native/iladlr.go new file mode 100644 index 00000000..a488a496 --- /dev/null +++ b/lapack/native/iladlr.go @@ -0,0 +1,30 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +// Iladlr scans a matrix for its last non-zero row. Returns -1 if the matrix +// is all zeros. +// +// Iladlr is an internal routine. It is exported for testing purposes. +func (Implementation) Iladlr(m, n int, a []float64, lda int) int { + if m == 0 { + return m - 1 + } + + checkMatrix(m, n, a, lda) + + // Check the common case where the corner is non-zero + if a[(m-1)*lda] != 0 || a[(m-1)*lda+n-1] != 0 { + return m - 1 + } + for i := m - 1; i >= 0; i-- { + for j := 0; j < n; j++ { + if a[i*lda+j] != 0 { + return i + } + } + } + return -1 +} diff --git a/lapack/native/ilaenv.go b/lapack/native/ilaenv.go new file mode 100644 index 00000000..cdd42327 --- /dev/null +++ b/lapack/native/ilaenv.go @@ -0,0 +1,387 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +// Ilaenv returns algorithm tuning parameters for the algorithm given by the +// input string. ispec specifies the parameter to return: +// 1: The optimal block size for a blocked algorithm. +// 2: The minimum block size for a blocked algorithm. +// 3: The block size of unprocessed data at which a blocked algorithm should +// crossover to an unblocked version. +// 4: The number of shifts. +// 5: The minimum column dimension for blocking to be used. +// 6: The crossover point for SVD (to use QR factorization or not). +// 7: The number of processors. +// 8: The crossover point for multi-shift in QR and QZ methods for non-symmetric eigenvalue problems. +// 9: Maximum size of the subproblems in divide-and-conquer algorithms. +// 10: ieee NaN arithmetic can be trusted not to trap. +// 11: infinity arithmetic can be trusted not to trap. +// 12...16: parameters for Dhseqr and related functions. See Iparmq for more +// information. +// +// Ilaenv is an internal routine. It is exported for testing purposes. +func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, n4 int) int { + // TODO(btracey): Replace this with a constant lookup? A list of constants? + sname := s[0] == 'S' || s[0] == 'D' + cname := s[0] == 'C' || s[0] == 'Z' + if !sname && !cname { + panic("lapack: bad name") + } + c2 := s[1:3] + c3 := s[3:6] + c4 := c3[1:3] + + switch ispec { + default: + panic("lapack: bad ispec") + case 1: + switch c2 { + default: + panic("lapack: bad function name") + case "GE": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + return 64 + } + return 64 + case "QRF", "RQF", "LQF", "QLF": + if sname { + return 32 + } + return 32 + case "HRD": + if sname { + return 32 + } + return 32 + case "BRD": + if sname { + return 32 + } + return 32 + case "TRI": + if sname { + return 64 + } + return 64 + } + case "PO": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + return 64 + } + return 64 + } + case "SY": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + return 64 + } + return 64 + case "TRD": + return 32 + case "GST": + return 64 + } + case "HE": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + return 64 + case "TRD": + return 32 + case "GST": + return 64 + } + case "OR": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c3[1:] { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 32 + } + case 'M': + switch c3[1:] { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 32 + } + } + case "UN": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c3[1:] { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 32 + } + case 'M': + switch c3[1:] { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 32 + } + } + case "GB": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + if n4 <= 64 { + return 1 + } + return 32 + } + if n4 <= 64 { + return 1 + } + return 32 + } + case "PB": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + if n4 <= 64 { + return 1 + } + return 32 + } + if n4 <= 64 { + return 1 + } + return 32 + } + case "TR": + switch c3 { + default: + panic("lapack: bad function name") + case "TRI": + if sname { + return 64 + } + return 64 + case "EVC": + if sname { + return 64 + } + return 64 + } + case "LA": + switch c3 { + default: + panic("lapack: bad function name") + case "UUM": + if sname { + return 64 + } + return 64 + } + case "ST": + if sname && c3 == "EBZ" { + return 1 + } + panic("lapack: bad function name") + } + case 2: + switch c2 { + default: + panic("lapack: bad function name") + case "GE": + switch c3 { + default: + panic("lapack: bad function name") + case "QRF", "RQF", "LQF", "QLF": + if sname { + return 2 + } + return 2 + case "HRD": + if sname { + return 2 + } + return 2 + case "BRD": + if sname { + return 2 + } + return 2 + case "TRI": + if sname { + return 2 + } + return 2 + } + case "SY": + switch c3 { + default: + panic("lapack: bad function name") + case "TRF": + if sname { + return 8 + } + return 8 + case "TRD": + if sname { + return 2 + } + panic("lapack: bad function name") + } + case "HE": + if c3 == "TRD" { + return 2 + } + panic("lapack: bad function name") + case "OR": + if !sname { + panic("lapack: bad function name") + } + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 2 + } + case 'M': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 2 + } + } + case "UN": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 2 + } + case 'M': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 2 + } + } + } + case 3: + switch c2 { + default: + panic("lapack: bad function name") + case "GE": + switch c3 { + default: + panic("lapack: bad function name") + case "QRF", "RQF", "LQF", "QLF": + if sname { + return 128 + } + return 128 + case "HRD": + if sname { + return 128 + } + return 128 + case "BRD": + if sname { + return 128 + } + return 128 + } + case "SY": + if sname && c3 == "TRD" { + return 32 + } + panic("lapack: bad function name") + case "HE": + if c3 == "TRD" { + return 32 + } + panic("lapack: bad function name") + case "OR": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 128 + } + } + case "UN": + switch c3[0] { + default: + panic("lapack: bad function name") + case 'G': + switch c4 { + default: + panic("lapack: bad function name") + case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": + return 128 + } + } + } + case 4: + // Used by xHSEQR + return 6 + case 5: + // Not used + return 2 + case 6: + // Used by xGELSS and xGESVD + return int(float64(min(n1, n2)) * 1.6) + case 7: + // Not used + return 1 + case 8: + // Used by xHSEQR + return 50 + case 9: + // used by xGELSD and xGESDD + return 25 + case 10: + // Go guarantees ieee + return 1 + case 11: + // Go guarantees ieee + return 1 + case 12, 13, 14, 15, 16: + // Dhseqr and related functions for eigenvalue problems. + return impl.Iparmq(ispec, s, opts, n1, n2, n3, n4) + } +} diff --git a/lapack/native/iparmq.go b/lapack/native/iparmq.go new file mode 100644 index 00000000..48cb000f --- /dev/null +++ b/lapack/native/iparmq.go @@ -0,0 +1,115 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import "math" + +// Iparmq returns problem and machine dependent parameters useful for Dhseqr and +// related subroutines for eigenvalue problems. +// +// ispec specifies the parameter to return: +// 12: Crossover point between Dlahqr and Dlaqr0. Will be at least 11. +// 13: Deflation window size. +// 14: Nibble crossover point. Determines when to skip a multi-shift QR sweep. +// 15: Number of simultaneous shifts in a multishift QR iteration. +// 16: Select structured matrix multiply. +// For other values of ispec Iparmq will panic. +// +// name is the name of the calling function. name must be in uppercase but this +// is not checked. +// +// opts is not used and exists for future use. +// +// n is the order of the Hessenberg matrix H. +// +// ilo and ihi specify the block [ilo:ihi+1,ilo:ihi+1] that is being processed. +// +// lwork is the amount of workspace available. +// +// Except for ispec input parameters are not checked. +// +// Iparmq is an internal routine. It is exported for testing purposes. +func (Implementation) Iparmq(ispec int, name, opts string, n, ilo, ihi, lwork int) int { + nh := ihi - ilo + 1 + ns := 2 + switch { + case nh >= 30: + ns = 4 + case nh >= 60: + ns = 10 + case nh >= 150: + ns = max(10, nh/int(math.Log(float64(nh))/math.Ln2)) + case nh >= 590: + ns = 64 + case nh >= 3000: + ns = 128 + case nh >= 6000: + ns = 256 + } + ns = max(2, ns-(ns%2)) + + switch ispec { + default: + panic("lapack: bad ispec") + + case 12: + // Matrices of order smaller than nmin get sent to Dlahqr, the + // classic double shift algorithm. This must be at least 11. + const nmin = 75 + return nmin + + case 13: + const knwswp = 500 + if nh <= knwswp { + return ns + } + return 3 * ns / 2 + + case 14: + // Skip a computationally expensive multi-shift QR sweep with + // Dlaqr5 whenever aggressive early deflation finds at least + // nibble*(window size)/100 deflations. The default, small, + // value reflects the expectation that the cost of looking + // through the deflation window with Dlaqr3 will be + // substantially smaller. + const nibble = 14 + return nibble + + case 15: + return ns + + case 16: + if len(name) != 6 { + panic("lapack: bad name") + } + const ( + k22min = 14 + kacmin = 14 + ) + var acc22 int + switch { + case name[1:] == "GGHRD" || name[1:] == "GGHD3": + acc22 = 1 + if nh >= k22min { + acc22 = 2 + } + case name[3:] == "EXC": + if nh >= kacmin { + acc22 = 1 + } + if nh >= k22min { + acc22 = 2 + } + case name[1:] == "HSEQR" || name[1:5] == "LAQR": + if ns >= kacmin { + acc22 = 1 + } + if ns >= k22min { + acc22 = 2 + } + } + return acc22 + } +} diff --git a/lapack/native/lapack_test.go b/lapack/native/lapack_test.go new file mode 100644 index 00000000..46f1af71 --- /dev/null +++ b/lapack/native/lapack_test.go @@ -0,0 +1,429 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package native + +import ( + "testing" + + "gonum.org/v1/gonum/lapack/testlapack" +) + +var impl = Implementation{} + +func TestDbdsqr(t *testing.T) { + testlapack.DbdsqrTest(t, impl) +} + +func TestDhseqr(t *testing.T) { + testlapack.DhseqrTest(t, impl) +} + +func TestDgebak(t *testing.T) { + testlapack.DgebakTest(t, impl) +} + +func TestDgebal(t *testing.T) { + testlapack.DgebalTest(t, impl) +} + +func TestDgebd2(t *testing.T) { + testlapack.Dgebd2Test(t, impl) +} + +func TestDgebrd(t *testing.T) { + testlapack.DgebrdTest(t, impl) +} + +func TestDgecon(t *testing.T) { + testlapack.DgeconTest(t, impl) +} + +func TestDgeev(t *testing.T) { + testlapack.DgeevTest(t, impl) +} + +func TestDgehd2(t *testing.T) { + testlapack.Dgehd2Test(t, impl) +} + +func TestDgehrd(t *testing.T) { + testlapack.DgehrdTest(t, impl) +} + +func TestDgelqf(t *testing.T) { + testlapack.DgelqfTest(t, impl) +} + +func TestDgelq2(t *testing.T) { + testlapack.Dgelq2Test(t, impl) +} + +func TestDgeql2(t *testing.T) { + testlapack.Dgeql2Test(t, impl) +} + +func TestDgels(t *testing.T) { + testlapack.DgelsTest(t, impl) +} + +func TestDgerq2(t *testing.T) { + testlapack.Dgerq2Test(t, impl) +} + +func TestDgeqp3(t *testing.T) { + testlapack.Dgeqp3Test(t, impl) +} + +func TestDgeqr2(t *testing.T) { + testlapack.Dgeqr2Test(t, impl) +} + +func TestDgeqrf(t *testing.T) { + testlapack.DgeqrfTest(t, impl) +} + +func TestDgerqf(t *testing.T) { + testlapack.DgerqfTest(t, impl) +} + +func TestDgesvd(t *testing.T) { + testlapack.DgesvdTest(t, impl) +} + +func TestDgetri(t *testing.T) { + testlapack.DgetriTest(t, impl) +} + +func TestDgetf2(t *testing.T) { + testlapack.Dgetf2Test(t, impl) +} + +func TestDgetrf(t *testing.T) { + testlapack.DgetrfTest(t, impl) +} + +func TestDgetrs(t *testing.T) { + testlapack.DgetrsTest(t, impl) +} + +func TestDggsvd3(t *testing.T) { + testlapack.Dggsvd3Test(t, impl) +} + +func TestDggsvp3(t *testing.T) { + testlapack.Dggsvp3Test(t, impl) +} + +func TestDlabrd(t *testing.T) { + testlapack.DlabrdTest(t, impl) +} + +func TestDlacn2(t *testing.T) { + testlapack.Dlacn2Test(t, impl) +} + +func TestDlacpy(t *testing.T) { + testlapack.DlacpyTest(t, impl) +} + +func TestDlae2(t *testing.T) { + testlapack.Dlae2Test(t, impl) +} + +func TestDlaev2(t *testing.T) { + testlapack.Dlaev2Test(t, impl) +} + +func TestDlaexc(t *testing.T) { + testlapack.DlaexcTest(t, impl) +} + +func TestDlags2(t *testing.T) { + testlapack.Dlags2Test(t, impl) +} + +func TestDlahqr(t *testing.T) { + testlapack.DlahqrTest(t, impl) +} + +func TestDlahr2(t *testing.T) { + testlapack.Dlahr2Test(t, impl) +} + +func TestDlaln2(t *testing.T) { + testlapack.Dlaln2Test(t, impl) +} + +func TestDlange(t *testing.T) { + testlapack.DlangeTest(t, impl) +} + +func TestDlapy2(t *testing.T) { + testlapack.Dlapy2Test(t, impl) +} + +func TestDlapll(t *testing.T) { + testlapack.DlapllTest(t, impl) +} + +func TestDlapmt(t *testing.T) { + testlapack.DlapmtTest(t, impl) +} + +func TestDlas2(t *testing.T) { + testlapack.Dlas2Test(t, impl) +} + +func TestDlascl(t *testing.T) { + testlapack.DlasclTest(t, impl) +} + +func TestDlaset(t *testing.T) { + testlapack.DlasetTest(t, impl) +} + +func TestDlasrt(t *testing.T) { + testlapack.DlasrtTest(t, impl) +} + +func TestDlaswp(t *testing.T) { + testlapack.DlaswpTest(t, impl) +} + +func TestDlasy2(t *testing.T) { + testlapack.Dlasy2Test(t, impl) +} + +func TestDlanst(t *testing.T) { + testlapack.DlanstTest(t, impl) +} + +func TestDlansy(t *testing.T) { + testlapack.DlansyTest(t, impl) +} + +func TestDlantr(t *testing.T) { + testlapack.DlantrTest(t, impl) +} + +func TestDlanv2(t *testing.T) { + testlapack.Dlanv2Test(t, impl) +} + +func TestDlaqr04(t *testing.T) { + testlapack.Dlaqr04Test(t, impl) +} + +func TestDlaqp2(t *testing.T) { + testlapack.Dlaqp2Test(t, impl) +} + +func TestDlaqps(t *testing.T) { + testlapack.DlaqpsTest(t, impl) +} + +func TestDlaqr1(t *testing.T) { + testlapack.Dlaqr1Test(t, impl) +} + +func TestDlaqr23(t *testing.T) { + testlapack.Dlaqr23Test(t, impl) +} + +func TestDlaqr5(t *testing.T) { + testlapack.Dlaqr5Test(t, impl) +} + +func TestDlarf(t *testing.T) { + testlapack.DlarfTest(t, impl) +} + +func TestDlarfb(t *testing.T) { + testlapack.DlarfbTest(t, impl) +} + +func TestDlarfg(t *testing.T) { + testlapack.DlarfgTest(t, impl) +} + +func TestDlarft(t *testing.T) { + testlapack.DlarftTest(t, impl) +} + +func TestDlarfx(t *testing.T) { + testlapack.DlarfxTest(t, impl) +} + +func TestDlartg(t *testing.T) { + testlapack.DlartgTest(t, impl) +} + +func TestDlasq1(t *testing.T) { + testlapack.Dlasq1Test(t, impl) +} + +func TestDlasq2(t *testing.T) { + testlapack.Dlasq2Test(t, impl) +} + +func TestDlasq3(t *testing.T) { + testlapack.Dlasq3Test(t, impl) +} + +func TestDlasq4(t *testing.T) { + testlapack.Dlasq4Test(t, impl) +} + +func TestDlasq5(t *testing.T) { + testlapack.Dlasq5Test(t, impl) +} + +func TestDlasr(t *testing.T) { + testlapack.DlasrTest(t, impl) +} + +func TestDlasv2(t *testing.T) { + testlapack.Dlasv2Test(t, impl) +} + +func TestDlatrd(t *testing.T) { + testlapack.DlatrdTest(t, impl) +} + +func TestDlatrs(t *testing.T) { + testlapack.DlatrsTest(t, impl) +} + +func TestDorg2r(t *testing.T) { + testlapack.Dorg2rTest(t, impl) +} + +func TestDorgbr(t *testing.T) { + testlapack.DorgbrTest(t, impl) +} + +func TestDorghr(t *testing.T) { + testlapack.DorghrTest(t, impl) +} + +func TestDorg2l(t *testing.T) { + testlapack.Dorg2lTest(t, impl) +} + +func TestDorgl2(t *testing.T) { + testlapack.Dorgl2Test(t, impl) +} + +func TestDorglq(t *testing.T) { + testlapack.DorglqTest(t, impl) +} + +func TestDorgql(t *testing.T) { + testlapack.DorgqlTest(t, impl) +} + +func TestDorgqr(t *testing.T) { + testlapack.DorgqrTest(t, impl) +} + +func TestDorgtr(t *testing.T) { + testlapack.DorgtrTest(t, impl) +} + +func TestDormbr(t *testing.T) { + testlapack.DormbrTest(t, impl) +} + +func TestDormhr(t *testing.T) { + testlapack.DormhrTest(t, impl) +} + +func TestDorml2(t *testing.T) { + testlapack.Dorml2Test(t, impl) +} + +func TestDormlq(t *testing.T) { + testlapack.DormlqTest(t, impl) +} + +func TestDormqr(t *testing.T) { + testlapack.DormqrTest(t, impl) +} + +func TestDormr2(t *testing.T) { + testlapack.Dormr2Test(t, impl) +} + +func TestDorm2r(t *testing.T) { + testlapack.Dorm2rTest(t, impl) +} + +func TestDpocon(t *testing.T) { + testlapack.DpoconTest(t, impl) +} + +func TestDpotf2(t *testing.T) { + testlapack.Dpotf2Test(t, impl) +} + +func TestDpotrf(t *testing.T) { + testlapack.DpotrfTest(t, impl) +} + +func TestDrscl(t *testing.T) { + testlapack.DrsclTest(t, impl) +} + +func TestDsteqr(t *testing.T) { + testlapack.DsteqrTest(t, impl) +} + +func TestDsterf(t *testing.T) { + testlapack.DsterfTest(t, impl) +} + +func TestDsyev(t *testing.T) { + testlapack.DsyevTest(t, impl) +} + +func TestDsytd2(t *testing.T) { + testlapack.Dsytd2Test(t, impl) +} + +func TestDsytrd(t *testing.T) { + testlapack.DsytrdTest(t, impl) +} + +func TestDtgsja(t *testing.T) { + testlapack.DtgsjaTest(t, impl) +} + +func TestDtrcon(t *testing.T) { + testlapack.DtrconTest(t, impl) +} + +func TestDtrevc3(t *testing.T) { + testlapack.Dtrevc3Test(t, impl) +} + +func TestDtrexc(t *testing.T) { + testlapack.DtrexcTest(t, impl) +} + +func TestDtrti2(t *testing.T) { + testlapack.Dtrti2Test(t, impl) +} + +func TestDtrtri(t *testing.T) { + testlapack.DtrtriTest(t, impl) +} + +func TestIladlc(t *testing.T) { + testlapack.IladlcTest(t, impl) +} + +func TestIladlr(t *testing.T) { + testlapack.IladlrTest(t, impl) +} diff --git a/lapack/testlapack/dbdsqr.go b/lapack/testlapack/dbdsqr.go new file mode 100644 index 00000000..8a09e3ac --- /dev/null +++ b/lapack/testlapack/dbdsqr.go @@ -0,0 +1,198 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dbdsqrer interface { + Dbdsqr(uplo blas.Uplo, n, ncvt, nru, ncc int, d, e, vt []float64, ldvt int, u []float64, ldu int, c []float64, ldc int, work []float64) (ok bool) +} + +func DbdsqrTest(t *testing.T, impl Dbdsqrer) { + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + _ = bi + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, test := range []struct { + n, ncvt, nru, ncc, ldvt, ldu, ldc int + }{ + {5, 5, 5, 5, 0, 0, 0}, + {10, 10, 10, 10, 0, 0, 0}, + {10, 11, 12, 13, 0, 0, 0}, + {20, 13, 12, 11, 0, 0, 0}, + + {5, 5, 5, 5, 6, 7, 8}, + {10, 10, 10, 10, 30, 40, 50}, + {10, 12, 11, 13, 30, 40, 50}, + {20, 12, 13, 11, 30, 40, 50}, + + {130, 130, 130, 500, 900, 900, 500}, + } { + for cas := 0; cas < 100; cas++ { + n := test.n + ncvt := test.ncvt + nru := test.nru + ncc := test.ncc + ldvt := test.ldvt + ldu := test.ldu + ldc := test.ldc + if ldvt == 0 { + ldvt = ncvt + } + if ldu == 0 { + ldu = n + } + if ldc == 0 { + ldc = ncc + } + + d := make([]float64, n) + for i := range d { + d[i] = rnd.NormFloat64() + } + e := make([]float64, n-1) + for i := range e { + e[i] = rnd.NormFloat64() + } + dCopy := make([]float64, len(d)) + copy(dCopy, d) + eCopy := make([]float64, len(e)) + copy(eCopy, e) + work := make([]float64, 4*n) + for i := range work { + work[i] = rnd.NormFloat64() + } + + // First test the decomposition of the bidiagonal matrix. Set + // pt and u equal to I with the correct size. At the result + // of Dbdsqr, p and u will contain the data of P^T and Q, which + // will be used in the next step to test the multiplication + // with Q and VT. + + q := make([]float64, n*n) + ldq := n + pt := make([]float64, n*n) + ldpt := n + for i := 0; i < n; i++ { + q[i*ldq+i] = 1 + } + for i := 0; i < n; i++ { + pt[i*ldpt+i] = 1 + } + + ok := impl.Dbdsqr(uplo, n, n, n, 0, d, e, pt, ldpt, q, ldq, nil, 0, work) + + isUpper := uplo == blas.Upper + errStr := fmt.Sprintf("isUpper = %v, n = %v, ncvt = %v, nru = %v, ncc = %v", isUpper, n, ncvt, nru, ncc) + if !ok { + t.Errorf("Unexpected Dbdsqr failure: %s", errStr) + } + + bMat := constructBidiagonal(uplo, n, dCopy, eCopy) + sMat := constructBidiagonal(uplo, n, d, e) + + tmp := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + ansMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, q, ldq, sMat.Data, sMat.Stride, 0, tmp.Data, tmp.Stride) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, tmp.Data, tmp.Stride, pt, ldpt, 0, ansMat.Data, ansMat.Stride) + + same := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if !floats.EqualWithinAbsOrRel(ansMat.Data[i*ansMat.Stride+j], bMat.Data[i*bMat.Stride+j], 1e-8, 1e-8) { + same = false + } + } + } + if !same { + t.Errorf("Bidiagonal mismatch. %s", errStr) + } + if !sort.IsSorted(sort.Reverse(sort.Float64Slice(d))) { + t.Errorf("D is not sorted. %s", errStr) + } + + // The above computed the real P and Q. Now input data for V^T, + // U, and C to check that the multiplications happen properly. + dAns := make([]float64, len(d)) + copy(dAns, d) + eAns := make([]float64, len(e)) + copy(eAns, e) + + u := make([]float64, nru*ldu) + for i := range u { + u[i] = rnd.NormFloat64() + } + uCopy := make([]float64, len(u)) + copy(uCopy, u) + vt := make([]float64, n*ldvt) + for i := range vt { + vt[i] = rnd.NormFloat64() + } + vtCopy := make([]float64, len(vt)) + copy(vtCopy, vt) + c := make([]float64, n*ldc) + for i := range c { + c[i] = rnd.NormFloat64() + } + cCopy := make([]float64, len(c)) + copy(cCopy, c) + + // Reset input data + copy(d, dCopy) + copy(e, eCopy) + impl.Dbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work) + + // Check result. + if !floats.EqualApprox(d, dAns, 1e-14) { + t.Errorf("D mismatch second time. %s", errStr) + } + if !floats.EqualApprox(e, eAns, 1e-14) { + t.Errorf("E mismatch second time. %s", errStr) + } + ans := make([]float64, len(vtCopy)) + copy(ans, vtCopy) + ldans := ldvt + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, ncvt, n, 1, pt, ldpt, vtCopy, ldvt, 0, ans, ldans) + if !floats.EqualApprox(ans, vt, 1e-10) { + t.Errorf("Vt result mismatch. %s", errStr) + } + ans = make([]float64, len(uCopy)) + copy(ans, uCopy) + ldans = ldu + bi.Dgemm(blas.NoTrans, blas.NoTrans, nru, n, n, 1, uCopy, ldu, q, ldq, 0, ans, ldans) + if !floats.EqualApprox(ans, u, 1e-10) { + t.Errorf("U result mismatch. %s", errStr) + } + ans = make([]float64, len(cCopy)) + copy(ans, cCopy) + ldans = ldc + bi.Dgemm(blas.Trans, blas.NoTrans, n, ncc, n, 1, q, ldq, cCopy, ldc, 0, ans, ldans) + if !floats.EqualApprox(ans, c, 1e-10) { + t.Errorf("C result mismatch. %s", errStr) + } + } + } + } +} diff --git a/lapack/testlapack/dgebak.go b/lapack/testlapack/dgebak.go new file mode 100644 index 00000000..7d1030a4 --- /dev/null +++ b/lapack/testlapack/dgebak.go @@ -0,0 +1,110 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dgebaker interface { + Dgebak(job lapack.Job, side lapack.EVSide, n, ilo, ihi int, scale []float64, m int, v []float64, ldv int) +} + +func DgebakTest(t *testing.T, impl Dgebaker) { + rnd := rand.New(rand.NewSource(1)) + + for _, job := range []lapack.Job{lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale} { + for _, side := range []lapack.EVSide{lapack.LeftEV, lapack.RightEV} { + for _, n := range []int{0, 1, 2, 3, 4, 5, 6, 10, 18, 31, 53} { + for _, extra := range []int{0, 11} { + for cas := 0; cas < 100; cas++ { + m := rnd.Intn(n + 1) + v := randomGeneral(n, m, m+extra, rnd) + var ilo, ihi int + if v.Rows > 0 { + ihi = rnd.Intn(n) + ilo = rnd.Intn(ihi + 1) + } else { + ihi = -1 + } + testDgebak(t, impl, job, side, ilo, ihi, v, rnd) + } + } + } + } + } +} + +func testDgebak(t *testing.T, impl Dgebaker, job lapack.Job, side lapack.EVSide, ilo, ihi int, v blas64.General, rnd *rand.Rand) { + const tol = 1e-15 + n := v.Rows + m := v.Cols + extra := v.Stride - v.Cols + + // Create D and D^{-1} by generating random scales between ilo and ihi. + d := eye(n, n) + dinv := eye(n, n) + scale := nanSlice(n) + if job == lapack.Scale || job == lapack.PermuteScale { + if ilo == ihi { + scale[ilo] = 1 + } else { + for i := ilo; i <= ihi; i++ { + scale[i] = 2 * rnd.Float64() + d.Data[i*d.Stride+i] = scale[i] + dinv.Data[i*dinv.Stride+i] = 1 / scale[i] + } + } + } + + // Create P by generating random column swaps. + p := eye(n, n) + if job == lapack.Permute || job == lapack.PermuteScale { + // Make up some random permutations. + for i := n - 1; i > ihi; i-- { + scale[i] = float64(rnd.Intn(i + 1)) + blas64.Swap(n, + blas64.Vector{p.Stride, p.Data[i:]}, + blas64.Vector{p.Stride, p.Data[int(scale[i]):]}) + } + for i := 0; i < ilo; i++ { + scale[i] = float64(i + rnd.Intn(ihi-i+1)) + blas64.Swap(n, + blas64.Vector{p.Stride, p.Data[i:]}, + blas64.Vector{p.Stride, p.Data[int(scale[i]):]}) + } + } + + got := cloneGeneral(v) + impl.Dgebak(job, side, n, ilo, ihi, scale, m, got.Data, got.Stride) + + prefix := fmt.Sprintf("Case job=%v, side=%v, n=%v, ilo=%v, ihi=%v, m=%v, extra=%v", + job, side, n, ilo, ihi, m, extra) + + if !generalOutsideAllNaN(got) { + t.Errorf("%v: out-of-range write to V\n%v", prefix, got.Data) + } + + // Compute D*V or D^{-1}*V and store into dv. + dv := zeros(n, m, m) + if side == lapack.RightEV { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d, v, 0, dv) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, dinv, v, 0, dv) + } + // Compute P*D*V or P*D^{-1}*V and store into want. + want := zeros(n, m, m) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, p, dv, 0, want) + + if !equalApproxGeneral(want, got, tol) { + t.Errorf("%v: unexpected value of V", prefix) + } +} diff --git a/lapack/testlapack/dgebal.go b/lapack/testlapack/dgebal.go new file mode 100644 index 00000000..eecd6914 --- /dev/null +++ b/lapack/testlapack/dgebal.go @@ -0,0 +1,175 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dgebaler interface { + Dgebal(job lapack.Job, n int, a []float64, lda int, scale []float64) (int, int) +} + +func DgebalTest(t *testing.T, impl Dgebaler) { + rnd := rand.New(rand.NewSource(1)) + + for _, job := range []lapack.Job{lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale} { + for _, n := range []int{0, 1, 2, 3, 4, 5, 6, 10, 18, 31, 53, 100} { + for _, extra := range []int{0, 11} { + for cas := 0; cas < 100; cas++ { + a := unbalancedSparseGeneral(n, n, n+extra, 2*n, rnd) + testDgebal(t, impl, job, a) + } + } + } + } +} + +func testDgebal(t *testing.T, impl Dgebaler, job lapack.Job, a blas64.General) { + const tol = 1e-14 + + n := a.Rows + extra := a.Stride - n + + var scale []float64 + if n > 0 { + scale = nanSlice(n) + } + + want := cloneGeneral(a) + + ilo, ihi := impl.Dgebal(job, n, a.Data, a.Stride, scale) + + prefix := fmt.Sprintf("Case job=%v, n=%v, extra=%v", job, n, extra) + + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + + if n == 0 { + if ilo != 0 { + t.Errorf("%v: unexpected ilo when n=0. Want 0, got %v", prefix, n, ilo) + } + if ihi != -1 { + t.Errorf("%v: unexpected ihi when n=0. Want -1, got %v", prefix, n, ihi) + } + return + } + + if job == lapack.None { + if ilo != 0 { + t.Errorf("%v: unexpected ilo when job=None. Want 0, got %v", prefix, ilo) + } + if ihi != n-1 { + t.Errorf("%v: unexpected ihi when job=None. Want %v, got %v", prefix, n-1, ihi) + } + k := -1 + for i := range scale { + if scale[i] != 1 { + k = i + break + } + } + if k != -1 { + t.Errorf("%v: unexpected scale[%v] when job=None. Want 1, got %v", prefix, k, scale[k]) + } + if !equalApproxGeneral(a, want, 0) { + t.Errorf("%v: unexpected modification of A when job=None", prefix) + } + return + } + + if ilo < 0 || ihi < ilo || n <= ihi { + t.Errorf("%v: invalid ordering of ilo=%v and ihi=%v", prefix, ilo, ihi) + } + + if ilo >= 2 && !isUpperTriangular(blas64.General{ilo - 1, ilo - 1, a.Stride, a.Data}) { + t.Errorf("%v: T1 is not upper triangular", prefix) + } + m := n - ihi - 1 // Order of T2. + k := ihi + 1 + if m >= 2 && !isUpperTriangular(blas64.General{m, m, a.Stride, a.Data[k*a.Stride+k:]}) { + t.Errorf("%v: T2 is not upper triangular", prefix) + } + + if job == lapack.Permute || job == lapack.PermuteScale { + // Check that all rows in [ilo:ihi+1] have at least one nonzero + // off-diagonal element. + zeroRow := -1 + for i := ilo; i <= ihi; i++ { + onlyZeros := true + for j := ilo; j <= ihi; j++ { + if i != j && a.Data[i*a.Stride+j] != 0 { + onlyZeros = false + break + } + } + if onlyZeros { + zeroRow = i + break + } + } + if zeroRow != -1 && ilo != ihi { + t.Errorf("%v: row %v has only zero off-diagonal elements, ilo=%v, ihi=%v", prefix, zeroRow, ilo, ihi) + } + // Check that all columns in [ilo:ihi+1] have at least one nonzero + // off-diagonal element. + zeroCol := -1 + for j := ilo; j <= ihi; j++ { + onlyZeros := true + for i := ilo; i <= ihi; i++ { + if i != j && a.Data[i*a.Stride+j] != 0 { + onlyZeros = false + break + } + } + if onlyZeros { + zeroCol = j + break + } + } + if zeroCol != -1 && ilo != ihi { + t.Errorf("%v: column %v has only zero off-diagonal elements, ilo=%v, ihi=%v", prefix, zeroCol, ilo, ihi) + } + + // Create the permutation matrix P. + p := eye(n, n) + for j := n - 1; j > ihi; j-- { + blas64.Swap(n, + blas64.Vector{p.Stride, p.Data[j:]}, + blas64.Vector{p.Stride, p.Data[int(scale[j]):]}) + } + for j := 0; j < ilo; j++ { + blas64.Swap(n, + blas64.Vector{p.Stride, p.Data[j:]}, + blas64.Vector{p.Stride, p.Data[int(scale[j]):]}) + } + // Compute P^T*A*P and store into want. + ap := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, want, p, 0, ap) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, p, ap, 0, want) + } + if job == lapack.Scale || job == lapack.PermuteScale { + // Modify want by D and D^{-1}. + d := eye(n, n) + dinv := eye(n, n) + for i := ilo; i <= ihi; i++ { + d.Data[i*d.Stride+i] = scale[i] + dinv.Data[i*dinv.Stride+i] = 1 / scale[i] + } + ad := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, want, d, 0, ad) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, dinv, ad, 0, want) + } + if !equalApproxGeneral(want, a, tol) { + t.Errorf("%v: unexpected value of A, ilo=%v, ihi=%v", prefix, ilo, ihi) + } +} diff --git a/lapack/testlapack/dgebd2.go b/lapack/testlapack/dgebd2.go new file mode 100644 index 00000000..f122c407 --- /dev/null +++ b/lapack/testlapack/dgebd2.go @@ -0,0 +1,54 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" +) + +type Dgebd2er interface { + Dgebd2(m, n int, a []float64, lda int, d, e, tauq, taup, work []float64) +} + +func Dgebd2Test(t *testing.T, impl Dgebd2er) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {3, 4, 0}, + {4, 3, 0}, + {3, 4, 10}, + {4, 3, 10}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + nb := min(m, n) // 'nb' name parallel with Dlabrd code. + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + d := nanSlice(nb) + e := nanSlice(nb - 1) + tauP := nanSlice(nb) + tauQ := nanSlice(nb) + work := nanSlice(max(m, n)) + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dgebd2(m, n, a, lda, d, e, tauQ, tauP, work) + if m >= n && nb == n { + tauP[n-1] = 0 + } + if m < n && nb == m { + tauQ[m-1] = 0 + } + + checkBidiagonal(t, m, n, nb, a, lda, d, e, tauP, tauQ, aCopy) + } +} diff --git a/lapack/testlapack/dgebrd.go b/lapack/testlapack/dgebrd.go new file mode 100644 index 00000000..0bbba460 --- /dev/null +++ b/lapack/testlapack/dgebrd.go @@ -0,0 +1,151 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dgebrder interface { + Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64, lwork int) + Dgebd2er +} + +func DgebrdTest(t *testing.T, impl Dgebrder) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {100, 100, 0}, + {100, 150, 0}, + {150, 100, 0}, + {100, 100, 200}, + {100, 150, 200}, + {150, 100, 200}, + + {300, 300, 0}, + {300, 400, 0}, + {400, 300, 0}, + {300, 300, 500}, + {300, 400, 500}, + {300, 400, 500}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + minmn := min(m, n) + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + d := make([]float64, minmn) + e := make([]float64, minmn-1) + tauP := make([]float64, minmn) + tauQ := make([]float64, minmn) + work := make([]float64, max(m, n)) + for i := range work { + work[i] = math.NaN() + } + + // Store a. + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + // Compute the true answer with the unblocked algorithm. + impl.Dgebd2(m, n, a, lda, d, e, tauQ, tauP, work) + aAns := make([]float64, len(a)) + copy(aAns, a) + dAns := make([]float64, len(d)) + copy(dAns, d) + eAns := make([]float64, len(e)) + copy(eAns, e) + tauQAns := make([]float64, len(tauQ)) + copy(tauQAns, tauQ) + tauPAns := make([]float64, len(tauP)) + copy(tauPAns, tauP) + + // Test with optimal work. + lwork := -1 + copy(a, aCopy) + impl.Dgebrd(m, n, a, lda, d, e, tauQ, tauP, work, lwork) + work = make([]float64, int(work[0])) + lwork = len(work) + for i := range work { + work[i] = math.NaN() + } + for i := range d { + d[i] = math.NaN() + } + for i := range e { + e[i] = math.NaN() + } + for i := range tauQ { + tauQ[i] = math.NaN() + } + for i := range tauP { + tauP[i] = math.NaN() + } + impl.Dgebrd(m, n, a, lda, d, e, tauQ, tauP, work, lwork) + + // Test answers + if !floats.EqualApprox(a, aAns, 1e-10) { + t.Errorf("a mismatch") + } + if !floats.EqualApprox(d, dAns, 1e-10) { + t.Errorf("d mismatch") + } + if !floats.EqualApprox(e, eAns, 1e-10) { + t.Errorf("e mismatch") + } + if !floats.EqualApprox(tauQ, tauQAns, 1e-10) { + t.Errorf("tauQ mismatch") + } + if !floats.EqualApprox(tauP, tauPAns, 1e-10) { + t.Errorf("tauP mismatch") + } + + // Test with shorter than optimal work. + lwork-- + copy(a, aCopy) + for i := range d { + d[i] = 0 + } + for i := range e { + e[i] = 0 + } + for i := range tauP { + tauP[i] = 0 + } + for i := range tauQ { + tauQ[i] = 0 + } + impl.Dgebrd(m, n, a, lda, d, e, tauQ, tauP, work, lwork) + + // Test answers + if !floats.EqualApprox(a, aAns, 1e-10) { + t.Errorf("a mismatch") + } + if !floats.EqualApprox(d, dAns, 1e-10) { + t.Errorf("d mismatch") + } + if !floats.EqualApprox(e, eAns, 1e-10) { + t.Errorf("e mismatch") + } + if !floats.EqualApprox(tauQ, tauQAns, 1e-10) { + t.Errorf("tauQ mismatch") + } + if !floats.EqualApprox(tauP, tauPAns, 1e-10) { + t.Errorf("tauP mismatch") + } + } +} diff --git a/lapack/testlapack/dgecon.go b/lapack/testlapack/dgecon.go new file mode 100644 index 00000000..bbb76284 --- /dev/null +++ b/lapack/testlapack/dgecon.go @@ -0,0 +1,97 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "log" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dgeconer interface { + Dlanger + Dgetrfer + Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 +} + +func DgeconTest(t *testing.T, impl Dgeconer) { + for _, test := range []struct { + m int + n int + a []float64 + condOne float64 + condInf float64 + }{ + { + a: []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + }, + m: 3, + n: 3, + condOne: 3.0 / 16, + condInf: 3.0 / 16, + }, + { + a: []float64{ + 2, 9, 3, 2, + 10, 9, 9, 3, + 1, 1, 5, 2, + 8, 4, 10, 2, + }, + m: 4, + n: 4, + condOne: 0.024740155174938, + condInf: 0.012034465570035, + }, + // Dgecon does not match Dpocon for this case. https://github.com/xianyi/OpenBLAS/issues/664. + { + a: []float64{ + 2.9995576045549965, -2.0898894566158663, 3.965560740124006, + -2.0898894566158663, 1.9634729526261008, -2.8681002706874104, + 3.965560740124006, -2.8681002706874104, 5.502416670471008, + }, + m: 3, + n: 3, + condOne: 0.024054837369015203, + condInf: 0.024054837369015203, + }, + } { + m := test.m + n := test.n + lda := n + a := make([]float64, len(test.a)) + copy(a, test.a) + ipiv := make([]int, min(m, n)) + + // Find the norms of the original matrix. + work := make([]float64, 4*n) + oneNorm := impl.Dlange(lapack.MaxColumnSum, m, n, a, lda, work) + infNorm := impl.Dlange(lapack.MaxRowSum, m, n, a, lda, work) + + // Compute LU factorization of a. + impl.Dgetrf(m, n, a, lda, ipiv) + + // Compute the condition number + iwork := make([]int, n) + condOne := impl.Dgecon(lapack.MaxColumnSum, n, a, lda, oneNorm, work, iwork) + condInf := impl.Dgecon(lapack.MaxRowSum, n, a, lda, infNorm, work, iwork) + + // Error if not the same order, otherwise log the difference. + if !floats.EqualWithinAbsOrRel(condOne, test.condOne, 1e0, 1e0) { + t.Errorf("One norm mismatch. Want %v, got %v.", test.condOne, condOne) + } else if !floats.EqualWithinAbsOrRel(condOne, test.condOne, 1e-14, 1e-14) { + log.Printf("Dgecon one norm mismatch. Want %v, got %v.", test.condOne, condOne) + } + if !floats.EqualWithinAbsOrRel(condInf, test.condInf, 1e0, 1e0) { + t.Errorf("One norm mismatch. Want %v, got %v.", test.condInf, condInf) + } else if !floats.EqualWithinAbsOrRel(condInf, test.condInf, 1e-14, 1e-14) { + log.Printf("Dgecon one norm mismatch. Want %v, got %v.", test.condInf, condInf) + } + } +} diff --git a/lapack/testlapack/dgeev.go b/lapack/testlapack/dgeev.go new file mode 100644 index 00000000..9b3d8fc1 --- /dev/null +++ b/lapack/testlapack/dgeev.go @@ -0,0 +1,735 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/cmplx" + "math/rand" + "strconv" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dgeever interface { + Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, n int, a []float64, lda int, + wr, wi []float64, vl []float64, ldvl int, vr []float64, ldvr int, work []float64, lwork int) int +} + +type dgeevTest struct { + a blas64.General + evWant []complex128 // If nil, the eigenvalues are not known. + valTol float64 // Tolerance for eigenvalue checks. + vecTol float64 // Tolerance for eigenvector checks. +} + +func DgeevTest(t *testing.T, impl Dgeever) { + rnd := rand.New(rand.NewSource(1)) + + for i, test := range []dgeevTest{ + { + a: A123{}.Matrix(), + evWant: A123{}.Eigenvalues(), + }, + + dgeevTestForAntisymRandom(10, rnd), + dgeevTestForAntisymRandom(11, rnd), + dgeevTestForAntisymRandom(50, rnd), + dgeevTestForAntisymRandom(51, rnd), + dgeevTestForAntisymRandom(100, rnd), + dgeevTestForAntisymRandom(101, rnd), + + { + a: Circulant(2).Matrix(), + evWant: Circulant(2).Eigenvalues(), + }, + { + a: Circulant(3).Matrix(), + evWant: Circulant(3).Eigenvalues(), + }, + { + a: Circulant(4).Matrix(), + evWant: Circulant(4).Eigenvalues(), + }, + { + a: Circulant(5).Matrix(), + evWant: Circulant(5).Eigenvalues(), + }, + { + a: Circulant(10).Matrix(), + evWant: Circulant(10).Eigenvalues(), + }, + { + a: Circulant(15).Matrix(), + evWant: Circulant(15).Eigenvalues(), + valTol: 1e-12, + }, + { + a: Circulant(30).Matrix(), + evWant: Circulant(30).Eigenvalues(), + valTol: 1e-11, + vecTol: 1e-12, + }, + { + a: Circulant(50).Matrix(), + evWant: Circulant(50).Eigenvalues(), + valTol: 1e-11, + vecTol: 1e-12, + }, + { + a: Circulant(101).Matrix(), + evWant: Circulant(101).Eigenvalues(), + valTol: 1e-10, + vecTol: 1e-11, + }, + { + a: Circulant(150).Matrix(), + evWant: Circulant(150).Eigenvalues(), + valTol: 1e-9, + vecTol: 1e-10, + }, + + { + a: Clement(2).Matrix(), + evWant: Clement(2).Eigenvalues(), + }, + { + a: Clement(3).Matrix(), + evWant: Clement(3).Eigenvalues(), + }, + { + a: Clement(4).Matrix(), + evWant: Clement(4).Eigenvalues(), + }, + { + a: Clement(5).Matrix(), + evWant: Clement(5).Eigenvalues(), + }, + { + a: Clement(10).Matrix(), + evWant: Clement(10).Eigenvalues(), + }, + { + a: Clement(15).Matrix(), + evWant: Clement(15).Eigenvalues(), + }, + { + a: Clement(30).Matrix(), + evWant: Clement(30).Eigenvalues(), + valTol: 1e-11, + }, + { + a: Clement(50).Matrix(), + evWant: Clement(50).Eigenvalues(), + valTol: 1e-7, + vecTol: 1e-11, + }, + + { + a: Creation(2).Matrix(), + evWant: Creation(2).Eigenvalues(), + }, + { + a: Creation(3).Matrix(), + evWant: Creation(3).Eigenvalues(), + }, + { + a: Creation(4).Matrix(), + evWant: Creation(4).Eigenvalues(), + }, + { + a: Creation(5).Matrix(), + evWant: Creation(5).Eigenvalues(), + }, + { + a: Creation(10).Matrix(), + evWant: Creation(10).Eigenvalues(), + }, + { + a: Creation(15).Matrix(), + evWant: Creation(15).Eigenvalues(), + }, + { + a: Creation(30).Matrix(), + evWant: Creation(30).Eigenvalues(), + }, + { + a: Creation(50).Matrix(), + evWant: Creation(50).Eigenvalues(), + }, + { + a: Creation(101).Matrix(), + evWant: Creation(101).Eigenvalues(), + }, + { + a: Creation(150).Matrix(), + evWant: Creation(150).Eigenvalues(), + }, + + { + a: Diagonal(0).Matrix(), + evWant: Diagonal(0).Eigenvalues(), + }, + { + a: Diagonal(10).Matrix(), + evWant: Diagonal(10).Eigenvalues(), + }, + { + a: Diagonal(50).Matrix(), + evWant: Diagonal(50).Eigenvalues(), + }, + { + a: Diagonal(151).Matrix(), + evWant: Diagonal(151).Eigenvalues(), + }, + + { + a: Downshift(2).Matrix(), + evWant: Downshift(2).Eigenvalues(), + }, + { + a: Downshift(3).Matrix(), + evWant: Downshift(3).Eigenvalues(), + }, + { + a: Downshift(4).Matrix(), + evWant: Downshift(4).Eigenvalues(), + }, + { + a: Downshift(5).Matrix(), + evWant: Downshift(5).Eigenvalues(), + }, + { + a: Downshift(10).Matrix(), + evWant: Downshift(10).Eigenvalues(), + }, + { + a: Downshift(15).Matrix(), + evWant: Downshift(15).Eigenvalues(), + }, + { + a: Downshift(30).Matrix(), + evWant: Downshift(30).Eigenvalues(), + }, + { + a: Downshift(50).Matrix(), + evWant: Downshift(50).Eigenvalues(), + }, + { + a: Downshift(101).Matrix(), + evWant: Downshift(101).Eigenvalues(), + }, + { + a: Downshift(150).Matrix(), + evWant: Downshift(150).Eigenvalues(), + }, + + { + a: Fibonacci(2).Matrix(), + evWant: Fibonacci(2).Eigenvalues(), + }, + { + a: Fibonacci(3).Matrix(), + evWant: Fibonacci(3).Eigenvalues(), + }, + { + a: Fibonacci(4).Matrix(), + evWant: Fibonacci(4).Eigenvalues(), + }, + { + a: Fibonacci(5).Matrix(), + evWant: Fibonacci(5).Eigenvalues(), + }, + { + a: Fibonacci(10).Matrix(), + evWant: Fibonacci(10).Eigenvalues(), + }, + { + a: Fibonacci(15).Matrix(), + evWant: Fibonacci(15).Eigenvalues(), + }, + { + a: Fibonacci(30).Matrix(), + evWant: Fibonacci(30).Eigenvalues(), + }, + { + a: Fibonacci(50).Matrix(), + evWant: Fibonacci(50).Eigenvalues(), + }, + { + a: Fibonacci(101).Matrix(), + evWant: Fibonacci(101).Eigenvalues(), + }, + { + a: Fibonacci(150).Matrix(), + evWant: Fibonacci(150).Eigenvalues(), + }, + + { + a: Gear(2).Matrix(), + evWant: Gear(2).Eigenvalues(), + }, + { + a: Gear(3).Matrix(), + evWant: Gear(3).Eigenvalues(), + }, + { + a: Gear(4).Matrix(), + evWant: Gear(4).Eigenvalues(), + valTol: 1e-7, + }, + { + a: Gear(5).Matrix(), + evWant: Gear(5).Eigenvalues(), + }, + { + a: Gear(10).Matrix(), + evWant: Gear(10).Eigenvalues(), + valTol: 1e-8, + }, + { + a: Gear(15).Matrix(), + evWant: Gear(15).Eigenvalues(), + }, + { + a: Gear(30).Matrix(), + evWant: Gear(30).Eigenvalues(), + valTol: 1e-8, + }, + { + a: Gear(50).Matrix(), + evWant: Gear(50).Eigenvalues(), + valTol: 1e-8, + }, + { + a: Gear(101).Matrix(), + evWant: Gear(101).Eigenvalues(), + }, + { + a: Gear(150).Matrix(), + evWant: Gear(150).Eigenvalues(), + valTol: 1e-8, + }, + + { + a: Grcar{N: 10, K: 3}.Matrix(), + evWant: Grcar{N: 10, K: 3}.Eigenvalues(), + }, + { + a: Grcar{N: 10, K: 7}.Matrix(), + evWant: Grcar{N: 10, K: 7}.Eigenvalues(), + }, + { + a: Grcar{N: 11, K: 7}.Matrix(), + evWant: Grcar{N: 11, K: 7}.Eigenvalues(), + }, + { + a: Grcar{N: 50, K: 3}.Matrix(), + evWant: Grcar{N: 50, K: 3}.Eigenvalues(), + }, + { + a: Grcar{N: 51, K: 3}.Matrix(), + evWant: Grcar{N: 51, K: 3}.Eigenvalues(), + }, + { + a: Grcar{N: 50, K: 10}.Matrix(), + evWant: Grcar{N: 50, K: 10}.Eigenvalues(), + }, + { + a: Grcar{N: 51, K: 10}.Matrix(), + evWant: Grcar{N: 51, K: 10}.Eigenvalues(), + }, + { + a: Grcar{N: 50, K: 30}.Matrix(), + evWant: Grcar{N: 50, K: 30}.Eigenvalues(), + }, + { + a: Grcar{N: 150, K: 2}.Matrix(), + evWant: Grcar{N: 150, K: 2}.Eigenvalues(), + }, + { + a: Grcar{N: 150, K: 148}.Matrix(), + evWant: Grcar{N: 150, K: 148}.Eigenvalues(), + }, + + { + a: Hanowa{N: 6, Alpha: 17}.Matrix(), + evWant: Hanowa{N: 6, Alpha: 17}.Eigenvalues(), + }, + { + a: Hanowa{N: 50, Alpha: -1}.Matrix(), + evWant: Hanowa{N: 50, Alpha: -1}.Eigenvalues(), + }, + { + a: Hanowa{N: 100, Alpha: -1}.Matrix(), + evWant: Hanowa{N: 100, Alpha: -1}.Eigenvalues(), + }, + + { + a: Lesp(2).Matrix(), + evWant: Lesp(2).Eigenvalues(), + }, + { + a: Lesp(3).Matrix(), + evWant: Lesp(3).Eigenvalues(), + }, + { + a: Lesp(4).Matrix(), + evWant: Lesp(4).Eigenvalues(), + }, + { + a: Lesp(5).Matrix(), + evWant: Lesp(5).Eigenvalues(), + }, + { + a: Lesp(10).Matrix(), + evWant: Lesp(10).Eigenvalues(), + }, + { + a: Lesp(15).Matrix(), + evWant: Lesp(15).Eigenvalues(), + }, + { + a: Lesp(30).Matrix(), + evWant: Lesp(30).Eigenvalues(), + }, + { + a: Lesp(50).Matrix(), + evWant: Lesp(50).Eigenvalues(), + valTol: 1e-12, + vecTol: 1e-12, + }, + { + a: Lesp(101).Matrix(), + evWant: Lesp(101).Eigenvalues(), + valTol: 1e-12, + vecTol: 1e-12, + }, + { + a: Lesp(150).Matrix(), + evWant: Lesp(150).Eigenvalues(), + valTol: 1e-12, + vecTol: 1e-12, + }, + + { + a: Rutis{}.Matrix(), + evWant: Rutis{}.Eigenvalues(), + }, + + { + a: Tris{N: 74, X: 1, Y: -2, Z: 1}.Matrix(), + evWant: Tris{N: 74, X: 1, Y: -2, Z: 1}.Eigenvalues(), + }, + { + a: Tris{N: 74, X: 1, Y: 2, Z: -3}.Matrix(), + evWant: Tris{N: 74, X: 1, Y: 2, Z: -3}.Eigenvalues(), + }, + { + a: Tris{N: 75, X: 1, Y: 2, Z: -3}.Matrix(), + evWant: Tris{N: 75, X: 1, Y: 2, Z: -3}.Eigenvalues(), + }, + + { + a: Wilk4{}.Matrix(), + evWant: Wilk4{}.Eigenvalues(), + }, + { + a: Wilk12{}.Matrix(), + evWant: Wilk12{}.Eigenvalues(), + valTol: 1e-8, + }, + { + a: Wilk20(0).Matrix(), + evWant: Wilk20(0).Eigenvalues(), + }, + { + a: Wilk20(1e-10).Matrix(), + evWant: Wilk20(1e-10).Eigenvalues(), + valTol: 1e-12, + vecTol: 1e-12, + }, + + { + a: Zero(1).Matrix(), + evWant: Zero(1).Eigenvalues(), + }, + { + a: Zero(10).Matrix(), + evWant: Zero(10).Eigenvalues(), + }, + { + a: Zero(50).Matrix(), + evWant: Zero(50).Eigenvalues(), + }, + { + a: Zero(100).Matrix(), + evWant: Zero(100).Eigenvalues(), + }, + } { + for _, jobvl := range []lapack.LeftEVJob{lapack.ComputeLeftEV, lapack.None} { + for _, jobvr := range []lapack.RightEVJob{lapack.ComputeRightEV, lapack.None} { + for _, extra := range []int{0, 11} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + testDgeev(t, impl, strconv.Itoa(i), test, jobvl, jobvr, extra, wl) + } + } + } + } + } + + for _, n := range []int{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 20, 50, 51, 100, 101} { + for _, jobvl := range []lapack.LeftEVJob{lapack.ComputeLeftEV, lapack.None} { + for _, jobvr := range []lapack.RightEVJob{lapack.ComputeRightEV, lapack.None} { + for cas := 0; cas < 10; cas++ { + // Create a block diagonal matrix with + // random eigenvalues of random multiplicity. + ev := make([]complex128, n) + tmat := zeros(n, n, n) + for i := 0; i < n; { + re := rnd.NormFloat64() + if i == n-1 || rnd.Float64() < 0.5 { + // Real eigenvalue. + nb := rnd.Intn(min(4, n-i)) + 1 + for k := 0; k < nb; k++ { + tmat.Data[i*tmat.Stride+i] = re + ev[i] = complex(re, 0) + i++ + } + continue + } + // Complex eigenvalue. + im := rnd.NormFloat64() + nb := rnd.Intn(min(4, (n-i)/2)) + 1 + for k := 0; k < nb; k++ { + // 2×2 block for the complex eigenvalue. + tmat.Data[i*tmat.Stride+i] = re + tmat.Data[(i+1)*tmat.Stride+i+1] = re + tmat.Data[(i+1)*tmat.Stride+i] = -im + tmat.Data[i*tmat.Stride+i+1] = im + ev[i] = complex(re, im) + ev[i+1] = complex(re, -im) + i += 2 + } + } + + // Compute A = Q T Q^T where Q is an + // orthogonal matrix. + q := randomOrthogonal(n, rnd) + tq := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.Trans, 1, tmat, q, 0, tq) + a := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, tq, 0, a) + + test := dgeevTest{ + a: a, + evWant: ev, + valTol: 1e-12, + vecTol: 1e-8, + } + testDgeev(t, impl, "random", test, jobvl, jobvr, 0, optimumWork) + } + } + } + } +} + +func testDgeev(t *testing.T, impl Dgeever, tc string, test dgeevTest, jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, extra int, wl worklen) { + const defaultTol = 1e-13 + valTol := test.valTol + if valTol == 0 { + valTol = defaultTol + } + vecTol := test.vecTol + if vecTol == 0 { + vecTol = defaultTol + } + + a := cloneGeneral(test.a) + n := a.Rows + + var vl blas64.General + if jobvl == lapack.ComputeLeftEV { + vl = nanGeneral(n, n, n) + } + + var vr blas64.General + if jobvr == lapack.ComputeRightEV { + vr = nanGeneral(n, n, n) + } + + wr := make([]float64, n) + wi := make([]float64, n) + + var lwork int + switch wl { + case minimumWork: + if jobvl == lapack.ComputeLeftEV || jobvr == lapack.ComputeRightEV { + lwork = max(1, 4*n) + } else { + lwork = max(1, 3*n) + } + case mediumWork: + work := make([]float64, 1) + impl.Dgeev(jobvl, jobvr, n, nil, 1, nil, nil, nil, 1, nil, 1, work, -1) + if jobvl == lapack.ComputeLeftEV || jobvr == lapack.ComputeRightEV { + lwork = (int(work[0]) + 4*n) / 2 + } else { + lwork = (int(work[0]) + 3*n) / 2 + } + lwork = max(1, lwork) + case optimumWork: + work := make([]float64, 1) + impl.Dgeev(jobvl, jobvr, n, nil, 1, nil, nil, nil, 1, nil, 1, work, -1) + lwork = int(work[0]) + } + work := make([]float64, lwork) + + first := impl.Dgeev(jobvl, jobvr, n, a.Data, a.Stride, wr, wi, + vl.Data, vl.Stride, vr.Data, vr.Stride, work, len(work)) + + prefix := fmt.Sprintf("Case #%v: n=%v, jobvl=%v, jobvr=%v, extra=%v, work=%v", + tc, n, jobvl, jobvr, extra, wl) + + if !generalOutsideAllNaN(vl) { + t.Errorf("%v: out-of-range write to VL", prefix) + } + if !generalOutsideAllNaN(vr) { + t.Errorf("%v: out-of-range write to VR", prefix) + } + + if first > 0 { + t.Log("%v: all eigenvalues haven't been computed, first=%v", prefix, first) + } + + // Check that conjugate pair eigevalues are ordered correctly. + for i := first; i < n; { + if wi[i] == 0 { + i++ + continue + } + if wr[i] != wr[i+1] { + t.Errorf("%v: real parts of %vth conjugate pair not equal", prefix, i) + } + if wi[i] < 0 || wi[i+1] > 0 { + t.Errorf("%v: unexpected ordering of %vth conjugate pair", prefix, i) + } + i += 2 + } + + // Check the computed eigenvalues against provided known eigenvalues. + if test.evWant != nil { + used := make([]bool, n) + for i := first; i < n; i++ { + evGot := complex(wr[i], wi[i]) + idx := -1 + for k, evWant := range test.evWant { + if !used[k] && cmplx.Abs(evWant-evGot) < valTol { + idx = k + used[k] = true + break + } + } + if idx == -1 { + t.Errorf("%v: unexpected eigenvalue %v", prefix, evGot) + } + } + } + + if first > 0 || (jobvl == lapack.None && jobvr == lapack.None) { + // No eigenvectors have been computed. + return + } + + // Check that the columns of VL and VR are eigenvectors that correspond + // to the computed eigenvalues. + for k := 0; k < n; { + if wi[k] == 0 { + if jobvl == lapack.ComputeLeftEV { + ev := columnOf(vl, k) + if !isLeftEigenvectorOf(test.a, ev, nil, complex(wr[k], 0), vecTol) { + t.Errorf("%v: VL[:,%v] is not left real eigenvector", + prefix, k) + } + + norm := floats.Norm(ev, 2) + if math.Abs(norm-1) >= defaultTol { + t.Errorf("%v: norm of left real eigenvector %v not equal to 1: got %v", + prefix, k, norm) + } + } + if jobvr == lapack.ComputeRightEV { + ev := columnOf(vr, k) + if !isRightEigenvectorOf(test.a, ev, nil, complex(wr[k], 0), vecTol) { + t.Errorf("%v: VR[:,%v] is not right real eigenvector", + prefix, k) + } + + norm := floats.Norm(ev, 2) + if math.Abs(norm-1) >= defaultTol { + t.Errorf("%v: norm of right real eigenvector %v not equal to 1: got %v", + prefix, k, norm) + } + } + k++ + } else { + if jobvl == lapack.ComputeLeftEV { + evre := columnOf(vl, k) + evim := columnOf(vl, k+1) + if !isLeftEigenvectorOf(test.a, evre, evim, complex(wr[k], wi[k]), vecTol) { + t.Errorf("%v: VL[:,%v:%v] is not left complex eigenvector", + prefix, k, k+1) + } + floats.Scale(-1, evim) + if !isLeftEigenvectorOf(test.a, evre, evim, complex(wr[k+1], wi[k+1]), vecTol) { + t.Errorf("%v: VL[:,%v:%v] is not left complex eigenvector", + prefix, k, k+1) + } + + norm := math.Hypot(floats.Norm(evre, 2), floats.Norm(evim, 2)) + if math.Abs(norm-1) > defaultTol { + t.Errorf("%v: norm of left complex eigenvector %v not equal to 1: got %v", + prefix, k, norm) + } + } + if jobvr == lapack.ComputeRightEV { + evre := columnOf(vr, k) + evim := columnOf(vr, k+1) + if !isRightEigenvectorOf(test.a, evre, evim, complex(wr[k], wi[k]), vecTol) { + t.Errorf("%v: VR[:,%v:%v] is not right complex eigenvector", + prefix, k, k+1) + } + floats.Scale(-1, evim) + if !isRightEigenvectorOf(test.a, evre, evim, complex(wr[k+1], wi[k+1]), vecTol) { + t.Errorf("%v: VR[:,%v:%v] is not right complex eigenvector", + prefix, k, k+1) + } + + norm := math.Hypot(floats.Norm(evre, 2), floats.Norm(evim, 2)) + if math.Abs(norm-1) > defaultTol { + t.Errorf("%v: norm of right complex eigenvector %v not equal to 1: got %v", + prefix, k, norm) + } + } + // We don't test whether the largest component is real + // because checking it is flaky due to rounding errors. + + k += 2 + } + } +} + +func dgeevTestForAntisymRandom(n int, rnd *rand.Rand) dgeevTest { + a := NewAntisymRandom(n, rnd) + return dgeevTest{ + a: a.Matrix(), + evWant: a.Eigenvalues(), + } +} diff --git a/lapack/testlapack/dgeev_bench.go b/lapack/testlapack/dgeev_bench.go new file mode 100644 index 00000000..177807de --- /dev/null +++ b/lapack/testlapack/dgeev_bench.go @@ -0,0 +1,63 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.7 + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +var resultGeneral blas64.General + +func DgeevBenchmark(b *testing.B, impl Dgeever) { + rnd := rand.New(rand.NewSource(1)) + benchmarks := []struct { + name string + a blas64.General + }{ + {"AntisymRandom3", NewAntisymRandom(3, rnd).Matrix()}, + {"AntisymRandom4", NewAntisymRandom(4, rnd).Matrix()}, + {"AntisymRandom5", NewAntisymRandom(5, rnd).Matrix()}, + {"AntisymRandom10", NewAntisymRandom(10, rnd).Matrix()}, + {"AntisymRandom50", NewAntisymRandom(50, rnd).Matrix()}, + {"AntisymRandom100", NewAntisymRandom(100, rnd).Matrix()}, + {"AntisymRandom200", NewAntisymRandom(200, rnd).Matrix()}, + {"AntisymRandom500", NewAntisymRandom(500, rnd).Matrix()}, + {"Circulant3", Circulant(3).Matrix()}, + {"Circulant4", Circulant(4).Matrix()}, + {"Circulant5", Circulant(5).Matrix()}, + {"Circulant10", Circulant(10).Matrix()}, + {"Circulant50", Circulant(50).Matrix()}, + {"Circulant100", Circulant(100).Matrix()}, + {"Circulant200", Circulant(200).Matrix()}, + {"Circulant500", Circulant(500).Matrix()}, + } + for _, bm := range benchmarks { + n := bm.a.Rows + a := zeros(n, n, n) + vl := zeros(n, n, n) + vr := zeros(n, n, n) + wr := make([]float64, n) + wi := make([]float64, n) + work := make([]float64, 1) + impl.Dgeev(lapack.ComputeLeftEV, lapack.ComputeRightEV, n, nil, n, nil, nil, nil, n, nil, n, work, -1) + work = make([]float64, int(work[0])) + b.Run(bm.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + copyGeneral(a, bm.a) + b.StartTimer() + impl.Dgeev(lapack.ComputeLeftEV, lapack.ComputeRightEV, n, a.Data, a.Stride, wr, wi, + vl.Data, vl.Stride, vr.Data, vr.Stride, work, len(work)) + } + resultGeneral = a + }) + } +} diff --git a/lapack/testlapack/dgehd2.go b/lapack/testlapack/dgehd2.go new file mode 100644 index 00000000..5b7e8309 --- /dev/null +++ b/lapack/testlapack/dgehd2.go @@ -0,0 +1,196 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgehd2er interface { + Dgehd2(n, ilo, ihi int, a []float64, lda int, tau, work []float64) +} + +func Dgehd2Test(t *testing.T, impl Dgehd2er) { + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{1, 2, 3, 4, 5, 7, 10, 30} { + for _, extra := range []int{0, 1, 13} { + for cas := 0; cas < 100; cas++ { + testDgehd2(t, impl, n, extra, rnd) + } + } + } +} + +func testDgehd2(t *testing.T, impl Dgehd2er, n, extra int, rnd *rand.Rand) { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + + tau := nanSlice(n - 1) + work := nanSlice(n) + + a := randomGeneral(n, n, n+extra, rnd) + // NaN out elements under the diagonal except + // for the [ilo:ihi,ilo:ihi] block. + for i := 1; i <= ihi; i++ { + for j := 0; j < min(ilo, i); j++ { + a.Data[i*a.Stride+j] = math.NaN() + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < i; j++ { + a.Data[i*a.Stride+j] = math.NaN() + } + } + aCopy := a + aCopy.Data = make([]float64, len(a.Data)) + copy(aCopy.Data, a.Data) + + impl.Dgehd2(n, ilo, ihi, a.Data, a.Stride, tau, work) + + prefix := fmt.Sprintf("Case n=%v, ilo=%v, ihi=%v, extra=%v", n, ilo, ihi, extra) + + // Check any invalid modifications of a. + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + for i := ilo; i <= ihi; i++ { + for j := 0; j < min(ilo, i); j++ { + if !math.IsNaN(a.Data[i*a.Stride+j]) { + t.Errorf("%v: expected NaN at A[%v,%v]", prefix, i, j) + } + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < i; j++ { + if !math.IsNaN(a.Data[i*a.Stride+j]) { + t.Errorf("%v: expected NaN at A[%v,%v]", prefix, i, j) + } + } + } + for i := 0; i <= ilo; i++ { + for j := i; j < ilo+1; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + for j := ihi + 1; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + } + for i := ihi + 1; i < n; i++ { + for j := i; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + } + + // Check that tau has been assigned properly. + for i, v := range tau { + if i < ilo || i >= ihi { + if !math.IsNaN(v) { + t.Errorf("%v: expected NaN at tau[%v]", prefix, i) + } + } else { + if math.IsNaN(v) { + t.Errorf("%v: unexpected NaN at tau[%v]", prefix, i) + } + } + } + + // Extract Q and check that it is orthogonal. + q := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < q.Rows; i++ { + q.Data[i*q.Stride+i] = 1 + } + qCopy := q + qCopy.Data = make([]float64, len(q.Data)) + for j := ilo; j < ihi; j++ { + h := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < h.Rows; i++ { + h.Data[i*h.Stride+i] = 1 + } + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + v.Data[j+1] = 1 + for i := j + 2; i < ihi+1; i++ { + v.Data[i] = a.Data[i*a.Stride+j] + } + blas64.Ger(-tau[j], v, v, h) + copy(qCopy.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q) + } + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal\nQ=%v", prefix, q) + } + + // Overwrite NaN elements of aCopy with zeros + // (we will multiply with it below). + for i := 1; i <= ihi; i++ { + for j := 0; j < min(ilo, i); j++ { + aCopy.Data[i*aCopy.Stride+j] = 0 + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < i; j++ { + aCopy.Data[i*aCopy.Stride+j] = 0 + } + } + + // Construct Q^T * AOrig * Q and check that it is + // equal to A from Dgehd2. + aq := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aCopy, q, 0, aq) + qaq := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aq, 0, qaq) + for i := ilo; i <= ihi; i++ { + for j := ilo; j <= ihi; j++ { + qaqij := qaq.Data[i*qaq.Stride+j] + if j < i-1 { + if math.Abs(qaqij) > 1e-14 { + t.Errorf("%v: Q^T*A*Q is not upper Hessenberg, [%v,%v]=%v", prefix, i, j, qaqij) + } + continue + } + diff := qaqij - a.Data[i*a.Stride+j] + if math.Abs(diff) > 1e-14 { + t.Errorf("%v: Q^T*AOrig*Q and A are not equal, diff at [%v,%v]=%v", prefix, i, j, diff) + } + } + } +} diff --git a/lapack/testlapack/dgehrd.go b/lapack/testlapack/dgehrd.go new file mode 100644 index 00000000..012b8707 --- /dev/null +++ b/lapack/testlapack/dgehrd.go @@ -0,0 +1,209 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgehrder interface { + Dgehrd(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) + + Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DgehrdTest(t *testing.T, impl Dgehrder) { + rnd := rand.New(rand.NewSource(1)) + + // Randomized tests for small matrix sizes that will most likely + // use the unblocked algorithm. + for _, n := range []int{1, 2, 3, 4, 5, 10, 34} { + for _, extra := range []int{0, 13} { + for _, optwork := range []bool{true, false} { + for cas := 0; cas < 10; cas++ { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + testDgehrd(t, impl, n, ilo, ihi, extra, optwork, rnd) + } + } + } + } + + // These are selected tests for larger matrix sizes to test the blocked + // algorithm. Use sizes around several powers of two because that is + // where the blocked path will most likely start to be taken. For + // example, at present the blocked algorithm is used for sizes larger + // than 129. + for _, test := range []struct { + n, ilo, ihi int + }{ + {0, 0, -1}, + + {68, 0, 63}, + {68, 0, 64}, + {68, 0, 65}, + {68, 0, 66}, + {68, 0, 67}, + + {132, 2, 129}, + {132, 1, 129}, // Size = 129, unblocked. + {132, 0, 129}, // Size = 130, blocked. + {132, 1, 130}, + {132, 0, 130}, + {132, 1, 131}, + {132, 0, 131}, + + {260, 2, 257}, + {260, 1, 257}, + {260, 0, 257}, + {260, 0, 258}, + {260, 0, 259}, + } { + for _, extra := range []int{0, 13} { + for _, optwork := range []bool{true, false} { + testDgehrd(t, impl, test.n, test.ilo, test.ihi, extra, optwork, rnd) + } + } + } +} + +func testDgehrd(t *testing.T, impl Dgehrder, n, ilo, ihi, extra int, optwork bool, rnd *rand.Rand) { + a := randomGeneral(n, n, n+extra, rnd) + aCopy := a + aCopy.Data = make([]float64, len(a.Data)) + copy(aCopy.Data, a.Data) + + var tau []float64 + if n > 1 { + tau = nanSlice(n - 1) + } + + var work []float64 + if optwork { + work = nanSlice(1) + impl.Dgehrd(n, ilo, ihi, nil, a.Stride, nil, work, -1) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, n)) + } + + impl.Dgehrd(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) + + if n == 0 { + // Just make sure there is no panic. + return + } + + prefix := fmt.Sprintf("Case n=%v, ilo=%v, ihi=%v, extra=%v", n, ilo, ihi, extra) + + // Check any invalid modifications of a. + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + for i := ilo; i <= ihi; i++ { + for j := 0; j < min(ilo, i); j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification of A[%v,%v]", prefix, i, j) + } + } + } + for i := ihi + 1; i < n; i++ { + for j := 0; j < i; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification of A[%v,%v]", prefix, i, j) + } + } + } + for i := 0; i <= ilo; i++ { + for j := i; j < ilo+1; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + for j := ihi + 1; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + } + for i := ihi + 1; i < n; i++ { + for j := i; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification at A[%v,%v]", prefix, i, j) + } + } + } + + // Check that tau has been assigned properly. + for i, v := range tau { + if math.IsNaN(v) { + t.Errorf("%v: unexpected NaN at tau[%v]", prefix, i) + } + } + + // Extract Q and check that it is orthogonal. + q := eye(n, n) + if ilo != ihi { + for i := ilo + 2; i <= ihi; i++ { + for j := ilo + 1; j < ihi; j++ { + q.Data[i*q.Stride+j] = a.Data[i*a.Stride+j-1] + } + } + nh := ihi - ilo + impl.Dorgqr(nh, nh, nh, q.Data[(ilo+1)*q.Stride+ilo+1:], q.Stride, tau[ilo:ihi], work, len(work)) + } + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal\nQ=%v", prefix, q) + } + + // Construct Q^T * AOrig * Q and check that it is upper Hessenberg. + aq := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aCopy, q, 0, aq) + qaq := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aq, 0, qaq) + for i := 0; i <= ilo; i++ { + for j := ilo + 1; j <= ihi; j++ { + qaqij := qaq.Data[i*qaq.Stride+j] + diff := qaqij - a.Data[i*a.Stride+j] + if math.Abs(diff) > 1e-13 { + t.Errorf("%v: Q^T*AOrig*Q and A are not equal, diff at [%v,%v]=%v", prefix, i, j, diff) + } + } + } + for i := ilo + 1; i <= ihi; i++ { + for j := ilo; j < n; j++ { + qaqij := qaq.Data[i*qaq.Stride+j] + if j < i-1 { + if math.Abs(qaqij) > 1e-13 { + t.Errorf("%v: Q^T*AOrig*Q is not upper Hessenberg, [%v,%v]=%v", prefix, i, j, qaqij) + } + continue + } + diff := qaqij - a.Data[i*a.Stride+j] + if math.Abs(diff) > 1e-13 { + t.Errorf("%v: Q^T*AOrig*Q and A are not equal, diff at [%v,%v]=%v", prefix, i, j, diff) + } + } + } +} diff --git a/lapack/testlapack/dgelq2.go b/lapack/testlapack/dgelq2.go new file mode 100644 index 00000000..20f95717 --- /dev/null +++ b/lapack/testlapack/dgelq2.go @@ -0,0 +1,113 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgelq2er interface { + Dgelq2(m, n int, a []float64, lda int, tau, work []float64) +} + +func Dgelq2Test(t *testing.T, impl Dgelq2er) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {1, 12, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {1, 12, 20}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := make([]float64, m) + for i := range work { + work[i] = rnd.Float64() + } + a := make([]float64, m*lda) + for i := 0; i < m*lda; i++ { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dgelq2(m, n, a, lda, tau, work) + + Q := constructQ("LQ", m, n, a, lda, tau) + + // Check that Q is orthonormal + for i := 0; i < Q.Rows; i++ { + nrm := blas64.Nrm2(Q.Cols, blas64.Vector{Inc: 1, Data: Q.Data[i*Q.Stride:]}) + if math.Abs(nrm-1) > 1e-14 { + t.Errorf("Q not normal. Norm is %v", nrm) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(Q.Rows, + blas64.Vector{Inc: 1, Data: Q.Data[i*Q.Stride:]}, + blas64.Vector{Inc: 1, Data: Q.Data[j*Q.Stride:]}, + ) + if math.Abs(dot) > 1e-14 { + t.Errorf("Q not orthogonal. Dot is %v", dot) + } + } + } + + L := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + L.Data[i*L.Stride+j] = a[i*lda+j] + } + } + + ans := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(ans.Data, aCopy) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, L, Q, 0, ans) + if !floats.EqualApprox(aCopy, ans.Data, 1e-14) { + t.Errorf("Case %v, LQ mismatch. Want %v, got %v.", c, aCopy, ans.Data) + } + } +} diff --git a/lapack/testlapack/dgelqf.go b/lapack/testlapack/dgelqf.go new file mode 100644 index 00000000..5bbe7312 --- /dev/null +++ b/lapack/testlapack/dgelqf.go @@ -0,0 +1,98 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dgelqfer interface { + Dgelq2er + Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DgelqfTest(t *testing.T, impl Dgelqfer) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {10, 5, 0}, + {5, 10, 0}, + {10, 10, 0}, + {300, 5, 0}, + {3, 500, 0}, + {200, 200, 0}, + {300, 200, 0}, + {204, 300, 0}, + {1, 3000, 0}, + {3000, 1, 0}, + {10, 5, 30}, + {5, 10, 30}, + {10, 10, 30}, + {300, 5, 500}, + {3, 500, 600}, + {200, 200, 300}, + {300, 200, 300}, + {204, 300, 400}, + {1, 3000, 4000}, + {3000, 1, 4000}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = rnd.Float64() + } + } + tau := make([]float64, n) + for i := 0; i < n; i++ { + tau[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + ans := make([]float64, len(a)) + copy(ans, a) + work := make([]float64, m) + for i := range work { + work[i] = rnd.Float64() + } + // Compute unblocked QR. + impl.Dgelq2(m, n, ans, lda, tau, work) + // Compute blocked QR with small work. + impl.Dgelqf(m, n, a, lda, tau, work, len(work)) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch small work.", c) + } + // Try the full length of work. + impl.Dgelqf(m, n, a, lda, tau, work, -1) + lwork := int(work[0]) + work = make([]float64, lwork) + copy(a, aCopy) + impl.Dgelqf(m, n, a, lda, tau, work, lwork) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch large work.", c) + } + + // Try a slightly smaller version of work to test blocking code. + if len(work) <= m { + continue + } + work = work[1:] + lwork-- + copy(a, aCopy) + impl.Dgelqf(m, n, a, lda, tau, work, lwork) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch large work.", c) + } + } +} diff --git a/lapack/testlapack/dgels.go b/lapack/testlapack/dgels.go new file mode 100644 index 00000000..9b49a54c --- /dev/null +++ b/lapack/testlapack/dgels.go @@ -0,0 +1,182 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgelser interface { + Dgels(trans blas.Transpose, m, n, nrhs int, a []float64, lda int, b []float64, ldb int, work []float64, lwork int) bool +} + +func DgelsTest(t *testing.T, impl Dgelser) { + rnd := rand.New(rand.NewSource(1)) + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + m, n, nrhs, lda, ldb int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + {3, 4, 5, 10, 20}, + {3, 5, 4, 10, 20}, + {4, 3, 5, 10, 20}, + {4, 5, 3, 10, 20}, + {5, 3, 4, 10, 20}, + {5, 4, 3, 10, 20}, + {3, 4, 5, 20, 10}, + {3, 5, 4, 20, 10}, + {4, 3, 5, 20, 10}, + {4, 5, 3, 20, 10}, + {5, 3, 4, 20, 10}, + {5, 4, 3, 20, 10}, + {200, 300, 400, 0, 0}, + {200, 400, 300, 0, 0}, + {300, 200, 400, 0, 0}, + {300, 400, 200, 0, 0}, + {400, 200, 300, 0, 0}, + {400, 300, 200, 0, 0}, + {200, 300, 400, 500, 600}, + {200, 400, 300, 500, 600}, + {300, 200, 400, 500, 600}, + {300, 400, 200, 500, 600}, + {400, 200, 300, 500, 600}, + {400, 300, 200, 500, 600}, + {200, 300, 400, 600, 500}, + {200, 400, 300, 600, 500}, + {300, 200, 400, 600, 500}, + {300, 400, 200, 600, 500}, + {400, 200, 300, 600, 500}, + {400, 300, 200, 600, 500}, + } { + m := test.m + n := test.n + nrhs := test.nrhs + + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + // Size of b is the same trans or no trans, because the number of rows + // has to be the max of (m,n). + mb := max(m, n) + nb := nrhs + ldb := test.ldb + if ldb == 0 { + ldb = nb + } + b := make([]float64, mb*ldb) + for i := range b { + b[i] = rnd.Float64() + } + bCopy := make([]float64, len(b)) + copy(bCopy, b) + + // Find optimal work length. + work := make([]float64, 1) + impl.Dgels(trans, m, n, nrhs, a, lda, b, ldb, work, -1) + + // Perform linear solve + work = make([]float64, int(work[0])) + lwork := len(work) + for i := range work { + work[i] = rnd.Float64() + } + impl.Dgels(trans, m, n, nrhs, a, lda, b, ldb, work, lwork) + + // Check that the answer is correct by comparing to the normal equations. + aMat := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, len(aCopy)), + } + copy(aMat.Data, aCopy) + szAta := n + if trans == blas.Trans { + szAta = m + } + aTA := blas64.General{ + Rows: szAta, + Cols: szAta, + Stride: szAta, + Data: make([]float64, szAta*szAta), + } + + // Compute A^T * A if notrans and A * A^T otherwise. + if trans == blas.NoTrans { + blas64.Gemm(blas.Trans, blas.NoTrans, 1, aMat, aMat, 0, aTA) + } else { + blas64.Gemm(blas.NoTrans, blas.Trans, 1, aMat, aMat, 0, aTA) + } + + // Multiply by X. + X := blas64.General{ + Rows: szAta, + Cols: nrhs, + Stride: ldb, + Data: b, + } + ans := blas64.General{ + Rows: aTA.Rows, + Cols: X.Cols, + Stride: X.Cols, + Data: make([]float64, aTA.Rows*X.Cols), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aTA, X, 0, ans) + + B := blas64.General{ + Rows: szAta, + Cols: nrhs, + Stride: ldb, + Data: make([]float64, len(bCopy)), + } + + copy(B.Data, bCopy) + var ans2 blas64.General + if trans == blas.NoTrans { + ans2 = blas64.General{ + Rows: aMat.Cols, + Cols: B.Cols, + Stride: B.Cols, + Data: make([]float64, aMat.Cols*B.Cols), + } + } else { + ans2 = blas64.General{ + Rows: aMat.Rows, + Cols: B.Cols, + Stride: B.Cols, + Data: make([]float64, aMat.Rows*B.Cols), + } + } + + // Compute A^T B if Trans or A * B otherwise + if trans == blas.NoTrans { + blas64.Gemm(blas.Trans, blas.NoTrans, 1, aMat, B, 0, ans2) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aMat, B, 0, ans2) + } + if !floats.EqualApprox(ans.Data, ans2.Data, 1e-12) { + t.Errorf("Normal equations not satisfied") + } + } + } +} diff --git a/lapack/testlapack/dgeql2.go b/lapack/testlapack/dgeql2.go new file mode 100644 index 00000000..0ff6a930 --- /dev/null +++ b/lapack/testlapack/dgeql2.go @@ -0,0 +1,99 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgeql2er interface { + Dgeql2(m, n int, a []float64, lda int, tau, work []float64) +} + +func Dgeql2Test(t *testing.T, impl Dgeql2er) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Add tests for m < n. + for _, test := range []struct { + m, n, lda int + }{ + {5, 5, 0}, + {5, 3, 0}, + {5, 4, 0}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + tau := nanSlice(min(m, n)) + work := nanSlice(n) + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dgeql2(m, n, a, lda, tau, work) + + k := min(m, n) + // Construct Q. + q := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: make([]float64, m*m), + } + for i := 0; i < m; i++ { + q.Data[i*q.Stride+i] = 1 + } + for i := 0; i < k; i++ { + h := blas64.General{Rows: m, Cols: m, Stride: m, Data: make([]float64, m*m)} + for j := 0; j < m; j++ { + h.Data[j*h.Stride+j] = 1 + } + v := blas64.Vector{Inc: 1, Data: make([]float64, m)} + v.Data[m-k+i] = 1 + for j := 0; j < m-k+i; j++ { + v.Data[j] = a[j*lda+n-k+i] + } + blas64.Ger(-tau[i], v, v, h) + qTmp := blas64.General{Rows: q.Rows, Cols: q.Cols, Stride: q.Stride, Data: make([]float64, len(q.Data))} + copy(qTmp.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, qTmp, 0, q) + } + if !isOrthonormal(q) { + t.Errorf("Q is not orthonormal") + } + l := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + if m >= n { + for i := m - n; i < m; i++ { + for j := 0; j <= min(i-(m-n), n-1); j++ { + l.Data[i*l.Stride+j] = a[i*lda+j] + } + } + } else { + panic("untested") + } + ans := blas64.General{Rows: m, Cols: n, Stride: lda, Data: make([]float64, len(a))} + copy(ans.Data, a) + + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, l, 0, ans) + if !floats.EqualApprox(ans.Data, aCopy, 1e-10) { + t.Errorf("Reconstruction mismatch: m = %v, n = %v", m, n) + } + } +} diff --git a/lapack/testlapack/dgeqp3.go b/lapack/testlapack/dgeqp3.go new file mode 100644 index 00000000..54e30bf5 --- /dev/null +++ b/lapack/testlapack/dgeqp3.go @@ -0,0 +1,135 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgeqp3er interface { + Dlapmter + Dgeqp3(m, n int, a []float64, lda int, jpvt []int, tau, work []float64, lwork int) +} + +func Dgeqp3Test(t *testing.T, impl Dgeqp3er) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {12, 1, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {12, 1, 20}, + {129, 256, 0}, + {256, 129, 0}, + {129, 256, 266}, + {256, 129, 266}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + const ( + all = iota + some + none + ) + for _, free := range []int{all, some, none} { + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + jpvt := make([]int, n) + for j := range jpvt { + switch free { + case all: + jpvt[j] = -1 + case some: + jpvt[j] = rnd.Intn(2) - 1 + case none: + jpvt[j] = 0 + default: + panic("bad freedom") + } + } + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := make([]float64, 1) + impl.Dgeqp3(m, n, a, lda, jpvt, tau, work, -1) + lwork := int(work[0]) + work = make([]float64, lwork) + for i := range work { + work[i] = rnd.Float64() + } + impl.Dgeqp3(m, n, a, lda, jpvt, tau, work, lwork) + + // Test that the QR factorization has completed successfully. Compute + // Q based on the vectors. + q := constructQ("QR", m, n, a, lda, tau) + + // Check that q is orthonormal + for i := 0; i < m; i++ { + nrm := blas64.Nrm2(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}) + if math.Abs(nrm-1) > 1e-13 { + t.Errorf("Case %v, q not normal", c) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}, blas64.Vector{Inc: 1, Data: q.Data[j*m:]}) + if math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", c) + } + } + } + // Check that A * P = Q * R + r := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + r.Data[i*n+j] = a[i*lda+j] + } + } + got := nanGeneral(m, n, lda) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, got) + + want := blas64.General{Rows: m, Cols: n, Stride: lda, Data: aCopy} + impl.Dlapmt(true, want.Rows, want.Cols, want.Data, want.Stride, jpvt) + if !equalApproxGeneral(got, want, 1e-13) { + t.Errorf("Case %v, Q*R != A*P\nQ*R=%v\nA*P=%v", c, got, want) + } + } + } +} diff --git a/lapack/testlapack/dgeqr2.go b/lapack/testlapack/dgeqr2.go new file mode 100644 index 00000000..f9ebf694 --- /dev/null +++ b/lapack/testlapack/dgeqr2.go @@ -0,0 +1,111 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgeqr2er interface { + Dgeqr2(m, n int, a []float64, lda int, tau []float64, work []float64) +} + +func Dgeqr2Test(t *testing.T, impl Dgeqr2er) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {12, 1, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {12, 1, 20}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := make([]float64, n) + for i := range work { + work[i] = rnd.Float64() + } + copy(aCopy, a) + impl.Dgeqr2(m, n, a, lda, tau, work) + + // Test that the QR factorization has completed successfully. Compute + // Q based on the vectors. + q := constructQ("QR", m, n, a, lda, tau) + + // Check that q is orthonormal + for i := 0; i < m; i++ { + nrm := blas64.Nrm2(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}) + if math.Abs(nrm-1) > 1e-14 { + t.Errorf("Case %v, q not normal", c) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}, blas64.Vector{Inc: 1, Data: q.Data[j*m:]}) + if math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", c) + } + } + } + // Check that A = Q * R + r := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + r.Data[i*n+j] = a[i*lda+j] + } + } + atmp := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(atmp.Data, a) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, atmp) + if !floats.EqualApprox(atmp.Data, aCopy, 1e-14) { + t.Errorf("Q*R != a") + } + } +} diff --git a/lapack/testlapack/dgeqrf.go b/lapack/testlapack/dgeqrf.go new file mode 100644 index 00000000..60386c08 --- /dev/null +++ b/lapack/testlapack/dgeqrf.go @@ -0,0 +1,95 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dgeqrfer interface { + Dgeqr2er + Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DgeqrfTest(t *testing.T, impl Dgeqrfer) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {10, 5, 0}, + {5, 10, 0}, + {10, 10, 0}, + {300, 5, 0}, + {3, 500, 0}, + {200, 200, 0}, + {300, 200, 0}, + {204, 300, 0}, + {1, 3000, 0}, + {3000, 1, 0}, + {10, 5, 20}, + {5, 10, 20}, + {10, 10, 20}, + {300, 5, 400}, + {3, 500, 600}, + {200, 200, 300}, + {300, 200, 300}, + {204, 300, 400}, + {1, 3000, 4000}, + {3000, 1, 4000}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = rnd.Float64() + } + } + tau := make([]float64, n) + for i := 0; i < n; i++ { + tau[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + ans := make([]float64, len(a)) + copy(ans, a) + work := make([]float64, n) + // Compute unblocked QR. + impl.Dgeqr2(m, n, ans, lda, tau, work) + // Compute blocked QR with small work. + impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch small work.", c) + } + // Try the full length of work. + impl.Dgeqrf(m, n, a, lda, tau, work, -1) + lwork := int(work[0]) + work = make([]float64, lwork) + copy(a, aCopy) + impl.Dgeqrf(m, n, a, lda, tau, work, lwork) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch large work.", c) + } + + // Try a slightly smaller version of work to test blocking. + if len(work) <= n { + continue + } + work = work[1:] + lwork-- + copy(a, aCopy) + impl.Dgeqrf(m, n, a, lda, tau, work, lwork) + if !floats.EqualApprox(ans, a, 1e-12) { + t.Errorf("Case %v, mismatch large work.", c) + } + } +} diff --git a/lapack/testlapack/dgerq2.go b/lapack/testlapack/dgerq2.go new file mode 100644 index 00000000..ec0dde2a --- /dev/null +++ b/lapack/testlapack/dgerq2.go @@ -0,0 +1,117 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgerq2er interface { + Dgerq2(m, n int, a []float64, lda int, tau []float64, work []float64) +} + +func Dgerq2Test(t *testing.T, impl Dgerq2er) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {12, 1, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {12, 1, 20}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := make([]float64, m) + for i := range work { + work[i] = rnd.Float64() + } + copy(aCopy, a) + impl.Dgerq2(m, n, a, lda, tau, work) + + // Test that the RQ factorization has completed successfully. Compute + // Q based on the vectors. + q := constructQ("RQ", m, n, a, lda, tau) + + // Check that q is orthonormal + for i := 0; i < q.Rows; i++ { + nrm := blas64.Nrm2(q.Cols, blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}) + if math.IsNaN(nrm) || math.Abs(nrm-1) > 1e-14 { + t.Errorf("Case %v, q not normal", c) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(q.Cols, blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}, blas64.Vector{Inc: 1, Data: q.Data[j*q.Stride:]}) + if math.IsNaN(dot) || math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", c) + } + } + } + // Check that A = R * Q + r := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + off := m - n + for j := max(0, i-off); j < n; j++ { + r.Data[i*r.Stride+j] = a[i*lda+j] + } + } + + got := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, r, q, 0, got) + want := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: aCopy, + } + if !equalApproxGeneral(got, want, 1e-14) { + t.Errorf("Case %d, R*Q != a\ngot: %+v\nwant:%+v", c, got, want) + } + } +} diff --git a/lapack/testlapack/dgerqf.go b/lapack/testlapack/dgerqf.go new file mode 100644 index 00000000..3aa585d5 --- /dev/null +++ b/lapack/testlapack/dgerqf.go @@ -0,0 +1,134 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgerqfer interface { + Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DgerqfTest(t *testing.T, impl Dgerqfer) { + rnd := rand.New(rand.NewSource(1)) + for c, test := range []struct { + m, n, lda int + }{ + {1, 1, 0}, + {2, 2, 0}, + {3, 2, 0}, + {2, 3, 0}, + {1, 12, 0}, + {2, 6, 0}, + {3, 4, 0}, + {4, 3, 0}, + {6, 2, 0}, + {12, 1, 0}, + {1, 1, 20}, + {2, 2, 20}, + {3, 2, 20}, + {2, 3, 20}, + {1, 12, 20}, + {2, 6, 20}, + {3, 4, 20}, + {4, 3, 20}, + {6, 2, 20}, + {12, 1, 20}, + } { + n := test.n + m := test.m + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + k := min(m, n) + tau := make([]float64, k) + for i := range tau { + tau[i] = rnd.Float64() + } + work := []float64{0} + impl.Dgerqf(m, n, a, lda, tau, work, -1) + lwkopt := int(work[0]) + for _, wk := range []struct { + name string + length int + }{ + {name: "short", length: m}, + {name: "medium", length: lwkopt - 1}, + {name: "long", length: lwkopt}, + } { + if wk.length < max(1, m) { + continue + } + lwork := wk.length + work = make([]float64, lwork) + for i := range work { + work[i] = rnd.Float64() + } + copy(a, aCopy) + impl.Dgerqf(m, n, a, lda, tau, work, lwork) + + // Test that the RQ factorization has completed successfully. Compute + // Q based on the vectors. + q := constructQ("RQ", m, n, a, lda, tau) + + // Check that q is orthonormal + for i := 0; i < q.Rows; i++ { + nrm := blas64.Nrm2(q.Cols, blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}) + if math.IsNaN(nrm) || math.Abs(nrm-1) > 1e-14 { + t.Errorf("Case %v, q not normal", c) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(q.Cols, blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}, blas64.Vector{Inc: 1, Data: q.Data[j*q.Stride:]}) + if math.IsNaN(dot) || math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", c) + } + } + } + // Check that A = R * Q + r := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < m; i++ { + off := m - n + for j := max(0, i-off); j < n; j++ { + r.Data[i*r.Stride+j] = a[i*lda+j] + } + } + + got := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, r, q, 0, got) + want := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: aCopy, + } + if !equalApproxGeneral(got, want, 1e-14) { + t.Errorf("Case %d, R*Q != a %s\ngot: %+v\nwant:%+v", c, wk.name, got, want) + } + } + } +} diff --git a/lapack/testlapack/dgesvd.go b/lapack/testlapack/dgesvd.go new file mode 100644 index 00000000..8c317993 --- /dev/null +++ b/lapack/testlapack/dgesvd.go @@ -0,0 +1,286 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dgesvder interface { + Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, lwork int) (ok bool) +} + +func DgesvdTest(t *testing.T, impl Dgesvder) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Add tests for all of the cases when the SVD implementation + // is finished. + // TODO(btracey): Add tests for m > mnthr and n > mnthr when other SVD + // conditions are implemented. Right now mnthr is 5,000,000 which is too + // large to create a square matrix of that size. + for _, test := range []struct { + m, n, lda, ldu, ldvt int + }{ + {5, 5, 0, 0, 0}, + {5, 6, 0, 0, 0}, + {6, 5, 0, 0, 0}, + {5, 9, 0, 0, 0}, + {9, 5, 0, 0, 0}, + + {5, 5, 10, 11, 12}, + {5, 6, 10, 11, 12}, + {6, 5, 10, 11, 12}, + {5, 5, 10, 11, 12}, + {5, 9, 10, 11, 12}, + {9, 5, 10, 11, 12}, + + {300, 300, 0, 0, 0}, + {300, 400, 0, 0, 0}, + {400, 300, 0, 0, 0}, + {300, 600, 0, 0, 0}, + {600, 300, 0, 0, 0}, + + {300, 300, 400, 450, 460}, + {300, 400, 500, 550, 560}, + {400, 300, 550, 550, 560}, + {300, 600, 700, 750, 760}, + {600, 300, 700, 750, 760}, + } { + jobU := lapack.SVDAll + jobVT := lapack.SVDAll + + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + ldu := test.ldu + if ldu == 0 { + ldu = m + } + ldvt := test.ldvt + if ldvt == 0 { + ldvt = n + } + + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + u := make([]float64, m*ldu) + for i := range u { + u[i] = rnd.NormFloat64() + } + + vt := make([]float64, n*ldvt) + for i := range vt { + vt[i] = rnd.NormFloat64() + } + + uAllOrig := make([]float64, len(u)) + copy(uAllOrig, u) + vtAllOrig := make([]float64, len(vt)) + copy(vtAllOrig, vt) + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + s := make([]float64, min(m, n)) + + work := make([]float64, 1) + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, vt, ldvt, work, -1) + + if !floats.Equal(a, aCopy) { + t.Errorf("a changed during call to get work length") + } + + work = make([]float64, int(work[0])) + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, vt, ldvt, work, len(work)) + + errStr := fmt.Sprintf("m = %v, n = %v, lda = %v, ldu = %v, ldv = %v", m, n, lda, ldu, ldvt) + svdCheck(t, false, errStr, m, n, s, a, u, ldu, vt, ldvt, aCopy, lda) + svdCheckPartial(t, impl, lapack.SVDAll, errStr, uAllOrig, vtAllOrig, aCopy, m, n, a, lda, s, u, ldu, vt, ldvt, work, false) + + // Test InPlace + jobU = lapack.SVDInPlace + jobVT = lapack.SVDInPlace + copy(a, aCopy) + copy(u, uAllOrig) + copy(vt, vtAllOrig) + + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, vt, ldvt, work, len(work)) + svdCheck(t, true, errStr, m, n, s, a, u, ldu, vt, ldvt, aCopy, lda) + svdCheckPartial(t, impl, lapack.SVDInPlace, errStr, uAllOrig, vtAllOrig, aCopy, m, n, a, lda, s, u, ldu, vt, ldvt, work, false) + } +} + +// svdCheckPartial checks that the singular values and vectors are computed when +// not all of them are computed. +func svdCheckPartial(t *testing.T, impl Dgesvder, job lapack.SVDJob, errStr string, uAllOrig, vtAllOrig, aCopy []float64, m, n int, a []float64, lda int, s, u []float64, ldu int, vt []float64, ldvt int, work []float64, shortWork bool) { + rnd := rand.New(rand.NewSource(1)) + jobU := job + jobVT := job + // Compare the singular values when computed with {SVDNone, SVDNone.} + sCopy := make([]float64, len(s)) + copy(sCopy, s) + copy(a, aCopy) + for i := range s { + s[i] = rnd.Float64() + } + tmp1 := make([]float64, 1) + tmp2 := make([]float64, 1) + jobU = lapack.SVDNone + jobVT = lapack.SVDNone + + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, tmp1, ldu, tmp2, ldvt, work, -1) + work = make([]float64, int(work[0])) + lwork := len(work) + if shortWork { + lwork-- + } + ok := impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, tmp1, ldu, tmp2, ldvt, work, lwork) + if !ok { + t.Errorf("Dgesvd did not complete successfully") + } + if !floats.EqualApprox(s, sCopy, 1e-10) { + t.Errorf("Singular value mismatch when singular vectors not computed: %s", errStr) + } + // Check that the singular vectors are correctly computed when the other + // is none. + uAll := make([]float64, len(u)) + copy(uAll, u) + vtAll := make([]float64, len(vt)) + copy(vtAll, vt) + + // Copy the original vectors so the data outside the matrix bounds is the same. + copy(u, uAllOrig) + copy(vt, vtAllOrig) + + jobU = job + jobVT = lapack.SVDNone + copy(a, aCopy) + for i := range s { + s[i] = rnd.Float64() + } + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, tmp2, ldvt, work, -1) + work = make([]float64, int(work[0])) + lwork = len(work) + if shortWork { + lwork-- + } + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, u, ldu, tmp2, ldvt, work, len(work)) + if !floats.EqualApprox(uAll, u, 1e-10) { + t.Errorf("U mismatch when VT is not computed: %s", errStr) + } + if !floats.EqualApprox(s, sCopy, 1e-10) { + t.Errorf("Singular value mismatch when U computed VT not") + } + jobU = lapack.SVDNone + jobVT = job + copy(a, aCopy) + for i := range s { + s[i] = rnd.Float64() + } + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, tmp1, ldu, vt, ldvt, work, -1) + work = make([]float64, int(work[0])) + lwork = len(work) + if shortWork { + lwork-- + } + impl.Dgesvd(jobU, jobVT, m, n, a, lda, s, tmp1, ldu, vt, ldvt, work, len(work)) + if !floats.EqualApprox(vtAll, vt, 1e-10) { + t.Errorf("VT mismatch when U is not computed: %s", errStr) + } + if !floats.EqualApprox(s, sCopy, 1e-10) { + t.Errorf("Singular value mismatch when VT computed U not") + } +} + +// svdCheck checks that the singular value decomposition correctly multiplies back +// to the original matrix. +func svdCheck(t *testing.T, thin bool, errStr string, m, n int, s, a, u []float64, ldu int, vt []float64, ldvt int, aCopy []float64, lda int) { + sigma := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + for i := 0; i < min(m, n); i++ { + sigma.Data[i*sigma.Stride+i] = s[i] + } + + uMat := blas64.General{ + Rows: m, + Cols: m, + Stride: ldu, + Data: u, + } + vTMat := blas64.General{ + Rows: n, + Cols: n, + Stride: ldvt, + Data: vt, + } + if thin { + sigma.Rows = min(m, n) + sigma.Cols = min(m, n) + uMat.Cols = min(m, n) + vTMat.Rows = min(m, n) + } + + tmp := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + ans := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(ans.Data, a) + + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, uMat, sigma, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, vTMat, 0, ans) + + if !floats.EqualApprox(ans.Data, aCopy, 1e-8) { + t.Errorf("Decomposition mismatch. Trim = %v, %s", thin, errStr) + } + + if !thin { + // Check that U and V are orthogonal. + for i := 0; i < uMat.Rows; i++ { + for j := i + 1; j < uMat.Rows; j++ { + dot := blas64.Dot(uMat.Cols, + blas64.Vector{Inc: 1, Data: uMat.Data[i*uMat.Stride:]}, + blas64.Vector{Inc: 1, Data: uMat.Data[j*uMat.Stride:]}, + ) + if dot > 1e-8 { + t.Errorf("U not orthogonal %s", errStr) + } + } + } + for i := 0; i < vTMat.Rows; i++ { + for j := i + 1; j < vTMat.Rows; j++ { + dot := blas64.Dot(vTMat.Cols, + blas64.Vector{Inc: 1, Data: vTMat.Data[i*vTMat.Stride:]}, + blas64.Vector{Inc: 1, Data: vTMat.Data[j*vTMat.Stride:]}, + ) + if dot > 1e-8 { + t.Errorf("V not orthogonal %s", errStr) + } + } + } + } +} diff --git a/lapack/testlapack/dgetf2.go b/lapack/testlapack/dgetf2.go new file mode 100644 index 00000000..7cb155e9 --- /dev/null +++ b/lapack/testlapack/dgetf2.go @@ -0,0 +1,195 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgetf2er interface { + Dgetf2(m, n int, a []float64, lda int, ipiv []int) bool +} + +func Dgetf2Test(t *testing.T, impl Dgetf2er) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {10, 10, 0}, + {10, 5, 0}, + {10, 5, 0}, + + {10, 10, 20}, + {5, 10, 20}, + {10, 5, 20}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + mn := min(m, n) + ipiv := make([]int, mn) + for i := range ipiv { + ipiv[i] = rnd.Int() + } + ok := impl.Dgetf2(m, n, a, lda, ipiv) + checkPLU(t, ok, m, n, lda, ipiv, a, aCopy, 1e-14, true) + } + + // Test with singular matrices (random matrices are almost surely non-singular). + for _, test := range []struct { + m, n, lda int + a []float64 + }{ + { + m: 2, + n: 2, + lda: 2, + a: []float64{ + 1, 0, + 0, 0, + }, + }, + { + m: 2, + n: 2, + lda: 2, + a: []float64{ + 1, 5, + 2, 10, + }, + }, + { + m: 3, + n: 3, + lda: 3, + // row 3 = row1 + 2 * row2 + a: []float64{ + 1, 5, 7, + 2, 10, -3, + 5, 25, 1, + }, + }, + { + m: 3, + n: 4, + lda: 4, + // row 3 = row1 + 2 * row2 + a: []float64{ + 1, 5, 7, 9, + 2, 10, -3, 11, + 5, 25, 1, 31, + }, + }, + } { + if impl.Dgetf2(test.m, test.n, test.a, test.lda, make([]int, min(test.m, test.n))) { + t.Log("Returned ok with singular matrix.") + } + } +} + +// checkPLU checks that the PLU factorization contained in factorize matches +// the original matrix contained in original. +func checkPLU(t *testing.T, ok bool, m, n, lda int, ipiv []int, factorized, original []float64, tol float64, print bool) { + var hasZeroDiagonal bool + for i := 0; i < min(m, n); i++ { + if factorized[i*lda+i] == 0 { + hasZeroDiagonal = true + break + } + } + if hasZeroDiagonal && ok { + t.Error("Has a zero diagonal but returned ok") + } + if !hasZeroDiagonal && !ok { + t.Error("Non-zero diagonal but returned !ok") + } + + // Check that the LU decomposition is correct. + mn := min(m, n) + l := make([]float64, m*mn) + ldl := mn + u := make([]float64, mn*n) + ldu := n + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + v := factorized[i*lda+j] + switch { + case i == j: + l[i*ldl+i] = 1 + u[i*ldu+i] = v + case i > j: + l[i*ldl+j] = v + case i < j: + u[i*ldu+j] = v + } + } + } + + LU := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + U := blas64.General{ + Rows: mn, + Cols: n, + Stride: ldu, + Data: u, + } + L := blas64.General{ + Rows: m, + Cols: mn, + Stride: ldl, + Data: l, + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, L, U, 0, LU) + + p := make([]float64, m*m) + ldp := m + for i := 0; i < m; i++ { + p[i*ldp+i] = 1 + } + for i := len(ipiv) - 1; i >= 0; i-- { + v := ipiv[i] + blas64.Swap(m, blas64.Vector{Inc: 1, Data: p[i*ldp:]}, blas64.Vector{Inc: 1, Data: p[v*ldp:]}) + } + P := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: p, + } + aComp := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(aComp.Data, factorized) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, P, LU, 0, aComp) + if !floats.EqualApprox(aComp.Data, original, tol) { + if print { + t.Errorf("PLU multiplication does not match original matrix.\nWant: %v\nGot: %v", original, aComp.Data) + return + } + t.Error("PLU multiplication does not match original matrix.") + } +} diff --git a/lapack/testlapack/dgetrf.go b/lapack/testlapack/dgetrf.go new file mode 100644 index 00000000..1c9c6e45 --- /dev/null +++ b/lapack/testlapack/dgetrf.go @@ -0,0 +1,65 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" +) + +type Dgetrfer interface { + Dgetrf(m, n int, a []float64, lda int, ipiv []int) bool +} + +func DgetrfTest(t *testing.T, impl Dgetrfer) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {10, 5, 0}, + {5, 10, 0}, + {10, 10, 0}, + {300, 5, 0}, + {3, 500, 0}, + {4, 5, 0}, + {300, 200, 0}, + {204, 300, 0}, + {1, 3000, 0}, + {3000, 1, 0}, + {10, 5, 20}, + {5, 10, 20}, + {10, 10, 20}, + {300, 5, 400}, + {3, 500, 600}, + {200, 200, 300}, + {300, 200, 300}, + {204, 300, 400}, + {1, 3000, 4000}, + {3000, 1, 4000}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + mn := min(m, n) + ipiv := make([]int, mn) + for i := range ipiv { + ipiv[i] = rnd.Int() + } + + // Cannot compare the outputs of Dgetrf and Dgetf2 because the pivoting may + // happen differently. Instead check that the LPQ factorization is correct. + aCopy := make([]float64, len(a)) + copy(aCopy, a) + ok := impl.Dgetrf(m, n, a, lda, ipiv) + checkPLU(t, ok, m, n, lda, ipiv, a, aCopy, 1e-10, false) + } +} diff --git a/lapack/testlapack/dgetri.go b/lapack/testlapack/dgetri.go new file mode 100644 index 00000000..fd79df2a --- /dev/null +++ b/lapack/testlapack/dgetri.go @@ -0,0 +1,89 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dgetrier interface { + Dgetrfer + Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) bool +} + +func DgetriTest(t *testing.T, impl Dgetrier) { + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, test := range []struct { + n, lda int + }{ + {5, 0}, + {5, 8}, + {45, 0}, + {45, 50}, + {65, 0}, + {65, 70}, + {150, 0}, + {150, 250}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + // Generate a random well conditioned matrix + perm := rnd.Perm(n) + a := make([]float64, n*lda) + for i := 0; i < n; i++ { + a[i*lda+perm[i]] = 1 + } + for i := range a { + a[i] += 0.01 * rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + ipiv := make([]int, n) + // Compute LU decomposition. + impl.Dgetrf(n, n, a, lda, ipiv) + // Compute inverse. + work := make([]float64, 1) + impl.Dgetri(n, a, lda, ipiv, work, -1) + work = make([]float64, int(work[0])) + lwork := len(work) + + ok := impl.Dgetri(n, a, lda, ipiv, work, lwork) + if !ok { + t.Errorf("Unexpected singular matrix.") + } + + // Check that A(inv) * A = I. + ans := make([]float64, len(a)) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, aCopy, lda, a, lda, 0, ans, lda) + isEye := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i == j { + // This tolerance is so high because computing matrix inverses + // is very unstable. + if math.Abs(ans[i*lda+j]-1) > 5e-2 { + isEye = false + } + } else { + if math.Abs(ans[i*lda+j]) > 5e-2 { + isEye = false + } + } + } + } + if !isEye { + t.Errorf("Inv(A) * A != I. n = %v, lda = %v", n, lda) + } + } +} diff --git a/lapack/testlapack/dgetrs.go b/lapack/testlapack/dgetrs.go new file mode 100644 index 00000000..edc6d502 --- /dev/null +++ b/lapack/testlapack/dgetrs.go @@ -0,0 +1,113 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dgetrser interface { + Dgetrfer + Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) +} + +func DgetrsTest(t *testing.T, impl Dgetrser) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Put more thought into creating more regularized matrices + // and what correct tolerances should be. Consider also seeding the random + // number in this test to make it more robust to code changes in other + // parts of the suite. + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + n, nrhs, lda, ldb int + tol float64 + }{ + {3, 3, 0, 0, 1e-12}, + {3, 5, 0, 0, 1e-12}, + {5, 3, 0, 0, 1e-12}, + + {3, 3, 8, 10, 1e-12}, + {3, 5, 8, 10, 1e-12}, + {5, 3, 8, 10, 1e-12}, + + {300, 300, 0, 0, 1e-8}, + {300, 500, 0, 0, 1e-8}, + {500, 300, 0, 0, 1e-6}, + + {300, 300, 700, 600, 1e-8}, + {300, 500, 700, 600, 1e-8}, + {500, 300, 700, 600, 1e-6}, + } { + n := test.n + nrhs := test.nrhs + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = nrhs + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + } + b := make([]float64, n*ldb) + for i := range b { + b[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + bCopy := make([]float64, len(b)) + copy(bCopy, b) + + ipiv := make([]int, n) + for i := range ipiv { + ipiv[i] = rnd.Int() + } + + // Compute the LU factorization. + impl.Dgetrf(n, n, a, lda, ipiv) + // Solve the system of equations given the result. + impl.Dgetrs(trans, n, nrhs, a, lda, ipiv, b, ldb) + + // Check that the system of equations holds. + A := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: aCopy, + } + B := blas64.General{ + Rows: n, + Cols: nrhs, + Stride: ldb, + Data: bCopy, + } + X := blas64.General{ + Rows: n, + Cols: nrhs, + Stride: ldb, + Data: b, + } + tmp := blas64.General{ + Rows: n, + Cols: nrhs, + Stride: ldb, + Data: make([]float64, n*ldb), + } + copy(tmp.Data, bCopy) + blas64.Gemm(trans, blas.NoTrans, 1, A, X, 0, B) + if !floats.EqualApprox(tmp.Data, bCopy, test.tol) { + t.Errorf("Linear solve mismatch. trans = %v, n = %v, nrhs = %v, lda = %v, ldb = %v", trans, n, nrhs, lda, ldb) + } + } + } +} diff --git a/lapack/testlapack/dggsvd3.go b/lapack/testlapack/dggsvd3.go new file mode 100644 index 00000000..0a4af656 --- /dev/null +++ b/lapack/testlapack/dggsvd3.go @@ -0,0 +1,173 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dggsvd3er interface { + Dggsvd3(jobU, jobV, jobQ lapack.GSVDJob, m, n, p int, a []float64, lda int, b []float64, ldb int, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64, lwork int, iwork []int) (k, l int, ok bool) +} + +func Dggsvd3Test(t *testing.T, impl Dggsvd3er) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + m, p, n, lda, ldb, ldu, ldv, ldq int + + ok bool + }{ + {m: 3, p: 3, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 10, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 10, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10, ok: true}, + {m: 5, p: 5, n: 5, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10, ok: true}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 10, p: 5, n: 5, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10, ok: true}, + {m: 10, p: 5, n: 5, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10, ok: true}, + {m: 10, p: 10, n: 10, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20, ok: true}, + {m: 10, p: 10, n: 10, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20, ok: true}, + } { + m := test.m + p := test.p + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = n + } + ldu := test.ldu + if ldu == 0 { + ldu = m + } + ldv := test.ldv + if ldv == 0 { + ldv = p + } + ldq := test.ldq + if ldq == 0 { + ldq = n + } + + a := randomGeneral(m, n, lda, rnd) + aCopy := cloneGeneral(a) + b := randomGeneral(p, n, ldb, rnd) + bCopy := cloneGeneral(b) + + alpha := make([]float64, n) + beta := make([]float64, n) + + u := nanGeneral(m, m, ldu) + v := nanGeneral(p, p, ldv) + q := nanGeneral(n, n, ldq) + + iwork := make([]int, n) + + work := []float64{0} + impl.Dggsvd3(lapack.GSVDU, lapack.GSVDV, lapack.GSVDQ, + m, n, p, + a.Data, a.Stride, + b.Data, b.Stride, + alpha, beta, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + work, -1, iwork) + + lwork := int(work[0]) + work = make([]float64, lwork) + + k, l, ok := impl.Dggsvd3(lapack.GSVDU, lapack.GSVDV, lapack.GSVDQ, + m, n, p, + a.Data, a.Stride, + b.Data, b.Stride, + alpha, beta, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + work, lwork, iwork) + + if !ok { + if test.ok { + t.Errorf("test %d unexpectedly did not converge", cas) + } + continue + } + + // Check orthogonality of U, V and Q. + if !isOrthonormal(u) { + t.Errorf("test %d: U is not orthogonal\n%+v", cas, u) + } + if !isOrthonormal(v) { + t.Errorf("test %d: V is not orthogonal\n%+v", cas, v) + } + if !isOrthonormal(q) { + t.Errorf("test %d: Q is not orthogonal\n%+v", cas, q) + } + + // Check C^2 + S^2 = I. + var elements []float64 + if m-k-l >= 0 { + elements = alpha[k : k+l] + } else { + elements = alpha[k:m] + } + for i := range elements { + i += k + d := alpha[i]*alpha[i] + beta[i]*beta[i] + if !floats.EqualWithinAbsOrRel(d, 1, 1e-14, 1e-14) { + t.Errorf("test %d: alpha_%d^2 + beta_%d^2 != 1: got: %v", cas, i, i, d) + } + } + + zeroR, d1, d2 := constructGSVDresults(n, p, m, k, l, a, b, alpha, beta) + + // Check U^T*A*Q = D1*[ 0 R ]. + uTmp := nanGeneral(m, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, u, aCopy, 0, uTmp) + uAns := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, uTmp, q, 0, uAns) + + d10r := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d1, zeroR, 0, d10r) + + if !equalApproxGeneral(uAns, d10r, 1e-14) { + t.Errorf("test %d: U^T*A*Q != D1*[ 0 R ]\nU^T*A*Q:\n%+v\nD1*[ 0 R ]:\n%+v", + cas, uAns, d10r) + } + + // Check V^T*B*Q = D2*[ 0 R ]. + vTmp := nanGeneral(p, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, v, bCopy, 0, vTmp) + vAns := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vTmp, q, 0, vAns) + + d20r := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d2, zeroR, 0, d20r) + + if !equalApproxGeneral(vAns, d20r, 1e-14) { + t.Errorf("test %d: V^T*B*Q != D2*[ 0 R ]\nV^T*B*Q:\n%+v\nD2*[ 0 R ]:\n%+v", + cas, vAns, d20r) + } + } +} diff --git a/lapack/testlapack/dggsvp3.go b/lapack/testlapack/dggsvp3.go new file mode 100644 index 00000000..23111518 --- /dev/null +++ b/lapack/testlapack/dggsvp3.go @@ -0,0 +1,146 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dggsvp3er interface { + Dlanger + Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, iwork []int, tau, work []float64, lwork int) (k, l int) +} + +func Dggsvp3Test(t *testing.T, impl Dggsvp3er) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + m, p, n, lda, ldb, ldu, ldv, ldq int + }{ + {m: 3, p: 3, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 10, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 10, p: 5, n: 5, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 10, p: 10, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 10, p: 10, n: 10, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0}, + {m: 5, p: 5, n: 5, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10}, + {m: 5, p: 5, n: 5, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20}, + {m: 5, p: 5, n: 10, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20}, + {m: 10, p: 5, n: 5, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10}, + {m: 10, p: 5, n: 5, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10}, + {m: 10, p: 10, n: 10, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20}, + {m: 10, p: 10, n: 10, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20}, + } { + m := test.m + p := test.p + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = n + } + ldu := test.ldu + if ldu == 0 { + ldu = m + } + ldv := test.ldv + if ldv == 0 { + ldv = p + } + ldq := test.ldq + if ldq == 0 { + ldq = n + } + + a := randomGeneral(m, n, lda, rnd) + aCopy := cloneGeneral(a) + b := randomGeneral(p, n, ldb, rnd) + bCopy := cloneGeneral(b) + + tola := float64(max(m, n)) * impl.Dlange(lapack.NormFrob, m, n, a.Data, a.Stride, nil) * dlamchE + tolb := float64(max(p, n)) * impl.Dlange(lapack.NormFrob, p, n, b.Data, b.Stride, nil) * dlamchE + + u := nanGeneral(m, m, ldu) + v := nanGeneral(p, p, ldv) + q := nanGeneral(n, n, ldq) + + iwork := make([]int, n) + tau := make([]float64, n) + + work := []float64{0} + impl.Dggsvp3(lapack.GSVDU, lapack.GSVDV, lapack.GSVDQ, + m, p, n, + a.Data, a.Stride, + b.Data, b.Stride, + tola, tolb, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + iwork, tau, + work, -1) + + lwork := int(work[0]) + work = make([]float64, lwork) + + k, l := impl.Dggsvp3(lapack.GSVDU, lapack.GSVDV, lapack.GSVDQ, + m, p, n, + a.Data, a.Stride, + b.Data, b.Stride, + tola, tolb, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + iwork, tau, + work, lwork) + + // Check orthogonality of U, V and Q. + if !isOrthonormal(u) { + t.Errorf("test %d: U is not orthogonal\n%+v", cas, u) + } + if !isOrthonormal(v) { + t.Errorf("test %d: V is not orthogonal\n%+v", cas, v) + } + if !isOrthonormal(q) { + t.Errorf("test %d: Q is not orthogonal\n%+v", cas, q) + } + + zeroA, zeroB := constructGSVPresults(n, p, m, k, l, a, b) + + // Check U^T*A*Q = [ 0 RA ]. + uTmp := nanGeneral(m, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, u, aCopy, 0, uTmp) + uAns := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, uTmp, q, 0, uAns) + + if !equalApproxGeneral(uAns, zeroA, 1e-14) { + t.Errorf("test %d: U^T*A*Q != [ 0 RA ]\nU^T*A*Q:\n%+v\n[ 0 RA ]:\n%+v", + cas, uAns, zeroA) + } + + // Check V^T*B*Q = [ 0 RB ]. + vTmp := nanGeneral(p, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, v, bCopy, 0, vTmp) + vAns := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vTmp, q, 0, vAns) + + if !equalApproxGeneral(vAns, zeroB, 1e-14) { + t.Errorf("test %d: V^T*B*Q != [ 0 RB ]\nV^T*B*Q:\n%+v\n[ 0 RB ]:\n%+v", + cas, vAns, zeroB) + } + } +} diff --git a/lapack/testlapack/dhseqr.go b/lapack/testlapack/dhseqr.go new file mode 100644 index 00000000..a12102b4 --- /dev/null +++ b/lapack/testlapack/dhseqr.go @@ -0,0 +1,861 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dhseqrer interface { + Dhseqr(job lapack.EVJob, compz lapack.EVComp, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, + z []float64, ldz int, work []float64, lwork int) int +} + +type dhseqrTest struct { + n int + ilo int + ihi int + h []float64 + tol float64 + + evWant []complex128 +} + +func DhseqrTest(t *testing.T, impl Dhseqrer) { + for i, tc := range dhseqrTests { + for _, job := range []lapack.EVJob{lapack.EigenvaluesOnly, lapack.EigenvaluesAndSchur} { + for _, wantz := range []bool{false, true} { + for _, extra := range []int{0, 11} { + testDhseqr(t, impl, i, tc, job, wantz, extra, true) + testDhseqr(t, impl, i, tc, job, wantz, extra, false) + } + } + } + } +} + +func testDhseqr(t *testing.T, impl Dhseqrer, i int, test dhseqrTest, job lapack.EVJob, wantz bool, extra int, optwork bool) { + const tol = 1e-14 + evTol := test.tol + if evTol == 0 { + evTol = tol + } + + n := test.n + ihi := test.ihi + ilo := test.ilo + h := zeros(n, n, n+extra) + copyGeneral(h, blas64.General{Rows: n, Cols: n, Stride: max(1, n), Data: test.h}) + hCopy := cloneGeneral(h) + + var compz lapack.EVComp = lapack.None + z := blas64.General{Stride: max(1, n)} + if wantz { + // First, let Dhseqr initialize Z to the identity matrix. + compz = lapack.HessEV + z = nanGeneral(n, n, n+extra) + } + + wr := nanSlice(n) + wi := nanSlice(n) + + work := nanSlice(max(1, n)) + if optwork { + impl.Dhseqr(job, lapack.HessEV, n, ilo, ihi, nil, h.Stride, nil, nil, nil, z.Stride, work, -1) + work = nanSlice(int(work[0])) + } + + unconverged := impl.Dhseqr(job, compz, n, ilo, ihi, h.Data, h.Stride, wr, wi, z.Data, z.Stride, work, len(work)) + prefix := fmt.Sprintf("Case %v: job=%v, compz=%v, n=%v, ilo=%v, ihi=%v, extra=%v, optwk=%v", + i, job, compz, n, ilo, ihi, extra, optwork) + if unconverged > 0 { + t.Log("%v: Dhseqr did not compute all eigenvalues. unconverged=%v", prefix, unconverged) + if unconverged <= ilo { + t.Fatalf("%v: 0 < unconverged <= ilo", prefix) + } + } + + // Check that wr and wi have been assigned completely. + if floats.HasNaN(wr) { + t.Errorf("%v: wr has NaN elements", prefix) + } + if floats.HasNaN(wi) { + t.Errorf("%v: wi has NaN elements", prefix) + } + + // Check that complex eigenvalues are stored in consecutive elements as + // complex conjugate pairs. + for i := 0; i < n; { + if unconverged > 0 && i == ilo { + // Skip the unconverged eigenvalues. + i = unconverged + continue + } + if wi[i] == 0 { + // Real eigenvalue. + i++ + continue + } + // Complex conjugate pair. + if wr[i] != wr[i+1] { + t.Errorf("%v: conjugate pair has real parts unequal", prefix) + } + if wi[i] < 0 { + t.Errorf("%v: first in conjugate pair has negative imaginary part", prefix) + } + if wi[i+1] != -wi[i] { + t.Errorf("%v: complex pair is not conjugate", prefix) + } + i += 2 + } + + // Check that H contains the Schur form T. + if job == lapack.EigenvaluesAndSchur { + for i := 0; i < n; { + if unconverged > 0 && i == ilo { + // Skip the unconverged eigenvalues. + i = unconverged + continue + } + if wi[i] == 0 { + // Real eigenvalue. + if wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: T not in Schur form (real eigenvalue not on diagonal)", prefix) + } + i++ + continue + } + // Complex conjugate pair. + im := math.Sqrt(math.Abs(h.Data[(i+1)*h.Stride+i])) * math.Sqrt(math.Abs(h.Data[i*h.Stride+i+1])) + if wr[i] != h.Data[i*h.Stride+i] || wr[i] != h.Data[(i+1)*h.Stride+i+1] || + math.Abs(wi[i]-im) > tol { + t.Errorf("%v: conjugate pair and 2×2 diagonal block don't correspond", prefix) + } + i += 2 + } + } + + // Check that all the found eigenvalues are really eigenvalues. + foundEV := make([]bool, len(test.evWant)) + for i := 0; i < n; { + if unconverged > 0 && i == ilo { + // Skip the unconverged eigenvalues. + i = unconverged + continue + } + ev := complex(wr[i], wi[i]) + // Use problem-specific tolerance for testing eigenvalues. + found, index := containsComplex(test.evWant, ev, evTol) + if !found { + t.Errorf("%v: unexpected eigenvalue %v", prefix, ev) + } else { + foundEV[index] = true + } + i++ + } + if unconverged == 0 { + // Check that all eigenvalues have been found. + // This simple check assumes that all eigenvalues are + // sufficiently separated from each other at least by evTol. + for i := range foundEV { + if !foundEV[i] { + t.Errorf("%v: %vth eigenvalue not found", prefix, i) + } + } + } + + if !wantz { + return + } + + // Z must be orthogonal. + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + + if job == lapack.EigenvaluesAndSchur { + tz := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.Trans, 1, h, z, 0, tz) + ztz := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, z, tz, 0, ztz) + if !equalApproxGeneral(ztz, hCopy, evTol) { + t.Errorf("%v: H != Z T Z^T", prefix) + } + } + + // Restore H. + copyGeneral(h, hCopy) + // Call Dhseqr again with the identity matrix given explicitly in Q. + q := eye(n, n+extra) + impl.Dhseqr(job, lapack.OriginalEV, n, ilo, ihi, h.Data, h.Stride, wr, wi, q.Data, q.Stride, work, len(work)) + if !equalApproxGeneral(z, q, 0) { + t.Errorf("%v: Z and Q are not equal", prefix) + } +} + +var dhseqrTests = []dhseqrTest{ + { + n: 0, + ilo: 0, + ihi: -1, + }, + { + n: 1, + ilo: 0, + ihi: 0, + h: []float64{0}, + evWant: []complex128{0}, + }, + { + n: 1, + ilo: 0, + ihi: 0, + h: []float64{7.09965484086874e-1}, + evWant: []complex128{7.09965484086874e-1}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{0, 0, 0, 0}, + evWant: []complex128{0}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{ + 1, 0, + 0, 1, + }, + evWant: []complex128{1}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{ + 0, -1, + 1, 0, + }, + evWant: []complex128{1i, -1i}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{ + 6.25219991450918e-1, 8.17510791994361e-1, + 3.31218891622294e-1, 1.24103744878131e-1, + }, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + n: 4, + ilo: 1, + ihi: 2, + h: []float64{ + 1, 0, 0, 0, + 0, 6.25219991450918e-1, 8.17510791994361e-1, 0, + 0, 3.31218891622294e-1, 1.24103744878131e-1, 0, + 0, 0, 0, 2, + }, + evWant: []complex128{1, 2, 9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + n: 2, + ilo: 0, + ihi: 1, + h: []float64{ + -1.1219562276608, 6.85473513349362e-1, + -8.19951061145131e-1, 1.93728523178888e-1, + }, + evWant: []complex128{ + -4.64113852240958e-1 + 3.59580510817350e-1i, + -4.64113852240958e-1 - 3.59580510817350e-1i, + }, + }, + { + n: 5, + ilo: 0, + ihi: 4, + h: []float64{ + 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2, + -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1, + 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1, + 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1, + 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1, + }, + evWant: []complex128{ + 2.94393309555622, + 4.97029793606701e-1 + 3.63041654992384e-1i, + 4.97029793606701e-1 - 3.63041654992384e-1i, + -1.74079119166145e-1 + 2.01570009462092e-1i, + -1.74079119166145e-1 - 2.01570009462092e-1i, + }, + }, + { + // BFW62A matrix from MatrixMarket, balanced and factorized into + // upper Hessenberg form in Octave. + // Eigenvalues computed by eig function in Octave. + // Dhseqr considers this matrix small (n <= 75). + n: 62, + ilo: 0, + ihi: 61, + tol: 1e-12, + h: []float64{ + 0.7610708, -0.71474042262732, -1.03373461417302e-17, 8.218284875369092e-18, -4.39003777724509e-18, -7.633870714681998e-18, -9.951525116511751e-18, -6.538760279193677e-18, -1.656240811786753e-18, -4.915424973452908e-18, -7.590492820502813e-18, -4.532592864746854e-18, 1.137360639223451e-18, -2.088794138001457e-18, 4.330727699351238e-18, 4.88172964159538e-18, -6.438459345602974e-18, 7.414402965763168e-18, 8.592387304092668e-19, 2.905505475188102e-18, -5.210204793418634e-18, 2.377023457149656e-18, -1.958364175388968e-18, -8.746122759061733e-20, 1.839015672758814e-18, 3.097454207400904e-18, 1.545856657360309e-18, 1.713923049773744e-21, 1.333951071201153e-18, -1.256151066318485e-18, 5.489655201308922e-19, -2.191335276195054e-18, 3.211054779957158e-18, -4.585099368362507e-19, 4.064807180521144e-18, -3.621561583390336e-18, 4.638803832189033e-19, 1.306132013406548e-18, 7.71710094138792e-19, 2.320760977517361e-18, -6.538298612520761e-19, -3.498839827985687e-18, 2.699116500378558e-18, -1.653627855476782e-18, 7.006984532830204e-19, -2.829108657299736e-18, -5.260772120044258e-18, 1.014346572590618e-18, -1.751563831849658e-18, -1.850186018112724e-19, 2.870415308417256e-18, -8.423700664162806e-19, 3.498345394735042e-19, 1.448350507022323e-18, -3.119800500343431e-18, 4.170966784863917e-18, -4.413795207992463e-19, -2.550853151356032e-18, 2.058575286932081e-18, 1.11609155804576e-18, -2.819648393130598e-18, -2.691434041700446e-19, + -0.71474042262732, 1.938395745278447, -1.179041092366627, 2.994496337305918e-17, -1.886890458028042e-17, -1.696051150581149e-17, -1.066654178739982e-17, -6.29828959344471e-18, -3.017613522337327e-18, -6.087774183044001e-18, -1.623722797471356e-17, -1.609066043798334e-17, 1.1222991062801e-17, -1.199415856132727e-17, 3.254808477409891e-17, 3.032574771313234e-17, -2.950307698970009e-17, 3.390164991463985e-17, 3.580652213399182e-17, -1.363239170451582e-17, 5.318959619432346e-19, -2.094826370136215e-17, 2.503105756608372e-17, 1.02172885473953e-17, 2.072365201436764e-17, 5.419721687057681e-17, 2.946627912791419e-17, -1.348815353957071e-17, -6.109538294302727e-18, 8.919596400140564e-19, -4.965011212156456e-18, -8.892555328798407e-18, -8.533370652960768e-18, 2.670935841220357e-17, 6.294143735482237e-17, -6.631964574578866e-17, 1.610888675267686e-17, -1.914212496162892e-17, 7.491989417296875e-17, 2.433601037912241e-17, -3.471972221532949e-17, 1.239231453972595e-18, 8.477927675716922e-17, 1.832368873558869e-17, -3.15614722379294e-17, -3.481308523858143e-17, 8.753655535825511e-17, -2.311094913977048e-17, -1.97736043621337e-17, -4.591312368362259e-18, -4.090767028097941e-17, 9.630744841167777e-17, 6.376373378245906e-17, 3.517117740157962e-18, -4.504796150838874e-17, 7.517908631343054e-17, 5.08947280115584e-17, -1.382149857389238e-17, -2.198919507523352e-18, 7.280187019637593e-18, -4.195544216643798e-17, -1.69351463438629e-16, + 0, -1.179041092366627, 1.770797890903813, 0.9251612011433773, 0.003661446613681521, -0.005110479724841567, 0.0005014497289028411, 0.00268637752732762, -0.003137790817099964, 0.0001251340392028716, 0.005236816389348038, -0.007596537304410319, -0.003216883293048434, 0.002836879838039065, 0.006069520262676079, 0.002668518333518884, 0.009131523505676264, 0.004626632495050776, 0.00181579510454105, 0.001123900611304629, 0.001677485377614088, 0.00363754391761903, -0.0007470406844762735, 0.002833257933303097, -0.0002375815340930377, -0.002849024657372476, -0.0002629124003065383, -0.0009435052243060314, -0.001501677820905836, 0.0007867717317979819, -0.003255814847476796, 0.0001229596171032013, 0.001899497807037465, 0.001586135347885108, -0.002155598204409179, -0.004095921626627291, -0.004749259183184092, -0.0003901939289968589, -0.00126397970751315, 0.001155644134671306, 0.000291837164140963, -0.0008540793573406925, 0.0005498493646965147, -0.000512747881346778, 0.001308619245804509, -0.001057469234737898, 8.364932352209563e-05, -0.0004759538737373512, 0.0002832407173157385, -2.502295625364179e-05, -0.001116422235449543, 0.0008744887175767913, -0.001577030646119032, 0.0006630051771088335, 0.0008174386956312274, 0.0005885600522543514, -0.000529324123745168, 0.0006462360717703873, -0.0005292503950906053, -0.0008409757119361148, 0.001179292096398777, -7.042243897656571e-05, + 0, 0, 0.9256234889252499, 2.188661152704918, -1.116554836905615, -0.02243454666837822, 0.001818477623431723, 0.01031345522542573, -0.02255181751639313, 0.01064389372187288, 0.02644236613167033, -0.03711341885334873, -0.01368507023909662, 0.005876976997280983, 0.04065670610764593, 0.01666467627475975, 0.04720670725274503, 0.02074371568474985, 0.02492606640786733, -0.0007477579555839802, 0.008780018993769038, 0.02228545976823896, -0.001309713708470288, 0.02515283874752867, -0.002695437114195642, -0.03058898397162627, -0.004721936411831751, -0.01112709820777293, 0.005156744291122814, 0.001266520229863774, -0.0173310067274492, 0.006032177243961209, 0.01546906824241716, 0.004122912475005991, -0.01457685983271352, -0.02472315268907353, -0.0146012575743626, 0.01613627552485761, -0.03570849487210562, 0.009634392591632741, 0.01396210133689555, -0.01085301942984549, 0.02308071799914048, -0.01534806641683973, 0.007461896675297811, 0.001678793578211992, -0.004550709803423801, -0.003543952787451961, 0.01328644094056202, 0.01722933205866279, -0.01604068924890588, 0.01061524273934986, -0.01948663408394128, 0.02488657490054273, 0.002560204204893632, -0.007049942019567433, -0.005861737475764968, 0.007063905438215945, -0.01302170441839208, -0.01452116548010346, 0.008856002952171451, 0.003352799875293177, + 0, 0, 0, -1.131565669446545, 3.458875937128813, -2.92300025604371, 0.0004977656856497978, 0.006279968970473544, 0.0775979532222543, -0.07809248806636047, -0.04323656216106807, 0.05001022064587737, 0.003864067108285046, 0.04141643188583877, -0.1284617838883834, -0.04493800214431209, -0.07456343090218126, -0.01563872481200422, -0.1339020629421785, 0.04186908269102881, -0.01575262227867954, -0.05122401589211525, -0.01356095585891559, -0.1061570482803366, 0.01819813598371521, 0.1481253462698246, 0.02550194602547843, 0.04637287461870648, -0.07444378895306285, 0.01361958240422481, 0.04035022896181466, -0.04232248915252568, -0.06075940528348658, 0.027263798939883, 0.03953143432541723, 0.06518841156851282, -0.03410646432627348, -0.1414076406563496, 0.2323217246349602, -0.03415439789233707, -0.1031903658536844, 0.06725801721048928, -0.1560521418148311, 0.1014900809050588, -0.02098771321982528, -0.03982159107235207, 0.03695361299827822, 0.01067293209294729, -0.09426629859219736, -0.1345822610538289, 0.09362330513280395, -0.05670709861587474, 0.1059566486421828, -0.1760916487632087, 0.003702764511325265, 0.07422105386227762, 0.02742567045198715, -0.03734725575689604, 0.08146131944298318, 0.09081980084945049, -0.03823012624212198, -0.02882941691361127, + 0, 0, 0, 0, -2.935177932025793, 5.590160898106907, -2.264162462726681, -0.02411424982833118, -0.1133643811701465, 0.1104837624251364, 0.05106708784671347, -0.03981053811687705, -0.02554107703230142, -0.06918772930550876, 0.1627330379332113, 0.0515325563326872, 0.0562468014393183, 0.0339155492439978, 0.1634368483167388, -0.06785129040640099, 0.04039982620620088, 0.04044710731973533, 0.0285518510842595, 0.1485759249940305, -0.0304537251951914, -0.2009213484930713, -0.05273834253818357, -0.03107458918212595, 0.09792748883617711, -0.0337039884304953, -0.06657284881035327, 0.04914327832710783, 0.07368372187446774, -0.0404082088678178, -0.04421178865717079, -0.0709487906769288, 0.048430647567918, 0.1864479159285081, -0.3079556699470428, 0.01491993158702447, 0.1333753802314968, -0.09591074161204663, 0.1894696359177905, -0.1319027537070656, 0.03081270942006841, 0.04847952392626505, -0.04816809266890478, -0.0008101823853040729, 0.1149477702272877, 0.1970244006374306, -0.1184305631819092, 0.07656633356645355, -0.140928669738484, 0.2423845347140408, -0.01430733985161339, -0.0967298709856266, -0.03791764167457073, 0.04501910433428818, -0.09499757971636948, -0.1139200858550714, 0.04630019674988028, 0.03975991363586522, + 0, 0, 0, 0, 0, -2.266072850070115, 4.40758227065786, -2.187592801167079, 0.04541318743325212, -0.0292500337966509, -0.02398663294591961, -0.0298607436249778, 0.0765927452101913, 0.03477459705241919, -0.0257224121936686, 0.001477537977391887, 0.04674868179804328, -0.07030659618878905, 0.0114383223715982, 0.04039500147294157, -0.06165490536387656, 0.03052165142437121, -0.03151343169646251, -0.04567511071619659, 0.01389646864038026, 0.03406059858329889, 0.07777247587370216, -0.05562215591676438, -0.02972304398764038, 0.04553302018172632, 0.04905358098395964, 0.02540110963535692, 0.00741827563880251, -0.02406479350578768, 0.00798549007761889, -0.02127832597347739, 0.01170084494509563, 0.002383029926628291, 0.02969332847749644, 0.07478610531483831, 0.01311741704707942, 0.004853415796376565, 0.02254889573704177, -0.0008058983249759786, -0.01674237970384834, 0.007747220993838389, 0.001741724814996781, -0.02678508693786828, 0.03009097476646124, -0.06933693587488159, -0.006894177513041368, -0.003212920179243059, 0.006244662438662574, -0.03261491350065344, 0.03016960268159134, -0.001128724172713099, 0.01002372353957473, 0.01549185843206932, -0.01638802914727083, -0.02186759059889685, 0.02607807397124053, -0.01433672343290503, + 0, 0, 0, 0, 0, 0, -2.208506791141428, 5.240066122406224, -2.182709291422287, -0.04831719550093321, -0.03858222961310988, 0.07090414091109702, 0.07618344970454043, 0.01210977758298604, -0.08775997916346844, -0.04209238321226993, -0.08158937930535407, -0.0691978468647506, -0.0718486976078294, 0.004433709126950578, -0.06338689200675134, -0.03622650750929987, -0.007019326939737634, -0.1038169299762074, -0.003664296783585897, 0.1260404715508425, 0.01449365280740196, 0.02152866502194497, -0.04579662426484265, 0.02137306190373941, 0.02841535413798802, -0.04356497460133966, -0.04882163279365745, 0.0002663261307664017, 0.04049595350038757, 0.05101584504101733, 0.02365749339968924, -0.05799471679730656, 0.1571971147245405, -0.01838060269733261, -0.05301211904637573, 0.02796283933445018, -0.0827747400120639, 0.0826539872568238, -0.004639853234141812, -0.03415100337915269, 0.02043301459221876, -0.01420687321749558, -0.07938788384250468, -0.06984431882951091, 0.01979778686221181, -0.05267713009695951, 0.05803585434476307, -0.1172598583231236, 0.01085942096095348, 0.03045318026097962, 0.03931707061762502, -0.0233260419792624, 0.02886660013519448, 0.03861548107303825, -0.03415507841094348, 0.008098200304311437, + 0, 0, 0, 0, 0, 0, 0, -2.279082737682327, 4.179202389209161, 2.014339592778223, -0.04255211810632337, 0.2215228709530191, 0.04554891291433198, -0.1776754857264893, 0.008167590360928265, -0.03396600462822136, -0.2424067171263278, -0.04982603310212124, 0.08199335145408625, -0.1620942794258422, 0.002338101300086993, -0.07021142224421691, 0.09194811379254013, 0.06141720296344315, -0.04343138202962209, -0.07659354927119244, -0.1361105641705367, 0.04365095033370017, 0.1736465880725596, -0.08740865081391179, -0.01477028109128357, -0.0188999323841316, -0.01077877669937425, -0.04294670860685663, 0.01729899060655344, 0.08739236799944389, 0.182034549192379, 0.1742753783161974, -0.2051811283512857, -0.09696129832199611, 0.08343537923840838, -0.04957366782909829, 0.1265093425463374, -0.07142635715461459, 0.03516617105992843, 0.0383997617140459, -0.04104973319490962, 0.02037353120337982, 0.04757894980296348, 0.2227131172970346, -0.07280127948445575, 0.01933448054625989, -0.05548809149836405, 0.2093056702150173, -0.07255565470500472, -0.123599084041237, -0.01537223729308192, 0.002577573950277644, -0.0733551734670323, -0.03190494711187865, -0.03967527247234395, 0.07966579792866824, + 0, 0, 0, 0, 0, 0, 0, 0, 1.903931035374501, 3.824975942360571, -1.918381148171332, -0.1657229385793016, -0.1612950026821678, 0.06698675826395525, 0.126725548868686, 0.05262161401229534, 0.1736974825351408, 0.1645930486922778, -0.008218244683807857, 0.0481824748986632, 0.1029912224929829, 0.04100531176584442, -0.05027752034197176, 0.03600703924093035, -0.03107821795488815, -0.09759422490480313, -0.04354787932553194, 0.08526304164417117, -0.05355786578034339, -0.0210819410892414, -0.1122497139926173, -0.02837719853579051, 0.02149997813969711, 0.06803627465540676, -0.0458177019216118, -0.09920218030202725, -0.1651400777956252, -0.0455277713939929, 0.003337830551949452, -0.06755253724103881, -0.07801076584667281, -0.04572759847378299, -0.02963338925321968, 0.07597836187621793, 0.01430341925034608, -0.02647305556934371, 0.0228555845523007, 0.01546873666210535, -0.03908905892485317, -0.01513876665871793, 0.0042446623219113, 0.03015387459510092, -0.02120400053387252, -0.03598829734362344, 0.004724005614895581, 0.07940598065515762, 0.01643813194117675, 0.005515400875796831, 0.03057541214871107, -0.01882273722478993, 0.001668026830005827, -0.02913002540516653, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.035489145812599, 3.958195998136282, -2.415518953202652, -0.1018252839623988, 0.09113791429521235, -0.143125166149266, -0.02308820648298807, 0.007900495974597297, 0.0891936029052371, -0.191496963455834, 0.08058392972181647, 0.05211306893716722, -0.02786699591928707, 0.007523375632267236, -0.05648289516476343, 0.06927000214275245, 0.1738730341952659, 0.04931088211870207, 0.03078035118979117, -0.09569654581650394, 0.01335103593932622, 0.06192961771791639, -0.02060940913305214, -0.05414923078827102, 0.06346107123244546, 0.02052335161999402, 0.0759441214578726, -0.1238298106880246, -0.2507681676381417, 0.3220100931816501, -0.01147160193974397, -0.1324548043218159, 0.1477869911354369, -0.2406607672124291, 0.06431201000607845, -0.01766450147458312, -0.0548904673124562, 0.05157233284634812, 0.04488059690309322, -0.06177517133954061, -0.23112183069299, 0.2080819465459902, -0.05619520043449243, 0.1795452492137158, -0.204269300276831, -0.01430899089131678, 0.08951777845217569, -0.02653873178692821, -0.04665500591425999, 0.1362175927592773, 0.1872861054389846, -0.02109220243469613, -0.07237982467321609, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.387825495222564, 5.631333594127314, 1.792900160009439, -0.1292562242890975, 0.1708356554410346, 0.04950951151168896, -0.009914110552264667, 0.1304655891154234, 0.1609748354747077, -0.08607480442007164, 0.1610516858008479, 0.006346254683211893, 0.02530117908848513, 0.2023262116291442, -0.04991598539162005, -0.3298986278194697, -0.1487726465103999, 0.04799870466505981, 0.1882318445518781, -0.1206769872912393, -0.09574976849564885, 0.04601707138105179, 0.0715991702971735, 0.0110319870997898, -0.07468722751312951, -0.06360236467100627, 0.03066807997062939, 0.1978804308092757, -0.4403223814664722, -0.09064370852004526, 0.08638179820445273, -0.1181221434581026, 0.2272147516466281, -0.1254616867610615, -0.0001501123827163629, 0.1032892317050803, -0.05195565185717236, 0.04689531008365307, 0.1236167395644631, 0.2849021718663459, -0.08639934992977449, 0.1211622058496298, -0.1593293433814323, 0.2959939998820938, -0.06193112020165896, -0.06245227757105343, -0.04632893647720479, 0.03583128970774434, -0.07735153068129821, -0.1215213155769518, 0.01117363777162431, 0.01224071348068845, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.970568498833333, 3.432745918572068, -2.179945131289983, 0.1549422681053906, 0.02156733618947362, -0.1743403098753009, 0.04884260166424702, 0.161193984588502, -0.2174611110448761, 0.05521624891494294, -0.05887323587614037, 0.1328019445063764, 0.150653877491827, -0.06531521571304157, -0.1543822385517836, -0.2043044123070031, 0.1255799677545108, 0.1951365223394271, -0.1233664137625445, -0.1191855712864921, -0.04903904444926842, 0.01721465629147372, -0.04824417949824886, -0.001809247060549745, 0.04683387964790045, 0.1406402447048902, 0.2582634735034707, -0.2591765142026595, -0.1617309876246061, 0.1040899633433518, -0.09204034179968526, 0.1659716858767694, -0.07258217699057123, 0.1238542047814545, -0.005315457299413418, -0.04888221850509963, 0.02889824196206881, 0.07250335907166307, 0.3039398127688065, -0.1278843615154275, 0.03794117583347663, -0.08815038995197073, 0.3363118210052076, -0.1106312150714128, -0.1943873573646721, -0.03270119577811206, 0.02061769160692044, -0.1147396461667833, -0.04432517129006736, -0.03624512007085111, 0.1372685073992675, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.971094433373163, 3.959369702740928, 1.887120354843997, -0.05026461165000308, -0.1399839889203879, -0.185627397808518, -0.04596340870656163, 0.008956420059669758, -0.1381531838530755, -0.06179826475610644, 0.03260995306247771, -0.0962297246933979, 0.05268169622571128, 0.2046211566675452, 0.1296024872478153, -0.05109478171641717, -0.06816393508471544, 0.06908783957203835, 0.1203829447316026, 0.01720249086925636, -0.03678250120900584, -0.09954728921499965, 0.08400427932827997, 0.09706474262764897, 0.1099658716687498, -0.02055867348093135, 0.1883358420037133, 0.09179573472650564, 0.0428976892444284, 0.06904499115717885, -0.07352106561747025, -0.01527177851177849, 0.007127245592600535, -0.03478704421611469, 0.003011747710224133, -0.02349766354391826, 0.01004232793292505, -0.1176867876164139, 0.02626695914041232, -0.06316783433824909, 0.07753431035296164, -0.05772959109292543, 0.01954926232340906, -0.06086028308842151, -0.003104675370067428, -0.004923780276110752, 0.008718170992460231, 0.05506074746847181, 0.02126352510068548, 0.02026026825978836, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.051962095286209, 4.783354200058216, -2.891753406247233, 0.1494225282409022, 0.212321254452782, -0.2121415539790813, 0.02466897820188111, 0.06733336624204075, 0.013113247694252, 0.1066584296274234, 0.08752061927245192, 0.07922179944730777, 0.2365701476731576, 0.007588213043408364, -0.05416415411776607, -0.2020969955640969, 0.06349969928685602, -0.06132787289740503, -0.03422718627771316, -0.01952915873386353, 0.0644213739673787, 0.002115696634784188, 0.06255822113535302, -0.199371510170398, -0.3230384741719209, 0.3808208705549075, 0.04071272810763353, -0.01872027971165153, 0.175074940224908, -0.3802378821499527, -0.06108501582393667, 0.06646559313315525, -0.1623676411929772, 0.03990883781119187, 0.04487902512075174, -0.1419408834211026, -0.1568779206082137, 0.1763292664552807, -0.09481989476682466, 0.1344530334023877, -0.1823509060475661, 0.01993854821358784, 0.06058475613302417, -0.08882610769003915, -0.07025689205542202, 0.1720722409076721, 0.2549799182126544, 0.01962928250874243, -0.01708969300024939, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.90166412025067, 5.683663549106058, 1.9210862649828, 0.003584348132213356, -0.04815067261613367, 0.08879292199376522, -0.005675898744132862, 0.03588291164670374, -0.1637463265891401, -0.2197707557186419, -0.08857402261688128, -0.04780383765954515, 0.007843151524149466, 0.1770531910307867, -0.01723997302062695, -0.02612834699223629, -0.00540746785723896, -0.0705490796246758, -0.04457806266766569, 0.06473113864983282, 0.006275761834464256, -0.08950765677362392, -0.1005085571651238, -0.009712772636099888, 0.1241037651167948, -0.1243232786387127, -0.2285046949724745, -0.09330919844079147, 0.05061721851550809, 0.2874490693586184, -0.03620828558028133, 0.009836453811605826, 0.06478449995192533, -0.01171663894787422, 0.006410086373602496, -0.2000108983272982, 0.03916914746487668, 0.03329096249389659, 0.07559233782463498, -0.1503685986635421, -0.006365422116363463, 0.1204026175721976, 0.125722416995956, 0.03865674591865399, -0.0001228620998850972, -0.06816612415831065, -0.03365741691324027, -0.07613321112893839, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.851490093348759, 5.320051320277479, 2.417643700741916, -0.1995237653475895, 0.07621645201183533, -0.1771833255682829, -0.01078146896182771, -0.06438976299009525, -0.2876178310323119, -0.006303714018374637, 0.356885069902641, 0.07024283797935846, 0.01881395860270091, -0.2092513663311028, 0.109718092264327, 0.02854685307727969, -0.1312757974509329, -0.1108285734230257, 0.05182740468109521, 0.07233132504659899, 0.05030539452868459, -0.06059975102985716, -0.2297336103700467, 0.5045083042485633, -0.0004325173131309776, -0.1784693418735473, 0.08394922707081144, -0.2680843663012994, 0.2671400195308918, -0.001793550843300997, -0.1325105555633781, 0.07300804882966573, -0.06897110118534086, -0.2665451791081322, -0.2630899900703882, 0.04369816343226968, -0.156643286665005, 0.1549466071737415, -0.4145076724124122, 0.07488318920361078, 0.1419270611119949, 0.1219043619914908, -0.06378625947413261, 0.08917372812331978, 0.1038377550424948, -0.08072252702869862, 0.009394294196957323, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.53934911433842, 3.08124689760215, -1.480395561682393, 0.2462776680494332, 0.01710234467080554, -0.01750922521427385, -0.08464899612469672, -0.08513339146210799, 0.1497690941692451, 0.2003583687026345, 0.229975304279735, -0.06773544482684146, -0.212962762165994, 0.100805918257745, 0.1387021642494545, 0.05756587177820099, -0.02342135307890196, 0.0413142771758164, 0.01012070144816604, 0.009465626383560421, -0.1768890665508353, -0.3114326451294799, 0.334908331740353, 0.1454336469709651, -0.1253099733433882, 0.187117750616515, -0.2556659183272817, 0.05828504568732875, -0.09923486906264152, -0.01295943412712868, 0.04742766192450461, 0.002467967102260226, -0.09546651038888934, -0.3163510329005083, 0.1861927610821425, -0.06672987133018268, 0.1437750260846377, -0.3332140898455062, 0.07302040974957998, 0.1701107028641413, -0.01658898261297759, -0.05269690883993056, 0.1563566521838276, 0.1337720630335788, 0.01368561538114742, -0.1213888256015452, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.307203302598592, 2.885610538012057, 2.250703368751336, 0.07975315762421138, 0.09370441866373114, -0.1923654024839493, -0.1853398422580131, -0.201205128559576, -0.2125042330970577, -0.1602582952706193, 0.3093660817821342, 0.01852414315637842, -0.09255035727223564, -0.1924195495982953, -0.1559361270247578, -0.02917817624329287, 0.1447862761755991, -0.04690491601291951, -0.1960912348494043, -0.2042284966615884, 0.05841637536106218, 0.02291485689303238, -0.2827174856981686, -0.2943255892311636, -0.2215807563938077, 0.1152617438267267, 0.3936419107039491, 0.02096945169954771, -0.02252698024658075, 0.07773344380322408, -0.006443114230257507, -0.03639999246001423, -0.09084547229099375, -0.0397561686169364, 0.07701104659075265, 0.005605523155556855, -0.09348135695481166, -0.03124263128081152, 0.1542717927672431, 0.175465847613986, 0.0572413755901381, -0.03334819451365621, -0.1404348146594518, -0.06481871409417514, -0.04848557273226619, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.221221516792545, 4.982054100250426, 2.183210516233156, 0.0908360095708884, -0.3019054223643021, -0.5366128211639946, -0.3196918354703204, -0.1253970246067154, -0.02164532399684936, 0.2556280160777759, 0.08182827430850881, -0.03680716913431671, 0.03290225595516987, -0.1262131502004158, -0.09569394699109128, -0.005709824337923843, 0.0821878342740492, -0.1407748396690034, 0.09719614879475127, 0.2301897192422586, 0.04576646414789445, -0.2184893983754594, -0.2792745493536102, -0.363844809151781, 0.3257684950525028, 0.4790184968677053, -0.07652744991329491, 0.06377373985106835, 0.09437678117499698, -0.06131442314952967, 0.1635757313451941, -0.2796573282080887, -0.05643997532345108, 0.1152912068418917, 0.05000521333406865, -0.1112720969259657, 0.0037148809503484, 0.1093948420140112, 0.2980235424512261, 0.1525445958488788, -0.1264302662462978, -0.2913624335279468, -0.003113019822754165, -0.1134308899923566, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.400474057942684, 3.406090954274398, 1.166212384143174, -0.2629422439993046, -0.2702044042321645, -0.06636757078595552, -0.08446798536159737, 0.1313648786119294, 0.1193846426124598, -0.07246210384479049, 0.01554276290017705, 0.07103237282021825, 0.00101034194025556, -0.02392135193032525, 0.06952201574673418, -0.007400528848880757, -0.1551607153718201, -0.1651416045393484, -0.0721038672300459, 0.1237766596982622, -0.03361356917856322, -0.2622129829975602, -0.09615056687603316, 0.06891513871408637, 0.2914707059926323, -0.1250888357080352, 0.06761344442133146, 0.0799843533260796, -0.01371538646021322, 0.07103228925121174, -0.3405952917653196, 0.09927170088586629, 0.07489758155119226, 0.08314980277563824, -0.2366684526630883, 0.04202882159469431, 0.2074629307377897, 0.133356144785867, 0.0637264741453499, 0.0308975379082297, -0.1084379405587302, 0.02099441886765496, -0.1808400593316885, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.086464017862694, 5.114621438496568, 1.930881617131408, 0.1620245301097141, 0.1255287200617495, 0.3368622640783234, -0.07183251945541429, -0.3012926287551759, -0.1116975660537743, 0.113190686135744, -0.04910476738177835, -0.0465386985036234, -0.01788084091497165, 0.06748386592535341, -0.02381369375912231, 0.1493221788544871, 0.02579249903686181, -0.2497357621560777, 0.1787366301893779, 0.1598754145183457, 0.1674188524026742, 0.2477399099122946, -0.3340328954217437, -0.2111911479084411, 0.05086712720251271, -0.1292081829605008, -0.04302551258734066, -0.04971415251604733, -0.3610534332063385, 0.1892568833309398, -0.04472498978753213, -0.2065739236157566, -0.02046944574279112, -0.1756213338724003, 0.07793636245748489, 0.001237377976353086, -0.09033779335999018, -0.160410772384528, 0.08626890948440605, 0.2182749871373348, -0.0838793833068209, 0.1464287335113856, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.723745364788649, 3.894040171351998, -1.604023474297945, 0.3564682842321129, -0.068601028463067, 0.2723514789823699, 0.1226064004710703, -0.1014104100043627, -0.01893991862852569, 0.08732928681306741, 0.1555840779063216, 0.08897747453791588, -0.05848831483689518, -0.0484062742636184, -0.01943252555803195, -0.1897987807964078, -0.04208301117450661, -0.05303588371252462, 0.1133610703860842, -0.02273323404597872, 0.2540238415394855, -0.07855533407962875, -0.06507240945437587, -0.005499676266161271, 0.06537585217565781, -0.04778965574559299, 0.03306331390850831, -0.03674334203422738, 0.03096742123062764, 0.01763537013767625, -0.02727086473016628, -0.003088168719969086, 0.0435625544938414, -0.03476926734733601, -0.03196005989505435, -0.1419829052022682, -0.06959993690169985, 0.04835942714075128, 0.06791350727690673, -0.02769231996290041, 0.02869640238709043, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.887735910703242, 2.376861553923156, -2.059488107339375, -0.1636149309402013, 0.4041266030614025, 0.3896070591189961, -0.2297552131134549, -0.01184707906318158, 0.07039303277467518, 0.09925344398529366, 0.06695981045037805, -0.008491592697259171, -0.04552531630716806, -0.2274274932314481, -0.4148399842074417, -0.04458879883972757, 0.1297363092206598, 0.006733546690957063, -0.3384389296777096, 0.1168946778492827, -0.005399720520138511, 0.3552679244548678, -0.05369187330796665, 0.07272949240516048, 0.04205583963833656, -0.003676655566636833, -0.02270378608066365, -0.2966711461982461, 0.02934135424925877, 0.02865469879716708, 0.06673230222014637, -0.1838317311908014, -0.004436962897364399, 0.1509614176408774, 0.03376168246202512, 0.0005117826261220852, 0.04498835681575293, -0.07866868520578868, -0.0334252458798712, -0.08545921183065397, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.342190295905557, 4.675687708808497, -2.268183880250829, 0.2090893331762786, 0.4578770822708127, -0.01884304914244323, -0.07920602266213114, 0.05860045842795304, -0.009411964143128677, -0.009484130845488712, -0.03376087164847531, 0.01728654546382909, -0.2136063948857168, -0.1250583122943451, 0.2295451258972967, -0.06031125891810103, -0.1745972831925295, -0.3612966512867564, -0.1696417690184429, 0.2894160200659208, 0.5167644047563161, -0.08805909441951841, 0.1382094329850753, 0.05099565505493066, -0.04533499187369815, 0.05797820328595679, -0.1922533222149581, -0.1102035618550493, 0.09431486137300341, -0.001494148493882944, -0.09571326182532253, -0.0247601912770405, 0.1256667582306468, 0.2120425181347171, 0.07968400246820299, -0.09760118083265475, -0.2941239252154335, -0.07105438440442044, -0.06896304227007152, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.005975891768637, 3.352830695220589, -1.754960054860547, 0.1623709029576712, -0.01686728241632605, -0.03827200221784547, 0.1561794350456731, 0.1402911103849665, 0.03386692126036084, -0.2383508690881479, 0.08335746314476074, 0.1222986332072196, 0.1365597783993524, 0.1833332391744543, -0.1153402862359182, 0.06132285746330645, 0.103916564083423, 0.1352942358705118, 0.03751837000428822, -0.09780641373392215, 0.01802532012439729, 0.07461290579154131, -0.07340909507755823, 0.0263628669211833, 0.05634194666559207, 0.1326983203399266, -0.07526750794049826, -0.0255602869082238, -0.03079487759048528, 0.2087632832461296, -0.06368900481673745, -0.1885028988850317, -0.09938432303399658, -0.02813603601003281, -0.03116773548046878, -0.01139744596335172, -0.007527417596076127, 0.09996642926056981, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.005352340672642, 4.225811150115511, 2.31447703108509, 0.2404320758625818, -0.1026845105793418, 0.09323203523714457, -0.07188013661735847, -0.04900547068951503, -0.01143900704943617, 0.03127208944683336, -0.1422425637959582, 0.1223555755457385, 0.3629752163517811, -0.1439880981371962, -0.2053548592359871, -0.2670448469719894, -0.2854950646499647, 0.4890836381626159, 0.4252198149550604, -0.04903353665384676, 0.1440097216561384, 0.05263434485402999, -0.05654435812537717, 0.2744897997285071, -0.1869384630385859, -0.0801988284405884, 0.1415754714387316, 0.0461903176790022, 0.07292418854739299, -0.07749396692418822, -0.01197157575397448, 0.2335354584093252, 0.1565196693950396, -0.2175672539551863, -0.294898244011832, -0.04250817996099358, -0.06254226634319582, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.023207199521003, 3.695034404904957, -1.278828575213463, -0.09576460539931182, 0.01293341047109737, -0.1025508423146749, -0.09879959800395338, 0.1293868360344177, 0.02661187351571312, -0.03208813036911215, 0.102284173268301, 0.01897487699556174, -4.171607187027272e-05, -0.2343929177751728, -0.1591895912128799, -0.3479923586821921, 0.2266119442104414, 0.1369767045914879, -0.093264948471121, 0.05584513287015452, 0.1113848723095114, 0.07805629549261404, 0.385159500396428, -0.315090514425508, 0.2619076486635123, 0.2100336864909587, 0.1489157028437222, 0.01899500010404414, -0.05839538028607237, 0.1065294735286251, 0.1429581389759609, 0.1768187396519744, -0.0107077164022975, -0.07184487656799306, 0.1053566314912159, -0.2656344309369447, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.535179041441933, 2.927516278644585, 1.069440149410428, -0.1940154888240462, -0.06435827084629098, 0.03118119256124731, 0.2144814653940334, -0.1459984300204726, -0.01884883111449459, -0.0996859848375896, -0.1929505482810151, -0.142915066638186, 0.04595119246484281, 0.09181030791542119, 0.1046793740137302, -0.1631714112553374, -0.1533173188313381, -0.008178614876768846, -0.03838516939058051, -0.04628352128726964, -0.04001834958725597, -0.3727398948175817, 0.349654467351177, -0.113952499262497, -0.101339746891288, -0.1603850568927218, -0.1309942015965596, 0.07772040042527674, 0.1275463112280693, -0.04252979249843156, -0.1408252690486143, 0.05191953638235136, 0.07165159166941262, -0.1158826338243819, 0.09369294636414835, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.042176179125399, 2.455373013093171, -1.298065125007905, 0.02028671121404909, 0.003306962463612291, -0.1036220220710941, 0.0481345337164661, 0.03315299260062861, 0.04992516180471544, 0.09592872957586211, 0.03096020094331417, 0.009903127869262564, 0.01875056235671545, 0.03272160535846057, 0.01927852349784328, 0.02325854762506147, 0.04608264369572843, -0.009983430343303928, -0.01609838886434818, -0.01003965210423024, 0.02113424938210403, 0.005924265966984703, -0.05179857793569453, -0.0244630676591391, 0.01057802494355381, 0.0691716202360271, -0.02554792020429601, -0.09556309673821282, -0.01109440159507958, 0.002795432770742045, -0.03608009327148794, -0.009904492448746673, -0.004701473084555832, 0.06319402826809284, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.341422080029597, 2.641177760807674, 1.591936295305328, 0.005262995989819829, 0.05712969006064635, -0.05864522459107201, -0.06744950477663363, 0.1271503047471045, 0.2094260695099903, -0.3057531846245879, -0.04037395011724824, -0.02967432474543921, -0.09059292764118339, 0.2862509429106201, 0.1048474566793039, -0.04995247127231636, 0.1184570436074571, -0.03693842645635304, -0.08306079853122639, -0.04945597334476677, 0.2089393586111927, -0.2028924047636768, 0.01499186002602688, -0.1284371246539898, 0.04369426140288886, 0.001107629872198076, 0.002549707872053236, 0.1030701664382734, 0.002039801798898688, -0.1568979174791054, -0.1881891997896287, -0.1100556548512126, 0.06948313266853789, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.629047221760682, 3.633220763136687, 1.407673550411567, 0.0339033673171226, -0.0440877649168133, -0.1309350154964067, -0.05292438726218229, 0.1243733326688556, -0.09611554125353661, -0.01801557361391788, -0.1394535956650391, -0.04800585756898997, 0.2092817652566071, 0.1937706427881193, -0.0316202819028252, 0.08185853657036937, 0.008847184587817514, -0.05390183527194951, 0.0500718698457836, -0.06277970709250076, -0.07596180328240805, 0.04008159730086977, -0.0124923156950488, -0.01841127788787308, -0.008904456301771634, 0.02894837811492813, 0.08379155755674296, 0.038658741027786, -0.1013410184828959, -0.1363862936525638, -0.04609547972146647, -0.01057837708981668, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.387217368144026, 2.728722184696696, 1.424749145313089, -0.01601470906433309, -0.07512459959692018, -0.101188344036713, -0.003441549977747002, 0.06449001937611275, -0.03196276224536809, -0.1213336580505604, -0.009099515848609243, 0.02592480117875633, 0.1486227237292286, -0.00133150660633606, 0.001532054214242922, 0.02645122343613796, -0.01679939752946042, -0.006472860460697598, -0.1046070432475455, 0.002013525317899786, 0.007407876301716394, 0.03426066213629017, -0.07238247076893806, -0.002515176653231992, 0.04897218815805249, 0.04708726516482133, 0.01321800810118652, -0.0106268999083793, -0.03069342204089823, -0.02184119543907794, -0.02064865378574994, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.391700331330132, 3.10873390469995, -1.005261568422076, 0.07033689862768554, -0.01130536743091839, -0.2012624886845097, 0.1894945671077086, 0.07933080126112255, 0.075305885120587, 0.07607468793519609, -0.2915128232499786, -0.05359107726226209, -0.0167141837673077, -0.09941630815355153, -0.003665007998583435, -0.0299234883671778, -0.3018441136613871, 0.06749072049202193, -0.04549007934188216, -0.1272169539451481, -0.04604367173781738, -0.2292387384782596, 0.1104667012348132, 0.1037443269592589, 0.003358877836343526, -0.09748118788274351, 0.1190372958872585, 0.07594840982846023, -0.02118200682737069, 0.04505746778768557, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.040421536922372, 2.090179325079248, 1.054133848546223, 0.1016135668098681, 0.1058908215655909, -0.1395436464948118, -0.0005843093291569908, 0.06576578822426617, -0.01954438761767608, 0.1340460322034086, -0.1079153000090457, 0.008558237228615952, 0.05442003661392834, -0.01948493437734833, 0.03204864462372618, 0.1899187419163797, 0.02651889944688371, 0.04143699821901681, 0.06155302263071664, 0.01361677379827648, 0.1864345911285355, -0.06057118267116334, -0.1079059175548875, -0.04926446070686546, 0.04450551753882914, -0.05461151981988153, -0.001886612406799282, 0.0366915411934175, -0.01306027401322379, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.017217105119183, 2.057885109672617, 1.717830826909398, 0.08026860099733665, -0.229664599517274, 0.08592953162584042, 0.07113555573927616, 0.1205711964241209, 0.06034607492733832, -0.1241960272046997, -0.02576402132560143, 0.100546870611732, -0.06664178017945782, 0.01551828302018928, 0.01075203286396453, 0.1648555544266941, -0.06180621835112392, 0.00904698466380283, -0.08614048879659969, 0.1377785336580386, -0.02458732719586508, -0.06527069420169623, -0.09919539357362668, -0.0371614630248139, -0.01956332576116701, -0.02610087976547117, -0.01636500296481732, 0.04290323999519369, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.73126542682124, 3.177372305562633, 1.069892746405991, -0.3373448837554265, 0.04914183280708707, 0.2222099960511715, 0.1000273467845214, 0.02495153836835336, -0.2988822213671982, 0.09070115558214502, 0.006890792477648951, -0.09774415864582336, 0.01733122536241725, -0.06539161565511441, 0.4180846670181008, -0.1348357420052125, -0.01486736897403777, -0.1707564509631871, 0.275788236310813, -0.03928409265616119, -0.1437568066337482, -0.159713937527644, -0.06441082113320754, -0.04838713636560495, 0.03935472474969938, -0.03034455737023176, 0.1502866267461562, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.9860332560182929, 2.457690638088044, 0.7585454975233088, -0.1838919851966072, -0.04382890538941454, -0.140552844264958, 0.09130507944212898, 0.001128260213507534, 0.06804648176327489, -0.03968302808799389, 0.02820745088433483, 0.03697025018803624, 0.06358690037762478, 0.08600302483044212, 0.04484515559448902, 0.08149618479019373, -0.008400294556984093, 0.1073491700579635, -0.06306885174166355, 0.02287587454966997, 0.01464609607772943, 0.03996572206258068, -0.03555777800156044, 0.01763122405260091, -0.01550330692085902, -0.021886735564678, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.8854567164260388, 3.24250422074227, -0.9209580946507911, 0.06835402983935927, 0.05640958121017869, 0.1025591786485125, -0.08943334614410312, -0.06811365067010508, 0.1109007141056824, -0.02177056785348171, 0.03875431100769289, 0.2363367275176182, -0.09273940436583276, 0.1105048998268415, 0.01324218642906586, 0.1204923454912281, 0.1300264818238509, -0.07418265989085007, -0.160155156583538, -0.03336518282890372, 0.03274839794300601, -0.02988917934624772, 0.0313012656489897, 0.02783060486964485, -0.03014058011457086, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.9647900465381067, 1.776310496646176, -1.171438051631132, 0.05140489138825926, 0.1299377347834004, 0.2201816497369831, 0.02994176320228855, 0.04558225788991847, -0.02505795321566107, -0.07354754829932028, -0.07990068462027206, 0.03705853127225793, -0.1892721965231484, -0.0414104999094905, -0.04365760163266805, 0.004082206348271171, -0.01640857151771855, -0.04917783956511107, 0.05677253037720179, -0.01538028417587433, -0.1057997510635607, -0.1262079630007641, -0.09383731776836683, 0.1119867440818691, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.059667715135062, 2.869444516413392, -0.768053436705612, -0.01982926570738622, -0.05898277292649027, 0.08032989813585734, 0.02430925291918696, -0.05541157112738762, 0.01387900032498306, 0.005672434099991189, 0.05365330433412881, -0.04355934883978447, -0.02337398496984892, -0.01686799971841361, 0.1422537288231567, -0.05666452598379437, -0.1164424129736735, -0.154242271156826, -0.04516863877735287, -0.01545725267339097, 0.05268933296374621, -0.01791535900714333, 0.08893369086218253, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.006637453830663, 1.684689844069783, 0.9123803878361401, 0.3537494043954367, -0.0934425457654232, 0.125950163184819, 0.0008929568569579045, -0.05163443135049815, -0.1076491218622526, -0.0453578935139585, -0.1495191189316716, 0.0001415820705124262, -0.05006551799497391, -0.128789667082152, 0.01100316880829279, 0.1037355563583926, 0.1230844198081173, -0.01355995466456035, -0.04069963982836227, -0.2068443754239467, -0.100425014495166, 0.005750041723483063, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7847696566083294, 2.188950883712381, -0.6166420348084849, 0.05427293688357122, -0.09172120702478551, 0.01394828380275868, -0.04214925628047594, -0.2002409114863903, 0.2374547253440619, -0.07586414645695061, -0.02243126761233804, -0.09086994858618591, -0.06440645239833823, 0.02923240705539655, 0.1008328000734136, 0.0681346127852103, -0.03404818684407405, -0.03418035480719885, 0.02177303810889437, -0.08932854185081496, 0.05516897717457826, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.5961213393185251, 2.487671728233433, 0.9779431494823534, -0.08808252008539449, 0.07346845556012158, 0.03791477768403206, 0.1133987101884693, -0.04867168124335965, 0.1007529815412284, 0.07012067318801543, 0.04686393658752402, -0.007976030601315085, 0.009647274715336393, 0.04388047564013912, 0.1448956828911585, 0.09593976527370232, 0.01772056425810449, -0.01920422214800561, 0.07683802973941063, -0.09812807079543846, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.990432056210743, 2.774709587520062, -0.9402258848421475, 0.01395715665576621, 0.05464370856162152, 0.05969855937401768, -0.09840756262028037, 0.1283282686407038, 0.01393286908802421, 0.0953055258318351, 0.007548139187554635, -0.05906283649224034, -0.0006153285921519075, -0.05497497151651637, -0.008769303020395835, 0.05051213594154082, 0.09095589353294919, -0.006367749500199228, -0.04367472066475442, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.9556547348028801, 2.802801220763579, -1.059088183997589, -0.06046741386547052, -0.109550403372664, 0.1079992883617651, -0.1303209308383404, 0.005273660747274722, -0.103872667440789, -0.06600322769700166, 0.05217402045757749, 0.08518450366824531, 0.09805210958705181, 0.003600709399162004, -0.05665622206864503, -0.1159528275969711, -0.04404155725184447, 0.02203210385909037, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.063540216854957, 1.744535368562572, 0.7905163601870416, 0.02656379893207305, -0.007035839152219695, 0.04085917849823771, -0.009245974538993987, 0.0249953312582957, -0.003223257434620091, 0.005723442767043741, -0.01704173254774269, -0.006825269002180425, 0.001391384124621517, 0.005712500889522121, 0.03850120618331365, 0.01404973463460888, -0.01209325063900243, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.788177934248775, 1.912200014248186, -0.7537507368298558, -0.0661262783848291, 0.05943707989564052, 0.02061524812146071, 0.02585592085441167, -0.02083197113611205, 0.003987942029650998, 0.02210665757083753, -0.02360486919891839, 0.005051227537696999, -0.0006754747654496297, 0.01013804196323632, 0.01058372156918393, -0.05401144478196152, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.8186713915600072, 1.708711700739236, 0.6332443934946002, 0.0347014944537665, -0.01300019502207845, 0.01605786260146845, -0.02637192977655575, -0.02304218343188766, 0.02296628976143508, -0.01424547177831386, -0.03972717940911979, -0.1167021874016301, 0.06633764648895558, -0.1293541599290803, 0.004742672723613311, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5157633499563469, 1.976352201317751, 0.6234503597941091, 0.01391296633390046, -0.07272602653366068, 0.0140570704220571, 0.01336752650183375, 0.05902767787103762, -0.08819062077742636, -0.02551451255772886, 0.1312142929003566, 0.01369744243814129, 0.06473360298498254, 0.01231850487143263, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6533080656351744, 1.758802439425837, 0.4318871049206415, -0.003082957500133511, -0.09814169758462682, 0.04175539354758488, 0.0235289164184994, -0.01629543995009982, -0.05231016932343414, -0.03672204848733453, 0.009389336932342413, -0.06142381433250257, -0.01010858967311151, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.4817927293509213, 1.408851322535897, -0.7676055176021872, -0.04505523423060897, 0.01813562786331449, 0.03138728238085502, 0.0007373169379419269, 0.001847667170281647, -0.01640431370966648, 0.04696818974656805, -0.004393748298759055, -0.02848496648956977, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7883892138973269, 1.746055173045302, 0.4846783430365095, -0.0003922243062844435, 0.01186867835550373, 0.01648380387048428, -0.03174672656471393, -0.03627511739090696, -0.004853687188112606, -0.06885884936290802, -0.004917829299265958, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5208363315616994, 2.037277859382022, 0.5232085356010402, 0.07175407188317283, -0.07019064479939288, -0.02385694223436976, -0.00819063541887864, 0.07192359009199149, -0.06656167507443485, -0.04927759893361527, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5819314677010843, 2.130167978098713, 0.5667361680393177, -0.01053764587057425, 0.01592751856907668, -0.01111604356574088, -0.004404610058468247, 0.03850545663289814, 0.04729794670040405, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6488904808178829, 1.974426530381294, -0.2820471741701222, 0.02456494941736511, 0.03486280653024869, -0.01809831529884736, 0.08408521068644187, -0.006474401058818371, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.3312307167387429, 1.235934836863219, -0.2452582871525679, 0.01878427096720662, 0.04975840840483642, 0.05672553943361373, 0.01742942062643791, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.2654365696129733, 2.208256891929066, 0.3360201888498769, 0.06660725081463706, -0.01286437627536736, -0.002070231898763094, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.3639062481633207, 2.248588741393716, -0.1889980205327704, 0.05688507493685012, -0.04579504315826421, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.1624755988486198, 1.590085647221482, 0.1168533202179821, 0.005293082667091636, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.173908380119132, 1.450043378319349, 0.02765965035599782, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.02984095753646376, 1.759629990218614, + }, + evWant: []complex128{ + -0.01716884621227793, + -0.1844331609734137, + 0.05200651487352193, + 0.1336851109127556, + 0.2020936631953806, + 0.3566470363060668, + 0.3627207699831158, + 0.4388555152488943, + 0.4776853636435153, + 0.5598821450074998, + 0.6249350549980947, + 0.6791310689291772, + 0.985877008147705 + 0.01929363300192029i, + 0.985877008147705 - 0.01929363300192029i, + 0.9908483217835712, + 1.011990761364073, + 1.130046345264462, + 1.323698071765709, + 1.348598229483672, + 1.363190626641638 + 0.05400660173350781i, + 1.363190626641638 - 0.05400660173350781i, + 1.632832316477256, + 1.646239548684271, + 1.742738908029794, + 1.763069014878969, + 1.789601126186348, + 1.945228042429256, + 1.946373262056993, + 1.997152389795002, + 2.261322781594966, + 2.286944100979884, + 2.447712649969029, + 2.557857506923634, + 2.608379034892128, + 2.653335615965549, + 2.675270309760236, + 2.964219802766918 + 0.01767482509567778i, + 2.964219802766918 - 0.01767482509567778i, + 3.014604817775139, + 3.158289371199042, + 3.311794215710077, + 3.389894197376214, + 3.553333074879877, + 3.641274442796651, + 3.857556223000175, + 4.045817381029103, + 4.330901939363569, + 4.337313647767939, + 4.527400487637496, + 4.917229128467305, + 4.985609414964091, + 5.687686849958608, + 5.79422309012183, + 5.997813119506478, + 6.732426637899077, + 6.957609338485607, + 7.529842664573327, + 7.609108287806763, + 7.761261355516287, + 8.311941758006698, + 9.07053741884884, + 9.217944588000314, + }, + }, + { + // TOLS90 matrix from MatrixMarket, balanced and factorized into + // upper Hessenberg form in Octave. + // Eigenvalues computed by eig function in Octave. + // Dhseqr considers this matrix big (n > 75). + n: 90, + ilo: 0, + ihi: 89, + tol: 1e-12, + h: []float64{ + 0, 15.87097792952162, -0.08018778146407576, 1.923854288576926, 0.2308884192434597, 0.3394611053158814, -0.137843056509317, 0.08273319299962868, 0.09094485832017182, -0.1932984706702652, 0.1180502933247899, -0.2497600660136686, 0.05058238526630414, 0.1559958264692184, -0.1159258671363344, 0.009240657808439554, -0.07576925270220009, -0.08136563335139357, 0.03812188405626555, 0.08890970810264923, 0.03109600803532232, -0.01649595143487545, -0.03210884292964193, -0.06264912164116895, 0.02576130685189339, 0.07030469513274047, -0.03577429596420342, -0.06755584096587573, -0.01609449751643862, -0.034609250889499, -0.006417485131372289, -0.03097242984568944, 0.009636702832094541, 0.03557221482377193, 0.03197869740177413, 0.006433398911967483, -0.01135683279223704, 0.005555822920782794, 0.005082647305173025, 0.009385366191684759, 0.008128896608623586, -0.02296712755081439, -0.003777413820214802, 0.005123235117691023, -0.001849213959133196, -0.02340110883416673, 0.03713005378535863, 0.001732375396842803, -0.002750608017025007, -0.008067437745595896, 0.007330916864526544, -0.002616316716217023, -0.006297132815168344, -0.005559964495164493, -0.009996463242082429, 0.005115046921377182, 0.001491016327339477, -0.000957347151456719, 0.006745577006930539, -0.004544035710017501, -0.004411949528299773, -0.006799740101884459, 0.0005344071027975155, 0.0004690847920096184, -0.004718575501368472, -0.002540214169642457, 0.00357159293854215, -0.003314789809413553, -0.003402372051470523, 0.0006527769815598059, -0.002716170091878954, -0.001540321517093821, 0.001756589868588563, -0.001379260966541515, 2.681259838616508e-05, -0.004307760317855304, -0.001109087032949234, -0.0001659937040461595, -0.0002235436314482387, -0.00119569899683125, 0.0005623327348935116, -0.0006320070189143994, 0.001043573892153891, -0.0008750118344396425, 0.0005348270042878935, 0.0008273143853381587, -0.0006622544067919339, -0.0008492128694001077, -0.0007986665099336194, -0.0009015882205421384, + -12.61872336344661, -0.7232497785660141, 7.609159226285555, 0.3870426982100038, 5.924856640096555, 0.6102682886559223, -0.1693535996869482, -1.919018099340693, -0.2138609560373459, 0.8042623392399718, 0.8674124147325857, 1.331963567449537, -1.782290696158441, -0.8346237530841022, -1.552156412468403, -0.6151273144224881, -0.7391936693539152, 0.9311934770410842, 0.6166024938842418, -1.54644771695033, -1.776481997993627, -0.934164018650274, 1.955449870926906, -2.082936149197492, -0.222464503236819, 0.1331142802435182, -0.7633944660137448, -0.8176194198678164, 0.2746498608375185, -0.1119720547510174, -0.3046093297897633, 0.093708523663493, -0.1254384253653835, -0.3826156782538976, 0.9720657328245648, 0.4435611080311743, -0.002705519800257373, 0.4068502033494004, 0.8228026417475635, 1.898141183528268, -2.19419418629088, -2.26250233043472, 1.169369389476936, -2.320900757809857, 1.963641620262248, -0.9292511308866737, 1.20566753941007, -3.909359844030778, -1.745106869690986, -0.1674293744185332, 1.824325508201922, -0.611032518780414, -0.8172751651339325, -0.379367811436249, -1.118039132172379, -2.1156899896767, 0.6317312221182597, 1.675601832555065, -0.1958681401344015, 3.202902011360347, 0.2083144054490269, 1.651454396883902, -1.879950006164014, 1.114962429097019, -3.728120039552464, 2.115800549383747, 1.993994934513307, 1.036800346894651, 2.843012388647532, 2.665528597975866, -0.08443708961414848, -1.658265513220315, 2.825691629937317, 1.163068598831327, 1.032612155987785, -0.3464359914213002, -0.7374155713124153, -0.009825846309687306, -1.878310233217088, 1.038183449333641, 0.8683442149070821, 0.2096953654957043, 1.097533010763627, -1.40566207568186, 1.539718090250373, -0.3057191046244732, 0.9596910019319377, 0.4410690813618931, -0.01734977865916698, -0.7028527205475527, + 0, -21.14096588949502, -11.77071611766029, 91.38817973790069, 24.01994594814793, 7.139034668143506, -7.77684013545977, 11.8189112903465, 4.350214240774185, -13.41161300072837, 0.8429515510200203, -0.1960485971162483, -1.892239827255886, -2.481138864200454, -4.993335484535367, -1.462743953230215, -1.649744938703439, -3.306123402194819, 0.6299802354863298, 0.006312776908129815, 0.7029217322720615, 0.1969979096896496, 0.6484394805159026, 0.4612739081461551, 1.218623710778157, 1.937283920899595, -4.274393204137636, -1.417028232311232, 1.761975679896983, -1.207846701077455, -2.947009378633724, -1.111456928119195, 2.001483835367479, -0.3273985739357373, 1.27142153234808, 2.470518283440578, -0.497592748085565, -1.01776837453108, 0.1736631347448449, 0.2170284795451557, -1.102797734602059, -0.8983239378242805, 0.8376082516437703, -1.015605628895311, 1.888662040615523, -1.813946159105028, 3.745871277192266, -1.691058864813766, 0.5544744103796291, -0.95962769863539, 1.495178118153111, 0.1369976805376806, -3.134133785033962, -1.134766199832475, -2.142472928604951, 0.4360359463007911, 1.080773790484485, 0.9136687613609559, 1.421868877932455, -0.4939788885367615, 0.01579620756278606, -0.4041188740514539, -0.3370957888349073, 0.4032844546374829, -1.281049156842126, 1.334866305935072, -0.4288161314791398, -0.4076960827986253, 0.8975402184760907, 0.008483305617251051, -0.02300021991545602, -0.4779200297205075, 0.8640559542693361, 0.6740166979504152, 1.271173988705413, -0.125268363712917, -0.02783785192682384, -0.7952831181002197, -0.1834134462936435, -0.3033906534395994, -0.1842466257842833, 0.3294577790658342, 0.4265858101126394, -1.050551059782219, 0.5557053448408287, -0.07549099980078718, 0.4485085972651929, 0.604772326452039, 0.02668915155289681, -0.35958437456048, + 0, 0, -71.67241414253803, -12.6925239065222, -58.51026881403752, -9.923972440030834, -18.08337737101079, 23.73437311293314, 10.42624729020936, -7.39628437264571, 6.93334510855383, -16.20186028661058, 19.09098951338167, 7.231158491837533, 25.86051183536314, 4.692849852643402, 13.50562601772541, -23.8959783279092, 10.46795736800158, 26.42552249365325, 25.55147405605497, 30.98455252329583, -38.26426057779729, 41.72459242758727, 14.01187370572939, -9.227025126956866, 17.69341876066779, 17.7058942448478, -13.2182156659012, 3.273277215940703, 7.82096407961303, -6.540134857551783, 5.302726399754003, 21.6168229759513, -35.45773268931614, -39.5771763658349, 16.91907564224343, 16.55810765769962, 10.84170890675409, 4.539182245882841, 5.966139065523301, 10.43624249585104, -6.306944364017387, 25.11309378553394, -23.98463112536712, -3.253554932408899, -26.20327820737005, 34.95346757431584, -22.06848426488626, 0.3787905650745691, 12.79793983153946, -15.15662916810503, 30.10820985389998, 17.18239253486946, 26.44238280127885, -17.53916820777098, -21.59984930800645, -20.89069843604591, -10.62614963929214, -4.16861219455282, -15.8281632392319, -15.45413424684084, 7.28126264287692, -17.30978445489622, 25.83878482866339, -18.20409699627451, 1.341279973912325, 6.060701390094514, -0.9930555858249585, -0.4770067839263625, -8.050723322366107, 15.00633993006825, -10.12301020599794, -15.02267685265745, -28.87546819977945, -4.887384695963816, 3.812851132430744, 19.10682316350844, 7.478580657962908, -7.486104775378393, 8.24517564743228, -7.51905558097683, -6.644004835040043, 16.04319982377311, -12.24015636297471, -0.4152718733052826, -15.37260980717165, -14.36579932723399, -1.30513875795791, 5.356894027365968, + 0, 0, 0, 88.73441744471468, -9.667604704172753, -22.84943872004879, 5.044285909895449, -2.76004875036668, 0.3050715430090338, 2.281066203460998, -3.081685045157843, 5.563173468318147, 1.196920824152984, 0.7508125732458136, 3.261490552895722, -0.1915889730517104, 2.178042983750966, -5.719722606964433, -0.808717831824074, 3.567750315780947, 4.405620166473985, 8.068713509838501, -3.974147763943233, 4.024558504483837, 1.343369353638846, -1.554164148226279, 1.397410693322202, 1.549071510171349, -0.6861822032616559, -0.03144220974090741, -1.503375319686877, -1.213563509509453, 1.485658175240746, 1.102628808733887, -2.836353822887371, -2.651198571403894, 1.944770277514162, 1.800720538730825, 2.925044559436877, 2.489394773406274, -3.99962439548742, -1.365153890760246, 1.729186611640552, 0.90732580595284, 0.02970965138899272, -9.802670261550649, -3.377885239589956, 3.311681996737421, -2.102890043550365, -2.752571666784161, 7.725320034635699, -0.8099349955071451, 0.5680350525364315, 2.461090824551101, 1.671002962178604, -4.651796111745832, -3.019627268376409, -1.456848301794733, 0.6765376227892419, -2.208873565004413, -2.755468168868538, -2.723938546851782, 1.844529360647301, -1.962817053181678, 2.77164872022158, -0.6312645341808628, 0.9959732581947718, -0.01141276076056162, -1.047045912982139, 0.9659655272370172, -1.069371622104567, -0.564318267120407, -0.9606489624515147, -0.3731646049074267, -0.4361324066751411, -1.228953081985217, 2.112718903093324, 3.774673462225595, 2.038526286226191, -2.037134562294253, -0.6272498215703869, -0.9130826952549337, -0.5356753186936942, 1.739354952287502, -2.607676632661601, 1.167128690015535, -3.643945638175477, -2.247788469333459, 0.4447578257714688, 0.8814188227164721, + 0, 0, 0, 0, 35.22951028609684, -22.61691132174376, 97.10536643650998, -3.714742139430975, 10.06500336745724, -16.35785983037913, 8.78437693523264, 1.985132974393485, -1.609800726068471, 10.55631691645605, 9.224290477011534, 4.722637143581605, 4.125150731568718, -5.396683914299057, 6.364591301561367, 8.24526687743292, 4.911724566872895, 6.542687463438916, -9.348997687795265, 14.18011100433374, 5.720905431367072, -1.582673805208176, 3.789638114574857, 6.440267872588953, -4.901278147004489, 0.421175984045115, 3.797008789173352, 0.2579925025997163, -1.093437933585557, -1.126991905684307, -4.4057666178694, -6.4297958780832, 4.918610437583255, 4.893900733343752, 7.627382484342153, 6.943539836193181, -10.22700285291435, -5.21717606135954, 5.635670539663245, -0.61979670671329, 1.025327494294112, -29.98298952616265, -10.87852244502099, 6.724183768213139, -5.415447368170939, -9.131548344141406, 25.08685243604318, -0.5163094225162969, 5.436141320006754, 5.254969244047728, 5.189340308692745, -14.05566775803058, -3.790558233978546, -2.867451571946585, -2.265074057881479, -13.27098968249704, -6.419573660857155, -2.44809433119093, 5.262803237338727, -6.396156300345669, 12.9332727436708, -2.828158861124294, 6.494893307712784, -4.900718840392307, -12.17623988734707, 2.132680032576169, -4.239391092443586, -4.723934051879516, -6.984654958110764, -2.787156581230434, 4.744573069448925, -7.311973630803457, 14.86842763617212, 11.70461213488476, 10.92665646005423, -8.812367256417245, -1.725823238463376, -0.599065820210566, -2.268141253505947, 2.588966312561057, -7.560432899806777, 4.711500915754516, -11.63409451724343, -3.784667325499409, 0.9845255581998278, 2.917504056968942, + 0, 0, 0, 0, 0, -116.0630192746665, 5.887300060633501, -55.36418027265255, -2.470006763999332, 13.03531089357281, 0.1172864444746298, 2.336301687054243, 4.34928920056458, 9.106206444726951, -0.8318917014102636, 2.753642271658936, -4.563539972366368, 5.616802475300401, -0.4836767449615566, -6.113950704235537, -7.384788928153566, -6.850835642415652, 4.436028327150289, -4.972441466665182, -5.074617872073305, 2.249115729647296, -1.27635805087233, -1.815933433231301, 2.59978300016936, -0.5676863289525813, 1.704036354039219, 1.966949252223741, -2.742379099660473, -5.759265103182953, 6.226978264278319, 6.392620681348136, -0.2885756166938758, -0.2986490248004344, 5.021918870709579, 7.495865991102269, -15.19741578062141, -10.52747112766237, 9.21669911214595, -12.00882240945578, 9.449065100345695, -22.03792558203701, -5.042603937347324, -5.034444931509023, 3.887859743790752, -4.92423649287837, 15.14459404442214, 4.709447859501895, -10.68403398232012, 2.785222602001631, -3.955139727592788, -10.90921547327889, -3.836568621330626, 5.465232651370832, 4.568243480001632, -2.511523602459496, -0.9621054122709324, -0.6044291916789493, 6.467023010391031, 2.662510020284552, -3.203951737691022, 7.315143747841559, 0.2986491524564562, 0.04345879316587933, -0.3120127984400304, 4.715818739144954, -0.3713148742857386, -7.592585985711748, 1.251675665881772, 5.563320889185214, 8.934186230540199, -1.034540314919822, 1.499762588438347, 3.648805772901489, 1.867765342642769, -3.856064394520797, -4.257325323439929, 0.9065282321682452, 0.9958862297862445, -2.214139637816267, -1.516486450508368, 2.326410461051852, -3.227358821350026, -0.4749483061012461, 2.179821376672413, 0.1114550663371978, + 0, 0, 0, 0, 0, 0, 53.90645393584658, -20.01147603384238, 68.25945706992877, -2.001388852130252, -0.6303875033830074, 7.681723436887633, -2.793396522752484, -3.849646005163192, 7.47502807954784, -2.524396627852584, -1.112160063163965, -0.4457759133018216, -5.425351770541893, -7.213840725579055, -0.6234582007920942, -0.3045445372121888, -1.838748235944519, -3.05429610717454, -5.218058811930899, -0.3089178689448414, -0.07503528649101057, 0.1630591210001797, 2.58742687436071, 0.8589336965724809, 0.3026886986297957, 0.0616540381895139, -1.743768523575526, 2.75507802571559, -2.587808530052548, -1.25512695563184, 3.800814529165174, 3.132593897658502, 9.751967320860086, 12.09676139406092, -18.96514427687867, -10.33529268364038, 9.423861340153673, -8.118494925333524, 6.455831882458702, -13.89851030432216, -5.253096745704963, 1.482474561585576, -0.7990859267629726, -0.1919859569182034, 14.99486076662231, 0.8403897566592956, -9.631758825484061, 7.546859017133015, 1.761650219269993, -14.8002789790671, -12.03184495751378, 1.278761976352118, -1.043958743156598, -6.425946785515577, -5.130193263963021, -8.943747092721882, 6.884559516868113, 0.02054820847870697, 1.622114564484586, 8.27790706580309, -0.4201537658318323, 6.949197674374433, 6.109317458173291, 7.745771202714325, -4.383777284917787, -5.023236465266974, 3.152075902042714, 1.185720299074054, -2.570558625807648, -2.575936989524232, 0.7822876332433506, 11.50350236141349, 2.541100031822599, -6.266519860892538, 5.220802309799155, -2.7113287362323, -0.0782755292810481, -1.306667606835813, 0.9121698644456847, 0.07469182002148761, -4.645428950155893, -1.074584465997386, 0.6604539390114011, -0.1666067442015038, + 0, 0, 0, 0, 0, 0, 0, -85.98674061062438, 1.162623410299333, -104.1491535027204, 7.969764337327856, -6.932488858320204, -6.767747448265724, -7.331077471298601, -1.288550484452708, -5.088257375240862, 2.763979746955463, 2.528081478578727, -2.575430737963284, -6.921068854524492, -4.018385524701809, -1.579042698955484, -0.7534247768022768, -5.324588385519177, -4.241013196984152, -2.113061191594958, 1.678130424336868, -0.2888364599120758, -2.575220703265352, 3.435198525295604, 4.161688539607654, 4.731385858073858, -4.276207990137705, -6.32017796521583, 6.190217309330307, 4.183836067935781, 1.849953972589691, 2.606132984461453, 10.00029158683688, 12.0615055907306, -22.12319815923896, -13.94593423436807, 13.56355336723619, -14.73390655737362, 8.504539865599947, -39.98652916386596, -13.54021158220439, -0.05790828602008728, 3.121363813023208, -10.26329339936837, 29.60358127644879, 5.640693459787456, -6.225202166414575, 8.49263970223689, 1.111516509579903, -18.45973622662288, -10.78955835552373, 3.866537233352727, 8.114971974287389, -7.188761733179074, -3.287441529549332, 5.156604610165261, 10.80793451072269, -1.239076505166311, 4.628996155335966, 5.792922582124358, 2.03417264625456, -4.707373530409962, -9.448778191150614, 6.51155292021117, -3.19382039380789, -7.177226661410774, -6.832018005921634, 3.442244659675745, 10.77505720982952, -1.609927625466521, 4.733127783256045, 7.444153456927645, 6.065657625755138, -7.768628874694797, -8.73223505289636, 1.578394964028069, -0.8054671616028769, 0.5972200288905033, -8.68273678581243, 5.453422469912097, -8.723308411603904, -3.656294698422601, 3.713788968458369, 2.245164999387903, + 0, 0, 0, 0, 0, 0, 0, 0, 82.30322830941419, -13.16495817094656, -40.37221874531644, -7.156146024985344, 6.407626256610186, -3.070719411573423, -1.248781274591569, -0.09188094231426196, -0.14791454863577, 10.46460085885971, 2.511645220965021, -7.306021862635426, -8.821036218813667, -11.27778024004047, 8.299073644975818, -2.786388825153335, -1.404614079695401, 1.895971545970186, -2.374603998420206, -1.895908635885413, 0.4177297064772442, 0.3179694660965782, 2.847483353627781, 2.28314647154709, -4.251315293192437, -7.351627496507233, 8.45101495879304, 6.656324309408108, 0.05811442721379975, 0.352210596662256, 7.158242198776926, 9.604014490962273, -19.05916411574244, -13.48053537548751, 11.11056501341958, -13.44816425524262, 13.03794734916214, -23.56660744892662, -3.179691183297922, -4.31381647439135, 9.383878541906311, -8.241547161602726, 15.17745487655014, 10.50533207581469, -12.3496460656361, 8.196225745083185, -0.03575510420729201, -7.579890340619093, -0.7363093925300244, 8.756813214260761, 11.93727799717407, 0.3635376217139206, 0.4603703423631014, 5.507079480435261, 9.421116342576116, 5.29496740123859, -3.941393949093798, 8.749586295075376, -3.842933870553052, -3.434396636354037, 0.7496949834113942, 5.050293641980197, -2.449146742066287, -0.1213669699610963, -2.640456287197764, 5.565782021620873, 8.693308402974377, 2.307206522787629, -4.138693274221668, -6.245432457269187, 0.202505673386626, -6.566863879917412, -11.74280124769381, 5.642870396242308, -0.659648816152216, -1.690565064770402, -5.93672734719091, 4.422450101243651, -0.7271854445212377, 0.7895970235545322, 3.96205972546395, 0.3762898199575608, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 52.18436402228633, -1.17071077050581, -78.74014811145696, -2.436421299700726, -6.158177326953696, -12.84920002328411, -13.40821294858424, -5.273362519386561, -6.872625202393317, -7.634332724591617, 1.036587235099262, 6.207608782298316, 3.391369867457635, -7.524695482267034, -4.223994548482144, 1.005090702038289, -2.66480555032824, 4.646608362152693, 2.243089562166944, -3.34529856305617, 5.740218757228164, 2.12882450346135, 2.939738798956252, -0.03146392010752049, 3.38958622345852, -0.2577487623574973, -3.051389295629871, -0.697296699287094, 0.6189380855708414, -2.814647546822989, -5.010744640386618, 10.8659101121065, 7.550151766381041, -5.138398331003744, 5.941882913285983, -6.24020929364107, 6.192495406215602, -0.1393925926206985, 3.522667688918142, -0.4029078058202559, -1.086721958116794, -9.106949733745292, 1.080723194973581, 12.43512076939469, -1.559991201757955, 2.834826471699229, 10.91592518979253, 10.14280540179991, -0.4312954736361566, 0.1698301469389144, 5.224021770744672, 1.399356722825569, 3.824858056231203, 1.187505521773207, -1.25027597821317, 3.154667536052018, -8.777523547457038, 1.485334722226234, -4.846848932499968, -5.331464798306308, -2.935610863284922, 2.146754442305868, 3.916678542801113, -5.097848412152915, -1.684939990487824, 2.003333243800943, -2.22594720641393, 4.656849950049951, -5.745353345757918, 0.6044487182322886, 1.596087705639433, -5.155786671036686, 3.16998966590795, -2.175693288642318, 2.801445787424951, -3.130319162400883, 2.85020826323644, 0.1640583474231081, -0.214298568273029, -0.1740891639628268, 1.273833756482144, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70.09446168050651, -11.26895002135244, -48.54705040053749, 4.118431277865748, 10.84591029041512, -0.6748674802174282, -3.045053711060402, 2.014682374966249, 2.306026198573233, -1.350656230483865, -2.329953831978132, -9.588390292055525, 3.269359204435148, 9.980505686658566, 1.082807022265471, 6.273567735324175, -5.719240792932494, -2.503890374538294, 5.253867760378612, -7.368019321193995, -5.092315009287605, -5.608336565960785, 7.85433697392239, 13.05231727795986, -10.24473853042492, -6.497760170002005, 0.7720864098024787, -0.9464942766836045, -5.75736090996403, -6.449685187648799, 14.67091581503414, 7.752227657052853, -8.313707502058552, 7.618733560061307, -10.26315766622777, 49.66932226344804, 9.396595252505557, 4.646105097651882, -1.000511699400161, 17.50139800181348, -24.58127340300144, -11.80138366202307, -5.227433380710831, -10.13287460063552, -3.337359409768342, 12.99698337996271, 3.068027046277927, -1.951738372661316, -7.666145241687218, 6.9088789851311, 0.2649618535564444, -15.99488743024383, -0.7701348417963114, 1.505671187381852, -5.323669521268157, 0.5338896728895715, -6.748253910318381, 14.64352852958436, 23.40931931143844, 4.375219426823375, -1.811045463489342, 4.773508381777763, 10.818209698722, -5.294039411650939, -18.70264738152938, -4.975296365083204, -2.600819681501243, 3.308632477674194, -6.40160106179316, 2.538884420020582, 18.76233248591015, -4.114557081532237, 0.5111695455673799, -4.794755383844113, 16.67507540569322, -6.886183084140394, 7.719834159396155, 4.933410312388084, -6.089459478292116, -3.503666218213469, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66.6637247212457, -0.5663386193537134, 86.66019711942882, -15.20175735117943, 4.314620867702222, -19.41396340483079, -15.38151259581058, -4.248235572512307, -2.600133694847515, 4.086685275316547, 6.543863987851957, -3.556770106796698, -8.862927415679744, 0.5940920961482564, 0.2891990484420937, 1.2985992187588, 0.6463973107839561, -0.1897507095552844, 4.999681085896536, -0.6439357872831064, 2.066718921953054, -0.1085645365015185, 0.1070768393458224, 3.026109517007545, 1.481907260983705, 0.1499047456480452, 0.9514718442208902, 3.068093096347056, 2.714461903454389, -3.99786212133959, -1.490015954498088, 3.704196600400429, -3.084024872438948, 1.383157275632034, -16.26579452857151, -7.173167896042849, 2.321998416940817, 2.275237906163105, -6.307537188875993, 6.209730858735038, 4.018421456135293, 0.9621119492629135, 1.945276954758256, 0.4126375340548999, -3.009694590378986, -2.629957817671035, 1.384131483830782, 5.687116562672569, 1.212032906758187, 0.4457093459378468, 5.044411045879187, 2.653766535846431, 0.2411195122877111, -1.543285991977046, 0.8571968890482712, -2.832787648800616, -6.089862603942122, -4.243058413925725, -0.2712347348375778, -0.7571525905438323, -0.1391757644986091, -3.374311051582727, 0.7719310852064701, 3.726864797116653, -0.7589171772472043, 1.688124623456514, -0.06145796388713081, 2.035112211335303, -1.275417314028715, -6.847693700987137, -1.324382865895411, 1.215308587453588, 3.389389718245654, -4.298340356096036, 3.252289347232091, -3.54897896652072, -2.583331482537173, 1.391546454632447, 1.526078993538325, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -76.15771433854052, -11.99852507214444, 27.62893281995865, -8.886170208363085, -9.022500867915554, -6.483908690769347, -6.478797015907496, 5.436632960504888, 10.11648415512398, 11.05236551506778, -6.555078182021158, 0.9926522830872675, 7.012674375514302, -3.958653565895998, 11.89784449953233, 4.997490823792532, -11.71308595491765, 7.473858613545575, 4.526049765812032, 2.627760851429408, -3.543040309678986, -0.6545512958150839, -1.975237359166213, -9.752416598897163, 0.1746629230980583, 3.764199942242819, -3.523765142660245, -6.526579460908251, 12.86892013415631, 9.636987335709112, -7.71437307352219, 9.374585571980461, -10.09888573625552, 2.627000532523575, -14.35239184493451, 17.7934680232572, 12.24617038938174, -6.2027891597684, -2.117824121844527, 2.304085371600412, 14.52899092304767, -1.375604453625678, 9.300885546968621, 18.94646416924206, 20.59266172433305, 2.716897787405002, 14.41056423737162, 4.669781485892746, 2.929418504934519, 8.242335741048715, 5.40876543323668, 2.002902940983452, 5.6098816375921, -14.20093255834947, 3.901682718637671, -7.337643713401271, -8.218284944457553, 3.072811403558771, -2.292798328406445, 10.69584853135417, -9.650335290149327, -4.330515729410567, 0.5204595970152146, -1.624267060418924, 8.140164084847148, -15.7637122001724, 2.453007028561554, -4.499820926337408, -18.34001755668463, 9.796120126023718, -6.012926560200856, 4.434295362280665, -9.67082400790736, 10.4548835691208, -1.769628011664158, 0.4768710210096864, 0.3854758620192356, 3.320903327037195, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -43.98223406015142, -5.032665049120959, 63.89171973078309, -17.03607126733364, -11.37762317554949, -1.901161248292645, -0.8260131144255914, 12.01428472457645, 5.352225349608783, -0.3266225326728286, -15.64216660863595, 0.3825939195623905, -1.494103371722206, -5.375511858816146, -1.862194375089014, 5.63824583310378, 5.360101148587418, -5.696506781095095, -2.080871954585809, -0.7829130324044875, 6.783149785809925, -0.3661710817347401, 2.462769544154133, -0.8126745345164752, -2.507928414100153, -0.7896746658950899, -0.4314818025686951, 3.924872737975131, 3.720963560907183, -0.9854313103876566, 0.5600582865792041, -1.688187106864158, 17.44248034254651, 7.56859337644358, -2.163244623250694, -0.7929207133815144, 6.398869750639878, -6.091736851159077, -4.728849132755795, -2.854085872325754, -4.826855364681831, -3.30106640664588, 0.2719713238103212, 0.2298412502409825, -0.853005758672194, -3.263371003058645, -1.287397261994707, 0.6221723886323094, -3.488369011339807, -1.414828169574871, 0.07717807180754992, -2.684195273815242, 0.2613139899890946, -4.206641018599038, 2.982830136882203, 6.657239919946693, -2.518089625188537, -0.4552654704803235, 2.298800483965624, 2.494983397734763, -1.284395189604125, -4.238400338443188, -0.6366063645353051, -3.325393279736908, -1.764225755959617, -1.813359309843393, -0.2947559613727277, 6.320461175365693, -1.048130219904732, 1.69129533904847, -2.336845279584976, 5.580341689077066, -4.541654669729592, 3.817079261725959, 1.972729191142582, -1.594128333779149, -1.535735104483785, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -59.46738063214526, -16.09510211169977, 75.92651854229776, -6.959588443327999, -2.809913552100682, -9.062449485347019, 2.929935910954824, -6.516445771274741, 5.618312537880061, 9.794206647467506, 10.44206520884292, 1.504143210681085, -1.194672878944117, -1.206412082832246, -1.592792412630419, -0.8713955483970806, -0.4430245993565414, 2.114713938914445, -0.3808503381452496, -0.3361054648766276, 1.810321218052103, 0.06324533489118153, -3.207697984086771, -1.888840647774234, -6.337450722394116, -7.051669943095036, 10.24163394168822, 4.591682020148506, -5.157620119910969, 1.350695165969617, 0.7792033958582947, -0.8363399401868995, 0.8398917333791918, -5.122390663285614, -0.589942253467838, 0.1140765360111759, -8.180634436361872, 0.782695084020231, -0.4316505953196415, -4.677604739058501, -3.371394391221965, 6.790122165196175, 5.900302157317789, -1.138518787666086, -2.696524630738898, 13.39780057844131, 4.194434073284752, 5.363099243116376, 4.110197934071277, -2.070985188896846, -1.165572235840805, -1.241624822428416, -7.086628398680193, -7.575672638929711, -1.486981977191632, -2.042873730189658, 5.495814100326541, 1.841533297055732, -6.033390059069625, 1.625951790058254, 5.031090908642416, -5.215840389266634, 1.850639244782789, 2.092351976481545, -1.480623358531872, 5.911569449582607, -1.869423525406329, -0.8096475091606794, -1.000819809262052, 1.841395444723725, 1.081170909224551, 2.284559473058704, -0.6250480378852277, -1.559903447023968, -1.853970655342937, 1.547744137147876, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -96.3647680893793, 1.199043513223026, 17.60420974833172, -13.06773608748545, -13.86009320666351, 0.1767817722626665, -0.5124263274350351, -16.26448243634644, -7.14143348503811, -14.24141019732697, 2.26049840163611, -0.5232284569456099, -1.920838853591793, 4.846489507057715, 3.042770898035555, 1.294385928313621, 3.262620434881149, -2.270944593759149, -1.408453286683619, 4.497236785795636, 5.977793107223872, 0.1340518117987963, -0.6905643209085197, 4.805322551598841, 6.502377969783907, -10.47261184903601, -4.131639902258459, 5.974051724377973, -4.360075843426007, 4.73500504926485, -9.718847270507625, -2.119804026495935, -5.657677043459689, -2.856025773969369, 1.756942740498222, 1.717927994018707, 2.836097818243513, -4.425043948906356, 4.283315817519375, -2.059940986323201, -6.307828936261935, -11.44715911847551, 0.3006681108636347, -5.507293839810647, 1.536345859738123, -2.26452399462477, -4.716331237978856, -1.255956886329029, 0.7042206945918659, -2.667007107490436, 6.672978852425663, 3.262254896828355, 5.937155133580987, 1.948386865395799, 4.552963709305849, 1.788332867713114, -10.63067323751173, 5.26892419774046, 3.167593513248493, 1.170780576616151, 1.205868492329382, -0.3777966262231325, 12.93219596919667, -1.629499482312095, 5.270759888996531, 6.75414771239083, -5.680238880370791, 1.763910811059415, 0.2558270515454605, 2.632569608785784, -0.6147023174800583, -1.873856188681823, -1.734814810908174, 0.7079064341945942, -0.9150650771583158, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -23.02913191459475, -22.68355714527637, -71.45920181332552, -7.335069133951983, 6.88897969406801, 14.22303129604287, -5.713578960023669, 15.25375807101405, 7.31607076966181, -22.97972556461536, 1.773867719140929, -10.21928707943674, 1.424895097068828, -6.202938372907802, -3.564833182189926, 2.874044501828823, 8.685525653278034, -6.81311188053174, 2.764368126088952, -1.051923578466305, -0.9476817080611526, 1.161644143534287, 0.8923143965210864, -1.986614015969402, -4.795152281813358, -4.571219954943216, 1.206804637019736, 1.189134886949103, -3.389219761826265, -1.403036249676163, 0.1159085048840897, 0.8722638450337192, 0.6308893671254719, 4.417698737007038, -3.617011218574619, -1.59415231672244, -0.4094009736543018, -4.615708070111476, -5.105781556006933, 7.165268502604309, -10.27990343205298, -2.449496798762735, 1.740806437896727, -1.676699767804021, 0.4392602027266447, -2.822535542169061, -7.693191637559086, -0.9799315922761813, -5.464041140223222, 1.890629379194414, -2.234640399497272, -0.9456666715392037, 0.997606186316458, -3.110634577331055, 1.532640947608809, -6.76298600927938, 1.926980466393365, -0.3975761625796731, -0.1074936397088645, 1.428032551521818, -0.2307372170405339, 10.50672618228523, -1.043253387292014, 7.351732297170027, 4.654268870350594, -10.97263974298692, 6.22881607660602, 5.315813011291942, 1.976388766185981, -1.590375718577871, -1.91368371633717, -4.647761418706064, -1.035563975020433, 0.1409584860123588, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75.07192855828178, 12.10308470349448, 73.0310118247737, -9.646003904806241, 4.932961189760345, 1.718589369927463, -15.44305085297956, -19.92076242236019, 1.289853308008594, 19.44625320979492, 4.210588674471425, -2.579319144988436, 2.410104964471558, -3.865247564242535, 0.826851006847084, -3.631426466227551, -2.842039660907502, 2.249433450127177, -3.309261383458769, 0.6757720427689214, 2.35903348697973, 2.568255552039278, -0.321803303996427, -1.108091120089183, -1.412785938851775, 1.785124078160854, 2.573232078948616, -2.076416085393783, -9.312869029610674, -4.310360243055708, 0.07839735762587302, -0.4810908104630088, 0.9952395155647055, -3.886794543907047, 2.525965274526253, 3.540664673781963, -2.704864111340364, -3.864627721141978, 4.457179505634837, -6.813519964253322, -2.007416166791153, -1.607611533013739, 10.38000897763594, -0.3046634977924537, -2.266871922238326, 2.573731821774683, -2.979571190380482, -2.320864784735163, -1.500209869827327, -5.106748863521393, -3.950957911975269, 0.7340374884876252, 1.73889407335216, 2.182641990536762, -6.356098593894809, -5.93055977994974, -0.6040135105288104, 3.029168613692871, -5.042929510576918, 5.833709461846172, 15.29860079283752, -1.235961351707758, 9.34323445595332, 3.785951093156088, -10.34177459105045, 2.911648799971752, 9.281014378066164, -0.4941493880528656, 3.071779513490743, -4.517815603760604, -6.192250219969715, -0.3317883573330157, 1.349445179208848, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -63.45021054279741, -15.82766767521525, 41.22915354775575, 4.664008353213778, -1.654066901130316, -23.18254021974398, -12.84906013980607, -0.9626027911697629, 3.41433891445458, -0.06961595567794145, -1.096971305807928, 0.8698295584855787, 3.772196521299375, 6.631293883425417, -7.052125668571361, -3.200823343555333, 3.814349784726156, 4.941784929229768, 0.6315537523938005, -0.01802357802850369, 3.141620177813325, 3.10250469485239, -4.155135005432694, 1.701739006290255, 1.540814933013846, 0.7387665729315541, -5.311958621040922, -13.02405885670838, -4.942498894115073, 2.149572755504388, 3.341124951208096, 3.870026706159178, -2.46509460954075, 0.4769961681706392, 6.604145321870847, -4.15894453283208, -3.374029939123039, 6.807566765521488, -11.58698328431105, -2.80185415106152, -0.002148524464262543, 7.754192162202266, 0.5225981165001614, 2.195290230986459, -5.408948531637178, 0.1049214015983932, -8.924285492967401, -2.350089393085131, -0.5423255417785425, -3.219609856555158, -4.390973896320624, -1.269742631984241, 4.051212063679165, -10.36139506901704, 0.3230350713187323, 1.674998606949747, 3.540984566900865, 1.18972973091647, 2.057607076615883, 13.40112401714828, -1.748763782836714, 13.13716409027571, -0.2243177932456299, -12.24721484928519, 5.87773220153188, 9.74466077242022, -0.8896869572089892, 2.189477242908632, -5.208603883097037, -8.105641911969411, -0.7300180023457923, 2.022265831725371, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -52.66687486179152, -3.101783038688906, 62.54840137160225, 9.616670950233983, -12.50481143141205, -28.04924352555032, 18.7558503771284, 14.97634693290006, 5.851320122566384, -0.1677270839150571, -2.409084137352026, -9.845991621034058, -3.801336162247693, -0.9907297274053595, -4.664351290089362, 4.309633797495072, 0.6048954669030202, 1.543984136643211, 0.7189536403742964, 5.611415033458477, 2.487672542609962, -8.621934168449286, -10.05094063299714, 8.742063873037001, -3.490157247009134, 2.066460908332703, -4.477586251672978, -5.332933548411357, -5.713234560480118, -8.240059969073409, -3.364164696488402, 6.227061542811854, 0.1791896591361718, -2.507565879175399, 3.698854501954176, -1.007279474702307, -5.481898046206347, -1.72805442027048, 1.655718519783813, -4.101110323704863, 3.320297978932387, -3.684641982534487, -2.130960673414645, 9.904486582652764, -2.376262647862093, 2.148900292669743, 4.759998469058096, -13.36944502872464, -7.978751527858369, 6.863214185815936, -1.882367548219069, -2.561088530514321, 4.873981502571982, -7.579320197588544, -1.497679078782172, 2.35834379567061, -8.385645880902972, 4.09880893561949, 4.828417395745121, 2.282140125429291, -4.833463519506268, 2.913845215609183, -1.612937226837221, -0.5525869262187749, 0.6145753612090259, -1.089608686377456, -0.3258113829684524, -2.210223671018175, -0.8097847014254713, 1.266046990796156, -0.1222971055896021, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -62.97383455884989, -15.72156846847342, -50.52987429444124, -5.821406791941631, -6.271938286848207, -28.08098151092815, 2.368560549147725, -14.39710551246207, 7.569330972477777, -13.4264330861926, 2.75461801976173, 2.688711269115824, 2.764732074458091, 8.408341398358559, -10.04776489918815, -7.396363378028368, -1.149416203511894, -1.054301083542792, -10.04596380901379, -11.69408823775871, 17.38686456253957, 8.299516226227814, -13.25762288717717, 7.349031579684647, -4.534835890890477, 25.89116419268924, -0.01992743860632668, 7.982099277597088, -0.04160883712533649, 2.573520590529096, -11.35149838346194, -4.227617111120538, 0.2168974914804734, -1.795362046493738, 5.631764300285649, 6.008575066010116, 15.72428788595154, -1.842254414189587, -0.5382261085672077, -9.552315485913649, 3.675875209168321, -2.602166724352801, 1.859610651661533, -1.895505270339744, 11.52276237353004, -6.239279748413804, -0.1297742740578715, 0.6991046300254831, -0.4208529689673289, -5.060072193399457, -1.906088726339328, 12.62054139647468, -5.130598829626098, -6.128474594316537, -7.690481592824534, -2.247055264194942, -1.447577869543198, -12.36316455006643, 2.732894276344731, -10.27755222960528, 0.5243468721916534, 9.047719038239586, -4.383971076616716, -4.842518948484556, 1.125600151566935, -1.90225576696169, 4.722031005971605, 5.306544131294808, -1.877228890927751, -0.1571777681548308, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62.52508007922609, -5.719488295515556, -63.28854566104216, -24.50023292372474, -1.974567606587724, 15.49864632949223, 6.998409457393456, -5.489144318408908, -0.6799511450744802, 0.6168873226031361, 7.888491941073679, -11.5213969968209, -12.02867471563315, 7.763694194348873, 8.334853365418969, -2.380451302943409, 0.09020014258787826, 2.3486772567884, 5.673982771176749, -11.02127409093227, -3.603461078419621, 3.167170753763195, -9.711383410279849, 4.723995107208117, -25.16138896067726, -12.23741325241211, -5.007012002050583, 2.190640446078525, -2.216636720328977, -0.5859489793413336, 8.233471386988535, 3.365237643930874, 4.189743657652521, -1.395157859959696, 0.3920210029284703, -7.056426817934152, 2.580560567814978, -2.128975130545938, 4.242435652432224, 2.235031188314527, 3.444275519482045, -0.7064127681508054, 3.521919688523948, -2.59915922665114, 2.796011561611334, 7.213677229286767, -0.2401477293445469, -9.239236230514949, 6.250101954381679, 6.220350851430839, -13.83625185491088, -1.200037472412707, 6.659714118020979, 11.18894360817651, 1.029186325547049, 3.013890675288255, 11.33035543805201, -0.7441654641054523, 9.147248359723497, -2.626393685016684, -5.110468073117602, -0.06530067048820608, 4.76431701962415, -2.253412642242864, 6.519983245052911, -3.976542599366748, -2.604614469192844, 2.348858737245175, 1.219946438299759, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71.32602496514716, -8.756876217814053, 35.04911984263231, 11.85596450877738, 3.138232705310344, -2.194824321913857, -2.176583710259183, -3.343478177638568, -4.236563157562049, -1.392674203474749, -10.32262876392589, -11.63217516576671, 6.360303917047404, 5.478160154717675, -1.373379667953706, 0.1222360308529321, 5.92992964189494, 6.968285486207656, -22.24412202832642, -14.08200805003572, 5.255065130840872, -9.647401891006457, 11.00321233823368, -26.63174562751841, -2.523162844598605, -6.145124307805637, 6.022273738346928, -2.926653347515803, 8.133925760802793, 8.591428362280888, -6.013423802818253, 5.249342941582124, -3.970400887670635, -1.748951928295462, -11.28492868937306, 3.683276522805945, 2.775813620317148, -1.942462052184175, 0.8891846150120821, 1.129690076778026, -5.55530433211887, 6.228804252833361, -6.493720150589822, 9.095196357844529, 8.099379043388204, 3.282276517555831, -3.970254131193375, 7.47529332111375, 3.579752526867083, -14.72795586609742, 5.127558963939634, 7.483150275119841, 8.143770403634198, 5.638865762472385, -1.070704874835951, 9.665581065265565, -1.166404516592552, 7.118528213260745, -2.114185083787445, -6.481345817022934, 2.439165766212086, 1.688770678506234, -1.42208740458422, 3.736908500476163, -2.52099822967916, -1.096365312903943, 3.115453100212649, -0.09261316039995293, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -53.91482041296031, -6.195234141533248, -84.22720528023089, -8.228357964869858, -5.335191448255144, 5.056702938346606, -7.464695583224544, 11.90761078244647, 13.09090097966719, 0.6578496842921259, -10.92616341315019, 13.03744853784803, 12.44023007567226, -1.161373459354644, -1.087744561840636, 5.932731979531396, 9.315732460781408, -21.37551613946766, -11.96248596464901, 13.63024808396517, -9.288714959320243, 7.289554080422293, -28.16285634112625, -9.571761912856207, -12.95118012023273, -3.750611197225868, -3.922432347873787, 6.124510964031026, 8.396222723906581, 0.6148965037770432, 5.13355621975811, -5.15138967657882, -8.114413035924995, -14.85090329064167, 3.39729299292902, -2.657124865451653, 11.34942261680844, -2.606547131090628, 0.1623880304796317, 0.3049177006141654, 1.35635227366094, -6.653050626870728, 8.073015458686122, 4.32132583894199, 2.212964809408603, -2.184076048165147, 9.799834020565784, 5.96606727639304, -17.42599122311193, 2.990347710352649, 8.359376262684071, 11.42371296595421, 0.9821035082629358, 3.26846258160433, 16.37981065781434, -2.885803722420936, 10.97059625603291, 1.611945735717845, -7.260237552742894, 0.9012561107562547, 4.615303611480527, -0.2799207674436057, 5.037467804678709, -4.682042101547799, -3.881526357472375, 2.728902770049329, -0.06849225345413945, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75.12896070864572, -14.55114803420073, -25.88520658421626, 0.3634408911932056, -5.749148081032294, -3.987054468607347, 3.605389714269859, 18.07840198100762, -7.822123425494485, 2.924157083708025, 1.962703760694055, -2.860064629683554, 2.959145172069614, 3.93868226857773, 6.366668810634879, 5.288829466990348, -4.294038560170033, -0.08801626773445168, 5.250702110881997, -0.3152641291658385, 2.199002653107061, -17.67833947760999, -5.045964490505647, 1.211048049454066, 2.421824405506, -4.376451661909966, 6.241973769898392, 4.290964226801218, 5.969309505771088, 0.8555684941579085, -2.217790960392097, -1.35718576281381, -1.746727805108543, 0.5254608653917869, 0.8086186851967726, 5.293064595586645, -0.3599247004146829, 1.959101109902374, 8.947006788222373, -2.378495602576101, 2.723709987744103, -2.329120911932814, -11.05882331472708, -13.0794383091978, -3.452514320213396, -1.512851055243775, 0.1639755205493351, 0.0825479539228451, -15.39065507630122, -3.091131632830409, 5.338329408636449, -8.829569668743607, 8.153591122859282, 9.18321870067153, 3.77411909040066, -0.7259214307321555, -2.707742728847757, -6.070142253582127, 0.8961401710073812, 9.291034725859165, -5.172620787510649, 5.77739330996065, -5.938409073064742, -5.68284811156704, 2.213899420332612, 2.230741101606077, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40.51083229358659, -6.657401086597119, 46.1651355827067, 3.571126140204381, -16.51018529197995, -18.81764925681962, -3.560003960730173, 1.069143039257071, 7.841419461017695, -7.426825297086943, 3.636227586276667, -2.832840975189855, -4.226091127266264, -10.32558071350056, -5.423718841813621, 7.898975963852462, 9.110182036344748, -4.818572270232188, 7.517064129930646, -3.069225466093795, 13.58082569251052, 1.95336044171603, 5.706764456088048, 5.029792791510202, 3.178869494747695, -5.047323754409704, -2.736438120770565, 1.426807143702085, -1.920567914619038, 3.428205422463726, 5.74585589697081, 5.382153677222462, -0.8865556423886194, 3.914778289385668, -6.604066141662078, 3.391876836068548, 3.169728760425306, -4.677156167446953, -1.155070546015535, 3.061191481464817, -3.13123995748959, 6.494562114793292, 3.376621926659731, -4.587404098548453, -4.277527442893002, 1.474886961462322, 3.323795372963384, 5.401089673065682, 0.3253871348814484, -2.369066423960044, 3.865796037257022, -1.638291040075763, -9.722922494527154, 0.5238103099430581, -1.203361374442151, -3.74503959737966, 4.569457144757759, -0.4965825177245843, -2.765019233250034, 0.2829604726448859, -1.146952017594104, 2.265032786536537, 2.680700571952246, -1.255503266954519, 0.1637658162738065, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -45.71426451969628, 0.3451233465733878, -42.83879591649266, -9.652152512053839, 2.943077049148836, 3.595807131194814, 12.07618358595724, 7.583721776261375, -2.798504129600953, 0.3493125113412846, -0.3060685650112926, -1.969954034839694, -2.226643423419492, 0.2775817976926701, 6.61252070570618, 0.2026442823847165, -1.756653814676166, 1.358336152476414, -2.953213341300402, 5.767247508163317, 4.576452080845395, -5.48265868666933, -5.584394192816982, 5.087476338922126, -3.141525913674985, -6.275099033613296, 5.577549390317852, -4.816802787505703, -2.484144702930381, -5.941817033794925, -10.3264911173429, -5.364557843392888, -7.843223405124702, -0.5283376840825795, -0.9570442251031415, -5.24883614050029, -7.185962189820855, -2.977003550332989, 1.181048111506568, -2.173863203462683, 4.403509726183693, 5.789771709589788, -3.251326838177565, 0.833293737507765, 2.197330074627189, -6.70359339703703, 2.969866449959098, -1.167049442438063, -0.3088855619701391, 2.234922153742612, -0.8743490423992627, 9.838111926343993, -3.681537357431789, 6.247482122998323, 10.24712337154277, -4.61734564949215, -0.06307486749200926, 1.334451074280191, 5.336299550216522, -2.297158597383811, -1.096756988788949, -2.950656621747207, -1.793982883674879, -1.379935304922622, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58.4305528833414, -10.93080151481084, -73.47222018485503, 1.299575050569214, 18.14449108892977, -6.050719753243367, 0.5840217211940599, 1.960086594084849, -4.368421952540212, 1.788116554787903, 2.164491069701282, 2.358970020887192, 1.093569678019126, 1.989649218755819, -1.28823196621902, -0.5313187250208743, -0.5624844430654856, -1.907667575555907, 6.909040860485212, 2.408127751390964, 0.4215555707913529, -2.780873876588656, 1.85248203975166, 3.135639744664483, -4.380299973926649, -3.921426250428929, 1.495099382458397, 2.622560565964388, 0.2177544811958763, -0.04339424448668048, -0.2214592105458387, -2.06944907992863, 0.1763703512794778, -2.846732426447117, -0.4639421303306322, 1.287390331822631, 0.6533086995560746, -2.425549690664099, 3.088053892492399, -1.130817472618208, 1.485446373139376, 4.380685859773039, -2.57028748480229, -2.127967029034677, 3.41369029366427, 7.568188803198317, 0.496744282104129, -3.964473757500087, 0.0282299427440213, -1.96849998024905, -3.553514188828535, 0.9438074995728989, -3.104500825703638, 1.724858829778236, 1.800147082209048, 0.224333685578572, -3.291601313990126, 1.370577599850704, -3.565441527576292, 1.823418080577437, 1.52484990001091, -0.828729219973382, -1.06107451712335, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60.4551144650917, -1.112031735605267, 40.52296759779913, -2.279357391039372, 4.563291267943169, 8.295632041224566, -3.939508280061141, 1.942114905022437, 3.077992623697353, 0.6979345603294407, 6.071625856395872, 9.832923870768321, -8.720411873028274, -8.458375209728874, 7.032936679862646, -3.660503707293801, 5.13609182864828, -3.763326595416756, -3.646534951906556, 3.175402986994713, 1.020866860271357, -3.886824646779147, 8.218325748247384, 3.32404792165843, -9.200062655640144, 6.295889066677559, 3.845719933212995, -3.43351185274513, 5.438009428491434, 6.112353772294139, 1.228860655027741, 1.024037136509394, -2.139240304739709, 1.532357918757432, 10.1079544033704, 4.044497472104775, -1.295614976235356, 9.473469973585541, -8.029083475961539, -4.343462366128194, 10.84815682088869, 1.011633882504112, -7.169231098330976, 8.133704565655293, 2.691632282997318, 0.8507816064460101, -3.282652921494739, -4.061244378839357, 0.05112572018852947, -3.547751950024609, 5.30365786223212, -9.690997968552335, -1.734557454096158, 2.931578504521047, -0.5834918591113373, -4.496448398993238, -3.031542637377464, -2.036988448519847, 2.154422493546257, 3.299173741623872, 1.162415691741919, -0.5670591291688311, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -70.06613504205954, -9.835478687386175, 48.52214856712762, 11.48136951108488, 5.892721436902954, -3.703795834979923, 0.8429544617402316, 0.6016790749403919, -1.12542788838987, 2.368548605557095, -0.6822772589146743, -4.287688004185707, -2.594460038219845, 1.811391939430363, -3.268064562811219, 1.460904850276689, -2.864974741945764, -1.034841388002912, 1.745241178328566, 2.486796799228639, -0.2269447058580376, 3.439717265105236, 1.02136554408696, -4.705182655489384, 2.499760827621522, 1.840963673652037, 2.953808675230261, 4.276133519908038, 2.651957942115774, 0.6355241666252862, 0.57194650441768, -0.1440454915229704, 2.242291193237154, 3.579445219558762, 2.752322997747827, -2.639308831991975, 2.4577698710486, -4.752199390601385, -3.863233755634323, 3.10435637509681, -3.028301690338678, -1.02478741743191, 2.754261908266995, 0.03535310362791887, 0.6383262792814937, 0.4368852433821509, -1.380097243200454, 0.281051180629981, -3.521710925389415, 2.247365619297284, -3.14338177048046, -3.302250573466052, 2.012036598405328, 0.1368976717018865, -1.193536497653941, -2.112322112549731, 0.1388066012915721, 0.8364226293226722, 1.307996121331485, 0.8916481210688338, 0.4828704628796113, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -48.35160025190098, -2.541971211171999, -40.68153564873732, 9.207954361446687, -5.556985583068949, -2.844696785788164, 2.796718046185394, 2.464041987072172, 1.893613270308423, 4.028977435880829, 1.580350980861052, -1.926871386712014, 1.936201877177753, 0.03605266371746324, 2.628195057996384, -4.803264934471255, 0.1432706764330213, 0.1079385572562689, 2.678825585163418, -1.064180917349414, -0.5008460410343695, 2.882130267316084, -0.15398049667585, -1.581309397233642, -3.437020133996731, 1.265459202748218, 1.117834225134362, 0.1360954343911673, 0.9375505319888843, 3.243740457337423, 2.092675870695559, 0.04783544042641906, 4.765463295666528, -0.4641437505818906, -0.4785294697426362, 0.9696458103026435, -8.685566793141595, -7.008778621407876, 1.595549810231035, 0.3128462080006037, -1.324425648748344, 1.053200285772633, -9.359526652432077, -1.580936494199254, 3.673447578818254, -5.544913965708159, 2.361010918728093, 4.208995052675768, 0.06177199204784918, -0.7315046900899178, -0.358711190997884, -4.578123417453783, 2.050322078756102, 3.974849259098512, -0.7452561049821164, 1.594734714218798, -1.737806196971752, -2.031916066155333, 0.5613088668818109, 0.7078249129938057, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51.98712898798419, -10.91279555750407, 16.5116520014062, 7.070082094300194, 7.316626743402702, -4.062538962997873, -0.7405273411971364, -2.403988646588473, 4.735499624487429, -2.288345916874214, 1.710004157792464, 0.7759293763857303, 2.319801872864849, 3.523736483172671, -4.063099150658085, -2.492051000480119, 4.11448548909593, 7.129988646336227, -2.243669991226699, -0.01638383640626986, 5.035870505157345, -0.9263294558811588, 2.097755508212908, 1.321512562673401, 3.748642620543865, 3.497629889280451, 2.535560833332076, 6.70155773507767, -2.222025277278504, 3.745469454508642, 4.860671405997067, 1.247993743903351, 1.366709222748014, 0.15728611894614, 2.359412737808513, 2.228713531327038, -1.291887607463255, -2.502446261947766, 0.8576018641230071, 0.2591128365637439, 0.1281550783740285, 1.457088120497456, 2.804040947211357, 3.04089132770398, 0.5933410236497064, 0.5620801447638994, -3.466284049616893, 1.640115928164911, -1.286700740977786, -6.179791106131169, 1.636998061183449, -0.2159342040060719, -0.3846813123879876, -3.023642425428129, 2.529816319670621, 0.03264733953770085, 1.353325216772121, 0.7761992320974147, 0.8335576498590705, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -25.43514166894322, -8.17729396479627, -9.755663509088453, 19.19784728348034, -4.384048886049747, -7.499153400798601, 4.435169145012178, 2.435444086759126, -9.059597245945259, -5.325657224831133, 5.740599830438042, -2.492050052381312, 4.19796696197511, -4.263587721918892, 1.77146723826956, -0.4935403175135217, 0.8862361772476778, 0.718637930367225, 2.234402910854942, 1.153322927018771, -3.443329198738874, 0.6587212840847486, -0.7054120735100874, -3.07872040612198, -1.371786433350092, 1.271824407901802, -3.947941817835058, -0.8336796717965617, 0.6116519681575391, -3.071696553703523, 4.475454076327929, 0.7609188629051276, 1.92281105267744, 3.40184922477059, -8.810192326908565, -4.590741833410618, 3.734024788110379, -1.509040639411721, -1.529465630170008, 0.9461084686824491, -6.75503144580174, -2.037690055578029, 1.030666583912851, -3.882610283293217, 2.375072374836591, 5.361220748281059, 2.030587685343521, -2.594516437562062, 3.173762351676447, -3.470985476419609, 0.8394945737986235, 1.011387559197422, -0.3451056702610979, -0.5600384586317051, -1.250437490195752, -0.6594046924812333, 1.043095979522655, 0.3317341014295642, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28.99829564612994, -7.919492306918029, 14.05556909884386, 7.925941651982717, 1.30923833477671, 2.711408876410578, 1.61295413285611, -1.556599660832906, -0.8098128328747748, 0.4820136628666691, 1.242144749021579, 2.59270514147219, 1.070695817241087, 0.3750106994386846, 0.1725150645491444, 1.817115818968294, -0.4814506723964737, -1.161742890285604, 1.472007131837003, -3.436966082846573, 0.6982494240111369, -0.3149935878404753, 0.423370074395463, -0.9574295293157908, 0.2421056567329433, -0.5049850377885065, -4.679003799785368, 1.836812379169509, -0.6413835068300918, 2.492048982685315, 1.392871072424903, 1.054456102018222, 1.562804344198468, -0.5360913571726491, 0.2289458184750688, -1.348818559581913, -0.7324130913590041, 0.2525553513400682, -0.719825146825839, -0.6622690818866591, -0.05716678780881196, 0.03985333634237294, -0.3355682149483769, -0.1341481930486313, -0.2245769325773339, 1.701054496016564, -2.071735516197021, 0.7197321751353539, -0.5990693757732555, 0.7461182301273023, -1.28537860516808, -0.1752635447217054, -0.01940763082982118, -0.1985636316510818, 0.9478745916084782, 0.2042482439571948, -0.4223294809395653, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -26.09223882232648, -12.37682729616652, -21.27874182963862, 4.348357266610032, 4.573400992223148, 5.451216191750214, -3.611392020039598, -0.07921190808374405, -0.8260009529279171, -0.8434890069043338, -0.4552052508830591, -0.4528369276968658, 0.485445048833045, 0.7411599447890793, -0.4977249990635382, 1.190184399027994, 0.5973815546085762, -0.787231230010092, 0.03686032549901305, -0.4890816251224443, 0.5247759592075937, -1.879966027178497, 0.7792555164671459, 1.08723712738975, -1.42032534259863, 0.1721744481327533, 0.1056055009830306, -2.005790677375433, 1.016109801476819, -1.242159849121084, 1.243013696198364, 3.432482241304956, -4.523104088240713, -1.568715574671622, 5.119814672065328, 0.3791289530216432, -2.190682514501041, 2.552754170198622, -0.449368385418214, -0.5848836895616387, -0.9128519962622303, -0.9291921116478306, 0.6344008715643001, 1.688400124637569, 0.3633977049284803, -1.575721206061369, 1.961090047103945, -0.6752069375516031, -0.7855465024767947, -0.2102475861881171, 0.6869577789805948, -1.299232189451566, 0.5683367030798885, 0.3130637568892004, 0.1545378225570001, 0.3790410707685513, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20.78430083032547, 1.185047939349582, 35.77538180501586, -6.08934280503613, -4.628055061913704, 4.470155638785817, 0.1274755893885796, -4.165150926841093, -2.90227906734488, -0.845111562541671, -1.740136245099567, -0.7946086439652909, 0.165908004480544, -0.6322554553948885, -0.7202811048901517, 0.962291525388159, 0.1867569707618253, 0.7090001464102381, -0.9034980429447981, -0.7997832600818465, 0.1057538227773544, -0.2295775902801903, -0.2167480404571516, -1.707234755317263, 2.041285551224553, -0.7878934898873934, -1.430438536425756, 5.730418488030445, 0.6926510312478421, -4.339109958364433, 6.727134105417382, -5.329326344720556, 0.2090167614184525, 9.514829796739471, 6.99752035864157, -5.726866864790069, 2.796275247427376, 2.891078173635352, 0.5284713674492778, -4.068212458937251, 0.007838785072538627, -1.603613176227203, 2.0145967452931, 0.8759256044597022, -3.80096540098218, 3.215984538447468, -2.552801380633107, 0.554399068571981, -0.3103317501790938, 1.208594964868666, -1.283494125131377, 0.7998967241899251, -0.386450465669298, -1.202893469925367, -1.317846847748221, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -47.41309320362173, -6.902809138581961, 24.68993718840007, -3.13534854977696, 7.054619343395385, 5.577611289513071, -3.877117196513223, -0.705447221487262, -0.8099002262119813, -0.1565635558190763, -1.127616075289359, -0.340714841660406, 0.660945871772091, -1.386755567315061, -0.4584883778560444, 0.9198751662032315, 1.002014450214894, -0.8640902794196041, -0.8777171102898179, 2.14825103785315, 0.989246034616117, -0.007095782785030112, 1.73906114106083, 0.6255059446607256, 0.1889696248858352, 1.03385909422522, 2.226668602394364, 0.1698945168834521, -1.873328492302393, 1.635950747204321, -0.6535224611564427, -0.5212140486619968, 1.003703892471871, 3.059411904595601, -1.892088474084682, 0.9339283828820583, 2.372361621792483, 1.133949816931869, -0.1994699011958669, 0.6535725484050933, -0.9195781603438848, -1.005444925904406, 0.06444426676642491, -0.8098171033672705, -1.318065403781523, 0.229094599479945, -0.1458840598162685, 0.2580570421599906, 0.599654091348747, -0.1055495042899468, 0.8993623666137143, 0.2691782537744015, -0.1099774106379499, 0.2977644683250328, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -24.74429137938651, -3.056148054133861, 19.0056932068058, 16.39870702492764, 4.267138497765569, -7.263096879020432, -2.919011924763906, -0.4167087337896431, -0.8396221408817942, -1.296684951975891, 0.7231090234720337, -0.1375746950653319, 0.4893869484915677, 0.3142640879884956, -0.2220967974170002, -1.109112753429507, 1.837593002510292, 1.479112432032976, -1.096302655894103, -1.964525246159897, -0.3280412024354407, -0.9206324506519383, -3.476018583754276, 0.6640599703563438, 0.3918183916355132, -3.395485381429018, -0.003002004945104059, 3.146782410011682, -5.072333819483568, 5.41257407183969, 0.6517585511003233, -7.269221543477382, -4.056630984171059, 4.210313402070434, -4.078813743290807, -2.25180663054022, -1.292189897325851, 1.427646253569202, -0.02497439324399699, 0.4774218280565992, -0.6503459447009956, 0.2399655638403526, 1.867125503961992, -0.9832308658323502, 0.3873487083709633, 0.05281139747950379, -0.3835529630274041, -1.6917245847278, 1.122860683946538, -1.59095315900844, -0.1293462709264742, 0.744401662451372, 0.550681606700183, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -34.33789589268527, -6.878943247619225, -14.64721261322692, 10.01107177766694, -10.23942535961409, -1.01498039173437, -1.897412320562053, 0.1671533339857628, -0.8712694561978971, -1.083706765312663, -0.8072110203673344, 0.8308152015963188, 0.2147544944441696, -0.5493919968376136, 0.1446575439684376, -0.6832698103437359, -0.3948442858808979, -1.115588657559433, 0.3579803772248178, 1.360983446684671, 1.00664254181845, 0.463405794612902, -0.01621384683534825, -0.8228161891870686, -0.9063503571998639, -1.803563811674677, 1.773734326519576, 0.4302873906114944, -1.04322351848609, -2.826856356023816, -1.324768966730078, -3.650267019006124, 0.4946176831514201, 0.9765254105590534, -2.029801194780261, -0.08501190782368655, 2.178344340984078, -1.920968439027878, 1.468087622744764, 0.7608787750954016, -1.000741195716964, 1.504164739818004, -0.2688678814948808, 0.6600983722848048, -1.220320200367525, 0.2410125647060634, 0.1664703506451447, -0.00850398171402288, 0.147174562643468, -0.02779982278043158, 0.8346719111354661, 1.343056942062318, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24.86877278577309, -16.79318934098175, 7.458488104737861, 9.49827773740922, -2.037264532584139, 1.252205231895099, 0.5394711870719748, 2.195699736074124, -0.06182472637253196, 0.7020281028590925, 0.3258270446041916, 0.1103891416148433, 0.2807839830050392, 0.8324674121995713, -0.07707017579260933, 0.04774101018547401, -0.6651862970621468, 0.5716949794838074, 0.2786641675385044, 0.6522299722084175, 0.9870590659751258, 0.07525858148281402, 0.2573717074126062, -0.8694521708682318, -1.166811640779638, 1.298799293918699, -2.203520860482713, 0.6442208455279349, -1.644267690640131, -2.625903488982017, -2.302992147951265, 1.257444945761727, -0.08416130603880936, -1.270800555411265, -0.7611165428890112, 1.039732198091014, -1.251481617872658, 0.668700121789956, -0.6911166576485717, -0.6139792747015455, 1.608281400168625, -0.2867634337303782, 0.1637144135551453, -0.00432411765221891, 0.07102947638320466, -1.167072230215902, 1.020402395737285, -0.8250836936353415, -0.6010780760217853, 0.1575436581466232, 0.3661602997463697, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -25.48744110290001, -0.8196103125693783, -28.12739691634226, -14.66875241082419, -0.615739550477418, 0.7968006490105319, 1.893633537382631, -1.654939455947577, -0.6163475289447353, -1.258986228668871, -0.1685854638534228, 0.3466358666389292, -1.426194843008651, -0.2003994306001548, -1.259905297827965, 1.344072840361883, -0.688819755049539, -1.014480774303581, -0.6295918075499517, 0.1776953465799677, -0.2343489103275878, 1.245580834373049, 0.282925806992274, 0.9010886337902754, -1.886506785726124, -1.464163182582124, 1.060688891787593, 0.9766666550692192, -0.7971522349237924, -0.3026477025841756, 0.1569473405096722, -1.562229392252153, -0.5092349552596337, 0.330008450314712, -0.6335053028536132, 0.4247451599698489, 0.0985199006348359, -0.3513889048599413, 0.06524354177060393, -0.1957245081554103, -0.9317593740728739, 0.1952654121598859, -0.2590026012553117, 0.3001134383078498, 1.986414203689662, -1.071273239462749, 1.253278874165287, 0.33617967896085, 0.7395830923202225, 1.549701849275336, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31.61694956773989, -9.578300913349803, -3.504213982861134, 2.937150834658584, 0.9888020778636044, -1.024980201460239, -0.5118645161888414, -1.146567755798608, -1.444823248641867, 0.119064333528641, -0.4696982483040331, 1.095121262010022, -0.5308991134969057, -0.5197247973700743, 1.05002708888555, 1.818937037971043, -0.464288009797318, 0.6619872266917841, 3.401021092823941, -0.9482749170371739, 2.813315825246367, 1.129476242162393, 0.1981687722797381, -1.019635015614744, -3.307198789311745, -1.432171362179824, -1.184749190478042, -1.044919901810701, -0.6539226010822516, 0.4625979387292016, 0.6826291685753989, -1.87320881210041, -0.02360508954848113, 1.040603087479057, -0.4961300270289009, 1.055913719807241, -2.655638121288787, 0.1835672294990115, -0.2887263743968013, -1.414391072650056, 0.9868620830546826, 0.6374153108068793, 0.1452572712918873, -0.3526782564487305, 0.6972915252755666, -0.01466270301749871, -0.4766248436639112, 0.2560860018610663, 0.5918528531262749, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16.11268891122238, -18.88517791209816, -7.849457648122431, 0.5186009516658268, 0.9174633102810905, -0.4433385845787631, 0.259117803259069, 0.4812800928303352, 0.3809278637536887, 0.1040308979050729, -0.05696819922547338, 0.04177348257977326, -0.19151417247168, -0.9633478211800127, -0.1242642511041362, 0.3111175057895781, -0.0993555030948718, 0.9200983120151756, -0.283630744431747, -0.3768440931992381, 0.2608693517536536, -0.1701114694365957, 0.1657033422918405, 0.5579125426286559, -1.625886334801126, -0.3807035749043056, 0.9640891719563836, -0.1517544113079037, -0.06175882514010688, 0.4876052179200603, -0.1171970532950455, 0.01944444533954101, 0.4490968232071326, -0.4458741922044034, 0.3254420663099036, 0.5282760372591894, -0.05934694150103174, 0.1060201539053977, 0.8283931026778301, -0.4074091722040743, 0.4784701634625882, -0.02952608481148086, -0.1915663172505298, 0.1218560114391382, -0.3518484009580818, -0.2587618544226619, -0.1011116715064274, -0.4008733499435151, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -10.28612342841808, -23.92112732279337, 5.771795426117762, -0.8030148991959661, 0.04406286929137412, -0.2462851679259779, -0.0790329685264313, 0.5162614125094603, 0.01081766552358586, -0.3771532498914852, 0.2371657873877063, -0.1121483962706096, -0.598902253817861, -1.018195608367853, -0.01053082672842091, -0.3684877801366509, 0.3508826267234865, -0.2390155682927431, -0.1773909049534708, 0.1757923535233533, 0.2788684363679378, -0.521760862098457, 0.3153403198775502, 0.08909424355874358, 0.3382317489455293, 0.2248194206427477, 0.6112323344458919, -0.05266682106538524, -0.857521487871565, 0.09621919673355192, 0.1820135304582492, -0.03556509270831806, 0.05480383694627229, -0.05236763037981038, 0.9935679652239512, -0.01831786321756342, 0.205863157809067, 0.3066879134775455, -0.5897438503738709, 0.1809856006527006, 0.2304158672123705, 0.1357359363236704, 0.01081706136475033, -0.2019643081867054, -0.2674765180786534, 0.1218826125012657, 0.06599894348285046, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7.508940298192356, -25.92446548490683, 0.8596283612994251, -0.885296785459307, 0.6510912736108546, 0.04489469589179211, 0.1153490121088812, 0.6103383563995985, -0.6314156415588608, 0.01915715564342266, -0.5113720254650198, 0.08321272888636021, 0.2526155635642888, 0.07676680070437664, -0.207069381512334, -0.4238244829828506, 0.1598019632669035, 0.01979690071582769, -0.1131733213057336, 0.1678269137319559, -0.06128460713493483, 0.2950474603493092, -0.05777326473555904, 0.1081544273212701, 0.1350575367841474, -0.1382598662249417, -0.02063619586362458, -0.01748166206219487, 0.1390481463209892, 0.07165704302950053, 0.1349895003361674, 0.06236059106166005, -0.1944785128320574, -0.2787255380331269, 0.01560113047175663, -0.2002320581613433, 0.3115961907926021, 0.1635870368788743, 0.05678294158098499, -0.476018191230865, 0.3068760522389033, -0.3033131104805271, 0.3509349305650783, 0.3398673523876503, -0.02472276597655712, -0.1406202583056918, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.938841061583187, -25.33986700948118, 3.895381103905187, -0.4068328885046618, -1.020248987608946, 1.875210227283616, 0.8326849356539051, 0.3197332657604331, 0.8814021905636888, -0.191597405724302, -1.189763075075068, -1.758874335134983, -0.01899353751647506, 0.0276611350365027, 0.5048267537307356, -0.5806174579955142, -0.02276182921702848, 0.4354081702397676, -0.1913814507405756, -0.1404271457144592, 0.4293939511517911, -0.2455037565707741, -0.6287458194591844, -0.4325390080784384, 0.5663792753160686, 0.06496758462505856, -1.013812891552513, -0.6580075377114708, 0.3012766122553553, 0.7826160029411943, -0.2956334704185347, 0.5829842798108729, 1.888181195419026, 0.2434171191535548, 0.4382404847806721, -0.2260461131572888, -1.002274173244901, 0.1511392353702925, 0.959534113889126, -0.7055427039674402, 0.6121511681849879, -1.070201333103883, -0.85450815461259, 0.3517683076365886, 0.2515058817628869, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.188440162629536, -18.32569924146616, -9.589804523680115, 0.3710427014950839, 0.3218205714481496, -0.2690828162556131, 0.3778764240350382, -0.3074423748293786, 0.005775081556014241, -0.01195607972614768, 0.4411561531339875, -0.03533727446997911, -0.1118188852301485, 0.5245470238731157, -0.01500837976097037, 0.2330462173829136, 0.3097172521421208, -0.1141404752456203, -0.03010554327463865, -0.3053455023961597, -0.568283713910994, -0.4659469523334061, 0.1389552806909783, -0.2547565634519277, -0.08627456156926228, 0.4559236364597809, -0.3852998773859254, -0.2059868514232366, -0.02375049165040808, -0.3131649641419055, 0.1909454021240402, -0.2322739633649241, 0.008020950818914468, -0.08341805591326434, -0.111253448846017, 0.05259516567515898, -0.001122570051102888, 0.1514471161594721, -0.0404691113211848, -0.008872368197677635, 0.0116933627886483, -0.09874720009960319, -0.03877084404075001, 0.05002466574186254, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -10.03537283004762, -31.0463181244779, 1.779031435921747, 0.5805779942073915, -0.1697490764077751, -0.01914980853094367, -0.2211539569318829, -0.4216165170128795, -0.6480115775079677, -0.4142538428904219, 0.06564004090328103, -0.4941714579440745, 1.034278660942381, -0.2047718684985376, -0.01268161547420685, 0.517525878890536, -0.1043791000267504, -0.3647396058345162, 0.2111603242370048, -0.9972172123676774, -0.5115981269692284, 0.4959144934872069, 0.04212237503456763, -0.0259339732866725, -0.1242882315804042, -0.4810924645313537, -0.02365156513499566, 0.2627756243130801, -0.5274144495229729, 0.2708662778382719, 0.8165087143124619, -0.1013704061972073, 0.2726522755404825, 0.3850625905291744, -0.5191444285929395, 0.1772802840204757, 0.3334115942202089, 0.1315431110247013, -0.02250684048613707, -0.169616886212142, -0.3125742719244352, 0.04507962853556727, 0.01003848565633635, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.534564874870957, -24.59524017605734, 3.803193767088361, 0.1204388472709394, 0.5761719808045163, -0.1117681261275701, -0.2329370688709992, -0.08102002281001033, 0.1428619986726483, 0.104842791253757, -0.1181730570197248, 0.4589008851142075, -0.1080200483321708, 0.1900878438866454, 0.1999148634974392, -0.1482677353246511, -0.1560253005429775, -0.148698943892873, -0.5439804195128841, -0.4178164555772285, 0.1013788135893234, -0.2170885424796042, -0.02176885122945166, 0.2064156754855712, -0.3206810843761114, -0.04373791424112124, 0.2504839663865664, -0.28090563960889, 0.1385536322071997, -0.08959168523700539, -0.05811267349918002, 0.005219295271455209, -0.0006095068025606334, 0.05188819365042641, 0.05557911001260952, 0.07279423774972828, 0.07138061600398075, -0.03756847423989253, 0.02816926549231814, -0.07480288912090098, -0.006340103202835009, 0.0003644593817090534, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.032984611804681, -27.23593121948949, 10.91195300159838, -0.1955025467061237, -0.3108776615407506, -0.3861125933123738, -0.2335216115611025, -0.9691736965590945, -0.2809799173614512, -0.2879486799582545, 0.2288415268907392, -0.06960881368743468, -0.3354356497684607, -0.3414928741679384, -0.060828537807209, -0.301089195863019, 0.200552261417137, 0.1352398329475678, 0.3340834458703997, 0.07377669861905928, 0.2564987850409935, 0.3238811050529972, -0.7225355496632641, 0.2551257047021489, 0.1771742636853869, 0.06594998613853977, 0.07018408521301191, -0.05587922004114503, 0.9700092972137774, -0.2579283194903866, 0.6519487404137869, 0.5508375252467951, -0.6490234945917377, 0.1447953357975773, 0.2164634615540051, 0.3169200204043436, -0.03463118539302083, -0.151318881732286, -0.2345691835471254, -0.01993158819697678, -0.05040377327442637, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11.4540626253999, -20.77158386493728, 0.8646709228308843, 0.1362724391608822, 0.1719025418456963, -0.2551996740096885, -0.03511714486680503, 0.1843273888070675, 0.1712704953498521, -0.08238211456267275, -0.0278396535204387, 0.09282985085557675, 0.2532178349906294, 0.08197119062309449, 0.0199260300618629, 0.2535665679716856, -0.1152352645199304, -0.1736314115581865, 0.01698268605977707, 0.04658947833988694, -0.1857939567479137, 0.01460595684305768, -0.05830186068372888, 0.03887623804842972, 0.1233901766950485, -0.03958735173141364, 0.07325984287647014, 0.01640653011899173, 0.1584691045459283, -0.2308825423077231, -0.1894450711707396, 0.01097836857891495, 0.04360019357535277, 0.005697416476426774, -0.2056452089585314, 0.04960126421902575, -0.09143466075759629, -0.0152240285154079, 0.07997148646231036, 0.03173856999389955, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.214993452284615, -24.05350963927314, 2.935180686952885, 0.009367576430711424, 0.02897145608792666, 1.037258110070721, 0.1361330302043889, 0.267403438521004, 0.2041268631368911, 0.009677886298345676, 0.4513281035866327, 0.4879183299083247, -0.04366463541582642, 0.1415327697743105, -0.2267638854965378, -0.4997584611277828, -0.6976848080687116, -0.02518594676737141, -0.2588366599642389, -0.2416744762736605, 0.7221885872238599, -0.5539147131834354, -0.1134910123367641, 0.2737448220857051, -0.2927880039131713, 0.2057867576341399, -0.79800324914354, 0.1932584636177841, -0.5035224041067244, -0.5321735749435307, 0.5437275964446536, -0.1399374304829474, -0.07507775144608267, -0.2918402578666227, 0.09771036738785385, 0.1114599184651533, 0.1302712088256483, 0.0519407976536088, 0.06216196476169271, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.947682961146469, -25.70508238397117, -11.46177925662307, -0.3724367020684367, -0.0346498317775926, 0.06864375351559394, 0.07554361694203379, -0.367323229127421, 0.09593202864671034, 0.1377534867847666, 0.1184603670917067, -0.02650248054294359, 0.2092301771249943, -0.009852203175540166, 0.1288173411245062, -0.01556723710218602, -0.2725343716448551, -0.04882125871058738, -0.1164191596901248, -0.01306504969938954, -0.09972247608276598, -0.05244353803868229, 0.08508888288435545, 0.01494712152255306, 0.06488803226510469, -0.1140190552259744, 0.1236269753074166, -0.2360969288917616, -0.1066473633353232, 0.1264867082185493, -0.02483266501799899, -0.04114542787579798, -0.1266313954297545, 0.03448373932480522, -0.05195144188753792, 0.03249420081315806, 0.03713923614715957, 0.01317281111328615, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -11.69631299718309, -22.48619259551776, 0.4736607761650089, 0.3364440611411286, 0.001896101447363962, -0.01839142547031177, 0.03683300808928491, 0.04804330923877288, 0.163622475873788, 0.1554000460872887, -0.08113035605009281, 0.0394436822356209, -0.1518190651150113, -0.2391233604051897, -0.1848160862235859, 0.005028918748719988, -0.1738801952717139, -0.1389518165707553, 0.2440059223399533, -0.1912611405349515, -0.1278732887547087, 0.03594552209482393, -0.1239443437214213, 0.07601115720720845, -0.2413170999853679, 0.01830028011033026, -0.1786719142755088, -0.05040746869497416, 0.1855068663687703, -0.01469530719590392, -0.03565818225935036, -0.006393469065442842, -0.02927051217417908, 0.04981431028590561, 0.01896848487153613, -0.02389638792932929, 0.001671298450249839, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7907072650120487, -24.90261765607406, -3.336934808793186, -0.1100561385510806, 0.03806580362882676, -0.9795899124384002, 0.2113562476336533, 0.1210755170917097, -0.5709907672936722, 0.06148724086826907, 0.4281734290575387, -0.1228023758602741, 1.217889711872614, 0.5772065011935688, -0.8854453190120086, -0.02188476051865783, 0.2939683523215479, -0.3364845598685323, 0.4389370528196214, 0.2175645153244334, 0.1003089157346634, 0.5938129566146761, -0.2639007244911475, -0.4694860419564821, 0.0619677643285282, -0.05717000630200545, -0.3202406910706038, 0.378107742758849, -0.14006136421472, -0.248450630677327, -0.1410998107329354, 0.0735235604182249, 0.006870838292283573, 0.1952510899320096, 0.0282675631387419, -0.003424908838937833, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.437730841654131, -33.27385476914327, -6.935734943236623, 0.2090812561111312, 0.3348393450135521, -0.223586923299236, -0.07352664648222718, 0.03785759488211347, -0.1513766386596058, -0.2099960883438794, 0.1017048240174961, 0.04182607962471709, 0.237579420640883, 0.2399067162829091, 0.07523955310772605, 0.05857405848698407, -0.05389473909058243, 0.2636593955046162, 0.1468245947741072, -0.1210583952104068, 0.1524669191535411, -0.214238636532872, -0.03816758506191603, -0.1354966639865573, 0.09316724617238126, -0.01615929313522045, 0.005900244511659499, 0.1042542689707338, 0.02949183866897195, 0.037267365131775, -0.07808591456574898, 0.03857619705636327, -0.07145363560926057, 0.002429628071270416, -0.01721018579426699, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.66333148382885, -14.4614219114703, -0.8464300600479908, 0.2514104375223278, -0.09861658442109786, 0.1691348097352446, 0.1896581102869329, -0.08087907706641626, 0.01174408327349146, -0.04072839225976889, -0.21084119330376, -0.2084820021746563, 0.06459499104581255, -0.07220761842989601, -0.08081244480389148, 0.2770967905223476, -0.1130641379249503, 0.01313709061334511, 0.1053117612678122, -0.08548227871695131, 0.04755230373305874, -0.239808392738221, 0.006594669706792055, -0.1160148635147146, -0.1546465218776207, 0.1797178820270592, -0.03514352886331645, -9.157443953328604e-05, -0.08036793482879778, 0.002475861135144963, 0.05097461589006569, 0.01013677531395254, 0.0105449596442005, 0.01367406076786437, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.019923386108676, -26.76235000723083, -5.231507339253204, 0.176832541192354, 0.3017249373834541, -0.1388443978394047, 0.2312643317132779, -0.04464652755082743, 0.07808084544420522, 0.4313216233613872, 0.3080530810133845, -0.3090015643058375, 0.2364897664214366, 0.06604367687341839, -0.1876613180395572, 0.3146210580156822, 0.1784726037504162, -0.02271540068963666, 0.2342699465461129, -0.1343387528471265, 0.06625828689355771, -0.003273887803178955, 0.1450943895905023, 0.00620258099433276, -0.09380102559767173, 0.01798478433460103, -0.07862806231355808, 0.05631636830032596, -0.0196969615930718, 0.04436104332404119, 0.05354400105458426, -0.02354762170847734, -0.02514305223947428, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.177075859399771, -33.39258164773348, 1.63759177075579, -0.06342533195251419, 0.1411980486906961, -0.1464775848775387, -0.04431760714090424, 0.01154744252601158, 0.1026506579361863, -0.02088412824928649, -0.02902179807556261, 0.01304836720502356, -0.07271697524786641, -0.07325213106164481, 0.03704096648459854, -0.05922855466144863, -0.06262650371609046, -0.03182071956590917, 0.009080904737058308, 0.1354599956171088, -0.012606916831903, 0.03239503119872632, 0.1409587222872537, -0.06002807561785677, 0.04627926839441229, 0.02573135330017627, 0.004605365395089219, -0.08725168654474108, 0.002587419133345108, -0.05185185645936881, -0.005849547735873801, -0.009771554197080978, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2.064718113513358, -13.12988850942804, -3.438372519392976, 0.1264586180050162, 0.004883996372652178, -0.04481988503927746, 0.09576485030352094, -0.3955235936343703, -0.2087500394183668, 0.3073328906227044, 0.02068102374422703, -0.1083588810681304, 0.1758168533371591, -0.1756277739685251, -0.07450374022378869, -0.01630094419723318, -0.1914647508380139, 0.08895278495397248, 0.1403814278690517, -0.03489253346297209, 0.01598763641739303, 0.1131830343890914, -0.06699742805657724, 0.00240472634967058, 0.05514166821797546, 0.03884124270426484, -0.01101385248527006, 0.01954817931909242, -0.03459346077345329, -0.01274466093412686, -0.003543141293631806, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.395368558938009, -27.6115795496259, 6.02328924849129, -0.0217949039676702, 0.01713458866911107, 0.1204807990971129, -0.1903985203838578, -0.245494995765684, -0.01567899867737631, -0.0483287391034937, -0.060209365295053, -0.00658859715813279, -0.1748730515278048, -0.1172896416076897, 0.002885900683208647, -0.2725962934388483, 0.1896424602622011, 0.2547718270544993, 0.08930762271234099, -0.05000517893940885, 0.198774168883364, -0.1836169107571341, -0.001441577306058042, 0.02027315191018264, 0.07922510191796643, -0.01081020778347853, -0.05485129878921055, -0.003504265936056936, -0.01741627502898858, -0.004300648475577595, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.881439123068173, -31.86267091719867, 0.3170578648639695, 0.4687236230510464, 0.02662683343011025, -0.3302193472780357, -0.477346463679984, -0.0517454341931882, -0.3336060762108314, 0.09422553730446168, 0.04946779745885752, -0.5432213903814268, -0.2492264416620409, 0.1732279550240386, -0.09454901437534985, 0.243084678749923, 0.184313316080481, 0.110429054715389, -0.03650964419849936, 0.09749969511293206, -0.1326505036247279, 0.05009598527464214, 0.1082240240233409, -0.1489278834552438, -0.08096188906466491, -0.0850388793794887, -0.1125032485965546, 0.05122382376743441, 0.05527189635692931, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7431797386269411, -14.65117500009382, 5.823447882655948, -0.1881157144876831, -0.3008729186775366, -0.2240680575846533, 0.02294923203244657, -0.1328373063914675, 0.01835629292837719, 0.1359000574454446, -0.3469510665265196, -0.1308216630102339, -0.03496464106937285, -0.2440104038689523, 0.04193512042581821, -0.1366336497635793, 0.03231520148337453, -0.1084198723292215, -0.06739647043502352, 0.08740658296680984, -0.05956248732431352, 0.05155443563206404, -0.06543491661245913, 0.06950710262417095, -0.02430554263388206, 0.003834848628751442, 0.03034298318482847, 0.03421651369935733, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.826424710849555, -27.75807925717017, 6.49845414271845, 0.2088222638768245, 0.2567583755247717, 0.1680006630260083, 0.07113722086014379, -0.03228298686790457, -0.1031612528617338, 0.1843360031254731, 0.07332196070209686, -0.01774216015656859, 0.2986364342557484, -0.00134569499401013, 0.05460048981943994, -0.02322575505419388, 0.08264206029436941, 0.08014218496669946, 0.02559186811441928, 0.06346651700418222, -0.0449661723444516, 0.02381879758386176, -0.08682020285221281, 0.08025959489260269, -0.01003292155179478, -0.02340991530415569, -0.02962714897774685, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6.435188878061354, -30.23792586523732, 0.4023394954316882, 0.1442634156119251, -0.1020481640743369, 0.2616580251348765, -0.1059180761079543, -0.08743876827521066, 0.2785769450080205, 0.04428252801918474, 0.0202832410441884, 0.04189636473520755, -0.1103209617823084, 0.08801265177191683, -0.06151324254000396, 0.01355502488640757, 0.1011883046619023, 0.01940829963761287, -0.02376145032104872, -0.04253776187455549, 0.1015931898787959, 0.004439366426774084, 0.02720943797022718, 0.03068092663135336, -0.02169503454248668, -0.04815156165797598, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.23475181130263, -25.85002095399512, -9.61072734631551, -0.2587337302523749, -0.2671090327042298, -0.1373193461266922, -0.01686645319925775, 0.1214524395626546, 0.04787321250564932, -0.0102808929635468, -0.1079687161735285, -0.1204158425469933, -0.01370170730210608, 0.03896661385808254, 0.02006408734658718, -0.01957557336743487, 0.02048657847215082, 0.03186441907330201, 0.01437600500970395, -0.07256365762710008, -0.04268726613146586, -0.004291692030780559, -0.02959742701650543, 0.009784658017416398, -0.001361411062570107, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.668539275335888, -23.18029209894821, -7.104549227457261, 0.009494835170991586, -0.2155484926554607, -0.05117708716304314, 0.09558257063666828, -0.006204864175755139, -0.0535983098279376, -0.1721078109347795, -0.1292907195966384, 0.04463480683436428, 0.03962458796875007, -0.03394918991811541, 0.0360179426993984, -0.05098248960386708, 0.05421613324558673, 0.006517343947994034, -0.02849867886559621, -0.07880371848866945, 0.02642259523254391, -0.03587610810807455, -0.0153740561986479, -0.01461543749433446, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.000678311567365, -23.41161932249744, 0.1115405160634775, -0.07148023127921439, -0.03829631039398255, 0.4350529946111771, 0.1273341721442011, -0.03309653396004558, 0.07269741094613814, -0.2517627759593927, -0.0916540014643315, -0.09513082346238068, 0.02936404485630485, -0.03887824155586548, 0.03259923092993516, 0.01480224718798229, -0.06089794884744876, 0.04533354466816, -0.04401696277253729, 0.08384757422274537, 0.03447473565697338, -0.03655777066458333, -0.04286881746219928, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.1997455187845329, -23.67906930857953, 3.298493240502194, -0.1847467985210671, 0.1243176781235989, -0.02243375998252476, -0.0004203531178173071, -0.1373119846655697, -0.07119941044543882, 0.0598855239376691, 0.0365497555952217, 0.09940083973287311, 0.02170561702085787, 0.02523145542278863, 0.01398860677045751, -0.02099249665794002, -0.08042834487614063, -0.04514933257707622, 0.0210691994836113, -0.01304565123088667, 0.003317809080060446, 0.01880126864882835, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.363427418619814, -17.41903576009931, 9.186568349711468, 0.1111029283919205, 0.08777631782411636, -0.0106122045071789, 0.1144225997334068, -0.02466841586746403, 0.02750112055321526, -0.05524437334870362, 0.04541263818821106, 0.04741842472464215, 0.03068743352629459, -0.03255656589538247, -0.03729968912772544, 0.01062121564506963, -0.008575892547858845, 0.02301960098527405, 0.01221098646015711, -0.007828736372639752, -0.02174734678713348, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9.23220561660408, -31.51893707701785, 0.629104414809966, -0.002885901152494686, -0.04654352249775812, 0.05655136143073162, 0.04644981489440897, 0.04886269814398012, 0.01421146833364892, -0.02220699538623673, 0.05311321315234985, -0.001358424574760307, 0.00136891734406154, -0.01810167863750104, 0.05846985549778336, 0.02464847599577873, 5.045357884432963e-05, 0.02313650001543124, -0.01897592900555872, -0.01000566869781843, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.6213531321316156, -24.30034243436851, -1.105212323117883, 0.1225585085553164, -0.2970472162797997, -0.1131121492749726, 0.005524192917051245, -0.005016083344128715, -0.05408343623542385, -0.02819561803866161, 0.009006334912992457, -0.02024545484485562, 0.03816393987230592, -0.0007047877611201743, 0.04901678014439114, -0.05163410574806857, -0.03130055103817821, 0.03533492988517593, 0.01195601678346641, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.097158496205909, -16.73710946124244, -9.426989245602673, -0.06261182983602319, -0.1059035148370443, 0.05076346286898199, 0.003678172466163399, -0.0454660155043527, 0.02462054291284395, -0.02110890517636086, 0.008241203910568698, 0.02390589384329424, 0.01198364473687612, -0.02957542631061049, 0.002236629456648171, -0.02809381563903465, 0.001689229093064753, -0.007600764285513168, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.412003466484951, -31.65984264675678, -0.1254812244514544, -0.09114636575550933, -0.0366463804259801, -0.03322040198025862, -0.01209970867041294, -0.01021849930537397, 0.02256075215944923, 0.01825223707293363, 0.003993042619294536, -0.008507286595193135, -0.02427249385479496, 0.03381794787948238, -0.02914842372731508, 0.007082873675038417, -0.006655560097220788, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.27548187849782, -16.01246939790233, 5.644600469890476, -0.04244915968443123, -0.0371436610514518, 0.0530212677895391, 0.008626194479801664, -0.02358451461610269, 0.007412437106157236, -0.04628615223361372, 0.0826909370927158, -0.01312239177378535, 0.05019812567992653, 0.05643602731883488, -0.03169977188973144, -0.02409525389114796, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.831745814038495, -20.41725582289098, -1.583013759260222, -0.02098081085371714, -0.03289988933600374, -0.006011309758863401, 0.03459650459981792, 0.01348477813223562, -0.02336540423557105, -0.003969872715414671, -0.05998169351462899, 0.05263821645435009, -0.0144354245014559, -0.005674777729486418, -0.03142277004383006, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.562800616132969, -36.13433050173559, 0.2585654510438173, -0.02913169721040965, 0.002592481347938085, 0.004329834978588065, 0.06325089767860387, 0.01951445115945309, -0.03070674283592272, -0.02183384192678349, 0.009849968434859515, -0.02891816499635688, 0.002667591177598971, -0.02361460878909238, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2286035973327459, -15.02261004686781, 5.184122379409034, -0.0264079721355016, -0.007786216137000334, -0.008663526410932022, -0.005309693290799501, -0.006680538291880966, 0.001397532516833339, -0.01528554327177548, -0.01182046150296639, 0.005955666147884051, 0.003523919303238692, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.214570242697843, -21.4621144179193, -1.555874989179182, -0.001447535808513384, 0.03124103143611023, 0.01560612912433155, 0.01254222023040845, -0.0006565581414721336, -0.005837445535672976, 0.003328905310192099, -0.003109407401498421, -0.001359993487917328, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.575215080762542, -36.12196181704586, -0.009581763987488548, 0.02181190823948241, 0.004249343259232833, 0.008866640947567769, -0.008827428692463307, 0.0111903702615688, -0.008259743446844802, 0.005994103918828306, 0.02884522108807095, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.02332478841374811, -20.31760288431249, 5.902175782312199, 0.01411291075117598, -0.0401626029282366, -0.04333034577745157, 0.006563645334078613, -0.02686027801335236, 1.82653938945055e-05, -0.009451944888619017, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.843446424852287, -17.22694391469142, 4.615021811975704, 0.03880112444568462, 0.01156878860697344, -0.02011735633875036, 0.007254465185871957, 0.006976302646061595, 0.01061407563995378, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4.636349195088934, -35.03142250661902, 0.03540637402307944, 0.006380325215592348, -0.01715112535803765, -0.005381045082520479, -0.02796704437114206, -0.01837431744975316, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03325953074641371, -17.29072432858197, 5.995094557622266, -0.004356649575832386, 0.01324648360020382, -0.002576747161993423, -0.0164552533090047, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5.976772821535572, -18.99788030681546, 0.01396461545715264, -0.007601183590626498, 0.005853929901760483, 0.0201199907208218, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.002983340164191267, -20.0342372815637, -5.741448414658583, -0.01215113512395332, -0.00662723431795657, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.752040939724589, -16.25515722920224, -0.00713497387655803, -0.004958024634924642, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0004916632598946193, -12.09805746213948, 0.000198676020167099, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0001765653829615133, -12.09823117436413, + }, + evWant: []complex128{ + -0.2513649571095319 + 26.5196181977274i, + -0.2513649571095319 - 26.5196181977274i, + -0.3323427794627154 + 14.12147023570828i, + -0.3323427794627154 - 14.12147023570828i, + -0.3885760957072044 + 34.01549575140551i, + -0.3885760957072044 - 34.01549575140551i, + -0.4938394681672298 + 19.28755724237434i, + -0.4938394681672298 - 19.28755724237434i, + -0.5354723308245726 + 44.07811563049843i, + -0.5354723308245726 - 44.07811563049843i, + -0.8831210193505878 + 40.64617136580856i, + -0.8831210193505878 - 40.64617136580856i, + -1.063691744877652 + 54.90113796777709i, + -1.063691744877652 - 54.90113796777709i, + -1.270999250073418 + 55.92169849615225i, + -1.270999250073418 - 55.92169849615225i, + -1.641962795944021 + 124.0727533257146i, + -1.641962795944021 - 124.0727533257146i, + -1.866212165366329 + 67.51198073484791i, + -1.866212165366329 - 67.51198073484791i, + -2.66562659457705 + 102.4818444744388i, + -2.66562659457705 - 102.4818444744388i, + -2.677285588970379 + 109.3976583973073i, + -2.677285588970379 - 109.3976583973073i, + -3.592328373007462 + 116.2450441105874i, + -3.592328373007462 - 116.2450441105874i, + -3.658587455178502 + 105.6223525143237i, + -3.658587455178502 - 105.6223525143237i, + -3.738335632746128 + 95.41374995650723i, + -3.738335632746128 - 95.41374995650723i, + -4.05659124602542 + 85.08673687146815i, + -4.05659124602542 - 85.08673687146815i, + -11.7967401639067 + 0.03421683561959875i, + -11.7967401639067 - 0.03421683561959875i, + -12.06591356324058 + 0.03010079020722811i, + -12.06591356324058 - 0.03010079020722811i, + -12.08354870692898, + -12.09435136773809 + 0.0007639916648241464i, + -12.09435136773809 - 0.0007639916648241464i, + -12.09785209014901 + 0.02991559300476182i, + -12.09785209014901 - 0.02991559300476182i, + -12.09806212746318, + -12.09850417485291, + -12.09864274565634, + -12.10160612637007 + 0.004700099158908263i, + -12.10160612637007 - 0.004700099158908263i, + -12.16873692768957 + 0.02446545858852495i, + -12.16873692768957 - 0.02446545858852495i, + -12.23495190373921 + 0.1453184367031505i, + -12.23495190373921 - 0.1453184367031505i, + -13.54778407074696 + 141.1839768257274i, + -13.54778407074696 - 141.1839768257274i, + -15.38790969472481 + 114.0584849752244i, + -15.38790969472481 - 114.0584849752244i, + -23.60369882806601 + 0.2464158068361128i, + -23.60369882806601 - 0.2464158068361128i, + -24.04314341198735 + 0.3315626206724418i, + -24.04314341198735 - 0.3315626206724418i, + -24.12753399862331 + 0.1634093642552133i, + -24.12753399862331 - 0.1634093642552133i, + -24.18103712080912, + -24.18908889661277, + -24.19357072143492, + -24.19567681157636, + -24.20660003986661, + -24.228086198612 + 0.0220672004906673i, + -24.228086198612 - 0.0220672004906673i, + -24.30677145425284 + 0.1813999700804981i, + -24.30677145425284 - 0.1813999700804981i, + -25.23862373866253 + 0.8733279005402655i, + -25.23862373866253 - 0.8733279005402655i, + -29.42427841595277 + 1.666886570068163i, + -29.42427841595277 - 1.666886570068163i, + -33.94959271558832, + -35.51958918286584, + -36.20666045708104 + 0.1660921702962803i, + -36.20666045708104 - 0.1660921702962803i, + -36.25710351845593 + 0.01052251476620707i, + -36.25710351845593 - 0.01052251476620707i, + -36.28714605125749, + -36.29431583135849, + -36.29711199023137, + -36.31304183793699, + -36.32232768169418, + -36.37871120972082 + 0.1557647672076243i, + -36.37871120972082 - 0.1557647672076243i, + -36.47694233727385 + 0.3738707259908102i, + -36.47694233727385 - 0.3738707259908102i, + -36.66483183150206, + -37.75937189360096, + }, + }, + { + // TUB100 matrix from MatrixMarket, balanced and factorized into + // upper Hessenberg form in Octave, and embedded into a 104×104 + // diagonal matrix to test with ilo != 0 and ihi != n-1. + // Eigenvalues computed by eig function in Octave. + // Dhseqr considers this matrix big (n > 75). + n: 104, + ilo: 2, + ihi: 101, + tol: 1e-10, + h: []float64{ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -1063.761, -960.3970563202379, -0.0006079108185996773, -0.009201940691316367, 0.002442836240270196, 0.01550988534551903, -0.005482455008401117, -0.02216870959395947, 0.009747347615349792, 0.02941831540681939, -0.01530136178573213, -0.03750794345694437, 0.02225359194453896, 0.046705617938318, -0.0307619752542162, -0.05730825585675074, 0.04103856105936231, 0.06965250072575992, -0.05335624663776811, -0.08412633500439758, 0.06805680196063389, 0.1011811513254484, -0.08555957035531082, -0.1213434441393789, 0.106369291926541, 0.1452243676184516, -0.1310809449650698, 0.1735240650736495, 0.1603769717276725, 0.2070245946752049, -0.195009056622052, 0.2465616197175694, 0.2357520481176992, 0.2929587463757468, -0.2833105069304027, 0.3469005841220431, 0.3381503031304328, 0.4087132445918312, -0.4002236126054999, 0.4780213717840138, 0.4685650013761221, 0.5532750093152425, -0.5407842250274101, 0.6312148133425258, 0.6125866029330725, 0.7064838330293224, -0.6776224584955323, 0.7717672671130079, 0.728093737707456, 0.4477228711606641, -1.832801684441419, 1.950252997191289, 0.804390452586547, 0.4832557718849113, 0.3060066166102118, 0.2756451553030591, 0.1719798268352208, 0.1844690914416081, 0.1028522851629666, 0.1338501876768783, 0.05922545829023376, 0.1041210893998114, 0.0294781768570502, 0.08738772703908808, 0.008665658061761334, 0.07957418017688388, -0.005841802748350547, 0.07832978350913038, -0.01561691241238414, 0.08229737118429636, -0.02164114160477788, 0.09076446627208183, -0.02452178964005379, -0.1034535010713481, 0.02461324557496748, 0.1203839900069163, -0.02209524508102444, 0.1417838483570761, -0.01702626635186736, 0.1680394493064578, 0.009377435518891378, -0.1996795871970759, -0.0009558646643977288, 0.2373933824702814, -0.01416583764558031, 0.2820880046959302, 0.03057782300299389, -0.3349961435755344, 0.05073634798692103, -0.3978562481735693, -0.0755607412701291, -0.4732063781751494, 0.1066126139010085, -0.5648764073871733, 0.1465759215609417, 0.67885880956596, 0.2001993093624898, -0.8249735752515708, 0.2762967421832379, -7.383366696690373, 0, 0, + 0, 0, -504.7000323579025, -960.7839130908893, 455.6939154064305, -0.0005890239049151091, 0.01222453307167895, 0.002380254112046573, -0.0183767018575125, -0.005347164384529943, 0.02487432959226112, 0.009507444863507727, -0.03195485414878263, -0.0149219770912947, 0.03986517031337426, 0.02169664773526838, -0.04887103316029169, -0.02998576954964119, 0.05926702273427436, 0.03999696952048423, -0.07138712464416012, -0.05199744338214077, 0.08561585141999975, 0.06632116378894419, -0.1023995009673016, -0.08337613594660015, 0.1222563158317329, 0.1036500341236005, -0.145783656379474, 0.1277114126111218, 0.173658096672846, 0.1562008437363875, -0.2066214365478053, 0.1898032066448404, 0.2454413266872829, 0.2291867817273585, -0.290828708487696, 0.2748879884412016, 0.343286767980235, 0.327114242278849, -0.4028620578438859, 0.3854382883926989, 0.4687761898935385, 0.4483798648521518, -0.5389586517254393, 0.5129393074648648, 0.6095951621601606, 0.5742741750224843, -0.6749584326212456, 0.6258664262549096, 0.7279030750048989, 0.361160520701244, -1.817820120247178, 1.493677993805868, 0.9093218408940651, 0.3437577565805193, 0.362630116371123, 0.182491216989941, 0.221714417427429, 0.1064242506044702, 0.1554403491948274, 0.05893517713417926, 0.1191987572531298, 0.02593630450949156, 0.09940153443435777, 0.001987949044964486, 0.0900967012871452, -0.01567758628187121, 0.08812023104053984, -0.02871634215129631, 0.09168600701701864, -0.03819855166921124, 0.09983277639781361, -0.04483241285443643, 0.112135778661831, 0.04908165568011769, -0.1285288605462619, -0.05123906116349945, 0.1491912175066926, -0.05147890107583802, 0.1744806002258908, -0.04989507359069757, -0.2049040909139878, 0.04652399206028981, -0.2411228487302952, -0.04134974220480257, -0.2839940475275046, -0.03428683940013912, 0.3346573639346669, 0.02513376678028306, 0.3946840836316033, 0.01348469011538719, -0.466320753537143, -0.00142779450121434, 0.5528931223683594, -0.0210105793668851, 0.6595061978534259, 0.04783831497380739, 0.7943401758885881, -0.08674091416897045, 7.282263793289921, 1.964402124200457, 0, 0, + 0, 0, 0, 504.7001065567226, -960.8071533894852, -455.6899665187256, -0.0006381542544069418, -0.01696123848664222, 0.002571421839873352, 0.02356372357492877, -0.005765057328779014, -0.03054576659236009, 0.01023675166561691, 0.03816637411322649, -0.01605159633648196, -0.04669530536153424, 0.02332395960802052, 0.05642332124514469, -0.03222102273610906, -0.06767293164234266, 0.04296780496196387, 0.08080966049331523, -0.05585344634069236, -0.09625362412257953, 0.07123822293842015, 0.1144906642960898, -0.08955981060276022, -0.1360815254382584, 0.1113369911164654, -0.1616662801387938, -0.1371665625346616, -0.1919585350680096, 0.1677064944291291, -0.2277205865868329, -0.2036342514104135, -0.2697050947227386, 0.2455629056115962, -0.3185418058062836, -0.2938904117765113, -0.3745411973588626, 0.3485540671441012, -0.4373871729832214, -0.4086704182323145, -0.5057124011628437, 0.4720841567744535, -0.5766169045256523, -0.5349437472430429, -0.6453152755169759, 0.5915742979267851, -0.705252589538002, -0.6350313138183948, -0.4095510871717013, 1.601644767644169, -1.801430257336091, -0.6783540858316911, -0.4521876448242478, -0.254377814677483, -0.2609137525907964, -0.1390187634586346, -0.1780644458672355, -0.07811098364662258, -0.1332228921784263, -0.03844450844393983, -0.1080065082071247, -0.01031758532230231, -0.09498853030853376, 0.01036100507490249, -0.09032395086444481, 0.02576859065961766, -0.09180684083159034, 0.03723131440198095, -0.09818648544931335, 0.04561209756712017, -0.1088355401035232, 0.05148345180798951, 0.1235465165704314, -0.05522144380747635, -0.1423972092039827, 0.05706613305793608, -0.1656652164809836, 0.0571654881872712, -0.1937812736972878, -0.05560491141385822, 0.2273160612316538, -0.05242306351060358, -0.2670005088314752, -0.04760687919206397, -0.3137829156332985, 0.04106438412981419, 0.3689347453356511, 0.03256097086263596, 0.4342239659065471, -0.02160937448771497, 0.5121963228132351, 0.007270440886606282, 0.6066421962514198, -0.01221319300610655, -0.7234154012137514, -0.04013586770219741, 7.505393492740379, 2.207569919375577, -2.286495948142137, 0, 0, + 0, 0, 0, 0, -504.7004946877645, -960.8313859426444, 455.6868630884425, -0.0004564668894400728, 0.01953047220881932, 0.002110185308335535, -0.02552492771185354, -0.004910008054476974, 0.03185603230051105, 0.008867203935794236, -0.03876493903116766, -0.0140372793617222, 0.04650258449956125, 0.02052143233325077, -0.05533916645715601, -0.02846939294478852, 0.06557394899483331, 0.03808355296447862, -0.07754536439486578, -0.04962400720722794, 0.09164110934556451, 0.06341371783532462, -0.1083072609262454, -0.07984241792495486, 0.1280548395158984, -0.09936692302911229, -0.1514604665622404, -0.1225031219103813, 0.1791553196119899, -0.1498024404391789, -0.2117929820588376, -0.181800940883612, 0.2499814001970585, -0.2189235487704594, -0.2941578702525302, -0.2613208334101781, 0.3443825148816139, -0.3086165449914435, -0.4000320253108334, -0.3595628891688978, 0.4594100673703709, -0.4116578643958037, -0.519368340488319, -0.4608838085460648, 0.5751583010135386, -0.5018561564823436, -0.6208288964715706, -0.2890646136834312, 1.547039886853192, -1.173755403489903, -0.7985207315322997, -0.2625825083083085, -0.321674668942854, -0.1352159819750655, -0.1999732725283456, -0.07366734029347159, -0.1440615953055945, -0.0338692953389332, -0.1147504606082463, -0.005029712242208511, -0.1000175433858401, 0.01695421717090311, -0.09456233266164106, 0.03415869939464086, -0.09556433616678824, 0.04784697925863496, -0.101446550453596, 0.05887259823103022, -0.1113844111571908, 0.06784319765312669, -0.1250437127185277, -0.07520036620749675, 0.1424161499432856, 0.08126890147440424, -0.1637146453439622, 0.08629375258215478, -0.189312804562382, 0.09046906112313131, 0.2197194565251569, -0.09395994411067805, 0.2555854707181692, 0.09691288686658349, 0.2977431307518454, 0.09945154948260918, -0.3472856237053809, -0.1016514559138057, -0.4057014604005721, -0.1034872918659082, 0.475092530300298, -0.1047384672449806, -0.5585328441816623, -0.1048045105961936, -0.6606855376279177, 0.1023541847811403, -7.645111917964669, -2.444190547643892, 3.259474730743878, -1.113400990501543, 0, 0, + 0, 0, 0, 0, 0, 504.7005483880675, -960.8563426765877, -455.6810385506663, -0.0006211890719464708, -0.02717449361052982, 0.002624545711740859, 0.03409357098285602, -0.005942159106883158, -0.04143715413018739, 0.01059135423887447, 0.04948858776950704, -0.0166413313054562, -0.05854418379382578, 0.0242148610679564, 0.06892421088657538, -0.03349146754772453, -0.0809841818387797, 0.04471193925388908, 0.09512623948475284, -0.05818359115254906, -0.1118100512572915, 0.07428496523273895, 0.1315618312735884, -0.09346828354041023, 0.1549790152282817, 0.1162558426750438, 0.1827256545244234, -0.1432240256832661, 0.2155105496963288, 0.1749650364632709, 0.254035038834301, -0.212010638405861, 0.2988909563929731, 0.2546958843850197, 0.3503831721602568, -0.3029377534844611, 0.4082512041088586, 0.3559113648605111, 0.471283605276577, -0.411645725224325, 0.5368790186329719, 0.4666463388955495, 0.6007202940611962, -0.5157903324539884, 0.6568675698020393, 0.5528415071271306, 0.3819646735423662, -1.398313345247025, 1.702130138980118, 0.5594893184855516, 0.4345731607149444, 0.2047273101100171, 0.2544540474780775, 0.1063741954770327, 0.1778805766776483, 0.05255231548952451, 0.137900569051342, 0.01589144268877343, 0.1168704015342846, -0.01147530402843068, 0.1075993573348887, -0.03281602394973369, 0.1063490908368691, -0.04987312975903418, 0.1109852985003045, -0.06374396058252166, 0.1203212709282059, -0.07519208505179932, 0.1337915946504525, -0.08477768059074928, -0.1512472309045833, 0.09292245189830053, 0.1728188948893017, -0.09995295179709891, 0.1988310587279109, -0.1061338258071349, 0.2297560668874317, 0.1116956612897333, -0.2662028365209533, 0.1168534044651449, 0.3089378582466848, 0.1218148638037771, 0.3589424141807773, -0.1267685950073432, -0.417514018459675, -0.1318530493084198, -0.4864325194506035, 0.1370935903164596, -0.5682256141066142, -0.1422822434012505, -0.666604844323565, -0.1467513256218947, 7.839832839255147, -2.591992660256728, 3.08252939024389, -1.472235565518307, 1.200611269528463, 0, 0, + 0, 0, 0, 0, 0, 0, -504.7015918274936, -960.8824172487933, 455.6786628322481, -0.0001386040108547678, 0.02825899575001721, 0.00148000990419925, -0.03396816329492456, -0.003913391729580158, 0.03999719012865367, 0.007442680878789934, -0.04659090322133554, -0.0121162968680667, 0.05400401596298283, 0.01802786748313866, -0.06251037884950617, -0.02531818062112227, 0.07241227284910066, 0.03417801432480141, -0.0840495440103118, -0.04485119411434383, 0.09780784101480898, 0.05763670862206309, -0.1141246897988619, 0.07288798740446953, 0.1334907230535002, 0.09100549877450563, -0.1564413552584702, 0.1124168465460749, 0.1835312438634551, 0.1375347555217266, -0.2152794341013849, 0.1666789233629258, 0.2520679325404323, 0.1999435400148238, -0.2939734797154126, 0.2369931492869313, 0.3405172515888476, 0.2767850762901711, -0.390345045347925, 0.3172634202969561, 0.4409132592457857, 0.3551552329611432, -0.4883580204443008, 0.3861049626417496, 0.5278024954606876, 0.221653617736939, -1.310709133012781, 0.8704550092422116, 0.7079030635461785, 0.1843303003648327, 0.289142189894577, 0.0890031466634482, 0.183755046796533, 0.04093279509465775, 0.1369845466667406, 0.008027106857080303, 0.1140671851302532, -0.01733485053642101, 0.104231064513174, -0.03796088669959809, 0.1026821086919593, -0.05525696194664861, 0.1068620954451136, -0.07011029660696497, 0.115354075966287, -0.08317464933480107, 0.1274397517866654, -0.09497453954477812, 0.1428557674294213, 0.1059485191998991, -0.1616373931580192, -0.116473125434708, 0.184018627644066, -0.1268840153469689, 0.2103748991036934, -0.1374978332735491, -0.2412002758106563, 0.1486321821340762, -0.2771135831612571, -0.1606234825346388, -0.318894700017657, -0.173836022567292, 0.3675540114045308, 0.1886613027997724, 0.4244484685316806, 0.2055082541208365, -0.4914687718702396, 0.224768184994539, 0.571342364466508, 0.246749172743278, 7.942734281408671, -2.790996821413193, -3.416416824440133, 1.502698673759963, -2.74025012280437, 0.4374074524376139, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 504.7014268866499, -960.9091609078547, -455.6702009059838, -0.0004715858695197065, -0.03982840046737102, 0.00242224023844466, 0.04693804869973257, -0.005712413463266942, -0.05453060690126599, 0.01036142963375495, 0.06291484964449161, -0.0164440331698878, -0.07241520054585564, 0.02409153161862073, 0.08338313108173702, -0.03349426180113407, -0.09620848027332857, 0.04490493324477595, 0.1113301550654768, -0.0586415214773373, -0.1292450786759426, 0.07508828443695986, -0.150513154673022, -0.09469143119899404, -0.1757538991751067, 0.1179438613939318, -0.2056275754842778, -0.1453500537954308, -0.2407890904812533, 0.1773573065390127, -0.2817971004678554, -0.2142337181273538, -0.3289552292807281, 0.255870859960439, -0.3820621733814443, -0.3014962025572454, -0.4400643963200938, 0.34931588173307, -0.5006585522123436, -0.3961850233060456, -0.5599910362173445, 0.4375268333475068, -0.612726531008857, -0.4678122672345172, -0.3569120201451431, 1.18831598199679, -1.617583791352987, -0.4321697836882517, -0.4219085060089673, -0.1510420456331972, -0.25146678538168, -0.07059891849129137, -0.1807609333405698, -0.0240329511553917, -0.1456531311906457, 0.009769195529775603, -0.1290384618111746, 0.03669700570302369, -0.1238682627899927, 0.05912761689067447, -0.1264561589974369, 0.07833483431516959, -0.1347055607275304, 0.0951733797931347, -0.1474724563406544, 0.1103088335611947, -0.1642393157936116, 0.1242996284536155, 0.1849045503710836, -0.1376315559768252, -0.2096404850603622, 0.150739321415534, -0.2388041370692126, 0.1640310219820809, -0.2728910081209138, -0.1779123181778702, 0.3125232856726328, -0.1928113592711771, -0.3584705110456833, -0.2091969136508766, -0.4117030466307595, 0.2275912605111247, 0.4734858653437208, 0.2485748286117511, 0.5455291692123926, -0.272779071272836, 0.6302263498990262, 0.3008643534306304, 8.20707478604357, 2.932590880343228, 3.566301858755951, 1.591737361864661, -2.080954844450352, 1.063336818518452, -0.312693340165919, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -504.7034311398602, -960.9369925632403, 455.6692107057009, 0.0004356100354586218, 0.03860199096161918, 0.0003618838493967148, -0.04386380370370079, -0.002169347414784144, 0.04942525667989209, 0.004982545942080307, -0.05553497828831112, -0.008840601544025953, 0.0624511939178053, 0.01382568492204521, -0.07045040500021758, -0.0200635944222586, 0.07983573655308961, 0.02772464186081651, -0.09094444742633617, -0.03702388344715066, 0.1041536259789221, -0.04821924316984402, -0.1198819820124656, -0.06160445551722481, 0.1385840425022496, -0.07749220106038934, -0.1607306169402915, -0.09617998733441638, 0.1867658703825194, -0.1178877608692904, -0.2170271396260865, -0.1426531229291118, 0.2516110942742074, -0.1701709400072701, -0.2901735669785757, -0.1995766655123539, 0.33167198231666, -0.2292104536632618, -0.3741087211620817, -0.2564669531327498, 0.4144141160994378, -0.2779196790709351, -0.4486695658607398, -0.1585148155348832, 1.108326036371431, -0.5816638331406274, -0.6376460733569355, -0.1083863705122823, -0.2651532591988918, -0.04346268036180279, -0.1731791135747381, -0.007919955521890586, -0.1343419559206488, 0.01884997316493552, -0.1172998435413015, 0.04139686964273688, -0.1122109969614702, 0.0612644512371045, -0.1146390321312077, 0.07920415164364861, -0.1222036115318655, 0.09574062739795554, -0.1335955000566879, 0.111342587990221, -0.1481684801491999, 0.1264688165440626, -0.1657058794392267, -0.1415730034357649, 0.1862665137934408, 0.1571022793772566, -0.2100850895889454, 0.1735027646062021, -0.2375159098214737, 0.1912338107828908, 0.2690093363603886, -0.2107891668533592, 0.305116325619871, 0.232719244011093, 0.3465174314368482, 0.2576565915212616, -0.3940792105482042, -0.2863453006006712, -0.4489464059320039, -0.3196699442525448, 0.5126872859904976, -0.3587010976918096, -8.28272768639917, -3.069060360130142, 3.927691039870548, 1.671176660764354, 2.407455234884137, -0.8625377998571393, 2.482297646744782, 0.1292734700574192, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7028824420881, -960.9653940857651, -455.6573959835257, -0.0001045342927213557, -0.05510952876884354, 0.001813256542621175, 0.06227481799574789, -0.004858797016936023, -0.07000242917077827, 0.009264808465575517, 0.07862878594870333, -0.01511232203008351, -0.08850890488940624, 0.02254001315406766, 0.1000277135969499, -0.03174536747972971, -0.1136106715000355, 0.04298556623718725, 0.1297326922178386, -0.05657684359155325, 0.1489234556474868, 0.07288927434017092, 0.1717652930940824, -0.09233189928394896, 0.198877283105147, 0.1153205669594968, 0.2308750852817715, -0.1422162239454809, 0.2682908269428334, 0.1732165788221063, 0.3114322670825245, -0.2081820549922315, 0.3601601689508011, 0.2463834229879688, 0.4135774742746823, -0.2861906631817055, 0.4696707079443848, 0.3247907144321164, 0.5250325498506966, -0.3581320852927125, 0.5749043514816392, 0.3813740651756898, 0.33559864255759, -0.975267052557106, 1.553286395488471, 0.2975654526534304, 0.4156488593431335, 0.09371170961137179, 0.2528219529681863, 0.0318602025876451, 0.1873286487076531, -0.007406320889202832, 0.1569749836318507, -0.03858434309919215, 0.144934740453739, -0.06545817090963257, 0.1441815831728718, -0.08945270328381889, 0.1510120365349771, -0.1113416651259841, 0.1633234601502849, -0.1317257394447766, 0.1799857228617523, -0.1511744615193794, 0.2005086220062386, -0.170257066128721, -0.2248204324462682, 0.1895400302751218, 0.2531160063974417, -0.2095887459424748, 0.2857621049048731, -0.2309786288335811, 0.3232475487327383, 0.2543197035673892, -0.3661698670568465, 0.2802839275652471, 0.4152519125737978, 0.3096388181156818, 0.4713879968706516, -0.3432857433502883, -0.5357238487236324, -0.3823039298241136, -0.6097820756813976, 0.4280142297040914, -8.593418202744859, -3.211955544343986, 4.01550610066904, -1.769542946482932, -2.385993943945727, -0.9351886806923488, 1.364050528322037, -0.9080040622263671, -0.4464199288967212, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7061722826078, -960.9950980825289, 455.6584934644936, 0.001353924213319257, 0.05069804235078336, -0.001403478172758728, -0.05531669887499667, 0.0005546746219488723, 0.0602176601279568, 0.001178736969878009, -0.06565366943648464, -0.003823298510146261, 0.07188614605884883, 0.007444087396122985, -0.07919288756514294, -0.0121433251462564, 0.08787498194637582, 0.01805863608944551, -0.09826218797222715, 0.02535989650826906, 0.1107152897665785, 0.0342421634090001, -0.1256225901932514, 0.04491137284146533, 0.1433858203414038, 0.05755711615621574, -0.1643879418622154, 0.07230425516591216, 0.1889319980546444, 0.08913300093328734, -0.2171379771443038, 0.107757891711349, 0.2487872536298442, 0.1274663214539597, -0.2831201330658301, 0.1469465463422727, 0.3186294299533511, 0.1641875797212851, -0.3529538909796769, 0.1765977012156841, 0.3830228392206152, 0.09923300750079445, -0.9387659102980379, 0.305398543764229, 0.5874526002501284, 0.03421711551743981, 0.2496160794636069, -0.00172104942964322, 0.1682097394146368, -0.02558725561576955, 0.1361268344344931, -0.04691707458719761, 0.1244564737090883, -0.06726669000070251, 0.1239690575086415, -0.08693811269512493, 0.1304369530627798, -0.1060389333362548, 0.141571663489697, -0.1247414524221453, 0.1561163886904096, -0.1433423840955047, 0.1734586694197238, -0.1622500485292275, 0.1933984716847243, 0.1819498382764446, -0.2159900192240643, -0.2029763815613684, 0.2414387822339389, -0.2259034630808185, 0.2700417931160715, -0.2513516107580024, -0.3021617326012637, 0.280007600114253, -0.3382255019637882, -0.3126552129313027, -0.3787429608129044, -0.3502182255490416, 0.4243439334152545, 0.3938138954989248, 0.4758372286628779, 0.4448387377462819, -8.646476556307604, 3.287657641880755, -4.395262558384979, 1.792030252359884, -2.73372973571881, -0.9241141660969929, -1.712422595404809, 0.4359874306747898, -2.432174107259886, -0.6397052114818167, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7050978056665, -961.0251353455429, -455.6426293119019, 0.0005789714464947707, -0.07319751886662666, 0.0006207879061930474, 0.0802799735867732, -0.003129094635399184, -0.08803596071851463, 0.006975460706357075, 0.09683290373786249, -0.01224653915288706, -0.1070596332625383, 0.01908491954449565, 0.1191369742779648, -0.02768776308106317, -0.1335267149602703, 0.03830435886062355, -0.1507372943186485, -0.05122967843956672, -0.1713229356970986, 0.06678971375544743, -0.1958705963395601, -0.08531182846472353, -0.2249654793739225, 0.107069570838405, -0.2591211079527574, -0.1321872027422623, -0.2986553751625171, 0.160487669363109, -0.3434934131000018, -0.191273923827569, -0.3928906485362413, 0.2230621626353611, -0.4451099722739455, -0.2533460049820092, -0.4971642549076689, 0.2785681040388742, -0.5448315365001141, -0.2945449187820606, -0.3188523354151554, 0.7617168830174238, -1.512960882421318, -0.1565418889317566, -0.416770638188017, -0.0330371554958069, -0.2590939561072727, 0.009692898702806391, -0.1979815715767451, 0.04169344337350171, -0.1721638220045798, 0.07052530713197516, -0.1647923498418741, 0.09775169543831891, -0.1687258056803347, 0.1237881291548195, -0.1801639057873346, 0.1488794308490554, -0.1969463086568264, 0.1733613896964222, -0.2179209500175104, 0.1977104526182695, -0.242597178003689, 0.2225166824607487, 0.2709069147142353, -0.2484447312925564, -0.303039084913382, 0.2762089619529779, -0.3393348213625563, 0.3065757332901756, -0.3802323858876161, -0.3403810643090954, 0.4262480705852916, -0.3785664996638002, -0.4779857272391611, -0.4222285054438267, -0.5361702328195965, 0.4726795168378314, 0.6017042384742251, 0.5315431534297506, 8.988404257252103, -3.434234591407497, -4.436704087040918, 1.904958600463788, -2.667252960757383, 1.019315404694702, 1.553413773220462, 0.5240360258904643, -0.8521059937283484, 0.9531203463970385, 1.133055091391562, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7100346863414, -961.0567364446957, 455.646613143601, 0.002722295284934282, 0.06461681973477371, -0.004007947943993217, -0.0683635324772939, 0.004536694220093283, 0.07238640000970466, -0.00433430930478059, -0.07694262150014541, 0.003392025878594218, 0.08229618144787393, -0.001670278858418917, -0.0887242115986121, -0.0008975016974408089, 0.09652212032887546, -0.004400201670914741, -0.1060064440564509, -0.008941741499294128, 0.1175134358385135, -0.01462879396175798, -0.1313898772830384, -0.02154950721841662, 0.1479705007616418, -0.02973757948750487, -0.1675338272440166, -0.03911447566452358, 0.1902263373250469, -0.0494038851796016, -0.2159464070642364, -0.06002011198536771, 0.24419037399957, -0.06995441855483667, -0.2738896861740276, -0.0777218007125729, 0.3033115380943844, -0.08147776924470845, -0.3301302888852998, -0.04342138832490353, 0.800108427299287, -0.04000732313755277, -0.5563775145367175, 0.03855669146460623, -0.2421457122014047, 0.04673467675853111, -0.1685947713495393, 0.05966925766215405, -0.1421356546813504, 0.07617060670611064, -0.1353431117620796, 0.09486340695112068, -0.1392947724748802, 0.1148236878882152, -0.1498272473624081, 0.1355229389653643, -0.1646584030588876, 0.1567892967260354, -0.1825265390991063, 0.1787580887629875, -0.2028097674378218, 0.2017993595211208, -0.2252868325806165, -0.2264439082886397, 0.2499694264649327, 0.2533278498840449, -0.2769901080244833, 0.2831665936584349, -0.3065367197788879, 0.31675352352134, 0.3388193022269569, -0.354979335807952, 0.3740594600432878, 0.3988728455325729, 0.412493048200239, 0.4496557166350698, -0.454379410749675, -0.5088325604398763, -9.020420590072227, -3.450565579378631, -4.828910565671182, -1.874110745373426, 3.031455262150587, -0.9554280057985601, 1.918824600147808, 0.4370410894016331, 1.245159522031377, -0.1566307455549422, 2.552719012229264, 1.137055157228564, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7083084832581, -961.088403701372, -455.6259949644748, 0.001693462288155773, -0.09425609907144253, -0.00135812958186467, 0.1011210298209119, -0.0002358251806337989, -0.1088168511442754, 0.003123702470935177, 0.117746189310862, -0.007394509226016558, -0.1283352037931964, 0.01318721808082886, 0.1410426164823464, -0.02068614552863905, 0.1563657899240353, 0.03011316521908753, 0.1748410515523016, -0.04171287552624901, 0.1970333700401475, 0.05572504926140202, 0.2235071819563995, -0.07233534673786346, 0.2547659637536581, 0.09159167502337025, 0.2911438853529135, -0.1132728046470395, 0.3326320892944551, 0.1367013692972142, 0.3786326012788764, -0.1605193483772494, 0.4276675386247564, 0.1824972953091496, 0.4771381978993297, -0.199534230207109, 0.5233118023773972, 0.2080647751939719, 0.3071312523515405, -0.549473955438997, 1.498520087318462, 0.00989782058163087, 0.4257392836989572, -0.03066419348029967, 0.27053141082994, -0.05385429393158369, 0.2128586455021746, -0.07865838364579553, 0.1912804624944068, -0.1054218514397032, 0.1886052588272439, -0.1333817841205637, 0.1974301330414755, -0.1618922650232225, 0.2137720478898956, -0.1906429188221663, 0.2353555123291881, -0.2196953036046989, 0.2609640871623732, -0.2494334138871651, 0.2900702342300163, -0.2804781709204113, -0.3225735541543351, 0.3136051709871521, 0.3586152379559984, -0.3496963324210602, 0.3984605855948943, -0.3897237334354889, 0.442433754373803, 0.4347674252373997, -0.4908899809534614, 0.48605633051341, 0.5442128827277137, 0.5450303291374311, 0.6028273664098085, -0.6134359722665157, -9.383238747186924, -3.600916739919184, 4.832694315608912, 2.003470413821713, 2.931212798765991, -1.076233974356122, 1.727556840630514, -0.5584158153153711, -0.9677000168663793, -0.2850220760337975, 0.4848137226350174, -1.162124180800043, -1.793676268616248, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7153141286621, -961.1217498954065, 455.6338248564796, 0.004666236513345801, 0.08033835876549655, -0.007676437270062325, -0.08295141844108442, 0.01009977011228604, 0.0858558666115623, -0.01197879976722524, -0.08931330796488612, 0.01333079539699938, 0.09358896098647876, -0.01415383176294858, -0.09895648285762505, -0.0144330727549111, 0.1057012528087135, -0.01414858625643324, -0.114120817737291, -0.01328610322696056, 0.1245201008433383, -0.01185312169985896, -0.1371974259500803, -0.009903932278386084, 0.1524155095853953, -0.007577483035196663, -0.170349858019879, -0.005151094173442019, 0.1910076219888127, -0.003106911843602696, -0.2141162385930753, -0.00219223603220216, 0.2389982098664602, -0.003428653267689329, -0.2644761408819428, -0.007993135284190185, 0.2888757583999775, -0.009238357725273051, -0.689494763421366, -0.2155878440195048, 0.5426652421405607, -0.1100760809768825, 0.2419872852187903, -0.0915757211308498, 0.1738068042043262, -0.09421490159299305, 0.1519131253021238, -0.1063902295366557, 0.1495062851706462, -0.1238496488930524, 0.1576921868225562, -0.144457445676418, 0.1722377145797942, -0.1670559652778887, 0.1907853469363053, -0.1911367180744256, 0.2120098595295308, -0.2166813899045869, 0.2352309624985876, -0.2440312262325445, 0.2601594028118362, 0.2737719046620724, -0.2867127897537385, -0.3066513544997664, 0.3148910096033804, -0.3435341329051073, 0.3446994182012239, -0.3853912741508331, -0.3761050372799959, 0.4333221867749439, -0.4090113357290798, -0.4885956544839816, -0.4432370036767068, -0.5527297958804152, 9.393725843325772, 3.559142669539414, -5.233438534663443, 1.922140772052916, 3.30916008332548, 0.9639922588619462, -2.108426983838054, 0.4210596150978028, -1.37488546401417, -0.126172291118237, -0.9417910946035264, -0.02489482226941209, -2.820413837240554, -1.65719959391188, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.712822627705, -961.1549732256356, -455.6077127096619, 0.003370363513768094, -0.1184233948149237, -0.004352589134933815, 0.1249488727742578, 0.004142598150015885, -0.1325266147065525, -0.002702309633903203, 0.1415989061506627, -5.193242257853952e-05, -0.1526322638582052, 0.004242516041704322, -0.1661238420831387, -0.01002108162905441, -0.1826028877145596, 0.01755321339895132, -0.2026229299653129, -0.02699257791731359, -0.2267375503327169, 0.03843678368101805, -0.2554486834745714, -0.05185463742576753, -0.2891125143344822, 0.06697380838544749, -0.3277869557881715, -0.08312340296797521, -0.3710132247776353, 0.09904931306822057, -0.4175532297672665, -0.1127668418736266, -0.4651618147564519, 0.121590215262521, -0.510544244533257, -0.1225288992181756, -0.3005345609258526, 0.3399230830669571, -1.510041866246306, 0.1414029629131923, -0.4424813889986434, 0.0969566625439009, -0.287030472441386, 0.1002877273344002, -0.2318097264729576, 0.1179696537132148, -0.2141130560573038, 0.1428989401173152, -0.216085496212976, 0.1718969363526398, -0.2299160646037506, 0.2032113426057577, -0.2513516264549205, 0.2359542056548815, -0.2779404049836417, 0.269903604489502, -0.3083522861668259, 0.3053525231567537, -0.3419775604673035, 0.3429586234253998, 0.3786342689363086, -0.3836208986559502, -0.4183589706424067, 0.4283986271914125, -0.4612706968478629, 0.4784824630112978, -0.5074923782141396, -0.5352066248608507, 0.5571092548388775, -0.6000923998546913, -0.6101471292691906, -0.6749305319888952, -9.770051112346868, 3.712532157622387, -5.204107151313059, 2.068330691047585, -3.18125125479366, -1.111446716858055, -1.892155190902516, 0.5769109527951105, -1.074175671579627, 0.2964457689798568, 0.5539281293589068, 0.1648327863802309, -0.2172096485697859, 1.512241614146546, 2.467635656276092, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7224116592663, -961.1902571610938, 455.6205915183505, 0.007332560323131098, 0.09772650675515225, -0.01266681647409895, -0.09890946144936448, 0.01761061930967164, 0.1004319663138764, -0.02223151529100917, -0.1025589734040736, 0.02658527800478494, 0.1055543905435332, 0.0307240137177325, -0.1096846360720932, 0.03470480005138991, 0.1152206928700177, 0.03859926962869588, -0.1224372229859417, 0.04250540794695284, 0.1316063042861069, 0.04656276217394649, -0.1429819416890049, 0.05097254854312608, 0.156770043109164, 0.05602256159687267, -0.1730781884191307, 0.06211263471333318, 0.1918417495221531, 0.06976604123079083, -0.212731221653107, 0.07959687794489242, 0.2350594264866488, 0.09218568189114314, -0.2577207095948243, 0.05895216380708893, 0.6030344606072978, 0.4616425346359402, -0.5436208097610066, 0.1801615878388285, -0.2479542818639472, 0.1359942495801694, -0.1829951211861444, 0.1288696776689487, -0.1647070482516714, 0.1370851711017615, -0.166186009742888, 0.1535729004651733, -0.1783286433187104, 0.175004017949945, -0.1967160001753221, 0.1996016370756137, -0.2188405755084354, 0.2265274150255044, -0.2432545072656078, 0.255616995167631, -0.2691644778819984, 0.287188623645841, -0.296154558573445, -0.3218894031796202, 0.3239813218519342, 0.3605820289961011, -0.3524309991867358, 0.404281451485633, -0.3812277505186181, 0.4541373257413515, 0.4099740685595717, -0.5114462459203447, 0.4381037210394499, 0.5777085075240355, 9.757187794715053, 3.613965379149533, 5.610766740550909, -1.938835199033022, 3.571436149045066, -0.9542168243229318, -2.288013661621963, -0.3938480967566447, 1.496351683252224, -0.08808345484880223, 1.023046330373567, -0.06957848752644458, 0.7559950874575174, 0.1446377341673701, 3.223159785518482, 2.231109599751307, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7190540960186, -961.2250192748934, -455.588180522695, 0.005760119451667827, -0.1458018459472323, -0.008617871967446157, 0.1518886251707371, 0.01036045836723483, -0.1593339434673855, -0.01095512117368798, 0.168623432319206, 0.01033715383235535, 0.1802652315855236, -0.008421308021689847, 0.194792393053006, 0.005117854913200912, 0.2127573865763628, -0.0003573018673901766, 0.2347123846839292, -0.005870115341541783, 0.2611655306170398, 0.0134514921104915, 0.2924997329898752, -0.02205646148738518, 0.3288391697120372, 0.03100724814840945, 0.3698554289066493, -0.0391314172858762, 0.4145293741812473, 0.04465629171074397, 0.4609333830920124, -0.04526915247447261, 0.5061591284697164, 0.03850943070266388, 0.2988211434046964, -0.1343140034874617, 1.545791848932921, -0.2960335360025335, 0.4663736910206594, -0.1651993031618597, 0.3081206807361616, -0.148466528783414, 0.2543776892222589, -0.1590822972569348, 0.2401547949000193, -0.1823264347853362, 0.2466363598796981, -0.2125374666877397, 0.2654664586167893, -0.2468230014420065, 0.2920378799634734, -0.28369945780944, 0.3236595023368128, -0.3226554917179421, 0.3588325700155615, -0.3638932634463122, 0.3968084947760234, -0.4081139430426112, -0.4372603761207967, 0.4563448325195634, 0.4800432615153861, -0.5098306130089106, 0.5250360251830816, -0.5699872792909377, 0.5720443097383854, 0.6384042472680606, -0.620739093955173, 0.7168958955657478, 10.1416026925784, 3.769624166608563, -5.550197612007544, -2.101714625470462, 3.418765229089471, -1.128530918815057, 2.05030202920546, 0.5843666730352316, 1.176141611311618, -0.2998770983489928, 0.6178281648963292, -0.1687738124565776, -0.2572515070648175, -0.1256951327451982, 0.01616907141314794, -1.992214070149926, -3.189662381847132, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7318794445075, -961.2622111936237, 455.6076615218215, 0.01089221138384335, 0.1164944818989575, -0.01927027124317406, -0.1159105114196266, 0.02747804138380453, 0.1157590237274542, -0.03562101111504409, -0.1163053571198556, -0.04381054622555893, 0.11780798689624, -0.05217348627038508, -0.1205218765117039, -0.06086108892227842, 0.1247010612781868, -0.07005691264492792, -0.1305992812196758, -0.07998336769309033, 0.1384666763445831, -0.09090568207321333, -0.148539099266325, -0.103130632313689, 0.1610155426830076, -0.1169945067947107, -0.1760175642549749, -0.1328292092990493, 0.1935251760227961, -0.1508900371219247, -0.2132847544560474, -0.1712230826203191, 0.2346889242553419, -0.1057755931109957, -0.5357642487146973, -0.6973878233988416, 0.5555297188556486, -0.2482482426823123, 0.2583893820691848, -0.1794481217099651, 0.1949556011152848, -0.1629964039187765, 0.1794404990383949, -0.167454966242039, 0.1842879058626768, -0.1830230404376604, 0.2000060175644817, -0.205209645685749, 0.2218995693363221, -0.2316338998877495, 0.2472470804664445, -0.2611383861136601, 0.2744206707423583, -0.2934188634283356, 0.3024520161486941, -0.3287766158418658, 0.330727168992488, 0.3679203274465594, -0.3587549762608285, -0.4118259797084023, 0.3860024176740223, -0.4616568968449378, 0.4117833750068759, -0.5187284681093876, -0.4351768010753159, 0.5845252467597436, -10.10272037837622, -3.615759296992346, 5.961002309639331, -1.925982279272278, -3.820398085376841, 0.9288290974303622, -2.461282861258473, 0.3588964134966156, 1.614524108256882, 0.04643312460190491, -1.101929869918408, -0.1156934037864506, -0.8069532966049089, 0.1939414294536783, -0.6549974120119686, -0.2285123742746999, -3.758505654153285, -2.887002774786242, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7275737129024, -961.2986900862034, -455.5680475291849, 0.00903586301318594, -0.1764481378529507, -0.01443633323006236, 0.1820293926317921, 0.01880447073763833, -0.1893830763324559, -0.02212739922183875, -0.1990394755651686, 0.02438113653662378, -0.2115459961113778, -0.02554785138683405, -0.2274636911241468, 0.02563963642219436, -0.2473516518290995, -0.02473404186599173, -0.271730510328668, 0.02302808689174882, -0.3010128812352733, -0.02091691897707183, -0.3353869095894007, 0.01909834439431709, -0.3746441757811209, -0.01868481784601551, -0.4179627386782013, 0.02126895992019769, -0.4636967305855159, -0.02883173464380446, -0.5092745443586736, 0.04334833925615389, -0.3014407655914791, -0.06601281923988526, -1.602324544766366, 0.4521688717502506, -0.4962602535568542, 0.2344899085974771, -0.3329721059649142, 0.1976354384687227, -0.2798012120081235, 0.201207847611257, -0.2686044483634154, 0.2227918565877333, -0.2793525517309335, 0.254208949035389, -0.3030265762539144, 0.2914075927648672, -0.3345889425740216, 0.3323002062548046, -0.3710472412454519, 0.376082825113517, -0.410672419727643, 0.4228703215020564, -0.4525090987053563, 0.4734101217025521, 0.4960038585709059, -0.5288630443220137, -0.5407310407243179, 0.5906642373893218, -0.5862073308755801, 0.6604544266659836, -0.631770882164199, -0.7400800113225439, 10.4912498465414, -3.773373232627433, 5.869292321428817, -2.105388476297262, 3.643747899009217, 1.129947070197685, -2.20333116034871, 0.5839586073720042, -1.276059903111896, -0.299240532723705, -0.6800685739125477, 0.1698588504724025, -0.2942327379600606, 0.1304150900865758, 0.03800351903695634, 0.1417197104665032, 0.1425294782604167, 2.600515797914067, 3.992077820801224, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7444899137037, -961.3378869284877, 455.5961766575729, 0.01554496586389417, 0.1361607262454429, -0.02781289414814694, -0.1334206115553933, 0.04015195437573545, 0.1312610252962056, 0.0527238328643537, -0.1299420806015547, 0.06571735393480846, 0.1297113267134137, 0.07935679284872428, -0.1308093221619015, 0.09390646392500906, 0.1334765342836597, 0.1096692934744826, -0.137961097981063, 0.1269759901739711, 0.1445257840878497, 0.1461596796124059, -0.1534505818065084, 0.1675090650339144, 0.1650223724407157, 0.1911922811662067, -0.1794965959880791, 0.2171469054347325, 0.1970054498924576, 0.2449372580636083, -0.2173831194355537, 0.1495893184212565, 0.4816785595258409, 0.9209202815588715, -0.5736517097497067, 0.313353604698171, -0.2711605588560934, 0.221082155663423, -0.2081281229339226, 0.195658000237407, -0.1947111978907778, 0.1963739070246782, -0.2023853087811128, 0.2108169700402979, -0.2211665513822386, 0.2333844452691181, -0.2460259436412557, 0.2611196517524419, -0.2739795084733933, 0.2925613936013013, -0.3031638285603235, 0.3272759615201772, -0.3323671520526524, 0.3655494198939995, -0.3606901700963588, -0.4081518881755232, 0.3872850919084128, 0.4561704112264385, -0.411165351471291, 0.5109046669029912, -0.4310695720851319, 0.5738286008172455, 10.42318783741847, -3.566018330179493, -6.283039963892671, 1.885086978417805, -4.056461148196111, 0.8896096623583637, 2.629879524658232, -0.3183134586090979, 1.732009409551348, -0.003597002249112677, -1.181752365540581, 0.1607426656367353, 0.8594318003331071, 0.2409887971627989, 0.6872601018528763, -0.2776927275225095, 0.6162945944580821, 0.2949229569475111, 4.432330830999809, 3.652258417704127, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7391854477888, -961.3761134831929, -455.5483160115629, 0.01339975427289111, -0.2103617083669475, -0.02212129334677451, 0.2154107935057459, 0.02989586468758025, 0.2227762054914026, -0.03675410570225757, 0.233029559420389, 0.04274488714190522, 0.2467489261215965, -0.04795860482498126, 0.2645069025107166, 0.05255917574259697, 0.2868406962417143, -0.05682989248602897, 0.3141931378633969, 0.06123725611583161, 0.3468116005115335, -0.06651167350925496, 0.3845953195758418, 0.07372631291715646, 0.4268969633578305, -0.084324035113474, 0.472317693749994, 0.09999329127000312, 0.5185766012306021, -0.122267111761034, 0.3075794130567557, 0.2594922311530679, 1.674677840688869, -0.6074411217165189, 0.530504621157434, -0.3036489093269464, 0.3604292259290603, -0.2468040165898022, 0.3070437102038547, -0.2433124059830945, 0.2983965063767964, -0.2631034380950553, 0.3130548980457453, -0.2954872738506904, 0.3412458946213262, -0.3352576648480358, 0.3774381296472452, -0.3797257621045876, 0.4182777341843855, -0.4278008133993835, 0.4617385983648974, -0.4795135491180799, 0.5065767007844517, -0.5356633184142464, -0.5519108635118929, 0.5975519447496171, 0.5969093166328796, -0.6668064787959627, 0.6405721802139768, -0.7452989581305071, 10.81295073151522, 3.725997667527157, 6.159022350342218, 2.081113170768998, -3.855102702242159, 1.117501368797665, -2.351235823926313, -0.5777697467504209, 1.374856223267653, -0.29701181947491, 0.7424138377886643, 0.1710585953742098, 0.330797445008233, -0.1353650627227564, 0.0576408564358677, -0.1510793503432264, 0.1322861784530395, -0.1959399824468592, -0.2765948893642101, -3.344039432155814, -4.906745836243842, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7613365642291, -961.4178098908683, 455.5878220684487, 0.02152739456950745, 0.155990589845504, -0.03865954626620611, -0.1506307363154621, -0.05612307601046214, 0.1460612037459447, -0.07415968563775244, -0.1425284489543925, -0.09305949879988605, 0.1402637839647557, -0.1131625092824421, -0.1394959528064121, -0.1348497243264618, 0.1404692206213771, -0.1585184900258227, -0.1434668149614358, -0.1845343498098827, 0.1488370709744961, -0.2131515106483328, -0.1570114703269528, -0.2443967819326662, 0.168490761061717, -0.2779233867878602, -0.1837542375722553, -0.3128574421494117, 0.203035425587468, -0.1900946734061147, -0.433834219025143, -1.129221067589957, 0.5923000478378968, -0.3740906900280064, 0.2836979264745814, -0.2597387711190001, 0.22062681445908, -0.2256295048723918, 0.2088235792854549, -0.2224048277552317, 0.2187578425407568, -0.2352143633671168, 0.2399405360599269, -0.2574227677607072, 0.2669932721109848, -0.2855421185023375, 0.2966388173566911, -0.317835119944384, 0.3267272928345747, -0.3537499822930283, 0.35572663703428, -0.3935627878927179, 0.382347718395156, 0.4381069694359088, -0.4052516396076142, -0.4885743991703206, 0.4228306365409398, -0.546400243704626, 10.7123505563827, -3.467401368528632, 6.574905698665654, 1.817773117729432, 4.278777619641925, -0.8378218541754415, 2.793944829112401, -0.2733177456826802, -1.849759245051467, -0.03915110965119177, -1.264069361132026, -0.2034284048409766, 0.9153371450385213, -0.2846049852576992, -0.7235404151249138, -0.3227953515570327, -0.637237958096172, 0.342187055210012, -0.6250483028853673, -0.3568764257507016, -5.257937304882959, -4.55508554936837, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7550364030109, -961.4583496977284, -455.530480379083, 0.0190938476296795, -0.2474730170941161, -0.0320248394429458, -0.2520068723070391, 0.04409746139951185, -0.2595497997911581, -0.05542064500866747, -0.2707037328264438, 0.06615890175647458, -0.2860590669957729, -0.07656112549161879, -0.3061707763092542, 0.08699898599850459, -0.3315091701035143, -0.09801668999733169, -0.3623728933478695, 0.1103893488200521, -0.3987539286431652, -0.1251703436227577, -0.4401558607610471, 0.1436810276293193, -0.4853934971597049, -0.1673540627022936, -0.5324352881075169, 0.1973214093273239, -0.3162259135719306, -0.4443061610633235, -1.756700779373999, 0.7590020979393318, -0.5670900504193579, 0.3712553167121694, -0.3890806275027168, 0.2947777467691565, -0.3348571513627888, 0.2841510646953452, -0.3282692231155715, 0.3018275022954646, -0.3463689030326972, 0.3346649164831056, -0.3785725697111055, 0.3763313412808598, -0.418806990424517, 0.4235591970882376, -0.4633012783675338, 0.4749833840580253, -0.5096588677124098, 0.5305616262560031, -0.5562508167799632, 0.5911571677427112, 0.6017445089562359, -0.658220168495264, -0.6447469122637461, 0.7335866606257689, -11.10138605254825, 3.631034314442978, 6.416520283055733, -2.030929045438653, -4.050883210517207, -1.09263234274095, 2.492947931639272, -0.5671254785083639, 1.472262538497965, 0.294648565121288, -0.8053212026371659, 0.1740959578194711, -0.3680979667177443, -0.1426477808213935, -0.07701400313898601, 0.1623356308255878, 0.1242639559307309, 0.2112653724844634, -0.2740335801422096, 0.2779853011318764, 0.3991136330708569, 4.237178417243852, 5.966755879689668, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.7839768955486, -961.5031356303735, 455.5850306639925, 0.02912480258648458, 0.1749203040042703, 0.05222060442792607, -0.1663669930730279, 0.07592414985531605, 0.1588763076469116, 0.1005831663097198, -0.1526711551376601, 0.1266078291343768, 0.1479660097637017, 0.1544547454180628, -0.1449948514511539, 0.1845887043750316, 0.1440505633533104, 0.2174126453759208, -0.1455339392818743, 0.253156701007274, 0.1499995768662069, 0.2917237939532877, -0.1581666783968385, 0.3325088566360749, 0.1708317017743966, 0.3742344872602825, -0.188600178511197, 0.2268316604370843, 0.3845480392234077, 1.318322244561246, -0.6050237732153305, 0.428731430577431, -0.2930800029727587, 0.2940064673796119, -0.2303095703759141, 0.2514426080702059, -0.2198597838188783, 0.2438453429385534, -0.2314722939759387, 0.2541700231595779, -0.2542443363261532, 0.2748630106477523, -0.2824784951384094, 0.3019732811307502, -0.3125960540799213, 0.3335263049897976, -0.342113632573852, 0.3688741680327827, -0.3690936466192343, 0.4082952782635644, -0.3917330876661867, -0.4526883946043698, 0.4080384200378837, 0.5033598302349126, -10.96490758246675, 3.324010782640217, 6.833995337770606, 1.726068427677496, -4.485538946284208, -0.7744900179888866, -2.952462441243869, 0.2245238076687357, -1.96746806450077, -0.08132430877219025, 1.349148411398959, 0.2433017034817874, 0.9753204169954288, 0.3244179414574758, -0.7646022741758332, 0.3636921476151955, 0.6637918690093022, 0.3848718174085247, 0.6393750651856561, -0.402120829041611, 0.672076261839223, 0.4236321878220717, 6.255464776858338, 5.625936364814542, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.7767711685316, -961.5466022439307, -455.5167169920276, 0.02641646045759053, 0.2876293875521561, -0.04455269836068995, 0.2917046426611087, 0.06192864199017718, 0.2996413203859867, -0.07877768540105098, 0.3120491459019933, 0.09543210301352055, 0.3294985036302559, -0.1123540725858994, 0.3524803724007334, 0.1301721006693483, 0.3813326175940071, -0.1497179815896551, 0.4161216500474114, 0.1720439307471236, 0.456476553154757, -0.1983762992393827, 0.5013934945639351, 0.229926008851196, 0.5490538865200292, -0.2674630790920627, 0.3262584781762246, 0.6184594756429348, 1.841505465819113, -0.9036920907968744, 0.6037649288986811, -0.435730331781932, 0.4173633503092889, -0.3402273078184248, 0.3618792001829753, -0.3223329221765415, 0.3568694292734518, -0.3373610302359374, 0.3778471175268359, -0.3698307686701466, 0.4133989349283659, -0.4123481977579463, 0.4568802691238098, -0.4611046705689894, 0.5040519090114971, -0.5144902166835649, 0.5520670643889852, -0.5724133548481751, 0.5987991975851327, -0.6358180460131468, -0.6423152491290044, 0.7063313713285493, 11.35202456455329, -3.493500196224254, -6.638568150183083, -1.957344673859988, -4.228485425971068, 1.056606712337717, 2.626551471527081, 0.5527901502998748, -1.5670524346359, 0.2928237369304179, -0.8682190156229788, -0.1797627572714807, 0.4061836395463059, -0.1532886909026603, 0.09679996807476349, 0.1768465936273609, -0.1170417081935488, -0.2292432522445197, -0.2742907297354369, -0.2992562708270863, 0.40201700883393, -0.38229571927536, -0.5200048155415438, -5.301175868637563, -7.207800765406747, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.8146309446975, -961.5954948017205, 455.5912580995108, -0.03868887300459015, 0.1914593508419486, -0.06896288380706332, -0.1789757931782649, -0.1001298844401407, 0.1678836436039876, -0.1326643353856479, -0.1583758389218828, -0.1670959289351405, 0.1506643220501891, -0.2039577762706567, -0.1450354518997625, -0.2436945939407161, 0.1419222648546592, -0.286520727014479, -0.1419791043669855, -0.3322284769841388, 0.1461191154367376, -0.3799736358824325, -0.1554340998005074, -0.4281019938694952, 0.1708890736518134, -0.2592200631304444, -0.3256852567521202, -1.483625349429867, 0.6048929864489581, -0.4753236422915989, 0.2961694592646632, -0.3223046209916502, 0.2348874153138894, -0.2714626999105824, 0.2257895769533033, -0.2588066214268311, 0.2385080365992549, -0.2654198271110554, 0.2619285315116793, -0.2829866644015172, 0.2901165131905762, -0.3071846631133203, 0.3192058852536734, -0.3358595624892154, 0.3463380609514268, -0.3683054470711298, 0.3690746037927644, -0.4048218311662792, 0.3849522860948287, 0.4463965618803197, -11.17658830910763, -3.141599888182389, -7.057308180610275, -1.612632569840935, -4.674228358739717, -0.7006254562246356, 3.103524645986586, 0.1721449712789752, 2.083843108349515, 0.1230344465499392, 1.436244916006413, 0.2805779655633087, -1.039058835442039, -0.3606873771771562, -0.8103535254099236, -0.4007449405027154, 0.6957974817861713, -0.4236310613634878, -0.6603595623427048, -0.4431665472145394, -0.6828038414913131, 0.4676302900407178, -0.7523362731509651, -0.5019606323960604, -7.451487262070271, -6.898592890440204, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.8067442478319, -961.6430987511887, 455.5101352313706, 0.03574672013766993, -0.3305806211988256, -0.06018793703629798, -0.3342789822135747, 0.08398862072600807, -0.3428477394831397, -0.1075626639881692, -0.3568661462114826, 0.1314655734088672, -0.3768341259425303, -0.1564176785432246, -0.4031115942603709, 0.1833201534769062, -0.4358166092177098, -0.2132428552839921, -0.4746756170442514, 0.2473424911876484, -0.5188341233287944, -0.2866404669967078, -0.566654544358885, 0.3315822789153745, -0.3365523808315161, -0.7799477365989287, -1.92204447761313, 1.038304945171675, -0.6382333295246007, 0.4954672252621077, -0.4437009237950818, 0.3817879746615038, -0.3867630435618042, 0.3564182943353214, -0.3828941956014584, 0.3680304652111646, -0.4061335779417263, 0.3989834362533684, -0.4442583228007695, 0.4409123847406293, -0.4900404834181868, 0.4895313969246102, -0.5387255048657738, 0.5430334536942414, -0.5869290800627904, 0.6013145526212335, -0.6318954893637412, 0.6654442464724272, 11.56123863009346, -3.319983549512171, 6.821845065194244, 1.863466932603496, 4.38488470063812, 1.01067094368389, 2.749511386838089, -0.5351194258268466, -1.657256920227764, -0.2915679928571555, 0.9297221747564861, -0.1880812619045127, 0.4442416560586033, 0.167463535694055, -0.1167505114866327, 0.1950254755353985, 0.1102695455592749, -0.2505965089753026, 0.2762752306336164, 0.3233977751863117, 0.4086760961549661, 0.4088566255401637, -0.527180830087615, 0.5067736816255463, 0.6471037120006224, 6.563582277433596, 8.669169878915001, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.8564496879252, -961.6978071512939, -455.611344166528, -0.05065962634433919, -0.2035667717073716, -0.08941939694818055, 0.1861819141070234, -0.1293463728361657, -0.1705641231959824, -0.1710413062870665, 0.1568853187052691, -0.2151073082088822, -0.1454027021144876, -0.2620355483771115, 0.1365557074206818, -0.3120320827642339, -0.1310718629875927, -0.364788555337083, 0.1300347438234267, -0.4192352859893375, -0.1348167335882609, -0.473360750181653, 0.1467438213440089, -0.2866158909387535, -0.2490263897518478, -1.620329947670383, 0.5848677254506903, -0.5118461330390914, 0.2897889114975229, -0.3429946413052233, 0.2320656306481047, -0.2839885316813635, 0.2246136703445073, -0.2653143559437961, 0.2379182651793468, -0.2665902029177392, 0.2609701715451156, -0.2789374326510159, 0.2877297688810677, -0.2977825578364603, 0.3140810644157221, -0.3208740171767074, 0.3367519648803812, -0.347497849625001, 0.3526960178041265, -0.3780240749856291, 11.34415339639681, 2.9276728518795, 7.241716186208386, -1.480912627484681, -4.841851735919054, -0.6174008600345655, -3.244551359081532, -0.1161699839121046, 2.196810963053788, -0.1648403832407603, 1.52378878614412, 0.3160144776303719, 1.105419207445201, 0.3942117305648183, -0.8599720166997633, -0.4347652751226382, -0.7325429176455468, -0.4593657200668957, 0.6870715556985062, -0.4812114897627066, -0.7009216608316468, -0.5083517726327081, -0.7613887957889477, 0.5458417512230326, -0.8637959811793713, -0.5970603500508016, -8.878579618167663, -8.41079729749319, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.8483022209899, -961.7515375401339, -455.515103378266, 0.04757600714722041, 0.3759601994912693, -0.07952182508355922, 0.3793600134854735, 0.1109858526574028, 0.3887731574427825, -0.1426212566623932, 0.4046909058892191, 0.1752498328905884, 0.4274717745852317, -0.2098572245667174, 0.4572568690190124, 0.2475512176980405, 0.4938376701380627, -0.2894449308435921, 0.5364758189264845, 0.3364018036152697, 0.5836858088124017, -0.3885795342274033, 0.3460998677017337, 0.9269607883637689, 1.991751849844172, -1.159894903453939, 0.6683678480468542, -0.5489774865143997, 0.4666584984984303, -0.4181743697237709, 0.4083256137378595, -0.3850224904055522, 0.4052531090492756, -0.3922030940012985, 0.430154764416738, -0.4201452172640414, 0.4700533145873315, -0.4596423877934347, 0.5171413042952349, -0.5060190814650223, 0.5661040793608841, -0.5573376710742627, 0.6129220747774261, -0.6135503322915893, 11.72621780801965, -3.118567404640785, 6.963211382717763, 1.75302164155703, -4.516867569899999, -0.9561071819941682, -2.858888666291709, -0.5141429755265274, -1.740364185208108, 0.2903667692240343, 0.9878145752430977, 0.1983973188452912, -0.4807765726797618, 0.1846015909228558, -0.1358948953187996, -0.2164957212324468, -0.1043808041537456, -0.2751935128773355, -0.279826746444909, 0.3505627343904102, -0.4181686778299342, -0.4382062477600169, -0.5392140048606524, -0.5377014109662097, 0.6579315820212267, -0.6517663504946155, -0.7869275609113959, -8.05753646041288, -10.39414405360874, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.9138637696153, -961.8143515653112, 455.6519677186474, -0.065587947208334, 0.2085029215343718, -0.1141904493380159, -0.1849281174071089, -0.16417292084848, 0.1635422401442634, -0.2162120711863979, -0.1445429665498645, -0.2708523356285875, 0.128343198787713, -0.3282995933633563, -0.115712162032152, -0.3881537124649574, 0.1078796554266659, -0.4491292094201663, -0.1064891874455163, -0.5088711427777188, 0.113241647884544, -0.3083741181691479, -0.1467011040433109, -1.723923205907633, 0.5382296108587682, -0.5363846735303583, 0.27092624926658, -0.3545066321432684, 0.2197099884192319, -0.287363686337111, 0.2145312764451768, -0.2614204612340402, 0.2280211406842278, -0.2553142195422838, 0.2496987336771662, -0.2598467419074491, 0.2735997743104482, -0.2703495132715409, 0.2954157424967072, -0.2845730952075546, 0.311423814533789, -0.3018822827637243, 11.46523893315575, -2.691413015229958, -7.384362245400597, 1.335236216275609, 4.985185235965488, -0.5262745591804759, -3.372485074148798, -0.05648924165287231, -2.303682267268397, 0.2076207204669117, 1.609522758219237, -0.3508002202525652, 1.172561778202216, 0.4262482117585027, 0.9119656734777154, 0.4669796982018008, -0.7727539450790861, -0.4932706593868525, -0.7182401966339386, -0.5175074770463448, 0.7247978830712355, -0.5473237053574408, -0.7783621609313609, -0.5876369322550071, -0.8723083916636201, 0.6419574139158084, -1.00657473616704, -0.7131802559475791, -10.57449072135191, -10.20410649815866, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.9061412862011, -961.8770732639229, 455.5376417683805, 0.06254419195417743, -0.4232684972590032, -0.1032882224080658, -0.4264012907068119, 0.1437641786514711, -0.4367775016311054, -0.1849091479680357, -0.4547230616343913, 0.2278125351396496, -0.4803659165556683, -0.2736445954407336, -0.5135240332136976, 0.3235038064582032, -0.5535385281539781, -0.3781288842484928, -0.5990476261198098, 0.4374274060989551, -0.3541391351405594, -1.058073342162964, -2.045216966325468, 1.266080794797456, -0.6924316493113732, 0.5950376234995193, -0.4851062828675501, 0.4482900280297341, -0.4257039247593362, 0.4069187711414488, -0.4232424419027072, 0.4083834788979941, -0.4493250721690615, 0.4314669583481853, -0.4903032612085907, 0.4662810430706394, -0.5378049265577316, 0.5078722409403839, -0.5859084246214689, 0.5542724904405595, -11.84485447706039, 2.898542856056091, 7.060252299552289, 1.630303727224056, -4.621383723680353, -0.8942453459292238, 2.951610305967167, 0.4895834794482448, 1.813545938433091, 0.2881843187274703, 1.040043542488245, -0.2094177206260044, -0.5137794499925029, -0.2034268577435624, 0.1527024933413826, -0.2401406725930453, -0.1004080668438968, 0.3021385233083859, 0.2854472563703663, 0.3800924576032388, 0.4303872415260588, -0.4699267499381296, 0.5551933085574434, 0.5711417670203969, 0.6747267714850889, 0.6859780125203653, -0.8010046828883495, 0.8192592301466893, 0.94515561658495, 9.820426173212363, 12.42939017103546, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 504.9930103786541, -961.9513356663066, -455.7221717257553, -0.08414743711096713, -0.2026736860667679, -0.1439128065966526, 0.1712281387505495, -0.2050964145610792, -0.1424763186319537, -0.2683067024845924, 0.1167626582609214, -0.333761142126125, -0.0948595784588155, -0.4009780128477423, 0.07811577117355756, -0.4684645116803408, -0.06843920146675211, -0.5335327087101004, 0.0679294038621997, -0.3239054824125787, -0.0116792012931699, -1.790663616927004, 0.4590524896071508, -0.5473106572190689, 0.2369585734237551, -0.3554648484778318, 0.1960271233909658, -0.2800877958506142, 0.1941244183782809, -0.2453078173802557, 0.2076091627418861, -0.2293383987055, 0.227046232106705, -0.2229498501452899, 0.2467672230652324, -0.2215577701206991, 0.2623437054600908, -0.2230571348710727, 11.53795815371153, -2.443315951606555, -7.483391968859528, -1.180817659033836, -5.101147725873458, 0.4291177015601163, 3.484008053855922, 0.006968221311336701, -2.401299468052032, 0.2524588129698827, -1.690603619495555, 0.3864574901609267, 1.238005582549325, -0.4584326101560443, 0.9641940337828574, 0.49897471755453, 0.8145568272198119, 0.5268294835097378, -0.7521215969515586, -0.5534552278380493, -0.7525858951277018, -0.5859592679598992, 0.8009010588386255, -0.6289928712031305, -0.8890676867080832, -0.6859830214698649, -1.014965640327654, 0.7599429084175442, -1.182234401254345, -0.8539617213615083, -12.58037930190747, -12.3224597531326, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -504.9867232586682, -962.0267397173889, -455.5858482841886, 0.08146568040030745, 0.4718570639702241, -0.1323792393628501, 0.4746520270081164, 0.1832926548394762, 0.4859370727590149, -0.2354260094769804, 0.5057808128620681, 0.2900438647951354, 0.5339800783871049, -0.3482656295242084, 0.5699120289626995, 0.410743635210365, 0.612307221970398, -0.4771765920828036, 0.3602759907915838, 1.17231410234708, 2.078779437679099, -1.355247085704674, 0.7092702971335834, -0.6327846462311433, 0.4983600087248974, -0.4713003995691609, 0.4384934063277775, -0.4210960673642488, 0.4367016135277066, -0.4152685840028347, 0.4637359288734594, -0.431277660159945, 0.5053758360548571, -0.4587373301787441, 0.5527030534382514, -0.4925622070803836, 11.91525071372664, -2.669737940207489, -7.112070179658535, -1.499950988056173, -4.695989395278955, -0.8264068408364236, 3.024764719308382, 0.4608488246132006, -1.873884959550882, -0.2834560461830024, -1.083707901266197, -0.2191901436954789, -0.5408889135616145, 0.2219393955259065, 0.1652261958197461, 0.2640887562841959, 0.09983770284304504, 0.3297673240943492, 0.2941272369903571, -0.4105473985768032, -0.4457746369230076, -0.5027821554303129, -0.5749124856717664, 0.6060241185316116, -0.6964125744179374, -0.7222036226954593, -0.8219917097087917, -0.8553991180861862, 0.961952339859114, -1.012160660965054, -1.126829376377705, -11.89125844216821, -14.82268386167739, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -505.1021960848271, -962.1169026393795, 455.8338729921806, -0.1071062110747086, 0.1815070603285521, -0.179150267652292, -0.1400998028560625, -0.2522503910014173, 0.1021004970621845, -0.3266542012589974, -0.06823635379950285, -0.4018139642522497, 0.03994126095184518, -0.4760406224002068, -0.01938011015157691, -0.5463234758642321, 0.009080595156260448, -0.332710657886771, 0.1616900475175027, -1.817966811669035, 0.3426834356104604, -0.5434318586351045, 0.1858789109600244, -0.3447965208108256, 0.1597482455188877, -0.260904925528362, 0.1625453870579868, -0.2153733000095499, 0.1761648327255745, -0.1866055914925562, 0.1928056464078325, -0.1656576200451232, 0.2073444379444271, -0.1482507898985436, 11.55984343995971, -2.194330913236887, -7.539191327935495, -1.023568455741856, -5.187360036320147, -0.328277306992068, -3.575805403221234, -0.07408649072083257, 2.486163835875462, 0.3004875937099439, -1.763663794387484, 0.4247125801810033, -1.298641369289637, 0.4926794598061576, 1.013844940412112, -0.5326247822284832, 0.855408835835386, 0.5617664880260144, 0.7863621255143287, 0.5906033658897508, -0.7819719026602904, -0.625663908357995, -0.8264736550053368, -0.6712690869377209, 0.9108668466439265, -0.7306688749077851, -1.031594825877172, -0.8068049947691155, -1.19005694174046, 0.9028377648786338, -1.393080617256989, -1.022486576162642, -14.93725702842511, -14.80858779518792, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505.0986792310538, -962.2097661716811, 455.6702293933568, 0.1053158391624666, -0.5209308336066629, -0.167801730661908, -0.5231587860538264, 0.2305615961092414, -0.5350545218265784, -0.2949981297092716, -0.5563330952365698, 0.3622987997093375, -0.5863529471226727, -0.4330778853603579, -0.6238972077621375, 0.5068738237225937, -0.3645929382416744, -1.269034197433159, -2.091002309996033, 1.426568270000934, -0.7184531759372009, 0.6617359656374076, -0.5062857257808602, 0.4866398522234159, -0.4468522920838534, 0.426758635928322, -0.4461365544464869, 0.4117361542474164, -0.4743095042403939, 0.4180529165899515, -0.5166800360497492, 0.4350417285374433, -11.93487401223153, 2.441424296363036, 7.120614763298893, 1.366543100975028, 4.739536856455961, 0.7537631620120923, 3.07601221737414, 0.4269745581475306, -1.918657953164775, -0.2740524529274999, 1.116076917175963, 0.22506572849195, 0.5595705076145522, 0.2373597796023182, 0.1712561169743348, -0.2856470413363019, 0.1044690985263356, -0.3555730312438909, -0.3071946247653678, -0.4396379038796807, -0.4651362087062904, 0.5346799860173224, 0.5985834061049665, 0.640392538677784, 0.7224826043854548, -0.7585342198697523, 0.8484129027006324, 0.8926513574029241, 0.9861836715435827, 1.048258602424987, -1.145257873605194, 1.233529400113939, 1.336236455566228, 14.30571745164884, 17.61787905052259, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505.2522684045481, -962.3209091459635, -456.0021243571045, -0.135204950106543, -0.1394617235875679, -0.220127550372105, 0.08571928452292403, -0.3049409043236431, -0.03659504642708369, -0.3890574180257759, -0.006436425325169574, -0.4706108350838175, 0.04096694825184889, -0.5462820434899358, -0.06401136348259447, -0.3343815237245166, 0.3770481192076843, -1.804641348780662, 0.1862488607745145, -0.5241026690461806, 0.1165329851236274, -0.3218108422408898, 0.1103182214298427, -0.2288701150093211, 0.1197089351929335, -0.1702872232337064, 0.1340809261902273, -0.1252999394856697, 0.1478955058540885, -0.08560365295523495, 11.52576378974406, -1.954372039977865, -7.556599118670414, -0.8696416229998727, -5.243139426145771, -0.2265893727803473, -3.645001180400495, 0.1444022525350471, -2.554614576511419, -0.3526936465053139, 1.824862320705907, 0.4673053399212604, -1.35071736012791, 0.531014596069754, -1.057368223650742, 0.5699553062659776, 0.8919929683549828, -0.5999463785086376, 0.8178418137071368, 0.630579143988404, 0.809941527510296, 0.6678139095408332, -0.8520024722473533, -0.7156241704641815, -0.934272389637509, -0.7770482361065687, 1.05215121053177, -0.8548848555187463, -1.205491122946197, -0.9521918975626668, -1.398620727934507, 1.072675726622418, -1.64131363116556, -1.220973810147752, -17.67939399433237, -17.69696009914344, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -505.253017754159, -962.4364747394324, -455.8036682152643, 0.1351126787098899, 0.5695864039965876, -0.2104884546621504, 0.5708245939994814, 0.2862709367223656, 0.5827540820095056, -0.3637808074554126, 0.6046421105793508, 0.4436589944498553, 0.6352690932451194, -0.5253459950861361, 0.3677303232551267, 1.347453344746686, 2.082926012424898, -1.479753805386014, 0.7203282114221324, -0.6816721371214693, 0.5093388325091368, -0.4939242839721554, 0.4515458590346876, -0.4232358982106663, 0.4527789299653081, -0.396731197291685, 0.482881928016134, -0.3902827551017815, 11.89894466315718, -2.22090063369331, -7.092747734361658, -1.234026593177227, -4.753181046423188, -0.6771950822291326, -3.104140201531702, -0.3866040328596608, -1.945692839472312, -0.2572635974024494, 1.134652874596721, 0.2236606491303219, -0.5673297987656002, -0.2460750486326881, -0.1685020505679479, -0.3012253263999956, 0.116250006339078, 0.3761133268443195, -0.3261558958623166, 0.4641080126177665, 0.4894613648488647, 0.5625417455833565, 0.6266107088037656, -0.6712930493524196, -0.7526658702381472, -0.7920386924545679, -0.8791718349910133, 0.9279565248449416, -1.015643135720146, -1.083803569712843, -1.170845050805069, -1.266390093671474, 1.354037366376675, -1.485576073474351, -1.576400237129784, -17.08748638019799, -20.84557350276546, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -505.4566106321672, -962.5733809140785, 456.2446669456525, -0.1688459112995087, 0.07034403444173644, -0.2661925457838576, -0.00201291370003544, -0.360842606721788, -0.05949303565750251, -0.4507864673737421, 0.1115494205452214, -0.5324222730975748, -0.150692878879795, -0.3285617939930261, 0.6352611728442655, -1.750928292301286, -0.01079073303553477, -0.4892798325673497, 0.02887167931331536, -0.2862455254245249, 0.04809364620457122, -0.1833951993284249, 0.06648914871000661, -0.1090258324830243, 0.08288235905924721, -0.04388087225057338, 11.42397334205316, -1.730411869135157, -7.54872126209005, -0.7246099232898299, -5.271259193087543, -0.1273016997487224, -3.689949677751227, 0.2168582799717596, -2.60315967042078, 0.4095966898831329, -1.869993120606597, -0.5156814339442469, 1.38982674111601, 0.5753023219269168, -1.090398441258875, 0.6129015965698307, -0.9200861758805992, 0.6431623698555172, 0.842501341267445, -0.6749156741454959, 0.8325483404989181, 0.713623361375966, 0.8735437835352988, 0.7629401789412279, -0.9551462767593792, -0.8256933589190248, -1.071962632591364, -0.9045223083409126, 1.222727743028186, -1.002327294123344, -1.410056693758905, -1.122638822704943, -1.640877341853048, 1.26995573475215, -1.927844246417485, -1.45003227706329, -20.82307411706698, -21.00155992122358, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505.4627685739322, -962.7160457792522, 456.0005200775191, 0.171584773148045, -0.6169168507138828, -0.2608304899009982, -0.6165570206329561, 0.3501697797170152, -0.627679892134454, -0.4403605479968019, -0.6489829640847168, 0.5308300518602039, -0.3709301239614179, -1.405815328723569, -2.058062413586543, 1.514443425105629, -0.7159719725315271, 0.692368587676033, -0.5085223559524636, 0.4927483234228063, -0.4539119844509412, 0.409786918662957, -0.4585601641836641, 0.369060795992091, -11.79766504079141, 2.012479939028762, 7.043555197226082, 1.105137043752469, 4.741914128289426, 0.5972094437860065, 3.109868363286502, 0.3381216846268515, 1.953867566077465, 0.2299457233923843, 1.137533669668121, 0.2109462622238532, -0.5620043637972509, -0.2436579564637029, 0.1548443572169821, 0.306307345836395, -0.1370525568840376, 0.3869435542219369, -0.3524856590577575, -0.4796460558277326, 0.5197151476832278, -0.5821783731153887, -0.6593590868915518, -0.6946136487705999, -0.7866414714126642, 0.8185951248778229, 0.913148489829942, 0.9570365064732725, 1.048232753669613, -1.114138187570384, 1.200190769798651, 1.295704602378807, 1.377356049197987, 1.509847257194258, -1.589258765649288, 1.768262183131415, 1.848069109594906, 20.23420853365266, 24.50766781694805, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 505.7302235739897, -962.8808897579297, -456.5799751938149, -0.2074665694865197, 0.03179270034629982, -0.314911648796822, -0.1160409354435016, -0.414899941317193, 0.1896042423128672, -0.5035929949910716, -0.2485406654930217, -0.3148720318285624, 0.9334281744469859, -1.658358518134329, -0.2459729705045449, -0.4395368675508144, -0.07575020637815727, -0.238298110932487, -0.02543448920587639, -0.1242798269864487, 0.00493022955061947, -0.03092176867721523, 11.22885110571361, -1.52501965073773, -7.543615992492188, -0.592424165410839, -5.281049101322963, -0.03384112642572992, -3.711740461545836, 0.2895170179898658, -2.629192995613142, 0.4707504030082303, -1.894805671641967, 0.5704662427677495, -1.411023004415436, -0.6267630427501154, 1.107747137626518, 0.662893542409588, -0.934479879776553, 0.692778028843108, -0.8551991883552512, 0.7247338818733859, 0.8447234697913153, -0.763869215310247, 0.8860283550216375, 0.8135940022344247, 0.9682811777983255, 0.8765586475933742, -1.085448060890765, -0.9552512796328857, -1.235412367552187, -1.052408869707694, 1.419557246828857, -1.171343028943237, -1.642863640112578, -1.316259793628108, -1.914688728881414, 1.492601140725079, -2.250602542324417, -1.707371208414184, -24.34911222913227, -24.69682337532403, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -505.741435494995, -963.0504155847199, -456.2741036613125, 0.214479472715505, 0.6621861981953745, -0.3177872890555592, 0.659477202360043, 0.4199363883935496, 0.6686966992655288, -0.5204604440629446, 0.3760250100904552, 1.440136329901755, 2.022077415101587, -1.529242860821105, 0.7070177320978236, -0.6931608182158253, 0.5052503305200324, -0.4823639976910435, 0.4557292865512613, -0.385316970783089, 11.61106437256959, -1.818394061749481, -7.001963622764721, -0.9813357744591734, -4.716881178048456, -0.5141556100260524, -3.0969906159148, -0.280097039848389, -1.943793145915662, -0.1889996708430733, -1.123912478997343, -0.18264542910118, -0.5421787669130134, -0.2251582877779384, 0.1286970772462299, 0.2956319802801666, 0.1683473607021652, -0.3827115546150297, 0.3873303842983701, -0.4809087334725033, 0.5565590506576561, 0.5882754140327704, -0.6968797879222629, 0.7050226515021639, 0.8237435880499643, 0.8327756810598531, 0.9488550233241532, -0.9742434109257527, -1.081502395328126, -1.133196471873608, -1.229668358197086, 1.3146823158554, -1.401016876114531, -1.525516610156299, -1.603885466468684, -1.775180446964151, 1.848426978531237, -2.07736997486411, -2.148126517552196, -23.69694322453203, -28.55450387022301, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -506.0870994444517, -963.2380980143934, 457.0227998243373, -0.2485169973393713, -0.1708755956446555, -0.3608775819654662, 0.2702463148020641, -0.4583288971296218, -0.3528976210982101, -0.2928214663649001, 1.263652831351624, -1.529505325655311, -0.5130238387785291, -0.3760704452139064, -0.1942204111583247, -0.1786533015765691, -0.1073884668217014, -0.05177939288958904, 10.88603291358535, -1.337180308687955, -7.596957579622598, -0.4747035515000937, -5.293796730009392, 0.05043538802520772, -3.716922670417109, 0.3592165384067125, -2.632466505734362, 0.5340539274802235, -1.895818658518178, 0.6306645190841967, -1.409275395512805, 0.685196075280273, -1.103655066088433, -0.7201507688034566, 0.929097908006366, 0.7491204140241028, -0.8497455883339168, 0.7802302755862421, -0.8402329799755162, 0.8184522926487809, 0.8831625818888247, -0.8670840673667023, 0.9672225533587266, 0.928669763681313, 1.085819612885373, 1.005581967725039, -1.236140490171399, -1.100404676155905, -1.418629151651308, -1.216231218475, 1.63686735128274, -1.356940773255257, -1.897950583839266, -1.527515842606489, -2.213574416593122, 1.73441741027332, -2.602284267564217, -1.985971407789865, -28.17877747730259, -28.69146328143491, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 506.0995030305882, -963.4251163002542, 456.6319082336776, 0.2614208946746435, -0.7049929537479934, -0.3775469776448249, -0.6990129299253891, 0.4897228036148983, -0.3853539179729928, -1.442770760684808, -1.98216326068838, 1.520548699194699, -0.6953740263821517, 0.6824190354472228, -0.5011233283967811, 0.4613118931865929, -11.29796537330876, 1.64449147211759, 7.022169169615215, 0.8641805347117423, 4.699276336140136, 0.4291404936096105, 3.07407334406547, 0.2123539984677152, 1.918769023964996, 0.1324679335590006, 1.09476296754075, 0.1352170432778689, 0.5077652860572863, 0.185910694584077, 0.08952722613195557, 0.2638426913931702, 0.2107393703819989, -0.3576622830692115, -0.4310960937466334, 0.4619085175014147, -0.5999884739982514, 0.5746756856778464, -0.7385868745992383, -0.6961886963160135, 0.8626657356149082, -0.8280065670824533, -0.9841390899478625, -0.9726569738046391, -1.112325598821782, 1.133551592359431, 1.25500535004336, 1.315134855586846, 1.419345051714987, -1.523232765666847, 1.612773491431782, 1.765677755404849, 1.843930722061922, 2.053380737994717, -2.123837663941296, 2.402145835888836, 2.467526732917271, 27.35441123139784, 32.85590905559759, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 506.535108831963, -963.6167931351213, -457.5765788302061, -0.2861761743318959, 0.3461105740480527, -0.3947395339422998, -0.4564377447058072, -0.2617296324114806, 1.611734008281398, -1.367678013419382, -0.8010059019283635, -0.3006880659872381, -0.3213053025395997, -0.1085392364738896, 10.2725543041519, -1.168526626564622, -7.82064895354263, -0.3713337568773262, -5.352508738636831, 0.1222893217356636, -3.722102280656161, 0.4211608377876347, -2.617734196748431, 0.594901972075254, -1.871992486237874, 0.6925901148668441, -1.38058734154616, 0.74787922336183, -1.072581160949938, 0.7826644587414839, -0.8975809094419182, -0.8105767210582541, 0.8193405723194567, 0.8399098661914142, -0.8120222073214457, 0.875770220099946, -0.8576881155650289, 0.9215289264833487, 0.9444708197958593, -0.9797395325755353, 1.065205863140835, 1.052722623302901, 1.216460299462672, 1.142943964195683, -1.397905992342116, -1.253291158068077, -1.612055771894061, -1.387322544088788, 1.864373007497077, -1.549535917211965, -2.163879565979816, -1.745709327273886, -2.524523036401785, 1.983325027495365, -2.967830167452788, -2.272019538910634, -32.14658674016512, -32.79917505195669, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -506.5385766328296, -963.7950492893284, -457.0688147458119, 0.3064737493454045, 0.7451295489392065, -0.4320824231461616, 0.4015780387117531, 1.401276142639599, 1.946107688605819, -1.48150526542528, 0.6828643239680722, -0.6570927744752225, 10.7638914509755, -1.517523554864524, -7.212410025151229, -0.7594650802490791, -4.727779988834981, -0.3459479511652795, -3.056982946412603, -0.137792378203823, -1.885965897429857, -0.06147034578463532, -1.053619513536147, -0.06771520575915954, -0.4606626658479292, -0.1231959710791077, -0.03846712123960974, -0.2069083481076168, 0.2634078610725342, -0.3068550531907182, -0.4829610805074276, 0.4170585080045313, 0.6489288141016536, -0.5352933146117154, 0.7829424333419256, -0.6615771584317809, 0.9012282823913962, 0.797293809624204, -1.016026767128407, 0.9447489034757597, 1.136789528309099, 1.107026430413602, 1.271196791521118, -1.288051047513149, -1.426037977791292, -1.492842932266066, -1.60802186802236, 1.727960361905206, -1.824590624194746, -2.002232368690374, -2.084863210703189, -2.327985171787624, 2.400861196107053, -2.723108602478969, -2.789278491542184, -30.98867169157857, -37.17333705763805, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507.0685285381397, -963.9513225378075, 458.2239814297878, -0.3105094100833926, -0.5489621604214274, -0.2207001619135986, 1.956288574692065, -1.176681603230856, -1.09375598392015, -0.2158081274278867, 9.039432404200522, -1.044683628994101, -8.468785467802409, -0.2840135792540254, -5.542745543449104, 0.1779572946344857, -3.761606785421675, 0.4684797722662275, -2.598930526573113, 0.6453592933930452, -1.827562760363265, 0.7487181877066253, -1.324101584715386, 0.808286952945908, -1.010847733279209, 0.8449471423636297, -0.8346332998503472, 0.8724833572892089, -0.7577244949265606, -0.8996473668870159, 0.7532210193109008, 0.9319700291879087, -0.8023001449790493, 0.9731169256921198, -0.8923272475697563, 1.025808942383718, 1.015464062032189, -1.092414194595597, 1.167634916611444, 1.175336052505714, 1.34782203022553, 1.277290630873182, -1.557658237162463, -1.401532229855291, -1.801354910586623, -1.552090405661354, 2.085991956058786, -1.734049468830996, -2.422322212155974, -1.953922901839827, -2.826392120689291, 2.220125678702697, -3.322576673428888, -2.543480350687961, -35.98052650947123, -36.71809122641062, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 507.044358239568, -964.0731038498507, 457.5609921269437, 0.339186245230021, -0.4273969477024003, -1.29863116329144, -1.9212155175519, 1.401898391182813, -9.726271535257508, 1.553331598619713, 7.831565439526993, 0.6875158984530817, 4.876888986260434, 0.2743174969664351, 3.073278715408381, 0.06481527948414105, 1.857848936458911, -0.0172058553164797, 1.007270300003323, -0.015493908041739, 0.4052734656641692, 0.03886914827152865, -0.02120544418256508, 0.1245454447689218, -0.3236527085621929, 0.2283392770229724, -0.5404903245807748, 0.3431422365149781, 0.7009598725924222, -0.4659137295498349, -0.8273152365264473, 0.5961381254254794, -0.9363871554481444, 0.7348226673958823, -1.040881025210011, -0.8839501590062537, 1.150503496114657, -1.046240633846492, -1.272940104510185, -1.2251386270737, -1.414709746711867, 1.424957765640063, 1.581930391736834, 1.651204358082938, 1.781057179003545, -1.911084747398959, 2.01966517958886, 2.214321569792053, 2.307406860022854, 2.574510651133963, -2.657307283406697, 3.01140106208788, 3.087681881697911, 34.27753948458455, 41.14981894020637, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 507.6607402118162, -964.1324178062038, -458.9202293050566, -0.1686378441806772, 2.26918481619089, -0.9605814475857066, 5.330862093858574, -1.138949076550252, -10.32445599072876, -0.2278821376240088, -6.053185271755386, 0.2111992660067487, -3.90195016026017, 0.4916948027703619, -2.604992480633718, 0.6736549508248011, -1.775821097551055, 0.7869195888388132, -1.245117363143849, 0.85511197805049, -0.9191931180792211, 0.8969679044521599, -0.7382433689234038, 0.9261198029941115, -0.6611696707630135, 0.9518531231496314, -0.6589875072665196, -0.9803308643977939, 0.7113879440961655, 1.015736615269503, -0.8045956932013681, 1.061136120387407, -0.9298638326235749, 1.119078818816151, 1.082360654284157, -1.191995373104534, 1.260356303986052, 1.282483463463084, 1.46470232087969, 1.393532235248562, -1.698581785001543, -1.528731717952134, -1.967581344572053, -1.69251044093007, 2.280123193492441, -1.890433165088037, -2.648431439034473, -2.129603108392172, -3.090370039310071, 2.419171909638182, -3.632813078727661, -2.770878258545604, -39.30905440906147, -40.04060379184506, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -507.5823569101401, -964.1327952153448, -453.1525519625071, 24.40574541777206, -56.14514099816383, -2.422186406437542, -25.22429964965732, 1.444867813899084, -12.70852566601807, 2.547941134817951, -6.850174344806808, 2.975175307411678, -3.480196946314358, 2.990960801627664, -1.417378358439735, 2.740289627402432, -0.1451237393712128, 2.339923467563752, 0.6224326970934283, 1.877490924183014, 1.064055147754233, 1.410245383546048, 1.298670025286794, 0.9699280356465935, 1.407692033072784, 0.570056365428795, -1.447206482446987, -0.2126606347621276, 1.45549590027687, -0.106700427367443, 1.458217449192367, -0.3956662520866513, 1.472227262174601, 0.6631737994890589, -1.508479947856337, 0.9184906204287088, 1.574231058518403, 1.170872531544465, 1.674716872315271, -1.429622942231864, -1.814460422530907, -1.704464741494625, -1.998356318905909, 2.006172401087063, -2.232676942948992, -2.347554579943283, -2.526186304333157, -2.745015993852846, 2.891570896342571, -3.221095840304374, -3.347521504585615, -36.81977934526557, -44.35189490614219, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -929.5916205582998, -941.0365306526329, -83.0205570677121, 28.17439325219577, 75.87533570257695, -1.696520866989221, 26.60699159785555, -5.409361115615388, 12.56934180801319, -6.877261269176024, 5.687519948140556, -7.195311665250237, 1.882753730836734, -6.793257487426405, -0.243954230030588, -5.985952308839798, -1.376766663139118, -5.007212173644259, -1.909776318300887, -4.012480308119807, -2.086793153052898, -3.09156896456971, -2.063263714473415, -2.286718302219568, -1.938915871123262, 1.609507069182077, 1.776860515294737, -1.053845022404726, -1.615732919376842, -0.6048003006133782, -1.477928334454509, -0.2440699657679927, 1.375377784059099, -0.0469141625735761, 1.313620215666728, 0.2854287861559656, 1.294663638447388, 0.4868539710419071, -1.318984666977386, -0.6646185691294326, -1.386978049510149, -0.8304585614062736, 1.500098994703478, -0.9948396546158864, -1.661963350617514, -1.167481907502111, -1.879718152404978, 1.357937431688009, -2.166151621008019, -1.576149522040385, -22.8426934593021, -23.12611835160169, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39.74325951288207, -1186.431523127095, 891.9981651399358, -63.78630277783328, -227.1996575944138, -21.36263524515902, -134.9940747033731, -11.91053467248452, -92.38872197451053, -7.137773558531492, -66.40883312595787, -4.159839971417969, -48.55372147263157, -2.266393752869894, -35.63597637393651, -1.094787188040574, -26.12268218585725, -0.3740073215893996, -19.11470230422248, 0.09756406262595478, -14.00177931344374, 0.4539441356094622, -10.33193495392373, 0.7738574705683541, 7.757284995888257, -1.098280483037155, -6.008113485615493, 1.446238834722165, -4.877217783576145, 1.8260185749213, -4.208135864627979, -2.242051708641171, 3.885327967594733, -2.698727377102662, -3.825903864288941, -3.202420566106344, -3.972879079281471, 3.762630114298621, 4.289949398982492, 4.392965687767301, 4.757754982238793, -5.112366708632306, 5.371588692477695, 5.947098472803463, 6.140643591545218, 6.934244894234055, -7.089006463457302, 8.127774292215216, 8.258953377781268, 92.70654077487185, 110.8916502269361, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 786.2689336767368, -815.9863464302587, -502.0050839453779, -90.73950140949509, -56.87432228337573, -51.99165992440596, -33.34091308622924, -34.04113075780467, -21.43377478029886, -23.06225529920733, -14.14681954842458, -15.59204793972567, -9.417386184375989, -10.29776713475104, -6.330831000664216, -6.493371297236832, -4.358412747427537, -3.752309549753657, -3.152344856102681, -1.780646844936822, -2.474087100314609, -0.3652993582829661, -2.159473586844666, -0.6519861739832791, 2.096803744336349, 1.389930130712824, -2.211583888600316, 1.937926207260219, -2.455755504596307, 2.363440987643714, 2.800164407662094, -2.717650504667941, 3.229401718516578, 3.039864785640401, 3.738480085017688, 3.361030069362782, -4.33092205126337, -3.706511692235448, -5.018136256707792, -4.098399590204935, 5.820036523452692, -4.557455346103694, -6.767262056924007, -5.104890578388991, -7.905837082177761, 5.763931574597367, -9.306048512065884, -6.560810197006163, -99.50178779115197, -96.99432423638203, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -321.507651312602, -910.0072663299117, -591.4192374647588, 2.348605212951472, -124.3655421160505, 2.519037737123322, -84.26548427045947, 2.573811571186274, -59.67166318149743, 2.542520312756454, -42.7047736707389, 2.300331152371294, -30.40208946365, 1.868906337655643, -21.33294075666419, 1.342284397278395, -14.64893633535513, 0.8120400288034471, -9.763872639971726, 0.3354516359221829, -6.235124240181859, -0.06553144651026029, 3.716540641341441, 0.3931256138944335, -1.936614843167815, -0.6618294981785842, -0.6848912674945181, -0.8900811776756501, 0.199127185761292, 1.095738020332698, -0.8359393889447138, 1.294255063198197, 1.31492328463649, 1.498467646770268, 1.702006092723583, -1.719202962560454, -2.046109758511857, -1.966270920929146, -2.384503193805934, 2.249628522569334, -2.747318106025392, -2.580712635786556, -3.161596749861384, -2.974131519986319, 3.655356432931151, -3.449999148965924, -4.262437651783252, -40.50763259878801, -54.03571513338518, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -344.0713331149046, -952.725510121053, -416.8443995257026, -1.06754986885831, 45.84646413547254, -1.058403868892041, 31.77101137436911, -1.019954379151325, 22.80926291367322, -0.9071659718312616, 16.5022307529763, -0.7068440514134203, 11.86549955113823, -0.4524387095841191, 8.40538251216984, -0.1887047159960708, 5.82217952814256, 0.05065134824649881, 3.9055606710333, 0.2489662036219396, 2.495002070050333, -0.4034520268008114, -1.463934384255092, 0.5196357992327747, 0.7123003579271661, 0.6066099511692123, 0.1617857928516114, 0.6740824416340541, 0.2481361170724213, -0.7308946494537877, 0.5637692276795909, 0.7845255109986143, 0.8204101808272708, 0.8411152733767217, -1.045170820232432, -0.9057592610820282, -1.259454345228306, -0.9828579943559127, 1.481169292533973, -1.076498380875339, -1.726879905570609, -1.190773320672958, -2.014212738164722, 1.33001392092199, -2.365085594225679, -1.498734072363048, -24.7211856905308, -22.78270797180551, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -442.6907539702701, -958.4534825933663, -525.0790057885872, 0.4830776577375593, -34.3647256467903, 0.6314006455905202, -24.3348172625214, 0.7058287395586245, -17.41434346405917, 0.6762376591103615, -12.39697921157262, 0.5581637364705839, -8.69979036834804, 0.3923850266317464, -5.976507461418807, 0.2173455777493897, -3.987524183530083, 0.05722832788370733, -2.551827878146577, -0.07817291001085155, 1.527904886231801, 0.1888356566437113, -0.8048407679343973, -0.2797226979198223, -0.2967379564291665, -0.3574286627927332, 0.06184616772257682, 0.4283754863248733, -0.3199942490552064, 0.4980819539573895, 0.5140709901171847, 0.5710827814267276, 0.6708672126762525, -0.6511525664070008, -0.8102397807569323, -0.741692223923563, -0.9473054632669835, 0.8461535960354408, -1.094295489000015, -0.9685246843169275, -1.262227087133157, -1.113917136472349, 1.462601455450445, -1.289351439294402, -1.709469206945622, -15.37887836207466, -21.35497052390839, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -428.3101323308657, -960.7693411578422, -474.342891355963, 0.04496720051684034, 19.40931799070891, -0.1673280524757375, 13.92731470257143, -0.2557102683826377, 10.07353665325728, -0.242060653548165, 7.24394212742543, -0.1622596506986207, 5.13483244576956, -0.05331961081104578, 3.56174021542921, 0.05739982125560644, 2.395487323148687, 0.1547037661558607, 1.537813226473135, -0.2331433212654467, -0.911475734135779, 0.2933066494077648, 0.4555476781368759, 0.338711646959178, 0.1224074525370889, 0.3738275323799262, 0.1247194820414306, -0.4030263556972666, 0.313950693100759, 0.4301452572858044, 0.4667062381065167, 0.4584109424144206, -0.5994212319450118, -0.4905216003205117, -0.7250428404204554, -0.5287981906358582, 0.8543669982497838, -0.5753440721198483, -0.9973355647586041, -0.6321710321880218, -1.164486942694627, 0.701242039243045, -1.368908791826208, -0.7842864184450526, -14.12684531258338, -12.34623872489789, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -453.5947291948034, -961.2035052944622, -514.6492553039509, 0.4825672633043259, -14.63884772835812, 0.4728625789819674, -10.46609788926318, 0.4223503876316634, -7.442448460093368, 0.3329214300137407, -5.216277203642393, 0.2244794898769337, -3.578425180158726, 0.1168914409785088, -2.383907106504585, 0.02230924598695424, -1.523064408492582, -0.05507450668021285, 0.9101446618023145, 0.1163992499184654, -0.4779690543716839, -0.1653691281434937, -0.1745659182869991, -0.2063444223336585, 0.039602682285727, 0.2433424061835201, -0.1941384821064465, 0.2796828695057331, 0.3109312828739628, 0.3179775825463946, 0.4060797546311572, -0.3603111282843304, -0.4915070533384577, -0.4084758403447379, -0.5763074319912898, 0.464226600596208, -0.6678922566067029, -0.5295368917237421, -0.7730382893753434, -0.6068884203575737, 0.89897954742318, -0.699610046209151, -1.054787068983536, -8.609652087354156, -12.8579032884007, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -446.0038881412778, -961.3008847776382, -491.7175432274707, 0.1943007163358473, 9.906958572878336, 0.02345340704111558, 7.173866633051514, -0.04242250621999444, 5.166677008312024, -0.03855525151603313, 3.669944479628774, 0.002466257542828118, 2.552845379807538, 0.05656495909653988, 1.723914622877545, 0.109389231273188, 1.113704343754537, -0.154326556966241, -0.6676835332672917, 0.1897295486417266, 0.3428450695372164, 0.2165827955413441, 0.1055512320135479, 0.2369862849228626, 0.07020719515760521, -0.2532876029564753, 0.2043491608705294, 0.2676915043075377, 0.3120764248151033, 0.2821088161452195, -0.4050727622745833, -0.2981576244336274, -0.4925541862044852, -0.3172019895469589, 0.5822117700075157, -0.3404097672817541, -0.6811329794436601, -0.3687673652742239, -0.7968425416319206, 0.4030092522096378, -0.9387219855322787, -0.4433201240139981, -9.48396669353969, -7.512457904532764, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.4328410845339, -961.0071327788293, -510.5524809166798, 0.4111184351918524, -6.829176411984103, 0.3361386406116716, -4.837760995294381, 0.2502764457319974, -3.37603312459292, 0.1626067927924462, -2.304361871960009, 0.08316396128852019, -1.525802347503765, 0.01755632843579077, -0.9670336043134922, -0.03330222974734559, 0.5708045845795261, 0.07150324591409365, -0.2923816210281723, -0.1003945101884875, -0.09727229178655826, -0.1234001397404901, 0.04066183518259721, 0.1434628037600845, -0.1409083950734027, 0.1628660783751044, 0.2178168134361163, 0.1832999676758237, 0.2819041405558238, -0.2060026677157682, -0.3409546634835108, -0.2319393727963857, -0.4009411424908401, 0.2619589247865226, -0.4668200628062795, -0.296933951573955, -0.5432787484033776, -0.3378788989574256, 0.6355506795869581, -0.3860209451465164, -0.7505093709414847, -5.105954891950948, -8.781352077679234, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -452.3304115985688, -960.7608316563131, -498.9493530569109, 0.2350526026148503, 5.452765778836735, 0.1144413317324554, 3.942743416705443, 0.06575193956155491, 2.813198060193881, 0.05979656827468521, 1.967247253532042, 0.07476481999950792, 1.33716927453409, 0.09679248669884244, 0.8715028539151225, -0.1184142632347635, -0.5297539525430655, 0.1364376500843866, 0.279883315023392, 0.1501362016677295, 0.0967277743463185, 0.1600101117691853, 0.0392623455333137, -0.1670646460060667, 0.1431394010753874, 0.1724122128993197, 0.2264583241675105, 0.1770984549392259, -0.2981564198474064, -0.1820260600993679, -0.3653319148757525, -0.1879277629602221, 0.433953340411416, -0.1953399947167113, -0.509568285645821, -0.2045344918635905, -0.5981230469754966, 0.2153519198444021, -0.7071121725209079, -0.2267809863092065, -6.916134867991262, -4.577761093605716, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457.2821812366932, -960.4249791586459, -508.406803593705, 0.3314600419524246, -3.131681676256192, 0.2387019139078725, -2.160834219382301, 0.1558482495866747, -1.455216313053963, 0.0871664614814559, -0.9473663287775979, 0.03419837662062589, -0.5864332248384088, -0.00432458333663224, 0.3329441537673535, 0.03128353627523617, -0.1562804280922136, -0.04999176058110387, -0.03302664185232766, -0.06346986930062509, 0.05440406541970694, 0.07411879158850035, -0.1190014687949248, 0.08368929303132233, 0.170242902230307, 0.09336390814052453, 0.2150244781654537, -0.1038994057814532, -0.2584450235024301, -0.1157578492126067, -0.3044688209695106, 0.1292115445076401, -0.3565100159947209, -0.144401977523982, -0.4180074998279228, -0.1613341173509704, 0.4930955968984639, -0.1797468301316631, -0.5875758018381303, -2.883918681365754, -6.475332235697652, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.0155128763931, -960.1981319999863, -502.3405067762259, 0.2542491852062611, 3.131489617552865, 0.1670909868692584, 2.252853211778165, 0.1252928337711295, 1.589512082778476, 0.1095856577497441, 1.091340808355062, 0.1069182126000217, 0.7200044935476559, -0.1094190566032491, -0.4450831238377702, 0.1128668647285452, 0.242278665253527, 0.1152987829103931, 0.09231415427747117, 0.1160486567327278, 0.0199468566918988, -0.1151073353429353, 0.1062892592500759, 0.1127688588569004, 0.1758680910212436, 0.1094184084764459, -0.2358574126255636, -0.1054171918706391, -0.2920380304032841, -0.1010121781961295, 0.3493514987155218, -0.09624584560739964, -0.4124750394872714, -0.09081842264154093, -0.4865154108104184, 0.08383114316573474, -0.5780232680965639, -0.07323520324207744, -5.417494102776475, -2.610329978177295, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457.4493352528837, -959.989698663586, -507.1401709474283, 0.286121368416555, -1.277585644216466, 0.1965314549725704, -0.8296361757391397, 0.126150204699882, -0.5143609771621193, 0.07411570076725935, -0.2955753603877085, 0.03772510850741548, 0.1456031206933647, -0.01346154359781873, -0.04333286374184881, -0.002152095041771392, 0.02709212845432325, -0.01203934086886425, 0.07735364223423614, 0.0184196895883106, -0.1159068759281938, 0.02282300685654621, 0.1487971666617892, 0.0262064128753012, 0.1803514533516238, -0.02907864514102102, -0.2137591327763108, -0.03161342078618522, -0.2515671959433391, 0.03371538499219204, -0.296132352891611, -0.0350175049709756, -0.3500936488703787, -0.03478013453039555, 0.4169709529674968, -0.03159734770668429, -0.5021045752952693, -1.359189375072352, -5.137658691990629, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.1816434524407, -959.8717700049582, -503.9632365405722, 0.2710790852321758, 1.868103062408168, 0.201731258488131, 1.336518241630041, 0.1607751340471668, 0.9312150774562233, 0.136744864573931, 0.6245135082334604, -0.1220039814863793, -0.3939736948288325, 0.1118064051450731, 0.2212852465254199, 0.1033807000084225, 0.09161715516324435, 0.09519253715708004, 0.006912715432142194, -0.08645745594199336, 0.08374228844933723, 0.07681239647201249, 0.1463556032104103, 0.06610891321647951, -0.2007459498469933, -0.05425819168043056, -0.2518586281471307, -0.0410971094331229, 0.3040320723461977, -0.02624784596427822, -0.3614859250552229, -0.00891781755958999, -0.4289462964027577, -0.01244251094956762, -0.5126072586924517, 0.0408259308513107, -4.58392784156386, -1.246428269166816, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457.3475780693374, -959.8013715842148, -506.3396543584333, 0.2767928687754797, -0.3507679094211566, 0.1964561308894208, -0.175454380884666, 0.1369018349817932, -0.06171313754209207, 0.0948996407982716, -0.01057868944381583, -0.06660941623334156, 0.05625273023108911, 0.04841249702381548, 0.08604193382443961, 0.03731356346471822, 0.1075373379529352, -0.03107613794426697, -0.1259926823207867, -0.02817283438261568, 0.1449896389440946, -0.02768249041446454, 0.1669869201040142, 0.0291682437735234, -0.1937749805283248, 0.03258348528255475, -0.2268682319663226, -0.03823766887670215, -0.2678770945127273, 0.0468458004168191, -0.318925108122332, 0.05970717770473746, 0.3832225686061499, 0.07913811719945757, -0.4660307877839935, -0.283439945606522, -4.418862273762176, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.6253594082521, -959.785934980976, -504.6940382140627, 0.2905146476860859, 1.164315682401765, 0.2287874192618208, 0.8278901909084367, 0.1855742595690876, 0.5670794972681463, -0.1543255466444327, -0.3664024755348232, 0.1304088025212251, 0.2126108080946933, 0.1106574375165147, 0.09451778970188139, 0.09297359092819958, -0.00282311457116445, -0.07598524984762452, 0.07011698901922347, 0.05880426133990931, 0.1305654348080172, 0.04082738142446098, -0.1837050518882388, -0.02156733869032677, -0.2339588783576583, -0.0004920786516655548, 0.2853442102851388, 0.02315710617373445, -0.3419026525153549, 0.05062046787596538, -0.4082936953470016, -0.08404423049499717, -0.4907590591221084, 0.1273101919619071, -4.206720311439787, -0.3002127507778516, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -457.1342767647928, -959.8106159477925, -505.8018624707027, 0.2900898798822178, 0.09138444482380856, 0.2187118527593231, 0.1292492004000186, 0.1662045097025605, -0.1438635095448789, -0.1291313858324679, 0.146482412369866, 0.104009216338187, 0.1447220224795449, 0.08785328495101051, 0.1435558243554511, -0.07835861397425346, -0.1461036208296098, -0.07391291396692715, 0.1542496939603918, -0.07351683292489485, 0.1691302490659806, 0.07668777947971103, -0.191528688062261, 0.08339243901741469, -0.2222158695109802, -0.09404049750512089, -0.262283667277891, 0.1095744988108133, -0.3135425638449527, 0.1317142932715506, 0.3791044132771236, 0.1635054212875869, -0.4644162154949849, 0.4754117380195617, -4.133127727067452, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.7075938580194, -959.859187561279, -504.9641545879152, 0.3112115826946246, 0.7603819900412184, 0.2515787922254607, 0.5346525976842389, -0.2046698188884306, -0.3549498970832715, 0.1667993851467113, 0.2128194443512869, 0.1349829906843502, 0.1004097453865731, 0.1069128978938258, -0.01069617548430252, -0.08086180012056307, 0.06245121559445837, 0.05554789383536447, 0.1243240851970876, 0.02998652907082099, -0.1795147550946357, -0.003335227685768387, -0.232122564808795, 0.02527939571162375, 0.2860328739068638, 0.05697314553891727, -0.3453056616278151, 0.09340770900657025, -0.4147626826939698, -0.1373004236343103, -0.5009888584183517, 0.1933830034629809, -4.165639675833453, 0.3383554269676927, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.8782696374187, -959.9297648403151, -505.4159286188464, 0.3121561806109645, 0.2822056061123752, 0.247980497057797, -0.2569956304425891, -0.1998295916895239, 0.2284297348242049, 0.1650722678022543, 0.2029125660834568, 0.1410884792635043, 0.1841746600175908, -0.1256771230171495, -0.174184152010238, -0.1171886991653117, 0.1738211936975961, -0.1145301840222644, 0.1833868779235939, 0.1171275690499658, -0.2030007615539205, 0.1248977602701297, -0.2329370726129333, -0.1382764499321328, -0.27395747110102, 0.1583471608991634, -0.3277192476797476, 0.1871380238475298, 0.3974011701543539, 0.2282921486952801, -0.4888358484669846, 0.9965699211078363, -4.174355176167373, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.6116649438044, -960.0038871245156, -505.0023454177997, 0.3295930205438109, 0.5143442094150634, -0.2695356906932027, -0.3518849459077303, 0.2184195529530754, 0.2177473194353936, 0.1742696183299925, 0.107588929061941, 0.1351123343048535, -0.01670816731731302, -0.09919323231873232, 0.05953720029339046, 0.06503073496805913, 0.125532380449224, 0.03137214041729913, -0.1853658264427238, 0.002916428236328955, -0.2429142837357705, 0.03901258336924512, 0.3020465696948311, 0.07836548079886681, -0.3669787240345666, 0.1230474258479728, -0.4428645014247397, -0.1763255542849716, -0.5368662993446999, 0.2437700678950443, -4.391525855268358, 0.7382567408086977, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.6126089063781, -960.0836158047517, -505.1187555600291, 0.3334848577914001, -0.348428051728459, -0.2752367222186492, 0.3006944638633078, 0.2302721093152811, 0.2591967524250096, 0.1970876226025629, 0.2278690906060197, -0.1740115500094767, -0.2085463212280925, -0.1595867622233282, 0.2018162461301135, -0.1527406251408078, 0.2076385119268662, 0.1528504282670753, -0.2258110308909343, 0.1597827219954589, -0.2563523040186093, -0.173969694548823, -0.2998702186943654, 0.1965747840879211, -0.3580175279469813, 0.229863604568186, 0.4341837938265395, 0.277970170008693, -0.5347627558106645, 1.329764914690779, -4.483596648143033, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.4349056684294, -960.156647229524, -504.9319775147893, -0.3423523620698637, -0.3475550534848461, 0.2809466994778753, 0.2215706829932298, 0.2255846777578883, 0.1128246391312395, 0.1754514594654858, -0.01937340515435665, -0.1292864557086762, 0.06168462942056975, 0.08573413224271821, 0.1336954218460845, 0.04347198911094055, -0.2001906469386318, -0.00119376064663685, -0.2648271503726893, 0.04251266830607562, 0.3315045719474604, 0.0893994185444924, -0.4046778456006963, 0.1419228134888831, -0.4899638274253278, -0.2038944668407005, -0.5952966220065167, 0.2817106712351145, -4.848415701454543, 0.9427020574859393, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.3526903101317, -960.2239683681914, 504.8729234307502, -0.3489451907029376, 0.3589886699197148, 0.2961466969614354, 0.310480710370148, 0.2543129428137268, 0.2722939468109425, -0.2230677496498586, -0.2472988907469534, -0.2016181817997352, 0.2366019906197148, -0.1891922917107881, 0.2403800750135453, 0.1852769979754018, -0.2584933857871972, 0.1897672879791922, -0.2909693456884552, -0.2031063479701883, -0.3384573551697876, 0.226529417912314, -0.4027594406465836, 0.2624902798236902, 0.4876253939462449, 0.3155583157701459, -0.6001811424846641, 1.506088170407175, -5.032413448243027, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 456.2281437872571, -960.2817251702837, -504.8181052368888, -0.3473974178704272, -0.2160721566413612, -0.2844115901002985, -0.1109673640897398, -0.2249663433659822, 0.01558619777087037, 0.1691160884458819, -0.07065303999293307, -0.1161602619016208, -0.1496942207346384, -0.06504337994709028, 0.2242986455097327, 0.01449731249119731, 0.2977971368954605, -0.03700838008878649, -0.3740870837044805, -0.09144942901497075, 0.457896128782557, -0.1516347645680779, 0.5553971193015861, 0.221891957236842, 0.6754711755316094, -0.3094582971264419, 5.522765460179463, -0.97751110694022, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -456.1038688686278, -960.3270004185782, 504.6545436979824, -0.356402682870272, -0.351340066980498, -0.309181275719597, -0.3137167192606073, 0.2710350810973345, 0.2878350893000941, 0.2426229671933997, -0.2763168527076123, 0.2239747467509561, -0.280241947819618, -0.214997170417235, 0.3000011000597085, -0.2157829211419849, 0.3359590943512027, 0.2268880461285561, 0.3890394964897786, -0.2496482263626514, 0.4613794461017247, -0.2867172754999331, -0.5572551598551461, -0.3430608494894536, 0.6847182926632671, -1.544015999089003, 5.81277117568367, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 456.0159328177219, -960.3639010644911, -504.6932803542561, 0.3438026307622749, 0.09449263891861819, 0.2791924853298788, -0.0003950261355616105, -0.2158018381788221, 0.08970415379288814, 0.1544060725265021, 0.1757031383879306, 0.09475353685250953, -0.2591866322084164, -0.03594501565049272, -0.3429135694153541, 0.02344530556719954, 0.4306584188832464, 0.08549582247561358, -0.5273917016008263, 0.1532791130988579, -0.6399042657976388, -0.2316168130063649, -0.778179175299526, 0.3285885099115871, -6.416369594901841, 0.8564491667855068, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.8653704619311, -960.3842612497629, -504.4466252991523, 0.3553710744569122, 0.3464161627180581, -0.3141480426464132, -0.3263434732993854, -0.2805185077726005, 0.318452179605292, -0.2561088381842067, 0.3256076632881188, 0.2417423068618511, -0.3493440004841665, 0.2380375239176739, -0.3907849327216811, -0.2458444207499498, -0.4514338824492233, 0.2667224509879774, -0.5339931109453619, 0.3035639225688179, 0.6434745768399498, 0.3617520533213044, -0.7890836608012997, 1.453287590263238, -6.830587030361006, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.8082369972718, -960.3994442233231, -504.5727798070742, 0.3313951499504466, 0.03334672491870352, -0.2650323687322864, 0.1237756771616079, 0.1977229200322088, 0.2152372282453819, 0.1308144824330917, -0.3074811043383469, -0.06431874746251602, -0.4022833530695494, 0.002753039484875582, 0.5030555348702184, 0.07234641380894129, -0.6149136653510678, 0.147681447081999, -0.7452813394287314, -0.2340032399414377, -0.9053839955214958, 0.3402398000888476, -7.541821253164034, 0.5849103543979055, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.6329040043291, -960.3950114540172, -504.2353754001218, -0.3460929449122671, -0.3573008762499605, -0.3114301376926339, 0.3594512386076111, -0.2833177549503088, 0.3742883157355104, 0.2642891667618492, -0.4053000240462633, 0.2559854273447855, -0.4549386843075994, -0.2598956392005766, -0.5256874172585198, 0.2779895068618159, -0.6211224810880993, 0.313525507512514, 0.7472565377041231, 0.3723660978852033, -0.9147314187079836, 1.237565421662729, -8.101822161846965, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.6073466604758, -960.3894853751993, 504.4633572926642, -0.3103733552874035, 0.1798092000949148, 0.2419934417708158, 0.2733274466086066, 0.170608369891661, -0.3730126262676927, -0.09792141422899953, -0.4790220884834106, -0.02392951925676049, 0.5940246336099106, 0.05285511329060938, -0.72308359247846, 0.1355803277369181, -0.8742174899740623, -0.2298115577107615, -1.060011360233898, 0.3453065574734215, -8.919981193604276, 0.1624134764758667, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 455.4000921853053, -960.361309464515, -504.007882194183, 0.3290914395050692, -0.3942786634383071, 0.3016661987186222, -0.4232028367455296, -0.2802278665379578, 0.4661762517445954, -0.2682364496083171, 0.5277412575464714, 0.2683110547053154, 0.6119088573807965, -0.2831724063939194, 0.7235386787769833, -0.3166483539775581, -0.8699916087218257, -0.3752194315750562, 1.063702555577482, -0.8961354452926642, 9.650619636505867, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.411737801223, -960.33634002581, -504.3683031089997, -0.2810675792469359, -0.3568683235024433, -0.2101973773067176, 0.4610263218581945, 0.1342569173742763, 0.5773846640444537, 0.0549895002126496, -0.7072872888655298, -0.02810812468448988, 0.8554232500908963, -0.1177949641523385, 1.030291473272884, 0.2197751447614384, 1.245920882288997, -0.3445848993688538, 10.57920381944338, 0.4160829872124499, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455.1591691278096, -960.2853155130464, 503.7506267530316, 0.3049590480459953, -0.4680278418562256, -0.2856076919532088, 0.5295716933187377, -0.2723080782051216, 0.6081924100973243, 0.2695854300651085, 0.7101704945576234, -0.2814097861384926, 0.8422035444139073, -0.3125162969328145, -1.013460137059419, -0.3702351580276053, 1.238618787929362, -0.4245068253530189, 11.50934860393606, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 455.2183025514214, -960.2418420556575, 504.2904567527979, 0.2437489235262463, -0.5785902355402166, -0.1696099295696916, -0.7030543018352547, -0.08807726217552897, 0.8477643119258153, -0.0003803922022015914, -1.016538148397893, 0.09536127235557913, -1.218135087789733, -0.2047067633976007, -1.468068679276456, 0.3388478362779086, -12.55632491341529, -1.160129556695031, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.9011576326581, -960.1679733535419, 503.4480310997173, -0.2743159215154021, 0.59210690664036, -0.2642341403577922, 0.6948327035340854, 0.2611611633095301, 0.820468994814445, -0.2710734389097403, 0.9783065442168752, -0.3001250829922114, -1.179929020129721, -0.3568752809307986, 1.442834925435452, 0.1861860221886378, 13.72072654131889, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 455.0234951961737, -960.1065185460631, -504.2341761382918, -0.1985155387376615, -0.8636702893987938, -0.1197570863030018, 1.022005815169442, -0.03046148161363051, -1.212498738675283, 0.06965185900521845, -1.44380567993779, -0.1855411271964486, -1.732900209415532, 0.3288765751169174, -14.89970702904785, -2.085331319125681, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -454.6155022554338, -960.0090394364709, 503.080419120223, 0.2378578162407876, -0.7855779404374899, -0.2389268322384859, -0.9427265300586574, 0.2493889345428649, -1.133389617235434, 0.2776001160195384, 1.372380149780934, 0.3338733668864364, -1.680779007748177, -0.9514699644735849, -16.34248127983827, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.8236752088293, -959.9291937205099, 504.2068595622975, 0.1450192700206833, -1.238921588152978, 0.05908037491561525, 1.451502248422423, -0.04247506464443443, 1.715440182112174, 0.1633637326099601, 2.049030098342237, -0.3153926679720489, 17.67488245777389, 3.216886963304409, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.2888780517075, -959.8060141768642, 502.6209139189659, -0.1963783784418207, -1.07681015710693, 0.2118129088940946, -1.30957289263114, 0.2416506844030767, 1.594926385284288, 0.2987764905571196, -1.958528602633205, -1.89790052548914, -19.45550897611078, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.6150435510897, -959.7057073918052, -504.2207918385922, 0.08191276561459389, 1.744978959223401, -0.01623102385292412, 2.044325279439126, 0.139362395300141, 2.428380353063932, -0.2989187527977135, 20.97397716279267, 4.596081079911148, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -453.9030102952942, -959.5514771839804, -502.0302313735755, -0.1509069873047727, 1.509921737993699, -0.1866506960156188, -1.853460072170985, -0.2470701568585754, 2.284756111156089, 3.070922511010462, 23.1773864785971, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -454.393273204417, -959.4263564611852, 504.2962075579032, 0.005942404933789297, 2.446660862635643, 0.1147302269971472, 2.888007099445928, -0.2794135351323237, 24.93107187619451, 6.291448555715359, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 453.4308183834945, -959.2306762470356, 501.2467662460859, 0.1030197566665109, 2.15672544959436, 0.1707450834055513, -2.672257869508826, -4.548465509453017, -27.68489865384783, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454.1521964870133, -959.071043583621, 504.4663679395445, 0.09038098396525029, 3.453184686592636, -0.2556696326547585, 29.74790742438, 8.418178566025752, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 452.828604749646, -958.8118098643598, -500.1677840008083, 0.05562336274628601, -3.140588015388957, -6.465358070370396, -33.25328104675387, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -453.8814454933349, -958.5973523296369, -504.7879798529249, 0.2240186812962395, -35.739305932474, -11.17424401632893, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -452.0207842240151, -958.2280932680816, 498.6099988306628, -9.061273073482408, -40.32955903922403, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 453.5608878051024, -957.9144120234951, 542.7656821084641, 14.91304502929086, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 450.8656330991661, -969.8578951037719, 452.1887612775597, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 787.8967774818433, -898.9789215779133, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + }, + evWant: []complex128{ + 1, + 2, + -0.8238783640171078 + 1.579766228862017i, + -0.8238783640171078 - 1.579766228862017i, + -3.922907917607387 + 1.654540870297146i, + -3.922907917607387 - 1.654540870297146i, + -10.04176861796659 + 1.651471031280953i, + -10.04176861796659 - 1.651471031280953i, + -19.90533512613429 + 1.64196864045227i, + -19.90533512613429 - 1.64196864045227i, + -33.60610872827028 + 1.635560741682501i, + -33.60610872827028 - 1.635560741682501i, + -51.10943733404228 + 1.631805014774364i, + -51.10943733404228 - 1.631805014774364i, + -72.34919707090897 + 1.629522740505929i, + -72.34919707090897 - 1.629522740505929i, + -97.24021794530901 + 1.628064860261413i, + -97.24021794530901 - 1.628064860261413i, + -125.6811625494976 + 1.627074041605065i, + -125.6811625494976 - 1.627074041605065i, + -157.5556174346503 + 1.626392967840776i, + -157.5556174346503 - 1.626392967840776i, + -192.732837945876 + 1.625893674037654i, + -192.732837945876 - 1.625893674037654i, + -231.0684238575969 + 1.625523897559938i, + -231.0684238575969 - 1.625523897559938i, + -272.404932676379 + 1.625248463045784i, + -272.404932676379 - 1.625248463045784i, + -316.5725618120467 + 1.625029322230836i, + -316.5725618120467 - 1.625029322230836i, + -363.3898435346347 + 1.624863705104029i, + -363.3898435346347 - 1.624863705104029i, + -412.6644183160402 + 1.624734783685709i, + -412.6644183160402 - 1.624734783685709i, + -464.1938275598905 + 1.624629407600858i, + -464.1938275598905 - 1.624629407600858i, + -517.7663337295413 + 1.624555040627727i, + -517.7663337295413 - 1.624555040627727i, + -573.1617958392867 + 1.62448889134649i, + -573.1617958392867 - 1.62448889134649i, + -630.1525854166166 + 1.624445355378192i, + -630.1525854166166 - 1.624445355378192i, + -688.5045249303587 + 1.624414401302088i, + -688.5045249303587 - 1.624414401302088i, + -747.9778126976437 + 1.624396390555459i, + -747.9778126976437 - 1.624396390555459i, + -808.3280706224909 + 1.62438480760184i, + -808.3280706224909 - 1.62438480760184i, + -869.3072903249724 + 1.624387678902335i, + -869.3072903249724 - 1.624387678902335i, + -930.6648831979091 + 1.624396130880259i, + -930.6648831979091 - 1.624396130880259i, + -992.1487134378474 + 1.624417808682915i, + -992.1487134378474 - 1.624417808682915i, + -1053.506114553354 + 1.624453056189826i, + -1053.506114553354 - 1.624453056189826i, + -1114.484928198698 + 1.62449544649428i, + -1114.484928198698 - 1.62449544649428i, + -1174.834554234014 + 1.624553207269019i, + -1174.834554234014 - 1.624553207269019i, + -1234.306981514973 + 1.624623553438826i, + -1234.306981514973 - 1.624623553438826i, + -1292.657768972259 + 1.624709216827242i, + -1292.657768972259 - 1.624709216827242i, + -1349.647106741638 + 1.624814444572517i, + -1349.647106741638 - 1.624814444572517i, + -1405.040739357668 + 1.624951632752096i, + -1405.040739357668 - 1.624951632752096i, + -1458.610953350783 + 1.625104547041682i, + -1458.610953350783 - 1.625104547041682i, + -1510.137508646807 + 1.625304666073007i, + -1510.137508646807 - 1.625304666073007i, + -1559.408520122221 + 1.625548293255404i, + -1559.408520122221 - 1.625548293255404i, + -1606.221305250554 + 1.625851986073836i, + -1606.221305250554 - 1.625851986073836i, + -1650.383201531125 + 1.62624202844641i, + -1650.383201531125 - 1.62624202844641i, + -1691.712315735984 + 1.6267345498979i, + -1691.712315735984 - 1.6267345498979i, + -1730.038177420971 + 1.627388968656263i, + -1730.038177420971 - 1.627388968656263i, + -1765.20230058066 + 1.628268412022146i, + -1765.20230058066 - 1.628268412022146i, + -1797.05860162894 + 1.629473972633416i, + -1797.05860162894 - 1.629473972633416i, + -1825.473493639258 + 1.631220665229006i, + -1825.473493639258 - 1.631220665229006i, + -1850.32542664842 + 1.633834593918563i, + -1850.32542664842 - 1.633834593918563i, + -1871.503056018116 + 1.637993570641514i, + -1871.503056018116 - 1.637993570641514i, + -1888.90026514681 + 1.64508855982818i, + -1888.90026514681 - 1.64508855982818i, + -1902.402515327158 + 1.658179541614067i, + -1902.402515327158 - 1.658179541614067i, + -1911.858940404498 + 1.682209391409579i, + -1911.858940404498 - 1.682209391409579i, + -1916.92602113601 + 1.761877988650816i, + -1916.92602113601 - 1.761877988650816i, + -1930.484166851586 + 1.202676762393897i, + -1930.484166851586 - 1.202676762393897i, + 3, + 4, + }, + }, +} diff --git a/lapack/testlapack/dlabrd.go b/lapack/testlapack/dlabrd.go new file mode 100644 index 00000000..460cefe7 --- /dev/null +++ b/lapack/testlapack/dlabrd.go @@ -0,0 +1,107 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" +) + +type Dlabrder interface { + Dlabrd(m, n, nb int, a []float64, lda int, d, e, tauq, taup, x []float64, ldx int, y []float64, ldy int) +} + +func DlabrdTest(t *testing.T, impl Dlabrder) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, nb, lda, ldx, ldy int + }{ + {4, 5, 2, 0, 0, 0}, + {4, 5, 4, 0, 0, 0}, + {5, 5, 2, 0, 0, 0}, + {5, 5, 5, 0, 0, 0}, + {5, 4, 4, 0, 0, 0}, + {5, 4, 4, 0, 0, 0}, + + {4, 5, 2, 10, 11, 12}, + {4, 5, 4, 10, 11, 12}, + {5, 5, 2, 10, 11, 12}, + {5, 5, 5, 10, 11, 12}, + {5, 4, 2, 10, 11, 12}, + {5, 4, 4, 10, 11, 12}, + + {4, 5, 2, 11, 12, 10}, + {4, 5, 4, 11, 12, 10}, + {5, 5, 2, 11, 12, 10}, + {5, 5, 5, 11, 12, 10}, + {5, 4, 2, 11, 12, 10}, + {5, 4, 4, 11, 12, 10}, + + {4, 5, 2, 12, 11, 10}, + {4, 5, 4, 12, 11, 10}, + {5, 5, 2, 12, 11, 10}, + {5, 5, 5, 12, 11, 10}, + {5, 4, 2, 12, 11, 10}, + {5, 4, 4, 12, 11, 10}, + } { + m := test.m + n := test.n + nb := test.nb + lda := test.lda + if lda == 0 { + lda = n + } + ldy := test.ldy + if ldy == 0 { + ldy = nb + } + ldx := test.ldx + if ldx == 0 { + ldx = nb + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + d := make([]float64, nb) + for i := range d { + d[i] = math.NaN() + } + e := make([]float64, nb) + for i := range e { + e[i] = math.NaN() + } + tauP := make([]float64, nb) + for i := range tauP { + tauP[i] = math.NaN() + } + tauQ := make([]float64, nb) + for i := range tauP { + tauQ[i] = math.NaN() + } + x := make([]float64, m*ldx) + for i := range x { + x[i] = rnd.NormFloat64() + } + y := make([]float64, n*ldy) + for i := range y { + y[i] = rnd.NormFloat64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + // Compute the reduction. + impl.Dlabrd(m, n, nb, a, lda, d, e, tauQ, tauP, x, ldx, y, ldy) + + if m >= n && nb == n { + tauP[n-1] = 0 + } + if m < n && nb == m { + tauQ[m-1] = 0 + } + checkBidiagonal(t, m, n, nb, a, lda, d, e, tauP, tauQ, aCopy) + } +} diff --git a/lapack/testlapack/dlacn2.go b/lapack/testlapack/dlacn2.go new file mode 100644 index 00000000..9e76c0b7 --- /dev/null +++ b/lapack/testlapack/dlacn2.go @@ -0,0 +1,72 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlacn2er interface { + Dlacn2(n int, v, x []float64, isgn []int, est float64, kase int, isave *[3]int) (float64, int) +} + +func Dlacn2Test(t *testing.T, impl Dlacn2er) { + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{1, 2, 3, 4, 5, 7, 10, 15, 20, 100} { + for cas := 0; cas < 10; cas++ { + a := randomGeneral(n, n, n, rnd) + + // Compute the 1-norm of A explicitly. + var norm1 float64 + for j := 0; j < n; j++ { + var sum float64 + for i := 0; i < n; i++ { + sum += math.Abs(a.Data[i*a.Stride+j]) + } + if sum > norm1 { + norm1 = sum + } + } + + // Compute the estimate of 1-norm using Dlanc2. + x := make([]float64, n) + work := make([]float64, n) + v := make([]float64, n) + isgn := make([]int, n) + var ( + kase int + isave [3]int + got float64 + ) + loop: + for { + got, kase = impl.Dlacn2(n, v, x, isgn, got, kase, &isave) + switch kase { + default: + panic("Dlacn2 returned invalid value of kase") + case 0: + break loop + case 1: + blas64.Gemv(blas.NoTrans, 1, a, blas64.Vector{1, x}, 0, blas64.Vector{1, work}) + copy(x, work) + case 2: + blas64.Gemv(blas.Trans, 1, a, blas64.Vector{1, x}, 0, blas64.Vector{1, work}) + copy(x, work) + } + } + + // Check that got is either accurate enough or a + // lower estimate of the 1-norm of A. + if math.Abs(got-norm1) > 1e-8 && got > norm1 { + t.Errorf("Case n=%v: not lower estimate. 1-norm %v, estimate %v", n, norm1, got) + } + } + } +} diff --git a/lapack/testlapack/dlacpy.go b/lapack/testlapack/dlacpy.go new file mode 100644 index 00000000..aa3e5e0f --- /dev/null +++ b/lapack/testlapack/dlacpy.go @@ -0,0 +1,89 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dlacpyer interface { + Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) +} + +func DlacpyTest(t *testing.T, impl Dlacpyer) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { + for _, test := range []struct { + m, n, lda, ldb int + }{ + {3, 5, 0, 0}, + {5, 5, 0, 0}, + {7, 5, 0, 0}, + + {3, 5, 10, 12}, + {5, 5, 10, 12}, + {7, 5, 10, 12}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + b := make([]float64, m*ldb) + for i := range b { + b[i] = rnd.Float64() + } + impl.Dlacpy(uplo, m, n, a, lda, b, ldb) + equal := true + switch uplo { + case blas.Upper: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + if b[i*ldb+j] != a[i*lda+j] { + equal = false + goto DoneCheck + } + } + } + case blas.Lower: + for i := 0; i < m; i++ { + for j := 0; j < min(i, n); j++ { + if b[i*ldb+j] != a[i*lda+j] { + equal = false + goto DoneCheck + } + } + } + case blas.All: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if b[i*ldb+j] != a[i*lda+j] { + equal = false + goto DoneCheck + } + } + } + } + DoneCheck: + if !equal { + fmt.Println(blas.Lower) + t.Errorf("Matrices not equal after copy. Uplo = %d, m = %d, n = %d", uplo, m, n) + } + } + } +} diff --git a/lapack/testlapack/dlae2.go b/lapack/testlapack/dlae2.go new file mode 100644 index 00000000..236b3f2b --- /dev/null +++ b/lapack/testlapack/dlae2.go @@ -0,0 +1,53 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "testing" +) + +type Dlae2er interface { + Dlae2(a, b, c float64) (rt1, rt2 float64) +} + +func Dlae2Test(t *testing.T, impl Dlae2er) { + for _, test := range []struct { + a, b, c float64 + }{ + {-10, 5, 3}, + {3, 5, -10}, + {0, 3, 0}, + {1, 3, 1}, + {1, -3, 1}, + {5, 0, 3}, + {3, 0, -5}, + {1, 3, 1.02}, + {1.02, 3, 1}, + {1, -3, -9}, + } { + a := test.a + b := test.b + c := test.c + rt1, rt2 := impl.Dlae2(a, b, c) + + errStr := fmt.Sprintf("a = %v, b = %v, c = %v", a, b, c) + // Check if rt1 and rt2 are eigenvalues by checking if det(a - λI) = 0 + a1 := a - rt1 + c1 := c - rt1 + det := a1*c1 - b*b + if math.Abs(det) > 1e-10 { + t.Errorf("First eigenvalue mismatch. %s. Det = %v", errStr, det) + } + + a2 := a - rt2 + c2 := c - rt2 + det = a2*c2 - b*b + if math.Abs(det) > 1e-10 { + t.Errorf("Second eigenvalue mismatch. %s. Det = %v", errStr, det) + } + } +} diff --git a/lapack/testlapack/dlaev2.go b/lapack/testlapack/dlaev2.go new file mode 100644 index 00000000..3aea2d74 --- /dev/null +++ b/lapack/testlapack/dlaev2.go @@ -0,0 +1,46 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" +) + +type Dlaev2er interface { + Dlaev2(a, b, c float64) (rt1, rt2, cs1, sn1 float64) +} + +func Dlaev2Test(t *testing.T, impl Dlaev2er) { + rnd := rand.New(rand.NewSource(1)) + for trial := 0; trial < 100; trial++ { + a := rnd.NormFloat64() + b := rnd.NormFloat64() + c := rnd.NormFloat64() + + rt1, rt2, cs1, sn1 := impl.Dlaev2(a, b, c) + tmp := mul2by2([2][2]float64{{cs1, sn1}, {-sn1, cs1}}, [2][2]float64{{a, b}, {b, c}}) + ans := mul2by2(tmp, [2][2]float64{{cs1, -sn1}, {sn1, cs1}}) + if math.Abs(ans[0][0]-rt1) > 1e-14 { + t.Errorf("Largest eigenvalue mismatch. Returned %v, mul %v", rt1, ans[0][0]) + } + if math.Abs(ans[1][0]) > 1e-14 || math.Abs(ans[0][1]) > 1e-14 { + t.Errorf("Non-zero off diagonal. ans[1][0] = %v, ans[0][1] = %v", ans[1][0], ans[0][1]) + } + if math.Abs(ans[1][1]-rt2) > 1e-14 { + t.Errorf("Smallest eigenvalue mismatch. Returned %v, mul %v", rt2, ans[1][1]) + } + } +} + +func mul2by2(a, b [2][2]float64) [2][2]float64 { + var c [2][2]float64 + c[0][0] = a[0][0]*b[0][0] + a[0][1]*b[1][0] + c[0][1] = a[0][0]*b[0][1] + a[0][1]*b[1][1] + c[1][0] = a[1][0]*b[0][0] + a[1][1]*b[1][0] + c[1][1] = a[1][0]*b[0][1] + a[1][1]*b[1][1] + return c +} diff --git a/lapack/testlapack/dlaexc.go b/lapack/testlapack/dlaexc.go new file mode 100644 index 00000000..23ac3303 --- /dev/null +++ b/lapack/testlapack/dlaexc.go @@ -0,0 +1,227 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/cmplx" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaexcer interface { + Dlaexc(wantq bool, n int, t []float64, ldt int, q []float64, ldq int, j1, n1, n2 int, work []float64) bool +} + +func DlaexcTest(t *testing.T, impl Dlaexcer) { + rnd := rand.New(rand.NewSource(1)) + + for _, wantq := range []bool{true, false} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 53} { + for _, extra := range []int{0, 1, 11} { + for cas := 0; cas < 100; cas++ { + j1 := rnd.Intn(n) + n1 := min(rnd.Intn(3), n-j1) + n2 := min(rnd.Intn(3), n-j1-n1) + testDlaexc(t, impl, wantq, n, j1, n1, n2, extra, rnd) + } + } + } + } +} + +func testDlaexc(t *testing.T, impl Dlaexcer, wantq bool, n, j1, n1, n2, extra int, rnd *rand.Rand) { + const tol = 1e-14 + + tmat := randomGeneral(n, n, n+extra, rnd) + // Zero out the lower triangle. + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + tmat.Data[i*tmat.Stride+j] = 0 + } + } + // Make any 2x2 diagonal block to be in Schur canonical form. + if n1 == 2 { + // Diagonal elements equal. + tmat.Data[(j1+1)*tmat.Stride+j1+1] = tmat.Data[j1*tmat.Stride+j1] + // Off-diagonal elements of opposite sign. + c := rnd.NormFloat64() + if math.Signbit(c) == math.Signbit(tmat.Data[j1*tmat.Stride+j1+1]) { + c *= -1 + } + tmat.Data[(j1+1)*tmat.Stride+j1] = c + } + if n2 == 2 { + // Diagonal elements equal. + tmat.Data[(j1+n1+1)*tmat.Stride+j1+n1+1] = tmat.Data[(j1+n1)*tmat.Stride+j1+n1] + // Off-diagonal elements of opposite sign. + c := rnd.NormFloat64() + if math.Signbit(c) == math.Signbit(tmat.Data[(j1+n1)*tmat.Stride+j1+n1+1]) { + c *= -1 + } + tmat.Data[(j1+n1+1)*tmat.Stride+j1+n1] = c + } + tmatCopy := cloneGeneral(tmat) + var q, qCopy blas64.General + if wantq { + q = eye(n, n+extra) + qCopy = cloneGeneral(q) + } + work := nanSlice(n) + + ok := impl.Dlaexc(wantq, n, tmat.Data, tmat.Stride, q.Data, q.Stride, j1, n1, n2, work) + + prefix := fmt.Sprintf("Case n=%v, j1=%v, n1=%v, n2=%v, wantq=%v, extra=%v", n, j1, n1, n2, wantq, extra) + + if !generalOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T", prefix) + } + if wantq && !generalOutsideAllNaN(q) { + t.Errorf("%v: out-of-range write to Q", prefix) + } + + if !ok { + if n1 == 1 && n2 == 1 { + t.Errorf("%v: unexpected failure", prefix) + } else { + t.Logf("%v: Dlaexc returned false") + } + } + + if !ok || n1 == 0 || n2 == 0 || j1+n1 >= n { + // Check that T is not modified. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if tmat.Data[i*tmat.Stride+j] != tmatCopy.Data[i*tmatCopy.Stride+j] { + t.Errorf("%v: ok == false but T[%v,%v] modified", prefix, i, j) + } + } + } + if !wantq { + return + } + // Check that Q is not modified. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if q.Data[i*q.Stride+j] != qCopy.Data[i*qCopy.Stride+j] { + t.Errorf("%v: ok == false but Q[%v,%v] modified", prefix, i, j) + } + } + } + return + } + + // Check that T is not modified outside of rows and columns [j1:j1+n1+n2]. + for i := 0; i < n; i++ { + if j1 <= i && i < j1+n1+n2 { + continue + } + for j := 0; j < n; j++ { + if j1 <= j && j < j1+n1+n2 { + continue + } + diff := tmat.Data[i*tmat.Stride+j] - tmatCopy.Data[i*tmatCopy.Stride+j] + if diff != 0 { + t.Errorf("%v: unexpected modification of T[%v,%v]", prefix, i, j) + } + } + } + + if n1 == 1 { + // 1×1 blocks are swapped exactly. + got := tmat.Data[(j1+n2)*tmat.Stride+j1+n2] + want := tmatCopy.Data[j1*tmatCopy.Stride+j1] + if want != got { + t.Errorf("%v: unexpected value of T[%v,%v]. Want %v, got %v", prefix, j1+n2, j1+n2, want, got) + } + } else { + // Check that the swapped 2×2 block is in Schur canonical form. + // The n1×n1 block is now located at T[j1+n2,j1+n2]. + a, b, c, d := extract2x2Block(tmat.Data[(j1+n2)*tmat.Stride+j1+n2:], tmat.Stride) + if !isSchurCanonical(a, b, c, d) { + t.Errorf("%v: 2×2 block at T[%v,%v] not in Schur canonical form", prefix, j1+n2, j1+n2) + } + ev1Got, ev2Got := schurBlockEigenvalues(a, b, c, d) + + // Check that the swapped 2×2 block has the same eigenvalues. + // The n1×n1 block was originally located at T[j1,j1]. + a, b, c, d = extract2x2Block(tmatCopy.Data[j1*tmatCopy.Stride+j1:], tmatCopy.Stride) + ev1Want, ev2Want := schurBlockEigenvalues(a, b, c, d) + if cmplx.Abs(ev1Got-ev1Want) > tol { + t.Errorf("%v: unexpected first eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, j1+n2, j1+n2, ev1Want, ev1Got) + } + if cmplx.Abs(ev2Got-ev2Want) > tol { + t.Errorf("%v: unexpected second eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, j1+n2, j1+n2, ev2Want, ev2Got) + } + } + if n2 == 1 { + // 1×1 blocks are swapped exactly. + got := tmat.Data[j1*tmat.Stride+j1] + want := tmatCopy.Data[(j1+n1)*tmatCopy.Stride+j1+n1] + if want != got { + t.Errorf("%v: unexpected value of T[%v,%v]. Want %v, got %v", prefix, j1, j1, want, got) + } + } else { + // Check that the swapped 2×2 block is in Schur canonical form. + // The n2×n2 block is now located at T[j1,j1]. + a, b, c, d := extract2x2Block(tmat.Data[j1*tmat.Stride+j1:], tmat.Stride) + if !isSchurCanonical(a, b, c, d) { + t.Errorf("%v: 2×2 block at T[%v,%v] not in Schur canonical form", prefix, j1, j1) + } + ev1Got, ev2Got := schurBlockEigenvalues(a, b, c, d) + + // Check that the swapped 2×2 block has the same eigenvalues. + // The n2×n2 block was originally located at T[j1+n1,j1+n1]. + a, b, c, d = extract2x2Block(tmatCopy.Data[(j1+n1)*tmatCopy.Stride+j1+n1:], tmatCopy.Stride) + ev1Want, ev2Want := schurBlockEigenvalues(a, b, c, d) + if cmplx.Abs(ev1Got-ev1Want) > tol { + t.Errorf("%v: unexpected first eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, j1, j1, ev1Want, ev1Got) + } + if cmplx.Abs(ev2Got-ev2Want) > tol { + t.Errorf("%v: unexpected second eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, j1, j1, ev2Want, ev2Got) + } + } + + if !wantq { + return + } + + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal", prefix) + } + // Check that Q is unchanged outside of columns [j1:j1+n1+n2]. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if j1 <= j && j < j1+n1+n2 { + continue + } + diff := q.Data[i*q.Stride+j] - qCopy.Data[i*qCopy.Stride+j] + if diff != 0 { + t.Errorf("%v: unexpected modification of Q[%v,%v]", prefix, i, j) + } + } + } + // Check that Q^T TOrig Q == T. + tq := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmatCopy, q, 0, tq) + qtq := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, tq, 0, qtq) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + diff := qtq.Data[i*qtq.Stride+j] - tmat.Data[i*tmat.Stride+j] + if math.Abs(diff) > tol { + t.Errorf("%v: unexpected value of T[%v,%v]", prefix, i, j) + } + } + } +} diff --git a/lapack/testlapack/dlags2.go b/lapack/testlapack/dlags2.go new file mode 100644 index 00000000..2a3da46d --- /dev/null +++ b/lapack/testlapack/dlags2.go @@ -0,0 +1,100 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dlags2er interface { + Dlags2(upper bool, a1, a2, a3, b1, b2, b3 float64) (csu, snu, csv, snv, csq, snq float64) +} + +func Dlags2Test(t *testing.T, impl Dlags2er) { + rnd := rand.New(rand.NewSource(1)) + for _, upper := range []bool{true, false} { + for i := 0; i < 100; i++ { + a1 := rnd.Float64() + a2 := rnd.Float64() + a3 := rnd.Float64() + b1 := rnd.Float64() + b2 := rnd.Float64() + b3 := rnd.Float64() + + csu, snu, csv, snv, csq, snq := impl.Dlags2(upper, a1, a2, a3, b1, b2, b3) + + detU := det2x2(csu, snu, -snu, csu) + if !floats.EqualWithinAbsOrRel(math.Abs(detU), 1, 1e-14, 1e-14) { + t.Errorf("U not orthogonal: det(U)=%v", detU) + } + detV := det2x2(csv, snv, -snv, csv) + if !floats.EqualWithinAbsOrRel(math.Abs(detV), 1, 1e-14, 1e-14) { + t.Errorf("V not orthogonal: det(V)=%v", detV) + } + detQ := det2x2(csq, snq, -snq, csq) + if !floats.EqualWithinAbsOrRel(math.Abs(detQ), 1, 1e-14, 1e-14) { + t.Errorf("Q not orthogonal: det(Q)=%v", detQ) + } + + u := blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{csu, snu, -snu, csu}, + } + v := blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{csv, snv, -snv, csv}, + } + q := blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{csq, snq, -snq, csq}, + } + + a := blas64.General{Rows: 2, Cols: 2, Stride: 2} + b := blas64.General{Rows: 2, Cols: 2, Stride: 2} + if upper { + a.Data = []float64{a1, a2, 0, a3} + b.Data = []float64{b1, b2, 0, b3} + } else { + a.Data = []float64{a1, 0, a2, a3} + b.Data = []float64{b1, 0, b2, b3} + } + + tmp := blas64.General{Rows: 2, Cols: 2, Stride: 2, Data: make([]float64, 4)} + blas64.Gemm(blas.Trans, blas.NoTrans, 1, u, a, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, a) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, v, b, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, b) + + var gotA, gotB float64 + if upper { + gotA = a.Data[1] + gotB = b.Data[1] + } else { + gotA = a.Data[2] + gotB = b.Data[2] + } + if !floats.EqualWithinAbsOrRel(gotA, 0, 1e-14, 1e-14) { + t.Errorf("unexpected non-zero value for zero triangle of U^T*A*Q: %v", gotA) + } + if !floats.EqualWithinAbsOrRel(gotB, 0, 1e-14, 1e-14) { + t.Errorf("unexpected non-zero value for zero triangle of V^T*B*Q: %v", gotB) + } + } + } +} + +func det2x2(a, b, c, d float64) float64 { return a*d - b*c } diff --git a/lapack/testlapack/dlahqr.go b/lapack/testlapack/dlahqr.go new file mode 100644 index 00000000..c68680a7 --- /dev/null +++ b/lapack/testlapack/dlahqr.go @@ -0,0 +1,441 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlahqrer interface { + Dlahqr(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int) int +} + +type dlahqrTest struct { + h blas64.General + ilo, ihi int + iloz, ihiz int + wantt, wantz bool + + evWant []complex128 // Optional slice holding known eigenvalues. +} + +func DlahqrTest(t *testing.T, impl Dlahqrer) { + rnd := rand.New(rand.NewSource(1)) + + // Tests that choose the [ilo:ihi+1,ilo:ihi+1] and + // [iloz:ihiz+1,ilo:ihi+1] blocks randomly. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 53} { + for _, extra := range []int{0, 1, 11} { + for cas := 0; cas < 100; cas++ { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + iloz := rnd.Intn(ilo + 1) + ihiz := ihi + rnd.Intn(n-ihi) + h := randomHessenberg(n, n+extra, rnd) + if ilo-1 >= 0 { + h.Data[ilo*h.Stride+ilo-1] = 0 + } + if ihi+1 < n { + h.Data[(ihi+1)*h.Stride+ihi] = 0 + } + test := dlahqrTest{ + h: h, + ilo: ilo, + ihi: ihi, + iloz: iloz, + ihiz: ihiz, + wantt: wantt, + wantz: wantz, + } + testDlahqr(t, impl, test) + } + } + } + } + } + // Tests that make sure that some potentially problematic corner cases, + // like zero-sized matrix, are covered. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, extra := range []int{0, 1, 11} { + for _, test := range []dlahqrTest{ + { + h: randomHessenberg(0, extra, rnd), + ilo: 0, + ihi: -1, + iloz: 0, + ihiz: -1, + }, + { + h: randomHessenberg(1, 1+extra, rnd), + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + }, + { + h: randomHessenberg(2, 2+extra, rnd), + ilo: 1, + ihi: 1, + iloz: 1, + ihiz: 1, + }, + { + h: randomHessenberg(2, 2+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 9, + iloz: 0, + ihiz: 9, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 9, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 9, + ihi: 9, + iloz: 0, + ihiz: 9, + }, + } { + if test.ilo-1 >= 0 { + test.h.Data[test.ilo*test.h.Stride+test.ilo-1] = 0 + } + if test.ihi+1 < test.h.Rows { + test.h.Data[(test.ihi+1)*test.h.Stride+test.ihi] = 0 + } + test.wantt = wantt + test.wantz = wantz + testDlahqr(t, impl, test) + } + } + } + } + + // Tests with explicit eigenvalues computed by Octave. + for _, test := range []dlahqrTest{ + { + h: blas64.General{ + Rows: 1, + Cols: 1, + Stride: 1, + Data: []float64{7.09965484086874e-1}, + }, + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + evWant: []complex128{7.09965484086874e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 0, -1, + 1, 0, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{1i, -1i}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 6.25219991450918e-1, 8.17510791994361e-1, + 3.31218891622294e-1, 1.24103744878131e-1, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 1, 0, 0, 0, + 0, 6.25219991450918e-1, 8.17510791994361e-1, 0, + 0, 3.31218891622294e-1, 1.24103744878131e-1, 0, + 0, 0, 0, 1, + }, + }, + ilo: 1, + ihi: 2, + iloz: 0, + ihiz: 3, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + -1.1219562276608, 6.85473513349362e-1, + -8.19951061145131e-1, 1.93728523178888e-1, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{ + -4.64113852240958e-1 + 3.59580510817350e-1i, + -4.64113852240958e-1 - 3.59580510817350e-1i, + }, + }, + { + h: blas64.General{ + Rows: 5, + Cols: 5, + Stride: 5, + Data: []float64{ + 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2, + -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1, + 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1, + 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1, + 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1, + }, + }, + ilo: 0, + ihi: 4, + iloz: 0, + ihiz: 4, + evWant: []complex128{ + 2.94393309555622, + 4.97029793606701e-1 + 3.63041654992384e-1i, + 4.97029793606701e-1 - 3.63041654992384e-1i, + -1.74079119166145e-1 + 2.01570009462092e-1i, + -1.74079119166145e-1 - 2.01570009462092e-1i, + }, + }, + } { + test.wantt = true + test.wantz = true + testDlahqr(t, impl, test) + } +} + +func testDlahqr(t *testing.T, impl Dlahqrer, test dlahqrTest) { + const tol = 1e-14 + + h := cloneGeneral(test.h) + n := h.Cols + extra := h.Stride - h.Cols + wantt := test.wantt + wantz := test.wantz + ilo := test.ilo + ihi := test.ihi + iloz := test.iloz + ihiz := test.ihiz + + var z, zCopy blas64.General + if wantz { + z = eye(n, n+extra) + zCopy = cloneGeneral(z) + } + + wr := nanSlice(ihi + 1) + wi := nanSlice(ihi + 1) + + unconverged := impl.Dlahqr(wantt, wantz, n, ilo, ihi, h.Data, h.Stride, wr, wi, iloz, ihiz, z.Data, z.Stride) + + prefix := fmt.Sprintf("Case wantt=%v, wantz=%v, n=%v, ilo=%v, ihi=%v, iloz=%v, ihiz=%v, extra=%v", + wantt, wantz, n, ilo, ihi, iloz, ihiz, extra) + + if !generalOutsideAllNaN(h) { + t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data) + } + if !generalOutsideAllNaN(z) { + t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data) + } + + if !isUpperHessenberg(h) { + t.Logf("%v: H is not Hessenberg", prefix) + } + + start := ilo // Index of the first computed eigenvalue. + if unconverged != 0 { + start = unconverged + if start == ihi+1 { + t.Logf("%v: no eigenvalue has converged", prefix) + } + } + + // Check that wr and wi have not been modified in [:start]. + if !isAllNaN(wr[:start]) { + t.Errorf("%v: unexpected modification of wr", prefix) + } + if !isAllNaN(wi[:start]) { + t.Errorf("%v: unexpected modification of wi", prefix) + } + + var hasReal bool + for i := start; i <= ihi; { + if wi[i] == 0 { // Real eigenvalue. + hasReal = true + // Check that the eigenvalue corresponds to a 1×1 block + // on the diagonal of H. + if wantt { + if wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i, i) + } + for _, index := range []struct{ r, c int }{ + {i, i - 1}, // h h h + {i + 1, i - 1}, // 0 wr[i] h + {i + 1, i}, // 0 0 h + } { + if index.r >= n || index.c < 0 { + continue + } + if h.Data[index.r*h.Stride+index.c] != 0 { + t.Errorf("%v: H[%v,%v] != 0", prefix, index.r, index.c) + } + } + } + i++ + continue + } + + // Complex eigenvalue. + + // In the conjugate pair the real parts must be equal. + if wr[i] != wr[i+1] { + t.Errorf("%v: real part of conjugate pair not equal, i=%v", prefix, i) + } + // The first imaginary part must be positive. + if wi[i] < 0 { + t.Errorf("%v: wi[%v] not positive", prefix, i) + } + // The second imaginary part must be negative with the same + // magnitude. + if wi[i] != -wi[i+1] { + t.Errorf("%v: wi[%v] != -wi[%v]", prefix, i, i+1) + } + if wantt { + // Check that wi[i] has the correct value. + if wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i, i) + } + if wr[i] != h.Data[(i+1)*h.Stride+i+1] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i+1, i+1) + } + prod := math.Abs(h.Data[(i+1)*h.Stride+i] * h.Data[i*h.Stride+i+1]) + if math.Abs(math.Sqrt(prod)-wi[i]) > tol { + t.Errorf("%v: unexpected value of wi[%v]: want %v, got %v", prefix, i, math.Sqrt(prod), wi[i]) + } + + // Check that the corresponding diagonal block is 2×2. + for _, index := range []struct{ r, c int }{ + {i, i - 1}, // i + {i + 1, i - 1}, // h h h h + {i + 2, i - 1}, // 0 wr[i] b h i + {i + 2, i}, // 0 c wr[i+1] h + {i + 2, i + 1}, // 0 0 0 h + } { + if index.r >= n || index.c < 0 { + continue + } + if h.Data[index.r*h.Stride+index.c] != 0 { + t.Errorf("%v: H[%v,%v] != 0", prefix, index.r, index.c) + } + } + } + i += 2 + } + // If the number of found eigenvalues is odd, at least one must be real. + if (ihi+1-start)%2 != 0 && !hasReal { + t.Errorf("%v: expected at least one real eigenvalue", prefix) + } + + // Compare found eigenvalues to the reference, if known. + if test.evWant != nil { + for i := start; i <= ihi; i++ { + ev := complex(wr[i], wi[i]) + found, _ := containsComplex(test.evWant, ev, tol) + if !found { + t.Errorf("%v: unexpected eigenvalue %v", prefix, ev) + } + } + } + + if !wantz { + return + } + + // Z should contain the orthogonal matrix U. + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + // Z should have been modified only in the + // [iloz:ihiz+1,ilo:ihi+1] block. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if iloz <= i && i <= ihiz && ilo <= j && j <= ihi { + continue + } + if z.Data[i*z.Stride+j] != zCopy.Data[i*zCopy.Stride+j] { + t.Errorf("%v: Z modified outside of [iloz:ihiz+1,ilo:ihi+1] block", prefix) + } + } + } + if wantt { + hu := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, test.h, z, 0, hu) + uhu := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hu, 0, uhu) + if !equalApproxGeneral(uhu, h, 10*tol) { + t.Errorf("%v: Z^T*(initial H)*Z and (final H) are not equal", prefix) + } + } +} diff --git a/lapack/testlapack/dlahr2.go b/lapack/testlapack/dlahr2.go new file mode 100644 index 00000000..28aee344 --- /dev/null +++ b/lapack/testlapack/dlahr2.go @@ -0,0 +1,240 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "compress/gzip" + "encoding/json" + "fmt" + "log" + "math" + "math/rand" + "os" + "path/filepath" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dlahr2er interface { + Dlahr2(n, k, nb int, a []float64, lda int, tau, t []float64, ldt int, y []float64, ldy int) +} + +type Dlahr2test struct { + N, K, NB int + A []float64 + + AWant []float64 + TWant []float64 + YWant []float64 + TauWant []float64 +} + +func Dlahr2Test(t *testing.T, impl Dlahr2er) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + n, k, nb int + }{ + {3, 0, 3}, + {3, 1, 2}, + {3, 1, 1}, + + {5, 0, 5}, + {5, 1, 4}, + {5, 1, 3}, + {5, 1, 2}, + {5, 1, 1}, + {5, 2, 3}, + {5, 2, 2}, + {5, 2, 1}, + {5, 3, 2}, + {5, 3, 1}, + + {7, 3, 4}, + {7, 3, 3}, + {7, 3, 2}, + {7, 3, 1}, + + {10, 0, 10}, + {10, 1, 9}, + {10, 1, 5}, + {10, 1, 1}, + {10, 5, 5}, + {10, 5, 3}, + {10, 5, 1}, + } { + for cas := 0; cas < 100; cas++ { + for _, extraStride := range []int{0, 1, 10} { + n := test.n + k := test.k + nb := test.nb + + a := randomGeneral(n, n-k+1, n-k+1+extraStride, rnd) + aCopy := a + aCopy.Data = make([]float64, len(a.Data)) + copy(aCopy.Data, a.Data) + tmat := nanTriangular(blas.Upper, nb, nb+extraStride) + y := nanGeneral(n, nb, nb+extraStride) + tau := nanSlice(nb) + + impl.Dlahr2(n, k, nb, a.Data, a.Stride, tau, tmat.Data, tmat.Stride, y.Data, y.Stride) + + prefix := fmt.Sprintf("Case n=%v, k=%v, nb=%v, ldex=%v", n, k, nb, extraStride) + + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + if !triangularOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T\n%v", prefix, tmat.Data) + } + if !generalOutsideAllNaN(y) { + t.Errorf("%v: out-of-range write to Y\n%v", prefix, y.Data) + } + + // Check that A[:k,:] and A[:,nb:] blocks were not modified. + for i := 0; i < n; i++ { + for j := 0; j < n-k+1; j++ { + if i >= k && j < nb { + continue + } + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected write to A[%v,%v]", prefix, i, j) + } + } + } + + // Check that all elements of tau were assigned. + for i, v := range tau { + if math.IsNaN(v) { + t.Errorf("%v: tau[%v] not assigned", prefix, i) + } + } + + // Extract V from a. + v := blas64.General{ + Rows: n - k + 1, + Cols: nb, + Stride: nb, + Data: make([]float64, (n-k+1)*nb), + } + for j := 0; j < v.Cols; j++ { + v.Data[(j+1)*v.Stride+j] = 1 + for i := j + 2; i < v.Rows; i++ { + v.Data[i*v.Stride+j] = a.Data[(i+k-1)*a.Stride+j] + } + } + + // VT = V. + vt := v + vt.Data = make([]float64, len(v.Data)) + copy(vt.Data, v.Data) + // VT = V * T. + blas64.Trmm(blas.Right, blas.NoTrans, 1, tmat, vt) + // YWant = A * V * T. + ywant := blas64.General{ + Rows: n, + Cols: nb, + Stride: nb, + Data: make([]float64, n*nb), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aCopy, vt, 0, ywant) + + // Compare Y and YWant. + for i := 0; i < n; i++ { + for j := 0; j < nb; j++ { + diff := math.Abs(ywant.Data[i*ywant.Stride+j] - y.Data[i*y.Stride+j]) + if diff > 1e-14 { + t.Errorf("%v: unexpected Y[%v,%v], diff=%v", prefix, i, j, diff) + } + } + } + + // Construct Q directly from the first nb columns of a. + q := constructQ("QR", n-k, nb, a.Data[k*a.Stride:], a.Stride, tau) + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal", prefix) + } + // Construct Q as the product Q = I - V*T*V^T. + qwant := blas64.General{ + Rows: n - k + 1, + Cols: n - k + 1, + Stride: n - k + 1, + Data: make([]float64, (n-k+1)*(n-k+1)), + } + for i := 0; i < qwant.Rows; i++ { + qwant.Data[i*qwant.Stride+i] = 1 + } + blas64.Gemm(blas.NoTrans, blas.Trans, -1, vt, v, 1, qwant) + if !isOrthonormal(qwant) { + t.Errorf("%v: Q = I - V*T*V^T is not orthogonal", prefix) + } + + // Compare Q and QWant. Note that since Q is + // (n-k)×(n-k) and QWant is (n-k+1)×(n-k+1), we + // ignore the first row and column of QWant. + for i := 0; i < n-k; i++ { + for j := 0; j < n-k; j++ { + diff := math.Abs(q.Data[i*q.Stride+j] - qwant.Data[(i+1)*qwant.Stride+j+1]) + if diff > 1e-14 { + t.Errorf("%v: unexpected Q[%v,%v], diff=%v", prefix, i, j, diff) + } + } + } + } + } + } + + // Go runs tests from the source directory, so unfortunately we need to + // include the "../testlapack" part. + file, err := os.Open(filepath.FromSlash("../testlapack/testdata/dlahr2data.json.gz")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + r, err := gzip.NewReader(file) + if err != nil { + log.Fatal(err) + } + defer r.Close() + + var tests []Dlahr2test + json.NewDecoder(r).Decode(&tests) + for _, test := range tests { + tau := make([]float64, len(test.TauWant)) + for _, ldex := range []int{0, 1, 20} { + n := test.N + k := test.K + nb := test.NB + + lda := n - k + 1 + ldex + a := make([]float64, (n-1)*lda+n-k+1) + copyMatrix(n, n-k+1, a, lda, test.A) + + ldt := nb + ldex + tmat := make([]float64, (nb-1)*ldt+nb) + + ldy := nb + ldex + y := make([]float64, (n-1)*ldy+nb) + + impl.Dlahr2(n, k, nb, a, lda, tau, tmat, ldt, y, ldy) + + prefix := fmt.Sprintf("Case n=%v, k=%v, nb=%v, ldex=%v", n, k, nb, ldex) + if !equalApprox(n, n-k+1, a, lda, test.AWant, 1e-14) { + t.Errorf("%v: unexpected matrix A\n got=%v\nwant=%v", prefix, a, test.AWant) + } + if !equalApproxTriangular(true, nb, tmat, ldt, test.TWant, 1e-14) { + t.Errorf("%v: unexpected matrix T\n got=%v\nwant=%v", prefix, tmat, test.TWant) + } + if !equalApprox(n, nb, y, ldy, test.YWant, 1e-14) { + t.Errorf("%v: unexpected matrix Y\n got=%v\nwant=%v", prefix, y, test.YWant) + } + if !floats.EqualApprox(tau, test.TauWant, 1e-14) { + t.Errorf("%v: unexpected slice tau\n got=%v\nwant=%v", prefix, tau, test.TauWant) + } + } + } +} diff --git a/lapack/testlapack/dlaln2.go b/lapack/testlapack/dlaln2.go new file mode 100644 index 00000000..07a322b8 --- /dev/null +++ b/lapack/testlapack/dlaln2.go @@ -0,0 +1,139 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/cmplx" + "math/rand" + "testing" +) + +type Dlaln2er interface { + Dlaln2(trans bool, na, nw int, smin, ca float64, a []float64, lda int, d1, d2 float64, b []float64, ldb int, wr, wi float64, x []float64, ldx int) (scale, xnorm float64, ok bool) +} + +func Dlaln2Test(t *testing.T, impl Dlaln2er) { + rnd := rand.New(rand.NewSource(1)) + for _, trans := range []bool{true, false} { + for _, na := range []int{1, 2} { + for _, nw := range []int{1, 2} { + for _, extra := range []int{0, 1, 2, 13} { + for cas := 0; cas < 1000; cas++ { + testDlaln2(t, impl, trans, na, nw, extra, rnd) + } + } + } + } + } +} + +func testDlaln2(t *testing.T, impl Dlaln2er, trans bool, na, nw, extra int, rnd *rand.Rand) { + const tol = 1e-12 + const dlamchE = 1.0 / (1 << 53) + const dlamchP = 2 * dlamchE + + ca := rnd.NormFloat64() + d1 := rnd.NormFloat64() + d2 := rnd.NormFloat64() + + var w complex128 + if nw == 1 { + w = complex(rand.NormFloat64(), 0) + } else { + w = complex(rand.NormFloat64(), rand.NormFloat64()) + } + smin := dlamchP * (math.Abs(real(w)) + math.Abs(imag(w))) + + a := randomGeneral(na, na, na+extra, rnd) + b := randomGeneral(na, nw, nw+extra, rnd) + x := randomGeneral(na, nw, nw+extra, rnd) + + scale, xnormGot, ok := impl.Dlaln2(trans, na, nw, smin, ca, a.Data, a.Stride, d1, d2, b.Data, b.Stride, real(w), imag(w), x.Data, x.Stride) + + prefix := fmt.Sprintf("Case trans=%v, na=%v, nw=%v, extra=%v", trans, na, nw, extra) + + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + if !generalOutsideAllNaN(b) { + t.Errorf("%v: out-of-range write to B\n%v", prefix, b.Data) + } + if !generalOutsideAllNaN(x) { + t.Errorf("%v: out-of-range write to X\n%v", prefix, x.Data) + } + + if scale <= 0 || 1 < scale { + t.Errorf("%v: invalid value of scale=%v", prefix, scale) + } + + var xnormWant float64 + for i := 0; i < na; i++ { + var rowsum float64 + for j := 0; j < nw; j++ { + rowsum += math.Abs(x.Data[i*x.Stride+j]) + } + if rowsum > xnormWant { + xnormWant = rowsum + } + } + if xnormWant != xnormGot { + t.Errorf("Case %v: unexpected xnorm with scale=%v. Want %v, got %v", prefix, scale, xnormWant, xnormGot) + } + + if !ok { + // If ok is false, the matrix has been perturbed but we don't + // know how. Return without comparing both sides of the + // equation. + return + } + + m := make([]complex128, na*na) + if trans { + for i := 0; i < na; i++ { + for j := 0; j < na; j++ { + m[i*na+j] = complex(ca*a.Data[j*a.Stride+i], 0) + } + } + } else { + for i := 0; i < na; i++ { + for j := 0; j < na; j++ { + m[i*na+j] = complex(ca*a.Data[i*a.Stride+j], 0) + } + } + } + m[0] -= w * complex(d1, 0) + if na == 2 { + m[3] -= w * complex(d2, 0) + } + + cx := make([]complex128, na) + cb := make([]complex128, na) + switch nw { + case 1: + for i := 0; i < na; i++ { + cx[i] = complex(x.Data[i*x.Stride], 0) + cb[i] = complex(scale*b.Data[i*x.Stride], 0) + } + case 2: + for i := 0; i < na; i++ { + cx[i] = complex(x.Data[i*x.Stride], x.Data[i*x.Stride+1]) + cb[i] = complex(scale*b.Data[i*b.Stride], scale*b.Data[i*b.Stride+1]) + } + } + + mx := make([]complex128, na) + for i := 0; i < na; i++ { + for j := 0; j < na; j++ { + mx[i] += m[i*na+j] * cx[j] + } + } + for i := 0; i < na; i++ { + if cmplx.Abs(mx[i]-cb[i]) > tol { + t.Errorf("Case %v: unexpected value of left-hand side at row %v with scale=%v. Want %v, got %v", prefix, i, scale, cb[i], mx[i]) + } + } +} diff --git a/lapack/testlapack/dlange.go b/lapack/testlapack/dlange.go new file mode 100644 index 00000000..33f7efe1 --- /dev/null +++ b/lapack/testlapack/dlange.go @@ -0,0 +1,93 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dlanger interface { + Dlange(norm lapack.MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 +} + +func DlangeTest(t *testing.T, impl Dlanger) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {4, 3, 0}, + {3, 4, 0}, + {4, 3, 100}, + {3, 4, 100}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() - 0.5 + } + work := make([]float64, n) + for i := range work { + work[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + // Test MaxAbs norm. + norm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, work) + var ans float64 + for i := 0; i < m; i++ { + idx := blas64.Iamax(n, blas64.Vector{Inc: 1, Data: aCopy[i*lda:]}) + ans = math.Max(ans, math.Abs(a[i*lda+idx])) + } + // Should be strictly equal because there is no floating point summation error. + if ans != norm { + t.Errorf("MaxAbs mismatch. Want %v, got %v.", ans, norm) + } + + // Test MaxColumnSum norm. + norm = impl.Dlange(lapack.MaxColumnSum, m, n, a, lda, work) + ans = 0 + for i := 0; i < n; i++ { + sum := blas64.Asum(m, blas64.Vector{Inc: lda, Data: aCopy[i:]}) + ans = math.Max(ans, sum) + } + if math.Abs(norm-ans) > 1e-14 { + t.Errorf("MaxColumnSum mismatch. Want %v, got %v.", ans, norm) + } + + // Test MaxRowSum norm. + norm = impl.Dlange(lapack.MaxRowSum, m, n, a, lda, work) + ans = 0 + for i := 0; i < m; i++ { + sum := blas64.Asum(n, blas64.Vector{Inc: 1, Data: aCopy[i*lda:]}) + ans = math.Max(ans, sum) + } + if math.Abs(norm-ans) > 1e-14 { + t.Errorf("MaxRowSum mismatch. Want %v, got %v.", ans, norm) + } + + // Test Frobenius norm + norm = impl.Dlange(lapack.NormFrob, m, n, a, lda, work) + ans = 0 + for i := 0; i < m; i++ { + sum := blas64.Nrm2(n, blas64.Vector{Inc: 1, Data: aCopy[i*lda:]}) + ans += sum * sum + } + ans = math.Sqrt(ans) + if math.Abs(norm-ans) > 1e-14 { + t.Errorf("NormFrob mismatch. Want %v, got %v.", ans, norm) + } + } +} diff --git a/lapack/testlapack/dlanst.go b/lapack/testlapack/dlanst.go new file mode 100644 index 00000000..224f1d07 --- /dev/null +++ b/lapack/testlapack/dlanst.go @@ -0,0 +1,53 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/lapack" +) + +type Dlanster interface { + Dlanst(norm lapack.MatrixNorm, n int, d, e []float64) float64 + Dlanger +} + +func DlanstTest(t *testing.T, impl Dlanster) { + rnd := rand.New(rand.NewSource(1)) + for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxColumnSum, lapack.MaxRowSum, lapack.NormFrob} { + for _, n := range []int{1, 3, 10, 100} { + for cas := 0; cas < 100; cas++ { + d := make([]float64, n) + for i := range d { + d[i] = rnd.NormFloat64() + } + e := make([]float64, n-1) + for i := range e { + e[i] = rnd.NormFloat64() + } + + m := n + lda := n + a := make([]float64, m*lda) + for i := 0; i < n; i++ { + a[i*lda+i] = d[i] + } + for i := 0; i < n-1; i++ { + a[i*lda+i+1] = e[i] + a[(i+1)*lda+i] = e[i] + } + work := make([]float64, n) + syNorm := impl.Dlanst(norm, n, d, e) + geNorm := impl.Dlange(norm, m, n, a, lda, work) + if math.Abs(syNorm-geNorm) > 1e-12 { + t.Errorf("Norm mismatch: norm = %v, cas = %v, n = %v. Want %v, got %v.", string(norm), cas, n, geNorm, syNorm) + } + } + } + } +} diff --git a/lapack/testlapack/dlansy.go b/lapack/testlapack/dlansy.go new file mode 100644 index 00000000..b38f6bb0 --- /dev/null +++ b/lapack/testlapack/dlansy.go @@ -0,0 +1,80 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +type Dlansyer interface { + Dlanger + Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 +} + +func DlansyTest(t *testing.T, impl Dlansyer) { + rnd := rand.New(rand.NewSource(1)) + for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxColumnSum, lapack.MaxRowSum, lapack.NormFrob} { + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {3, 0}, + + {1, 10}, + {3, 10}, + } { + for trial := 0; trial < 100; trial++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, lda*n) + if trial == 0 { + for i := range a { + a[i] = float64(i) + } + } else { + for i := range a { + a[i] = rnd.NormFloat64() + } + } + + aDense := make([]float64, n*n) + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := a[i*lda+j] + aDense[i*n+j] = v + aDense[j*n+i] = v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := a[i*lda+j] + aDense[i*n+j] = v + aDense[j*n+i] = v + } + } + } + work := make([]float64, n) + got := impl.Dlansy(norm, uplo, n, a, lda, work) + want := impl.Dlange(norm, n, n, aDense, n, work) + if math.Abs(want-got) > 1e-14 { + t.Errorf("Norm mismatch. norm = %c, upper = %v, n = %v, lda = %v, want %v, got %v.", + norm, uplo == blas.Upper, n, lda, got, want) + } + } + } + } + } +} diff --git a/lapack/testlapack/dlantr.go b/lapack/testlapack/dlantr.go new file mode 100644 index 00000000..74f3c656 --- /dev/null +++ b/lapack/testlapack/dlantr.go @@ -0,0 +1,89 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/lapack" +) + +type Dlantrer interface { + Dlanger + Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 +} + +func DlantrTest(t *testing.T, impl Dlantrer) { + rnd := rand.New(rand.NewSource(1)) + for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxColumnSum, lapack.MaxRowSum, lapack.NormFrob} { + for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, test := range []struct { + m, n, lda int + }{ + {3, 3, 0}, + {3, 5, 0}, + {10, 5, 0}, + + {5, 5, 11}, + {5, 10, 11}, + {10, 5, 11}, + } { + // Do a couple of random trials since the values change. + for trial := 0; trial < 100; trial++ { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + if trial == 0 { + for i := range a { + a[i] = float64(i) + } + } else { + for i := range a { + a[i] = rnd.NormFloat64() + } + } + aDense := make([]float64, len(a)) + if uplo == blas.Lower { + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + aDense[i*lda+j] = a[i*lda+j] + } + } + } else { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + aDense[i*lda+j] = a[i*lda+j] + } + } + } + if diag == blas.Unit { + for i := 0; i < min(m, n); i++ { + aDense[i*lda+i] = 1 + } + } + work := make([]float64, n+6) + for i := range work { + work[i] = rnd.Float64() + } + got := impl.Dlantr(norm, uplo, diag, m, n, a, lda, work) + want := impl.Dlange(norm, m, n, aDense, lda, work) + if math.Abs(got-want) > 1e-13 { + t.Errorf("Norm mismatch. norm = %c, unitdiag = %v, upper = %v, m = %v, n = %v, lda = %v, Want %v, got %v.", + norm, diag == blas.Unit, uplo == blas.Upper, m, n, lda, got, want) + } + } + } + } + } + } +} diff --git a/lapack/testlapack/dlanv2.go b/lapack/testlapack/dlanv2.go new file mode 100644 index 00000000..07cf2c51 --- /dev/null +++ b/lapack/testlapack/dlanv2.go @@ -0,0 +1,69 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" +) + +type Dlanv2er interface { + Dlanv2(a, b, c, d float64) (aa, bb, cc, dd float64, rt1r, rt1i, rt2r, rt2i float64, cs, sn float64) +} + +func Dlanv2Test(t *testing.T, impl Dlanv2er) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < 1000; i++ { + a := rnd.NormFloat64() + b := rnd.NormFloat64() + c := rnd.NormFloat64() + d := rnd.NormFloat64() + aa, bb, cc, dd, rt1r, rt1i, rt2r, rt2i, cs, sn := impl.Dlanv2(a, b, c, d) + + mat := fmt.Sprintf("[%v %v; %v %v]", a, b, c, d) + if cc == 0 { + if rt1i != 0 || rt2i != 0 { + t.Errorf("Unexpected complex eigenvalues for %v", mat) + } + } else { + if aa != dd { + t.Errorf("Diagonal elements not equal for %v: got [%v %v]", mat, aa, dd) + } + if bb*cc >= 0 { + t.Errorf("Non-diagonal elements have the same sign for %v: got [%v %v]", mat, bb, cc) + } else { + im := math.Sqrt(-bb * cc) + if math.Abs(rt1i-im) > 1e-14 && math.Abs(rt1i+im) > 1e-14 { + t.Errorf("Unexpected imaginary part of eigenvalue for %v: got %v, want %v or %v", mat, rt1i, im, -im) + } + if math.Abs(rt2i-im) > 1e-14 && math.Abs(rt2i+im) > 1e-14 { + t.Errorf("Unexpected imaginary part of eigenvalue for %v: got %v, want %v or %v", mat, rt2i, im, -im) + } + } + } + if rt1r != aa && rt1r != dd { + t.Errorf("Unexpected real part of eigenvalue for %v: got %v, want %v or %v", mat, rt1r, aa, dd) + } + if rt2r != aa && rt2r != dd { + t.Errorf("Unexpected real part of eigenvalue for %v: got %v, want %v or %v", mat, rt2r, aa, dd) + } + if math.Abs(math.Hypot(cs, sn)-1) > 1e-14 { + t.Errorf("Unexpected unitary matrix for %v: got cs %v, sn %v", mat, cs, sn) + } + + gota := cs*(aa*cs-bb*sn) - sn*(cc*cs-dd*sn) + gotb := cs*(aa*sn+bb*cs) - sn*(cc*sn+dd*cs) + gotc := sn*(aa*cs-bb*sn) + cs*(cc*cs-dd*sn) + gotd := sn*(aa*sn+bb*cs) + cs*(cc*sn+dd*cs) + if math.Abs(gota-a) > 1e-14 || + math.Abs(gotb-b) > 1e-14 || + math.Abs(gotc-c) > 1e-14 || + math.Abs(gotd-d) > 1e-14 { + t.Errorf("Unexpected factorization: got [%v %v; %v %v], want [%v %v; %v %v]", gota, gotb, gotc, gotd, a, b, c, d) + } + } +} diff --git a/lapack/testlapack/dlapll.go b/lapack/testlapack/dlapll.go new file mode 100644 index 00000000..1c35f039 --- /dev/null +++ b/lapack/testlapack/dlapll.go @@ -0,0 +1,46 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlapller interface { + Dgesvder + Dlapll(n int, x []float64, incX int, y []float64, incY int) float64 +} + +func DlapllTest(t *testing.T, impl Dlapller) { + rnd := rand.New(rand.NewSource(1)) + for i, m := range []int{5, 6, 9, 300, 400, 600} { + n := 2 + lda := n + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + got := impl.Dlapll(m, a[0:], 2, a[1:], 2) + + s := make([]float64, min(m, n)) + work := make([]float64, 1) + impl.Dgesvd(lapack.SVDNone, lapack.SVDNone, m, n, aCopy, lda, s, nil, 0, nil, 0, work, -1) + work = make([]float64, int(work[0])) + impl.Dgesvd(lapack.SVDNone, lapack.SVDNone, m, n, aCopy, lda, s, nil, 0, nil, 0, work, len(work)) + want := s[len(s)-1] + + if !floats.EqualWithinAbsOrRel(got, want, 1e-14, 1e-14) { + t.Errorf("unexpected ssmin for test %d: got:%f want:%f", i, got, want) + } + } +} diff --git a/lapack/testlapack/dlapmt.go b/lapack/testlapack/dlapmt.go new file mode 100644 index 00000000..b2fd1f8d --- /dev/null +++ b/lapack/testlapack/dlapmt.go @@ -0,0 +1,113 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlapmter interface { + Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) +} + +func DlapmtTest(t *testing.T, impl Dlapmter) { + for ti, test := range []struct { + forward bool + k []int + + want blas64.General + }{ + { + forward: true, k: []int{0, 1, 2}, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + }, + }, + }, + { + forward: false, k: []int{0, 1, 2}, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + }, + }, + }, + { + forward: true, k: []int{1, 2, 0}, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 2, 3, 1, + 5, 6, 4, + 8, 9, 7, + 11, 12, 10, + }, + }, + }, + { + forward: false, k: []int{1, 2, 0}, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 3, 1, 2, + 6, 4, 5, + 9, 7, 8, + 12, 10, 11, + }, + }, + }, + } { + m := test.want.Rows + n := test.want.Cols + if len(test.k) != n { + panic("bad length of k") + } + + for _, extra := range []int{0, 11} { + x := zeros(m, n, n+extra) + c := 1 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + x.Data[i*x.Stride+j] = float64(c) + c++ + } + } + + k := make([]int, len(test.k)) + copy(k, test.k) + + impl.Dlapmt(test.forward, m, n, x.Data, x.Stride, k) + + prefix := fmt.Sprintf("Case %v (forward=%t,m=%v,n=%v,extra=%v)", ti, test.forward, m, n, extra) + if !generalOutsideAllNaN(x) { + t.Errorf("%v: out-of-range write to X", prefix) + } + + if !equalApproxGeneral(x, test.want, 0) { + t.Errorf("%v: unexpected X\n%v\n%v", prefix, x, test.want) + } + } + } +} diff --git a/lapack/testlapack/dlapy2.go b/lapack/testlapack/dlapy2.go new file mode 100644 index 00000000..6efb81d9 --- /dev/null +++ b/lapack/testlapack/dlapy2.go @@ -0,0 +1,30 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlapy2er interface { + Dlapy2(float64, float64) float64 +} + +func Dlapy2Test(t *testing.T, impl Dlapy2er) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < 10; i++ { + x := math.Abs(1e200 * rnd.NormFloat64()) + y := math.Abs(1e200 * rnd.NormFloat64()) + got := impl.Dlapy2(x, y) + want := math.Hypot(x, y) + if !floats.EqualWithinRel(got, want, 1e-16) { + t.Errorf("Dlapy2(%g, %g) = %g, want %g", x, y, got, want) + } + } +} diff --git a/lapack/testlapack/dlaqp2.go b/lapack/testlapack/dlaqp2.go new file mode 100644 index 00000000..5ccfe996 --- /dev/null +++ b/lapack/testlapack/dlaqp2.go @@ -0,0 +1,115 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqp2er interface { + Dlapmter + Dlaqp2(m, n, offset int, a []float64, lda int, jpvt []int, tau, vn1, vn2, work []float64) +} + +func Dlaqp2Test(t *testing.T, impl Dlaqp2er) { + for ti, test := range []struct { + m, n, offset int + }{ + {m: 4, n: 3, offset: 0}, + {m: 4, n: 3, offset: 2}, + {m: 4, n: 3, offset: 4}, + {m: 3, n: 4, offset: 0}, + {m: 3, n: 4, offset: 1}, + {m: 3, n: 4, offset: 2}, + {m: 8, n: 3, offset: 0}, + {m: 8, n: 3, offset: 4}, + {m: 8, n: 3, offset: 8}, + {m: 3, n: 8, offset: 0}, + {m: 3, n: 8, offset: 1}, + {m: 3, n: 8, offset: 2}, + {m: 10, n: 10, offset: 0}, + {m: 10, n: 10, offset: 5}, + {m: 10, n: 10, offset: 10}, + } { + m := test.m + n := test.n + jpiv := make([]int, n) + + for _, extra := range []int{0, 11} { + a := zeros(m, n, n+extra) + c := 1 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = float64(c) + c++ + } + } + aCopy := cloneGeneral(a) + for j := range jpiv { + jpiv[j] = j + } + + tau := make([]float64, n) + vn1 := columnNorms(m, n, a.Data, a.Stride) + vn2 := columnNorms(m, n, a.Data, a.Stride) + work := make([]float64, n) + + impl.Dlaqp2(m, n, test.offset, a.Data, a.Stride, jpiv, tau, vn1, vn2, work) + + prefix := fmt.Sprintf("Case %v (offset=%t,m=%v,n=%v,extra=%v)", ti, test.offset, m, n, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + + if test.offset == m { + continue + } + + mo := m - test.offset + q := constructQ("QR", mo, n, a.Data[test.offset*a.Stride:], a.Stride, tau) + // Check that q is orthonormal + for i := 0; i < mo; i++ { + nrm := blas64.Nrm2(mo, blas64.Vector{Inc: 1, Data: q.Data[i*mo:]}) + if math.Abs(nrm-1) > 1e-13 { + t.Errorf("Case %v, q not normal", ti) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(mo, blas64.Vector{Inc: 1, Data: q.Data[i*mo:]}, blas64.Vector{Inc: 1, Data: q.Data[j*mo:]}) + if math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", ti) + } + } + } + + // Check that A * P = Q * R + r := blas64.General{ + Rows: mo, + Cols: n, + Stride: n, + Data: make([]float64, mo*n), + } + for i := 0; i < mo; i++ { + for j := i; j < n; j++ { + r.Data[i*n+j] = a.Data[(test.offset+i)*a.Stride+j] + } + } + got := nanGeneral(mo, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, got) + + want := aCopy + impl.Dlapmt(true, want.Rows, want.Cols, want.Data, want.Stride, jpiv) + want.Rows = mo + want.Data = want.Data[test.offset*want.Stride:] + if !equalApproxGeneral(got, want, 1e-12) { + t.Errorf("Case %v, Q*R != A*P\nQ*R=%v\nA*P=%v", ti, got, want) + } + } + } +} diff --git a/lapack/testlapack/dlaqps.go b/lapack/testlapack/dlaqps.go new file mode 100644 index 00000000..edf19378 --- /dev/null +++ b/lapack/testlapack/dlaqps.go @@ -0,0 +1,112 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqpser interface { + Dlapmter + Dlaqps(m, n, offset, nb int, a []float64, lda int, jpvt []int, tau, vn1, vn2, auxv, f []float64, ldf int) (kb int) +} + +func DlaqpsTest(t *testing.T, impl Dlaqpser) { + for ti, test := range []struct { + m, n, nb, offset int + }{ + {m: 4, n: 3, nb: 2, offset: 0}, + {m: 4, n: 3, nb: 1, offset: 2}, + {m: 3, n: 4, nb: 2, offset: 0}, + {m: 3, n: 4, nb: 1, offset: 2}, + {m: 8, n: 3, nb: 2, offset: 0}, + {m: 8, n: 3, nb: 1, offset: 4}, + {m: 3, n: 8, nb: 2, offset: 0}, + {m: 3, n: 8, nb: 1, offset: 1}, + {m: 10, n: 10, nb: 3, offset: 0}, + {m: 10, n: 10, nb: 2, offset: 5}, + } { + m := test.m + n := test.n + jpiv := make([]int, n) + + for _, extra := range []int{0, 11} { + a := zeros(m, n, n+extra) + c := 1 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = float64(c) + c++ + } + } + aCopy := cloneGeneral(a) + for j := range jpiv { + jpiv[j] = j + } + + tau := make([]float64, n) + vn1 := columnNorms(m, n, a.Data, a.Stride) + vn2 := columnNorms(m, n, a.Data, a.Stride) + auxv := make([]float64, test.nb) + f := zeros(test.n, test.nb, n) + + kb := impl.Dlaqps(m, n, test.offset, test.nb, a.Data, a.Stride, jpiv, tau, vn1, vn2, auxv, f.Data, f.Stride) + + prefix := fmt.Sprintf("Case %v (offset=%t,m=%v,n=%v,extra=%v)", ti, test.offset, m, n, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + + if test.offset == m { + continue + } + + mo := m - test.offset + q := constructQ("QR", mo, kb, a.Data[test.offset*a.Stride:], a.Stride, tau) + // Check that q is orthonormal + for i := 0; i < mo; i++ { + nrm := blas64.Nrm2(mo, blas64.Vector{Inc: 1, Data: q.Data[i*mo:]}) + if math.Abs(nrm-1) > 1e-13 { + t.Errorf("Case %v, q not normal", ti) + } + for j := 0; j < i; j++ { + dot := blas64.Dot(mo, blas64.Vector{Inc: 1, Data: q.Data[i*mo:]}, blas64.Vector{Inc: 1, Data: q.Data[j*mo:]}) + if math.Abs(dot) > 1e-14 { + t.Errorf("Case %v, q not orthogonal", ti) + } + } + } + + // Check that A * P = Q * R + r := blas64.General{ + Rows: mo, + Cols: kb, + Stride: kb, + Data: make([]float64, mo*kb), + } + for i := 0; i < mo; i++ { + for j := i; j < kb; j++ { + r.Data[i*kb+j] = a.Data[(test.offset+i)*a.Stride+j] + } + } + got := nanGeneral(mo, kb, kb) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, got) + + want := aCopy + impl.Dlapmt(true, want.Rows, want.Cols, want.Data, want.Stride, jpiv) + want.Rows = mo + want.Cols = kb + want.Data = want.Data[test.offset*want.Stride:] + if !equalApproxGeneral(got, want, 1e-12) { + t.Errorf("Case %v, Q*R != A*P\nQ*R=%v\nA*P=%v", ti, got, want) + } + } + } +} diff --git a/lapack/testlapack/dlaqr04.go b/lapack/testlapack/dlaqr04.go new file mode 100644 index 00000000..c92104e7 --- /dev/null +++ b/lapack/testlapack/dlaqr04.go @@ -0,0 +1,449 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqr04er interface { + Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, iloz, ihiz int, z []float64, ldz int, work []float64, lwork int, recur int) int + + Dlahqrer +} + +type dlaqr04Test struct { + h blas64.General + ilo, ihi int + iloz, ihiz int + wantt, wantz bool + + evWant []complex128 // Optional slice holding known eigenvalues. +} + +func Dlaqr04Test(t *testing.T, impl Dlaqr04er) { + rnd := rand.New(rand.NewSource(1)) + + // Tests for small matrices that choose the ilo,ihi and iloz,ihiz pairs + // randomly. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 11, 12, 18, 29} { + for _, extra := range []int{0, 11} { + for recur := 0; recur <= 2; recur++ { + for cas := 0; cas < n; cas++ { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + iloz := rnd.Intn(ilo + 1) + ihiz := ihi + rnd.Intn(n-ihi) + h := randomHessenberg(n, n+extra, rnd) + if ilo-1 >= 0 { + h.Data[ilo*h.Stride+ilo-1] = 0 + } + if ihi+1 < n { + h.Data[(ihi+1)*h.Stride+ihi] = 0 + } + test := dlaqr04Test{ + h: h, + ilo: ilo, + ihi: ihi, + iloz: iloz, + ihiz: ihiz, + wantt: wantt, + wantz: wantz, + } + testDlaqr04(t, impl, test, false, recur) + testDlaqr04(t, impl, test, true, recur) + } + } + } + } + } + } + + // Tests for matrices large enough to possibly use the recursion (but it + // doesn't seem to be the case). + for _, n := range []int{100, 500} { + for cas := 0; cas < 5; cas++ { + h := randomHessenberg(n, n, rnd) + test := dlaqr04Test{ + h: h, + ilo: 0, + ihi: n - 1, + iloz: 0, + ihiz: n - 1, + wantt: true, + wantz: true, + } + testDlaqr04(t, impl, test, true, 1) + } + } + + // Tests that make sure that some potentially problematic corner cases, + // like zero-sized matrix, are covered. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, extra := range []int{0, 1, 11} { + for _, test := range []dlaqr04Test{ + { + h: randomHessenberg(0, extra, rnd), + ilo: 0, + ihi: -1, + iloz: 0, + ihiz: -1, + }, + { + h: randomHessenberg(1, 1+extra, rnd), + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + }, + { + h: randomHessenberg(2, 2+extra, rnd), + ilo: 1, + ihi: 1, + iloz: 1, + ihiz: 1, + }, + { + h: randomHessenberg(2, 2+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 9, + iloz: 0, + ihiz: 9, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 9, + }, + { + h: randomHessenberg(10, 10+extra, rnd), + ilo: 9, + ihi: 9, + iloz: 0, + ihiz: 9, + }, + } { + if test.ilo-1 >= 0 { + test.h.Data[test.ilo*test.h.Stride+test.ilo-1] = 0 + } + if test.ihi+1 < test.h.Rows { + test.h.Data[(test.ihi+1)*test.h.Stride+test.ihi] = 0 + } + test.wantt = wantt + test.wantz = wantz + testDlaqr04(t, impl, test, false, 1) + testDlaqr04(t, impl, test, true, 1) + } + } + } + } + + // Tests with known eigenvalues computed by Octave. + for _, test := range []dlaqr04Test{ + { + h: blas64.General{ + Rows: 1, + Cols: 1, + Stride: 1, + Data: []float64{7.09965484086874e-1}, + }, + ilo: 0, + ihi: 0, + iloz: 0, + ihiz: 0, + evWant: []complex128{7.09965484086874e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 0, -1, + 1, 0, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{1i, -1i}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 6.25219991450918e-1, 8.17510791994361e-1, + 3.31218891622294e-1, 1.24103744878131e-1, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 1, 0, 0, 0, + 0, 6.25219991450918e-1, 8.17510791994361e-1, 0, + 0, 3.31218891622294e-1, 1.24103744878131e-1, 0, + 0, 0, 0, 1, + }, + }, + ilo: 1, + ihi: 2, + iloz: 0, + ihiz: 3, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + -1.1219562276608, 6.85473513349362e-1, + -8.19951061145131e-1, 1.93728523178888e-1, + }, + }, + ilo: 0, + ihi: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{ + -4.64113852240958e-1 + 3.59580510817350e-1i, + -4.64113852240958e-1 - 3.59580510817350e-1i, + }, + }, + { + h: blas64.General{ + Rows: 5, + Cols: 5, + Stride: 5, + Data: []float64{ + 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2, + -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1, + 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1, + 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1, + 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1, + }, + }, + ilo: 0, + ihi: 4, + iloz: 0, + ihiz: 4, + evWant: []complex128{ + 2.94393309555622, + 4.97029793606701e-1 + 3.63041654992384e-1i, + 4.97029793606701e-1 - 3.63041654992384e-1i, + -1.74079119166145e-1 + 2.01570009462092e-1i, + -1.74079119166145e-1 - 2.01570009462092e-1i, + }, + }, + } { + test.wantt = true + test.wantz = true + testDlaqr04(t, impl, test, false, 1) + testDlaqr04(t, impl, test, true, 1) + } +} + +func testDlaqr04(t *testing.T, impl Dlaqr04er, test dlaqr04Test, optwork bool, recur int) { + const tol = 1e-14 + + h := cloneGeneral(test.h) + n := h.Cols + extra := h.Stride - h.Cols + wantt := test.wantt + wantz := test.wantz + ilo := test.ilo + ihi := test.ihi + iloz := test.iloz + ihiz := test.ihiz + + var z, zCopy blas64.General + if wantz { + z = eye(n, n+extra) + zCopy = cloneGeneral(z) + } + + wr := nanSlice(ihi + 1) + wi := nanSlice(ihi + 1) + + var work []float64 + if optwork { + work = nanSlice(1) + impl.Dlaqr04(wantt, wantz, n, ilo, ihi, nil, 0, nil, nil, iloz, ihiz, nil, 0, work, -1, recur) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, n)) + } + + unconverged := impl.Dlaqr04(wantt, wantz, n, ilo, ihi, h.Data, h.Stride, wr, wi, iloz, ihiz, z.Data, z.Stride, work, len(work), recur) + + prefix := fmt.Sprintf("Case wantt=%v, wantz=%v, n=%v, ilo=%v, ihi=%v, iloz=%v, ihiz=%v, extra=%v, opt=%v", + wantt, wantz, n, ilo, ihi, iloz, ihiz, extra, optwork) + + if !generalOutsideAllNaN(h) { + t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data) + } + if !generalOutsideAllNaN(z) { + t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data) + } + + start := ilo // Index of the first computed eigenvalue. + if unconverged != 0 { + start = unconverged + if start == ihi+1 { + t.Logf("%v: no eigenvalue has converged", prefix) + } + } + + // Check that wr and wi have not been modified within [:start]. + if !isAllNaN(wr[:start]) { + t.Errorf("%v: unexpected modification of wr", prefix) + } + if !isAllNaN(wi[:start]) { + t.Errorf("%v: unexpected modification of wi", prefix) + } + + var hasReal bool + for i := start; i <= ihi; { + if wi[i] == 0 { // Real eigenvalue. + hasReal = true + // Check that the eigenvalue corresponds to a 1×1 block + // on the diagonal of H. + if wantt && wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i, i) + } + i++ + continue + } + + // Complex eigenvalue. + + // In the conjugate pair the real parts must be equal. + if wr[i] != wr[i+1] { + t.Errorf("%v: real part of conjugate pair not equal, i=%v", prefix, i) + } + // The first imaginary part must be positive. + if wi[i] < 0 { + t.Errorf("%v: wi[%v] not positive", prefix, i) + } + // The second imaginary part must be negative with the same + // magnitude. + if wi[i] != -wi[i+1] { + t.Errorf("%v: wi[%v] != wi[%v]", prefix, i, i+1) + } + if wantt { + // Check that wi[i] has the correct value. + if wr[i] != h.Data[i*h.Stride+i] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i, i) + } + if wr[i] != h.Data[(i+1)*h.Stride+i+1] { + t.Errorf("%v: wr[%v] != H[%v,%v]", prefix, i, i+1, i+1) + } + im := math.Sqrt(math.Abs(h.Data[(i+1)*h.Stride+i])) * math.Sqrt(math.Abs(h.Data[i*h.Stride+i+1])) + if math.Abs(im-wi[i]) > tol { + t.Errorf("%v: unexpected value of wi[%v]: want %v, got %v", prefix, i, im, wi[i]) + } + } + i += 2 + } + // If the number of found eigenvalues is odd, at least one must be real. + if (ihi+1-start)%2 != 0 && !hasReal { + t.Errorf("%v: expected at least one real eigenvalue", prefix) + } + + // Compare found eigenvalues to the reference, if known. + if test.evWant != nil { + for i := start; i <= ihi; i++ { + ev := complex(wr[i], wi[i]) + found, _ := containsComplex(test.evWant, ev, tol) + if !found { + t.Errorf("%v: unexpected eigenvalue %v", prefix, ev) + } + } + } + + if !wantz { + return + } + + // Z should contain the orthogonal matrix U. + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + // Z should have been modified only in the + // [iloz:ihiz+1,ilo:ihi+1] block. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if iloz <= i && i <= ihiz && ilo <= j && j <= ihi { + continue + } + if z.Data[i*z.Stride+j] != zCopy.Data[i*zCopy.Stride+j] { + t.Errorf("%v: Z modified outside of [iloz:ihiz+1,ilo:ihi+1] block", prefix) + } + } + } + if wantt { + // Zero out h under the subdiagonal because Dlaqr04 uses it as + // workspace. + for i := 2; i < n; i++ { + for j := 0; j < i-1; j++ { + h.Data[i*h.Stride+j] = 0 + } + } + hz := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, test.h, z, 0, hz) + zhz := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hz, 0, zhz) + if !equalApproxGeneral(zhz, h, 10*tol) { + t.Errorf("%v: Z^T*(initial H)*Z and (final H) are not equal", prefix) + } + } +} diff --git a/lapack/testlapack/dlaqr1.go b/lapack/testlapack/dlaqr1.go new file mode 100644 index 00000000..9276bfd5 --- /dev/null +++ b/lapack/testlapack/dlaqr1.go @@ -0,0 +1,91 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlaqr1er interface { + Dlaqr1(n int, h []float64, ldh int, sr1, si1, sr2, si2 float64, v []float64) +} + +func Dlaqr1Test(t *testing.T, impl Dlaqr1er) { + rnd := rand.New(rand.NewSource(1)) + + for _, n := range []int{2, 3} { + for _, ldh := range []int{n, n + 1, n + 10} { + for _, cas := range []int{1, 2} { + for k := 0; k < 100; k++ { + v := make([]float64, n) + for i := range v { + v[i] = math.NaN() + } + h := make([]float64, n*(n-1)*ldh) + for i := range h { + h[i] = math.NaN() + } + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + h[i*ldh+j] = rnd.NormFloat64() + } + } + var sr1, sr2, si1, si2 float64 + if cas == 1 { + sr1 = rnd.NormFloat64() + sr2 = sr1 + si1 = rnd.NormFloat64() + si2 = -si1 + } else { + sr1 = rnd.NormFloat64() + sr2 = rnd.NormFloat64() + si1 = 0 + si2 = 0 + } + impl.Dlaqr1(n, h, ldh, sr1, si1, sr2, si2, v) + + // Matrix H - s1*I. + h1 := make([]complex128, n*n) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + h1[i*n+j] = complex(h[i*ldh+j], 0) + if i == j { + h1[i*n+j] -= complex(sr1, si1) + } + } + } + // First column of H - s2*I. + h2 := make([]complex128, n) + for i := 0; i < n; i++ { + h2[i] = complex(h[i*ldh], 0) + } + h2[0] -= complex(sr2, si2) + + wantv := make([]float64, n) + // Multiply (H-s1*I)*(H-s2*I) to get a tentative + // wantv. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + wantv[i] += real(h1[i*n+j] * h2[j]) + } + } + // Get the unknown scale. + scale := v[0] / wantv[0] + // Compute the actual wantv. + floats.Scale(scale, wantv) + + // The scale must be the same for all elements. + if floats.Distance(wantv, v, math.Inf(1)) > 1e-13 { + t.Errorf("n = %v, ldh = %v, case = %v: Unexpected value of v: got %v, want %v", n, ldh, cas, v, wantv) + } + } + } + } + } +} diff --git a/lapack/testlapack/dlaqr23.go b/lapack/testlapack/dlaqr23.go new file mode 100644 index 00000000..236b3519 --- /dev/null +++ b/lapack/testlapack/dlaqr23.go @@ -0,0 +1,335 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqr23er interface { + Dlaqr23(wantt, wantz bool, n, ktop, kbot, nw int, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, sr, si []float64, v []float64, ldv int, nh int, t []float64, ldt int, nv int, wv []float64, ldwv int, work []float64, lwork int, recur int) (ns, nd int) +} + +type dlaqr23Test struct { + wantt, wantz bool + ktop, kbot int + nw int + h blas64.General + iloz, ihiz int + + evWant []complex128 // Optional slice with known eigenvalues. +} + +func Dlaqr23Test(t *testing.T, impl Dlaqr23er) { + rnd := rand.New(rand.NewSource(1)) + + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 100} { + for _, extra := range []int{0, 11} { + for cas := 0; cas < 30; cas++ { + var nw int + if nw <= 75 { + nw = rnd.Intn(n) + 1 + } else { + nw = 76 + rnd.Intn(n-75) + } + ktop := rnd.Intn(n - nw + 1) + kbot := ktop + nw - 1 + kbot += rnd.Intn(n - kbot) + h := randomHessenberg(n, n+extra, rnd) + if ktop-1 >= 0 { + h.Data[ktop*h.Stride+ktop-1] = 0 + } + if kbot+1 < n { + h.Data[(kbot+1)*h.Stride+kbot] = 0 + } + iloz := rnd.Intn(ktop + 1) + ihiz := kbot + rnd.Intn(n-kbot) + test := dlaqr23Test{ + wantt: wantt, + wantz: wantz, + ktop: ktop, + kbot: kbot, + nw: nw, + h: h, + iloz: iloz, + ihiz: ihiz, + } + testDlaqr23(t, impl, test, false, 1, rnd) + testDlaqr23(t, impl, test, true, 1, rnd) + testDlaqr23(t, impl, test, false, 0, rnd) + testDlaqr23(t, impl, test, true, 0, rnd) + } + } + } + } + } + + // Tests with n=0. + for _, wantt := range []bool{true, false} { + for _, wantz := range []bool{true, false} { + for _, extra := range []int{0, 1, 11} { + test := dlaqr23Test{ + wantt: wantt, + wantz: wantz, + h: randomHessenberg(0, extra, rnd), + ktop: 0, + kbot: -1, + iloz: 0, + ihiz: -1, + nw: 0, + } + testDlaqr23(t, impl, test, true, 1, rnd) + testDlaqr23(t, impl, test, false, 1, rnd) + testDlaqr23(t, impl, test, true, 0, rnd) + testDlaqr23(t, impl, test, false, 0, rnd) + } + } + } + + // Tests with explicit eigenvalues computed by Octave. + for _, test := range []dlaqr23Test{ + { + h: blas64.General{ + Rows: 1, + Cols: 1, + Stride: 1, + Data: []float64{7.09965484086874e-1}, + }, + ktop: 0, + kbot: 0, + iloz: 0, + ihiz: 0, + evWant: []complex128{7.09965484086874e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 0, -1, + 1, 0, + }, + }, + ktop: 0, + kbot: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{1i, -1i}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + 6.25219991450918e-1, 8.17510791994361e-1, + 3.31218891622294e-1, 1.24103744878131e-1, + }, + }, + ktop: 0, + kbot: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 1, 0, 0, 0, + 0, 6.25219991450918e-1, 8.17510791994361e-1, 0, + 0, 3.31218891622294e-1, 1.24103744878131e-1, 0, + 0, 0, 0, 1, + }, + }, + ktop: 1, + kbot: 2, + iloz: 0, + ihiz: 3, + evWant: []complex128{9.52203547663447e-1, -2.02879811334398e-1}, + }, + { + h: blas64.General{ + Rows: 2, + Cols: 2, + Stride: 2, + Data: []float64{ + -1.1219562276608, 6.85473513349362e-1, + -8.19951061145131e-1, 1.93728523178888e-1, + }, + }, + ktop: 0, + kbot: 1, + iloz: 0, + ihiz: 1, + evWant: []complex128{ + -4.64113852240958e-1 + 3.59580510817350e-1i, + -4.64113852240958e-1 - 3.59580510817350e-1i, + }, + }, + { + h: blas64.General{ + Rows: 5, + Cols: 5, + Stride: 5, + Data: []float64{ + 9.57590178533658e-1, -5.10651295522708e-1, 9.24974510015869e-1, -1.30016306879522e-1, 2.92601986926954e-2, + -1.08084756637964, 1.77529701001213, -1.36480197632509, 2.23196371219601e-1, 1.12912853063308e-1, + 0, -8.44075612174676e-1, 1.067867614486, -2.55782915176399e-1, -2.00598563137468e-1, + 0, 0, -5.67097237165410e-1, 2.07205057427341e-1, 6.54998340743380e-1, + 0, 0, 0, -1.89441413886041e-1, -4.18125416021786e-1, + }, + }, + ktop: 0, + kbot: 4, + iloz: 0, + ihiz: 4, + evWant: []complex128{ + 2.94393309555622, + 4.97029793606701e-1 + 3.63041654992384e-1i, + 4.97029793606701e-1 - 3.63041654992384e-1i, + -1.74079119166145e-1 + 2.01570009462092e-1i, + -1.74079119166145e-1 - 2.01570009462092e-1i, + }, + }, + } { + test.wantt = true + test.wantz = true + test.nw = test.kbot - test.ktop + 1 + testDlaqr23(t, impl, test, true, 1, rnd) + testDlaqr23(t, impl, test, false, 1, rnd) + testDlaqr23(t, impl, test, true, 0, rnd) + testDlaqr23(t, impl, test, false, 0, rnd) + } +} + +func testDlaqr23(t *testing.T, impl Dlaqr23er, test dlaqr23Test, opt bool, recur int, rnd *rand.Rand) { + const tol = 1e-14 + + h := cloneGeneral(test.h) + n := h.Cols + extra := h.Stride - h.Cols + wantt := test.wantt + wantz := test.wantz + ktop := test.ktop + kbot := test.kbot + nw := test.nw + iloz := test.iloz + ihiz := test.ihiz + + var z, zCopy blas64.General + if wantz { + z = eye(n, n+extra) + zCopy = cloneGeneral(z) + } + + sr := nanSlice(kbot + 1) + si := nanSlice(kbot + 1) + + v := randomGeneral(nw, nw, nw+extra, rnd) + var nh int + if nw > 0 { + nh = nw + rnd.Intn(nw) // nh must be at least nw. + } + tmat := randomGeneral(nw, nh, nh+extra, rnd) + var nv int + if nw > 0 { + nv = rnd.Intn(nw) + 1 + } + wv := randomGeneral(nv, nw, nw+extra, rnd) + + var work []float64 + if opt { + work = nanSlice(1) + impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, nil, h.Stride, iloz, ihiz, nil, z.Stride, + nil, nil, nil, v.Stride, tmat.Cols, nil, tmat.Stride, wv.Rows, nil, wv.Stride, work, -1, recur) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, 2*nw)) + } + + ns, nd := impl.Dlaqr23(wantt, wantz, n, ktop, kbot, nw, h.Data, h.Stride, iloz, ihiz, z.Data, z.Stride, + sr, si, v.Data, v.Stride, tmat.Cols, tmat.Data, tmat.Stride, wv.Rows, wv.Data, wv.Stride, work, len(work), recur) + + prefix := fmt.Sprintf("Case wantt=%v, wantz=%v, n=%v, ktop=%v, kbot=%v, nw=%v, iloz=%v, ihiz=%v, extra=%v", + wantt, wantz, n, ktop, kbot, nw, iloz, ihiz, extra) + + if !generalOutsideAllNaN(h) { + t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data) + } + if !generalOutsideAllNaN(z) { + t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data) + } + if !generalOutsideAllNaN(v) { + t.Errorf("%v: out-of-range write to V\n%v", prefix, v.Data) + } + if !generalOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T\n%v", prefix, tmat.Data) + } + if !generalOutsideAllNaN(wv) { + t.Errorf("%v: out-of-range write to WV\n%v", prefix, wv.Data) + } + if !isAllNaN(sr[:kbot-nd-ns+1]) || !isAllNaN(sr[kbot+1:]) { + t.Errorf("%v: out-of-range write to sr") + } + if !isAllNaN(si[:kbot-nd-ns+1]) || !isAllNaN(si[kbot+1:]) { + t.Errorf("%v: out-of-range write to si") + } + + if !isUpperHessenberg(h) { + t.Errorf("%v: H is not upper Hessenberg", prefix) + } + + if test.evWant != nil { + for i := kbot - nd + 1; i <= kbot; i++ { + ev := complex(sr[i], si[i]) + found, _ := containsComplex(test.evWant, ev, tol) + if !found { + t.Errorf("%v: unexpected eigenvalue %v", prefix, ev) + } + } + } + + if !wantz { + return + } + + var zmod bool + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if z.Data[i*z.Stride+j] == zCopy.Data[i*zCopy.Stride+j] { + continue + } + if i < iloz || i > ihiz || j < kbot-nw+1 || j > kbot { + zmod = true + } + } + } + if zmod { + t.Errorf("%v: unexpected modification of Z", prefix) + } + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + if wantt { + hu := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, test.h, z, 0, hu) + uhu := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hu, 0, uhu) + if !equalApproxGeneral(uhu, h, 10*tol) { + t.Errorf("%v: Z^T*(initial H)*Z and (final H) are not equal", prefix) + } + } +} diff --git a/lapack/testlapack/dlaqr5.go b/lapack/testlapack/dlaqr5.go new file mode 100644 index 00000000..a93181dc --- /dev/null +++ b/lapack/testlapack/dlaqr5.go @@ -0,0 +1,214 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "compress/gzip" + "encoding/json" + "fmt" + "log" + "math" + "math/rand" + "os" + "path/filepath" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaqr5er interface { + Dlaqr5(wantt, wantz bool, kacc22 int, n, ktop, kbot, nshfts int, sr, si []float64, h []float64, ldh int, iloz, ihiz int, z []float64, ldz int, v []float64, ldv int, u []float64, ldu int, nh int, wh []float64, ldwh int, nv int, wv []float64, ldwv int) +} + +type Dlaqr5test struct { + WantT bool + N int + NShifts int + KTop, KBot int + ShiftR, ShiftI []float64 + H []float64 + + HWant []float64 + ZWant []float64 +} + +func Dlaqr5Test(t *testing.T, impl Dlaqr5er) { + // Test without using reference data. + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 30} { + for _, extra := range []int{0, 1, 20} { + for _, kacc22 := range []int{0, 1, 2} { + for cas := 0; cas < 100; cas++ { + testDlaqr5(t, impl, n, extra, kacc22, rnd) + } + } + } + } + + // Test using reference data computed by the reference netlib + // implementation. + file, err := os.Open(filepath.FromSlash("../testlapack/testdata/dlaqr5data.json.gz")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + r, err := gzip.NewReader(file) + if err != nil { + log.Fatal(err) + } + defer r.Close() + + var tests []Dlaqr5test + json.NewDecoder(r).Decode(&tests) + for _, test := range tests { + wantt := test.WantT + n := test.N + nshfts := test.NShifts + ktop := test.KTop + kbot := test.KBot + sr := test.ShiftR + si := test.ShiftI + + for _, extra := range []int{0, 1, 10} { + v := randomGeneral(nshfts/2, 3, 3+extra, rnd) + u := randomGeneral(3*nshfts-3, 3*nshfts-3, 3*nshfts-3+extra, rnd) + nh := n + wh := randomGeneral(3*nshfts-3, n, n+extra, rnd) + nv := n + wv := randomGeneral(n, 3*nshfts-3, 3*nshfts-3+extra, rnd) + + h := nanGeneral(n, n, n+extra) + + for _, kacc22 := range []int{0, 1, 2} { + copyMatrix(n, n, h.Data, h.Stride, test.H) + z := eye(n, n+extra) + + impl.Dlaqr5(wantt, true, kacc22, + n, ktop, kbot, + nshfts, sr, si, + h.Data, h.Stride, + 0, n-1, z.Data, z.Stride, + v.Data, v.Stride, + u.Data, u.Stride, + nv, wv.Data, wv.Stride, + nh, wh.Data, wh.Stride) + + prefix := fmt.Sprintf("wantt=%v, n=%v, nshfts=%v, ktop=%v, kbot=%v, extra=%v, kacc22=%v", + wantt, n, nshfts, ktop, kbot, extra, kacc22) + if !equalApprox(n, n, h.Data, h.Stride, test.HWant, 1e-13) { + t.Errorf("Case %v: unexpected matrix H\nh =%v\nhwant=%v", prefix, h.Data, test.HWant) + } + if !equalApprox(n, n, z.Data, z.Stride, test.ZWant, 1e-13) { + t.Errorf("Case %v: unexpected matrix Z\nz =%v\nzwant=%v", prefix, z.Data, test.ZWant) + } + } + } + } +} + +func testDlaqr5(t *testing.T, impl Dlaqr5er, n, extra, kacc22 int, rnd *rand.Rand) { + wantt := true + wantz := true + nshfts := 2 * n + sr := make([]float64, nshfts) + si := make([]float64, nshfts) + for i := 0; i < n; i++ { + re := rnd.NormFloat64() + im := rnd.NormFloat64() + sr[2*i], sr[2*i+1] = re, re + si[2*i], si[2*i+1] = im, -im + } + ktop := rnd.Intn(n) + kbot := rnd.Intn(n) + if kbot < ktop { + ktop, kbot = kbot, ktop + } + + v := randomGeneral(nshfts/2, 3, 3+extra, rnd) + u := randomGeneral(3*nshfts-3, 3*nshfts-3, 3*nshfts-3+extra, rnd) + nh := n + wh := randomGeneral(3*nshfts-3, n, n+extra, rnd) + nv := n + wv := randomGeneral(n, 3*nshfts-3, 3*nshfts-3+extra, rnd) + + h := randomHessenberg(n, n+extra, rnd) + if ktop > 0 { + h.Data[ktop*h.Stride+ktop-1] = 0 + } + if kbot < n-1 { + h.Data[(kbot+1)*h.Stride+kbot] = 0 + } + hCopy := h + hCopy.Data = make([]float64, len(h.Data)) + copy(hCopy.Data, h.Data) + + z := eye(n, n+extra) + + impl.Dlaqr5(wantt, wantz, kacc22, + n, ktop, kbot, + nshfts, sr, si, + h.Data, h.Stride, + 0, n-1, z.Data, z.Stride, + v.Data, v.Stride, + u.Data, u.Stride, + nv, wv.Data, wv.Stride, + nh, wh.Data, wh.Stride) + + prefix := fmt.Sprintf("Case n=%v, extra=%v, kacc22=%v", n, extra, kacc22) + + if !generalOutsideAllNaN(h) { + t.Errorf("%v: out-of-range write to H\n%v", prefix, h.Data) + } + if !generalOutsideAllNaN(z) { + t.Errorf("%v: out-of-range write to Z\n%v", prefix, z.Data) + } + if !generalOutsideAllNaN(u) { + t.Errorf("%v: out-of-range write to U\n%v", prefix, u.Data) + } + if !generalOutsideAllNaN(v) { + t.Errorf("%v: out-of-range write to V\n%v", prefix, v.Data) + } + if !generalOutsideAllNaN(wh) { + t.Errorf("%v: out-of-range write to WH\n%v", prefix, wh.Data) + } + if !generalOutsideAllNaN(wv) { + t.Errorf("%v: out-of-range write to WV\n%v", prefix, wv.Data) + } + + for i := 0; i < n; i++ { + for j := 0; j < i-1; j++ { + if h.Data[i*h.Stride+j] != 0 { + t.Errorf("%v: H is not Hessenberg, H[%v,%v]!=0", prefix, i, j) + } + } + } + if !isOrthonormal(z) { + t.Errorf("%v: Z is not orthogonal", prefix) + } + // Construct Z^T * HOrig * Z and check that it is equal to H from Dlaqr5. + hz := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hCopy, z, 0, hz) + zhz := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, z, hz, 0, zhz) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + diff := zhz.Data[i*zhz.Stride+j] - h.Data[i*h.Stride+j] + if math.Abs(diff) > 1e-13 { + t.Errorf("%v: Z^T*HOrig*Z and H are not equal, diff at [%v,%v]=%v", prefix, i, j, diff) + } + } + } +} diff --git a/lapack/testlapack/dlarf.go b/lapack/testlapack/dlarf.go new file mode 100644 index 00000000..82b2756a --- /dev/null +++ b/lapack/testlapack/dlarf.go @@ -0,0 +1,173 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dlarfer interface { + Dlarf(side blas.Side, m, n int, v []float64, incv int, tau float64, c []float64, ldc int, work []float64) +} + +func DlarfTest(t *testing.T, impl Dlarfer) { + rnd := rand.New(rand.NewSource(1)) + for i, test := range []struct { + m, n, ldc int + incv, lastv int + lastr, lastc int + tau float64 + }{ + { + m: 3, + n: 2, + ldc: 2, + + incv: 4, + lastv: 1, + + lastr: 2, + lastc: 1, + + tau: 2, + }, + { + m: 2, + n: 3, + ldc: 3, + + incv: 4, + lastv: 1, + + lastr: 1, + lastc: 2, + + tau: 2, + }, + { + m: 2, + n: 3, + ldc: 3, + + incv: 4, + lastv: 1, + + lastr: 0, + lastc: 1, + + tau: 2, + }, + { + m: 2, + n: 3, + ldc: 3, + + incv: 4, + lastv: 0, + + lastr: 0, + lastc: 1, + + tau: 2, + }, + { + m: 10, + n: 10, + ldc: 10, + + incv: 4, + lastv: 6, + + lastr: 9, + lastc: 8, + + tau: 2, + }, + } { + // Construct a random matrix. + c := make([]float64, test.ldc*test.m) + for i := 0; i <= test.lastr; i++ { + for j := 0; j <= test.lastc; j++ { + c[i*test.ldc+j] = rnd.Float64() + } + } + cCopy := make([]float64, len(c)) + copy(cCopy, c) + cCopy2 := make([]float64, len(c)) + copy(cCopy2, c) + + // Test with side right. + sz := max(test.m, test.n) // so v works for both right and left side. + v := make([]float64, test.incv*sz+1) + // Fill with nonzero entries up until lastv. + for i := 0; i <= test.lastv; i++ { + v[i*test.incv] = rnd.Float64() + } + // Construct h explicitly to compare. + h := make([]float64, test.n*test.n) + for i := 0; i < test.n; i++ { + h[i*test.n+i] = 1 + } + hMat := blas64.General{ + Rows: test.n, + Cols: test.n, + Stride: test.n, + Data: h, + } + vVec := blas64.Vector{ + Inc: test.incv, + Data: v, + } + blas64.Ger(-test.tau, vVec, vVec, hMat) + + // Apply multiplication (2nd copy is to avoid aliasing). + cMat := blas64.General{ + Rows: test.m, + Cols: test.n, + Stride: test.ldc, + Data: cCopy, + } + cMat2 := blas64.General{ + Rows: test.m, + Cols: test.n, + Stride: test.ldc, + Data: cCopy2, + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMat2, hMat, 0, cMat) + + // cMat now stores the true answer. Compare with the function call. + work := make([]float64, sz) + impl.Dlarf(blas.Right, test.m, test.n, v, test.incv, test.tau, c, test.ldc, work) + if !floats.EqualApprox(c, cMat.Data, 1e-14) { + t.Errorf("Dlarf mismatch right, case %v. Want %v, got %v", i, cMat.Data, c) + } + + // Test on the left side. + copy(c, cCopy2) + copy(cCopy, c) + // Construct h. + h = make([]float64, test.m*test.m) + for i := 0; i < test.m; i++ { + h[i*test.m+i] = 1 + } + hMat = blas64.General{ + Rows: test.m, + Cols: test.m, + Stride: test.m, + Data: h, + } + blas64.Ger(-test.tau, vVec, vVec, hMat) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hMat, cMat2, 0, cMat) + impl.Dlarf(blas.Left, test.m, test.n, v, test.incv, test.tau, c, test.ldc, work) + if !floats.EqualApprox(c, cMat.Data, 1e-14) { + t.Errorf("Dlarf mismatch left, case %v. Want %v, got %v", i, cMat.Data, c) + } + } +} diff --git a/lapack/testlapack/dlarfb.go b/lapack/testlapack/dlarfb.go new file mode 100644 index 00000000..89e65e64 --- /dev/null +++ b/lapack/testlapack/dlarfb.go @@ -0,0 +1,161 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlarfber interface { + Dlarfter + Dlarfb(side blas.Side, trans blas.Transpose, direct lapack.Direct, + store lapack.StoreV, m, n, k int, v []float64, ldv int, t []float64, ldt int, + c []float64, ldc int, work []float64, ldwork int) +} + +func DlarfbTest(t *testing.T, impl Dlarfber) { + rnd := rand.New(rand.NewSource(1)) + for _, store := range []lapack.StoreV{lapack.ColumnWise, lapack.RowWise} { + for _, direct := range []lapack.Direct{lapack.Forward, lapack.Backward} { + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.Trans, blas.NoTrans} { + for cas, test := range []struct { + ma, na, cdim, lda, ldt, ldc int + }{ + {6, 6, 6, 0, 0, 0}, + {6, 8, 10, 0, 0, 0}, + {6, 10, 8, 0, 0, 0}, + {8, 6, 10, 0, 0, 0}, + {8, 10, 6, 0, 0, 0}, + {10, 6, 8, 0, 0, 0}, + {10, 8, 6, 0, 0, 0}, + {6, 6, 6, 12, 15, 30}, + {6, 8, 10, 12, 15, 30}, + {6, 10, 8, 12, 15, 30}, + {8, 6, 10, 12, 15, 30}, + {8, 10, 6, 12, 15, 30}, + {10, 6, 8, 12, 15, 30}, + {10, 8, 6, 12, 15, 30}, + {6, 6, 6, 15, 12, 30}, + {6, 8, 10, 15, 12, 30}, + {6, 10, 8, 15, 12, 30}, + {8, 6, 10, 15, 12, 30}, + {8, 10, 6, 15, 12, 30}, + {10, 6, 8, 15, 12, 30}, + {10, 8, 6, 15, 12, 30}, + } { + // Generate a matrix for QR + ma := test.ma + na := test.na + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := 0; i < ma; i++ { + for j := 0; j < lda; j++ { + a[i*lda+j] = rnd.Float64() + } + } + k := min(ma, na) + + // H is always ma x ma + var m, n, rowsWork int + switch { + default: + panic("not implemented") + case side == blas.Left: + m = test.ma + n = test.cdim + rowsWork = n + case side == blas.Right: + m = test.cdim + n = test.ma + rowsWork = m + } + + // Use dgeqr2 to find the v vectors + tau := make([]float64, na) + work := make([]float64, na) + impl.Dgeqr2(ma, k, a, lda, tau, work) + + // Correct the v vectors based on the direct and store + vMatTmp := extractVMat(ma, na, a, lda, lapack.Forward, lapack.ColumnWise) + vMat := constructVMat(vMatTmp, store, direct) + v := vMat.Data + ldv := vMat.Stride + + // Use dlarft to find the t vector + ldt := test.ldt + if ldt == 0 { + ldt = k + } + tm := make([]float64, k*ldt) + + impl.Dlarft(direct, store, ma, k, v, ldv, tau, tm, ldt) + + // Generate c matrix + ldc := test.ldc + if ldc == 0 { + ldc = n + } + c := make([]float64, m*ldc) + for i := 0; i < m; i++ { + for j := 0; j < ldc; j++ { + c[i*ldc+j] = rnd.Float64() + } + } + cCopy := make([]float64, len(c)) + copy(cCopy, c) + + ldwork := k + work = make([]float64, rowsWork*k) + + // Call Dlarfb with this information + impl.Dlarfb(side, trans, direct, store, m, n, k, v, ldv, tm, ldt, c, ldc, work, ldwork) + + h := constructH(tau, vMat, store, direct) + + cMat := blas64.General{ + Rows: m, + Cols: n, + Stride: ldc, + Data: make([]float64, m*ldc), + } + copy(cMat.Data, cCopy) + ans := blas64.General{ + Rows: m, + Cols: n, + Stride: ldc, + Data: make([]float64, m*ldc), + } + copy(ans.Data, cMat.Data) + switch { + default: + panic("not implemented") + case side == blas.Left && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, cMat, 0, ans) + case side == blas.Left && trans == blas.Trans: + blas64.Gemm(blas.Trans, blas.NoTrans, 1, h, cMat, 0, ans) + case side == blas.Right && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMat, h, 0, ans) + case side == blas.Right && trans == blas.Trans: + blas64.Gemm(blas.NoTrans, blas.Trans, 1, cMat, h, 0, ans) + } + if !floats.EqualApprox(ans.Data, c, 1e-14) { + t.Errorf("Cas %v mismatch. Want %v, got %v.", cas, ans.Data, c) + } + } + } + } + } + } +} diff --git a/lapack/testlapack/dlarfg.go b/lapack/testlapack/dlarfg.go new file mode 100644 index 00000000..aa463235 --- /dev/null +++ b/lapack/testlapack/dlarfg.go @@ -0,0 +1,134 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlarfger interface { + Dlarfg(n int, alpha float64, x []float64, incX int) (beta, tau float64) +} + +func DlarfgTest(t *testing.T, impl Dlarfger) { + rnd := rand.New(rand.NewSource(1)) + for i, test := range []struct { + alpha float64 + n int + x []float64 + }{ + { + alpha: 4, + n: 3, + }, + { + alpha: -2, + n: 3, + }, + { + alpha: 0, + n: 3, + }, + { + alpha: 1, + n: 1, + }, + { + alpha: 1, + n: 2, + x: []float64{4, 5, 6}, + }, + } { + n := test.n + incX := 1 + var x []float64 + if test.x == nil { + x = make([]float64, n-1) + for i := range x { + x[i] = rnd.Float64() + } + } else { + x = make([]float64, n-1) + copy(x, test.x) + } + xcopy := make([]float64, n-1) + copy(xcopy, x) + alpha := test.alpha + beta, tau := impl.Dlarfg(n, alpha, x, incX) + + // Verify the returns and the values in v. Construct h and perform + // the explicit multiplication. + h := make([]float64, n*n) + for i := 0; i < n; i++ { + h[i*n+i] = 1 + } + hmat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: h, + } + v := make([]float64, n) + copy(v[1:], x) + v[0] = 1 + vVec := blas64.Vector{ + Inc: 1, + Data: v, + } + blas64.Ger(-tau, vVec, vVec, hmat) + eye := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, hmat, hmat, 0, eye) + iseye := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i == j { + if math.Abs(eye.Data[i*n+j]-1) > 1e-14 { + iseye = false + } + } else { + if math.Abs(eye.Data[i*n+j]) > 1e-14 { + iseye = false + } + } + } + } + if !iseye { + t.Errorf("H^T * H is not I %v", eye) + } + + xVec := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + xVec.Data[0] = test.alpha + copy(xVec.Data[1:], xcopy) + + ans := make([]float64, n) + ansVec := blas64.Vector{ + Inc: 1, + Data: ans, + } + blas64.Gemv(blas.NoTrans, 1, hmat, xVec, 0, ansVec) + if math.Abs(ans[0]-beta) > 1e-14 { + t.Errorf("Case %v, beta mismatch. Want %v, got %v", i, ans[0], beta) + } + for i := 1; i < n; i++ { + if math.Abs(ans[i]) > 1e-14 { + t.Errorf("Case %v, nonzero answer %v", i, ans) + break + } + } + } +} diff --git a/lapack/testlapack/dlarft.go b/lapack/testlapack/dlarft.go new file mode 100644 index 00000000..e63abb9e --- /dev/null +++ b/lapack/testlapack/dlarft.go @@ -0,0 +1,168 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlarfter interface { + Dgeqr2er + Dlarft(direct lapack.Direct, store lapack.StoreV, n, k int, v []float64, ldv int, tau []float64, t []float64, ldt int) +} + +func DlarftTest(t *testing.T, impl Dlarfter) { + rnd := rand.New(rand.NewSource(1)) + for _, store := range []lapack.StoreV{lapack.ColumnWise, lapack.RowWise} { + for _, direct := range []lapack.Direct{lapack.Forward, lapack.Backward} { + for _, test := range []struct { + m, n, ldv, ldt int + }{ + {6, 6, 0, 0}, + {8, 6, 0, 0}, + {6, 8, 0, 0}, + {6, 6, 10, 15}, + {8, 6, 10, 15}, + {6, 8, 10, 15}, + {6, 6, 15, 10}, + {8, 6, 15, 10}, + {6, 8, 15, 10}, + } { + // Generate a matrix + m := test.m + n := test.n + lda := n + if lda == 0 { + lda = n + } + + a := make([]float64, m*lda) + for i := 0; i < m; i++ { + for j := 0; j < lda; j++ { + a[i*lda+j] = rnd.Float64() + } + } + // Use dgeqr2 to find the v vectors + tau := make([]float64, n) + work := make([]float64, n) + impl.Dgeqr2(m, n, a, lda, tau, work) + + // Construct H using these answers + vMatTmp := extractVMat(m, n, a, lda, lapack.Forward, lapack.ColumnWise) + vMat := constructVMat(vMatTmp, store, direct) + v := vMat.Data + ldv := vMat.Stride + + h := constructH(tau, vMat, store, direct) + + k := min(m, n) + ldt := test.ldt + if ldt == 0 { + ldt = k + } + // Find T from the actual function + tm := make([]float64, k*ldt) + for i := range tm { + tm[i] = 100 + rnd.Float64() + } + // The v data has been put into a. + impl.Dlarft(direct, store, m, k, v, ldv, tau, tm, ldt) + + tData := make([]float64, len(tm)) + copy(tData, tm) + if direct == lapack.Forward { + // Zero out the lower traingular portion. + for i := 0; i < k; i++ { + for j := 0; j < i; j++ { + tData[i*ldt+j] = 0 + } + } + } else { + // Zero out the upper traingular portion. + for i := 0; i < k; i++ { + for j := i + 1; j < k; j++ { + tData[i*ldt+j] = 0 + } + } + } + + T := blas64.General{ + Rows: k, + Cols: k, + Stride: ldt, + Data: tData, + } + + vMatT := blas64.General{ + Rows: vMat.Cols, + Cols: vMat.Rows, + Stride: vMat.Rows, + Data: make([]float64, vMat.Cols*vMat.Rows), + } + for i := 0; i < vMat.Rows; i++ { + for j := 0; j < vMat.Cols; j++ { + vMatT.Data[j*vMatT.Stride+i] = vMat.Data[i*vMat.Stride+j] + } + } + var comp blas64.General + if store == lapack.ColumnWise { + // H = I - V * T * V^T + tmp := blas64.General{ + Rows: T.Rows, + Cols: vMatT.Cols, + Stride: vMatT.Cols, + Data: make([]float64, T.Rows*vMatT.Cols), + } + // T * V^T + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, T, vMatT, 0, tmp) + comp = blas64.General{ + Rows: vMat.Rows, + Cols: tmp.Cols, + Stride: tmp.Cols, + Data: make([]float64, vMat.Rows*tmp.Cols), + } + // V * (T * V^T) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vMat, tmp, 0, comp) + } else { + // H = I - V^T * T * V + tmp := blas64.General{ + Rows: T.Rows, + Cols: vMat.Cols, + Stride: vMat.Cols, + Data: make([]float64, T.Rows*vMat.Cols), + } + // T * V + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, T, vMat, 0, tmp) + comp = blas64.General{ + Rows: vMatT.Rows, + Cols: tmp.Cols, + Stride: tmp.Cols, + Data: make([]float64, vMatT.Rows*tmp.Cols), + } + // V^T * (T * V) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vMatT, tmp, 0, comp) + } + // I - V^T * T * V + for i := 0; i < comp.Rows; i++ { + for j := 0; j < comp.Cols; j++ { + comp.Data[i*m+j] *= -1 + if i == j { + comp.Data[i*m+j] += 1 + } + } + } + if !floats.EqualApprox(comp.Data, h.Data, 1e-14) { + t.Errorf("T does not construct proper H. Store = %v, Direct = %v.\nWant %v\ngot %v.", string(store), string(direct), h.Data, comp.Data) + } + } + } + } +} diff --git a/lapack/testlapack/dlarfx.go b/lapack/testlapack/dlarfx.go new file mode 100644 index 00000000..a73e4f44 --- /dev/null +++ b/lapack/testlapack/dlarfx.go @@ -0,0 +1,82 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlarfxer interface { + Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) +} + +func DlarfxTest(t *testing.T, impl Dlarfxer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Right, blas.Left} { + for m := 1; m < 12; m++ { + for n := 1; n < 12; n++ { + for _, extra := range []int{0, 1, 11} { + for cas := 0; cas < 10; cas++ { + testDlarfx(t, impl, side, m, n, extra, rnd) + } + } + } + } + } +} + +func testDlarfx(t *testing.T, impl Dlarfxer, side blas.Side, m, n, extra int, rnd *rand.Rand) { + const tol = 1e-13 + + c := randomGeneral(m, n, n+extra, rnd) + cWant := randomGeneral(m, n, n+extra, rnd) + tau := rnd.NormFloat64() + + var ( + v []float64 + h blas64.General + ) + if side == blas.Left { + v = randomSlice(m, rnd) + h = eye(m, m+extra) + } else { + v = randomSlice(n, rnd) + h = eye(n, n+extra) + } + blas64.Ger(-tau, blas64.Vector{Inc: 1, Data: v}, blas64.Vector{Inc: 1, Data: v}, h) + if side == blas.Left { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, c, 0, cWant) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, c, h, 0, cWant) + } + + var work []float64 + if h.Rows > 10 { + // Allocate work only if H has order > 10. + if side == blas.Left { + work = make([]float64, n) + } else { + work = make([]float64, m) + } + } + + impl.Dlarfx(side, m, n, v, tau, c.Data, c.Stride, work) + + prefix := fmt.Sprintf("Case side=%v, m=%v, n=%v, extra=%v", side, m, n, extra) + + // Check any invalid modifications of c. + if !generalOutsideAllNaN(c) { + t.Errorf("%v: out-of-range write to C\n%v", prefix, c.Data) + } + + if !equalApproxGeneral(c, cWant, tol) { + t.Errorf("%v: unexpected C\n%v", prefix, c.Data) + } +} diff --git a/lapack/testlapack/dlartg.go b/lapack/testlapack/dlartg.go new file mode 100644 index 00000000..c7cade84 --- /dev/null +++ b/lapack/testlapack/dlartg.go @@ -0,0 +1,98 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlartger interface { + Dlartg(f, g float64) (cs, sn, r float64) +} + +func DlartgTest(t *testing.T, impl Dlartger) { + const tol = 1e-14 + // safmn2 and safmx2 are copied from native.Dlartg. + safmn2 := math.Pow(dlamchB, math.Trunc(math.Log(dlamchS/dlamchE)/math.Log(dlamchB)/2)) + safmx2 := 1 / safmn2 + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < 1000; i++ { + var f float64 + var fHuge bool + switch rnd.Intn(3) { + case 0: + // Huge f. + fHuge = true + f = math.Pow(10, 10-20*rnd.Float64()) * safmx2 + case 1: + // Tiny f. + f = math.Pow(10, 10-20*rnd.Float64()) * safmn2 + default: + f = rnd.NormFloat64() + } + if rnd.Intn(2) == 0 { + f *= -1 + } + + var g float64 + var gHuge bool + switch rnd.Intn(3) { + case 0: + // Huge g. + gHuge = true + g = math.Pow(10, 10-20*rnd.Float64()) * safmx2 + case 1: + // Tiny g. + g = math.Pow(10, 10-20*rnd.Float64()) * safmn2 + default: + g = rnd.NormFloat64() + } + if rnd.Intn(2) == 0 { + g *= -1 + } + + cs, sn, r := impl.Dlartg(f, g) + + rWant := cs*f + sn*g + if !floats.EqualWithinAbsOrRel(math.Abs(rWant), math.Abs(r), tol, tol) { + t.Errorf("Case f=%v,g=%v: unexpected r. Want %v, got %v", f, g, rWant, r) + } + oneTest := cs*cs + sn*sn + if math.Abs(oneTest-1) > tol { + t.Errorf("Case f=%v,g=%v: expected cs^2+sn^2==1, got %v", f, g, oneTest) + } + if !fHuge && !gHuge { + zeroTest := -sn*f + cs*g + if math.Abs(zeroTest) > tol { + t.Errorf("Case f=%v,g=%v: expected zero, got %v", f, g, zeroTest) + } + } + if math.Abs(f) > math.Abs(g) && cs < 0 { + t.Errorf("Case f=%v,g=%v: unexpected negative cs %v", f, g, cs) + } + } + for i := 0; i < 100; i++ { + cs, sn, _ := impl.Dlartg(rnd.NormFloat64(), 0) + if cs != 1 { + t.Errorf("Unexpected cs for g=0. Want 1, got %v", cs) + } + if sn != 0 { + t.Errorf("Unexpected sn for g=0. Want 0, got %v", sn) + } + } + for i := 0; i < 100; i++ { + cs, sn, _ := impl.Dlartg(0, rnd.NormFloat64()) + if cs != 0 { + t.Errorf("Unexpected cs for f=0. Want 0, got %v", cs) + } + if sn != 1 { + t.Errorf("Unexpected sn for f=0. Want 1, got %v", sn) + } + } +} diff --git a/lapack/testlapack/dlas2.go b/lapack/testlapack/dlas2.go new file mode 100644 index 00000000..a76e2742 --- /dev/null +++ b/lapack/testlapack/dlas2.go @@ -0,0 +1,34 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "testing" +) + +type Dlas2er interface { + Dlas2(f, g, h float64) (min, max float64) +} + +func Dlas2Test(t *testing.T, impl Dlas2er) { + for i, test := range []struct { + f, g, h, ssmin, ssmax float64 + }{ + // Singular values computed from Octave. + {10, 30, 12, 3.567778859365365, 33.634371616111189}, + {10, 30, -12, 3.567778859365365, 33.634371616111189}, + {2, 30, -12, 0.741557056404952, 32.364333658088754}, + {-2, 5, 12, 1.842864429909778, 13.023204317408728}, + } { + ssmin, ssmax := impl.Dlas2(test.f, test.g, test.h) + if math.Abs(ssmin-test.ssmin) > 1e-12 { + t.Errorf("Case %d, minimal singular value mismatch. Want %v, got %v", i, test.ssmin, ssmin) + } + if math.Abs(ssmax-test.ssmax) > 1e-12 { + t.Errorf("Case %d, minimal singular value mismatch. Want %v, got %v", i, test.ssmin, ssmin) + } + } +} diff --git a/lapack/testlapack/dlascl.go b/lapack/testlapack/dlascl.go new file mode 100644 index 00000000..db792a4d --- /dev/null +++ b/lapack/testlapack/dlascl.go @@ -0,0 +1,106 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/lapack" +) + +type Dlascler interface { + Dlascl(kind lapack.MatrixType, kl, ku int, cfrom, cto float64, m, n int, a []float64, lda int) +} + +func DlasclTest(t *testing.T, impl Dlascler) { + const tol = 1e-16 + + rnd := rand.New(rand.NewSource(1)) + for ti, test := range []struct { + m, n int + }{ + {0, 0}, + {1, 1}, + {1, 10}, + {10, 1}, + {2, 2}, + {2, 11}, + {11, 2}, + {3, 3}, + {3, 11}, + {11, 3}, + {11, 11}, + {11, 100}, + {100, 11}, + } { + m := test.m + n := test.n + for _, extra := range []int{0, 11} { + for _, kind := range []lapack.MatrixType{lapack.General, lapack.UpperTri, lapack.LowerTri} { + a := randomGeneral(m, n, n+extra, rnd) + aCopy := cloneGeneral(a) + cfrom := rnd.NormFloat64() + cto := rnd.NormFloat64() + scale := cto / cfrom + + impl.Dlascl(kind, -1, -1, cfrom, cto, m, n, a.Data, a.Stride) + + prefix := fmt.Sprintf("Case #%v: kind=%v,m=%v,n=%v,extra=%v", ti, kind, m, n, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + switch kind { + case lapack.General: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + want := scale * aCopy.Data[i*aCopy.Stride+j] + got := a.Data[i*a.Stride+j] + if math.Abs(want-got) > tol { + t.Errorf("%v: unexpected A[%v,%v]=%v, want %v", prefix, i, j, got, want) + } + } + } + case lapack.UpperTri: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + want := scale * aCopy.Data[i*aCopy.Stride+j] + got := a.Data[i*a.Stride+j] + if math.Abs(want-got) > tol { + t.Errorf("%v: unexpected A[%v,%v]=%v, want %v", prefix, i, j, got, want) + } + } + } + for i := 0; i < m; i++ { + for j := 0; j < min(i, n); j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification in lower triangle of A", prefix) + } + } + } + case lapack.LowerTri: + for i := 0; i < m; i++ { + for j := 0; j <= min(i, n-1); j++ { + want := scale * aCopy.Data[i*aCopy.Stride+j] + got := a.Data[i*a.Stride+j] + if math.Abs(want-got) > tol { + t.Errorf("%v: unexpected A[%v,%v]=%v, want %v", prefix, i, j, got, want) + } + } + } + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + if a.Data[i*a.Stride+j] != aCopy.Data[i*aCopy.Stride+j] { + t.Errorf("%v: unexpected modification in upper triangle of A", prefix) + } + } + } + } + } + } + } +} diff --git a/lapack/testlapack/dlaset.go b/lapack/testlapack/dlaset.go new file mode 100644 index 00000000..2b70b7af --- /dev/null +++ b/lapack/testlapack/dlaset.go @@ -0,0 +1,76 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" +) + +type Dlaseter interface { + Dlaset(uplo blas.Uplo, m, n int, alpha, beta float64, a []float64, lda int) +} + +func DlasetTest(t *testing.T, impl Dlaseter) { + rnd := rand.New(rand.NewSource(1)) + for ti, test := range []struct { + m, n int + }{ + {0, 0}, + {1, 1}, + {1, 10}, + {10, 1}, + {2, 2}, + {2, 10}, + {10, 2}, + {11, 11}, + {11, 100}, + {100, 11}, + } { + m := test.m + n := test.n + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { + for _, extra := range []int{0, 10} { + a := randomGeneral(m, n, n+extra, rnd) + alpha := 1.0 + beta := 2.0 + + impl.Dlaset(uplo, m, n, alpha, beta, a.Data, a.Stride) + + prefix := fmt.Sprintf("Case #%v: m=%v,n=%v,uplo=%v,extra=%v", + ti, m, n, uplo, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + for i := 0; i < min(m, n); i++ { + if a.Data[i*a.Stride+i] != beta { + t.Errorf("%v: unexpected diagonal of A") + } + } + if uplo == blas.Upper || uplo == blas.All { + for i := 0; i < m; i++ { + for j := i + 1; j < n; j++ { + if a.Data[i*a.Stride+j] != alpha { + t.Errorf("%v: unexpected upper triangle of A") + } + } + } + } + if uplo == blas.Lower || uplo == blas.All { + for i := 1; i < m; i++ { + for j := 0; j < min(i, n); j++ { + if a.Data[i*a.Stride+j] != alpha { + t.Errorf("%v: unexpected lower triangle of A") + } + } + } + } + } + } + } +} diff --git a/lapack/testlapack/dlasq1.go b/lapack/testlapack/dlasq1.go new file mode 100644 index 00000000..cebc2004 --- /dev/null +++ b/lapack/testlapack/dlasq1.go @@ -0,0 +1,96 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +func printDlasq1FortranInput(d, e, work []float64, n int) { + printFortranArray(d, "d") + printFortranArray(e, "e") + printFortranArray(work, "work") + fmt.Println("n = ", n) + fmt.Println("info = 0") +} + +type Dlasq1er interface { + Dlasq1(n int, d, e, work []float64) int + Dgetrfer +} + +func Dlasq1Test(t *testing.T, impl Dlasq1er) { + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + // TODO(btracey): Increase the size of this test when we have a more numerically + // stable way to test the singular values. + for _, n := range []int{1, 2, 5, 8} { + work := make([]float64, 4*n) + d := make([]float64, n) + e := make([]float64, n-1) + for cas := 0; cas < 1; cas++ { + for i := range work { + work[i] = rnd.Float64() + } + for i := range d { + d[i] = rnd.NormFloat64() + 10 + } + for i := range e { + e[i] = rnd.NormFloat64() + } + ldm := n + m := make([]float64, n*ldm) + // Set up the matrix + for i := 0; i < n; i++ { + m[i*ldm+i] = d[i] + if i != n-1 { + m[(i+1)*ldm+i] = e[i] + } + } + + ldmm := n + mm := make([]float64, n*ldmm) + bi.Dgemm(blas.Trans, blas.NoTrans, n, n, n, 1, m, ldm, m, ldm, 0, mm, ldmm) + + impl.Dlasq1(n, d, e, work) + + // Check that they are singular values. The + // singular values are the square roots of the + // eigenvalues of X^T * X + mmCopy := make([]float64, len(mm)) + copy(mmCopy, mm) + ipiv := make([]int, n) + for elem, sv := range d[0:n] { + copy(mm, mmCopy) + lambda := sv * sv + for i := 0; i < n; i++ { + mm[i*ldm+i] -= lambda + } + + // Compute LU. + ok := impl.Dgetrf(n, n, mm, ldmm, ipiv) + if !ok { + // Definitely singular. + continue + } + // Compute determinant + var logdet float64 + for i := 0; i < n; i++ { + v := mm[i*ldm+i] + logdet += math.Log(math.Abs(v)) + } + if math.Exp(logdet) > 2 { + t.Errorf("Incorrect singular value. n = %d, cas = %d, elem = %d, det = %v", n, cas, elem, math.Exp(logdet)) + } + } + } + } +} diff --git a/lapack/testlapack/dlasq2.go b/lapack/testlapack/dlasq2.go new file mode 100644 index 00000000..99696b19 --- /dev/null +++ b/lapack/testlapack/dlasq2.go @@ -0,0 +1,721 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func printDlasq2FortranInput(z []float64, n int) { + printFortranArray(z, "z") + fmt.Println("n = ", n) + fmt.Println("info = 0") +} + +type Dlasq2er interface { + Dgetrfer + Dlasq2(n int, z []float64) (info int) +} + +func Dlasq2Test(t *testing.T, impl Dlasq2er) { + dTol := 1e-6 + // Answers from calling the netlib Dlasq2 function directly. + for c, test := range []struct { + n int + z []float64 + info int + zOut []float64 + }{ + { + z: []float64{0.9975595900926172E+00, 0.5668247076112733E+00, 0.9659153754961249E+00, 0.7479276854714322E+00, 0.3673908973747557E+00, 0.4806368987547315E+00, 0.7375426363398452E-01, 0.5355229277727247E-02, 0.3470812885180155E+00, 0.3422438160728350E+00, 0.2179517263384726E+00, 0.1331604100136593E+00, 0.9005245144218924E+00, 0.3867660104574036E+00, 0.4454822893878481E+00, 0.6619321808958428E+00, 0.1610830043055933E-01, 0.6508548361039168E+00, 0.6464088254838254E+00, 0.3229872909405558E+00, 0.8556924028853313E+00, 0.4012869193638139E+00, 0.2068743292187569E+00, 0.9685394642165999E+00, 0.5983995343181346E+00, 0.6729807327762632E+00, 0.4568823106729620E+00, 0.3300151235733747E+00, 0.1003829265021773E+00, 0.7554533047597268E+00, 0.6056932669802318E+00, 0.7190479134084530E+00, 0.8973346038865299E+00, 0.6582291204811077E+00, 0.1507168371301046E+00, 0.6123149049967000E+00, 0.9786602381321465E+00, 0.9991422694268032E+00, 0.2567979861831603E+00, 0.5508654031552206E+00, 0.6590475178936379E+00, 0.5540051353968156E+00, 0.9777600986094505E+00, 0.9019233044604550E+00, 0.6579246844202109E+00, 0.7288585083995637E+00, 0.4024552650632751E+00, 0.9286276631540373E+00, 0.1478351900438915E+00, 0.6745292990637881E+00, 0.7696143092758962E+00, 0.3393225521457851E+00, 0.1158188549489931E+00, 0.6143691843615144E+00, 0.8206171394658319E+00, 0.9470946559240657E+00, 0.7311286518535550E+00, 0.4976039064630389E+00, 0.3748017407872005E+00, 0.4215058560045335E+00, 0.5529030382557849E+00, 0.9979192791781042E+00, 0.9903947480415133E+00, 0.7463096553073095E+00, 0.9537590617479789E+00, 0.9327469033343772E-01, 0.7340236871158429E+00, 0.7517616159256260E+00, 0.9468485056759987E+00, 0.7061763632511533E+00, 0.8138096664824992E+00, 0.5585945195965548E+00, 0.6170557687507783E-01, 0.4803807801853603E+00, 0.5976897721963292E+00, 0.1375319188363359E+00, 0.5873952004066820E+00, 0.5199682629163997E+00, 0.8858783448129579E+00, 0.3038101719904888E+00, 0.6696573039722583E+00, 0.6649400915297697E+00, 0.5036768993979404E+00, 0.2615751204119269E+00}, + n: 21, + zOut: []float64{0.2550031738262204E+01, 0.2480977513501848E+01, 0.2366602269912148E+01, 0.2169993432366266E+01, 0.1810817848712033E+01, 0.1681677309759878E+01, 0.1303743375476047E+01, 0.1202161769544433E+01, 0.1183377192742860E+01, 0.1094206688544886E+01, 0.9154376259418607E+00, 0.8241395430971566E+00, 0.7318275341991307E+00, 0.5186198053161721E+00, 0.4143051093784424E+00, 0.2112065329503869E+00, 0.1093987140067686E+00, 0.9751785856405315E-01, 0.2818174710670554E-01, 0.1697846193036144E-01, 0.2117542506861687E-04, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.2171122324673871E+02, 0.2171122324673871E+02, 0.1020000000000000E+03, 0.3081632653061225E+01, 0.2941176470588236E+01, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + info: 0, + }, + { + z: []float64{0.7655950151081736E-01, 0.1012496627944287E+00, 0.5492657397218519E+00, 0.3755849474908193E+00, 0.1514950257902281E-01, 0.7929154460744389E+00, 0.6208775449015512E+00, 0.7736035774285512E+00, 0.9535807609862423E+00, 0.1142443721338974E+00, 0.3184626428755636E+00, 0.5968198462235605E+00, 0.4815290260558158E-01, 0.1142057780273510E+00, 0.2159649191761220E+00, 0.1005733924928321E+00, 0.7334180249993905E-01, 0.2468617397276878E+00, 0.4433842667962828E+00, 0.2083675732544600E+00, 0.5669983427348256E+00, 0.2431239969651688E-01, 0.4202905770712168E+00, 0.3978530241169832E+00, 0.9765854254920880E+00, 0.6926050329928320E+00, 0.4943367486777372E-02, 0.1299210324451839E+00, 0.4677725963527957E-01, 0.8397777412847708E+00, 0.6784888222113696E+00, 0.5819508167748705E+00, 0.7335259194567719E+00, 0.1160427446694747E+00, 0.8402996546275487E+00, 0.8349959735427709E+00, 0.7465363962886192E+00, 0.8432008930683078E+00, 0.5288390014350658E+00, 0.6654846664813405E+00, 0.7307365692392301E+00, 0.4106042636492306E+00, 0.3557215961646439E+00, 0.7353770423280176E+00, 0.4713176648251016E+00, 0.4626254343486430E+00, 0.7596917071958065E+00, 0.7024594192654096E+00, 0.2579658084846748E+00, 0.9377050325544740E+00, 0.4561035840049426E+00, 0.8084892970067921E+00, 0.9088480529888660E+00, 0.6948766633235142E+00, 0.2194885062923195E+00, 0.8549545559228027E+00, 0.7443966896835119E+00, 0.3011130612705175E+00, 0.6719685452983997E+00, 0.6187140363783860E+00, 0.9675736114028010E+00, 0.9902393027740470E+00, 0.3380065169449795E+00, 0.9207672475882130E+00, 0.3390733399571427E+00, 0.9309435300662920E+00, 0.5465285509796513E+00, 0.4655125893217942E+00, 0.1769140958718970E+00, 0.3779940975005719E+00, 0.1752206228227682E+00, 0.3568582675012224E+00, 0.6656764250906758E+00, 0.6185492680730227E+00, 0.4689472437795331E+00, 0.3162518610221317E+00, 0.2688799086902824E+00, 0.1999212438248075E+00, 0.4154279763213168E+00, 0.9793029133347251E+00, 0.5432115888768534E+00, 0.1295182752745038E+00, 0.8047416637896615E+00, 0.8458210244967665E+00}, + n: 21, + zOut: []float64{0.2649710614371106E+01, 0.2321564474027070E+01, 0.2090779203479937E+01, 0.2001510674733695E+01, 0.1702794694134603E+01, 0.1077066053646038E+01, 0.1060140274732043E+01, 0.9894235909971354E+00, 0.9539342071687115E+00, 0.8046649468928653E+00, 0.7009142227469247E+00, 0.5502651835254770E+00, 0.4423863025187732E+00, 0.3697086796938907E+00, 0.1446051340026323E+00, 0.1110032523123295E+00, 0.7513603923341917E-01, 0.6860214953971246E-01, 0.2434478048112329E-01, 0.6989818532012803E-03, 0.7811996215926567E-04, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.1813933158005285E+02, 0.1813933158005285E+02, 0.1090000000000000E+03, 0.3231292517006803E+01, 0.5504587155963303E+01, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + info: 0, + }, + { + z: []float64{0.7090328374865308E+00, 0.5289732604915972E+00, 0.6638408676820399E+00, 0.9007392577685345E+00, 0.9411642674278379E+00, 0.1144202631330921E+00, 0.8666675899972089E+00, 0.6323680737151134E+00, 0.2427877245566508E+00, 0.1603957810123527E+00, 0.2123565414665629E-01, 0.1902539934369850E+00, 0.3123401294447815E+00, 0.8096475663099788E+00, 0.5737184899962203E+00, 0.8262606712006769E+00, 0.2864548736211023E+00, 0.1605147759074373E+00, 0.3309241142010387E+00, 0.2658533720189140E+00, 0.5447811280109880E+00, 0.5535203163154195E+00, 0.2161483615344606E-01, 0.1487480590324270E+00, 0.1049033762317957E+00, 0.6142137665037214E+00, 0.4062909815669834E+00, 0.9015282863354186E+00, 0.9428381000165521E+00, 0.1566198551488233E+00, 0.9369593797444957E+00, 0.1354729715149707E+00, 0.3712821832808397E+00, 0.3215112250898227E+00, 0.7149642455474942E+00, 0.7297077774959745E+00, 0.3785927874981971E+00, 0.8289344072747380E+00, 0.9536643756705742E+00, 0.3084192540817629E+00, 0.5797406195506623E+00, 0.2334488720392539E+00, 0.8444034680728870E+00, 0.2581324672603945E+00, 0.8397436353763532E+00, 0.5376562757207516E+00, 0.6215703771401371E+00, 0.4908247191212207E+00, 0.2848423854658637E+00, 0.2355591822832676E+00, 0.6513799258897619E+00, 0.6071703403704332E+00, 0.3981458512505542E+00, 0.8487946917355450E+00, 0.6376169839751418E+00, 0.2588233361358196E+00, 0.3588309885453386E+00, 0.5618301121344036E+00, 0.1214685095104872E+00, 0.9784693864155333E+00, 0.3832063578469370E+00, 0.7206987579838013E+00, 0.3582640246022534E+00, 0.9098815720988161E+00, 0.5436872318254895E+00, 0.9596753969896468E+00, 0.9294728975416107E+00, 0.6333208483475120E+00, 0.2956089747729942E+00, 0.1747395639573214E+00, 0.8425785962238860E+00, 0.6185896542974498E+00, 0.7058928872472775E+00, 0.2424399357290958E+00, 0.7979610473510427E+00, 0.3910140128664733E+00, 0.1099592891010870E+00, 0.7536879342329168E+00, 0.2979717756246736E-01, 0.7006607890734408E+00, 0.5252033671714352E+00, 0.7525598235593517E+00, 0.6476778890126167E+00, 0.8710847630132640E+00}, + n: 21, + zOut: []float64{0.2486733497028020E+01, 0.2359071020584524E+01, 0.2276435093308226E+01, 0.2061969496713965E+01, 0.1674052496256098E+01, 0.1634406821090099E+01, 0.1324515540477209E+01, 0.1213036064691536E+01, 0.1142092570196908E+01, 0.8479728747156923E+00, 0.7723287409164926E+00, 0.6845846156476076E+00, 0.4690003902541462E+00, 0.3969394481970619E+00, 0.3209839311891622E+00, 0.1762493640751034E+00, 0.1552318325824889E+00, 0.1299582823757977E+00, 0.4568511390642456E-01, 0.2058742849236605E-01, 0.6687292092604351E-04, 0.0000000000000000E+00, 0.9075510178548721E-16, 0.1809089799756099E-15, 0.1324515540477209E+01, 0.1972152263052530E-28, 0.7207148989396829E-15, 0.1135837106477965E-14, 0.1213036064691536E+01, 0.6865185493883853E-20, 0.3862483738583121E-14, 0.5795548067006594E-14, 0.1142092570196908E+01, 0.1237761291638161E-15, 0.1761387669893985E-13, 0.1204467761940304E-13, 0.8479728747156923E+00, 0.5980780785048348E-20, 0.5961915529495600E-12, 0.8546407799162654E-12, 0.7723287409164926E+00, 0.9983823616477125E-26, 0.2019190149561986E+02, 0.2019190149561985E+02, 0.1120000000000000E+03, 0.3267573696145125E+01, 0.7142857142857143E+01, 0.2981196239393922E-10, 0.4690003902541462E+00, 0.1411215361455214E-23, 0.1291839253366726E-09, 0.2114581039065388E-09, 0.3969394481970619E+00, 0.3215018396446338E-24, 0.8992249144513522E-09, 0.1460279739604385E-08, 0.3209839311891622E+00, 0.5301710738582062E-20, 0.5956459688113839E-08, 0.9509260151006140E-08, 0.1762493640751034E+00, 0.3305918938014538E-18, 0.2145126200057182E-06, 0.1391189925457742E-06, 0.1552318325824889E+00, 0.0000000000000000E+00, 0.8222867095540534E-06, 0.8520250895881005E-06, 0.1299582823757977E+00, 0.1946507846527860E-19, 0.4299487364203470E-05, 0.2670451838837521E-05, 0.4568511390642456E-01, 0.1783600337601646E-17, 0.1688330183620908E-03, 0.2840434656464124E-03, 0.2058742849236605E-01, 0.2127174768075152E-17, 0.5266290662212281E-04, 0.3082204001196310E-04, 0.6687292092604351E-04, 0.4725269249209171E-22, 0.3479992598793783E-02, 0.7157534417412210E-03}, + info: 0, + }, + { + z: []float64{0.8307212987388154E+00, 0.9571804405037874E+00, 0.2222674360399970E+00, 0.5794927951917870E+00, 0.9907605078898842E+00, 0.8399673535531696E+00, 0.1748054629244838E+00, 0.7095417514667766E+00, 0.3015507353664195E+00, 0.2504155371033889E-01, 0.9167396887269817E+00, 0.6888065712047682E+00, 0.7567577995550097E+00, 0.9327280452266753E+00, 0.5500991579404824E-01, 0.4989499454693689E+00, 0.5949898652751251E-01, 0.1718660951302574E+00, 0.6883620036166904E+00, 0.3066205390931208E+00, 0.7351901912310475E+00, 0.7521684164853142E+00, 0.3957210266430871E+00, 0.8778502662051324E-01, 0.4896297811280748E-01, 0.7793618951247419E+00, 0.6807766665219679E+00, 0.3115699624095645E+00, 0.5227646665950632E+00, 0.5057964692468060E+00, 0.4385260593432981E+00, 0.5876392780963172E+00, 0.2973252261444674E+00, 0.2948995727695043E+00, 0.7378444260331429E-01, 0.9749457382350615E+00, 0.7281626398300706E+00, 0.7580903878987629E+00, 0.3091762186458183E+00, 0.2464983240671905E+00, 0.2568872936019900E+00, 0.6180627613788815E+00, 0.9377882352337240E+00, 0.9921824152100049E+00, 0.2248192100106184E+00, 0.9472840045361628E+00, 0.8477853668436538E+00, 0.7001263233958666E+00, 0.5544440083201581E+00, 0.4415839019184687E+00, 0.2491818172148126E+00, 0.8976627554942691E+00, 0.1457298176556392E+00, 0.4345936198183369E+00, 0.4573762249453559E+00, 0.3093805347522776E+00, 0.4809246108862507E+00, 0.6897426752489948E+00, 0.8107988692352123E+00, 0.3921644162683642E+00, 0.2931487419364392E+00, 0.5759780604710760E+00, 0.7253418085569345E+00, 0.1427733376597652E+00, 0.3335555091947459E+00, 0.1603897948564823E+00, 0.5345943097231743E+00, 0.7233253065718669E+00, 0.2281802915301432E+00, 0.1990064435881517E+00, 0.9726196083044836E+00, 0.9935713768557323E+00, 0.8195201715007894E-01, 0.2508806553004002E+00, 0.2158489797899930E+00, 0.1957771185505375E+00, 0.8502651710165565E+00, 0.4468235108377239E-01, 0.8639211642125266E+00, 0.6713373034638015E-01, 0.4273173462824215E+00, 0.1373188375801981E+00, 0.1190874985301729E+00, 0.3059495456429208E+00}, + n: 21, + zOut: []float64{0.2399198387954965E+01, 0.2388283868878418E+01, 0.2234728187505421E+01, 0.1947641030296732E+01, 0.1845273105794422E+01, 0.1837097911259683E+01, 0.1471118007292610E+01, 0.1105651020532553E+01, 0.9883044021137968E+00, 0.9478841363642468E+00, 0.8550293065516678E+00, 0.7566674361156733E+00, 0.5310790726859680E+00, 0.3571217714437427E+00, 0.2893653184719416E+00, 0.2534414197270934E+00, 0.2173582726294167E+00, 0.4908458037260943E-01, 0.1246498683649276E-01, 0.5862142085722914E-02, 0.4704104342516643E-04, 0.1939986690620616E-19, 0.1034652479755287E-16, 0.1536368559490732E-16, 0.1471118007292610E+01, 0.5364686198585281E-13, 0.6088846084221820E-07, 0.1529604999486430E-06, 0.1105651020532553E+01, 0.2903008131213323E-27, 0.1160127138141562E-06, 0.1335479603764263E-06, 0.9883044021137968E+00, 0.2125606020077514E-18, 0.5906967539735199E-07, 0.6675815740532400E-07, 0.9478841363642468E+00, 0.1331202777560457E-29, 0.4438231138534822E-07, 0.3948328125271971E-07, 0.8550293065516678E+00, 0.5860341995390921E-20, 0.2049270140595660E+02, 0.2049270140595660E+02, 0.9800000000000000E+02, 0.2893424036281179E+01, 0.4081632653061225E+01, 0.1377712740565197E-07, 0.5310790726859680E+00, 0.1537961403283359E-19, 0.8011211497963711E-08, 0.8400248580143560E-08, 0.3571217714437427E+00, 0.5389497704469953E-25, 0.6965765014245226E-08, 0.7336584331089061E-08, 0.2893653184719416E+00, 0.6081961202185573E-17, 0.9973730165755502E-08, 0.8562226724273748E-08, 0.2534414197270934E+00, 0.3644137891043716E-17, 0.1552441635408352E-06, 0.1605842922922618E-07, 0.2173582726294167E+00, 0.1710250442519154E-26, 0.2805940935843235E-04, 0.1153299285109565E-04, 0.4908458037260943E-01, 0.1140499340513312E-15, 0.3458275194991493E-03, 0.2689727098393103E-03, 0.1246498683649276E-01, 0.4437342591868191E-30, 0.1429141842628293E-03, 0.1683368406483595E-03, 0.5862142085722914E-02, 0.2515327803596613E-22, 0.2394538487567536E-03, 0.1603201011413965E-03, 0.4704104342516643E-04, 0.0000000000000000E+00, 0.2149753858259932E-02, 0.4092589741085703E-02}, + info: 0, + }, + { + z: []float64{0.6132370003914160E+00, 0.6636632940312478E+00, 0.8959100063178993E+00, 0.7536793777540497E+00, 0.6298705159481864E+00, 0.2209880035966978E+00, 0.4838373503885766E+00, 0.6150203746616348E+00, 0.9876587724998732E+00, 0.5591876171910803E+00, 0.3708840600033242E+00, 0.3375947236522073E+00, 0.7454250822233153E+00, 0.5697349010621601E+00, 0.4561367007431339E+00, 0.6481896738286699E+00, 0.6835960923418801E+00, 0.1703905177923075E+00, 0.2730661115049011E+00, 0.4407624886449348E+00, 0.4577220273293221E+00, 0.3952566732937318E+00, 0.6883342106097436E+00, 0.2988887099704991E+00, 0.2052274263883085E+00, 0.1922842703083140E+00, 0.4189999528960880E+00, 0.6906452535299822E+00, 0.1405554539793709E+00, 0.1437412601859918E+00, 0.6624635742176765E+00, 0.5756752017566100E+00, 0.7749505183416766E+00, 0.7752965769666669E+00, 0.7653541054136069E+00, 0.8765107194498384E+00, 0.9921378985956986E-01, 0.3345156485504346E+00, 0.6450936562634260E+00, 0.1316181443467312E+00, 0.8075436662342752E+00, 0.5418723210737144E+00, 0.2657525890099199E+00, 0.4588749915888913E+00, 0.5109250246010762E+00, 0.5048342930643721E+00, 0.9617739307304302E+00, 0.5502351700731637E+00, 0.1896288106400514E+00, 0.2011189112848212E+00, 0.2487376305081674E+00, 0.9700914054633822E+00, 0.7763920500140777E+00, 0.2727004477756484E+00, 0.4969507403482072E+00, 0.3987515903118115E+00, 0.6132963384905279E+00, 0.8526865910258985E-01, 0.7370021348269777E+00, 0.8628692345603857E+00, 0.3410351221174988E+00, 0.6944408188735030E+00, 0.6418832405583447E+00, 0.8549561267667016E-01, 0.7079842121947655E+00, 0.5924596383322266E+00, 0.2327865765542259E+00, 0.7519783901092147E-01, 0.3243359400926964E+00, 0.9130914950306788E+00, 0.2042866226175709E+00, 0.4527677275849958E+00, 0.7271733772634871E+00, 0.2835797318864963E-01, 0.5170298378180002E+00, 0.7676612860726464E+00, 0.8943646165240225E+00, 0.9444900692816881E+00, 0.2898061819682256E+00, 0.5314658042534958E+00, 0.2328255902743269E+00, 0.3127766212762262E+00, 0.1415213232426512E+00, 0.3425808715425687E+00}, + n: 21, + zOut: []float64{0.2568497247033635E+01, 0.2474290441512907E+01, 0.2254355189310800E+01, 0.1987099258783412E+01, 0.1595738223681455E+01, 0.1520583769371047E+01, 0.1349481184037943E+01, 0.1286943522977408E+01, 0.1233633359467258E+01, 0.1105388350935419E+01, 0.8741663391031235E+00, 0.7042784684853729E+00, 0.6809050564171195E+00, 0.5312535309083547E+00, 0.3765999563195902E+00, 0.2982885955048700E+00, 0.1761408438030470E+00, 0.1021950592815966E+00, 0.5149411253987173E-01, 0.2409819364774552E-01, 0.3292801347387554E-02, 0.7649046082865931E-16, 0.2073367755475779E-07, 0.1625592945762753E-07, 0.1349481184037943E+01, 0.1183291357831518E-29, 0.4660703060512034E-13, 0.1807862490656452E-12, 0.1286943522977408E+01, 0.1649665924998180E-25, 0.1294990598064480E-10, 0.5231829186377068E-10, 0.1233633359467258E+01, 0.8526291632353489E-16, 0.3101844497115867E-08, 0.1140775990076438E-07, 0.1105388350935419E+01, 0.9624103043696344E-28, 0.5663389137423196E-06, 0.4346359020206590E-06, 0.8741663391031235E+00, 0.3067428736041242E-19, 0.2119872350446936E+02, 0.2119872350446936E+02, 0.1030000000000000E+03, 0.3056689342403628E+01, 0.2912621359223301E+01, 0.2039882393707806E-06, 0.6809050564171195E+00, 0.0000000000000000E+00, 0.3469744030301619E-06, 0.2644131172050035E-06, 0.5312535309083547E+00, 0.3043881270837009E-21, 0.5541811479797519E-05, 0.3827690844980446E-05, 0.3765999563195902E+00, 0.1909043390634849E-27, 0.3412067971678679E-04, 0.3418356678006945E-04, 0.2982885955048700E+00, 0.1167175485134229E-15, 0.1390598737761422E-03, 0.1685020271483295E-03, 0.1761408438030470E+00, 0.3311298373357662E-16, 0.2687183242739271E-03, 0.2970561145148615E-03, 0.1021950592815966E+00, 0.3861046454850253E-20, 0.3877059717439437E-03, 0.4274183271611622E-03, 0.5149411253987173E-01, 0.3171094621243632E-24, 0.5614281929126997E-03, 0.6201503766753644E-03, 0.2409819364774552E-01, 0.5854827030937197E-31, 0.8580439238194122E-03, 0.9937175751003719E-03, 0.3292801347387554E-02, 0.1687712113428427E-19, 0.6404816195044538E-02, 0.3574263865391779E-02}, + info: 0, + }, + { + z: []float64{0.1535280608392028E+00, 0.8492164242958209E+00, 0.9720508422713467E+00, 0.4409240313091006E+00, 0.7744413453832578E+00, 0.4562143200311385E+00, 0.8645004927526174E+00, 0.7279750979364787E+00, 0.6373358699411871E+00, 0.7240388495630282E+00, 0.6042124182518795E+00, 0.2629417492305242E-01, 0.2927658696806527E+00, 0.1971917075100318E+00, 0.9486620805007744E+00, 0.5318461733579811E+00, 0.1035922758398233E-01, 0.4521355876782263E+00, 0.9635828765019094E+00, 0.9861179636072996E+00, 0.3409131837267612E+00, 0.9592913933135179E+00, 0.3267081303471464E+00, 0.7042329006712417E+00, 0.7904477014671945E+00, 0.7235636505410947E+00, 0.7289557043239185E+00, 0.4453819137782510E+00, 0.3817792285714174E+00, 0.9222246883547156E+00, 0.7484233302016036E+00, 0.4267300781414476E+00, 0.2174272124496083E+00, 0.7294135193889231E+00, 0.7969150359898325E+00, 0.5584233158827989E+00, 0.8854167010119880E+00, 0.3831257236275667E+00, 0.2407966333760054E+00, 0.3150832526072347E+00, 0.4329046703236793E+00, 0.4798261053116015E-01, 0.4240797212710790E+00, 0.7373271503520912E+00, 0.8727856342792233E+00, 0.3079871491200393E+00, 0.8433176604823556E+00, 0.8160920845908722E+00, 0.4068006968345205E+00, 0.8649881745683563E+00, 0.8522504948442566E+00, 0.5120820890311298E+00, 0.7764141319706099E+00, 0.4928600452500731E+00, 0.2048536231221674E+00, 0.4451308747598662E+00, 0.4335546033385644E+00, 0.5471256397417612E-01, 0.7004960984988220E+00, 0.9192372420579460E+00, 0.3890133989146303E+00, 0.2488782917619309E+00, 0.3663470187625480E+00, 0.9986636866778884E+00, 0.6620792031393874E+00, 0.1797345205931197E+00, 0.8723761011602340E+00, 0.2439575243714007E+00, 0.1163919437436586E+00, 0.8182195270597429E+00, 0.5356403226658167E+00, 0.9880537276300997E+00, 0.4163057033602857E+00, 0.8081980088045720E+00, 0.2399383760782623E+00, 0.9702581513812658E+00, 0.3763181880939181E+00, 0.6334004896983517E+00, 0.1368995930243956E+00, 0.7684724492197631E+00, 0.1011989548860721E+00, 0.5519462180485674E+00, 0.8316516728108886E+00, 0.3772586994144635E+00}, + n: 21, + zOut: []float64{0.2579297838383781E+01, 0.2566242251743589E+01, 0.2402206059499122E+01, 0.2314572748831938E+01, 0.2210246243389976E+01, 0.2073991263591532E+01, 0.1647852770173070E+01, 0.1458062583915517E+01, 0.1424747680105817E+01, 0.1229594627898745E+01, 0.8682818248784862E+00, 0.7800126440184885E+00, 0.7769870810337002E+00, 0.4018986220147585E+00, 0.3451236345722463E+00, 0.2059421010707241E+00, 0.1665395041671736E+00, 0.1384541468623413E+00, 0.4569625338134105E-01, 0.3572364569397507E-01, 0.7785678858960618E-04, 0.1325624140040768E-19, 0.1464254707155794E-03, 0.9424803187834284E-04, 0.1647852770173070E+01, 0.1564186274351218E-15, 0.3473328524848360E-05, 0.4592867365821283E-05, 0.1458062583915517E+01, 0.3231174267785264E-26, 0.1403657959312935E-04, 0.9634257574341414E-05, 0.1424747680105817E+01, 0.1020140793606197E-15, 0.1723203566561169E-05, 0.6067379842882497E-05, 0.1229594627898745E+01, 0.2663149152121406E-17, 0.1061013981937667E-04, 0.1674993264096194E-04, 0.8682818248784862E+00, 0.8099755562101574E-24, 0.2367155138201492E+02, 0.2367155138201491E+02, 0.1110000000000000E+03, 0.3174603174603174E+01, 0.5405405405405405E+01, 0.8398559432747079E-06, 0.7769870810337002E+00, 0.0000000000000000E+00, 0.6532651675838807E-05, 0.1393736055608104E-04, 0.4018986220147585E+00, 0.1488702756444268E-16, 0.4786924897797409E-03, 0.2484818164296786E-03, 0.3451236345722463E+00, 0.1393994753571567E-18, 0.7967956438667165E-06, 0.1566848631115136E-05, 0.2059421010707241E+00, 0.1872521839860791E-17, 0.1674828806776016E-04, 0.3829209207735075E-04, 0.1665395041671736E+00, 0.5127595883936577E-29, 0.1145979873394449E-04, 0.6763541499702777E-05, 0.1384541468623413E+00, 0.6162975822039155E-31, 0.1509781169748205E-03, 0.4934238518442497E-04, 0.4569625338134105E-01, 0.3815207438965640E-25, 0.3298388086972868E-02, 0.1367005987525658E-02, 0.3572364569397507E-01, 0.2773930797150972E-21, 0.3955985102398275E-03, 0.3433403686203228E-03, 0.7785678858960618E-04, 0.7790054198074833E-21, 0.1914938157793930E-01, 0.1330976133014081E-01}, + info: 0, + }, + { + z: []float64{0.8677677383100214E+00, 0.6246622741727026E+00, 0.5523136647126087E+00, 0.2116103484147348E+00, 0.8227197076777661E+00, 0.3636019443697256E+00, 0.2305222034118074E+00, 0.3291143648196290E+00, 0.6800926583943011E+00, 0.4290450477605455E+00, 0.4523048516285796E+00, 0.9276084588261152E+00, 0.4462311938877914E+00, 0.6672491542978151E+00, 0.7808537049355564E+00, 0.7908271145868994E+00, 0.1977402045683964E+00, 0.2563794060302639E+00, 0.6768044668199432E+00, 0.8985309013607360E+00, 0.3750140409512910E+00, 0.2003663066929584E-01, 0.4020022629723622E+00, 0.9909625073113403E+00, 0.9747495116121061E+00, 0.9702779584867087E+00, 0.9688371740876045E+00, 0.3747269639045615E+00, 0.9728403214040160E-01, 0.7507234588709335E+00, 0.8245099981459856E+00, 0.7244448753186800E+00, 0.3670523289486082E+00, 0.6220520718362722E+00, 0.3063226611493952E+00, 0.3012769332894331E+00, 0.6763821017483275E+00, 0.8300640433662996E+00, 0.5563237542291373E+00, 0.5594449054752113E+00, 0.3278038518373678E+00, 0.7307041435680680E+00, 0.1582529760475658E+00, 0.5328751876026443E+00, 0.7841944053171677E+00, 0.2157818394558657E+00, 0.3253134136288985E+00, 0.5014502641306768E+00, 0.2229178930043155E+00, 0.4664985859426845E+00, 0.1867987929192785E+00, 0.1951091673564507E+00, 0.2069185156156168E+00, 0.9058058542218750E+00, 0.7999188612304056E+00, 0.7349484002829904E+00, 0.4153480749961962E+00, 0.8109879258422723E+00, 0.9883741464101338E+00, 0.4911202582082937E+00, 0.2193166361224579E+00, 0.7618820222564749E+00, 0.9073087210515056E+00, 0.5896383620860655E+00, 0.8706198942119541E+00, 0.3860710050052940E-01, 0.9380336544251486E+00, 0.4690283060543987E-01, 0.8970820572284144E+00, 0.1974579201509297E-01, 0.9992442335759629E+00, 0.9801967887432729E+00, 0.6116617864086051E+00, 0.5875675950916066E+00, 0.9622537584002233E+00, 0.8934200351761762E+00, 0.2022182729782195E+00, 0.1273316669652236E-01, 0.2549904925850485E+00, 0.8904280763656908E+00, 0.2695748922419082E+00, 0.8890196843116763E+00, 0.5191439214393291E+00, 0.3672061831861048E+00}, + n: 21, + zOut: []float64{0.3071910136434907E+01, 0.2366684893081943E+01, 0.2247985022656176E+01, 0.2134160618983571E+01, 0.1929380862422316E+01, 0.1895668448583188E+01, 0.1735809456784568E+01, 0.1390623822795548E+01, 0.1372853012616850E+01, 0.1197489438156041E+01, 0.1106600205023489E+01, 0.8564547950868329E+00, 0.4949238197552136E+00, 0.3889452841496929E+00, 0.3405947975938995E+00, 0.2516597920662951E+00, 0.2113890461921598E+00, 0.1169778386549868E+00, 0.1072268106836703E+00, 0.7646784687889400E-02, 0.1286588928027629E-02, 0.1194767075191949E-22, 0.1162094363453686E-09, 0.8691558890693288E-10, 0.1735809456784568E+01, 0.8134816760001801E-14, 0.1019665656815186E-08, 0.1906916241197346E-08, 0.1390623822795548E+01, 0.0000000000000000E+00, 0.1594323424098234E-05, 0.3312168640703357E-05, 0.1372853012616850E+01, 0.0000000000000000E+00, 0.3830524268846776E-04, 0.1577534719508939E-04, 0.1197489438156041E+01, 0.1592850300841939E-16, 0.1256296423282912E-03, 0.1149042579564614E-03, 0.1106600205023489E+01, 0.6530365529382261E-18, 0.2322627147533726E+02, 0.2322627147533726E+02, 0.1020000000000000E+03, 0.2963718820861678E+01, 0.3921568627450980E+01, 0.6483516393063832E-03, 0.4949238197552136E+00, 0.1972152263052530E-28, 0.5430985229870038E-04, 0.4447663749968261E-04, 0.3889452841496929E+00, 0.1329049288162406E-17, 0.2738942590248176E-04, 0.1582812372822289E-04, 0.3405947975938995E+00, 0.1187508759187252E-18, 0.7465410105999781E-04, 0.1255487400488340E-03, 0.2516597920662951E+00, 0.4141519752410312E-29, 0.2152266118694742E-04, 0.6710408995051273E-05, 0.2113890461921598E+00, 0.3333294884283764E-18, 0.6132111109262542E-03, 0.4277764486586744E-03, 0.1169778386549868E+00, 0.2711709361697228E-30, 0.3832079371139971E-03, 0.3904887652242632E-03, 0.1072268106836703E+00, 0.2176254805972020E-18, 0.4306247975784355E-03, 0.4948147025217374E-03, 0.7646784687889400E-02, 0.1110488679882733E-19, 0.1569670832436511E-02, 0.2092370053382882E-02, 0.1286588928027629E-02, 0.5442848430598922E-18, 0.4460307636637516E-02, 0.7046212350403941E-02}, + info: 0, + }, + { + z: []float64{0.9838241499564321E+00, 0.8769514477589457E+00, 0.6814467524843054E+00, 0.3624618995089947E+00, 0.1981908649829056E+00, 0.1872278407669582E+00, 0.9876554444003832E+00, 0.1826583579385833E+00, 0.1183269767614670E-01, 0.9437175277915953E+00, 0.4919320768587329E+00, 0.9805291749478650E+00, 0.6132842150855770E+00, 0.3626870797541525E+00, 0.5323780753704027E+00, 0.1457937981484730E+00, 0.1328300737138376E+00, 0.3811835111034733E+00, 0.7003413504474413E+00, 0.5497308136521228E+00, 0.8255713255718768E+00, 0.5373393799690840E+00, 0.6623327475759663E+00, 0.5316913920782962E-01, 0.1714649183335913E+00, 0.6186592957613974E+00, 0.7587327126921758E+00, 0.9100586255702885E+00, 0.7140000863381626E+00, 0.7400119974078728E+00, 0.3567025022071233E+00, 0.8218612151637966E+00, 0.5520556331010515E+00, 0.6508027169553372E+00, 0.1875664464519897E+00, 0.8183092398415237E+00, 0.2239662369231676E-01, 0.6571790154721793E+00, 0.1196415656369646E+00, 0.3853512775546503E+00, 0.2426450009067070E+00, 0.9653447575661293E+00, 0.4852906340727067E+00, 0.9923496603563310E+00, 0.2812811891225394E+00, 0.9784300144088514E+00, 0.9528689986126391E+00, 0.2431080020200448E+00, 0.4166208849723857E+00, 0.7357806826601304E+00, 0.1952831632199464E+00, 0.6393407699957093E+00, 0.6296804002658308E+00, 0.1028694374663701E+00, 0.1387452591062114E+00, 0.4549213107961220E+00, 0.9843671628976580E+00, 0.4249152858158138E+00, 0.7048043599695387E+00, 0.3653998904622074E+00, 0.2003765309007774E+00, 0.4095912484595889E+00, 0.2392233396621621E+00, 0.7050044605645847E+00, 0.7908086424110450E-01, 0.2038177493661538E+00, 0.1735168081909322E-01, 0.3343100300667304E+00, 0.2848572906345944E+00, 0.8454138442968477E+00, 0.4944340369822147E+00, 0.7101083458004501E+00, 0.2546477176633619E+00, 0.8227235336957786E+00, 0.2816146807741101E+00, 0.6247995550265835E+00, 0.7458069042729408E+00, 0.8739345864578790E+00, 0.1278937298671606E+00, 0.2791833532060612E+00, 0.9234762152279486E+00, 0.9863012584972185E+00, 0.7892913846591531E+00, 0.3479266835120939E+00}, + n: 21, + zOut: []float64{0.2623495482601064E+01, 0.2337512212773574E+01, 0.2310508039367694E+01, 0.2188663096012427E+01, 0.1954141717332891E+01, 0.1371476701077329E+01, 0.1267869950064541E+01, 0.1203016320141301E+01, 0.1132845050819559E+01, 0.9979737678355206E+00, 0.8633053234635751E+00, 0.6603430282082061E+00, 0.6064350433288983E+00, 0.4855760962077864E+00, 0.4280373135604714E+00, 0.3659370670152315E+00, 0.1453682093766173E+00, 0.9617861239701422E-01, 0.7192949634365248E-01, 0.1892143303127712E-02, 0.3946528731286962E-05, 0.0000000000000000E+00, 0.9258243476772570E-07, 0.9000418438492766E-07, 0.1267869950064541E+01, 0.0000000000000000E+00, 0.2500234135491857E-07, 0.1856395032302831E-07, 0.1203016320141301E+01, 0.2658426139847422E-18, 0.4168972835699797E-07, 0.5531467635213317E-07, 0.1132845050819559E+01, 0.2518044009465470E-24, 0.1194059466661935E-08, 0.2159625808467239E-08, 0.9979737678355206E+00, 0.1047506307937635E-23, 0.4478743649191460E-07, 0.9991281120631680E-07, 0.8633053234635751E+00, 0.5895762127714383E-22, 0.2111250861775921E+02, 0.2111250861775921E+02, 0.9900000000000000E+02, 0.2927437641723356E+01, 0.4040404040404041E+01, 0.9244672049175682E-07, 0.6064350433288983E+00, 0.1817535525629211E-26, 0.9398974933478891E-07, 0.9547946669183887E-07, 0.4855760962077864E+00, 0.3185418565406740E-17, 0.9937648506460343E-07, 0.9792626502078532E-07, 0.4280373135604714E+00, 0.2958228394578794E-30, 0.9921525775570031E-07, 0.1006425128472401E-06, 0.3659370670152315E+00, 0.4461863922899316E-21, 0.1047488573169732E-06, 0.1032270990738791E-06, 0.1453682093766173E+00, 0.6504493884088473E-15, 0.1102576940374778E-06, 0.1180293023862048E-06, 0.9617861239701422E-01, 0.6467797587852522E-18, 0.1844536574504796E-06, 0.1488485108626942E-06, 0.7192949634365248E-01, 0.2114103686638959E-13, 0.8531410278849863E-06, 0.1408572284551695E-05, 0.1892143303127712E-02, 0.0000000000000000E+00, 0.6242841403373791E-04, 0.3522115697192072E-04, 0.3946528731286962E-05, 0.6203854594147708E-24, 0.1209929086462260E-02, 0.4906802871097585E-03}, + info: 0, + }, + { + z: []float64{0.7643247442799757E+00, 0.1930914554442843E+00, 0.6441117687067544E-01, 0.4522061669974708E-01, 0.1465182320932497E+00, 0.8069033698425149E+00, 0.6560188128523874E+00, 0.2446749124420051E+00, 0.3243649544497533E+00, 0.9836733438970116E+00, 0.6137527621157332E+00, 0.2925225554635034E+00, 0.4955619768673408E+00, 0.7361289066349539E+00, 0.3953262269487445E-01, 0.1565854250658760E-01, 0.4785236355428808E+00, 0.7766165270899886E+00, 0.9069259340739989E+00, 0.9151936268801151E+00, 0.3338292872636017E+00, 0.2993135005490550E+00, 0.8287022194584887E+00, 0.4593628480546942E+00, 0.1484428934315618E-01, 0.3390977660295040E+00, 0.5819746692101802E-01, 0.9277352020779983E-01, 0.6517310862845033E+00, 0.3951866136249272E+00, 0.6199300068296295E+00, 0.8252199884043853E+00, 0.3390764160478065E+00, 0.3084679704183562E+00, 0.3609211283483548E+00, 0.4116857210304998E+00, 0.4609476939442378E+00, 0.3824129844545763E+00, 0.6431169626236315E+00, 0.2416519334621993E+00, 0.7156780768158061E+00, 0.8568018406565006E+00, 0.1639408452444666E+00, 0.7313040585903831E+00, 0.5099183572592548E+00, 0.2801641590611897E+00, 0.9930562568266591E+00, 0.7612468327164370E+00, 0.3271886985411110E-01, 0.7066605591101006E+00, 0.6720867845388043E+00, 0.9004209067318458E-01, 0.4611918168927077E+00, 0.2638384667560661E+00, 0.3554909044606102E+00, 0.7231384727137510E+00, 0.2729268177075039E-01, 0.5848397641916390E+00, 0.6942450598380807E+00, 0.1106927451590289E+00, 0.5262572286481777E+00, 0.9936768911750095E+00, 0.7262536107933111E+00, 0.7604873714570974E+00, 0.2036182130165832E+00, 0.8632527217998969E+00, 0.1924957421132846E+00, 0.8815968660524154E-01, 0.2412813036310424E+00, 0.9105232147744077E+00, 0.8298587923387578E+00, 0.7754575363227978E-01, 0.8714764594177653E+00, 0.5571901679066804E+00, 0.3971870017409277E+00, 0.9993097753535422E+00, 0.7700188328643205E+00, 0.7856615172810383E+00, 0.7533953600915489E+00, 0.5602208064288483E+00, 0.6944234372397261E+00, 0.8756090822068926E+00, 0.1433700749181099E-01, 0.2857413018245216E+00}, + n: 21, + zOut: []float64{0.2546753248931182E+01, 0.2051980365170268E+01, 0.1958366389726797E+01, 0.1631238683423845E+01, 0.1586034790683645E+01, 0.1538534425510682E+01, 0.1255412586747036E+01, 0.1121690972560896E+01, 0.9718147643766369E+00, 0.9049110982817965E+00, 0.7946671649858114E+00, 0.5884376759528481E+00, 0.4050217422474118E+00, 0.3189813042957475E+00, 0.2502079076659038E+00, 0.1378021633219403E+00, 0.1230588999356998E+00, 0.5024634530670342E-01, 0.4118371112977081E-01, 0.5279820157992808E-02, 0.1421284452028254E-03, 0.2680065184671810E-21, 0.2301930285321580E-14, 0.5132436462785431E-14, 0.1255412586747036E+01, 0.2424007516335156E-18, 0.1913029885324846E-10, 0.9021761757831104E-11, 0.1121690972560896E+01, 0.1977581519346623E-22, 0.4602280167506019E-08, 0.2460881124989248E-08, 0.9718147643766369E+00, 0.1104484640438811E-18, 0.4278245612761057E-07, 0.2387897413722468E-07, 0.9049110982817965E+00, 0.2768434971275651E-16, 0.3015076539683485E-07, 0.2961312447326530E-07, 0.7946671649858114E+00, 0.1262042385269225E-19, 0.1828176618885781E+02, 0.1828176618885782E+02, 0.1040000000000000E+03, 0.3122448979591837E+01, 0.3846153846153846E+01, 0.1851926648424158E-06, 0.4050217422474118E+00, 0.9293221980374701E-17, 0.1284245841610550E-05, 0.2164676294343609E-05, 0.3189813042957475E+00, 0.1378649105642637E-16, 0.4610281885819925E-06, 0.1003327305702036E-05, 0.2502079076659038E+00, 0.2177821011994986E-13, 0.3677246803752887E-04, 0.3095541926811936E-04, 0.1378021633219403E+00, 0.9210656120777790E-20, 0.9401458780737957E-05, 0.1039122642078444E-04, 0.1230588999356998E+00, 0.4930380657631324E-30, 0.6528493871226699E-06, 0.1524653341983116E-05, 0.5024634530670342E-01, 0.6838275466788171E-23, 0.2104276631320477E-03, 0.3160258883556432E-03, 0.4118371112977081E-01, 0.6162975822039155E-32, 0.9318133168194381E-04, 0.1261364640367337E-03, 0.5279820157992808E-02, 0.7005084838362585E-27, 0.1903158606362315E-02, 0.7288242235414376E-03, 0.1421284452028254E-03, 0.7703719777548943E-33, 0.7890744155827079E-03, 0.6129022301104231E-03}, + info: 0, + }, + { + z: []float64{0.1813251202119042E+00, 0.8077156210855166E+00, 0.5525396662071069E+00, 0.4858391136124270E+00, 0.5367389425969793E+00, 0.4534294101162717E-01, 0.1438386197304258E+00, 0.7801305810912117E+00, 0.7706244548712898E+00, 0.1595286891781422E+00, 0.4689597797472277E+00, 0.1630160981693277E+00, 0.5488525733069047E+00, 0.3050379405729475E+00, 0.1544160351990825E+00, 0.5750210099163514E+00, 0.1440876969429373E+00, 0.1932969959898051E+00, 0.6910796187912660E+00, 0.9501882645686455E+00, 0.1314109921701710E+00, 0.7099941843070685E+00, 0.3797313713209320E+00, 0.3979808845174081E+00, 0.1006018923100482E-02, 0.4131896358268045E+00, 0.8038132966802857E+00, 0.8778643630407806E+00, 0.1407889867849830E+00, 0.4305134083308382E-01, 0.5656496703997997E+00, 0.5820188952601091E-01, 0.8713537916178680E+00, 0.3443162753417257E+00, 0.4898335360866699E+00, 0.2822165738696382E+00, 0.2385629061714932E+00, 0.5496478420286478E+00, 0.7138724344268773E+00, 0.9028268569137332E+00, 0.7573748459251011E+00, 0.5392259606733280E+00, 0.6459213128573325E+00, 0.7769497211063184E+00, 0.8790154346127051E+00, 0.6027389165195913E+00, 0.6151696559086139E-01, 0.4391208291942791E+00, 0.8705350585502258E-02, 0.2995750933531418E+00, 0.9735013653226658E+00, 0.9551710085419519E+00, 0.2132875677034638E+00, 0.6739668529657764E+00, 0.5361543284664445E+00, 0.3596977928604983E+00, 0.1373006735837845E-02, 0.8494363479416891E+00, 0.4214720423022895E+00, 0.7478449906096684E+00, 0.1164429527473354E-01, 0.6143683285709396E+00, 0.4444360064738268E+00, 0.6626608299302873E+00, 0.6887459689591686E+00, 0.9391262494647765E+00, 0.7167310461528731E+00, 0.4516657019045726E+00, 0.6345059624902227E+00, 0.2241941493026407E+00, 0.3981621310014529E+00, 0.8300976429090324E+00, 0.1390103241004258E+00, 0.7559319384422415E+00, 0.7929892786129927E+00, 0.2279061631835571E+00, 0.5280867615120838E+00, 0.1374499172030500E+00, 0.1739503966093568E+00, 0.1475298919309330E+00, 0.8100098524713260E+00, 0.2514850916075489E+00, 0.4100580488172028E+00, 0.9565966467338131E+00}, + n: 21, + zOut: []float64{0.2319179815575576E+01, 0.1965907124623829E+01, 0.1887317422176422E+01, 0.1806195743608332E+01, 0.1738584542532610E+01, 0.1518839817892385E+01, 0.1233018482483247E+01, 0.1147944957333420E+01, 0.8847632334488245E+00, 0.7964611162721277E+00, 0.7478364459856081E+00, 0.6404526251941426E+00, 0.4533452491188792E+00, 0.4218888103472739E+00, 0.2727838365998446E+00, 0.2511907405802137E+00, 0.9874721307137806E-01, 0.7639943902083833E-01, 0.4105860224136690E-01, 0.2835039177122555E-01, 0.1849635761425839E-05, 0.5687744349931984E-17, 0.4733652108368680E-16, 0.8474188088642906E-16, 0.1233018482483247E+01, 0.2772075531849652E-16, 0.2588283290162890E-14, 0.3835910828290052E-14, 0.1147944957333420E+01, 0.1246926305809672E-21, 0.2331804915191085E-13, 0.1628473983494628E-13, 0.8847632334488245E+00, 0.1029638495848151E-18, 0.6869501877456999E-13, 0.5177641249986829E-13, 0.7964611162721277E+00, 0.2366582715663035E-28, 0.1931319748910825E-12, 0.1483226506162133E-12, 0.7478364459856081E+00, 0.0000000000000000E+00, 0.1833026745951331E+02, 0.1833026745951330E+02, 0.1060000000000000E+03, 0.3281179138321995E+01, 0.4716981132075472E+01, 0.1032982741787823E-11, 0.4533452491188792E+00, 0.1306947070833229E-13, 0.7648022419924529E-11, 0.9563864191611805E-11, 0.4218888103472739E+00, 0.2958228394578794E-30, 0.1901963755802408E-10, 0.2450915092704452E-10, 0.2727838365998446E+00, 0.2459678163240430E-25, 0.5533379126041796E-09, 0.3623624255644135E-09, 0.2511907405802137E+00, 0.1890110728909544E-26, 0.3358805149198491E-08, 0.5375184613165106E-08, 0.9874721307137806E-01, 0.5174927538249837E-27, 0.5300164302540724E-07, 0.8261446474891677E-07, 0.7639943902083833E-01, 0.5686866711287438E-23, 0.3075058441398368E-06, 0.1980286028193141E-06, 0.4105860224136690E-01, 0.3391723239215845E-21, 0.3233943307567427E-08, 0.7908141105983331E-09, 0.2835039177122555E-01, 0.0000000000000000E+00, 0.6263230510933575E-04, 0.3843833760247782E-04, 0.1849635761425839E-05, 0.1263270231490984E-18, 0.3749684628997549E-02, 0.9345197933294263E-02}, + info: 0, + }, + { + z: []float64{0.7197398584131909E+00, 0.8353840049537183E+00, 0.7768334206137515E+00, 0.5378835466874095E+00, 0.6112887154160760E+00, 0.6941229566444685E+00, 0.6006831303610110E+00, 0.9634869426512738E-01, 0.5491965547787625E+00, 0.2928965321959978E+00, 0.2058564636772363E+00, 0.8430652032339261E+00, 0.6514967955084195E+00, 0.9630832188959448E+00, 0.6099558369768557E+00, 0.4038812997556026E+00, 0.1286146012481256E+00, 0.1377932216741019E+00, 0.2151249629422850E+00, 0.5230096632076910E+00, 0.7097266420339532E+00, 0.5223889086485353E+00, 0.1844557902493219E+00, 0.8630886970819189E+00, 0.3143018526841452E+00, 0.3064747008129198E-02, 0.9995777893655772E+00, 0.8804003743833377E+00, 0.2437734590599224E+00, 0.5439224193002447E+00, 0.7609946860078259E+00, 0.6816222186177212E+00, 0.4213100187092527E+00, 0.5947299218072758E+00, 0.4464510683518146E+00, 0.9444991162538406E+00, 0.1663546170185037E+00, 0.9745722490509305E+00, 0.8691156687582791E-01, 0.1511122923287322E+00, 0.9099013034006386E+00, 0.2055280668016559E+00, 0.2215435147609097E+00, 0.1341458340087506E+00, 0.6974464577249216E+00, 0.9770585050570383E+00, 0.2836484389736937E-02, 0.4942205711890229E+00, 0.2476589071081227E+00, 0.9025674475802441E+00, 0.1043173067377164E+00, 0.7752297952628227E+00, 0.1045812556997563E+00, 0.6207135868564088E+00, 0.3343332589884191E+00, 0.9777410164371825E+00, 0.6919265640807399E+00, 0.8276791372331573E+00, 0.9681277631171376E+00, 0.2774385945770376E+00, 0.3660516291700039E+00, 0.1542243233614283E+00, 0.9809065840498956E+00, 0.9317468521553756E+00, 0.2342755587307467E+00, 0.1233924367977165E+00, 0.3662228319745224E+00, 0.8394462754756703E+00, 0.1257927855780998E+00, 0.9899742295380913E+00, 0.4800112259347978E+00, 0.9614338190585195E+00, 0.9605383026678687E+00, 0.7532278237974727E+00, 0.6455994058946259E+00, 0.6648840697262024E+00, 0.8792931963163917E+00, 0.7296338860815629E+00, 0.6962759488463338E+00, 0.5343477930729980E+00, 0.7488075021642351E+00, 0.8267598422017227E+00, 0.4128864062622362E-02, 0.2248794313377519E+00}, + n: 21, + zOut: []float64{0.2440396187223568E+01, 0.2429593845031884E+01, 0.2248977224883395E+01, 0.1983141106497864E+01, 0.1775047097539426E+01, 0.1685850120713433E+01, 0.1685238074648001E+01, 0.1228212776246503E+01, 0.1167582065653490E+01, 0.1163468828895948E+01, 0.9840288601088477E+00, 0.8446765744020336E+00, 0.5858419229944851E+00, 0.5828733061329966E+00, 0.4321746091262585E+00, 0.2506332278777725E+00, 0.1601952029039821E+00, 0.9519704710728188E-01, 0.5380488026634178E-01, 0.2070966044404248E-02, 0.4144953892415127E-03, 0.1577721810442024E-28, 0.2622007349295965E-13, 0.1959395597612919E-13, 0.1685238074648001E+01, 0.5298116057209151E-24, 0.4690429322435832E-13, 0.6275308499802102E-13, 0.1228212776246503E+01, 0.3786532345060857E-26, 0.6968636880972768E-12, 0.1483661956038748E-11, 0.1167582065653490E+01, 0.4135903062764930E-23, 0.1852086238235612E-10, 0.7750996975985970E-11, 0.1163468828895948E+01, 0.1171277614412583E-17, 0.1085363071939462E-09, 0.2643024434742409E-09, 0.9840288601088477E+00, 0.6878867093527223E-27, 0.2179941841968715E+02, 0.2179941841968716E+02, 0.1010000000000000E+03, 0.3140589569160998E+01, 0.4950495049504950E+01, 0.1077573597463830E-06, 0.5858419229944851E+00, 0.3627601229823987E-15, 0.8463992810044351E-06, 0.7647582718993818E-06, 0.5828733061329966E+00, 0.5798443197736525E-25, 0.5805124866712180E-06, 0.5336279095847515E-06, 0.4321746091262585E+00, 0.1164890830118439E-21, 0.3270430863981586E-06, 0.3120015969970153E-06, 0.2506332278777725E+00, 0.1344740577327136E-22, 0.6612009870063018E-06, 0.4716796838663449E-06, 0.1601952029039821E+00, 0.0000000000000000E+00, 0.1909143391170965E-04, 0.1029106625513428E-04, 0.9519704710728188E-01, 0.5127595883936577E-28, 0.3722911957200607E-04, 0.5334790194682025E-04, 0.5380488026634178E-01, 0.4916199468524512E-16, 0.8145434425645190E-04, 0.4879722252791062E-03, 0.2070966044404248E-02, 0.2051115390772406E-31, 0.1886522673573371E-02, 0.1146190938097804E-02, 0.4144953892415127E-03, 0.1134788402846185E-20, 0.5837570815253673E-02, 0.1435831510150291E-01}, + info: 0, + }, + { + z: []float64{0.4141124863190200E+00, 0.6286592513493726E+00, 0.4875442526190354E-01, 0.6631999174821102E+00, 0.1778328741285358E+00, 0.5820997881750413E+00, 0.9610329112936564E+00, 0.2860180457593013E+00, 0.2800413372286658E+00, 0.8782990052007664E+00, 0.6769848820880126E+00, 0.2361981145928655E+00, 0.1864129841856804E+00, 0.6207802268756868E-01, 0.1668832170172669E+00, 0.2136536864861034E+00, 0.4266698341219798E+00, 0.9672331991204097E-01, 0.2350195655513042E+00, 0.1297162551474343E+00, 0.9428942697229301E+00, 0.3355426683568981E+00, 0.6977568272344947E-01, 0.4926170514192555E+00, 0.6966571762613959E+00, 0.7422949877167778E+00, 0.1216493993328296E+00, 0.5414775352707472E+00, 0.4507250901570525E+00, 0.6851601412475350E+00, 0.8339584749808495E+00, 0.9321374665508209E+00, 0.7664819871766777E+00, 0.5935455015911359E+00, 0.4047285985374618E+00, 0.9996987445838635E+00, 0.1347158425141065E+00, 0.3601395592420920E+00, 0.1128763847009464E+00, 0.6316809196633902E+00, 0.1559195263655234E+00, 0.4041853050912981E+00, 0.1854167847278504E+00, 0.6852913644854558E+00, 0.6126092157077416E+00, 0.2444516268314137E+00, 0.1447238269517732E+00, 0.7179956614587130E+00, 0.8198652148251639E+00, 0.1186997025611126E+00, 0.1267596520196094E+00, 0.2863431547875360E+00, 0.9867539057590858E+00, 0.2454746550565152E+00, 0.4891318294681372E+00, 0.2969454310391295E-01, 0.2349636207332649E+00, 0.4537731552146703E+00, 0.2883801124165087E+00, 0.7150664117598651E+00, 0.4359050919721921E+00, 0.6116081525473241E+00, 0.5619840590438748E+00, 0.3431726287099235E+00, 0.7715898362788249E+00, 0.4981359837313185E+00, 0.4537925078699018E+00, 0.6956466175473529E+00, 0.1814680828887681E+00, 0.4413903687143481E+00, 0.4367593306147978E+00, 0.5875066776157845E-01, 0.3688522862246468E+00, 0.4308468783440871E+00, 0.1986553761412286E+00, 0.3949957841484223E+00, 0.2468986938324821E+00, 0.6216444107315144E-01, 0.9076510210089642E+00, 0.5197394332656491E+00, 0.8460559187475114E-01, 0.3959477165848089E+00, 0.1014864219123556E+00, 0.4789226780612066E-01}, + n: 21, + zOut: []float64{0.2746085040517442E+01, 0.2006646947029628E+01, 0.1843368381126182E+01, 0.1738309804669461E+01, 0.1678478075610122E+01, 0.1408432532104903E+01, 0.1219097982435216E+01, 0.1121569511965291E+01, 0.9315294884679637E+00, 0.7914377647612258E+00, 0.7334412101899261E+00, 0.6113376828240070E+00, 0.4134386595159317E+00, 0.3303980566325673E+00, 0.2866331058299493E+00, 0.2287206720574312E+00, 0.1408981800627584E+00, 0.6649497607659796E-01, 0.5733628497886722E-01, 0.1387598234001070E-02, 0.2497701489633820E-04, 0.3487740233155725E-22, 0.3361270559917294E-05, 0.1214091727263821E-05, 0.1219097982435216E+01, 0.2843433355651033E-23, 0.3877657623657789E-06, 0.2861458561047538E-06, 0.1121569511965291E+01, 0.1501849799666580E-22, 0.7980776610337536E-07, 0.1296132789777516E-06, 0.9315294884679637E+00, 0.1397279453391396E-14, 0.3797866386428551E-06, 0.5462183171930727E-06, 0.7914377647612258E+00, 0.1231982124821006E-21, 0.6463973892160826E-06, 0.4555968092429713E-06, 0.7334412101899261E+00, 0.9423416829408119E-25, 0.1835506693210437E+02, 0.1835506693210436E+02, 0.9800000000000000E+02, 0.2884353741496599E+01, 0.2040816326530612E+01, 0.6355562713716383E-07, 0.4134386595159317E+00, 0.4284860196510039E-21, 0.4931868922851139E-05, 0.2760082849901006E-05, 0.3303980566325673E+00, 0.1448288531514775E-16, 0.4631299886341806E-05, 0.9149811670123540E-05, 0.2866331058299493E+00, 0.1558000287811498E-28, 0.1337090019087612E-05, 0.8008074996380075E-06, 0.2287206720574312E+00, 0.2366582715663035E-29, 0.4303808308110317E-06, 0.3181248709867330E-06, 0.1408981800627584E+00, 0.2443697032165075E-19, 0.2973006759321362E-05, 0.5017304713868616E-05, 0.6649497607659796E-01, 0.1131941655598205E-16, 0.8328041136745409E-04, 0.8552508571764750E-04, 0.5733628497886722E-01, 0.9398173280441046E-25, 0.5097763200650848E-04, 0.5644224660768206E-04, 0.1387598234001070E-02, 0.8888394955180400E-22, 0.1868721561136477E-03, 0.1091351925463373E-03, 0.2497701489633820E-04, 0.0000000000000000E+00, 0.1020791029288490E-01, 0.2791888375404797E-02}, + info: 0, + }, + { + z: []float64{0.2396228092919251E+00, 0.6434601049058037E+00, 0.5488667726527494E+00, 0.1843504645657519E+00, 0.4269001369847240E+00, 0.6276093013166625E+00, 0.8724336393628729E-01, 0.5371039952903035E+00, 0.8447460457667564E+00, 0.4094766929502263E+00, 0.2031514124499976E+00, 0.8271428312997948E+00, 0.9658284302973903E+00, 0.3777353969048113E+00, 0.6471334022587341E+00, 0.6777435175679861E+00, 0.4456890557292859E+00, 0.1720826572683752E+00, 0.3520207432901141E+00, 0.3291396508341311E+00, 0.7468262262373744E+00, 0.2715104496960554E+00, 0.5612917863396235E+00, 0.1324429469286776E+00, 0.7983766064014711E+00, 0.2059599586019641E+00, 0.2655510256425775E-01, 0.1962390264484870E+00, 0.7845246896371560E-02, 0.8217737559711210E+00, 0.9444498218704492E+00, 0.4679957695831033E+00, 0.1135918053039552E+00, 0.1604948252571132E+00, 0.8452381101613837E+00, 0.8537070814716049E+00, 0.3013932596816266E+00, 0.2511715406702125E+00, 0.2008647638036438E+00, 0.2607897573444329E+00, 0.2571050910078490E+00, 0.6286174024463315E+00, 0.4739701849723611E+00, 0.8698947534844018E+00, 0.6486079589595961E+00, 0.8894321904301987E+00, 0.7952475840185558E+00, 0.8801661721215410E+00, 0.2147272194381030E+00, 0.9518356646476019E+00, 0.7191152289414877E+00, 0.1106524971173308E+00, 0.9574587230734148E+00, 0.6469474230679395E+00, 0.5818260757443584E+00, 0.1292202837075540E-01, 0.2761722913438078E+00, 0.8004535925585585E+00, 0.3278973855590038E+00, 0.5794037438664289E+00, 0.2396155443104175E-01, 0.6699048475753794E+00, 0.1814492937128086E+00, 0.2866184936222242E+00, 0.6584557212506269E+00, 0.5889651227775431E+00, 0.6369766519060738E-01, 0.1328193529598596E+00, 0.7416631417262871E+00, 0.5003318278706693E+00, 0.3144077296395376E-01, 0.9907393156403193E+00, 0.3423696594914594E-02, 0.6992922072850826E+00, 0.7590519617064543E+00, 0.2542182514116359E+00, 0.3314657184555089E+00, 0.5728659684019645E+00, 0.9915854796414423E+00, 0.4896749730105238E+00, 0.5611369720796141E+00, 0.6064142215043516E+00, 0.8567590164766914E-01, 0.2581731932678185E+00}, + n: 21, + zOut: []float64{0.2319327880258489E+01, 0.2079713994229665E+01, 0.1953873370330741E+01, 0.1755147049127663E+01, 0.1569664109844580E+01, 0.1497177879850755E+01, 0.1442939549198070E+01, 0.1142654640257259E+01, 0.1037259380018118E+01, 0.7336163063097807E+00, 0.6300572204242147E+00, 0.3966542874116493E+00, 0.3925821156107781E+00, 0.2721798695257625E+00, 0.2365431978248397E+00, 0.2044065204974935E+00, 0.1570073942488483E+00, 0.8918832674569614E-01, 0.5938710196407761E-01, 0.3241742658191688E-02, 0.4778146591607052E-04, 0.1325286320771300E-27, 0.1485620696270319E-14, 0.4653485276256090E-14, 0.1442939549198070E+01, 0.1846131417899111E-22, 0.1162592678154001E-11, 0.3263011919854044E-11, 0.1142654640257259E+01, 0.4412642697382792E-11, 0.1735169830505648E-08, 0.3333560963091213E-08, 0.1037259380018118E+01, 0.1055565179678919E-18, 0.1940309609380032E-07, 0.3465529731850831E-07, 0.7336163063097807E+00, 0.4440642298320086E-11, 0.3810071749579748E-06, 0.5916980508399715E-06, 0.6300572204242147E+00, 0.4658681208910640E-20, 0.1797266971780259E+02, 0.1797266971780259E+02, 0.1110000000000000E+03, 0.3253968253968254E+01, 0.3603603603603604E+01, 0.2492194730770069E-13, 0.3925821156107781E+00, 0.0000000000000000E+00, 0.7667233942003248E-12, 0.2416678934089916E-12, 0.2721798695257625E+00, 0.2051915459060795E-16, 0.1487877135020801E-08, 0.6143545671036994E-08, 0.2365431978248397E+00, 0.1972152263052530E-29, 0.1960096418178738E-05, 0.2274829676605902E-05, 0.2044065204974935E+00, 0.2021903259098794E-21, 0.8745843979356665E-06, 0.9251106153042376E-06, 0.1570073942488483E+00, 0.5482898835648120E-25, 0.7118492322907369E-04, 0.3316595178521346E-03, 0.8918832674569614E-01, 0.1022725463125710E-19, 0.2167108979032774E-02, 0.1228336641518804E-02, 0.5938710196407761E-01, 0.1994240368398718E-26, 0.2711464061500906E-02, 0.2561834534417173E-02, 0.3241742658191688E-02, 0.1814380082008327E-27, 0.4237092909216320E-02, 0.4420407214578293E-02, 0.4778146591607052E-04, 0.2596519942803954E-20, 0.1820843269063370E-02, 0.8929397931439835E-02}, + info: 0, + }, + { + z: []float64{0.4704013808869884E+00, 0.8133248937317098E+00, 0.7246209022332254E+00, 0.9930301346620946E+00, 0.6565279241713462E-01, 0.7480498761899035E-01, 0.8311943018468732E+00, 0.4127487814312358E+00, 0.6620288516904083E+00, 0.2540390589975015E+00, 0.4830377447593585E+00, 0.6124023244542695E+00, 0.6830062885714996E+00, 0.4006497306883100E+00, 0.2108017907398356E+00, 0.9099126499549155E+00, 0.4756780627224959E+00, 0.8563186613679700E+00, 0.9168447467108382E+00, 0.5153963449488133E+00, 0.7188966629304918E+00, 0.2875525393671987E+00, 0.6200986280097742E-01, 0.3765186242141257E+00, 0.2589923271177115E+00, 0.5404093081826918E+00, 0.5343437371907505E+00, 0.3104227497255196E-01, 0.4221838478889377E+00, 0.4233113354732956E+00, 0.6486058235731677E+00, 0.1590032665029245E+00, 0.3877113621801469E+00, 0.6038849620024899E+00, 0.5400341407425849E+00, 0.7060013907006117E+00, 0.1173345165878200E+00, 0.8548311704210352E+00, 0.5804532700087333E+00, 0.5231399784962363E+00, 0.4754841524148748E+00, 0.3395282932287647E-01, 0.7668594432348432E+00, 0.8184682560752043E+00, 0.5633264054575460E-01, 0.2127176392631261E+00, 0.7432372685121402E+00, 0.3098453278874418E+00, 0.1150335122169536E+00, 0.8681635561145716E+00, 0.3593935949259885E+00, 0.9085822737263088E+00, 0.2122810259380176E+00, 0.3589456483065394E+00, 0.9437026007300053E-01, 0.6518875210051764E+00, 0.9046367728621729E+00, 0.7638617707854546E+00, 0.8924521343092110E+00, 0.8353112965912926E+00, 0.5076189975461921E+00, 0.4955137299922637E+00, 0.5041148053921253E+00, 0.7686114107944846E+00, 0.3833696141187980E+00, 0.9181102072361824E-01, 0.9260679284685853E+00, 0.7081687340916837E+00, 0.8312629527805896E+00, 0.8010881636433624E+00, 0.5891143654107377E+00, 0.8149927954305255E+00, 0.7192672792238343E+00, 0.9981622901025261E+00, 0.9368513325443091E+00, 0.6909941993236977E+00, 0.7208744872845105E+00, 0.6334330703247726E+00, 0.8856108044732016E+00, 0.7612967011342276E+00, 0.6840498257884192E+00, 0.8627400929877541E+00, 0.2970500386847904E+00, 0.9828991929119790E+00}, + n: 21, + zOut: []float64{0.2548749189884266E+01, 0.2318283655447516E+01, 0.1949991272828373E+01, 0.1903113092077109E+01, 0.1681173723989745E+01, 0.1621144658162279E+01, 0.1435953736019784E+01, 0.1373215273744876E+01, 0.1276544145324249E+01, 0.8508650942792525E+00, 0.7433578075251207E+00, 0.7333566617981635E+00, 0.6327824956484905E+00, 0.5146506379994326E+00, 0.4497218333883862E+00, 0.2736876649003249E+00, 0.2262999758546705E+00, 0.6320618886076086E-01, 0.1413547856395308E-01, 0.6182735080657475E-02, 0.1223662826415605E-02, 0.9844984097158227E-26, 0.2664250906052687E-13, 0.8143635875649387E-14, 0.1435953736019784E+01, 0.7237830359838992E-24, 0.1147364015889613E-09, 0.4819137169184198E-10, 0.1373215273744876E+01, 0.5490471900338242E-27, 0.1654936529088367E-07, 0.7460880307437913E-08, 0.1276544145324249E+01, 0.2958228394578794E-30, 0.1455672577071588E-05, 0.7169454013791148E-06, 0.8508650942792525E+00, 0.4041314959719700E-19, 0.1917383253612269E-05, 0.1657209462004936E-05, 0.7433578075251207E+00, 0.2357464745776125E-22, 0.2061763898420382E+02, 0.2061763898420383E+02, 0.9600000000000000E+02, 0.2888888888888889E+01, 0.3125000000000000E+01, 0.6718966036888534E-06, 0.6327824956484905E+00, 0.1006441314168352E-20, 0.4252254757420258E-06, 0.3750418335727261E-06, 0.5146506379994326E+00, 0.1125208173090593E-20, 0.1634173128014842E-06, 0.1777130114194832E-06, 0.4497218333883862E+00, 0.1397861524051633E-26, 0.1373153840978587E-06, 0.1424351942740530E-06, 0.2736876649003249E+00, 0.3055476705078142E-15, 0.2530372171390620E-06, 0.3073674645773779E-06, 0.2262999758546705E+00, 0.3987473575125276E-15, 0.5814400581048744E-06, 0.7370753629310487E-06, 0.6320618886076086E-01, 0.9597492304117215E-21, 0.2453687283764395E-05, 0.3193610655869065E-05, 0.1413547856395308E-01, 0.8528167491936360E-20, 0.7231103044220720E-05, 0.9769896858142881E-05, 0.6182735080657475E-02, 0.0000000000000000E+00, 0.3039337033448658E-04, 0.5367078032707280E-04, 0.1223662826415605E-02, 0.6617444900424221E-23, 0.7353916438463039E-03, 0.2144171525794732E-02}, + info: 0, + }, + { + z: []float64{0.9714680453643365E-01, 0.6357804703219754E+00, 0.6664990519488578E-01, 0.1729636879767130E+00, 0.4638342338705743E+00, 0.4390808892462035E+00, 0.8041041328438946E+00, 0.4288731182982508E+00, 0.7624625505229141E+00, 0.7083386603826051E+00, 0.2464792096944004E+00, 0.9011775040224685E+00, 0.6339539510596026E-01, 0.1795036824346197E-01, 0.9473751738931280E+00, 0.4886196718733559E+00, 0.3845982510172906E+00, 0.8175566437299375E-01, 0.4796454941504319E+00, 0.1995303497008669E+00, 0.3542217290845850E+00, 0.4313075601907782E+00, 0.9062634832132850E+00, 0.9362490171108290E+00, 0.7454458344912314E+00, 0.9678028365928690E+00, 0.8785588729275070E+00, 0.2582842558253936E+00, 0.7937433110799214E+00, 0.7912406502001545E-01, 0.1813501620770241E-01, 0.3340784700607168E+00, 0.3348119644971841E+00, 0.5042866134297835E+00, 0.3808798817625770E+00, 0.8932448815066745E+00, 0.2612469692343123E+00, 0.4943911382967600E+00, 0.7396437014435053E+00, 0.6180267747680381E+00, 0.6768529193184074E+00, 0.7346572400466492E+00, 0.8658232798365260E+00, 0.6590888814314796E+00, 0.9020629495832085E+00, 0.2719526227756762E+00, 0.9337960905099231E+00, 0.1402012445044727E+00, 0.3363383773836534E+00, 0.4741712787560632E+00, 0.1270352327896518E-02, 0.2317652069389444E+00, 0.9583986396877475E+00, 0.8857657675309066E+00, 0.5564654172742324E+00, 0.3373121694331064E+00, 0.1866413892025005E+00, 0.3829716065530064E+00, 0.6660176769447556E+00, 0.9140619394089379E+00, 0.4126532961354976E+00, 0.9883322088463480E+00, 0.1678362296131076E+00, 0.1246866166129172E+00, 0.5083959276848560E+00, 0.4743484764552197E+00, 0.1561141239638767E+00, 0.4867628897662705E+00, 0.8068909470080686E+00, 0.9878597697456749E+00, 0.8535449450676436E-01, 0.9609706407601909E+00, 0.7015171470525342E+00, 0.4808513401395343E+00, 0.4421870922261545E+00, 0.2476919441028158E-01, 0.2417065613871903E+00, 0.1174043678151601E+00, 0.4259626380136439E-02, 0.2614829171642307E+00, 0.5973781466265196E+00, 0.3195524674053074E-01, 0.4778949570977242E+00, 0.2741401812748340E+00}, + n: 21, + zOut: []float64{0.2956562879292357E+01, 0.2160920112738185E+01, 0.2057048821491083E+01, 0.1826665062315388E+01, 0.1626476426276149E+01, 0.1617659828407750E+01, 0.1458559932420392E+01, 0.1037845007643388E+01, 0.9436387491729998E+00, 0.8889042931978449E+00, 0.8147110102488896E+00, 0.7938854029224469E+00, 0.5240642869032099E+00, 0.4281570616174346E+00, 0.4032231719469492E+00, 0.2134769254146812E+00, 0.1570954054223686E+00, 0.5771888278451791E-01, 0.2771650645038780E-01, 0.1168397530048623E-02, 0.8626671344136174E-03, 0.6837796509826355E-18, 0.5416843762303492E-12, 0.3045298824248355E-12, 0.1458559932420392E+01, 0.8473754517266856E-24, 0.4783112378014045E-11, 0.8163747631331082E-11, 0.1037845007643388E+01, 0.8077935669463161E-27, 0.2442833758035109E-10, 0.3576901446935589E-10, 0.9436387491729998E+00, 0.1292469707114106E-25, 0.1060154010453575E-09, 0.7148292157772074E-10, 0.8889042931978449E+00, 0.5995342879679690E-28, 0.2265830666026058E-09, 0.3413067902462323E-09, 0.8147110102488896E+00, 0.6874131484520357E-19, 0.1999636083133089E+02, 0.1999636083133089E+02, 0.1000000000000000E+03, 0.3002267573696145E+01, 0.2000000000000000E+01, 0.2441378744031031E-06, 0.5240642869032099E+00, 0.2169367489357782E-29, 0.9564347597274963E-06, 0.8629398155870994E-06, 0.4281570616174346E+00, 0.1533177238774536E-16, 0.2198723423439569E-05, 0.1852641299824983E-05, 0.4032231719469492E+00, 0.1742814620686677E-24, 0.6898774546312495E-05, 0.1242988026413374E-04, 0.2134769254146812E+00, 0.1303198215425112E-25, 0.3054946518379762E-04, 0.2458010895625246E-04, 0.1570954054223686E+00, 0.2480178686014861E-25, 0.5573684427056079E-04, 0.2879079609909993E-04, 0.5771888278451791E-01, 0.0000000000000000E+00, 0.4895501114079361E-04, 0.6615663653270374E-04, 0.2771650645038780E-01, 0.6559433690090112E-18, 0.2090848897194263E-03, 0.3843856621792604E-03, 0.1168397530048623E-02, 0.0000000000000000E+00, 0.2396113765895983E-02, 0.4353699886144585E-02, 0.8626671344136174E-03, 0.1420984816841217E-20, 0.3572874909786609E-04, 0.2591037812233495E-05}, + info: 0, + }, + { + z: []float64{0.7761482897976135E-01, 0.7690133527529974E-01, 0.8589697242168557E+00, 0.5718901484414876E+00, 0.8450349347421171E-01, 0.5688250545090190E+00, 0.6202247495663940E+00, 0.7388100008042665E+00, 0.9890328265375476E+00, 0.2969659976080158E+00, 0.5442392738534707E-01, 0.9562602329262000E+00, 0.8530135563879812E+00, 0.5471012261519459E-01, 0.9710076793297340E+00, 0.4869447961696205E+00, 0.4659851368281548E+00, 0.7647605444900396E-01, 0.7872766307526106E+00, 0.3237029299700311E+00, 0.7194522935712468E+00, 0.7270865543961295E+00, 0.5183429612108851E+00, 0.3145688411100903E+00, 0.9096514649777033E+00, 0.7816253592835525E+00, 0.4809049584349555E+00, 0.2052154618933422E-01, 0.1481963756328628E+00, 0.8742358520807045E+00, 0.4565878430880338E+00, 0.1977913919695908E+00, 0.6526813957349178E+00, 0.8032154703264597E+00, 0.2356108621359847E+00, 0.4857415898450358E+00, 0.2259727396620309E+00, 0.1176413330041139E+00, 0.8335507369731385E+00, 0.4539477133958770E+00, 0.8910876835374724E+00, 0.1559757847548392E+00, 0.1885199219441583E+00, 0.1520953639100613E+00, 0.6035948595957944E+00, 0.9286538294716984E+00, 0.9676298024186124E+00, 0.1209629819848071E+00, 0.1660874781174386E+00, 0.8622065054293394E+00, 0.7485077140876945E+00, 0.9420716698171637E+00, 0.2904751962009996E+00, 0.2180437045655230E+00, 0.6692025851955981E+00, 0.9258369042460884E+00, 0.6243742234586596E+00, 0.6760203577391158E+00, 0.2199572443863818E-02, 0.5981650670220221E+00, 0.8252506688545779E+00, 0.9433813762695346E+00, 0.5320093960532474E+00, 0.3846966829839934E+00, 0.6727780061271659E+00, 0.4937802596181958E+00, 0.1177802539787526E+00, 0.2963448754612064E-01, 0.2479547713122239E+00, 0.2694003173993550E+00, 0.8186090816580105E+00, 0.2886041049393229E-01, 0.7384561600560133E+00, 0.8345282295575730E+00, 0.1740871089016751E+00, 0.7946006936544379E+00, 0.5640836203667244E+00, 0.4951346622832815E+00, 0.4981407974176422E+00, 0.2513094341381288E+00, 0.4316077257561814E+00, 0.1685190107506288E+00, 0.3264570829830372E+00, 0.1676643753771256E-01}, + n: 21, + zOut: []float64{0.2309990065237698E+01, 0.2261037149894265E+01, 0.1946075797700671E+01, 0.1868880050926239E+01, 0.1838164096767709E+01, 0.1792848619787804E+01, 0.1601503570675395E+01, 0.1526383850720226E+01, 0.1395433670210245E+01, 0.1010109387319946E+01, 0.8644978203099237E+00, 0.7632668975571170E+00, 0.4552388959212355E+00, 0.4364144823342648E+00, 0.2696980874891977E+00, 0.1302983706884531E+00, 0.1278582769210706E+00, 0.7956979307866878E-01, 0.7389266586143965E-01, 0.8102308371415692E-02, 0.2690335013870282E-02, 0.5752609692135112E-13, 0.2842400234743069E-06, 0.1045980487121886E-05, 0.1601503570675395E+01, 0.1668093198756260E-18, 0.5190756964721459E-05, 0.2367180586416983E-05, 0.1526383850720226E+01, 0.1262177448353619E-27, 0.1974011051185169E-03, 0.4728862593194215E-03, 0.1395433670210245E+01, 0.2337388813815525E-19, 0.1632969150852556E-06, 0.4026698297028720E-06, 0.1010109387319946E+01, 0.3802651360818291E-21, 0.1380334146666910E-03, 0.1568641113059460E-03, 0.8644978203099237E+00, 0.2788260408793746E-19, 0.2076195419278686E+02, 0.2076195419278686E+02, 0.1070000000000000E+03, 0.3183673469387755E+01, 0.2803738317757009E+01, 0.1273578837393323E-04, 0.4552388959212355E+00, 0.1016579123433529E-20, 0.9426551662020599E-04, 0.5179870206653002E-04, 0.4364144823342648E+00, 0.7336406418555410E-28, 0.1112142557098828E-05, 0.1460057881679474E-05, 0.2696980874891977E+00, 0.8909623382378835E-18, 0.3232451044433717E-03, 0.3229988347563871E-03, 0.1302983706884531E+00, 0.0000000000000000E+00, 0.2867336104451064E-03, 0.2890982620847502E-03, 0.1278582769210706E+00, 0.6875938841518755E-23, 0.2127348925826359E-06, 0.9655734242129450E-07, 0.7956979307866878E-01, 0.3291208348307372E-17, 0.5717743824937758E-07, 0.2183606505996598E-06, 0.7389266586143965E-01, 0.7801771243763389E-24, 0.1012732311499954E-04, 0.2863554462185051E-05, 0.8102308371415692E-02, 0.5719241562852336E-29, 0.6292939995324734E-04, 0.3382281194073554E-04, 0.2690335013870282E-02, 0.4951522129891247E-25, 0.3008856418189283E-03, 0.2691027365699742E-03}, + info: 0, + }, + { + z: []float64{0.1834451937168287E+00, 0.4501020603239488E+00, 0.9673873583575473E+00, 0.2207688184907047E+00, 0.4205773270263516E+00, 0.6767264871143511E+00, 0.2493506785870784E+00, 0.7809638015955807E+00, 0.8297195492174936E+00, 0.1617611869044215E+00, 0.9206032300762146E+00, 0.1914715918877316E+00, 0.7976268296797403E+00, 0.9839522457816396E+00, 0.8841932579084628E+00, 0.6979540605797908E+00, 0.8049859576106227E+00, 0.8117504351099887E+00, 0.3842107296635322E+00, 0.6368881208030270E+00, 0.2369530469547876E+00, 0.8005533377467571E+00, 0.7105152962140180E+00, 0.5356376472112734E-02, 0.2192323464228777E+00, 0.8992715082939398E+00, 0.5988055508193698E+00, 0.4081645962203215E+00, 0.1002944447483383E+00, 0.1052431248059748E+00, 0.5730054733733171E+00, 0.2386396328544268E+00, 0.6503058109411604E+00, 0.9019164849722401E+00, 0.4702244241412763E+00, 0.5759947448793571E+00, 0.7588959717342861E+00, 0.4126392985506339E+00, 0.9987799941641187E+00, 0.5598172962702971E+00, 0.2151524348024290E+00, 0.7511708041336773E-01, 0.1539602741757972E+00, 0.4584191954304165E+00, 0.8937659116858414E+00, 0.6186897030318780E+00, 0.6386630452844105E+00, 0.9151803046984296E+00, 0.3614526997644965E+00, 0.9143967867261915E+00, 0.1523575506386343E+00, 0.9745493424336691E+00, 0.4149640117372425E+00, 0.7418302113477876E+00, 0.3041602774831942E-01, 0.4852660298208696E+00, 0.9115870107661288E+00, 0.9024516441581734E+00, 0.9201550825657324E+00, 0.5200815862126855E+00, 0.7353784634707106E+00, 0.8264932398040087E+00, 0.7035838297463828E+00, 0.6738634069153341E+00, 0.7657166064092835E-01, 0.4678396966074577E+00, 0.9927685693816569E+00, 0.5845157970225999E+00, 0.5638346985777254E+00, 0.5850492500516753E+00, 0.3856054034589584E+00, 0.8134648529141429E+00, 0.4174766661784889E+00, 0.3336151222017159E+00, 0.5355530597844248E+00, 0.9274106499154580E+00, 0.7442750408730826E+00, 0.2948331405701974E+00, 0.5696937454611060E+00, 0.3104181547964658E+00, 0.4694844160987418E+00, 0.1538578615150018E+00, 0.5969883537795497E+00, 0.3873507919637014E+00}, + n: 21, + zOut: []float64{0.2914952592069403E+01, 0.2353566179964282E+01, 0.2062119351173516E+01, 0.1965819938313762E+01, 0.1942714243081098E+01, 0.1812271492844174E+01, 0.1712144141310849E+01, 0.1666892005264074E+01, 0.1208030687686805E+01, 0.1159871012571561E+01, 0.9581193432281622E+00, 0.7738358894690665E+00, 0.7454032361827709E+00, 0.3901865930581417E+00, 0.3240765847275939E+00, 0.2173673669709887E+00, 0.1778074780703053E+00, 0.5660863840842725E-01, 0.3038731391621440E-01, 0.1466323002394464E-01, 0.7362797481955845E-02, 0.1496427221292385E-15, 0.2798385737764086E-17, 0.6348906733176861E-18, 0.1712144141310849E+01, 0.2625127144183791E-23, 0.5842516095868784E-15, 0.1699577922475928E-15, 0.1666892005264074E+01, 0.2934562567422164E-27, 0.7233314809955462E-13, 0.2286859678494404E-12, 0.1208030687686805E+01, 0.8467561517631538E-12, 0.2143114506868008E-08, 0.4305471816838367E-08, 0.1159871012571561E+01, 0.4930380657631324E-31, 0.3270528389239616E-07, 0.6410715811146478E-07, 0.9581193432281622E+00, 0.8911174733768286E-23, 0.2249420011581710E+02, 0.2249420011581710E+02, 0.1050000000000000E+03, 0.3197278911564626E+01, 0.2857142857142857E+01, 0.6896683202589802E-07, 0.7454032361827709E+00, 0.3255610023185390E-23, 0.5315428740895598E-04, 0.2875762635390457E-03, 0.3901865930581417E+00, 0.4610239445276015E-22, 0.9146669702187219E-04, 0.4183987855699404E-04, 0.3240765847275939E+00, 0.4688433862556419E-23, 0.8204008598914952E-05, 0.1523341313649621E-04, 0.2173673669709887E+00, 0.4570683409889788E-20, 0.9316307389873694E-05, 0.2741587710667867E-05, 0.1778074780703053E+00, 0.3706159570762342E-17, 0.9605798472890332E-04, 0.3099752510959849E-03, 0.5660863840842725E-01, 0.5638682600030866E-16, 0.1627758109301002E-02, 0.5977814903797443E-03, 0.3038731391621440E-01, 0.7161878634670464E-18, 0.4935537640644100E-05, 0.4281293465082162E-05, 0.1466323002394464E-01, 0.9343665470806783E-19, 0.1384059308707374E-05, 0.7139695062761456E-05, 0.7362797481955845E-02, 0.1252221392641006E-22, 0.1398979151771859E-02, 0.1830558814226920E-02}, + info: 0, + }, + { + z: []float64{0.1901253435444810E+00, 0.1005117877448146E+00, 0.7431497892893435E-02, 0.4180244733822649E+00, 0.5723993917742813E+00, 0.5092276894610764E+00, 0.6914570054828403E+00, 0.6343440208263138E+00, 0.9714240100252226E+00, 0.9708780190932921E+00, 0.7346948492781401E+00, 0.9261658900466149E+00, 0.6500321763704298E-01, 0.2101988980308164E+00, 0.2569765082490436E+00, 0.6872855071573251E+00, 0.7393915007490531E+00, 0.5293076476804583E+00, 0.5736721160165409E+00, 0.6249080544922647E+00, 0.1805969142240157E+00, 0.6235867578362418E+00, 0.3156395994838945E+00, 0.6768110107418109E+00, 0.5036038244498190E+00, 0.2096885591435443E+00, 0.2471056170621776E+00, 0.4420201221816504E+00, 0.5954916898507195E+00, 0.6849385183400085E+00, 0.6865376402638398E+00, 0.5015659601935997E+00, 0.9646916309223035E+00, 0.1976274617660123E+00, 0.6173831761654865E+00, 0.9161785290588952E+00, 0.8303766381148641E+00, 0.4163407208236638E+00, 0.2406183750735502E-01, 0.9033217043220854E+00, 0.3435327703530300E-01, 0.4851293431546745E+00, 0.1308952665690980E+00, 0.1639949900839996E+00, 0.6530528840204755E+00, 0.4007776795656349E+00, 0.6520732821596675E-01, 0.2482448577499247E+00, 0.6417548063561368E+00, 0.6287927677318972E+00, 0.2491821746122613E+00, 0.1309766085785375E+00, 0.1799023200797401E+00, 0.6166520678731939E+00, 0.4068347418426869E+00, 0.8022499378251485E+00, 0.2090643045880468E+00, 0.9552039287477454E-01, 0.3405285833145572E+00, 0.9010017729234689E+00, 0.8087026571264999E-01, 0.6784547103017031E+00, 0.5001579210546183E+00, 0.9044563563261202E+00, 0.6248337185292430E-01, 0.7231216956646513E+00, 0.3330924448715603E+00, 0.5906941805835393E+00, 0.6144619726434308E-01, 0.4494963607638514E-01, 0.5817524116985039E+00, 0.4323943825883398E+00, 0.9871518362913079E-01, 0.9577530955877981E+00, 0.7720928198042669E+00, 0.1473259710759589E+00, 0.7227644962870149E+00, 0.9964485210410867E+00, 0.3235582385765219E+00, 0.5984954533580267E-01, 0.1531719633524309E-01, 0.8969070444410814E+00, 0.8320043732823273E+00, 0.7541623800831910E+00}, + n: 21, + zOut: []float64{0.2943190889471759E+01, 0.2404733889291933E+01, 0.2164120218254414E+01, 0.2101040443717650E+01, 0.1828309865967689E+01, 0.1647179310188885E+01, 0.1393092850251358E+01, 0.1217421086377993E+01, 0.1157068329170861E+01, 0.9693609911235493E+00, 0.7556225164779018E+00, 0.6051010122910800E+00, 0.5244111548905432E+00, 0.4204021043595824E+00, 0.3294230503008973E+00, 0.2905705444026201E+00, 0.1318042053167392E+00, 0.6748792703931331E-01, 0.3115549452672914E-01, 0.3850968595106850E-02, 0.1766035472385010E-05, 0.2996366283941816E-12, 0.8018633237482923E-17, 0.2249911398990393E-16, 0.1393092850251358E+01, 0.8588781736260544E-19, 0.1768526861021460E-14, 0.8068659675231548E-15, 0.1217421086377993E+01, 0.2465190328815662E-30, 0.6841595655394777E-14, 0.1344694857995563E-13, 0.1157068329170861E+01, 0.2714422906896024E-19, 0.9771202940807984E-13, 0.1895423136689650E-12, 0.9693609911235493E+00, 0.1093011646009194E-15, 0.5148224565067754E-11, 0.9904113235317579E-11, 0.7556225164779018E+00, 0.6752649348691861E-27, 0.2098534861805207E+02, 0.2098534861805208E+02, 0.9600000000000000E+02, 0.2832199546485261E+01, 0.2083333333333333E+01, 0.3437245789676428E-09, 0.5244111548905432E+00, 0.2665011951551765E-23, 0.6566411319039389E-08, 0.3635282930812000E-08, 0.4204021043595824E+00, 0.1249353725478346E-22, 0.6690013285699780E-07, 0.1185995569029548E-06, 0.3294230503008973E+00, 0.3250106929510569E-26, 0.6264577969246473E-06, 0.1086745069147475E-05, 0.2905705444026201E+00, 0.1121066009627684E-24, 0.5553814969713904E-05, 0.9554866377781883E-05, 0.1318042053167392E+00, 0.1875595688253478E-25, 0.3215548179944659E-03, 0.4036498498040293E-03, 0.6748792703931331E-01, 0.4043956767801041E-20, 0.1191830515693705E-02, 0.1851908589351717E-02, 0.3115549452672914E-01, 0.1124126789939942E-28, 0.7898349055483677E-03, 0.3617649115749287E-02, 0.3850968595106850E-02, 0.4455486392688275E-26, 0.3971779475237804E-01, 0.1814591379891354E-01, 0.1766035472385010E-05, 0.2780981219403279E-20, 0.1014029004767683E-01, 0.8718057102094371E-02}, + info: 0, + }, + { + z: []float64{0.3437994630115073E+00, 0.2969584004763312E+00, 0.5428789456218400E+00, 0.3643219910857877E+00, 0.8842011736515154E-01, 0.4426793535323088E+00, 0.9851327949196382E+00, 0.9928836193844874E+00, 0.9294888334528270E+00, 0.5131906939013953E+00, 0.8372743749579292E-01, 0.3799113781856175E+00, 0.9980979619320958E+00, 0.1940068951405882E+00, 0.1265916571930514E+00, 0.7533120158726621E+00, 0.7604310151358937E+00, 0.9521608240404056E-01, 0.6048411980078113E+00, 0.8887307551694945E-01, 0.9109406880842844E+00, 0.9457532858494480E+00, 0.7192031611135805E+00, 0.5051759890546635E+00, 0.1927673350758418E+00, 0.6784576615085791E+00, 0.4582307655806892E+00, 0.4110913566635671E+00, 0.5843861752552199E+00, 0.1849014446101248E+00, 0.5286425989283670E+00, 0.9425316584065953E+00, 0.9757360470900053E+00, 0.4697986765545260E+00, 0.5423082602059015E-01, 0.4516134263086808E+00, 0.2022962345269688E+00, 0.4899666677522230E-01, 0.9657583521001409E+00, 0.7147044884479304E+00, 0.8698989147298346E+00, 0.1620630683580001E+00, 0.4917083507892124E+00, 0.6587971895356357E+00, 0.2830046270176211E+00, 0.8907428232631098E-01, 0.3385480253038764E-01, 0.3808208973559474E+00, 0.6301790073720519E+00, 0.7283330529106518E+00, 0.8754045015579843E+00, 0.5691786300850922E+00, 0.2221459247333947E+00, 0.3807253530058278E+00, 0.5099681617674874E+00, 0.8815981352292609E+00, 0.2670679959789202E-02, 0.3061419069919761E+00, 0.9088634553510815E+00, 0.3137439308670030E+00, 0.3256630871489109E+00, 0.7397175549546020E-01, 0.8600700672393357E+00, 0.2944165267259768E-01, 0.1962740610392520E+00, 0.7223088666910011E+00, 0.1555262415199788E+00, 0.7683934132272936E+00, 0.9837306979871404E+00, 0.4307236017454147E+00, 0.2763099157748476E+00, 0.5623054633156477E-01, 0.1414438705425911E+00, 0.3910643421231946E+00, 0.3414855836828583E+00, 0.4833767934540261E+00, 0.1874948602631823E+00, 0.6456680649630069E+00, 0.5377739930676261E+00, 0.4911199998049517E+00, 0.3925147326457343E+00, 0.1205990368593943E+00, 0.6208170182205421E+00, 0.4308681300066786E+00}, + n: 21, + zOut: []float64{0.2838978926644850E+01, 0.2478331275466363E+01, 0.2456585262660691E+01, 0.2180185738821122E+01, 0.1712066680562540E+01, 0.1602701074250422E+01, 0.1503969746560551E+01, 0.1233768461187729E+01, 0.9787455830966086E+00, 0.9668289373592873E+00, 0.7729605529095109E+00, 0.7035556930615693E+00, 0.5295938697567051E+00, 0.4165425267136870E+00, 0.3781386605204551E+00, 0.3701077812928417E+00, 0.1575477292510020E+00, 0.7328369731218511E-01, 0.3974472017556452E-01, 0.4256064253578745E-02, 0.1985700463370783E-02, 0.0000000000000000E+00, 0.2182718854229073E-04, 0.3091215918753839E-04, 0.1503969746560551E+01, 0.7889046064910921E-15, 0.8525655623819580E-10, 0.5987167574554257E-09, 0.1233768461187729E+01, 0.1850899338648654E-19, 0.6965867087478826E-06, 0.6532556049979120E-06, 0.9787455830966086E+00, 0.3101927297073854E-24, 0.3608646891594891E-06, 0.2907657476508735E-06, 0.9668289373592873E+00, 0.5936688180990121E-20, 0.1421522625242826E-07, 0.7063390122609291E-08, 0.7729605529095109E+00, 0.1231338578304599E-17, 0.2139987868232064E+02, 0.2139987868232063E+02, 0.9600000000000000E+02, 0.2854875283446712E+01, 0.2083333333333333E+01, 0.2575545978160743E-06, 0.5295938697567051E+00, 0.8537368260663878E-24, 0.6647760383095535E-05, 0.6726768703723720E-05, 0.4165425267136870E+00, 0.5898327163094257E-18, 0.6007815560144262E-05, 0.6070984870789135E-05, 0.3781386605204551E+00, 0.1932242212135588E-23, 0.5780348596252855E-05, 0.5727260717649887E-05, 0.3701077812928417E+00, 0.2291245128765917E-16, 0.5589406660782675E-05, 0.5617175435749363E-05, 0.1575477292510020E+00, 0.3855952104720306E-26, 0.8404567502440466E-05, 0.1060626986994499E-04, 0.7328369731218511E-01, 0.1176980470589750E-26, 0.3402042835087641E-05, 0.5518338211116594E-05, 0.3974472017556452E-01, 0.3697785493223493E-30, 0.6423930978115149E-05, 0.5690659965930955E-05, 0.4256064253578745E-02, 0.1813010266067178E-20, 0.3330330670135602E-05, 0.3509207052336586E-05, 0.1985700463370783E-02, 0.9911627066431288E-23, 0.2656536456367949E-04, 0.9644853918428974E-05}, + info: 0, + }, + { + z: []float64{0.6087347824331316E+00, 0.2344592930815549E+00, 0.1839180152431182E+00, 0.8946895357068063E-01, 0.3789275576065679E+00, 0.1028144130339237E-01, 0.8432962228323871E+00, 0.5720035990048252E+00, 0.9674750777949459E+00, 0.1387850858951470E+00, 0.1049983295079311E+00, 0.1869597635484084E+00, 0.2049847474830355E+00, 0.9353902309354832E+00, 0.7711597045807418E+00, 0.6677931698783810E+00, 0.5710020050743191E+00, 0.7559352115290241E+00, 0.8799700817290574E+00, 0.2989086447618220E+00, 0.7223221852829088E+00, 0.9172044263776469E-01, 0.8222766733565161E+00, 0.4357755436106698E+00, 0.3174399370719186E+00, 0.3716323007311311E+00, 0.5710261889832198E+00, 0.5875728000816982E-01, 0.1970825867540514E+00, 0.7514821290356389E+00, 0.4768968814440278E+00, 0.1414806690779697E+00, 0.5126469713172739E+00, 0.2618595999903317E-01, 0.3414455658478163E+00, 0.7845736413672471E+00, 0.3193997824316201E+00, 0.5244207174429636E+00, 0.7114985438553419E+00, 0.6380953409710879E+00, 0.5110544105167975E+00, 0.6987353947091863E+00, 0.2359552404464268E+00, 0.1389779414569779E+00, 0.4283565484470430E+00, 0.5978343235372734E+00, 0.8941068622870674E+00, 0.9993918591572127E+00, 0.9276104816334276E+00, 0.6840640077048410E+00, 0.1906252952212643E+00, 0.3896055694019390E+00, 0.8889540838698040E-01, 0.6972017776398595E+00, 0.7403854978121883E+00, 0.9624319129844994E-01, 0.7107468555423346E-01, 0.2167351328914763E+00, 0.5250363507339506E-01, 0.3012298012035964E+00, 0.7467053513110199E+00, 0.6311877906561809E+00, 0.6465457722939830E+00, 0.9462483307457270E-01, 0.1615629644808589E+00, 0.3714392567485900E+00, 0.5909086992570731E+00, 0.2147078824711308E+00, 0.8083150503324107E+00, 0.1136496291628873E+00, 0.3556622878263437E+00, 0.1687673308056986E+00, 0.2663369573375586E+00, 0.9992292880074174E+00, 0.4743706799728067E+00, 0.3784791276003248E+00, 0.9641428139214289E+00, 0.4526980047510465E-01, 0.5291384859598749E+00, 0.9114927597067145E+00, 0.2015740390806801E+00, 0.9111109510473957E+00, 0.4797378470164849E+00, 0.4344842342843944E+00}, + n: 21, + zOut: []float64{0.2535248843080872E+01, 0.2027297538476471E+01, 0.1999341423958793E+01, 0.1905819580237666E+01, 0.1558994176508815E+01, 0.1443542425236611E+01, 0.1321312714967014E+01, 0.1044341128979687E+01, 0.9175998827905956E+00, 0.8543653487373744E+00, 0.6128068085852322E+00, 0.5723484802692980E+00, 0.4865842293721045E+00, 0.4743009418296827E+00, 0.4424121716041568E+00, 0.2157744105271115E+00, 0.1401155020588904E+00, 0.9545054691199920E-01, 0.4846378139764250E-01, 0.2597131641839770E-01, 0.9574417588705024E-02, 0.7983827718913915E-23, 0.5897957913656464E-08, 0.4905965358471980E-08, 0.1321312714967014E+01, 0.1437620113674772E-24, 0.2330664696165742E-08, 0.2036082149427908E-08, 0.1044341128979687E+01, 0.7099748146989106E-29, 0.1191493821660667E-08, 0.1294122655697948E-08, 0.9175998827905956E+00, 0.7069460558567906E-16, 0.2320495180901029E-08, 0.3242686959161780E-08, 0.8543653487373744E+00, 0.3414430154917050E-13, 0.2143028595220802E-07, 0.3181347787023606E-07, 0.6128068085852322E+00, 0.0000000000000000E+00, 0.1873166566953712E+02, 0.1873166566953712E+02, 0.1040000000000000E+03, 0.3224489795918367E+01, 0.2884615384615385E+01, 0.3533200143891392E-06, 0.4865842293721045E+00, 0.4552522969733916E-17, 0.1776353409716398E-09, 0.6419018055060889E-09, 0.4743009418296827E+00, 0.4679164786798698E-18, 0.4782181507340309E-06, 0.1264406900548246E-06, 0.4424121716041568E+00, 0.1728289684559415E-20, 0.3046857378867568E-04, 0.2182730305393890E-04, 0.2157744105271115E+00, 0.1120182485413837E-27, 0.4003877877583194E-03, 0.2588513428463001E-03, 0.1401155020588904E+00, 0.0000000000000000E+00, 0.6916990427934659E-04, 0.5501406364660823E-04, 0.9545054691199920E-01, 0.6162975822039155E-32, 0.1059944134272042E-03, 0.1421052287262650E-03, 0.4846378139764250E-01, 0.1755514705909767E-17, 0.4499204819889415E-04, 0.2567010249779503E-03, 0.2597131641839770E-01, 0.1143848312570467E-28, 0.5289175880660015E-04, 0.5437725505075631E-04, 0.9574417588705024E-02, 0.3697785493223493E-31, 0.2606391166909807E-05, 0.6294847321319143E-06}, + info: 0, + }, + { + z: []float64{0.3257261020965838E+00, 0.9499222527145429E+00, 0.3597416524070001E+00, 0.7608369220069154E+00, 0.3348964244425234E-01, 0.9918240230913730E+00, 0.2435073049094116E-01, 0.2927090414647138E-01, 0.2724578324033788E+00, 0.7486167980650003E+00, 0.2854897136111678E+00, 0.2267361867398041E+00, 0.4294380831801550E+00, 0.7722184192395405E+00, 0.5889718788171796E+00, 0.5201154937785833E+00, 0.1341644467607439E-01, 0.3251983707424297E+00, 0.3712514383296180E+00, 0.8346822920283823E+00, 0.2613611110008908E+00, 0.7377020224374462E+00, 0.4290238209924468E-01, 0.8422463567888154E+00, 0.1390406385354674E+00, 0.8899155813346852E+00, 0.5366293959824918E+00, 0.1311808378334547E+00, 0.5127829646320820E+00, 0.3806825827063995E+00, 0.9008244723505014E+00, 0.8397173164045483E+00, 0.8005434668537068E+00, 0.4188784622408616E+00, 0.4815341947551696E+00, 0.2004130034689415E+00, 0.9620560381224039E+00, 0.9936712626034268E+00, 0.7996240982628953E+00, 0.9066259300527590E+00, 0.7119745510778175E+00, 0.4009593231138309E+00, 0.7503038869147766E+00, 0.2307657656692345E+00, 0.5796381959344894E+00, 0.4564585857276309E+00, 0.3087632483431468E-01, 0.4925813444884515E+00, 0.2548189626174928E+00, 0.7548007003619551E+00, 0.2595357873879023E+00, 0.2576161595637174E+00, 0.6530834734960895E+00, 0.9659056802808288E+00, 0.4073417244577716E+00, 0.7973054858347279E+00, 0.1098542135402614E-03, 0.5270152208809449E+00, 0.9503221531609122E+00, 0.3389760481404548E+00, 0.2936463197963648E+00, 0.1532837593240226E+00, 0.7039965742744211E+00, 0.1538522429841973E+00, 0.4565500206514618E+00, 0.4890306322657354E+00, 0.7406911389536464E+00, 0.4609110724077861E+00, 0.3010957214922741E+00, 0.4706875322819619E+00, 0.9245411658881026E+00, 0.1225486958523536E-02, 0.7513538867599376E+00, 0.7480092012350148E+00, 0.1668544624863488E+00, 0.6027497133760584E+00, 0.4060848284780354E+00, 0.7777661676033926E+00, 0.5476587806685121E+00, 0.3318235867866506E+00, 0.4865355710680780E+00, 0.9789804028805801E+00, 0.6449091593541079E-01, 0.3386899175207851E+00}, + n: 21, + zOut: []float64{0.2916446272919928E+01, 0.2518523111789073E+01, 0.1881620740030630E+01, 0.1802535552376618E+01, 0.1705712498790935E+01, 0.1630934300031556E+01, 0.1493206464268041E+01, 0.1289863129801601E+01, 0.1141879970494692E+01, 0.1064939765404915E+01, 0.9148995873510519E+00, 0.6667419164223021E+00, 0.5793746811807822E+00, 0.5763823737203533E+00, 0.5577209455074719E+00, 0.2258972104173268E+00, 0.1775772659782911E+00, 0.1224839196229167E+00, 0.7643325286481288E-01, 0.1088888144792382E-01, 0.1013218159024319E-07, 0.1529626957613473E-16, 0.4760904670371191E-26, 0.1685698503770275E-25, 0.1493206464268041E+01, 0.4740164255731978E-15, 0.6203207773025231E-22, 0.1697026618649852E-21, 0.1289863129801601E+01, 0.1555744028694447E-17, 0.2220966892754199E-18, 0.8352563633635413E-19, 0.1141879970494692E+01, 0.8283039504820624E-29, 0.9137114046044313E-17, 0.2186983724354431E-16, 0.1064939765404915E+01, 0.7560947786617519E-24, 0.1476623491156538E-14, 0.6521525514986541E-15, 0.9148995873510519E+00, 0.3956572890903056E-23, 0.2135406185055340E+02, 0.2135406185055340E+02, 0.1110000000000000E+03, 0.3462585034013606E+01, 0.7207207207207207E+01, 0.3107640874581820E-11, 0.5793746811807822E+00, 0.0000000000000000E+00, 0.5611258671513064E-10, 0.1000932867794445E-09, 0.5763823737203533E+00, 0.2935229715008717E-19, 0.5869279282596528E-09, 0.3232392517855140E-09, 0.5577209455074719E+00, 0.7161080495560552E-17, 0.6771347567635994E-08, 0.1273942735381484E-07, 0.2258972104173268E+00, 0.2531843062293473E-19, 0.3233128964696781E-05, 0.1839431244951091E-05, 0.1775772659782911E+00, 0.1025519176787315E-28, 0.1632093348006395E-04, 0.1394944946706296E-04, 0.1224839196229167E+00, 0.3147671031182890E-20, 0.4090539240175316E-04, 0.3499438731982919E-04, 0.7643325286481288E-01, 0.4418024966021139E-23, 0.7751221398283570E-04, 0.6522231732461535E-04, 0.1088888144792382E-01, 0.0000000000000000E+00, 0.1168516922729128E-02, 0.6798960389683572E-03, 0.1013218159024319E-07, 0.8311253061997563E-15, 0.2266806408535672E-02, 0.8228900118596701E-02}, + info: 0, + }, + { + z: []float64{0.9013837094783728E-01, 0.4093071371456288E+00, 0.7563443593246222E-01, 0.6047712831067179E+00, 0.3616734158068488E+00, 0.3179352368154293E+00, 0.4877726790168605E+00, 0.7283754332956183E+00, 0.6564126870433257E+00, 0.7426267273836333E+00, 0.9575970808689874E+00, 0.2328163542816707E+00, 0.9804488839127946E+00, 0.5880329556580101E+00, 0.6720101508999355E+00, 0.3029641470022006E+00, 0.9176198736416905E+00, 0.9273523415722473E-01, 0.7356501689695268E+00, 0.3516482504433937E+00, 0.5613309946663773E+00, 0.8064085547776983E+00, 0.2421909924481950E+00, 0.4321291285180304E+00, 0.7195726435630079E+00, 0.4201959590716675E-01, 0.6971840239025084E-03, 0.6931587576362976E+00, 0.4512374813335629E+00, 0.9105433528826555E+00, 0.8233348499205092E+00, 0.5270028711667427E+00, 0.5092902528068642E+00, 0.6527825111058926E+00, 0.8077059946216197E+00, 0.5037249441803524E+00, 0.7474524841642615E+00, 0.8361353459662745E+00, 0.6675800963161582E+00, 0.5004244151247563E+00, 0.7976263900002633E+00, 0.1983499023889042E+00, 0.7522366994446783E+00, 0.3654861843844912E+00, 0.8247542543249066E+00, 0.9124235995852386E+00, 0.1818459043196227E+00, 0.8196813052173683E+00, 0.5538880208895494E+00, 0.9080443570480472E+00, 0.2981632101337024E+00, 0.6044133722200155E+00, 0.1883025355842233E+00, 0.2434431972046255E+00, 0.3420561860884004E+00, 0.3312086041097358E+00, 0.8261796050670067E-01, 0.2597483126975232E+00, 0.9037350022806145E+00, 0.5691251256015616E+00, 0.5433137600205407E-01, 0.2948423088781353E+00, 0.7125818959241866E+00, 0.1168360183447441E+00, 0.2271931321361120E-01, 0.5832011197836875E+00, 0.4321285977614958E+00, 0.9214755199664483E+00, 0.2929460789941122E+00, 0.9911839954873096E+00, 0.9352897353900299E+00, 0.6549195608155846E+00, 0.7733376794047198E-01, 0.7345459966842849E+00, 0.2997108680399072E+00, 0.6923968300089707E+00, 0.9895794156524929E+00, 0.2694202749089550E+00, 0.2419924375765692E-01, 0.2728256718882756E+00, 0.7688978378093437E+00, 0.6794051971520565E-01, 0.8211384369868754E+00, 0.7581877817293103E-01}, + n: 21, + zOut: []float64{0.2587082763537058E+01, 0.2518438946693926E+01, 0.2381638511714923E+01, 0.2064758819607097E+01, 0.1861546331198453E+01, 0.1823771413694203E+01, 0.1462413605342042E+01, 0.1295483717305927E+01, 0.1204792654692795E+01, 0.1153126691944095E+01, 0.9646786889507554E+00, 0.8876075724637406E+00, 0.7328920239265601E+00, 0.5128961040525114E+00, 0.4187721082034697E+00, 0.3198505150609477E+00, 0.1661143074789019E+00, 0.1249876230738883E+00, 0.5554047196429147E-01, 0.2079344839078052E-02, 0.4713171572265143E-04, 0.1874281408120013E-19, 0.2104034717604745E-09, 0.2619972849686678E-09, 0.1462413605342042E+01, 0.9259545558536950E-18, 0.2890370685025388E-10, 0.3242632456342165E-10, 0.1295483717305927E+01, 0.1323488980084844E-22, 0.2279224462592833E-10, 0.2555931367214743E-10, 0.1204792654692795E+01, 0.2978738778114541E-26, 0.7485181957332586E-10, 0.4566030880095840E-10, 0.1153126691944095E+01, 0.6733803272339514E-21, 0.2633277318950464E-08, 0.1440235383519861E-08, 0.9646786889507554E+00, 0.7499216124683276E-17, 0.2253851934746039E+02, 0.2253851934746038E+02, 0.1040000000000000E+03, 0.3111111111111111E+01, 0.5769230769230769E+01, 0.2633869415622400E-06, 0.7328920239265601E+00, 0.6980417424693642E-13, 0.1603044445805627E-06, 0.1255532606981617E-06, 0.5128961040525114E+00, 0.6981404369947554E-21, 0.8484909168369356E-07, 0.7367232980661418E-07, 0.4187721082034697E+00, 0.2465190328815662E-30, 0.1470967366725541E-06, 0.2274394647752198E-06, 0.3198505150609477E+00, 0.9424343740971753E-25, 0.8932721831570202E-05, 0.5259727349591482E-05, 0.1661143074789019E+00, 0.1697763391846713E-18, 0.4712327641645974E-05, 0.7305995006514358E-05, 0.1249876230738883E+00, 0.9266645908481002E-19, 0.3596318120009657E-04, 0.2001742175196116E-04, 0.5554047196429147E-01, 0.5985976337495067E-16, 0.4811066675748340E-03, 0.3416912105856511E-03, 0.2079344839078052E-02, 0.8697917232094458E-24, 0.5710266423841766E-02, 0.2981491759065521E-02, 0.4713171572265143E-04, 0.0000000000000000E+00, 0.3288287603570621E-02, 0.1038987759212308E-02}, + info: 0, + }, + { + z: []float64{0.3453921918700114E+00, 0.8256584009865165E+00, 0.5027306146870630E+00, 0.5014619412470180E+00, 0.9910264683396075E+00, 0.7385152238869899E+00, 0.9936695869989243E+00, 0.6206355260490602E+00, 0.6835539321104728E+00, 0.3987727521414011E+00, 0.2155721742355131E+00, 0.8212295891891395E+00, 0.7021626430853991E+00, 0.3753314442932942E+00, 0.2575710525141791E+00, 0.6551328468445583E+00, 0.3738398426943970E+00, 0.8805730558289802E+00, 0.6848909798416613E+00, 0.5520069040756137E-01, 0.8817067703079440E+00, 0.3238117712584516E+00, 0.1001825089826291E+00, 0.7369585910327309E+00, 0.7601318359400422E+00, 0.4312449588193277E+00, 0.4932891154015395E+00, 0.1099211239093930E+00, 0.5764729343614433E+00, 0.1286539516629047E+00, 0.5170000684627285E+00, 0.4006756226519864E+00, 0.5897018197291505E+00, 0.3774659871747915E+00, 0.4211183018281148E+00, 0.6260997273722376E+00, 0.7810234892670644E+00, 0.9934154489086249E+00, 0.5116204079460294E+00, 0.7948452919719275E+00, 0.5998807734230309E+00, 0.4868691071952969E-01, 0.7977221292955683E+00, 0.4907992372099745E+00, 0.4337635562764541E-01, 0.4865658084478622E+00, 0.7887982210525304E+00, 0.6218441262679077E+00, 0.1807768964120138E-01, 0.7341707407508724E+00, 0.4738048273586776E+00, 0.9324751870816922E+00, 0.4643019354540665E+00, 0.2401905271601299E+00, 0.6072757133952530E+00, 0.6257046236339610E+00, 0.1662572295885112E-01, 0.3360107439465247E+00, 0.5925152832499899E+00, 0.4206234399601897E+00, 0.1828405120649758E+00, 0.8923354266778754E+00, 0.6211472795399554E+00, 0.3215240169291051E+00, 0.3967102459115966E+00, 0.4376502563326659E+00, 0.4571232280132043E-01, 0.2973405440159681E+00, 0.1737124961451384E+00, 0.1123665207380958E+00, 0.8069742345287393E+00, 0.5302931605046994E+00, 0.2541675285808478E+00, 0.9099997182043015E+00, 0.7562530283478575E-01, 0.2521110146593245E+00, 0.2525672524245413E+00, 0.8930826245328107E+00, 0.8545394186204489E+00, 0.1856025965008533E+00, 0.8541401621096930E+00, 0.7406868214039234E+00, 0.5851270108744718E+00, 0.7554853143122133E+00}, + n: 21, + zOut: []float64{0.2818806710434786E+01, 0.2596766072486540E+01, 0.2041400548479265E+01, 0.1919012388179902E+01, 0.1900863080415201E+01, 0.1778136512482050E+01, 0.1649297429111022E+01, 0.1375943901620400E+01, 0.1287933944237744E+01, 0.1246950647018126E+01, 0.9346701076388835E+00, 0.8619836761278706E+00, 0.6928534822715838E+00, 0.5816592049742084E+00, 0.4759893592204403E+00, 0.2537953742738920E+00, 0.2205935192530503E+00, 0.8350022078832350E-01, 0.3307087507037688E-01, 0.2105652896299196E-01, 0.3857874617179747E-02, 0.9177981866196648E-17, 0.6043035417783778E-14, 0.7682115486038763E-14, 0.1649297429111022E+01, 0.9047287949798740E-23, 0.2120842457393041E-14, 0.2617862539054627E-14, 0.1375943901620400E+01, 0.1499552906513639E-17, 0.3376573256769321E-15, 0.2886563968474245E-15, 0.1287933944237744E+01, 0.1966621906344823E-17, 0.2937881411718043E-15, 0.4577311861870994E-15, 0.1246950647018126E+01, 0.2742371736879744E-17, 0.2913637797754287E-14, 0.1483948533056680E-14, 0.9346701076388835E+00, 0.5800058106323822E-18, 0.2277814145766384E+02, 0.2277814145766384E+02, 0.9800000000000000E+02, 0.2997732426303855E+01, 0.1020408163265306E+01, 0.9030119244814722E-12, 0.6928534822715838E+00, 0.1471303281095442E-16, 0.2634125396797654E-10, 0.5071585384120369E-10, 0.5816592049742084E+00, 0.1365675999118616E-25, 0.3358753759221612E-09, 0.6258446588335648E-09, 0.4759893592204403E+00, 0.1479114197289397E-30, 0.3734630956704811E-08, 0.6716634735981551E-08, 0.2537953742738920E+00, 0.7467396771867359E-25, 0.3072344915986320E-06, 0.1829961043616119E-06, 0.2205935192530503E+00, 0.4437342591868191E-30, 0.2385309167517414E-05, 0.3978543929472447E-05, 0.8350022078832350E-01, 0.2436129622029919E-19, 0.4589207629691226E-04, 0.2836221395611648E-04, 0.3307087507037688E-01, 0.3081487911019577E-32, 0.1362072635971665E-04, 0.2978962617014088E-04, 0.2105652896299196E-01, 0.2711709361697228E-30, 0.2444625596237189E-05, 0.7827983423195974E-05, 0.3857874617179747E-02, 0.8925769947935872E-20, 0.9826965253502863E-02, 0.1259209175531780E-01}, + info: 0, + }, + { + z: []float64{0.9560856702670685E+00, 0.5885863857778361E+00, 0.8071258175651005E+00, 0.5175476341605639E+00, 0.1941426739297742E+00, 0.8451490614471896E+00, 0.9052305950784733E+00, 0.6791526261185319E+00, 0.6480230038264980E+00, 0.8438040949137990E+00, 0.3034844043967853E+00, 0.3090582723248356E+00, 0.3282769832503399E+00, 0.7489751201458807E+00, 0.6672021557248126E+00, 0.1697989591956236E+00, 0.5723860504781838E+00, 0.3660621222567975E+00, 0.1505291330148173E-01, 0.7436839329892437E+00, 0.3679212455376497E+00, 0.5305714072096270E+00, 0.5792221354999488E+00, 0.3031533452885045E+00, 0.9514596930492207E+00, 0.3278419583960311E+00, 0.5742176036064726E+00, 0.7216680447710266E+00, 0.6608941225668634E+00, 0.3887216422692293E+00, 0.6952172825541724E+00, 0.8072929471269218E+00, 0.8776672848787970E-01, 0.9363773133978057E+00, 0.3470717327786855E+00, 0.9438495003134180E+00, 0.5511880105145929E+00, 0.5826637033513504E+00, 0.3416802173197317E+00, 0.5650234571673005E+00, 0.2927187699119284E+00, 0.4936451925034285E+00, 0.7496439056333554E+00, 0.8462697295115110E+00, 0.4661250827466905E+00, 0.3912590593193351E+00, 0.9140228064649625E+00, 0.4016314378444454E+00, 0.7105479239000361E+00, 0.3751330850058705E+00, 0.7309804928539319E+00, 0.1378037023247644E+00, 0.7527056268407295E+00, 0.1640478774378548E+00, 0.6030857470066908E+00, 0.7427119073248016E+00, 0.9996405952923426E-01, 0.7406467144237725E+00, 0.3762498316380406E+00, 0.8295145255291534E+00, 0.8322845800948830E-01, 0.6101670185797291E+00, 0.9451596878306588E+00, 0.1176379504958335E+00, 0.7940514845464750E+00, 0.3068100097277620E+00, 0.2371282369406802E+00, 0.2163781309135768E+00, 0.4705542393165623E+00, 0.4003463805482307E+00, 0.2731285781388088E+00, 0.8862626881898287E+00, 0.5854390777280626E+00, 0.4661955367614972E+00, 0.1993415035442425E+00, 0.9213995968359628E+00, 0.1542739762296447E+00, 0.9419076789558214E+00, 0.9611493561784724E+00, 0.7596360150269755E+00, 0.6590873675145426E+00, 0.3894853423829039E+00, 0.8407621320868611E+00, 0.4517123559923821E+00}, + n: 21, + zOut: []float64{0.2583735261373388E+01, 0.2239759728480232E+01, 0.2157858012928955E+01, 0.2146305201359927E+01, 0.1853050031878152E+01, 0.1788497392649839E+01, 0.1558387970436693E+01, 0.1494017846927041E+01, 0.1323723239351723E+01, 0.1188003233397794E+01, 0.9827022795744828E+00, 0.8335582164080391E+00, 0.7854672559750093E+00, 0.6236176061997519E+00, 0.4677974993044671E+00, 0.2968385185647548E+00, 0.2304456569541352E+00, 0.1793008998018142E+00, 0.2471364396669566E-01, 0.7537422761275628E-02, 0.3241997301555496E-04, 0.1184063810429910E-21, 0.1281976731077423E-10, 0.2849227344309828E-10, 0.1558387970436693E+01, 0.3001369155282220E-19, 0.2940080271049715E-08, 0.1685793775386140E-08, 0.1494017846927041E+01, 0.1696366490587264E-24, 0.4557030850938984E-08, 0.5166797185591864E-08, 0.1323723239351723E+01, 0.1862197338326049E-12, 0.1908610209474282E-08, 0.1816527091730617E-08, 0.1188003233397794E+01, 0.1613415991578665E-17, 0.2801618631477443E-08, 0.2177314380835442E-08, 0.9827022795744828E+00, 0.1073695634537585E-17, 0.2276534933826718E+02, 0.2276534933826718E+02, 0.1060000000000000E+03, 0.3113378684807256E+01, 0.3773584905660377E+01, 0.2107018980320373E-07, 0.7854672559750093E+00, 0.7395570986446986E-31, 0.5134101120680572E-07, 0.6949862017183880E-07, 0.6236176061997519E+00, 0.1700003115737185E-12, 0.4917011909790346E-06, 0.6444201346122313E-06, 0.4677974993044671E+00, 0.1676329423594650E-29, 0.2178752696080751E-05, 0.1697685142168825E-05, 0.2968385185647548E+00, 0.2903323170704433E-20, 0.9062193610690628E-05, 0.7062135859641892E-05, 0.2304456569541352E+00, 0.9860761315262648E-30, 0.1460945060339096E-04, 0.1904220434906198E-04, 0.1793008998018142E+00, 0.4606947686490709E-27, 0.4451684144215141E-07, 0.1728984935219646E-06, 0.2471364396669566E-01, 0.1407327854914285E-26, 0.1942342839475662E-02, 0.3052712133602924E-02, 0.7537422761275628E-02, 0.9865964111678957E-20, 0.3214451590395407E-02, 0.5215635567340069E-02, 0.3241997301555496E-04, 0.0000000000000000E+00, 0.1184307710713820E-01, 0.9427403294935964E-02}, + info: 0, + }, + { + z: []float64{0.4101594051788160E+00, 0.1002974419660251E+00, 0.8434067081152193E+00, 0.7258916354493068E+00, 0.9256853341957688E+00, 0.8379265467529036E+00, 0.1564408324797836E+00, 0.8292039738515364E+00, 0.3771190822561328E+00, 0.8236097732630416E+00, 0.3320638300046872E+00, 0.6850750205938005E-01, 0.5616647045816037E+00, 0.8305938719521835E+00, 0.6006351465721590E+00, 0.8469146468608777E+00, 0.1179160781320751E+00, 0.6975716721259332E+00, 0.3237957597653003E+00, 0.1297318227605904E-01, 0.8416519209661123E+00, 0.2623987624579764E+00, 0.3323289069826861E+00, 0.9848995259497869E+00, 0.1295798367899781E-01, 0.4196318718239949E+00, 0.8791346827157692E+00, 0.9015205418757779E+00, 0.2557984197164971E+00, 0.7295221077613672E+00, 0.8796719157178668E+00, 0.6983240767110626E+00, 0.6461186804049626E+00, 0.5003600760145155E-01, 0.3411701822058120E+00, 0.6026846298507913E+00, 0.4649210011845201E+00, 0.4169632595817018E+00, 0.9745024564197420E+00, 0.9159749674174896E+00, 0.3798779762430529E+00, 0.6757581567027395E+00, 0.1501600637708167E+00, 0.8841295845033917E+00, 0.1700642059156726E+00, 0.5745602516925833E+00, 0.7146078194346678E+00, 0.7876321314233041E+00, 0.3623958693011297E+00, 0.1316504845867333E+00, 0.6150819295249010E+00, 0.9948396700221377E+00, 0.2186788175334711E+00, 0.3433450548510013E+00, 0.4434886569716980E+00, 0.6596978167473024E+00, 0.7067569387667516E+00, 0.2710992196058543E+00, 0.2531644393448058E+00, 0.6179743389634106E+00, 0.6395694224823617E+00, 0.6233992467844496E-01, 0.9270082862838847E-01, 0.6813409948026068E+00, 0.8489230752840353E+00, 0.4248777519526148E+00, 0.9258241367507150E+00, 0.7591306919901064E-01, 0.1337231221457533E+00, 0.6673452115706187E+00, 0.3161361894802919E+00, 0.9287930266484576E+00, 0.9211411715651807E+00, 0.7110889130885073E+00, 0.6783920645346327E+00, 0.5798290672446252E+00, 0.6003988035906362E+00, 0.8338909998640337E+00, 0.1150264810560550E+00, 0.8268177524919460E+00, 0.2868686997384918E+00, 0.7734675037869032E+00, 0.8495624932870276E+00, 0.7382167415731139E+00}, + n: 21, + zOut: []float64{0.2565771617602568E+01, 0.2464815559540473E+01, 0.2377249642737961E+01, 0.2182027799722737E+01, 0.1994511663794419E+01, 0.1777930797653110E+01, 0.1532836111328556E+01, 0.1298104160091711E+01, 0.1162548328490141E+01, 0.1031426069242260E+01, 0.9067767207978197E+00, 0.7702116437984168E+00, 0.7023507576840374E+00, 0.5846573732521254E+00, 0.3836750731694669E+00, 0.3732780616075560E+00, 0.2146097506115993E+00, 0.5462411591703480E-01, 0.3208967690429450E-01, 0.2788258306628742E-02, 0.1838228532938987E-03, 0.1703684557466520E-17, 0.8886730161731292E-14, 0.1725592004801531E-13, 0.1532836111328556E+01, 0.2310659810285515E-15, 0.8778995686431983E-12, 0.1396745951735637E-11, 0.1298104160091711E+01, 0.0000000000000000E+00, 0.8497749401208094E-11, 0.5925398902948847E-11, 0.1162548328490141E+01, 0.1292469707114106E-25, 0.1515360700076446E-10, 0.2085752134421418E-10, 0.1031426069242260E+01, 0.1195331315767287E-17, 0.8898419915788489E-10, 0.1186621585503233E-09, 0.9067767207978197E+00, 0.1888339631531495E-12, 0.2241246700510621E+02, 0.2241246700510621E+02, 0.1190000000000000E+03, 0.3539682539682540E+01, 0.7563025210084033E+01, 0.2596357213906324E-08, 0.7023507576840374E+00, 0.1416275483756143E-17, 0.5106480833143134E-08, 0.6438584684288567E-08, 0.5846573732521254E+00, 0.1317619996636992E-15, 0.1896058302301025E-07, 0.2367797858508706E-07, 0.3836750731694669E+00, 0.9199951564453634E-11, 0.8967796171107713E-07, 0.1296821709728121E-06, 0.3732780616075560E+00, 0.1615587133892578E-26, 0.3088999981101691E-06, 0.2343043411729366E-06, 0.2146097506115993E+00, 0.2055968734232262E-28, 0.9134179982896841E-05, 0.6280501592969192E-05, 0.5462411591703480E-01, 0.1901142159808155E-23, 0.3768301572228235E-05, 0.8777513601148953E-05, 0.3208967690429450E-01, 0.1479114197289397E-29, 0.1428515450408294E-03, 0.5208612044311805E-04, 0.2788258306628742E-02, 0.2057124874537592E-17, 0.2063479623178836E-02, 0.3566698154744510E-02, 0.1838228532938987E-03, 0.3273772756667199E-28, 0.8538542526496483E-03, 0.1571849612061994E-03}, + info: 0, + }, + { + z: []float64{0.1589037341524596E+00, 0.1455226073481288E+00, 0.1938395273812957E+00, 0.1962691615573132E+00, 0.1687822326883440E+00, 0.6650981615477494E+00, 0.8270615916362424E+00, 0.1710502783654970E+00, 0.2206713720159043E+00, 0.4369721197399372E+00, 0.9301314325299896E+00, 0.5722466234411457E+00, 0.1135089451836189E+00, 0.5846068541971138E+00, 0.9216025315561343E+00, 0.9066267701445474E+00, 0.5584279552920539E+00, 0.4343925455049338E+00, 0.9858452060735702E+00, 0.6563046209578444E+00, 0.7077011175365495E+00, 0.4947310926689127E+00, 0.7385820400647596E+00, 0.5937728681009750E+00, 0.9762402194896037E+00, 0.3450302019452143E+00, 0.3805099852593911E+00, 0.7529397554746390E+00, 0.7330092480109731E+00, 0.3330086450808912E+00, 0.9038518043983117E+00, 0.6574079221280790E+00, 0.2509077957372493E+00, 0.6249580721461656E+00, 0.2757992349681960E+00, 0.5001238277403597E+00, 0.9621194298806066E+00, 0.3061711826567661E+00, 0.1119838022409911E+00, 0.2976298035182879E+00, 0.6363137835930621E-01, 0.4930031667447814E+00, 0.1865676338649569E-01, 0.4250211458984191E+00, 0.1095501188334868E+00, 0.2763357459722963E+00, 0.7075737347301593E+00, 0.5363987747039417E+00, 0.3986581101260644E+00, 0.2692140175173962E+00, 0.5588052030209328E+00, 0.5539805437492590E+00, 0.6882419411200217E+00, 0.6525011142322502E+00, 0.2351213214810641E+00, 0.4862287407564582E+00, 0.9494457572755843E-01, 0.2775605674126462E+00, 0.6088686305117397E-01, 0.1602712446759722E+00, 0.6726078044316741E-01, 0.1771280849255007E+00, 0.9403546682132294E+00, 0.1182787468569617E+00, 0.6084837514797026E+00, 0.4725411123129805E+00, 0.2891346904124859E-01, 0.3056197468639377E-01, 0.3597281640784106E+00, 0.3047108802830497E+00, 0.9462624965987684E+00, 0.6795048656132132E+00, 0.3142878274718968E+00, 0.2255775176392846E+00, 0.5741746909618360E+00, 0.6125119194512041E+00, 0.8636232492271716E+00, 0.5595270150362563E-01, 0.4894380312911951E+00, 0.2945948126181174E+00, 0.4782956027971728E+00, 0.1100404727801326E+00, 0.2692801555328298E+00, 0.4567347029351195E+00}, + n: 21, + zOut: []float64{0.2662663085210597E+01, 0.2404979690430721E+01, 0.2214109781172517E+01, 0.2010332580463078E+01, 0.1879931283999763E+01, 0.1831239586461748E+01, 0.1664682288858752E+01, 0.1512516241203824E+01, 0.1081258277181201E+01, 0.8471473481460485E+00, 0.6221178288483303E+00, 0.5493156782308360E+00, 0.4496825320738197E+00, 0.3768653101376996E+00, 0.2833465507506064E+00, 0.2013980912694376E+00, 0.1418989984144841E+00, 0.7096946004385345E-01, 0.4542843847166723E-01, 0.6747056508451696E-02, 0.1343590842619022E-02, 0.4141519752410312E-28, 0.4845145585707669E-05, 0.3343357997526164E-05, 0.1664682288858752E+01, 0.8527270841077049E-25, 0.1655046287299363E-04, 0.2231546414257453E-04, 0.1512516241203824E+01, 0.5692210911982269E-19, 0.1383329297784762E-03, 0.1072264803352635E-03, 0.1081258277181201E+01, 0.1459392674658872E-28, 0.4158771817821724E-03, 0.3910579975830214E-03, 0.8471473481460485E+00, 0.2949199315750023E-16, 0.2216793811640345E-03, 0.2203201078239036E-03, 0.6221178288483303E+00, 0.2055113688275276E-18, 0.2085797369872005E+02, 0.2085797369872006E+02, 0.9000000000000000E+02, 0.2732426303854875E+01, 0.0000000000000000E+00, 0.1772659828830871E-05, 0.4496825320738197E+00, 0.4437342591868191E-30, 0.2138076899966292E-04, 0.1340116970023588E-04, 0.3768653101376996E+00, 0.2904017873172006E-24, 0.4668906275608195E-04, 0.7182837805013731E-04, 0.2833465507506064E+00, 0.4888968615550842E-22, 0.1290326696826671E-05, 0.6479808231987577E-06, 0.2013980912694376E+00, 0.4436553730962970E-26, 0.1673384055036320E-03, 0.7106703019344439E-04, 0.1418989984144841E+00, 0.3443985257364436E-16, 0.1415746442632383E-02, 0.1286112519803737E-02, 0.7096946004385345E-01, 0.1380506584136771E-29, 0.1898294559619081E-02, 0.3536485589649533E-02, 0.4542843847166723E-01, 0.9860761315262648E-31, 0.1085724134073318E-03, 0.2838967874935677E-03, 0.6747056508451696E-02, 0.2742900553697359E-16, 0.1307657950440773E-02, 0.4192938789348323E-02, 0.1343590842619022E-02, 0.2423380700838948E-25, 0.4340570868086748E-02, 0.9691995934364128E-02}, + info: 0, + }, + { + z: []float64{0.6603307676446488E+00, 0.5215490552441340E+00, 0.9279560414420993E+00, 0.3871591216009305E+00, 0.4489001158072897E+00, 0.2115798060938074E+00, 0.6013990647859857E-01, 0.6977506014884622E+00, 0.8981757899514635E+00, 0.6366966965554082E+00, 0.5447619366248987E+00, 0.2926906196279220E+00, 0.9538633412864880E+00, 0.4052441866103130E+00, 0.9970193775088028E+00, 0.1550480233350559E+00, 0.9697068099139655E+00, 0.3748402815554551E+00, 0.3906465669660910E+00, 0.4103562008634933E+00, 0.9514404866677418E+00, 0.5608812699221558E+00, 0.6226680723027547E+00, 0.8653188982275728E+00, 0.3999642050403411E+00, 0.8968004947108832E+00, 0.1007886665847859E+00, 0.2055140520989622E+00, 0.8479005785073866E+00, 0.4772281284198989E+00, 0.3664785333935638E+00, 0.9311163393120341E+00, 0.2051534177095988E+00, 0.5588930379235971E+00, 0.9385948972790567E+00, 0.1380523811906209E+00, 0.9076293986285472E+00, 0.9937542903014829E+00, 0.5330397746663563E+00, 0.5373590340921116E+00, 0.2667502750074380E-01, 0.9996497580467543E+00, 0.7460509377370035E+00, 0.5868152625248035E+00, 0.2352631583529476E+00, 0.2062979890255305E+00, 0.1864397664760209E-02, 0.1562262993494207E+00, 0.1880894213999632E+00, 0.5369024951393064E+00, 0.6560943776892021E+00, 0.9558063214302399E+00, 0.1463497248954505E+00, 0.6977928179134164E+00, 0.8204108917709737E+00, 0.9530026100161404E+00, 0.7191901603465490E+00, 0.4974721533134605E+00, 0.8445129869563219E+00, 0.9007488855711614E+00, 0.4164322161987429E+00, 0.5750362072910759E+00, 0.1935672755254650E+00, 0.2663393354536251E+00, 0.3913931132271733E+00, 0.7724103066167269E+00, 0.7871420607985310E+00, 0.3766724710952808E+00, 0.9224124235283799E+00, 0.1080194858843619E+00, 0.3512364719709385E+00, 0.9868075881536598E-02, 0.9893144531298202E+00, 0.5983612801716819E+00, 0.2882889058269555E-01, 0.2759662054778022E+00, 0.4865673169207868E+00, 0.4317793431152178E+00, 0.4039098350536063E-01, 0.7594353556100967E+00, 0.6702102151313558E+00, 0.5757953377080282E+00, 0.7036908158147406E+00, 0.3078985083785768E+00}, + n: 21, + zOut: []float64{0.2422149931211175E+01, 0.2394118175176597E+01, 0.2305882752563478E+01, 0.2031709011458775E+01, 0.2015634640599460E+01, 0.1933740155888154E+01, 0.1715509223328114E+01, 0.1559424733880939E+01, 0.1425500044444135E+01, 0.1021162532677627E+01, 0.8999999270989295E+00, 0.8371987758218183E+00, 0.7469639623683311E+00, 0.6494523294995699E+00, 0.4251816116188064E+00, 0.2881024603279346E+00, 0.2247792687845145E+00, 0.8318936570759092E-01, 0.1886599847837073E-01, 0.1029977709531541E-01, 0.8015530498900421E-03, 0.8380373580927862E-22, 0.1621276583815588E-04, 0.5889624784943332E-05, 0.1715509223328114E+01, 0.2616454581976124E-17, 0.2563506401168800E-03, 0.3048038004625151E-03, 0.1559424733880939E+01, 0.5629222562364776E-20, 0.1824080863602310E-03, 0.8021857862878124E-04, 0.1425500044444135E+01, 0.1078233452249475E-15, 0.2986624164553499E-03, 0.4306384056300427E-03, 0.1021162532677627E+01, 0.2425965640253176E-21, 0.3415477187080772E-04, 0.2730971166672021E-04, 0.8999999270989295E+00, 0.1110716154551185E-26, 0.2300966623107952E+02, 0.2300966623107953E+02, 0.9800000000000000E+02, 0.2877551020408163E+01, 0.3061224489795918E+01, 0.5341669529353412E-07, 0.7469639623683311E+00, 0.1147369787651374E-23, 0.3199917396615717E-04, 0.1114773640824220E-03, 0.6494523294995699E+00, 0.1324417262847731E-16, 0.4143040953885707E-03, 0.3815591968277185E-03, 0.4251816116188064E+00, 0.4294702353329713E-20, 0.5586157832836348E-03, 0.4985099391803953E-03, 0.2881024603279346E+00, 0.3449343154346125E-19, 0.3018840928486242E-04, 0.4804099248496092E-04, 0.2247792687845145E+00, 0.8223054085459871E-16, 0.6535536077614123E-03, 0.5704051254743707E-03, 0.8318936570759092E-01, 0.1269822990867506E-16, 0.2750660948852983E-03, 0.2439371709019565E-03, 0.1886599847837073E-01, 0.2261821987449685E-25, 0.1693307421164339E-03, 0.1879460762504110E-03, 0.1029977709531541E-01, 0.2207699818464282E-23, 0.8362752373159153E-06, 0.5564443135649789E-05, 0.8015530498900421E-03, 0.1142002837193949E-22, 0.2005722186927794E-03, 0.1790331282576109E-02}, + info: 0, + }, + { + z: []float64{0.7180522604364612E+00, 0.1926580568606098E+00, 0.9998274874952506E-01, 0.5945840846677781E+00, 0.6814004826706310E-01, 0.6532586662527488E+00, 0.6162535781196632E+00, 0.6323752897874746E+00, 0.6913197528064650E+00, 0.8218961980054600E+00, 0.2391583485552943E+00, 0.6893465701234240E+00, 0.8646254741258573E+00, 0.4399082441653793E+00, 0.7657207697437258E+00, 0.6442902814401660E+00, 0.2997828758931008E+00, 0.3311754429773528E+00, 0.4602753981904284E-01, 0.2937498413335546E+00, 0.9438033090912972E+00, 0.6689413829611792E+00, 0.3690605709328096E+00, 0.1297746871929878E+00, 0.5761771518385747E+00, 0.9470476076636891E+00, 0.6065387228873672E+00, 0.3279182193602236E+00, 0.7521029317260848E+00, 0.3448791591170053E-01, 0.8260379882894462E+00, 0.3381289908082724E+00, 0.6350192899014672E+00, 0.6181098759446546E+00, 0.7961594478307139E+00, 0.9929813242449080E+00, 0.4678192142649594E+00, 0.8317252674327552E+00, 0.1301328932823079E+00, 0.9710090231649569E+00, 0.1522128889234372E+00, 0.8594558260240532E+00, 0.6013715693159983E+00, 0.8742383713574672E+00, 0.7309721379377087E+00, 0.5021385621750218E+00, 0.9190365975533138E+00, 0.8027800227596282E-01, 0.1149439815205374E+00, 0.3491372322884074E+00, 0.3638810075690350E+00, 0.7397316797734275E+00, 0.6765505976038609E+00, 0.6412509132149137E+00, 0.6636796276324973E+00, 0.2769301898862327E+00, 0.6293983439129569E+00, 0.7661949976862148E+00, 0.1787796367414251E+00, 0.2134901744318570E+00, 0.8213730837735125E+00, 0.5732135541056227E+00, 0.8956530012694059E+00, 0.5095442527120628E+00, 0.8428538487299666E+00, 0.6837140150023939E+00, 0.1256023460764972E+00, 0.1828667371827231E-01, 0.3922785557614588E+00, 0.9906794824083128E+00, 0.6528984219237121E+00, 0.2175815548938115E+00, 0.5215238469901794E+00, 0.6874084104558049E+00, 0.4144717036123762E+00, 0.5901719497674505E+00, 0.3178975712304457E+00, 0.7061784208820305E+00, 0.6028763180221938E+00, 0.6012903376000152E+00, 0.6812913355997376E+00, 0.7728807542206401E+00, 0.4888911469874758E+00, 0.1012713084879602E+00}, + n: 21, + zOut: []float64{0.2588311953706596E+01, 0.2370344164465735E+01, 0.2152772432177807E+01, 0.2121020324458281E+01, 0.1935798000017230E+01, 0.1639966751245229E+01, 0.1447991497477954E+01, 0.1303796318075928E+01, 0.1122178474206467E+01, 0.1028684266176079E+01, 0.9663785372526962E+00, 0.8401839996503420E+00, 0.6468021461987292E+00, 0.5148128374433424E+00, 0.4081393344645305E+00, 0.3744044838513741E+00, 0.1951863401557736E+00, 0.1222936930600034E+00, 0.3610852087288927E-01, 0.2215175692702855E-02, 0.1055251342481684E-03, 0.5816113682013476E-24, 0.3490790538048844E-06, 0.5279190866861155E-06, 0.1447991497477954E+01, 0.6749793798367842E-21, 0.1187240552619153E-05, 0.8669686727541259E-06, 0.1303796318075928E+01, 0.2818270319791895E-16, 0.1425495821091504E-08, 0.4238958678865879E-08, 0.1122178474206467E+01, 0.1974523135472784E-17, 0.8140039386639262E-06, 0.3278912117172865E-06, 0.1028684266176079E+01, 0.3004196424688596E-17, 0.2459469608149132E-06, 0.1027360875624831E-06, 0.9663785372526962E+00, 0.8319175140295936E-21, 0.2181749477578394E+02, 0.2181749477578394E+02, 0.1040000000000000E+03, 0.3040816326530612E+01, 0.3846153846153846E+01, 0.3006532860022149E-05, 0.6468021461987292E+00, 0.2129924444096732E-28, 0.3097317061779137E-05, 0.3301766384461962E-05, 0.5148128374433424E+00, 0.5841522899747606E-17, 0.6589564866042633E-05, 0.8825655271690012E-05, 0.4081393344645305E+00, 0.5522026336547083E-29, 0.6929345622607317E-04, 0.1121666398022498E-03, 0.3744044838513741E+00, 0.4071868297361024E-19, 0.4964849153130707E-03, 0.6240579194345771E-03, 0.1951863401557736E+00, 0.3096999756315481E-22, 0.1538823843362176E-02, 0.5557701536471033E-03, 0.1222936930600034E+00, 0.9508642973366516E-17, 0.9344625728185554E-03, 0.1303932473154565E-02, 0.3610852087288927E-01, 0.2671050208464689E-19, 0.5349955893117279E-02, 0.9991286391872665E-02, 0.2215175692702855E-02, 0.2465190328815662E-30, 0.2737788875312504E-02, 0.2378589653250575E-02, 0.1055251342481684E-03, 0.0000000000000000E+00, 0.1487915832966980E-01, 0.9945584373260818E-02}, + info: 0, + }, + { + z: []float64{0.2443960928887767E+00, 0.5306690011327519E+00, 0.8844980893594125E+00, 0.8505050348613927E+00, 0.1179365025679910E+00, 0.6787232231004032E+00, 0.4781425309482933E+00, 0.8596658025119301E+00, 0.7267566040500681E+00, 0.7988986860541384E+00, 0.5066697395752245E+00, 0.9256193759419001E+00, 0.1614174453766865E+00, 0.7938782145253169E+00, 0.3207377639351938E+00, 0.5936236877473402E+00, 0.5294512496859689E+00, 0.3341300959064973E+00, 0.8739309914591177E+00, 0.1643518115289022E-01, 0.9695643985202173E+00, 0.9508789318813814E+00, 0.6599781146531454E+00, 0.8013437877388673E+00, 0.1929493765752847E+00, 0.7655052376601326E+00, 0.6319580998438735E+00, 0.6831519307583876E+00, 0.3834927697748418E+00, 0.7094548193343077E+00, 0.7020510393185050E+00, 0.6520146205437408E+00, 0.6562814689912274E+00, 0.5240471964184201E+00, 0.2362557689024753E+00, 0.4347621644220048E+00, 0.1660979681267404E+00, 0.2422730270980831E+00, 0.7891782502389337E+00, 0.5007812255281535E+00, 0.4444633531981611E+00, 0.3026778693869716E+00, 0.9990331636150707E-02, 0.4097233632314936E+00, 0.9940240633376396E+00, 0.1626467187830966E+00, 0.3461071508544706E+00, 0.6476433090511620E+00, 0.7204399230581238E-01, 0.6885344672911693E+00, 0.1941295874559149E+00, 0.5883115695765473E+00, 0.7359955011333836E+00, 0.4277388472789430E+00, 0.4017294206583021E+00, 0.7838762945853397E+00, 0.9128155969033611E+00, 0.4856080402782125E+00, 0.4763260467232836E+00, 0.5586410048770161E+00, 0.8031586091432461E+00, 0.6068401118620381E-01, 0.9247455618544214E+00, 0.5857147883918616E+00, 0.7467203590494284E+00, 0.1453563221196804E+00, 0.2297646010524917E+00, 0.8950965613541395E+00, 0.3335127494359967E+00, 0.9671078623732762E+00, 0.8023166958816280E+00, 0.1059134943829219E+00, 0.7122485680883537E+00, 0.3211310961264330E+00, 0.1626983074059779E+00, 0.4042697895935750E+00, 0.4799615975845870E+00, 0.3426607739026810E-02, 0.5147088911567483E+00, 0.7533023355653040E+00, 0.9693400349159813E+00, 0.7251923493536844E+00, 0.9132309180417886E-01, 0.4001770994110867E+00}, + n: 21, + zOut: []float64{0.2574587707602998E+01, 0.2548516143888565E+01, 0.2328646361106399E+01, 0.2152335028165169E+01, 0.1900054508136636E+01, 0.1821843561986577E+01, 0.1641395708303600E+01, 0.1593513640807486E+01, 0.1254245828754644E+01, 0.1184500984874290E+01, 0.9407518766665146E+00, 0.8321813659237318E+00, 0.6961683120499664E+00, 0.5315544763312857E+00, 0.4082285577131941E+00, 0.4022023658419822E+00, 0.2892256147411429E+00, 0.1412172326671640E+00, 0.7919841586115514E-01, 0.2055312514153672E-02, 0.1458583715266580E-03, 0.5995342879679690E-28, 0.2082901809770958E-07, 0.9383395476751434E-08, 0.1641395708303600E+01, 0.1321835131711384E-15, 0.1191741688360734E-04, 0.3695487724817346E-05, 0.1593513640807486E+01, 0.5607617048340495E-15, 0.5232768419257040E-05, 0.4082864434107817E-05, 0.1254245828754644E+01, 0.1850697850686327E-14, 0.2071860298001858E-05, 0.2753629328588578E-05, 0.1184500984874290E+01, 0.3549874073494553E-29, 0.9441520198112501E-05, 0.5871348343515868E-05, 0.9407518766665146E+00, 0.3656881477565973E-23, 0.2332256886230818E+02, 0.2332256886230818E+02, 0.1000000000000000E+03, 0.2984126984126984E+01, 0.3000000000000000E+01, 0.1218265160373847E-03, 0.6961683120499664E+00, 0.3847797347882626E-19, 0.2944801840696127E-03, 0.4565874591840146E-03, 0.5315544763312857E+00, 0.2366582715663035E-29, 0.5951942600827748E-04, 0.7082415940475930E-04, 0.4082285577131941E+00, 0.1744834104604043E-24, 0.4087064324555941E-04, 0.4051735857075661E-04, 0.4022023658419822E+00, 0.5055621275172978E-20, 0.1443306547898801E-05, 0.5013891517830428E-06, 0.2892256147411429E+00, 0.1446770900175336E-26, 0.7439355829951562E-04, 0.1741194257531676E-03, 0.1412172326671640E+00, 0.3448013628188340E-14, 0.2774107535050150E-02, 0.3338675080262731E-02, 0.7919841586115514E-01, 0.2413026984508734E-18, 0.7157138061395222E-03, 0.6803125903293225E-03, 0.2055312514153672E-02, 0.3994185778863994E-23, 0.5722078415717462E-03, 0.5910838594703896E-03, 0.1458583715266580E-03, 0.1183291357831518E-27, 0.8602246198024520E-03, 0.1402897408133881E-02}, + info: 0, + }, + { + z: []float64{0.6756942057876089E+00, 0.6579919202857232E+00, 0.8168130848194743E+00, 0.2483963371195050E+00, 0.2866280219451008E+00, 0.7172808579862799E-03, 0.2411898945446896E+00, 0.5534360794587689E-02, 0.3878248310175912E+00, 0.4256983490856848E+00, 0.7118512164413080E+00, 0.8762976594477806E+00, 0.6850772131038755E+00, 0.4603991232581716E+00, 0.6546622425118448E+00, 0.3103854094723100E+00, 0.7913005955185648E+00, 0.4864788053022765E+00, 0.6214717223070496E+00, 0.7079028836241165E+00, 0.2446362485461124E+00, 0.3062353821816216E+00, 0.8766788389923219E-01, 0.4381267847541642E+00, 0.4459912790878073E-01, 0.9432264671740954E+00, 0.3830574008366420E+00, 0.3381025391982955E+00, 0.6585260539196298E+00, 0.1004337858849739E+00, 0.9320890528134474E+00, 0.3322930037041504E+00, 0.7282334590214989E-02, 0.8367863647557111E+00, 0.9736104021592913E+00, 0.1613168640897539E+00, 0.6409545774446285E+00, 0.8441218931570360E-01, 0.9793937208019250E+00, 0.8303681522642254E+00, 0.1022316826967604E+00, 0.3021608972738009E+00, 0.1238379032543057E+00, 0.3839961366681232E+00, 0.8871553342676223E+00, 0.2909019998361990E+00, 0.7955411369197152E-01, 0.6476593477808288E+00, 0.1739219408315845E+00, 0.6498034164943688E+00, 0.3405210004266120E+00, 0.5459816771585898E+00, 0.2574285667818188E-01, 0.8691155035114945E+00, 0.4320450067500660E+00, 0.6967311316847606E+00, 0.9186339034853966E+00, 0.9491091410944081E+00, 0.2046793386144015E+00, 0.4114169869296881E+00, 0.9170199522695309E+00, 0.1514288291023066E+00, 0.2203325773257230E+00, 0.7891126546748299E+00, 0.4738113210301682E+00, 0.6729225031084131E+00, 0.2382373075875677E+00, 0.4180455054749687E+00, 0.9185761229203592E+00, 0.8030412579733187E+00, 0.4789612026295414E+00, 0.5038982716350845E+00, 0.9959829239394621E+00, 0.3087119711461705E-01, 0.6615773194242809E+00, 0.4461280013353816E+00, 0.1982838436639324E+00, 0.7583555141388076E+00, 0.7946309632008934E+00, 0.6749216068143323E+00, 0.9948312782688508E+00, 0.2854132428873886E+00, 0.8405396060835862E+00, 0.3412432527462372E-01}, + n: 21, + zOut: []float64{0.2393193272196224E+01, 0.2018136210599260E+01, 0.1995725670346335E+01, 0.1962470040389077E+01, 0.1880885332732760E+01, 0.1640866198530974E+01, 0.1381237309251015E+01, 0.1349378962361067E+01, 0.9454836406584929E+00, 0.7636867441308103E+00, 0.6820433637129892E+00, 0.6091604279437030E+00, 0.5856982990037397E+00, 0.4957297472312800E+00, 0.2553870576469542E+00, 0.2360257010865909E+00, 0.1371029529316844E+00, 0.8102847375475340E-01, 0.5521596879227348E-01, 0.9135542089709688E-02, 0.7426079491367038E-04, 0.1040308236944517E-14, 0.7301351780522185E-10, 0.7774740781328628E-10, 0.1381237309251015E+01, 0.2169367489357782E-29, 0.6020076428884570E-10, 0.5781767346304832E-10, 0.1349378962361067E+01, 0.1885108385497271E-16, 0.6878646083705261E-10, 0.6530919047819172E-10, 0.9454836406584929E+00, 0.5778430642028005E-17, 0.9207835097245334E-10, 0.7637719283517905E-10, 0.7636867441308103E+00, 0.1387778780781446E-16, 0.1259777267883337E-09, 0.1656656563258317E-09, 0.6820433637129892E+00, 0.0000000000000000E+00, 0.1947766517618461E+02, 0.1947766517618461E+02, 0.1070000000000000E+03, 0.3197278911564626E+01, 0.3738317757009346E+01, 0.5169611983503601E-09, 0.5856982990037397E+00, 0.2460562659624748E-15, 0.4628473083370263E-08, 0.9345989594028561E-08, 0.4957297472312800E+00, 0.2615714135774493E-18, 0.2264320058754590E-06, 0.2929148984854635E-06, 0.2553870576469542E+00, 0.1029104326196136E-18, 0.2640422579955958E-07, 0.2108896012270181E-07, 0.2360257010865909E+00, 0.3005450327091600E-17, 0.6822175517251369E-08, 0.8519370047734521E-08, 0.1371029529316844E+00, 0.3395257336071235E-24, 0.2687435952714477E-08, 0.2177398712709520E-08, 0.8102847375475340E-01, 0.0000000000000000E+00, 0.5343374415472690E-09, 0.5384901342094013E-09, 0.5521596879227348E-01, 0.2914620163738177E-24, 0.6457803167637477E-08, 0.2258738450739571E-07, 0.9135542089709688E-02, 0.5326388832052272E-25, 0.9576323906120589E-06, 0.3243967823107194E-05, 0.7426079491367038E-04, 0.3164925372525892E-18, 0.6752170208452239E-05, 0.3302115586194402E-04}, + info: 0, + }, + { + z: []float64{0.1859840927709887E+00, 0.1326482709507555E+00, 0.1830793816152183E+00, 0.4955347339015181E+00, 0.7174832323677909E+00, 0.1239131234434754E-01, 0.8960455455727024E+00, 0.1883195594308053E+00, 0.3701760109540279E+00, 0.5189832590024491E+00, 0.8746518205444311E+00, 0.5127960794741733E+00, 0.2715029219143491E+00, 0.3130984190329523E+00, 0.6427011945330067E+00, 0.2728531634457195E+00, 0.4849915812764480E+00, 0.4474855195890282E-01, 0.1232624016522375E+00, 0.4054507321320544E+00, 0.8168182420396084E+00, 0.5779650563825861E+00, 0.3336575737681243E+00, 0.4793345429794458E+00, 0.3323762775436829E+00, 0.4013874798394268E-01, 0.3250840079396182E+00, 0.3339528328323188E+00, 0.6534745789256358E+00, 0.1592419685588734E+00, 0.4882641395765897E-01, 0.3378473153079410E+00, 0.1498873352536064E+00, 0.9366519936638189E+00, 0.8628314489246045E+00, 0.9035188141748132E+00, 0.3376603415628452E+00, 0.8754867721780122E+00, 0.4314313357227496E+00, 0.6689080802643724E+00, 0.7427192946427073E+00, 0.8408966332922378E+00, 0.3923135283693152E+00, 0.9856346160535667E+00, 0.5253798946684216E+00, 0.4589666030610524E+00, 0.3627813920321372E+00, 0.6650592661455799E+00, 0.5488555419923284E+00, 0.8723519563008553E+00, 0.5759829964509324E+00, 0.8314551283704829E+00, 0.8033910216639006E-01, 0.5533270198466882E+00, 0.4579854660280547E-01, 0.8805162884999327E+00, 0.7798601625088321E+00, 0.3998529604552336E+00, 0.2290634020126769E-01, 0.4087780821380217E+00, 0.8084384129630373E-01, 0.1651045317338867E+00, 0.5138876592921692E+00, 0.1502237554834691E+00, 0.3139451210283801E+00, 0.4951417832103121E+00, 0.4305502836911147E+00, 0.4221379680427187E+00, 0.6629276271381638E+00, 0.6032939209531929E+00, 0.7486429236694788E+00, 0.4603187644190643E+00, 0.9910999698454684E+00, 0.9830579802970648E+00, 0.1327788029232968E+00, 0.7906300391462903E+00, 0.4870686063503010E+00, 0.9107501765395865E-01, 0.5847999740468798E+00, 0.5237055378474927E+00, 0.1949033413503392E+00, 0.6706570830152104E+00, 0.4839742423553839E+00, 0.6933746141255293E+00}, + n: 21, + zOut: []float64{0.2594702985921864E+01, 0.1963381202215380E+01, 0.1899121104965353E+01, 0.1852857657580134E+01, 0.1352179381057759E+01, 0.1316420368068040E+01, 0.1223907530772361E+01, 0.1104722051320913E+01, 0.1042814535040686E+01, 0.9392359492223399E+00, 0.5879944547218380E+00, 0.5343064059199153E+00, 0.3616892068472140E+00, 0.3474187565935542E+00, 0.3132932870269020E+00, 0.2394766491234008E+00, 0.1924620369224269E+00, 0.5796610832720670E-01, 0.4900919199482741E-01, 0.2087594658763894E-01, 0.6804292520862544E-03, 0.2186403793390500E-19, 0.2668268315891067E-16, 0.1216320938093713E-16, 0.1223907530772361E+01, 0.3077822220048293E-18, 0.9690290545884895E-18, 0.1677534925257981E-18, 0.1104722051320913E+01, 0.3294338264035954E-18, 0.1270509199570000E-13, 0.4678488073918506E-13, 0.1042814535040686E+01, 0.2740439675865377E-23, 0.1047809983111396E-11, 0.5781643460797313E-12, 0.9392359492223399E+00, 0.3379215452805658E-16, 0.8350045830190690E-10, 0.5730922211948388E-10, 0.5879944547218380E+00, 0.6938893903907228E-17, 0.1799451523948185E+02, 0.1799451523948184E+02, 0.1150000000000000E+03, 0.3578231292517007E+01, 0.6086956521739131E+01, 0.8630088713732289E-10, 0.3616892068472140E+00, 0.1664229231319872E-20, 0.9644621511794884E-10, 0.9354199679969641E-10, 0.3474187565935542E+00, 0.0000000000000000E+00, 0.1015403419286529E-09, 0.1046840761330470E-09, 0.3132932870269020E+00, 0.6366107505133565E-27, 0.3071873418074744E-11, 0.5342885575500614E-12, 0.2394766491234008E+00, 0.2599072586631376E-18, 0.1837414559126179E-09, 0.2303923049314304E-09, 0.1924620369224269E+00, 0.3400814535759169E-17, 0.9192916981159684E-08, 0.4803632388224207E-08, 0.5796610832720670E-01, 0.0000000000000000E+00, 0.1565526746702558E-05, 0.8408463868497472E-06, 0.4900919199482741E-01, 0.7888609052210118E-30, 0.1903794116022181E-04, 0.1014775117962413E-04, 0.2087594658763894E-01, 0.9734740470109229E-22, 0.4676468030348868E-06, 0.4248047233272650E-05, 0.6804292520862544E-03, 0.3161038140634776E-18, 0.1818811163938070E-02, 0.3653457173655013E-02}, + info: 0, + }, + { + z: []float64{0.2029039404458555E-01, 0.4529725864625287E+00, 0.6412066909421453E+00, 0.6139288440336396E+00, 0.3661028502807454E+00, 0.9178254749803582E+00, 0.4307551173824371E+00, 0.4985808870906128E+00, 0.8171615510934167E+00, 0.8279058065788196E+00, 0.3035261047197422E+00, 0.7877147223127390E+00, 0.7688130520483442E+00, 0.4834409462671818E-01, 0.3121145202501183E+00, 0.5269232357652766E+00, 0.7600633371694686E+00, 0.5251092877920901E+00, 0.8263235554592012E+00, 0.6894073332954654E+00, 0.3521429062439027E+00, 0.6447189811681343E+00, 0.1105592548668879E+00, 0.1049454508922576E+00, 0.7381247076050562E+00, 0.7320584094686099E+00, 0.7003114013559573E+00, 0.9638534557041758E+00, 0.5727311775052889E+00, 0.3930768970870516E+00, 0.7640649329763241E+00, 0.3221407324893386E+00, 0.9725443946255905E+00, 0.6922592425787558E+00, 0.3449642467056757E-01, 0.1384627086161467E+00, 0.4398391723165511E+00, 0.8406456486574913E+00, 0.4126144976348992E+00, 0.5351779876797247E-01, 0.6669497026260232E+00, 0.5746288223886410E+00, 0.4589594741804619E+00, 0.7484833637036891E+00, 0.3274476209575072E-01, 0.7067960763848782E+00, 0.8759136475280368E+00, 0.3284828537280239E+00, 0.2536109230678856E+00, 0.8799264273691800E+00, 0.8159607815416694E+00, 0.5729670098854700E-01, 0.8884200881604851E+00, 0.5249116128877267E+00, 0.6498061599007876E-01, 0.6075292761444269E+00, 0.2428201413403417E+00, 0.2668460043818345E+00, 0.1429723702275580E+00, 0.6942338078813951E+00, 0.9271225003121289E+00, 0.8931957344289477E+00, 0.6420336733834545E+00, 0.3786225606645894E+00, 0.9421368123010410E-01, 0.9476439119845459E+00, 0.6497389318978118E+00, 0.3841806572586668E+00, 0.1329188317035728E+00, 0.6545507077812880E+00, 0.4430247695845350E+00, 0.1753161904868739E+00, 0.2413409779703910E+00, 0.1476409499735053E+00, 0.1179852848482287E+00, 0.3704631210033814E+00, 0.1967445635592234E+00, 0.2100970549835486E+00, 0.5744473538919733E+00, 0.1093206314301038E+00, 0.5132572818416121E+00, 0.4964557538937117E+00, 0.7518888363275744E-02, 0.9720615373003737E+00}, + n: 21, + zOut: []float64{0.2563191374817756E+01, 0.2359364796169898E+01, 0.2296884847589588E+01, 0.2056943321577226E+01, 0.1949112826206492E+01, 0.1629835138023691E+01, 0.1562766390641567E+01, 0.1422208590143927E+01, 0.1368481726990307E+01, 0.1150114414099739E+01, 0.8482773777570239E+00, 0.7665061168435710E+00, 0.7135198036652551E+00, 0.3486547062556205E+00, 0.2456691453437445E+00, 0.2203009969871996E+00, 0.1404417091680581E+00, 0.1160909181211330E+00, 0.2112854362928769E-01, 0.5069559443178203E-02, 0.5650407111696261E-03, 0.3717112585401408E-26, 0.2316306425767847E-08, 0.1632477182259275E-08, 0.1562766390641567E+01, 0.6446192664231602E-24, 0.9634960729667980E-08, 0.6524712961691138E-08, 0.1422208590143927E+01, 0.1932709217791479E-28, 0.4932058767625490E-07, 0.7860293908453283E-07, 0.1368481726990307E+01, 0.1238511621196989E-27, 0.2778987342481399E-06, 0.5558918854266694E-06, 0.1150114414099739E+01, 0.2156683454185074E-19, 0.1662595987219070E-04, 0.2580299679298412E-04, 0.8482773777570239E+00, 0.7914569980025776E-17, 0.2178512734418544E+02, 0.2178512734418543E+02, 0.1000000000000000E+03, 0.2934240362811791E+01, 0.1000000000000000E+01, 0.1715129124192563E-05, 0.7135198036652551E+00, 0.1613909508212798E-19, 0.2836076293001813E-04, 0.1595224464977716E-04, 0.3486547062556205E+00, 0.3352658847189300E-29, 0.8812160938383347E-04, 0.1178320764067675E-03, 0.2456691453437445E+00, 0.0000000000000000E+00, 0.5251568647637462E-04, 0.4480459044047029E-04, 0.2203009969871996E+00, 0.6471183777709004E-25, 0.1114279427921990E-09, 0.2270576453660371E-10, 0.1404417091680581E+00, 0.2855676476900063E-27, 0.2886261726979772E-05, 0.5470704056451658E-06, 0.1160909181211330E+00, 0.3526208246337923E-27, 0.3588687949078309E-02, 0.5383294574404876E-02, 0.2112854362928769E-01, 0.2896602354076833E-17, 0.1732996915625309E-02, 0.1499310228751921E-02, 0.5069559443178203E-02, 0.1003594455767978E-17, 0.5081816639203317E-03, 0.1080637708244138E-02, 0.5650407111696261E-03, 0.0000000000000000E+00, 0.5066428376081889E-02, 0.3247326449492487E-02}, + info: 0, + }, + { + z: []float64{0.7177806115181969E+00, 0.9619042524298227E+00, 0.9756290650460009E-01, 0.2695657197860104E+00, 0.5092382615580680E+00, 0.2216490915715645E+00, 0.7713962041593733E+00, 0.9019626308054164E+00, 0.1009043823109016E+00, 0.7164892891763703E+00, 0.6972336574704985E+00, 0.5604456603447616E-01, 0.4658944020177349E+00, 0.4677429402719713E+00, 0.9395972368396054E+00, 0.6567060928508761E-01, 0.6711470087762763E+00, 0.3572615865847095E-01, 0.7841795004355456E-01, 0.2100489732227784E+00, 0.1528790147771258E+00, 0.2944728557463859E+00, 0.6929796239262105E+00, 0.5593689694083593E+00, 0.5600220347177359E+00, 0.6885800745012647E+00, 0.1441376161827218E+00, 0.2468678391528564E+00, 0.2219056216366488E+00, 0.7828887069679423E+00, 0.1781536622262658E-01, 0.9712383516530864E+00, 0.1031071887927941E+00, 0.5428204596104211E+00, 0.9920375605622551E+00, 0.2231614148449633E+00, 0.1774197365731667E+00, 0.1667803739895276E+00, 0.2293956181863850E+00, 0.8453959149417756E+00, 0.2211895679989639E+00, 0.5610288802043042E+00, 0.3749535737701304E-01, 0.7418144847444434E+00, 0.2593245755300763E+00, 0.5358881543370908E-01, 0.9118629582226685E+00, 0.6483736004795430E+00, 0.7595140552166778E+00, 0.2981894989055883E+00, 0.6091779707233183E+00, 0.7798268953767704E+00, 0.1682114110436058E+00, 0.3801835867597201E+00, 0.6380508025759659E+00, 0.7892946000460455E-01, 0.7607559424299619E+00, 0.3271484239841950E+00, 0.7700240256278714E+00, 0.5894107219393652E+00, 0.6207117138108632E+00, 0.4725019923733027E+00, 0.3616574024313524E+00, 0.6744122205664662E+00, 0.5489632027065386E+00, 0.1532930834122788E+00, 0.1692473010839316E+00, 0.7515070367293223E+00, 0.1186783750638719E+00, 0.1028479850139022E+00, 0.3468642488228025E+00, 0.5278752643808988E+00, 0.3849250707234438E+00, 0.7889573536656195E+00, 0.4738712276132427E+00, 0.7058571493185843E+00, 0.8948240863202030E+00, 0.3494029097065446E+00, 0.4916843795342892E+00, 0.1993321046695898E+00, 0.3650043431665774E+00, 0.2403686388300026E+00, 0.5474155466298688E+00, 0.6157434374908201E+00}, + n: 21, + zOut: []float64{0.1955717973339200E+01, 0.1915826728710446E+01, 0.1780143898982495E+01, 0.1751081083154649E+01, 0.1679171531306522E+01, 0.1398798787154148E+01, 0.1289579288306139E+01, 0.1171599632002814E+01, 0.9950381700653156E+00, 0.9008548767119643E+00, 0.7944341357698450E+00, 0.7347990252582277E+00, 0.4053391427425183E+00, 0.3415476013970046E+00, 0.2769292856200630E+00, 0.2086988709391624E+00, 0.7594980741000955E-01, 0.5721582845751132E-01, 0.5152297043277422E-01, 0.6186350115045150E-02, 0.5774958135565486E-05, 0.6722096271457334E-14, 0.6635533119216432E-06, 0.1048982691930868E-05, 0.1289579288306139E+01, 0.0000000000000000E+00, 0.9172850657907766E-08, 0.6527900227304331E-08, 0.1171599632002814E+01, 0.0000000000000000E+00, 0.3386861611239913E-06, 0.1115072165646295E-06, 0.9950381700653156E+00, 0.1044578056257455E-24, 0.5793689136913799E-11, 0.1625904890507595E-10, 0.9008548767119643E+00, 0.8883435102679349E-21, 0.3220671712964998E-09, 0.8453946299986560E-09, 0.7944341357698450E+00, 0.1653452457343241E-26, 0.1779044076283400E+02, 0.1779044076283399E+02, 0.1120000000000000E+03, 0.3267573696145125E+01, 0.3571428571428572E+01, 0.1211740269624600E-06, 0.4053391427425183E+00, 0.5298753945086544E-14, 0.1515410194583574E-06, 0.2069357347527298E-06, 0.3415476013970046E+00, 0.0000000000000000E+00, 0.2579333883676927E-05, 0.8435987645777294E-05, 0.2769292856200630E+00, 0.2465190328815662E-30, 0.1658852164453815E-08, 0.3207072615633299E-09, 0.2086988709391624E+00, 0.2017246551328580E-19, 0.6091457019925236E-05, 0.6297972233022177E-05, 0.7594980741000955E-01, 0.2553131970482608E-15, 0.2736366650719638E-04, 0.2348362771705736E-04, 0.5721582845751132E-01, 0.1141311335899276E-23, 0.6030351005218485E-04, 0.3385365250818500E-04, 0.5152297043277422E-01, 0.0000000000000000E+00, 0.4442856906399686E-04, 0.3980460155412817E-04, 0.6186350115045150E-02, 0.2711709361697228E-30, 0.1322896557202734E-03, 0.3209571887096705E-03, 0.5774958135565486E-05, 0.0000000000000000E+00, 0.9248295446812529E-03, 0.1317994001905306E-02}, + info: 0, + }, + { + z: []float64{0.7669589114699304E-01, 0.2959120838012549E+00, 0.8617075527885690E+00, 0.3774472194278293E+00, 0.7430204868341380E+00, 0.3337487204025202E-01, 0.2115072947611989E+00, 0.8195300149220009E+00, 0.4610153087687133E+00, 0.1049580467270205E+00, 0.6553761031646719E+00, 0.2044425657813468E+00, 0.1419536829746254E+00, 0.8338399989758465E+00, 0.9917105482281005E+00, 0.3698082853107363E+00, 0.5656210986926330E+00, 0.5849265049217818E+00, 0.9018145207330325E+00, 0.7089264704350354E+00, 0.2562038341655152E+00, 0.1524378342317656E-01, 0.9206210351037002E+00, 0.1877259832276945E+00, 0.3637451600309541E+00, 0.9979742594017312E+00, 0.8919698496914060E+00, 0.3716780472994426E+00, 0.3142548907151147E+00, 0.4170439734847903E+00, 0.3197415298896636E+00, 0.7285365914169133E+00, 0.5784968714882697E+00, 0.6831919512327895E+00, 0.6057174197537164E+00, 0.6413693987683566E-01, 0.8827799219498907E+00, 0.4192891003797022E+00, 0.6040167945472836E+00, 0.6469271762278970E+00, 0.7359461974470041E+00, 0.5539488596393002E+00, 0.4023966166720030E+00, 0.9915288950117843E+00, 0.3043860170301459E+00, 0.4917889743094436E+00, 0.1179472550216760E+00, 0.9125202427370891E+00, 0.8786441005384636E+00, 0.4634730997209351E+00, 0.1080276946115265E+00, 0.6187727001119313E+00, 0.6709766557170562E+00, 0.3818949179452977E+00, 0.8906457783485427E+00, 0.8010289089804480E+00, 0.6931910498827129E+00, 0.8914072225833563E+00, 0.3822463769530011E+00, 0.5898102885291842E+00, 0.1092049166271940E+00, 0.8496011938807149E+00, 0.2304394290731624E+00, 0.5949006075515944E+00, 0.3290638194228065E+00, 0.1971699984758039E+00, 0.7443144303888384E+00, 0.4653555333092598E+00, 0.8207632269304853E+00, 0.4152482306441556E+00, 0.1689785233215235E+00, 0.1721084345877374E+00, 0.3931596107353640E+00, 0.5403345228237123E+00, 0.6387555392172577E+00, 0.1804790096977364E+00, 0.5783025205396422E+00, 0.7395837791384520E+00, 0.5701597209798811E+00, 0.1952734055752668E+00, 0.9661114908130567E+00, 0.4893113195434146E+00, 0.6562980654604210E+00, 0.1879394621701417E+00}, + n: 21, + zOut: []float64{0.2390558120678448E+01, 0.2326196956724044E+01, 0.2071676597874671E+01, 0.1995424877356871E+01, 0.1973795189776371E+01, 0.1728273264358535E+01, 0.1492322130169846E+01, 0.1216694895544233E+01, 0.1149617898796123E+01, 0.1007011094632661E+01, 0.9207056739913982E+00, 0.7404938152461292E+00, 0.6082352700464410E+00, 0.5965144149455339E+00, 0.2276577044879657E+00, 0.1776272681811473E+00, 0.1662286875439616E+00, 0.8310804130734020E-01, 0.4604735683437314E-01, 0.1806926893972028E-01, 0.1257133375345320E-01, 0.3600386373101646E-15, 0.6280777483216298E-03, 0.1060573000233681E-02, 0.1492322130169846E+01, 0.1292469707114105E-25, 0.5799349861429450E-06, 0.5584709508928944E-06, 0.1216694895544233E+01, 0.2047280287874868E-18, 0.1299955932331242E-09, 0.8534229075832313E-10, 0.1149617898796123E+01, 0.5088714046955349E-16, 0.6001732451841635E-09, 0.4081989685050919E-09, 0.1007011094632661E+01, 0.5578719308559292E-21, 0.1498995168909837E-07, 0.5625367692005608E-08, 0.9207056739913982E+00, 0.2728742825015995E-21, 0.2094882986118927E+02, 0.2094882986118927E+02, 0.9800000000000000E+02, 0.3004535147392290E+01, 0.4081632653061225E+01, 0.6223967900246754E-04, 0.6082352700464410E+00, 0.4038967834731580E-26, 0.1122996207538654E-05, 0.1754126012223728E-05, 0.5965144149455339E+00, 0.4386207914826929E-19, 0.1334483593164094E-04, 0.6982705884252015E-05, 0.2276577044879657E+00, 0.3148538924591216E-18, 0.9085150621800872E-04, 0.4628114404518947E-04, 0.1776272681811473E+00, 0.1149284743081177E-19, 0.3934684725502468E-05, 0.5044161242313764E-05, 0.1662286875439616E+00, 0.3944304526105059E-30, 0.1149340461723492E-04, 0.8510588625472410E-05, 0.8310804130734020E-01, 0.1540743955509789E-32, 0.1285467894756909E-02, 0.9239857033877289E-03, 0.4604735683437314E-01, 0.2169367489357782E-29, 0.2808730938050547E-03, 0.3455059327639833E-03, 0.1806926893972028E-01, 0.4614836295542919E-28, 0.7683442768713957E-06, 0.1846813906304985E-05, 0.1257133375345320E-01, 0.2538554393001216E-26, 0.4028502005942143E-04, 0.8466712427867894E-04}, + info: 0, + }, + { + z: []float64{0.5568197491282034E+00, 0.7338530212513171E+00, 0.1711270247791036E+00, 0.6696990680288049E+00, 0.1107644593582661E+00, 0.1487844153251054E+00, 0.6221478836712087E+00, 0.3739707210550620E+00, 0.6142936216832375E+00, 0.4504419047617665E+00, 0.1390832371836795E+00, 0.9602056283222130E+00, 0.4128383897877478E+00, 0.6202590221465013E+00, 0.5716294881431405E+00, 0.7009876531280159E+00, 0.8556346552408018E+00, 0.4300043005510307E+00, 0.5625488786064613E+00, 0.5236571943623558E+00, 0.2035297706440273E+00, 0.5324677179555473E+00, 0.9854023908952125E+00, 0.8088580870995794E+00, 0.7902887218423563E+00, 0.4196418643524230E+00, 0.5294914665193529E+00, 0.5947417442754066E-01, 0.2753919335549286E+00, 0.8807083336864044E+00, 0.6016279529290567E+00, 0.4144655693858035E-01, 0.4808953029705748E+00, 0.8506686680287934E-01, 0.2145404015834380E+00, 0.3020133878086849E+00, 0.8967140938263458E+00, 0.5344538485865815E+00, 0.2536120629120923E+00, 0.2552452828610304E+00, 0.9211096671641958E+00, 0.9028760680202415E+00, 0.3005599522329846E+00, 0.1197919551028395E+00, 0.3772579707039786E+00, 0.4157715274081910E+00, 0.2203607291065889E+00, 0.1084188329562713E+00, 0.5463193166123409E+00, 0.8107359194268960E+00, 0.6676190072779817E+00, 0.6711454730587799E+00, 0.6360708014875704E-01, 0.8242026716736568E+00, 0.3687006444230088E+00, 0.2216898043026083E-01, 0.4978612409817640E+00, 0.3144452507777135E+00, 0.3412289603988730E+00, 0.3266626310182044E+00, 0.4581662376370765E+00, 0.6985218227047190E+00, 0.6594479039269319E-01, 0.3938130402504401E+00, 0.9907371819490932E+00, 0.2478499678343852E+00, 0.3565435772734814E+00, 0.8420455744018336E+00, 0.2692247454903065E+00, 0.7327570909626056E+00, 0.1752776205164243E+00, 0.3569190164542581E+00, 0.2122621782757903E+00, 0.2056257129895300E+00, 0.6641092684756426E+00, 0.5386917539530447E+00, 0.8420713652275945E+00, 0.3587226239611645E+00, 0.9561844063661247E+00, 0.9126272291387975E+00, 0.5768542567999925E+00, 0.1972168939311342E+00, 0.5763304496236371E+00, 0.9478337554439876E+00}, + n: 21, + zOut: []float64{0.2593664459139222E+01, 0.2338172956520739E+01, 0.1783072679058981E+01, 0.1768637196043293E+01, 0.1688808722758796E+01, 0.1535694950136988E+01, 0.1488691522387158E+01, 0.1290354539321546E+01, 0.1187570436840380E+01, 0.1077679082742636E+01, 0.7925423484101771E+00, 0.6549022645335129E+00, 0.6315653598883190E+00, 0.5184441284206909E+00, 0.3791491409939438E+00, 0.3105722740860607E+00, 0.1128189367670211E+00, 0.7036440937731858E-01, 0.4999153992819697E-01, 0.2730914559941030E-01, 0.7241089204639656E-03, 0.7344040350490801E-18, 0.1828200693350630E-07, 0.2226187377323797E-07, 0.1488691522387158E+01, 0.4586948101010510E-17, 0.3930142187345605E-07, 0.5206893736347286E-07, 0.1290354539321546E+01, 0.6658190007940994E-20, 0.1499933495859733E-06, 0.7910043275590841E-07, 0.1187570436840380E+01, 0.2370536763713858E-16, 0.1192422432592963E-05, 0.6065280015592916E-06, 0.1077679082742636E+01, 0.6803770690793804E-23, 0.5360141282897325E-04, 0.3254990522417721E-04, 0.7925423484101771E+00, 0.8404284270509473E-23, 0.2030073020187486E+02, 0.2030073020187486E+02, 0.9700000000000000E+02, 0.2975056689342404E+01, 0.1030927835051546E+01, 0.1762395614510388E-04, 0.6315653598883190E+00, 0.2034005362457094E-16, 0.3178492515415974E-08, 0.1141868824523976E-08, 0.5184441284206909E+00, 0.1631704231140345E-20, 0.1154759308961600E-04, 0.3555504775624820E-05, 0.3791491409939438E+00, 0.9251916923707874E-19, 0.1302644751785016E-04, 0.1874642271188771E-04, 0.3105722740860607E+00, 0.1235671721938193E-25, 0.8697586673438179E-05, 0.7595546859022038E-05, 0.1128189367670211E+00, 0.1175733067685735E-18, 0.2174688695641498E-03, 0.1411064498403114E-03, 0.7036440937731858E-01, 0.5916456789157589E-30, 0.4997004849851516E-03, 0.7625846015345374E-03, 0.4999153992819697E-01, 0.3710108611279200E-20, 0.2898431160817185E-04, 0.2329024376647231E-03, 0.2730914559941030E-01, 0.1593079290931123E-17, 0.5731904499848677E-04, 0.7071520517918782E-04, 0.7241089204639656E-03, 0.1043820749788443E-25, 0.2096656950463827E-03, 0.4915700720935459E-03}, + info: 0, + }, + { + z: []float64{0.2129092067945103E+00, 0.6174796583507793E+00, 0.2209275310088966E+00, 0.1770681976597738E+00, 0.8468210663920229E+00, 0.7900600194799612E+00, 0.8319584509547915E+00, 0.8077183726155964E+00, 0.7964773509287093E+00, 0.2479492923952727E+00, 0.5169395370002006E-01, 0.6312063121285433E+00, 0.5688486960732374E+00, 0.3049379579822397E+00, 0.3779887662042721E+00, 0.4551165943302187E+00, 0.8807128836121972E+00, 0.1333615670826408E+00, 0.6901278826487529E+00, 0.8360350720177558E+00, 0.4190492004641316E+00, 0.9067077556412378E+00, 0.9762584494767094E+00, 0.9959763915912888E+00, 0.8503724779590973E+00, 0.6671116075685212E+00, 0.8841807167789617E+00, 0.6917331852931945E+00, 0.3414398718690443E+00, 0.2211364241075178E+00, 0.8057250135329493E+00, 0.4405475768508057E+00, 0.9321382353755537E+00, 0.6976358515081519E+00, 0.3254605598548291E+00, 0.1144237265035558E+00, 0.8547099978727912E-01, 0.3131314226614652E+00, 0.6940029038044814E+00, 0.2327469211945017E+00, 0.3523896044562020E+00, 0.6443116162172926E+00, 0.5382708884344491E+00, 0.9378966459649967E+00, 0.7274262519928346E+00, 0.4882092650189528E+00, 0.4497457043638882E+00, 0.8803511251742836E+00, 0.1077837527475992E+00, 0.4760275900323754E+00, 0.9725944612716640E+00, 0.4013370227296387E+00, 0.8188706727711300E+00, 0.7549128555022213E+00, 0.3045373312490215E+00, 0.9776368127163177E+00, 0.5516094182757485E+00, 0.8449472155130459E+00, 0.9309695118211208E+00, 0.6985346927019656E+00, 0.3270836933831586E+00, 0.2305805980953167E+00, 0.9135598850313159E+00, 0.2886818807914165E+00, 0.6607756604738726E+00, 0.7992086772120486E+00, 0.9191714969823802E+00, 0.9956222713515444E+00, 0.1646632133753003E+00, 0.8114783440114911E+00, 0.9650128806412454E+00, 0.1382218488636167E-01, 0.8464890579713791E+00, 0.2866238720970538E+00, 0.4485743907736028E-01, 0.5384705384174762E+00, 0.2996807710312754E-01, 0.7020716858392958E+00, 0.6280049430389886E+00, 0.2750308929159380E+00, 0.1648004007672321E-01, 0.8720570971091830E+00, 0.9962373992422624E+00, 0.8022759164194093E-01}, + n: 21, + zOut: []float64{0.3179557858974794E+01, 0.2694788878259719E+01, 0.2281326093492730E+01, 0.2196001939032204E+01, 0.1828355236773963E+01, 0.1586247682528960E+01, 0.1454772213395289E+01, 0.1286809233158695E+01, 0.1269332746846940E+01, 0.1099355321362049E+01, 0.9971216943768625E+00, 0.8310914612054856E+00, 0.4047131081238095E+00, 0.3869245862172090E+00, 0.3328473924133467E+00, 0.2908704078018756E+00, 0.1880200745280021E+00, 0.5784266149949692E-01, 0.4139216712761701E-01, 0.1651732519409763E-01, 0.3149646326524349E-02, 0.0000000000000000E+00, 0.5227593374295754E-11, 0.1202138413496143E-10, 0.1454772213395289E+01, 0.1393199790273629E-16, 0.1121878363020271E-09, 0.5353121918082171E-10, 0.1286809233158695E+01, 0.8659547037664508E-24, 0.1645814283637519E-08, 0.8601359367531547E-09, 0.1269332746846940E+01, 0.2823844361652584E-22, 0.5929700276768749E-08, 0.1126902625809321E-07, 0.1099355321362049E+01, 0.2358945595467410E-22, 0.2764360194400850E-05, 0.1553001254800959E-05, 0.9971216943768625E+00, 0.4450651748190101E-21, 0.2242703772863968E+02, 0.2242703772863967E+02, 0.1000000000000000E+03, 0.3015873015873016E+01, 0.3000000000000000E+01, 0.2632919892231646E-04, 0.4047131081238095E+00, 0.5820888909768840E-10, 0.2209233784503674E-04, 0.4136287504408153E-04, 0.3869245862172090E+00, 0.6462348535570008E-26, 0.3088379129783557E-03, 0.1528857353804532E-03, 0.3328473924133467E+00, 0.5549599819233453E-15, 0.8893453420684614E-08, 0.8741044673362129E-07, 0.2908704078018756E+00, 0.2289589891313465E-25, 0.5532514209995071E-04, 0.2183152999074702E-03, 0.1880200745280021E+00, 0.6113672015462841E-28, 0.9851023787951559E-03, 0.2769770083415459E-02, 0.5784266149949692E-01, 0.3571962178840741E-24, 0.3360295855593957E-02, 0.3874576703777444E-02, 0.4139216712761701E-01, 0.1555002616371658E-25, 0.3047908004675713E-02, 0.4283880536865950E-02, 0.1651732519409763E-01, 0.1498533807074276E-21, 0.9218134151523294E-06, 0.6993690185531638E-05, 0.3149646326524349E-02, 0.5476587948406352E-25, 0.9434027266146764E-03, 0.1032678112098284E-02}, + info: 0, + }, + { + z: []float64{0.5325973817915391E+00, 0.8075384328404875E+00, 0.2063920576624930E+00, 0.4895050697482526E+00, 0.3224859392283662E+00, 0.4597919629142447E+00, 0.5480240110168966E-01, 0.5228709929272914E+00, 0.9956836568223112E+00, 0.3978480622803672E+00, 0.9124816118920143E-01, 0.3247027355683270E+00, 0.9224658967837341E+00, 0.9984579111484309E+00, 0.8533112174943273E+00, 0.8907006920892125E+00, 0.3659539504394835E+00, 0.5561036191465061E+00, 0.7570794287369270E+00, 0.7781602931894585E+00, 0.8583979385494303E+00, 0.5883490719908564E+00, 0.2958788793535505E+00, 0.8441503484168636E+00, 0.7171074610327245E+00, 0.6324186559935309E+00, 0.6889002812298057E+00, 0.9679449699589238E-01, 0.8071604187540067E+00, 0.5036464295967858E+00, 0.3075050973746345E+00, 0.4354181299061508E+00, 0.5397482510302705E+00, 0.3266316370831254E+00, 0.7127302469392831E+00, 0.7822329043112050E+00, 0.1787867076882754E+00, 0.5059399114486356E+00, 0.1635357104384569E+00, 0.7923616792404551E+00, 0.8527619409672080E+00, 0.6624868870738707E+00, 0.6395827198572863E+00, 0.5045303635733072E+00, 0.5207053335438128E-01, 0.3872927271413512E+00, 0.8590236531191382E+00, 0.8644737695336893E+00, 0.5447620155822054E+00, 0.3420775682173337E+00, 0.1787889858336624E+00, 0.2962040723342502E+00, 0.1197091589896203E+00, 0.2582729465177200E+00, 0.8564224654785235E+00, 0.1003255861450059E+00, 0.5792751794645187E+00, 0.3553877787422808E+00, 0.3515051629979192E+00, 0.7026347035497048E+00, 0.7851727410421285E+00, 0.9451470000488936E+00, 0.1482591966327134E+00, 0.8035088707163867E+00, 0.8018983228501475E-02, 0.5992223740738118E+00, 0.3369698862429809E+00, 0.9971168486495201E+00, 0.7449267587097297E+00, 0.5929357935363798E+00, 0.8575900212486389E+00, 0.8115297023854162E+00, 0.3380359989630263E+00, 0.8328174310878843E+00, 0.8255713836908419E+00, 0.7399149789721748E+00, 0.1725333812438860E+00, 0.6828663265380140E+00, 0.6234367510076171E+00, 0.5628070366267671E+00, 0.8501068267959022E-01, 0.9315797050119701E+00, 0.1842029704669090E+00, 0.9504814303233714E+00}, + n: 21, + zOut: []float64{0.2923425454171414E+01, 0.2535311958925162E+01, 0.2192080092128743E+01, 0.1925146455902099E+01, 0.1841700496719334E+01, 0.1753280727277585E+01, 0.1582442080550360E+01, 0.1581069533140902E+01, 0.1420113611638973E+01, 0.1070153147168429E+01, 0.9980373856163754E+00, 0.9531244298503998E+00, 0.7077665812605668E+00, 0.5659990522281487E+00, 0.3146390113583965E+00, 0.2516605740660456E+00, 0.1663945631562664E+00, 0.1260010860507715E+00, 0.4255237190875141E-01, 0.7100815132372204E-02, 0.1566331927046113E-03, 0.4122332130840440E-22, 0.4572750287882177E-06, 0.8150029788456509E-06, 0.1582442080550360E+01, 0.6246970091107327E-19, 0.1184058245159526E-05, 0.5957129004529113E-06, 0.1581069533140902E+01, 0.2712893915232508E-21, 0.4684400026881307E-05, 0.9374804625040887E-05, 0.1420113611638973E+01, 0.4814409269321697E-22, 0.2425457953812455E-04, 0.3059673263223507E-04, 0.1070153147168429E+01, 0.4457872866361589E-11, 0.2849702090992769E-05, 0.4079444611357521E-05, 0.9980373856163754E+00, 0.2148022614677702E-19, 0.2295815606144379E+02, 0.2295815606144380E+02, 0.9700000000000000E+02, 0.2981859410430839E+01, 0.2061855670103093E+01, 0.4336961109868880E-06, 0.7077665812605668E+00, 0.3355216099479021E-19, 0.2178215603335118E-03, 0.1596478432727446E-03, 0.5659990522281487E+00, 0.3777948407501058E-19, 0.1732350582817826E-03, 0.1687341431970761E-03, 0.3146390113583965E+00, 0.4215672677501087E-24, 0.8708765796225133E-03, 0.5753505295482449E-03, 0.2516605740660456E+00, 0.8872339250080977E-20, 0.2809442395187102E-02, 0.2330568324677941E-02, 0.1663945631562664E+00, 0.1848892746611746E-31, 0.7424955400801435E-06, 0.1353946060853610E-06, 0.1260010860507715E+00, 0.7099748146989106E-27, 0.5320431162642944E-03, 0.1085271179151602E-03, 0.4255237190875141E-01, 0.2808116620904140E-21, 0.1709028753951538E-02, 0.8528114742759547E-03, 0.7100815132372204E-02, 0.4930380657631324E-31, 0.2904056487242609E-02, 0.3026916823887611E-02, 0.1566331927046113E-03, 0.0000000000000000E+00, 0.2549645590833870E-02, 0.2592045976400073E-02}, + info: 0, + }, + { + z: []float64{0.6141085085904113E+00, 0.3421028526671319E+00, 0.2523050636037050E-01, 0.6894939888024587E+00, 0.1106696902059259E+00, 0.3232796216228777E+00, 0.5026462674631121E+00, 0.4061906185674803E+00, 0.2489870821257593E+00, 0.5655528330838598E+00, 0.8215445521378404E+00, 0.6847122058387792E+00, 0.1058838690465073E+00, 0.3150742731806708E+00, 0.6299058795873502E-01, 0.2792122534089967E+00, 0.6156682980944264E+00, 0.6784924553414444E+00, 0.5548029179057333E+00, 0.9875334352131669E+00, 0.7114388615166174E+00, 0.4680838251435693E+00, 0.9939378516921551E+00, 0.9317334719497590E+00, 0.7166727913665860E+00, 0.9133735504519750E+00, 0.6652039093977162E+00, 0.8687642647047388E+00, 0.5616945762819415E+00, 0.3985759546461669E+00, 0.7431799484571856E+00, 0.7126935860242257E+00, 0.1006984098734091E+00, 0.3341210154632034E+00, 0.8752290131259591E+00, 0.9044047683690323E+00, 0.2748574881470656E+00, 0.9153414825361147E+00, 0.1879700367171477E-01, 0.4139829057070108E+00, 0.6163962814716032E+00, 0.4758310984958897E+00, 0.7283265374189019E-01, 0.4293121596195046E+00, 0.1627494487778676E+00, 0.6477819718948226E+00, 0.1769525517070647E-01, 0.8315284238294101E+00, 0.3951374239126071E-01, 0.8607842403091001E+00, 0.4542147501441236E+00, 0.7533183963616871E+00, 0.3860688952521878E+00, 0.7194066659377851E+00, 0.5625319388225433E+00, 0.2666855367146020E+00, 0.1952117588514313E+00, 0.4351982558470283E+00, 0.5735131371596182E+00, 0.6135067797741378E-01, 0.6627925797553079E+00, 0.5958408703801275E+00, 0.1272760770553625E+00, 0.9764806486481753E+00, 0.3738230266231765E+00, 0.8498786384730982E+00, 0.9509621583287799E+00, 0.5442964253426497E+00, 0.1274761736897801E+00, 0.8749459887021185E+00, 0.5319902581507450E+00, 0.4050330112540623E-01, 0.4679445276719574E-01, 0.6398654173496683E+00, 0.1619398995392787E+00, 0.2834692561637309E-01, 0.7369067773846130E+00, 0.2655208002136908E+00, 0.1902643003388997E+00, 0.7054378485643029E+00, 0.8869999325574263E+00, 0.1700725746174213E+00, 0.7638558771240449E+00, 0.3965145662986846E+00}, + n: 21, + zOut: []float64{0.3026266675500349E+01, 0.2485098580281992E+01, 0.2208517136068298E+01, 0.2089817225148914E+01, 0.1987605159106218E+01, 0.1671782272803828E+01, 0.1288709839574181E+01, 0.1226108028801468E+01, 0.1094715872236073E+01, 0.9893293804315401E+00, 0.9470004635866569E+00, 0.8354737908875075E+00, 0.7678170961167213E+00, 0.5139691139127377E+00, 0.3402258729602133E+00, 0.2640682732152568E+00, 0.1814642316568930E+00, 0.9210283120697343E-01, 0.5017295169510767E-01, 0.1311272184039149E-01, 0.2605821149103687E-06, 0.8821141249794507E-26, 0.1703621403540070E-06, 0.1022946688596755E-06, 0.1288709839574181E+01, 0.0000000000000000E+00, 0.7771811135093639E-06, 0.1129025861285597E-05, 0.1226108028801468E+01, 0.8850832554089860E-22, 0.6461044606060110E-07, 0.3214361230688769E-07, 0.1094715872236073E+01, 0.5589172803550431E-19, 0.3128365184192157E-08, 0.1088448901615084E-07, 0.9893293804315401E+00, 0.4249640396990678E-22, 0.2862531707476509E-05, 0.1047704834723032E-05, 0.9470004635866569E+00, 0.2336393132634786E-16, 0.2207335777761344E+02, 0.2207335777761343E+02, 0.1020000000000000E+03, 0.3043083900226757E+01, 0.9803921568627451E+00, 0.1031792375203169E-03, 0.7678170961167213E+00, 0.8633839815190009E-18, 0.1747705279299585E-04, 0.1213546251050483E-04, 0.5139691139127377E+00, 0.2016356967855187E-17, 0.7704963297163309E-04, 0.2063636533685701E-03, 0.3402258729602133E+00, 0.5916456789157589E-30, 0.2417908304509407E-03, 0.2207145059751390E-03, 0.2640682732152568E+00, 0.1479114197289397E-30, 0.1687694376453652E-02, 0.8888286778685235E-03, 0.1814642316568930E+00, 0.1064934658613210E-15, 0.3591290150683059E-02, 0.7604711042910346E-02, 0.9210283120697343E-01, 0.2042102137240287E-23, 0.1463034917919357E-02, 0.1882622569903463E-02, 0.5017295169510767E-01, 0.2551739098626718E-22, 0.3961160948815250E-03, 0.9438210467320612E-03, 0.1311272184039149E-01, 0.1972152263052530E-29, 0.6693623055505279E-03, 0.9046122259092353E-03, 0.2605821149103687E-06, 0.3100321587303656E-14, 0.3978735902689679E-02, 0.4253573989104679E-02}, + info: 0, + }, + { + z: []float64{0.8778106868894964E+00, 0.4777882175260769E+00, 0.1820603962716897E+00, 0.7891460918977841E+00, 0.7131176407472852E+00, 0.2166796106605611E+00, 0.7093860568912320E+00, 0.6747559124413653E+00, 0.1755802732664898E+00, 0.2538529139601842E-01, 0.3839736304139417E+00, 0.4972278527690542E+00, 0.2219918935874782E+00, 0.6587468361459490E+00, 0.6959875726535614E+00, 0.8785259347357933E+00, 0.4385001119617188E+00, 0.2992124106963234E-01, 0.9853525010355352E+00, 0.1842422327604198E-01, 0.7939453301916002E+00, 0.8502867854292200E+00, 0.6683895767567380E+00, 0.8502503508041696E+00, 0.2705991244761674E-02, 0.2273590703395093E+00, 0.1996606140173212E+00, 0.5828845765712893E+00, 0.7928614954547730E+00, 0.1675870051229429E+00, 0.3078809727828886E+00, 0.6073537805183471E-01, 0.3498986727103111E+00, 0.4266607326484094E+00, 0.7790595486765419E+00, 0.6274781693151706E+00, 0.3468808495278470E+00, 0.4002308549977796E+00, 0.8927740819756569E+00, 0.5380209790008849E+00, 0.9944530064668308E+00, 0.8382845348910617E+00, 0.6578833875204938E+00, 0.6784609218227333E-01, 0.9880398702345439E-01, 0.1591591396324092E+00, 0.3625625292925116E-01, 0.7834491156107602E+00, 0.8935128283958205E-01, 0.6534249936105881E+00, 0.9608003610697393E+00, 0.9122649849010867E+00, 0.3064782192618438E+00, 0.6165812021330105E+00, 0.3942978367050161E+00, 0.2389206118855702E+00, 0.4357310309586615E+00, 0.6366539061757281E+00, 0.2487697657706114E+00, 0.3158114775243555E+00, 0.4359459725257834E+00, 0.8521387333399649E+00, 0.7376171834812397E+00, 0.7198918826028659E+00, 0.3787355957929660E+00, 0.5132345781976363E+00, 0.5880413889667653E+00, 0.8394688090887562E+00, 0.3673771632022454E+00, 0.1291928261630060E+00, 0.6552015571219838E+00, 0.7918941075374089E+00, 0.3759434916876330E+00, 0.2131514444401432E+00, 0.5997464643577372E+00, 0.8626895671971565E+00, 0.1962050188754781E+00, 0.6291330853690040E+00, 0.6873926281549517E+00, 0.8949666870308315E-01, 0.1384684788210775E+00, 0.8959871983479050E+00, 0.5967626810459625E+00, 0.6838507108780668E+00}, + n: 21, + zOut: []float64{0.2344484145674817E+01, 0.2205594465347172E+01, 0.2180337141043826E+01, 0.1936893457336740E+01, 0.1819297464222486E+01, 0.1595314798543036E+01, 0.1497965290687764E+01, 0.1192635586559562E+01, 0.1109297670462514E+01, 0.1021894664697417E+01, 0.8474592078637809E+00, 0.7996737801504824E+00, 0.5357931354846659E+00, 0.5077230661246940E+00, 0.4005808269588222E+00, 0.2350964781455809E+00, 0.1732854339186359E+00, 0.5510322151786835E-01, 0.3865442753785928E-01, 0.1308309165665133E-01, 0.1986637888070920E-03, 0.1267902442921281E-19, 0.1632713022477316E-10, 0.9197304681744396E-11, 0.1497965290687764E+01, 0.6540946849634405E-22, 0.1644600422568816E-11, 0.2569557641484267E-11, 0.1192635586559562E+01, 0.1886570321166912E-23, 0.1155544514329289E-09, 0.3178796095468434E-10, 0.1109297670462514E+01, 0.2958228394578794E-30, 0.1814581278982536E-06, 0.5763166468812303E-07, 0.1021894664697417E+01, 0.1648133134119960E-16, 0.5817023408243420E-07, 0.2381874475610022E-07, 0.8474592078637809E+00, 0.5828670879282072E-15, 0.2051036601772319E+02, 0.2051036601772318E+02, 0.1250000000000000E+03, 0.3639455782312925E+01, 0.8800000000000001E+01, 0.1964091724818299E-07, 0.5357931354846659E+00, 0.3518203713570956E-14, 0.1200151291154190E-07, 0.2251426423705210E-07, 0.5077230661246940E+00, 0.6882401190382613E-24, 0.1803872146382089E-06, 0.4763453660743515E-06, 0.4005808269588222E+00, 0.1559915108945621E-18, 0.4978941410546894E-05, 0.5275156660739611E-05, 0.2350964781455809E+00, 0.1004043408045437E-17, 0.5647304839276210E-04, 0.2873291365503010E-04, 0.1732854339186359E+00, 0.2485883728081419E-23, 0.9907264920144563E-04, 0.1293007080503375E-03, 0.5510322151786835E-01, 0.0000000000000000E+00, 0.9623294785827948E-04, 0.7898847596644510E-04, 0.3865442753785928E-01, 0.0000000000000000E+00, 0.2279226510196514E-03, 0.3149968919986460E-03, 0.1308309165665133E-01, 0.4893402802699089E-27, 0.4145854568122489E-03, 0.3196372933697030E-03, 0.1986637888070920E-03, 0.1930680189793120E-17, 0.2183385452652873E-03, 0.3171631588309268E-03}, + info: 0, + }, + { + z: []float64{0.3053504558052776E+00, 0.2234484687205406E+00, 0.6531459952011753E+00, 0.3122060875846019E+00, 0.9991431676363117E+00, 0.2727966396486101E+00, 0.9325466197866266E+00, 0.9368849148298319E+00, 0.8561644447997885E+00, 0.1054815122266185E+00, 0.4923718332155202E-01, 0.9268095624277023E+00, 0.1888864280722891E+00, 0.7655148720572605E+00, 0.1232767826602820E+00, 0.5903563091717590E+00, 0.9248190356569348E+00, 0.5395288290327440E+00, 0.9028402566412551E+00, 0.9500520891471187E-01, 0.8953008781613688E+00, 0.2933361506740548E+00, 0.8453264440546789E+00, 0.5481580781657376E+00, 0.3587646761786403E+00, 0.5176903549368316E+00, 0.7562422108585272E+00, 0.9675296263022207E+00, 0.8986594456301542E+00, 0.5421338625853966E-01, 0.1201688601088308E+00, 0.6190380352364769E+00, 0.5038255434020116E+00, 0.6721007162690862E+00, 0.5702376374225947E+00, 0.9284095682432886E+00, 0.3695163217482177E+00, 0.6039359484498441E-01, 0.4652604684312921E+00, 0.8651698808632446E-01, 0.7546245127264203E+00, 0.7397909213681499E+00, 0.1212064081570199E+00, 0.3507242515197573E+00, 0.1903823153835104E+00, 0.7217789084869874E-01, 0.4631739813227773E+00, 0.4692891642215747E+00, 0.4583968848602870E+00, 0.1862358222844885E+00, 0.2939086301666586E+00, 0.5739509914073745E+00, 0.2602639918141684E+00, 0.7265362515535626E+00, 0.2180031380994948E+00, 0.1132710387386646E+00, 0.7997129355612416E+00, 0.7503609043894605E+00, 0.7921549516519859E+00, 0.2820213454373731E+00, 0.3757885220124352E+00, 0.7700990985029622E+00, 0.7233316318551536E+00, 0.1305854233773539E+00, 0.7245124401476205E+00, 0.5999815977622437E+00, 0.3886468370487757E+00, 0.5608149286383455E+00, 0.4298380566755162E+00, 0.6436590616913128E+00, 0.3743035898091585E-01, 0.4516061963302198E-01, 0.3504820364503235E+00, 0.4814816352089226E+00, 0.5678245050510763E+00, 0.5711961955150159E+00, 0.9549329198325482E+00, 0.8527165734568565E-01, 0.4185783350739758E-01, 0.5702414021975877E-01, 0.2302271730247050E+00, 0.7442529870754924E+00, 0.5366636699040384E+00, 0.8085683101567075E+00}, + n: 21, + zOut: []float64{0.2590499366480712E+01, 0.2541239603587953E+01, 0.2259909426243320E+01, 0.2181782566945434E+01, 0.1886341857097904E+01, 0.1651483296972034E+01, 0.1427705031981996E+01, 0.1248256205386413E+01, 0.1112814709657656E+01, 0.9343995210628773E+00, 0.8379224813887226E+00, 0.8181328249547786E+00, 0.6165308413237942E+00, 0.4939038343854810E+00, 0.4603621358717260E+00, 0.3639045182225083E+00, 0.3137819362841643E+00, 0.1577326270698492E+00, 0.8198100142281199E-01, 0.9578206270736807E-02, 0.4942793252781514E-03, 0.1292469707114106E-22, 0.1980335658106781E-04, 0.1681298419390782E-04, 0.1427705031981996E+01, 0.2584939414228211E-25, 0.8200031816835676E-05, 0.9102296987148495E-05, 0.1248256205386413E+01, 0.4930380657631324E-30, 0.4104488055426074E-09, 0.2576051753309951E-09, 0.1112814709657656E+01, 0.6452508963690269E-19, 0.2339325112754308E-08, 0.4010758969857423E-08, 0.9343995210628773E+00, 0.2041003537989240E-20, 0.4754834042401540E-06, 0.1343807701186157E-06, 0.8379224813887226E+00, 0.2942145729531872E-22, 0.2198875627193616E+02, 0.2198875627193615E+02, 0.1030000000000000E+03, 0.3158730158730159E+01, 0.5825242718446602E+01, 0.2325395492704734E-05, 0.6165308413237942E+00, 0.1475671084242936E-18, 0.4982404846255511E-06, 0.2497087821784679E-06, 0.4939038343854810E+00, 0.1295808538938520E-16, 0.6559194735079054E-05, 0.3408173383041987E-05, 0.4603621358717260E+00, 0.5811344985782108E-17, 0.9559725090946887E-05, 0.1189458663431952E-04, 0.3639045182225083E+00, 0.2913839059670682E-18, 0.4863259217476146E-04, 0.7411068946771063E-04, 0.3137819362841643E+00, 0.2338183723075079E-26, 0.4219303942492233E-03, 0.5983359002845232E-03, 0.1577326270698492E+00, 0.3451266460341927E-30, 0.4370512454739224E-03, 0.2953761682364422E-03, 0.8198100142281199E-01, 0.2482356093574565E-20, 0.7632038538424591E-04, 0.1389505478745866E-03, 0.9578206270736807E-02, 0.1680537859656637E-20, 0.1168521819007177E-01, 0.1200804951998557E-01, 0.4942793252781514E-03, 0.1967697241141140E-19, 0.1184783913560175E-01, 0.1590443390723593E-01}, + info: 0, + }, + { + z: []float64{0.9721612501531746E+00, 0.9226086145236946E+00, 0.6294635256706198E+00, 0.3023176111891041E+00, 0.6049371291087220E+00, 0.2862933293136216E+00, 0.8819078559307578E+00, 0.5258944749310531E+00, 0.1024274135843443E+00, 0.4745865163816484E+00, 0.3569366663070145E+00, 0.5081536020377282E+00, 0.6994675492692721E+00, 0.3184330055525583E+00, 0.4062572718658636E+00, 0.8497577069296732E+00, 0.7686323719242980E+00, 0.8873781649289114E+00, 0.5445815352331720E+00, 0.5465168091072755E+00, 0.2655612328242208E+00, 0.7149116271405493E+00, 0.2779393895548951E+00, 0.1344927254674255E-01, 0.4544708454847078E+00, 0.5332505496545747E-01, 0.3223583007255554E+00, 0.4314145703973596E+00, 0.6194759383350579E+00, 0.9673744275195654E+00, 0.5445933229599376E-01, 0.2359803760372408E+00, 0.4349989237395262E+00, 0.3983243124260842E+00, 0.1549760127081995E+00, 0.6483062457720113E+00, 0.9796384288763583E+00, 0.2088098624466561E-01, 0.7266086220595113E+00, 0.7787182393455840E+00, 0.2714545750078465E+00, 0.3281766266219532E-01, 0.4443206765749519E+00, 0.7385116967559627E+00, 0.4742748966298079E+00, 0.2719801119596308E+00, 0.5535252469642412E+00, 0.6819653774052530E+00, 0.5802197659205470E+00, 0.8706014802153047E+00, 0.7899732601913489E-01, 0.6149130585720997E+00, 0.1184080138409910E+00, 0.7335155686110397E+00, 0.3161056790243246E+00, 0.4751009230144272E+00, 0.6074228340613933E+00, 0.1834459697241099E+00, 0.5602196728537751E+00, 0.6036792416269905E+00, 0.4996379576165632E+00, 0.5762117563802562E+00, 0.4313302593954876E+00, 0.2357090997139660E+00, 0.5266696040444221E+00, 0.4943568418910921E+00, 0.5194970579745682E+00, 0.8729901711287622E+00, 0.1253423978225398E+00, 0.3249303186427334E+00, 0.1476841747547597E+00, 0.8115004890141919E+00, 0.3358761522855614E+00, 0.6267425544884889E+00, 0.8684373664078195E+00, 0.3410509649937432E+00, 0.1223171934609151E+00, 0.6692100819077175E+00, 0.8714060240466885E+00, 0.8435328911476530E+00, 0.3613173587051273E+00, 0.5970888673100956E+00, 0.4814113673780336E+00, 0.9518076426657822E+00}, + n: 21, + zOut: []float64{0.2554276088974017E+01, 0.2353122577016648E+01, 0.1866240795386955E+01, 0.1792222013488891E+01, 0.1776522631286352E+01, 0.1671843747376224E+01, 0.1608565757744856E+01, 0.1413448668253747E+01, 0.9978397039940720E+00, 0.9776727877490632E+00, 0.8701050228770406E+00, 0.6522479060818760E+00, 0.6295532782699175E+00, 0.4076513128864766E+00, 0.3045303763029391E+00, 0.2026925943270836E+00, 0.1597713759311400E+00, 0.1149331809326307E+00, 0.5501161781795570E-01, 0.3472328989596482E-02, 0.1615352262160075E-02, 0.2261810287929078E-15, 0.1434223756681676E-21, 0.1189989751754647E-20, 0.1608565757744856E+01, 0.1068494074045434E-17, 0.1018285523195584E-14, 0.1812446834981097E-15, 0.1413448668253747E+01, 0.8361925595342725E-26, 0.5806129122189708E-11, 0.1848580748818003E-11, 0.9978397039940720E+00, 0.5222833230866609E-21, 0.9842396145073251E-07, 0.4923018478143697E-07, 0.9776727877490632E+00, 0.9540591325261466E-21, 0.1504532523487471E-05, 0.7619936176069947E-06, 0.8701050228770406E+00, 0.2405710216561998E-25, 0.2041333911794964E+02, 0.2041333911794964E+02, 0.1050000000000000E+03, 0.3108843537414966E+01, 0.6666666666666667E+01, 0.1010063659896995E-05, 0.6295532782699175E+00, 0.2958228394578794E-30, 0.7231781167780556E-06, 0.8027785243996724E-06, 0.4076513128864766E+00, 0.2327139670401985E-28, 0.4311361064418766E-06, 0.4365718303993244E-06, 0.3045303763029391E+00, 0.3511198893363720E-17, 0.5813968676396444E-06, 0.4990623034093460E-06, 0.2026925943270836E+00, 0.5787194672316798E-22, 0.1414410322798341E-05, 0.1084116171450400E-05, 0.1597713759311400E+00, 0.3368436065293720E-27, 0.4438807230072854E-05, 0.3295442179394680E-05, 0.1149331809326307E+00, 0.3973698114522315E-22, 0.1450590122472916E-04, 0.1074561246336364E-04, 0.5501161781795570E-01, 0.1153335343143272E-20, 0.9954779132989017E-07, 0.6305695341872095E-07, 0.3472328989596482E-02, 0.7183968878891587E-15, 0.2465868832870137E-03, 0.3524118878925340E-03, 0.1615352262160075E-02, 0.1517768381645227E-26, 0.5410549418889337E-03, 0.6396403869804795E-03}, + info: 0, + }, + { + z: []float64{0.9945523629868341E+00, 0.6311483525653909E+00, 0.7029190400645571E+00, 0.6452581068575963E+00, 0.9353553331334358E+00, 0.1547193049011500E+00, 0.5087511216875095E+00, 0.8821879483245458E+00, 0.5873463835171173E+00, 0.3391476900726194E+00, 0.3121839954924539E+00, 0.2777103145160921E+00, 0.2404463284577694E+00, 0.9114535183484027E+00, 0.4707329974301702E+00, 0.8965398451252625E+00, 0.6082343132413309E+00, 0.6509204493235183E+00, 0.1573499033176421E+00, 0.7416865701488552E+00, 0.1617007503826062E-01, 0.9896605969885931E+00, 0.3427350027671039E+00, 0.9677837053324486E+00, 0.1744936477417883E+00, 0.1063275349300943E+00, 0.7956875801511568E+00, 0.8998967378241718E-01, 0.9957418429488507E-01, 0.2587083053394715E+00, 0.3753593926504107E+00, 0.7537263520315082E+00, 0.1726167393116790E+00, 0.1420490749456633E+00, 0.1475360304745418E+00, 0.3281044300775052E+00, 0.4011897283558843E+00, 0.5039659382748809E+00, 0.8444659776686902E-01, 0.6685320205580927E+00, 0.8425776598223370E+00, 0.6334616337862548E+00, 0.6754035119469365E+00, 0.3594856315188868E+00, 0.4308279252773916E+00, 0.2170629535054914E+00, 0.5040120070238915E+00, 0.3780998968579012E+00, 0.9176188652711103E+00, 0.1603892455353655E+00, 0.2475008720560291E+00, 0.4414989878913728E+00, 0.3466658552370731E+00, 0.3098329951977107E+00, 0.8940921934240968E+00, 0.6686136942966417E+00, 0.4049936818549904E-01, 0.1308695446239941E+00, 0.8770734618597430E+00, 0.7917220872288512E+00, 0.5736823795257117E+00, 0.5474219864141461E+00, 0.3320663514826834E+00, 0.5824816531032581E+00, 0.6748067573570548E+00, 0.8139348519761679E+00, 0.1984641509226878E+00, 0.5557729841117627E+00, 0.1101812804319026E+00, 0.2169710965518002E+00, 0.5846617154920911E+00, 0.9784843983810533E+00, 0.8650267562586114E+00, 0.4041298540058539E+00, 0.9548165813531374E+00, 0.3839697059508718E+00, 0.4296171922210591E+00, 0.9617664542372570E+00, 0.2102779850721345E+00, 0.6135130181658475E+00, 0.3331715196673474E+00, 0.3177082868916457E+00, 0.2836520073686416E+00, 0.4452894940247868E+00}, + n: 21, + zOut: []float64{0.2413112525759640E+01, 0.2309698811549223E+01, 0.1971065496840386E+01, 0.1839093033734385E+01, 0.1586321309986888E+01, 0.1384287501933647E+01, 0.1357349915568794E+01, 0.1342137050614370E+01, 0.1098398899504136E+01, 0.1013688381736709E+01, 0.8838922773071145E+00, 0.7023193003094995E+00, 0.6083268670387161E+00, 0.3967105732701523E+00, 0.3295901758335739E+00, 0.2610566591740404E+00, 0.2254040681461952E+00, 0.1107925081061023E+00, 0.7084089717166595E-01, 0.5790734022898784E-02, 0.1162539701808497E-05, 0.2217532248565769E-17, 0.1400266087055540E-09, 0.1806586784837133E-09, 0.1357349915568794E+01, 0.1160047396826257E-18, 0.1994113072724655E-16, 0.4228494360227003E-16, 0.1342137050614370E+01, 0.1172187884313513E-15, 0.1255075745859590E-14, 0.2503873040081153E-15, 0.1098398899504136E+01, 0.3711182370878063E-20, 0.5744299067797088E-08, 0.4873476684669810E-08, 0.1013688381736709E+01, 0.1283916659070448E-18, 0.9737119066622311E-08, 0.8382615528986061E-08, 0.8838922773071145E+00, 0.3385457556489824E-15, 0.1990987815014785E+02, 0.1990987815014784E+02, 0.1050000000000000E+03, 0.3324263038548753E+01, 0.5714285714285714E+01, 0.5531678096648157E-07, 0.6083268670387161E+00, 0.9327491343333244E-26, 0.3094358165149238E-06, 0.4992693882721107E-06, 0.3967105732701523E+00, 0.1615587133892632E-26, 0.5013465632663534E-06, 0.4474558637993164E-06, 0.3295901758335739E+00, 0.7527343574232552E-22, 0.6917755140723670E-06, 0.9191878134168280E-06, 0.2610566591740404E+00, 0.8992644540970212E-27, 0.3283328599477859E-08, 0.8980185396558612E-09, 0.2254040681461952E+00, 0.2761013168273541E-29, 0.1566859737304233E-05, 0.9651044230345755E-05, 0.1107925081061023E+00, 0.7853700447084989E-18, 0.2494389596499284E-03, 0.3103855763358142E-03, 0.7084089717166595E-01, 0.7910121402691465E-20, 0.9848486231185840E-03, 0.1285663115805527E-02, 0.5790734022898784E-02, 0.1925929944387236E-33, 0.1531134660067926E-02, 0.1103959511478054E-02, 0.1162539701808497E-05, 0.0000000000000000E+00, 0.3553926119432854E-02, 0.1161337136649311E-01}, + info: 0, + }, + { + z: []float64{0.6912525216559012E+00, 0.7535513505900934E+00, 0.9471932644608124E+00, 0.3186447229836621E+00, 0.5324891284853083E+00, 0.8568362673509099E+00, 0.7683599820389093E+00, 0.5584553004793524E+00, 0.5571013534938567E+00, 0.9300192917069305E-01, 0.8580829209571639E+00, 0.7019126526839274E+00, 0.6637712341629651E+00, 0.1211000088170944E+00, 0.6340253546080570E+00, 0.8089912896293909E+00, 0.9056005723453709E+00, 0.8259750504337368E+00, 0.7787230128973186E+00, 0.5552567089885843E+00, 0.1575217143336131E+00, 0.6258385609742768E+00, 0.3943745586872103E+00, 0.2414131111537543E-02, 0.1491577729788018E-01, 0.3231570165180105E+00, 0.6629837458829935E+00, 0.3692715436026686E+00, 0.4217957028148089E+00, 0.9587355452830710E+00, 0.2048474370070816E+00, 0.9514275263988156E+00, 0.6824099372375696E+00, 0.4368303647429550E-01, 0.1779948598152153E+00, 0.8894462775192779E+00, 0.5101271266317630E+00, 0.9448652224292025E+00, 0.2265718177112338E+00, 0.3995811139403516E+00, 0.8380789267629041E+00, 0.6621441253102893E+00, 0.1548712624835822E+00, 0.6028850196944033E+00, 0.6938032609628844E+00, 0.6847684356722229E+00, 0.5160938472467536E+00, 0.2489894297094153E+00, 0.1603949345362032E-01, 0.8469682453172568E+00, 0.1332301650751776E+00, 0.4964641576870391E+00, 0.8955382322295532E+00, 0.8913224930710517E-01, 0.1632933980261509E+00, 0.7671629642421702E+00, 0.1918190416387825E+00, 0.4660642407804531E+00, 0.3421851388276426E+00, 0.6793284417353496E-03, 0.4856583571413033E+00, 0.6596584184483706E+00, 0.3999565195667565E-01, 0.4265147212719423E+00, 0.1721559491949431E-01, 0.4779030554385033E-01, 0.9628058707102425E+00, 0.4575395386200597E+00, 0.3526890078762277E+00, 0.7271726865364773E+00, 0.1741804541232641E+00, 0.3524640041347155E+00, 0.2143698389021181E+00, 0.9553499123803968E+00, 0.7803670081719427E+00, 0.7906509834069840E+00, 0.5939624443460740E+00, 0.5439294231719827E+00, 0.4026522884432556E+00, 0.2400403086558794E+00, 0.1695045416332096E+00, 0.8774151073165960E+00, 0.9528799076371641E-01, 0.6357307125994049E-01}, + n: 21, + zOut: []float64{0.2768602537214622E+01, 0.2449987435840808E+01, 0.2103617452638331E+01, 0.2091492233971247E+01, 0.2040261542124423E+01, 0.1984511273424848E+01, 0.1507960384149227E+01, 0.1491386484166052E+01, 0.1283295633334833E+01, 0.1065640575633715E+01, 0.9760063516861833E+00, 0.9535053549649605E+00, 0.6117733318422185E+00, 0.5156356643703764E+00, 0.4217391763517565E+00, 0.2514332616796913E+00, 0.1056943786041289E+00, 0.6556299181229375E-01, 0.2554189252987301E-01, 0.1599343544217954E-01, 0.7248128851221257E-03, 0.1757582096832414E-26, 0.8938568486456872E-12, 0.7801064326234513E-12, 0.1507960384149227E+01, 0.1792073872399063E-19, 0.2167105506392983E-08, 0.2566615495401212E-08, 0.1491386484166052E+01, 0.2939740300877914E-17, 0.1513553473151668E-08, 0.1292098164447321E-08, 0.1283295633334833E+01, 0.5002192774679673E-18, 0.3422853236655498E-09, 0.3087733884567774E-09, 0.1065640575633715E+01, 0.2649562899583917E-24, 0.1824851422869684E-09, 0.1969539993879423E-09, 0.9760063516861833E+00, 0.4849588587138365E-15, 0.2273036620466689E+02, 0.2273036620466689E+02, 0.1110000000000000E+03, 0.3401360544217687E+01, 0.6306306306306307E+01, 0.7012703734578152E-09, 0.6117733318422185E+00, 0.2636779683484747E-15, 0.8832037497597917E-08, 0.1377654767646391E-07, 0.5156356643703764E+00, 0.0000000000000000E+00, 0.4403364729024244E-07, 0.2921450058151117E-07, 0.4217391763517565E+00, 0.5116160632510206E-16, 0.4627032593211780E-06, 0.6780935482482274E-06, 0.2514332616796913E+00, 0.3477119313860159E-18, 0.8396751469149006E-05, 0.1191099168408868E-04, 0.1056943786041289E+00, 0.3125614770312806E-14, 0.3873238345753621E-04, 0.1564927337192913E-03, 0.6556299181229375E-01, 0.2145521217817673E-17, 0.9476510350371504E-03, 0.9104754488359111E-03, 0.2554189252987301E-01, 0.1508279173816323E-23, 0.1093077353977330E-02, 0.3191708039391989E-03, 0.1599343544217954E-01, 0.1319576415787468E-18, 0.1003863779460019E-02, 0.1271197433268307E-02, 0.7248128851221257E-03, 0.5169135658374832E-21, 0.1128681157512944E-02, 0.4574374031799749E-02}, + info: 0, + }, + { + z: []float64{0.8514967554120231E+00, 0.1903564904561825E+00, 0.9315134585755248E+00, 0.6865565499502658E+00, 0.9874780893034819E+00, 0.4243732836164926E-01, 0.4493254789963134E+00, 0.1218497220886967E+00, 0.3032420422448456E-01, 0.4472006833337416E+00, 0.7764061193501844E+00, 0.2765680149425037E+00, 0.1540380964603436E+00, 0.8227084597523057E+00, 0.1281873340097673E+00, 0.2797045229662546E+00, 0.1723485697940061E+00, 0.5407468670158238E+00, 0.3703892253237170E+00, 0.3275545813562609E+00, 0.1384768695152372E+00, 0.8683661690082241E+00, 0.2417038393999236E+00, 0.1573965961648072E+00, 0.7549703050710239E+00, 0.4197135409081310E+00, 0.5565257749798536E-01, 0.7494783707245707E+00, 0.8342833407960080E+00, 0.7207413539297494E+00, 0.3936911272324267E+00, 0.8307872407436112E-01, 0.5696677800088412E-01, 0.2580569153061851E-01, 0.3976149332803511E+00, 0.4082340292723502E+00, 0.3620800929220623E+00, 0.2078006460748600E+00, 0.6810562489816266E+00, 0.8414616295760738E+00, 0.2053319202340824E+00, 0.7745582586901971E+00, 0.8243869237197288E-01, 0.7513634029365589E+00, 0.8658814490552211E+00, 0.7014202441287165E-01, 0.8786892218281559E+00, 0.2415414918645031E-01, 0.1648367770784782E+00, 0.5852629690413500E+00, 0.6558826026732849E+00, 0.3505171007322015E+00, 0.5959744796861849E+00, 0.6000199298251039E+00, 0.5156931460104713E+00, 0.1010243586499049E-01, 0.2804608587164645E+00, 0.7088599878489240E+00, 0.3159377781412633E+00, 0.1196632783263437E+00, 0.8053993759743566E+00, 0.9537751230670044E+00, 0.6890540876884894E+00, 0.7327967809533995E+00, 0.1752177926983489E-01, 0.1176294169286665E+00, 0.1417165464977135E+00, 0.1128117051181837E+00, 0.4431718138373526E+00, 0.6383761487884151E+00, 0.4394388749172047E+00, 0.4496324720961747E+00, 0.2336818223819791E+00, 0.8283237197456694E+00, 0.5968446077081969E+00, 0.2123688346867825E-03, 0.2316409292069651E+00, 0.4041203764036865E+00, 0.5989557684304492E-01, 0.1751475090786662E+00, 0.3300532749209990E+00, 0.5257653351639615E+00, 0.9423173850128755E+00, 0.5110067889308013E+00}, + n: 21, + zOut: []float64{0.2298367449128524E+01, 0.2183508003369306E+01, 0.1768578955898148E+01, 0.1497740650820804E+01, 0.1451044171656134E+01, 0.1248562072819587E+01, 0.1096241131844911E+01, 0.1047761158237631E+01, 0.1036921434023463E+01, 0.1001878203872264E+01, 0.6028997776208512E+00, 0.5966927468392602E+00, 0.3787547972649039E+00, 0.3164597916816877E+00, 0.2770907680746649E+00, 0.1378928396715414E+00, 0.1008983167754413E+00, 0.7523836829300481E-01, 0.4549396861483578E-01, 0.2905908538794771E-01, 0.1164397397714791E-04, 0.2593449025859535E-11, 0.4028878361793870E-19, 0.4523833078775027E-19, 0.1096241131844911E+01, 0.2254118867995285E-20, 0.6781252758190456E-19, 0.6132859990189332E-19, 0.1047761158237631E+01, 0.2208810534618833E-28, 0.7941399228881527E-19, 0.8755467647203911E-19, 0.1036921434023463E+01, 0.2697904295855860E-27, 0.1193508568348155E-18, 0.1375302458176128E-18, 0.1001878203872264E+01, 0.1808754486438286E-19, 0.1585460437287443E-17, 0.7110442921296878E-18, 0.6028997776208512E+00, 0.1121217470921487E-23, 0.1719109533586889E+02, 0.1719109533586889E+02, 0.1020000000000000E+03, 0.3002267573696145E+01, 0.7843137254901960E+01, 0.6126841018734423E-14, 0.3787547972649039E+00, 0.2514494135391975E-29, 0.3694268515215640E-12, 0.2142184401680204E-12, 0.3164597916816877E+00, 0.2495880173472380E-22, 0.1052194788283320E-11, 0.1801542652052392E-11, 0.2770907680746649E+00, 0.2042405059827892E-23, 0.3416315088185822E-10, 0.1784450556067769E-10, 0.1378928396715414E+00, 0.2231720057459842E-17, 0.5936850868223322E-09, 0.2792901329469146E-09, 0.1008983167754413E+00, 0.4009937753419447E-25, 0.1438568455567306E-07, 0.6376284135652434E-08, 0.7523836829300481E-01, 0.1673899732006569E-23, 0.3811420638095229E-06, 0.1677978014843256E-06, 0.4549396861483578E-01, 0.4108428387966160E-20, 0.9969899927958168E-05, 0.2238705130236833E-04, 0.2905908538794771E-01, 0.5621738354967019E-25, 0.1622697124847995E-03, 0.1340889241809050E-03, 0.1164397397714791E-04, 0.4733165431326071E-29, 0.2205086015306072E-02, 0.1109731617446849E-02}, + info: 0, + }, + { + z: []float64{0.9566341326420642E+00, 0.1368890791339401E+00, 0.1041033686995702E+00, 0.1843288381431366E+00, 0.9983016155690853E+00, 0.1786866722264480E+00, 0.3401743522788719E+00, 0.3857333052582377E+00, 0.5001620282112933E+00, 0.9013417473823726E+00, 0.9483009872337210E+00, 0.8066933876879568E+00, 0.5299205541713562E+00, 0.1746250429119467E-01, 0.9676426134678857E+00, 0.9451210738656991E+00, 0.4964770237154315E+00, 0.7837324008636358E+00, 0.9355959680316486E+00, 0.6160646886859618E+00, 0.3400424465599898E+00, 0.5332164761252830E+00, 0.3086260018745091E+00, 0.7161810741898500E+00, 0.9586563909920308E+00, 0.5072089025298385E+00, 0.5345428289191819E+00, 0.3564033548208417E+00, 0.5073508962435702E-01, 0.5457190349920044E+00, 0.5924351087865416E+00, 0.4551284321479383E+00, 0.1212070325395470E+00, 0.4136992969230449E+00, 0.9668715153070689E+00, 0.5158905905227948E+00, 0.3815356588296225E+00, 0.9643666102790432E+00, 0.2243124357596349E-01, 0.1865949320717719E+00, 0.7081123336136068E+00, 0.8847286955309422E+00, 0.8075237017566694E+00, 0.7058935338718864E+00, 0.8930194548226011E-01, 0.5968683124630468E+00, 0.6423123320238798E+00, 0.4264046421741549E+00, 0.6535060636263267E+00, 0.8848885990305457E+00, 0.1727496532173951E+00, 0.2233116713730792E+00, 0.5179656160482806E+00, 0.8833427955005373E+00, 0.5463392573098168E+00, 0.2339495215057854E+00, 0.2531599269911875E+00, 0.8693933445310196E+00, 0.9904673923253784E+00, 0.5001765262594373E+00, 0.8475066901059425E+00, 0.7747140538451288E+00, 0.8097617518836179E+00, 0.6177833422496881E+00, 0.4294196301939426E+00, 0.8754149021622922E+00, 0.1154777972031917E+00, 0.4002319777705416E+00, 0.8948519482752643E+00, 0.2680092666078437E-01, 0.4982362166797213E+00, 0.8946688039099321E+00, 0.6004540842339657E+00, 0.7864972660235388E+00, 0.5343742612900907E+00, 0.6804570163829448E+00, 0.8534533212497195E+00, 0.6588190749186591E+00, 0.3987256626502571E+00, 0.9641448737959348E+00, 0.8049200655531427E+00, 0.8429466638354991E+00, 0.3173537092974966E+00, 0.2969758130071765E+00}, + n: 21, + zOut: []float64{0.2691092090580979E+01, 0.2651656165852700E+01, 0.2273892452779949E+01, 0.2046491657483657E+01, 0.1856589708219707E+01, 0.1474606896148613E+01, 0.1449970763396692E+01, 0.1157826920722246E+01, 0.1131422765724169E+01, 0.1103316690199991E+01, 0.1081571209422854E+01, 0.8863514547656711E+00, 0.7487688552248520E+00, 0.4946957959671176E+00, 0.3261665336572834E+00, 0.2704116388140369E+00, 0.1035778920187539E+00, 0.8274904671505576E-01, 0.4712842456001845E-01, 0.3463118683574901E-01, 0.5254769424391846E-04, 0.2373014771939845E-22, 0.2238209824420786E-09, 0.1516830937674482E-09, 0.1449970763396692E+01, 0.6496080927593321E-18, 0.4705401432274776E-09, 0.6877602609145650E-09, 0.1157826920722246E+01, 0.9485735114056482E-11, 0.6765447972194981E-08, 0.9075269590011981E-08, 0.1131422765724169E+01, 0.0000000000000000E+00, 0.2115471642425146E-07, 0.1586124232313620E-07, 0.1103316690199991E+01, 0.1685550134725853E-21, 0.9651672077875321E-13, 0.7184159896265294E-12, 0.1081571209422854E+01, 0.5505416081326749E-23, 0.2191297069678434E+02, 0.2191297069678434E+02, 0.1080000000000000E+03, 0.3308390022675737E+01, 0.4629629629629630E+01, 0.3615019372146533E-05, 0.7487688552248520E+00, 0.2711157159063573E-25, 0.1185348717221526E-04, 0.1538970705040117E-04, 0.4946957959671176E+00, 0.7711572887860419E-23, 0.5228762878644057E-04, 0.2140066476035995E-04, 0.3261665336572834E+00, 0.1027012207743053E-16, 0.1058102716324823E-03, 0.1097923206605328E-03, 0.2704116388140369E+00, 0.1419949629397821E-27, 0.3075139383959133E-03, 0.2041016121130936E-03, 0.1035778920187539E+00, 0.1569288801032274E-18, 0.2245437021601444E-03, 0.2161294383881767E-03, 0.8274904671505576E-01, 0.1322963914266329E-22, 0.4098429023844965E-03, 0.2685224923308173E-03, 0.4712842456001845E-01, 0.1972152263052530E-27, 0.1445743106447529E-03, 0.3591079434142046E-04, 0.3463118683574901E-01, 0.1109335647967048E-30, 0.1752604588321185E-04, 0.1168961103966469E-04, 0.5254769424391846E-04, 0.0000000000000000E+00, 0.7596773881065606E-02, 0.6101958366533248E-02}, + info: 0, + }, + { + z: []float64{0.8353120998595153E+00, 0.2762691216596785E+00, 0.4005263075088337E+00, 0.2013066591993183E+00, 0.7159087664363259E+00, 0.6826958051178053E+00, 0.3940626911632166E+00, 0.4990834556070268E+00, 0.6760530863202496E-02, 0.5490926358579395E-01, 0.1673564807759778E+00, 0.6884305772394704E+00, 0.3902830106720901E+00, 0.9394502319309270E+00, 0.1453732258871473E+00, 0.6913382271536774E+00, 0.4797608951630542E+00, 0.8813081041297155E+00, 0.7179153476502249E+00, 0.8684015860527726E+00, 0.4912919359735076E+00, 0.2734537604788182E+00, 0.6687443482830383E+00, 0.1554406884207427E+00, 0.2919860915775756E+00, 0.2642733542167044E+00, 0.8429147529046822E+00, 0.2888320698097314E+00, 0.8826173246454528E+00, 0.8977386905269689E+00, 0.7688524109189127E+00, 0.9833521147086286E+00, 0.9216258197795713E-01, 0.4886212819310254E-01, 0.2266462269156035E+00, 0.3411440109054314E+00, 0.3008601997419669E-01, 0.6174499545648404E+00, 0.5004878789063633E+00, 0.6820549240543587E+00, 0.2697209119346977E-01, 0.5561910637447186E+00, 0.5496066776611622E+00, 0.5185759009159874E+00, 0.1533641991284778E+00, 0.9896294286837857E+00, 0.3752499036369343E+00, 0.6748924776803822E-01, 0.2328081038279309E+00, 0.6721552304404512E+00, 0.5472950056303504E+00, 0.9949773164461492E+00, 0.5646629720515278E+00, 0.4280389734679516E+00, 0.4488723317267336E+00, 0.7263390986042261E+00, 0.2371171913738990E-01, 0.2980895305269504E-01, 0.2561842200752050E+00, 0.2554059142478259E+00, 0.5952758446711104E-01, 0.7921877816291150E+00, 0.2045719212105177E+00, 0.9215889426626128E+00, 0.7130733301970400E+00, 0.1420514661017834E+00, 0.8292002693849506E+00, 0.5327095640926792E+00, 0.9857821333545339E+00, 0.6686900428841760E+00, 0.1963263366455671E+00, 0.2881353528210300E+00, 0.7077457532403378E+00, 0.9075905470440924E+00, 0.1600253949359417E+00, 0.1037543259304946E+00, 0.3343707004174388E+00, 0.7287034220491817E-01, 0.8402900560224008E+00, 0.1343632243665364E+00, 0.8746515522185468E+00, 0.4102434537961821E+00, 0.1922774302984470E+00, 0.7386986269659255E+00}, + n: 21, + zOut: []float64{0.2705701250380865E+01, 0.2517516394575531E+01, 0.1823532784589120E+01, 0.1787562059778101E+01, 0.1543666662169401E+01, 0.1517718677289282E+01, 0.1380407836894782E+01, 0.1248997815711926E+01, 0.1005808190406691E+01, 0.8278526045363968E+00, 0.6708485238929687E+00, 0.6082664705845506E+00, 0.5949155529076431E+00, 0.3419285270749396E+00, 0.2930861537880754E+00, 0.2677590880174420E+00, 0.1897681878114907E+00, 0.4498262444281959E-01, 0.4027859329477797E-01, 0.1212960387301111E-02, 0.4788271754899720E-05, 0.2113479533223326E-17, 0.1072835726919963E-07, 0.2769573896400322E-08, 0.1380407836894782E+01, 0.2075077381359190E-19, 0.2509615479685493E-12, 0.8472237738633739E-13, 0.1248997815711926E+01, 0.8862433277732312E-18, 0.5565142852935547E-10, 0.1115246324111066E-09, 0.1005808190406691E+01, 0.1508363342119467E-20, 0.4766364300104371E-06, 0.1686414207934524E-06, 0.8278526045363968E+00, 0.2958228394578794E-30, 0.1339811587116281E-04, 0.9618739022097639E-05, 0.6708485238929687E+00, 0.5096041447727736E-27, 0.1941181574680586E+02, 0.1941181574680586E+02, 0.1100000000000000E+03, 0.3301587301587301E+01, 0.6363636363636363E+01, 0.2769598741382734E-05, 0.5949155529076431E+00, 0.1660823573641619E-23, 0.5008194680845295E-05, 0.3644576454263968E-05, 0.3419285270749396E+00, 0.8597611808520244E-19, 0.8197192371775147E-05, 0.1495511835801176E-04, 0.2930861537880754E+00, 0.6452008777913547E-22, 0.7613853051650506E-05, 0.9176969716117157E-05, 0.2677590880174420E+00, 0.1626694295438144E-23, 0.2172962611604878E-06, 0.9910144268854854E-06, 0.1897681878114907E+00, 0.5698278443334010E-17, 0.3051734820342141E-03, 0.3112883552318466E-03, 0.4498262444281959E-01, 0.6022708464481807E-24, 0.1205042765713422E-04, 0.1759326252954196E-04, 0.4027859329477797E-01, 0.1150776253123047E-20, 0.1426316484726719E-04, 0.9508927802446297E-05, 0.1212960387301111E-02, 0.3136662420452545E-23, 0.9384394253406367E-03, 0.4268700521479601E-03, 0.4788271754899720E-05, 0.0000000000000000E+00, 0.1227549320701017E-01, 0.5132215250850077E-02}, + info: 0, + }, + { + z: []float64{0.6118263281058917E+00, 0.9095172470423057E+00, 0.3600259528878788E+00, 0.2816648927398081E+00, 0.1399164597780194E+00, 0.8570391268113827E+00, 0.6056165732881742E+00, 0.8852338629006543E+00, 0.5421670517489531E+00, 0.6780884449288360E+00, 0.8758212925230515E+00, 0.8288674605669587E+00, 0.6440226363310471E+00, 0.5894956271378661E+00, 0.5783475018163303E+00, 0.3156005123186516E+00, 0.8703974350876685E+00, 0.2617715240366199E+00, 0.8370578409687427E+00, 0.5560169751702698E+00, 0.7455275952513329E-01, 0.7082615127868872E+00, 0.1297707357428401E-02, 0.3064709066297203E+00, 0.8391571848933236E+00, 0.9253805128965463E+00, 0.1130984054668048E+00, 0.8319072101853607E+00, 0.7799276064931965E+00, 0.8579163369971375E+00, 0.5543120979067712E+00, 0.1549966158329672E+00, 0.2643029344048516E+00, 0.8314141615883028E+00, 0.5782452249644381E+00, 0.6319732449892587E+00, 0.4892864093075822E+00, 0.1584418066385224E+00, 0.1120577745932696E+00, 0.6617954786615949E+00, 0.1159882395495345E+00, 0.2876505945591634E+00, 0.7061058070010036E+00, 0.7252986915993946E+00, 0.6775944839786487E+00, 0.7230010551819884E+00, 0.6571938557215073E+00, 0.7482251296401533E+00, 0.9684494841571512E-01, 0.1940071502680237E+00, 0.8896785746779762E+00, 0.9170179284973872E+00, 0.8053995841969270E+00, 0.9321965525342302E+00, 0.7288973738137661E-01, 0.3849028957514653E+00, 0.4410947536600551E+00, 0.4770808300783691E-01, 0.3690162722923055E+00, 0.1908498348358704E+00, 0.8094133574022262E+00, 0.4809437445509840E+00, 0.1405808283203624E+00, 0.4482801388864215E+00, 0.7023724161235537E+00, 0.5041894616412674E+00, 0.2984594028552712E+00, 0.8510121345026274E+00, 0.7612412832182369E-01, 0.8890771840141870E+00, 0.8611357776125709E+00, 0.7702458212424681E+00, 0.8813091992976040E+00, 0.3838156614335277E+00, 0.1536911508311884E+00, 0.2763378258408019E+00, 0.7613349010649187E+00, 0.4228084592762277E+00, 0.5894002697827440E+00, 0.5744691724607953E-01, 0.3014767112059925E+00, 0.7221203248495245E-01, 0.7619553096876313E+00, 0.5154237548276358E+00}, + n: 21, + zOut: []float64{0.2723457737035386E+01, 0.2426437846006860E+01, 0.2169822787916940E+01, 0.1997417054976096E+01, 0.1928996526776896E+01, 0.1891356815602834E+01, 0.1803418741268920E+01, 0.1442378108645599E+01, 0.1026854281138765E+01, 0.9766368850685674E+00, 0.8449303421617025E+00, 0.7575761304896602E+00, 0.7013909577306906E+00, 0.6362631409338654E+00, 0.3605885444762012E+00, 0.1912852882240109E+00, 0.1837209447646653E+00, 0.1221129878112117E+00, 0.2486838916706533E-01, 0.9765050532318768E-02, 0.3171294864219318E-06, 0.1371236688474761E-19, 0.2987011438498780E-15, 0.8087574764480620E-15, 0.1803418741268920E+01, 0.5451390847569379E-21, 0.7270236634641202E-11, 0.2896404140496822E-11, 0.1442378108645599E+01, 0.6954964380428437E-14, 0.4131395561099005E-08, 0.7275670618661885E-08, 0.1026854281138765E+01, 0.1292469707114106E-25, 0.1838064307199299E-06, 0.1238204560933622E-06, 0.9766368850685674E+00, 0.3388131789017201E-20, 0.3880169268725981E-06, 0.5681289313967714E-06, 0.8449303421617025E+00, 0.6785686819474261E-17, 0.2221927887785774E+02, 0.2221927887785774E+02, 0.1080000000000000E+03, 0.3244897959183673E+01, 0.4629629629629630E+01, 0.3025393053677348E-08, 0.7013909577306906E+00, 0.1341063538875720E-28, 0.3767849368753714E-07, 0.3184959175038880E-07, 0.6362631409338654E+00, 0.8874685183736383E-29, 0.5999352088776256E-07, 0.7114794232343430E-07, 0.3605885444762012E+00, 0.1582265649256097E-24, 0.2391907791779699E-03, 0.3344095791507466E-03, 0.1912852882240109E+00, 0.1130832107634320E-25, 0.4040482702647743E-03, 0.3567248396804949E-03, 0.1837209447646653E+00, 0.4930380657631324E-31, 0.1016317982961682E-02, 0.8970313840717793E-03, 0.1221129878112117E+00, 0.2076836816009399E-16, 0.1892596629513954E-02, 0.2329446640559320E-02, 0.2486838916706533E-01, 0.1713835026472478E-23, 0.3568672048225553E-04, 0.1599561599209249E-03, 0.9765050532318768E-02, 0.0000000000000000E+00, 0.3650779499194616E-03, 0.5712243726145556E-03, 0.3171294864219318E-06, 0.8599783076848839E-19, 0.2181668718924628E-02, 0.9598847336904798E-03}, + info: 0, + }, + { + z: []float64{0.1133237741366075E+00, 0.6519297783748091E+00, 0.1419059404596466E+00, 0.6942573823108688E+00, 0.4899507169502382E-03, 0.4408585439270172E+00, 0.4089484333544855E+00, 0.8087151633238087E+00, 0.7299241994604067E-01, 0.7772039339909241E+00, 0.6160100823712519E+00, 0.1679565169487562E+00, 0.3276744683398485E+00, 0.8481565553508272E+00, 0.5614085421003249E+00, 0.5889702994117808E+00, 0.9865181317193454E+00, 0.5686958983255483E+00, 0.2173616127956169E+00, 0.6617740807852496E+00, 0.1324295788322836E+00, 0.5932751564887147E+00, 0.4417023572495267E+00, 0.8308006832392040E+00, 0.6963900525231828E+00, 0.7023649910778577E+00, 0.2540087053190563E+00, 0.5116605124111596E+00, 0.4580501208371790E+00, 0.9900881058795367E+00, 0.6233054379975522E+00, 0.5093215893644945E+00, 0.8805051397371310E+00, 0.5918749676473295E+00, 0.8024628157090720E+00, 0.1089848141144264E+00, 0.9385822032209372E+00, 0.9676954608704463E+00, 0.7567544231269694E+00, 0.7763472508927070E+00, 0.7544500156824916E+00, 0.7080578938468585E-02, 0.8622695184492650E+00, 0.1268681530179145E+00, 0.2408963669487220E+00, 0.1909503620360825E+00, 0.9251648557888137E-01, 0.4447315055648083E+00, 0.1504005134322962E+00, 0.6245252202415555E+00, 0.8432800589533600E+00, 0.1408178180805120E+00, 0.8538656063298837E+00, 0.6959250082173740E-01, 0.7452290984944354E-01, 0.8186895700534982E+00, 0.4817344889163616E+00, 0.8941802149688474E+00, 0.8277272846279742E+00, 0.3122760515919010E+00, 0.4631046821883726E+00, 0.9939521405533804E+00, 0.5067334594578294E+00, 0.3251044449945518E+00, 0.4514296322650755E+00, 0.9520015267726308E+00, 0.3811787795610073E+00, 0.6466473208499942E+00, 0.1035647165455822E-01, 0.3768739780085785E+00, 0.7301131130949717E+00, 0.6341150979687762E+00, 0.2006486990564113E+00, 0.7995641372737874E+00, 0.3501522989293299E+00, 0.7212117404145123E+00, 0.3724384783514179E+00, 0.2704745802524587E+00, 0.5954948132025037E+00, 0.8796174543237598E+00, 0.2533217117523398E+00, 0.2406431629179949E+00, 0.4238947154458014E+00, 0.1002294321190256E+00}, + n: 21, + zOut: []float64{0.2763722715135843E+01, 0.2473753815483350E+01, 0.2367461218794171E+01, 0.2245079256722998E+01, 0.1833576927640889E+01, 0.1670289128561736E+01, 0.1457654822263786E+01, 0.1350493275779479E+01, 0.1277854548609735E+01, 0.1156481310792204E+01, 0.1106963375568883E+01, 0.8704957369830484E+00, 0.6845380809859644E+00, 0.4950109522946930E+00, 0.4198272059610658E+00, 0.2867476262636770E+00, 0.2180239597616727E+00, 0.1578141753335409E+00, 0.1153511714179556E+00, 0.2506658150747594E-01, 0.5048803894682267E-08, 0.8470329472540474E-20, 0.3080709680328647E-07, 0.2263725078605666E-07, 0.1457654822263786E+01, 0.6882142696441190E-21, 0.4511645736903135E-07, 0.5799182381327367E-07, 0.1350493275779479E+01, 0.3225542408567476E-17, 0.3673248914261325E-08, 0.2431637013515395E-08, 0.1277854548609735E+01, 0.1479114197289397E-30, 0.1457855695816495E-07, 0.1029378003116242E-07, 0.1156481310792204E+01, 0.9441087313685069E-24, 0.4178859307872738E-07, 0.3166226192774972E-07, 0.1106963375568883E+01, 0.1745440919131533E-19, 0.2297620589091097E+02, 0.2297620589091097E+02, 0.9600000000000000E+02, 0.3092970521541950E+01, 0.3125000000000000E+01, 0.2193086683474567E-06, 0.6845380809859644E+00, 0.6815668447404457E-13, 0.1173742870849872E-05, 0.2415236474615244E-05, 0.4950109522946930E+00, 0.4604423331594002E-25, 0.1089056660110428E-04, 0.1249035785040860E-04, 0.4198272059610658E+00, 0.2034864306780130E-21, 0.1807219455044531E-04, 0.1582973453084106E-04, 0.2867476262636770E+00, 0.1157544870450433E-16, 0.1788428346885188E-06, 0.1048647571833164E-05, 0.2180239597616727E+00, 0.2820966597070338E-26, 0.2675556367648033E-04, 0.1965631735302374E-04, 0.1578141753335409E+00, 0.4632909363938796E-19, 0.6657143729168815E-04, 0.2311126907684945E-04, 0.1153511714179556E+00, 0.7089566920435294E-17, 0.2519028315687161E-03, 0.1126597449160621E-03, 0.2506658150747594E-01, 0.1511791266627385E-18, 0.1819059120658101E-02, 0.1223404988252185E-02, 0.5048803894682267E-08, 0.5048803894682267E-08, 0.1176483960189416E-01, 0.7561758166988619E-02}, + info: 0, + }, + { + z: []float64{0.6007483099411913E+00, 0.8757604992442719E+00, 0.3498665716095440E+00, 0.4974125174432915E+00, 0.3942177430818359E+00, 0.4655097178512825E+00, 0.7062255099400584E+00, 0.5955461614709365E+00, 0.5705117921786074E+00, 0.2580859610386106E+00, 0.5213970441770472E+00, 0.3227485215512098E+00, 0.8200431655548257E-01, 0.9521784777464899E+00, 0.9768302381970198E+00, 0.5401259459761943E+00, 0.2876249345369413E+00, 0.9928912621382637E+00, 0.9068004769556834E+00, 0.8136746797372185E+00, 0.6557906174128045E+00, 0.7593059043472016E+00, 0.7306718357524993E+00, 0.7872142480398446E+00, 0.2169453387448870E+00, 0.1236189910537125E+00, 0.4376414329540577E+00, 0.2475974410903709E+00, 0.5743712937757064E+00, 0.8451940172770922E+00, 0.2954362279165403E+00, 0.9333330371592371E+00, 0.7261884685452219E+00, 0.2905925760133674E+00, 0.3022535752338255E+00, 0.6907049310391071E+00, 0.2616870809800952E+00, 0.3758121789769751E+00, 0.7112612645989228E+00, 0.9602233026485287E+00, 0.7212734445945013E+00, 0.9266335266312882E+00, 0.7829804394259932E-01, 0.6683939253194693E+00, 0.3539007443404153E+00, 0.1629995906155713E+00, 0.2470024645126471E+00, 0.7250237828800384E+00, 0.9725422312806663E+00, 0.1983270881451602E+00, 0.2167236969811593E+00, 0.2406674239058443E+00, 0.3811046126380717E+00, 0.6358718370494476E-01, 0.6038903598347725E+00, 0.2622945348536884E+00, 0.4871669697876424E+00, 0.1853788955105938E+00, 0.3471794920367192E+00, 0.9520318129455714E+00, 0.9596274379126818E+00, 0.5893179749928269E+00, 0.8560240909608330E-01, 0.9435308110759013E+00, 0.2058424446004554E+00, 0.2877465111691004E+00, 0.6254635389850627E+00, 0.5518846905281638E-01, 0.1132608874973561E+00, 0.8191427866511807E+00, 0.1031178242713734E+00, 0.1909407653284053E+00, 0.5428362177906626E+00, 0.2973328401307228E+00, 0.6079142025065691E+00, 0.1448090006401505E+00, 0.5807148716343321E+00, 0.2207276122221573E+00, 0.4617526470734991E+00, 0.2133930631010816E-01, 0.8719991154365724E+00, 0.4224743304865443E+00, 0.7012315055540164E+00, 0.9970966526798359E+00}, + n: 21, + zOut: []float64{0.2875734378878489E+01, 0.2344615299508293E+01, 0.2292398069608056E+01, 0.2200897502376554E+01, 0.2016889876654445E+01, 0.1997885510503641E+01, 0.1786196162676624E+01, 0.1505330793574375E+01, 0.1193246823746953E+01, 0.1153847743209180E+01, 0.9864509519829328E+00, 0.8076407462080507E+00, 0.6427729668463894E+00, 0.4808392927305387E+00, 0.3994667257867982E+00, 0.3273321022655395E+00, 0.1654363687174887E+00, 0.1176242694536732E+00, 0.4639514928819789E-01, 0.1592499252046327E-01, 0.3521629889976334E-03, 0.1784216669875992E-16, 0.7121431862167897E-10, 0.2812798494121821E-10, 0.1786196162676624E+01, 0.4108568523994154E-17, 0.4438281217193102E-07, 0.2274689950145052E-07, 0.1505330793574375E+01, 0.7499168293791558E-11, 0.5226296435976747E-05, 0.8641809444662033E-05, 0.1193246823746953E+01, 0.0000000000000000E+00, 0.2628223783350490E-04, 0.3987870710471355E-04, 0.1153847743209180E+01, 0.5865702946789929E-16, 0.1241308452869419E-07, 0.3894882997253744E-08, 0.9864509519829328E+00, 0.7673863643253590E-18, 0.2335727788952568E+02, 0.2335727788952568E+02, 0.1040000000000000E+03, 0.3058956916099773E+01, 0.2884615384615385E+01, 0.3948721236408985E-04, 0.6427729668463894E+00, 0.1028674620408199E-26, 0.2391232675375281E-03, 0.2086678697444007E-03, 0.4808392927305387E+00, 0.3130051437900657E-19, 0.1426864276581422E-03, 0.1522473256880454E-03, 0.3994667257867982E+00, 0.2101777886998446E-24, 0.1526280399103512E-05, 0.7002070790936748E-06, 0.3273321022655395E+00, 0.1242239255406691E-15, 0.1253374424171423E-04, 0.2848254240665514E-04, 0.1654363687174887E+00, 0.2455402723507254E-17, 0.1659752591164777E-02, 0.8476830847116842E-03, 0.1176242694536732E+00, 0.1344218982496604E-26, 0.1195138829435961E-02, 0.1583065192028977E-02, 0.4639514928819789E-01, 0.2205655090997949E-26, 0.2795062437264197E-03, 0.9604240981222648E-03, 0.1592499252046327E-01, 0.6574583373762050E-21, 0.7008887495297913E-02, 0.4078689360266482E-02, 0.3521629889976334E-03, 0.2981894221735425E-26, 0.7785429009218255E-02, 0.8697865294154498E-02}, + info: 0, + }, + { + z: []float64{0.3565428176835072E+00, 0.1947118362244993E+00, 0.7741156920152520E+00, 0.2422304602782238E+00, 0.6344560478781652E+00, 0.6454994272905118E+00, 0.1782236022643452E+00, 0.1761708296759242E+00, 0.4902923959906477E+00, 0.3501715044277058E+00, 0.8606282659620700E+00, 0.4671519599404039E-03, 0.9177061631942818E+00, 0.9869535184930249E+00, 0.9615604930014852E+00, 0.2283553018405985E+00, 0.2470322441623238E+00, 0.5789642646481346E+00, 0.9797717987449011E+00, 0.2628090453859127E+00, 0.1063995753795172E+00, 0.9446865880365994E+00, 0.8109285339456792E+00, 0.4534650679402863E-01, 0.9560542860825706E+00, 0.7338084401822241E+00, 0.4719995459594307E+00, 0.8981162685661518E+00, 0.6088366551058919E+00, 0.4061662134958367E+00, 0.6141507801286759E+00, 0.7683300427463863E+00, 0.2030033710532269E+00, 0.5109903203799075E+00, 0.1295039929316932E-01, 0.1313823831505738E+00, 0.4600541675974348E+00, 0.8052912479215125E+00, 0.7315674921483241E+00, 0.1311059905375703E+00, 0.9372521946935908E-01, 0.2804058432106148E+00, 0.1426401168120447E+00, 0.1302494454623315E-01, 0.9936953989155247E+00, 0.7109841901452127E+00, 0.8438933393801377E+00, 0.5599779486257196E+00, 0.6224094357036947E-01, 0.3722277721927331E+00, 0.2128496963914419E+00, 0.2132595627624145E+00, 0.1761474673379855E+00, 0.5003566260610350E+00, 0.5448249098276142E+00, 0.5701738373290982E+00, 0.5196161461339291E+00, 0.4684002904633344E-01, 0.3091316721875115E+00, 0.9311143262655500E+00, 0.5165589926587729E+00, 0.4230658512580241E+00, 0.1580095970610971E+00, 0.9213403630754643E+00, 0.8395102804227733E+00, 0.6279936637330286E-01, 0.2118369865058433E+00, 0.5654902136914255E+00, 0.8603345552081203E+00, 0.6355651085391135E+00, 0.9504788095745560E+00, 0.4928822316317183E+00, 0.8546738890428598E+00, 0.1506739079739667E+00, 0.7955004699434830E+00, 0.8623803468730415E+00, 0.3328976137523824E+00, 0.6282681071703561E+00, 0.5253150183233042E+00, 0.5508861108006231E+00, 0.8482246434328706E+00, 0.3438184421622726E+00, 0.4546750663905129E+00, 0.2702842147468514E+00}, + n: 21, + zOut: []float64{0.2599043716461175E+01, 0.2392272222815941E+01, 0.1945154273268249E+01, 0.1882117601080557E+01, 0.1808214125087810E+01, 0.1701027479657859E+01, 0.1674631474676720E+01, 0.1432830957842129E+01, 0.1245386641860508E+01, 0.1003047986420639E+01, 0.5925499318269597E+00, 0.5737323778075372E+00, 0.4619197085153934E+00, 0.3795861721644865E+00, 0.2896752472940557E+00, 0.2024598813435771E+00, 0.1753335138277014E+00, 0.8865983947068434E-01, 0.4088280438555415E-01, 0.2271023207656241E-01, 0.3207012114254504E-03, 0.1328658858913301E-22, 0.6931093261583948E-12, 0.1962539051213948E-11, 0.1674631474676720E+01, 0.1972152263052530E-30, 0.1003060686577864E-09, 0.7786971971568132E-10, 0.1432830957842129E+01, 0.3552283923653146E-20, 0.1335875663368593E-08, 0.1098996752778210E-08, 0.1245386641860508E+01, 0.6078417508770261E-16, 0.6005521677860925E-08, 0.4565873133117504E-08, 0.1003047986420639E+01, 0.4907378230941548E-20, 0.6042756667162823E-07, 0.1337733817342293E-06, 0.5925499318269597E+00, 0.7849166006949067E-28, 0.2051155688909552E+02, 0.2051155688909552E+02, 0.1190000000000000E+03, 0.3632653061224490E+01, 0.6722689075630252E+01, 0.9823469248695270E-04, 0.4619197085153934E+00, 0.3582825487703231E-19, 0.4408755124729528E-13, 0.6425665938157879E-14, 0.3795861721644865E+00, 0.3049769924381334E-19, 0.2649002399507504E-08, 0.1284693180187630E-07, 0.2896752472940557E+00, 0.2730342256278547E-24, 0.3857186710932351E-04, 0.7729247272182434E-05, 0.2024598813435771E+00, 0.2411244474478362E-13, 0.9974443273860175E-04, 0.7715885583051736E-04, 0.1753335138277014E+00, 0.1003583340528496E-19, 0.1275804036051463E-05, 0.1384195629265487E-05, 0.8865983947068434E-01, 0.1976477763343393E-17, 0.9250271469637329E-05, 0.1838436200742544E-04, 0.4088280438555415E-01, 0.1570480975080192E-18, 0.1665813744256122E-03, 0.9368787794988337E-04, 0.2271023207656241E-01, 0.1120555887990158E-19, 0.1174000031728850E-02, 0.1217958466428532E-03, 0.3207012114254504E-03, 0.0000000000000000E+00, 0.1126152474028795E-01, 0.4219515300090987E-02}, + info: 0, + }, + { + z: []float64{0.1431540885741494E+00, 0.8417471667062104E+00, 0.3721480902981644E-01, 0.9023772086815021E+00, 0.7374866167630612E-01, 0.8092071841305744E+00, 0.8019394206305236E+00, 0.4350675566733520E+00, 0.8704440278245326E+00, 0.8549104680538234E+00, 0.1422025173760633E+00, 0.8968456705882693E+00, 0.1647179447265090E-01, 0.8994077105608889E-01, 0.8596481603583839E-02, 0.3900328616396558E+00, 0.4012630844305533E+00, 0.8262908556770313E+00, 0.9026062467432411E+00, 0.6485345137550630E+00, 0.5598932241080331E+00, 0.6084992568220661E+00, 0.5039450314115669E+00, 0.3490854750626526E+00, 0.9921372250281116E+00, 0.1522469068827847E-01, 0.9395473455386270E+00, 0.3928498832803473E-01, 0.1672951108814763E+00, 0.9480670302336689E+00, 0.8743929741539138E+00, 0.9201765927311700E-01, 0.8641536356563365E+00, 0.8867562289118487E+00, 0.7156446870854873E+00, 0.5025184567500440E-01, 0.4878799838415181E+00, 0.5568327059782646E+00, 0.4596548235310455E+00, 0.6857902774944131E+00, 0.4795565553491499E-01, 0.4752906527216701E+00, 0.9288351773531449E+00, 0.7419018575576386E+00, 0.9987802353476521E+00, 0.8896105755435116E+00, 0.3190450046252536E+00, 0.9685806853440787E+00, 0.3396383774694021E+00, 0.9164401886915974E+00, 0.1269879571285023E+00, 0.7912318128907188E+00, 0.9987805345221650E+00, 0.4107567957671243E+00, 0.4798441760727139E+00, 0.2357309197085595E+00, 0.3404494185276096E+00, 0.7067865773496134E+00, 0.2931542927088892E+00, 0.6654441577727066E+00, 0.9279529535770864E+00, 0.9667208022109988E+00, 0.5518920376663735E+00, 0.1657487215954807E+00, 0.3897636058410684E+00, 0.9489706352102197E+00, 0.9626390247015670E+00, 0.1020775856599213E+00, 0.3545784768064359E+00, 0.3098089336816090E+00, 0.3791089991258285E+00, 0.6519489570740321E+00, 0.4763523952410913E+00, 0.3754524631080590E+00, 0.9792813089520809E+00, 0.1998301915332230E+00, 0.7618060057813935E+00, 0.1923436350325713E+00, 0.2507012719817848E+00, 0.9704520069999245E-01, 0.2277384851702763E+00, 0.7790727508043876E+00, 0.9105177383528497E+00, 0.9714469561729607E+00}, + n: 21, + zOut: []float64{0.2499720115178021E+01, 0.2371028651009860E+01, 0.2298220416774619E+01, 0.1883765650093571E+01, 0.1735426237683963E+01, 0.1616050162695453E+01, 0.1545275083087796E+01, 0.1187762610175739E+01, 0.1136805332133151E+01, 0.9576839460725933E+00, 0.9184986446054146E+00, 0.7702442640767845E+00, 0.6433137908930019E+00, 0.6160049176831036E+00, 0.3208789970551323E+00, 0.1900871628722621E+00, 0.9670499780074775E-01, 0.7460708611062000E-01, 0.6486083888512703E-01, 0.9966295048259487E-02, 0.4462615269650136E-07, 0.2765885173224186E-23, 0.3446029508568731E-11, 0.2660256849760007E-11, 0.1545275083087796E+01, 0.1351675564459578E-15, 0.5238898174323723E-11, 0.6640890994279970E-11, 0.1187762610175739E+01, 0.1020402561847179E-21, 0.5048392892414130E-10, 0.4263729817754413E-10, 0.1136805332133151E+01, 0.1429794613494979E-24, 0.1140378416083416E-09, 0.8548580688939750E-10, 0.9576839460725933E+00, 0.1302866745903472E-12, 0.1207358062805810E-07, 0.1106598026337004E-07, 0.9184986446054146E+00, 0.3538135823224864E-23, 0.2093690524456137E+02, 0.2093690524456137E+02, 0.1130000000000000E+03, 0.3331065759637188E+01, 0.7964601769911504E+01, 0.4249897555997367E-08, 0.6433137908930019E+00, 0.4627357327667341E-16, 0.5702383148705814E-08, 0.8656383665454304E-08, 0.6160049176831036E+00, 0.0000000000000000E+00, 0.4551987331271016E-07, 0.8434005257711676E-07, 0.3208789970551323E+00, 0.2939872200043623E-13, 0.4894684795516590E-05, 0.8200734504818474E-05, 0.1900871628722621E+00, 0.9080407486043539E-23, 0.2659953011765320E-05, 0.2713538128245964E-05, 0.9670499780074775E-01, 0.1949336478520425E-16, 0.1287973346598181E-04, 0.3266830247798530E-04, 0.7460708611062000E-01, 0.0000000000000000E+00, 0.5588793940970657E-03, 0.8233963212342685E-03, 0.6486083888512703E-01, 0.1680331387617770E-17, 0.5510428852120968E-02, 0.6166917183278490E-02, 0.9966295048259487E-02, 0.9229672591085838E-28, 0.3019065027713110E-04, 0.7674568090533565E-04, 0.4462615269650136E-07, 0.1609276246650864E-27, 0.6212935138424260E-03, 0.6196304337665942E-02}, + info: 0, + }, + { + z: []float64{0.2117689827794353E+00, 0.3469390325266096E+00, 0.8556157513093896E+00, 0.4757820823688597E-01, 0.8174618541686680E+00, 0.7502623797079592E+00, 0.3473865910309967E+00, 0.1102061280439136E+00, 0.3838366632541155E+00, 0.4335750892772081E+00, 0.8350483733926333E+00, 0.8472841724322083E+00, 0.7001411292294977E+00, 0.1602971622162627E+00, 0.8475208106005836E+00, 0.1606731136869689E+00, 0.1282020202063155E+00, 0.7021142414638628E+00, 0.6509542291315448E+00, 0.3403267711628978E+00, 0.2783715946342622E+00, 0.2391807909006515E+00, 0.9326061845277929E+00, 0.8200594229325990E+00, 0.5326312099842309E+00, 0.4390518762985745E+00, 0.9087332134146432E+00, 0.8586305843825174E+00, 0.5289458618923581E+00, 0.6098713986238019E+00, 0.4124733909450122E+00, 0.2730411694523917E+00, 0.8437528550291284E+00, 0.6776322145297138E+00, 0.6772761566308538E+00, 0.6457716484911746E+00, 0.4290441069454122E+00, 0.9486890113840626E+00, 0.1145429178800543E+00, 0.8512453512490206E+00, 0.6435458910126746E+00, 0.6571563420730420E-01, 0.6473933144723745E+00, 0.2355560081089225E+00, 0.1262112692360912E+00, 0.6892345322103945E+00, 0.9088034154559810E-01, 0.5725023743105110E+00, 0.8924086653580375E+00, 0.6645221244511262E+00, 0.7287357579298158E+00, 0.6462379994906295E+00, 0.8254375000545862E+00, 0.2402799002378904E+00, 0.2312499677892260E+00, 0.7164295349077132E-01, 0.1216505240532725E+00, 0.5279275209153104E+00, 0.2010432640871422E+00, 0.2335833224032272E+00, 0.7053869472451330E+00, 0.1271428628255256E-01, 0.5920854820119847E-01, 0.1973220586788875E+00, 0.9024202349843203E+00, 0.2696040474399301E+00, 0.2399100427530529E+00, 0.4936945945994136E+00, 0.7377918193661529E+00, 0.4454167008139350E+00, 0.6822934143143184E+00, 0.1980205964978332E+00, 0.9382259163150929E+00, 0.7952650736079295E+00, 0.2147267423149601E+00, 0.2160850567828982E+00, 0.2063316967709339E-02, 0.4613555480251579E+00, 0.2983741464914229E+00, 0.7653433710630531E+00, 0.9319255930520460E+00, 0.9624604653562387E+00, 0.7921958309630666E+00, 0.3349247737517954E+00}, + n: 21, + zOut: []float64{0.2554012710728313E+01, 0.2350385283314499E+01, 0.2336543487584985E+01, 0.2078331003959482E+01, 0.1819938506810449E+01, 0.1751888604422140E+01, 0.1642765030717598E+01, 0.1391850148176030E+01, 0.1265614265169072E+01, 0.1192296172100378E+01, 0.1118290194286764E+01, 0.7471001949454404E+00, 0.6602310515087256E+00, 0.5223373748122110E+00, 0.3101567956620342E+00, 0.2634177676934227E+00, 0.1468471914237014E+00, 0.9669691105737251E-01, 0.6862527639473751E-01, 0.2251868425683227E-01, 0.2442899974694956E-02, 0.0000000000000000E+00, 0.3247526756203984E-07, 0.3301672636248404E-07, 0.1642765030717598E+01, 0.2849742554922193E-13, 0.2093860354423170E-09, 0.9504157619668633E-09, 0.1391850148176030E+01, 0.5471978423050590E-17, 0.2765846142955850E-06, 0.3763175370346248E-06, 0.1265614265169072E+01, 0.7099748146989106E-29, 0.8629250150360319E-06, 0.7218261937815504E-06, 0.1192296172100378E+01, 0.0000000000000000E+00, 0.1792585742344500E-05, 0.1391262462240339E-05, 0.1118290194286764E+01, 0.2158808112824856E-22, 0.2234228955499889E+02, 0.2234228955499888E+02, 0.1130000000000000E+03, 0.3253968253968254E+01, 0.7079646017699115E+01, 0.1273852622682608E-03, 0.6602310515087256E+00, 0.1370219837932689E-23, 0.6841106514156665E-04, 0.6915431692027581E-04, 0.5223373748122110E+00, 0.8086955524743426E-16, 0.3151324787101243E-03, 0.4936870820060986E-03, 0.3101567956620342E+00, 0.1690864291947714E-17, 0.5342613094053112E-03, 0.4525307423692253E-03, 0.2634177676934227E+00, 0.1569544193046020E-19, 0.8085628512848309E-03, 0.5320256570924908E-03, 0.1468471914237014E+00, 0.1725633230170963E-30, 0.2171574910172427E-04, 0.7393923467130197E-05, 0.9669691105737251E-01, 0.8185725058097063E-19, 0.6259416979424432E-04, 0.7993629240914341E-04, 0.6862527639473751E-01, 0.1144304443709360E-17, 0.8363460972147480E-05, 0.2145990923718838E-04, 0.2251868425683227E-01, 0.3423656328659191E-26, 0.4258124540743150E-02, 0.4456054742147899E-02, 0.2442899974694956E-02, 0.7553929676107889E-20, 0.1657093833399320E-01, 0.2123214045479585E-01}, + info: 0, + }, + { + z: []float64{0.5143465832338334E-01, 0.9671338481452775E+00, 0.2594126021369855E+00, 0.4887933538896223E+00, 0.4809357095031462E+00, 0.1648852435705869E+00, 0.5382296047886386E+00, 0.2404093745709619E+00, 0.5749849863516346E+00, 0.8755417117410101E+00, 0.6479432781744229E+00, 0.8462387170859478E+00, 0.1030360983310576E+00, 0.2790419505795448E+00, 0.2643216914883461E+00, 0.5072751399665939E+00, 0.9813013168637370E+00, 0.5270325239254721E+00, 0.1341185443667956E+00, 0.1666757001787883E+00, 0.8421762037577841E+00, 0.6333707418037352E+00, 0.9714076539879462E+00, 0.8133030640726957E-01, 0.5961674478430062E+00, 0.9962348063653491E+00, 0.9690228851917282E-02, 0.4933763527820312E-01, 0.1005560439675963E+00, 0.9794838233988775E+00, 0.8412211319105695E+00, 0.4530689238841823E+00, 0.9824397821984348E+00, 0.9435184376619912E+00, 0.5899369853858024E+00, 0.3347062982138894E+00, 0.6634688706474758E+00, 0.7781534216536603E+00, 0.5213269680559092E+00, 0.2415498257414400E+00, 0.4153017903771141E+00, 0.6142268391585892E-01, 0.1582256219487426E+00, 0.5180630943028907E+00, 0.2531248086553088E+00, 0.4588063905612799E+00, 0.9850645955475579E-01, 0.4386688206276981E+00, 0.6723312445641013E+00, 0.2417358982121058E+00, 0.9102202020018957E+00, 0.4790528316718639E+00, 0.8645283277006380E+00, 0.5896385561561974E+00, 0.3547186358320912E+00, 0.2570702739547999E+00, 0.8872414069371877E+00, 0.7977277358714381E+00, 0.2283476919840042E+00, 0.5481349489617042E+00, 0.9565429487676439E+00, 0.3941453871538936E-01, 0.2005355998230810E+00, 0.6815820255993522E+00, 0.8827641753074383E+00, 0.3721138471690448E+00, 0.3473678385941080E+00, 0.5958558861949184E+00, 0.5289126915593071E+00, 0.7848410946975201E+00, 0.9380898148044153E+00, 0.4238368524709774E+00, 0.9095202310640094E-01, 0.5205916750079600E+00, 0.3388678441932766E+00, 0.9218715971576251E+00, 0.2785357832665022E+00, 0.7353529037048490E+00, 0.3430576699659011E+00, 0.1583386336396764E-03, 0.1574217518812531E+00, 0.2808549182652627E+00, 0.9165809855463820E+00, 0.2729923295285186E-01}, + n: 21, + zOut: []float64{0.2740279952468604E+01, 0.2296796691149573E+01, 0.2162929780566866E+01, 0.2022438316208162E+01, 0.1971555203048247E+01, 0.1712998698314224E+01, 0.1596820997274643E+01, 0.1536702996895977E+01, 0.1112897445143912E+01, 0.8259900943746278E+00, 0.7751147071242228E+00, 0.6231241133597348E+00, 0.5263220334234422E+00, 0.4481765711163059E+00, 0.4215577615769598E+00, 0.1440581718410880E+00, 0.1296344814538628E+00, 0.5340807481344281E-01, 0.1871489185523312E-01, 0.3434703213692513E-02, 0.2376961512853157E-03, 0.2255238469879073E-22, 0.1711146112720571E-14, 0.5183409008081618E-15, 0.1596820997274643E+01, 0.0000000000000000E+00, 0.1075504130778587E-11, 0.4005497363076952E-12, 0.1536702996895977E+01, 0.1981618593915182E-26, 0.4700742807330894E-10, 0.1164621641126979E-09, 0.1112897445143912E+01, 0.4726602108594632E-24, 0.9459556816770867E-09, 0.1692486098434743E-08, 0.8259900943746278E+00, 0.0000000000000000E+00, 0.4245107391668450E-08, 0.4612248550244559E-08, 0.7751147071242228E+00, 0.8284213834597216E-21, 0.2112319338137411E+02, 0.2112319338137411E+02, 0.1000000000000000E+03, 0.2931972789115646E+01, 0.2000000000000000E+01, 0.1818678155237499E-07, 0.5263220334234422E+00, 0.4246772729828520E-23, 0.1119198730079850E-06, 0.4602199017952358E-06, 0.4481765711163059E+00, 0.1035379938102578E-29, 0.2940687130487931E-04, 0.4282452030972280E-04, 0.4215577615769598E+00, 0.5276311108751726E-20, 0.8277389737129399E-05, 0.6004055084531256E-05, 0.1440581718410880E+00, 0.0000000000000000E+00, 0.8355340113184283E-05, 0.1023986211128489E-04, 0.1296344814538628E+00, 0.1552281967638183E-19, 0.6343521312985942E-05, 0.6697527987420460E-05, 0.5340807481344281E-01, 0.6040133837432384E-17, 0.1556990792688111E-03, 0.3593183434334682E-03, 0.1871489185523312E-01, 0.1153562559317783E-18, 0.8237486079760113E-03, 0.4973426416094711E-03, 0.3434703213692513E-02, 0.0000000000000000E+00, 0.1008741049678482E-02, 0.1888495698860201E-02, 0.2376961512853157E-03, 0.2773339119917620E-31, 0.6098206042824776E-05, 0.1474144332182451E-03}, + info: 0, + }, + { + z: []float64{0.1099031735712288E+00, 0.5724174842808358E+00, 0.3122550743498126E+00, 0.7231231021981217E+00, 0.6175771623314344E+00, 0.5814310193624382E+00, 0.6423493353686718E+00, 0.8309609356975209E+00, 0.6400193102877816E-01, 0.8728840273137624E+00, 0.8682274216885312E+00, 0.7829529646382269E+00, 0.4658588928084396E+00, 0.4997300418007194E+00, 0.5750522308672811E+00, 0.5282811502940782E+00, 0.7877382060309071E+00, 0.2242905591148447E-01, 0.9672168595892823E+00, 0.9229185948074735E+00, 0.7120977511666169E+00, 0.9513613307832994E+00, 0.6495350224590044E+00, 0.1796094611119584E+00, 0.6238202085518583E+00, 0.4056553414984787E-01, 0.2863733551163383E-01, 0.7740758620163646E-01, 0.1652368945937387E+00, 0.5017774327613052E+00, 0.6445125305703996E+00, 0.5670374114090049E-01, 0.1147723121006077E+00, 0.5126855432858525E+00, 0.9526888308153642E+00, 0.1724272641761350E+00, 0.9682495468226523E+00, 0.2579549866163475E+00, 0.5365442422680400E+00, 0.7055455249537391E+00, 0.6510869341601188E+00, 0.6910931676909811E+00, 0.8245356137796966E+00, 0.2467134555988069E+00, 0.2932965007679977E-01, 0.3174819406165880E+00, 0.1008447548759832E+00, 0.7998426243165985E+00, 0.6780870841109060E+00, 0.2896057920811994E+00, 0.9303619290394473E+00, 0.3607716194531815E+00, 0.5211419140438559E+00, 0.1046120770241560E+00, 0.7683871590101677E+00, 0.2147990043395044E+00, 0.6702055898403114E+00, 0.2446830800671760E+00, 0.1275992810549672E+00, 0.9234458715873217E+00, 0.6974016894347440E+00, 0.2461420250226486E+00, 0.2448954779360711E+00, 0.1956976010946661E+00, 0.8608131397075515E+00, 0.7387865940798233E-01, 0.5053692911917109E+00, 0.3354069180988316E+00, 0.4024076719528004E+00, 0.5167351886997615E+00, 0.7829885112810930E-01, 0.3735275576161866E+00, 0.9546718920527260E+00, 0.5321377922787256E+00, 0.6121034951800618E+00, 0.8028222695558183E+00, 0.3295254582685344E+00, 0.5907471536091985E+00, 0.8247143229089846E+00, 0.1329486496858557E+00, 0.9484305946158008E+00, 0.4510190965747323E+00, 0.1159598040227069E+00, 0.7290524870797256E+00}, + n: 21, + zOut: []float64{0.2759844065448739E+01, 0.2469029941309663E+01, 0.2170232676307031E+01, 0.1960369893365743E+01, 0.1773994559660628E+01, 0.1654180064160601E+01, 0.1454572475268221E+01, 0.1398795476174613E+01, 0.1260788731803824E+01, 0.1011169812035994E+01, 0.9032283997666860E+00, 0.7344998632955592E+00, 0.6915613254033124E+00, 0.3097922830021908E+00, 0.2074097203460417E+00, 0.1750683611049406E+00, 0.1335859329381489E+00, 0.1070304609992355E+00, 0.6466361262660925E-01, 0.1024517112836532E-01, 0.4658519939343828E-03, 0.5916456789157589E-30, 0.2414839775472174E-07, 0.1563475838564645E-07, 0.1454572475268221E+01, 0.5710570490785520E-12, 0.1598956453701674E-05, 0.9938094799470723E-06, 0.1398795476174613E+01, 0.7078291130367095E-25, 0.1301105456376455E-06, 0.7650088290739393E-07, 0.1260788731803824E+01, 0.6660939091008025E-19, 0.3865722666202593E-07, 0.5454440035759107E-07, 0.1011169812035994E+01, 0.5414223942436753E-17, 0.3344051754361652E-04, 0.2635566037358100E-04, 0.9032283997666860E+00, 0.5272968833424410E-16, 0.2125052867814009E+02, 0.2125052867814008E+02, 0.1090000000000000E+03, 0.3179138321995465E+01, 0.2752293577981651E+01, 0.8667028517906969E-06, 0.6915613254033124E+00, 0.6016648435007899E-23, 0.2921486269254270E-05, 0.9773987035049091E-05, 0.3097922830021908E+00, 0.6500213859021137E-26, 0.6786203908623285E-05, 0.1231548092049969E-04, 0.2074097203460417E+00, 0.0000000000000000E+00, 0.7819652657144090E-06, 0.1217347772587842E-05, 0.1750683611049406E+00, 0.6582255393164123E-26, 0.1458540666485106E-06, 0.3789967922095048E-07, 0.1335859329381489E+00, 0.1232595164407831E-31, 0.4615373247666497E-05, 0.3177332815969559E-05, 0.1070304609992355E+00, 0.5947376905467984E-20, 0.9914288367235413E-05, 0.1492808588608919E-04, 0.6466361262660925E-01, 0.5865227530883812E-22, 0.3814164765172745E-05, 0.1095283410948310E-05, 0.1024517112836532E-01, 0.3761300629007363E-24, 0.3159730783704485E-04, 0.5907442037524074E-05, 0.4658519939343828E-03, 0.2094421310984266E-20, 0.1426408794386696E-02, 0.1350744215392459E-02}, + info: 0, + }, + { + z: []float64{0.1337238926382778E+00, 0.3106335653974364E+00, 0.8951406789337562E+00, 0.2282076226383426E+00, 0.3559900270036094E+00, 0.1333708564991680E+00, 0.9225357561814306E+00, 0.6383337981459615E+00, 0.7455817572577521E+00, 0.9604635037498299E-01, 0.1362822625756884E+00, 0.7894982141438661E+00, 0.5371956247017955E+00, 0.2757551089818502E+00, 0.9298698100988576E+00, 0.8755382224220718E+00, 0.2542040210765101E+00, 0.1287904754285962E+00, 0.6810846780454294E+00, 0.6526638813043742E+00, 0.5955845877046446E+00, 0.4670096896697419E+00, 0.5475207984291373E+00, 0.6684162034597571E+00, 0.5235410539200527E+00, 0.7337617639827179E+00, 0.8903194008545992E+00, 0.8072217495300122E+00, 0.3881183186356038E+00, 0.9675156751063907E+00, 0.4869149855955625E+00, 0.4861129300486463E+00, 0.5200718178308463E+00, 0.7592798686765068E+00, 0.7809192005748844E+00, 0.9939952535261979E+00, 0.4314053553650160E+00, 0.3880099380329156E+00, 0.9349849386467751E+00, 0.5291872418075704E+00, 0.7655812944336832E+00, 0.7077741471317599E+00, 0.5275519688342463E+00, 0.1415092279196126E+00, 0.1904335663118598E+00, 0.3699272115054363E+00, 0.7445484920377089E+00, 0.8400049615316296E+00, 0.8734700661006028E+00, 0.8683217518669656E+00, 0.8515176384024258E+00, 0.6202080985416659E+00, 0.3604998919630682E+00, 0.2403115969743893E+00, 0.9554672796937618E+00, 0.1693873282831592E+00, 0.5994144523705257E+00, 0.1384422941659869E-01, 0.6596251817370012E+00, 0.5636231004812753E+00, 0.5389166856740800E+00, 0.2607457441602791E+00, 0.5920539595206202E+00, 0.2966504229935458E+00, 0.5816050348468149E+00, 0.9328164339475690E+00, 0.5805507576670368E+00, 0.6771712743677023E+00, 0.9823651336988842E+00, 0.9793282488782439E+00, 0.4667245203343464E+00, 0.7134684364121646E+00, 0.4880671978756712E-01, 0.8383078993270572E+00, 0.7936419849408084E+00, 0.5385800856643647E+00, 0.4634644976924968E+00, 0.3931501879746360E+00, 0.1248524879525928E+00, 0.3152310060096000E+00, 0.9363438862709352E+00, 0.3520470715344234E+00, 0.1429338846554544E+00, 0.1326946626315275E+00}, + n: 21, + zOut: []float64{0.2657315323020249E+01, 0.2572905823883155E+01, 0.2192663626292596E+01, 0.2071095653426940E+01, 0.2044494413445205E+01, 0.1999166174223334E+01, 0.1788414821296782E+01, 0.1468335212647637E+01, 0.1398203839606685E+01, 0.1347197234417596E+01, 0.1032902470665773E+01, 0.6608948302945201E+00, 0.5911878145202527E+00, 0.5378924504889658E+00, 0.3142273934265400E+00, 0.2842363451796606E+00, 0.2019484989227465E+00, 0.1206949829709270E+00, 0.7426269792367300E-01, 0.2567909008435554E-01, 0.2199972943425967E-02, 0.1467781105980630E-22, 0.1166962122444304E-12, 0.3923264640094201E-13, 0.1788414821296782E+01, 0.4047127357551305E-19, 0.1945479305169457E-09, 0.9334440121571419E-10, 0.1468335212647637E+01, 0.0000000000000000E+00, 0.9722951216797492E-08, 0.1689489155058893E-07, 0.1398203839606685E+01, 0.0000000000000000E+00, 0.7669133926546234E-07, 0.4506074380002258E-07, 0.1347197234417596E+01, 0.5319335283638860E-18, 0.5446647026201709E-11, 0.3163064243829271E-10, 0.1032902470665773E+01, 0.4430813007685208E-16, 0.2338591866968101E+02, 0.2338591866968102E+02, 0.1020000000000000E+03, 0.3054421768707483E+01, 0.2941176470588236E+01, 0.1546723845733498E-03, 0.5911878145202527E+00, 0.3652829585034170E-19, 0.1702044288822486E-03, 0.2177596193354961E-03, 0.5378924504889658E+00, 0.1350864780951217E-19, 0.2554902108144373E-06, 0.3466691719880105E-07, 0.3142273934265400E+00, 0.2387932220615686E-11, 0.6740109938598231E-04, 0.1019437079103270E-03, 0.2842363451796606E+00, 0.4338734978715565E-28, 0.4438729696644533E-03, 0.6983868198931385E-03, 0.2019484989227465E+00, 0.2612058427213185E-17, 0.1559412966194519E-03, 0.4467949014161081E-04, 0.1206949829709270E+00, 0.7367960854764250E-27, 0.5572085070843593E-03, 0.6756387538188178E-03, 0.7426269792367300E-01, 0.4936220984925504E-18, 0.5280924471496804E-02, 0.4881438130898638E-02, 0.2567909008435554E-01, 0.4675428386128583E-22, 0.7885638578366546E-02, 0.6344653647355715E-02, 0.2199972943425967E-02, 0.1043187069080892E-15, 0.1144606019330652E-02, 0.5299576363060843E-02}, + info: 0, + }, + { + z: []float64{0.2890643798273074E-01, 0.8912209063965303E+00, 0.7091793456137876E+00, 0.8245039023218966E+00, 0.5191833323605244E+00, 0.9894484508239253E+00, 0.5658659268235589E-01, 0.1289734762146678E+00, 0.3341027001588562E+00, 0.6587235353882195E+00, 0.7097532970603662E+00, 0.5025058684824796E+00, 0.5130835936402325E+00, 0.6692657853529054E+00, 0.2879265169895939E+00, 0.8181258306911487E-01, 0.2380388408780171E+00, 0.1056636973917433E+00, 0.4227669640232596E+00, 0.8862610364887391E+00, 0.3174262171725216E+00, 0.4110634725577023E+00, 0.6279625314936111E+00, 0.2325114979496041E+00, 0.5638889949786475E+00, 0.7596856267416864E+00, 0.8240081240110467E+00, 0.9973320050910897E+00, 0.5587421997876323E+00, 0.4288334013103122E+00, 0.8314043340979348E+00, 0.5650188659610876E+00, 0.2964679109455457E+00, 0.8407175605087841E+00, 0.1058970658656445E+00, 0.6883026296612506E+00, 0.9166830669002658E+00, 0.7992763288082885E+00, 0.5373538962118501E+00, 0.8167960120885054E-01, 0.9998997916538879E+00, 0.1975674901149639E+00, 0.7582212604798201E+00, 0.2860808530483561E+00, 0.5862675745609662E+00, 0.4334284293442484E+00, 0.9545191575190999E+00, 0.5542276060509370E+00, 0.9135493345204525E+00, 0.9597250519108470E+00, 0.4020434518393716E+00, 0.2147209304773570E+00, 0.8396072187357826E+00, 0.5371494282057584E+00, 0.9930506172699961E+00, 0.3818967451326610E+00, 0.8312670748053316E+00, 0.7518558266385443E+00, 0.7897281313428761E+00, 0.4898691976861856E+00, 0.9259118998644267E+00, 0.2411762039549979E+00, 0.3003769542607895E+00, 0.9868194969589331E+00, 0.1841003538786936E+00, 0.1211293694641126E+00, 0.7968556025054743E+00, 0.5500013093928259E+00, 0.1705581246551358E-01, 0.5695318221187962E-02, 0.1626907733376057E+00, 0.3178865594423397E-01, 0.6489383021126400E+00, 0.3661200730578906E-01, 0.9937238435410299E+00, 0.8693948290233534E+00, 0.8108974262339508E-01, 0.4858895290851201E+00, 0.5417752479164495E+00, 0.3742432440371155E+00, 0.4593696265617863E+00, 0.7058043658513553E+00, 0.3505553117224474E+00, 0.9647100571711842E+00}, + n: 21, + zOut: []float64{0.2698643664756728E+01, 0.2430046536911446E+01, 0.2385739474636754E+01, 0.2028138720182182E+01, 0.1901894919230603E+01, 0.1736372633374239E+01, 0.1325608228839813E+01, 0.1300504895564844E+01, 0.1261345481029282E+01, 0.1136052475360616E+01, 0.1031365869480280E+01, 0.7689316276636458E+00, 0.5233321832080760E+00, 0.4817169321317593E+00, 0.3418348106633131E+00, 0.2652183763191593E+00, 0.1871042345023881E+00, 0.9160826173360032E-01, 0.4317601760647842E-01, 0.3303497213448481E-02, 0.1231458285303120E-03, 0.9226440439387837E-18, 0.2555628409159789E-14, 0.2440793084913596E-14, 0.1325608228839813E+01, 0.0000000000000000E+00, 0.5589422112493051E-13, 0.3085898188945034E-13, 0.1300504895564844E+01, 0.7444625512849138E-23, 0.1759654299048522E-12, 0.9781103208866350E-13, 0.1261345481029282E+01, 0.6802337789204302E-18, 0.3650786119252150E-16, 0.3306223266172732E-17, 0.1136052475360616E+01, 0.9063201483067583E-22, 0.4434055300668524E-09, 0.2614666143660316E-09, 0.1031365869480280E+01, 0.2213258132402469E-23, 0.2194206198623719E+02, 0.2194206198623719E+02, 0.1100000000000000E+03, 0.3090702947845805E+01, 0.2727272727272727E+01, 0.1493749053307339E-05, 0.5233321832080760E+00, 0.6795157417200880E-17, 0.4382394072074649E-04, 0.6871024518289093E-04, 0.4817169321317593E+00, 0.6227468015696590E-20, 0.2332676874935389E-03, 0.1644354889791431E-03, 0.3418348106633131E+00, 0.8455074291031222E-24, 0.5211421342985135E-03, 0.2133578004049512E-03, 0.2652183763191593E+00, 0.4572942646937810E-19, 0.1472671843690071E-04, 0.1084821769416695E-04, 0.1871042345023881E+00, 0.4930380657631324E-31, 0.2208706795255935E-03, 0.1179477310012027E-03, 0.9160826173360032E-01, 0.2210123199165121E-23, 0.1806566548732391E-03, 0.1927419907906541E-03, 0.4317601760647842E-01, 0.5416053917983313E-23, 0.1030445327331746E-02, 0.1902956416897231E-02, 0.3303497213448481E-02, 0.8065145389241560E-19, 0.2031248978330205E-02, 0.9946626682395031E-03, 0.1231458285303120E-03, 0.1613264727387662E-23, 0.1026826157383968E-01, 0.7685291223570192E-02}, + info: 0, + }, + { + z: []float64{0.9180725347208115E+00, 0.2301506372544524E+00, 0.2276838071944142E+00, 0.3342400207211600E+00, 0.9639463843013925E+00, 0.5437724527901152E+00, 0.1580993234156807E+00, 0.7877490287014776E+00, 0.3507533849023979E+00, 0.8833112450245699E+00, 0.3185731691946991E-01, 0.4118134066759526E+00, 0.8069686780110494E+00, 0.8681061806796153E-01, 0.6859948674552803E+00, 0.3663178920382139E+00, 0.3720291416615038E+00, 0.8903287156706564E+00, 0.1324429304812152E+00, 0.1008541223140741E+00, 0.8373883396136816E-01, 0.6715628313581425E+00, 0.1594467086953334E+00, 0.5413131938455139E+00, 0.1818140526389971E+00, 0.8685248287187100E+00, 0.5132298455242696E+00, 0.6886095101515632E+00, 0.4005049001067575E+00, 0.6084237383755163E+00, 0.7877676299774720E+00, 0.7102138904901485E+00, 0.6423372229000449E+00, 0.5613660527307726E+00, 0.9158966894941798E+00, 0.4933711427035579E+00, 0.7338439214039514E+00, 0.9908978412238557E+00, 0.5798575644928616E-01, 0.8977291910051136E+00, 0.9253772304099678E+00, 0.3904911857418987E+00, 0.4422593302764081E+00, 0.8489177311215401E+00, 0.7212670509555793E+00, 0.9615617648004515E+00, 0.8226716687395509E+00, 0.9612871412036802E+00, 0.1291974168797438E-01, 0.4488531482063538E+00, 0.2469769340642032E+00, 0.3614360453900619E+00, 0.2074351009622584E+00, 0.7016685284881871E+00, 0.1548060648394445E-01, 0.7311687113133817E+00, 0.9296728393442250E+00, 0.9396166536686752E+00, 0.8501954423645642E+00, 0.4336964896981472E+00, 0.6496017727538979E+00, 0.4464862127725214E+00, 0.4878335970157573E+00, 0.3486784051750773E+00, 0.7455411052079824E+00, 0.5444043691163374E+00, 0.3832092245164885E+00, 0.2030848069834680E+00, 0.9785068556455849E+00, 0.4981273340936699E+00, 0.2968547769748885E+00, 0.8139137104995479E+00, 0.5979876314385963E+00, 0.7890959952347512E+00, 0.1396638856742113E+00, 0.6423356747667288E+00, 0.4204101650717844E+00, 0.3861511203891811E+00, 0.5255853602620404E+00, 0.8105960955427686E+00, 0.1919308380441287E-01, 0.5308532240470543E-01, 0.3836913823972644E+00, 0.5510156269652182E+00}, + n: 21, + zOut: []float64{0.2573005090179951E+01, 0.2214810120454235E+01, 0.1922733254389488E+01, 0.1915272191491466E+01, 0.1796031325760082E+01, 0.1645710570695390E+01, 0.1570469265391087E+01, 0.1354841927194508E+01, 0.1294466452193999E+01, 0.1181212352080131E+01, 0.1084541549607215E+01, 0.7996017680870424E+00, 0.7671322760534200E+00, 0.5413194973828868E+00, 0.4525283650095193E+00, 0.2478901170080125E+00, 0.2160828479985811E+00, 0.1019188530491480E+00, 0.3154199687907010E-01, 0.6039114283538317E-02, 0.2585297601905087E-05, 0.1842779074596284E-25, 0.3846373205279405E-07, 0.1879918241657939E-07, 0.1570469265391087E+01, 0.5301607341005493E-20, 0.5291292043249480E-06, 0.9680604951014117E-06, 0.1354841927194508E+01, 0.4298088920574052E-25, 0.7835178780587823E-04, 0.5534134534297650E-04, 0.1294466452193999E+01, 0.1009741958682895E-27, 0.1198198722705974E-04, 0.2465537083987539E-04, 0.1181212352080131E+01, 0.6309019138365174E-17, 0.1614759348306573E-06, 0.9017894254302745E-07, 0.1084541549607215E+01, 0.2228464273087314E-11, 0.2171715152048637E+02, 0.2171715152048638E+02, 0.1110000000000000E+03, 0.3170068027210884E+01, 0.4504504504504505E+01, 0.2430910851731611E-05, 0.7671322760534200E+00, 0.2706512346053632E-23, 0.6377722122869933E-05, 0.4589261521941547E-05, 0.5413194973828868E+00, 0.6745076284001739E-23, 0.1892848367477632E-04, 0.2486261833151780E-04, 0.4525283650095193E+00, 0.4943696629711454E-24, 0.8902582280300076E-04, 0.6878116767917398E-04, 0.2478901170080125E+00, 0.2843433355651033E-22, 0.3448699135776589E-03, 0.2736188045956721E-03, 0.2160828479985811E+00, 0.6002787666751380E-18, 0.2577148216451160E-04, 0.6049628369117275E-04, 0.1019188530491480E+00, 0.1341063538875720E-28, 0.1448550797531803E-02, 0.1280708514177034E-02, 0.3154199687907010E-01, 0.6162975822039155E-32, 0.1183522807025889E-02, 0.1098677799367788E-02, 0.6039114283538317E-02, 0.2067951531379678E-24, 0.3575820084217755E-02, 0.2195872556012757E-02, 0.2585297601905087E-05, 0.1137373342260413E-23, 0.1063898509008824E-02, 0.9861644892506420E-03}, + info: 0, + }, + { + z: []float64{0.9985296910189717E+00, 0.8831740589213332E+00, 0.2324113848518039E+00, 0.7533238559688371E+00, 0.3064992106368385E+00, 0.3932363212439300E+00, 0.5064743635322475E+00, 0.2720810167440399E+00, 0.1759478514683438E+00, 0.1390889491193166E+00, 0.1132483424706631E+00, 0.7690628781223635E+00, 0.9618570638759271E+00, 0.5440138404508711E+00, 0.4137500693527351E+00, 0.1092888165750733E+00, 0.3873107100859553E+00, 0.6511277223354393E+00, 0.2155123791160785E-02, 0.9398729888067584E+00, 0.6720352720616287E+00, 0.1535603342192503E+00, 0.1531061200685264E+00, 0.7545904619621174E+00, 0.7663253741916968E+00, 0.9523625338296001E+00, 0.7564452546028717E+00, 0.3871338859213032E+00, 0.8414924166180344E+00, 0.9656526120147547E+00, 0.8983142486291256E+00, 0.4931225086134777E+00, 0.2402429523967143E+00, 0.2566457485714786E+00, 0.6291482026295649E+00, 0.3102713820139572E+00, 0.8907835976003569E+00, 0.7576089622962475E+00, 0.4268794706004859E+00, 0.9679759265393412E+00, 0.8761096912299335E+00, 0.8367482459498927E+00, 0.6924039391525048E+00, 0.1390797616032549E+00, 0.4788493402292462E+00, 0.4619292003991998E+00, 0.6108276748986761E+00, 0.4236594210420574E-01, 0.1642264441572165E+00, 0.3019681501044491E+00, 0.6872347566608095E-01, 0.4797791709329366E+00, 0.3191437336153862E+00, 0.4231397520665843E+00, 0.9123119461602809E+00, 0.4032629658718287E+00, 0.3761450089120290E+00, 0.1152232563042578E+00, 0.9954630682646954E+00, 0.5373824202779058E+00, 0.6106178691724040E-01, 0.8364420731639322E-01, 0.8933845816890847E+00, 0.5581653322395922E+00, 0.2899731736068278E-01, 0.1770979452363362E+00, 0.5004901441174880E-01, 0.7090935149513330E+00, 0.6196074778714252E+00, 0.7620558730426811E+00, 0.3663579087238161E+00, 0.7799033559850937E+00, 0.5196335588513137E+00, 0.2674625162438964E+00, 0.2943854187199277E+00, 0.7770221064689762E+00, 0.1654873860303906E+00, 0.1664508117665333E+00, 0.4846990191351895E+00, 0.8900931539882498E+00, 0.1193560423223905E-01, 0.7974122776570580E+00, 0.1940680748090599E+00, 0.6554519288132757E+00}, + n: 21, + zOut: []float64{0.2834962035267250E+01, 0.2457739633394971E+01, 0.2412615740112653E+01, 0.2205350258735166E+01, 0.2102070731548960E+01, 0.1691268502125131E+01, 0.1682341944223941E+01, 0.1365229052855181E+01, 0.1159748452086257E+01, 0.1104152264055237E+01, 0.9082896055849982E+00, 0.8350561719565637E+00, 0.6006322679527780E+00, 0.5944104151258589E+00, 0.3054714512857917E+00, 0.1934898777304675E+00, 0.1070106456037005E+00, 0.7977404013852835E-01, 0.4467492857453391E-01, 0.1796045849894196E-01, 0.1273912617121224E-04, 0.5392013224803094E-11, 0.7047397633000775E-04, 0.4975950204285101E-04, 0.1682341944223941E+01, 0.0000000000000000E+00, 0.1776257168565356E-04, 0.2478687660984077E-04, 0.1365229052855181E+01, 0.2904595710528663E-17, 0.2723859519581362E-08, 0.9106491605280572E-08, 0.1159748452086257E+01, 0.1011100673149366E-15, 0.1332628661445848E-04, 0.5871026575773219E-05, 0.1104152264055237E+01, 0.8308334390451641E-18, 0.8332699889408906E-05, 0.9212653513444334E-05, 0.9082896055849982E+00, 0.3518078502828044E-18, 0.2270226121598308E+02, 0.2270226121598308E+02, 0.1240000000000000E+03, 0.3505668934240363E+01, 0.5645161290322581E+01, 0.2479678732743906E-05, 0.6006322679527780E+00, 0.0000000000000000E+00, 0.7879659138115500E-06, 0.7199236433698600E-06, 0.5944104151258589E+00, 0.3024585909035025E-20, 0.8203337497349541E-06, 0.8765068833865939E-06, 0.3054714512857917E+00, 0.4733165431326071E-26, 0.3737214231038995E-06, 0.3923468144379782E-06, 0.1934898777304675E+00, 0.4260044778133448E-20, 0.3232147542049518E-06, 0.3376352641996194E-06, 0.1070106456037005E+00, 0.3308722450212072E-23, 0.5070207875063323E-06, 0.4107488228647395E-06, 0.7977404013852835E-01, 0.6162975822039155E-32, 0.1529214528521930E-08, 0.6332986682625979E-08, 0.4467492857453391E-01, 0.1074272623509048E-20, 0.2583088473438835E-04, 0.1663016813733052E-04, 0.1796045849894196E-01, 0.7053209140113412E-22, 0.1477449551257491E-03, 0.9547349784916723E-04, 0.1273912617121224E-04, 0.0000000000000000E+00, 0.2066074227952428E-02, 0.2903362394245088E-02}, + info: 0, + }, + { + z: []float64{0.9711900205601530E+00, 0.1638861523026915E+00, 0.1833187318057834E+00, 0.9072755753374127E+00, 0.2283578849017619E+00, 0.7520216236020175E+00, 0.3999380553956507E+00, 0.2624503967963340E+00, 0.4831766333071612E+00, 0.5439216550253211E+00, 0.6414566703448968E+00, 0.4958417903972772E+00, 0.6484413600580574E+00, 0.7544273119845675E+00, 0.7061059155531373E+00, 0.9606326194792012E+00, 0.5067069535242709E+00, 0.3029510615023524E+00, 0.6987030441702768E+00, 0.9783205951302908E+00, 0.1548952654742521E+00, 0.9315036439248046E+00, 0.5516706717897903E+00, 0.5168328579759034E+00, 0.3596295330063849E+00, 0.4476574932894306E-01, 0.9741728325615778E+00, 0.2804678894509116E-01, 0.3902916772468864E+00, 0.8530466945184888E+00, 0.2969904800916723E-01, 0.1860020491995459E+00, 0.7523094177753908E-01, 0.1049676044274535E+00, 0.9260152605248726E+00, 0.4316992548719201E+00, 0.7469073285915341E+00, 0.9833774639100495E+00, 0.4974597252506658E+00, 0.4177634673241238E+00, 0.2822911131407428E+00, 0.8441017127353869E+00, 0.3634452570924520E+00, 0.3139202807660985E+00, 0.3006600055674361E+00, 0.3009046530704764E+00, 0.5749841775931973E+00, 0.8312625997674838E+00, 0.7353697939061690E+00, 0.5347208541042444E+00, 0.3745659295783104E+00, 0.2530774659476339E+00, 0.4186076940004666E+00, 0.9926397860987635E+00, 0.9744627902125954E+00, 0.5156862870399348E-01, 0.9609885826474012E+00, 0.1340044668459911E+00, 0.4269295726396694E+00, 0.1323606439861225E+00, 0.9547002490565327E+00, 0.3235500895339022E+00, 0.9408694232081565E+00, 0.5256315334453321E-01, 0.5435043012268493E+00, 0.8290694048290136E+00, 0.3690485876123201E+00, 0.1315626820984572E+00, 0.7782838224801890E+00, 0.4824080201008953E+00, 0.4904940544366522E+00, 0.7125669967024466E+00, 0.2079010288312985E+00, 0.3154779356788950E+00, 0.8039212621301359E+00, 0.1606576564727077E+00, 0.9470564071979923E+00, 0.9189825217362574E+00, 0.4332760074849629E+00, 0.2823180730446854E+00, 0.8869162317432342E+00, 0.9632623909785668E+00, 0.5010388463829042E+00, 0.4287967421178640E+00}, + n: 21, + zOut: []float64{0.2578695081979337E+01, 0.2397185171350384E+01, 0.2122428254475021E+01, 0.1845603260474165E+01, 0.1680081614592041E+01, 0.1588339204725779E+01, 0.1309467974766432E+01, 0.1299839243529426E+01, 0.1209324813016549E+01, 0.1078225499420584E+01, 0.1021574489264402E+01, 0.8212075951361281E+00, 0.6252200086865959E+00, 0.5691142568406321E+00, 0.4167987738801949E+00, 0.2624912719101158E+00, 0.1530089161378868E+00, 0.6867147881453296E-01, 0.2505166907249862E-01, 0.2349256929716605E-02, 0.7151879759250424E-03, 0.1577721810442024E-29, 0.4511324342265551E-10, 0.2432911773654117E-10, 0.1309467974766432E+01, 0.0000000000000000E+00, 0.2950215161815511E-09, 0.4606013118502744E-09, 0.1299839243529426E+01, 0.0000000000000000E+00, 0.1717787641934460E-08, 0.1104907179077728E-08, 0.1209324813016549E+01, 0.2227112107619961E-25, 0.8047601721100021E-14, 0.3064349892439287E-13, 0.1078225499420584E+01, 0.1519533811285116E-12, 0.1082897652895214E-09, 0.2849698526408556E-09, 0.1021574489264402E+01, 0.9160719227198137E-18, 0.2107539302297835E+02, 0.2107539302297835E+02, 0.1110000000000000E+03, 0.3317460317460318E+01, 0.3603603603603604E+01, 0.1689224645784323E-04, 0.6252200086865959E+00, 0.1615587133892632E-26, 0.8276137867398754E-04, 0.1155304449854771E-03, 0.5691142568406321E+00, 0.1852884571782062E-20, 0.2098842504693311E-03, 0.1630830816462844E-03, 0.4167987738801949E+00, 0.7013543182763534E-16, 0.5750632050789642E-07, 0.3137720527277731E-06, 0.2624912719101158E+00, 0.1295300917428640E-14, 0.8049639874935534E-04, 0.1584688939577041E-03, 0.1530089161378868E+00, 0.3636550670570672E-17, 0.1206768167404478E-03, 0.2128462525136164E-03, 0.6867147881453296E-01, 0.4176548246217679E-19, 0.3626791442965051E-04, 0.6269592722343766E-04, 0.2505166907249862E-01, 0.8628166150854817E-31, 0.1144078296038157E-02, 0.1062123559861287E-02, 0.2349256929716605E-02, 0.1853343815383365E-22, 0.1348818609641394E-03, 0.1209095310981735E-04, 0.7151879759250424E-03, 0.2331746618088476E-23, 0.3639492207606013E-03, 0.1002254703741813E-03}, + info: 0, + }, + { + z: []float64{0.5145122753774686E+00, 0.7453791781450037E+00, 0.4937919697078275E-01, 0.9600912461125237E+00, 0.5558575009096904E+00, 0.9202496102671529E+00, 0.1803962777705234E+00, 0.6732582413383450E+00, 0.3646300420523177E+00, 0.4351523227625338E+00, 0.5258615952095320E+00, 0.2618724553334706E-01, 0.6600255279090639E+00, 0.4323183918305084E+00, 0.2184526174816337E+00, 0.7758998738943313E+00, 0.3700044944947983E+00, 0.9075309916724112E+00, 0.7873590137849384E-02, 0.6422780210226944E+00, 0.7012374235504933E+00, 0.3225317189575561E-01, 0.9626413579028830E+00, 0.2957325301869758E+00, 0.9393912496594896E+00, 0.3122772343061888E+00, 0.3372582329155205E-01, 0.6694758703662361E+00, 0.5160501222108982E-03, 0.9689575293997177E-01, 0.3780626069308365E+00, 0.1243877469635841E+00, 0.3753610862140089E+00, 0.7686454249086220E+00, 0.8958999262270639E+00, 0.9484254659678725E+00, 0.7229120985603210E-01, 0.7282046499931183E+00, 0.1602916509824523E+00, 0.3708722215113680E+00, 0.5328491413896952E+00, 0.7547173918812869E+00, 0.4313535833192655E+00, 0.5849601017371611E+00, 0.5030126650939655E+00, 0.3345267020968724E+00, 0.8264894134567216E+00, 0.3997968176112487E+00, 0.7977852660508306E+00, 0.3214021056175872E+00, 0.4636510192825659E+00, 0.6796405156053968E+00, 0.6279823358542748E+00, 0.1573806073104234E-01, 0.6382889890358745E-01, 0.5417145287154319E+00, 0.2343304174607242E+00, 0.7662339681589646E+00, 0.6291880658725347E+00, 0.5139706179483768E+00, 0.1583956600060378E+00, 0.9391868842090931E+00, 0.2645051239078070E+00, 0.7814123021217941E+00, 0.8945112708258808E+00, 0.7464898217422987E+00, 0.3770460515219444E+00, 0.3622886345531428E+00, 0.2208273216958112E-01, 0.7102940678247979E+00, 0.2735151315490909E+00, 0.4039400600381490E+00, 0.9317363313474538E+00, 0.5754441557390587E+00, 0.5886999087747160E+00, 0.3030246870939485E+00, 0.8507721951782303E+00, 0.3043440840669203E+00, 0.6021496993262363E+00, 0.4505272689007913E+00, 0.3874595231430722E+00, 0.2566155965014733E+00, 0.2521494866083717E+00, 0.7091848125152684E+00}, + n: 21, + zOut: []float64{0.2432728498446405E+01, 0.2127807422546525E+01, 0.1810603620342434E+01, 0.1754551066335428E+01, 0.1442239744319712E+01, 0.1358471286041730E+01, 0.1268104094970585E+01, 0.1166598518949770E+01, 0.1142749842956014E+01, 0.8038795081997708E+00, 0.7842646316799070E+00, 0.7340488722153766E+00, 0.6406325830516326E+00, 0.6326463399427553E+00, 0.4829120798428922E+00, 0.4021501496449236E+00, 0.3628067219099092E+00, 0.1315077965186685E-01, 0.3447035773652165E-02, 0.9829838131645125E-03, 0.5542446906743292E-07, 0.3726944967513355E-18, 0.7775649827661083E-15, 0.4707679240410040E-15, 0.1268104094970585E+01, 0.4204313080465905E-25, 0.2081271826241763E-14, 0.3549560565109884E-14, 0.1166598518949770E+01, 0.0000000000000000E+00, 0.3900682806423283E-13, 0.2423637210496787E-13, 0.1142749842956014E+01, 0.1408856084028437E-16, 0.9605918786201080E-13, 0.6043593726409546E-13, 0.8038795081997708E+00, 0.8160364745046778E-12, 0.9063031760991450E-12, 0.1255592191298957E-11, 0.7842646316799070E+00, 0.2274746684496083E-23, 0.1936477583605892E+02, 0.1936477583605892E+02, 0.1150000000000000E+03, 0.3673469387755102E+01, 0.7826086956521739E+01, 0.1055105767279683E-11, 0.6406325830516326E+00, 0.7534418653829021E-12, 0.2026915084594321E-10, 0.1938443898507311E-10, 0.6326463399427553E+00, 0.7428954317778491E-22, 0.1822158222411987E-10, 0.2310105649781206E-10, 0.4829120798428922E+00, 0.6818472407494482E-21, 0.4806621018591031E-08, 0.3430760494577760E-08, 0.4021501496449236E+00, 0.9407638730741502E-13, 0.4934881466368944E-07, 0.7682525823543034E-07, 0.3628067219099092E+00, 0.4641733924717305E-17, 0.3006332568302334E-06, 0.4841414710438772E-06, 0.1315077965186685E-01, 0.0000000000000000E+00, 0.4649166787994157E-03, 0.6126205080519521E-03, 0.3447035773652165E-02, 0.0000000000000000E+00, 0.8654037114492079E-03, 0.1518309118546661E-02, 0.9829838131645125E-03, 0.2948446519354054E-25, 0.2136365904689920E-10, 0.9493111427282873E-09, 0.5542446906743292E-07, 0.0000000000000000E+00, 0.8210503952597113E-02, 0.1866280792966489E-03}, + info: 0, + }, + { + z: []float64{0.1382149566425072E+00, 0.6575474867299980E+00, 0.6348472674088155E+00, 0.2171300387013793E+00, 0.8255967246227341E+00, 0.3006539504418347E+00, 0.2997341048143420E+00, 0.8472159875058289E+00, 0.6738978429295159E+00, 0.5424646868297128E+00, 0.4120014569672862E+00, 0.8343380028244362E+00, 0.3003911043596160E+00, 0.4710045367840567E+00, 0.4862652198104067E-01, 0.7471894777046170E+00, 0.1793049886163456E+00, 0.7023511329140396E+00, 0.7338019696975340E-02, 0.6396982308318109E+00, 0.9907774162255600E-01, 0.9295761484947797E+00, 0.9648060362942152E+00, 0.9280158186031068E+00, 0.2707915909911263E-01, 0.3838735516497237E+00, 0.1682677327524866E+00, 0.2113105759433432E+00, 0.9045861188128749E+00, 0.7471063495001966E+00, 0.8342180430544732E-01, 0.1412979915701199E+00, 0.8279925714974835E+00, 0.1155895711297670E+00, 0.9231783969041454E+00, 0.3728782651185074E+00, 0.6830046202574890E+00, 0.9069008465878121E+00, 0.9754648591267837E+00, 0.8893150707687680E-01, 0.6771275111272185E+00, 0.9913978119103384E+00, 0.7253101374756428E+00, 0.9967636737323063E+00, 0.8627812047783159E+00, 0.3179382291892185E-01, 0.3971194218951257E+00, 0.1929798662828303E+00, 0.8983406738830656E+00, 0.8696986427722838E+00, 0.1626550211323166E+00, 0.5446758738044107E+00, 0.7791897500950196E+00, 0.5495589328822522E+00, 0.2598162756138545E+00, 0.4878822167962611E+00, 0.1063554708684851E+00, 0.9205986422545666E+00, 0.2525019548845375E+00, 0.6202404757545382E+00, 0.4398012123976176E+00, 0.3367811528280380E+00, 0.2846930465290612E+00, 0.3637854092863660E+00, 0.2816012898088578E+00, 0.8253973364224151E+00, 0.1068693035499244E+00, 0.6335234891165292E+00, 0.4457012705011152E+00, 0.3822128202770037E-01, 0.8044679788500431E-02, 0.1644333417433916E+00, 0.8243501026702226E+00, 0.3724822902257573E+00, 0.3284619434713851E+00, 0.8284230195063381E+00, 0.9834160248288059E+00, 0.5390643127606534E+00, 0.4874602694948874E+00, 0.3393327340444893E+00, 0.9478697182248690E+00, 0.9005921446100461E+00, 0.6870582101064761E+00, 0.8753727823211164E+00}, + n: 21, + zOut: []float64{0.2520205603715150E+01, 0.2467591671122728E+01, 0.2156156465592955E+01, 0.1830603796963098E+01, 0.1688980285573207E+01, 0.1475729352347043E+01, 0.1457403847234258E+01, 0.1216096979409916E+01, 0.1020221539309743E+01, 0.9109792709218910E+00, 0.7786685137433046E+00, 0.6943983149907305E+00, 0.5952732619368740E+00, 0.5747064141061984E+00, 0.4193783470766816E+00, 0.2849493660130012E+00, 0.2000335007304226E+00, 0.1879518797669419E+00, 0.9250201866750386E-01, 0.6720326503698931E-01, 0.2522304426258675E-08, 0.0000000000000000E+00, 0.6146929522129176E-12, 0.1808448588630822E-11, 0.1457403847234258E+01, 0.4890937612370273E-28, 0.1829381779873047E-10, 0.6063479072736104E-11, 0.1216096979409916E+01, 0.3707772472283591E-24, 0.7129364201262979E-09, 0.6841733798178873E-09, 0.1020221539309743E+01, 0.2138261883449577E-21, 0.5257033338238628E-09, 0.5072654023074907E-09, 0.9109792709218910E+00, 0.7953858577580093E-22, 0.4258628064439383E-09, 0.4402488234184115E-09, 0.7786685137433046E+00, 0.2050608176139579E-11, 0.2063903369678094E+02, 0.2063903369678095E+02, 0.1070000000000000E+03, 0.3256235827664399E+01, 0.7476635514018692E+01, 0.2680505535092421E-09, 0.5952732619368740E+00, 0.3490920289236852E-22, 0.2767075275933556E-09, 0.2579359628684292E-09, 0.5747064141061984E+00, 0.6550779105727953E-17, 0.5565909614599560E-09, 0.4340922452181151E-09, 0.4193783470766816E+00, 0.3307688474446419E-20, 0.4344481061547019E-08, 0.2950068756973984E-08, 0.2849493660130012E+00, 0.2114500635677851E-23, 0.2105683914952377E-07, 0.1386409244069912E-07, 0.2000335007304226E+00, 0.2552627671550359E-24, 0.1231406445198996E-06, 0.7724199195397155E-07, 0.1879518797669419E+00, 0.2762617809804602E-19, 0.3259696859933768E-06, 0.5428848805276070E-06, 0.9250201866750386E-01, 0.2465190328815662E-31, 0.5308529636258477E-04, 0.3674504775836459E-04, 0.6720326503698931E-01, 0.4910144116114772E-20, 0.8312610965835068E-03, 0.3682729181838852E-03, 0.2522304426258675E-08, 0.0000000000000000E+00, 0.2850162708346282E-01, 0.1272924532804709E-01}, + info: 0, + }, + { + z: []float64{0.8107097465650837E+00, 0.6284212325752714E-02, 0.8801609468679439E-01, 0.1317925189426976E+00, 0.7816238529622888E+00, 0.5138440552812117E+00, 0.8491910920486024E+00, 0.5354109734403600E-01, 0.9922209940223927E+00, 0.5302203883752287E+00, 0.7634020308181488E-01, 0.1679415943232965E+00, 0.2329711998757648E+00, 0.1414305919938111E+00, 0.1841480420952157E-01, 0.3417588803467335E+00, 0.2555749764808386E+00, 0.5793635436480560E-01, 0.5867939998055902E+00, 0.9699556000711096E+00, 0.2545002439558014E+00, 0.6318762794888357E+00, 0.3917398730545906E+00, 0.5624711052874073E+00, 0.4151753215255505E-01, 0.2323556867603191E+00, 0.8346423132579881E+00, 0.4193569213002444E+00, 0.5070048505400149E+00, 0.9880568155195324E-01, 0.6350898210108906E+00, 0.2370382383359541E+00, 0.3299228061150288E+00, 0.4349239764921071E+00, 0.5262500692361848E+00, 0.5263549923651836E+00, 0.8161052184432745E+00, 0.5568267671289201E+00, 0.7852669932205985E+00, 0.4481607592551184E-01, 0.6290146498792036E+00, 0.9736787804665343E+00, 0.5369941621471508E+00, 0.6750777504837204E+00, 0.9452511173220645E+00, 0.3252402467696922E+00, 0.8149000487070703E+00, 0.8087485664240622E+00, 0.8643101435258340E+00, 0.4683483752594740E+00, 0.5054760923588362E+00, 0.9646412930917844E+00, 0.1611953384510251E+00, 0.6426851941066625E-01, 0.3732266796993424E+00, 0.6384029126799168E+00, 0.3844644469584264E+00, 0.6635273633462982E+00, 0.2553934870916856E+00, 0.7037835913610216E+00, 0.7783327991001192E+00, 0.7381327592761330E+00, 0.2765915485450557E+00, 0.9846188872724937E-01, 0.1992562101416243E+00, 0.2440052895970430E+00, 0.3301477999473963E+00, 0.5338134839029927E+00, 0.5498293871712301E+00, 0.1974401363114953E+00, 0.7407533997655510E+00, 0.6821638940995054E+00, 0.9814777780110351E+00, 0.4891456709117443E+00, 0.6868139367703679E+00, 0.4181531426430654E+00, 0.6623070699739451E+00, 0.9202771282456093E+00, 0.2973080397025486E+00, 0.4403051603022431E+00, 0.1603780540263299E+00, 0.4910562348998989E+00, 0.7838834745165658E+00, 0.1931809149066596E+00}, + n: 21, + zOut: []float64{0.2163023058341640E+01, 0.1906105992609667E+01, 0.1885682431608721E+01, 0.1629672232824707E+01, 0.1530256904983391E+01, 0.1307296833197682E+01, 0.1220997281181084E+01, 0.9674288853031870E+00, 0.8179252376135864E+00, 0.6735586841320580E+00, 0.6320597056120635E+00, 0.5126868322939253E+00, 0.4828683228163860E+00, 0.4745823594217251E+00, 0.3685025909289511E+00, 0.2947763441663148E+00, 0.8912041525268403E-01, 0.6456597576955210E-01, 0.6259461554584676E-01, 0.1853533814873023E-01, 0.2023108580404890E-03, 0.8671199725506423E-13, 0.1722304485286045E-09, 0.1666294529992108E-09, 0.1220997281181084E+01, 0.1774302413926244E-21, 0.1370178691819834E-09, 0.1399340123848638E-09, 0.9674288853031870E+00, 0.4276620702127187E-22, 0.3173068333548179E-09, 0.2274343348931791E-09, 0.8179252376135864E+00, 0.7888609052210118E-30, 0.5644994943584269E-09, 0.8117631577107350E-09, 0.6735586841320580E+00, 0.2962158340816585E-16, 0.9564613436107998E-08, 0.6775718950029066E-08, 0.6320597056120635E+00, 0.4964115825120276E-16, 0.1710244235260994E+02, 0.1710244235260994E+02, 0.1120000000000000E+03, 0.3265306122448980E+01, 0.6250000000000000E+01, 0.5299633299932952E-07, 0.4828683228163860E+00, 0.2680954403830288E-19, 0.1311205982337445E-05, 0.9790063018353157E-06, 0.4745823594217251E+00, 0.5160286279848935E-24, 0.1890785247579508E-05, 0.1394729630636152E-05, 0.3685025909289511E+00, 0.4693722386065020E-28, 0.6031882082954460E-05, 0.2415384446316590E-05, 0.2947763441663148E+00, 0.1882813323774143E-21, 0.7814092950831008E-04, 0.8799876387761915E-04, 0.8912041525268403E-01, 0.1005797654156790E-28, 0.3017726164846613E-06, 0.1278833151586840E-06, 0.6456597576955210E-01, 0.4635851024992188E-19, 0.2982580055136947E-07, 0.4759731822531787E-07, 0.6259461554584676E-01, 0.4490807166402986E-22, 0.9170799331172770E-06, 0.3025792024297308E-06, 0.1853533814873023E-01, 0.4985600920996795E-27, 0.9814614537388964E-04, 0.3116488226164178E-03, 0.2023108580404890E-03, 0.0000000000000000E+00, 0.9878507322060364E-03, 0.9125548412055403E-03}, + info: 0, + }, + { + z: []float64{0.4943635351465083E+00, 0.1295760812930432E+00, 0.7491711827268356E+00, 0.8583007697336751E+00, 0.8597988452333791E+00, 0.9020619105716389E+00, 0.2915077046929524E+00, 0.2667690273281318E+00, 0.2640508133196529E-01, 0.6592981688042527E+00, 0.5004017812459820E+00, 0.7056211227388411E+00, 0.2254860841977465E+00, 0.8570117342825790E+00, 0.6863131135194549E+00, 0.6029337708611949E+00, 0.6631267757314846E+00, 0.5332167960220966E+00, 0.3047497072553197E+00, 0.3019927731659721E+00, 0.6244714872283929E+00, 0.3204566006732108E+00, 0.9437738905138152E+00, 0.4462876020196550E+00, 0.6693016494515551E+00, 0.5687239407477801E+00, 0.5130358959101252E+00, 0.1634623710980615E+00, 0.6356065394794165E+00, 0.9187737904031696E+00, 0.8612817405760382E+00, 0.1602125514297330E+00, 0.5297426144233635E+00, 0.3699984812614213E+00, 0.3455622529703073E+00, 0.9962779456692529E+00, 0.3564481259772661E+00, 0.2073475342531472E-01, 0.5839325153640170E+00, 0.6856088547326490E+00, 0.1606020836922776E+00, 0.2475573692197572E+00, 0.8169030104559274E+00, 0.1727021335202554E+00, 0.8794153095346040E+00, 0.1052546999951709E-01, 0.4332903851899277E+00, 0.4302943891085251E+00, 0.6360909664440160E+00, 0.1924830187263967E+00, 0.6792019925733094E+00, 0.7328300669715262E+00, 0.8282900281692296E+00, 0.1586820387506954E+00, 0.5999731076117462E+00, 0.4873494502000296E+00, 0.4446262392098149E+00, 0.6430807880043099E-01, 0.4949024386471711E+00, 0.7324156973660632E+00, 0.4547667791304575E+00, 0.7542985454738853E+00, 0.3755946849636591E+00, 0.7135765429513076E+00, 0.7888131931751277E+00, 0.6384460726826821E+00, 0.4685063200928931E+00, 0.1343379262734882E+00, 0.8857603211032115E+00, 0.5798608180272281E+00, 0.8765662925729737E+00, 0.2107645345329755E+00, 0.7032612644639602E-01, 0.2672549085142431E+00, 0.5322118352980683E+00, 0.4697779217142906E-01, 0.1959612687762308E+00, 0.7346288295330818E+00, 0.4373432557584073E+00, 0.2514178299506654E+00, 0.7845430350805238E+00, 0.7823648156079857E+00, 0.6098686444303012E+00, 0.2687771415020881E+00}, + n: 21, + zOut: []float64{0.2638973127799410E+01, 0.2299941431214051E+01, 0.2280019421450360E+01, 0.2103910562764817E+01, 0.1753406216295798E+01, 0.1675269066003242E+01, 0.1419658234290438E+01, 0.1365959224584141E+01, 0.1187696680558471E+01, 0.1126073702945326E+01, 0.8926412592525027E+00, 0.7715773240739381E+00, 0.5428647577479762E+00, 0.4329885186763779E+00, 0.3589145864992100E+00, 0.2461266947628802E+00, 0.1802035742271595E+00, 0.1083562693061272E+00, 0.7909884021715781E-01, 0.2853616071040153E-01, 0.1859995500862765E-03, 0.5169878828456423E-25, 0.7099412452593561E-13, 0.1129160994681896E-12, 0.1419658234290438E+01, 0.7523863534922662E-17, 0.1645873945742296E-11, 0.1162641799741134E-11, 0.1365959224584141E+01, 0.3171195595439500E-23, 0.6168272840237550E-11, 0.8582511762369885E-11, 0.1187696680558471E+01, 0.8519789992808060E-16, 0.1934844654065141E-10, 0.2568816579510325E-10, 0.1126073702945326E+01, 0.8564308176121538E-22, 0.5690968370753065E-10, 0.7456610067231580E-10, 0.8926412592525027E+00, 0.4500097668303756E-13, 0.2149240165292988E+02, 0.2149240165292987E+02, 0.1030000000000000E+03, 0.2950113378684807E+01, 0.4854368932038835E+01, 0.1146501122497315E-08, 0.5428647577479762E+00, 0.2966117003631004E-27, 0.2887486457338918E-08, 0.3484100742696835E-08, 0.4329885186763779E+00, 0.9478952637135678E-26, 0.8311221870318503E-08, 0.6953572191921854E-08, 0.3589145864992100E+00, 0.2375820297137957E-16, 0.1629548458200623E-07, 0.1368379043565619E-07, 0.2461266947628802E+00, 0.1012567897168591E-16, 0.3168042687452701E-07, 0.3807114536183845E-07, 0.1802035742271595E+00, 0.8688408444571280E-16, 0.7017919615597339E-07, 0.9241973720004823E-07, 0.1083562693061272E+00, 0.3747089299799806E-28, 0.3320058009883818E-06, 0.6266972429387508E-06, 0.7909884021715781E-01, 0.9269115636346889E-29, 0.6452918276099027E-05, 0.1508443954686445E-04, 0.2853616071040153E-01, 0.2499111347740165E-24, 0.3360677328899296E-03, 0.1546059694047028E-03, 0.1859995500862765E-03, 0.1972152263052530E-28, 0.5448826922428762E-03, 0.1724316467181159E-02}, + info: 0, + }, + { + z: []float64{0.5641760158025995E+00, 0.2227931624220032E+00, 0.1040729150876691E+00, 0.7228520011975436E+00, 0.2490915552877161E+00, 0.4463107957028827E+00, 0.6882435259034004E+00, 0.2173580561342540E+00, 0.8146865135594571E+00, 0.3630549548424193E+00, 0.2813912484076728E+00, 0.7560034280086618E+00, 0.7800835186160227E-01, 0.9984316063995433E+00, 0.2057310185040729E+00, 0.4428139729521006E+00, 0.1946530136132755E+00, 0.8953866467149748E+00, 0.5910093704925600E+00, 0.9736056943014803E+00, 0.7342559355497796E+00, 0.5630651274913434E+00, 0.3586901690989497E+00, 0.1859950386974873E-01, 0.4012559193852120E+00, 0.5767984160414075E-01, 0.3379735138652440E+00, 0.6337834884220164E+00, 0.8830566914548466E-01, 0.2985048049064926E+00, 0.9820684138520455E+00, 0.1144932752938616E+00, 0.5905532956519596E+00, 0.4757653978696945E+00, 0.1997612463043563E-01, 0.6356348606671800E+00, 0.8478495728965164E+00, 0.4997410778119411E+00, 0.6861774168985810E+00, 0.6912919871514965E+00, 0.1276032443467088E+00, 0.2695430969348002E+00, 0.9446688115451145E+00, 0.5104603739010690E+00, 0.8863068797328323E+00, 0.3347723354379355E+00, 0.2977917172311930E+00, 0.9464871506253476E+00, 0.4279639349386329E+00, 0.6378279454376028E+00, 0.2778621310060349E+00, 0.6971058794896068E-01, 0.6309805553452471E+00, 0.3447281367207256E-01, 0.8480855191050544E+00, 0.6700112511333863E+00, 0.1616260465745026E+00, 0.7744510887458210E+00, 0.8408544531170117E+00, 0.8444763755373497E-01, 0.3286971575766536E+00, 0.8244867044222992E+00, 0.8036107174439190E+00, 0.4654902702844697E+00, 0.8300602115903392E+00, 0.5911511948645825E+00, 0.5734805041784674E+00, 0.6046912223886362E+00, 0.4400460907177143E+00, 0.4069795298963303E+00, 0.2413714645456244E+00, 0.7838758775665940E+00, 0.1371288591293247E+00, 0.8435169936355635E-01, 0.4867567406491472E+00, 0.2914527168883616E+00, 0.7540094160758792E+00, 0.6792178828893637E+00, 0.8924641252729165E+00, 0.2188072300242774E+00, 0.1899571860965691E+00, 0.7806965639263314E+00, 0.8706240780095753E-01, 0.7170634647198669E+00}, + n: 21, + zOut: []float64{0.2553381332090116E+01, 0.2166390759033473E+01, 0.1737362408504838E+01, 0.1528419999405254E+01, 0.1507484707859341E+01, 0.1334735890703865E+01, 0.1222641790395049E+01, 0.1186722126839839E+01, 0.1073660052771764E+01, 0.9488489095119069E+00, 0.9141860725715962E+00, 0.7726247731371300E+00, 0.6075856291402457E+00, 0.5409244297850613E+00, 0.4230641503671385E+00, 0.2356839373494127E+00, 0.1583434617720056E+00, 0.3187519618749328E-01, 0.2747107248999187E-01, 0.1480095837386152E-02, 0.5569185181399456E-04, 0.3215260779752862E-17, 0.2284971140234050E-13, 0.6915955898032105E-13, 0.1222641790395049E+01, 0.9860761315262648E-31, 0.9831000121605633E-10, 0.3802561298586086E-10, 0.1186722126839839E+01, 0.2066815571679051E-27, 0.6142487424703478E-09, 0.1524532000885779E-08, 0.1073660052771764E+01, 0.3155443620884047E-29, 0.1933670198753400E-07, 0.4311109498288097E-07, 0.9488489095119069E+00, 0.6613963504021090E-17, 0.7125410558010122E-07, 0.6137903750393884E-07, 0.9141860725715962E+00, 0.2713620929442760E-22, 0.1897294248760472E+02, 0.1897294248760472E+02, 0.1070000000000000E+03, 0.3233560090702948E+01, 0.4672897196261682E+01, 0.2313496546014482E-05, 0.6075856291402457E+00, 0.2008094738046662E-26, 0.6354651604911740E-04, 0.4633045629030685E-04, 0.5409244297850613E+00, 0.2465190328815662E-30, 0.8082164119218066E-03, 0.5151838483992701E-03, 0.4230641503671385E+00, 0.3299331849996360E-25, 0.9881103085087938E-03, 0.1036550305023510E-02, 0.2356839373494127E+00, 0.2111622871095604E-25, 0.1203513003711909E-02, 0.1300398061184096E-02, 0.1583434617720056E+00, 0.1737664936697394E-23, 0.8260928074113359E-03, 0.9484297179228856E-03, 0.3187519618749328E-01, 0.0000000000000000E+00, 0.1785275423606748E-03, 0.4485462762371783E-03, 0.2747107248999187E-01, 0.8804949879714635E-25, 0.5200632154389635E-08, 0.3234666977722410E-08, 0.1480095837386152E-02, 0.5399595124056782E-24, 0.5661901580915454E-02, 0.5860254353052324E-02, 0.5569185181399456E-04, 0.0000000000000000E+00, 0.1190560893471898E-01, 0.9131404251707014E-02}, + info: 0, + }, + { + z: []float64{0.7290518158132969E+00, 0.5196659176766039E-03, 0.6083923160589086E+00, 0.3459319602615154E+00, 0.3277021139736517E+00, 0.6020592719504614E-01, 0.4608784204502808E+00, 0.8430478676154098E+00, 0.3856212930081542E+00, 0.6602823264317716E+00, 0.4451601253283373E+00, 0.4130313322309198E-01, 0.7414750648249350E+00, 0.1630235543068703E-01, 0.6004925370465983E+00, 0.6953287054569501E+00, 0.7809046354974044E+00, 0.7892746585788727E+00, 0.8348704064067982E+00, 0.5999411739898802E+00, 0.5502575606089829E+00, 0.4392206918044746E+00, 0.7984758158185817E+00, 0.9084185319619590E+00, 0.1786837110145214E+00, 0.2414921532322530E+00, 0.5630913108462098E+00, 0.7820323704275389E+00, 0.5523326888742272E+00, 0.9015512185421630E+00, 0.6659841765947113E+00, 0.2845604319423287E+00, 0.3491764093356571E+00, 0.9628247275953050E-01, 0.6976897044251388E+00, 0.2960314575787897E+00, 0.5554565606281359E-01, 0.3558757052257084E+00, 0.9341850945519581E+00, 0.6665938574616496E+00, 0.9614102712845256E+00, 0.8607214960584614E+00, 0.4038740733880183E+00, 0.8195623831081322E+00, 0.6129183541897144E+00, 0.7215327066311872E-01, 0.5031970254369666E-01, 0.1396452298202989E+00, 0.9662061833347503E+00, 0.1270920838674061E+00, 0.4311106155362532E+00, 0.8052749852152479E+00, 0.4015794631208873E+00, 0.9090852867289334E-01, 0.6606775367976888E+00, 0.1481179966505828E+00, 0.9638580924515038E+00, 0.9709844996525795E+00, 0.1150673643193312E-01, 0.1429293205078334E+00, 0.2900042758147406E+00, 0.9072348766684573E+00, 0.5781273728635536E+00, 0.5436950045999074E+00, 0.1857622262967125E+00, 0.9164714647876027E+00, 0.1370982861482903E+00, 0.4992756875010576E+00, 0.1554652709586491E+00, 0.3126479857720679E+00, 0.4107075699045055E+00, 0.2895846225773548E+00, 0.6273125726015746E+00, 0.2838905730735005E+00, 0.5809021463377108E+00, 0.7647718231557297E+00, 0.2069816461533343E+00, 0.3140055757156704E+00, 0.1235726138058405E+00, 0.4368723232060789E-01, 0.7675622822273089E+00, 0.9898297711455730E+00, 0.5845844813092991E+00, 0.3724928805727834E+00}, + n: 21, + zOut: []float64{0.2656606156715505E+01, 0.2361088067613179E+01, 0.2270460825471249E+01, 0.2122871466419806E+01, 0.1864972075992565E+01, 0.1483766917780093E+01, 0.1313593002893207E+01, 0.1121546276208008E+01, 0.1100149868182268E+01, 0.9659264313206680E+00, 0.7624972132947719E+00, 0.7289080649182198E+00, 0.6752163576811447E+00, 0.6611764720975886E+00, 0.5004340625462813E+00, 0.2440674815088013E+00, 0.2171809202435314E+00, 0.1235497606154792E+00, 0.3737121186344041E-01, 0.2834840406904476E-01, 0.5846755428136478E-02, 0.7443896006885402E-16, 0.5016677150024004E-07, 0.3707799983650212E-07, 0.1313593002893207E+01, 0.2958228394578794E-29, 0.1581957950672119E-06, 0.2298083114979900E-06, 0.1121546276208008E+01, 0.1915993820645148E-16, 0.4749045639556273E-06, 0.4145613346073258E-06, 0.1100149868182268E+01, 0.9026685982667287E-18, 0.2821283116535875E-06, 0.3158894087015811E-06, 0.9659264313206680E+00, 0.2037048580685469E-20, 0.2246093425341190E-06, 0.2076005360058006E-06, 0.7624972132947719E+00, 0.1234566306928925E-21, 0.2124557779286299E+02, 0.2124557779286298E+02, 0.1010000000000000E+03, 0.3002267573696145E+01, 0.2970297029702970E+01, 0.4897987464996691E-04, 0.6752163576811447E+00, 0.7461812581271996E-18, 0.7761124913531668E-04, 0.7483244468930916E-04, 0.6611764720975886E+00, 0.1038114253693458E-19, 0.1582094808245393E-03, 0.1235322388201987E-03, 0.5004340625462813E+00, 0.1010613662291919E-16, 0.2610534203903574E-03, 0.4450812691210283E-03, 0.2440674815088013E+00, 0.1110435042389887E-20, 0.5668320309921573E-04, 0.5311544381771655E-04, 0.2171809202435314E+00, 0.4733165431326071E-27, 0.6599010146996593E-04, 0.7896621041843452E-04, 0.1235497606154792E+00, 0.3155385912111625E-18, 0.1746230697391169E-01, 0.1331928313395539E-01, 0.3737121186344041E-01, 0.7395570986446986E-31, 0.1364698415102933E-02, 0.9400709901879650E-03, 0.2834840406904476E-01, 0.1581043861486090E-22, 0.9826835453665868E-03, 0.1307033404080312E-02, 0.5846755428136478E-02, 0.5593364605928029E-23, 0.6675960788692170E-02, 0.6853670175678725E-02}, + info: 0, + }, + { + z: []float64{0.4059771234161322E+00, 0.9607215623246773E+00, 0.2458768097786967E-01, 0.2349999394464353E-01, 0.5195584553698999E+00, 0.4267565401751807E+00, 0.5653505726897825E+00, 0.1993982232067181E+00, 0.7123509462851438E+00, 0.7322091078130321E+00, 0.6397865818692764E+00, 0.7795245712118530E+00, 0.9924677795119503E+00, 0.9446777193650685E+00, 0.9161440637569995E+00, 0.4356325057978820E+00, 0.6968317286853016E+00, 0.8623411680463823E+00, 0.8789901991689911E+00, 0.3964880116495537E+00, 0.3452640838632506E+00, 0.2457053330236874E+00, 0.3088650440709877E+00, 0.3819576657222301E+00, 0.3428589632713919E-01, 0.5108638376023356E-01, 0.1646491337519898E+00, 0.4402398340108123E+00, 0.6741907107293844E+00, 0.8399512836956711E+00, 0.5689849385173426E+00, 0.5208530271268840E+00, 0.1800472375386978E+00, 0.7659410457647264E+00, 0.2320702606914905E+00, 0.1105800266048680E+00, 0.9555355666039600E-02, 0.1859192596152662E+00, 0.7825627400019242E-02, 0.5286418396370182E+00, 0.2569279638014341E+00, 0.5549104171411018E+00, 0.7406835450501670E+00, 0.8319568443444482E+00, 0.1523286720686696E+00, 0.6741822248281739E+00, 0.7686049385045001E+00, 0.7046090895325479E+00, 0.5187887151753254E+00, 0.1082987708911324E+00, 0.1267838014025160E+00, 0.1115865001832446E+00, 0.9799554493413084E+00, 0.2112830058825086E+00, 0.1414836977037485E+00, 0.6416690587599562E+00, 0.7257743058080667E+00, 0.5941533679852271E+00, 0.2889670048515264E+00, 0.2352763591376699E+00, 0.4250778140801711E+00, 0.1017573282390372E-01, 0.7592168685641336E+00, 0.1236630021486789E+00, 0.3794258137484455E+00, 0.3894249799986492E+00, 0.3467719607731882E+00, 0.5651244918121399E+00, 0.7941305753999619E+00, 0.7160004674307343E+00, 0.6194397297375442E+00, 0.1453439098617406E+00, 0.3817157280391337E-03, 0.9381666563671931E+00, 0.8543357988390619E+00, 0.4675645670082479E+00, 0.8133557631373793E+00, 0.1160066189475003E+00, 0.6551894700973839E+00, 0.6157191087148942E+00, 0.4651705119652626E+00, 0.2935400080400429E+00, 0.4317648586994048E+00, 0.8522331953027451E-01}, + n: 21, + zOut: []float64{0.3090946182879871E+01, 0.2427731098824810E+01, 0.2178358732328273E+01, 0.1944657148720347E+01, 0.1388313875420951E+01, 0.1366009016577358E+01, 0.1254539813854158E+01, 0.1096743376160052E+01, 0.8976114875705017E+00, 0.7925182471468240E+00, 0.7633415317747125E+00, 0.5940562138773567E+00, 0.3406702196684873E+00, 0.2541261981011808E+00, 0.2081990106830526E+00, 0.1967266434974441E+00, 0.8212572008660911E-01, 0.6231598248219099E-01, 0.2121611392818772E-01, 0.6627852439078377E-02, 0.2020564063973749E-05, 0.5156511541642804E-17, 0.3563959083802911E-09, 0.2193664839500192E-09, 0.1254539813854158E+01, 0.5107396913706617E-17, 0.2245013704648247E-08, 0.3514139913607919E-08, 0.1096743376160052E+01, 0.1770166510860316E-21, 0.1137128600534393E-07, 0.7589514151253922E-08, 0.8976114875705017E+00, 0.3631375006656261E-16, 0.1027683956127825E-09, 0.1703981899256795E-09, 0.7925182471468240E+00, 0.0000000000000000E+00, 0.2692111438183261E-08, 0.1491447500870467E-08, 0.7633415317747125E+00, 0.3655079503368504E-18, 0.1896683648658551E+02, 0.1896683648658551E+02, 0.9800000000000000E+02, 0.2941043083900227E+01, 0.3061224489795918E+01, 0.1473194721443778E-07, 0.3406702196684873E+00, 0.8487843002529896E-19, 0.1107295924775035E-05, 0.6897939613884539E-06, 0.2541261981011808E+00, 0.8699892772041781E-19, 0.4010969039165872E-05, 0.5564243023106877E-05, 0.2081990106830526E+00, 0.1258849778182470E-17, 0.2192657884798391E-05, 0.1921286515322920E-05, 0.1967266434974441E+00, 0.1498835719919922E-28, 0.3181611995531238E-06, 0.2328457188758453E-05, 0.8212572008660911E-01, 0.9162137014768053E-16, 0.4655593170815260E-04, 0.2906458517213153E-04, 0.6231598248219099E-01, 0.7111877894410489E-19, 0.1084455050840344E-03, 0.4940544045928809E-04, 0.2121611392818772E-01, 0.1296887328183343E-24, 0.1059468102013224E-02, 0.9250155264543548E-03, 0.6627852439078377E-02, 0.2014616961124939E-22, 0.1082171160654875E-03, 0.1415095048461561E-03, 0.2020564063973749E-05, 0.0000000000000000E+00, 0.6572087989553770E-04, 0.6490933881766271E-04}, + info: 0, + }, + { + z: []float64{0.3515867373170093E+00, 0.6900024519663606E-01, 0.2562617636787797E+00, 0.4448144612254716E+00, 0.1882829208975508E+00, 0.5473764707914393E+00, 0.2385465140832452E+00, 0.1069888484826550E+00, 0.6650479699038470E+00, 0.5577458834974632E+00, 0.3827016483759793E-01, 0.2430476485682098E-01, 0.4730689827049095E-01, 0.7028807845337007E+00, 0.2183345614483843E+00, 0.4504620631941809E+00, 0.4989666416356805E+00, 0.3524179690092576E+00, 0.2245980971932510E+00, 0.4235501615333767E+00, 0.5262756658101302E+00, 0.9543218824354944E+00, 0.7932768470961233E+00, 0.6115989702914060E-01, 0.5090745247561921E+00, 0.6231416396947956E+00, 0.5848645563028462E+00, 0.4261243979220120E-01, 0.7488050001299923E+00, 0.1371419590365067E+00, 0.2276573560104874E+00, 0.3333510148295767E+00, 0.8801005866377587E+00, 0.1783788042757909E+00, 0.7167665061134074E+00, 0.8328416386285911E+00, 0.3239179761297745E+00, 0.3396256067647054E+00, 0.3124818554244235E-01, 0.3558253686357221E+00, 0.3434895378785284E+00, 0.5623459587025392E-01, 0.2638452014850361E+00, 0.8291744484791080E+00, 0.1974847584119865E+00, 0.7319795333910079E+00, 0.2610606436005336E+00, 0.5710127034520260E+00, 0.1439281438102160E+00, 0.9086761346521347E+00, 0.8079247890865698E+00, 0.9018578929430654E+00, 0.4900454364738460E+00, 0.8138610668520670E+00, 0.6711229676830790E+00, 0.5055629692453131E+00, 0.7743169767236130E+00, 0.4534345901632091E+00, 0.9064089158232752E+00, 0.4827899713942460E+00, 0.7358703780808750E+00, 0.9369729458478693E-02, 0.8597279323370060E+00, 0.7253136203352766E+00, 0.9571052925069841E+00, 0.2164676786228616E+00, 0.5574107740713430E-05, 0.7154716238932374E+00, 0.1141135068223202E+00, 0.6209438587853456E+00, 0.7851847140042024E+00, 0.4215540797089058E+00, 0.9132020640887749E+00, 0.1510454496157759E+00, 0.4172986352579149E+00, 0.5037450189692434E+00, 0.4485087403424131E+00, 0.5740668076879305E+00, 0.2978796610784261E+00, 0.6581099078338648E-01, 0.8930273171304047E+00, 0.8152477689300778E+00, 0.1069556485483132E+00, 0.6932157626522990E+00}, + n: 21, + zOut: []float64{0.2205969711876647E+01, 0.1949821527895322E+01, 0.1555841877124327E+01, 0.1396030697440207E+01, 0.1339074151471965E+01, 0.1304928492707023E+01, 0.1082549957806062E+01, 0.9163938874206132E+00, 0.8887122139609793E+00, 0.7285328536138327E+00, 0.6136134334950112E+00, 0.5962413214799335E+00, 0.4250735423840991E+00, 0.3604939377250871E+00, 0.2295486599338548E+00, 0.1443459206161604E+00, 0.1184188267216090E+00, 0.7075746168152415E-01, 0.2006576919306350E-01, 0.3756273174580983E-02, 0.4503973951446061E-03, 0.2214970142320351E-19, 0.1258326061053631E-10, 0.9003557400980630E-11, 0.1082549957806062E+01, 0.1308878013942703E-25, 0.3368372626791194E-10, 0.2572022209508410E-10, 0.9163938874206132E+00, 0.7614331624527915E-16, 0.1049500061330476E-08, 0.2928487158224854E-08, 0.8887122139609793E+00, 0.1203547791264655E-21, 0.7079518778653070E-07, 0.2057204985301009E-06, 0.7285328536138327E+00, 0.1084769825180869E-21, 0.6504687546036223E-07, 0.2011551828019932E-07, 0.6136134334950112E+00, 0.1678480469223895E-16, 0.1595062091511705E+02, 0.1595062091511705E+02, 0.1020000000000000E+03, 0.3156462585034014E+01, 0.2941176470588236E+01, 0.1336032003974816E-08, 0.4250735423840991E+00, 0.1033222323690773E-11, 0.1230907576002882E-05, 0.1377773980605759E-05, 0.3604939377250871E+00, 0.5435093612356237E-21, 0.5904438579725169E-05, 0.1247176535660427E-04, 0.2295486599338548E+00, 0.3794809073678436E-22, 0.8654598111714590E-03, 0.7607233838455693E-03, 0.1443459206161604E+00, 0.2335329392584174E-18, 0.9486551585203510E-04, 0.5848864829043123E-04, 0.1184188267216090E+00, 0.2421802979028506E-27, 0.4440929582264130E-04, 0.3669242548994226E-04, 0.7075746168152415E-01, 0.1891688450719986E-26, 0.5237855019006247E-04, 0.2468105637453731E-04, 0.2006576919306350E-01, 0.1180787648903814E-27, 0.8134126440113327E-03, 0.8865157422262554E-03, 0.3756273174580983E-02, 0.2581152881883151E-26, 0.5819544721666204E-02, 0.3152501351079271E-02, 0.4503973951446061E-03, 0.0000000000000000E+00, 0.5880303886253363E-04, 0.1585743718762697E-03}, + info: 0, + }, + { + z: []float64{0.5610544265871693E+00, 0.3865731523333528E+00, 0.8792353035941016E+00, 0.8523516652694250E+00, 0.1444314813898040E-01, 0.8826603847895033E+00, 0.6868176286586357E+00, 0.1885799699020001E+00, 0.8756021324147915E+00, 0.9000748303342890E+00, 0.6057362077051875E+00, 0.7116572505145777E+00, 0.4651180401287146E+00, 0.2732222796277717E-01, 0.4226433912686857E+00, 0.2137613193249559E+00, 0.8364980217841237E+00, 0.7760779616422476E+00, 0.4204777290352190E+00, 0.6224635225380051E+00, 0.2764474942580449E+00, 0.3783169947455127E+00, 0.5180995217194659E+00, 0.3065081068358929E+00, 0.7865831746887696E+00, 0.1478697978858728E+00, 0.9439830303880672E+00, 0.8253272390565236E-01, 0.3067445628749279E+00, 0.7129198739696287E+00, 0.1655397340526111E+00, 0.1744497852178990E+00, 0.8123176080018479E-01, 0.7468152661528306E+00, 0.8702942511684653E-01, 0.2665897748347560E+00, 0.9213749341388631E+00, 0.1523897006311256E+00, 0.9645030292913545E+00, 0.9612618327522493E-01, 0.4802656873918926E+00, 0.9400504426452867E+00, 0.4625574582408437E+00, 0.7387695442245192E+00, 0.7695082904503155E+00, 0.1394488941705607E+00, 0.4086909510206329E+00, 0.8420266381115991E+00, 0.9564685490270811E+00, 0.7091850518571272E+00, 0.5799173993611073E+00, 0.1780919033120022E+00, 0.4196947685163247E+00, 0.9892865772966106E+00, 0.5502405891255741E+00, 0.7805747931381838E+00, 0.8443114386354278E-01, 0.3818004737775779E+00, 0.5006744900666209E+00, 0.8330036981446504E+00, 0.6972526215524509E+00, 0.5997317354738497E+00, 0.6745658299087246E+00, 0.2369187863883299E+00, 0.4162907871251388E+00, 0.3987550165661536E+00, 0.3127240434721901E+00, 0.9587921004875174E+00, 0.9734600215022703E+00, 0.9507333301136496E+00, 0.3445022862066339E+00, 0.6240012410156072E+00, 0.3036264632031094E-01, 0.6999839547669153E+00, 0.4672138296892350E+00, 0.4669965382645248E+00, 0.7561275857160221E-01, 0.9250454776547237E+00, 0.8620177110728862E+00, 0.5266728805873626E+00, 0.6377535363121675E+00, 0.6098026285363055E+00, 0.8075088997828720E+00, 0.8486821693163010E+00}, + n: 21, + zOut: []float64{0.2468092632282687E+01, 0.2093427673862981E+01, 0.2055392019191517E+01, 0.1647867143267642E+01, 0.1615849876515927E+01, 0.1589328968238607E+01, 0.1271214388518367E+01, 0.1121382381594411E+01, 0.1069461264755295E+01, 0.1002295596318809E+01, 0.8815764834354939E+00, 0.8051252546404786E+00, 0.6374343329196452E+00, 0.5469723867709347E+00, 0.4015178604185544E+00, 0.3707602923265790E+00, 0.1795105850679969E+00, 0.1400595531050117E+00, 0.2548349514639473E-01, 0.1561366451013735E-02, 0.1155321273825210E-02, 0.3137752941767923E-22, 0.1448569525610494E-09, 0.1682297708320945E-10, 0.1271214388518367E+01, 0.3747089299799806E-29, 0.3127891707973917E-07, 0.1432924100618686E-07, 0.1121382381594411E+01, 0.1829309924661015E-19, 0.1414348814679943E-06, 0.1338467241717145E-06, 0.1069461264755295E+01, 0.2814655709828570E-26, 0.1421706541245010E-06, 0.1494636997707923E-06, 0.1002295596318809E+01, 0.2555408239179452E-16, 0.1745096068338993E-06, 0.1639215185470380E-06, 0.8815764834354939E+00, 0.5195421261043265E-21, 0.1992546887610216E+02, 0.1992546887610217E+02, 0.1040000000000000E+03, 0.3263038548752835E+01, 0.3846153846153846E+01, 0.5490557769901970E-06, 0.6374343329196452E+00, 0.1696050946225175E-28, 0.4391959465127471E-06, 0.4441570425561870E-06, 0.5469723867709347E+00, 0.4122920742224575E-16, 0.4792107785920969E-06, 0.5244422797027597E-06, 0.4015178604185544E+00, 0.4437342591868191E-30, 0.1189624719598388E-05, 0.1545254324980458E-05, 0.3707602923265790E+00, 0.0000000000000000E+00, 0.3830671301160838E-05, 0.5436396467135237E-05, 0.1795105850679969E+00, 0.1558228073167050E-14, 0.5423210427919237E-04, 0.1228583690085413E-03, 0.1400595531050117E+00, 0.8832743148296122E-19, 0.1395228897382397E-04, 0.1537585917376726E-04, 0.2548349514639473E-01, 0.0000000000000000E+00, 0.8277350694369951E-03, 0.9528953717632958E-03, 0.1561366451013735E-02, 0.2465190328815662E-31, 0.7095009159403311E-03, 0.6952609237045969E-03, 0.1155321273825210E-02, 0.1309509102666880E-27, 0.9046555260897671E-03, 0.1226313636978587E-02}, + info: 0, + }, + { + z: []float64{0.1242522906682814E+00, 0.6390609620209767E+00, 0.4481822861180138E+00, 0.4850355616354706E+00, 0.4018997557884576E+00, 0.7075817751574985E+00, 0.3076496509717662E+00, 0.9845619472128853E+00, 0.4421050939804582E+00, 0.3472138710835164E+00, 0.7694977672753175E+00, 0.4786944038481857E+00, 0.6974278852457209E+00, 0.5004517708240744E+00, 0.7658513494839985E+00, 0.7508522623862479E-01, 0.8645614962374704E-02, 0.2513671118506070E+00, 0.9355687048630774E+00, 0.2836435232395548E+00, 0.8653687008315966E+00, 0.3043727382738487E+00, 0.8973655399535756E+00, 0.7135517870607274E+00, 0.4956863425678929E+00, 0.8362506849216409E+00, 0.9829450079482006E+00, 0.9413718361369072E+00, 0.2542921002853715E-01, 0.5951158954104814E+00, 0.9317747763384295E+00, 0.9085271053958202E+00, 0.9993466426511500E+00, 0.2497009223772528E-01, 0.8726460080387569E+00, 0.3868463012727243E+00, 0.5820757557404177E-01, 0.7974577837432384E-01, 0.8242609714155934E+00, 0.1887913799920241E+00, 0.3268225406700475E+00, 0.2264596835393817E+00, 0.4020160264981738E+00, 0.8597685353848280E+00, 0.5429598215579996E+00, 0.4134507486351844E+00, 0.8781720494573462E+00, 0.3655827200857601E+00, 0.2876763179222336E+00, 0.9193112804533413E+00, 0.3958413207165046E-01, 0.7980401670837647E+00, 0.5101422689515223E-01, 0.2194050847732673E+00, 0.6115669547384739E-02, 0.9036470382476453E+00, 0.6696681747677364E+00, 0.1689100553906829E+00, 0.9284887836539969E+00, 0.8748192507086142E+00, 0.7181738874264668E+00, 0.8990747837549429E-01, 0.7166811698029575E+00, 0.8712804839027968E+00, 0.2571898936326318E+00, 0.2264160460654618E+00, 0.6364724288557849E+00, 0.9550337894922362E+00, 0.8995892333665090E+00, 0.3728949594240628E+00, 0.6496276036419958E+00, 0.7218580021816370E+00, 0.2620053580399828E+00, 0.8492826434932900E+00, 0.1090756692624820E+00, 0.1230806328807070E+00, 0.5326342483791896E+00, 0.3425391815117244E+00, 0.4714474424671373E+00, 0.9044440560476328E+00, 0.2298320061743346E+00, 0.7771450381369926E+00, 0.4623588499686800E+00, 0.8996441805847293E+00}, + n: 21, + zOut: []float64{0.2749036998648791E+01, 0.2657147938200912E+01, 0.2156780738808330E+01, 0.2057290308234013E+01, 0.1910481192038085E+01, 0.1550197528741744E+01, 0.1531663815430223E+01, 0.1307411568456853E+01, 0.1180055477995477E+01, 0.1145160315453326E+01, 0.8462599780670359E+00, 0.8196023258344234E+00, 0.7505058481318937E+00, 0.3802378569170251E+00, 0.3493658644293456E+00, 0.2733852715996189E+00, 0.1920071438579977E+00, 0.3602127141457542E-01, 0.1503353393017178E-01, 0.5047074669949666E-02, 0.4814167031169938E-03, 0.1615587133892632E-26, 0.3701495167228324E-14, 0.8166164251788096E-14, 0.1531663815430223E+01, 0.5400326177233737E-21, 0.8345943934662111E-13, 0.3845954584916692E-13, 0.1307411568456853E+01, 0.2270604060615577E-17, 0.1098158814550649E-11, 0.6011774632275279E-12, 0.1180055477995477E+01, 0.6617444900424221E-23, 0.1039362721731823E-10, 0.1780733867152956E-10, 0.1145160315453326E+01, 0.3193234771665464E-17, 0.8582967920523009E-10, 0.1451582492090454E-09, 0.8462599780670359E+00, 0.4268426102972081E-16, 0.2191317346756291E+02, 0.2191317346756291E+02, 0.1100000000000000E+03, 0.3303854875283447E+01, 0.6363636363636363E+01, 0.9730504757902699E-07, 0.7505058481318937E+00, 0.1718125187449148E-14, 0.1758342086676891E-05, 0.2642640058729254E-05, 0.3802378569170251E+00, 0.9047523974206004E-14, 0.3754566725544834E-04, 0.5673943129185001E-04, 0.3493658644293456E+00, 0.2726303288443817E-26, 0.2006689219611138E-03, 0.1777791597062721E-03, 0.2733852715996189E+00, 0.1852245405458936E-26, 0.4273484804153724E-06, 0.2289494629295668E-05, 0.1920071438579977E+00, 0.7673537210642012E-17, 0.3631464818839244E-02, 0.3052322482564877E-02, 0.3602127141457542E-01, 0.1402889840288648E-17, 0.2065820498676818E-02, 0.7907462477517949E-03, 0.1503353393017178E-01, 0.3588277137446075E-19, 0.9842420036565967E-03, 0.4295497278130008E-03, 0.5047074669949666E-02, 0.1100487290795119E-18, 0.2169791314757801E-02, 0.2746294001732303E-02, 0.4814167031169938E-03, 0.9926167349879280E-23, 0.2524480967032520E-02, 0.1685323473608901E-02}, + info: 0, + }, + { + z: []float64{0.4452569544189223E+00, 0.3712416527218666E+00, 0.4540009468556715E+00, 0.9149505778015055E-01, 0.9825460881415958E+00, 0.8144387623295611E+00, 0.4257438310114644E+00, 0.4055209729019219E+00, 0.1358301754544711E-01, 0.6660365069195171E+00, 0.4791028777450690E-01, 0.3657122138300755E+00, 0.9244230955293443E+00, 0.2570776992045346E+00, 0.5718524872194095E+00, 0.6959027703199671E+00, 0.8022093165313721E+00, 0.4495167304148069E+00, 0.4533829141769831E+00, 0.4399857636092745E+00, 0.8343772053001745E+00, 0.5841091089133705E+00, 0.9225724116024000E+00, 0.3646730358635919E+00, 0.4342402996301750E+00, 0.1979669913465428E+00, 0.2710080252534286E+00, 0.4064878156937679E+00, 0.1329017000110605E+00, 0.3577863781516848E+00, 0.7737638611946227E+00, 0.3628629851888825E+00, 0.6191378950237536E+00, 0.9181610808896479E-01, 0.3164967052049129E+00, 0.1800354212961807E+00, 0.5261304159866632E+00, 0.2095779664090124E+00, 0.4734470785970568E+00, 0.8233700542774806E+00, 0.1405149000531442E+00, 0.5739228235076023E+00, 0.4484023224779539E+00, 0.7953415183519565E+00, 0.5683020712105596E+00, 0.3828815589637512E+00, 0.9478512018818865E+00, 0.9398576744287683E+00, 0.6799918835962694E+00, 0.9795978835389229E+00, 0.9415167003494995E+00, 0.9804631144197878E+00, 0.4529282233852833E+00, 0.6987441800620822E+00, 0.1071819561656476E+00, 0.6287695276127018E+00, 0.2573913359217608E+00, 0.5283299892256954E-01, 0.1312057002484920E+00, 0.2566822109082798E+00, 0.5022596747022927E+00, 0.3755634037822867E+00, 0.7687685406410046E+00, 0.9286257388850563E+00, 0.2460950353669618E+00, 0.4615682752011302E+00, 0.2668978314403934E+00, 0.9526334220011422E+00, 0.7113266960956600E+00, 0.8033610237680390E+00, 0.2049912091857929E+00, 0.9104136201043411E+00, 0.9905140155095393E+00, 0.5284892163797259E+00, 0.4617116226676921E-01, 0.7638541825257228E+00, 0.8058860223281950E-01, 0.6562405799504624E+00, 0.4217948031372573E+00, 0.8444441663937204E+00, 0.4135300708069887E+00, 0.3992676961789670E+00, 0.9443059736340937E+00, 0.4697907769676380E+00}, + n: 21, + zOut: []float64{0.2339652518244840E+01, 0.2127240999798084E+01, 0.2122097736373912E+01, 0.1640409192349226E+01, 0.1522936721900112E+01, 0.1513900850773956E+01, 0.1190428480890818E+01, 0.1098839257111754E+01, 0.9060499827420537E+00, 0.8483833633939547E+00, 0.7423625631343986E+00, 0.6441873762582893E+00, 0.5561064852023264E+00, 0.5332801819376103E+00, 0.3323799891685881E+00, 0.2356658160961767E+00, 0.1910001776595044E+00, 0.1052937995306845E+00, 0.3493206724380617E-01, 0.1582963148293342E-01, 0.1362410302334481E-03, 0.2902907641693595E-19, 0.1235088787739235E-18, 0.5938156039510254E-18, 0.1190428480890818E+01, 0.2366582715663035E-29, 0.1736669751992271E-12, 0.4479686287025860E-12, 0.1098839257111754E+01, 0.4930380657631324E-31, 0.6845104399398104E-11, 0.1631652613834293E-10, 0.9060499827420537E+00, 0.3623410171350593E-13, 0.4397239464622790E-08, 0.8783797026819435E-08, 0.8483833633939547E+00, 0.1680831004707752E-20, 0.6292544501750849E-07, 0.1207646260809090E-06, 0.7423625631343986E+00, 0.1044536639065691E-17, 0.1870111343232326E+02, 0.1870111343232326E+02, 0.1030000000000000E+03, 0.3002267573696145E+01, 0.3883495145631068E+01, 0.8796985420666049E-06, 0.5561064852023264E+00, 0.6232001151245993E-28, 0.4765675419124029E-06, 0.5281771988202168E-06, 0.5332801819376103E+00, 0.5995342879679690E-28, 0.3211676631039122E-06, 0.3513325837054497E-06, 0.3323799891685881E+00, 0.2177256098409993E-25, 0.1826919937583927E-06, 0.1747056528730059E-06, 0.2356658160961767E+00, 0.1311326116357865E-17, 0.1784537561302489E-06, 0.2175474607275274E-06, 0.1910001776595044E+00, 0.3862262991962074E-24, 0.9127544222909640E-06, 0.4962248419758332E-06, 0.1052937995306845E+00, 0.1072850831100576E-26, 0.2872845137271569E-03, 0.1413151427897814E-03, 0.3493206724380617E-01, 0.8028654523313936E-17, 0.5779626756191757E-04, 0.4784930511330926E-04, 0.1582963148293342E-01, 0.9359045779542084E-26, 0.9339546012110267E-04, 0.6206712854083305E-04, 0.1362410302334481E-03, 0.4535950205020818E-29, 0.1799327870469576E-03, 0.1621654177500190E-02}, + info: 0, + }, + { + z: []float64{0.6327743759434090E-01, 0.8874473183212240E+00, 0.1587228549487630E+00, 0.1869853022948459E+00, 0.1852952724381735E+00, 0.2190328352455733E+00, 0.7936705141328082E+00, 0.1573124860628259E+00, 0.2446308768539528E+00, 0.2441044501798444E+00, 0.4435884001235265E+00, 0.1783624365771731E+00, 0.6874700271616803E+00, 0.4796486989431838E+00, 0.2471425348644392E+00, 0.4391077480264999E+00, 0.9973269002312380E+00, 0.4770343529783838E+00, 0.3451566405930041E+00, 0.5011834710046675E+00, 0.8072188861666797E+00, 0.5748577907200507E+00, 0.2986003422862493E+00, 0.4760318526964945E+00, 0.5838957192070238E-01, 0.1760621214885278E+00, 0.7926085978219721E+00, 0.3379849703418611E+00, 0.6012719579585296E+00, 0.1130783704430351E+00, 0.5590675745254436E-01, 0.8616930340961984E+00, 0.9917564091315376E+00, 0.4219575368674273E+00, 0.1044382974319413E+00, 0.1886528536659160E-01, 0.9337085742573710E+00, 0.6447952074628677E+00, 0.7158824182577913E+00, 0.3883216757352448E+00, 0.2116568255149501E+00, 0.9819105316462939E+00, 0.8471687522868032E-01, 0.2785996362910685E+00, 0.8775405646426044E+00, 0.5671584270354416E+00, 0.4912868754910720E+00, 0.5767395813214109E+00, 0.7327323379759062E+00, 0.8184048812627022E+00, 0.3325270745990432E+00, 0.3026500963479654E+00, 0.7228591188664935E+00, 0.1094677581261434E+00, 0.5280482398171430E+00, 0.9974727380694979E+00, 0.5087630734843742E+00, 0.6953603638889684E+00, 0.9103967979863506E+00, 0.2584730811693510E+00, 0.5498750728524477E+00, 0.9758543899455846E+00, 0.8309066632970131E+00, 0.4311646442586020E+00, 0.4732818688792167E+00, 0.4096051739313099E+00, 0.7479697576436509E+00, 0.9369473766445329E+00, 0.7380538090811954E+00, 0.1199951604231148E+00, 0.5672128274092054E+00, 0.7150763241893471E+00, 0.6134240647991112E+00, 0.7095501841622953E-01, 0.1510080432732774E-01, 0.2912426074708729E+00, 0.1611746025295486E+00, 0.3946903662654964E+00, 0.7408818971566200E-01, 0.3978128748254128E+00, 0.3580504147215868E+00, 0.2603799996304434E-01, 0.8990784999913340E+00, 0.1985602490013758E+00}, + n: 21, + zOut: []float64{0.2139906798692060E+01, 0.2104052265745164E+01, 0.2080474521860817E+01, 0.1784368581097839E+01, 0.1501145759273247E+01, 0.1395549430074518E+01, 0.1236063891814824E+01, 0.1123736402991315E+01, 0.8211474325690415E+00, 0.7411912844479571E+00, 0.7336682913123216E+00, 0.5274366057326734E+00, 0.3715621485686555E+00, 0.3171624722931449E+00, 0.2809062056956198E+00, 0.1668884413843382E+00, 0.9744092162322979E-01, 0.7613224124753509E-01, 0.1665106039654164E-01, 0.4700366860927376E-02, 0.1401918312945850E-02, 0.1084683744678891E-29, 0.4021673570416241E-08, 0.3931910860092540E-08, 0.1236063891814824E+01, 0.1439956010332256E-19, 0.3626387646080745E-08, 0.3543555828237728E-08, 0.1123736402991315E+01, 0.3006506681978320E-24, 0.3371387381785702E-08, 0.3448854867663729E-08, 0.8211474325690415E+00, 0.6197291271416269E-26, 0.2831422041774839E-08, 0.2886341750444270E-08, 0.7411912844479571E+00, 0.0000000000000000E+00, 0.2880306038760265E-08, 0.2936321908308739E-08, 0.7336682913123216E+00, 0.2406371799476454E-20, 0.1752158704199472E+02, 0.1752158704199472E+02, 0.1050000000000000E+03, 0.3111111111111111E+01, 0.7619047619047619E+01, 0.3652487989473621E-08, 0.3715621485686555E+00, 0.1451701975030564E-21, 0.4296538801302010E-08, 0.3992227758256396E-08, 0.3171624722931449E+00, 0.6162975822039155E-31, 0.5151357395533313E-08, 0.5974032086218965E-08, 0.2809062056956198E+00, 0.2039658356197591E-16, 0.1134165265363298E-07, 0.1513934018844884E-07, 0.1668884413843382E+00, 0.2400943524542200E-24, 0.1781584505522029E-06, 0.1218300442987205E-06, 0.9744092162322979E-01, 0.6162975822039155E-31, 0.9557876398738343E-06, 0.5872690889712619E-06, 0.7613224124753509E-01, 0.5074727415413836E-17, 0.2309052370169074E-04, 0.5924498773169641E-04, 0.1665106039654164E-01, 0.1400228106767296E-28, 0.5116509326795711E-04, 0.5154480234673206E-04, 0.4700366860927376E-02, 0.1956855682120442E-20, 0.1061141342429108E-03, 0.9755516139369119E-04, 0.1401918312945850E-02, 0.0000000000000000E+00, 0.1229085807195224E-02, 0.8009097549502667E-02}, + info: 0, + }, + { + z: []float64{0.7225493913848618E+00, 0.3268825038779278E+00, 0.2580957584922012E+00, 0.4222896610254372E+00, 0.8243187922209068E+00, 0.3973391932422579E+00, 0.3700698452657641E+00, 0.2073422474585492E+00, 0.3071746797249822E+00, 0.2370168833330754E+00, 0.7779583030993944E+00, 0.4350651843345934E+00, 0.7867543754352369E+00, 0.3439673345654075E+00, 0.3736479358698906E+00, 0.8450641599616520E+00, 0.3880138308747846E+00, 0.2479782080134303E+00, 0.3220864609073060E+00, 0.8460149388339712E+00, 0.6082870752479030E+00, 0.3396261004129498E+00, 0.1231305479976765E+00, 0.6514493424347317E+00, 0.4987273421671501E-01, 0.2199653339283912E+00, 0.5626339029868159E+00, 0.6755574738917364E+00, 0.7016850168758351E+00, 0.7957347983005405E+00, 0.3394687111682781E-01, 0.1490794513934588E+00, 0.9837873705641814E+00, 0.5038299137267350E+00, 0.8394265886439850E+00, 0.1438624872728633E-01, 0.4444190467253504E+00, 0.1489248400425094E+00, 0.6410535698206483E+00, 0.2739267916732867E+00, 0.6522097474411971E+00, 0.9086492388715542E+00, 0.1949071722314141E+00, 0.7176724675018002E+00, 0.9247176136838016E+00, 0.4929580602677628E+00, 0.3824418236647242E+00, 0.2425574232540663E+00, 0.7085287909144397E+00, 0.2574302555167504E+00, 0.6093160252921369E+00, 0.2417561032032995E+00, 0.4795262420397247E+00, 0.4658200993830509E+00, 0.9033699918994937E+00, 0.1295021719769064E+00, 0.6219991535812029E+00, 0.7040800557612208E+00, 0.8644629036591867E-01, 0.5129394685202899E+00, 0.7988983132437487E+00, 0.8322467913624354E+00, 0.9905487172695071E-01, 0.7093832076693246E+00, 0.1992462440538834E-01, 0.6378263512182120E+00, 0.5823949252324323E-02, 0.7826279628890456E+00, 0.5919828344466795E+00, 0.3815528510244244E+00, 0.6537355893096064E-01, 0.6459825623191251E-01, 0.4466210788758083E+00, 0.6620124961190184E+00, 0.6318809895815939E+00, 0.8145861476435108E+00, 0.5938169865214039E+00, 0.8092284578140500E+00, 0.5378701643349270E+00, 0.1648044346935199E+00, 0.9874291179811017E+00, 0.3210667070512012E+00, 0.6809988920516613E+00, 0.6410080963943865E+00}, + n: 21, + zOut: []float64{0.2108032684782400E+01, 0.1971253922847928E+01, 0.1952878543820764E+01, 0.1839982524288513E+01, 0.1730503177731785E+01, 0.1509287569836986E+01, 0.1316544049683026E+01, 0.1117715356834192E+01, 0.9058841126016787E+00, 0.8452427684353671E+00, 0.7582219581243467E+00, 0.6392786878439012E+00, 0.5749674919024932E+00, 0.5111167278611346E+00, 0.3859485208834002E+00, 0.2295319067023061E+00, 0.2262113890497363E+00, 0.1122658486667464E+00, 0.7234153262002044E-01, 0.4527048542558528E-01, 0.8319414807792288E-04, 0.2547288901631409E-13, 0.9052716547280089E-04, 0.7818093042872877E-04, 0.1316544049683026E+01, 0.0000000000000000E+00, 0.2537869832861900E-04, 0.2058109204222074E-04, 0.1117715356834192E+01, 0.0000000000000000E+00, 0.1154377886785102E-04, 0.1215574110748570E-04, 0.9058841126016787E+00, 0.8843729980912407E-17, 0.1391102994778336E-08, 0.5248885105740662E-08, 0.8452427684353671E+00, 0.2445468806185137E-28, 0.2192473584471834E-06, 0.3792344586441173E-06, 0.7582219581243467E+00, 0.6480317173221865E-17, 0.1885256245409039E+02, 0.1885256245409039E+02, 0.1090000000000000E+03, 0.3303854875283447E+01, 0.3669724770642202E+01, 0.3715603111278862E-08, 0.5749674919024932E+00, 0.4928548884551519E-18, 0.2515491583997865E-07, 0.9138389520203617E-08, 0.5111167278611346E+00, 0.6587911462745685E-21, 0.7857712130631377E-05, 0.2298529163657988E-05, 0.3859485208834002E+00, 0.6162975822039155E-32, 0.1022329296046741E-03, 0.8680151473672892E-04, 0.2295319067023061E+00, 0.0000000000000000E+00, 0.4616464530663241E-04, 0.3877924919889212E-04, 0.2262113890497363E+00, 0.5522026336547083E-29, 0.2365660345682357E-03, 0.1990352708186489E-03, 0.1122658486667464E+00, 0.9015102222917331E-20, 0.6825572508936817E-03, 0.6443371781720532E-03, 0.7234153262002044E-01, 0.1168271446196110E-24, 0.1518594231951364E-05, 0.3554999772664582E-05, 0.4527048542558528E-01, 0.1023373475125114E-24, 0.5037539097182833E-02, 0.4761613742874584E-02, 0.8319414807792288E-04, 0.1479114197289397E-30, 0.9105689905446296E-02, 0.4825995872157137E-02}, + info: 0, + }, + { + z: []float64{0.3256696334281521E+00, 0.7530856859911462E+00, 0.8853989127988440E+00, 0.4058112879440673E+00, 0.4296659748141172E+00, 0.5414662225246791E-01, 0.7727106089758434E+00, 0.8219533891865206E+00, 0.8804898818241804E+00, 0.2701661776792790E+00, 0.3062100113053869E+00, 0.7616550925245322E+00, 0.7441861437457686E+00, 0.1208643477044503E+00, 0.1894387751691341E+00, 0.5502297763300060E+00, 0.7033314588214317E+00, 0.9049640752657374E+00, 0.7642474001418834E+00, 0.6461873559439021E+00, 0.7323555348666727E+00, 0.6137344390498661E+00, 0.4469041036073067E+00, 0.6120974783290001E+00, 0.3695185251601272E+00, 0.9332999793731735E+00, 0.3981597952563400E+00, 0.5926926060619504E+00, 0.2218776156238759E+00, 0.5556127447847847E-01, 0.2642041684868913E+00, 0.3100431241269808E-01, 0.7617158805289858E+00, 0.5576464290832684E+00, 0.1499291988028689E+00, 0.6071627267784354E+00, 0.2903444085740193E+00, 0.8982141027722228E+00, 0.3437740722392461E+00, 0.5257340992985249E-02, 0.9772197173932363E+00, 0.2743313505008338E-01, 0.5939995532981283E+00, 0.8125099455585232E+00, 0.8394050677385213E+00, 0.2410326841076476E+00, 0.6066214991817382E+00, 0.1828025638429278E+00, 0.5406675263078469E+00, 0.1108622672142920E+00, 0.2412280709874803E+00, 0.5713495470758625E+00, 0.6315445401927943E+00, 0.2035563756883153E+00, 0.8696814083183412E+00, 0.2313134367709406E+00, 0.4474447231170641E+00, 0.6238312383525342E+00, 0.4961806049996582E+00, 0.8121574484576765E+00, 0.8702938949430352E+00, 0.4187164629520156E+00, 0.9204090241956668E+00, 0.8587176140225750E-02, 0.5171057705188283E+00, 0.5195595031109387E+00, 0.1704600468811621E+00, 0.3205951022793651E+00, 0.5643494948239225E-01, 0.9895063272544601E+00, 0.5554681247022339E+00, 0.6098243547887802E+00, 0.4730289261335907E+00, 0.1850396134174421E+00, 0.9997475966289492E+00, 0.6812817712215841E+00, 0.8515433432907883E+00, 0.7377047940023331E+00, 0.2280516830782600E+00, 0.7204549837953970E+00, 0.6096260713045146E+00, 0.9381128478076188E+00, 0.8446173293023428E+00, 0.6255387686605924E+00}, + n: 21, + zOut: []float64{0.2655567567233002E+01, 0.2307219644143945E+01, 0.2068899090176533E+01, 0.2040332602619700E+01, 0.1742115921396612E+01, 0.1681856112031183E+01, 0.1680515965675234E+01, 0.1379580829731510E+01, 0.1074312270120212E+01, 0.9816962393879983E+00, 0.7217300335876665E+00, 0.6931029681515243E+00, 0.5680300928567689E+00, 0.5098239945058581E+00, 0.4280073603039590E+00, 0.2868581986899945E+00, 0.1650069923584772E+00, 0.9685136354131559E-01, 0.5953175886938158E-01, 0.1010639579838301E-01, 0.1940920539235378E-02, 0.0000000000000000E+00, 0.6683246174917478E-10, 0.4267275295503314E-10, 0.1680515965675234E+01, 0.3510431028233503E-28, 0.1660414363340253E-09, 0.1048896312812690E-09, 0.1379580829731510E+01, 0.1462018530271286E-15, 0.3421106985799154E-06, 0.1788748688597153E-06, 0.1074312270120212E+01, 0.6708481546523056E-14, 0.2133146148219686E-04, 0.4629406838917969E-04, 0.9816962393879983E+00, 0.1747667198202037E-19, 0.5113942524303023E-03, 0.6287577911928029E-03, 0.7217300335876665E+00, 0.3213860550383917E-17, 0.2115308632171850E+02, 0.2115308632171849E+02, 0.1090000000000000E+03, 0.3217687074829932E+01, 0.4587155963302752E+01, 0.4202140396420195E-04, 0.5680300928567689E+00, 0.4489765112701642E-21, 0.3523329095202763E-09, 0.1167512512099963E-08, 0.5098239945058581E+00, 0.1652551767516096E-21, 0.2872281528375301E-06, 0.1040291448945555E-06, 0.4280073603039590E+00, 0.3262461795428160E-16, 0.6249760558326680E-04, 0.5475920486023645E-04, 0.2868581986899945E+00, 0.1568256893218114E-20, 0.1414968677825121E-03, 0.1814031293335571E-03, 0.1650069923584772E+00, 0.8677469957431130E-28, 0.6720068122740940E-03, 0.4975589868187537E-03, 0.9685136354131559E-01, 0.5127595883936577E-29, 0.9260272777115331E-03, 0.1730290225790419E-02, 0.5953175886938158E-01, 0.7227833914448031E-23, 0.5968169418548035E-04, 0.1670361992731526E-04, 0.1010639579838301E-01, 0.1295106991551472E-19, 0.1213518994781533E-03, 0.2534883535393275E-03, 0.1940920539235378E-02, 0.0000000000000000E+00, 0.1005634135102979E-02, 0.2318000467665894E-02}, + info: 0, + }, + { + z: []float64{0.1944566011999833E+00, 0.2181910996636003E+00, 0.3150099357031281E+00, 0.2091722274105127E+00, 0.6593858021341683E+00, 0.9426815336068497E+00, 0.5288011644568881E+00, 0.7784091503839152E+00, 0.1751638954124558E+00, 0.6164772800195180E+00, 0.6225196859922683E+00, 0.2786175486675760E+00, 0.1945914328217568E+00, 0.5779085626077999E+00, 0.5568218939451671E+00, 0.5170566254269496E+00, 0.5742861029155353E+00, 0.6923056150383281E+00, 0.5876692361605969E+00, 0.4295639666640205E+00, 0.8612105519992207E+00, 0.9963836880013683E+00, 0.2692934182903581E+00, 0.6181020857251435E+00, 0.1251902537663725E+00, 0.2838625146280274E+00, 0.2999174442521634E+00, 0.7258439193048929E+00, 0.2048904835805728E+00, 0.1174987481558037E+00, 0.6887427109309550E+00, 0.7409107864964065E+00, 0.5306892441542433E+00, 0.6214581212205206E-01, 0.1234501953117273E-01, 0.2038789370511589E+00, 0.6180963044354376E+00, 0.2820746320472540E+00, 0.4643004781082601E+00, 0.2642696366861867E+00, 0.4102198269957935E-01, 0.1495900075045802E+00, 0.2060405615637534E+00, 0.3399183002928583E+00, 0.7918555051917199E+00, 0.9699614514519834E+00, 0.2922678000248715E+00, 0.1376674512222148E+00, 0.2496993200590716E+00, 0.3432539555227123E+00, 0.5835005548357151E+00, 0.4094205671447549E+00, 0.4876670000237163E+00, 0.7973523995663028E+00, 0.8851386592921134E+00, 0.1523554028450115E+00, 0.7049520832902729E+00, 0.4689643982524618E+00, 0.4347705823917429E+00, 0.8152140283905303E+00, 0.9259201525760803E+00, 0.3175789772106010E+00, 0.3950010049586650E+00, 0.7107346574834400E+00, 0.8109922991383097E+00, 0.6889072760433030E+00, 0.7861311781839575E-02, 0.7751963519893628E+00, 0.7382950156197396E+00, 0.9729693586970557E+00, 0.7283826758396350E+00, 0.1269651196972527E+00, 0.3530947260257147E+00, 0.2061448083515627E-01, 0.5931058475369740E+00, 0.9689379021952851E+00, 0.3254887771415839E+00, 0.2808523639662175E-01, 0.6211468186653845E+00, 0.6037463613076512E+00, 0.8746435454108382E+00, 0.5300695323546331E+00, 0.5276801989236730E+00, 0.2128951663669798E-01}, + n: 21, + zOut: []float64{0.2424279264689105E+01, 0.2270324150901105E+01, 0.1935128898096250E+01, 0.1814500336114905E+01, 0.1538233405195664E+01, 0.1297421320254112E+01, 0.1267282488999314E+01, 0.1249158514677014E+01, 0.9155076211264116E+00, 0.8242950831432680E+00, 0.5949232544739386E+00, 0.5630079212779312E+00, 0.4530053256303904E+00, 0.3458193312768856E+00, 0.2146623096050983E+00, 0.1686454472303586E+00, 0.1155214217797334E+00, 0.5180948935108346E-01, 0.2789744048901975E-01, 0.8268186305777192E-02, 0.6680158028153346E-04, 0.0000000000000000E+00, 0.3986945646893946E-08, 0.7023072825762287E-08, 0.1267282488999314E+01, 0.0000000000000000E+00, 0.2355158572444734E-07, 0.1877711213087836E-07, 0.1249158514677014E+01, 0.3384506411488746E-20, 0.2648360770785381E-11, 0.1741394977127960E-10, 0.9155076211264116E+00, 0.3299177303725225E-12, 0.2487861145673591E-05, 0.4028407591944186E-05, 0.8242950831432680E+00, 0.2441420600100056E-16, 0.1869515956083083E-05, 0.1842279235203962E-05, 0.5949232544739386E+00, 0.2024938139529812E-20, 0.1807975801219765E+02, 0.1807975801219765E+02, 0.9300000000000000E+02, 0.2836734693877551E+01, 0.1075268817204301E+01, 0.9521662195121400E-05, 0.4530053256303904E+00, 0.1259501632163109E-23, 0.1468124594065504E-05, 0.4670591953230941E-05, 0.3458193312768856E+00, 0.7975064420889996E-22, 0.1308295990671250E-06, 0.6690001990389955E-07, 0.2146623096050983E+00, 0.1927976052360153E-26, 0.3812574759844485E-05, 0.3580340604691736E-05, 0.1686454472303586E+00, 0.3739200690747596E-27, 0.6844384387279355E-05, 0.5557405125771409E-05, 0.1155214217797334E+00, 0.7506098603421864E-21, 0.2139339757899294E-04, 0.3026575107963825E-04, 0.5180948935108346E-01, 0.3886068668379982E-20, 0.1983680974127293E-03, 0.1336830557694390E-03, 0.2789744048901975E-01, 0.1991084924777834E-26, 0.4443273484877918E-03, 0.6821022035819646E-03, 0.8268186305777192E-02, 0.1921747358113822E-20, 0.1778955160858100E-05, 0.3048292256883238E-06, 0.6680158028153346E-04, 0.7915528772828604E-21, 0.4499131616906370E-02, 0.1547765737453591E-02}, + info: 0, + }, + { + z: []float64{0.3849545441014558E+00, 0.9201984078647510E+00, 0.4611893507512446E+00, 0.9426704990067624E+00, 0.4513996483425642E+00, 0.3546824995764211E+00, 0.2673932938327498E+00, 0.2250322436282782E+00, 0.3003875396759296E+00, 0.8637078150569484E+00, 0.2463125523040188E-01, 0.6381498516846796E+00, 0.9054059378226459E+00, 0.9211368359293561E+00, 0.6899055937753183E+00, 0.6469675067081565E+00, 0.2524386712411693E+00, 0.4816130873217878E+00, 0.8437265349008123E+00, 0.8843672501609817E+00, 0.3917808232071412E+00, 0.4109107468556734E+00, 0.6294664210780233E+00, 0.5231064834871043E+00, 0.6006449315760222E+00, 0.2321330919598237E+00, 0.9857216391074231E-01, 0.5246894901632879E+00, 0.2429723268334654E+00, 0.3385437000243748E+00, 0.1784805178646218E+00, 0.8008314854810928E+00, 0.3388059467143087E+00, 0.4957241256656372E+00, 0.6108069077503485E+00, 0.8350989375447051E+00, 0.1087391555565628E+00, 0.5847974581188020E+00, 0.8316850716702742E+00, 0.8921011586703487E+00, 0.1947070853010260E+00, 0.1394928972102342E+00, 0.7929088249487071E+00, 0.4078510186300481E+00, 0.6849316610029904E+00, 0.1436003498260631E+00, 0.5673845335495399E+00, 0.7998164012861997E-01, 0.6667892725157643E+00, 0.7612117828169483E+00, 0.8195812739875934E+00, 0.1507277483884870E+00, 0.6683936863561600E+00, 0.1889659251016290E+00, 0.7979363461805246E+00, 0.9481151487908223E+00, 0.3017570036067704E+00, 0.2677628114499495E+00, 0.4479716416042271E+00, 0.3773062273227097E+00, 0.1756267436681674E+00, 0.6251009447636316E+00, 0.3010990216120933E+00, 0.6044916624270988E+00, 0.3012752666004853E+00, 0.7113839134297870E+00, 0.7355680503868338E+00, 0.1830572310895536E+00, 0.2065116792960049E+00, 0.2432895898830973E+00, 0.9615089470298006E+00, 0.3137165160357294E+00, 0.5335631824040450E+00, 0.8324142824771229E+00, 0.9749825715503555E+00, 0.3108065469391890E+00, 0.2584483510692804E+00, 0.5679665509067858E+00, 0.9084113884935793E+00, 0.3061643504016712E+00, 0.1856860631474661E+00, 0.4086356189591027E+00, 0.2761517708925276E+00, 0.9203155374121844E+00}, + n: 21, + zOut: []float64{0.2651616639993538E+01, 0.2278042999629812E+01, 0.2198077975076974E+01, 0.2185608493228643E+01, 0.1866238785250178E+01, 0.1694317687161655E+01, 0.1314780820581521E+01, 0.1267230115137409E+01, 0.1165102366599241E+01, 0.1094106513205574E+01, 0.9375639320451692E+00, 0.7228525903025090E+00, 0.5063995930233953E+00, 0.4433597755655621E+00, 0.3782868675227946E+00, 0.2710178897462153E+00, 0.1447594933682902E+00, 0.1060101050946834E+00, 0.8449698031014202E-01, 0.1468593250969371E-01, 0.8406928034951682E-06, 0.3591986573571771E-20, 0.3864386735331416E-10, 0.3252595492372177E-10, 0.1314780820581521E+01, 0.1447952803137974E-21, 0.5374081097788385E-10, 0.4849713226733927E-10, 0.1267230115137409E+01, 0.2958228394578794E-29, 0.8017357434413146E-10, 0.7063808972759981E-10, 0.1165102366599241E+01, 0.1139115147139141E-26, 0.1961041727821929E-09, 0.1374026522849091E-09, 0.1094106513205574E+01, 0.3915388343685865E-19, 0.1756082891845291E-08, 0.3338672481507716E-08, 0.9375639320451692E+00, 0.4870203640784043E-16, 0.2132455639604580E+02, 0.2132455639604580E+02, 0.9900000000000000E+02, 0.2972789115646258E+01, 0.5050505050505050E+01, 0.1300256830939750E-04, 0.5063995930233953E+00, 0.4338734978715565E-29, 0.3205424704587136E-04, 0.3879495859639124E-04, 0.4433597755655621E+00, 0.9466330862652142E-25, 0.6653798840082298E-04, 0.6266988927201412E-04, 0.3782868675227946E+00, 0.2274100449667269E-22, 0.3059080514749475E-04, 0.2450157710629126E-04, 0.2710178897462153E+00, 0.2739429933906694E-24, 0.4451877567018950E-05, 0.2739439060253447E-05, 0.1447594933682902E+00, 0.1897052704875489E-25, 0.3311215248867682E-05, 0.2822048496282046E-05, 0.1060101050946834E+00, 0.7924889161564951E-19, 0.2588042287900903E-05, 0.3305698843095029E-05, 0.8449698031014202E-01, 0.2523395625690618E-18, 0.1425730854724969E-04, 0.2612802087529877E-04, 0.1468593250969371E-01, 0.7520086356827106E-20, 0.6278930605158724E-03, 0.1193309863751681E-02, 0.8406928034951682E-06, 0.0000000000000000E+00, 0.8769018979884540E-02, 0.6748334476252631E-02}, + info: 0, + }, + { + z: []float64{0.5539290016733247E+00, 0.6936589108803458E+00, 0.1862325586311042E-01, 0.3903593359823143E+00, 0.1387446022374186E+00, 0.9230050933369500E+00, 0.1655735508788293E+00, 0.5464594833562775E+00, 0.4407574799078734E+00, 0.7597516703282015E+00, 0.3240675365298944E+00, 0.8527429657828770E+00, 0.6134024974884296E+00, 0.1359668624923763E+00, 0.8589771621484943E+00, 0.8334002673394481E+00, 0.3811010712979018E+00, 0.4518439634289880E+00, 0.4121953913957921E-01, 0.1499929777106017E+00, 0.7537932319194001E+00, 0.1137770685080763E+00, 0.9362285670837264E+00, 0.2284833451474525E+00, 0.4661006612092690E+00, 0.3461611111488332E+00, 0.1608705680575839E-01, 0.9250298701911358E+00, 0.5983544857783111E+00, 0.9400090024445320E+00, 0.6595514287179831E+00, 0.2725099566160494E+00, 0.6509556024164401E+00, 0.8851211780351773E+00, 0.5925872091724521E+00, 0.5318402341230010E+00, 0.3225952236300995E+00, 0.6233031538827258E+00, 0.1806586091116282E+00, 0.9476369741031940E+00, 0.6784219735316235E+00, 0.6934023884718178E+00, 0.5000312772557033E+00, 0.6725383579734943E+00, 0.6771923299216058E+00, 0.9125469473100194E+00, 0.9862018367238429E+00, 0.7259311136907298E+00, 0.9021849324334038E+00, 0.6032549715715884E+00, 0.9017706724408630E+00, 0.8975979926873651E+00, 0.5949035726420406E+00, 0.6903449880442312E+00, 0.7574844360343417E+00, 0.2889632382233942E-01, 0.9428474184445177E+00, 0.5555118914598791E+00, 0.8663544108664935E+00, 0.6853450780608091E+00, 0.1464483859238053E+00, 0.6491672315887742E+00, 0.2994712877436206E+00, 0.3101752077576794E+00, 0.4920466664329196E+00, 0.2135103260181662E+00, 0.3809190441316870E+00, 0.8437350743416491E+00, 0.5443983884818225E+00, 0.7426189539459086E+00, 0.1055227287563778E+00, 0.3059118205598027E+00, 0.8189910523272392E+00, 0.9773505795713493E+00, 0.7305661438576656E+00, 0.6062516615534109E+00, 0.4660033490547544E+00, 0.5413353206637471E+00, 0.2388208915142312E+00, 0.6428463909118429E+00, 0.2982699820336984E+00, 0.2856298024316706E-01, 0.5487207914459959E+00, 0.4464180688275057E+00}, + n: 21, + zOut: []float64{0.2448593467642387E+01, 0.2141330855004301E+01, 0.2126430153924173E+01, 0.1907639051889359E+01, 0.1812500110390200E+01, 0.1510069013602020E+01, 0.1441897976798092E+01, 0.1263171337642769E+01, 0.1138107892295268E+01, 0.1088450894719558E+01, 0.9398511957468885E+00, 0.8468227425873083E+00, 0.6124964740092524E+00, 0.5436278175488470E+00, 0.4066256939946141E+00, 0.3972422051503922E+00, 0.2390787026361968E+00, 0.4848296808782174E-01, 0.2905803980602126E-01, 0.1302961362478940E-02, 0.3616542154739030E-05, 0.3187755557432356E-18, 0.8836722322771784E-05, 0.6065531139006927E-05, 0.1441897976798092E+01, 0.7730421460348975E-16, 0.3574427637238573E-07, 0.1935178018527985E-07, 0.1263171337642769E+01, 0.8058524406205312E-18, 0.1418632976070110E-05, 0.4069026170914173E-05, 0.1138107892295268E+01, 0.1371633476674845E-23, 0.4721385684453755E-04, 0.3623692584267971E-04, 0.1088450894719558E+01, 0.1790018845564752E-20, 0.4055026077404345E-04, 0.2446096735206838E-04, 0.9398511957468885E+00, 0.3178330447896772E-25, 0.2094278317138010E+02, 0.2094278317138010E+02, 0.1040000000000000E+03, 0.3031746031746032E+01, 0.4807692307692307E+01, 0.8138465546053722E-05, 0.6124964740092524E+00, 0.1019617235038814E-22, 0.4736809894069740E-03, 0.1915264360566004E-03, 0.5436278175488470E+00, 0.2004410489406572E-21, 0.1259085689345719E-03, 0.2338760337361548E-03, 0.4066256939946141E+00, 0.1231392444306089E-15, 0.6226403214695822E-04, 0.7644683470656998E-04, 0.3972422051503922E+00, 0.5914962592392188E-17, 0.1887068321547840E-03, 0.1345267246510674E-03, 0.2390787026361968E+00, 0.1936824017247308E-20, 0.7333182971373067E-03, 0.1062997506116107E-02, 0.4848296808782174E-01, 0.3799154119544393E-26, 0.1269933545612727E-03, 0.1297822869175177E-03, 0.2905803980602126E-01, 0.8465676581597317E-24, 0.5642309440908588E-03, 0.2732446225021143E-03, 0.1302961362478940E-02, 0.2467375723434259E-18, 0.9177892725485271E-03, 0.8034707353774361E-03, 0.3616542154739030E-05, 0.2761013168273541E-28, 0.6531167933367503E-03, 0.6727959129527735E-03}, + info: 0, + }, + { + z: []float64{0.7455810318731756E+00, 0.1881309445499726E+00, 0.6290241532486281E+00, 0.9426231091333456E+00, 0.1402641401457146E+00, 0.5545071521563689E+00, 0.3467970399972181E+00, 0.6378935846273492E-01, 0.8187242451993508E+00, 0.8444039716090014E+00, 0.8807815832461214E+00, 0.6871811349512845E+00, 0.6041217734774926E+00, 0.2285364565760638E+00, 0.6287288909172152E+00, 0.5441550558534458E+00, 0.6062929607453951E+00, 0.1528830611582420E+00, 0.7289323622783690E+00, 0.8693274251763169E+00, 0.1210720262902459E+00, 0.4752572018677603E+00, 0.8160358228459934E+00, 0.5003926181135285E+00, 0.2800920281530351E+00, 0.3817159580569316E+00, 0.1419563352692587E+00, 0.9738793587569783E+00, 0.2402077997739175E+00, 0.5021080238100061E+00, 0.5325521311583831E+00, 0.7002793445871702E+00, 0.2004913666518293E-01, 0.6858750037076770E+00, 0.5705320248969311E+00, 0.6000416876176061E+00, 0.9254592880635680E+00, 0.2987366812581649E+00, 0.8838368946481180E+00, 0.7495294261248863E+00, 0.2516401660161148E+00, 0.5770724542103510E+00, 0.8689432882806168E+00, 0.3108844333247283E+00, 0.7611598373381380E+00, 0.9533545884676758E+00, 0.6146629999183371E+00, 0.7337933880625785E+00, 0.1335018938357140E+00, 0.4054745880121539E+00, 0.9816031767048012E+00, 0.5190257866591561E+00, 0.9457220484783406E+00, 0.2563725588490263E+00, 0.8953616129834293E+00, 0.1343673038869742E+00, 0.1198867110907023E+00, 0.7765966504091196E+00, 0.1685346783514826E+00, 0.9322265874533907E+00, 0.4968937019786546E+00, 0.3933065437909874E+00, 0.7046190939244956E-01, 0.5772052710604483E+00, 0.1220174671595003E+00, 0.3586914192309758E+00, 0.4743117898783903E+00, 0.1205436116155321E+00, 0.2068106627971966E-01, 0.5035688415619853E+00, 0.2656792568844590E-01, 0.4951625786650252E+00, 0.1600264513881963E+00, 0.4218870487180432E+00, 0.4847863747130776E-01, 0.9478135093620923E+00, 0.1811694594266104E+00, 0.5311488460048615E+00, 0.2296061187775216E+00, 0.9932681440344262E+00, 0.2007921586496573E+00, 0.9684478357621775E+00, 0.9322927111902295E+00, 0.6234102172880590E+00}, + n: 21, + zOut: []float64{0.2617080551859897E+01, 0.2305187568066598E+01, 0.1942735806791493E+01, 0.1834812272403632E+01, 0.1760060933961288E+01, 0.1720372963502770E+01, 0.1676173250234917E+01, 0.1530300579122039E+01, 0.1214313538868506E+01, 0.1146550683576815E+01, 0.9555081169996513E+00, 0.8235353939361046E+00, 0.7281321711646775E+00, 0.5964515885643180E+00, 0.4105953672636856E+00, 0.2154672622243388E+00, 0.1469861329023305E+00, 0.1350631498164301E+00, 0.8120368457133148E-01, 0.1548517647968005E-01, 0.1861612641330624E-04, 0.6389970231972139E-21, 0.6259229043737505E-18, 0.1065975851985723E-17, 0.1676173250234917E+01, 0.1398996249446581E-17, 0.1485385179581525E-16, 0.5390878377546583E-16, 0.1530300579122039E+01, 0.1934286939601921E-26, 0.4995235293268131E-13, 0.1480097232724468E-13, 0.1214313538868506E+01, 0.1393981231259665E-11, 0.4031414073293921E-10, 0.9065983401759033E-10, 0.1146550683576815E+01, 0.7754818242684634E-25, 0.9068533370171412E-09, 0.1932480064220526E-08, 0.9555081169996513E+00, 0.5937598997073433E-12, 0.2185603480843691E+02, 0.2185603480843692E+02, 0.1010000000000000E+03, 0.3183673469387755E+01, 0.2970297029702970E+01, 0.4106209724092858E-05, 0.7281321711646775E+00, 0.2221432309102369E-26, 0.2012416535197213E-04, 0.1179395510019159E-04, 0.5964515885643180E+00, 0.6492360922940637E-17, 0.6055695087058826E-05, 0.1676327789285107E-04, 0.4105953672636856E+00, 0.1174834768927548E-24, 0.8526024871833974E-05, 0.9608606324255413E-05, 0.2154672622243388E+00, 0.1186446801452402E-26, 0.9887524717240814E-05, 0.1072842889916555E-04, 0.1469861329023305E+00, 0.0000000000000000E+00, 0.1666923382276663E-04, 0.2139923074663986E-04, 0.1350631498164301E+00, 0.4860988391194038E-18, 0.4968094868839375E-08, 0.1325007303324406E-08, 0.8120368457133148E-01, 0.5476819983069490E-18, 0.5501364953991437E-04, 0.1068949633822309E-04, 0.1548517647968005E-01, 0.6621786174648700E-13, 0.4934492558904634E-03, 0.7815729865935395E-03, 0.1861612641330624E-04, 0.0000000000000000E+00, 0.2047621357235247E-01, 0.1218736604744046E-01}, + info: 0, + }, + { + z: []float64{0.1913768959569714E+00, 0.7347223265181069E+00, 0.9087350122086006E+00, 0.8876448886267929E-02, 0.1794058368310475E+00, 0.3375830657319635E+00, 0.4153249303964603E+00, 0.3079259326141542E+00, 0.5095638682609168E+00, 0.6300946130469818E+00, 0.5367870439046851E-02, 0.6082577193589970E+00, 0.6096872650047096E+00, 0.8098482943683755E+00, 0.4018780482667224E+00, 0.1612961166583111E+00, 0.4165836183710623E+00, 0.6711774659609234E+00, 0.1871437048914691E+00, 0.2043648411447756E+00, 0.4603921058522200E+00, 0.5138380788557162E-01, 0.3299651081607302E+00, 0.5178779891127856E+00, 0.8488474652006981E+00, 0.4000528745818374E+00, 0.7038372186752184E-01, 0.1091866126814279E+00, 0.4601541814804277E-01, 0.2814862519917873E+00, 0.5969661695911915E+00, 0.1111325580672384E+00, 0.1377964900539917E+00, 0.4488655138014651E+00, 0.5793089439934721E+00, 0.4068390675279384E+00, 0.3141858292757815E-01, 0.3803058398371814E+00, 0.6865263808463873E-01, 0.6565571596516916E+00, 0.4227763797508006E+00, 0.9281332433572439E+00, 0.2549706813172651E+00, 0.1472316879439791E+00, 0.8389980826186394E+00, 0.4949206978487660E+00, 0.8778524239605636E+00, 0.8125876339222501E+00, 0.6384442407604712E+00, 0.6297206683503800E+00, 0.1074594814776241E+00, 0.4635106216187717E+00, 0.2149027083261391E+00, 0.2926633791426133E+00, 0.8718806127632718E+00, 0.9358351753143842E+00, 0.5812389276262170E+00, 0.8361764419241092E+00, 0.1334582685582402E+00, 0.6700349085889619E+00, 0.1370175035793201E+00, 0.2605729802823288E+00, 0.7055670307426516E+00, 0.1974656950667419E-01, 0.9516894704106690E+00, 0.7509460514650641E+00, 0.9770872584819335E-01, 0.1679929405438133E+00, 0.2605432695744189E+00, 0.7255281751885829E+00, 0.2060091110826470E+00, 0.5123028703888126E+00, 0.5392241233948379E+00, 0.3215743887975069E+00, 0.4306560982435532E+00, 0.9326432909148183E+00, 0.1891146429259456E+00, 0.5585690444839775E+00, 0.8103752159402208E+00, 0.3850798219907741E+00, 0.6027394925107610E-01, 0.6960376568363590E+00, 0.6132631218829975E+00, 0.5859904896405407E+00}, + n: 21, + zOut: []float64{0.1948845699194504E+01, 0.1757754653408917E+01, 0.1739740003489702E+01, 0.1427189755042558E+01, 0.1354312190162734E+01, 0.1300861212306309E+01, 0.1144086431430055E+01, 0.9728683413380136E+00, 0.7924660843958955E+00, 0.7190108168957414E+00, 0.5334843173898538E+00, 0.4234595469843583E+00, 0.3840099969172215E+00, 0.2310167712576353E+00, 0.1706582281146164E+00, 0.1481114719972525E+00, 0.9844570800522298E-01, 0.8643465546688130E-01, 0.2116850399857309E-01, 0.1490679637756442E-02, 0.9506251872618699E-05, 0.0000000000000000E+00, 0.3139247800552953E-11, 0.1114956279480716E-10, 0.1144086431430055E+01, 0.2611946364919696E-16, 0.1910542599593587E-05, 0.1867627468366115E-05, 0.9728683413380136E+00, 0.3548331964791209E-13, 0.9422609200466975E-06, 0.3861796048985941E-05, 0.7924660843958955E+00, 0.4543838814073028E-27, 0.1545075054473009E-06, 0.2314398440634665E-06, 0.7190108168957414E+00, 0.1033975765689929E-24, 0.9239329035775786E-07, 0.1002180390059042E-06, 0.5334843173898538E+00, 0.0000000000000000E+00, 0.1525542457368567E+02, 0.1525542457368567E+02, 0.1120000000000000E+03, 0.3308390022675737E+01, 0.5357142857142857E+01, 0.1175851227353848E-05, 0.3840099969172215E+00, 0.1009741958682895E-27, 0.6285056589702800E-05, 0.7777675415159152E-05, 0.2310167712576353E+00, 0.4642054879586336E-19, 0.2707022647265855E-04, 0.1462219920606713E-04, 0.1706582281146164E+00, 0.0000000000000000E+00, 0.1442808298792521E-03, 0.1499267314065209E-03, 0.1481114719972525E+00, 0.1784642171583157E-21, 0.9060208842449760E-06, 0.2604899516157433E-05, 0.9844570800522298E-01, 0.3285517707584525E-17, 0.4009882974094740E-08, 0.9813054658490708E-08, 0.8643465546688130E-01, 0.1441804758967627E-17, 0.1005867330167897E-05, 0.3548177460196556E-06, 0.2116850399857309E-01, 0.1161145423573808E-16, 0.4264476922944564E-04, 0.6523019800084465E-04, 0.1490679637756442E-02, 0.5282426871388410E-23, 0.4120097727637851E-03, 0.5256559484655862E-03, 0.9506251872618699E-05, 0.7858215819253763E-23, 0.4122429400478702E-03, 0.4195795458123320E-03}, + info: 0, + }, + { + z: []float64{0.8707866955342474E+00, 0.7817747598907121E-01, 0.3395074897480099E-01, 0.4299950297507704E+00, 0.8088090483755312E+00, 0.8059665333356031E+00, 0.8715468955879169E-01, 0.7726332912417854E+00, 0.8113440783694211E+00, 0.3884398998833286E+00, 0.2376236729669906E+00, 0.1163685212573567E+00, 0.9165435854442110E+00, 0.6267984817484763E+00, 0.9624876615834328E+00, 0.3034180669232360E+00, 0.2061796047621195E+00, 0.5768621491208505E+00, 0.9925917678590149E+00, 0.6443157924817072E+00, 0.5967958277754652E+00, 0.6529032825080359E+00, 0.2463148548215904E+00, 0.3434579503978075E+00, 0.9563439871443443E+00, 0.2121028540747388E+00, 0.7195547303990343E+00, 0.2508441805243417E+00, 0.1006260142041168E+00, 0.8893309100691102E+00, 0.5028754540045453E+00, 0.8271029410166070E+00, 0.1744058577319449E+00, 0.1497291367846938E+00, 0.9760674104574272E+00, 0.1217237467828105E+00, 0.5182991497218187E+00, 0.9638099804000833E-01, 0.3920754919448237E+00, 0.5405769677178972E+00, 0.2099631365577761E+00, 0.7305783624173950E+00, 0.5230361650507421E+00, 0.3249231142539155E+00, 0.6943021078034506E+00, 0.8039502137729849E+00, 0.5430939865698426E+00, 0.5802454813209417E+00, 0.4521353811622019E+00, 0.6022646695138674E+00, 0.5085578584349214E+00, 0.2084880202460930E+00, 0.7893764544854661E+00, 0.8499187425465698E+00, 0.6507732600828079E+00, 0.6030189256946239E+00, 0.2748834677816949E+00, 0.7991444375081345E+00, 0.3953548021356785E+00, 0.8063610109500122E+00, 0.9322494176165492E+00, 0.2295756744488692E+00, 0.9380170922026533E+00, 0.6349173046266506E+00, 0.8138238710526029E+00, 0.1723717901392456E+00, 0.7436778507578146E+00, 0.9748296910217159E+00, 0.9719004334667378E+00, 0.1097372829332979E+00, 0.6782829454939702E+00, 0.5097404868982898E+00, 0.9485025358778609E+00, 0.7313319469015522E-01, 0.6156780373408383E+00, 0.8764490831370680E+00, 0.2737186188000360E+00, 0.3500606337779347E+00, 0.7029831161979777E+00, 0.1747477098480691E+00, 0.8887436470613648E+00, 0.8441051781034927E+00, 0.3534934185139980E+00, 0.9278581973721739E+00}, + n: 21, + zOut: []float64{0.2399590582568773E+01, 0.2223029747781157E+01, 0.2028465681071774E+01, 0.1928601105940012E+01, 0.1734632538043284E+01, 0.1705587556623443E+01, 0.1335586809119933E+01, 0.1201248979220471E+01, 0.1103973785860777E+01, 0.9516762968928613E+00, 0.8501027578146555E+00, 0.7334218559333251E+00, 0.5694462065979470E+00, 0.4616704914677346E+00, 0.3869349008726894E+00, 0.2370229392379994E+00, 0.1895639186923105E+00, 0.6837204156138489E-01, 0.3336561258733767E-01, 0.4796873010443177E-02, 0.8309969413683648E-03, 0.1974829088984998E-20, 0.1178494024155901E-08, 0.8095343015842228E-09, 0.1335586809119933E+01, 0.2220446049250313E-15, 0.1020576889344504E-06, 0.1802026823995536E-06, 0.1201248979220471E+01, 0.0000000000000000E+00, 0.6243063866214613E-06, 0.3862955415798747E-06, 0.1103973785860777E+01, 0.6981113564263453E-22, 0.3544097463307990E-10, 0.1357364267827356E-10, 0.9516762968928613E+00, 0.9072531498765813E-25, 0.7979152396248553E-09, 0.3946058728874109E-09, 0.8501027578146555E+00, 0.3130538746543124E-14, 0.2014792167783968E+02, 0.2014792167783968E+02, 0.1020000000000000E+03, 0.3129251700680272E+01, 0.5882352941176471E+01, 0.5818593578868780E-05, 0.5694462065979470E+00, 0.1588643710672175E-16, 0.4031382989989102E-05, 0.4054337523014161E-05, 0.4616704914677346E+00, 0.4437342591868191E-30, 0.3922192530785082E-05, 0.4209867122852495E-05, 0.3869349008726894E+00, 0.1490631566505624E-25, 0.4185837521330395E-06, 0.8450171931154743E-06, 0.2370229392379994E+00, 0.9509832565716118E-20, 0.2486232683772935E-03, 0.1020105306066691E-03, 0.1895639186923105E+00, 0.4152563805083406E-26, 0.4122104994398350E-03, 0.2603466333914367E-03, 0.6837204156138489E-01, 0.2482703040911568E-24, 0.1451022916339763E-02, 0.8718585538326752E-03, 0.3336561258733767E-01, 0.7888609052210118E-30, 0.3124612722893384E-02, 0.2800832977531187E-02, 0.4796873010443177E-02, 0.5945360652724886E-23, 0.1330631700030230E-06, 0.1700369028500688E-07, 0.8309969413683648E-03, 0.0000000000000000E+00, 0.1665788949608015E-02, 0.1927727749653244E-02}, + info: 0, + }, + { + z: []float64{0.5557143146495949E+00, 0.5989968816903124E+00, 0.2940668070493605E+00, 0.6865591553636113E+00, 0.2538362881116337E+00, 0.8562930572057048E-01, 0.8935270452331215E+00, 0.2427258280604294E-01, 0.8872146530392093E+00, 0.8383596820641517E+00, 0.7298494135137694E+00, 0.5456106579379609E+00, 0.5284508278981448E+00, 0.4551015440756836E+00, 0.8310297436868961E+00, 0.2533050402685522E+00, 0.8204820449217906E+00, 0.3961557150240700E+00, 0.9768702237400030E+00, 0.2370292739142171E+00, 0.2559318188841475E-02, 0.9750517337670606E-01, 0.4332045279801727E+00, 0.9393777930670477E+00, 0.1401411199977110E-01, 0.6412771440674316E+00, 0.3992540155849937E+00, 0.6710909099058460E+00, 0.7286319488310415E+00, 0.2796269361967505E+00, 0.7441899058930037E+00, 0.6626826587793098E+00, 0.9214594500725222E+00, 0.3161807402236700E+00, 0.5522479249937589E+00, 0.8328895958825197E+00, 0.3188368475648113E+00, 0.7495883496609020E+00, 0.7525354981370723E+00, 0.4819658709067065E-01, 0.8655147680740739E+00, 0.9438778396406793E+00, 0.2488475915004000E+00, 0.6823535213934872E+00, 0.1937525404626215E+00, 0.5005903164733780E+00, 0.8863816362271992E-01, 0.8279647895785316E+00, 0.7576076924432378E+00, 0.7026499641621615E+00, 0.4430381204856144E+00, 0.7250369983032848E+00, 0.6848785243425647E+00, 0.4460397323983623E+00, 0.4708648248777212E+00, 0.2715064773162834E+00, 0.3027887490966231E+00, 0.7428389405348396E+00, 0.4450045451144832E+00, 0.4683793136386452E+00, 0.2207684946192057E+00, 0.2427030064074031E+00, 0.9554840783351275E+00, 0.4627007756736100E+00, 0.2498171419709001E+00, 0.6457883819068694E+00, 0.9852852516910280E+00, 0.1549706320399313E-01, 0.5863698153730145E+00, 0.8639664213849532E+00, 0.3535803218615043E+00, 0.5300900503312423E+00, 0.6390014357018353E+00, 0.7961857807391770E+00, 0.2691637990251612E+00, 0.5302467438659471E+00, 0.3050412123368091E+00, 0.6256487701731338E+00, 0.3334512397543001E+00, 0.4160884062357342E+00, 0.1255438899512573E+00, 0.1645317210625844E+00, 0.3238197294562333E+00, 0.8765325383521217E+00}, + n: 21, + zOut: []float64{0.2427342887003738E+01, 0.2350720031505609E+01, 0.2023223336640000E+01, 0.1998000565720247E+01, 0.1766392007527096E+01, 0.1571733737439641E+01, 0.1560415852981921E+01, 0.1417948678305651E+01, 0.1258973312710257E+01, 0.1056655934390461E+01, 0.8835393928887348E+00, 0.8723851974669989E+00, 0.7820423442972025E+00, 0.7419840433476598E+00, 0.4998280519834369E+00, 0.4045332331022956E+00, 0.9795545665796999E-01, 0.6816976350034422E-01, 0.5040003524610775E-01, 0.3066447317814986E-01, 0.1707038609221110E-04, 0.0000000000000000E+00, 0.7788285758834551E-10, 0.4967814553062384E-10, 0.1560415852981921E+01, 0.2584939414223288E-25, 0.2197123097785426E-09, 0.1273532664170934E-09, 0.1417948678305651E+01, 0.1666074231826777E-26, 0.1275101209751314E-13, 0.3690153580151478E-13, 0.1258973312710257E+01, 0.3205217501722064E-17, 0.9823174457391989E-10, 0.2521354047663225E-09, 0.1056655934390461E+01, 0.7258232531419596E-14, 0.3712131332588551E-06, 0.9470624651125662E-06, 0.8835393928887348E+00, 0.1013078509970455E-14, 0.2186292540627962E+02, 0.2186292540627962E+02, 0.1200000000000000E+03, 0.3639455782312925E+01, 0.8333333333333334E+01, 0.8044662327724623E-11, 0.7820423442972025E+00, 0.1609007833004439E-16, 0.1435272653873044E-05, 0.2709954877521105E-06, 0.7419840433476598E+00, 0.7040565915227063E-17, 0.3841536774665796E-05, 0.2871402006582635E-05, 0.4998280519834369E+00, 0.2100142105025380E-22, 0.2079096157763567E-04, 0.3245111531694086E-04, 0.4045332331022956E+00, 0.1391829401523057E-17, 0.6737785910120600E-04, 0.9764140649613147E-04, 0.9795545665796999E-01, 0.0000000000000000E+00, 0.6779864796214124E-03, 0.3130513090482015E-03, 0.6816976350034422E-01, 0.2326445472805242E-24, 0.3547436816484852E-02, 0.2240007954218211E-02, 0.5040003524610775E-01, 0.1487168151587342E-22, 0.3710761871988309E-06, 0.2590766399899962E-07, 0.3066447317814986E-01, 0.7395570986446986E-31, 0.2806228106658499E-03, 0.1300265719680322E-02, 0.1707038609221110E-04, 0.5107323294632100E-21, 0.5584126334680110E-02, 0.2863707539154273E-03}, + info: 0, + }, + { + z: []float64{0.8091224458140820E+00, 0.8008972278830493E+00, 0.2578176398184776E+00, 0.1256248089219657E+00, 0.6581359192692769E+00, 0.2304361454551056E+00, 0.7582551898966047E+00, 0.1757884371165862E+00, 0.3186400696162690E+00, 0.7479165768101737E+00, 0.3726824047207358E+00, 0.8797387692666324E+00, 0.5750380180879821E+00, 0.5660816893967801E+00, 0.4438713938433396E+00, 0.1758644078670230E+00, 0.5631776732547016E+00, 0.3584358301396408E+00, 0.9436101806256550E+00, 0.5626737326978751E+00, 0.6424649400467324E+00, 0.8481112336470399E+00, 0.5655978701315552E+00, 0.8705727446437589E+00, 0.2336253154027212E-01, 0.5296192722406249E+00, 0.2416414888807097E+00, 0.8901032371078870E+00, 0.6213866196646989E+00, 0.7130035148592161E+00, 0.7957781913464947E+00, 0.8476792055481847E+00, 0.9456821938668590E+00, 0.9119251640705257E+00, 0.6793496748825844E+00, 0.1959111178023272E+00, 0.1712010119398182E+00, 0.1826738976471362E+00, 0.2526159624017289E+00, 0.1636253698204285E+00, 0.5186411299293459E+00, 0.9760895321955887E-01, 0.6893646610477002E+00, 0.9919227436537437E-01, 0.3790249398464486E+00, 0.9060767708258410E+00, 0.1329141344440885E+00, 0.8748053076614649E+00, 0.3613991427617499E+00, 0.1317424493721138E+00, 0.1676759484196766E-01, 0.7195688942861501E+00, 0.7508197149131951E+00, 0.1084062966598669E+00, 0.7799888885196686E+00, 0.8731271868042269E+00, 0.7281667421703623E+00, 0.5506096404209293E+00, 0.2344365678709384E+00, 0.8253982006984435E+00, 0.6925029659724733E+00, 0.2137159289768908E+00, 0.6304949708624844E+00, 0.2263541700174215E+00, 0.3731966957484361E+00, 0.4056710443895672E-01, 0.1518575777839423E+00, 0.7000182640684851E+00, 0.5207195688041865E+00, 0.3546513077756396E+00, 0.5223091585165126E+00, 0.1312526670646489E+00, 0.6075518716591177E+00, 0.7815133160786110E+00, 0.1466092133856621E+00, 0.6908403097208041E+00, 0.5289383481177163E+00, 0.3060973141340825E+00, 0.2719751878023001E+00, 0.4367099092855503E+00, 0.1678669773704986E+00, 0.2384522838837465E+00, 0.7578135131488263E+00, 0.2260651503779529E+00}, + n: 21, + zOut: []float64{0.3001718609114466E+01, 0.2461580649918252E+01, 0.2139800724137603E+01, 0.2110198913058292E+01, 0.1773285881581521E+01, 0.1731854037718996E+01, 0.1434868444776101E+01, 0.1292334845681036E+01, 0.1202898865215905E+01, 0.9074690574580867E+00, 0.8145281637318031E+00, 0.6833997197084192E+00, 0.6303801796404412E+00, 0.5115989792032534E+00, 0.4365028215455523E+00, 0.3347059637856380E+00, 0.2704761845997483E+00, 0.1007567293499011E+00, 0.7404356572986662E-01, 0.2225224658576705E-01, 0.1003499792335912E-03, 0.1163915500165708E-19, 0.5702083577853931E-06, 0.6235005324467382E-06, 0.1434868444776101E+01, 0.7352183636659830E-27, 0.3221030091629643E-04, 0.6932009635225803E-04, 0.1292334845681036E+01, 0.1547654926086715E-20, 0.2859096049606110E-03, 0.1689403705904475E-03, 0.1202898865215905E+01, 0.5187952724823741E-19, 0.3457740509453089E-04, 0.1548723988845099E-04, 0.9074690574580867E+00, 0.1883346903736854E-18, 0.4924250006037621E-06, 0.3064183963004930E-06, 0.8145281637318031E+00, 0.7436271633171000E-16, 0.2193475493251988E+02, 0.2193475493251988E+02, 0.9400000000000000E+02, 0.2913832199546485E+01, 0.3191489361702128E+01, 0.6928384721316203E-06, 0.6303801796404412E+00, 0.4344707644406440E-17, 0.8243004381261832E-06, 0.1242944619712133E-05, 0.5115989792032534E+00, 0.1321342016245195E-28, 0.6830327722875946E-05, 0.4610227507804771E-05, 0.4365028215455523E+00, 0.7922538128148438E-16, 0.5185315150043044E-04, 0.9574812800552337E-04, 0.3347059637856380E+00, 0.4042912139257686E-29, 0.6190562688247171E-03, 0.1111720505727282E-02, 0.2704761845997483E+00, 0.1659171176970474E-17, 0.3895087988050344E-03, 0.1929449868539905E-03, 0.1007567293499011E+00, 0.2919870821923328E-23, 0.2088900906409071E-03, 0.1786849109209585E-03, 0.7404356572986662E-01, 0.6310887241768094E-28, 0.1266951898160773E-03, 0.1217799054154213E-03, 0.2225224658576705E-01, 0.3697785493223493E-31, 0.1828672832615040E-03, 0.2196698921083079E-03, 0.1003499792335912E-03, 0.0000000000000000E+00, 0.1256202468809242E-02, 0.9158129895566399E-03}, + info: 0, + }, + { + z: []float64{0.7473165994595915E+00, 0.9383144044637891E+00, 0.9705766820209645E+00, 0.3093136353727625E+00, 0.7158638842786125E+00, 0.8927477442087851E+00, 0.5846837014009232E-02, 0.2823227977987499E+00, 0.4656399961948744E+00, 0.1783480145929806E-01, 0.8517241739910267E+00, 0.2968236367983081E+00, 0.3828703962512207E+00, 0.1618551942929359E+00, 0.8422815023410849E+00, 0.9667213467147939E+00, 0.1872774458350456E+00, 0.9673785609387944E+00, 0.1668393270938346E+00, 0.1793363294699661E+00, 0.3882509817575230E+00, 0.9322497724034516E+00, 0.1678634979113953E+00, 0.4000730353927472E+00, 0.1370854040387474E+00, 0.1383728853360747E+00, 0.8728086099072359E+00, 0.7142605368034651E+00, 0.1298497843576266E+00, 0.4890695005398649E+00, 0.6561831309305255E+00, 0.2551502145039813E+00, 0.3137603328050955E+00, 0.4725573834392259E+00, 0.1864194559915778E+00, 0.2476903242862807E+00, 0.3016682498100809E-01, 0.6028908129301045E+00, 0.9699532639034771E+00, 0.6804787742392342E+00, 0.5085224418131328E+00, 0.8160312832212636E+00, 0.4537844508149779E+00, 0.7698002058576117E+00, 0.9102837491884663E-01, 0.7957963901796614E+00, 0.4129806172970929E+00, 0.1183929303892000E+00, 0.7231979382284242E+00, 0.6908050716155305E+00, 0.9129211251463741E+00, 0.8407226028232299E+00, 0.7511043357392063E+00, 0.6614037096770188E+00, 0.5816383867961591E+00, 0.9508597818692400E+00, 0.6671834981267941E+00, 0.5353731249555691E+00, 0.8270836995328532E+00, 0.4748649574057349E+00, 0.7310961648034807E+00, 0.5329698192925740E+00, 0.5537463638220994E+00, 0.8202244086458278E+00, 0.3089778794417031E-01, 0.8347421543151022E+00, 0.7341688304615497E+00, 0.6293051268804178E+00, 0.9685330131023850E-01, 0.2218306173097127E+00, 0.4005982063157664E+00, 0.8004209862846372E+00, 0.9322471342744776E-02, 0.5252230232113276E+00, 0.8078446044346348E+00, 0.8663675770089085E-02, 0.4174348230921995E+00, 0.5316704871571061E+00, 0.8080873214304936E+00, 0.3191328650837369E+00, 0.2265528787275422E+00, 0.1299687059183835E+00, 0.5606006275148095E+00, 0.2716326223111132E+00}, + n: 21, + zOut: []float64{0.2557856639061994E+01, 0.2221569823028635E+01, 0.2113175506056959E+01, 0.1791034203034858E+01, 0.1626866366713385E+01, 0.1553853827140545E+01, 0.1378038738404736E+01, 0.1313711478279983E+01, 0.1103021858691488E+01, 0.8924372074434684E+00, 0.7465727975101516E+00, 0.5658880123536838E+00, 0.5427616116084486E+00, 0.3934406603234193E+00, 0.3139076008306549E+00, 0.2922956394268174E+00, 0.1324157743308766E+00, 0.8492495339426936E-01, 0.1726019296564064E-01, 0.1478900502211735E-02, 0.3047316799617542E-04, 0.0000000000000000E+00, 0.2209423397088722E-18, 0.1230851536694111E-18, 0.1378038738404736E+01, 0.4653537180464338E-22, 0.4724643033910209E-17, 0.2943893377745906E-17, 0.1313711478279983E+01, 0.2193156221990361E-16, 0.1119006893822957E-16, 0.1741431705208298E-16, 0.1103021858691488E+01, 0.2831227495869906E-12, 0.2860829853751284E-15, 0.4129571258389818E-15, 0.8924372074434684E+00, 0.1711229892219076E-22, 0.2249832739645017E-14, 0.3254005212313171E-14, 0.7465727975101516E+00, 0.5231751935973153E-19, 0.1964254226427022E+02, 0.1964254226427022E+02, 0.1110000000000000E+03, 0.3285714285714286E+01, 0.8108108108108109E+01, 0.1373504512438542E-12, 0.5427616116084486E+00, 0.0000000000000000E+00, 0.2663664432452481E-11, 0.1451131289962852E-11, 0.3934406603234193E+00, 0.3021704178298789E-14, 0.8991877456137337E-10, 0.1576401145017008E-09, 0.3139076008306549E+00, 0.2274554202459952E-24, 0.7202855721215940E-08, 0.4214854283718170E-08, 0.2922956394268174E+00, 0.3975858962313899E-27, 0.6024353396932969E-07, 0.1022672043122323E-06, 0.1324157743308766E+00, 0.6969933701296916E-21, 0.1098572510799548E-05, 0.1404105143401733E-05, 0.8492495339426936E-01, 0.6511321020566649E-24, 0.5604469692434887E-06, 0.6104659421650381E-06, 0.1726019296564064E-01, 0.9860761315262648E-31, 0.7747760678878360E-06, 0.1026260244983655E-05, 0.1478900502211735E-02, 0.1334496117765360E-28, 0.5102973157105362E-05, 0.1258609455819239E-04, 0.3047316799617542E-04, 0.0000000000000000E+00, 0.4753862314998056E-03, 0.1863315015192667E-02}, + info: 0, + }, + { + z: []float64{0.2548672807470598E-01, 0.1495421137012933E+00, 0.6637277283391485E-01, 0.6233200993667132E-01, 0.4958061473131723E+00, 0.9804571594196556E+00, 0.5741929121502225E+00, 0.9319350517768583E+00, 0.5154498317218548E-01, 0.4165283024496188E+00, 0.9821854184367015E+00, 0.7510033276340442E+00, 0.2648151368970406E+00, 0.9698327797382789E-01, 0.1433813304773114E+00, 0.1687421369042604E+00, 0.6230509959313209E+00, 0.8106153730403777E+00, 0.5719487513699320E+00, 0.5761793262532514E+00, 0.4983158430615118E+00, 0.8860830618783583E+00, 0.7136722399358287E+00, 0.6310350013419201E+00, 0.5509601824732582E+00, 0.5806336147624858E-01, 0.1818648959869262E+00, 0.2346005241916651E+00, 0.5346851174706903E+00, 0.4444466121668155E+00, 0.8418378722202517E+00, 0.6164532479196363E+00, 0.4298553148227666E+00, 0.2296849794057675E+00, 0.3620982682376475E+00, 0.3645096805309075E+00, 0.9980228064491022E+00, 0.7106112428543574E+00, 0.6651697421094976E+00, 0.9830151455980368E+00, 0.3483046917749841E+00, 0.3668589729383628E+00, 0.5655614401040915E+00, 0.8891526728148491E+00, 0.9164649086142118E+00, 0.4065736846475075E+00, 0.1470436468080603E+00, 0.5802557267939668E+00, 0.8272597245263099E+00, 0.7163617706554632E+00, 0.3488790096540706E+00, 0.6404227109073246E+00, 0.1472796557920839E+00, 0.8764536863696604E-02, 0.5020645462548778E-01, 0.6906675094909457E+00, 0.4668434450047272E+00, 0.7886435616506033E+00, 0.8775817704321313E+00, 0.4246952359284411E+00, 0.1646609549881360E+00, 0.6697681588293083E+00, 0.7914692739599321E+00, 0.1396674072195736E-01, 0.5167232939537366E+00, 0.9374340964740459E+00, 0.4228531365925756E+00, 0.9727064517088465E+00, 0.5765501520393458E+00, 0.5648508784605104E+00, 0.3049637657479770E+00, 0.3063190445223624E+00, 0.5204528216889723E+00, 0.8180178920731451E+00, 0.4938773599630263E+00, 0.8975563911549045E-01, 0.5983688838646251E+00, 0.3698925131813697E+00, 0.2992530973981942E+00, 0.7463539101278609E+00, 0.8005980511688328E+00, 0.7944834752945218E-01, 0.3132925544163919E+00, 0.8866951016419623E+00}, + n: 21, + zOut: []float64{0.2548744028948828E+01, 0.2439584200134194E+01, 0.2276898263864132E+01, 0.2083856178014486E+01, 0.2039342663979975E+01, 0.1949418505713503E+01, 0.1425638870874207E+01, 0.1087729835971203E+01, 0.9667696375323971E+00, 0.8022433247488755E+00, 0.5846254874613492E+00, 0.5355025899480791E+00, 0.3940805795947064E+00, 0.2663780336330241E+00, 0.2413081251593111E+00, 0.1817740817404329E+00, 0.1073144197241267E+00, 0.4327520903789019E-01, 0.3141654146246065E-01, 0.2017433957164045E-01, 0.3181705377209195E-03, 0.2778526523712400E-12, 0.1839247883012458E-10, 0.2248848580297948E-10, 0.1425638870874207E+01, 0.4660214926831417E-16, 0.5684400877302917E-10, 0.6387162891082867E-10, 0.1087729835971203E+01, 0.6729715978266918E-13, 0.1741585337702246E-09, 0.2256709509706825E-09, 0.9667696375323971E+00, 0.8583633357857125E-17, 0.5122248377584688E-09, 0.7095864943104643E-09, 0.8022433247488755E+00, 0.1479114197289397E-30, 0.3545102092401686E-08, 0.2547082836533246E-08, 0.5846254874613492E+00, 0.1684748530176799E-17, 0.2002639308765254E+02, 0.2002639308765254E+02, 0.9900000000000000E+02, 0.2829931972789116E+01, 0.2020202020202020E+01, 0.1450844904575395E-08, 0.3940805795947064E+00, 0.8431345355002174E-26, 0.2834737824482197E-07, 0.1323731756234205E-07, 0.2663780336330241E+00, 0.1205202152489745E-19, 0.2553256673132341E-06, 0.1983391491151363E-06, 0.2413081251593111E+00, 0.5052150994009667E-21, 0.4174664103103917E-06, 0.5361294231508838E-06, 0.1817740817404329E+00, 0.4777592300362271E-19, 0.1103166278762495E-05, 0.1411552925870387E-05, 0.1073144197241267E+00, 0.1369462531463676E-25, 0.4868310689385493E-05, 0.3749559753873054E-05, 0.4327520903789019E-01, 0.6517810995642209E-18, 0.3308901711413922E-04, 0.5021439046381042E-04, 0.3141654146246065E-01, 0.3980258690751375E-19, 0.2091355707842741E-03, 0.1263714817696205E-03, 0.2017433957164045E-01, 0.9608259223012324E-19, 0.2907989762339014E-03, 0.3270695437261140E-04, 0.3181705377209195E-03, 0.2078018254813854E-20, 0.5046681645946245E-02, 0.5971971384809690E-02}, + info: 0, + }, + { + z: []float64{0.7556699778432414E+00, 0.9264145479756024E+00, 0.2732571748073197E+00, 0.6411921070422063E+00, 0.9885815056247259E+00, 0.3723918099656685E+00, 0.8347397513753253E+00, 0.1449609854320509E+00, 0.7237973270068254E+00, 0.7937879503069174E+00, 0.1580314367294657E+00, 0.6183123759968190E-01, 0.8526562423479169E+00, 0.4515796037285547E+00, 0.4273610709781387E+00, 0.9916977661043136E-01, 0.6106106148524300E+00, 0.8331371477897991E+00, 0.3226596180395027E+00, 0.9411873968460633E+00, 0.4713107215814810E+00, 0.2408559451890391E-01, 0.8159283865403915E+00, 0.2484819964854622E+00, 0.9053457264816500E-01, 0.7765873412573800E+00, 0.6903393919382517E-01, 0.4737861094943234E+00, 0.2953181034757211E+00, 0.1455852388723616E+00, 0.3595484224812872E+00, 0.7546693773577520E+00, 0.2176499262400425E+00, 0.2180463762362660E+00, 0.4619066216292487E+00, 0.9195384505328125E+00, 0.7817199663072332E+00, 0.7252058550809327E+00, 0.7231496659924924E+00, 0.4997135548263443E+00, 0.7857040551775740E-01, 0.9096915224111880E+00, 0.5048166916632318E+00, 0.9737715836828489E+00, 0.6597329703373522E+00, 0.1262659377119990E-01, 0.3525536903406803E+00, 0.6167857219758321E+00, 0.7408468432196044E+00, 0.7867196986400673E+00, 0.2313289425583596E+00, 0.8524506859175643E+00, 0.1392061690435467E+00, 0.4799927308227143E+00, 0.5988201473645773E+00, 0.8148615971957359E+00, 0.9991849415795491E+00, 0.4062458282025133E+00, 0.8021012361110058E-01, 0.7041715844729369E+00, 0.9319571339573152E-01, 0.9303801779957639E+00, 0.6825635414858495E+00, 0.2651022334979941E+00, 0.2966022780498856E-01, 0.2756350604456157E+00, 0.3996117016882065E+00, 0.4084803031952775E+00, 0.7693093419592285E+00, 0.5425247266459055E+00, 0.7317803042615013E+00, 0.9398853135227920E+00, 0.5923013015298344E+00, 0.6749323490534131E-01, 0.2677632908794654E+00, 0.1468441510303787E+00, 0.1088650133568649E+00, 0.2179701521651023E+00, 0.8673093102161434E+00, 0.5667697713082290E+00, 0.5061732946886482E+00, 0.4707781162637231E+00, 0.4572852405093119E+00, 0.2817384205908577E+00}, + n: 21, + zOut: []float64{0.2549866140639053E+01, 0.2289692363298807E+01, 0.2042824675422646E+01, 0.1807091836494319E+01, 0.1608583829794490E+01, 0.1518595775727545E+01, 0.1431682400757094E+01, 0.1278141352537376E+01, 0.1218077200015686E+01, 0.1115746594519385E+01, 0.9489661418934578E+00, 0.7950491688285616E+00, 0.6705557578092293E+00, 0.4223587911677574E+00, 0.3211641543143434E+00, 0.1395786344205778E+00, 0.9463219952875908E-01, 0.4563841563552573E-01, 0.3718976888616738E-01, 0.2766660139323238E-01, 0.2861060880329385E-03, 0.1489369389057270E-25, 0.4009456273839574E-11, 0.5913965075566282E-11, 0.1431682400757094E+01, 0.9808641529204798E-18, 0.1658075466067222E-10, 0.2375182467377229E-10, 0.1278141352537376E+01, 0.1561716996498461E-20, 0.5563872147228742E-10, 0.4003249215027731E-10, 0.1218077200015686E+01, 0.8198555146385643E-18, 0.1047304739332037E-09, 0.1509388346471184E-09, 0.1115746594519385E+01, 0.6804594514014344E-21, 0.1132515351796206E-08, 0.7305070647547987E-09, 0.9489661418934578E+00, 0.6324297261214257E-19, 0.2036338790917205E+02, 0.2036338790917205E+02, 0.1050000000000000E+03, 0.3147392290249433E+01, 0.2857142857142857E+01, 0.1188392639382130E-06, 0.6705557578092293E+00, 0.2287929633195320E-19, 0.1283168907741916E-05, 0.1048613283787068E-05, 0.4223587911677574E+00, 0.1189072130544977E-23, 0.1798535669474704E-05, 0.2477367923932174E-05, 0.3211641543143434E+00, 0.8187795594567816E-23, 0.5813187502570164E-05, 0.4274698539216166E-05, 0.1395786344205778E+00, 0.4387796946624011E-14, 0.1512969274311187E-04, 0.4383088766938462E-04, 0.9463219952875908E-01, 0.2802074325023381E-22, 0.1713816584845726E-03, 0.1715892923902221E-03, 0.4563841563552573E-01, 0.8331483361628599E-18, 0.1806157324013782E-06, 0.1193242630586832E-05, 0.3718976888616738E-01, 0.1396316416906445E-20, 0.3480495660704905E-03, 0.4402048010276426E-03, 0.2766660139323238E-01, 0.1504073756330590E-24, 0.6353091961964474E-03, 0.1317363577877200E-03, 0.2861060880329385E-03, 0.4589883047388968E-23, 0.3883745848947868E-02, 0.5358907697572753E-02}, + info: 0, + }, + { + z: []float64{0.8456683250225028E-01, 0.3058015837199188E+00, 0.4317902183064470E-01, 0.3671979469896071E+00, 0.3595487854233631E+00, 0.8791524368561765E+00, 0.1256853689373587E+00, 0.3494000337993621E+00, 0.2131672180923028E+00, 0.4488324680055523E+00, 0.9452502344450827E+00, 0.7197446096567599E+00, 0.8918071015747069E+00, 0.5551949519753436E+00, 0.5627883747367335E+00, 0.6930858113379974E+00, 0.7026202611250518E+00, 0.3856840921343180E+00, 0.4453224782611998E+00, 0.9627551339340559E+00, 0.6255469039377685E+00, 0.6093210861157965E+00, 0.1297243619022892E-01, 0.2745425059216151E+00, 0.5902573930769862E+00, 0.3658719785914519E+00, 0.8179101736936932E+00, 0.4251816548465440E+00, 0.3319568042078717E+00, 0.8294675656951641E+00, 0.1906193594777114E+00, 0.6862699206380130E+00, 0.6832362040809048E+00, 0.8968537122850908E+00, 0.3753636108676777E+00, 0.9926770667520373E+00, 0.7473790867948205E-01, 0.3653635034012445E+00, 0.6553100464759598E-01, 0.1045856631958887E+00, 0.2265961870023414E+00, 0.3205967446655300E-01, 0.1845082884370131E+00, 0.2250092498055734E+00, 0.5876866067653603E+00, 0.2146512915654570E+00, 0.3937206506545190E+00, 0.4110924225795073E+00, 0.3228836105384403E+00, 0.3531543308069818E-01, 0.9472843614842231E+00, 0.2348052564069324E+00, 0.1315455878409307E+00, 0.2246729768637089E+00, 0.8445861542610614E+00, 0.9528962673528295E+00, 0.4907499555456967E+00, 0.9420172239501383E+00, 0.4896535244350841E-01, 0.5088622551995382E+00, 0.1789066474661110E+00, 0.3566730680524121E+00, 0.4279936896698711E-01, 0.5241586506933626E-02, 0.9191361995860731E+00, 0.7666474814508011E+00, 0.8302596584023555E+00, 0.4738482866502817E+00, 0.2085735695866969E+00, 0.3976808123484415E+00, 0.4364253757027529E+00, 0.2407360056333678E+00, 0.4002772343201099E+00, 0.7717338386755229E+00, 0.5023514841326452E+00, 0.8988902694804358E+00, 0.4259852339101408E+00, 0.2067093317010162E+00, 0.8456128611542781E+00, 0.1290027044731792E+00, 0.2598901078235174E+00, 0.5836006873243835E+00, 0.9777637054617091E+00, 0.4896357840832322E+00}, + n: 21, + zOut: []float64{0.2625813250937807E+01, 0.2316814186652984E+01, 0.2239421861777163E+01, 0.1853308891402210E+01, 0.1827033391537137E+01, 0.1481398580531558E+01, 0.1385699025778513E+01, 0.1101045596651604E+01, 0.1077490875294086E+01, 0.6790358065311344E+00, 0.6361857378195889E+00, 0.5095707085100130E+00, 0.4739579905788711E+00, 0.4209497658895578E+00, 0.3012142858983374E+00, 0.2432742659092710E+00, 0.2088674538811938E+00, 0.1664409530858738E+00, 0.2606656040091844E-01, 0.1205810631995507E-01, 0.9325512290661112E-07, 0.1292469707114106E-24, 0.1719039818430849E-04, 0.1845080438772963E-04, 0.1385699025778513E+01, 0.2224123229986848E-19, 0.6819642419856913E-05, 0.9079053758699490E-05, 0.1101045596651604E+01, 0.6054420446023063E-14, 0.5392861994521241E-06, 0.8422816920290823E-06, 0.1077490875294086E+01, 0.7330726620037819E-25, 0.4290042344637304E-06, 0.3471234449409943E-06, 0.6790358065311344E+00, 0.1969273319091676E-18, 0.8635424232755040E-07, 0.8294124288205587E-07, 0.6361857378195889E+00, 0.4466775307674635E-22, 0.1958564738864290E+02, 0.1958564738864290E+02, 0.9700000000000000E+02, 0.2927437641723356E+01, 0.2061855670103093E+01, 0.4284285350948107E-09, 0.4739579905788711E+00, 0.4844247598072386E-17, 0.1501956526577450E-07, 0.4599310764980267E-07, 0.4209497658895578E+00, 0.5697556379758414E-13, 0.1468884761079027E-05, 0.1935721204206928E-05, 0.3012142858983374E+00, 0.3414189997796539E-26, 0.7129394687116921E-05, 0.9262068822983554E-05, 0.2432742659092710E+00, 0.2465190328815662E-31, 0.3320148255009530E-04, 0.2563439348523979E-04, 0.2088674538811938E+00, 0.8874685183736383E-29, 0.9377671959730327E-04, 0.7166613903737452E-04, 0.1664409530858738E+00, 0.1175218723307338E-19, 0.5883141447281398E-03, 0.4140832085136277E-03, 0.2606656040091844E-01, 0.2634795423438179E-27, 0.4797918408258123E-02, 0.4833036765864798E-02, 0.1205810631995507E-01, 0.6530371216255944E-19, 0.7811358433513861E-02, 0.1392611548870054E-01, 0.9325512290661112E-07, 0.1190420191421466E-12, 0.6274023555637595E-01, 0.1241063086176471E-01}, + info: 0, + }, + { + z: []float64{0.6345014789904082E+00, 0.9828013844807603E+00, 0.5292373213190880E+00, 0.3345627500234365E+00, 0.9345959669050260E+00, 0.5873733336147081E+00, 0.8888462128293518E+00, 0.1044020545901757E+00, 0.9375280272458696E+00, 0.1233411973951652E+00, 0.3330283913003940E+00, 0.2432208394685875E-01, 0.6106490172620382E+00, 0.9136489477065954E+00, 0.8250850334045809E+00, 0.7866479843500775E+00, 0.1629924039124250E+00, 0.2349971551206693E+00, 0.1024684774133804E+00, 0.7852727749024598E+00, 0.1427984573527686E+00, 0.4315181982028241E+00, 0.6564047419338838E+00, 0.5555590030741936E+00, 0.8205569452257172E+00, 0.4368031922318115E+00, 0.2897575605849890E+00, 0.6163386054890784E+00, 0.7016794584968877E+00, 0.7265422079630662E+00, 0.6393115149906525E+00, 0.7552597718778955E+00, 0.5029129969011173E+00, 0.4874732646810529E+00, 0.5094624150009296E+00, 0.4766369914172104E+00, 0.9003818070855094E+00, 0.6813014247956244E+00, 0.2988296447575162E+00, 0.6597790416796705E+00, 0.5646192150605487E+00, 0.3275024686793908E+00, 0.2725061169408716E-01, 0.8098076662320616E+00, 0.3345276190659139E+00, 0.1812780354242056E+00, 0.1997802571871318E+00, 0.5440765633504190E+00, 0.9774510594766147E+00, 0.1863483792916641E+00, 0.5910097330685633E+00, 0.2734489448477760E+00, 0.4395818444416557E+00, 0.9022786559097939E+00, 0.1029995124123335E+00, 0.9437933734967648E+00, 0.1226746192846208E+00, 0.1122541771291640E+00, 0.1756516455268763E+00, 0.9109529416432673E+00, 0.3050345572159197E-01, 0.1746678233544180E+00, 0.3750993781268622E+00, 0.4476224977918100E+00, 0.5437446694835568E+00, 0.3729575052852190E+00, 0.3542378566336749E+00, 0.7449948633772266E+00, 0.3157555204945224E+00, 0.7753984984296890E+00, 0.3284038993889418E+00, 0.5159361949232710E-01, 0.4529339074400007E-01, 0.5693581512511349E+00, 0.2213156237057901E+00, 0.9395831428155459E+00, 0.3843047271617620E+00, 0.2968653921042081E+00, 0.6156090467550724E+00, 0.3170556612853570E-01, 0.8265655132088339E+00, 0.3165750369023552E+00, 0.7055602587055542E+00, 0.8365600455841105E+00}, + n: 21, + zOut: []float64{0.2473859321883559E+01, 0.2422834159796051E+01, 0.2342770718537345E+01, 0.2190393245355733E+01, 0.2048748874742353E+01, 0.1880327408972340E+01, 0.1569014269461521E+01, 0.1302496773444914E+01, 0.1193514796722045E+01, 0.1150651682141956E+01, 0.8969794111087930E+00, 0.8226581338194529E+00, 0.6917042463755413E+00, 0.5972139808466055E+00, 0.3480375932216391E+00, 0.2932789944580818E+00, 0.2090971942801221E+00, 0.1221616224423389E+00, 0.1000478595340333E+00, 0.3412207557320287E-01, 0.3160927987836547E-03, 0.2386777554836693E-25, 0.1787847554062023E-08, 0.1930667016131883E-08, 0.1569014269461521E+01, 0.5039432348921582E-18, 0.3047636948536222E-07, 0.1223330280849913E-07, 0.1302496773444914E+01, 0.0000000000000000E+00, 0.7408697490815375E-06, 0.1498788057488595E-05, 0.1193514796722045E+01, 0.6273021918317486E-26, 0.8867922405978688E-08, 0.3710956866722375E-08, 0.1150651682141956E+01, 0.1462883977034466E-17, 0.2681277488017278E-06, 0.6188429230273071E-06, 0.8969794111087930E+00, 0.4930380657631324E-31, 0.2269022845551642E+02, 0.2269022845551641E+02, 0.1110000000000000E+03, 0.3215419501133787E+01, 0.4504504504504505E+01, 0.4606971433208740E-07, 0.6917042463755413E+00, 0.7123549154360197E-18, 0.1197511514786163E-07, 0.1386949181837661E-07, 0.5972139808466055E+00, 0.4652335183636722E-20, 0.1082703076660205E-07, 0.1003906263016573E-07, 0.3480375932216391E+00, 0.3573127201018094E-16, 0.2388210318135170E-06, 0.5694782222336181E-06, 0.2932789944580818E+00, 0.7601337464964823E-24, 0.7791755144624492E-05, 0.3242296896441773E-05, 0.2090971942801221E+00, 0.1663630656286764E-22, 0.9916420504550920E-06, 0.3916254919710180E-05, 0.1221616224423389E+00, 0.1406614427791829E-18, 0.1356917845842480E-04, 0.1379449187478977E-04, 0.1000478595340333E+00, 0.2800456213534592E-28, 0.3213444959426999E-04, 0.2790230345312924E-04, 0.3412207557320287E-01, 0.1075846717720530E-17, 0.8531299184272352E-03, 0.1419520770966347E-02, 0.3160927987836547E-03, 0.1848892746611746E-31, 0.7376316906583622E-02, 0.6546496744187779E-02}, + info: 0, + }, + { + z: []float64{0.7781991870339823E+00, 0.3799726947828087E+00, 0.8225406656461727E+00, 0.4322410258771066E+00, 0.4965834581857734E+00, 0.1642548945285990E+00, 0.4773703559733889E+00, 0.7580746486223987E+00, 0.9220155673403277E+00, 0.1624062232083541E+00, 0.5664470130564820E+00, 0.7367013127895712E+00, 0.4720756942873998E+00, 0.8695958825780965E+00, 0.6045812450089678E+00, 0.8503421320137978E+00, 0.7291568033584502E+00, 0.9563602214514951E+00, 0.1245752972610169E+00, 0.2621011209284912E+00, 0.8642265339858576E+00, 0.9528021036615359E+00, 0.9515862784178062E+00, 0.2632504807072628E+00, 0.8585529108378003E+00, 0.3025834513231899E+00, 0.7125877353473579E+00, 0.9221275053156179E+00, 0.9787992369955746E+00, 0.8789465750552752E+00, 0.9318675804398889E+00, 0.8827440896392771E+00, 0.3124337393280541E+00, 0.3124656972853590E-01, 0.5860766227864144E+00, 0.9812515177915087E+00, 0.4480000254042209E+00, 0.5121903109069345E+00, 0.1837298514334742E+00, 0.2680410429176278E+00, 0.5529294510898309E+00, 0.3627557909974974E+00, 0.9282219359125773E+00, 0.2173723036967439E+00, 0.7593665130145739E+00, 0.6245533364325671E+00, 0.1767680905493787E+00, 0.3823356866170564E+00, 0.5171578058722374E+00, 0.5376155024979712E+00, 0.5280269975706942E-01, 0.7947058949878518E+00, 0.1214716509814368E+00, 0.6840110600217510E+00, 0.7041243787921371E+00, 0.6945194787199669E+00, 0.8184844284849127E+00, 0.3440855810599863E+00, 0.1619958520504678E+00, 0.6990470088709023E+00, 0.3532225659848430E+00, 0.8229090368317697E+00, 0.8349696782028652E+00, 0.6932180266797183E-01, 0.6880274120498576E+00, 0.7566065163897195E+00, 0.2981422921509080E-01, 0.8636153925759227E-02, 0.7928093803058089E-01, 0.3096144259285381E+00, 0.6829886066202427E+00, 0.8246144682759358E+00, 0.2007259621364732E+00, 0.8710862365466575E+00, 0.6898755422119236E+00, 0.9105030198433044E+00, 0.8974818523094739E+00, 0.8909991694059211E+00, 0.8084341913662618E-01, 0.6072211485624930E+00, 0.9680950749726419E+00, 0.3932275197607872E+00, 0.8781208296025552E+00, 0.5527043030768199E+00}, + n: 21, + zOut: []float64{0.3158195987040060E+01, 0.2674397094280163E+01, 0.2611167345511754E+01, 0.2117792657212280E+01, 0.2026395303611904E+01, 0.1943316400161173E+01, 0.1877195462180231E+01, 0.1801757023901512E+01, 0.1273111869927408E+01, 0.1088705127135854E+01, 0.9559661931705944E+00, 0.9013607966201198E+00, 0.6445742634037150E+00, 0.5446175180211763E+00, 0.4486902226406620E+00, 0.3854842198344371E+00, 0.2741584921777233E+00, 0.1210105287753585E+00, 0.6940868812740908E-01, 0.2059029850850508E-01, 0.3673564803695461E-02, 0.8077935669463161E-25, 0.2195808487174199E-10, 0.8449955132778232E-10, 0.1877195462180231E+01, 0.1633831636278255E-19, 0.3497961877980620E-08, 0.7650955873935623E-08, 0.1801757023901512E+01, 0.4072241987713803E-24, 0.2126842707416970E-06, 0.1130018646589442E-06, 0.1273111869927408E+01, 0.1740941751301712E-20, 0.3388039768888790E-03, 0.2863573324805332E-03, 0.1088705127135854E+01, 0.2858227958137079E-16, 0.2905468688553340E-03, 0.2787380120464217E-03, 0.9559661931705944E+00, 0.1315475667900737E-21, 0.2494156905704573E+02, 0.2494156905704573E+02, 0.1010000000000000E+03, 0.3074829931972789E+01, 0.1980198019801980E+01, 0.2647338938369395E-05, 0.6445742634037150E+00, 0.2341846562030201E-22, 0.2667503836084351E-03, 0.1510510164587073E-03, 0.5446175180211763E+00, 0.2242636890234710E-24, 0.5495840118850513E-05, 0.4810476319752364E-05, 0.4486902226406620E+00, 0.3552400222016096E-16, 0.2740332708518062E-05, 0.2562621073339741E-05, 0.3854842198344371E+00, 0.1036641484462207E-22, 0.2248949759797675E-05, 0.2492010005917310E-05, 0.2741584921777233E+00, 0.6071156729318302E-20, 0.4130294607665845E-03, 0.1141603094124651E-03, 0.1210105287753585E+00, 0.2468629837810345E-16, 0.7230132634032991E-02, 0.6618694284253705E-02, 0.6940868812740908E-01, 0.5487745597049798E-23, 0.4151017130761703E-02, 0.4525758324635968E-02, 0.2059029850850508E-01, 0.6083695301064443E-26, 0.3095027772299370E-02, 0.3218440937246976E-02, 0.3673564803695461E-02, 0.6106717417722413E-22, 0.6443405665983428E-02, 0.1622720765285148E-02}, + info: 0, + }, + { + z: []float64{0.1985414918961074E+00, 0.4386372064833388E-01, 0.9272679997999695E+00, 0.9276564660006267E+00, 0.9509373652834754E+00, 0.6247274629358034E+00, 0.4838472987754385E+00, 0.6222976111124274E+00, 0.4248800474043221E+00, 0.9755567793536163E+00, 0.8912410754920851E+00, 0.2313492132656925E-01, 0.1563015923526294E+00, 0.7905214363406186E+00, 0.4927898149840948E+00, 0.5370919594301193E+00, 0.4644799081842790E+00, 0.9960946978984735E+00, 0.2493095982292803E+00, 0.3814725574373231E+00, 0.2940816225707878E+00, 0.6535898793246008E+00, 0.2084037192546966E+00, 0.5132959253232522E+00, 0.4251209694264122E+00, 0.9378579353373483E+00, 0.9786807729708236E+00, 0.7781441628535176E+00, 0.3951333405907657E+00, 0.3920742203259495E+00, 0.1500883321285087E+00, 0.9121803806188729E+00, 0.8516361075320147E+00, 0.6824417668614835E-01, 0.1390781730568696E+00, 0.3112124735573820E+00, 0.2535919561468232E+00, 0.7644352497405866E+00, 0.9218252733114815E+00, 0.9901458352558505E+00, 0.3279511469507669E+00, 0.8365860218696105E+00, 0.3198677553816687E+00, 0.6133665370063144E+00, 0.2580491557527305E+00, 0.6586714927743139E+00, 0.3933698458458805E+00, 0.7194383869235133E-01, 0.2213903901048253E-02, 0.1496106697134404E+00, 0.6766438239122079E+00, 0.7197724372602395E+00, 0.4797148651858846E+00, 0.5998154083597278E+00, 0.5590962662612089E+00, 0.6336887670809047E+00, 0.1072453740736307E+00, 0.7505878626477551E+00, 0.1427362910235584E+00, 0.6016163404777434E+00, 0.9488238354107547E+00, 0.4206748665323531E+00, 0.4473756257202280E+00, 0.2658295729210566E+00, 0.2340075619597504E+00, 0.9617320234413022E+00, 0.5962761690405762E+00, 0.8519099982463364E+00, 0.5571747680961063E+00, 0.1982921114470393E-01, 0.2779304562486129E-01, 0.7924439389736488E+00, 0.9672136382383878E-01, 0.8417095886148459E+00, 0.7473598542298929E+00, 0.9746159458640847E+00, 0.5038819873190444E+00, 0.9169242656654556E+00, 0.5252626769192049E+00, 0.5100979601115528E+00, 0.2790149607164115E+00, 0.4554892778467722E+00, 0.9762420639370454E+00, 0.9832519154713986E+00}, + n: 21, + zOut: []float64{0.2773247209998878E+01, 0.2684570079202721E+01, 0.2535407140485478E+01, 0.2251849067745984E+01, 0.2036533658934636E+01, 0.1904369707782458E+01, 0.1446171755624304E+01, 0.1299751831669502E+01, 0.1269533063987320E+01, 0.1007664938847636E+01, 0.8251797533661941E+00, 0.5818474246453018E+00, 0.5486201168977923E+00, 0.3772420051451134E+00, 0.3380340897724159E+00, 0.2023767003460897E+00, 0.1840234711841343E+00, 0.9225167203340243E-01, 0.4232592978815707E-01, 0.2771262583534443E-01, 0.7321455618534900E-04, 0.2977163580658995E-22, 0.3752078887401622E-10, 0.4179376226086309E-10, 0.1446171755624304E+01, 0.2236367039610280E-12, 0.1299965948722022E-10, 0.1595321259646779E-10, 0.1299751831669502E+01, 0.9926167350636332E-23, 0.8604643146515003E-10, 0.1864418628665438E-09, 0.1269533063987320E+01, 0.1306353659045996E-24, 0.1991121186029356E-08, 0.8983175437487846E-09, 0.1007664938847636E+01, 0.1213184768518325E-22, 0.3444432736029153E-07, 0.6437805745712839E-07, 0.8251797533661941E+00, 0.7772022937681214E-16, 0.2242878545784906E+02, 0.2242878545784905E+02, 0.1000000000000000E+03, 0.3024943310657596E+01, 0.3000000000000000E+01, 0.1709907812443784E-06, 0.5486201168977923E+00, 0.2972680326362443E-23, 0.1350081364219064E-06, 0.1255933647347444E-06, 0.3772420051451134E+00, 0.8046381233254320E-28, 0.7022416754922569E-08, 0.2768431074740138E-07, 0.3380340897724159E+00, 0.1719716773381806E-27, 0.7079953450794871E-07, 0.6648251035830866E-07, 0.2023767003460897E+00, 0.1940724044588524E-24, 0.4764709677102475E-07, 0.4597049352360845E-07, 0.1840234711841343E+00, 0.3459682911934042E-21, 0.4438757837191216E-07, 0.4402069254647340E-07, 0.9225167203340243E-01, 0.2596900924099520E-17, 0.8125925620122143E-07, 0.6770863964779914E-07, 0.4232592978815707E-01, 0.1280067631025782E-15, 0.3584234088053806E-06, 0.4822962810861105E-06, 0.2771262583534443E-01, 0.1012934875847350E-18, 0.1556396151524861E-05, 0.2916279508701459E-05, 0.7321455618534900E-04, 0.1540743955509789E-32, 0.4190434742116713E-02, 0.1362677535010021E-02}, + info: 0, + }, + { + z: []float64{0.6703344952482478E+00, 0.3577116069291627E+00, 0.8432263018920840E+00, 0.9584130033491455E+00, 0.2861685401430958E+00, 0.9668570623620085E+00, 0.6957796127156375E+00, 0.7603022900919236E+00, 0.7677099838587329E+00, 0.2702658617954818E+00, 0.9607212720070546E-01, 0.3973573502375266E+00, 0.8455511814548733E+00, 0.6862903202354254E-01, 0.1789860417278408E+00, 0.1112926642215833E+00, 0.8320621955974556E+00, 0.2637090148175287E+00, 0.7109403389502641E+00, 0.6494529820495407E+00, 0.8828985636942858E+00, 0.9098303542318168E+00, 0.1777489928582532E+00, 0.8977650882542143E-01, 0.7154356412046237E-01, 0.2693107133832517E-01, 0.7956794415059365E-02, 0.8852594037406200E+00, 0.2162284138438216E+00, 0.9216829080200467E+00, 0.9874282279096652E+00, 0.6087745498247736E+00, 0.7694028142872190E+00, 0.5918349824988693E+00, 0.1915561020798640E+00, 0.1135335598824661E-01, 0.6670902390154858E+00, 0.6601113994758983E+00, 0.7779237148990382E+00, 0.9023999203058302E+00, 0.1848842750705929E+00, 0.6120355291150891E+00, 0.7209828136916797E+00, 0.3124354740483853E+00, 0.9520753904353354E+00, 0.9694533109968584E+00, 0.6869212426966154E+00, 0.3510392134251344E+00, 0.7696249856763533E+00, 0.9203915575905880E+00, 0.4616165896255233E+00, 0.6796681592119477E+00, 0.9261196886552191E+00, 0.4511929507295228E+00, 0.5162093776469306E+00, 0.3093101029632945E+00, 0.1162653262260159E+00, 0.1951366360676013E+00, 0.7945099687545387E+00, 0.9707806531485516E+00, 0.4161172559602336E+00, 0.5813461713597171E+00, 0.8442974147064882E+00, 0.9135490286183924E+00, 0.3261094875410662E+00, 0.7080588637364270E+00, 0.3833080381406134E+00, 0.9095051028453779E+00, 0.6909172438403831E+00, 0.5187928284332267E+00, 0.5783778059525303E+00, 0.9615928062069277E+00, 0.2127624116065856E+00, 0.7254035177440832E+00, 0.2587362009618467E+00, 0.7570212065831576E+00, 0.2401238007004233E+00, 0.2744934873404078E+00, 0.9420426561890750E+00, 0.7098059460475599E+00, 0.2691363643891775E+00, 0.4536316870833661E+00, 0.6839445343274818E+00, 0.9336823543434762E+00}, + n: 21, + zOut: []float64{0.2634467575625416E+01, 0.2594635276829839E+01, 0.2463070407655619E+01, 0.2293127065694029E+01, 0.2072673505384417E+01, 0.1459936798288049E+01, 0.1378497856793854E+01, 0.1333239471494390E+01, 0.1102542278566289E+01, 0.8930469384549427E+00, 0.8520787727779708E+00, 0.6953298055150813E+00, 0.6847648677749263E+00, 0.2185116940651705E+00, 0.2008337976176149E+00, 0.1757551361146239E+00, 0.1271484717317025E+00, 0.5049064582277562E-01, 0.3515271339576785E-01, 0.7966224551514293E-02, 0.1685389559757755E-03, 0.1635721388548769E-22, 0.3551032227485648E-11, 0.3089325791958004E-11, 0.1378497856793854E+01, 0.6463020148652660E-17, 0.4439365591922079E-11, 0.5247211770454983E-11, 0.1333239471494390E+01, 0.8616343098037817E-25, 0.4343651596456738E-10, 0.2452653826174233E-10, 0.1102542278566289E+01, 0.9876517884224792E-16, 0.1549700306365952E-08, 0.1012434062383302E-08, 0.8930469384549427E+00, 0.4606319384654338E-19, 0.1115188986357716E-08, 0.1237013304894199E-08, 0.8520787727779708E+00, 0.1447566071967798E-23, 0.2127343784310997E+02, 0.2127343784310997E+02, 0.1270000000000000E+03, 0.3675736961451247E+01, 0.9448818897637794E+01, 0.2782364756724027E-11, 0.6847648677749263E+00, 0.6100457017578579E-23, 0.1535488071926541E-09, 0.5733950833190260E-09, 0.2185116940651705E+00, 0.6436934318898579E-12, 0.5207333190112868E-06, 0.4302907440331721E-06, 0.2008337976176149E+00, 0.1972152263052530E-30, 0.2421587237749379E-06, 0.2920528765870267E-06, 0.1757551361146239E+00, 0.8101601496619791E-27, 0.1434500575863456E-11, 0.9045851929625007E-13, 0.1271484717317025E+00, 0.1560107593833772E-17, 0.1620731838764033E-06, 0.1206839073349329E-06, 0.5049064582277562E-01, 0.3155443620884047E-29, 0.7221494757183839E-05, 0.4279630756550309E-05, 0.3515271339576785E-01, 0.0000000000000000E+00, 0.2092539651031481E-04, 0.3641666945464839E-04, 0.7966224551514293E-02, 0.1018583906139065E-23, 0.4276808715243643E-05, 0.6380573645111411E-06, 0.1685389559757755E-03, 0.0000000000000000E+00, 0.2828744147621957E-02, 0.2649548441232189E-02}, + info: 0, + }, + { + z: []float64{0.7647749557731113E+00, 0.1439440544256733E+00, 0.7500486933916728E+00, 0.6414832886183546E+00, 0.8122572937542115E+00, 0.9529234674941257E+00, 0.3352470221802866E+00, 0.6936226545338587E+00, 0.9931729574752579E-01, 0.3187856199297912E-01, 0.1671537284832858E+00, 0.6799274061730229E+00, 0.8177446911383146E+00, 0.5321042755342652E+00, 0.1611635863708949E+00, 0.1556305029012977E+00, 0.8064987994430675E+00, 0.6086425937675999E-01, 0.9539387771768112E+00, 0.5483826791143146E+00, 0.1624656726546599E+00, 0.8604262189788422E+00, 0.3348601405085260E+00, 0.6512790728986305E+00, 0.3357978279833680E+00, 0.7104789129438286E+00, 0.4161092786312924E+00, 0.8790797243791704E+00, 0.1469866181354552E+00, 0.7277776395098579E-01, 0.4317417806367096E-01, 0.8731968970940820E+00, 0.4856440529809196E+00, 0.2315660100703048E+00, 0.2955911335168215E+00, 0.4119299294790694E+00, 0.4565975215473586E+00, 0.8915397570999283E+00, 0.1639735129501203E+00, 0.5055946074157277E+00, 0.9530743160791620E+00, 0.9836351183281582E+00, 0.2913429799811792E+00, 0.9289008959282562E+00, 0.5996674664338365E+00, 0.6609996028219567E+00, 0.7317528474660470E+00, 0.9903648665746729E+00, 0.3982305249886617E+00, 0.3563571411857538E+00, 0.8851540908639802E+00, 0.8253410045707608E+00, 0.8085297859672740E+00, 0.3918185712378985E+00, 0.7922842941861202E+00, 0.7487878715845681E+00, 0.3117744132747395E+00, 0.7135433852632408E+00, 0.8969220948763633E+00, 0.5840741001028926E+00, 0.3261515465187765E+00, 0.5368137772779212E+00, 0.6371156779602756E+00, 0.5575308178040213E+00, 0.1319054467962255E+00, 0.6274305773732142E+00, 0.9230553933157697E+00, 0.3589158151867838E+00, 0.1429059780004028E+00, 0.6433214640390554E+00, 0.9159704795536289E+00, 0.8998439182451070E+00, 0.5665265465351250E+00, 0.4290736239553739E+00, 0.4923118412965143E+00, 0.3733795042755129E+00, 0.4008465132226234E+00, 0.8630963810875470E+00, 0.2835407905147469E+00, 0.8431337072866282E+00, 0.7450545748778526E+00, 0.2948369760127234E+00, 0.6896108484670013E+00, 0.1073791710993542E+00}, + n: 21, + zOut: []float64{0.2492440020550355E+01, 0.1951232214041701E+01, 0.1924880150346451E+01, 0.1800337146913507E+01, 0.1731259644349016E+01, 0.1515025732591961E+01, 0.1392131403063820E+01, 0.1337121843604905E+01, 0.1335944341051471E+01, 0.9695979508906304E+00, 0.8602855628657217E+00, 0.7598736716193354E+00, 0.5663438341779535E+00, 0.4991982558529897E+00, 0.3900147250500268E+00, 0.2612685334229408E+00, 0.1040703325016068E+00, 0.5095987426708586E-01, 0.4270469018444285E-01, 0.6313950453962554E-02, 0.4526318588114864E-04, 0.1623810366421630E-16, 0.5786287269352850E-19, 0.2440824886543042E-19, 0.1392131403063820E+01, 0.1972152263052530E-30, 0.1305662432930495E-17, 0.2687054746502436E-17, 0.1337121843604905E+01, 0.6807276388656606E-23, 0.2125450465832215E-16, 0.4166517172824519E-16, 0.1335944341051471E+01, 0.3971441341244662E-25, 0.3131313418539388E-15, 0.1598422579069803E-15, 0.9695979508906304E+00, 0.2612707318091991E-24, 0.3703169268599905E-13, 0.5897085302084673E-13, 0.8602855628657217E+00, 0.3944304526105059E-30, 0.1999104914098575E+02, 0.1999104914098576E+02, 0.1050000000000000E+03, 0.3185941043083900E+01, 0.4761904761904762E+01, 0.3815530651290367E-11, 0.5663438341779535E+00, 0.4442864618204738E-26, 0.2314135864505331E-10, 0.3280099800133426E-10, 0.4991982558529897E+00, 0.2524354896707238E-28, 0.8792792965154248E-10, 0.6284153656438893E-10, 0.3900147250500268E+00, 0.2716911819042188E-17, 0.6371083763388994E-09, 0.9063994743331422E-09, 0.2612685334229408E+00, 0.7682295356186976E-14, 0.2615630848198228E-07, 0.4934681155229334E-07, 0.1040703325016068E+00, 0.3134368286722418E-21, 0.1338644268367565E-05, 0.2571041054206291E-05, 0.5095987426708586E-01, 0.6829203137199389E-20, 0.1734538060272007E-04, 0.9160403953625247E-05, 0.4270469018444285E-01, 0.5620633949699709E-29, 0.1970936154220316E-07, 0.7875060113736862E-07, 0.6313950453962554E-02, 0.1074365444038600E-22, 0.1950342748319920E-02, 0.1960570817697857E-02, 0.4526318588114864E-04, 0.5045801736573469E-22, 0.2719687288170513E-02, 0.7229547441545878E-02}, + info: 0, + }, + { + z: []float64{0.6830594937182136E+00, 0.2806903427821971E+00, 0.3842580501524426E+00, 0.7113293946876786E+00, 0.6120481717427926E+00, 0.4087522624125913E+00, 0.2683959794755927E+00, 0.1982680719912362E+00, 0.5503761648124630E+00, 0.9947639519912582E+00, 0.4817851020535202E-01, 0.1841410650783141E+00, 0.7364485595361944E+00, 0.2204876163244174E+00, 0.8785531172976315E+00, 0.3900984044089164E+00, 0.9898399332392419E+00, 0.4652324815840650E+00, 0.6574114801218780E+00, 0.6641201888165797E+00, 0.5371222655177923E+00, 0.2241732155112269E+00, 0.6726821610374456E-01, 0.2361953456198683E+00, 0.5602287124209401E+00, 0.7836687903368798E+00, 0.2633616918428828E+00, 0.9669553142730151E+00, 0.3692579170869618E+00, 0.5395054150347700E-01, 0.4776047537674022E-01, 0.5691410116455676E+00, 0.1304181940038973E+00, 0.2107738642513712E+00, 0.5434523182333528E-01, 0.4019375962886824E+00, 0.7125153526157032E+00, 0.5305712841430671E+00, 0.1164846974244694E+00, 0.2037577925839799E+00, 0.2045617511271008E+00, 0.6122054957321945E+00, 0.5114531146106966E+00, 0.2882478115017332E+00, 0.5304873168821023E+00, 0.1796380649103803E+00, 0.9949092378946756E-01, 0.5448372048900864E+00, 0.1971761401002603E+00, 0.9487011110186927E+00, 0.8526405089060669E+00, 0.4533764477818548E+00, 0.8410819408489681E+00, 0.7592016862970913E+00, 0.8131142938762341E+00, 0.1445496351282255E+00, 0.6614974180377753E+00, 0.3394841721225367E+00, 0.4878107636737276E+00, 0.5499609605641745E+00, 0.1789798083030991E+00, 0.2008397619575961E+00, 0.5247567247775218E+00, 0.7394478154071386E+00, 0.6713478520024037E+00, 0.3894295843862983E+00, 0.9099978858741096E+00, 0.9872931573704680E-01, 0.5370559804237263E+00, 0.8492599321050560E+00, 0.4671993983916084E+00, 0.6397070306147701E+00, 0.2884512208824136E+00, 0.5002881141083532E+00, 0.3356213102526899E+00, 0.4102730364689955E+00, 0.8172446941984062E+00, 0.1463391840674726E+00, 0.6374760821459636E+00, 0.2986995049911381E+00, 0.6932950085590186E+00, 0.8475246239619540E+00, 0.3550038162879430E+00, 0.9747731646460122E+00}, + n: 21, + zOut: []float64{0.2302037253547019E+01, 0.1904432769194928E+01, 0.1838629010091233E+01, 0.1679631021950300E+01, 0.1638588328999231E+01, 0.1556939208705248E+01, 0.1154775776884602E+01, 0.1123025367728587E+01, 0.1005963210310813E+01, 0.7892040895461047E+00, 0.6171474041407791E+00, 0.5107385873854940E+00, 0.4745466376069911E+00, 0.2987072329916590E+00, 0.2518976395749056E+00, 0.1562926917018191E+00, 0.1208002043434920E+00, 0.1117929648180551E+00, 0.3025264937486962E-01, 0.5461437067005637E-02, 0.3901591662109151E-04, 0.2028008633963607E-17, 0.1197298285059118E-05, 0.1163352934520667E-05, 0.1154775776884602E+01, 0.2502221352972909E-22, 0.7438201518083012E-06, 0.8784873727121712E-06, 0.1123025367728587E+01, 0.2368236188315088E-19, 0.3676741199329849E-11, 0.3039307086935086E-11, 0.1005963210310813E+01, 0.2065553394230697E-24, 0.6686270095375819E-11, 0.8550052948388210E-11, 0.7892040895461047E+00, 0.1239058396467615E-20, 0.2067843352216928E-06, 0.6687212675645054E-07, 0.6171474041407791E+00, 0.2620094590259913E-21, 0.1757090250187976E+02, 0.1757090250187975E+02, 0.9500000000000000E+02, 0.2798185941043084E+01, 0.1052631578947368E+01, 0.6997553999213272E-08, 0.4745466376069911E+00, 0.5994838008700348E-24, 0.1052996378646298E-04, 0.6312169743031761E-04, 0.2987072329916590E+00, 0.9860761315262648E-30, 0.1466875513591431E-03, 0.1024839055944592E-03, 0.2518976395749056E+00, 0.7516632826070909E-17, 0.5524256710713082E-08, 0.1151290676113078E-07, 0.1562926917018191E+00, 0.1348952147927930E-27, 0.1222984298841777E-06, 0.3042067118561864E-06, 0.1208002043434920E+00, 0.4760428464210509E-23, 0.9492582004636672E-05, 0.3402727365723720E-04, 0.1117929648180551E+00, 0.7018716354804804E-22, 0.2431231599464108E-03, 0.1315672135071063E-03, 0.3025264937486962E-01, 0.4377821080194221E-21, 0.1333575496853992E-02, 0.6988231628130009E-03, 0.5461437067005637E-02, 0.2193916840728260E-24, 0.1845211740639344E-02, 0.8881725247692956E-03, 0.3901591662109151E-04, 0.2067951531382569E-23, 0.6469870796864946E-02, 0.1027022788337614E-01}, + info: 0, + }, + { + z: []float64{0.3270384527330652E+00, 0.4068565573647237E+00, 0.5445258191923925E+00, 0.9571802305689175E+00, 0.1840747434207346E-01, 0.8759261930487382E+00, 0.3018283835341639E+00, 0.4754674889513868E+00, 0.9620709342523251E+00, 0.3596342978433105E+00, 0.1820397917245298E+00, 0.9562190617892271E+00, 0.8004073710305811E+00, 0.9503584926946729E+00, 0.1634422399578277E+00, 0.3053134184266467E+00, 0.3871438286377282E+00, 0.1225252880124038E+00, 0.5955538022158587E+00, 0.9831372787057571E+00, 0.2130378801829313E+00, 0.1502296787149880E+00, 0.5120891507658710E+00, 0.2769158347903287E+00, 0.6740978559159013E+00, 0.6671510755324899E+00, 0.5252429573239310E+00, 0.7312875683466940E+00, 0.6359518339326128E+00, 0.3635213813950466E-01, 0.7509704695539338E+00, 0.2796455326190517E+00, 0.3929933998036216E+00, 0.2441550702438192E+00, 0.5181887041338979E+00, 0.2149631476903890E-01, 0.1922157358558590E+00, 0.8352708839021310E+00, 0.2143118694803675E+00, 0.8099207585987700E+00, 0.4013415573783083E+00, 0.8990854368069680E+00, 0.2274365144039603E-01, 0.1574221848735892E+00, 0.5021896402707141E+00, 0.6811320055313477E+00, 0.4008235511220088E+00, 0.2607115591315068E+00, 0.8396807341169598E+00, 0.3393611517447541E+00, 0.3095200315094494E+00, 0.8849677836408325E+00, 0.3309280721041051E+00, 0.2177939175852258E+00, 0.7396054658394657E-02, 0.5387313739545944E+00, 0.5592732178453728E+00, 0.4422242955757759E+00, 0.6010599951901635E+00, 0.2729214395073326E+00, 0.8861412244709392E+00, 0.3303460134234409E+00, 0.3230906405176623E+00, 0.5979281304041633E+00, 0.1747480524852378E+00, 0.5019201598522602E+00, 0.3041629115671023E+00, 0.7344252813174572E+00, 0.5145018596354390E+00, 0.7032668540687012E+00, 0.4542245378490408E+00, 0.6883469599293311E+00, 0.7365046871633816E+00, 0.6892200550994384E+00, 0.9612097768268251E+00, 0.3687306903044788E+00, 0.4902139977664450E+00, 0.4004732628576805E+00, 0.2121831569752699E+00, 0.3483027732062219E+00, 0.4140454821962284E+00, 0.5590476647584736E+00, 0.1191647727722587E+00, 0.7126611758207085E+00}, + n: 21, + zOut: []float64{0.2451808019367049E+01, 0.2128252216129400E+01, 0.1884015768998821E+01, 0.1793403527862625E+01, 0.1731698897481475E+01, 0.1605979322764491E+01, 0.1346135733575790E+01, 0.1222183737737495E+01, 0.1054517637460965E+01, 0.8541696661721662E+00, 0.8335553929836017E+00, 0.7643627371640215E+00, 0.6493538020248019E+00, 0.5117674171078171E+00, 0.4801902398267136E+00, 0.1830481952424627E+00, 0.1336751260833609E+00, 0.7548204386515513E-01, 0.4276641694583261E-01, 0.1152852330305948E-01, 0.4825291327526518E-04, 0.1046558665109411E-21, 0.5148060409033168E-10, 0.1742874021361670E-10, 0.1346135733575790E+01, 0.3944304526105059E-30, 0.1177385120842054E-08, 0.5739784145251797E-09, 0.1222183737737495E+01, 0.5228352308675503E-16, 0.2817945521555932E-11, 0.1891433639936970E-11, 0.1054517637460965E+01, 0.1775328283321620E-16, 0.9506244555381454E-11, 0.6780149876052939E-11, 0.8541696661721662E+00, 0.4289572169691169E-11, 0.3560204585171959E-10, 0.5552509181949502E-10, 0.8335553929836017E+00, 0.8925278809447169E-21, 0.1975794267501038E+02, 0.1975794267501038E+02, 0.9900000000000000E+02, 0.3029478458049887E+01, 0.2020202020202020E+01, 0.4057773458399609E-09, 0.6493538020248019E+00, 0.3196600703119960E-17, 0.4936238682205707E-06, 0.2172173957444601E-06, 0.5117674171078171E+00, 0.2475160268480207E-20, 0.1127880382626992E-04, 0.1031817493791828E-04, 0.4801902398267136E+00, 0.2327139670401985E-28, 0.8359957951383868E-05, 0.8045173068477057E-05, 0.1830481952424627E+00, 0.2763487036072314E-23, 0.1049648761427048E-04, 0.8607871065540926E-05, 0.1336751260833609E+00, 0.6392286336815055E-18, 0.5478798785309189E-04, 0.3178071334079827E-04, 0.7548204386515513E-01, 0.1886324196564483E-25, 0.4604839715747456E-05, 0.3206078546562559E-04, 0.4276641694583261E-01, 0.2130807968310579E-24, 0.2160396768988393E-02, 0.2401524776593251E-02, 0.1152852330305948E-01, 0.4597153189491485E-23, 0.1577121702032026E-02, 0.1548884890976950E-02, 0.4825291327526518E-04, 0.0000000000000000E+00, 0.1144436370534878E-01, 0.4805213857273134E-02}, + info: 0, + }, + { + z: []float64{0.1204296195656108E+00, 0.2644532009534747E+00, 0.2981945708465356E+00, 0.3379851046426219E-01, 0.5872157683391875E+00, 0.3661495849020495E+00, 0.2783310889774259E+00, 0.8471009797765506E+00, 0.6087926721027869E+00, 0.7227374835926721E+00, 0.1157491272838733E+00, 0.5565144099551486E+00, 0.8949691253636921E+00, 0.4271566773654165E+00, 0.6387841251831913E+00, 0.3125047228733280E-01, 0.2092736013478247E-01, 0.9188324418961444E+00, 0.2275180796997284E+00, 0.4519662960462961E+00, 0.1155877493866434E+00, 0.3574940735178409E+00, 0.1489772525039219E+00, 0.3847908470095970E+00, 0.4780110568180811E+00, 0.3489586723075616E+00, 0.2559758537216194E+00, 0.7015930720521131E+00, 0.6512181083044030E+00, 0.1619173394771481E+00, 0.5094142654629881E+00, 0.9037662631759247E+00, 0.8829671919577533E+00, 0.5739200804260277E+00, 0.6584413366512047E+00, 0.7174965427568090E+00, 0.2705911606916550E+00, 0.6519148889036277E+00, 0.8284421625450799E+00, 0.1417109678591228E+00, 0.8472265674806589E-01, 0.3638971914001953E+00, 0.8802661885427909E-01, 0.5730596475071164E+00, 0.6156880168413905E+00, 0.3769532609458294E+00, 0.6302840487845919E+00, 0.8652028697564479E+00, 0.5886269364510055E-01, 0.9901772381773877E-01, 0.9679961670969370E+00, 0.9025028618130532E+00, 0.2858592550914936E+00, 0.4523960301168739E-01, 0.9961073801516410E+00, 0.5404176614913075E+00, 0.2161216977420954E+00, 0.6517643909270738E+00, 0.1408193879882935E-01, 0.2323315528058443E+00, 0.4040647670376405E+00, 0.5063393857452272E+00, 0.2149141182072994E+00, 0.8405813011731451E+00, 0.8044826512704509E+00, 0.5364711289689184E+00, 0.2922476360373625E+00, 0.9518940562302493E+00, 0.1980063292193738E+00, 0.6243757640305569E-01, 0.3641799792979717E+00, 0.4781083740929701E+00, 0.3488268687432241E+00, 0.8284107864073382E+00, 0.5855039308834178E+00, 0.2593007284605915E+00, 0.9998845891621441E+00, 0.5048349794999019E+00, 0.5828201446782487E+00, 0.8921301000231074E+00, 0.2672402237051515E+00, 0.3352853759971494E+00, 0.5977528180071631E+00, 0.1151194604047919E+00}, + n: 21, + zOut: []float64{0.2557315455353142E+01, 0.2083235685800309E+01, 0.1875944452104717E+01, 0.1852714062580819E+01, 0.1643995946812320E+01, 0.1314218355716144E+01, 0.1293789198407225E+01, 0.1108624029644386E+01, 0.1060866236520538E+01, 0.6893140608436983E+00, 0.6265017468006577E+00, 0.6169803536834606E+00, 0.4472638275156540E+00, 0.3909824987049766E+00, 0.2990543016857948E+00, 0.1644755201813542E+00, 0.1145158516686298E+00, 0.6240413476421734E-01, 0.2540980528285533E-01, 0.1114684260186565E-01, 0.3077034058364147E-04, 0.1514612938024343E-27, 0.1068838715614041E-10, 0.1816953714834036E-10, 0.1293789198407225E+01, 0.1634858280249726E-16, 0.1546152805249061E-09, 0.7139985980503436E-10, 0.1108624029644386E+01, 0.1852295205932338E-17, 0.2931760870340471E-08, 0.5717158524063146E-08, 0.1060866236520538E+01, 0.1656986554198631E-24, 0.3897819821179759E-07, 0.2050786216968739E-07, 0.6893140608436983E+00, 0.1054613376713825E-21, 0.1114796130440952E-06, 0.1754727955273104E-06, 0.6265017468006577E+00, 0.0000000000000000E+00, 0.1823878313701335E+02, 0.1823878313701335E+02, 0.1020000000000000E+03, 0.3172335600907029E+01, 0.3921568627450980E+01, 0.4944285541926277E-08, 0.4472638275156540E+00, 0.7188113412291574E-19, 0.5360570179815202E-09, 0.5055207828345367E-09, 0.3909824987049766E+00, 0.7011182861561962E-17, 0.5424596001050196E-08, 0.1149191082508281E-07, 0.2990543016857948E+00, 0.1397964075969312E-24, 0.2148922978775398E-05, 0.1039924072201963E-05, 0.1644755201813542E+00, 0.1424715207546021E-19, 0.1286356681922344E-03, 0.6709371685087021E-04, 0.1145158516686298E+00, 0.1923558431290915E-24, 0.1040681698574874E-03, 0.9690504707177204E-04, 0.6240413476421734E-01, 0.3021337266996475E-27, 0.3740811812377314E-06, 0.8725750691496404E-06, 0.2540980528285533E-01, 0.6622271595176623E-28, 0.2937391640354928E-03, 0.1148070460566611E-03, 0.1114684260186565E-01, 0.3845696912952433E-29, 0.9582588059437623E-03, 0.1284334386264186E-02, 0.3077034058364147E-04, 0.1610185014413679E-23, 0.1713355521956925E-01, 0.1560043716021792E-01}, + info: 0, + }, + { + z: []float64{0.6550531738065145E+00, 0.9006303757888976E+00, 0.9204609778380736E+00, 0.4658341923257867E+00, 0.5436644687290008E+00, 0.2908556755036122E+00, 0.1209811495723523E+00, 0.6227378829506942E+00, 0.3843019792679099E+00, 0.4431829610151485E+00, 0.4903210952175132E+00, 0.4210264133022774E+00, 0.3200750839632230E+00, 0.2252794777033682E+00, 0.5128630958928748E-01, 0.5136099492114639E+00, 0.4906286803922755E+00, 0.1747340137845675E+00, 0.6367238354860758E+00, 0.7515407582129341E+00, 0.4275500565044866E+00, 0.2014278558825494E+00, 0.7137603260056157E+00, 0.8686875192977085E+00, 0.7169591605793454E+00, 0.9050302202813415E+00, 0.9899533400874350E-01, 0.9969046692447475E+00, 0.6121260436585757E+00, 0.6518683331715626E+00, 0.5607404970528083E+00, 0.4000687152662108E-03, 0.1221862374388689E+00, 0.4484923714483016E+00, 0.4074629631039243E+00, 0.2322333097032281E-01, 0.4732551077558298E+00, 0.7342979327909982E+00, 0.3458749207719752E+00, 0.7729568887054280E+00, 0.2047858477824707E+00, 0.7991048365911296E+00, 0.5370237056253078E+00, 0.2233168849800682E-01, 0.5135288197983614E+00, 0.9129664417816657E+00, 0.9407166870649586E+00, 0.4321958081203685E+00, 0.5563774896630214E-01, 0.9494906037764664E+00, 0.9674063566885983E+00, 0.2302624676329315E+00, 0.1506811640032519E+00, 0.4445855507514112E+00, 0.6038782945102905E-01, 0.4499742519338505E+00, 0.1940991655604004E+00, 0.6493052482066142E-01, 0.2902929850901331E+00, 0.2876163569026815E+00, 0.9140475482126542E+00, 0.7006705577674063E+00, 0.2819386709216735E+00, 0.9125816873773608E+00, 0.9433170896498744E-01, 0.1632821600392161E+00, 0.3150556796654537E+00, 0.4051206017420083E+00, 0.2687493393481850E+00, 0.5768057516945001E+00, 0.4306858988251338E+00, 0.3827211690774009E+00, 0.3593520435650671E+00, 0.5610694397953092E+00, 0.7151178950427733E+00, 0.7138830385076256E-01, 0.5281951083990266E-01, 0.4880677722651299E+00, 0.9334247489037772E+00, 0.6764242544288053E+00, 0.8551178347453967E+00, 0.1876923010834376E+00, 0.7408118952029578E+00, 0.7967219280126981E+00}, + n: 21, + zOut: []float64{0.2493394334366539E+01, 0.2460477172068809E+01, 0.2083159145455880E+01, 0.1779228959307519E+01, 0.1724095029781113E+01, 0.1560812668654360E+01, 0.1120482054552078E+01, 0.1088744749350826E+01, 0.9613598859526896E+00, 0.9456175481954929E+00, 0.9119552728538921E+00, 0.7767939725863090E+00, 0.6893167116879397E+00, 0.4408717103973492E+00, 0.2706330695081346E+00, 0.2343515836463984E+00, 0.6795401725828518E-01, 0.6600498464192311E-01, 0.2004873521291848E-01, 0.1421097732958122E-01, 0.4015560238058376E-03, 0.2226481018895784E-25, 0.2564499425740104E-12, 0.2658329977886514E-12, 0.1120482054552078E+01, 0.4315813836253463E-23, 0.1335501643346940E-12, 0.1368307862991113E-12, 0.1088744749350826E+01, 0.3926080427856238E-18, 0.1185565636052547E-12, 0.1214013431095007E-12, 0.9613598859526896E+00, 0.2719992401202049E-26, 0.9906513980413714E-13, 0.1012398200894782E-12, 0.9456175481954929E+00, 0.3937993638863291E-26, 0.9389079133840153E-13, 0.9189527811944332E-13, 0.9119552728538921E+00, 0.1580250204306566E-21, 0.1970991413883184E+02, 0.1970991413883184E+02, 0.1080000000000000E+03, 0.3401360544217687E+01, 0.8333333333333334E+01, 0.6496201881821226E-13, 0.6893167116879397E+00, 0.2040319821514109E-19, 0.6886568712781699E-13, 0.6342531805840532E-13, 0.4408717103973492E+00, 0.9116462109840799E-16, 0.6575726430673280E-12, 0.1146915438924438E-11, 0.2706330695081346E+00, 0.6100742213737356E-14, 0.5548784478521690E-10, 0.9411844035493366E-10, 0.2343515836463984E+00, 0.2464780121144947E-24, 0.1267470050081896E-08, 0.7549586177318002E-09, 0.6795401725828518E-01, 0.6058451752097371E-27, 0.2494439518946058E-07, 0.4030144639288306E-07, 0.6600498464192311E-01, 0.1931466728993349E-20, 0.1742718098912744E-06, 0.1063050845015484E-06, 0.2004873521291848E-01, 0.2078695185822955E-22, 0.1365398583912438E-05, 0.6056776980192580E-06, 0.1421097732958122E-01, 0.3944304526105059E-30, 0.8436693551699617E-06, 0.8772483974218289E-06, 0.4015560238058376E-03, 0.5424456586666688E-20, 0.1372662528173007E-02, 0.2323379424199439E-03}, + info: 0, + }, + { + z: []float64{0.5955158028190186E+00, 0.9601282390728449E-01, 0.2944266054820921E+00, 0.3924250378682403E+00, 0.4462256781176310E-01, 0.5690757232665151E+00, 0.7855339329019884E-01, 0.8681545225840360E+00, 0.7288006955920397E+00, 0.2963229749240101E+00, 0.2728029241156386E+00, 0.4237536504971896E+00, 0.9003368942847588E+00, 0.7357957067011865E+00, 0.4901129309073038E-01, 0.4716171621744532E+00, 0.4890099406800087E+00, 0.3570165784460172E+00, 0.7160897857565474E-01, 0.6109824519907316E+00, 0.1221913259189585E+00, 0.1847302629402909E+00, 0.4009366884871202E-01, 0.9703472440233364E+00, 0.6369052870991366E+00, 0.5580400433416689E+00, 0.9024815855223057E+00, 0.1227045689636573E+00, 0.9668897094172768E+00, 0.5989409973498315E+00, 0.9709139844325040E+00, 0.9532564522700616E+00, 0.6239574483953332E+00, 0.7056703505253071E+00, 0.9506691238320553E-01, 0.7998586962365666E+00, 0.6556519136464994E+00, 0.4181856697120553E+00, 0.9478314170226607E+00, 0.3832663309972284E-01, 0.4257218688507075E+00, 0.2049443327129853E+00, 0.9168853967010917E+00, 0.5423988966788751E-02, 0.3002879152136316E+00, 0.7743151012217909E+00, 0.5154350917338609E+00, 0.9658560730800175E+00, 0.6314599250676610E+00, 0.5584937104443134E+00, 0.4741445335250092E+00, 0.3157508358915576E+00, 0.4349529093465575E+00, 0.7860003715032308E+00, 0.8695087804152180E-02, 0.3920445280700808E+00, 0.3765485221235618E+00, 0.4334604109656897E+00, 0.1636117026415890E+00, 0.3006093728066712E+00, 0.2129148932459900E+00, 0.3092975700919495E+00, 0.1986761620686717E-01, 0.9075541031649185E+00, 0.9781911433730479E+00, 0.6945955075731600E+00, 0.9959584477684137E+00, 0.7505944883792014E+00, 0.7627854018352902E+00, 0.1267035334952504E+00, 0.8056780234474171E+00, 0.4507060196586773E+00, 0.1799397964631048E+00, 0.7554691089798000E+00, 0.3012534688386570E+00, 0.9612172487804931E+00, 0.4056708256608614E+00, 0.6648221051068217E+00, 0.1966051207552482E+00, 0.6661008672469584E+00, 0.6875730168317549E+00, 0.9591133633640367E+00, 0.8995318056907078E+00, 0.1435403265941513E+00}, + n: 21, + zOut: []float64{0.2826953331143077E+01, 0.2184946373215138E+01, 0.2011432985807930E+01, 0.1983939371799505E+01, 0.1783403572375380E+01, 0.1527291743334771E+01, 0.1218359458122959E+01, 0.1031625203087357E+01, 0.9141017580644314E+00, 0.8935891545682184E+00, 0.7995009441187808E+00, 0.6760292370761557E+00, 0.5375939998175604E+00, 0.5031272745805969E+00, 0.4136950654384539E+00, 0.4077555149266558E+00, 0.1977184484214556E+00, 0.1172157517521918E+00, 0.4197144528461013E-01, 0.1336078057720851E-01, 0.3545889291755145E-06, 0.2544082546855865E-16, 0.2583036406189355E-05, 0.3206950450307273E-05, 0.1218359458122959E+01, 0.6512835633504673E-25, 0.5241867641497365E-06, 0.5644106780290774E-06, 0.1031625203087357E+01, 0.0000000000000000E+00, 0.4305359229680111E-07, 0.8271940560154021E-07, 0.9141017580644314E+00, 0.0000000000000000E+00, 0.3911233321019150E-06, 0.2241550799736728E-06, 0.8935891545682184E+00, 0.2385737520619250E-22, 0.4206034452718400E-11, 0.9899461762377114E-11, 0.7995009441187808E+00, 0.9331359083488707E-16, 0.2008361176810137E+02, 0.2008361176810137E+02, 0.1130000000000000E+03, 0.3444444444444445E+01, 0.6194690265486726E+01, 0.1651034509856568E-04, 0.5375939998175604E+00, 0.1421716677825516E-23, 0.1528222338287967E-04, 0.2433829126418849E-04, 0.5031272745805969E+00, 0.6632003279205155E-19, 0.4757657931696731E-05, 0.2751276356124619E-05, 0.4136950654384539E+00, 0.1680371209901916E-16, 0.1318069984220972E-06, 0.1659409431372840E-06, 0.4077555149266558E+00, 0.2554525986432683E-22, 0.5944173486813264E-06, 0.1429245864393051E-05, 0.1977184484214556E+00, 0.1494891415393817E-27, 0.8465737022131437E-03, 0.4160790916597339E-03, 0.1172157517521918E+00, 0.6780166836549887E-20, 0.3655496023749206E-04, 0.5562211290196199E-04, 0.4197144528461013E-01, 0.1803076020780872E-22, 0.2337686132102848E-02, 0.5241185550833300E-02, 0.1336078057720851E-01, 0.3234329711406148E-27, 0.6369386968947829E-02, 0.2727172056719641E-02, 0.3545889291755145E-06, 0.0000000000000000E+00, 0.6135698199493001E-02, 0.4453215245051444E-02}, + info: 0, + }, + { + z: []float64{0.5256994769563229E+00, 0.4751970954150097E+00, 0.5550798296722601E+00, 0.3565746805143110E+00, 0.3971523551134015E-01, 0.7088262788771817E+00, 0.6369448567868402E+00, 0.6372974860231623E+00, 0.5963599363854956E+00, 0.7996832763398349E+00, 0.7266271077857295E+00, 0.3813393981851099E+00, 0.8884393254050771E-01, 0.8685934834267716E+00, 0.3797066359545181E+00, 0.4541910736411658E+00, 0.6285354031372432E+00, 0.5295256159852654E+00, 0.8908170817260027E+00, 0.5793264969983637E+00, 0.6056871126785802E+00, 0.6045507124525907E+00, 0.9734230310286895E-01, 0.9482358811543057E+00, 0.8804820874856442E+00, 0.4472263119108183E+00, 0.5843860139759072E+00, 0.5372922689923049E+00, 0.5799351791336661E+00, 0.5116182356749631E+00, 0.3816355069915517E+00, 0.6475808331559241E+00, 0.8746013736579017E-02, 0.8411650861050215E+00, 0.2992737481736951E-01, 0.6246901010621124E+00, 0.3123078564554325E+00, 0.7411164234121632E+00, 0.5960432842954070E+00, 0.8102594121204127E+00, 0.3552957522458323E+00, 0.6235337320803771E+00, 0.5962195242077326E+00, 0.4845790335098474E+00, 0.4045953379382708E+00, 0.2452522545656534E+00, 0.2743318280596185E+00, 0.2023077390748810E+00, 0.4206973723636350E+00, 0.4039949452544738E+00, 0.9114680949622015E+00, 0.7779482986378454E+00, 0.6812819304160683E+00, 0.5580962104642140E-01, 0.4287711156774094E+00, 0.9817581515129085E+00, 0.4431516884275333E+00, 0.6237912221093689E-01, 0.8364254576520689E+00, 0.8759899245723605E+00, 0.8787473635901457E+00, 0.4702211826699049E+00, 0.8284521047414805E+00, 0.2041855966018515E+00, 0.8060130309143703E+00, 0.5501723689038956E+00, 0.2188842792675016E-01, 0.5672241818001204E+00, 0.6450459353754012E+00, 0.2431902854401001E+00, 0.5193698672717711E+00, 0.1962120228423043E+00, 0.6361488000943472E-01, 0.5342761659162559E+00, 0.1758994081846166E-01, 0.7459187699999678E+00, 0.5953394313659540E+00, 0.9379918174958790E+00, 0.4032831592210619E+00, 0.7704238877222783E+00, 0.9410981148731864E+00, 0.8355998775704846E+00, 0.7904637124553195E+00, 0.4324126135288506E+00}, + n: 21, + zOut: []float64{0.2360605380677641E+01, 0.2349812365456326E+01, 0.2259072978559188E+01, 0.2074669549844899E+01, 0.1734529465065066E+01, 0.1635336277856887E+01, 0.1535245292061319E+01, 0.1453596007978833E+01, 0.1156130097482147E+01, 0.1084746900314168E+01, 0.1034520391904089E+01, 0.8201881896309742E+00, 0.6191782955028541E+00, 0.5267433243518804E+00, 0.4355086546946592E+00, 0.4155619327338856E+00, 0.3396295360604018E+00, 0.9317218785919168E-01, 0.5773665727788814E-01, 0.1842462732727454E-01, 0.2018232369069597E-07, 0.4517585523147273E-24, 0.2167663685989129E-10, 0.1523023581682742E-10, 0.1535245292061319E+01, 0.1340432450151543E-25, 0.8069500146896454E-10, 0.1279555645700667E-09, 0.1453596007978833E+01, 0.6673291668607916E-16, 0.1337219714947293E-07, 0.4537550993048733E-08, 0.1156130097482147E+01, 0.2388039732285047E-25, 0.6170125127971897E-05, 0.1353762614268721E-04, 0.1084746900314168E+01, 0.3862470231561244E-18, 0.2338329578753200E-04, 0.2318969913953679E-04, 0.1034520391904089E+01, 0.6409494854920721E-30, 0.2200440813282189E+02, 0.2200440813282190E+02, 0.9400000000000000E+02, 0.2857142857142857E+01, 0.0000000000000000E+00, 0.2156912239043876E-04, 0.6191782955028541E+00, 0.4311940021813490E-19, 0.2098085305628239E-04, 0.2047701462113856E-04, 0.5267433243518804E+00, 0.7292491488692259E-18, 0.2483658471590867E-04, 0.2278231239253353E-04, 0.4355086546946592E+00, 0.6335396825622830E-16, 0.5560492899787359E-04, 0.8068766398366361E-04, 0.4155619327338856E+00, 0.7336406418555410E-28, 0.3220618566867426E-03, 0.1956958209756436E-03, 0.3396295360604018E+00, 0.1297676189088564E-27, 0.4121897802138222E-02, 0.2587205720417875E-02, 0.9317218785919168E-01, 0.7651950780643815E-28, 0.2826512581544380E-02, 0.2814359488753958E-02, 0.5773665727788814E-01, 0.4923437167052441E-21, 0.1821079370679042E-04, 0.2969056479875054E-04, 0.1842462732727454E-01, 0.4842851680813876E-21, 0.4217326450522519E-02, 0.5738852897157041E-02, 0.2018232369069597E-07, 0.2018232369069597E-07, 0.3702854219118327E-02, 0.7091388009151286E-02}, + info: 0, + }, + { + z: []float64{0.5196081465664333E+00, 0.1450873999446859E+00, 0.1902498073897446E+00, 0.9459083122514356E-01, 0.6971960507146802E-01, 0.2126447963850432E+00, 0.1693138701795316E-01, 0.6615449591751588E-01, 0.6671851537110856E+00, 0.7116922416084167E+00, 0.7735840319989629E+00, 0.8593705742984634E+00, 0.6060015557980403E+00, 0.1071620560007485E+00, 0.6056582690297291E+00, 0.2064801115284116E+00, 0.4992099275808294E+00, 0.9056413330105546E+00, 0.6051575714193578E+00, 0.1395071235858423E+00, 0.3386142237730057E+00, 0.2065895571122717E+00, 0.2774285740015214E-01, 0.4649920904615868E+00, 0.9062834189437683E+00, 0.3022801499192989E+00, 0.2125071125007829E+00, 0.2366624610094756E+00, 0.3232052419625674E+00, 0.5879745505340277E+00, 0.3212955913685801E+00, 0.9110441809347004E+00, 0.2144184579231917E+00, 0.5617161155671668E-01, 0.9725855527757206E+00, 0.9798782363582490E+00, 0.9666637418953663E+00, 0.1842420381101751E+00, 0.9810363127661145E+00, 0.4061071205983764E+00, 0.4929437214282740E+00, 0.3087398230344144E+00, 0.8692083335886002E+00, 0.7401065606674918E+00, 0.6829833274325647E+00, 0.9797795404622264E+00, 0.6101846761247042E+00, 0.7796537878703258E+00, 0.4568641605073986E-01, 0.1752946998854403E+00, 0.7558659638245062E+00, 0.4081915619381170E+00, 0.5344465439920063E+00, 0.3199118710728778E+00, 0.3613720388280138E+00, 0.1409062127217534E+00, 0.2811520826338662E+00, 0.9462348779627723E+00, 0.4911007415294493E+00, 0.2488061765237712E+00, 0.1661818317483100E+00, 0.1203910774987040E+00, 0.4544163143251944E+00, 0.8767242907488393E+00, 0.6688224142601292E+00, 0.2497550267789769E+00, 0.2658845545571695E+00, 0.4072601097670568E+00, 0.5517137496493807E+00, 0.4206663434956901E+00, 0.3655154771809294E+00, 0.6509199815744504E-01, 0.6480911975614350E+00, 0.1271267318339999E+00, 0.8874102966539428E+00, 0.9607257650026479E+00, 0.8902777005093224E+00, 0.7074702462790970E+00, 0.5045879991550398E+00, 0.3357826713243962E+00, 0.9303671751018463E+00, 0.3667268693834904E+00, 0.7709773173263057E+00, 0.1274123220614284E+00}, + n: 21, + zOut: []float64{0.2669666350125788E+01, 0.2458073928301015E+01, 0.1960648799383531E+01, 0.1674511937828339E+01, 0.1629444569956276E+01, 0.1605168511500282E+01, 0.1169506153633164E+01, 0.8378899015114316E+00, 0.8214470290652885E+00, 0.7290022816300561E+00, 0.5956393798847858E+00, 0.5147057006185641E+00, 0.3415078453317431E+00, 0.3316800239182673E+00, 0.2245847640277715E+00, 0.1981086483360383E+00, 0.1729134064527326E+00, 0.1081292683666610E+00, 0.4856623040087921E-01, 0.2705373732739987E-02, 0.9745444154776346E-03, 0.7298616502634276E-19, 0.4601636530183765E-14, 0.3001385089664378E-13, 0.1169506153633164E+01, 0.5522026336547083E-28, 0.9439817212889541E-12, 0.1534086358433234E-11, 0.8378899015114316E+00, 0.7174347921301560E-11, 0.1095021852663145E-10, 0.1580074435702411E-10, 0.8214470290652885E+00, 0.3131705799125763E-20, 0.2247124942125492E-10, 0.3228253356903498E-10, 0.7290022816300561E+00, 0.6063934311659721E-18, 0.3794147471177530E-13, 0.3318524623173314E-12, 0.5956393798847858E+00, 0.3765687391680646E-13, 0.1809487464842083E+02, 0.1809487464842083E+02, 0.1050000000000000E+03, 0.3215419501133787E+01, 0.3809523809523809E+01, 0.2077325438490571E-07, 0.3415078453317431E+00, 0.1645262238367970E-20, 0.7912752069326401E-07, 0.6053132028546428E-07, 0.3316800239182673E+00, 0.4184118241292247E-26, 0.1343987419983520E-06, 0.1754397466154310E-06, 0.2245847640277715E+00, 0.3340387958036406E-22, 0.6150231447604006E-06, 0.4780001259056422E-06, 0.1981086483360383E+00, 0.1070733604161610E-20, 0.1003229473607176E-05, 0.1287291281183416E-05, 0.1729134064527326E+00, 0.1298955481663118E-20, 0.1611116216931278E-05, 0.3807035614938680E-06, 0.1081292683666610E+00, 0.4901279578837721E-23, 0.3565927169328702E-03, 0.2312261838015572E-03, 0.4856623040087921E-01, 0.3325573155747123E-13, 0.4389787505319806E-03, 0.9715248586459800E-03, 0.2705373732739987E-02, 0.1348432029845013E-20, 0.7371401467208961E-04, 0.2975668602269332E-04, 0.9745444154776346E-03, 0.4135903062570168E-24, 0.7273370201297700E-04, 0.3602244970122637E-04}, + info: 0, + }, + { + z: []float64{0.3441168249350421E+00, 0.7064572711980356E+00, 0.6589781374655990E+00, 0.8687841598825752E+00, 0.7811747459515918E+00, 0.7470750719206745E+00, 0.7591454338662803E+00, 0.7956934079357347E-01, 0.3416983743372617E+00, 0.3365394610260509E+00, 0.8635365040683821E+00, 0.4793906833418223E+00, 0.9394584418725971E+00, 0.7354375226759881E+00, 0.3959912256877245E+00, 0.4088558388864650E+00, 0.6899389113237457E+00, 0.6329180251180861E+00, 0.6760812245614891E+00, 0.1743991444245150E+00, 0.3881927716152306E+00, 0.2103848624556167E+00, 0.5309784956583943E+00, 0.5758384660199964E+00, 0.6542468116269122E+00, 0.2141275453071043E+00, 0.4917208240158387E+00, 0.6996271491850585E+00, 0.7074081025976766E+00, 0.1896811377589238E+00, 0.4872676647104760E+00, 0.8987347035581787E+00, 0.1651654313203957E+00, 0.7969431328829826E+00, 0.8979672856778195E+00, 0.2621352236509209E+00, 0.2994430908669790E+00, 0.8412000921937168E+00, 0.6910228781616401E-01, 0.9849719192333963E+00, 0.2835195798153757E+00, 0.6126955834278749E+00, 0.9957514180764350E+00, 0.4133859474205875E+00, 0.2126790023013077E+00, 0.9230696247878700E-01, 0.5165813646587417E+00, 0.9232126059423650E+00, 0.6160486127374017E+00, 0.5529065454633691E+00, 0.6862175458708878E+00, 0.2677675454795836E-01, 0.6729513992144193E+00, 0.8612993184178528E+00, 0.5455358966165057E+00, 0.2518716982253303E+00, 0.5312849864208884E+00, 0.7551228210749875E+00, 0.1095520838657484E+00, 0.8767983608629261E+00, 0.9578119141004069E+00, 0.6878921114137557E+00, 0.2890574974795965E+00, 0.9851780344062913E+00, 0.9392886821673129E+00, 0.4125982690623264E+00, 0.6817912182549608E+00, 0.7805388095263401E+00, 0.1567802887930034E+00, 0.1901362770322003E+00, 0.5155717108920093E+00, 0.5470641908290981E+00, 0.9496522047623522E+00, 0.4367251554723609E+00, 0.7016249991347693E+00, 0.6652534390290816E+00, 0.3892590437090979E+00, 0.1464591367640408E+00, 0.9179795596761495E+00, 0.1527313083317114E+00, 0.8661173016992874E+00, 0.8044520995141484E+00, 0.4399581275677011E+00, 0.6590078920726725E+00}, + n: 21, + zOut: []float64{0.2654671686308588E+01, 0.2409077903364995E+01, 0.2090082174851482E+01, 0.1940605709090538E+01, 0.1909776782011245E+01, 0.1629990303184568E+01, 0.1566043989638403E+01, 0.1473218419964192E+01, 0.1321200673977518E+01, 0.1275771383585936E+01, 0.9826159405158056E+00, 0.8184731809209335E+00, 0.6715230178331039E+00, 0.5669018352800101E+00, 0.3641671875118937E+00, 0.2699135892930649E+00, 0.1446269090001342E+00, 0.8937359624216266E-01, 0.5860931848549461E-01, 0.3094108728329079E-01, 0.6182329613034853E-03, 0.9233403587623171E-22, 0.2552413399194827E-12, 0.1309204970235786E-12, 0.1566043989638403E+01, 0.2003762315848454E-18, 0.9222125989396634E-12, 0.1831545934750265E-11, 0.1473218419964192E+01, 0.1899959664962892E-11, 0.5682525570474145E-10, 0.1113952503246639E-09, 0.1321200673977518E+01, 0.5311918312726658E-16, 0.2115322762070563E-08, 0.1208354514490733E-08, 0.1275771383585936E+01, 0.1424261829852281E-16, 0.6059411460508015E-08, 0.1032477558436010E-07, 0.9826159405158056E+00, 0.5397353496908506E-22, 0.2226820292130466E+02, 0.2226820292130466E+02, 0.9500000000000000E+02, 0.2927437641723356E+01, 0.1052631578947368E+01, 0.2555943178691847E-06, 0.6715230178331039E+00, 0.1218922493912602E-18, 0.4789189736721279E-06, 0.5466231772857101E-06, 0.5669018352800101E+00, 0.1893266172530428E-27, 0.9952011217509916E-06, 0.1128113648538554E-05, 0.3641671875118937E+00, 0.1993230626440035E-24, 0.2427606592544749E-05, 0.2156829827516489E-05, 0.2699135892930649E+00, 0.2761013168273541E-29, 0.3900010091178873E-05, 0.3393761026267541E-05, 0.1446269090001342E+00, 0.2150416673893778E-15, 0.8242388755752233E-05, 0.1105863902029246E-04, 0.8937359624216266E-01, 0.2934562567422164E-27, 0.3455780897358792E-04, 0.2250328346305790E-04, 0.5860931848549461E-01, 0.8147325136863849E-21, 0.2346512312055719E-04, 0.8962661529405173E-05, 0.3094108728329079E-01, 0.2460979885389816E-17, 0.5238375287742530E-03, 0.1080192509223090E-02, 0.6182329613034853E-03, 0.8383483586160605E-23, 0.7400552677463828E-02, 0.1581674273722876E-01}, + info: 0, + }, + { + z: []float64{0.7940281584071446E+00, 0.8540600349699839E+00, 0.8158431165852809E-01, 0.5431841788581357E+00, 0.3696613346727944E+00, 0.2343742079469738E+00, 0.4891909888056500E-01, 0.6769876984160987E+00, 0.4777767465052760E+00, 0.1867381312399053E+00, 0.2018744873845245E+00, 0.5511201479607295E+00, 0.6938788283912793E+00, 0.8167542438070282E+00, 0.7904606414789531E+00, 0.9443564310071292E+00, 0.7287247677237652E-01, 0.8645122013586991E+00, 0.1884651475116826E+00, 0.3844755283611681E+00, 0.9959264361467982E+00, 0.6424370932833342E+00, 0.1972122925077952E+00, 0.2842024247377670E+00, 0.9819646913482807E+00, 0.9118347224008859E+00, 0.8184691845197246E+00, 0.7051587281589254E+00, 0.7604703230109544E+00, 0.6312964755149379E+00, 0.5240863862347888E+00, 0.3442050916384676E-01, 0.2415614308212055E+00, 0.2814868323669945E+00, 0.6529284673126197E+00, 0.3727305084153835E+00, 0.5033733868757848E+00, 0.2317122058804952E+00, 0.7555584130128312E+00, 0.5854566742645219E+00, 0.5481204696337160E+00, 0.8479425268049923E+00, 0.2310874615764000E+00, 0.1250993726775007E-01, 0.6243285982203539E-01, 0.8533587246073391E+00, 0.9203815588639257E+00, 0.9256849509751471E+00, 0.6691405057262187E+00, 0.8847091531299658E+00, 0.6783572983386376E+00, 0.4701257141291857E+00, 0.8976078424378102E+00, 0.8575018884445876E+00, 0.4119363561363949E+00, 0.2824477027676924E+00, 0.2787507690368071E+00, 0.7994878185780909E+00, 0.6141832897278305E+00, 0.6772728066124333E+00, 0.1568652581579784E+00, 0.8025492691231176E+00, 0.2609459151100056E+00, 0.4956700691019098E+00, 0.1008839464621498E+00, 0.6129709499983976E+00, 0.4551038858718992E-02, 0.8382785474023564E+00, 0.9327452694814308E+00, 0.9710431593941808E+00, 0.3785578217695214E+00, 0.9620839159000718E+00, 0.3183561960196257E-01, 0.9167635157854341E+00, 0.8989971039988554E+00, 0.2723769512210017E-01, 0.4176537489735596E+00, 0.9619881273217982E+00, 0.8761769579995293E+00, 0.6385245520487358E+00, 0.6821739872929905E+00, 0.3927943300877799E+00, 0.3299501391296433E-01, 0.6026481165267817E+00}, + n: 21, + zOut: []float64{0.2841529467847260E+01, 0.2556740368064117E+01, 0.2029069210305357E+01, 0.1816492749229813E+01, 0.1807397947918166E+01, 0.1724050761249482E+01, 0.1394683696862690E+01, 0.1363282300837870E+01, 0.1235317529564993E+01, 0.1007821728138393E+01, 0.9728972767837659E+00, 0.8110838192609224E+00, 0.6190683239156912E+00, 0.3314348466978195E+00, 0.2969816495631171E+00, 0.2506421226611442E+00, 0.1551624233480766E+00, 0.1141049603637759E+00, 0.6806098279643324E-01, 0.4065442795375918E-01, 0.1509783792061944E-04, 0.2745446733802996E-19, 0.2334033424405603E-14, 0.7232047343832039E-15, 0.1394683696862690E+01, 0.7652022750203868E-17, 0.1502464319787860E-09, 0.5990324067027169E-10, 0.1363282300837870E+01, 0.5511008105786353E-19, 0.1215529748555577E-07, 0.3576186028975079E-08, 0.1235317529564993E+01, 0.6271335389136957E-17, 0.2589527811059762E-05, 0.3563684464760320E-05, 0.1007821728138393E+01, 0.6928731028484552E-15, 0.2286607739649456E-04, 0.2916328836696281E-04, 0.9728972767837659E+00, 0.4013724285764508E-25, 0.2143649169120057E+02, 0.2143649169120056E+02, 0.1080000000000000E+03, 0.3174603174603174E+01, 0.5555555555555555E+01, 0.5006788488237952E-04, 0.6190683239156912E+00, 0.1272779738919789E-24, 0.5392273695714327E-05, 0.6586751690782050E-05, 0.3314348466978195E+00, 0.9952016744778614E-24, 0.4588114650322476E-05, 0.4104030919118472E-05, 0.2969816495631171E+00, 0.1254277227268884E-20, 0.1579210272170037E-05, 0.2523508055026877E-05, 0.2506421226611442E+00, 0.1514835081255253E-22, 0.9117975197333799E-05, 0.1415311657319248E-04, 0.1551624233480766E+00, 0.3272195034856757E-26, 0.3128414626489953E-04, 0.4770966856082524E-04, 0.1141049603637759E+00, 0.7575261888623807E-20, 0.6277758538102519E-05, 0.4644422903178713E-05, 0.6806098279643324E-01, 0.3715389965619895E-21, 0.5956965112658162E-05, 0.4447744978930882E-05, 0.4065442795375918E-01, 0.1972152263052530E-30, 0.2965586553650948E-04, 0.1900611263569203E-04, 0.1509783792061944E-04, 0.1009741958682895E-26, 0.1608958133772104E-02, 0.9583670521235791E-03}, + info: 0, + }, + } { + z := make([]float64, len(test.z)) + copy(z, test.z) + + info := impl.Dlasq2(test.n, z) + if !floats.EqualApprox(test.zOut, z, dTol) { + diff := make([]float64, len(z)) + floats.SubTo(diff, z, test.zOut) + for i := range diff { + diff[i] = math.Abs(diff[i]) + } + t.Errorf("Case %v, Z Mismatch", c) + } + if test.info != info { + t.Errorf("Info mismatch. Want %v, got %v", test.info, info) + } + } + + rnd := rand.New(rand.NewSource(1)) + // Perform a bunch of random tests to check for access out of bounds or + // infinite loops. + // TODO(btracey): Implement direct tests. + // bi := blas64.Implementation() + for _, n := range []int{5, 8, 20, 25} { + for k := 0; k < 10; k++ { + z := make([]float64, 4*n) + for i := range z { + z[i] = rnd.Float64() + } + zCopy := make([]float64, len(z)) + copy(zCopy, z) + + // Compute the eigenvalues + impl.Dlasq2(n, z) + + // Below is the code to test the eigenvalues. Eventually implement + // real tests. + // The code below is missing the transformation from L and U into + // the symmetric tridiagonal matrix. + // See discussion http://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=5&t=4839 + // for format. + + /* + ldl := n + ldu := n + u := make([]float64, n*n) + for i := 0; i < n; i++ { + u[i*ldu+i] = zCopy[2*i] + if i != n-1 { + u[i*ldu+i+1] = 1 + } + } + l := make([]float64, n*n) + for i := 0; i < n; i++ { + l[i*ldl+i] = 1 + if i != n-1 { + l[(i+1)*ldl+i] = zCopy[2*i+1] + } + } + + ldTriDi := n + triDi := make([]float64, n*n) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, l, ldl, u, ldu, 0, triDi, ldTriDi) + + tridi2 := make([]float64, n*n) + bi.Dgemm(blas.Trans, blas.NoTrans, n, n, n, 1, triDi, n, triDi, n, 0, tridi2, n) + + // Eigenvalues have the property that det(A - lambda I ) = 0 + triDiCopy := make([]float64, len(triDi)) + copy(triDiCopy, triDi) + for _, lambda := range z[1:n] { + copy(triDi, triDiCopy) + for i := 0; i < n; i++ { + triDi[i*n+i] -= lambda + } + + // Compute LU + //ipiv := make([]int, n) + //impl.Dgetrf(n, n, triDi, n, ipiv) + ok := impl.Dpotrf(blas.Upper, n, triDi, n) + fmt.Println(ok) + + var det float64 + for i := 0; i < n; i++ { + det += math.Log(math.Abs(triDi[i*n+i])) + } + fmt.Println("det = ", math.Exp(det)) + } + */ + } + } +} diff --git a/lapack/testlapack/dlasq3.go b/lapack/testlapack/dlasq3.go new file mode 100644 index 00000000..95395beb --- /dev/null +++ b/lapack/testlapack/dlasq3.go @@ -0,0 +1,2728 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlasq3er interface { + Dlasq3(i0, n0 int, z []float64, pp int, dmin, sigma, desig, qmax float64, nFail, iter, nDiv int, ttype int, dmin1, dmin2, dn, dn1, dn2, g, tau float64) ( + i0Out, n0Out, ppOut int, dminOut, sigmaOut, desigOut, qmaxOut float64, nFailOut, iterOut, nDivOut, ttypeOut int, dmin1Out, dmin2Out, dnOut, dn1Out, dn2Out, gOut, tauOut float64) +} + +func printDlasq3FortranInput(d dlasq3teststruct) { + z := d.z + printFortranArray(z, "z") + fmt.Println("i0 =", d.i0) + fmt.Println("n0 =", d.n0) + fmt.Println("pp =", d.pp) + + fmt.Println("dmin =", fortran64(d.dmin)) + fmt.Println("sigma =", fortran64(d.sigma)) + fmt.Println("desig =", fortran64(d.desig)) + fmt.Println("qmax =", fortran64(d.qmax)) + fmt.Println("nFail =", d.nFail) + fmt.Println("iter =", d.iter) + fmt.Println("nDiv =", d.nDiv) + fmt.Println("ttype =", d.ttype) + fmt.Println("dmin1 =", fortran64(d.dmin1)) + fmt.Println("dmin2 =", fortran64(d.dmin2)) + fmt.Println("dn =", fortran64(d.dn)) + fmt.Println("dn1 =", fortran64(d.dn1)) + fmt.Println("dn2 =", fortran64(d.dn2)) + fmt.Println("g =", fortran64(d.g)) + fmt.Println("tau =", fortran64(d.tau)) +} + +type dlasq3teststruct struct { + z []float64 + i0, n0, pp int + dmin, desig, sigma, qmax float64 + nFail, iter, nDiv, ttype int + dmin1, dmin2, dn, dn1, dn2, g, tau float64 + + zOut []float64 + i0Out, n0Out, ppOut int + dminOut, desigOut, sigmaOut, qmaxOut float64 + nFailOut, iterOut, nDivOut, ttypeOut int + dmin1Out, dmin2Out, dnOut, dn1Out, dn2Out, gOut, tauOut float64 +} + +func Dlasq3Test(t *testing.T, impl Dlasq3er) { + dTol := 1e-14 + // Tests computed from calling the netlib Dlasq + for _, test := range []dlasq3teststruct{ + { + i0: 1, + n0: 21, + z: []float64{0.1914365246180821E+01, 0.1564384297703890E+01, 0.2493389162143899E+00, 0.3499809484769305E+00, 0.1315996513131545E+01, 0.1363862112490627E+01, 0.9898466611970759E-01, 0.2014733168553078E+00, 0.6023973979587287E+00, 0.6465544792741794E+00, 0.2210033410638781E-02, 0.5482758480425683E-01, 0.9861857233678967E-01, 0.2428190810745492E-01, 0.4756321484454819E+00, 0.7654669763997353E-01, 0.2588748143677115E+00, 0.6127784069508770E+00, 0.1078611376690004E+00, 0.1217285558623164E+00, 0.6442896492255246E+00, 0.2293835804898155E+00, 0.6203230486639705E+00, 0.5227672064047094E+00, 0.3695660678607585E+00, 0.7645233184745865E+00, 0.5378838054252265E+00, 0.2253657980501426E+00, 0.3562533181264623E+00, 0.8820486722335483E+00, 0.2222132496436145E-01, 0.1208845131814035E-01, 0.1275094303021685E+01, 0.6548746852163357E+00, 0.1647324354821218E+00, 0.6424409427697111E+00, 0.1007530576543866E+01, 0.3269551736546701E+00, 0.3453881601783118E+00, 0.8453078383713172E+00, 0.2679391719153404E+00, 0.4116714838778281E+00, 0.7328677736683723E+00, 0.2016558482158241E+00, 0.8360828138307410E+00, 0.9737579452195326E+00, 0.4813660709592822E+00, 0.5951926422795808E+00, 0.6495370513676459E+00, 0.6761876248148171E+00, 0.2325475880222648E+00, 0.4547154975121112E+00, 0.1993624802893807E+00, 0.3321819367342255E+00, 0.3782318916911257E+00, 0.9972813157741996E-01, 0.9830449403503746E+00, 0.7561080996844842E+00, 0.4429733864040367E+00, 0.6051687323570161E+00, 0.1173279550602403E+01, 0.7195724480316686E+00, 0.5035524069144587E+00, 0.8966804889747714E+00, 0.3058980395058521E+00, 0.6588832353928662E+00, 0.3014634433415453E+00, 0.1505672110274446E+00, 0.1289422237567578E+01, 0.6124645310993601E+00, 0.7583364305799440E+00, 0.9784211498097629E+00, 0.4977814779461571E+00, 0.9993813577491869E+00, 0.2841468847862598E+00, 0.2567365507769143E+00, 0.9257539794205765E+00, 0.5509268385614666E+00, 0.5231355605450990E-04, 0.6589740256453697E+00, 0.2117869221381033E-04, 0.7349224826832024E-04, 0.0000000000000000E+00, 0.0000000000000000E+00}, + pp: 0, + dmin: -0.0000000000000000, + desig: 0.0000000000000000, + qmax: 2.1637041623952107, + ttype: 0, + dmin1: 0.0000000000000000, + dmin2: 0.0000000000000000, + dn: 0.0000000000000000, + dn1: 0.0000000000000000, + dn2: 0.0000000000000000, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 2, + sigma: 0.0000000000000000, + nDiv: 40, + zOut: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 2.1175426017541180E-005, + desigOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + qmaxOut: 2.1637041623952107, + nFailOut: 0, + iterOut: 3, + nDivOut: 62, + ttypeOut: -1, + dmin1Out: 4.4311601260836921E-002, + dmin2Out: 4.4311601260836921E-002, + dnOut: 2.1175426017541180E-005, + dn1Out: 0.33915960483100382, + dn2Out: 0.16428924199195991, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03}, + pp: 1, + dmin: 2.1175426017541180E-005, + desig: 0.0000000000000000, + qmax: 2.1637041623952107, + ttype: -1, + dmin1: 4.4311601260836921E-002, + dmin2: 4.4311601260836921E-002, + dn: 2.1175426017541180E-005, + dn1: 0.33915960483100382, + dn2: 0.16428924199195991, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 3, + sigma: 0.0000000000000000, + nDiv: 62, + zOut: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 2.1175425069176302E-005, + desigOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + qmaxOut: 2.1637041623952107, + nFailOut: 0, + iterOut: 4, + nDivOut: 84, + ttypeOut: -4, + dmin1Out: 2.9944624525135358E-002, + dmin2Out: 2.9944624525135358E-002, + dnOut: 2.1175425069176302E-005, + dn1Out: 7.2928780948497918E-002, + dn2Out: 0.16065460645225654, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + pp: 0, + dmin: 2.1175425069176302E-005, + desig: 0.0000000000000000, + qmax: 2.1637041623952107, + ttype: -4, + dmin1: 2.9944624525135358E-002, + dmin2: 2.9944624525135358E-002, + dn: 2.1175425069176302E-005, + dn1: 7.2928780948497918E-002, + dn2: 0.16065460645225654, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 4, + sigma: 0.0000000000000000, + nDiv: 84, + zOut: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 1.1127325659669794E-010, + desigOut: 0.0000000000000000, + sigmaOut: 2.1175313795360271E-005, + qmaxOut: 2.1637041623952107, + nFailOut: 0, + iterOut: 5, + nDivOut: 106, + ttypeOut: -4, + dmin1Out: 3.1433071595911154E-002, + dmin2Out: 3.1433071595911154E-002, + dnOut: 1.1127325659669794E-010, + dn1Out: 3.5896964560873705E-002, + dn2Out: 0.25842281720128102, + gOut: 0.0000000000000000, + tauOut: 2.1175313795360271E-005, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03}, + pp: 1, + dmin: 1.1127325659669794E-010, + desig: 0.0000000000000000, + qmax: 2.1637041623952107, + ttype: -4, + dmin1: 3.1433071595911154E-002, + dmin2: 3.1433071595911154E-002, + dn: 1.1127325659669794E-010, + dn1: 3.5896964560873705E-002, + dn2: 0.25842281720128102, + g: 0.0000000000000000, + tau: 2.1175313795360271E-005, + nFail: 0, + iter: 5, + sigma: 2.1175313795360271E-005, + nDiv: 106, + zOut: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 0.0000000000000000, + desigOut: -5.1698788284564230E-026, + sigmaOut: 2.1175425068616867E-005, + qmaxOut: 2.1637041623952107, + nFailOut: 1, + iterOut: 7, + nDivOut: 150, + ttypeOut: -15, + dmin1Out: 2.9139336744737766E-002, + dmin2Out: 4.9426557292086552E-002, + dnOut: -2.0808762284537102E-024, + dn1Out: 2.9139336744737766E-002, + dn2Out: 0.15959234211062134, + gOut: 0.0000000000000000, + tauOut: 1.1127325659669789E-010, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + pp: 0, + dmin: 0.0000000000000000, + desig: -5.1698788284564230E-026, + qmax: 2.1637041623952107, + ttype: -15, + dmin1: 2.9139336744737766E-002, + dmin2: 4.9426557292086552E-002, + dn: -2.0808762284537102E-024, + dn1: 2.9139336744737766E-002, + dn2: 0.15959234211062134, + g: 0.0000000000000000, + tau: 1.1127325659669789E-010, + nFail: 1, + iter: 7, + sigma: 2.1175425068616867E-005, + nDiv: 150, + zOut: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 0.0000000000000000, + desigOut: -5.1698788284564230E-026, + sigmaOut: 2.1175425068616867E-005, + qmaxOut: 2.1637041623952107, + nFailOut: 1, + iterOut: 8, + nDivOut: 172, + ttypeOut: -1, + dmin1Out: 2.7016889331018056E-002, + dmin2Out: 5.3061698118516694E-002, + dnOut: 0.0000000000000000, + dn1Out: 2.7016889331018056E-002, + dn2Out: 8.6018658784156071E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 0.0000000000000000, + desig: -5.1698788284564230E-026, + qmax: 2.1637041623952107, + ttype: -1, + dmin1: 2.7016889331018056E-002, + dmin2: 5.3061698118516694E-002, + dn: 0.0000000000000000, + dn1: 2.7016889331018056E-002, + dn2: 8.6018658784156071E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 1, + iter: 8, + sigma: 2.1175425068616867E-005, + nDiv: 172, + zOut: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.0000000000000000E+00, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 2.5763383633962696E-002, + desigOut: -5.1698788284564230E-026, + sigmaOut: 2.1175425068616867E-005, + qmaxOut: 2.1637041623952107, + nFailOut: 1, + iterOut: 9, + nDivOut: 193, + ttypeOut: -1, + dmin1Out: 4.3622798915905092E-002, + dmin2Out: 7.4536672467372611E-002, + dnOut: 2.5763383633962696E-002, + dn1Out: 4.3622798915905092E-002, + dn2Out: 9.8141518071882677E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.1620493249248586E-02, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 2.5763383633962696E-002, + desig: -5.1698788284564230E-026, + qmax: 2.4715692224139039, + ttype: -1, + dmin1: 4.3622798915905092E-002, + dmin2: 7.4536672467372611E-002, + dn: 2.5763383633962696E-002, + dn1: 4.3622798915905092E-002, + dn2: 9.8141518071882677E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 1, + iter: 9, + sigma: 2.1175425068616867E-005, + nDiv: 193, + zOut: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 1.8576185384092288E-002, + desigOut: 2.6427422784455342E-019, + sigmaOut: 5.0413140237881371E-003, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 11, + nDivOut: 235, + ttypeOut: -15, + dmin1Out: 1.8576185384092288E-002, + dmin2Out: 5.2365600435162571E-002, + dnOut: 1.9114649409197451E-002, + dn1Out: 1.8576185384092288E-002, + dn2Out: 5.2365600435162571E-002, + gOut: 0.0000000000000000, + tauOut: 5.0201385987195205E-003, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 1.8576185384092288E-002, + desig: 2.6427422784455342E-019, + qmax: 2.4715692224139039, + ttype: -15, + dmin1: 1.8576185384092288E-002, + dmin2: 5.2365600435162571E-002, + dn: 1.9114649409197451E-002, + dn1: 1.8576185384092288E-002, + dn2: 5.2365600435162571E-002, + g: 0.0000000000000000, + tau: 5.0201385987195205E-003, + nFail: 2, + iter: 11, + sigma: 5.0413140237881371E-003, + nDiv: 235, + zOut: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 9.5622848228283271E-003, + desigOut: -6.0308751014385013E-019, + sigmaOut: 1.0518227355316156E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 12, + nDivOut: 256, + ttypeOut: -4, + dmin1Out: 9.5622848228283271E-003, + dmin2Out: 6.9533978479808370E-002, + dnOut: 1.0856003705186750E-002, + dn1Out: 9.5622848228283271E-003, + dn2Out: 6.9533978479808370E-002, + gOut: 0.0000000000000000, + tauOut: 5.4769133315280185E-003, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 9.5622848228283271E-003, + desig: -6.0308751014385013E-019, + qmax: 2.4715692224139039, + ttype: -4, + dmin1: 9.5622848228283271E-003, + dmin2: 6.9533978479808370E-002, + dn: 1.0856003705186750E-002, + dn1: 9.5622848228283271E-003, + dn2: 6.9533978479808370E-002, + g: 0.0000000000000000, + tau: 5.4769133315280185E-003, + nFail: 2, + iter: 12, + sigma: 1.0518227355316156E-002, + nDiv: 256, + zOut: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 2.0601312480394186E-003, + desigOut: 0.0000000000000000, + sigmaOut: 1.5639833716481661E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 13, + nDivOut: 277, + ttypeOut: -4, + dmin1Out: 5.4371870398960158E-003, + dmin2Out: 8.0023511442426670E-002, + dnOut: 2.0601312480394186E-003, + dn1Out: 5.4371870398960158E-003, + dn2Out: 8.0023511442426670E-002, + gOut: 0.0000000000000000, + tauOut: 5.1216063611655054E-003, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 2.0601312480394186E-003, + desig: 0.0000000000000000, + qmax: 2.4715692224139039, + ttype: -4, + dmin1: 5.4371870398960158E-003, + dmin2: 8.0023511442426670E-002, + dn: 2.0601312480394186E-003, + dn1: 5.4371870398960158E-003, + dn2: 8.0023511442426670E-002, + g: 0.0000000000000000, + tau: 5.1216063611655054E-003, + nFail: 2, + iter: 13, + sigma: 1.5639833716481661E-002, + nDiv: 277, + zOut: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 6.0731361153288982E-005, + desigOut: 1.7347234759768071E-018, + sigmaOut: 1.6921621533398150E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 14, + nDivOut: 298, + ttypeOut: -2, + dmin1Out: 6.8738708636769136E-003, + dmin2Out: 8.1489512892123819E-002, + dnOut: 6.0731361153288982E-005, + dn1Out: 6.8738708636769136E-003, + dn2Out: 8.1489512892123819E-002, + gOut: 0.0000000000000000, + tauOut: 1.2817878169164906E-003, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 6.0731361153288982E-005, + desig: 1.7347234759768071E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 6.8738708636769136E-003, + dmin2: 8.1489512892123819E-002, + dn: 6.0731361153288982E-005, + dn1: 6.8738708636769136E-003, + dn2: 8.1489512892123819E-002, + g: 0.0000000000000000, + tau: 1.2817878169164906E-003, + nFail: 2, + iter: 14, + sigma: 1.6921621533398150E-002, + nDiv: 298, + zOut: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 3.1568086081919418E-009, + desigOut: 4.7433845046240819E-020, + sigmaOut: 1.6978458774649190E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 15, + nDivOut: 319, + ttypeOut: -2, + dmin1Out: 1.0483100129151506E-002, + dmin2Out: 8.1316774559040517E-002, + dnOut: 3.1568086081919418E-009, + dn1Out: 1.0483100129151506E-002, + dn2Out: 8.1316774559040517E-002, + gOut: 0.0000000000000000, + tauOut: 5.6837241251038845E-005, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 3.1568086081919418E-009, + desig: 4.7433845046240819E-020, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 1.0483100129151506E-002, + dmin2: 8.1316774559040517E-002, + dn: 3.1568086081919418E-009, + dn1: 1.0483100129151506E-002, + dn2: 8.1316774559040517E-002, + g: 0.0000000000000000, + tau: 5.6837241251038845E-005, + nFail: 2, + iter: 15, + sigma: 1.6978458774649190E-002, + nDiv: 319, + zOut: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 6.9684975813366743E-017, + desigOut: 1.5445815365207740E-018, + sigmaOut: 1.6978461930361368E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 16, + nDivOut: 340, + ttypeOut: -2, + dmin1Out: 1.1199576261102989E-002, + dmin2Out: 8.1067607231828140E-002, + dnOut: 6.9684975813366743E-017, + dn1Out: 1.1199576261102989E-002, + dn2Out: 8.1067607231828140E-002, + gOut: 0.0000000000000000, + tauOut: 3.1557121791797713E-009, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 6.9684975813366743E-017, + desig: 1.5445815365207740E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 1.1199576261102989E-002, + dmin2: 8.1067607231828140E-002, + dn: 6.9684975813366743E-017, + dn1: 1.1199576261102989E-002, + dn2: 8.1067607231828140E-002, + g: 0.0000000000000000, + tau: 3.1557121791797713E-009, + nFail: 2, + iter: 16, + sigma: 1.6978461930361368E-002, + nDiv: 340, + zOut: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 6.1629758220391547E-032, + desigOut: -1.6288286479578371E-018, + sigmaOut: 1.6978461930361441E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 17, + nDivOut: 361, + ttypeOut: -2, + dmin1Out: 1.1203310405167735E-002, + dmin2Out: 8.0927116373146771E-002, + dnOut: 6.1629758220391547E-032, + dn1Out: 1.1203310405167735E-002, + dn2Out: 8.0927116373146771E-002, + gOut: 0.0000000000000000, + tauOut: 6.9684975806547287E-017, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 6.1629758220391547E-032, + desig: -1.6288286479578371E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 1.1203310405167735E-002, + dmin2: 8.0927116373146771E-002, + dn: 6.1629758220391547E-032, + dn1: 1.1203310405167735E-002, + dn2: 8.0927116373146771E-002, + g: 0.0000000000000000, + tau: 6.9684975806547287E-017, + nFail: 2, + iter: 17, + sigma: 1.6978461930361441E-002, + nDiv: 361, + zOut: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26, 0.6162975822039155E-31, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 6.1629758220391547E-032, + desigOut: -1.6288286479578371E-018, + sigmaOut: 1.6978461930361441E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 18, + nDivOut: 382, + ttypeOut: -2, + dmin1Out: 1.1203288675083998E-002, + dmin2Out: 8.0846453894262649E-002, + dnOut: 6.1629758220391547E-032, + dn1Out: 1.1203288675083998E-002, + dn2Out: 8.0846453894262649E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26, 0.6162975822039155E-31, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 6.1629758220391547E-032, + desig: -1.6288286479578371E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 1.1203288675083998E-002, + dmin2: 8.0846453894262649E-002, + dn: 6.1629758220391547E-032, + dn1: 1.1203288675083998E-002, + dn2: 8.0846453894262649E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 18, + sigma: 1.6978461930361441E-002, + nDiv: 382, + zOut: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 8.9043085058082561E-010, + desigOut: 1.7347234759768071E-018, + sigmaOut: 2.8181746216274728E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 19, + nDivOut: 402, + ttypeOut: -7, + dmin1Out: 6.9585227169791292E-002, + dmin2Out: 0.11373841371027797, + dnOut: 8.9043085058082561E-010, + dn1Out: 6.9585227169791292E-002, + dn2Out: 0.11373841371027797, + gOut: 0.0000000000000000, + tauOut: 1.1203284285913290E-002, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.9043085058082561E-010, + desig: 1.7347234759768071E-018, + qmax: 2.4715692224139039, + ttype: -7, + dmin1: 6.9585227169791292E-002, + dmin2: 0.11373841371027797, + dn: 8.9043085058082561E-010, + dn1: 6.9585227169791292E-002, + dn2: 0.11373841371027797, + g: 0.0000000000000000, + tau: 1.1203284285913290E-002, + nFail: 2, + iter: 19, + sigma: 2.8181746216274728E-002, + nDiv: 402, + zOut: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 19, + ppOut: 1, + dminOut: 1.3962105636374437E-019, + desigOut: -1.5687885635568321E-018, + sigmaOut: 2.8181747106705537E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 20, + nDivOut: 422, + ttypeOut: -2, + dmin1Out: 6.9544122471813200E-002, + dmin2Out: 9.8247027562672340E-002, + dnOut: 1.3962105636374437E-019, + dn1Out: 6.9544122471813200E-002, + dn2Out: 9.8247027562672340E-002, + gOut: 0.0000000000000000, + tauOut: 8.9043080564395014E-010, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.3962105636374437E-019, + desig: -1.5687885635568321E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 6.9544122471813200E-002, + dmin2: 9.8247027562672340E-002, + dn: 1.3962105636374437E-019, + dn1: 6.9544122471813200E-002, + dn2: 9.8247027562672340E-002, + g: 0.0000000000000000, + tau: 8.9043080564395014E-010, + nFail: 2, + iter: 20, + sigma: 2.8181747106705537E-002, + nDiv: 422, + zOut: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.1396210563637444E-18, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 1.3962105636374430E-019, + desigOut: -1.5687885635568321E-018, + sigmaOut: 2.8181747106705537E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 21, + nDivOut: 442, + ttypeOut: -2, + dmin1Out: 6.9512134440652351E-002, + dmin2Out: 8.9358776708560295E-002, + dnOut: 1.3962105636374430E-019, + dn1Out: 6.9512134440652351E-002, + dn2Out: 8.9358776708560295E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.1396210563637444E-18, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 1.3962105636374430E-019, + desig: -1.5687885635568321E-018, + qmax: 2.4715692224139039, + ttype: -2, + dmin1: 6.9512134440652351E-002, + dmin2: 8.9358776708560295E-002, + dn: 1.3962105636374430E-019, + dn1: 6.9512134440652351E-002, + dn2: 8.9358776708560295E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 21, + sigma: 2.8181747106705537E-002, + nDiv: 442, + zOut: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.8997910999570377E-34, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 1, + dminOut: 1.2643548659038301E-003, + desigOut: -5.0382355155104463E-018, + sigmaOut: 9.6270319212300656E-002, + qmaxOut: 2.4715692224139039, + nFailOut: 2, + iterOut: 22, + nDivOut: 461, + ttypeOut: -8, + dmin1Out: 1.3935943135754067E-002, + dmin2Out: 9.9495800084882416E-002, + dnOut: 1.2643548659038301E-003, + dn1Out: 1.3935943135754067E-002, + dn2Out: 9.9495800084882416E-002, + gOut: 0.0000000000000000, + tauOut: 6.8088572105595116E-002, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.2643548659038301E-003, + desig: -5.0382355155104463E-018, + qmax: 2.3847059974280183, + ttype: -8, + dmin1: 1.3935943135754067E-002, + dmin2: 9.9495800084882416E-002, + dn: 1.2643548659038301E-003, + dn1: 1.3935943135754067E-002, + dn2: 9.9495800084882416E-002, + g: 0.0000000000000000, + tau: 6.8088572105595116E-002, + nFail: 2, + iter: 22, + sigma: 9.6270319212300656E-002, + nDiv: 461, + zOut: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 0, + dminOut: 1.2236274461701734E-006, + desigOut: -3.2526065174565133E-018, + sigmaOut: 9.7516636666659787E-002, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 23, + nDivOut: 480, + ttypeOut: -2, + dmin1Out: 1.1812799375517376E-002, + dmin2Out: 0.10597947881780349, + dnOut: 1.2236274461701734E-006, + dn1Out: 1.1812799375517376E-002, + dn2Out: 0.10597947881780349, + gOut: 0.0000000000000000, + tauOut: 1.2463174543591322E-003, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 1.2236274461701734E-006, + desig: -3.2526065174565133E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 1.1812799375517376E-002, + dmin2: 0.10597947881780349, + dn: 1.2236274461701734E-006, + dn1: 1.1812799375517376E-002, + dn2: 0.10597947881780349, + g: 0.0000000000000000, + tau: 1.2463174543591322E-003, + nFail: 2, + iter: 23, + sigma: 9.7516636666659787E-002, + nDiv: 480, + zOut: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 1, + dminOut: 9.5986727915820745E-012, + desigOut: 6.4755668817591261E-018, + sigmaOut: 9.7517858554454467E-002, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 24, + nDivOut: 499, + ttypeOut: -2, + dmin1Out: 1.1875197612370336E-002, + dmin2Out: 0.11291768719739126, + dnOut: 9.5986727915820745E-012, + dn1Out: 1.1875197612370336E-002, + dn2Out: 0.11291768719739126, + gOut: 0.0000000000000000, + tauOut: 1.2218877946904154E-006, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 9.5986727915820745E-012, + desig: 6.4755668817591261E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 1.1875197612370336E-002, + dmin2: 0.11291768719739126, + dn: 9.5986727915820745E-012, + dn1: 1.1875197612370336E-002, + dn2: 0.11291768719739126, + g: 0.0000000000000000, + tau: 1.2218877946904154E-006, + nFail: 2, + iter: 24, + sigma: 9.7517858554454467E-002, + nDiv: 499, + zOut: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 0, + dminOut: 6.6174125886815435E-022, + desigOut: -5.0906815225379586E-018, + sigmaOut: 9.7517858564053150E-002, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 25, + nDivOut: 518, + ttypeOut: -2, + dmin1Out: 1.1882019541390456E-002, + dmin2Out: 0.11366976186212303, + dnOut: 6.6174125886815435E-022, + dn1Out: 1.1882019541390456E-002, + dn2Out: 0.11366976186212303, + gOut: 0.0000000000000000, + tauOut: 9.5986713933289272E-012, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 6.6174125886815435E-022, + desig: -5.0906815225379586E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 1.1882019541390456E-002, + dmin2: 0.11366976186212303, + dn: 6.6174125886815435E-022, + dn1: 1.1882019541390456E-002, + dn2: 0.11366976186212303, + g: 0.0000000000000000, + tau: 9.5986713933289272E-012, + nFail: 2, + iter: 25, + sigma: 9.7517858564053150E-002, + nDiv: 518, + zOut: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17, 0.6617412588681543E-21, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 18, + ppOut: 1, + dminOut: 6.6174125886815426E-022, + desigOut: -5.0906815225379586E-018, + sigmaOut: 9.7517858564053150E-002, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 26, + nDivOut: 537, + ttypeOut: -2, + dmin1Out: 1.1880977265773463E-002, + dmin2Out: 0.11370904624558997, + dnOut: 6.6174125886815426E-022, + dn1Out: 1.1880977265773463E-002, + dn2Out: 0.11370904624558997, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 18, + z: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17, 0.6617412588681543E-21, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 6.6174125886815426E-022, + desig: -5.0906815225379586E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 1.1880977265773463E-002, + dmin2: 0.11370904624558997, + dn: 6.6174125886815426E-022, + dn1: 1.1880977265773463E-002, + dn2: 0.11370904624558997, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 26, + sigma: 9.7517858564053150E-002, + nDiv: 537, + zOut: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 17, + ppOut: 0, + dminOut: 2.3287035572430725E-008, + desigOut: 1.7347234759768071E-018, + sigmaOut: 0.10939869071976092, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 27, + nDivOut: 555, + ttypeOut: -7, + dmin1Out: 0.10181720511285566, + dmin2Out: 0.30482311636216664, + dnOut: 2.3287035572430725E-008, + dn1Out: 0.10181720511285566, + dn2Out: 0.30482311636216664, + gOut: 0.0000000000000000, + tauOut: 1.1880832155707781E-002, + }, + { + i0: 1, + n0: 17, + z: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 2.3287035572430725E-008, + desig: 1.7347234759768071E-018, + qmax: 2.3847059974280183, + ttype: -7, + dmin1: 0.10181720511285566, + dmin2: 0.30482311636216664, + dn: 2.3287035572430725E-008, + dn1: 0.10181720511285566, + dn2: 0.30482311636216664, + g: 0.0000000000000000, + tau: 1.1880832155707781E-002, + nFail: 2, + iter: 27, + sigma: 0.10939869071976092, + nDiv: 555, + zOut: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 17, + ppOut: 1, + dminOut: 2.6961654281145418E-018, + desigOut: -3.8251180717391650E-018, + sigmaOut: 0.10939871400676864, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 28, + nDivOut: 573, + ttypeOut: -2, + dmin1Out: 0.10181121275944585, + dmin2Out: 0.30487633314418217, + dnOut: 2.6961654281145418E-018, + dn1Out: 0.10181121275944585, + dn2Out: 0.30487633314418217, + gOut: 0.0000000000000000, + tauOut: 2.3287007705477136E-008, + }, + { + i0: 1, + n0: 17, + z: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 2.6961654281145418E-018, + desig: -3.8251180717391650E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 0.10181121275944585, + dmin2: 0.30487633314418217, + dn: 2.6961654281145418E-018, + dn1: 0.10181121275944585, + dn2: 0.30487633314418217, + g: 0.0000000000000000, + tau: 2.3287007705477136E-008, + nFail: 2, + iter: 28, + sigma: 0.10939871400676864, + nDiv: 573, + zOut: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.2696165428114542E-17, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 17, + ppOut: 0, + dminOut: 2.6961654281138038E-018, + desigOut: -3.8251180717391650E-018, + sigmaOut: 0.10939871400676864, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 29, + nDivOut: 591, + ttypeOut: -2, + dmin1Out: 0.10180899282350273, + dmin2Out: 0.30489636738914000, + dnOut: 2.6961654281138038E-018, + dn1Out: 0.10180899282350273, + dn2Out: 0.30489636738914000, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 17, + z: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.2696165428114542E-17, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 2.6961654281138038E-018, + desig: -3.8251180717391650E-018, + qmax: 2.3847059974280183, + ttype: -2, + dmin1: 0.10180899282350273, + dmin2: 0.30489636738914000, + dn: 2.6961654281138038E-018, + dn1: 0.10180899282350273, + dn2: 0.30489636738914000, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 29, + sigma: 0.10939871400676864, + nDiv: 591, + zOut: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.7379175991216932E-30, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 16, + ppOut: 1, + dminOut: 1.3142485785350155E-006, + desigOut: 0.0000000000000000, + sigmaOut: 0.21120521870940451, + qmaxOut: 2.3847059974280183, + nFailOut: 2, + iterOut: 30, + nDivOut: 608, + ttypeOut: -7, + dmin1Out: 0.20309651253108729, + dmin2Out: 0.57610166617362735, + dnOut: 1.3142485785350155E-006, + dn1Out: 0.20309651253108729, + dn2Out: 0.81137144083676127, + gOut: 0.0000000000000000, + tauOut: 0.10180650470263587, + }, + { + i0: 1, + n0: 16, + z: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.3142485785350155E-006, + desig: 0.0000000000000000, + qmax: 2.2697722926067549, + ttype: -7, + dmin1: 0.20309651253108729, + dmin2: 0.57610166617362735, + dn: 1.3142485785350155E-006, + dn1: 0.20309651253108729, + dn2: 0.81137144083676127, + g: 0.0000000000000000, + tau: 0.10180650470263587, + nFail: 2, + iter: 30, + sigma: 0.21120521870940451, + nDiv: 608, + zOut: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 16, + ppOut: 0, + dminOut: 8.4118841991824567E-018, + desigOut: 1.0739530738237274E-017, + sigmaOut: 0.21120653295038691, + qmaxOut: 2.2697722926067549, + nFailOut: 2, + iterOut: 31, + nDivOut: 625, + ttypeOut: -2, + dmin1Out: 0.20309744276965425, + dmin2Out: 0.50018599148866161, + dnOut: 8.4118841991824567E-018, + dn1Out: 0.20309744276965425, + dn2Out: 0.75834178007645303, + gOut: 0.0000000000000000, + tauOut: 1.3142409824136984E-006, + }, + { + i0: 1, + n0: 16, + z: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.4118841991824567E-018, + desig: 1.0739530738237274E-017, + qmax: 2.2697722926067549, + ttype: -2, + dmin1: 0.20309744276965425, + dmin2: 0.50018599148866161, + dn: 8.4118841991824567E-018, + dn1: 0.20309744276965425, + dn2: 0.75834178007645303, + g: 0.0000000000000000, + tau: 1.3142409824136984E-006, + nFail: 2, + iter: 31, + sigma: 0.21120653295038691, + nDiv: 625, + zOut: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 16, + ppOut: 1, + dminOut: 8.4118841988678429E-018, + desigOut: 1.0739530738237274E-017, + sigmaOut: 0.21120653295038691, + qmaxOut: 2.2697722926067549, + nFailOut: 2, + iterOut: 32, + nDivOut: 642, + ttypeOut: -2, + dmin1Out: 0.20309858884628909, + dmin2Out: 0.53283137411117854, + dnOut: 8.4118841988678429E-018, + dn1Out: 0.20309858884628909, + dn2Out: 0.71080515929391042, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 16, + z: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 8.4118841988678429E-018, + desig: 1.0739530738237274E-017, + qmax: 2.2697722926067549, + ttype: -2, + dmin1: 0.20309858884628909, + dmin2: 0.53283137411117854, + dn: 8.4118841988678429E-018, + dn1: 0.20309858884628909, + dn2: 0.71080515929391042, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 32, + sigma: 0.21120653295038691, + nDiv: 642, + zOut: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.8411884198867843E-17, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 16, + ppOut: 0, + dminOut: 8.4118841988678429E-018, + desigOut: 1.0739530738237274E-017, + sigmaOut: 0.21120653295038691, + qmaxOut: 2.2697722926067549, + nFailOut: 2, + iterOut: 33, + nDivOut: 659, + ttypeOut: -2, + dmin1Out: 0.20309858045029386, + dmin2Out: 0.51860540644834729, + dnOut: 8.4118841988678429E-018, + dn1Out: 0.20309858045029386, + dn2Out: 0.67176795876146822, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 16, + z: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.8411884198867843E-17, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.4118841988678429E-018, + desig: 1.0739530738237274E-017, + qmax: 2.2697722926067549, + ttype: -2, + dmin1: 0.20309858045029386, + dmin2: 0.51860540644834729, + dn: 8.4118841988678429E-018, + dn1: 0.20309858045029386, + dn2: 0.67176795876146822, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 2, + iter: 33, + sigma: 0.21120653295038691, + nDiv: 659, + zOut: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.1303059324279677E-43, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 15, + ppOut: 1, + dminOut: 0.10154928703201281, + desigOut: 0.0000000000000000, + sigmaOut: 0.31275582317553385, + qmaxOut: 2.2697722926067549, + nFailOut: 2, + iterOut: 34, + nDivOut: 675, + ttypeOut: -9, + dmin1Out: 0.32391205918605420, + dmin2Out: 0.32391205918605420, + dnOut: 0.10154928703201281, + dn1Out: 0.53450854002684800, + dn2Out: 0.69531980574199759, + gOut: 0.0000000000000000, + tauOut: 0.10154929022514693, + }, + { + i0: 1, + n0: 15, + z: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 0.10154928703201281, + desig: 0.0000000000000000, + qmax: 2.1682216902523144, + ttype: -9, + dmin1: 0.32391205918605420, + dmin2: 0.32391205918605420, + dn: 0.10154928703201281, + dn1: 0.53450854002684800, + dn2: 0.69531980574199759, + g: 0.0000000000000000, + tau: 0.10154929022514693, + nFail: 2, + iter: 34, + sigma: 0.31275582317553385, + nDiv: 675, + zOut: []float64{0.2168221690252314E+01, 0.2066680684115085E+01, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.8728911912704126E+00, 0.7726711989960955E+00, 0.1321013925721922E-02, 0.2361487308570419E-02, 0.1381252078118717E+01, 0.1279505990312372E+01, 0.2156405683614187E-02, 0.2803234389363145E-02, 0.1663302606134993E+01, 0.1580598225403798E+01, 0.2163985983955575E-01, 0.2200217261925751E-01, 0.1607061933620194E+01, 0.1511873816770092E+01, 0.2835506195054301E-01, 0.1320468740761088E-01, 0.7040655098910235E+00, 0.6628877301101292E+00, 0.7356791380810462E-01, 0.1945110224949301E+00, 0.1752652257061283E+01, 0.1621214783142186E+01, 0.1646145547572216E+00, 0.8703165684534678E-01, 0.8571356821219610E+00, 0.7442679496495411E+00, 0.7570493055431493E-01, 0.1597129865933493E+00, 0.1570165327329021E+01, 0.1651350720852550E+01, 0.3424393862982660E+00, 0.1337269360034139E+00, 0.6448734608299306E+00, 0.5118619205977412E+00, 0.1022564019526126E+00, 0.1169456581236225E+00, 0.5853915063475871E+00, 0.4777529393688394E+00, 0.1108480973262629E+00, 0.8163333047984263E-01, 0.3518379162830466E+00, 0.2373651048287110E+00, 0.6870152520689508E-01, 0.2125478936639627E+00, 0.7343571035538636E+00, 0.4559783600136673E+00, 0.3571015630515456E-01, 0.4186028435717903E-01, 0.5345085484304394E+00, 0.3911072610850064E+00, 0.3193134112956561E-08, 0.8290832843879624E-09, 0.1015492870320128E+00, 0.8280021541434701E-05, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 15, + ppOut: 0, + dminOut: 8.2800215414347011E-006, + desigOut: -1.3877787807814457E-017, + sigmaOut: 0.41429682935692197, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 35, + nDivOut: 691, + ttypeOut: -4, + dmin1Out: 0.16866357962181588, + dmin2Out: 0.16866357962181588, + dnOut: 8.2800215414347011E-006, + dn1Out: 0.39110725789187228, + dn2Out: 0.42026820370851276, + gOut: 0.0000000000000000, + tauOut: 0.10154100618138810, + }, + { + i0: 1, + n0: 11, + z: []float64{0.1565539912114361E+01, 0.1565539887559990E+01, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.1185508165627851E+01, 0.1209595044804978E+01, 0.2408690373149840E-01, 0.1773879145177052E-01, 0.8908058287637680E+00, 0.9017845275302323E+00, 0.2871751477260568E-01, 0.4376453959373496E-01, 0.1374289696466428E+01, 0.1388278114489740E+01, 0.5775298217141787E-01, 0.3977262621431848E-01, 0.9560626040960629E+00, 0.9795790109656241E+00, 0.6328905763825028E-01, 0.5927283946360358E-01, 0.9174165586530958E+00, 0.1200347187817445E+01, 0.3422034931823232E+00, 0.1225138368952072E+00, 0.4297417838091302E+00, 0.3072280530227507E+00, 0.1306631986684747E-06, 0.1577236754259593E-06, 0.3708552845063717E+00, 0.3753559465594062E+00, 0.4500844331080801E-02, 0.3315910790466669E-02, 0.2765362989488873E+00, 0.2810497954194954E+00, 0.7829431815445537E-02, 0.5406547261581845E-02, 0.1940765355151052E+00, 0.1886700618399915E+00, 0.9814083907923291E-07, 0.1277249852674422E-13, 0.2455438642568072E-07, 0.2764930279233778E-14, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 2.7649302792337775E-015, + desig: 4.8519526217661568E-017, + qmax: 2.1682216902523144, + ttype: -2, + dmin1: 0.18866996369915248, + dmin2: 0.27322036360404983, + dn: 2.7649302792337775E-015, + dn1: 0.18866996369915248, + dn2: 0.27322036360404983, + g: 0.0000000000000000, + tau: 2.4554370888251911E-008, + nFail: 2, + iter: 57, + sigma: 0.91543762594185796, + nDiv: 1001, + zOut: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13, 0.3470987982972452E-28, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 11, + ppOut: 1, + dminOut: 3.4709879829724519E-029, + desigOut: 3.7892243888322520E-017, + sigmaOut: 0.91543762594186073, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 58, + nDivOut: 1013, + ttypeOut: -2, + dmin1Out: 0.18507826404867261, + dmin2Out: 0.27717487004787600, + dnOut: 3.4709879829724519E-029, + dn1Out: 0.18507826404867261, + dn2Out: 0.27858872904535659, + gOut: 0.0000000000000000, + tauOut: 2.7649302792335523E-015, + }, + { + i0: 1, + n0: 11, + z: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13, 0.3470987982972452E-28, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 3.4709879829724519E-029, + desig: 3.7892243888322520E-017, + qmax: 2.1682216902523144, + ttype: -2, + dmin1: 0.18507826404867261, + dmin2: 0.27717487004787600, + dn: 3.4709879829724519E-029, + dn1: 0.18507826404867261, + dn2: 0.27858872904535659, + g: 0.0000000000000000, + tau: 2.7649302792335523E-015, + nFail: 2, + iter: 58, + sigma: 0.91543762594186073, + nDiv: 1013, + zOut: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 0, + dminOut: 8.9088074504151571E-002, + desigOut: -4.1633363423443370E-017, + sigmaOut: 1.0079767579661971, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 59, + nDivOut: 1024, + ttypeOut: -9, + dmin1Out: 0.17705256406949207, + dmin2Out: 0.17705256406949207, + dnOut: 8.9088074504151571E-002, + dn1Out: 0.18903428744201686, + dn2Out: 0.28613205491191551, + gOut: 0.0000000000000000, + tauOut: 9.2539132024336307E-002, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.9088074504151571E-002, + desig: -4.1633363423443370E-017, + qmax: 2.1682216902523144, + ttype: -9, + dmin1: 0.17705256406949207, + dmin2: 0.17705256406949207, + dn: 8.9088074504151571E-002, + dn1: 0.18903428744201686, + dn2: 0.28613205491191551, + g: 0.0000000000000000, + tau: 9.2539132024336307E-002, + nFail: 2, + iter: 59, + sigma: 1.0079767579661971, + nDiv: 1024, + zOut: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 1, + dminOut: 1.1106216559126303E-002, + desigOut: -4.1633363423443370E-017, + sigmaOut: 1.0833646797982348, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 60, + nDivOut: 1035, + ttypeOut: -4, + dmin1Out: 0.10021441433509834, + dmin2Out: 0.10021441433509834, + dnOut: 1.1106216559126303E-002, + dn1Out: 0.11507463320059727, + dn2Out: 0.21320388392650824, + gOut: 0.0000000000000000, + tauOut: 7.5387921832037685E-002, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.1106216559126303E-002, + desig: -4.1633363423443370E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 0.10021441433509834, + dmin2: 0.10021441433509834, + dn: 1.1106216559126303E-002, + dn1: 0.11507463320059727, + dn2: 0.21320388392650824, + g: 0.0000000000000000, + tau: 7.5387921832037685E-002, + nFail: 2, + iter: 60, + sigma: 1.0833646797982348, + nDiv: 1035, + zOut: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 0, + dminOut: 1.6452860548183366E-003, + desigOut: 7.9797279894933126E-017, + sigmaOut: 1.0925653435343534, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 61, + nDivOut: 1046, + ttypeOut: -4, + dmin1Out: 9.0837695870445614E-002, + dmin2Out: 9.0837695870445614E-002, + dnOut: 1.6452860548183366E-003, + dn1Out: 0.10809563217808144, + dn2Out: 0.20642195434625446, + gOut: 0.0000000000000000, + tauOut: 9.2006637361187298E-003, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 1.6452860548183366E-003, + desig: 7.9797279894933126E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 9.0837695870445614E-002, + dmin2: 9.0837695870445614E-002, + dn: 1.6452860548183366E-003, + dn1: 0.10809563217808144, + dn2: 0.20642195434625446, + g: 0.0000000000000000, + tau: 9.2006637361187298E-003, + nFail: 2, + iter: 61, + sigma: 1.0925653435343534, + nDiv: 1046, + zOut: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 1, + dminOut: 8.1926049685687600E-005, + desigOut: -9.9312918999672206E-017, + sigmaOut: 1.0941247654737283, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 62, + nDivOut: 1057, + ttypeOut: -4, + dmin1Out: 8.9258234858565516E-002, + dmin2Out: 8.9258234858565516E-002, + dnOut: 8.1926049685687600E-005, + dn1Out: 0.10847668953277810, + dn2Out: 0.20701876553386761, + gOut: 0.0000000000000000, + tauOut: 1.5594219393746818E-003, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 8.1926049685687600E-005, + desig: -9.9312918999672206E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 8.9258234858565516E-002, + dmin2: 8.9258234858565516E-002, + dn: 8.1926049685687600E-005, + dn1: 0.10847668953277810, + dn2: 0.20701876553386761, + g: 0.0000000000000000, + tau: 1.5594219393746818E-003, + nFail: 2, + iter: 62, + sigma: 1.0941247654737283, + nDiv: 1057, + zOut: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 0, + dminOut: 5.0612658152462498E-007, + desigOut: -9.3553094958342964E-017, + sigmaOut: 1.0942061824183187, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 63, + nDivOut: 1068, + ttypeOut: -4, + dmin1Out: 8.9177229293753768E-002, + dmin2Out: 8.9177229293753768E-002, + dnOut: 5.0612658152462498E-007, + dn1Out: 0.10831524323681536, + dn2Out: 0.20814970454128662, + gOut: 0.0000000000000000, + tauOut: 8.1416944590412474E-005, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 5.0612658152462498E-007, + desig: -9.3553094958342964E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 8.9177229293753768E-002, + dmin2: 8.9177229293753768E-002, + dn: 5.0612658152462498E-007, + dn1: 0.10831524323681536, + dn2: 0.20814970454128662, + g: 0.0000000000000000, + tau: 8.1416944590412474E-005, + nFail: 2, + iter: 63, + sigma: 1.0942061824183187, + nDiv: 1068, + zOut: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 1, + dminOut: 8.6071246971392626E-011, + desigOut: 7.0901951641105278E-017, + sigmaOut: 1.0942066884588149, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 64, + nDivOut: 1079, + ttypeOut: -4, + dmin1Out: 8.9183660885577137E-002, + dmin2Out: 8.9183660885577137E-002, + dnOut: 8.6071246971392626E-011, + dn1Out: 0.10814239569959758, + dn2Out: 0.20876277035564564, + gOut: 0.0000000000000000, + tauOut: 5.0604049633765406E-007, + }, + { + i0: 1, + n0: 10, + z: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 8.6071246971392626E-011, + desig: 7.0901951641105278E-017, + qmax: 2.1682216902523144, + ttype: -4, + dmin1: 8.9183660885577137E-002, + dmin2: 8.9183660885577137E-002, + dn: 8.6071246971392626E-011, + dn1: 0.10814239569959758, + dn2: 0.20876277035564564, + g: 0.0000000000000000, + tau: 5.0604049633765406E-007, + nFail: 2, + iter: 64, + sigma: 1.0942066884588149, + nDiv: 1079, + zOut: []float64{0.1386770825043033E+01, 0.1386770824956962E+01, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.1102429917229558E+01, 0.1110569728432201E+01, 0.8139811288713328E-02, 0.9529690622753703E-02, 0.1300200404108803E+01, 0.1331504517453077E+01, 0.4083380405309871E-01, 0.2408506071837550E-01, 0.7853632031918177E+00, 0.8215785038267327E+00, 0.6030036143936175E-01, 0.8130667336500198E-01, 0.1107784654351057E+01, 0.1056786122273951E+01, 0.3030814137396716E-01, 0.1929354325655847E-01, 0.6727284432075471E+00, 0.6534352593063080E+00, 0.3594413905024206E-06, 0.4906748310831983E-07, 0.8920069974016231E-01, 0.8924053555066887E-01, 0.3988496406087022E-04, 0.9345605379795243E-04, 0.2091030664752072E+00, 0.2091858898978174E+00, 0.1762795624794033E-03, 0.9113088236382798E-04, 0.1081423986781113E+00, 0.1080512677096902E+00, 0.1393999949133917E-13, 0.1110429488179469E-22, 0.8607124697139263E-10, 0.3167883469916549E-16, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 10, + ppOut: 0, + dminOut: 3.1678834699165494E-017, + desigOut: -8.6057196331979189E-017, + sigmaOut: 1.0942066885448862, + qmaxOut: 2.1682216902523144, + nFailOut: 2, + iterOut: 65, + nDivOut: 1090, + ttypeOut: -4, + dmin1Out: 8.9200650586607991E-002, + dmin2Out: 8.9200650586607991E-002, + dnOut: 3.1678834699165494E-017, + dn1Out: 0.10805126770967630, + dn2Out: 0.20900961033533805, + gOut: 0.0000000000000000, + tauOut: 8.6071215292546838E-011, + }, + { + i0: 1, + n0: 3, + z: []float64{0.1143865217830237E+00, 0.1154808079639322E+00, 0.2932453102768040E-16, 0.1817901582187390E-16, 0.1834406364024603E+00, 0.1845166504084682E+00, 0.1101341475930520E-06, 0.1827217490071947E-04, 0.1127820009512990E-04, 0.1105674515151256E-02, 0.1845166504084682E+00, 0.2816548643828996E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 1.1278200095129901E-005, + desig: 1.1991276027689679E-016, + qmax: 0.41760242607758735, + ttype: -4, + dmin1: 0.11438652178302365, + dmin2: 0.11438652178302365, + dn: 1.1278200095129901E-005, + dn1: 0.18342236422755959, + dn2: 0.11438652178302365, + g: 0.0000000000000000, + tau: 1.0942861809085330E-003, + nFail: 3, + iter: 99, + sigma: 2.3665909917188244, + nDiv: 1347, + zOut: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 3, + ppOut: 0, + dminOut: 8.9549629620034135E-009, + desigOut: -3.3964327119002935E-017, + sigmaOut: 2.3666022609571851, + qmaxOut: 0.41760242607758735, + nFailOut: 3, + iterOut: 100, + nDivOut: 1351, + ttypeOut: -4, + dmin1Out: 0.11437525254466312, + dmin2Out: 0.11437525254466312, + dnOut: 8.9549629620034135E-009, + dn1Out: 0.18342936716409974, + dn2Out: 0.11437525254466312, + gOut: 0.0000000000000000, + tauOut: 1.1269238360546607E-005, + }, + { + i0: 1, + n0: 3, + z: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 8.9549629620034135E-009, + desig: -3.3964327119002935E-017, + qmax: 0.41760242607758735, + ttype: -4, + dmin1: 0.11437525254466312, + dmin2: 0.11437525254466312, + dn: 8.9549629620034135E-009, + dn1: 0.18342936716409974, + dn2: 0.11437525254466312, + g: 0.0000000000000000, + tau: 1.1269238360546607E-005, + nFail: 3, + iter: 100, + sigma: 2.3666022609571851, + nDiv: 1351, + zOut: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 3, + ppOut: 1, + dminOut: 5.5753269291151117E-014, + desigOut: 1.3632246356731358E-016, + sigmaOut: 2.3666022699120921, + qmaxOut: 0.41760242607758735, + nFailOut: 3, + iterOut: 101, + nDivOut: 1355, + ttypeOut: -4, + dmin1Out: 0.11437524358975594, + dmin2Out: 0.11437524358975594, + dnOut: 5.5753269291151117E-014, + dn1Out: 0.18342946834334006, + dn2Out: 0.11437524358975594, + gOut: 0.0000000000000000, + tauOut: 8.9549072084035346E-009, + }, + { + i0: 1, + n0: 3, + z: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 0, + dmin: 5.5753269291151117E-014, + desig: 1.3632246356731358E-016, + qmax: 0.41760242607758735, + ttype: -4, + dmin1: 0.11437524358975594, + dmin2: 0.11437524358975594, + dn: 5.5753269291151117E-014, + dn1: 0.18342946834334006, + dn2: 0.11437524358975594, + g: 0.0000000000000000, + tau: 8.9549072084035346E-009, + nFail: 3, + iter: 101, + sigma: 2.3666022699120921, + nDiv: 1355, + zOut: []float64{0.1143752435897560E+00, 0.1143752435897003E+00, 0.7542783706608855E-16, 0.1209675067575323E-15, 0.1834294683501117E+00, 0.1834294683500558E+00, 0.3305882004599510E-18, 0.1004820715586787E-30, 0.5575326929115112E-13, 0.7669624420364386E-22, 0.1834294772982473E+00, 0.1834294683501117E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 3, + ppOut: 0, + dminOut: 7.6696244203643861E-023, + desigOut: -6.5648763085702813E-017, + sigmaOut: 2.3666022699121481, + qmaxOut: 0.41760242607758735, + nFailOut: 3, + iterOut: 102, + nDivOut: 1359, + ttypeOut: -4, + dmin1Out: 0.11437524358970023, + dmin2Out: 0.11437524358970023, + dnOut: 7.6696244203643861E-023, + dn1Out: 0.18342946835005580, + dn2Out: 0.11437524358970023, + gOut: 0.0000000000000000, + tauOut: 5.5753269214454873E-014, + }, + { + i0: 1, + n0: 3, + z: []float64{0.1143752435897560E+00, 0.1143752435897003E+00, 0.7542783706608855E-16, 0.1209675067575323E-15, 0.1834294683501117E+00, 0.1834294683500558E+00, 0.3305882004599510E-18, 0.1004820715586787E-30, 0.5575326929115112E-13, 0.7669624420364386E-22, 0.1834294772982473E+00, 0.1834294683501117E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + pp: 1, + dmin: 7.6696244203643861E-023, + desig: -6.5648763085702813E-017, + qmax: 0.41760242607758735, + ttype: -4, + dmin1: 0.11437524358970023, + dmin2: 0.11437524358970023, + dn: 7.6696244203643861E-023, + dn1: 0.18342946835005580, + dn2: 0.11437524358970023, + g: 0.0000000000000000, + tau: 5.5753269214454873E-014, + nFail: 3, + iter: 102, + sigma: 2.3666022699121481, + nDiv: 1359, + zOut: []float64{0.2550031738262204E+01, 0.1834294683500561E+00, 0.7542783706608855E-16, 0.1209675067575323E-15, 0.2480977513501848E+01, 0.1143752435897001E+00, 0.3305882004599510E-18, 0.1004820715586787E-30, 0.2366602269912148E+01, 0.7669624420364386E-22, 0.1834294772982473E+00, 0.1834294683501117E+00, 0.2169993432366266E+01, 0.5067642455139780E-26, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.1810817848712033E+01, 0.1972152263052530E-29, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.1681677309759878E+01, 0.5241368559131172E-22, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.1303743375476047E+01, 0.0000000000000000E+00, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1202161769544433E+01, 0.0000000000000000E+00, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1183377192742860E+01, 0.2033579915108999E-22, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1094206688544886E+01, 0.3167883469916549E-16, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.9154376259418607E+00, 0.2764930279233778E-14, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.8241395430971566E+00, 0.2245698748385924E-16, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.7318275341991307E+00, 0.4959852501050381E-23, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.5186198053161721E+00, 0.1503295986001297E-14, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.4143051093784424E+00, 0.1303656847202082E-15, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.2112065329503869E+00, 0.8411884198867843E-17, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.1093987140067686E+00, 0.2696165428113804E-17, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.9751785856405315E-01, 0.6617412588681544E-21, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.2818174710670554E-01, 0.1396210563637443E-18, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1697846193036144E-01, 0.6162975822039155E-31, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.2117542506861687E-04, 0.0000000000000000E+00, 0.9895328911616120E-03, 0.1620493249248586E-02}, + i0Out: 1, + n0Out: 0, + ppOut: 1, + dminOut: 7.6696244203643861E-023, + desigOut: -6.5648763085702813E-017, + sigmaOut: 2.3666022699121481, + qmaxOut: 0.41760242607758735, + nFailOut: 3, + iterOut: 102, + nDivOut: 1359, + ttypeOut: -4, + dmin1Out: 0.11437524358970023, + dmin2Out: 0.11437524358970023, + dnOut: 7.6696244203643861E-023, + dn1Out: 0.18342946835005580, + dn2Out: 0.11437524358970023, + gOut: 0.0000000000000000, + tauOut: 5.5753269214454873E-014, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1648283185136998E+01, 0.1396221235720571E+01, 0.1712714336271993E+00, 0.2520619494164272E+00, 0.1510753432847732E+01, 0.1119977945086946E+01, 0.3792800633372563E+00, 0.5620469213879850E+00, 0.1328441621586708E+01, 0.1019485448443405E+01, 0.1388998759717073E+00, 0.6882362364805590E+00, 0.4466938077796418E+00, 0.2681061628164644E+00, 0.7093206047768255E+00, 0.3174875209348847E+00, 0.6843112870203156E+00, 0.9979892152967577E+00, 0.6490582981441884E+00, 0.3956426765003833E+00, 0.5085572738629487E+00, 0.1122623886995757E+01, 0.9750235054014829E-02, 0.3499168501137979E-01, 0.1364886053450573E+00, 0.1417066070690837E+00, 0.2301225778544498E-01, 0.4532233329988395E-02, 0.1646009972289452E+01, 0.6930161671496210E+00, 0.2362515608142310E+00, 0.9760060629252760E+00, 0.5818602562677768E+00, 0.3984323866837953E+00, 0.1797665269485310E-01, 0.4196794303982125E+00, 0.5600419521166516E+00, 0.2492354636952108E-01, 0.2195137569256029E+00, 0.5530950584419837E+00, 0.4184071984843414E+00, 0.2222708575473020E+00, 0.2727864547293006E+00, 0.4156500978626423E+00, 0.6774373914466536E-01, 0.2745959086613283E+00, 0.1050967099374242E+00, 0.6593428521263771E-01, 0.2040338718098096E+00, 0.1079809097801335E+00, 0.1271971985482246E+00, 0.2011496719671002E+00, 0.4444741998443960E-01, 0.1290210252363728E+00, 0.5776327498150620E+00, 0.4262359329629137E-01, 0.3402556968467140E+00, 0.6023491555328507E+00, 0.1086565805630269E+00, 0.3155392911289253E+00, 0.9382999256694983E+00, 0.1171677238805356E+00, 0.7901625299559836E+00, 0.9297887823519896E+00, 0.6095853796269167E+00, 0.7973955560628040E+00, 0.8018125008387630E+00, 0.6023523535200964E+00, 0.2443177602187348E-01, 0.8114406374558937E+00, 0.2277830378453201E+00, 0.1480363940474286E-01, 0.6969081780841352E+00, 0.3759308106650992E+00, 0.8012406122589412E-01, 0.5487604052643561E+00, 0.9781022865072954E-01, 0.1017549972519246E+00, 0.2961248981181939E-03, 0.7617929262469909E-01, 0.8408398800007548E-04, 0.3802088861182694E-03, 0.0000000000000000E+00, 0.0000000000000000E+00}, + pp: 0, + dmin: -0.0000000000000000, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: 0, + dmin1: 0.0000000000000000, + dmin2: 0.0000000000000000, + dn: 0.0000000000000000, + dn1: 0.0000000000000000, + dn2: 0.0000000000000000, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 2, + sigma: 0.0000000000000000, + nDiv: 40, + zOut: []float64{0.1648283185136998E+01, 0.1819554618764197E+01, 0.1712714336271993E+00, 0.1422045283129674E+00, 0.1510753432847732E+01, 0.1747828967872021E+01, 0.3792800633372563E+00, 0.2882727267008810E+00, 0.1328441621586708E+01, 0.1179068770857534E+01, 0.1388998759717073E+00, 0.5262264257308433E-01, 0.4466938077796418E+00, 0.1103391769983383E+01, 0.7093206047768255E+00, 0.4399127392187891E+00, 0.6843112870203156E+00, 0.8934568459457148E+00, 0.6490582981441884E+00, 0.3694451726238032E+00, 0.5085572738629487E+00, 0.1488623362931603E+00, 0.9750235054014829E-02, 0.8939776288934402E-02, 0.1364886053450573E+00, 0.1505610868415679E+00, 0.2301225778544498E-01, 0.2515816443301624E+00, 0.1646009972289452E+01, 0.1630679888773521E+01, 0.2362515608142310E+00, 0.8429943526342391E-01, 0.5818602562677768E+00, 0.5155374736992060E+00, 0.1797665269485310E-01, 0.1952851185677853E-01, 0.5600419521166516E+00, 0.7600271971854760E+00, 0.2195137569256029E+00, 0.1208458544696003E+00, 0.4184071984843414E+00, 0.5703477987440417E+00, 0.2727864547293006E+00, 0.3240053608004366E-01, 0.6774373914466536E-01, 0.1404399130020459E+00, 0.1050967099374242E+00, 0.1526865702536626E+00, 0.2040338718098096E+00, 0.1785445001043715E+00, 0.1271971985482246E+00, 0.3166486394939177E-01, 0.4444741998443960E-01, 0.5904153058501098E+00, 0.5776327498150620E+00, 0.3328891237445398E+00, 0.3402556968467140E+00, 0.1160231536652011E+00, 0.1086565805630269E+00, 0.8787251358464724E+00, 0.9382999256694983E+00, 0.8497373197790092E+00, 0.7901625299559836E+00, 0.5668475593321608E+00, 0.6095853796269167E+00, 0.8445503211335190E+00, 0.8018125008387630E+00, 0.2319542476253924E-01, 0.2443177602187348E-01, 0.2290193891046544E+00, 0.2277830378453201E+00, 0.6931459494493321E+00, 0.6969081780841352E+00, 0.8388628986069724E-01, 0.8012406122589412E-01, 0.9342352322344821E-01, 0.9781022865072954E-01, 0.4682830325399513E-02, 0.2961248981181939E-03, 0.5317160915449039E-05, 0.8408398800007548E-04, 0.7876682708462645E-04, 0.0000000000000000E+00, 0.8939776288934402E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 7.8766827084626452E-005, + desigOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 3, + nDivOut: 62, + ttypeOut: -1, + dmin1Out: 1.2363512593342330E-003, + dmin2Out: 1.2363512593342330E-003, + dnOut: 7.8766827084626452E-005, + dn1Out: 4.3867054272813191E-003, + dn2Out: 3.7622286348031123E-003, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1648283185136998E+01, 0.1819554618764197E+01, 0.1712714336271993E+00, 0.1422045283129674E+00, 0.1510753432847732E+01, 0.1747828967872021E+01, 0.3792800633372563E+00, 0.2882727267008810E+00, 0.1328441621586708E+01, 0.1179068770857534E+01, 0.1388998759717073E+00, 0.5262264257308433E-01, 0.4466938077796418E+00, 0.1103391769983383E+01, 0.7093206047768255E+00, 0.4399127392187891E+00, 0.6843112870203156E+00, 0.8934568459457148E+00, 0.6490582981441884E+00, 0.3694451726238032E+00, 0.5085572738629487E+00, 0.1488623362931603E+00, 0.9750235054014829E-02, 0.8939776288934402E-02, 0.1364886053450573E+00, 0.1505610868415679E+00, 0.2301225778544498E-01, 0.2515816443301624E+00, 0.1646009972289452E+01, 0.1630679888773521E+01, 0.2362515608142310E+00, 0.8429943526342391E-01, 0.5818602562677768E+00, 0.5155374736992060E+00, 0.1797665269485310E-01, 0.1952851185677853E-01, 0.5600419521166516E+00, 0.7600271971854760E+00, 0.2195137569256029E+00, 0.1208458544696003E+00, 0.4184071984843414E+00, 0.5703477987440417E+00, 0.2727864547293006E+00, 0.3240053608004366E-01, 0.6774373914466536E-01, 0.1404399130020459E+00, 0.1050967099374242E+00, 0.1526865702536626E+00, 0.2040338718098096E+00, 0.1785445001043715E+00, 0.1271971985482246E+00, 0.3166486394939177E-01, 0.4444741998443960E-01, 0.5904153058501098E+00, 0.5776327498150620E+00, 0.3328891237445398E+00, 0.3402556968467140E+00, 0.1160231536652011E+00, 0.1086565805630269E+00, 0.8787251358464724E+00, 0.9382999256694983E+00, 0.8497373197790092E+00, 0.7901625299559836E+00, 0.5668475593321608E+00, 0.6095853796269167E+00, 0.8445503211335190E+00, 0.8018125008387630E+00, 0.2319542476253924E-01, 0.2443177602187348E-01, 0.2290193891046544E+00, 0.2277830378453201E+00, 0.6931459494493321E+00, 0.6969081780841352E+00, 0.8388628986069724E-01, 0.8012406122589412E-01, 0.9342352322344821E-01, 0.9781022865072954E-01, 0.4682830325399513E-02, 0.2961248981181939E-03, 0.5317160915449039E-05, 0.8408398800007548E-04, 0.7876682708462645E-04, 0.0000000000000000E+00, 0.8939776288934402E-02}, + pp: 1, + dmin: 7.8766827084626452E-005, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: -1, + dmin1: 1.2363512593342330E-003, + dmin2: 1.2363512593342330E-003, + dn: 7.8766827084626452E-005, + dn1: 4.3867054272813191E-003, + dn2: 3.7622286348031123E-003, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 3, + sigma: 0.0000000000000000, + nDiv: 62, + zOut: []float64{0.1961759147077164E+01, 0.1819554618764197E+01, 0.1266970995487882E+00, 0.1422045283129674E+00, 0.1909404595024114E+01, 0.1747828967872021E+01, 0.1780101349021133E+00, 0.2882727267008810E+00, 0.1053681278528505E+01, 0.1179068770857534E+01, 0.5510526941411123E-01, 0.5262264257308433E-01, 0.1488199239788061E+01, 0.1103391769983383E+01, 0.2641064704009213E+00, 0.4399127392187891E+00, 0.9987955481685968E+00, 0.8934568459457148E+00, 0.5506279200968747E-01, 0.3694451726238032E+00, 0.1027393205724072E+00, 0.1488623362931603E+00, 0.1310094739466220E-01, 0.8939776288934402E-02, 0.3890417837770681E+00, 0.1505610868415679E+00, 0.1054511738587064E+01, 0.2515816443301624E+00, 0.6604675854498806E+00, 0.1630679888773521E+01, 0.6580113672099847E-01, 0.8429943526342391E-01, 0.4692648488349861E+00, 0.5155374736992060E+00, 0.3162862116895929E-01, 0.1952851185677853E-01, 0.8492444304861170E+00, 0.7600271971854760E+00, 0.8115939841327705E-01, 0.1208458544696003E+00, 0.5215889364108083E+00, 0.5703477987440417E+00, 0.8723974284448969E-02, 0.3240053608004366E-01, 0.2844025089712595E+00, 0.1404399130020459E+00, 0.9585480612390133E-01, 0.1526865702536626E+00, 0.1143545579298620E+00, 0.1785445001043715E+00, 0.1634864466429828E+00, 0.3166486394939177E-01, 0.7598179829516669E+00, 0.5904153058501098E+00, 0.5083170815153470E-01, 0.3328891237445398E+00, 0.9439165813601388E+00, 0.1160231536652011E+00, 0.7910503496831139E+00, 0.8787251358464724E+00, 0.6255345294280562E+00, 0.8497373197790092E+00, 0.7653155273545736E+00, 0.5668475593321608E+00, 0.1024302185414846E+00, 0.8445503211335190E+00, 0.5186166821452450E-01, 0.2319542476253924E-01, 0.8703036703394620E+00, 0.2290193891046544E+00, 0.6681052144545734E-01, 0.6931459494493321E+00, 0.1104992916386881E+00, 0.8388628986069724E-01, 0.3959179295799719E-02, 0.9342352322344821E-01, 0.7289681905152429E-03, 0.4682830325399513E-02, 0.5745324691222600E-06, 0.5317160915449039E-05, 0.7819229461550419E-04, 0.7876682708462645E-04, 0.8723974284448969E-02, 0.8939776288934402E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 7.8192294615504193E-005, + desigOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 4, + nDivOut: 84, + ttypeOut: -4, + dmin1Out: 7.2365102959979382E-004, + dmin2Out: 1.7075768415239889E-002, + dnOut: 7.8192294615504193E-005, + dn1Out: 7.2365102959979382E-004, + dn2Out: 1.7075768415239889E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1961759147077164E+01, 0.1819554618764197E+01, 0.1266970995487882E+00, 0.1422045283129674E+00, 0.1909404595024114E+01, 0.1747828967872021E+01, 0.1780101349021133E+00, 0.2882727267008810E+00, 0.1053681278528505E+01, 0.1179068770857534E+01, 0.5510526941411123E-01, 0.5262264257308433E-01, 0.1488199239788061E+01, 0.1103391769983383E+01, 0.2641064704009213E+00, 0.4399127392187891E+00, 0.9987955481685968E+00, 0.8934568459457148E+00, 0.5506279200968747E-01, 0.3694451726238032E+00, 0.1027393205724072E+00, 0.1488623362931603E+00, 0.1310094739466220E-01, 0.8939776288934402E-02, 0.3890417837770681E+00, 0.1505610868415679E+00, 0.1054511738587064E+01, 0.2515816443301624E+00, 0.6604675854498806E+00, 0.1630679888773521E+01, 0.6580113672099847E-01, 0.8429943526342391E-01, 0.4692648488349861E+00, 0.5155374736992060E+00, 0.3162862116895929E-01, 0.1952851185677853E-01, 0.8492444304861170E+00, 0.7600271971854760E+00, 0.8115939841327705E-01, 0.1208458544696003E+00, 0.5215889364108083E+00, 0.5703477987440417E+00, 0.8723974284448969E-02, 0.3240053608004366E-01, 0.2844025089712595E+00, 0.1404399130020459E+00, 0.9585480612390133E-01, 0.1526865702536626E+00, 0.1143545579298620E+00, 0.1785445001043715E+00, 0.1634864466429828E+00, 0.3166486394939177E-01, 0.7598179829516669E+00, 0.5904153058501098E+00, 0.5083170815153470E-01, 0.3328891237445398E+00, 0.9439165813601388E+00, 0.1160231536652011E+00, 0.7910503496831139E+00, 0.8787251358464724E+00, 0.6255345294280562E+00, 0.8497373197790092E+00, 0.7653155273545736E+00, 0.5668475593321608E+00, 0.1024302185414846E+00, 0.8445503211335190E+00, 0.5186166821452450E-01, 0.2319542476253924E-01, 0.8703036703394620E+00, 0.2290193891046544E+00, 0.6681052144545734E-01, 0.6931459494493321E+00, 0.1104992916386881E+00, 0.8388628986069724E-01, 0.3959179295799719E-02, 0.9342352322344821E-01, 0.7289681905152429E-03, 0.4682830325399513E-02, 0.5745324691222600E-06, 0.5317160915449039E-05, 0.7819229461550419E-04, 0.7876682708462645E-04, 0.8723974284448969E-02, 0.8939776288934402E-02}, + pp: 0, + dmin: 7.8192294615504193E-005, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: -4, + dmin1: 7.2365102959979382E-004, + dmin2: 1.7075768415239889E-002, + dn: 7.8192294615504193E-005, + dn1: 7.2365102959979382E-004, + dn2: 1.7075768415239889E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 4, + sigma: 0.0000000000000000, + nDiv: 84, + zOut: []float64{0.1961759147077164E+01, 0.2088378163269771E+01, 0.1266970995487882E+00, 0.1158391848322702E+00, 0.1909404595024114E+01, 0.1971497461737776E+01, 0.1780101349021133E+00, 0.9513882222772962E-01, 0.1053681278528505E+01, 0.1013569642358705E+01, 0.5510526941411123E-01, 0.8090970429970110E-01, 0.1488199239788061E+01, 0.1671317922533099E+01, 0.2641064704009213E+00, 0.1578325483874163E+00, 0.9987955481685968E+00, 0.8959477084346864E+00, 0.5506279200968747E-01, 0.6314111623521673E-02, 0.1027393205724072E+00, 0.1094480729873660E+00, 0.1310094739466220E-01, 0.4656834793406785E-01, 0.3890417837770681E+00, 0.1396907091073883E+01, 0.1054511738587064E+01, 0.4985806330739840E+00, 0.6604675854498806E+00, 0.2276100057407134E+00, 0.6580113672099847E-01, 0.1356625794022653E+00, 0.4692648488349861E+00, 0.3651528072454984E+00, 0.3162862116895929E-01, 0.7355942454424362E-01, 0.8492444304861170E+00, 0.8567663209989688E+00, 0.8115939841327705E-01, 0.4940885660487250E-01, 0.5215889364108083E+00, 0.4808259707342031E+00, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.2844025089712595E+00, 0.3750191107685802E+00, 0.9585480612390133E-01, 0.2922900104287094E-01, 0.1143545579298620E+00, 0.2485339201737921E+00, 0.1634864466429828E+00, 0.4998108187459615E+00, 0.7598179829516669E+00, 0.3107607890010585E+00, 0.5083170815153470E-01, 0.1543981540828483E+00, 0.9439165813601388E+00, 0.1580490693604223E+01, 0.7910503496831139E+00, 0.3130858727896049E+00, 0.6255345294280562E+00, 0.1077686100636843E+01, 0.7653155273545736E+00, 0.7274051012980143E-01, 0.1024302185414846E+00, 0.8147329327002600E-01, 0.5186166821452450E-01, 0.5539901283655780E+00, 0.8703036703394620E+00, 0.3830459800631597E+00, 0.6681052144545734E-01, 0.1927318305890360E-01, 0.1104992916386881E+00, 0.9510720451940254E-01, 0.3959179295799719E-02, 0.3034592154998885E-04, 0.7289681905152429E-03, 0.6211134452527084E-03, 0.5745324691222600E-06, 0.7232819130731082E-07, 0.7819229461550419E-04, 0.3661024252896476E-07, 0.8723974284448969E-02, 0.5160120970399038E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 3.6610242528964756E-008, + desigOut: 0.0000000000000000, + sigmaOut: 7.8083356181667918E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 5, + nDivOut: 106, + ttypeOut: -2, + dmin1Out: 6.2053891278358614E-004, + dmin2Out: 2.9611625055501498E-002, + dnOut: 3.6610242528964756E-008, + dn1Out: 6.2053891278358614E-004, + dn2Out: 9.1148025223602810E-002, + gOut: 0.0000000000000000, + tauOut: 7.8083356181667918E-005, + }, + { + i0: 1, + n0: 21, + z: []float64{0.1961759147077164E+01, 0.2088378163269771E+01, 0.1266970995487882E+00, 0.1158391848322702E+00, 0.1909404595024114E+01, 0.1971497461737776E+01, 0.1780101349021133E+00, 0.9513882222772962E-01, 0.1053681278528505E+01, 0.1013569642358705E+01, 0.5510526941411123E-01, 0.8090970429970110E-01, 0.1488199239788061E+01, 0.1671317922533099E+01, 0.2641064704009213E+00, 0.1578325483874163E+00, 0.9987955481685968E+00, 0.8959477084346864E+00, 0.5506279200968747E-01, 0.6314111623521673E-02, 0.1027393205724072E+00, 0.1094480729873660E+00, 0.1310094739466220E-01, 0.4656834793406785E-01, 0.3890417837770681E+00, 0.1396907091073883E+01, 0.1054511738587064E+01, 0.4985806330739840E+00, 0.6604675854498806E+00, 0.2276100057407134E+00, 0.6580113672099847E-01, 0.1356625794022653E+00, 0.4692648488349861E+00, 0.3651528072454984E+00, 0.3162862116895929E-01, 0.7355942454424362E-01, 0.8492444304861170E+00, 0.8567663209989688E+00, 0.8115939841327705E-01, 0.4940885660487250E-01, 0.5215889364108083E+00, 0.4808259707342031E+00, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.2844025089712595E+00, 0.3750191107685802E+00, 0.9585480612390133E-01, 0.2922900104287094E-01, 0.1143545579298620E+00, 0.2485339201737921E+00, 0.1634864466429828E+00, 0.4998108187459615E+00, 0.7598179829516669E+00, 0.3107607890010585E+00, 0.5083170815153470E-01, 0.1543981540828483E+00, 0.9439165813601388E+00, 0.1580490693604223E+01, 0.7910503496831139E+00, 0.3130858727896049E+00, 0.6255345294280562E+00, 0.1077686100636843E+01, 0.7653155273545736E+00, 0.7274051012980143E-01, 0.1024302185414846E+00, 0.8147329327002600E-01, 0.5186166821452450E-01, 0.5539901283655780E+00, 0.8703036703394620E+00, 0.3830459800631597E+00, 0.6681052144545734E-01, 0.1927318305890360E-01, 0.1104992916386881E+00, 0.9510720451940254E-01, 0.3959179295799719E-02, 0.3034592154998885E-04, 0.7289681905152429E-03, 0.6211134452527084E-03, 0.5745324691222600E-06, 0.7232819130731082E-07, 0.7819229461550419E-04, 0.3661024252896476E-07, 0.8723974284448969E-02, 0.5160120970399038E-02}, + pp: 1, + dmin: 3.6610242528964756E-008, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 6.2053891278358614E-004, + dmin2: 2.9611625055501498E-002, + dn: 3.6610242528964756E-008, + dn1: 6.2053891278358614E-004, + dn2: 9.1148025223602810E-002, + g: 0.0000000000000000, + tau: 7.8083356181667918E-005, + nFail: 0, + iter: 5, + sigma: 7.8083356181667918E-005, + nDiv: 106, + zOut: []float64{0.2204217311496068E+01, 0.2088378163269771E+01, 0.1036089580076783E+00, 0.1158391848322702E+00, 0.1963027289351853E+01, 0.1971497461737776E+01, 0.4912301654839819E-01, 0.9513882222772962E-01, 0.1045356293504034E+01, 0.1013569642358705E+01, 0.1293586117415210E+00, 0.8090970429970110E-01, 0.1699791822573021E+01, 0.1671317922533099E+01, 0.8319236989271818E-01, 0.1578325483874163E+00, 0.8190694135595162E+00, 0.8959477084346864E+00, 0.8437225690290790E-03, 0.6314111623521673E-02, 0.1551726617464312E+00, 0.1094480729873660E+00, 0.4192211096758560E+00, 0.4656834793406785E-01, 0.1476266577866037E+01, 0.1396907091073883E+01, 0.7687090018675194E-01, 0.4985806330739840E+00, 0.2864016483502532E+00, 0.2276100057407134E+00, 0.1729653861709652E+00, 0.1356625794022653E+00, 0.2657468090128033E+00, 0.3651528072454984E+00, 0.2371551996266359E+00, 0.7355942454424362E-01, 0.6690199413712319E+00, 0.8567663209989688E+00, 0.3551024412099299E-01, 0.4940885660487250E-01, 0.4504758109776356E+00, 0.4808259707342031E+00, 0.4295777776785939E-02, 0.5160120970399038E-02, 0.3999522974286917E+00, 0.3750191107685802E+00, 0.1816316160365039E-01, 0.2922900104287094E-01, 0.7301815407101296E+00, 0.2485339201737921E+00, 0.2127164214993764E+00, 0.4998108187459615E+00, 0.2524424849785568E+00, 0.3107607890010585E+00, 0.9666552191416621E+00, 0.1543981540828483E+00, 0.9269213106461920E+00, 0.1580490693604223E+01, 0.3640096408786760E+00, 0.3130858727896049E+00, 0.7864169332819952E+00, 0.1077686100636843E+01, 0.7535963003344312E-02, 0.7274051012980143E-01, 0.6279274220262862E+00, 0.8147329327002600E-01, 0.3379430237022286E+00, 0.5539901283655780E+00, 0.6437610281386123E-01, 0.3830459800631597E+00, 0.2847358698029713E-01, 0.1927318305890360E-01, 0.6666392685468185E-01, 0.9510720451940254E-01, 0.2827355178816361E-06, 0.3034592154998885E-04, 0.6208664319525956E-03, 0.6211134452527084E-03, 0.4264931214133004E-11, 0.7232819130731082E-07, 0.4059351646211308E-14, 0.3661024252896476E-07, 0.8437225690290790E-03, 0.5160120970399038E-02}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 4.0593516462113082E-015, + desigOut: 4.3344264097778650E-021, + sigmaOut: 7.8119962155206313E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 6, + nDivOut: 128, + ttypeOut: -2, + dmin1Out: 6.2079410376128833E-004, + dmin2Out: 4.5102919754957636E-002, + dnOut: 4.0593516462113082E-015, + dn1Out: 6.2079410376128833E-004, + dn2Out: 6.6633580933131861E-002, + gOut: 0.0000000000000000, + tauOut: 3.6605973538398975E-008, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2204217311496068E+01, 0.2088378163269771E+01, 0.1036089580076783E+00, 0.1158391848322702E+00, 0.1963027289351853E+01, 0.1971497461737776E+01, 0.4912301654839819E-01, 0.9513882222772962E-01, 0.1045356293504034E+01, 0.1013569642358705E+01, 0.1293586117415210E+00, 0.8090970429970110E-01, 0.1699791822573021E+01, 0.1671317922533099E+01, 0.8319236989271818E-01, 0.1578325483874163E+00, 0.8190694135595162E+00, 0.8959477084346864E+00, 0.8437225690290790E-03, 0.6314111623521673E-02, 0.1551726617464312E+00, 0.1094480729873660E+00, 0.4192211096758560E+00, 0.4656834793406785E-01, 0.1476266577866037E+01, 0.1396907091073883E+01, 0.7687090018675194E-01, 0.4985806330739840E+00, 0.2864016483502532E+00, 0.2276100057407134E+00, 0.1729653861709652E+00, 0.1356625794022653E+00, 0.2657468090128033E+00, 0.3651528072454984E+00, 0.2371551996266359E+00, 0.7355942454424362E-01, 0.6690199413712319E+00, 0.8567663209989688E+00, 0.3551024412099299E-01, 0.4940885660487250E-01, 0.4504758109776356E+00, 0.4808259707342031E+00, 0.4295777776785939E-02, 0.5160120970399038E-02, 0.3999522974286917E+00, 0.3750191107685802E+00, 0.1816316160365039E-01, 0.2922900104287094E-01, 0.7301815407101296E+00, 0.2485339201737921E+00, 0.2127164214993764E+00, 0.4998108187459615E+00, 0.2524424849785568E+00, 0.3107607890010585E+00, 0.9666552191416621E+00, 0.1543981540828483E+00, 0.9269213106461920E+00, 0.1580490693604223E+01, 0.3640096408786760E+00, 0.3130858727896049E+00, 0.7864169332819952E+00, 0.1077686100636843E+01, 0.7535963003344312E-02, 0.7274051012980143E-01, 0.6279274220262862E+00, 0.8147329327002600E-01, 0.3379430237022286E+00, 0.5539901283655780E+00, 0.6437610281386123E-01, 0.3830459800631597E+00, 0.2847358698029713E-01, 0.1927318305890360E-01, 0.6666392685468185E-01, 0.9510720451940254E-01, 0.2827355178816361E-06, 0.3034592154998885E-04, 0.6208664319525956E-03, 0.6211134452527084E-03, 0.4264931214133004E-11, 0.7232819130731082E-07, 0.4059351646211308E-14, 0.3661024252896476E-07, 0.8437225690290790E-03, 0.5160120970399038E-02}, + pp: 0, + dmin: 4.0593516462113082E-015, + desig: 4.3344264097778650E-021, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 6.2079410376128833E-004, + dmin2: 4.5102919754957636E-002, + dn: 4.0593516462113082E-015, + dn1: 6.2079410376128833E-004, + dn2: 6.6633580933131861E-002, + g: 0.0000000000000000, + tau: 3.6605973538398975E-008, + nFail: 0, + iter: 6, + sigma: 7.8119962155206313E-005, + nDiv: 128, + zOut: []float64{0.2204217311496068E+01, 0.2307826269503742E+01, 0.1036089580076783E+00, 0.8812934261040264E-01, 0.1963027289351853E+01, 0.1924020963289845E+01, 0.4912301654839819E-01, 0.2668944646890268E-01, 0.1045356293504034E+01, 0.1148025458776649E+01, 0.1293586117415210E+00, 0.1915312145184878E+00, 0.1699791822573021E+01, 0.1591452977947247E+01, 0.8319236989271818E-01, 0.4281642408847453E-01, 0.8190694135595162E+00, 0.7770967120400667E+00, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1551726617464312E+00, 0.5742252947387723E+00, 0.4192211096758560E+00, 0.1077768810640642E+01, 0.1476266577866037E+01, 0.4753686674121431E+00, 0.7687090018675194E-01, 0.4631342794110950E-01, 0.2864016483502532E+00, 0.4130536065801048E+00, 0.1729653861709652E+00, 0.1112809541240190E+00, 0.2657468090128033E+00, 0.3916210545154161E+00, 0.2371551996266359E+00, 0.4051405202062471E+00, 0.6690199413712319E+00, 0.2993896652859737E+00, 0.3551024412099299E-01, 0.5343038813025977E-01, 0.4504758109776356E+00, 0.4013412006241577E+00, 0.4295777776785939E-02, 0.4280911574482486E-02, 0.3999522974286917E+00, 0.4138345474578556E+00, 0.1816316160365039E-01, 0.3204760309498118E-01, 0.7301815407101296E+00, 0.9108503591145208E+00, 0.2127164214993764E+00, 0.5895442813598011E-01, 0.2524424849785568E+00, 0.1160143275984235E+01, 0.9666552191416621E+00, 0.7723298847804961E+00, 0.9269213106461920E+00, 0.5186010667443678E+00, 0.3640096408786760E+00, 0.5519914319921668E+00, 0.7864169332819952E+00, 0.2419614642931688E+00, 0.7535963003344312E-02, 0.1955698951896722E-01, 0.6279274220262862E+00, 0.9463134562095434E+00, 0.3379430237022286E+00, 0.2298969194226957E-01, 0.6437610281386123E-01, 0.6985999785188474E-01, 0.2847358698029713E-01, 0.2717093011896993E-01, 0.6666392685468185E-01, 0.3949327947122574E-01, 0.2827355178816361E-06, 0.4444831994804014E-08, 0.6208664319525956E-03, 0.6208619913814727E-03, 0.4264931214133004E-11, 0.2788519153273688E-22, 0.4059351646211308E-14, 0.3786532345060857E-28, 0.8437225690290790E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 0, + dminOut: 3.7865323450608567E-029, + desigOut: -5.4012504887129591E-021, + sigmaOut: 7.8119962159265674E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 7, + nDivOut: 150, + ttypeOut: -2, + dmin1Out: 6.2086198711654151E-004, + dmin2Out: 3.9492996735707858E-002, + dnOut: 3.7865323450608567E-029, + dn1Out: 6.2086198711654151E-004, + dn2Out: 3.9492996735707858E-002, + gOut: 0.0000000000000000, + tauOut: 4.0593516183260787E-015, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2204217311496068E+01, 0.2307826269503742E+01, 0.1036089580076783E+00, 0.8812934261040264E-01, 0.1963027289351853E+01, 0.1924020963289845E+01, 0.4912301654839819E-01, 0.2668944646890268E-01, 0.1045356293504034E+01, 0.1148025458776649E+01, 0.1293586117415210E+00, 0.1915312145184878E+00, 0.1699791822573021E+01, 0.1591452977947247E+01, 0.8319236989271818E-01, 0.4281642408847453E-01, 0.8190694135595162E+00, 0.7770967120400667E+00, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1551726617464312E+00, 0.5742252947387723E+00, 0.4192211096758560E+00, 0.1077768810640642E+01, 0.1476266577866037E+01, 0.4753686674121431E+00, 0.7687090018675194E-01, 0.4631342794110950E-01, 0.2864016483502532E+00, 0.4130536065801048E+00, 0.1729653861709652E+00, 0.1112809541240190E+00, 0.2657468090128033E+00, 0.3916210545154161E+00, 0.2371551996266359E+00, 0.4051405202062471E+00, 0.6690199413712319E+00, 0.2993896652859737E+00, 0.3551024412099299E-01, 0.5343038813025977E-01, 0.4504758109776356E+00, 0.4013412006241577E+00, 0.4295777776785939E-02, 0.4280911574482486E-02, 0.3999522974286917E+00, 0.4138345474578556E+00, 0.1816316160365039E-01, 0.3204760309498118E-01, 0.7301815407101296E+00, 0.9108503591145208E+00, 0.2127164214993764E+00, 0.5895442813598011E-01, 0.2524424849785568E+00, 0.1160143275984235E+01, 0.9666552191416621E+00, 0.7723298847804961E+00, 0.9269213106461920E+00, 0.5186010667443678E+00, 0.3640096408786760E+00, 0.5519914319921668E+00, 0.7864169332819952E+00, 0.2419614642931688E+00, 0.7535963003344312E-02, 0.1955698951896722E-01, 0.6279274220262862E+00, 0.9463134562095434E+00, 0.3379430237022286E+00, 0.2298969194226957E-01, 0.6437610281386123E-01, 0.6985999785188474E-01, 0.2847358698029713E-01, 0.2717093011896993E-01, 0.6666392685468185E-01, 0.3949327947122574E-01, 0.2827355178816361E-06, 0.4444831994804014E-08, 0.6208664319525956E-03, 0.6208619913814727E-03, 0.4264931214133004E-11, 0.2788519153273688E-22, 0.4059351646211308E-14, 0.3786532345060857E-28, 0.8437225690290790E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 3.7865323450608567E-029, + desig: -5.4012504887129591E-021, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 6.2086198711654151E-004, + dmin2: 3.9492996735707858E-002, + dn: 3.7865323450608567E-029, + dn1: 6.2086198711654151E-004, + dn2: 3.9492996735707858E-002, + g: 0.0000000000000000, + tau: 4.0593516183260787E-015, + nFail: 0, + iter: 7, + sigma: 7.8119962159265674E-005, + nDiv: 150, + zOut: []float64{0.2395955612114145E+01, 0.2307826269503742E+01, 0.7077038564739886E-01, 0.8812934261040264E-01, 0.1879940024111348E+01, 0.1924020963289845E+01, 0.1629847954401656E-01, 0.2668944646890268E-01, 0.1323258193751120E+01, 0.1148025458776649E+01, 0.2303502998543534E+00, 0.1915312145184878E+00, 0.1403919102181368E+01, 0.1591452977947247E+01, 0.2369972908607684E-01, 0.4281642408847453E-01, 0.7535654596375009E+00, 0.7770967120400667E+00, 0.1283811140869274E-03, 0.1684766835109566E-03, 0.1651865724265327E+01, 0.5742252947387723E+00, 0.3101568824672333E+00, 0.1077768810640642E+01, 0.2115252128860193E+00, 0.4753686674121431E+00, 0.9043805314343908E-01, 0.4631342794110950E-01, 0.4338965075606848E+00, 0.4130536065801048E+00, 0.1004386157577793E+00, 0.1112809541240190E+00, 0.6963229589638840E+00, 0.3916210545154161E+00, 0.1741934301847783E+00, 0.4051405202062471E+00, 0.1786266232314551E+00, 0.2993896652859737E+00, 0.1200482645536405E+00, 0.5343038813025977E-01, 0.2855738476449996E+00, 0.4013412006241577E+00, 0.6203611145567293E-02, 0.4280911574482486E-02, 0.4396785394072695E+00, 0.4138345474578556E+00, 0.6639071087521134E-01, 0.3204760309498118E-01, 0.9034140763752896E+00, 0.9108503591145208E+00, 0.7570790092830114E-01, 0.5895442813598011E-01, 0.1856765259836430E+01, 0.1160143275984235E+01, 0.2157144528657351E+00, 0.7723298847804961E+00, 0.8548780458707995E+00, 0.5186010667443678E+00, 0.1562335771835849E+00, 0.5519914319921668E+00, 0.1052848766285511E+00, 0.2419614642931688E+00, 0.1757806338135458E+00, 0.1955698951896722E-01, 0.7935225143382671E+00, 0.9463134562095434E+00, 0.2023962522401480E-02, 0.2298969194226957E-01, 0.9500696544845319E-01, 0.6985999785188474E-01, 0.1129463646814219E-01, 0.2717093011896993E-01, 0.2819864744791555E-01, 0.3949327947122574E-01, 0.9786381594178541E-10, 0.4444831994804014E-08, 0.6208618935176568E-03, 0.6208619913814727E-03, 0.1700670967075909E-47, 0.2788519153273688E-22, 0.3786532345060857E-28, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 21, + ppOut: 1, + dminOut: 3.7865323450608567E-029, + desigOut: -5.4012504887129591E-021, + sigmaOut: 7.8119962159265674E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 8, + nDivOut: 172, + ttypeOut: -2, + dmin1Out: 6.2086189351765679E-004, + dmin2Out: 2.8198643003083550E-002, + dnOut: 3.7865323450608567E-029, + dn1Out: 6.2086189351765679E-004, + dn2Out: 2.8198643003083550E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 21, + z: []float64{0.2395955612114145E+01, 0.2307826269503742E+01, 0.7077038564739886E-01, 0.8812934261040264E-01, 0.1879940024111348E+01, 0.1924020963289845E+01, 0.1629847954401656E-01, 0.2668944646890268E-01, 0.1323258193751120E+01, 0.1148025458776649E+01, 0.2303502998543534E+00, 0.1915312145184878E+00, 0.1403919102181368E+01, 0.1591452977947247E+01, 0.2369972908607684E-01, 0.4281642408847453E-01, 0.7535654596375009E+00, 0.7770967120400667E+00, 0.1283811140869274E-03, 0.1684766835109566E-03, 0.1651865724265327E+01, 0.5742252947387723E+00, 0.3101568824672333E+00, 0.1077768810640642E+01, 0.2115252128860193E+00, 0.4753686674121431E+00, 0.9043805314343908E-01, 0.4631342794110950E-01, 0.4338965075606848E+00, 0.4130536065801048E+00, 0.1004386157577793E+00, 0.1112809541240190E+00, 0.6963229589638840E+00, 0.3916210545154161E+00, 0.1741934301847783E+00, 0.4051405202062471E+00, 0.1786266232314551E+00, 0.2993896652859737E+00, 0.1200482645536405E+00, 0.5343038813025977E-01, 0.2855738476449996E+00, 0.4013412006241577E+00, 0.6203611145567293E-02, 0.4280911574482486E-02, 0.4396785394072695E+00, 0.4138345474578556E+00, 0.6639071087521134E-01, 0.3204760309498118E-01, 0.9034140763752896E+00, 0.9108503591145208E+00, 0.7570790092830114E-01, 0.5895442813598011E-01, 0.1856765259836430E+01, 0.1160143275984235E+01, 0.2157144528657351E+00, 0.7723298847804961E+00, 0.8548780458707995E+00, 0.5186010667443678E+00, 0.1562335771835849E+00, 0.5519914319921668E+00, 0.1052848766285511E+00, 0.2419614642931688E+00, 0.1757806338135458E+00, 0.1955698951896722E-01, 0.7935225143382671E+00, 0.9463134562095434E+00, 0.2023962522401480E-02, 0.2298969194226957E-01, 0.9500696544845319E-01, 0.6985999785188474E-01, 0.1129463646814219E-01, 0.2717093011896993E-01, 0.2819864744791555E-01, 0.3949327947122574E-01, 0.9786381594178541E-10, 0.4444831994804014E-08, 0.6208618935176568E-03, 0.6208619913814727E-03, 0.1700670967075909E-47, 0.2788519153273688E-22, 0.3786532345060857E-28, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 3.7865323450608567E-029, + desig: -5.4012504887129591E-021, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 6.2086189351765679E-004, + dmin2: 2.8198643003083550E-002, + dn: 3.7865323450608567E-029, + dn1: 6.2086189351765679E-004, + dn2: 2.8198643003083550E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 8, + sigma: 7.8119962159265674E-005, + nDiv: 172, + zOut: []float64{0.2395955612114145E+01, 0.2466725997761544E+01, 0.7077038564739886E-01, 0.5393549207373363E-01, 0.1879940024111348E+01, 0.1842303011581631E+01, 0.1629847954401656E-01, 0.1170659574821484E-01, 0.1323258193751120E+01, 0.1541901897857258E+01, 0.2303502998543534E+00, 0.2097365510789915E+00, 0.1403919102181368E+01, 0.1217882280188454E+01, 0.2369972908607684E-01, 0.1466422291592108E-01, 0.7535654596375009E+00, 0.7390296178356669E+00, 0.1283811140869274E-03, 0.2869551596920546E-03, 0.1651865724265327E+01, 0.1961735651572868E+01, 0.3101568824672333E+00, 0.3344283443049241E-01, 0.2115252128860193E+00, 0.2685204315989660E+00, 0.9043805314343908E-01, 0.1461369444993732E+00, 0.4338965075606848E+00, 0.3881981788190908E+00, 0.1004386157577793E+00, 0.1801598202532681E+00, 0.6963229589638840E+00, 0.6903565688953941E+00, 0.1741934301847783E+00, 0.4507175802324546E-01, 0.1786266232314551E+00, 0.2536031297618502E+00, 0.1200482645536405E+00, 0.1351822623162481E+00, 0.2855738476449996E+00, 0.1565951964743188E+00, 0.6203611145567293E-02, 0.1741812487831326E-01, 0.4396785394072695E+00, 0.4886511254041676E+00, 0.6639071087521134E-01, 0.1227425859208231E+00, 0.9034140763752896E+00, 0.8563793913827676E+00, 0.7570790092830114E-01, 0.1641466407918003E+00, 0.1856765259836430E+01, 0.1908333071910365E+01, 0.2157144528657351E+00, 0.9663383852973971E-01, 0.8548780458707995E+00, 0.9144777845246447E+00, 0.1562335771835849E+00, 0.1798735100772441E-01, 0.1052848766285511E+00, 0.2630781594343725E+00, 0.1757806338135458E+00, 0.5302070335887964E+00, 0.7935225143382671E+00, 0.2653394432718723E+00, 0.2023962522401480E-02, 0.7246963929058098E-03, 0.9500696544845319E-01, 0.1055769055236896E+00, 0.1129463646814219E-01, 0.3016696409481782E-02, 0.2819864744791555E-01, 0.2518195113629758E-01, 0.9786381594178541E-10, 0.2412835834031154E-11, 0.6208618935176568E-03, 0.6208618911048210E-03, 0.1700670967075909E-47, 0.2869551596920546E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 6.2086189110482101E-004, + desigOut: -5.4012504887129591E-021, + sigmaOut: 7.8119962159265674E-005, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 9, + nDivOut: 193, + ttypeOut: -7, + dmin1Out: 2.5181951038433764E-002, + dmin2Out: 8.7297525620826724E-002, + dnOut: 6.2086189110482101E-004, + dn1Out: 2.5181951038433764E-002, + dn2Out: 9.4282269055547374E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2395955612114145E+01, 0.2466725997761544E+01, 0.7077038564739886E-01, 0.5393549207373363E-01, 0.1879940024111348E+01, 0.1842303011581631E+01, 0.1629847954401656E-01, 0.1170659574821484E-01, 0.1323258193751120E+01, 0.1541901897857258E+01, 0.2303502998543534E+00, 0.2097365510789915E+00, 0.1403919102181368E+01, 0.1217882280188454E+01, 0.2369972908607684E-01, 0.1466422291592108E-01, 0.7535654596375009E+00, 0.7390296178356669E+00, 0.1283811140869274E-03, 0.2869551596920546E-03, 0.1651865724265327E+01, 0.1961735651572868E+01, 0.3101568824672333E+00, 0.3344283443049241E-01, 0.2115252128860193E+00, 0.2685204315989660E+00, 0.9043805314343908E-01, 0.1461369444993732E+00, 0.4338965075606848E+00, 0.3881981788190908E+00, 0.1004386157577793E+00, 0.1801598202532681E+00, 0.6963229589638840E+00, 0.6903565688953941E+00, 0.1741934301847783E+00, 0.4507175802324546E-01, 0.1786266232314551E+00, 0.2536031297618502E+00, 0.1200482645536405E+00, 0.1351822623162481E+00, 0.2855738476449996E+00, 0.1565951964743188E+00, 0.6203611145567293E-02, 0.1741812487831326E-01, 0.4396785394072695E+00, 0.4886511254041676E+00, 0.6639071087521134E-01, 0.1227425859208231E+00, 0.9034140763752896E+00, 0.8563793913827676E+00, 0.7570790092830114E-01, 0.1641466407918003E+00, 0.1856765259836430E+01, 0.1908333071910365E+01, 0.2157144528657351E+00, 0.9663383852973971E-01, 0.8548780458707995E+00, 0.9144777845246447E+00, 0.1562335771835849E+00, 0.1798735100772441E-01, 0.1052848766285511E+00, 0.2630781594343725E+00, 0.1757806338135458E+00, 0.5302070335887964E+00, 0.7935225143382671E+00, 0.2653394432718723E+00, 0.2023962522401480E-02, 0.7246963929058098E-03, 0.9500696544845319E-01, 0.1055769055236896E+00, 0.1129463646814219E-01, 0.3016696409481782E-02, 0.2819864744791555E-01, 0.2518195113629758E-01, 0.9786381594178541E-10, 0.2412835834031154E-11, 0.6208618935176568E-03, 0.6208618911048210E-03, 0.1700670967075909E-47, 0.2869551596920546E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 6.2086189110482101E-004, + desig: -5.4012504887129591E-021, + qmax: 1.8900334961849885, + ttype: -7, + dmin1: 2.5181951038433764E-002, + dmin2: 8.7297525620826724E-002, + dn: 6.2086189110482101E-004, + dn1: 2.5181951038433764E-002, + dn2: 9.4282269055547374E-002, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 9, + sigma: 7.8119962159265674E-005, + nDiv: 193, + zOut: []float64{0.2520040627944239E+01, 0.2466725997761544E+01, 0.3943012599746679E-01, 0.5393549207373363E-01, 0.1813958619441340E+01, 0.1842303011581631E+01, 0.9950845630193767E-02, 0.1170659574821484E-01, 0.1741066741415017E+01, 0.1541901897857258E+01, 0.1467114516582776E+00, 0.2097365510789915E+00, 0.1085214189555058E+01, 0.1217882280188454E+01, 0.9986318978978259E-02, 0.1466422291592108E-01, 0.7287093921253419E+00, 0.7390296178356669E+00, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.1993785121145770E+01, 0.1961735651572868E+01, 0.4504038193447841E-02, 0.3344283443049241E-01, 0.4095324760138526E+00, 0.2685204315989660E+00, 0.1385240464077977E+00, 0.1461369444993732E+00, 0.4292130907735224E+00, 0.3881981788190908E+00, 0.2897733504323247E+00, 0.1801598202532681E+00, 0.4450341145952761E+00, 0.6903565688953941E+00, 0.2568418582687495E-01, 0.4507175802324546E-01, 0.3624803443601846E+00, 0.2536031297618502E+00, 0.5840011260368079E-01, 0.1351822623162481E+00, 0.1149923468579125E+00, 0.1565951964743188E+00, 0.7401698075381481E-01, 0.1741812487831326E-01, 0.5367558686801371E+00, 0.4886511254041676E+00, 0.1958324578473516E+00, 0.1227425859208231E+00, 0.8240727124361776E+00, 0.8563793913827676E+00, 0.3801199318200257E+00, 0.1641466407918003E+00, 0.1624226116729040E+01, 0.1908333071910365E+01, 0.5440714051978934E-01, 0.9663383852973971E-01, 0.8774371331215411E+00, 0.9144777845246447E+00, 0.5393069221241477E-02, 0.1798735100772441E-01, 0.7872712619108886E+00, 0.2630781594343725E+00, 0.1786993199393658E+00, 0.5302070335887964E+00, 0.8674395783437358E-01, 0.2653394432718723E+00, 0.8820349511059155E-03, 0.7246963929058098E-03, 0.1070907050910267E+00, 0.1055769055236896E+00, 0.7093640994523618E-03, 0.3016696409481782E-02, 0.2385172514821930E-01, 0.2518195113629758E-01, 0.6280626703238275E-13, 0.2412835834031154E-11, 0.3257377007015450E-14, 0.6208618911048210E-03, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 3.2573770070154495E-015, + desigOut: 2.1703803823424652E-020, + sigmaOut: 6.9898185319802297E-004, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 10, + nDivOut: 214, + ttypeOut: -2, + dmin1Out: 2.3851725145806461E-002, + dmin2Out: 8.6019261441467765E-002, + dnOut: 3.2573770070154495E-015, + dn1Out: 2.3851725145806461E-002, + dn2Out: 0.10407400868154487, + gOut: 0.0000000000000000, + tauOut: 6.2086189103875732E-004, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2520040627944239E+01, 0.2466725997761544E+01, 0.3943012599746679E-01, 0.5393549207373363E-01, 0.1813958619441340E+01, 0.1842303011581631E+01, 0.9950845630193767E-02, 0.1170659574821484E-01, 0.1741066741415017E+01, 0.1541901897857258E+01, 0.1467114516582776E+00, 0.2097365510789915E+00, 0.1085214189555058E+01, 0.1217882280188454E+01, 0.9986318978978259E-02, 0.1466422291592108E-01, 0.7287093921253419E+00, 0.7390296178356669E+00, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.1993785121145770E+01, 0.1961735651572868E+01, 0.4504038193447841E-02, 0.3344283443049241E-01, 0.4095324760138526E+00, 0.2685204315989660E+00, 0.1385240464077977E+00, 0.1461369444993732E+00, 0.4292130907735224E+00, 0.3881981788190908E+00, 0.2897733504323247E+00, 0.1801598202532681E+00, 0.4450341145952761E+00, 0.6903565688953941E+00, 0.2568418582687495E-01, 0.4507175802324546E-01, 0.3624803443601846E+00, 0.2536031297618502E+00, 0.5840011260368079E-01, 0.1351822623162481E+00, 0.1149923468579125E+00, 0.1565951964743188E+00, 0.7401698075381481E-01, 0.1741812487831326E-01, 0.5367558686801371E+00, 0.4886511254041676E+00, 0.1958324578473516E+00, 0.1227425859208231E+00, 0.8240727124361776E+00, 0.8563793913827676E+00, 0.3801199318200257E+00, 0.1641466407918003E+00, 0.1624226116729040E+01, 0.1908333071910365E+01, 0.5440714051978934E-01, 0.9663383852973971E-01, 0.8774371331215411E+00, 0.9144777845246447E+00, 0.5393069221241477E-02, 0.1798735100772441E-01, 0.7872712619108886E+00, 0.2630781594343725E+00, 0.1786993199393658E+00, 0.5302070335887964E+00, 0.8674395783437358E-01, 0.2653394432718723E+00, 0.8820349511059155E-03, 0.7246963929058098E-03, 0.1070907050910267E+00, 0.1055769055236896E+00, 0.7093640994523618E-03, 0.3016696409481782E-02, 0.2385172514821930E-01, 0.2518195113629758E-01, 0.6280626703238275E-13, 0.2412835834031154E-11, 0.3257377007015450E-14, 0.6208618911048210E-03, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 3.2573770070154495E-015, + desig: 2.1703803823424652E-020, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 2.3851725145806461E-002, + dmin2: 8.6019261441467765E-002, + dn: 3.2573770070154495E-015, + dn1: 2.3851725145806461E-002, + dn2: 0.10407400868154487, + g: 0.0000000000000000, + tau: 6.2086189103875732E-004, + nFail: 0, + iter: 10, + sigma: 6.9898185319802297E-004, + nDiv: 214, + zOut: []float64{0.2520040627944239E+01, 0.2559470753941703E+01, 0.3943012599746679E-01, 0.2794508075882943E-01, 0.1813958619441340E+01, 0.1795964384312701E+01, 0.9950845630193767E-02, 0.9646675917972324E-02, 0.1741066741415017E+01, 0.1878131517155319E+01, 0.1467114516582776E+00, 0.8477220453173254E-01, 0.1085214189555058E+01, 0.1010428304002300E+01, 0.9986318978978259E-02, 0.7202019583097946E-02, 0.7287093921253419E+00, 0.7222798755087921E+00, 0.7725029665513934E-03, 0.2132421202606784E-02, 0.1993785121145770E+01, 0.1996156738136608E+01, 0.4504038193447841E-02, 0.9240506410060376E-03, 0.4095324760138526E+00, 0.5471324717806409E+00, 0.1385240464077977E+00, 0.1086689918286978E+00, 0.4292130907735224E+00, 0.6103174493771462E+00, 0.2897733504323247E+00, 0.2112982785836522E+00, 0.4450341145952761E+00, 0.2594200218384955E+00, 0.2568418582687495E-01, 0.3588779484774172E-01, 0.3624803443601846E+00, 0.3849926621161204E+00, 0.5840011260368079E-01, 0.1744336104525046E-01, 0.1149923468579125E+00, 0.1715659665664736E+00, 0.7401698075381481E-01, 0.2315671901408358E+00, 0.5367558686801371E+00, 0.5010211363866497E+00, 0.1958324578473516E+00, 0.3221025481782661E+00, 0.8240727124361776E+00, 0.8820900960779340E+00, 0.3801199318200257E+00, 0.6999293195746292E+00, 0.1624226116729040E+01, 0.9787039376741966E+00, 0.5440714051978934E-01, 0.4877761656142095E-01, 0.8774371331215411E+00, 0.8340525857813585E+00, 0.5393069221241477E-02, 0.5090576402208483E-02, 0.7872712619108886E+00, 0.9608800054480426E+00, 0.1786993199393658E+00, 0.1613217694817542E-01, 0.8674395783437358E-01, 0.7149381583730083E-01, 0.8820349511059155E-03, 0.1321201613351008E-02, 0.1070907050910267E+00, 0.1064788675771248E+00, 0.7093640994523618E-03, 0.1589006148839502E-03, 0.2385172514821930E-01, 0.2369282453339490E-01, 0.6280626703238275E-13, 0.8634837515442557E-26, 0.3257377007015450E-14, 0.9466330862652142E-28, 0.7725029665513934E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 20, + ppOut: 0, + dminOut: 9.4663308626521417E-029, + desigOut: 2.1703795093889875E-020, + sigmaOut: 6.9898185320128035E-004, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 11, + nDivOut: 235, + ttypeOut: -2, + dmin1Out: 2.3692824533332088E-002, + dmin2Out: 7.0611780886194908E-002, + dnOut: 9.4663308626521417E-029, + dn1Out: 2.3692824533332088E-002, + dn2Out: 0.10576950347767239, + gOut: 0.0000000000000000, + tauOut: 3.2573770070067200E-015, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2520040627944239E+01, 0.2559470753941703E+01, 0.3943012599746679E-01, 0.2794508075882943E-01, 0.1813958619441340E+01, 0.1795964384312701E+01, 0.9950845630193767E-02, 0.9646675917972324E-02, 0.1741066741415017E+01, 0.1878131517155319E+01, 0.1467114516582776E+00, 0.8477220453173254E-01, 0.1085214189555058E+01, 0.1010428304002300E+01, 0.9986318978978259E-02, 0.7202019583097946E-02, 0.7287093921253419E+00, 0.7222798755087921E+00, 0.7725029665513934E-03, 0.2132421202606784E-02, 0.1993785121145770E+01, 0.1996156738136608E+01, 0.4504038193447841E-02, 0.9240506410060376E-03, 0.4095324760138526E+00, 0.5471324717806409E+00, 0.1385240464077977E+00, 0.1086689918286978E+00, 0.4292130907735224E+00, 0.6103174493771462E+00, 0.2897733504323247E+00, 0.2112982785836522E+00, 0.4450341145952761E+00, 0.2594200218384955E+00, 0.2568418582687495E-01, 0.3588779484774172E-01, 0.3624803443601846E+00, 0.3849926621161204E+00, 0.5840011260368079E-01, 0.1744336104525046E-01, 0.1149923468579125E+00, 0.1715659665664736E+00, 0.7401698075381481E-01, 0.2315671901408358E+00, 0.5367558686801371E+00, 0.5010211363866497E+00, 0.1958324578473516E+00, 0.3221025481782661E+00, 0.8240727124361776E+00, 0.8820900960779340E+00, 0.3801199318200257E+00, 0.6999293195746292E+00, 0.1624226116729040E+01, 0.9787039376741966E+00, 0.5440714051978934E-01, 0.4877761656142095E-01, 0.8774371331215411E+00, 0.8340525857813585E+00, 0.5393069221241477E-02, 0.5090576402208483E-02, 0.7872712619108886E+00, 0.9608800054480426E+00, 0.1786993199393658E+00, 0.1613217694817542E-01, 0.8674395783437358E-01, 0.7149381583730083E-01, 0.8820349511059155E-03, 0.1321201613351008E-02, 0.1070907050910267E+00, 0.1064788675771248E+00, 0.7093640994523618E-03, 0.1589006148839502E-03, 0.2385172514821930E-01, 0.2369282453339490E-01, 0.6280626703238275E-13, 0.8634837515442557E-26, 0.3257377007015450E-14, 0.9466330862652142E-28, 0.7725029665513934E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 9.4663308626521417E-029, + desig: 2.1703795093889875E-020, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 2.3692824533332088E-002, + dmin2: 7.0611780886194908E-002, + dn: 9.4663308626521417E-029, + dn1: 2.3692824533332088E-002, + dn2: 0.10576950347767239, + g: 0.0000000000000000, + tau: 3.2573770070067200E-015, + nFail: 0, + iter: 11, + sigma: 6.9898185320128035E-004, + nDiv: 235, + zOut: []float64{0.2587415834700532E+01, 0.2559470753941703E+01, 0.1939710234687058E-01, 0.2794508075882943E-01, 0.1786213957883803E+01, 0.1795964384312701E+01, 0.1014308840067055E-01, 0.9646675917972324E-02, 0.1952760633286381E+01, 0.1878131517155319E+01, 0.4386417535844126E-01, 0.8477220453173254E-01, 0.9737661482269571E+00, 0.1010428304002300E+01, 0.5342015449359675E-02, 0.7202019583097946E-02, 0.7190702812620393E+00, 0.7222798755087921E+00, 0.5919653562455767E-02, 0.2132421202606784E-02, 0.1991161135215158E+01, 0.1996156738136608E+01, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.6555475524103290E+00, 0.5471324717806409E+00, 0.1011712753337584E+00, 0.1086689918286978E+00, 0.7204444526270400E+00, 0.6103174493771462E+00, 0.7608498315828412E-01, 0.2112982785836522E+00, 0.2192228335279531E+00, 0.2594200218384955E+00, 0.6302508481237896E-01, 0.3588779484774172E-01, 0.3394109383489919E+00, 0.3849926621161204E+00, 0.8817297145618809E-02, 0.1744336104525046E-01, 0.3943158595616905E+00, 0.1715659665664736E+00, 0.2942312715577539E+00, 0.2315671901408358E+00, 0.5288924130071619E+00, 0.5010211363866497E+00, 0.5372046576619481E+00, 0.3221025481782661E+00, 0.1044814757990615E+01, 0.8820900960779340E+00, 0.6556411803358774E+00, 0.6999293195746292E+00, 0.3718403738997403E+00, 0.9787039376741966E+00, 0.1094101127175453E+00, 0.4877761656142095E-01, 0.7297330494660218E+00, 0.8340525857813585E+00, 0.6703044469024726E-02, 0.5090576402208483E-02, 0.9703091379271934E+00, 0.9608800054480426E+00, 0.1188642714683105E-02, 0.1613217694817542E-01, 0.7162637473596872E-01, 0.7149381583730083E-01, 0.1964081696850700E-02, 0.1321201613351008E-02, 0.1046736864951580E+00, 0.1064788675771248E+00, 0.3596705640885345E-04, 0.1589006148839502E-03, 0.2365685747698604E-01, 0.2369282453339490E-01, 0.3455244592226135E-52, 0.8634837515442557E-26, 0.9466330862652142E-28, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 20, + ppOut: 1, + dminOut: 9.4663308626521417E-029, + desigOut: 2.1703795093889875E-020, + sigmaOut: 6.9898185320128035E-004, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 12, + nDivOut: 256, + ttypeOut: -2, + dmin1Out: 2.3656857476986041E-002, + dmin2Out: 7.0305173122617720E-002, + dnOut: 9.4663308626521417E-029, + dn1Out: 2.3656857476986041E-002, + dn2Out: 0.10451478588027406, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 20, + z: []float64{0.2587415834700532E+01, 0.2559470753941703E+01, 0.1939710234687058E-01, 0.2794508075882943E-01, 0.1786213957883803E+01, 0.1795964384312701E+01, 0.1014308840067055E-01, 0.9646675917972324E-02, 0.1952760633286381E+01, 0.1878131517155319E+01, 0.4386417535844126E-01, 0.8477220453173254E-01, 0.9737661482269571E+00, 0.1010428304002300E+01, 0.5342015449359675E-02, 0.7202019583097946E-02, 0.7190702812620393E+00, 0.7222798755087921E+00, 0.5919653562455767E-02, 0.2132421202606784E-02, 0.1991161135215158E+01, 0.1996156738136608E+01, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.6555475524103290E+00, 0.5471324717806409E+00, 0.1011712753337584E+00, 0.1086689918286978E+00, 0.7204444526270400E+00, 0.6103174493771462E+00, 0.7608498315828412E-01, 0.2112982785836522E+00, 0.2192228335279531E+00, 0.2594200218384955E+00, 0.6302508481237896E-01, 0.3588779484774172E-01, 0.3394109383489919E+00, 0.3849926621161204E+00, 0.8817297145618809E-02, 0.1744336104525046E-01, 0.3943158595616905E+00, 0.1715659665664736E+00, 0.2942312715577539E+00, 0.2315671901408358E+00, 0.5288924130071619E+00, 0.5010211363866497E+00, 0.5372046576619481E+00, 0.3221025481782661E+00, 0.1044814757990615E+01, 0.8820900960779340E+00, 0.6556411803358774E+00, 0.6999293195746292E+00, 0.3718403738997403E+00, 0.9787039376741966E+00, 0.1094101127175453E+00, 0.4877761656142095E-01, 0.7297330494660218E+00, 0.8340525857813585E+00, 0.6703044469024726E-02, 0.5090576402208483E-02, 0.9703091379271934E+00, 0.9608800054480426E+00, 0.1188642714683105E-02, 0.1613217694817542E-01, 0.7162637473596872E-01, 0.7149381583730083E-01, 0.1964081696850700E-02, 0.1321201613351008E-02, 0.1046736864951580E+00, 0.1064788675771248E+00, 0.3596705640885345E-04, 0.1589006148839502E-03, 0.2365685747698604E-01, 0.2369282453339490E-01, 0.3455244592226135E-52, 0.8634837515442557E-26, 0.9466330862652142E-28, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 9.4663308626521417E-029, + desig: 2.1703795093889875E-020, + qmax: 1.8900334961849885, + ttype: -2, + dmin1: 2.3656857476986041E-002, + dmin2: 7.0305173122617720E-002, + dn: 9.4663308626521417E-029, + dn1: 2.3656857476986041E-002, + dn2: 0.10451478588027406, + g: 0.0000000000000000, + tau: 0.0000000000000000, + nFail: 0, + iter: 12, + sigma: 6.9898185320128035E-004, + nDiv: 256, + zOut: []float64{0.2587415834700532E+01, 0.2594984508308910E+01, 0.1939710234687058E-01, 0.1335166928493912E-01, 0.1786213957883803E+01, 0.1771176948261041E+01, 0.1014308840067055E-01, 0.1118297285215907E-01, 0.1952760633286381E+01, 0.1973613407054170E+01, 0.4386417535844126E-01, 0.2164225725832272E-01, 0.9737661482269571E+00, 0.9456374776795010E+00, 0.5342015449359675E-02, 0.4062111160297227E-02, 0.7190702812620393E+00, 0.7090993949257048E+00, 0.5919653562455767E-02, 0.1662247097070905E-01, 0.1991161135215158E+01, 0.1962964146704966E+01, 0.2539111990097616E-03, 0.8479567256479229E-04, 0.6555475524103290E+00, 0.7448056033330296E+00, 0.1011712753337584E+00, 0.9786215859981671E-01, 0.7204444526270400E+00, 0.6868388484470145E+00, 0.7608498315828412E-01, 0.2428454015756268E-01, 0.2192228335279531E+00, 0.2461349494442763E+00, 0.6302508481237896E-01, 0.8690924724014965E-01, 0.3394109383489919E+00, 0.2494905595159681E+00, 0.8817297145618809E-02, 0.1393559784278329E-01, 0.3943158595616905E+00, 0.6627831045381681E+00, 0.2942312715577539E+00, 0.2347927793131975E+00, 0.5288924130071619E+00, 0.8194758626174196E+00, 0.5372046576619481E+00, 0.6849248159595133E+00, 0.1044814757990615E+01, 0.1003702693628486E+01, 0.6556411803358774E+00, 0.2428944977310168E+00, 0.3718403738997403E+00, 0.2265275601477758E+00, 0.1094101127175453E+00, 0.3524523689025369E+00, 0.7297330494660218E+00, 0.3721552962940165E+00, 0.6703044469024726E-02, 0.1747664312451059E-01, 0.9703091379271934E+00, 0.9421927087788731E+00, 0.1188642714683105E-02, 0.9036173567869616E-04, 0.7162637473596872E-01, 0.6167166595864771E-01, 0.1964081696850700E-02, 0.3333583884775863E-02, 0.1046736864951580E+00, 0.8954764092829798E-01, 0.3596705640885345E-04, 0.9501841907954501E-05, 0.2365685747698604E-01, 0.1181892689658507E-01, 0.3455244592226135E-52, 0.8479567256479229E-04, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 1.1818926896585069E-002, + desigOut: 3.4696444683954120E-019, + sigmaOut: 1.2527410591694300E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 13, + nDivOut: 276, + ttypeOut: -9, + dmin1Out: 5.9707584261797009E-002, + dmin2Out: 5.9707584261797009E-002, + dnOut: 1.1818926896585069E-002, + dn1Out: 8.9511673871889130E-002, + dn2Out: 5.9707584261797009E-002, + gOut: 0.0000000000000000, + tauOut: 1.1828428738493020E-002, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2587415834700532E+01, 0.2594984508308910E+01, 0.1939710234687058E-01, 0.1335166928493912E-01, 0.1786213957883803E+01, 0.1771176948261041E+01, 0.1014308840067055E-01, 0.1118297285215907E-01, 0.1952760633286381E+01, 0.1973613407054170E+01, 0.4386417535844126E-01, 0.2164225725832272E-01, 0.9737661482269571E+00, 0.9456374776795010E+00, 0.5342015449359675E-02, 0.4062111160297227E-02, 0.7190702812620393E+00, 0.7090993949257048E+00, 0.5919653562455767E-02, 0.1662247097070905E-01, 0.1991161135215158E+01, 0.1962964146704966E+01, 0.2539111990097616E-03, 0.8479567256479229E-04, 0.6555475524103290E+00, 0.7448056033330296E+00, 0.1011712753337584E+00, 0.9786215859981671E-01, 0.7204444526270400E+00, 0.6868388484470145E+00, 0.7608498315828412E-01, 0.2428454015756268E-01, 0.2192228335279531E+00, 0.2461349494442763E+00, 0.6302508481237896E-01, 0.8690924724014965E-01, 0.3394109383489919E+00, 0.2494905595159681E+00, 0.8817297145618809E-02, 0.1393559784278329E-01, 0.3943158595616905E+00, 0.6627831045381681E+00, 0.2942312715577539E+00, 0.2347927793131975E+00, 0.5288924130071619E+00, 0.8194758626174196E+00, 0.5372046576619481E+00, 0.6849248159595133E+00, 0.1044814757990615E+01, 0.1003702693628486E+01, 0.6556411803358774E+00, 0.2428944977310168E+00, 0.3718403738997403E+00, 0.2265275601477758E+00, 0.1094101127175453E+00, 0.3524523689025369E+00, 0.7297330494660218E+00, 0.3721552962940165E+00, 0.6703044469024726E-02, 0.1747664312451059E-01, 0.9703091379271934E+00, 0.9421927087788731E+00, 0.1188642714683105E-02, 0.9036173567869616E-04, 0.7162637473596872E-01, 0.6167166595864771E-01, 0.1964081696850700E-02, 0.3333583884775863E-02, 0.1046736864951580E+00, 0.8954764092829798E-01, 0.3596705640885345E-04, 0.9501841907954501E-05, 0.2365685747698604E-01, 0.1181892689658507E-01, 0.3455244592226135E-52, 0.8479567256479229E-04, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 1.1818926896585069E-002, + desig: 3.4696444683954120E-019, + qmax: 1.8900334961849885, + ttype: -9, + dmin1: 5.9707584261797009E-002, + dmin2: 5.9707584261797009E-002, + dn: 1.1818926896585069E-002, + dn1: 8.9511673871889130E-002, + dn2: 5.9707584261797009E-002, + g: 0.0000000000000000, + tau: 1.1828428738493020E-002, + nFail: 0, + iter: 13, + sigma: 1.2527410591694300E-002, + nDiv: 276, + zOut: []float64{0.2596646703688871E+01, 0.2594984508308910E+01, 0.9107195378059658E-02, 0.1335166928493912E-01, 0.1761563251830163E+01, 0.1771176948261041E+01, 0.1252913577120413E-01, 0.1118297285215907E-01, 0.1971037054636311E+01, 0.1973613407054170E+01, 0.1038322923301279E-01, 0.2164225725832272E-01, 0.9276268857018078E+00, 0.9456374776795010E+00, 0.3105171497598932E-02, 0.4062111160297227E-02, 0.7109272204938374E+00, 0.7090993949257048E+00, 0.4589684232723624E-01, 0.1662247097070905E-01, 0.1905462626145317E+01, 0.1962964146704966E+01, 0.3314486004504485E-04, 0.8479567256479229E-04, 0.8309451431678238E+00, 0.7448056033330296E+00, 0.8089045693556918E-01, 0.9786215859981671E-01, 0.6185434577640304E+00, 0.6868388484470145E+00, 0.9663466631053550E-02, 0.2428454015756268E-01, 0.3116912561483949E+00, 0.2461349494442763E+00, 0.6956575230565126E-01, 0.8690924724014965E-01, 0.1821709311481225E+00, 0.2494905595159681E+00, 0.5070116699532772E-01, 0.1393559784278329E-01, 0.8351852429510604E+00, 0.6627831045381681E+00, 0.2303764547900405E+00, 0.2347927793131975E+00, 0.1262334749881915E+01, 0.8194758626174196E+00, 0.5445947541061251E+00, 0.6849248159595133E+00, 0.6903129633483998E+00, 0.1003702693628486E+01, 0.7970630839299049E-01, 0.2428944977310168E+00, 0.4875841467523446E+00, 0.2265275601477758E+00, 0.2690141110044630E+00, 0.3524523689025369E+00, 0.1089283545090865E+00, 0.3721552962940165E+00, 0.1511669372043137E+00, 0.1747664312451059E-01, 0.7794266594052606E+00, 0.9421927087788731E+00, 0.7149818024536710E-05, 0.9036173567869616E-04, 0.5330862612042146E-01, 0.6167166595864771E-01, 0.5599742376476567E-02, 0.3333583884775863E-02, 0.7226792648875177E-01, 0.8954764092829798E-01, 0.1553961492315709E-05, 0.9501841907954501E-05, 0.1278990301151681E-03, 0.1181892689658507E-01, 0.7149818024536710E-05, 0.8479567256479229E-04, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 1, + dminOut: 1.2789903011516807E-004, + desigOut: 0.0000000000000000, + sigmaOut: 2.4216884496671885E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 0, + iterOut: 14, + nDivOut: 296, + ttypeOut: -4, + dmin1Out: 4.9975042235645591E-002, + dmin2Out: 4.9975042235645591E-002, + dnOut: 1.2789903011516807E-004, + dn1Out: 7.2258424646843816E-002, + dn2Out: 4.9975042235645591E-002, + gOut: 0.0000000000000000, + tauOut: 1.1689473904977585E-002, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2596646703688871E+01, 0.2594984508308910E+01, 0.9107195378059658E-02, 0.1335166928493912E-01, 0.1761563251830163E+01, 0.1771176948261041E+01, 0.1252913577120413E-01, 0.1118297285215907E-01, 0.1971037054636311E+01, 0.1973613407054170E+01, 0.1038322923301279E-01, 0.2164225725832272E-01, 0.9276268857018078E+00, 0.9456374776795010E+00, 0.3105171497598932E-02, 0.4062111160297227E-02, 0.7109272204938374E+00, 0.7090993949257048E+00, 0.4589684232723624E-01, 0.1662247097070905E-01, 0.1905462626145317E+01, 0.1962964146704966E+01, 0.3314486004504485E-04, 0.8479567256479229E-04, 0.8309451431678238E+00, 0.7448056033330296E+00, 0.8089045693556918E-01, 0.9786215859981671E-01, 0.6185434577640304E+00, 0.6868388484470145E+00, 0.9663466631053550E-02, 0.2428454015756268E-01, 0.3116912561483949E+00, 0.2461349494442763E+00, 0.6956575230565126E-01, 0.8690924724014965E-01, 0.1821709311481225E+00, 0.2494905595159681E+00, 0.5070116699532772E-01, 0.1393559784278329E-01, 0.8351852429510604E+00, 0.6627831045381681E+00, 0.2303764547900405E+00, 0.2347927793131975E+00, 0.1262334749881915E+01, 0.8194758626174196E+00, 0.5445947541061251E+00, 0.6849248159595133E+00, 0.6903129633483998E+00, 0.1003702693628486E+01, 0.7970630839299049E-01, 0.2428944977310168E+00, 0.4875841467523446E+00, 0.2265275601477758E+00, 0.2690141110044630E+00, 0.3524523689025369E+00, 0.1089283545090865E+00, 0.3721552962940165E+00, 0.1511669372043137E+00, 0.1747664312451059E-01, 0.7794266594052606E+00, 0.9421927087788731E+00, 0.7149818024536710E-05, 0.9036173567869616E-04, 0.5330862612042146E-01, 0.6167166595864771E-01, 0.5599742376476567E-02, 0.3333583884775863E-02, 0.7226792648875177E-01, 0.8954764092829798E-01, 0.1553961492315709E-05, 0.9501841907954501E-05, 0.1278990301151681E-03, 0.1181892689658507E-01, 0.7149818024536710E-05, 0.8479567256479229E-04, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 1.2789903011516807E-004, + desig: 0.0000000000000000, + qmax: 1.8900334961849885, + ttype: -4, + dmin1: 4.9975042235645591E-002, + dmin2: 4.9975042235645591E-002, + dn: 1.2789903011516807E-004, + dn1: 7.2258424646843816E-002, + dn2: 4.9975042235645591E-002, + g: 0.0000000000000000, + tau: 1.1689473904977585E-002, + nFail: 0, + iter: 14, + sigma: 2.4216884496671885E-002, + nDiv: 296, + zOut: []float64{0.2596646703688871E+01, 0.2605626003858251E+01, 0.9107195378059658E-02, 0.6157023564192275E-02, 0.1761563251830163E+01, 0.1767807468828494E+01, 0.1252913577120413E-01, 0.1396950250695455E-01, 0.1971037054636311E+01, 0.1967322886153689E+01, 0.1038322923301279E-01, 0.4895872794820515E-02, 0.9276268857018078E+00, 0.9257082891959054E+00, 0.3105171497598932E-02, 0.2384715539127593E-02, 0.7109272204938374E+00, 0.7543114520732653E+00, 0.4589684232723624E-01, 0.1159397984377132E+00, 0.1905462626145317E+01, 0.1789428077358968E+01, 0.3314486004504485E-04, 0.1539126429493388E-04, 0.8309451431678238E+00, 0.9116923136304173E+00, 0.8089045693556918E-01, 0.5488064578914756E-01, 0.6185434577640304E+00, 0.5731983833972557E+00, 0.9663466631053550E-02, 0.5254756712901782E-02, 0.3116912561483949E+00, 0.3758743565324636E+00, 0.6956575230565126E-01, 0.3371567560620648E-01, 0.1821709311481225E+00, 0.1990285273285630E+00, 0.5070116699532772E-01, 0.2127577741907859E+00, 0.8351852429510604E+00, 0.8526760283416343E+00, 0.2303764547900405E+00, 0.3410582621885915E+00, 0.1262334749881915E+01, 0.1465743346590768E+01, 0.5445947541061251E+00, 0.2564847518533230E+00, 0.6903129633483998E+00, 0.5134066246793865E+00, 0.7970630839299049E-01, 0.7569737222001199E-01, 0.4875841467523446E+00, 0.6807729903281149E+00, 0.2690141110044630E+00, 0.4304410555024735E-01, 0.1089283545090865E+00, 0.2169232909544721E+00, 0.1511669372043137E+00, 0.5431576312495270E+00, 0.7794266594052606E+00, 0.2361482827650774E+00, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.5330862612042146E-01, 0.5877885927277143E-01, 0.5599742376476567E-02, 0.6884818375619963E-02, 0.7226792648875177E-01, 0.6525676686594341E-01, 0.1553961492315709E-05, 0.3045663725752605E-08, 0.1278990301151681E-03, 0.7757707209639971E-09, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 7.7577072096399712E-010, + desigOut: -5.4210108624275222E-020, + sigmaOut: 2.4344779705352607E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 1, + iterOut: 16, + nDivOut: 336, + ttypeOut: -15, + dmin1Out: 5.3179116896294863E-002, + dmin2Out: 5.3179116896294863E-002, + dnOut: 7.7577072096399712E-010, + dn1Out: 6.5255212904451090E-002, + dn2Out: 5.3179116896294863E-002, + gOut: 0.0000000000000000, + tauOut: 1.2789520868072135E-004, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2596646703688871E+01, 0.2605626003858251E+01, 0.9107195378059658E-02, 0.6157023564192275E-02, 0.1761563251830163E+01, 0.1767807468828494E+01, 0.1252913577120413E-01, 0.1396950250695455E-01, 0.1971037054636311E+01, 0.1967322886153689E+01, 0.1038322923301279E-01, 0.4895872794820515E-02, 0.9276268857018078E+00, 0.9257082891959054E+00, 0.3105171497598932E-02, 0.2384715539127593E-02, 0.7109272204938374E+00, 0.7543114520732653E+00, 0.4589684232723624E-01, 0.1159397984377132E+00, 0.1905462626145317E+01, 0.1789428077358968E+01, 0.3314486004504485E-04, 0.1539126429493388E-04, 0.8309451431678238E+00, 0.9116923136304173E+00, 0.8089045693556918E-01, 0.5488064578914756E-01, 0.6185434577640304E+00, 0.5731983833972557E+00, 0.9663466631053550E-02, 0.5254756712901782E-02, 0.3116912561483949E+00, 0.3758743565324636E+00, 0.6956575230565126E-01, 0.3371567560620648E-01, 0.1821709311481225E+00, 0.1990285273285630E+00, 0.5070116699532772E-01, 0.2127577741907859E+00, 0.8351852429510604E+00, 0.8526760283416343E+00, 0.2303764547900405E+00, 0.3410582621885915E+00, 0.1262334749881915E+01, 0.1465743346590768E+01, 0.5445947541061251E+00, 0.2564847518533230E+00, 0.6903129633483998E+00, 0.5134066246793865E+00, 0.7970630839299049E-01, 0.7569737222001199E-01, 0.4875841467523446E+00, 0.6807729903281149E+00, 0.2690141110044630E+00, 0.4304410555024735E-01, 0.1089283545090865E+00, 0.2169232909544721E+00, 0.1511669372043137E+00, 0.5431576312495270E+00, 0.7794266594052606E+00, 0.2361482827650774E+00, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.5330862612042146E-01, 0.5877885927277143E-01, 0.5599742376476567E-02, 0.6884818375619963E-02, 0.7226792648875177E-01, 0.6525676686594341E-01, 0.1553961492315709E-05, 0.3045663725752605E-08, 0.1278990301151681E-03, 0.7757707209639971E-09, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 7.7577072096399712E-010, + desig: -5.4210108624275222E-020, + qmax: 1.8900334961849885, + ttype: -15, + dmin1: 5.3179116896294863E-002, + dmin2: 5.3179116896294863E-002, + dn: 7.7577072096399712E-010, + dn1: 6.5255212904451090E-002, + dn2: 5.3179116896294863E-002, + g: 0.0000000000000000, + tau: 1.2789520868072135E-004, + nFail: 1, + iter: 16, + sigma: 2.4344779705352607E-002, + nDiv: 336, + zOut: []float64{0.2611783026646672E+01, 0.2605626003858251E+01, 0.4167433562238479E-02, 0.6157023564192275E-02, 0.1777609536997439E+01, 0.1767807468828494E+01, 0.1546038171944878E-01, 0.1396950250695455E-01, 0.1956758376453290E+01, 0.1967322886153689E+01, 0.2316152103168096E-02, 0.4895872794820515E-02, 0.9257768518560943E+00, 0.9257082891959054E+00, 0.1943036529261404E-02, 0.2384715539127593E-02, 0.8683082132059464E+00, 0.7543114520732653E+00, 0.2389312083572061E+00, 0.1159397984377132E+00, 0.1550512259490286E+01, 0.1789428077358968E+01, 0.9049975109102588E-05, 0.1539126429493388E-04, 0.9665639086686850E+00, 0.9116923136304173E+00, 0.3254569838994440E-01, 0.5488064578914756E-01, 0.5459074409444424E+00, 0.5731983833972557E+00, 0.3618064437406363E-02, 0.5254756712901782E-02, 0.4059719669254931E+00, 0.3758743565324636E+00, 0.1652917395900484E-01, 0.3371567560620648E-01, 0.3952571267845734E+00, 0.1990285273285630E+00, 0.4589757947481138E+00, 0.2127577741907859E+00, 0.7347584950063413E+00, 0.8526760283416343E+00, 0.6803648845168142E+00, 0.3410582621885915E+00, 0.1041863213151506E+01, 0.1465743346590768E+01, 0.1263898840735783E+00, 0.2564847518533230E+00, 0.4627141120500496E+00, 0.5134066246793865E+00, 0.1113705527974558E+00, 0.7569737222001199E-01, 0.6124465423051357E+00, 0.6807729903281149E+00, 0.1524585149425051E-01, 0.4304410555024735E-01, 0.7448350699339780E+00, 0.2169232909544721E+00, 0.1722069046798406E+00, 0.5431576312495270E+00, 0.6394299132491200E-01, 0.2361482827650774E+00, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6566219320748727E-01, 0.5877885927277143E-01, 0.6842308575232983E-02, 0.6884818375619963E-02, 0.5841446056060346E-01, 0.6525676686594341E-01, 0.4044780558898965E-16, 0.3045663725752605E-08, 0.1013559914197710E-18, 0.7757707209639971E-09, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 1, + dminOut: 1.0135599141977102E-019, + desigOut: 2.7104744119407903E-020, + sigmaOut: 2.4344780481123287E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 2, + iterOut: 18, + nDivOut: 376, + ttypeOut: -15, + dmin1Out: 5.8414457514939733E-002, + dmin2Out: 5.8777374831867304E-002, + dnOut: 1.0135599141977102E-019, + dn1Out: 5.8414457514939733E-002, + dn2Out: 5.8777374831867304E-002, + gOut: 0.0000000000000000, + tauOut: 7.7577068041483555E-010, + }, + { + i0: 1, + n0: 19, + z: []float64{0.2611783026646672E+01, 0.2605626003858251E+01, 0.4167433562238479E-02, 0.6157023564192275E-02, 0.1777609536997439E+01, 0.1767807468828494E+01, 0.1546038171944878E-01, 0.1396950250695455E-01, 0.1956758376453290E+01, 0.1967322886153689E+01, 0.2316152103168096E-02, 0.4895872794820515E-02, 0.9257768518560943E+00, 0.9257082891959054E+00, 0.1943036529261404E-02, 0.2384715539127593E-02, 0.8683082132059464E+00, 0.7543114520732653E+00, 0.2389312083572061E+00, 0.1159397984377132E+00, 0.1550512259490286E+01, 0.1789428077358968E+01, 0.9049975109102588E-05, 0.1539126429493388E-04, 0.9665639086686850E+00, 0.9116923136304173E+00, 0.3254569838994440E-01, 0.5488064578914756E-01, 0.5459074409444424E+00, 0.5731983833972557E+00, 0.3618064437406363E-02, 0.5254756712901782E-02, 0.4059719669254931E+00, 0.3758743565324636E+00, 0.1652917395900484E-01, 0.3371567560620648E-01, 0.3952571267845734E+00, 0.1990285273285630E+00, 0.4589757947481138E+00, 0.2127577741907859E+00, 0.7347584950063413E+00, 0.8526760283416343E+00, 0.6803648845168142E+00, 0.3410582621885915E+00, 0.1041863213151506E+01, 0.1465743346590768E+01, 0.1263898840735783E+00, 0.2564847518533230E+00, 0.4627141120500496E+00, 0.5134066246793865E+00, 0.1113705527974558E+00, 0.7569737222001199E-01, 0.6124465423051357E+00, 0.6807729903281149E+00, 0.1524585149425051E-01, 0.4304410555024735E-01, 0.7448350699339780E+00, 0.2169232909544721E+00, 0.1722069046798406E+00, 0.5431576312495270E+00, 0.6394299132491200E-01, 0.2361482827650774E+00, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6566219320748727E-01, 0.5877885927277143E-01, 0.6842308575232983E-02, 0.6884818375619963E-02, 0.5841446056060346E-01, 0.6525676686594341E-01, 0.4044780558898965E-16, 0.3045663725752605E-08, 0.1013559914197710E-18, 0.7757707209639971E-09, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 1.0135599141977102E-019, + desig: 2.7104744119407903E-020, + qmax: 1.8900334961849885, + ttype: -15, + dmin1: 5.8414457514939733E-002, + dmin2: 5.8777374831867304E-002, + dn: 1.0135599141977102E-019, + dn1: 5.8414457514939733E-002, + dn2: 5.8777374831867304E-002, + g: 0.0000000000000000, + tau: 7.7577068041483555E-010, + nFail: 2, + iter: 18, + sigma: 2.4344780481123287E-002, + nDiv: 376, + zOut: []float64{0.2611783026646672E+01, 0.2615950460208911E+01, 0.4167433562238479E-02, 0.2831884532112553E-02, 0.1777609536997439E+01, 0.1790238034184775E+01, 0.1546038171944878E-01, 0.1689844079671380E-01, 0.1956758376453290E+01, 0.1942176087759744E+01, 0.2316152103168096E-02, 0.1104039956008399E-02, 0.9257768518560943E+00, 0.9266158484293474E+00, 0.1943036529261404E-02, 0.1820770257466081E-02, 0.8683082132059464E+00, 0.1105418651305687E+01, 0.2389312083572061E+00, 0.3351361651941490E+00, 0.1550512259490286E+01, 0.1215385144271246E+01, 0.9049975109102588E-05, 0.7197207696703830E-05, 0.9665639086686850E+00, 0.9991024098509327E+00, 0.3254569838994440E-01, 0.1778290067827487E-01, 0.5459074409444424E+00, 0.5317426047035739E+00, 0.3618064437406363E-02, 0.2762300261676148E-02, 0.4059719669254931E+00, 0.4197388406228219E+00, 0.1652917395900484E-01, 0.1556509232613395E-01, 0.3952571267845734E+00, 0.8386678292065533E+00, 0.4589757947481138E+00, 0.4021095747913879E+00, 0.7347584950063413E+00, 0.1013013804731768E+01, 0.6803648845168142E+00, 0.6997408538631263E+00, 0.1041863213151506E+01, 0.4685122433619579E+00, 0.1263898840735783E+00, 0.1248257304047288E+00, 0.4627141120500496E+00, 0.4492589344427766E+00, 0.1113705527974558E+00, 0.1518244930621437E+00, 0.6124465423051357E+00, 0.4758679007372426E+00, 0.1524585149425051E-01, 0.2386301922514691E-01, 0.7448350699339780E+00, 0.8931789553886716E+00, 0.1722069046798406E+00, 0.1232835205710967E-01, 0.6394299132491200E-01, 0.5161612293293578E-01, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6566219320748727E-01, 0.7250261437426894E-01, 0.6842308575232983E-02, 0.5512763475647510E-02, 0.5841446056060346E-01, 0.5290169708495600E-01, 0.4044780558898965E-16, 0.7749519698096867E-34, 0.1013559914197710E-18, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 19, + ppOut: 0, + dminOut: 1.0135599141977093E-019, + desigOut: 2.7104744119407903E-020, + sigmaOut: 2.4344780481123287E-002, + qmaxOut: 1.8900334961849885, + nFailOut: 2, + iterOut: 19, + nDivOut: 396, + ttypeOut: -2, + dmin1Out: 5.1614639267802333E-002, + dmin2Out: 5.1614639267802333E-002, + dnOut: 1.0135599141977093E-019, + dn1Out: 5.2901697084955956E-002, + dn2Out: 6.5660305799035965E-002, + gOut: 0.0000000000000000, + tauOut: 0.0000000000000000, + }, + { + i0: 1, + n0: 4, + z: []float64{0.6482015258643838E+00, 0.6481999396438409E+00, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.8927011497345719E-01, 0.8926852875357447E-01, 0.6601400172354812E-12, 0.2332164496627946E-11, 0.3153708122363886E+00, 0.3200537757344777E+00, 0.4684549720964035E-02, 0.2356209328895529E-07, 0.1609789066298190E-05, 0.6430148075154844E-11, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 6.4301480751548441E-012, + desig: -2.0633404957759536E-016, + qmax: 1.6602870234255678, + ttype: -2, + dmin1: 8.9268528752914328E-002, + dmin2: 8.9268528752914328E-002, + dn: 6.4301480751548441E-012, + dn1: 0.31536922601351364, + dn2: 8.9268528752914328E-002, + g: 0.49975000000000003, + tau: 1.5862205428611591E-006, + nFail: 5, + iter: 102, + sigma: 2.0015106747272648, + nDiv: 1395, + zOut: []float64{0.6481999396374125E+00, 0.6481999396438409E+00, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.8926852874947827E-01, 0.8926852875357447E-01, 0.8361491594360282E-11, 0.2332164496627946E-11, 0.3200537992817811E+00, 0.3200537757344777E+00, 0.4733821287189426E-18, 0.2356209328895529E-07, 0.1787791211067534E-14, 0.6430148075154844E-11, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 4, + ppOut: 1, + dminOut: 1.7877912110675335E-015, + desigOut: -3.7836067586147711E-017, + sigmaOut: 2.0015106747336930, + qmaxOut: 1.6602870234255678, + nFailOut: 5, + iterOut: 103, + nDivOut: 1400, + ttypeOut: -4, + dmin1Out: 8.9268528747146109E-002, + dmin2Out: 8.9268528747146109E-002, + dnOut: 1.7877912110675335E-015, + dn1Out: 0.32005377571968785, + dn2Out: 8.9268528747146109E-002, + gOut: 0.49975000000000003, + tauOut: 6.4283598105616478E-012, + }, + { + i0: 1, + n0: 4, + z: []float64{0.6481999396374125E+00, 0.6481999396438409E+00, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.8926852874947827E-01, 0.8926852875357447E-01, 0.8361491594360282E-11, 0.2332164496627946E-11, 0.3200537992817811E+00, 0.3200537757344777E+00, 0.4733821287189426E-18, 0.2356209328895529E-07, 0.1787791211067534E-14, 0.6430148075154844E-11, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 1.7877912110675335E-015, + desig: -3.7836067586147711E-017, + qmax: 1.6602870234255678, + ttype: -4, + dmin1: 8.9268528747146109E-002, + dmin2: 8.9268528747146109E-002, + dn: 1.7877912110675335E-015, + dn1: 0.32005377571968785, + dn2: 8.9268528747146109E-002, + g: 0.49975000000000003, + tau: 6.4283598105616478E-012, + nFail: 5, + iter: 103, + sigma: 2.0015106747336930, + nDiv: 1400, + zOut: []float64{0.6481999396374125E+00, 0.6481999396374107E+00, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.8926852874947827E-01, 0.8926852875783797E-01, 0.8361491594360282E-11, 0.2997839428604580E-10, 0.3200537992817811E+00, 0.3200537992518009E+00, 0.4733821287189426E-18, 0.2644269217171004E-32, 0.1787791211067534E-14, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 4, + ppOut: 0, + dminOut: 2.2279522444840209E-024, + desigOut: -2.6401698146816920E-017, + sigmaOut: 2.0015106747336948, + qmaxOut: 1.6602870234255678, + nFailOut: 5, + iterOut: 104, + nDivOut: 1405, + ttypeOut: -4, + dmin1Out: 8.9268528749476481E-002, + dmin2Out: 8.9268528749476481E-002, + dnOut: 2.2279522444840209E-024, + dn1Out: 0.32005379925180094, + dn2Out: 8.9268528749476481E-002, + gOut: 0.49975000000000003, + tauOut: 1.7877912088395813E-015, + }, + { + i0: 1, + n0: 4, + z: []float64{0.6481999396374125E+00, 0.6481999396374107E+00, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.8926852874947827E-01, 0.8926852875783797E-01, 0.8361491594360282E-11, 0.2997839428604580E-10, 0.3200537992817811E+00, 0.3200537992518009E+00, 0.4733821287189426E-18, 0.2644269217171004E-32, 0.1787791211067534E-14, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 2.2279522444840209E-024, + desig: -2.6401698146816920E-017, + qmax: 1.6602870234255678, + ttype: -4, + dmin1: 8.9268528749476481E-002, + dmin2: 8.9268528749476481E-002, + dn: 2.2279522444840209E-024, + dn1: 0.32005379925180094, + dn2: 8.9268528749476481E-002, + g: 0.49975000000000003, + tau: 1.7877912088395813E-015, + nFail: 5, + iter: 104, + sigma: 2.0015106747336948, + nDiv: 1405, + zOut: []float64{0.6258828074500417E+00, 0.6481999396374107E+00, 0.7879513719234823E-20, 0.5524513774965514E-19, 0.6695139660044724E-01, 0.8926852875783797E-01, 0.1433084218388560E-09, 0.2997839428604580E-10, 0.2977366669211234E+00, 0.3200537992518009E+00, 0.8926852875783797E-01, 0.2644269217171004E-32, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 3, + ppOut: 1, + dminOut: 6.6951396570468849E-002, + desigOut: -1.0061396160665481E-016, + sigmaOut: 2.0238278069210640, + qmaxOut: 1.6602870234255678, + nFailOut: 5, + iterOut: 105, + nDivOut: 1409, + ttypeOut: -9, + dmin1Out: 6.6951396570468849E-002, + dmin2Out: 0.62588280745004166, + dnOut: 0.29773666692112338, + dn1Out: 6.6951396570468849E-002, + dn2Out: 0.62588280745004166, + gOut: 0.49975000000000003, + tauOut: 2.2317132187369120E-002, + }, + { + i0: 1, + n0: 3, + z: []float64{0.6258828074500417E+00, 0.6481999396374107E+00, 0.7879513719234823E-20, 0.5524513774965514E-19, 0.6695139660044724E-01, 0.8926852875783797E-01, 0.1433084218388560E-09, 0.2997839428604580E-10, 0.2977366669211234E+00, 0.3200537992518009E+00, 0.8926852875783797E-01, 0.2644269217171004E-32, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 6.6951396570468849E-002, + desig: -1.0061396160665481E-016, + qmax: 1.6602870234255678, + ttype: -9, + dmin1: 6.6951396570468849E-002, + dmin2: 0.62588280745004166, + dn: 0.29773666692112338, + dn1: 6.6951396570468849E-002, + dn2: 0.62588280745004166, + g: 0.49975000000000003, + tau: 2.2317132187369120E-002, + nFail: 5, + iter: 105, + sigma: 2.0238278069210640, + nDiv: 1409, + zOut: []float64{0.6258828074500417E+00, 0.5589320748538995E+00, 0.7879513719234823E-20, 0.9438435755776795E-21, 0.6695139660044724E-01, 0.6641476135588615E-06, 0.1433084218388560E-09, 0.6424501268835132E-04, 0.2977366669211234E+00, 0.2307216893122929E+00, 0.8926852875783797E-01, 0.6695139660044724E-01, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 3, + ppOut: 0, + dminOut: 6.6400430513702258E-007, + desigOut: 1.9428902930940239E-016, + sigmaOut: 2.0907785395172058, + qmaxOut: 1.6602870234255678, + nFailOut: 5, + iterOut: 106, + nDivOut: 1413, + ttypeOut: -4, + dmin1Out: 6.6400430513702258E-007, + dmin2Out: 0.55893207485389951, + dnOut: 0.23072168931229292, + dn1Out: 6.6400430513702258E-007, + dn2Out: 0.55893207485389951, + gOut: 0.49975000000000003, + tauOut: 6.6950732596142107E-002, + }, + { + i0: 1, + n0: 3, + z: []float64{0.6258828074500417E+00, 0.5589320748538995E+00, 0.7879513719234823E-20, 0.9438435755776795E-21, 0.6695139660044724E-01, 0.6641476135588615E-06, 0.1433084218388560E-09, 0.6424501268835132E-04, 0.2977366669211234E+00, 0.2307216893122929E+00, 0.8926852875783797E-01, 0.6695139660044724E-01, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 6.6400430513702258E-007, + desig: 1.9428902930940239E-016, + qmax: 1.6602870234255678, + ttype: -4, + dmin1: 6.6400430513702258E-007, + dmin2: 0.55893207485389951, + dn: 0.23072168931229292, + dn1: 6.6400430513702258E-007, + dn2: 0.55893207485389951, + g: 0.49975000000000003, + tau: 6.6950732596142107E-002, + nFail: 5, + iter: 106, + sigma: 2.0907785395172058, + nDiv: 1413, + zOut: []float64{0.5589315065851642E+00, 0.5589320748538995E+00, 0.1121517486324177E-26, 0.9438435755776795E-21, 0.6434089156657428E-04, 0.6641476135588615E-06, 0.2303778747300831E+00, 0.6424501268835132E-04, 0.3432463134744483E-03, 0.2307216893122929E+00, 0.6641476135588615E-06, 0.6695139660044724E-01, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 3, + ppOut: 1, + dminOut: 9.5878878222950548E-008, + desigOut: -9.3233975295464906E-017, + sigmaOut: 2.0907791077859414, + qmaxOut: 1.6602870234255678, + nFailOut: 6, + iterOut: 108, + nDivOut: 1421, + ttypeOut: -15, + dmin1Out: 9.5878878222950548E-008, + dmin2Out: 0.55893150658516422, + dnOut: 3.4324631347444829E-004, + dn1Out: 9.5878878222950548E-008, + dn2Out: 0.55893150658516422, + gOut: 0.49975000000000003, + tauOut: 5.6826873533591094E-007, + }, + { + i0: 1, + n0: 3, + z: []float64{0.5589315065851642E+00, 0.5589320748538995E+00, 0.1121517486324177E-26, 0.9438435755776795E-21, 0.6434089156657428E-04, 0.6641476135588615E-06, 0.2303778747300831E+00, 0.6424501268835132E-04, 0.3432463134744483E-03, 0.2307216893122929E+00, 0.6641476135588615E-06, 0.6695139660044724E-01, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 0, + dmin: 9.5878878222950548E-008, + desig: -9.3233975295464906E-017, + qmax: 1.6602870234255678, + ttype: -15, + dmin1: 9.5878878222950548E-008, + dmin2: 0.55893150658516422, + dn: 3.4324631347444829E-004, + dn1: 9.5878878222950548E-008, + dn2: 0.55893150658516422, + g: 0.49975000000000003, + tau: 5.6826873533591094E-007, + nFail: 6, + iter: 108, + sigma: 2.0907791077859414, + nDiv: 1421, + zOut: []float64{0.5589315065851642E+00, 0.5589314123732620E+00, 0.1121517486324177E-26, 0.1291024862446124E-30, 0.6434089156657428E-04, 0.2304421214097475E+00, 0.2303778747300831E+00, 0.3431506172718059E-03, 0.3432463134744483E-03, 0.1484300435548105E-08, 0.6641476135588615E-06, 0.6434089156657428E-04, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 3, + ppOut: 0, + dminOut: 1.4843004355481051E-009, + desigOut: -1.6593817482031092E-016, + sigmaOut: 2.0907792019978437, + qmaxOut: 1.6602870234255678, + nFailOut: 6, + iterOut: 109, + nDivOut: 1425, + ttypeOut: -4, + dmin1Out: 6.4246679664367451E-005, + dmin2Out: 0.55893141237326205, + dnOut: 1.4843004355481051E-009, + dn1Out: 6.4246679664367451E-005, + dn2Out: 0.55893141237326205, + gOut: 0.49975000000000003, + tauOut: 9.4211902206835373E-008, + }, + { + i0: 1, + n0: 3, + z: []float64{0.5589315065851642E+00, 0.5589314123732620E+00, 0.1121517486324177E-26, 0.1291024862446124E-30, 0.6434089156657428E-04, 0.2304421214097475E+00, 0.2303778747300831E+00, 0.3431506172718059E-03, 0.3432463134744483E-03, 0.1484300435548105E-08, 0.6641476135588615E-06, 0.6434089156657428E-04, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + pp: 1, + dmin: 1.4843004355481051E-009, + desig: -1.6593817482031092E-016, + qmax: 1.6602870234255678, + ttype: -4, + dmin1: 6.4246679664367451E-005, + dmin2: 0.55893141237326205, + dn: 1.4843004355481051E-009, + dn1: 6.4246679664367451E-005, + dn2: 0.55893141237326205, + g: 0.49975000000000003, + tau: 9.4211902206835373E-008, + nFail: 6, + iter: 109, + sigma: 2.0907792019978437, + nDiv: 1425, + zOut: []float64{0.2649710614371106E+01, 0.5589314123732620E+00, 0.1121517486324177E-26, 0.1291024862446124E-30, 0.2321564474027070E+01, 0.2307852720292263E+00, 0.2303778747300831E+00, 0.3431506172718059E-03, 0.2090779203479937E+01, 0.1482093454966231E-08, 0.6641476135588615E-06, 0.6434089156657428E-04, 0.2001510674733695E+01, 0.2227952244484021E-23, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.1702794694134603E+01, 0.2545269924803487E-17, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.1077066053646038E+01, 0.7156177943897596E-01, 0.2292199980814605E-03, 0.1899018778701386E-03, 0.1060140274732043E+01, 0.8660746506696473E-01, 0.1357005210961402E-39, 0.1331360138522907E-23, 0.9894235909971354E+00, 0.8804208964992894E-17, 0.8660746506696473E-01, 0.8679736700028205E-01, 0.9539342071687115E+00, 0.2761013168273541E-29, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.8046649468928653E+00, 0.5098326619997980E-22, 0.1416795225784663E-10, 0.1216165317638265E-10, 0.7009142227469247E+00, 0.1183291357831518E-29, 0.4806926318247711E-11, 0.3824647564366386E-11, 0.5502651835254770E+00, 0.1368072596837427E-11, 0.1169503544861386E-10, 0.4068037876491279E-10, 0.4423863025187732E+00, 0.2477754901417239E-20, 0.1737857614720001E-07, 0.5295826057530262E-07, 0.3697086796938907E+00, 0.5143373102040997E-26, 0.1312431380925897E-05, 0.1614374370413396E-05, 0.1446051340026323E+00, 0.9928287808749566E-25, 0.3777515963415321E-05, 0.2773141909621761E-05, 0.1110032523123295E+00, 0.0000000000000000E+00, 0.2532463507333992E-05, 0.2934028940292093E-05, 0.7513603923341917E-01, 0.5394210206791908E-19, 0.6032617175984252E-07, 0.2575740214720034E-06, 0.6860214953971246E-01, 0.7542232825258426E-19, 0.3784397549471832E-09, 0.1131370986389306E-09, 0.2434478048112329E-01, 0.1013559914197709E-18, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6989818532012803E-03, 0.9466330862652142E-28, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.7811996215926567E-04, 0.3786532345060857E-28, 0.1283811140869274E-03, 0.1684766835109566E-03}, + i0Out: 1, + n0Out: 0, + ppOut: 1, + dminOut: 1.4843004355481051E-009, + desigOut: -1.6593817482031092E-016, + sigmaOut: 2.0907792019978437, + qmaxOut: 1.6602870234255678, + nFailOut: 6, + iterOut: 109, + nDivOut: 1425, + ttypeOut: -4, + dmin1Out: 6.4246679664367451E-005, + dmin2Out: 0.55893141237326205, + dnOut: 1.4843004355481051E-009, + dn1Out: 6.4246679664367451E-005, + dn2Out: 0.55893141237326205, + gOut: 0.49975000000000003, + tauOut: 9.4211902206835373E-008, + }, + } { + z := make([]float64, len(test.z)) + copy(z, test.z) + i0 := test.i0 - 1 // zero index + n0 := test.n0 - 1 // zero index + + i0Out, n0Out, ppOut, dminOut, sigmaOut, desigOut, qmaxOut, nFailOut, iterOut, nDivOut, ttypeOut, dmin1Out, dmin2Out, dnOut, dn1Out, dn2Out, gOut, tauOut := + impl.Dlasq3(i0, n0, z, test.pp, test.dmin, test.sigma, test.desig, test.qmax, test.nFail, test.iter, test.nDiv, test.ttype, test.dmin1, test.dmin2, test.dn, test.dn1, test.dn2, test.g, test.tau) + + if !floats.EqualApprox(z, test.zOut, dTol) { + t.Error("Z mismatch") + } + if i0Out != test.i0Out-1 { + t.Errorf("i0 mismatch. Want %v, got %v", test.n0Out, n0Out) + } + if n0Out != test.n0Out-1 { + t.Errorf("n0 mismatch. Want %v, got %v", test.n0Out, n0Out) + } + if ppOut != test.ppOut { + t.Errorf("pp mismatch. Want %v, got %v", test.ppOut, ppOut) + } + if !floats.EqualWithinAbsOrRel(dminOut, test.dminOut, dTol, dTol) { + t.Errorf("dmin mismatch. Want %v, got %v", test.dminOut, dminOut) + } + if !floats.EqualWithinAbsOrRel(desigOut, test.desigOut, dTol, dTol) { + t.Errorf("desig mismatch. Want %v, got %v", test.desigOut, desigOut) + } + if !floats.EqualWithinAbsOrRel(sigmaOut, test.sigmaOut, dTol, dTol) { + t.Errorf("sigma mismatch. Want %v, got %v", test.sigmaOut, sigmaOut) + } + if !floats.EqualWithinAbsOrRel(qmaxOut, test.qmaxOut, dTol, dTol) { + t.Errorf("qmax mismatch. Want %v, got %v", test.qmaxOut, qmaxOut) + } + if nFailOut != test.nFailOut { + t.Errorf("nFail mismatch. Want %v, got %v", test.nFailOut, nFailOut) + } + if iterOut != test.iterOut { + t.Errorf("iter mismatch. Want %v, got %v", test.iterOut, iterOut) + } + if nDivOut != test.nDivOut { + t.Errorf("nFail mismatch. Want %v, got %v", test.nDivOut, nDivOut) + } + if ttypeOut != test.ttypeOut { + t.Errorf("ttype mismatch. Want %v, got %v", test.ttypeOut, ttypeOut) + } + if !floats.EqualWithinAbsOrRel(dmin1Out, test.dmin1Out, dTol, dTol) { + t.Errorf("dmin1 mismatch. Want %v, got %v", test.dmin1Out, dmin1Out) + } + if !floats.EqualWithinAbsOrRel(dmin2Out, test.dmin2Out, dTol, dTol) { + t.Errorf("dmin2 mismatch. Want %v, got %v", test.dmin2Out, dmin2Out) + } + if !floats.EqualWithinAbsOrRel(dnOut, test.dnOut, dTol, dTol) { + t.Errorf("dn mismatch. Want %v, got %v", test.dnOut, dnOut) + } + if !floats.EqualWithinAbsOrRel(dn1Out, test.dn1Out, dTol, dTol) { + t.Errorf("dn1 mismatch. Want %v, got %v", test.dn1Out, dn1Out) + } + if !floats.EqualWithinAbsOrRel(dn2Out, test.dn2Out, dTol, dTol) { + t.Errorf("dn2 mismatch. Want %v, got %v", test.dn2Out, dn2Out) + } + if !floats.EqualWithinAbsOrRel(gOut, test.gOut, dTol, dTol) { + t.Errorf("g mismatch. Want %v, got %v", test.gOut, gOut) + } + if !floats.EqualWithinAbsOrRel(tauOut, test.tauOut, dTol, dTol) { + t.Errorf("tau mismatch. Want %v, got %v", test.tauOut, tauOut) + } + } +} diff --git a/lapack/testlapack/dlasq4.go b/lapack/testlapack/dlasq4.go new file mode 100644 index 00000000..b061defe --- /dev/null +++ b/lapack/testlapack/dlasq4.go @@ -0,0 +1,3121 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type dlasq4teststruct struct { + z []float64 + i0, n0, pp, n0in int + dmin, dmin1, dmin2, dn, dn1, dn2, tau float64 + ttype int + g float64 + + zOut []float64 + tauOut float64 + ttypeOut int + gOut float64 +} + +func printDlasq4FortranInput(d dlasq4teststruct) { + z := d.z + printFortranArray(z, "z") + fmt.Println("i0 =", d.i0) + fmt.Println("n0 =", d.n0) + fmt.Println("pp =", d.pp) + fmt.Println("n0in =", d.n0in) + + fmt.Println("dmin =", fortran64(d.dmin)) + fmt.Println("dmin1 =", fortran64(d.dmin1)) + fmt.Println("dmin2 =", fortran64(d.dmin2)) + fmt.Println("dn =", fortran64(d.dn)) + fmt.Println("dn1 =", fortran64(d.dn1)) + fmt.Println("dn2 =", fortran64(d.dn2)) + fmt.Println("g =", fortran64(d.g)) + fmt.Println("tau =", fortran64(d.tau)) + fmt.Println("ttype =", d.ttype) +} + +type Dlasq4er interface { + Dlasq4(i0, n0 int, z []float64, pp int, n0in int, dmin, dmin1, dmin2, dn, dn1, dn2, tau float64, ttype int, g float64) (tauOut float64, ttypeOut int, gOut float64) +} + +func Dlasq4Test(t *testing.T, impl Dlasq4er) { + dTol := 1e-14 + // Tests computed from calling the netlib Dlasq + for cas, test := range []dlasq4teststruct{ + { + z: []float64{0.1914365246180821E+01, 0.1564384297703890E+01, 0.2493389162143899E+00, 0.3499809484769305E+00, 0.1315996513131545E+01, 0.1363862112490627E+01, 0.9898466611970759E-01, 0.2014733168553078E+00, 0.6023973979587287E+00, 0.6465544792741794E+00, 0.2210033410638781E-02, 0.5482758480425683E-01, 0.9861857233678967E-01, 0.2428190810745492E-01, 0.4756321484454819E+00, 0.7654669763997353E-01, 0.2588748143677115E+00, 0.6127784069508770E+00, 0.1078611376690004E+00, 0.1217285558623164E+00, 0.6442896492255246E+00, 0.2293835804898155E+00, 0.6203230486639705E+00, 0.5227672064047094E+00, 0.3695660678607585E+00, 0.7645233184745865E+00, 0.5378838054252265E+00, 0.2253657980501426E+00, 0.3562533181264623E+00, 0.8820486722335483E+00, 0.2222132496436145E-01, 0.1208845131814035E-01, 0.1275094303021685E+01, 0.6548746852163357E+00, 0.1647324354821218E+00, 0.6424409427697111E+00, 0.1007530576543866E+01, 0.3269551736546701E+00, 0.3453881601783118E+00, 0.8453078383713172E+00, 0.2679391719153404E+00, 0.4116714838778281E+00, 0.7328677736683723E+00, 0.2016558482158241E+00, 0.8360828138307410E+00, 0.9737579452195326E+00, 0.4813660709592822E+00, 0.5951926422795808E+00, 0.6495370513676459E+00, 0.6761876248148171E+00, 0.2325475880222648E+00, 0.4547154975121112E+00, 0.1993624802893807E+00, 0.3321819367342255E+00, 0.3782318916911257E+00, 0.9972813157741996E-01, 0.9830449403503746E+00, 0.7561080996844842E+00, 0.4429733864040367E+00, 0.6051687323570161E+00, 0.1173279550602403E+01, 0.7195724480316686E+00, 0.5035524069144587E+00, 0.8966804889747714E+00, 0.3058980395058521E+00, 0.6588832353928662E+00, 0.3014634433415453E+00, 0.1505672110274446E+00, 0.1289422237567578E+01, 0.6124645310993601E+00, 0.7583364305799440E+00, 0.9784211498097629E+00, 0.4977814779461571E+00, 0.9993813577491869E+00, 0.2841468847862598E+00, 0.2567365507769143E+00, 0.9257539794205765E+00, 0.5509268385614666E+00, 0.5231355605450990E-04, 0.6589740256453697E+00, 0.2117869221381033E-04, 0.7349224826832024E-04, 0.0000000000000000E+00, 0.0000000000000000E+00}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: -0.0000000000000000, + dmin1: 0.0000000000000000, + dmin2: 0.0000000000000000, + dn: 0.0000000000000000, + dn1: 0.0000000000000000, + dn2: 0.0000000000000000, + tau: 0.0000000000000000, + ttype: 0, + g: 0.0000000000000000, + zOut: []float64{0.1914365246180821E+01, 0.1564384297703890E+01, 0.2493389162143899E+00, 0.3499809484769305E+00, 0.1315996513131545E+01, 0.1363862112490627E+01, 0.9898466611970759E-01, 0.2014733168553078E+00, 0.6023973979587287E+00, 0.6465544792741794E+00, 0.2210033410638781E-02, 0.5482758480425683E-01, 0.9861857233678967E-01, 0.2428190810745492E-01, 0.4756321484454819E+00, 0.7654669763997353E-01, 0.2588748143677115E+00, 0.6127784069508770E+00, 0.1078611376690004E+00, 0.1217285558623164E+00, 0.6442896492255246E+00, 0.2293835804898155E+00, 0.6203230486639705E+00, 0.5227672064047094E+00, 0.3695660678607585E+00, 0.7645233184745865E+00, 0.5378838054252265E+00, 0.2253657980501426E+00, 0.3562533181264623E+00, 0.8820486722335483E+00, 0.2222132496436145E-01, 0.1208845131814035E-01, 0.1275094303021685E+01, 0.6548746852163357E+00, 0.1647324354821218E+00, 0.6424409427697111E+00, 0.1007530576543866E+01, 0.3269551736546701E+00, 0.3453881601783118E+00, 0.8453078383713172E+00, 0.2679391719153404E+00, 0.4116714838778281E+00, 0.7328677736683723E+00, 0.2016558482158241E+00, 0.8360828138307410E+00, 0.9737579452195326E+00, 0.4813660709592822E+00, 0.5951926422795808E+00, 0.6495370513676459E+00, 0.6761876248148171E+00, 0.2325475880222648E+00, 0.4547154975121112E+00, 0.1993624802893807E+00, 0.3321819367342255E+00, 0.3782318916911257E+00, 0.9972813157741996E-01, 0.9830449403503746E+00, 0.7561080996844842E+00, 0.4429733864040367E+00, 0.6051687323570161E+00, 0.1173279550602403E+01, 0.7195724480316686E+00, 0.5035524069144587E+00, 0.8966804889747714E+00, 0.3058980395058521E+00, 0.6588832353928662E+00, 0.3014634433415453E+00, 0.1505672110274446E+00, 0.1289422237567578E+01, 0.6124645310993601E+00, 0.7583364305799440E+00, 0.9784211498097629E+00, 0.4977814779461571E+00, 0.9993813577491869E+00, 0.2841468847862598E+00, 0.2567365507769143E+00, 0.9257539794205765E+00, 0.5509268385614666E+00, 0.5231355605450990E-04, 0.6589740256453697E+00, 0.2117869221381033E-04, 0.7349224826832024E-04, 0.0000000000000000E+00, 0.0000000000000000E+00}, + tauOut: 0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 2.1175426017541180E-005, + dmin1: 4.4311601260836921E-002, + dmin2: 4.4311601260836921E-002, + dn: 2.1175426017541180E-005, + dn1: 0.33915960483100382, + dn2: 0.16428924199195991, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03, 0.1037537856266618 - 321}, + tauOut: 0.0000000000000000, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: 2.1175425069176302E-005, + dmin1: 2.9944624525135358E-002, + dmin2: 2.9944624525135358E-002, + dn: 2.1175425069176302E-005, + dn1: 7.2928780948497918E-002, + dn2: 0.16065460645225654, + tau: 0.0000000000000000, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + tauOut: 2.1175313795360271E-005, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 1.1127325659669794E-010, + dmin1: 3.1433071595911154E-002, + dmin2: 3.1433071595911154E-002, + dn: 1.1127325659669794E-010, + dn1: 3.5896964560873705E-002, + dn2: 0.25842281720128102, + tau: 2.1175313795360271E-005, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.1037537856266618 - 321}, + tauOut: 2.1175313795360271E-005, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: 0.0000000000000000, + dmin1: 2.9139336744737766E-002, + dmin2: 4.9426557292086552E-002, + dn: -2.0808762284537102E-024, + dn1: 2.9139336744737766E-002, + dn2: 0.15959234211062134, + tau: 1.1127325659669789E-010, + ttype: -15, + g: 0.0000000000000000, + zOut: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 21, + dmin: 0.0000000000000000, + dmin1: 2.7016889331018056E-002, + dmin2: 5.3061698118516694E-002, + dn: 0.0000000000000000, + dn1: 2.7016889331018056E-002, + dn2: 8.6018658784156071E-002, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.2117542506861687E-04}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.1620493249248586E-02}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 2.5763383633962696E-002, + dmin1: 4.3622798915905092E-002, + dmin2: 7.4536672467372611E-002, + dn: 2.5763383633962696E-002, + dn1: 4.3622798915905092E-002, + dn2: 9.8141518071882677E-002, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.1620493249248586E-02}, + tauOut: 2.0080554394878082E-002, + ttypeOut: -3, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 1.8576185384092288E-002, + dmin1: 1.8576185384092288E-002, + dmin2: 5.2365600435162571E-002, + dn: 1.9114649409197451E-002, + dn1: 1.8576185384092288E-002, + dn2: 5.2365600435162571E-002, + tau: 5.0201385987195205E-003, + ttype: -15, + g: 0.0000000000000000, + zOut: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04}, + tauOut: 5.4769133315280185E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 9.5622848228283271E-003, + dmin1: 9.5622848228283271E-003, + dmin2: 6.9533978479808370E-002, + dn: 1.0856003705186750E-002, + dn1: 9.5622848228283271E-003, + dn2: 6.9533978479808370E-002, + tau: 5.4769133315280185E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03}, + tauOut: 5.1216063611655054E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 2.0601312480394186E-003, + dmin1: 5.4371870398960158E-003, + dmin2: 8.0023511442426670E-002, + dn: 2.0601312480394186E-003, + dn1: 5.4371870398960158E-003, + dn2: 8.0023511442426670E-002, + tau: 5.1216063611655054E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04}, + tauOut: 1.2817878169164906E-003, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 6.0731361153288982E-005, + dmin1: 6.8738708636769136E-003, + dmin2: 8.1489512892123819E-002, + dn: 6.0731361153288982E-005, + dn1: 6.8738708636769136E-003, + dn2: 8.1489512892123819E-002, + tau: 1.2817878169164906E-003, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04}, + tauOut: 5.6837241251038845E-005, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 3.1568086081919418E-009, + dmin1: 1.0483100129151506E-002, + dmin2: 8.1316774559040517E-002, + dn: 3.1568086081919418E-009, + dn1: 1.0483100129151506E-002, + dn2: 8.1316774559040517E-002, + tau: 5.6837241251038845E-005, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04}, + tauOut: 3.1557121791797713E-009, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 6.9684975813366743E-017, + dmin1: 1.1199576261102989E-002, + dmin2: 8.1067607231828140E-002, + dn: 6.9684975813366743E-017, + dn1: 1.1199576261102989E-002, + dn2: 8.1067607231828140E-002, + tau: 3.1557121791797713E-009, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04}, + tauOut: 6.9684975806547287E-017, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 6.1629758220391547E-032, + dmin1: 1.1203310405167735E-002, + dmin2: 8.0927116373146771E-002, + dn: 6.1629758220391547E-032, + dn1: 1.1203310405167735E-002, + dn2: 8.0927116373146771E-002, + tau: 6.9684975806547287E-017, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04}, + tauOut: 6.1629758220391547E-032, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26}, + i0: 1, + n0: 19, + pp: 0, + n0in: 20, + dmin: 6.1629758220391547E-032, + dmin1: 1.1203288675083998E-002, + dmin2: 8.0846453894262649E-002, + dn: 6.1629758220391547E-032, + dn1: 1.1203288675083998E-002, + dn2: 8.0846453894262649E-002, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26}, + tauOut: 1.1203284285913290E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01}, + i0: 1, + n0: 19, + pp: 1, + n0in: 19, + dmin: 8.9043085058082561E-010, + dmin1: 6.9585227169791292E-002, + dmin2: 0.11373841371027797, + dn: 8.9043085058082561E-010, + dn1: 6.9585227169791292E-002, + dn2: 0.11373841371027797, + tau: 1.1203284285913290E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01}, + tauOut: 8.9043080564395014E-010, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05}, + i0: 1, + n0: 19, + pp: 0, + n0in: 19, + dmin: 1.3962105636374437E-019, + dmin1: 6.9544122471813200E-002, + dmin2: 9.8247027562672340E-002, + dn: 1.3962105636374437E-019, + dn1: 6.9544122471813200E-002, + dn2: 9.8247027562672340E-002, + tau: 8.9043080564395014E-010, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05}, + tauOut: 1.3962105636374427E-019, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 19, + dmin: 1.3962105636374430E-019, + dmin1: 6.9512134440652351E-002, + dmin2: 8.9358776708560295E-002, + dn: 1.3962105636374430E-019, + dn1: 6.9512134440652351E-002, + dn2: 8.9358776708560295E-002, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.2818174710670554E-01}, + tauOut: 6.8088572105595116E-002, + ttypeOut: -8, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.1344352644992036E-05}, + i0: 1, + n0: 18, + pp: 0, + n0in: 18, + dmin: 1.2643548659038301E-003, + dmin1: 1.3935943135754067E-002, + dmin2: 9.9495800084882416E-002, + dn: 1.2643548659038301E-003, + dn1: 1.3935943135754067E-002, + dn2: 9.9495800084882416E-002, + tau: 6.8088572105595116E-002, + ttype: -8, + g: 0.0000000000000000, + zOut: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.1344352644992036E-05}, + tauOut: 1.2463174543591322E-003, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 18, + dmin: 1.2236274461701734E-006, + dmin1: 1.1812799375517376E-002, + dmin2: 0.10597947881780349, + dn: 1.2236274461701734E-006, + dn1: 1.1812799375517376E-002, + dn2: 0.10597947881780349, + tau: 1.2463174543591322E-003, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01}, + tauOut: 1.2218877946904154E-006, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06}, + i0: 1, + n0: 18, + pp: 0, + n0in: 18, + dmin: 9.5986727915820745E-012, + dmin1: 1.1875197612370336E-002, + dmin2: 0.11291768719739126, + dn: 9.5986727915820745E-012, + dn1: 1.1875197612370336E-002, + dn2: 0.11291768719739126, + tau: 1.2218877946904154E-006, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06}, + tauOut: 9.5986713933289272E-012, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 18, + dmin: 6.6174125886815435E-022, + dmin1: 1.1882019541390456E-002, + dmin2: 0.11366976186212303, + dn: 6.6174125886815435E-022, + dn1: 1.1882019541390456E-002, + dn2: 0.11366976186212303, + tau: 9.5986713933289272E-012, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01}, + tauOut: 6.6174125886815426E-022, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17}, + i0: 1, + n0: 17, + pp: 0, + n0in: 18, + dmin: 6.6174125886815426E-022, + dmin1: 1.1880977265773463E-002, + dmin2: 0.11370904624558997, + dn: 6.6174125886815426E-022, + dn1: 1.1880977265773463E-002, + dn2: 0.11370904624558997, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17}, + tauOut: 1.1880832155707781E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01}, + i0: 1, + n0: 17, + pp: 1, + n0in: 17, + dmin: 2.3287035572430725E-008, + dmin1: 0.10181720511285566, + dmin2: 0.30482311636216664, + dn: 2.3287035572430725E-008, + dn1: 0.10181720511285566, + dn2: 0.30482311636216664, + tau: 1.1880832155707781E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01}, + tauOut: 2.3287007705477136E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07}, + i0: 1, + n0: 17, + pp: 0, + n0in: 17, + dmin: 2.6961654281145418E-018, + dmin1: 0.10181121275944585, + dmin2: 0.30487633314418217, + dn: 2.6961654281145418E-018, + dn1: 0.10181121275944585, + dn2: 0.30487633314418217, + tau: 2.3287007705477136E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07}, + tauOut: 2.6961654281138038E-018, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.1093987140067686E+00}, + i0: 1, + n0: 16, + pp: 1, + n0in: 17, + dmin: 2.6961654281138038E-018, + dmin1: 0.10180899282350273, + dmin2: 0.30489636738914000, + dn: 2.6961654281138038E-018, + dn1: 0.10180899282350273, + dn2: 0.30489636738914000, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.1093987140067686E+00}, + tauOut: 0.10180650470263587, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.2638661645752538E-08}, + i0: 1, + n0: 16, + pp: 0, + n0in: 16, + dmin: 1.3142485785350155E-006, + dmin1: 0.20309651253108729, + dmin2: 0.57610166617362735, + dn: 1.3142485785350155E-006, + dn1: 0.20309651253108729, + dn2: 0.81137144083676127, + tau: 0.10180650470263587, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.2638661645752538E-08}, + tauOut: 1.3142409824136984E-006, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00}, + i0: 1, + n0: 16, + pp: 1, + n0in: 16, + dmin: 8.4118841991824567E-018, + dmin1: 0.20309744276965425, + dmin2: 0.50018599148866161, + dn: 8.4118841991824567E-018, + dn1: 0.20309744276965425, + dn2: 0.75834178007645303, + tau: 1.3142409824136984E-006, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00}, + tauOut: 8.4118841988678429E-018, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09}, + i0: 1, + n0: 16, + pp: 0, + n0in: 16, + dmin: 8.4118841988678429E-018, + dmin1: 0.20309858884628909, + dmin2: 0.53283137411117854, + dn: 8.4118841988678429E-018, + dn1: 0.20309858884628909, + dn2: 0.71080515929391042, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09}, + tauOut: 8.4118841988678429E-018, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + n0in: 16, + dmin: 8.4118841988678429E-018, + dmin1: 0.20309858045029386, + dmin2: 0.51860540644834729, + dn: 8.4118841988678429E-018, + dn1: 0.20309858045029386, + dn2: 0.67176795876146822, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.2112065329503869E+00}, + tauOut: 0.10154929022514693, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.9833566024906726E-10}, + i0: 1, + n0: 15, + pp: 0, + n0in: 15, + dmin: 0.10154928703201281, + dmin1: 0.32391205918605420, + dmin2: 0.32391205918605420, + dn: 0.10154928703201281, + dn1: 0.53450854002684800, + dn2: 0.69531980574199759, + tau: 0.10154929022514693, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.9833566024906726E-10}, + tauOut: 0.10154100618138810, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2168221690252314E+01, 0.2066680684115085E+01, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.8728911912704126E+00, 0.7726711989960955E+00, 0.1321013925721922E-02, 0.2361487308570419E-02, 0.1381252078118717E+01, 0.1279505990312372E+01, 0.2156405683614187E-02, 0.2803234389363145E-02, 0.1663302606134993E+01, 0.1580598225403798E+01, 0.2163985983955575E-01, 0.2200217261925751E-01, 0.1607061933620194E+01, 0.1511873816770092E+01, 0.2835506195054301E-01, 0.1320468740761088E-01, 0.7040655098910235E+00, 0.6628877301101292E+00, 0.7356791380810462E-01, 0.1945110224949301E+00, 0.1752652257061283E+01, 0.1621214783142186E+01, 0.1646145547572216E+00, 0.8703165684534678E-01, 0.8571356821219610E+00, 0.7442679496495411E+00, 0.7570493055431493E-01, 0.1597129865933493E+00, 0.1570165327329021E+01, 0.1651350720852550E+01, 0.3424393862982660E+00, 0.1337269360034139E+00, 0.6448734608299306E+00, 0.5118619205977412E+00, 0.1022564019526126E+00, 0.1169456581236225E+00, 0.5853915063475871E+00, 0.4777529393688394E+00, 0.1108480973262629E+00, 0.8163333047984263E-01, 0.3518379162830466E+00, 0.2373651048287110E+00, 0.6870152520689508E-01, 0.2125478936639627E+00, 0.7343571035538636E+00, 0.4559783600136673E+00, 0.3571015630515456E-01, 0.4186028435717903E-01, 0.5345085484304394E+00, 0.3911072610850064E+00, 0.3193134112956561E-08, 0.8290832843879624E-09, 0.1015492870320128E+00, 0.8280021541434701E-05, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + n0in: 15, + dmin: 8.2800215414347011E-006, + dmin1: 0.16866357962181588, + dmin2: 0.16866357962181588, + dn: 8.2800215414347011E-006, + dn1: 0.39110725789187228, + dn2: 0.42026820370851276, + tau: 0.10154100618138810, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2168221690252314E+01, 0.2066680684115085E+01, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.8728911912704126E+00, 0.7726711989960955E+00, 0.1321013925721922E-02, 0.2361487308570419E-02, 0.1381252078118717E+01, 0.1279505990312372E+01, 0.2156405683614187E-02, 0.2803234389363145E-02, 0.1663302606134993E+01, 0.1580598225403798E+01, 0.2163985983955575E-01, 0.2200217261925751E-01, 0.1607061933620194E+01, 0.1511873816770092E+01, 0.2835506195054301E-01, 0.1320468740761088E-01, 0.7040655098910235E+00, 0.6628877301101292E+00, 0.7356791380810462E-01, 0.1945110224949301E+00, 0.1752652257061283E+01, 0.1621214783142186E+01, 0.1646145547572216E+00, 0.8703165684534678E-01, 0.8571356821219610E+00, 0.7442679496495411E+00, 0.7570493055431493E-01, 0.1597129865933493E+00, 0.1570165327329021E+01, 0.1651350720852550E+01, 0.3424393862982660E+00, 0.1337269360034139E+00, 0.6448734608299306E+00, 0.5118619205977412E+00, 0.1022564019526126E+00, 0.1169456581236225E+00, 0.5853915063475871E+00, 0.4777529393688394E+00, 0.1108480973262629E+00, 0.8163333047984263E-01, 0.3518379162830466E+00, 0.2373651048287110E+00, 0.6870152520689508E-01, 0.2125478936639627E+00, 0.7343571035538636E+00, 0.4559783600136673E+00, 0.3571015630515456E-01, 0.4186028435717903E-01, 0.5345085484304394E+00, 0.3911072610850064E+00, 0.3193134112956561E-08, 0.8290832843879624E-09, 0.1015492870320128E+00, 0.8280021541434701E-05, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.2112065329503869E+00}, + tauOut: 8.2795951083136037E-006, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2066672404538628E+01, 0.2066680684115085E+01, 0.6973096395115281E-11, 0.1865101988102620E-10, 0.7750244067025847E+00, 0.7726711989960955E+00, 0.3898634844569491E-02, 0.2361487308570419E-02, 0.1278402310262057E+01, 0.1279505990312372E+01, 0.3465878671879142E-02, 0.2803234389363145E-02, 0.1599126239756068E+01, 0.1580598225403798E+01, 0.2080167773382635E-01, 0.2200217261925751E-01, 0.1504268546848768E+01, 0.1511873816770092E+01, 0.5818924606767697E-02, 0.1320468740761088E-01, 0.8515715484031834E+00, 0.6628877301101292E+00, 0.3703084558710277E+00, 0.1945110224949301E+00, 0.1337929704521397E+01, 0.1621214783142186E+01, 0.4841425717359337E-01, 0.8703165684534678E-01, 0.8555583994741887E+00, 0.7442679496495411E+00, 0.3082690272254148E+00, 0.1597129865933493E+00, 0.1476800350035441E+01, 0.1651350720852550E+01, 0.4635002036444261E-01, 0.1337269360034139E+00, 0.5824492787618127E+00, 0.5118619205977412E+00, 0.9592445892242578E-01, 0.1169456581236225E+00, 0.4634535313311479E+00, 0.4777529393688394E+00, 0.4180980990954932E-01, 0.8163333047984263E-01, 0.4080949089880160E+00, 0.2373651048287110E+00, 0.2374870106014949E+00, 0.2125478936639627E+00, 0.2603433541742431E+00, 0.4559783600136673E+00, 0.6288565043307552E-01, 0.4186028435717903E-01, 0.3282133318859058E+00, 0.3911072610850064E+00, 0.2091574834858362E-13, 0.8290832843879624E-09, 0.4264122053484397E-09, 0.8280021541434701E-05, 0.6973096395115281E-11, 0.1865101988102620E-10}, + i0: 1, + n0: 15, + pp: 0, + n0in: 15, + dmin: 4.2641220534843968E-010, + dmin1: 0.19554701532405336, + dmin2: 0.19554701532405336, + dn: 4.2641220534843968E-010, + dn1: 0.32821333105682254, + dn2: 0.21848306981706411, + tau: 8.2795951083136037E-006, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2066672404538628E+01, 0.2066680684115085E+01, 0.6973096395115281E-11, 0.1865101988102620E-10, 0.7750244067025847E+00, 0.7726711989960955E+00, 0.3898634844569491E-02, 0.2361487308570419E-02, 0.1278402310262057E+01, 0.1279505990312372E+01, 0.3465878671879142E-02, 0.2803234389363145E-02, 0.1599126239756068E+01, 0.1580598225403798E+01, 0.2080167773382635E-01, 0.2200217261925751E-01, 0.1504268546848768E+01, 0.1511873816770092E+01, 0.5818924606767697E-02, 0.1320468740761088E-01, 0.8515715484031834E+00, 0.6628877301101292E+00, 0.3703084558710277E+00, 0.1945110224949301E+00, 0.1337929704521397E+01, 0.1621214783142186E+01, 0.4841425717359337E-01, 0.8703165684534678E-01, 0.8555583994741887E+00, 0.7442679496495411E+00, 0.3082690272254148E+00, 0.1597129865933493E+00, 0.1476800350035441E+01, 0.1651350720852550E+01, 0.4635002036444261E-01, 0.1337269360034139E+00, 0.5824492787618127E+00, 0.5118619205977412E+00, 0.9592445892242578E-01, 0.1169456581236225E+00, 0.4634535313311479E+00, 0.4777529393688394E+00, 0.4180980990954932E-01, 0.8163333047984263E-01, 0.4080949089880160E+00, 0.2373651048287110E+00, 0.2374870106014949E+00, 0.2125478936639627E+00, 0.2603433541742431E+00, 0.4559783600136673E+00, 0.6288565043307552E-01, 0.4186028435717903E-01, 0.3282133318859058E+00, 0.3911072610850064E+00, 0.2091574834858362E-13, 0.8290832843879624E-09, 0.4264122053484397E-09, 0.8280021541434701E-05, 0.6973096395115281E-11, 0.1865101988102620E-10}, + tauOut: 4.2641207498271701E-010, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2066672404538628E+01, 0.2066672404119188E+01, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.7750244067025847E+00, 0.7789230411181270E+00, 0.3898634844569491E-02, 0.6398608757305904E-02, 0.1278402310262057E+01, 0.1275469579750218E+01, 0.3465878671879142E-02, 0.4345362379476143E-02, 0.1599126239756068E+01, 0.1615582554684006E+01, 0.2080167773382635E-01, 0.1936843737632438E-01, 0.1504268546848768E+01, 0.1490719033652799E+01, 0.5818924606767697E-02, 0.3324054047451484E-02, 0.8515715484031834E+00, 0.1218555949800348E+01, 0.3703084558710277E+00, 0.4065850919906259E+00, 0.1337929704521397E+01, 0.9797588692779520E+00, 0.4841425717359337E-01, 0.4227695780870786E-01, 0.8555583994741887E+00, 0.1121550468464483E+01, 0.3082690272254148E+00, 0.4059129037098644E+00, 0.1476800350035441E+01, 0.1117237466263607E+01, 0.4635002036444261E-01, 0.2416365074306882E-01, 0.5824492787618127E+00, 0.6542100865147574E+00, 0.9592445892242578E-01, 0.6795451513972497E-01, 0.4634535313311479E+00, 0.4373088256745602E+00, 0.4180980990954932E-01, 0.3901675330591518E-01, 0.4080949089880160E+00, 0.6065651658571838E+00, 0.2374870106014949E+00, 0.1019316116273065E+00, 0.2603433541742431E+00, 0.2212973925536000E+00, 0.6288565043307552E-01, 0.9326774535516916E-01, 0.3282133318859058E+00, 0.2349455861043456E+00, 0.2091574834858362E-13, 0.3796083394336032E-22, 0.4264122053484397E-09, 0.1303656847202082E-15, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + n0in: 15, + dmin: 1.3036568472020817E-016, + dmin1: 0.15841174212052453, + dmin2: 0.15841174212052453, + dn: 1.3036568472020817E-016, + dn1: 0.23494558610432464, + dn2: 0.15841174212052453, + tau: 4.2641207498271701E-010, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2066672404538628E+01, 0.2066672404119188E+01, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.7750244067025847E+00, 0.7789230411181270E+00, 0.3898634844569491E-02, 0.6398608757305904E-02, 0.1278402310262057E+01, 0.1275469579750218E+01, 0.3465878671879142E-02, 0.4345362379476143E-02, 0.1599126239756068E+01, 0.1615582554684006E+01, 0.2080167773382635E-01, 0.1936843737632438E-01, 0.1504268546848768E+01, 0.1490719033652799E+01, 0.5818924606767697E-02, 0.3324054047451484E-02, 0.8515715484031834E+00, 0.1218555949800348E+01, 0.3703084558710277E+00, 0.4065850919906259E+00, 0.1337929704521397E+01, 0.9797588692779520E+00, 0.4841425717359337E-01, 0.4227695780870786E-01, 0.8555583994741887E+00, 0.1121550468464483E+01, 0.3082690272254148E+00, 0.4059129037098644E+00, 0.1476800350035441E+01, 0.1117237466263607E+01, 0.4635002036444261E-01, 0.2416365074306882E-01, 0.5824492787618127E+00, 0.6542100865147574E+00, 0.9592445892242578E-01, 0.6795451513972497E-01, 0.4634535313311479E+00, 0.4373088256745602E+00, 0.4180980990954932E-01, 0.3901675330591518E-01, 0.4080949089880160E+00, 0.6065651658571838E+00, 0.2374870106014949E+00, 0.1019316116273065E+00, 0.2603433541742431E+00, 0.2212973925536000E+00, 0.6288565043307552E-01, 0.9326774535516916E-01, 0.3282133318859058E+00, 0.2349455861043456E+00, 0.2091574834858362E-13, 0.3796083394336032E-22, 0.4264122053484397E-09, 0.1303656847202082E-15, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.2112065329503869E+00}, + tauOut: 1.3036568471812905E-016, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2066672404121803E+01, 0.2066672404119188E+01, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.7853216498744473E+00, 0.7789230411181270E+00, 0.1039221422709001E-01, 0.6398608757305904E-02, 0.1269422727902604E+01, 0.1275469579750218E+01, 0.5530302475095172E-02, 0.4345362379476143E-02, 0.1629420689585235E+01, 0.1615582554684006E+01, 0.1771973219288664E-01, 0.1936843737632438E-01, 0.1476323355507364E+01, 0.1490719033652799E+01, 0.2743671176012720E-02, 0.3324054047451484E-02, 0.1622397370614960E+01, 0.1218555949800348E+01, 0.2455350071499520E+00, 0.4065850919906259E+00, 0.7765008199367077E+00, 0.9797588692779520E+00, 0.6106335063429082E-01, 0.4227695780870786E-01, 0.1466400021540057E+01, 0.1121550468464483E+01, 0.3092615230516922E+00, 0.4059129037098644E+00, 0.8321395939549830E+00, 0.1117237466263607E+01, 0.1899693772291602E-01, 0.2416365074306882E-01, 0.7031676639315663E+00, 0.6542100865147574E+00, 0.4226176876348708E-01, 0.6795451513972497E-01, 0.4340638102169883E+00, 0.4373088256745602E+00, 0.5452240634477346E-01, 0.3901675330591518E-01, 0.6539743711397168E+00, 0.6065651658571838E+00, 0.3449248298919955E-01, 0.1019316116273065E+00, 0.2800726549195695E+00, 0.2212973925536000E+00, 0.7823985923721809E-01, 0.9326774535516916E-01, 0.1567057268671274E+00, 0.2349455861043456E+00, 0.3158014839988858E-37, 0.3796083394336032E-22}, + i0: 1, + n0: 14, + pp: 0, + n0in: 15, + dmin: 2.0791168714198411E-027, + dmin1: 0.15670572686712736, + dmin2: 0.18680490956440032, + dn: 2.0791168714198411E-027, + dn1: 0.15670572686712736, + dn2: 0.18680490956440032, + tau: 1.3036568471812905E-016, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2066672404121803E+01, 0.2066672404119188E+01, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.7853216498744473E+00, 0.7789230411181270E+00, 0.1039221422709001E-01, 0.6398608757305904E-02, 0.1269422727902604E+01, 0.1275469579750218E+01, 0.5530302475095172E-02, 0.4345362379476143E-02, 0.1629420689585235E+01, 0.1615582554684006E+01, 0.1771973219288664E-01, 0.1936843737632438E-01, 0.1476323355507364E+01, 0.1490719033652799E+01, 0.2743671176012720E-02, 0.3324054047451484E-02, 0.1622397370614960E+01, 0.1218555949800348E+01, 0.2455350071499520E+00, 0.4065850919906259E+00, 0.7765008199367077E+00, 0.9797588692779520E+00, 0.6106335063429082E-01, 0.4227695780870786E-01, 0.1466400021540057E+01, 0.1121550468464483E+01, 0.3092615230516922E+00, 0.4059129037098644E+00, 0.8321395939549830E+00, 0.1117237466263607E+01, 0.1899693772291602E-01, 0.2416365074306882E-01, 0.7031676639315663E+00, 0.6542100865147574E+00, 0.4226176876348708E-01, 0.6795451513972497E-01, 0.4340638102169883E+00, 0.4373088256745602E+00, 0.5452240634477346E-01, 0.3901675330591518E-01, 0.6539743711397168E+00, 0.6065651658571838E+00, 0.3449248298919955E-01, 0.1019316116273065E+00, 0.2800726549195695E+00, 0.2212973925536000E+00, 0.7823985923721809E-01, 0.9326774535516916E-01, 0.1567057268671274E+00, 0.2349455861043456E+00, 0.3158014839988858E-37, 0.3796083394336032E-22}, + tauOut: 5.2226904068357879E-002, + ttypeOut: -8, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2066672404121803E+01, 0.2014445500054431E+01, 0.9855809897129084E-12, 0.3842238913414725E-12, 0.7853216498744473E+00, 0.7434869600327952E+00, 0.1039221422709001E-01, 0.1774357001838869E-01, 0.1269422727902604E+01, 0.1204982556290953E+01, 0.5530302475095172E-02, 0.7478273627729330E-02, 0.1629420689585235E+01, 0.1587435244082034E+01, 0.1771973219288664E-01, 0.1647944669694028E-01, 0.1476323355507364E+01, 0.1410360675918078E+01, 0.2743671176012720E-02, 0.3156160674217245E-02, 0.1622397370614960E+01, 0.1812549313022337E+01, 0.2455350071499520E+00, 0.1051878329628395E+00, 0.7765008199367077E+00, 0.6801494335398012E+00, 0.6106335063429082E-01, 0.1316523902981273E+00, 0.1466400021540057E+01, 0.1591782250225264E+01, 0.3092615230516922E+00, 0.1616733433116970E+00, 0.8321395939549830E+00, 0.6372362842978442E+00, 0.1899693772291602E-01, 0.2096244776016672E-01, 0.7031676639315663E+00, 0.6722400808665288E+00, 0.4226176876348708E-01, 0.2728832287468248E-01, 0.4340638102169883E+00, 0.4090709896187213E+00, 0.5452240634477346E-01, 0.8716398206477828E-01, 0.6539743711397168E+00, 0.5490759679957803E+00, 0.3449248298919955E-01, 0.1759392479116377E-01, 0.2800726549195695E+00, 0.2884916852972659E+00, 0.7823985923721809E-01, 0.4249908970207047E-01, 0.1567057268671274E+00, 0.6197973309669901E-01, 0.3158014839988858E-37, 0.3842238913414725E-12, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + n0in: 14, + dmin: 6.1979733096699005E-002, + dmin1: 0.21025182606004778, + dmin2: 0.35454858327394784, + dn: 6.1979733096699005E-002, + dn1: 0.21025182606004778, + dn2: 0.51458348500658069, + tau: 5.2226904068357879E-002, + ttype: -8, + g: 0.0000000000000000, + zOut: []float64{0.2066672404121803E+01, 0.2014445500054431E+01, 0.9855809897129084E-12, 0.3842238913414725E-12, 0.7853216498744473E+00, 0.7434869600327952E+00, 0.1039221422709001E-01, 0.1774357001838869E-01, 0.1269422727902604E+01, 0.1204982556290953E+01, 0.5530302475095172E-02, 0.7478273627729330E-02, 0.1629420689585235E+01, 0.1587435244082034E+01, 0.1771973219288664E-01, 0.1647944669694028E-01, 0.1476323355507364E+01, 0.1410360675918078E+01, 0.2743671176012720E-02, 0.3156160674217245E-02, 0.1622397370614960E+01, 0.1812549313022337E+01, 0.2455350071499520E+00, 0.1051878329628395E+00, 0.7765008199367077E+00, 0.6801494335398012E+00, 0.6106335063429082E-01, 0.1316523902981273E+00, 0.1466400021540057E+01, 0.1591782250225264E+01, 0.3092615230516922E+00, 0.1616733433116970E+00, 0.8321395939549830E+00, 0.6372362842978442E+00, 0.1899693772291602E-01, 0.2096244776016672E-01, 0.7031676639315663E+00, 0.6722400808665288E+00, 0.4226176876348708E-01, 0.2728832287468248E-01, 0.4340638102169883E+00, 0.4090709896187213E+00, 0.5452240634477346E-01, 0.8716398206477828E-01, 0.6539743711397168E+00, 0.5490759679957803E+00, 0.3449248298919955E-01, 0.1759392479116377E-01, 0.2800726549195695E+00, 0.2884916852972659E+00, 0.7823985923721809E-01, 0.4249908970207047E-01, 0.1567057268671274E+00, 0.6197973309669901E-01, 0.3158014839988858E-37, 0.3842238913414725E-12, 0.4143051093784424E+00}, + tauOut: 4.3992746597899146E-002, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1970452753456916E+01, 0.2014445500054431E+01, 0.1449745254963753E-12, 0.3842238913414725E-12, 0.7172377834531399E+00, 0.7434869600327952E+00, 0.2980976860358389E-01, 0.1774357001838869E-01, 0.1138658314717199E+01, 0.1204982556290953E+01, 0.1042566937606312E-01, 0.7478273627729330E-02, 0.1549496274805013E+01, 0.1587435244082034E+01, 0.1499968987352189E-01, 0.1647944669694028E-01, 0.1354524400120875E+01, 0.1410360675918078E+01, 0.4223398900256122E-02, 0.3156160674217245E-02, 0.1869521000487022E+01, 0.1812549313022337E+01, 0.3826832915293116E-01, 0.1051878329628395E+00, 0.7295407480870981E+00, 0.6801494335398012E+00, 0.2872518617030954E+00, 0.1316523902981273E+00, 0.1422210985235967E+01, 0.1591782250225264E+01, 0.7243940711431240E-01, 0.1616733433116970E+00, 0.5417665783457993E+00, 0.6372362842978442E+00, 0.2601082853889214E-01, 0.2096244776016672E-01, 0.6295248286044199E+00, 0.6722400808665288E+00, 0.1773220171177086E-01, 0.2728832287468248E-01, 0.4345100233738295E+00, 0.4090709896187213E+00, 0.1101462457758059E+00, 0.8716398206477828E-01, 0.4125309004132391E+00, 0.5490759679957803E+00, 0.1230380805149813E-01, 0.1759392479116377E-01, 0.2746942203499391E+00, 0.2884916852972659E+00, 0.9589143278047064E-02, 0.4249908970207047E-01, 0.8397843220752800E-02, 0.6197973309669901E-01, 0.1449745254963753E-12, 0.3842238913414725E-12}, + i0: 1, + n0: 14, + pp: 0, + n0in: 14, + dmin: 8.3978432207528000E-003, + dmin1: 0.23219513064786862, + dmin2: 0.34734604130905122, + dn: 8.3978432207528000E-003, + dn1: 0.23219513064786862, + dn2: 0.39493697562207530, + tau: 4.3992746597899146E-002, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1970452753456916E+01, 0.2014445500054431E+01, 0.1449745254963753E-12, 0.3842238913414725E-12, 0.7172377834531399E+00, 0.7434869600327952E+00, 0.2980976860358389E-01, 0.1774357001838869E-01, 0.1138658314717199E+01, 0.1204982556290953E+01, 0.1042566937606312E-01, 0.7478273627729330E-02, 0.1549496274805013E+01, 0.1587435244082034E+01, 0.1499968987352189E-01, 0.1647944669694028E-01, 0.1354524400120875E+01, 0.1410360675918078E+01, 0.4223398900256122E-02, 0.3156160674217245E-02, 0.1869521000487022E+01, 0.1812549313022337E+01, 0.3826832915293116E-01, 0.1051878329628395E+00, 0.7295407480870981E+00, 0.6801494335398012E+00, 0.2872518617030954E+00, 0.1316523902981273E+00, 0.1422210985235967E+01, 0.1591782250225264E+01, 0.7243940711431240E-01, 0.1616733433116970E+00, 0.5417665783457993E+00, 0.6372362842978442E+00, 0.2601082853889214E-01, 0.2096244776016672E-01, 0.6295248286044199E+00, 0.6722400808665288E+00, 0.1773220171177086E-01, 0.2728832287468248E-01, 0.4345100233738295E+00, 0.4090709896187213E+00, 0.1101462457758059E+00, 0.8716398206477828E-01, 0.4125309004132391E+00, 0.5490759679957803E+00, 0.1230380805149813E-01, 0.1759392479116377E-01, 0.2746942203499391E+00, 0.2884916852972659E+00, 0.9589143278047064E-02, 0.4249908970207047E-01, 0.8397843220752800E-02, 0.6197973309669901E-01, 0.1449745254963753E-12, 0.3842238913414725E-12}, + tauOut: 8.0121275381568099E-003, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1970452753456916E+01, 0.1962440625918904E+01, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.7172377834531399E+00, 0.7390354245185139E+00, 0.2980976860358389E-01, 0.4592897681783073E-01, 0.1138658314717199E+01, 0.1095142879737275E+01, 0.1042566937606312E-01, 0.1475107600976594E-01, 0.1549496274805013E+01, 0.1541732761130612E+01, 0.1499968987352189E-01, 0.1317831886314191E-01, 0.1354524400120875E+01, 0.1337557352619832E+01, 0.4223398900256122E-02, 0.5903098601340335E-02, 0.1869521000487022E+01, 0.1893874103500456E+01, 0.3826832915293116E-01, 0.1474137347708128E-01, 0.7295407480870981E+00, 0.9940391087749554E+00, 0.2872518617030954E+00, 0.4109825756725979E+00, 0.1422210985235967E+01, 0.1075655689139524E+01, 0.7243940711431240E-01, 0.3648495529374628E-01, 0.5417665783457993E+00, 0.5232803240527883E+00, 0.2601082853889214E-01, 0.3129195122603765E-01, 0.6295248286044199E+00, 0.6079529515519964E+00, 0.1773220171177086E-01, 0.1267338099203561E-01, 0.4345100233738295E+00, 0.5239707606194429E+00, 0.1101462457758059E+00, 0.8671997249104711E-01, 0.4125309004132391E+00, 0.3301026084355332E+00, 0.1230380805149813E-01, 0.1023858907404432E-01, 0.2746942203499391E+00, 0.2660326470157850E+00, 0.9589143278047064E-02, 0.3027001489241909E-03, 0.8397843220752800E-02, 0.8301553367179998E-04, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + n0in: 14, + dmin: 8.3015533671799979E-005, + dmin1: 0.25644350373773794, + dmin2: 0.31779880038403513, + dn: 8.3015533671799979E-005, + dn1: 0.25644350373773794, + dn2: 0.31779880038403513, + tau: 8.0121275381568099E-003, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1970452753456916E+01, 0.1962440625918904E+01, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.7172377834531399E+00, 0.7390354245185139E+00, 0.2980976860358389E-01, 0.4592897681783073E-01, 0.1138658314717199E+01, 0.1095142879737275E+01, 0.1042566937606312E-01, 0.1475107600976594E-01, 0.1549496274805013E+01, 0.1541732761130612E+01, 0.1499968987352189E-01, 0.1317831886314191E-01, 0.1354524400120875E+01, 0.1337557352619832E+01, 0.4223398900256122E-02, 0.5903098601340335E-02, 0.1869521000487022E+01, 0.1893874103500456E+01, 0.3826832915293116E-01, 0.1474137347708128E-01, 0.7295407480870981E+00, 0.9940391087749554E+00, 0.2872518617030954E+00, 0.4109825756725979E+00, 0.1422210985235967E+01, 0.1075655689139524E+01, 0.7243940711431240E-01, 0.3648495529374628E-01, 0.5417665783457993E+00, 0.5232803240527883E+00, 0.2601082853889214E-01, 0.3129195122603765E-01, 0.6295248286044199E+00, 0.6079529515519964E+00, 0.1773220171177086E-01, 0.1267338099203561E-01, 0.4345100233738295E+00, 0.5239707606194429E+00, 0.1101462457758059E+00, 0.8671997249104711E-01, 0.4125309004132391E+00, 0.3301026084355332E+00, 0.1230380805149813E-01, 0.1023858907404432E-01, 0.2746942203499391E+00, 0.2660326470157850E+00, 0.9589143278047064E-02, 0.3027001489241909E-03, 0.8397843220752800E-02, 0.8301553367179998E-04, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.4143051093784424E+00}, + tauOut: 8.2898056486573887E-005, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1962357727862470E+01, 0.1962440625918904E+01, 0.1995470932711637E-13, 0.5298565773193886E-13, 0.7848815032798381E+00, 0.7390354245185139E+00, 0.6408456783027588E-01, 0.4592897681783073E-01, 0.1045726489860278E+01, 0.1095142879737275E+01, 0.2174776805091989E-01, 0.1475107600976594E-01, 0.1533080413886347E+01, 0.1541732761130612E+01, 0.1149760777771624E-01, 0.1317831886314191E-01, 0.1331879945386970E+01, 0.1337557352619832E+01, 0.8393943921304423E-02, 0.5903098601340335E-02, 0.1900138634999746E+01, 0.1893874103500456E+01, 0.7711806645770664E-02, 0.1474137347708128E-01, 0.1397226979745296E+01, 0.9940391087749554E+00, 0.3163950825942626E+00, 0.4109825756725979E+00, 0.7956626637825215E+00, 0.1075655689139524E+01, 0.2399491656225486E-01, 0.3648495529374628E-01, 0.5304944606600845E+00, 0.5232803240527883E+00, 0.3586094769777509E-01, 0.3129195122603765E-01, 0.5846824867897703E+00, 0.6079529515519964E+00, 0.1135741402906866E-01, 0.1267338099203561E-01, 0.5992504210249349E+00, 0.5239707606194429E+00, 0.4777049480214081E-01, 0.8671997249104711E-01, 0.2924878046509502E+00, 0.3301026084355332E+00, 0.9312521444528056E-02, 0.1023858907404432E-01, 0.2569399276636945E+00, 0.2660326470157850E+00, 0.9780034825247492E-07, 0.3027001489241909E-03, 0.1967683697362142E-07, 0.8301553367179998E-04, 0.1995470932711637E-13, 0.5298565773193886E-13}, + i0: 1, + n0: 14, + pp: 0, + n0in: 14, + dmin: 1.9676836973621424E-008, + dmin1: 0.25663722751477031, + dmin2: 0.28224921557690585, + dn: 1.9676836973621424E-008, + dn1: 0.25663722751477031, + dn2: 0.28224921557690585, + tau: 8.2898056486573887E-005, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1962357727862470E+01, 0.1962440625918904E+01, 0.1995470932711637E-13, 0.5298565773193886E-13, 0.7848815032798381E+00, 0.7390354245185139E+00, 0.6408456783027588E-01, 0.4592897681783073E-01, 0.1045726489860278E+01, 0.1095142879737275E+01, 0.2174776805091989E-01, 0.1475107600976594E-01, 0.1533080413886347E+01, 0.1541732761130612E+01, 0.1149760777771624E-01, 0.1317831886314191E-01, 0.1331879945386970E+01, 0.1337557352619832E+01, 0.8393943921304423E-02, 0.5903098601340335E-02, 0.1900138634999746E+01, 0.1893874103500456E+01, 0.7711806645770664E-02, 0.1474137347708128E-01, 0.1397226979745296E+01, 0.9940391087749554E+00, 0.3163950825942626E+00, 0.4109825756725979E+00, 0.7956626637825215E+00, 0.1075655689139524E+01, 0.2399491656225486E-01, 0.3648495529374628E-01, 0.5304944606600845E+00, 0.5232803240527883E+00, 0.3586094769777509E-01, 0.3129195122603765E-01, 0.5846824867897703E+00, 0.6079529515519964E+00, 0.1135741402906866E-01, 0.1267338099203561E-01, 0.5992504210249349E+00, 0.5239707606194429E+00, 0.4777049480214081E-01, 0.8671997249104711E-01, 0.2924878046509502E+00, 0.3301026084355332E+00, 0.9312521444528056E-02, 0.1023858907404432E-01, 0.2569399276636945E+00, 0.2660326470157850E+00, 0.9780034825247492E-07, 0.3027001489241909E-03, 0.1967683697362142E-07, 0.8301553367179998E-04, 0.1995470932711637E-13, 0.5298565773193886E-13}, + tauOut: 1.9676827722764296E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1962357727862470E+01, 0.1962357708185662E+01, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.7848815032798381E+00, 0.8489660514332782E+00, 0.6408456783027588E-01, 0.7893711422056097E-01, 0.1045726489860278E+01, 0.9885371240138099E+00, 0.2174776805091989E-01, 0.3372769361380378E-01, 0.1533080413886347E+01, 0.1510850308373431E+01, 0.1149760777771624E-01, 0.1013563894066502E-01, 0.1331879945386970E+01, 0.1330138230690781E+01, 0.8393943921304423E-02, 0.1199097716077874E-01, 0.1900138634999746E+01, 0.1895859444807910E+01, 0.7711806645770664E-02, 0.5683514322519618E-02, 0.1397226979745296E+01, 0.1707938528340212E+01, 0.3163950825942626E+00, 0.1473962616612956E+00, 0.7956626637825215E+00, 0.6722612990066530E+00, 0.2399491656225486E-01, 0.1893485515094503E-01, 0.5304944606600845E+00, 0.5474205335300870E+00, 0.3586094769777509E-01, 0.3830193935796279E-01, 0.5846824867897703E+00, 0.5577379417840483E+00, 0.1135741402906866E-01, 0.1220274725600271E-01, 0.5992504210249349E+00, 0.6348181488942451E+00, 0.4777049480214081E-01, 0.2200990500366971E-01, 0.2924878046509502E+00, 0.2797904014149808E+00, 0.9312521444528056E-02, 0.8551968095484232E-02, 0.2569399276636945E+00, 0.2483880376917308E+00, 0.9780034825247492E-07, 0.7747561140265878E-14, 0.1967683697362142E-07, 0.1503295986001297E-14, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + n0in: 14, + dmin: 1.5032959860012969E-015, + dmin1: 0.24838793989138258, + dmin2: 0.27047787997045275, + dn: 1.5032959860012969E-015, + dn1: 0.24838793989138258, + dn2: 0.27047787997045275, + tau: 1.9676827722764296E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1962357727862470E+01, 0.1962357708185662E+01, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.7848815032798381E+00, 0.8489660514332782E+00, 0.6408456783027588E-01, 0.7893711422056097E-01, 0.1045726489860278E+01, 0.9885371240138099E+00, 0.2174776805091989E-01, 0.3372769361380378E-01, 0.1533080413886347E+01, 0.1510850308373431E+01, 0.1149760777771624E-01, 0.1013563894066502E-01, 0.1331879945386970E+01, 0.1330138230690781E+01, 0.8393943921304423E-02, 0.1199097716077874E-01, 0.1900138634999746E+01, 0.1895859444807910E+01, 0.7711806645770664E-02, 0.5683514322519618E-02, 0.1397226979745296E+01, 0.1707938528340212E+01, 0.3163950825942626E+00, 0.1473962616612956E+00, 0.7956626637825215E+00, 0.6722612990066530E+00, 0.2399491656225486E-01, 0.1893485515094503E-01, 0.5304944606600845E+00, 0.5474205335300870E+00, 0.3586094769777509E-01, 0.3830193935796279E-01, 0.5846824867897703E+00, 0.5577379417840483E+00, 0.1135741402906866E-01, 0.1220274725600271E-01, 0.5992504210249349E+00, 0.6348181488942451E+00, 0.4777049480214081E-01, 0.2200990500366971E-01, 0.2924878046509502E+00, 0.2797904014149808E+00, 0.9312521444528056E-02, 0.8551968095484232E-02, 0.2569399276636945E+00, 0.2483880376917308E+00, 0.9780034825247492E-07, 0.7747561140265878E-14, 0.1967683697362142E-07, 0.1503295986001297E-14, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.4143051093784424E+00}, + tauOut: 1.5032959860012393E-015, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1962357708185669E+01, 0.1962357708185662E+01, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.9279031656538340E+00, 0.8489660514332782E+00, 0.8409527066820451E-01, 0.7893711422056097E-01, 0.9381695469594078E+00, 0.9885371240138099E+00, 0.5431587122209677E-01, 0.3372769361380378E-01, 0.1466670076091998E+01, 0.1510850308373431E+01, 0.9192115573380727E-02, 0.1013563894066502E-01, 0.1332937092278178E+01, 0.1330138230690781E+01, 0.1705497388769041E-01, 0.1199097716077874E-01, 0.1884487985242738E+01, 0.1895859444807910E+01, 0.5151050664063701E-02, 0.5683514322519618E-02, 0.1850183739337442E+01, 0.1707938528340212E+01, 0.5355619565040129E-01, 0.1473962616612956E+00, 0.6376399585071952E+00, 0.6722612990066530E+00, 0.1625577000116482E-01, 0.1893485515094503E-01, 0.5694667028868834E+00, 0.5474205335300870E+00, 0.3751307094084999E-01, 0.3830193935796279E-01, 0.5324276180991995E+00, 0.5577379417840483E+00, 0.1454944326918194E-01, 0.1220274725600271E-01, 0.6422786106287314E+00, 0.6348181488942451E+00, 0.9587988848101409E-02, 0.2200990500366971E-01, 0.2787543806623621E+00, 0.2797904014149808E+00, 0.7620352256320365E-02, 0.8551968095484232E-02, 0.2407676854354167E+00, 0.2483880376917308E+00, 0.4837392336267432E-28, 0.7747561140265878E-14}, + i0: 1, + n0: 13, + pp: 0, + n0in: 14, + dmin: 9.2691156363468887E-030, + dmin1: 0.24076768543540897, + dmin2: 0.27020241256687788, + dn: 9.2691156363468887E-030, + dn1: 0.24076768543540897, + dn2: 0.27020241256687788, + tau: 1.5032959860012393E-015, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1962357708185669E+01, 0.1962357708185662E+01, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.9279031656538340E+00, 0.8489660514332782E+00, 0.8409527066820451E-01, 0.7893711422056097E-01, 0.9381695469594078E+00, 0.9885371240138099E+00, 0.5431587122209677E-01, 0.3372769361380378E-01, 0.1466670076091998E+01, 0.1510850308373431E+01, 0.9192115573380727E-02, 0.1013563894066502E-01, 0.1332937092278178E+01, 0.1330138230690781E+01, 0.1705497388769041E-01, 0.1199097716077874E-01, 0.1884487985242738E+01, 0.1895859444807910E+01, 0.5151050664063701E-02, 0.5683514322519618E-02, 0.1850183739337442E+01, 0.1707938528340212E+01, 0.5355619565040129E-01, 0.1473962616612956E+00, 0.6376399585071952E+00, 0.6722612990066530E+00, 0.1625577000116482E-01, 0.1893485515094503E-01, 0.5694667028868834E+00, 0.5474205335300870E+00, 0.3751307094084999E-01, 0.3830193935796279E-01, 0.5324276180991995E+00, 0.5577379417840483E+00, 0.1454944326918194E-01, 0.1220274725600271E-01, 0.6422786106287314E+00, 0.6348181488942451E+00, 0.9587988848101409E-02, 0.2200990500366971E-01, 0.2787543806623621E+00, 0.2797904014149808E+00, 0.7620352256320365E-02, 0.8551968095484232E-02, 0.2407676854354167E+00, 0.2483880376917308E+00, 0.4837392336267432E-28, 0.7747561140265878E-14}, + tauOut: 0.19361025134591583, + ttypeOut: -8, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1962357708185669E+01, 0.1768747456839757E+01, 0.3452895805257589E-14, 0.1811424766142649E-14, 0.9279031656538340E+00, 0.8183881849761209E+00, 0.8409527066820451E-01, 0.9640366690596863E-01, 0.9381695469594078E+00, 0.7024714999296202E+00, 0.5431587122209677E-01, 0.1134045480653624E+00, 0.1466670076091998E+01, 0.1168847392254101E+01, 0.9192115573380727E-02, 0.1048255904531585E-01, 0.1332937092278178E+01, 0.1145899255774637E+01, 0.1705497388769041E-01, 0.2804774784346500E-01, 0.1884487985242738E+01, 0.1667981036717421E+01, 0.5151050664063701E-02, 0.5713728135608638E-02, 0.1850183739337442E+01, 0.1704415955506319E+01, 0.5355619565040129E-01, 0.2003593680404179E-01, 0.6376399585071952E+00, 0.4402495403584025E+00, 0.1625577000116482E-01, 0.2102698332839761E-01, 0.5694667028868834E+00, 0.3923425391534199E+00, 0.3751307094084999E-01, 0.5090703407211448E-01, 0.5324276180991995E+00, 0.3024597759503511E+00, 0.1454944326918194E-01, 0.3089599659653809E-01, 0.6422786106287314E+00, 0.4273603515343789E+00, 0.9587988848101409E-02, 0.6253958476854957E-02, 0.2787543806623621E+00, 0.8651052309591171E-01, 0.7620352256320365E-02, 0.2120822426333837E-01, 0.2407676854354167E+00, 0.2594920982616250E-01, 0.4837392336267432E-28, 0.1811424766142649E-14, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + n0in: 13, + dmin: 2.5949209826162500E-002, + dmin1: 7.8890170839591350E-002, + dmin2: 0.28791033268116917, + dn: 2.5949209826162500E-002, + dn1: 7.8890170839591350E-002, + dn2: 0.41777236268627749, + tau: 0.19361025134591583, + ttype: -8, + g: 0.0000000000000000, + zOut: []float64{0.1962357708185669E+01, 0.1768747456839757E+01, 0.3452895805257589E-14, 0.1811424766142649E-14, 0.9279031656538340E+00, 0.8183881849761209E+00, 0.8409527066820451E-01, 0.9640366690596863E-01, 0.9381695469594078E+00, 0.7024714999296202E+00, 0.5431587122209677E-01, 0.1134045480653624E+00, 0.1466670076091998E+01, 0.1168847392254101E+01, 0.9192115573380727E-02, 0.1048255904531585E-01, 0.1332937092278178E+01, 0.1145899255774637E+01, 0.1705497388769041E-01, 0.2804774784346500E-01, 0.1884487985242738E+01, 0.1667981036717421E+01, 0.5151050664063701E-02, 0.5713728135608638E-02, 0.1850183739337442E+01, 0.1704415955506319E+01, 0.5355619565040129E-01, 0.2003593680404179E-01, 0.6376399585071952E+00, 0.4402495403584025E+00, 0.1625577000116482E-01, 0.2102698332839761E-01, 0.5694667028868834E+00, 0.3923425391534199E+00, 0.3751307094084999E-01, 0.5090703407211448E-01, 0.5324276180991995E+00, 0.3024597759503511E+00, 0.1454944326918194E-01, 0.3089599659653809E-01, 0.6422786106287314E+00, 0.4273603515343789E+00, 0.9587988848101409E-02, 0.6253958476854957E-02, 0.2787543806623621E+00, 0.8651052309591171E-01, 0.7620352256320365E-02, 0.2120822426333837E-01, 0.2407676854354167E+00, 0.2594920982616250E-01, 0.4837392336267432E-28, 0.1811424766142649E-14, 0.5186198053161721E+00}, + tauOut: 1.8780556192507153E-002, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749966900647251E+01, 0.1768747456839757E+01, 0.8471295234418270E-15, 0.1811424766142649E-14, 0.8960112956895816E+00, 0.8183881849761209E+00, 0.7558032897122403E-01, 0.9640366690596863E-01, 0.7215151628312513E+00, 0.7024714999296202E+00, 0.1837142406762631E+00, 0.1134045480653624E+00, 0.9768351544306461E+00, 0.1168847392254101E+01, 0.1229681032071614E-01, 0.1048255904531585E-01, 0.1142869637104878E+01, 0.1145899255774637E+01, 0.4093477506677201E-01, 0.2804774784346500E-01, 0.1613979433593750E+01, 0.1667981036717421E+01, 0.6033886923870183E-02, 0.5713728135608638E-02, 0.1699637449193983E+01, 0.1704415955506319E+01, 0.5189819730562233E-02, 0.2003593680404179E-01, 0.4373061477637308E+00, 0.4402495403584025E+00, 0.1886499897608887E-01, 0.2102698332839761E-01, 0.4056040180569384E+00, 0.3923425391534199E+00, 0.3796148320598534E-01, 0.5090703407211448E-01, 0.2766137331483968E+00, 0.3024597759503511E+00, 0.4773343613933298E-01, 0.3089599659653809E-01, 0.3671003176793937E+00, 0.4273603515343789E+00, 0.1473802100398464E-02, 0.6253958476854957E-02, 0.8746438906634448E-01, 0.8651052309591171E-01, 0.6292122626412339E-02, 0.2120822426333837E-01, 0.8765310072430081E-03, 0.2594920982616250E-01, 0.8471295234418270E-15, 0.1811424766142649E-14}, + i0: 1, + n0: 13, + pp: 0, + n0in: 13, + dmin: 8.7653100724300811E-004, + dmin1: 6.6256164803006098E-002, + dmin2: 0.24571773655185866, + dn: 8.7653100724300811E-004, + dn1: 6.6256164803006098E-002, + dn2: 0.36084635920253871, + tau: 1.8780556192507153E-002, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749966900647251E+01, 0.1768747456839757E+01, 0.8471295234418270E-15, 0.1811424766142649E-14, 0.8960112956895816E+00, 0.8183881849761209E+00, 0.7558032897122403E-01, 0.9640366690596863E-01, 0.7215151628312513E+00, 0.7024714999296202E+00, 0.1837142406762631E+00, 0.1134045480653624E+00, 0.9768351544306461E+00, 0.1168847392254101E+01, 0.1229681032071614E-01, 0.1048255904531585E-01, 0.1142869637104878E+01, 0.1145899255774637E+01, 0.4093477506677201E-01, 0.2804774784346500E-01, 0.1613979433593750E+01, 0.1667981036717421E+01, 0.6033886923870183E-02, 0.5713728135608638E-02, 0.1699637449193983E+01, 0.1704415955506319E+01, 0.5189819730562233E-02, 0.2003593680404179E-01, 0.4373061477637308E+00, 0.4402495403584025E+00, 0.1886499897608887E-01, 0.2102698332839761E-01, 0.4056040180569384E+00, 0.3923425391534199E+00, 0.3796148320598534E-01, 0.5090703407211448E-01, 0.2766137331483968E+00, 0.3024597759503511E+00, 0.4773343613933298E-01, 0.3089599659653809E-01, 0.3671003176793937E+00, 0.4273603515343789E+00, 0.1473802100398464E-02, 0.6253958476854957E-02, 0.8746438906634448E-01, 0.8651052309591171E-01, 0.6292122626412339E-02, 0.2120822426333837E-01, 0.8765310072430081E-03, 0.2594920982616250E-01, 0.8471295234418270E-15, 0.1811424766142649E-14}, + tauOut: 8.1622622999092049E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749966900647251E+01, 0.1749150674417261E+01, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.8960112956895816E+00, 0.9707753984308143E+00, 0.7558032897122403E-01, 0.5617401661873561E-01, 0.7215151628312513E+00, 0.8482391606587878E+00, 0.1837142406762631E+00, 0.2115659556707206E+00, 0.9768351544306461E+00, 0.7767497828506508E+00, 0.1229681032071614E-01, 0.1809289356632693E-01, 0.1142869637104878E+01, 0.1164895292375332E+01, 0.4093477506677201E-01, 0.5671572845129930E-01, 0.1613979433593750E+01, 0.1562481365836330E+01, 0.6033886923870183E-02, 0.6563547191183529E-02, 0.1699637449193983E+01, 0.1697447495503371E+01, 0.5189819730562233E-02, 0.1337031089310571E-02, 0.4373061477637308E+00, 0.4540178894205181E+00, 0.1886499897608887E-01, 0.1685334336738995E-01, 0.4056040180569384E+00, 0.4258959316655428E+00, 0.3796148320598534E-01, 0.2465547755855056E-01, 0.2766137331483968E+00, 0.2988754654991882E+00, 0.4773343613933298E-01, 0.5862963539483231E-01, 0.3671003176793937E+00, 0.3091282581549689E+00, 0.1473802100398464E-02, 0.4169958485368410E-03, 0.8746438906634448E-01, 0.9252328961422907E-01, 0.6292122626412339E-02, 0.5960921413863723E-04, 0.8765310072430081E-03, 0.6955631134505013E-06, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + n0in: 13, + dmin: 6.9556311345050133E-007, + dmin1: 8.6231166987816729E-002, + dmin2: 0.25114202935985525, + dn: 6.9556311345050133E-007, + dn1: 8.6231166987816729E-002, + dn2: 0.30765445605457048, + tau: 8.1622622999092049E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749966900647251E+01, 0.1749150674417261E+01, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.8960112956895816E+00, 0.9707753984308143E+00, 0.7558032897122403E-01, 0.5617401661873561E-01, 0.7215151628312513E+00, 0.8482391606587878E+00, 0.1837142406762631E+00, 0.2115659556707206E+00, 0.9768351544306461E+00, 0.7767497828506508E+00, 0.1229681032071614E-01, 0.1809289356632693E-01, 0.1142869637104878E+01, 0.1164895292375332E+01, 0.4093477506677201E-01, 0.5671572845129930E-01, 0.1613979433593750E+01, 0.1562481365836330E+01, 0.6033886923870183E-02, 0.6563547191183529E-02, 0.1699637449193983E+01, 0.1697447495503371E+01, 0.5189819730562233E-02, 0.1337031089310571E-02, 0.4373061477637308E+00, 0.4540178894205181E+00, 0.1886499897608887E-01, 0.1685334336738995E-01, 0.4056040180569384E+00, 0.4258959316655428E+00, 0.3796148320598534E-01, 0.2465547755855056E-01, 0.2766137331483968E+00, 0.2988754654991882E+00, 0.4773343613933298E-01, 0.5862963539483231E-01, 0.3671003176793937E+00, 0.3091282581549689E+00, 0.1473802100398464E-02, 0.4169958485368410E-03, 0.8746438906634448E-01, 0.9252328961422907E-01, 0.6292122626412339E-02, 0.5960921413863723E-04, 0.8765310072430081E-03, 0.6955631134505013E-06, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.5186198053161721E+00}, + tauOut: 6.9511331676175615E-007, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749149979303945E+01, 0.1749150674417261E+01, 0.2408395422307052E-15, 0.4339463906783712E-15, 0.1026948719936233E+01, 0.9707753984308143E+00, 0.4639861736277134E-01, 0.5617401661873561E-01, 0.1013405803853420E+01, 0.8482391606587878E+00, 0.1621599259654447E+00, 0.2115659556707206E+00, 0.6326820553382161E+00, 0.7767497828506508E+00, 0.3331266686486833E-01, 0.1809289356632693E-01, 0.1188297658848447E+01, 0.1164895292375332E+01, 0.7457497555020480E-01, 0.5671572845129930E-01, 0.1494469242363992E+01, 0.1562481365836330E+01, 0.7455005714048079E-02, 0.6563547191183529E-02, 0.1691328825765317E+01, 0.1697447495503371E+01, 0.3589107121045615E-03, 0.1337031089310571E-02, 0.4705116269624868E+00, 0.4540178894205181E+00, 0.1525524548983380E-01, 0.1685334336738995E-01, 0.4352954686209429E+00, 0.4258959316655428E+00, 0.1692854133253905E-01, 0.2465547755855056E-01, 0.3405758644481647E+00, 0.2988754654991882E+00, 0.5321597610926388E-01, 0.5862963539483231E-01, 0.2563285827809251E+00, 0.3091282581549689E+00, 0.1505170716567330E-03, 0.4169958485368410E-03, 0.9243168664339420E-01, 0.9252328961422907E-01, 0.4485687980202113E-09, 0.5960921413863723E-04, 0.1227890724922389E-11, 0.6955631134505013E-06, 0.2408395422307052E-15, 0.4339463906783712E-15}, + i0: 1, + n0: 13, + pp: 0, + n0in: 13, + dmin: 1.2278907249223888E-012, + dmin1: 9.2372077429255559E-002, + dmin2: 0.25591158693238830, + dn: 1.2278907249223888E-012, + dn1: 9.2372077429255559E-002, + dn2: 0.25591158693238830, + tau: 6.9511331676175615E-007, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749149979303945E+01, 0.1749150674417261E+01, 0.2408395422307052E-15, 0.4339463906783712E-15, 0.1026948719936233E+01, 0.9707753984308143E+00, 0.4639861736277134E-01, 0.5617401661873561E-01, 0.1013405803853420E+01, 0.8482391606587878E+00, 0.1621599259654447E+00, 0.2115659556707206E+00, 0.6326820553382161E+00, 0.7767497828506508E+00, 0.3331266686486833E-01, 0.1809289356632693E-01, 0.1188297658848447E+01, 0.1164895292375332E+01, 0.7457497555020480E-01, 0.5671572845129930E-01, 0.1494469242363992E+01, 0.1562481365836330E+01, 0.7455005714048079E-02, 0.6563547191183529E-02, 0.1691328825765317E+01, 0.1697447495503371E+01, 0.3589107121045615E-03, 0.1337031089310571E-02, 0.4705116269624868E+00, 0.4540178894205181E+00, 0.1525524548983380E-01, 0.1685334336738995E-01, 0.4352954686209429E+00, 0.4258959316655428E+00, 0.1692854133253905E-01, 0.2465547755855056E-01, 0.3405758644481647E+00, 0.2988754654991882E+00, 0.5321597610926388E-01, 0.5862963539483231E-01, 0.2563285827809251E+00, 0.3091282581549689E+00, 0.1505170716567330E-03, 0.4169958485368410E-03, 0.9243168664339420E-01, 0.9252328961422907E-01, 0.4485687980202113E-09, 0.5960921413863723E-04, 0.1227890724922389E-11, 0.6955631134505013E-06, 0.2408395422307052E-15, 0.4339463906783712E-15}, + tauOut: 1.2278907189544363E-012, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749149979303945E+01, 0.1749149979302717E+01, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.1026948719936233E+01, 0.1073347337297776E+01, 0.4639861736277134E-01, 0.4380746706334982E-01, 0.1013405803853420E+01, 0.1131758262754287E+01, 0.1621599259654447E+00, 0.9065158049178278E-01, 0.6326820553382161E+00, 0.5753431417100738E+00, 0.3331266686486833E-01, 0.6880305191066147E-01, 0.1188297658848447E+01, 0.1194069582486762E+01, 0.7457497555020480E-01, 0.9333627524262254E-01, 0.1494469242363992E+01, 0.1408587972834190E+01, 0.7455005714048079E-02, 0.8951422490882578E-02, 0.1691328825765317E+01, 0.1682736313985311E+01, 0.3589107121045615E-03, 0.1003553923945662E-03, 0.4705116269624868E+00, 0.4856665170586981E+00, 0.1525524548983380E-01, 0.1367304312976171E-01, 0.4352954686209429E+00, 0.4385509668224923E+00, 0.1692854133253905E-01, 0.1314659648329904E-01, 0.3405758644481647E+00, 0.3806452440729016E+00, 0.5321597610926388E-01, 0.3583592846566260E-01, 0.2563285827809251E+00, 0.2206431713856914E+00, 0.1505170716567330E-03, 0.6305450884558253E-04, 0.9243168664339420E-01, 0.9236863258188953E-01, 0.4485687980202113E-09, 0.5962992535266723E-20, 0.1227890724922389E-11, 0.4959852501050381E-23, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + n0in: 13, + dmin: 4.9598525010503808E-024, + dmin1: 9.2368632133320736E-002, + dmin2: 0.22049265431403467, + dn: 4.9598525010503808E-024, + dn1: 9.2368632133320736E-002, + dn2: 0.22049265431403467, + tau: 1.2278907189544363E-012, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749149979303945E+01, 0.1749149979302717E+01, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.1026948719936233E+01, 0.1073347337297776E+01, 0.4639861736277134E-01, 0.4380746706334982E-01, 0.1013405803853420E+01, 0.1131758262754287E+01, 0.1621599259654447E+00, 0.9065158049178278E-01, 0.6326820553382161E+00, 0.5753431417100738E+00, 0.3331266686486833E-01, 0.6880305191066147E-01, 0.1188297658848447E+01, 0.1194069582486762E+01, 0.7457497555020480E-01, 0.9333627524262254E-01, 0.1494469242363992E+01, 0.1408587972834190E+01, 0.7455005714048079E-02, 0.8951422490882578E-02, 0.1691328825765317E+01, 0.1682736313985311E+01, 0.3589107121045615E-03, 0.1003553923945662E-03, 0.4705116269624868E+00, 0.4856665170586981E+00, 0.1525524548983380E-01, 0.1367304312976171E-01, 0.4352954686209429E+00, 0.4385509668224923E+00, 0.1692854133253905E-01, 0.1314659648329904E-01, 0.3405758644481647E+00, 0.3806452440729016E+00, 0.5321597610926388E-01, 0.3583592846566260E-01, 0.2563285827809251E+00, 0.2206431713856914E+00, 0.1505170716567330E-03, 0.6305450884558253E-04, 0.9243168664339420E-01, 0.9236863258188953E-01, 0.4485687980202113E-09, 0.5962992535266723E-20, 0.1227890724922389E-11, 0.4959852501050381E-23, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.5186198053161721E+00}, + tauOut: 4.9598525010503808E-024, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749149979302717E+01, 0.1749149979302717E+01, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.1117154804361126E+01, 0.1073347337297776E+01, 0.4438011869593646E-01, 0.4380746706334982E-01, 0.1178029724550133E+01, 0.1131758262754287E+01, 0.4427372589519608E-01, 0.9065158049178278E-01, 0.5998724677255393E+00, 0.5753431417100738E+00, 0.1369551627869799E+00, 0.6880305191066147E-01, 0.1150450694942405E+01, 0.1194069582486762E+01, 0.1142789997988411E+00, 0.9333627524262254E-01, 0.1303260395526232E+01, 0.1408587972834190E+01, 0.1155784656615063E-01, 0.8951422490882578E-02, 0.1671278822811555E+01, 0.1682736313985311E+01, 0.2916285016424428E-04, 0.1003553923945662E-03, 0.4993103973382956E+00, 0.4856665170586981E+00, 0.1200921574220688E-01, 0.1367304312976171E-01, 0.4396883475635844E+00, 0.4385509668224923E+00, 0.1138121911768345E-01, 0.1314659648329904E-01, 0.4050999534208807E+00, 0.3806452440729016E+00, 0.1951852336551518E-01, 0.3583592846566260E-01, 0.2011877025290218E+00, 0.2206431713856914E+00, 0.2894937755625969E-04, 0.6305450884558253E-04, 0.9233968320433328E-01, 0.9236863258188953E-01, 0.3202909346606844E-42, 0.5962992535266723E-20}, + i0: 1, + n0: 12, + pp: 0, + n0in: 13, + dmin: 4.9598525010503808E-024, + dmin1: 9.2339683204333278E-002, + dmin2: 0.20112464802017624, + dn: 4.9598525010503808E-024, + dn1: 9.2339683204333278E-002, + dn2: 0.20112464802017624, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1749149979302717E+01, 0.1749149979302717E+01, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.1117154804361126E+01, 0.1073347337297776E+01, 0.4438011869593646E-01, 0.4380746706334982E-01, 0.1178029724550133E+01, 0.1131758262754287E+01, 0.4427372589519608E-01, 0.9065158049178278E-01, 0.5998724677255393E+00, 0.5753431417100738E+00, 0.1369551627869799E+00, 0.6880305191066147E-01, 0.1150450694942405E+01, 0.1194069582486762E+01, 0.1142789997988411E+00, 0.9333627524262254E-01, 0.1303260395526232E+01, 0.1408587972834190E+01, 0.1155784656615063E-01, 0.8951422490882578E-02, 0.1671278822811555E+01, 0.1682736313985311E+01, 0.2916285016424428E-04, 0.1003553923945662E-03, 0.4993103973382956E+00, 0.4856665170586981E+00, 0.1200921574220688E-01, 0.1367304312976171E-01, 0.4396883475635844E+00, 0.4385509668224923E+00, 0.1138121911768345E-01, 0.1314659648329904E-01, 0.4050999534208807E+00, 0.3806452440729016E+00, 0.1951852336551518E-01, 0.3583592846566260E-01, 0.2011877025290218E+00, 0.2206431713856914E+00, 0.2894937755625969E-04, 0.6305450884558253E-04, 0.9233968320433328E-01, 0.9236863258188953E-01, 0.3202909346606844E-42, 0.5962992535266723E-20}, + tauOut: 9.2159326345418235E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1749149979302717E+01, 0.1656990652957299E+01, 0.8676862906242004E-16, 0.5850002270797901E-16, 0.1117154804361126E+01, 0.1069375596711644E+01, 0.4438011869593646E-01, 0.4888936980013561E-01, 0.1178029724550133E+01, 0.1081254754299776E+01, 0.4427372589519608E-01, 0.2456274906772994E-01, 0.5998724677255393E+00, 0.6201055550993710E+00, 0.1369551627869799E+00, 0.2540860356894923E+00, 0.1150450694942405E+01, 0.9184843327063353E+00, 0.1142789997988411E+00, 0.1621533314992303E+00, 0.1303260395526232E+01, 0.1060505584247734E+01, 0.1155784656615063E-01, 0.1821431635083262E-01, 0.1671278822811555E+01, 0.1560934342965469E+01, 0.2916285016424428E-04, 0.9328588590960435E-05, 0.4993103973382956E+00, 0.4191509581464933E+00, 0.1200921574220688E-01, 0.1259763844648080E-01, 0.4396883475635844E+00, 0.3463126018893689E+00, 0.1138121911768345E-01, 0.1331320693873929E-01, 0.4050999534208807E+00, 0.3191459435022383E+00, 0.1951852336551518E-01, 0.1230436091267282E-01, 0.2011877025290218E+00, 0.9675296464848704E-01, 0.2894937755625969E-04, 0.2762888312745317E-04, 0.9233968320433328E-01, 0.1527279757875810E-03, 0.3202909346606844E-42, 0.5850002270797901E-16, 0.7318275341991307E+00}, + i0: 1, + n0: 12, + pp: 1, + n0in: 12, + dmin: 1.5272797578758102E-004, + dmin1: 9.6724015270930774E-002, + dmin2: 0.29962742013672317, + dn: 1.5272797578758102E-004, + dn1: 9.6724015270930774E-002, + dn2: 0.29962742013672317, + tau: 9.2159326345418235E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.1749149979302717E+01, 0.1656990652957299E+01, 0.8676862906242004E-16, 0.5850002270797901E-16, 0.1117154804361126E+01, 0.1069375596711644E+01, 0.4438011869593646E-01, 0.4888936980013561E-01, 0.1178029724550133E+01, 0.1081254754299776E+01, 0.4427372589519608E-01, 0.2456274906772994E-01, 0.5998724677255393E+00, 0.6201055550993710E+00, 0.1369551627869799E+00, 0.2540860356894923E+00, 0.1150450694942405E+01, 0.9184843327063353E+00, 0.1142789997988411E+00, 0.1621533314992303E+00, 0.1303260395526232E+01, 0.1060505584247734E+01, 0.1155784656615063E-01, 0.1821431635083262E-01, 0.1671278822811555E+01, 0.1560934342965469E+01, 0.2916285016424428E-04, 0.9328588590960435E-05, 0.4993103973382956E+00, 0.4191509581464933E+00, 0.1200921574220688E-01, 0.1259763844648080E-01, 0.4396883475635844E+00, 0.3463126018893689E+00, 0.1138121911768345E-01, 0.1331320693873929E-01, 0.4050999534208807E+00, 0.3191459435022383E+00, 0.1951852336551518E-01, 0.1230436091267282E-01, 0.2011877025290218E+00, 0.9675296464848704E-01, 0.2894937755625969E-04, 0.2762888312745317E-04, 0.9233968320433328E-01, 0.1527279757875810E-03, 0.3202909346606844E-42, 0.5850002270797901E-16, 0.7318275341991307E+00}, + tauOut: 1.5267965277267402E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1656837973304527E+01, 0.1656990652957299E+01, 0.3775776370348287E-16, 0.5850002270797901E-16, 0.1118112286859007E+01, 0.1069375596711644E+01, 0.4727777715386321E-01, 0.4888936980013561E-01, 0.1058387046560870E+01, 0.1081254754299776E+01, 0.1439123541326830E-01, 0.2456274906772994E-01, 0.8596476757228223E+00, 0.6201055550993710E+00, 0.2714763844897646E+00, 0.2540860356894923E+00, 0.8090086000630283E+00, 0.9184843327063353E+00, 0.2125620340079330E+00, 0.1621533314992303E+00, 0.8660051869378607E+00, 0.1060505584247734E+01, 0.3283046378299830E-01, 0.1821431635083262E-01, 0.1527960528118289E+01, 0.1560934342965469E+01, 0.2559023465659061E-05, 0.9328588590960435E-05, 0.4315933579167358E+00, 0.4191509581464933E+00, 0.1010840613748274E-01, 0.1259763844648080E-01, 0.3493647230378528E+00, 0.3463126018893689E+00, 0.1216166289646864E-01, 0.1331320693873929E-01, 0.3191359618656699E+00, 0.3191459435022383E+00, 0.3730332957296599E-02, 0.1230436091267282E-01, 0.9289758092154521E-01, 0.9675296464848704E-01, 0.4542317842367971E-07, 0.2762888312745317E-04, 0.2899836483324881E-08, 0.1527279757875810E-03, 0.3775776370348287E-16, 0.5850002270797901E-16}, + i0: 1, + n0: 12, + pp: 0, + n0in: 12, + dmin: 2.8998364833248812E-009, + dmin1: 9.2869952038417761E-002, + dmin2: 0.30683160095299705, + dn: 2.8998364833248812E-009, + dn1: 9.2869952038417761E-002, + dn2: 0.30683160095299705, + tau: 1.5267965277267402E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1656837973304527E+01, 0.1656990652957299E+01, 0.3775776370348287E-16, 0.5850002270797901E-16, 0.1118112286859007E+01, 0.1069375596711644E+01, 0.4727777715386321E-01, 0.4888936980013561E-01, 0.1058387046560870E+01, 0.1081254754299776E+01, 0.1439123541326830E-01, 0.2456274906772994E-01, 0.8596476757228223E+00, 0.6201055550993710E+00, 0.2714763844897646E+00, 0.2540860356894923E+00, 0.8090086000630283E+00, 0.9184843327063353E+00, 0.2125620340079330E+00, 0.1621533314992303E+00, 0.8660051869378607E+00, 0.1060505584247734E+01, 0.3283046378299830E-01, 0.1821431635083262E-01, 0.1527960528118289E+01, 0.1560934342965469E+01, 0.2559023465659061E-05, 0.9328588590960435E-05, 0.4315933579167358E+00, 0.4191509581464933E+00, 0.1010840613748274E-01, 0.1259763844648080E-01, 0.3493647230378528E+00, 0.3463126018893689E+00, 0.1216166289646864E-01, 0.1331320693873929E-01, 0.3191359618656699E+00, 0.3191459435022383E+00, 0.3730332957296599E-02, 0.1230436091267282E-01, 0.9289758092154521E-01, 0.9675296464848704E-01, 0.4542317842367971E-07, 0.2762888312745317E-04, 0.2899836483324881E-08, 0.1527279757875810E-03, 0.3775776370348287E-16, 0.5850002270797901E-16}, + tauOut: 2.8998350258011044E-009, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1656837973304527E+01, 0.1656837970404692E+01, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.1118112286859007E+01, 0.1165390061113035E+01, 0.4727777715386321E-01, 0.4293685745187325E-01, 0.1058387046560870E+01, 0.1029841421622430E+01, 0.1439123541326830E-01, 0.1201290976848257E-01, 0.8596476757228223E+00, 0.1119111147544269E+01, 0.2714763844897646E+00, 0.1962510428460807E+00, 0.8090086000630283E+00, 0.8253195883250457E+00, 0.2125620340079330E+00, 0.2230406579474441E+00, 0.8660051869378607E+00, 0.6757949898735797E+00, 0.3283046378299830E-01, 0.7422909836846008E-01, 0.1527960528118289E+01, 0.1453733985873459E+01, 0.2559023465659061E-05, 0.7597383986781573E-06, 0.4315933579167358E+00, 0.4417010014159849E+00, 0.1010840613748274E-01, 0.7995273950601426E-02, 0.3493647230378528E+00, 0.3535311090838850E+00, 0.1216166289646864E-01, 0.1097845108004235E-01, 0.3191359618656699E+00, 0.3118878408430891E+00, 0.3730332957296599E-02, 0.1111101051031713E-02, 0.9289758092154521E-01, 0.9178652239385691E-01, 0.4542317842367971E-07, 0.1435066789177947E-14, 0.2899836483324881E-08, 0.2245698748385924E-16, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.7318275341991307E+00}, + i0: 1, + n0: 12, + pp: 1, + n0in: 12, + dmin: 2.2456987483859239E-017, + dmin1: 9.1786476970678488E-002, + dmin2: 0.30815750788579249, + dn: 2.2456987483859239E-017, + dn1: 9.1786476970678488E-002, + dn2: 0.30815750788579249, + tau: 2.8998350258011044E-009, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1656837973304527E+01, 0.1656837970404692E+01, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.1118112286859007E+01, 0.1165390061113035E+01, 0.4727777715386321E-01, 0.4293685745187325E-01, 0.1058387046560870E+01, 0.1029841421622430E+01, 0.1439123541326830E-01, 0.1201290976848257E-01, 0.8596476757228223E+00, 0.1119111147544269E+01, 0.2714763844897646E+00, 0.1962510428460807E+00, 0.8090086000630283E+00, 0.8253195883250457E+00, 0.2125620340079330E+00, 0.2230406579474441E+00, 0.8660051869378607E+00, 0.6757949898735797E+00, 0.3283046378299830E-01, 0.7422909836846008E-01, 0.1527960528118289E+01, 0.1453733985873459E+01, 0.2559023465659061E-05, 0.7597383986781573E-06, 0.4315933579167358E+00, 0.4417010014159849E+00, 0.1010840613748274E-01, 0.7995273950601426E-02, 0.3493647230378528E+00, 0.3535311090838850E+00, 0.1216166289646864E-01, 0.1097845108004235E-01, 0.3191359618656699E+00, 0.3118878408430891E+00, 0.3730332957296599E-02, 0.1111101051031713E-02, 0.9289758092154521E-01, 0.9178652239385691E-01, 0.4542317842367971E-07, 0.1435066789177947E-14, 0.2899836483324881E-08, 0.2245698748385924E-16, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.7318275341991307E+00}, + tauOut: 2.2456987483858885E-017, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1656837970404692E+01, 0.1656837970404692E+01, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.1208326918564908E+01, 0.1165390061113035E+01, 0.3659452888027460E-01, 0.4293685745187325E-01, 0.1005259802510638E+01, 0.1029841421622430E+01, 0.1337343958524596E-01, 0.1201290976848257E-01, 0.1301988750805104E+01, 0.1119111147544269E+01, 0.1244018658302015E+00, 0.1962510428460807E+00, 0.9239583804422884E+00, 0.8253195883250457E+00, 0.1631347930486186E+00, 0.2230406579474441E+00, 0.5868892951934211E+00, 0.6757949898735797E+00, 0.1838666404767374E+00, 0.7422909836846008E-01, 0.1269868105135121E+01, 0.1453733985873459E+01, 0.2642614694812039E-06, 0.7597383986781573E-06, 0.4496960111051168E+00, 0.4417010014159849E+00, 0.6285530663790794E-02, 0.7995273950601426E-02, 0.3582240295001366E+00, 0.3535311090838850E+00, 0.9558391177537082E-02, 0.1097845108004235E-01, 0.3034405507165837E+00, 0.3118878408430891E+00, 0.3360925270585024E-03, 0.1111101051031713E-02, 0.9145042986679984E-01, 0.9178652239385691E-01, 0.3524015903480299E-30, 0.1435066789177947E-14}, + i0: 1, + n0: 11, + pp: 0, + n0in: 12, + dmin: 2.2456987483858888E-017, + dmin1: 9.1450429866798411E-002, + dmin2: 0.30232944966555197, + dn: 2.2456987483858888E-017, + dn1: 9.1450429866798411E-002, + dn2: 0.30232944966555197, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1656837970404692E+01, 0.1656837970404692E+01, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.1208326918564908E+01, 0.1165390061113035E+01, 0.3659452888027460E-01, 0.4293685745187325E-01, 0.1005259802510638E+01, 0.1029841421622430E+01, 0.1337343958524596E-01, 0.1201290976848257E-01, 0.1301988750805104E+01, 0.1119111147544269E+01, 0.1244018658302015E+00, 0.1962510428460807E+00, 0.9239583804422884E+00, 0.8253195883250457E+00, 0.1631347930486186E+00, 0.2230406579474441E+00, 0.5868892951934211E+00, 0.6757949898735797E+00, 0.1838666404767374E+00, 0.7422909836846008E-01, 0.1269868105135121E+01, 0.1453733985873459E+01, 0.2642614694812039E-06, 0.7597383986781573E-06, 0.4496960111051168E+00, 0.4417010014159849E+00, 0.6285530663790794E-02, 0.7995273950601426E-02, 0.3582240295001366E+00, 0.3535311090838850E+00, 0.9558391177537082E-02, 0.1097845108004235E-01, 0.3034405507165837E+00, 0.3118878408430891E+00, 0.3360925270585024E-03, 0.1111101051031713E-02, 0.9145042986679984E-01, 0.9178652239385691E-01, 0.3524015903480299E-30, 0.1435066789177947E-14}, + tauOut: 9.1173077708044642E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1656837970404692E+01, 0.1565664892696647E+01, 0.1792267857826344E-16, 0.1383211380667930E-16, 0.1208326918564908E+01, 0.1153748369737138E+01, 0.3659452888027460E-01, 0.3188477647299814E-01, 0.1005259802510638E+01, 0.8955753879148407E+00, 0.1337343958524596E-01, 0.1944232516271161E-01, 0.1301988750805104E+01, 0.1315775213764550E+01, 0.1244018658302015E+00, 0.8735697805677015E-01, 0.9239583804422884E+00, 0.9085631177260922E+00, 0.1631347930486186E+00, 0.1053774491236745E+00, 0.5868892951934211E+00, 0.5742054088384394E+00, 0.1838666404767374E+00, 0.4066251880351924E+00, 0.1269868105135121E+01, 0.7720701036533529E+00, 0.2642614694812039E-06, 0.1539203864417861E-06, 0.4496960111051168E+00, 0.3648083101404764E+00, 0.6285530663790794E-02, 0.6172085611379779E-02, 0.3582240295001366E+00, 0.2704372573582493E+00, 0.9558391177537082E-02, 0.1072486650400470E-01, 0.3034405507165837E+00, 0.2018786990315928E+00, 0.3360925270585024E-03, 0.1522488812438262E-03, 0.9145042986679984E-01, 0.1251032775113764E-03, 0.3524015903480299E-30, 0.1383211380667930E-16, 0.8241395430971566E+00}, + i0: 1, + n0: 11, + pp: 1, + n0in: 11, + dmin: 1.2510327751137640E-004, + dmin1: 0.20154260650453434, + dmin2: 0.26087886618071221, + dn: 1.2510327751137640E-004, + dn1: 0.20154260650453434, + dn2: 0.26087886618071221, + tau: 9.1173077708044642E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.1656837970404692E+01, 0.1565664892696647E+01, 0.1792267857826344E-16, 0.1383211380667930E-16, 0.1208326918564908E+01, 0.1153748369737138E+01, 0.3659452888027460E-01, 0.3188477647299814E-01, 0.1005259802510638E+01, 0.8955753879148407E+00, 0.1337343958524596E-01, 0.1944232516271161E-01, 0.1301988750805104E+01, 0.1315775213764550E+01, 0.1244018658302015E+00, 0.8735697805677015E-01, 0.9239583804422884E+00, 0.9085631177260922E+00, 0.1631347930486186E+00, 0.1053774491236745E+00, 0.5868892951934211E+00, 0.5742054088384394E+00, 0.1838666404767374E+00, 0.4066251880351924E+00, 0.1269868105135121E+01, 0.7720701036533529E+00, 0.2642614694812039E-06, 0.1539203864417861E-06, 0.4496960111051168E+00, 0.3648083101404764E+00, 0.6285530663790794E-02, 0.6172085611379779E-02, 0.3582240295001366E+00, 0.2704372573582493E+00, 0.9558391177537082E-02, 0.1072486650400470E-01, 0.3034405507165837E+00, 0.2018786990315928E+00, 0.3360925270585024E-03, 0.1522488812438262E-03, 0.9145042986679984E-01, 0.1251032775113764E-03, 0.3524015903480299E-30, 0.1383211380667930E-16, 0.8241395430971566E+00}, + tauOut: 1.2498058228587147E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1565539912114361E+01, 0.1565664892696647E+01, 0.1019378594629470E-16, 0.1383211380667930E-16, 0.1185508165627851E+01, 0.1153748369737138E+01, 0.2408690373149840E-01, 0.3188477647299814E-01, 0.8908058287637680E+00, 0.8955753879148407E+00, 0.2871751477260568E-01, 0.1944232516271161E-01, 0.1374289696466428E+01, 0.1315775213764550E+01, 0.5775298217141787E-01, 0.8735697805677015E-01, 0.9560626040960629E+00, 0.9085631177260922E+00, 0.6328905763825028E-01, 0.1053774491236745E+00, 0.9174165586530958E+00, 0.5742054088384394E+00, 0.3422034931823232E+00, 0.4066251880351924E+00, 0.4297417838091302E+00, 0.7720701036533529E+00, 0.1306631986684747E-06, 0.1539203864417861E-06, 0.3708552845063717E+00, 0.3648083101404764E+00, 0.4500844331080801E-02, 0.6172085611379779E-02, 0.2765362989488873E+00, 0.2704372573582493E+00, 0.7829431815445537E-02, 0.1072486650400470E-01, 0.1940765355151052E+00, 0.2018786990315928E+00, 0.9814083907923291E-07, 0.1522488812438262E-03, 0.2455438642568072E-07, 0.1251032775113764E-03, 0.1019378594629470E-16, 0.1383211380667930E-16}, + i0: 1, + n0: 11, + pp: 0, + n0in: 11, + dmin: 2.4554386425680716E-008, + dmin1: 0.19392428663386141, + dmin2: 0.26581143244488259, + dn: 2.4554386425680716E-008, + dn1: 0.19392428663386141, + dn2: 0.26581143244488259, + tau: 1.2498058228587147E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1565539912114361E+01, 0.1565664892696647E+01, 0.1019378594629470E-16, 0.1383211380667930E-16, 0.1185508165627851E+01, 0.1153748369737138E+01, 0.2408690373149840E-01, 0.3188477647299814E-01, 0.8908058287637680E+00, 0.8955753879148407E+00, 0.2871751477260568E-01, 0.1944232516271161E-01, 0.1374289696466428E+01, 0.1315775213764550E+01, 0.5775298217141787E-01, 0.8735697805677015E-01, 0.9560626040960629E+00, 0.9085631177260922E+00, 0.6328905763825028E-01, 0.1053774491236745E+00, 0.9174165586530958E+00, 0.5742054088384394E+00, 0.3422034931823232E+00, 0.4066251880351924E+00, 0.4297417838091302E+00, 0.7720701036533529E+00, 0.1306631986684747E-06, 0.1539203864417861E-06, 0.3708552845063717E+00, 0.3648083101404764E+00, 0.4500844331080801E-02, 0.6172085611379779E-02, 0.2765362989488873E+00, 0.2704372573582493E+00, 0.7829431815445537E-02, 0.1072486650400470E-01, 0.1940765355151052E+00, 0.2018786990315928E+00, 0.9814083907923291E-07, 0.1522488812438262E-03, 0.2455438642568072E-07, 0.1251032775113764E-03, 0.1019378594629470E-16, 0.1383211380667930E-16}, + tauOut: 2.4554370888251911E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1565539912114361E+01, 0.1565539887559990E+01, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.1185508165627851E+01, 0.1209595044804978E+01, 0.2408690373149840E-01, 0.1773879145177052E-01, 0.8908058287637680E+00, 0.9017845275302323E+00, 0.2871751477260568E-01, 0.4376453959373496E-01, 0.1374289696466428E+01, 0.1388278114489740E+01, 0.5775298217141787E-01, 0.3977262621431848E-01, 0.9560626040960629E+00, 0.9795790109656241E+00, 0.6328905763825028E-01, 0.5927283946360358E-01, 0.9174165586530958E+00, 0.1200347187817445E+01, 0.3422034931823232E+00, 0.1225138368952072E+00, 0.4297417838091302E+00, 0.3072280530227507E+00, 0.1306631986684747E-06, 0.1577236754259593E-06, 0.3708552845063717E+00, 0.3753559465594062E+00, 0.4500844331080801E-02, 0.3315910790466669E-02, 0.2765362989488873E+00, 0.2810497954194954E+00, 0.7829431815445537E-02, 0.5406547261581845E-02, 0.1940765355151052E+00, 0.1886700618399915E+00, 0.9814083907923291E-07, 0.1277249852674422E-13, 0.2455438642568072E-07, 0.2764930279233778E-14, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.8241395430971566E+00}, + i0: 1, + n0: 11, + pp: 1, + n0in: 11, + dmin: 2.7649302792337775E-015, + dmin1: 0.18866996369915248, + dmin2: 0.27322036360404983, + dn: 2.7649302792337775E-015, + dn1: 0.18866996369915248, + dn2: 0.27322036360404983, + tau: 2.4554370888251911E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1565539912114361E+01, 0.1565539887559990E+01, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.1185508165627851E+01, 0.1209595044804978E+01, 0.2408690373149840E-01, 0.1773879145177052E-01, 0.8908058287637680E+00, 0.9017845275302323E+00, 0.2871751477260568E-01, 0.4376453959373496E-01, 0.1374289696466428E+01, 0.1388278114489740E+01, 0.5775298217141787E-01, 0.3977262621431848E-01, 0.9560626040960629E+00, 0.9795790109656241E+00, 0.6328905763825028E-01, 0.5927283946360358E-01, 0.9174165586530958E+00, 0.1200347187817445E+01, 0.3422034931823232E+00, 0.1225138368952072E+00, 0.4297417838091302E+00, 0.3072280530227507E+00, 0.1306631986684747E-06, 0.1577236754259593E-06, 0.3708552845063717E+00, 0.3753559465594062E+00, 0.4500844331080801E-02, 0.3315910790466669E-02, 0.2765362989488873E+00, 0.2810497954194954E+00, 0.7829431815445537E-02, 0.5406547261581845E-02, 0.1940765355151052E+00, 0.1886700618399915E+00, 0.9814083907923291E-07, 0.1277249852674422E-13, 0.2455438642568072E-07, 0.2764930279233778E-14, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.8241395430971566E+00}, + tauOut: 2.7649302792335523E-015, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13}, + i0: 1, + n0: 10, + pp: 0, + n0in: 11, + dmin: 3.4709879829724519E-029, + dmin1: 0.18507826404867261, + dmin2: 0.27717487004787600, + dn: 3.4709879829724519E-029, + dn1: 0.18507826404867261, + dn2: 0.27858872904535659, + tau: 2.7649302792335523E-015, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13}, + tauOut: 9.2539132024336307E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + n0in: 10, + dmin: 8.9088074504151571E-002, + dmin1: 0.17705256406949207, + dmin2: 0.17705256406949207, + dn: 8.9088074504151571E-002, + dn1: 0.18903428744201686, + dn2: 0.28613205491191551, + tau: 9.2539132024336307E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00}, + tauOut: 7.5387921832037685E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17}, + i0: 1, + n0: 10, + pp: 0, + n0in: 10, + dmin: 1.1106216559126303E-002, + dmin1: 0.10021441433509834, + dmin2: 0.10021441433509834, + dn: 1.1106216559126303E-002, + dn1: 0.11507463320059727, + dn2: 0.21320388392650824, + tau: 7.5387921832037685E-002, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17}, + tauOut: 9.2006637361187298E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + n0in: 10, + dmin: 1.6452860548183366E-003, + dmin1: 9.0837695870445614E-002, + dmin2: 9.0837695870445614E-002, + dn: 1.6452860548183366E-003, + dn1: 0.10809563217808144, + dn2: 0.20642195434625446, + tau: 9.2006637361187298E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00}, + tauOut: 1.5594219393746818E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17}, + i0: 1, + n0: 10, + pp: 0, + n0in: 10, + dmin: 8.1926049685687600E-005, + dmin1: 8.9258234858565516E-002, + dmin2: 8.9258234858565516E-002, + dn: 8.1926049685687600E-005, + dn1: 0.10847668953277810, + dn2: 0.20701876553386761, + tau: 1.5594219393746818E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17}, + tauOut: 8.1416944590412474E-005, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + n0in: 10, + dmin: 5.0612658152462498E-007, + dmin1: 8.9177229293753768E-002, + dmin2: 8.9177229293753768E-002, + dn: 5.0612658152462498E-007, + dn1: 0.10831524323681536, + dn2: 0.20814970454128662, + tau: 8.1416944590412474E-005, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00}, + tauOut: 5.0604049633765406E-007, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17}, + i0: 1, + n0: 10, + pp: 0, + n0in: 10, + dmin: 8.6071246971392626E-011, + dmin1: 8.9183660885577137E-002, + dmin2: 8.9183660885577137E-002, + dn: 8.6071246971392626E-011, + dn1: 0.10814239569959758, + dn2: 0.20876277035564564, + tau: 5.0604049633765406E-007, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17}, + tauOut: 8.6071215292546838E-011, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386770825043033E+01, 0.1386770824956962E+01, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.1102429917229558E+01, 0.1110569728432201E+01, 0.8139811288713328E-02, 0.9529690622753703E-02, 0.1300200404108803E+01, 0.1331504517453077E+01, 0.4083380405309871E-01, 0.2408506071837550E-01, 0.7853632031918177E+00, 0.8215785038267327E+00, 0.6030036143936175E-01, 0.8130667336500198E-01, 0.1107784654351057E+01, 0.1056786122273951E+01, 0.3030814137396716E-01, 0.1929354325655847E-01, 0.6727284432075471E+00, 0.6534352593063080E+00, 0.3594413905024206E-06, 0.4906748310831983E-07, 0.8920069974016231E-01, 0.8924053555066887E-01, 0.3988496406087022E-04, 0.9345605379795243E-04, 0.2091030664752072E+00, 0.2091858898978174E+00, 0.1762795624794033E-03, 0.9113088236382798E-04, 0.1081423986781113E+00, 0.1080512677096902E+00, 0.1393999949133917E-13, 0.1110429488179469E-22, 0.8607124697139263E-10, 0.3167883469916549E-16, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + n0in: 10, + dmin: 3.1678834699165494E-017, + dmin1: 8.9200650586607991E-002, + dmin2: 8.9200650586607991E-002, + dn: 3.1678834699165494E-017, + dn1: 0.10805126770967630, + dn2: 0.20900961033533805, + tau: 8.6071215292546838E-011, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386770825043033E+01, 0.1386770824956962E+01, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.1102429917229558E+01, 0.1110569728432201E+01, 0.8139811288713328E-02, 0.9529690622753703E-02, 0.1300200404108803E+01, 0.1331504517453077E+01, 0.4083380405309871E-01, 0.2408506071837550E-01, 0.7853632031918177E+00, 0.8215785038267327E+00, 0.6030036143936175E-01, 0.8130667336500198E-01, 0.1107784654351057E+01, 0.1056786122273951E+01, 0.3030814137396716E-01, 0.1929354325655847E-01, 0.6727284432075471E+00, 0.6534352593063080E+00, 0.3594413905024206E-06, 0.4906748310831983E-07, 0.8920069974016231E-01, 0.8924053555066887E-01, 0.3988496406087022E-04, 0.9345605379795243E-04, 0.2091030664752072E+00, 0.2091858898978174E+00, 0.1762795624794033E-03, 0.9113088236382798E-04, 0.1081423986781113E+00, 0.1080512677096902E+00, 0.1393999949133917E-13, 0.1110429488179469E-22, 0.8607124697139263E-10, 0.3167883469916549E-16, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.9154376259418607E+00}, + tauOut: 3.1678834698836348E-017, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386770824956962E+01, 0.1386770824956962E+01, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.1120099419054954E+01, 0.1110569728432201E+01, 0.1132830345080667E-01, 0.9529690622753703E-02, 0.1344261274720646E+01, 0.1331504517453077E+01, 0.1472018016266302E-01, 0.2408506071837550E-01, 0.8881649970290716E+00, 0.8215785038267327E+00, 0.9674301998819117E-01, 0.8130667336500198E-01, 0.9793366455423188E+00, 0.1056786122273951E+01, 0.1287308250760436E-01, 0.1929354325655847E-01, 0.6405622258661866E+00, 0.6534352593063080E+00, 0.6835883063177366E-08, 0.4906748310831983E-07, 0.8933398476858376E-01, 0.8924053555066887E-01, 0.2188381927740679E-03, 0.9345605379795243E-04, 0.2090581825874072E+00, 0.2091858898978174E+00, 0.4710079866305792E-04, 0.9113088236382798E-04, 0.1080041669110272E+00, 0.1080512677096902E+00, 0.3257014354834561E-38, 0.1110429488179469E-22}, + i0: 1, + n0: 9, + pp: 0, + n0in: 10, + dmin: 3.1678834699165494E-017, + dmin1: 8.9240528714785800E-002, + dmin2: 8.9240528714785800E-002, + dn: 3.1678834699165494E-017, + dn1: 0.10800416691102718, + dn2: 0.20896705170504334, + tau: 0.0000000000000000, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1386770824956962E+01, 0.1386770824956962E+01, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.1120099419054954E+01, 0.1110569728432201E+01, 0.1132830345080667E-01, 0.9529690622753703E-02, 0.1344261274720646E+01, 0.1331504517453077E+01, 0.1472018016266302E-01, 0.2408506071837550E-01, 0.8881649970290716E+00, 0.8215785038267327E+00, 0.9674301998819117E-01, 0.8130667336500198E-01, 0.9793366455423188E+00, 0.1056786122273951E+01, 0.1287308250760436E-01, 0.1929354325655847E-01, 0.6405622258661866E+00, 0.6534352593063080E+00, 0.6835883063177366E-08, 0.4906748310831983E-07, 0.8933398476858376E-01, 0.8924053555066887E-01, 0.2188381927740679E-03, 0.9345605379795243E-04, 0.2090581825874072E+00, 0.2091858898978174E+00, 0.4710079866305792E-04, 0.9113088236382798E-04, 0.1080041669110272E+00, 0.1080512677096902E+00, 0.3257014354834561E-38, 0.1110429488179469E-22}, + tauOut: 2.2310132178696450E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1386770824956962E+01, 0.1364460692778266E+01, 0.9806070694382835E-18, 0.8049901434408684E-18, 0.1120099419054954E+01, 0.1109117590327065E+01, 0.1132830345080667E-01, 0.1373001363427395E-01, 0.1344261274720646E+01, 0.1322941309070339E+01, 0.1472018016266302E-01, 0.9882485852396858E-02, 0.8881649970290716E+00, 0.9527153989861693E+00, 0.9674301998819117E-01, 0.9944626147083412E-01, 0.9793366455423188E+00, 0.8704533344003925E+00, 0.1287308250760436E-01, 0.9473236598617136E-02, 0.6405622258661866E+00, 0.6087788639247561E+00, 0.6835883063177366E-08, 0.1003117403762534E-08, 0.8933398476858376E-01, 0.6724268977954398E-01, 0.2188381927740679E-03, 0.6803700894781421E-03, 0.2090581825874072E+00, 0.1861147811178956E+00, 0.4710079866305792E-04, 0.2733303872960605E-04, 0.1080041669110272E+00, 0.8566670169360113E-01, 0.3257014354834561E-38, 0.8049901434408684E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 6.7023851586769906E-002, + dmin1: 6.7023851586769906E-002, + dmin2: 6.7023851586769906E-002, + dn: 8.5666701693601133E-002, + dn1: 0.18606768031923254, + dn2: 6.7023851586769906E-002, + tau: 2.2310132178696450E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.1386770824956962E+01, 0.1364460692778266E+01, 0.9806070694382835E-18, 0.8049901434408684E-18, 0.1120099419054954E+01, 0.1109117590327065E+01, 0.1132830345080667E-01, 0.1373001363427395E-01, 0.1344261274720646E+01, 0.1322941309070339E+01, 0.1472018016266302E-01, 0.9882485852396858E-02, 0.8881649970290716E+00, 0.9527153989861693E+00, 0.9674301998819117E-01, 0.9944626147083412E-01, 0.9793366455423188E+00, 0.8704533344003925E+00, 0.1287308250760436E-01, 0.9473236598617136E-02, 0.6405622258661866E+00, 0.6087788639247561E+00, 0.6835883063177366E-08, 0.1003117403762534E-08, 0.8933398476858376E-01, 0.6724268977954398E-01, 0.2188381927740679E-03, 0.6803700894781421E-03, 0.2090581825874072E+00, 0.1861147811178956E+00, 0.4710079866305792E-04, 0.2733303872960605E-04, 0.1080041669110272E+00, 0.8566670169360113E-01, 0.3257014354834561E-38, 0.8049901434408684E-18, 0.1094206688544886E+01}, + tauOut: 6.4730147312741043E-002, + ttypeOut: -5, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1299730545465525E+01, 0.1364460692778266E+01, 0.6869337119490330E-18, 0.8049901434408684E-18, 0.1058117456648598E+01, 0.1109117590327065E+01, 0.1716633828952343E-01, 0.1373001363427395E-01, 0.1250927309320471E+01, 0.1322941309070339E+01, 0.7526573591998700E-02, 0.9882485852396858E-02, 0.9799049395522637E+00, 0.9527153989861693E+00, 0.8833849733474472E-01, 0.9944626147083412E-01, 0.7268579263515238E+00, 0.8704533344003925E+00, 0.7934296380510910E-02, 0.9473236598617136E-02, 0.5361144212346215E+00, 0.6087788639247561E+00, 0.1258170079408221E-09, 0.1003117403762534E-08, 0.3192912430464083E-02, 0.6724268977954398E-01, 0.3965875451961033E-01, 0.6803700894781421E-03, 0.8175321232427381E-01, 0.1861147811178956E+00, 0.2864145895504550E-04, 0.2733303872960605E-04, 0.2090791292190505E-01, 0.8566670169360113E-01, 0.6869337119490330E-18, 0.8049901434408684E-18}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 2.5125423409859404E-003, + dmin1: 2.5125423409859404E-003, + dmin2: 2.5125423409859404E-003, + dn: 2.0907912921905053E-002, + dn1: 8.1725879285544201E-002, + dn2: 2.5125423409859404E-003, + tau: 6.4730147312741043E-002, + ttype: -5, + g: 0.0000000000000000, + zOut: []float64{0.1299730545465525E+01, 0.1364460692778266E+01, 0.6869337119490330E-18, 0.8049901434408684E-18, 0.1058117456648598E+01, 0.1109117590327065E+01, 0.1716633828952343E-01, 0.1373001363427395E-01, 0.1250927309320471E+01, 0.1322941309070339E+01, 0.7526573591998700E-02, 0.9882485852396858E-02, 0.9799049395522637E+00, 0.9527153989861693E+00, 0.8833849733474472E-01, 0.9944626147083412E-01, 0.7268579263515238E+00, 0.8704533344003925E+00, 0.7934296380510910E-02, 0.9473236598617136E-02, 0.5361144212346215E+00, 0.6087788639247561E+00, 0.1258170079408221E-09, 0.1003117403762534E-08, 0.3192912430464083E-02, 0.6724268977954398E-01, 0.3965875451961033E-01, 0.6803700894781421E-03, 0.8175321232427381E-01, 0.1861147811178956E+00, 0.2864145895504550E-04, 0.2733303872960605E-04, 0.2090791292190505E-01, 0.8566670169360113E-01, 0.6869337119490330E-18, 0.8049901434408684E-18}, + tauOut: 2.3478378904869292E-003, + ttypeOut: -5, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1299730545465525E+01, 0.1299143585992903E+01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1058117456648598E+01, 0.1074696835465499E+01, 0.1716633828952343E-01, 0.1998130138542489E-01, 0.1250927309320471E+01, 0.1237885622054423E+01, 0.7526573591998700E-02, 0.5958003315736791E-02, 0.9799049395522637E+00, 0.1061698474098650E+01, 0.8833849733474472E-01, 0.6047812873071532E-01, 0.7268579263515238E+00, 0.6737271345286977E+00, 0.7934296380510910E-02, 0.6313669873066943E-02, 0.5361144212346215E+00, 0.5292137920147498E+00, 0.1258170079408221E-09, 0.7590933847144573E-12, 0.3192912430464083E-02, 0.4226470747669359E-01, 0.3965875451961033E-01, 0.7671248122433710E-01, 0.8175321232427381E-01, 0.4482413086270017E-02, 0.2864145895504550E-04, 0.1335961497218277E-03, 0.2090791292190505E-01, 0.2018735729956149E-01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 2.6059529570832572E-003, + dmin1: 2.6059529570832572E-003, + dmin2: 2.6059529570832572E-003, + dn: 2.0187357299561493E-002, + dn1: 4.4537716273149721E-003, + dn2: 2.6059529570832572E-003, + tau: 5.8695947262173229E-004, + ttype: -17, + g: 0.0000000000000000, + zOut: []float64{0.1299730545465525E+01, 0.1299143585992903E+01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1058117456648598E+01, 0.1074696835465499E+01, 0.1716633828952343E-01, 0.1998130138542489E-01, 0.1250927309320471E+01, 0.1237885622054423E+01, 0.7526573591998700E-02, 0.5958003315736791E-02, 0.9799049395522637E+00, 0.1061698474098650E+01, 0.8833849733474472E-01, 0.6047812873071532E-01, 0.7268579263515238E+00, 0.6737271345286977E+00, 0.7934296380510910E-02, 0.6313669873066943E-02, 0.5361144212346215E+00, 0.5292137920147498E+00, 0.1258170079408221E-09, 0.7590933847144573E-12, 0.3192912430464083E-02, 0.4226470747669359E-01, 0.3965875451961033E-01, 0.7671248122433710E-01, 0.8175321232427381E-01, 0.4482413086270017E-02, 0.2864145895504550E-04, 0.1335961497218277E-03, 0.2090791292190505E-01, 0.2018735729956149E-01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1094206688544886E+01}, + tauOut: 4.9324499328963489E-004, + ttypeOut: -5, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1298650340999613E+01, 0.1299143585992903E+01, 0.4630045856693428E-18, 0.5594890049187079E-18, 0.1094184891857634E+01, 0.1074696835465499E+01, 0.2260547177996662E-01, 0.1998130138542489E-01, 0.1220744908596903E+01, 0.1237885622054423E+01, 0.5181756634367578E-02, 0.5958003315736791E-02, 0.1116501601201708E+01, 0.1061698474098650E+01, 0.3649413160495897E-01, 0.6047812873071532E-01, 0.6430534278035160E+00, 0.6737271345286977E+00, 0.5195962000339362E-02, 0.6313669873066943E-02, 0.5235245850218799E+00, 0.5292137920147498E+00, 0.6128243213469890E-13, 0.7590933847144573E-12, 0.1184839437076798E+00, 0.4226470747669359E-01, 0.2902140315050332E-02, 0.7671248122433710E-01, 0.1220623927651878E-02, 0.4482413086270017E-02, 0.2209487416380896E-02, 0.1335961497218277E-03, 0.1748462488989096E-01, 0.2018735729956149E-01, 0.4630045856693428E-18, 0.5594890049187079E-18}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 1.0870277779300500E-003, + dmin1: 1.0870277779300500E-003, + dmin2: 4.1771462483342674E-002, + dn: 1.7484624889890960E-002, + dn1: 1.0870277779300500E-003, + dn2: 4.1771462483342674E-002, + tau: 4.9324499328963489E-004, + ttype: -5, + g: 0.0000000000000000, + zOut: []float64{0.1298650340999613E+01, 0.1299143585992903E+01, 0.4630045856693428E-18, 0.5594890049187079E-18, 0.1094184891857634E+01, 0.1074696835465499E+01, 0.2260547177996662E-01, 0.1998130138542489E-01, 0.1220744908596903E+01, 0.1237885622054423E+01, 0.5181756634367578E-02, 0.5958003315736791E-02, 0.1116501601201708E+01, 0.1061698474098650E+01, 0.3649413160495897E-01, 0.6047812873071532E-01, 0.6430534278035160E+00, 0.6737271345286977E+00, 0.5195962000339362E-02, 0.6313669873066943E-02, 0.5235245850218799E+00, 0.5292137920147498E+00, 0.6128243213469890E-13, 0.7590933847144573E-12, 0.1184839437076798E+00, 0.4226470747669359E-01, 0.2902140315050332E-02, 0.7671248122433710E-01, 0.1220623927651878E-02, 0.4482413086270017E-02, 0.2209487416380896E-02, 0.1335961497218277E-03, 0.1748462488989096E-01, 0.2018735729956149E-01, 0.4630045856693428E-18, 0.5594890049187079E-18}, + tauOut: 8.6238530354903250E-004, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1298650340999613E+01, 0.1297787955696064E+01, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094184891857634E+01, 0.1115927978334052E+01, 0.2260547177996662E-01, 0.2472875948770642E-01, 0.1220744908596903E+01, 0.1200335520440015E+01, 0.5181756634367578E-02, 0.4819852017032840E-02, 0.1116501601201708E+01, 0.1147313495486085E+01, 0.3649413160495897E-01, 0.2045445862496274E-01, 0.6430534278035160E+00, 0.6269325458753436E+00, 0.5195962000339362E-02, 0.4338925882718484E-02, 0.5235245850218799E+00, 0.5183232738356738E+00, 0.6128243213469890E-13, 0.1400860159256393E-13, 0.1184839437076798E+00, 0.1205236987191671E+00, 0.2902140315050332E-02, 0.2939191169537379E-04, 0.1220623927651878E-02, 0.2538334128788367E-02, 0.2209487416380896E-02, 0.1521945367089819E-01, 0.1748462488989096E-01, 0.1402785915443734E-02, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 3.2884671240747138E-004, + dmin1: 3.2884671240747138E-004, + dmin2: 0.11762155840411674, + dn: 1.4027859154437344E-003, + dn1: 3.2884671240747138E-004, + dn2: 0.11762155840411674, + tau: 8.6238530354903250E-004, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1298650340999613E+01, 0.1297787955696064E+01, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094184891857634E+01, 0.1115927978334052E+01, 0.2260547177996662E-01, 0.2472875948770642E-01, 0.1220744908596903E+01, 0.1200335520440015E+01, 0.5181756634367578E-02, 0.4819852017032840E-02, 0.1116501601201708E+01, 0.1147313495486085E+01, 0.3649413160495897E-01, 0.2045445862496274E-01, 0.6430534278035160E+00, 0.6269325458753436E+00, 0.5195962000339362E-02, 0.4338925882718484E-02, 0.5235245850218799E+00, 0.5183232738356738E+00, 0.6128243213469890E-13, 0.1400860159256393E-13, 0.1184839437076798E+00, 0.1205236987191671E+00, 0.2902140315050332E-02, 0.2939191169537379E-04, 0.1220623927651878E-02, 0.2538334128788367E-02, 0.2209487416380896E-02, 0.1521945367089819E-01, 0.1748462488989096E-01, 0.1402785915443734E-02, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094206688544886E+01}, + tauOut: 1.8442717265434725E-004, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1297603528523410E+01, 0.1297787955696064E+01, 0.3357116521683426E-18, 0.3903662538064461E-18, 0.1140472310649104E+01, 0.1115927978334052E+01, 0.2602676813137004E-01, 0.2472875948770642E-01, 0.1178944177153024E+01, 0.1200335520440015E+01, 0.4690536984322235E-02, 0.4819852017032840E-02, 0.1162892989954071E+01, 0.1147313495486085E+01, 0.1102729651913737E-01, 0.2045445862496274E-01, 0.6200597480662705E+00, 0.6269325458753436E+00, 0.3627015421456806E-02, 0.4338925882718484E-02, 0.5145118312415766E+00, 0.5183232738356738E+00, 0.3281495925457712E-14, 0.1400860159256393E-13, 0.1203686634582048E+00, 0.1205236987191671E+00, 0.6198165737098726E-06, 0.2939191169537379E-04, 0.1757274081045850E-01, 0.2538334128788367E-02, 0.1214929161054836E-02, 0.1521945367089819E-01, 0.3429581734551261E-05, 0.1402785915443734E-02, 0.3357116521683426E-18, 0.3903662538064461E-18}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 3.4295817345512611E-006, + dmin1: 2.3532871395603098E-003, + dmin2: 0.12033927154650945, + dn: 3.4295817345512611E-006, + dn1: 2.3532871395603098E-003, + dn2: 0.12033927154650945, + tau: 1.8442717265434725E-004, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1297603528523410E+01, 0.1297787955696064E+01, 0.3357116521683426E-18, 0.3903662538064461E-18, 0.1140472310649104E+01, 0.1115927978334052E+01, 0.2602676813137004E-01, 0.2472875948770642E-01, 0.1178944177153024E+01, 0.1200335520440015E+01, 0.4690536984322235E-02, 0.4819852017032840E-02, 0.1162892989954071E+01, 0.1147313495486085E+01, 0.1102729651913737E-01, 0.2045445862496274E-01, 0.6200597480662705E+00, 0.6269325458753436E+00, 0.3627015421456806E-02, 0.4338925882718484E-02, 0.5145118312415766E+00, 0.5183232738356738E+00, 0.3281495925457712E-14, 0.1400860159256393E-13, 0.1203686634582048E+00, 0.1205236987191671E+00, 0.6198165737098726E-06, 0.2939191169537379E-04, 0.1757274081045850E-01, 0.2538334128788367E-02, 0.1214929161054836E-02, 0.1521945367089819E-01, 0.3429581734551261E-05, 0.1402785915443734E-02, 0.3357116521683426E-18, 0.3903662538064461E-18}, + tauOut: 3.2077610710809750E-006, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1297603528523410E+01, 0.1297600320762339E+01, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1140472310649104E+01, 0.1166495871019403E+01, 0.2602676813137004E-01, 0.2630451380147252E-01, 0.1178944177153024E+01, 0.1157326992574803E+01, 0.4690536984322235E-02, 0.4713095445958055E-02, 0.1162892989954071E+01, 0.1169203983266179E+01, 0.1102729651913737E-01, 0.5848066547299594E-02, 0.6200597480662705E+00, 0.6178354891793567E+00, 0.3627015421456806E-02, 0.3020451850239120E-02, 0.5145118312415766E+00, 0.5114881716302697E+00, 0.3281495925457712E-14, 0.7722354114894537E-15, 0.1203686634582048E+00, 0.1203660755137067E+00, 0.6198165737098726E-06, 0.9048958315991394E-07, 0.1757274081045850E-01, 0.1878437172085910E-01, 0.1214929161054836E-02, 0.2218173128942313E-06, 0.3429581734551261E-05, 0.3350576054907334E-11, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 3.3505760549073344E-012, + dmin1: 1.7569442559804263E-002, + dmin2: 0.12036545569713296, + dn: 3.3505760549073344E-012, + dn1: 1.7569442559804263E-002, + dn2: 0.12036545569713296, + tau: 3.2077610710809750E-006, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1297603528523410E+01, 0.1297600320762339E+01, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1140472310649104E+01, 0.1166495871019403E+01, 0.2602676813137004E-01, 0.2630451380147252E-01, 0.1178944177153024E+01, 0.1157326992574803E+01, 0.4690536984322235E-02, 0.4713095445958055E-02, 0.1162892989954071E+01, 0.1169203983266179E+01, 0.1102729651913737E-01, 0.5848066547299594E-02, 0.6200597480662705E+00, 0.6178354891793567E+00, 0.3627015421456806E-02, 0.3020451850239120E-02, 0.5145118312415766E+00, 0.5114881716302697E+00, 0.3281495925457712E-14, 0.7722354114894537E-15, 0.1203686634582048E+00, 0.1203660755137067E+00, 0.6198165737098726E-06, 0.9048958315991394E-07, 0.1757274081045850E-01, 0.1878437172085910E-01, 0.1214929161054836E-02, 0.2218173128942313E-06, 0.3429581734551261E-05, 0.3350576054907334E-11, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1094206688544886E+01}, + tauOut: 3.3505364896797715E-012, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1297600320758988E+01, 0.1297600320762339E+01, 0.2652482201353177E-18, 0.2950599175525191E-18, 0.1192800384817525E+01, 0.1166495871019403E+01, 0.2552222839336001E-01, 0.2630451380147252E-01, 0.1136517859624050E+01, 0.1157326992574803E+01, 0.4848643531876122E-02, 0.4713095445958055E-02, 0.1170203406278252E+01, 0.1169203983266179E+01, 0.3087619670750762E-02, 0.5848066547299594E-02, 0.6177683213554945E+00, 0.6178354891793567E+00, 0.2500816796475141E-02, 0.3020451850239120E-02, 0.5089873548304448E+00, 0.5114881716302697E+00, 0.1826193617023393E-15, 0.7722354114894537E-15, 0.1203661659999391E+00, 0.1203660755137067E+00, 0.1412182528886294E-07, 0.9048958315991394E-07, 0.1878457941299617E-01, 0.1878437172085910E-01, 0.3956520722700361E-16, 0.2218173128942313E-06, 0.2033579915109003E-22, 0.3350576054907334E-11, 0.2652482201353177E-18, 0.2950599175525191E-18}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 2.0335799151090034E-023, + dmin1: 1.8784357595683275E-002, + dmin2: 0.12036607551035594, + dn: 2.0335799151090034E-023, + dn1: 1.8784357595683275E-002, + dn2: 0.12036607551035594, + tau: 3.3505364896797715E-012, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1297600320758988E+01, 0.1297600320762339E+01, 0.2652482201353177E-18, 0.2950599175525191E-18, 0.1192800384817525E+01, 0.1166495871019403E+01, 0.2552222839336001E-01, 0.2630451380147252E-01, 0.1136517859624050E+01, 0.1157326992574803E+01, 0.4848643531876122E-02, 0.4713095445958055E-02, 0.1170203406278252E+01, 0.1169203983266179E+01, 0.3087619670750762E-02, 0.5848066547299594E-02, 0.6177683213554945E+00, 0.6178354891793567E+00, 0.2500816796475141E-02, 0.3020451850239120E-02, 0.5089873548304448E+00, 0.5114881716302697E+00, 0.1826193617023393E-15, 0.7722354114894537E-15, 0.1203661659999391E+00, 0.1203660755137067E+00, 0.1412182528886294E-07, 0.9048958315991394E-07, 0.1878457941299617E-01, 0.1878437172085910E-01, 0.3956520722700361E-16, 0.2218173128942313E-06, 0.2033579915109003E-22, 0.3350576054907334E-11, 0.2652482201353177E-18, 0.2950599175525191E-18}, + tauOut: 2.0335799151089990E-023, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1297600320758988E+01, 0.1297600320758988E+01, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1192800384817525E+01, 0.1218322613210885E+01, 0.2552222839336001E-01, 0.2380852827644004E-01, 0.1136517859624050E+01, 0.1117557974879486E+01, 0.4848643531876122E-02, 0.5077051306839188E-02, 0.1170203406278252E+01, 0.1168213974642164E+01, 0.3087619670750762E-02, 0.1632777609571200E-02, 0.6177683213554945E+00, 0.6186363605423986E+00, 0.2500816796475141E-02, 0.2057564358223963E-02, 0.5089873548304448E+00, 0.5069297904722210E+00, 0.1826193617023393E-15, 0.4336141378669131E-16, 0.1203661659999391E+00, 0.1203661801217644E+00, 0.1412182528886294E-07, 0.2203879431304952E-08, 0.1878457941299617E-01, 0.1878457720911678E-01, 0.3956520722700361E-16, 0.4283248425464200E-37, 0.1183377192742860E+01}, + i0: 1, + n0: 8, + pp: 1, + n0in: 9, + dmin: 2.0335799151089993E-023, + dmin1: 1.8784577209116738E-002, + dmin2: 0.12036616599993906, + dn: 2.0335799151089993E-023, + dn1: 1.8784577209116738E-002, + dn2: 0.12036616599993906, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1297600320758988E+01, 0.1297600320758988E+01, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1192800384817525E+01, 0.1218322613210885E+01, 0.2552222839336001E-01, 0.2380852827644004E-01, 0.1136517859624050E+01, 0.1117557974879486E+01, 0.4848643531876122E-02, 0.5077051306839188E-02, 0.1170203406278252E+01, 0.1168213974642164E+01, 0.3087619670750762E-02, 0.1632777609571200E-02, 0.6177683213554945E+00, 0.6186363605423986E+00, 0.2500816796475141E-02, 0.2057564358223963E-02, 0.5089873548304448E+00, 0.5069297904722210E+00, 0.1826193617023393E-15, 0.4336141378669131E-16, 0.1203661659999391E+00, 0.1203661801217644E+00, 0.1412182528886294E-07, 0.2203879431304952E-08, 0.1878457941299617E-01, 0.1878457720911678E-01, 0.3956520722700361E-16, 0.4283248425464200E-37, 0.1183377192742860E+01}, + tauOut: 1.8784576682472597E-002, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1278815744076516E+01, 0.1297600320758988E+01, 0.2322916695987584E-18, 0.2438256017573345E-18, 0.1223346564804853E+01, 0.1218322613210885E+01, 0.2174969171530204E-01, 0.2380852827644004E-01, 0.1082100757788551E+01, 0.1117557974879486E+01, 0.5481081353963683E-02, 0.5077051306839188E-02, 0.1145581094215299E+01, 0.1168213974642164E+01, 0.8817320773368219E-03, 0.1632777609571200E-02, 0.6010276161408131E+00, 0.6186363605423986E+00, 0.1735428857154564E-02, 0.2057564358223963E-02, 0.4864097849325938E+00, 0.5069297904722210E+00, 0.1073014545319338E-16, 0.4336141378669131E-16, 0.1015816056431712E+00, 0.1203661801217644E+00, 0.4075436992240071E-09, 0.2203879431304952E-08, 0.1191004794787176E-09, 0.1878457720911678E-01, 0.2322916695987584E-18, 0.2438256017573345E-18}, + i0: 1, + n0: 8, + pp: 0, + n0in: 8, + dmin: 1.1910047947871760E-010, + dmin1: 0.10158160343929173, + dmin2: 0.48640978493259379, + dn: 1.1910047947871760E-010, + dn1: 0.10158160343929173, + dn2: 0.48640978493259379, + tau: 1.8784576682472597E-002, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.1278815744076516E+01, 0.1297600320758988E+01, 0.2322916695987584E-18, 0.2438256017573345E-18, 0.1223346564804853E+01, 0.1218322613210885E+01, 0.2174969171530204E-01, 0.2380852827644004E-01, 0.1082100757788551E+01, 0.1117557974879486E+01, 0.5481081353963683E-02, 0.5077051306839188E-02, 0.1145581094215299E+01, 0.1168213974642164E+01, 0.8817320773368219E-03, 0.1632777609571200E-02, 0.6010276161408131E+00, 0.6186363605423986E+00, 0.1735428857154564E-02, 0.2057564358223963E-02, 0.4864097849325938E+00, 0.5069297904722210E+00, 0.1073014545319338E-16, 0.4336141378669131E-16, 0.1015816056431712E+00, 0.1203661801217644E+00, 0.4075436992240071E-09, 0.2203879431304952E-08, 0.1191004794787176E-09, 0.1878457720911678E-01, 0.2322916695987584E-18, 0.2438256017573345E-18}, + tauOut: 1.1910047900088848E-010, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1278815744076516E+01, 0.1278815743957415E+01, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1223346564804853E+01, 0.1245096256401054E+01, 0.2174969171530204E-01, 0.1890244048666934E-01, 0.1082100757788551E+01, 0.1068679398536745E+01, 0.5481081353963683E-02, 0.5875497537946494E-02, 0.1145581094215299E+01, 0.1140587328635589E+01, 0.8817320773368219E-03, 0.4646249482278370E-03, 0.6010276161408131E+00, 0.6022984199306394E+00, 0.1735428857154564E-02, 0.1401513849681988E-02, 0.4864097849325938E+00, 0.4850082709638114E+00, 0.1073014545319338E-16, 0.2247354260070927E-17, 0.1015816056431712E+00, 0.1015816059316144E+00, 0.4075436992240071E-09, 0.4778291260603437E-18, 0.1191004794787176E-09, 0.0000000000000000E+00, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1183377192742860E+01}, + i0: 1, + n0: 8, + pp: 1, + n0in: 8, + dmin: 0.0000000000000000, + dmin1: 0.10158160552407068, + dmin2: 0.48500827096381138, + dn: 0.0000000000000000, + dn1: 0.10158160552407068, + dn2: 0.48500827096381138, + tau: 1.1910047900088848E-010, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1278815744076516E+01, 0.1278815743957415E+01, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1223346564804853E+01, 0.1245096256401054E+01, 0.2174969171530204E-01, 0.1890244048666934E-01, 0.1082100757788551E+01, 0.1068679398536745E+01, 0.5481081353963683E-02, 0.5875497537946494E-02, 0.1145581094215299E+01, 0.1140587328635589E+01, 0.8817320773368219E-03, 0.4646249482278370E-03, 0.6010276161408131E+00, 0.6022984199306394E+00, 0.1735428857154564E-02, 0.1401513849681988E-02, 0.4864097849325938E+00, 0.4850082709638114E+00, 0.1073014545319338E-16, 0.2247354260070927E-17, 0.1015816056431712E+00, 0.1015816059316144E+00, 0.4075436992240071E-09, 0.4778291260603437E-18, 0.1191004794787176E-09, 0.0000000000000000E+00, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1183377192742860E+01}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1263998696887723E+01, 0.1245096256401054E+01, 0.1598154237018549E-01, 0.1890244048666934E-01, 0.1058573353704506E+01, 0.1068679398536745E+01, 0.6330707284251229E-02, 0.5875497537946494E-02, 0.1134721246299565E+01, 0.1140587328635589E+01, 0.2466181655543824E-03, 0.4646249482278370E-03, 0.6034533156147670E+00, 0.6022984199306394E+00, 0.1126426504548419E-02, 0.1401513849681988E-02, 0.4838818444592630E+00, 0.4850082709638114E+00, 0.4717884282068346E-18, 0.2247354260070927E-17, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.4778291260603437E-18}, + i0: 1, + n0: 7, + pp: 0, + n0in: 8, + dmin: 0.0000000000000000, + dmin1: 0.10158160593161437, + dmin2: 0.48388184445926297, + dn: 0.0000000000000000, + dn1: 0.10158160593161437, + dn2: 0.48388184445926297, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1263998696887723E+01, 0.1245096256401054E+01, 0.1598154237018549E-01, 0.1890244048666934E-01, 0.1058573353704506E+01, 0.1068679398536745E+01, 0.6330707284251229E-02, 0.5875497537946494E-02, 0.1134721246299565E+01, 0.1140587328635589E+01, 0.2466181655543824E-03, 0.4646249482278370E-03, 0.6034533156147670E+00, 0.6022984199306394E+00, 0.1126426504548419E-02, 0.1401513849681988E-02, 0.4838818444592630E+00, 0.4850082709638114E+00, 0.4717884282068346E-18, 0.2247354260070927E-17, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.4778291260603437E-18}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2138497627045302E-18, 0.1263998696887723E+01, 0.1279980239257909E+01, 0.1598154237018549E-01, 0.1321710631563048E-01, 0.1058573353704506E+01, 0.1051686954673127E+01, 0.6330707284251229E-02, 0.6830538334266978E-02, 0.1134721246299565E+01, 0.1128137326130852E+01, 0.2466181655543824E-03, 0.1319188242844840E-03, 0.6034533156147670E+00, 0.6044478232950309E+00, 0.1126426504548419E-02, 0.9017442261557238E-03, 0.4838818444592630E+00, 0.4829801002331072E+00, 0.4717884282068346E-18, 0.9922774494036444E-19, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.2138497627045302E-18, 0.1202161769544433E+01}, + i0: 1, + n0: 7, + pp: 1, + n0in: 7, + dmin: 0.10158160593161437, + dmin1: 0.48298010023310722, + dmin2: 0.60332139679048247, + dn: 0.10158160593161437, + dn1: 0.48298010023310722, + dn2: 0.60332139679048247, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2138497627045302E-18, 0.1263998696887723E+01, 0.1279980239257909E+01, 0.1598154237018549E-01, 0.1321710631563048E-01, 0.1058573353704506E+01, 0.1051686954673127E+01, 0.6330707284251229E-02, 0.6830538334266978E-02, 0.1134721246299565E+01, 0.1128137326130852E+01, 0.2466181655543824E-03, 0.1319188242844840E-03, 0.6034533156147670E+00, 0.6044478232950309E+00, 0.1126426504548419E-02, 0.9017442261557238E-03, 0.4838818444592630E+00, 0.4829801002331072E+00, 0.4717884282068346E-18, 0.9922774494036444E-19, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.2138497627045302E-18, 0.1202161769544433E+01}, + tauOut: 0.10158160593161437, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1177234138025801E+01, 0.1278815743957415E+01, 0.2325140442247288E-18, 0.2138497627045302E-18, 0.1191615739641925E+01, 0.1279980239257909E+01, 0.1166505092896250E-01, 0.1321710631563048E-01, 0.9452708361468171E+00, 0.1051686954673127E+01, 0.8151933771558135E-02, 0.6830538334266978E-02, 0.1018535705251965E+01, 0.1128137326130852E+01, 0.7828694249915420E-04, 0.1319188242844840E-03, 0.5036896746470730E+00, 0.6044478232950309E+00, 0.8646683437346259E-03, 0.9017442261557238E-03, 0.3805338259577582E+00, 0.4829801002331072E+00, 0.2648835135390502E-19, 0.9922774494036444E-19, 0.0000000000000000E+00, 0.1015816059316144E+00, 0.2325140442247288E-18, 0.2138497627045302E-18}, + i0: 1, + n0: 7, + pp: 0, + n0in: 7, + dmin: 0.0000000000000000, + dmin1: 0.38053382595775820, + dmin2: 0.50278793042091730, + dn: 0.0000000000000000, + dn1: 0.38053382595775820, + dn2: 0.50278793042091730, + tau: 0.10158160593161437, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1177234138025801E+01, 0.1278815743957415E+01, 0.2325140442247288E-18, 0.2138497627045302E-18, 0.1191615739641925E+01, 0.1279980239257909E+01, 0.1166505092896250E-01, 0.1321710631563048E-01, 0.9452708361468171E+00, 0.1051686954673127E+01, 0.8151933771558135E-02, 0.6830538334266978E-02, 0.1018535705251965E+01, 0.1128137326130852E+01, 0.7828694249915420E-04, 0.1319188242844840E-03, 0.5036896746470730E+00, 0.6044478232950309E+00, 0.8646683437346259E-03, 0.9017442261557238E-03, 0.3805338259577582E+00, 0.4829801002331072E+00, 0.2648835135390502E-19, 0.9922774494036444E-19, 0.0000000000000000E+00, 0.1015816059316144E+00, 0.2325140442247288E-18, 0.2138497627045302E-18}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1191615739641925E+01, 0.1203280790570888E+01, 0.1166505092896250E-01, 0.9163806595868684E-02, 0.9452708361468171E+00, 0.9442589633225065E+00, 0.8151933771558135E-02, 0.8793176380307672E-02, 0.1018535705251965E+01, 0.1009820815814156E+01, 0.7828694249915420E-04, 0.3904883319791864E-04, 0.5036896746470730E+00, 0.5045152941576099E+00, 0.8646683437346259E-03, 0.6521815232088979E-03, 0.3805338259577582E+00, 0.3798816444345493E+00, 0.2648835135390502E-19, 0.0000000000000000E+00, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + n0in: 7, + dmin: 0.0000000000000000, + dmin1: 0.37988164443454930, + dmin2: 0.50365062581387521, + dn: 0.0000000000000000, + dn1: 0.37988164443454930, + dn2: 0.50365062581387521, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1191615739641925E+01, 0.1203280790570888E+01, 0.1166505092896250E-01, 0.9163806595868684E-02, 0.9452708361468171E+00, 0.9442589633225065E+00, 0.8151933771558135E-02, 0.8793176380307672E-02, 0.1018535705251965E+01, 0.1009820815814156E+01, 0.7828694249915420E-04, 0.3904883319791864E-04, 0.5036896746470730E+00, 0.5045152941576099E+00, 0.8646683437346259E-03, 0.6521815232088979E-03, 0.3805338259577582E+00, 0.3798816444345493E+00, 0.2648835135390502E-19, 0.0000000000000000E+00, 0.1303743375476047E+01}, + tauOut: -0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2405618249359890E-18, 0.2353545363971710E-18, 0.1212444597166756E+01, 0.1203280790570888E+01, 0.7136826323052847E-02, 0.9163806595868684E-02, 0.9459153133797613E+00, 0.9442589633225065E+00, 0.9387238392656353E-02, 0.8793176380307672E-02, 0.1000472626254697E+01, 0.1009820815814156E+01, 0.1969142688202247E-04, 0.3904883319791864E-04, 0.5051477842539368E+00, 0.5045152941576099E+00, 0.4904540754787929E-03, 0.6521815232088979E-03, 0.3793911903590705E+00, 0.3798816444345493E+00, 0.2405618249359890E-18, 0.2353545363971710E-18}, + i0: 1, + n0: 6, + pp: 0, + n0in: 6, + dmin: 0.37939119035907048, + dmin1: 0.50449560273072791, + dmin2: 0.93712213699945368, + dn: 0.37939119035907048, + dn1: 0.50449560273072791, + dn2: 1.0004335774214996, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2405618249359890E-18, 0.2353545363971710E-18, 0.1212444597166756E+01, 0.1203280790570888E+01, 0.7136826323052847E-02, 0.9163806595868684E-02, 0.9459153133797613E+00, 0.9442589633225065E+00, 0.9387238392656353E-02, 0.8793176380307672E-02, 0.1000472626254697E+01, 0.1009820815814156E+01, 0.1969142688202247E-04, 0.3904883319791864E-04, 0.5051477842539368E+00, 0.5045152941576099E+00, 0.4904540754787929E-03, 0.6521815232088979E-03, 0.3793911903590705E+00, 0.3798816444345493E+00, 0.2405618249359890E-18, 0.2353545363971710E-18}, + tauOut: 0.37791671367087804, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1177234138025801E+01, 0.7993174243549228E+00, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1212444597166756E+01, 0.8416647098189309E+00, 0.7136826323052847E-02, 0.8020810697124018E-02, 0.9459153133797613E+00, 0.5693650274044155E+00, 0.9387238392656353E-02, 0.1649499810480807E-01, 0.1000472626254697E+01, 0.6060806059058935E+00, 0.1969142688202247E-04, 0.1641214148963635E-04, 0.5051477842539368E+00, 0.1277051125170478E+00, 0.4904540754787929E-03, 0.1457059563590431E-02, 0.3793911903590705E+00, 0.1741712460201494E-04, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + n0in: 6, + dmin: 1.7417124602014944E-005, + dmin1: 0.12721465844156904, + dmin2: 0.55997778901175921, + dn: 1.7417124602014944E-005, + dn1: 0.12721465844156904, + dn2: 0.60606091447901145, + tau: 0.37791671367087804, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1177234138025801E+01, 0.7993174243549228E+00, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1212444597166756E+01, 0.8416647098189309E+00, 0.7136826323052847E-02, 0.8020810697124018E-02, 0.9459153133797613E+00, 0.5693650274044155E+00, 0.9387238392656353E-02, 0.1649499810480807E-01, 0.1000472626254697E+01, 0.6060806059058935E+00, 0.1969142688202247E-04, 0.1641214148963635E-04, 0.5051477842539368E+00, 0.1277051125170478E+00, 0.4904540754787929E-03, 0.1457059563590431E-02, 0.3793911903590705E+00, 0.1741712460201494E-04, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1303743375476047E+01}, + tauOut: 1.7220607103034587E-005, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.7993002037478197E+00, 0.7993174243549228E+00, 0.3842364192156412E-18, 0.3648961927279404E-18, 0.8496682999089519E+00, 0.8416647098189309E+00, 0.5374766956544110E-02, 0.8020810697124018E-02, 0.5804680379455763E+00, 0.5693650274044155E+00, 0.1722282329473577E-01, 0.1649499810480807E-01, 0.5888569741455443E+00, 0.6060806059058935E+00, 0.3559292778388127E-05, 0.1641214148963635E-04, 0.1291413921807568E+00, 0.1277051125170478E+00, 0.1965116493098606E-06, 0.1457059563590431E-02, 0.5849670496393478E-11, 0.1741712460201494E-04, 0.3842364192156412E-18, 0.3648961927279404E-18}, + i0: 1, + n0: 6, + pp: 0, + n0in: 6, + dmin: 5.8496704963934779E-012, + dmin1: 0.12768433261716639, + dmin2: 0.56397303984076830, + dn: 5.8496704963934779E-012, + dn1: 0.12768433261716639, + dn2: 0.58884056200405466, + tau: 1.7220607103034587E-005, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.7993002037478197E+00, 0.7993174243549228E+00, 0.3842364192156412E-18, 0.3648961927279404E-18, 0.8496682999089519E+00, 0.8416647098189309E+00, 0.5374766956544110E-02, 0.8020810697124018E-02, 0.5804680379455763E+00, 0.5693650274044155E+00, 0.1722282329473577E-01, 0.1649499810480807E-01, 0.5888569741455443E+00, 0.6060806059058935E+00, 0.3559292778388127E-05, 0.1641214148963635E-04, 0.1291413921807568E+00, 0.1277051125170478E+00, 0.1965116493098606E-06, 0.1457059563590431E-02, 0.5849670496393478E-11, 0.1741712460201494E-04, 0.3842364192156412E-18, 0.3648961927279404E-18}, + tauOut: 5.8496615949827599E-012, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.7993002037478197E+00, 0.7993002037419701E+00, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.8496682999089519E+00, 0.8550430668596465E+00, 0.5374766956544110E-02, 0.3648799166500929E-02, 0.5804680379455763E+00, 0.5940420620679615E+00, 0.1722282329473577E-01, 0.1707249411982080E-01, 0.5888569741455443E+00, 0.5717880393126522E+00, 0.3559292778388127E-05, 0.8038853438286423E-06, 0.1291413921807568E+00, 0.1291407848012127E+00, 0.1965116493098606E-06, 0.8901358303923820E-17, 0.5849670496393478E-11, 0.5241368559131172E-22, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + n0in: 6, + dmin: 5.2413685591311719E-023, + dmin1: 0.12914058828956335, + dmin2: 0.57178448001987381, + dn: 5.2413685591311719E-023, + dn1: 0.12914058828956335, + dn2: 0.57178448001987381, + tau: 5.8496615949827599E-012, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.7993002037478197E+00, 0.7993002037419701E+00, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.8496682999089519E+00, 0.8550430668596465E+00, 0.5374766956544110E-02, 0.3648799166500929E-02, 0.5804680379455763E+00, 0.5940420620679615E+00, 0.1722282329473577E-01, 0.1707249411982080E-01, 0.5888569741455443E+00, 0.5717880393126522E+00, 0.3559292778388127E-05, 0.8038853438286423E-06, 0.1291413921807568E+00, 0.1291407848012127E+00, 0.1965116493098606E-06, 0.8901358303923820E-17, 0.5849670496393478E-11, 0.5241368559131172E-22, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.1303743375476047E+01}, + tauOut: 5.2413685591311714E-023, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.7993002037419701E+00, 0.7993002037419701E+00, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.8586918660261474E+00, 0.8550430668596465E+00, 0.2524235138002424E-02, 0.3648799166500929E-02, 0.6085903210497798E+00, 0.5940420620679615E+00, 0.1604009725641142E-01, 0.1707249411982080E-01, 0.5557487459415846E+00, 0.5717880393126522E+00, 0.1868009328861996E-06, 0.8038853438286423E-06, 0.1291405980002798E+00, 0.1291407848012127E+00, 0.3612752323451872E-38, 0.8901358303923820E-17}, + i0: 1, + n0: 5, + pp: 0, + n0in: 6, + dmin: 5.2413685591311719E-023, + dmin1: 0.12914059800027977, + dmin2: 0.55574794205624078, + dn: 5.2413685591311719E-023, + dn1: 0.12914059800027977, + dn2: 0.55574794205624078, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.7993002037419701E+00, 0.7993002037419701E+00, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.8586918660261474E+00, 0.8550430668596465E+00, 0.2524235138002424E-02, 0.3648799166500929E-02, 0.6085903210497798E+00, 0.5940420620679615E+00, 0.1604009725641142E-01, 0.1707249411982080E-01, 0.5557487459415846E+00, 0.5717880393126522E+00, 0.1868009328861996E-06, 0.8038853438286423E-06, 0.1291405980002798E+00, 0.1291407848012127E+00, 0.3612752323451872E-38, 0.8901358303923820E-17}, + tauOut: 0.12914051019182277, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.7993002037419701E+00, 0.6701596935501473E+00, 0.4369342452764876E-18, 0.5598544436768911E-18, 0.8586918660261474E+00, 0.7320755909723271E+00, 0.2524235138002424E-02, 0.2098451433139096E-02, 0.6085903210497798E+00, 0.4933914566812295E+00, 0.1604009725641142E-01, 0.1806732527351204E-01, 0.5557487459415846E+00, 0.4085410972771827E+00, 0.1868009328861996E-06, 0.5904812108429529E-07, 0.1291405980002798E+00, 0.2876033591836524E-07, 0.3612752323451872E-38, 0.5598544436768911E-18, 0.1681677309759878E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 2.8760335918365243E-008, + dmin1: 0.40854091047624980, + dmin2: 0.47735135942481804, + dn: 2.8760335918365243E-008, + dn1: 0.40854091047624980, + dn2: 0.47735135942481804, + tau: 0.12914051019182277, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.7993002037419701E+00, 0.6701596935501473E+00, 0.4369342452764876E-18, 0.5598544436768911E-18, 0.8586918660261474E+00, 0.7320755909723271E+00, 0.2524235138002424E-02, 0.2098451433139096E-02, 0.6085903210497798E+00, 0.4933914566812295E+00, 0.1604009725641142E-01, 0.1806732527351204E-01, 0.5557487459415846E+00, 0.4085410972771827E+00, 0.1868009328861996E-06, 0.5904812108429529E-07, 0.1291405980002798E+00, 0.2876033591836524E-07, 0.3612752323451872E-38, 0.5598544436768911E-18, 0.1681677309759878E+01}, + tauOut: 2.8760330654564486E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.6701596647898166E+00, 0.6701596935501473E+00, 0.6115792910959321E-18, 0.5598544436768911E-18, 0.7341740136451356E+00, 0.7320755909723271E+00, 0.1410235162411720E-02, 0.2098451433139096E-02, 0.5100485180319990E+00, 0.4933914566812295E+00, 0.1447165246275905E-01, 0.1806732527351204E-01, 0.3940694751022140E+00, 0.4085410972771827E+00, 0.4309503539425748E-14, 0.5904812108429529E-07, 0.9542972193014773E-15, 0.2876033591836524E-07, 0.6115792910959321E-18, 0.5598544436768911E-18}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: 9.5429721930147733E-016, + dmin1: 0.39406941605409296, + dmin2: 0.49198119275848701, + dn: 9.5429721930147733E-016, + dn1: 0.39406941605409296, + dn2: 0.49198119275848701, + tau: 2.8760330654564486E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.6701596647898166E+00, 0.6701596935501473E+00, 0.6115792910959321E-18, 0.5598544436768911E-18, 0.7341740136451356E+00, 0.7320755909723271E+00, 0.1410235162411720E-02, 0.2098451433139096E-02, 0.5100485180319990E+00, 0.4933914566812295E+00, 0.1447165246275905E-01, 0.1806732527351204E-01, 0.3940694751022140E+00, 0.4085410972771827E+00, 0.4309503539425748E-14, 0.5904812108429529E-07, 0.9542972193014773E-15, 0.2876033591836524E-07, 0.6115792910959321E-18, 0.5598544436768911E-18}, + tauOut: 9.5429721930146451E-016, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.6701596647898166E+00, 0.6701596647898156E+00, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.7341740136451356E+00, 0.7355842488075462E+00, 0.1410235162411720E-02, 0.9778463253267723E-03, 0.5100485180319990E+00, 0.5235423241694304E+00, 0.1447165246275905E-01, 0.1089278980244500E-01, 0.3940694751022140E+00, 0.3831766852997724E+00, 0.4309503539425748E-14, 0.1073277003016631E-28, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 5, + dmin: 1.9721522630525295E-030, + dmin1: 0.38317668529976806, + dmin2: 0.50907067170667131, + dn: 1.9721522630525295E-030, + dn1: 0.38317668529976806, + dn2: 0.50907067170667131, + tau: 9.5429721930146451E-016, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.6701596647898166E+00, 0.6701596647898156E+00, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.7341740136451356E+00, 0.7355842488075462E+00, 0.1410235162411720E-02, 0.9778463253267723E-03, 0.5100485180319990E+00, 0.5235423241694304E+00, 0.1447165246275905E-01, 0.1089278980244500E-01, 0.3940694751022140E+00, 0.3831766852997724E+00, 0.4309503539425748E-14, 0.1073277003016631E-28, 0.1810817848712033E+01}, + tauOut: 0.31895966905528556, + ttypeOut: -8, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3511999957345300E+00, 0.6701596647898156E+00, 0.1403302870260262E-17, 0.6699979816704878E-18, 0.4176024260775874E+00, 0.7355842488075462E+00, 0.1225912269357841E-02, 0.9778463253267723E-03, 0.2142495326472319E+00, 0.5235423241694304E+00, 0.1948131712866055E-01, 0.1089278980244500E-01, 0.4473569911582631E-01, 0.3831766852997724E+00, 0.1403302870260262E-17, 0.6699979816704878E-18}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 4.4735699115826311E-002, + dmin1: 0.20335674284478694, + dmin2: 0.35119999573453003, + dn: 4.4735699115826311E-002, + dn1: 0.20335674284478694, + dn2: 0.41662457975226058, + tau: 0.31895966905528556, + ttype: -8, + g: 0.0000000000000000, + zOut: []float64{0.3511999957345300E+00, 0.6701596647898156E+00, 0.1403302870260262E-17, 0.6699979816704878E-18, 0.4176024260775874E+00, 0.7355842488075462E+00, 0.1225912269357841E-02, 0.9778463253267723E-03, 0.2142495326472319E+00, 0.5235423241694304E+00, 0.1948131712866055E-01, 0.1089278980244500E-01, 0.4473569911582631E-01, 0.3831766852997724E+00, 0.1403302870260262E-17, 0.6699979816704878E-18}, + tauOut: 3.9897804510299034E-002, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3511999957345300E+00, 0.3113021912242310E+00, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.4176024260775874E+00, 0.3789305338366462E+00, 0.1225912269357841E-02, 0.6931379430343076E-03, 0.2142495326472319E+00, 0.1931399073225591E+00, 0.1948131712866055E-01, 0.4512326600593524E-02, 0.4473569911582631E-01, 0.3255680049337531E-03, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 3.2556800493375310E-004, + dmin1: 0.17365859019389857, + dmin2: 0.31130219122423097, + dn: 3.2556800493375310E-004, + dn1: 0.17365859019389857, + dn2: 0.37770462156728835, + tau: 3.9897804510299034E-002, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3511999957345300E+00, 0.3113021912242310E+00, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.4176024260775874E+00, 0.3789305338366462E+00, 0.1225912269357841E-02, 0.6931379430343076E-03, 0.2142495326472319E+00, 0.1931399073225591E+00, 0.1948131712866055E-01, 0.4512326600593524E-02, 0.4473569911582631E-01, 0.3255680049337531E-03, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.1810817848712033E+01}, + tauOut: 3.1797943619548145E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3109842117880355E+00, 0.3113021912242310E+00, 0.2293789231233262E-17, 0.1882488140663987E-17, 0.3793056923434850E+00, 0.3789305338366462E+00, 0.3529411785314453E-03, 0.6931379430343076E-03, 0.1969813133084257E+00, 0.1931399073225591E+00, 0.7457911333267062E-05, 0.4512326600593524E-02, 0.1306574050045526E-06, 0.3255680049337531E-03, 0.2293789231233262E-17, 0.1882488140663987E-17}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 1.3065740500455263E-007, + dmin1: 0.19246898670783216, + dmin2: 0.31098421178803548, + dn: 1.3065740500455263E-007, + dn1: 0.19246898670783216, + dn2: 0.37861255440045072, + tau: 3.1797943619548145E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3109842117880355E+00, 0.3113021912242310E+00, 0.2293789231233262E-17, 0.1882488140663987E-17, 0.3793056923434850E+00, 0.3789305338366462E+00, 0.3529411785314453E-03, 0.6931379430343076E-03, 0.1969813133084257E+00, 0.1931399073225591E+00, 0.7457911333267062E-05, 0.4512326600593524E-02, 0.1306574050045526E-06, 0.3255680049337531E-03, 0.2293789231233262E-17, 0.1882488140663987E-17}, + tauOut: 1.3065240973281283E-007, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3109842117880355E+00, 0.3109840811356258E+00, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.3793056923434850E+00, 0.3796585028696068E+00, 0.3529411785314453E-03, 0.1831193463132450E-03, 0.1969813133084257E+00, 0.1968055212210360E+00, 0.7457911333267062E-05, 0.4951239861123181E-11, 0.1306574050045526E-06, 0.4403187866809611E-13, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 4.4031878668096113E-014, + dmin1: 0.19679806330970273, + dmin2: 0.31098408113562576, + dn: 4.4031878668096113E-014, + dn1: 0.19679806330970273, + dn2: 0.37930556169107532, + tau: 1.3065240973281283E-007, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3109842117880355E+00, 0.3109840811356258E+00, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.3793056923434850E+00, 0.3796585028696068E+00, 0.3529411785314453E-03, 0.1831193463132450E-03, 0.1969813133084257E+00, 0.1968055212210360E+00, 0.7457911333267062E-05, 0.4951239861123181E-11, 0.1306574050045526E-06, 0.4403187866809611E-13, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.1810817848712033E+01}, + tauOut: 4.4031878666982759E-014, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3109840811355817E+00, 0.3109840811356258E+00, 0.3415542419024794E-17, 0.2797722987188916E-17, 0.3798416222158761E+00, 0.3796585028696068E+00, 0.9487875021856221E-04, 0.1831193463132450E-03, 0.1967106424757246E+00, 0.1968055212210360E+00, 0.1108289770587888E-23, 0.4951239861123181E-11, 0.5067642455139780E-26, 0.4403187866809611E-13, 0.3415542419024794E-17, 0.2797722987188916E-17}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 5.0676424551397798E-027, + dmin1: 0.19671064247077341, + dmin2: 0.31098408113558174, + dn: 5.0676424551397798E-027, + dn1: 0.19671064247077341, + dn2: 0.37965850286956282, + tau: 4.4031878666982759E-014, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3109840811355817E+00, 0.3109840811356258E+00, 0.3415542419024794E-17, 0.2797722987188916E-17, 0.3798416222158761E+00, 0.3796585028696068E+00, 0.9487875021856221E-04, 0.1831193463132450E-03, 0.1967106424757246E+00, 0.1968055212210360E+00, 0.1108289770587888E-23, 0.4951239861123181E-11, 0.5067642455139780E-26, 0.4403187866809611E-13, 0.3415542419024794E-17, 0.2797722987188916E-17}, + tauOut: 5.0676424551397798E-027, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.3109840811355817E+00, 0.3109840811355817E+00, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.3798416222158761E+00, 0.3799365009660947E+00, 0.9487875021856221E-04, 0.4912310311151891E-04, 0.1967106424757246E+00, 0.1966615193726131E+00, 0.1108289770587888E-23, 0.2855879641297252E-49, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 4, + dmin: 5.0676424551397798E-027, + dmin1: 0.19666151937261311, + dmin2: 0.31098408113558174, + dn: 5.0676424551397798E-027, + dn1: 0.19666151937261311, + dn2: 0.37984162221587608, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.3109840811355817E+00, 0.3109840811355817E+00, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.3798416222158761E+00, 0.3799365009660947E+00, 0.9487875021856221E-04, 0.4912310311151891E-04, 0.1967106424757246E+00, 0.1966615193726131E+00, 0.1108289770587888E-23, 0.2855879641297252E-49, 0.2169993432366266E+01}, + tauOut: 9.8330759686306557E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2126533214492752E+00, 0.3109840811355817E+00, 0.7453545812882342E-17, 0.4171805735046273E-17, 0.2816548643828996E+00, 0.3799365009660947E+00, 0.3429951091160839E-04, 0.4912310311151891E-04, 0.9829646017539498E-01, 0.1966615193726131E+00, 0.3799365009660947E+00, 0.2855879641297252E-49}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 9.8296460175394978E-002, + dmin1: 0.21265332144927518, + dmin2: 0.21265332144927518, + dn: 9.8296460175394978E-002, + dn1: 0.28160574127978810, + dn2: 0.21265332144927518, + tau: 9.8330759686306557E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.2126533214492752E+00, 0.3109840811355817E+00, 0.7453545812882342E-17, 0.4171805735046273E-17, 0.2816548643828996E+00, 0.3799365009660947E+00, 0.3429951091160839E-04, 0.4912310311151891E-04, 0.9829646017539498E-01, 0.1966615193726131E+00, 0.3799365009660947E+00, 0.2855879641297252E-49}, + tauOut: 9.7172513485343004E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2126533214492752E+00, 0.1154808079639322E+00, 0.7453545812882342E-17, 0.1817901582187390E-16, 0.2816548643828996E+00, 0.1845166504084682E+00, 0.3429951091160839E-04, 0.1827217490071947E-04, 0.9829646017539498E-01, 0.1105674515151256E-02, 0.3799365009660947E+00, 0.2816548643828996E+00, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 3, + dmin: 1.1056745151512559E-003, + dmin1: 0.11548080796393217, + dmin2: 0.11548080796393217, + dn: 1.1056745151512559E-003, + dn1: 0.18448235089755655, + dn2: 0.11548080796393217, + tau: 9.7172513485343004E-002, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2126533214492752E+00, 0.1154808079639322E+00, 0.7453545812882342E-17, 0.1817901582187390E-16, 0.2816548643828996E+00, 0.1845166504084682E+00, 0.3429951091160839E-04, 0.1827217490071947E-04, 0.9829646017539498E-01, 0.1105674515151256E-02, 0.3799365009660947E+00, 0.2816548643828996E+00, 0.2169993432366266E+01}, + tauOut: 1.0942861809085330E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1143865217830237E+00, 0.1154808079639322E+00, 0.2932453102768040E-16, 0.1817901582187390E-16, 0.1834406364024603E+00, 0.1845166504084682E+00, 0.1101341475930520E-06, 0.1827217490071947E-04, 0.1127820009512990E-04, 0.1105674515151256E-02, 0.1845166504084682E+00, 0.2816548643828996E+00}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 1.1278200095129901E-005, + dmin1: 0.11438652178302365, + dmin2: 0.11438652178302365, + dn: 1.1278200095129901E-005, + dn1: 0.18342236422755959, + dn2: 0.11438652178302365, + tau: 1.0942861809085330E-003, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1143865217830237E+00, 0.1154808079639322E+00, 0.2932453102768040E-16, 0.1817901582187390E-16, 0.1834406364024603E+00, 0.1845166504084682E+00, 0.1101341475930520E-06, 0.1827217490071947E-04, 0.1127820009512990E-04, 0.1105674515151256E-02, 0.1845166504084682E+00, 0.2816548643828996E+00}, + tauOut: 1.1269238360546607E-005, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 3, + dmin: 8.9549629620034135E-009, + dmin1: 0.11437525254466312, + dmin2: 0.11437525254466312, + dn: 8.9549629620034135E-009, + dn1: 0.18342936716409974, + dn2: 0.11437525254466312, + tau: 1.1269238360546607E-005, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01}, + tauOut: 8.9549072084035346E-009, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 5.5753269291151117E-014, + dmin1: 0.11437524358975594, + dmin2: 0.11437524358975594, + dn: 5.5753269291151117E-014, + dn1: 0.18342946834334006, + dn2: 0.11437524358975594, + tau: 8.9549072084035346E-009, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00}, + tauOut: 5.5753269214454873E-014, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1648283185136998E+01, 0.1396221235720571E+01, 0.1712714336271993E+00, 0.2520619494164272E+00, 0.1510753432847732E+01, 0.1119977945086946E+01, 0.3792800633372563E+00, 0.5620469213879850E+00, 0.1328441621586708E+01, 0.1019485448443405E+01, 0.1388998759717073E+00, 0.6882362364805590E+00, 0.4466938077796418E+00, 0.2681061628164644E+00, 0.7093206047768255E+00, 0.3174875209348847E+00, 0.6843112870203156E+00, 0.9979892152967577E+00, 0.6490582981441884E+00, 0.3956426765003833E+00, 0.5085572738629487E+00, 0.1122623886995757E+01, 0.9750235054014829E-02, 0.3499168501137979E-01, 0.1364886053450573E+00, 0.1417066070690837E+00, 0.2301225778544498E-01, 0.4532233329988395E-02, 0.1646009972289452E+01, 0.6930161671496210E+00, 0.2362515608142310E+00, 0.9760060629252760E+00, 0.5818602562677768E+00, 0.3984323866837953E+00, 0.1797665269485310E-01, 0.4196794303982125E+00, 0.5600419521166516E+00, 0.2492354636952108E-01, 0.2195137569256029E+00, 0.5530950584419837E+00, 0.4184071984843414E+00, 0.2222708575473020E+00, 0.2727864547293006E+00, 0.4156500978626423E+00, 0.6774373914466536E-01, 0.2745959086613283E+00, 0.1050967099374242E+00, 0.6593428521263771E-01, 0.2040338718098096E+00, 0.1079809097801335E+00, 0.1271971985482246E+00, 0.2011496719671002E+00, 0.4444741998443960E-01, 0.1290210252363728E+00, 0.5776327498150620E+00, 0.4262359329629137E-01, 0.3402556968467140E+00, 0.6023491555328507E+00, 0.1086565805630269E+00, 0.3155392911289253E+00, 0.9382999256694983E+00, 0.1171677238805356E+00, 0.7901625299559836E+00, 0.9297887823519896E+00, 0.6095853796269167E+00, 0.7973955560628040E+00, 0.8018125008387630E+00, 0.6023523535200964E+00, 0.2443177602187348E-01, 0.8114406374558937E+00, 0.2277830378453201E+00, 0.1480363940474286E-01, 0.6969081780841352E+00, 0.3759308106650992E+00, 0.8012406122589412E-01, 0.5487604052643561E+00, 0.9781022865072954E-01, 0.1017549972519246E+00, 0.2961248981181939E-03, 0.7617929262469909E-01, 0.8408398800007548E-04, 0.3802088861182694E-03, 0.0000000000000000E+00, 0.0000000000000000E+00}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: -0.0000000000000000, + dmin1: 0.0000000000000000, + dmin2: 0.0000000000000000, + dn: 0.0000000000000000, + dn1: 0.0000000000000000, + dn2: 0.0000000000000000, + tau: 0.0000000000000000, + ttype: 0, + g: 0.0000000000000000, + zOut: []float64{0.1648283185136998E+01, 0.1396221235720571E+01, 0.1712714336271993E+00, 0.2520619494164272E+00, 0.1510753432847732E+01, 0.1119977945086946E+01, 0.3792800633372563E+00, 0.5620469213879850E+00, 0.1328441621586708E+01, 0.1019485448443405E+01, 0.1388998759717073E+00, 0.6882362364805590E+00, 0.4466938077796418E+00, 0.2681061628164644E+00, 0.7093206047768255E+00, 0.3174875209348847E+00, 0.6843112870203156E+00, 0.9979892152967577E+00, 0.6490582981441884E+00, 0.3956426765003833E+00, 0.5085572738629487E+00, 0.1122623886995757E+01, 0.9750235054014829E-02, 0.3499168501137979E-01, 0.1364886053450573E+00, 0.1417066070690837E+00, 0.2301225778544498E-01, 0.4532233329988395E-02, 0.1646009972289452E+01, 0.6930161671496210E+00, 0.2362515608142310E+00, 0.9760060629252760E+00, 0.5818602562677768E+00, 0.3984323866837953E+00, 0.1797665269485310E-01, 0.4196794303982125E+00, 0.5600419521166516E+00, 0.2492354636952108E-01, 0.2195137569256029E+00, 0.5530950584419837E+00, 0.4184071984843414E+00, 0.2222708575473020E+00, 0.2727864547293006E+00, 0.4156500978626423E+00, 0.6774373914466536E-01, 0.2745959086613283E+00, 0.1050967099374242E+00, 0.6593428521263771E-01, 0.2040338718098096E+00, 0.1079809097801335E+00, 0.1271971985482246E+00, 0.2011496719671002E+00, 0.4444741998443960E-01, 0.1290210252363728E+00, 0.5776327498150620E+00, 0.4262359329629137E-01, 0.3402556968467140E+00, 0.6023491555328507E+00, 0.1086565805630269E+00, 0.3155392911289253E+00, 0.9382999256694983E+00, 0.1171677238805356E+00, 0.7901625299559836E+00, 0.9297887823519896E+00, 0.6095853796269167E+00, 0.7973955560628040E+00, 0.8018125008387630E+00, 0.6023523535200964E+00, 0.2443177602187348E-01, 0.8114406374558937E+00, 0.2277830378453201E+00, 0.1480363940474286E-01, 0.6969081780841352E+00, 0.3759308106650992E+00, 0.8012406122589412E-01, 0.5487604052643561E+00, 0.9781022865072954E-01, 0.1017549972519246E+00, 0.2961248981181939E-03, 0.7617929262469909E-01, 0.8408398800007548E-04, 0.3802088861182694E-03, 0.0000000000000000E+00, 0.0000000000000000E+00}, + tauOut: 0.0000000000000000, + ttypeOut: -1, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1648283185136998E+01, 0.1819554618764197E+01, 0.1712714336271993E+00, 0.1422045283129674E+00, 0.1510753432847732E+01, 0.1747828967872021E+01, 0.3792800633372563E+00, 0.2882727267008810E+00, 0.1328441621586708E+01, 0.1179068770857534E+01, 0.1388998759717073E+00, 0.5262264257308433E-01, 0.4466938077796418E+00, 0.1103391769983383E+01, 0.7093206047768255E+00, 0.4399127392187891E+00, 0.6843112870203156E+00, 0.8934568459457148E+00, 0.6490582981441884E+00, 0.3694451726238032E+00, 0.5085572738629487E+00, 0.1488623362931603E+00, 0.9750235054014829E-02, 0.8939776288934402E-02, 0.1364886053450573E+00, 0.1505610868415679E+00, 0.2301225778544498E-01, 0.2515816443301624E+00, 0.1646009972289452E+01, 0.1630679888773521E+01, 0.2362515608142310E+00, 0.8429943526342391E-01, 0.5818602562677768E+00, 0.5155374736992060E+00, 0.1797665269485310E-01, 0.1952851185677853E-01, 0.5600419521166516E+00, 0.7600271971854760E+00, 0.2195137569256029E+00, 0.1208458544696003E+00, 0.4184071984843414E+00, 0.5703477987440417E+00, 0.2727864547293006E+00, 0.3240053608004366E-01, 0.6774373914466536E-01, 0.1404399130020459E+00, 0.1050967099374242E+00, 0.1526865702536626E+00, 0.2040338718098096E+00, 0.1785445001043715E+00, 0.1271971985482246E+00, 0.3166486394939177E-01, 0.4444741998443960E-01, 0.5904153058501098E+00, 0.5776327498150620E+00, 0.3328891237445398E+00, 0.3402556968467140E+00, 0.1160231536652011E+00, 0.1086565805630269E+00, 0.8787251358464724E+00, 0.9382999256694983E+00, 0.8497373197790092E+00, 0.7901625299559836E+00, 0.5668475593321608E+00, 0.6095853796269167E+00, 0.8445503211335190E+00, 0.8018125008387630E+00, 0.2319542476253924E-01, 0.2443177602187348E-01, 0.2290193891046544E+00, 0.2277830378453201E+00, 0.6931459494493321E+00, 0.6969081780841352E+00, 0.8388628986069724E-01, 0.8012406122589412E-01, 0.9342352322344821E-01, 0.9781022865072954E-01, 0.4682830325399513E-02, 0.2961248981181939E-03, 0.5317160915449039E-05, 0.8408398800007548E-04, 0.7876682708462645E-04, 0.0000000000000000E+00, 0.8939776288934402E-02, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 7.8766827084626452E-005, + dmin1: 1.2363512593342330E-003, + dmin2: 1.2363512593342330E-003, + dn: 7.8766827084626452E-005, + dn1: 4.3867054272813191E-003, + dn2: 3.7622286348031123E-003, + tau: 0.0000000000000000, + ttype: -1, + g: 0.0000000000000000, + zOut: []float64{0.1648283185136998E+01, 0.1819554618764197E+01, 0.1712714336271993E+00, 0.1422045283129674E+00, 0.1510753432847732E+01, 0.1747828967872021E+01, 0.3792800633372563E+00, 0.2882727267008810E+00, 0.1328441621586708E+01, 0.1179068770857534E+01, 0.1388998759717073E+00, 0.5262264257308433E-01, 0.4466938077796418E+00, 0.1103391769983383E+01, 0.7093206047768255E+00, 0.4399127392187891E+00, 0.6843112870203156E+00, 0.8934568459457148E+00, 0.6490582981441884E+00, 0.3694451726238032E+00, 0.5085572738629487E+00, 0.1488623362931603E+00, 0.9750235054014829E-02, 0.8939776288934402E-02, 0.1364886053450573E+00, 0.1505610868415679E+00, 0.2301225778544498E-01, 0.2515816443301624E+00, 0.1646009972289452E+01, 0.1630679888773521E+01, 0.2362515608142310E+00, 0.8429943526342391E-01, 0.5818602562677768E+00, 0.5155374736992060E+00, 0.1797665269485310E-01, 0.1952851185677853E-01, 0.5600419521166516E+00, 0.7600271971854760E+00, 0.2195137569256029E+00, 0.1208458544696003E+00, 0.4184071984843414E+00, 0.5703477987440417E+00, 0.2727864547293006E+00, 0.3240053608004366E-01, 0.6774373914466536E-01, 0.1404399130020459E+00, 0.1050967099374242E+00, 0.1526865702536626E+00, 0.2040338718098096E+00, 0.1785445001043715E+00, 0.1271971985482246E+00, 0.3166486394939177E-01, 0.4444741998443960E-01, 0.5904153058501098E+00, 0.5776327498150620E+00, 0.3328891237445398E+00, 0.3402556968467140E+00, 0.1160231536652011E+00, 0.1086565805630269E+00, 0.8787251358464724E+00, 0.9382999256694983E+00, 0.8497373197790092E+00, 0.7901625299559836E+00, 0.5668475593321608E+00, 0.6095853796269167E+00, 0.8445503211335190E+00, 0.8018125008387630E+00, 0.2319542476253924E-01, 0.2443177602187348E-01, 0.2290193891046544E+00, 0.2277830378453201E+00, 0.6931459494493321E+00, 0.6969081780841352E+00, 0.8388628986069724E-01, 0.8012406122589412E-01, 0.9342352322344821E-01, 0.9781022865072954E-01, 0.4682830325399513E-02, 0.2961248981181939E-03, 0.5317160915449039E-05, 0.8408398800007548E-04, 0.7876682708462645E-04, 0.0000000000000000E+00, 0.8939776288934402E-02, 0.1037537856266618 - 321}, + tauOut: 0.0000000000000000, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1961759147077164E+01, 0.1819554618764197E+01, 0.1266970995487882E+00, 0.1422045283129674E+00, 0.1909404595024114E+01, 0.1747828967872021E+01, 0.1780101349021133E+00, 0.2882727267008810E+00, 0.1053681278528505E+01, 0.1179068770857534E+01, 0.5510526941411123E-01, 0.5262264257308433E-01, 0.1488199239788061E+01, 0.1103391769983383E+01, 0.2641064704009213E+00, 0.4399127392187891E+00, 0.9987955481685968E+00, 0.8934568459457148E+00, 0.5506279200968747E-01, 0.3694451726238032E+00, 0.1027393205724072E+00, 0.1488623362931603E+00, 0.1310094739466220E-01, 0.8939776288934402E-02, 0.3890417837770681E+00, 0.1505610868415679E+00, 0.1054511738587064E+01, 0.2515816443301624E+00, 0.6604675854498806E+00, 0.1630679888773521E+01, 0.6580113672099847E-01, 0.8429943526342391E-01, 0.4692648488349861E+00, 0.5155374736992060E+00, 0.3162862116895929E-01, 0.1952851185677853E-01, 0.8492444304861170E+00, 0.7600271971854760E+00, 0.8115939841327705E-01, 0.1208458544696003E+00, 0.5215889364108083E+00, 0.5703477987440417E+00, 0.8723974284448969E-02, 0.3240053608004366E-01, 0.2844025089712595E+00, 0.1404399130020459E+00, 0.9585480612390133E-01, 0.1526865702536626E+00, 0.1143545579298620E+00, 0.1785445001043715E+00, 0.1634864466429828E+00, 0.3166486394939177E-01, 0.7598179829516669E+00, 0.5904153058501098E+00, 0.5083170815153470E-01, 0.3328891237445398E+00, 0.9439165813601388E+00, 0.1160231536652011E+00, 0.7910503496831139E+00, 0.8787251358464724E+00, 0.6255345294280562E+00, 0.8497373197790092E+00, 0.7653155273545736E+00, 0.5668475593321608E+00, 0.1024302185414846E+00, 0.8445503211335190E+00, 0.5186166821452450E-01, 0.2319542476253924E-01, 0.8703036703394620E+00, 0.2290193891046544E+00, 0.6681052144545734E-01, 0.6931459494493321E+00, 0.1104992916386881E+00, 0.8388628986069724E-01, 0.3959179295799719E-02, 0.9342352322344821E-01, 0.7289681905152429E-03, 0.4682830325399513E-02, 0.5745324691222600E-06, 0.5317160915449039E-05, 0.7819229461550419E-04, 0.7876682708462645E-04, 0.8723974284448969E-02, 0.8939776288934402E-02}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: 7.8192294615504193E-005, + dmin1: 7.2365102959979382E-004, + dmin2: 1.7075768415239889E-002, + dn: 7.8192294615504193E-005, + dn1: 7.2365102959979382E-004, + dn2: 1.7075768415239889E-002, + tau: 0.0000000000000000, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1961759147077164E+01, 0.1819554618764197E+01, 0.1266970995487882E+00, 0.1422045283129674E+00, 0.1909404595024114E+01, 0.1747828967872021E+01, 0.1780101349021133E+00, 0.2882727267008810E+00, 0.1053681278528505E+01, 0.1179068770857534E+01, 0.5510526941411123E-01, 0.5262264257308433E-01, 0.1488199239788061E+01, 0.1103391769983383E+01, 0.2641064704009213E+00, 0.4399127392187891E+00, 0.9987955481685968E+00, 0.8934568459457148E+00, 0.5506279200968747E-01, 0.3694451726238032E+00, 0.1027393205724072E+00, 0.1488623362931603E+00, 0.1310094739466220E-01, 0.8939776288934402E-02, 0.3890417837770681E+00, 0.1505610868415679E+00, 0.1054511738587064E+01, 0.2515816443301624E+00, 0.6604675854498806E+00, 0.1630679888773521E+01, 0.6580113672099847E-01, 0.8429943526342391E-01, 0.4692648488349861E+00, 0.5155374736992060E+00, 0.3162862116895929E-01, 0.1952851185677853E-01, 0.8492444304861170E+00, 0.7600271971854760E+00, 0.8115939841327705E-01, 0.1208458544696003E+00, 0.5215889364108083E+00, 0.5703477987440417E+00, 0.8723974284448969E-02, 0.3240053608004366E-01, 0.2844025089712595E+00, 0.1404399130020459E+00, 0.9585480612390133E-01, 0.1526865702536626E+00, 0.1143545579298620E+00, 0.1785445001043715E+00, 0.1634864466429828E+00, 0.3166486394939177E-01, 0.7598179829516669E+00, 0.5904153058501098E+00, 0.5083170815153470E-01, 0.3328891237445398E+00, 0.9439165813601388E+00, 0.1160231536652011E+00, 0.7910503496831139E+00, 0.8787251358464724E+00, 0.6255345294280562E+00, 0.8497373197790092E+00, 0.7653155273545736E+00, 0.5668475593321608E+00, 0.1024302185414846E+00, 0.8445503211335190E+00, 0.5186166821452450E-01, 0.2319542476253924E-01, 0.8703036703394620E+00, 0.2290193891046544E+00, 0.6681052144545734E-01, 0.6931459494493321E+00, 0.1104992916386881E+00, 0.8388628986069724E-01, 0.3959179295799719E-02, 0.9342352322344821E-01, 0.7289681905152429E-03, 0.4682830325399513E-02, 0.5745324691222600E-06, 0.5317160915449039E-05, 0.7819229461550419E-04, 0.7876682708462645E-04, 0.8723974284448969E-02, 0.8939776288934402E-02}, + tauOut: 7.8083356181667918E-005, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1961759147077164E+01, 0.2088378163269771E+01, 0.1266970995487882E+00, 0.1158391848322702E+00, 0.1909404595024114E+01, 0.1971497461737776E+01, 0.1780101349021133E+00, 0.9513882222772962E-01, 0.1053681278528505E+01, 0.1013569642358705E+01, 0.5510526941411123E-01, 0.8090970429970110E-01, 0.1488199239788061E+01, 0.1671317922533099E+01, 0.2641064704009213E+00, 0.1578325483874163E+00, 0.9987955481685968E+00, 0.8959477084346864E+00, 0.5506279200968747E-01, 0.6314111623521673E-02, 0.1027393205724072E+00, 0.1094480729873660E+00, 0.1310094739466220E-01, 0.4656834793406785E-01, 0.3890417837770681E+00, 0.1396907091073883E+01, 0.1054511738587064E+01, 0.4985806330739840E+00, 0.6604675854498806E+00, 0.2276100057407134E+00, 0.6580113672099847E-01, 0.1356625794022653E+00, 0.4692648488349861E+00, 0.3651528072454984E+00, 0.3162862116895929E-01, 0.7355942454424362E-01, 0.8492444304861170E+00, 0.8567663209989688E+00, 0.8115939841327705E-01, 0.4940885660487250E-01, 0.5215889364108083E+00, 0.4808259707342031E+00, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.2844025089712595E+00, 0.3750191107685802E+00, 0.9585480612390133E-01, 0.2922900104287094E-01, 0.1143545579298620E+00, 0.2485339201737921E+00, 0.1634864466429828E+00, 0.4998108187459615E+00, 0.7598179829516669E+00, 0.3107607890010585E+00, 0.5083170815153470E-01, 0.1543981540828483E+00, 0.9439165813601388E+00, 0.1580490693604223E+01, 0.7910503496831139E+00, 0.3130858727896049E+00, 0.6255345294280562E+00, 0.1077686100636843E+01, 0.7653155273545736E+00, 0.7274051012980143E-01, 0.1024302185414846E+00, 0.8147329327002600E-01, 0.5186166821452450E-01, 0.5539901283655780E+00, 0.8703036703394620E+00, 0.3830459800631597E+00, 0.6681052144545734E-01, 0.1927318305890360E-01, 0.1104992916386881E+00, 0.9510720451940254E-01, 0.3959179295799719E-02, 0.3034592154998885E-04, 0.7289681905152429E-03, 0.6211134452527084E-03, 0.5745324691222600E-06, 0.7232819130731082E-07, 0.7819229461550419E-04, 0.3661024252896476E-07, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 3.6610242528964756E-008, + dmin1: 6.2053891278358614E-004, + dmin2: 2.9611625055501498E-002, + dn: 3.6610242528964756E-008, + dn1: 6.2053891278358614E-004, + dn2: 9.1148025223602810E-002, + tau: 7.8083356181667918E-005, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.1961759147077164E+01, 0.2088378163269771E+01, 0.1266970995487882E+00, 0.1158391848322702E+00, 0.1909404595024114E+01, 0.1971497461737776E+01, 0.1780101349021133E+00, 0.9513882222772962E-01, 0.1053681278528505E+01, 0.1013569642358705E+01, 0.5510526941411123E-01, 0.8090970429970110E-01, 0.1488199239788061E+01, 0.1671317922533099E+01, 0.2641064704009213E+00, 0.1578325483874163E+00, 0.9987955481685968E+00, 0.8959477084346864E+00, 0.5506279200968747E-01, 0.6314111623521673E-02, 0.1027393205724072E+00, 0.1094480729873660E+00, 0.1310094739466220E-01, 0.4656834793406785E-01, 0.3890417837770681E+00, 0.1396907091073883E+01, 0.1054511738587064E+01, 0.4985806330739840E+00, 0.6604675854498806E+00, 0.2276100057407134E+00, 0.6580113672099847E-01, 0.1356625794022653E+00, 0.4692648488349861E+00, 0.3651528072454984E+00, 0.3162862116895929E-01, 0.7355942454424362E-01, 0.8492444304861170E+00, 0.8567663209989688E+00, 0.8115939841327705E-01, 0.4940885660487250E-01, 0.5215889364108083E+00, 0.4808259707342031E+00, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.2844025089712595E+00, 0.3750191107685802E+00, 0.9585480612390133E-01, 0.2922900104287094E-01, 0.1143545579298620E+00, 0.2485339201737921E+00, 0.1634864466429828E+00, 0.4998108187459615E+00, 0.7598179829516669E+00, 0.3107607890010585E+00, 0.5083170815153470E-01, 0.1543981540828483E+00, 0.9439165813601388E+00, 0.1580490693604223E+01, 0.7910503496831139E+00, 0.3130858727896049E+00, 0.6255345294280562E+00, 0.1077686100636843E+01, 0.7653155273545736E+00, 0.7274051012980143E-01, 0.1024302185414846E+00, 0.8147329327002600E-01, 0.5186166821452450E-01, 0.5539901283655780E+00, 0.8703036703394620E+00, 0.3830459800631597E+00, 0.6681052144545734E-01, 0.1927318305890360E-01, 0.1104992916386881E+00, 0.9510720451940254E-01, 0.3959179295799719E-02, 0.3034592154998885E-04, 0.7289681905152429E-03, 0.6211134452527084E-03, 0.5745324691222600E-06, 0.7232819130731082E-07, 0.7819229461550419E-04, 0.3661024252896476E-07, 0.8723974284448969E-02, 0.5160120970399038E-02, 0.1037537856266618 - 321}, + tauOut: 3.6605973538398975E-008, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2204217311496068E+01, 0.2088378163269771E+01, 0.1036089580076783E+00, 0.1158391848322702E+00, 0.1963027289351853E+01, 0.1971497461737776E+01, 0.4912301654839819E-01, 0.9513882222772962E-01, 0.1045356293504034E+01, 0.1013569642358705E+01, 0.1293586117415210E+00, 0.8090970429970110E-01, 0.1699791822573021E+01, 0.1671317922533099E+01, 0.8319236989271818E-01, 0.1578325483874163E+00, 0.8190694135595162E+00, 0.8959477084346864E+00, 0.8437225690290790E-03, 0.6314111623521673E-02, 0.1551726617464312E+00, 0.1094480729873660E+00, 0.4192211096758560E+00, 0.4656834793406785E-01, 0.1476266577866037E+01, 0.1396907091073883E+01, 0.7687090018675194E-01, 0.4985806330739840E+00, 0.2864016483502532E+00, 0.2276100057407134E+00, 0.1729653861709652E+00, 0.1356625794022653E+00, 0.2657468090128033E+00, 0.3651528072454984E+00, 0.2371551996266359E+00, 0.7355942454424362E-01, 0.6690199413712319E+00, 0.8567663209989688E+00, 0.3551024412099299E-01, 0.4940885660487250E-01, 0.4504758109776356E+00, 0.4808259707342031E+00, 0.4295777776785939E-02, 0.5160120970399038E-02, 0.3999522974286917E+00, 0.3750191107685802E+00, 0.1816316160365039E-01, 0.2922900104287094E-01, 0.7301815407101296E+00, 0.2485339201737921E+00, 0.2127164214993764E+00, 0.4998108187459615E+00, 0.2524424849785568E+00, 0.3107607890010585E+00, 0.9666552191416621E+00, 0.1543981540828483E+00, 0.9269213106461920E+00, 0.1580490693604223E+01, 0.3640096408786760E+00, 0.3130858727896049E+00, 0.7864169332819952E+00, 0.1077686100636843E+01, 0.7535963003344312E-02, 0.7274051012980143E-01, 0.6279274220262862E+00, 0.8147329327002600E-01, 0.3379430237022286E+00, 0.5539901283655780E+00, 0.6437610281386123E-01, 0.3830459800631597E+00, 0.2847358698029713E-01, 0.1927318305890360E-01, 0.6666392685468185E-01, 0.9510720451940254E-01, 0.2827355178816361E-06, 0.3034592154998885E-04, 0.6208664319525956E-03, 0.6211134452527084E-03, 0.4264931214133004E-11, 0.7232819130731082E-07, 0.4059351646211308E-14, 0.3661024252896476E-07, 0.8437225690290790E-03, 0.5160120970399038E-02}, + i0: 1, + n0: 21, + pp: 0, + n0in: 21, + dmin: 4.0593516462113082E-015, + dmin1: 6.2079410376128833E-004, + dmin2: 4.5102919754957636E-002, + dn: 4.0593516462113082E-015, + dn1: 6.2079410376128833E-004, + dn2: 6.6633580933131861E-002, + tau: 3.6605973538398975E-008, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2204217311496068E+01, 0.2088378163269771E+01, 0.1036089580076783E+00, 0.1158391848322702E+00, 0.1963027289351853E+01, 0.1971497461737776E+01, 0.4912301654839819E-01, 0.9513882222772962E-01, 0.1045356293504034E+01, 0.1013569642358705E+01, 0.1293586117415210E+00, 0.8090970429970110E-01, 0.1699791822573021E+01, 0.1671317922533099E+01, 0.8319236989271818E-01, 0.1578325483874163E+00, 0.8190694135595162E+00, 0.8959477084346864E+00, 0.8437225690290790E-03, 0.6314111623521673E-02, 0.1551726617464312E+00, 0.1094480729873660E+00, 0.4192211096758560E+00, 0.4656834793406785E-01, 0.1476266577866037E+01, 0.1396907091073883E+01, 0.7687090018675194E-01, 0.4985806330739840E+00, 0.2864016483502532E+00, 0.2276100057407134E+00, 0.1729653861709652E+00, 0.1356625794022653E+00, 0.2657468090128033E+00, 0.3651528072454984E+00, 0.2371551996266359E+00, 0.7355942454424362E-01, 0.6690199413712319E+00, 0.8567663209989688E+00, 0.3551024412099299E-01, 0.4940885660487250E-01, 0.4504758109776356E+00, 0.4808259707342031E+00, 0.4295777776785939E-02, 0.5160120970399038E-02, 0.3999522974286917E+00, 0.3750191107685802E+00, 0.1816316160365039E-01, 0.2922900104287094E-01, 0.7301815407101296E+00, 0.2485339201737921E+00, 0.2127164214993764E+00, 0.4998108187459615E+00, 0.2524424849785568E+00, 0.3107607890010585E+00, 0.9666552191416621E+00, 0.1543981540828483E+00, 0.9269213106461920E+00, 0.1580490693604223E+01, 0.3640096408786760E+00, 0.3130858727896049E+00, 0.7864169332819952E+00, 0.1077686100636843E+01, 0.7535963003344312E-02, 0.7274051012980143E-01, 0.6279274220262862E+00, 0.8147329327002600E-01, 0.3379430237022286E+00, 0.5539901283655780E+00, 0.6437610281386123E-01, 0.3830459800631597E+00, 0.2847358698029713E-01, 0.1927318305890360E-01, 0.6666392685468185E-01, 0.9510720451940254E-01, 0.2827355178816361E-06, 0.3034592154998885E-04, 0.6208664319525956E-03, 0.6211134452527084E-03, 0.4264931214133004E-11, 0.7232819130731082E-07, 0.4059351646211308E-14, 0.3661024252896476E-07, 0.8437225690290790E-03, 0.5160120970399038E-02}, + tauOut: 4.0593516183260787E-015, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2204217311496068E+01, 0.2307826269503742E+01, 0.1036089580076783E+00, 0.8812934261040264E-01, 0.1963027289351853E+01, 0.1924020963289845E+01, 0.4912301654839819E-01, 0.2668944646890268E-01, 0.1045356293504034E+01, 0.1148025458776649E+01, 0.1293586117415210E+00, 0.1915312145184878E+00, 0.1699791822573021E+01, 0.1591452977947247E+01, 0.8319236989271818E-01, 0.4281642408847453E-01, 0.8190694135595162E+00, 0.7770967120400667E+00, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1551726617464312E+00, 0.5742252947387723E+00, 0.4192211096758560E+00, 0.1077768810640642E+01, 0.1476266577866037E+01, 0.4753686674121431E+00, 0.7687090018675194E-01, 0.4631342794110950E-01, 0.2864016483502532E+00, 0.4130536065801048E+00, 0.1729653861709652E+00, 0.1112809541240190E+00, 0.2657468090128033E+00, 0.3916210545154161E+00, 0.2371551996266359E+00, 0.4051405202062471E+00, 0.6690199413712319E+00, 0.2993896652859737E+00, 0.3551024412099299E-01, 0.5343038813025977E-01, 0.4504758109776356E+00, 0.4013412006241577E+00, 0.4295777776785939E-02, 0.4280911574482486E-02, 0.3999522974286917E+00, 0.4138345474578556E+00, 0.1816316160365039E-01, 0.3204760309498118E-01, 0.7301815407101296E+00, 0.9108503591145208E+00, 0.2127164214993764E+00, 0.5895442813598011E-01, 0.2524424849785568E+00, 0.1160143275984235E+01, 0.9666552191416621E+00, 0.7723298847804961E+00, 0.9269213106461920E+00, 0.5186010667443678E+00, 0.3640096408786760E+00, 0.5519914319921668E+00, 0.7864169332819952E+00, 0.2419614642931688E+00, 0.7535963003344312E-02, 0.1955698951896722E-01, 0.6279274220262862E+00, 0.9463134562095434E+00, 0.3379430237022286E+00, 0.2298969194226957E-01, 0.6437610281386123E-01, 0.6985999785188474E-01, 0.2847358698029713E-01, 0.2717093011896993E-01, 0.6666392685468185E-01, 0.3949327947122574E-01, 0.2827355178816361E-06, 0.4444831994804014E-08, 0.6208664319525956E-03, 0.6208619913814727E-03, 0.4264931214133004E-11, 0.2788519153273688E-22, 0.4059351646211308E-14, 0.3786532345060857E-28, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + n0in: 21, + dmin: 3.7865323450608567E-029, + dmin1: 6.2086198711654151E-004, + dmin2: 3.9492996735707858E-002, + dn: 3.7865323450608567E-029, + dn1: 6.2086198711654151E-004, + dn2: 3.9492996735707858E-002, + tau: 4.0593516183260787E-015, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2204217311496068E+01, 0.2307826269503742E+01, 0.1036089580076783E+00, 0.8812934261040264E-01, 0.1963027289351853E+01, 0.1924020963289845E+01, 0.4912301654839819E-01, 0.2668944646890268E-01, 0.1045356293504034E+01, 0.1148025458776649E+01, 0.1293586117415210E+00, 0.1915312145184878E+00, 0.1699791822573021E+01, 0.1591452977947247E+01, 0.8319236989271818E-01, 0.4281642408847453E-01, 0.8190694135595162E+00, 0.7770967120400667E+00, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1551726617464312E+00, 0.5742252947387723E+00, 0.4192211096758560E+00, 0.1077768810640642E+01, 0.1476266577866037E+01, 0.4753686674121431E+00, 0.7687090018675194E-01, 0.4631342794110950E-01, 0.2864016483502532E+00, 0.4130536065801048E+00, 0.1729653861709652E+00, 0.1112809541240190E+00, 0.2657468090128033E+00, 0.3916210545154161E+00, 0.2371551996266359E+00, 0.4051405202062471E+00, 0.6690199413712319E+00, 0.2993896652859737E+00, 0.3551024412099299E-01, 0.5343038813025977E-01, 0.4504758109776356E+00, 0.4013412006241577E+00, 0.4295777776785939E-02, 0.4280911574482486E-02, 0.3999522974286917E+00, 0.4138345474578556E+00, 0.1816316160365039E-01, 0.3204760309498118E-01, 0.7301815407101296E+00, 0.9108503591145208E+00, 0.2127164214993764E+00, 0.5895442813598011E-01, 0.2524424849785568E+00, 0.1160143275984235E+01, 0.9666552191416621E+00, 0.7723298847804961E+00, 0.9269213106461920E+00, 0.5186010667443678E+00, 0.3640096408786760E+00, 0.5519914319921668E+00, 0.7864169332819952E+00, 0.2419614642931688E+00, 0.7535963003344312E-02, 0.1955698951896722E-01, 0.6279274220262862E+00, 0.9463134562095434E+00, 0.3379430237022286E+00, 0.2298969194226957E-01, 0.6437610281386123E-01, 0.6985999785188474E-01, 0.2847358698029713E-01, 0.2717093011896993E-01, 0.6666392685468185E-01, 0.3949327947122574E-01, 0.2827355178816361E-06, 0.4444831994804014E-08, 0.6208664319525956E-03, 0.6208619913814727E-03, 0.4264931214133004E-11, 0.2788519153273688E-22, 0.4059351646211308E-14, 0.3786532345060857E-28, 0.8437225690290790E-03, 0.1684766835109566E-03, 0.1037537856266618 - 321}, + tauOut: 3.7865323450608567E-029, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2395955612114145E+01, 0.2307826269503742E+01, 0.7077038564739886E-01, 0.8812934261040264E-01, 0.1879940024111348E+01, 0.1924020963289845E+01, 0.1629847954401656E-01, 0.2668944646890268E-01, 0.1323258193751120E+01, 0.1148025458776649E+01, 0.2303502998543534E+00, 0.1915312145184878E+00, 0.1403919102181368E+01, 0.1591452977947247E+01, 0.2369972908607684E-01, 0.4281642408847453E-01, 0.7535654596375009E+00, 0.7770967120400667E+00, 0.1283811140869274E-03, 0.1684766835109566E-03, 0.1651865724265327E+01, 0.5742252947387723E+00, 0.3101568824672333E+00, 0.1077768810640642E+01, 0.2115252128860193E+00, 0.4753686674121431E+00, 0.9043805314343908E-01, 0.4631342794110950E-01, 0.4338965075606848E+00, 0.4130536065801048E+00, 0.1004386157577793E+00, 0.1112809541240190E+00, 0.6963229589638840E+00, 0.3916210545154161E+00, 0.1741934301847783E+00, 0.4051405202062471E+00, 0.1786266232314551E+00, 0.2993896652859737E+00, 0.1200482645536405E+00, 0.5343038813025977E-01, 0.2855738476449996E+00, 0.4013412006241577E+00, 0.6203611145567293E-02, 0.4280911574482486E-02, 0.4396785394072695E+00, 0.4138345474578556E+00, 0.6639071087521134E-01, 0.3204760309498118E-01, 0.9034140763752896E+00, 0.9108503591145208E+00, 0.7570790092830114E-01, 0.5895442813598011E-01, 0.1856765259836430E+01, 0.1160143275984235E+01, 0.2157144528657351E+00, 0.7723298847804961E+00, 0.8548780458707995E+00, 0.5186010667443678E+00, 0.1562335771835849E+00, 0.5519914319921668E+00, 0.1052848766285511E+00, 0.2419614642931688E+00, 0.1757806338135458E+00, 0.1955698951896722E-01, 0.7935225143382671E+00, 0.9463134562095434E+00, 0.2023962522401480E-02, 0.2298969194226957E-01, 0.9500696544845319E-01, 0.6985999785188474E-01, 0.1129463646814219E-01, 0.2717093011896993E-01, 0.2819864744791555E-01, 0.3949327947122574E-01, 0.9786381594178541E-10, 0.4444831994804014E-08, 0.6208618935176568E-03, 0.6208619913814727E-03, 0.1700670967075909E-47, 0.2788519153273688E-22}, + i0: 1, + n0: 20, + pp: 0, + n0in: 21, + dmin: 3.7865323450608567E-029, + dmin1: 6.2086189351765679E-004, + dmin2: 2.8198643003083550E-002, + dn: 3.7865323450608567E-029, + dn1: 6.2086189351765679E-004, + dn2: 2.8198643003083550E-002, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2395955612114145E+01, 0.2307826269503742E+01, 0.7077038564739886E-01, 0.8812934261040264E-01, 0.1879940024111348E+01, 0.1924020963289845E+01, 0.1629847954401656E-01, 0.2668944646890268E-01, 0.1323258193751120E+01, 0.1148025458776649E+01, 0.2303502998543534E+00, 0.1915312145184878E+00, 0.1403919102181368E+01, 0.1591452977947247E+01, 0.2369972908607684E-01, 0.4281642408847453E-01, 0.7535654596375009E+00, 0.7770967120400667E+00, 0.1283811140869274E-03, 0.1684766835109566E-03, 0.1651865724265327E+01, 0.5742252947387723E+00, 0.3101568824672333E+00, 0.1077768810640642E+01, 0.2115252128860193E+00, 0.4753686674121431E+00, 0.9043805314343908E-01, 0.4631342794110950E-01, 0.4338965075606848E+00, 0.4130536065801048E+00, 0.1004386157577793E+00, 0.1112809541240190E+00, 0.6963229589638840E+00, 0.3916210545154161E+00, 0.1741934301847783E+00, 0.4051405202062471E+00, 0.1786266232314551E+00, 0.2993896652859737E+00, 0.1200482645536405E+00, 0.5343038813025977E-01, 0.2855738476449996E+00, 0.4013412006241577E+00, 0.6203611145567293E-02, 0.4280911574482486E-02, 0.4396785394072695E+00, 0.4138345474578556E+00, 0.6639071087521134E-01, 0.3204760309498118E-01, 0.9034140763752896E+00, 0.9108503591145208E+00, 0.7570790092830114E-01, 0.5895442813598011E-01, 0.1856765259836430E+01, 0.1160143275984235E+01, 0.2157144528657351E+00, 0.7723298847804961E+00, 0.8548780458707995E+00, 0.5186010667443678E+00, 0.1562335771835849E+00, 0.5519914319921668E+00, 0.1052848766285511E+00, 0.2419614642931688E+00, 0.1757806338135458E+00, 0.1955698951896722E-01, 0.7935225143382671E+00, 0.9463134562095434E+00, 0.2023962522401480E-02, 0.2298969194226957E-01, 0.9500696544845319E-01, 0.6985999785188474E-01, 0.1129463646814219E-01, 0.2717093011896993E-01, 0.2819864744791555E-01, 0.3949327947122574E-01, 0.9786381594178541E-10, 0.4444831994804014E-08, 0.6208618935176568E-03, 0.6208619913814727E-03, 0.1700670967075909E-47, 0.2788519153273688E-22}, + tauOut: 0.0000000000000000, + ttypeOut: -7, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2395955612114145E+01, 0.2466725997761544E+01, 0.7077038564739886E-01, 0.5393549207373363E-01, 0.1879940024111348E+01, 0.1842303011581631E+01, 0.1629847954401656E-01, 0.1170659574821484E-01, 0.1323258193751120E+01, 0.1541901897857258E+01, 0.2303502998543534E+00, 0.2097365510789915E+00, 0.1403919102181368E+01, 0.1217882280188454E+01, 0.2369972908607684E-01, 0.1466422291592108E-01, 0.7535654596375009E+00, 0.7390296178356669E+00, 0.1283811140869274E-03, 0.2869551596920546E-03, 0.1651865724265327E+01, 0.1961735651572868E+01, 0.3101568824672333E+00, 0.3344283443049241E-01, 0.2115252128860193E+00, 0.2685204315989660E+00, 0.9043805314343908E-01, 0.1461369444993732E+00, 0.4338965075606848E+00, 0.3881981788190908E+00, 0.1004386157577793E+00, 0.1801598202532681E+00, 0.6963229589638840E+00, 0.6903565688953941E+00, 0.1741934301847783E+00, 0.4507175802324546E-01, 0.1786266232314551E+00, 0.2536031297618502E+00, 0.1200482645536405E+00, 0.1351822623162481E+00, 0.2855738476449996E+00, 0.1565951964743188E+00, 0.6203611145567293E-02, 0.1741812487831326E-01, 0.4396785394072695E+00, 0.4886511254041676E+00, 0.6639071087521134E-01, 0.1227425859208231E+00, 0.9034140763752896E+00, 0.8563793913827676E+00, 0.7570790092830114E-01, 0.1641466407918003E+00, 0.1856765259836430E+01, 0.1908333071910365E+01, 0.2157144528657351E+00, 0.9663383852973971E-01, 0.8548780458707995E+00, 0.9144777845246447E+00, 0.1562335771835849E+00, 0.1798735100772441E-01, 0.1052848766285511E+00, 0.2630781594343725E+00, 0.1757806338135458E+00, 0.5302070335887964E+00, 0.7935225143382671E+00, 0.2653394432718723E+00, 0.2023962522401480E-02, 0.7246963929058098E-03, 0.9500696544845319E-01, 0.1055769055236896E+00, 0.1129463646814219E-01, 0.3016696409481782E-02, 0.2819864744791555E-01, 0.2518195113629758E-01, 0.9786381594178541E-10, 0.2412835834031154E-11, 0.6208618935176568E-03, 0.6208618911048210E-03, 0.1700670967075909E-47, 0.2869551596920546E-03, 0.7811996215926567E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 6.2086189110482101E-004, + dmin1: 2.5181951038433764E-002, + dmin2: 8.7297525620826724E-002, + dn: 6.2086189110482101E-004, + dn1: 2.5181951038433764E-002, + dn2: 9.4282269055547374E-002, + tau: 0.0000000000000000, + ttype: -7, + g: 0.0000000000000000, + zOut: []float64{0.2395955612114145E+01, 0.2466725997761544E+01, 0.7077038564739886E-01, 0.5393549207373363E-01, 0.1879940024111348E+01, 0.1842303011581631E+01, 0.1629847954401656E-01, 0.1170659574821484E-01, 0.1323258193751120E+01, 0.1541901897857258E+01, 0.2303502998543534E+00, 0.2097365510789915E+00, 0.1403919102181368E+01, 0.1217882280188454E+01, 0.2369972908607684E-01, 0.1466422291592108E-01, 0.7535654596375009E+00, 0.7390296178356669E+00, 0.1283811140869274E-03, 0.2869551596920546E-03, 0.1651865724265327E+01, 0.1961735651572868E+01, 0.3101568824672333E+00, 0.3344283443049241E-01, 0.2115252128860193E+00, 0.2685204315989660E+00, 0.9043805314343908E-01, 0.1461369444993732E+00, 0.4338965075606848E+00, 0.3881981788190908E+00, 0.1004386157577793E+00, 0.1801598202532681E+00, 0.6963229589638840E+00, 0.6903565688953941E+00, 0.1741934301847783E+00, 0.4507175802324546E-01, 0.1786266232314551E+00, 0.2536031297618502E+00, 0.1200482645536405E+00, 0.1351822623162481E+00, 0.2855738476449996E+00, 0.1565951964743188E+00, 0.6203611145567293E-02, 0.1741812487831326E-01, 0.4396785394072695E+00, 0.4886511254041676E+00, 0.6639071087521134E-01, 0.1227425859208231E+00, 0.9034140763752896E+00, 0.8563793913827676E+00, 0.7570790092830114E-01, 0.1641466407918003E+00, 0.1856765259836430E+01, 0.1908333071910365E+01, 0.2157144528657351E+00, 0.9663383852973971E-01, 0.8548780458707995E+00, 0.9144777845246447E+00, 0.1562335771835849E+00, 0.1798735100772441E-01, 0.1052848766285511E+00, 0.2630781594343725E+00, 0.1757806338135458E+00, 0.5302070335887964E+00, 0.7935225143382671E+00, 0.2653394432718723E+00, 0.2023962522401480E-02, 0.7246963929058098E-03, 0.9500696544845319E-01, 0.1055769055236896E+00, 0.1129463646814219E-01, 0.3016696409481782E-02, 0.2819864744791555E-01, 0.2518195113629758E-01, 0.9786381594178541E-10, 0.2412835834031154E-11, 0.6208618935176568E-03, 0.6208618911048210E-03, 0.1700670967075909E-47, 0.2869551596920546E-03, 0.7811996215926567E-04}, + tauOut: 6.2086189103875732E-004, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2520040627944239E+01, 0.2466725997761544E+01, 0.3943012599746679E-01, 0.5393549207373363E-01, 0.1813958619441340E+01, 0.1842303011581631E+01, 0.9950845630193767E-02, 0.1170659574821484E-01, 0.1741066741415017E+01, 0.1541901897857258E+01, 0.1467114516582776E+00, 0.2097365510789915E+00, 0.1085214189555058E+01, 0.1217882280188454E+01, 0.9986318978978259E-02, 0.1466422291592108E-01, 0.7287093921253419E+00, 0.7390296178356669E+00, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.1993785121145770E+01, 0.1961735651572868E+01, 0.4504038193447841E-02, 0.3344283443049241E-01, 0.4095324760138526E+00, 0.2685204315989660E+00, 0.1385240464077977E+00, 0.1461369444993732E+00, 0.4292130907735224E+00, 0.3881981788190908E+00, 0.2897733504323247E+00, 0.1801598202532681E+00, 0.4450341145952761E+00, 0.6903565688953941E+00, 0.2568418582687495E-01, 0.4507175802324546E-01, 0.3624803443601846E+00, 0.2536031297618502E+00, 0.5840011260368079E-01, 0.1351822623162481E+00, 0.1149923468579125E+00, 0.1565951964743188E+00, 0.7401698075381481E-01, 0.1741812487831326E-01, 0.5367558686801371E+00, 0.4886511254041676E+00, 0.1958324578473516E+00, 0.1227425859208231E+00, 0.8240727124361776E+00, 0.8563793913827676E+00, 0.3801199318200257E+00, 0.1641466407918003E+00, 0.1624226116729040E+01, 0.1908333071910365E+01, 0.5440714051978934E-01, 0.9663383852973971E-01, 0.8774371331215411E+00, 0.9144777845246447E+00, 0.5393069221241477E-02, 0.1798735100772441E-01, 0.7872712619108886E+00, 0.2630781594343725E+00, 0.1786993199393658E+00, 0.5302070335887964E+00, 0.8674395783437358E-01, 0.2653394432718723E+00, 0.8820349511059155E-03, 0.7246963929058098E-03, 0.1070907050910267E+00, 0.1055769055236896E+00, 0.7093640994523618E-03, 0.3016696409481782E-02, 0.2385172514821930E-01, 0.2518195113629758E-01, 0.6280626703238275E-13, 0.2412835834031154E-11, 0.3257377007015450E-14, 0.6208618911048210E-03, 0.7725029665513934E-03, 0.2869551596920546E-03}, + i0: 1, + n0: 20, + pp: 0, + n0in: 20, + dmin: 3.2573770070154495E-015, + dmin1: 2.3851725145806461E-002, + dmin2: 8.6019261441467765E-002, + dn: 3.2573770070154495E-015, + dn1: 2.3851725145806461E-002, + dn2: 0.10407400868154487, + tau: 6.2086189103875732E-004, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2520040627944239E+01, 0.2466725997761544E+01, 0.3943012599746679E-01, 0.5393549207373363E-01, 0.1813958619441340E+01, 0.1842303011581631E+01, 0.9950845630193767E-02, 0.1170659574821484E-01, 0.1741066741415017E+01, 0.1541901897857258E+01, 0.1467114516582776E+00, 0.2097365510789915E+00, 0.1085214189555058E+01, 0.1217882280188454E+01, 0.9986318978978259E-02, 0.1466422291592108E-01, 0.7287093921253419E+00, 0.7390296178356669E+00, 0.7725029665513934E-03, 0.2869551596920546E-03, 0.1993785121145770E+01, 0.1961735651572868E+01, 0.4504038193447841E-02, 0.3344283443049241E-01, 0.4095324760138526E+00, 0.2685204315989660E+00, 0.1385240464077977E+00, 0.1461369444993732E+00, 0.4292130907735224E+00, 0.3881981788190908E+00, 0.2897733504323247E+00, 0.1801598202532681E+00, 0.4450341145952761E+00, 0.6903565688953941E+00, 0.2568418582687495E-01, 0.4507175802324546E-01, 0.3624803443601846E+00, 0.2536031297618502E+00, 0.5840011260368079E-01, 0.1351822623162481E+00, 0.1149923468579125E+00, 0.1565951964743188E+00, 0.7401698075381481E-01, 0.1741812487831326E-01, 0.5367558686801371E+00, 0.4886511254041676E+00, 0.1958324578473516E+00, 0.1227425859208231E+00, 0.8240727124361776E+00, 0.8563793913827676E+00, 0.3801199318200257E+00, 0.1641466407918003E+00, 0.1624226116729040E+01, 0.1908333071910365E+01, 0.5440714051978934E-01, 0.9663383852973971E-01, 0.8774371331215411E+00, 0.9144777845246447E+00, 0.5393069221241477E-02, 0.1798735100772441E-01, 0.7872712619108886E+00, 0.2630781594343725E+00, 0.1786993199393658E+00, 0.5302070335887964E+00, 0.8674395783437358E-01, 0.2653394432718723E+00, 0.8820349511059155E-03, 0.7246963929058098E-03, 0.1070907050910267E+00, 0.1055769055236896E+00, 0.7093640994523618E-03, 0.3016696409481782E-02, 0.2385172514821930E-01, 0.2518195113629758E-01, 0.6280626703238275E-13, 0.2412835834031154E-11, 0.3257377007015450E-14, 0.6208618911048210E-03, 0.7725029665513934E-03, 0.2869551596920546E-03}, + tauOut: 3.2573770070067200E-015, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2520040627944239E+01, 0.2559470753941703E+01, 0.3943012599746679E-01, 0.2794508075882943E-01, 0.1813958619441340E+01, 0.1795964384312701E+01, 0.9950845630193767E-02, 0.9646675917972324E-02, 0.1741066741415017E+01, 0.1878131517155319E+01, 0.1467114516582776E+00, 0.8477220453173254E-01, 0.1085214189555058E+01, 0.1010428304002300E+01, 0.9986318978978259E-02, 0.7202019583097946E-02, 0.7287093921253419E+00, 0.7222798755087921E+00, 0.7725029665513934E-03, 0.2132421202606784E-02, 0.1993785121145770E+01, 0.1996156738136608E+01, 0.4504038193447841E-02, 0.9240506410060376E-03, 0.4095324760138526E+00, 0.5471324717806409E+00, 0.1385240464077977E+00, 0.1086689918286978E+00, 0.4292130907735224E+00, 0.6103174493771462E+00, 0.2897733504323247E+00, 0.2112982785836522E+00, 0.4450341145952761E+00, 0.2594200218384955E+00, 0.2568418582687495E-01, 0.3588779484774172E-01, 0.3624803443601846E+00, 0.3849926621161204E+00, 0.5840011260368079E-01, 0.1744336104525046E-01, 0.1149923468579125E+00, 0.1715659665664736E+00, 0.7401698075381481E-01, 0.2315671901408358E+00, 0.5367558686801371E+00, 0.5010211363866497E+00, 0.1958324578473516E+00, 0.3221025481782661E+00, 0.8240727124361776E+00, 0.8820900960779340E+00, 0.3801199318200257E+00, 0.6999293195746292E+00, 0.1624226116729040E+01, 0.9787039376741966E+00, 0.5440714051978934E-01, 0.4877761656142095E-01, 0.8774371331215411E+00, 0.8340525857813585E+00, 0.5393069221241477E-02, 0.5090576402208483E-02, 0.7872712619108886E+00, 0.9608800054480426E+00, 0.1786993199393658E+00, 0.1613217694817542E-01, 0.8674395783437358E-01, 0.7149381583730083E-01, 0.8820349511059155E-03, 0.1321201613351008E-02, 0.1070907050910267E+00, 0.1064788675771248E+00, 0.7093640994523618E-03, 0.1589006148839502E-03, 0.2385172514821930E-01, 0.2369282453339490E-01, 0.6280626703238275E-13, 0.8634837515442557E-26, 0.3257377007015450E-14, 0.9466330862652142E-28, 0.7725029665513934E-03, 0.9240506410060376E-03, 0.7811996215926567E-04}, + i0: 1, + n0: 20, + pp: 1, + n0in: 20, + dmin: 9.4663308626521417E-029, + dmin1: 2.3692824533332088E-002, + dmin2: 7.0611780886194908E-002, + dn: 9.4663308626521417E-029, + dn1: 2.3692824533332088E-002, + dn2: 0.10576950347767239, + tau: 3.2573770070067200E-015, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2520040627944239E+01, 0.2559470753941703E+01, 0.3943012599746679E-01, 0.2794508075882943E-01, 0.1813958619441340E+01, 0.1795964384312701E+01, 0.9950845630193767E-02, 0.9646675917972324E-02, 0.1741066741415017E+01, 0.1878131517155319E+01, 0.1467114516582776E+00, 0.8477220453173254E-01, 0.1085214189555058E+01, 0.1010428304002300E+01, 0.9986318978978259E-02, 0.7202019583097946E-02, 0.7287093921253419E+00, 0.7222798755087921E+00, 0.7725029665513934E-03, 0.2132421202606784E-02, 0.1993785121145770E+01, 0.1996156738136608E+01, 0.4504038193447841E-02, 0.9240506410060376E-03, 0.4095324760138526E+00, 0.5471324717806409E+00, 0.1385240464077977E+00, 0.1086689918286978E+00, 0.4292130907735224E+00, 0.6103174493771462E+00, 0.2897733504323247E+00, 0.2112982785836522E+00, 0.4450341145952761E+00, 0.2594200218384955E+00, 0.2568418582687495E-01, 0.3588779484774172E-01, 0.3624803443601846E+00, 0.3849926621161204E+00, 0.5840011260368079E-01, 0.1744336104525046E-01, 0.1149923468579125E+00, 0.1715659665664736E+00, 0.7401698075381481E-01, 0.2315671901408358E+00, 0.5367558686801371E+00, 0.5010211363866497E+00, 0.1958324578473516E+00, 0.3221025481782661E+00, 0.8240727124361776E+00, 0.8820900960779340E+00, 0.3801199318200257E+00, 0.6999293195746292E+00, 0.1624226116729040E+01, 0.9787039376741966E+00, 0.5440714051978934E-01, 0.4877761656142095E-01, 0.8774371331215411E+00, 0.8340525857813585E+00, 0.5393069221241477E-02, 0.5090576402208483E-02, 0.7872712619108886E+00, 0.9608800054480426E+00, 0.1786993199393658E+00, 0.1613217694817542E-01, 0.8674395783437358E-01, 0.7149381583730083E-01, 0.8820349511059155E-03, 0.1321201613351008E-02, 0.1070907050910267E+00, 0.1064788675771248E+00, 0.7093640994523618E-03, 0.1589006148839502E-03, 0.2385172514821930E-01, 0.2369282453339490E-01, 0.6280626703238275E-13, 0.8634837515442557E-26, 0.3257377007015450E-14, 0.9466330862652142E-28, 0.7725029665513934E-03, 0.9240506410060376E-03, 0.7811996215926567E-04}, + tauOut: 9.4663308626521417E-029, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2587415834700532E+01, 0.2559470753941703E+01, 0.1939710234687058E-01, 0.2794508075882943E-01, 0.1786213957883803E+01, 0.1795964384312701E+01, 0.1014308840067055E-01, 0.9646675917972324E-02, 0.1952760633286381E+01, 0.1878131517155319E+01, 0.4386417535844126E-01, 0.8477220453173254E-01, 0.9737661482269571E+00, 0.1010428304002300E+01, 0.5342015449359675E-02, 0.7202019583097946E-02, 0.7190702812620393E+00, 0.7222798755087921E+00, 0.5919653562455767E-02, 0.2132421202606784E-02, 0.1991161135215158E+01, 0.1996156738136608E+01, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.6555475524103290E+00, 0.5471324717806409E+00, 0.1011712753337584E+00, 0.1086689918286978E+00, 0.7204444526270400E+00, 0.6103174493771462E+00, 0.7608498315828412E-01, 0.2112982785836522E+00, 0.2192228335279531E+00, 0.2594200218384955E+00, 0.6302508481237896E-01, 0.3588779484774172E-01, 0.3394109383489919E+00, 0.3849926621161204E+00, 0.8817297145618809E-02, 0.1744336104525046E-01, 0.3943158595616905E+00, 0.1715659665664736E+00, 0.2942312715577539E+00, 0.2315671901408358E+00, 0.5288924130071619E+00, 0.5010211363866497E+00, 0.5372046576619481E+00, 0.3221025481782661E+00, 0.1044814757990615E+01, 0.8820900960779340E+00, 0.6556411803358774E+00, 0.6999293195746292E+00, 0.3718403738997403E+00, 0.9787039376741966E+00, 0.1094101127175453E+00, 0.4877761656142095E-01, 0.7297330494660218E+00, 0.8340525857813585E+00, 0.6703044469024726E-02, 0.5090576402208483E-02, 0.9703091379271934E+00, 0.9608800054480426E+00, 0.1188642714683105E-02, 0.1613217694817542E-01, 0.7162637473596872E-01, 0.7149381583730083E-01, 0.1964081696850700E-02, 0.1321201613351008E-02, 0.1046736864951580E+00, 0.1064788675771248E+00, 0.3596705640885345E-04, 0.1589006148839502E-03, 0.2365685747698604E-01, 0.2369282453339490E-01, 0.3455244592226135E-52, 0.8634837515442557E-26}, + i0: 1, + n0: 19, + pp: 0, + n0in: 20, + dmin: 9.4663308626521417E-029, + dmin1: 2.3656857476986041E-002, + dmin2: 7.0305173122617720E-002, + dn: 9.4663308626521417E-029, + dn1: 2.3656857476986041E-002, + dn2: 0.10451478588027406, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2587415834700532E+01, 0.2559470753941703E+01, 0.1939710234687058E-01, 0.2794508075882943E-01, 0.1786213957883803E+01, 0.1795964384312701E+01, 0.1014308840067055E-01, 0.9646675917972324E-02, 0.1952760633286381E+01, 0.1878131517155319E+01, 0.4386417535844126E-01, 0.8477220453173254E-01, 0.9737661482269571E+00, 0.1010428304002300E+01, 0.5342015449359675E-02, 0.7202019583097946E-02, 0.7190702812620393E+00, 0.7222798755087921E+00, 0.5919653562455767E-02, 0.2132421202606784E-02, 0.1991161135215158E+01, 0.1996156738136608E+01, 0.2539111990097616E-03, 0.9240506410060376E-03, 0.6555475524103290E+00, 0.5471324717806409E+00, 0.1011712753337584E+00, 0.1086689918286978E+00, 0.7204444526270400E+00, 0.6103174493771462E+00, 0.7608498315828412E-01, 0.2112982785836522E+00, 0.2192228335279531E+00, 0.2594200218384955E+00, 0.6302508481237896E-01, 0.3588779484774172E-01, 0.3394109383489919E+00, 0.3849926621161204E+00, 0.8817297145618809E-02, 0.1744336104525046E-01, 0.3943158595616905E+00, 0.1715659665664736E+00, 0.2942312715577539E+00, 0.2315671901408358E+00, 0.5288924130071619E+00, 0.5010211363866497E+00, 0.5372046576619481E+00, 0.3221025481782661E+00, 0.1044814757990615E+01, 0.8820900960779340E+00, 0.6556411803358774E+00, 0.6999293195746292E+00, 0.3718403738997403E+00, 0.9787039376741966E+00, 0.1094101127175453E+00, 0.4877761656142095E-01, 0.7297330494660218E+00, 0.8340525857813585E+00, 0.6703044469024726E-02, 0.5090576402208483E-02, 0.9703091379271934E+00, 0.9608800054480426E+00, 0.1188642714683105E-02, 0.1613217694817542E-01, 0.7162637473596872E-01, 0.7149381583730083E-01, 0.1964081696850700E-02, 0.1321201613351008E-02, 0.1046736864951580E+00, 0.1064788675771248E+00, 0.3596705640885345E-04, 0.1589006148839502E-03, 0.2365685747698604E-01, 0.2369282453339490E-01, 0.3455244592226135E-52, 0.8634837515442557E-26}, + tauOut: 1.1828428738493020E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2587415834700532E+01, 0.2594984508308910E+01, 0.1939710234687058E-01, 0.1335166928493912E-01, 0.1786213957883803E+01, 0.1771176948261041E+01, 0.1014308840067055E-01, 0.1118297285215907E-01, 0.1952760633286381E+01, 0.1973613407054170E+01, 0.4386417535844126E-01, 0.2164225725832272E-01, 0.9737661482269571E+00, 0.9456374776795010E+00, 0.5342015449359675E-02, 0.4062111160297227E-02, 0.7190702812620393E+00, 0.7090993949257048E+00, 0.5919653562455767E-02, 0.1662247097070905E-01, 0.1991161135215158E+01, 0.1962964146704966E+01, 0.2539111990097616E-03, 0.8479567256479229E-04, 0.6555475524103290E+00, 0.7448056033330296E+00, 0.1011712753337584E+00, 0.9786215859981671E-01, 0.7204444526270400E+00, 0.6868388484470145E+00, 0.7608498315828412E-01, 0.2428454015756268E-01, 0.2192228335279531E+00, 0.2461349494442763E+00, 0.6302508481237896E-01, 0.8690924724014965E-01, 0.3394109383489919E+00, 0.2494905595159681E+00, 0.8817297145618809E-02, 0.1393559784278329E-01, 0.3943158595616905E+00, 0.6627831045381681E+00, 0.2942312715577539E+00, 0.2347927793131975E+00, 0.5288924130071619E+00, 0.8194758626174196E+00, 0.5372046576619481E+00, 0.6849248159595133E+00, 0.1044814757990615E+01, 0.1003702693628486E+01, 0.6556411803358774E+00, 0.2428944977310168E+00, 0.3718403738997403E+00, 0.2265275601477758E+00, 0.1094101127175453E+00, 0.3524523689025369E+00, 0.7297330494660218E+00, 0.3721552962940165E+00, 0.6703044469024726E-02, 0.1747664312451059E-01, 0.9703091379271934E+00, 0.9421927087788731E+00, 0.1188642714683105E-02, 0.9036173567869616E-04, 0.7162637473596872E-01, 0.6167166595864771E-01, 0.1964081696850700E-02, 0.3333583884775863E-02, 0.1046736864951580E+00, 0.8954764092829798E-01, 0.3596705640885345E-04, 0.9501841907954501E-05, 0.2365685747698604E-01, 0.1181892689658507E-01, 0.3455244592226135E-52, 0.8479567256479229E-04, 0.6989818532012803E-03}, + i0: 1, + n0: 19, + pp: 1, + n0in: 19, + dmin: 1.1818926896585069E-002, + dmin1: 5.9707584261797009E-002, + dmin2: 5.9707584261797009E-002, + dn: 1.1818926896585069E-002, + dn1: 8.9511673871889130E-002, + dn2: 5.9707584261797009E-002, + tau: 1.1828428738493020E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.2587415834700532E+01, 0.2594984508308910E+01, 0.1939710234687058E-01, 0.1335166928493912E-01, 0.1786213957883803E+01, 0.1771176948261041E+01, 0.1014308840067055E-01, 0.1118297285215907E-01, 0.1952760633286381E+01, 0.1973613407054170E+01, 0.4386417535844126E-01, 0.2164225725832272E-01, 0.9737661482269571E+00, 0.9456374776795010E+00, 0.5342015449359675E-02, 0.4062111160297227E-02, 0.7190702812620393E+00, 0.7090993949257048E+00, 0.5919653562455767E-02, 0.1662247097070905E-01, 0.1991161135215158E+01, 0.1962964146704966E+01, 0.2539111990097616E-03, 0.8479567256479229E-04, 0.6555475524103290E+00, 0.7448056033330296E+00, 0.1011712753337584E+00, 0.9786215859981671E-01, 0.7204444526270400E+00, 0.6868388484470145E+00, 0.7608498315828412E-01, 0.2428454015756268E-01, 0.2192228335279531E+00, 0.2461349494442763E+00, 0.6302508481237896E-01, 0.8690924724014965E-01, 0.3394109383489919E+00, 0.2494905595159681E+00, 0.8817297145618809E-02, 0.1393559784278329E-01, 0.3943158595616905E+00, 0.6627831045381681E+00, 0.2942312715577539E+00, 0.2347927793131975E+00, 0.5288924130071619E+00, 0.8194758626174196E+00, 0.5372046576619481E+00, 0.6849248159595133E+00, 0.1044814757990615E+01, 0.1003702693628486E+01, 0.6556411803358774E+00, 0.2428944977310168E+00, 0.3718403738997403E+00, 0.2265275601477758E+00, 0.1094101127175453E+00, 0.3524523689025369E+00, 0.7297330494660218E+00, 0.3721552962940165E+00, 0.6703044469024726E-02, 0.1747664312451059E-01, 0.9703091379271934E+00, 0.9421927087788731E+00, 0.1188642714683105E-02, 0.9036173567869616E-04, 0.7162637473596872E-01, 0.6167166595864771E-01, 0.1964081696850700E-02, 0.3333583884775863E-02, 0.1046736864951580E+00, 0.8954764092829798E-01, 0.3596705640885345E-04, 0.9501841907954501E-05, 0.2365685747698604E-01, 0.1181892689658507E-01, 0.3455244592226135E-52, 0.8479567256479229E-04, 0.6989818532012803E-03}, + tauOut: 1.1689473904977585E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2596646703688871E+01, 0.2594984508308910E+01, 0.9107195378059658E-02, 0.1335166928493912E-01, 0.1761563251830163E+01, 0.1771176948261041E+01, 0.1252913577120413E-01, 0.1118297285215907E-01, 0.1971037054636311E+01, 0.1973613407054170E+01, 0.1038322923301279E-01, 0.2164225725832272E-01, 0.9276268857018078E+00, 0.9456374776795010E+00, 0.3105171497598932E-02, 0.4062111160297227E-02, 0.7109272204938374E+00, 0.7090993949257048E+00, 0.4589684232723624E-01, 0.1662247097070905E-01, 0.1905462626145317E+01, 0.1962964146704966E+01, 0.3314486004504485E-04, 0.8479567256479229E-04, 0.8309451431678238E+00, 0.7448056033330296E+00, 0.8089045693556918E-01, 0.9786215859981671E-01, 0.6185434577640304E+00, 0.6868388484470145E+00, 0.9663466631053550E-02, 0.2428454015756268E-01, 0.3116912561483949E+00, 0.2461349494442763E+00, 0.6956575230565126E-01, 0.8690924724014965E-01, 0.1821709311481225E+00, 0.2494905595159681E+00, 0.5070116699532772E-01, 0.1393559784278329E-01, 0.8351852429510604E+00, 0.6627831045381681E+00, 0.2303764547900405E+00, 0.2347927793131975E+00, 0.1262334749881915E+01, 0.8194758626174196E+00, 0.5445947541061251E+00, 0.6849248159595133E+00, 0.6903129633483998E+00, 0.1003702693628486E+01, 0.7970630839299049E-01, 0.2428944977310168E+00, 0.4875841467523446E+00, 0.2265275601477758E+00, 0.2690141110044630E+00, 0.3524523689025369E+00, 0.1089283545090865E+00, 0.3721552962940165E+00, 0.1511669372043137E+00, 0.1747664312451059E-01, 0.7794266594052606E+00, 0.9421927087788731E+00, 0.7149818024536710E-05, 0.9036173567869616E-04, 0.5330862612042146E-01, 0.6167166595864771E-01, 0.5599742376476567E-02, 0.3333583884775863E-02, 0.7226792648875177E-01, 0.8954764092829798E-01, 0.1553961492315709E-05, 0.9501841907954501E-05, 0.1278990301151681E-03, 0.1181892689658507E-01, 0.7149818024536710E-05, 0.8479567256479229E-04}, + i0: 1, + n0: 19, + pp: 0, + n0in: 19, + dmin: 1.2789903011516807E-004, + dmin1: 4.9975042235645591E-002, + dmin2: 4.9975042235645591E-002, + dn: 1.2789903011516807E-004, + dn1: 7.2258424646843816E-002, + dn2: 4.9975042235645591E-002, + tau: 1.1689473904977585E-002, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2596646703688871E+01, 0.2594984508308910E+01, 0.9107195378059658E-02, 0.1335166928493912E-01, 0.1761563251830163E+01, 0.1771176948261041E+01, 0.1252913577120413E-01, 0.1118297285215907E-01, 0.1971037054636311E+01, 0.1973613407054170E+01, 0.1038322923301279E-01, 0.2164225725832272E-01, 0.9276268857018078E+00, 0.9456374776795010E+00, 0.3105171497598932E-02, 0.4062111160297227E-02, 0.7109272204938374E+00, 0.7090993949257048E+00, 0.4589684232723624E-01, 0.1662247097070905E-01, 0.1905462626145317E+01, 0.1962964146704966E+01, 0.3314486004504485E-04, 0.8479567256479229E-04, 0.8309451431678238E+00, 0.7448056033330296E+00, 0.8089045693556918E-01, 0.9786215859981671E-01, 0.6185434577640304E+00, 0.6868388484470145E+00, 0.9663466631053550E-02, 0.2428454015756268E-01, 0.3116912561483949E+00, 0.2461349494442763E+00, 0.6956575230565126E-01, 0.8690924724014965E-01, 0.1821709311481225E+00, 0.2494905595159681E+00, 0.5070116699532772E-01, 0.1393559784278329E-01, 0.8351852429510604E+00, 0.6627831045381681E+00, 0.2303764547900405E+00, 0.2347927793131975E+00, 0.1262334749881915E+01, 0.8194758626174196E+00, 0.5445947541061251E+00, 0.6849248159595133E+00, 0.6903129633483998E+00, 0.1003702693628486E+01, 0.7970630839299049E-01, 0.2428944977310168E+00, 0.4875841467523446E+00, 0.2265275601477758E+00, 0.2690141110044630E+00, 0.3524523689025369E+00, 0.1089283545090865E+00, 0.3721552962940165E+00, 0.1511669372043137E+00, 0.1747664312451059E-01, 0.7794266594052606E+00, 0.9421927087788731E+00, 0.7149818024536710E-05, 0.9036173567869616E-04, 0.5330862612042146E-01, 0.6167166595864771E-01, 0.5599742376476567E-02, 0.3333583884775863E-02, 0.7226792648875177E-01, 0.8954764092829798E-01, 0.1553961492315709E-05, 0.9501841907954501E-05, 0.1278990301151681E-03, 0.1181892689658507E-01, 0.7149818024536710E-05, 0.8479567256479229E-04}, + tauOut: 1.1689473904977585E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2596646703688871E+01, 0.2605626003858251E+01, 0.9107195378059658E-02, 0.6157023564192275E-02, 0.1761563251830163E+01, 0.1767807468828494E+01, 0.1252913577120413E-01, 0.1396950250695455E-01, 0.1971037054636311E+01, 0.1967322886153689E+01, 0.1038322923301279E-01, 0.4895872794820515E-02, 0.9276268857018078E+00, 0.9257082891959054E+00, 0.3105171497598932E-02, 0.2384715539127593E-02, 0.7109272204938374E+00, 0.7543114520732653E+00, 0.4589684232723624E-01, 0.1159397984377132E+00, 0.1905462626145317E+01, 0.1789428077358968E+01, 0.3314486004504485E-04, 0.1539126429493388E-04, 0.8309451431678238E+00, 0.9116923136304173E+00, 0.8089045693556918E-01, 0.5488064578914756E-01, 0.6185434577640304E+00, 0.5731983833972557E+00, 0.9663466631053550E-02, 0.5254756712901782E-02, 0.3116912561483949E+00, 0.3758743565324636E+00, 0.6956575230565126E-01, 0.3371567560620648E-01, 0.1821709311481225E+00, 0.1990285273285630E+00, 0.5070116699532772E-01, 0.2127577741907859E+00, 0.8351852429510604E+00, 0.8526760283416343E+00, 0.2303764547900405E+00, 0.3410582621885915E+00, 0.1262334749881915E+01, 0.1465743346590768E+01, 0.5445947541061251E+00, 0.2564847518533230E+00, 0.6903129633483998E+00, 0.5134066246793865E+00, 0.7970630839299049E-01, 0.7569737222001199E-01, 0.4875841467523446E+00, 0.6807729903281149E+00, 0.2690141110044630E+00, 0.4304410555024735E-01, 0.1089283545090865E+00, 0.2169232909544721E+00, 0.1511669372043137E+00, 0.5431576312495270E+00, 0.7794266594052606E+00, 0.2361482827650774E+00, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.5330862612042146E-01, 0.5877885927277143E-01, 0.5599742376476567E-02, 0.6884818375619963E-02, 0.7226792648875177E-01, 0.6525676686594341E-01, 0.1553961492315709E-05, 0.3045663725752605E-08, 0.1278990301151681E-03, 0.7757707209639971E-09, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.6989818532012803E-03}, + i0: 1, + n0: 19, + pp: 1, + n0in: 19, + dmin: 7.7577072096399712E-010, + dmin1: 5.3179116896294863E-002, + dmin2: 5.3179116896294863E-002, + dn: 7.7577072096399712E-010, + dn1: 6.5255212904451090E-002, + dn2: 5.3179116896294863E-002, + tau: 1.2789520868072135E-004, + ttype: -15, + g: 0.0000000000000000, + zOut: []float64{0.2596646703688871E+01, 0.2605626003858251E+01, 0.9107195378059658E-02, 0.6157023564192275E-02, 0.1761563251830163E+01, 0.1767807468828494E+01, 0.1252913577120413E-01, 0.1396950250695455E-01, 0.1971037054636311E+01, 0.1967322886153689E+01, 0.1038322923301279E-01, 0.4895872794820515E-02, 0.9276268857018078E+00, 0.9257082891959054E+00, 0.3105171497598932E-02, 0.2384715539127593E-02, 0.7109272204938374E+00, 0.7543114520732653E+00, 0.4589684232723624E-01, 0.1159397984377132E+00, 0.1905462626145317E+01, 0.1789428077358968E+01, 0.3314486004504485E-04, 0.1539126429493388E-04, 0.8309451431678238E+00, 0.9116923136304173E+00, 0.8089045693556918E-01, 0.5488064578914756E-01, 0.6185434577640304E+00, 0.5731983833972557E+00, 0.9663466631053550E-02, 0.5254756712901782E-02, 0.3116912561483949E+00, 0.3758743565324636E+00, 0.6956575230565126E-01, 0.3371567560620648E-01, 0.1821709311481225E+00, 0.1990285273285630E+00, 0.5070116699532772E-01, 0.2127577741907859E+00, 0.8351852429510604E+00, 0.8526760283416343E+00, 0.2303764547900405E+00, 0.3410582621885915E+00, 0.1262334749881915E+01, 0.1465743346590768E+01, 0.5445947541061251E+00, 0.2564847518533230E+00, 0.6903129633483998E+00, 0.5134066246793865E+00, 0.7970630839299049E-01, 0.7569737222001199E-01, 0.4875841467523446E+00, 0.6807729903281149E+00, 0.2690141110044630E+00, 0.4304410555024735E-01, 0.1089283545090865E+00, 0.2169232909544721E+00, 0.1511669372043137E+00, 0.5431576312495270E+00, 0.7794266594052606E+00, 0.2361482827650774E+00, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.5330862612042146E-01, 0.5877885927277143E-01, 0.5599742376476567E-02, 0.6884818375619963E-02, 0.7226792648875177E-01, 0.6525676686594341E-01, 0.1553961492315709E-05, 0.3045663725752605E-08, 0.1278990301151681E-03, 0.7757707209639971E-09, 0.7149818024536710E-05, 0.1614015445872399E-05, 0.6989818532012803E-03}, + tauOut: 1.2789520868072135E-004, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2611783026646672E+01, 0.2605626003858251E+01, 0.4167433562238479E-02, 0.6157023564192275E-02, 0.1777609536997439E+01, 0.1767807468828494E+01, 0.1546038171944878E-01, 0.1396950250695455E-01, 0.1956758376453290E+01, 0.1967322886153689E+01, 0.2316152103168096E-02, 0.4895872794820515E-02, 0.9257768518560943E+00, 0.9257082891959054E+00, 0.1943036529261404E-02, 0.2384715539127593E-02, 0.8683082132059464E+00, 0.7543114520732653E+00, 0.2389312083572061E+00, 0.1159397984377132E+00, 0.1550512259490286E+01, 0.1789428077358968E+01, 0.9049975109102588E-05, 0.1539126429493388E-04, 0.9665639086686850E+00, 0.9116923136304173E+00, 0.3254569838994440E-01, 0.5488064578914756E-01, 0.5459074409444424E+00, 0.5731983833972557E+00, 0.3618064437406363E-02, 0.5254756712901782E-02, 0.4059719669254931E+00, 0.3758743565324636E+00, 0.1652917395900484E-01, 0.3371567560620648E-01, 0.3952571267845734E+00, 0.1990285273285630E+00, 0.4589757947481138E+00, 0.2127577741907859E+00, 0.7347584950063413E+00, 0.8526760283416343E+00, 0.6803648845168142E+00, 0.3410582621885915E+00, 0.1041863213151506E+01, 0.1465743346590768E+01, 0.1263898840735783E+00, 0.2564847518533230E+00, 0.4627141120500496E+00, 0.5134066246793865E+00, 0.1113705527974558E+00, 0.7569737222001199E-01, 0.6124465423051357E+00, 0.6807729903281149E+00, 0.1524585149425051E-01, 0.4304410555024735E-01, 0.7448350699339780E+00, 0.2169232909544721E+00, 0.1722069046798406E+00, 0.5431576312495270E+00, 0.6394299132491200E-01, 0.2361482827650774E+00, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6566219320748727E-01, 0.5877885927277143E-01, 0.6842308575232983E-02, 0.6884818375619963E-02, 0.5841446056060346E-01, 0.6525676686594341E-01, 0.4044780558898965E-16, 0.3045663725752605E-08, 0.1013559914197710E-18, 0.7757707209639971E-09, 0.1483665133446019E-05, 0.1614015445872399E-05}, + i0: 1, + n0: 19, + pp: 0, + n0in: 19, + dmin: 1.0135599141977102E-019, + dmin1: 5.8414457514939733E-002, + dmin2: 5.8777374831867304E-002, + dn: 1.0135599141977102E-019, + dn1: 5.8414457514939733E-002, + dn2: 5.8777374831867304E-002, + tau: 7.7577068041483555E-010, + ttype: -15, + g: 0.0000000000000000, + zOut: []float64{0.2611783026646672E+01, 0.2605626003858251E+01, 0.4167433562238479E-02, 0.6157023564192275E-02, 0.1777609536997439E+01, 0.1767807468828494E+01, 0.1546038171944878E-01, 0.1396950250695455E-01, 0.1956758376453290E+01, 0.1967322886153689E+01, 0.2316152103168096E-02, 0.4895872794820515E-02, 0.9257768518560943E+00, 0.9257082891959054E+00, 0.1943036529261404E-02, 0.2384715539127593E-02, 0.8683082132059464E+00, 0.7543114520732653E+00, 0.2389312083572061E+00, 0.1159397984377132E+00, 0.1550512259490286E+01, 0.1789428077358968E+01, 0.9049975109102588E-05, 0.1539126429493388E-04, 0.9665639086686850E+00, 0.9116923136304173E+00, 0.3254569838994440E-01, 0.5488064578914756E-01, 0.5459074409444424E+00, 0.5731983833972557E+00, 0.3618064437406363E-02, 0.5254756712901782E-02, 0.4059719669254931E+00, 0.3758743565324636E+00, 0.1652917395900484E-01, 0.3371567560620648E-01, 0.3952571267845734E+00, 0.1990285273285630E+00, 0.4589757947481138E+00, 0.2127577741907859E+00, 0.7347584950063413E+00, 0.8526760283416343E+00, 0.6803648845168142E+00, 0.3410582621885915E+00, 0.1041863213151506E+01, 0.1465743346590768E+01, 0.1263898840735783E+00, 0.2564847518533230E+00, 0.4627141120500496E+00, 0.5134066246793865E+00, 0.1113705527974558E+00, 0.7569737222001199E-01, 0.6124465423051357E+00, 0.6807729903281149E+00, 0.1524585149425051E-01, 0.4304410555024735E-01, 0.7448350699339780E+00, 0.2169232909544721E+00, 0.1722069046798406E+00, 0.5431576312495270E+00, 0.6394299132491200E-01, 0.2361482827650774E+00, 0.1483665133446019E-05, 0.1614015445872399E-05, 0.6566219320748727E-01, 0.5877885927277143E-01, 0.6842308575232983E-02, 0.6884818375619963E-02, 0.5841446056060346E-01, 0.6525676686594341E-01, 0.4044780558898965E-16, 0.3045663725752605E-08, 0.1013559914197710E-18, 0.7757707209639971E-09, 0.1483665133446019E-05, 0.1614015445872399E-05}, + tauOut: 1.0135599141977091E-019, + ttypeOut: -2, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2611783026646672E+01, 0.2615950460208911E+01, 0.4167433562238479E-02, 0.2831884532112553E-02, 0.1777609536997439E+01, 0.1790238034184775E+01, 0.1546038171944878E-01, 0.1689844079671380E-01, 0.1956758376453290E+01, 0.1942176087759744E+01, 0.2316152103168096E-02, 0.1104039956008399E-02, 0.9257768518560943E+00, 0.9266158484293474E+00, 0.1943036529261404E-02, 0.1820770257466081E-02, 0.8683082132059464E+00, 0.1105418651305687E+01, 0.2389312083572061E+00, 0.3351361651941490E+00, 0.1550512259490286E+01, 0.1215385144271246E+01, 0.9049975109102588E-05, 0.7197207696703830E-05, 0.9665639086686850E+00, 0.9991024098509327E+00, 0.3254569838994440E-01, 0.1778290067827487E-01, 0.5459074409444424E+00, 0.5317426047035739E+00, 0.3618064437406363E-02, 0.2762300261676148E-02, 0.4059719669254931E+00, 0.4197388406228219E+00, 0.1652917395900484E-01, 0.1556509232613395E-01, 0.3952571267845734E+00, 0.8386678292065533E+00, 0.4589757947481138E+00, 0.4021095747913879E+00, 0.7347584950063413E+00, 0.1013013804731768E+01, 0.6803648845168142E+00, 0.6997408538631263E+00, 0.1041863213151506E+01, 0.4685122433619579E+00, 0.1263898840735783E+00, 0.1248257304047288E+00, 0.4627141120500496E+00, 0.4492589344427766E+00, 0.1113705527974558E+00, 0.1518244930621437E+00, 0.6124465423051357E+00, 0.4758679007372426E+00, 0.1524585149425051E-01, 0.2386301922514691E-01, 0.7448350699339780E+00, 0.8931789553886716E+00, 0.1722069046798406E+00, 0.1232835205710967E-01, 0.6394299132491200E-01, 0.5161612293293578E-01, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6566219320748727E-01, 0.7250261437426894E-01, 0.6842308575232983E-02, 0.5512763475647510E-02, 0.5841446056060346E-01, 0.5290169708495600E-01, 0.4044780558898965E-16, 0.7749519698096867E-34, 0.2434478048112329E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 19, + dmin: 1.0135599141977093E-019, + dmin1: 5.1614639267802333E-002, + dmin2: 5.1614639267802333E-002, + dn: 1.0135599141977093E-019, + dn1: 5.2901697084955956E-002, + dn2: 6.5660305799035965E-002, + tau: 0.0000000000000000, + ttype: -2, + g: 0.0000000000000000, + zOut: []float64{0.2611783026646672E+01, 0.2615950460208911E+01, 0.4167433562238479E-02, 0.2831884532112553E-02, 0.1777609536997439E+01, 0.1790238034184775E+01, 0.1546038171944878E-01, 0.1689844079671380E-01, 0.1956758376453290E+01, 0.1942176087759744E+01, 0.2316152103168096E-02, 0.1104039956008399E-02, 0.9257768518560943E+00, 0.9266158484293474E+00, 0.1943036529261404E-02, 0.1820770257466081E-02, 0.8683082132059464E+00, 0.1105418651305687E+01, 0.2389312083572061E+00, 0.3351361651941490E+00, 0.1550512259490286E+01, 0.1215385144271246E+01, 0.9049975109102588E-05, 0.7197207696703830E-05, 0.9665639086686850E+00, 0.9991024098509327E+00, 0.3254569838994440E-01, 0.1778290067827487E-01, 0.5459074409444424E+00, 0.5317426047035739E+00, 0.3618064437406363E-02, 0.2762300261676148E-02, 0.4059719669254931E+00, 0.4197388406228219E+00, 0.1652917395900484E-01, 0.1556509232613395E-01, 0.3952571267845734E+00, 0.8386678292065533E+00, 0.4589757947481138E+00, 0.4021095747913879E+00, 0.7347584950063413E+00, 0.1013013804731768E+01, 0.6803648845168142E+00, 0.6997408538631263E+00, 0.1041863213151506E+01, 0.4685122433619579E+00, 0.1263898840735783E+00, 0.1248257304047288E+00, 0.4627141120500496E+00, 0.4492589344427766E+00, 0.1113705527974558E+00, 0.1518244930621437E+00, 0.6124465423051357E+00, 0.4758679007372426E+00, 0.1524585149425051E-01, 0.2386301922514691E-01, 0.7448350699339780E+00, 0.8931789553886716E+00, 0.1722069046798406E+00, 0.1232835205710967E-01, 0.6394299132491200E-01, 0.5161612293293578E-01, 0.1483665133446019E-05, 0.1887408451311279E-05, 0.6566219320748727E-01, 0.7250261437426894E-01, 0.6842308575232983E-02, 0.5512763475647510E-02, 0.5841446056060346E-01, 0.5290169708495600E-01, 0.4044780558898965E-16, 0.7749519698096867E-34, 0.2434478048112329E-01}, + tauOut: 1.2903659816950583E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2605878684924073E+01, 0.2615950460208911E+01, 0.1945503997226627E-02, 0.2831884532112553E-02, 0.1792287311167312E+01, 0.1790238034184775E+01, 0.1831165540887852E-01, 0.1689844079671380E-01, 0.1912064812489923E+01, 0.1942176087759744E+01, 0.5350346462390188E-03, 0.1104039956008399E-02, 0.9149979242236238E+00, 0.9266158484293474E+00, 0.2199691768758329E-02, 0.1820770257466081E-02, 0.1425451464914127E+01, 0.1105418651305687E+01, 0.2857477273065492E+00, 0.3351361651941490E+00, 0.9167409543554429E+00, 0.1215385144271246E+01, 0.7843816205451699E-05, 0.7197207696703830E-05, 0.1003973806896052E+01, 0.9991024098509327E+00, 0.9418498631040351E-02, 0.1778290067827487E-01, 0.5121827465172590E+00, 0.5317426047035739E+00, 0.2263732461064059E-02, 0.2762300261676148E-02, 0.4201365406709412E+00, 0.4197388406228219E+00, 0.3107071375346623E-01, 0.1556509232613395E-01, 0.1196803030427524E+01, 0.8386678292065533E+00, 0.3403588894097180E+00, 0.4021095747913879E+00, 0.1359492109368225E+01, 0.1013013804731768E+01, 0.2411467892724848E+00, 0.6997408538631263E+00, 0.3392875246772514E+00, 0.4685122433619579E+00, 0.1652848117124708E+00, 0.1248257304047288E+00, 0.4228949559754990E+00, 0.4492589344427766E+00, 0.1708424320817961E+00, 0.1518244930621437E+00, 0.3159848280636428E+00, 0.4758679007372426E+00, 0.6745243660763246E-01, 0.2386301922514691E-01, 0.8251512110211983E+00, 0.8931789553886716E+00, 0.7711819686391232E-03, 0.1232835205710967E-01, 0.3794316855579739E-01, 0.5161612293293578E-01, 0.3606500256058598E-05, 0.1887408451311279E-05, 0.6510811153270980E-01, 0.7250261437426894E-01, 0.4479235177066975E-02, 0.5512763475647510E-02, 0.3551880209093845E-01, 0.5290169708495600E-01, 0.7843816205451699E-05, 0.7197207696703830E-05}, + i0: 1, + n0: 18, + pp: 0, + n0in: 18, + dmin: 3.5518802090938446E-002, + dmin1: 3.7941281147346073E-002, + dmin2: 3.7941281147346073E-002, + dn: 3.5518802090938446E-002, + dn1: 5.9595348057062299E-002, + dn2: 3.7941281147346073E-002, + tau: 1.2903659816950583E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.2605878684924073E+01, 0.2615950460208911E+01, 0.1945503997226627E-02, 0.2831884532112553E-02, 0.1792287311167312E+01, 0.1790238034184775E+01, 0.1831165540887852E-01, 0.1689844079671380E-01, 0.1912064812489923E+01, 0.1942176087759744E+01, 0.5350346462390188E-03, 0.1104039956008399E-02, 0.9149979242236238E+00, 0.9266158484293474E+00, 0.2199691768758329E-02, 0.1820770257466081E-02, 0.1425451464914127E+01, 0.1105418651305687E+01, 0.2857477273065492E+00, 0.3351361651941490E+00, 0.9167409543554429E+00, 0.1215385144271246E+01, 0.7843816205451699E-05, 0.7197207696703830E-05, 0.1003973806896052E+01, 0.9991024098509327E+00, 0.9418498631040351E-02, 0.1778290067827487E-01, 0.5121827465172590E+00, 0.5317426047035739E+00, 0.2263732461064059E-02, 0.2762300261676148E-02, 0.4201365406709412E+00, 0.4197388406228219E+00, 0.3107071375346623E-01, 0.1556509232613395E-01, 0.1196803030427524E+01, 0.8386678292065533E+00, 0.3403588894097180E+00, 0.4021095747913879E+00, 0.1359492109368225E+01, 0.1013013804731768E+01, 0.2411467892724848E+00, 0.6997408538631263E+00, 0.3392875246772514E+00, 0.4685122433619579E+00, 0.1652848117124708E+00, 0.1248257304047288E+00, 0.4228949559754990E+00, 0.4492589344427766E+00, 0.1708424320817961E+00, 0.1518244930621437E+00, 0.3159848280636428E+00, 0.4758679007372426E+00, 0.6745243660763246E-01, 0.2386301922514691E-01, 0.8251512110211983E+00, 0.8931789553886716E+00, 0.7711819686391232E-03, 0.1232835205710967E-01, 0.3794316855579739E-01, 0.5161612293293578E-01, 0.3606500256058598E-05, 0.1887408451311279E-05, 0.6510811153270980E-01, 0.7250261437426894E-01, 0.4479235177066975E-02, 0.5512763475647510E-02, 0.3551880209093845E-01, 0.5290169708495600E-01, 0.7843816205451699E-05, 0.7197207696703830E-05}, + tauOut: 2.4222106054237202E-002, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.2605878684924073E+01, 0.2583602082867062E+01, 0.1945503997226627E-02, 0.1349628161076996E-02, 0.1792287311167312E+01, 0.1785027232360876E+01, 0.1831165540887852E-01, 0.1961486711855321E-01, 0.1912064812489923E+01, 0.1868762873963372E+01, 0.5350346462390188E-03, 0.2619677421449130E-03, 0.9149979242236238E+00, 0.8927135421960001E+00, 0.2199691768758329E-02, 0.3512385223173503E-02, 0.1425451464914127E+01, 0.1683464700943265E+01, 0.2857477273065492E+00, 0.1556056649653108E+00, 0.9167409543554429E+00, 0.7369210271521004E+00, 0.7843816205451699E-05, 0.1068633642713914E-04, 0.1003973806896052E+01, 0.9891595131364276E+00, 0.9418498631040351E-02, 0.4876860034049891E-02, 0.5121827465172590E+00, 0.4853475128900360E+00, 0.2263732461064059E-02, 0.1959578858316830E-02, 0.4201365406709412E+00, 0.4250255695118534E+00, 0.3107071375346623E-01, 0.8749008776201990E-01, 0.1196803030427524E+01, 0.1425449726020986E+01, 0.3403588894097180E+00, 0.3246099922425689E+00, 0.1359492109368225E+01, 0.1251806800343904E+01, 0.2411467892724848E+00, 0.6536000379104072E-01, 0.3392875246772514E+00, 0.4149902265444443E+00, 0.1652848117124708E+00, 0.1684331550518530E+00, 0.4228949559754990E+00, 0.4010821269512049E+00, 0.1708424320817961E+00, 0.1345949193440586E+00, 0.3159848280636428E+00, 0.2246202392729794E+00, 0.6745243660763246E-01, 0.2477891570824889E+00, 0.8251512110211983E+00, 0.5539111298531113E+00, 0.7711819686391232E-03, 0.5282632149136541E-04, 0.3794316855579739E-01, 0.1367184268032488E-01, 0.3606500256058598E-05, 0.1717489195894037E-04, 0.6510811153270980E-01, 0.4534806576358064E-01, 0.4479235177066975E-02, 0.3508353996892708E-02, 0.3551880209093845E-01, 0.7788342039808532E-02, 0.7843816205451699E-05, 0.1068633642713914E-04, 0.2434478048112329E-01}, + i0: 1, + n0: 18, + pp: 1, + n0in: 18, + dmin: 7.7883420398085317E-003, + dmin1: 1.3668236180068825E-002, + dmin2: 1.3668236180068825E-002, + dn: 7.7883420398085317E-003, + dn1: 4.0868830586513666E-002, + dn2: 1.3668236180068825E-002, + tau: 2.4222106054237202E-002, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.2605878684924073E+01, 0.2583602082867062E+01, 0.1945503997226627E-02, 0.1349628161076996E-02, 0.1792287311167312E+01, 0.1785027232360876E+01, 0.1831165540887852E-01, 0.1961486711855321E-01, 0.1912064812489923E+01, 0.1868762873963372E+01, 0.5350346462390188E-03, 0.2619677421449130E-03, 0.9149979242236238E+00, 0.8927135421960001E+00, 0.2199691768758329E-02, 0.3512385223173503E-02, 0.1425451464914127E+01, 0.1683464700943265E+01, 0.2857477273065492E+00, 0.1556056649653108E+00, 0.9167409543554429E+00, 0.7369210271521004E+00, 0.7843816205451699E-05, 0.1068633642713914E-04, 0.1003973806896052E+01, 0.9891595131364276E+00, 0.9418498631040351E-02, 0.4876860034049891E-02, 0.5121827465172590E+00, 0.4853475128900360E+00, 0.2263732461064059E-02, 0.1959578858316830E-02, 0.4201365406709412E+00, 0.4250255695118534E+00, 0.3107071375346623E-01, 0.8749008776201990E-01, 0.1196803030427524E+01, 0.1425449726020986E+01, 0.3403588894097180E+00, 0.3246099922425689E+00, 0.1359492109368225E+01, 0.1251806800343904E+01, 0.2411467892724848E+00, 0.6536000379104072E-01, 0.3392875246772514E+00, 0.4149902265444443E+00, 0.1652848117124708E+00, 0.1684331550518530E+00, 0.4228949559754990E+00, 0.4010821269512049E+00, 0.1708424320817961E+00, 0.1345949193440586E+00, 0.3159848280636428E+00, 0.2246202392729794E+00, 0.6745243660763246E-01, 0.2477891570824889E+00, 0.8251512110211983E+00, 0.5539111298531113E+00, 0.7711819686391232E-03, 0.5282632149136541E-04, 0.3794316855579739E-01, 0.1367184268032488E-01, 0.3606500256058598E-05, 0.1717489195894037E-04, 0.6510811153270980E-01, 0.4534806576358064E-01, 0.4479235177066975E-02, 0.3508353996892708E-02, 0.3551880209093845E-01, 0.7788342039808532E-02, 0.7843816205451699E-05, 0.1068633642713914E-04, 0.2434478048112329E-01}, + tauOut: 5.1484099711571517E-003, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + + { + z: []float64{0.1845045664413523E+01, 0.1845045673681623E+01, 0.9284324334305927E-09, 0.1331924177594376E-08, 0.1286110617891388E+01, 0.1286109423357647E+01, 0.8600075793510468E-06, 0.1206062196852843E-05, 0.9228692597002398E+00, 0.9170877606119078E+00, 0.7344017075309068E-02, 0.5782369695935185E-02, 0.1164764979181097E+01, 0.1172109006845551E+01, 0.1416795225784663E-10, 0.1087898982148097E-10, 0.1516899526939413E+01, 0.1516899536394917E+01, 0.1175479719901021E-09, 0.1158688024893155E-08, 0.1569402316257081E+00, 0.1538882419371820E+00, 0.4821181617659422E-02, 0.3052000406097992E-02, 0.2431018491557045E+00, 0.2479152225121892E+00, 0.8755391955186837E-05, 0.7818861198543554E-05, 0.2722314297289909E+00, 0.2722202019375114E+00, 0.1357252989661879E-04, 0.1999378345859679E-04, 0.1847873189363651E+00, 0.1848009020627515E+00, 0.2027258571663375E-18, 0.3534048617228375E-11, 0.4750110334503861E-13, 0.1060007138617788E-07, 0.1416795225784663E-10, 0.1087898982148097E-10}, + i0: 1, + n0: 10, + pp: 0, + n0in: 10, + dmin: 4.7501103345038606E-014, + dmin1: 0.15388823121961009, + dmin2: 0.15388823121961009, + dn: 4.7501103345038606E-014, + dn1: 0.18478731893283101, + dn2: 0.27221143594553232, + tau: 1.0600023884871808E-008, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1845045664413523E+01, 0.1845045673681623E+01, 0.9284324334305927E-09, 0.1331924177594376E-08, 0.1286110617891388E+01, 0.1286109423357647E+01, 0.8600075793510468E-06, 0.1206062196852843E-05, 0.9228692597002398E+00, 0.9170877606119078E+00, 0.7344017075309068E-02, 0.5782369695935185E-02, 0.1164764979181097E+01, 0.1172109006845551E+01, 0.1416795225784663E-10, 0.1087898982148097E-10, 0.1516899526939413E+01, 0.1516899536394917E+01, 0.1175479719901021E-09, 0.1158688024893155E-08, 0.1569402316257081E+00, 0.1538882419371820E+00, 0.4821181617659422E-02, 0.3052000406097992E-02, 0.2431018491557045E+00, 0.2479152225121892E+00, 0.8755391955186837E-05, 0.7818861198543554E-05, 0.2722314297289909E+00, 0.2722202019375114E+00, 0.1357252989661879E-04, 0.1999378345859679E-04, 0.1847873189363651E+00, 0.1848009020627515E+00, 0.2027258571663375E-18, 0.3534048617228375E-11, 0.4750110334503861E-13, 0.1060007138617788E-07, 0.1416795225784663E-10, 0.1087898982148097E-10}, + tauOut: 4.7501103294055340E-014, + ttypeOut: -4, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1845045664413523E+01, 0.1845045665341908E+01, 0.9284324334305927E-09, 0.6471746651368383E-09, 0.1286110617891388E+01, 0.1286111477251745E+01, 0.8600075793510468E-06, 0.6171117917307419E-06, 0.9228692597002398E+00, 0.9302126596637096E+00, 0.7344017075309068E-02, 0.9195804644198721E-02, 0.1164764979181097E+01, 0.1155569174551018E+01, 0.1416795225784663E-10, 0.1859807318413278E-10, 0.1516899526939413E+01, 0.1516899527038316E+01, 0.1175479719901021E-09, 0.1216165317638265E-10, 0.1569402316257081E+00, 0.1617614132311584E+00, 0.4821181617659422E-02, 0.7245474325163344E-02, 0.2431018491557045E+00, 0.2358651302224488E+00, 0.8755391955186837E-05, 0.1010532106865606E-04, 0.2722314297289909E+00, 0.2722348969377714E+00, 0.1357252989661879E-04, 0.9212747663842461E-05, 0.1847873189363651E+00, 0.1847781061886537E+00, 0.2027258571663375E-18, 0.5211495068651724E-31, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 10, + dmin: 5.0983266199979805E-023, + dmin1: 0.15694023161349893, + dmin2: 0.15694023161349893, + dn: 5.0983266199979805E-023, + dn1: 0.18477810618865373, + dn2: 0.27222132440787472, + tau: 4.7501103294055340E-014, + ttype: -4, + g: 0.0000000000000000, + zOut: []float64{0.1845045664413523E+01, 0.1845045665341908E+01, 0.9284324334305927E-09, 0.6471746651368383E-09, 0.1286110617891388E+01, 0.1286111477251745E+01, 0.8600075793510468E-06, 0.6171117917307419E-06, 0.9228692597002398E+00, 0.9302126596637096E+00, 0.7344017075309068E-02, 0.9195804644198721E-02, 0.1164764979181097E+01, 0.1155569174551018E+01, 0.1416795225784663E-10, 0.1859807318413278E-10, 0.1516899526939413E+01, 0.1516899527038316E+01, 0.1175479719901021E-09, 0.1216165317638265E-10, 0.1569402316257081E+00, 0.1617614132311584E+00, 0.4821181617659422E-02, 0.7245474325163344E-02, 0.2431018491557045E+00, 0.2358651302224488E+00, 0.8755391955186837E-05, 0.1010532106865606E-04, 0.2722314297289909E+00, 0.2722348969377714E+00, 0.1357252989661879E-04, 0.9212747663842461E-05, 0.1847873189363651E+00, 0.1847781061886537E+00, 0.2027258571663375E-18, 0.5211495068651724E-31, 0.8046649468928653E+00}, + tauOut: 3.9235057903374733E-002, + ttypeOut: -9, + gOut: 0.0000000000000000, + }, + { + z: []float64{0.1805810608085708E+01, 0.1845045665341908E+01, 0.4609225136302542E-09, 0.6471746651368383E-09, 0.1246877035999240E+01, 0.1286111477251745E+01, 0.4603863769418564E-06, 0.6171117917307419E-06, 0.9001729460181566E+00, 0.9302126596637096E+00, 0.1180482975969687E-01, 0.9195804644198721E-02, 0.1104529286906545E+01, 0.1155569174551018E+01, 0.2554156666668993E-10, 0.1859807318413278E-10, 0.1477664469121561E+01, 0.1516899527038316E+01, 0.1331348385339719E-11, 0.1216165317638265E-10, 0.1297718296516156E+00, 0.1617614132311584E+00, 0.1316891924708087E-01, 0.7245474325163344E-02, 0.1834712583930619E+00, 0.2358651302224488E+00, 0.1499428882618218E-04, 0.1010532106865606E-04, 0.2329940574932343E+00, 0.2722348969377714E+00, 0.7306255294378852E-05, 0.9212747663842461E-05, 0.1455357420299846E+00, 0.1847781061886537E+00, 0.1331348385339719E-11, 0.1216165317638265E-10}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 0.12252635532645229, + dmin1: 0.12252635532645229, + dmin2: 0.12252635532645229, + dn: 0.14553574202998462, + dn1: 0.23298484474557046, + dn2: 0.18346115307199323, + tau: 3.9235057903374733E-002, + ttype: -9, + g: 0.0000000000000000, + zOut: []float64{0.1805810608085708E+01, 0.1845045665341908E+01, 0.4609225136302542E-09, 0.6471746651368383E-09, 0.1246877035999240E+01, 0.1286111477251745E+01, 0.4603863769418564E-06, 0.6171117917307419E-06, 0.9001729460181566E+00, 0.9302126596637096E+00, 0.1180482975969687E-01, 0.9195804644198721E-02, 0.1104529286906545E+01, 0.1155569174551018E+01, 0.2554156666668993E-10, 0.1859807318413278E-10, 0.1477664469121561E+01, 0.1516899527038316E+01, 0.1331348385339719E-11, 0.1216165317638265E-10, 0.1297718296516156E+00, 0.1617614132311584E+00, 0.1316891924708087E-01, 0.7245474325163344E-02, 0.1834712583930619E+00, 0.2358651302224488E+00, 0.1499428882618218E-04, 0.1010532106865606E-04, 0.2329940574932343E+00, 0.2722348969377714E+00, 0.7306255294378852E-05, 0.9212747663842461E-05, 0.1455357420299846E+00, 0.1847781061886537E+00, 0.1331348385339719E-11, 0.1216165317638265E-10}, + tauOut: 3.0631588831613071E-002, + ttypeOut: -6, + gOut: 0.25000000000000000, + }, + { + z: []float64{0.1805810608085708E+01, 0.1775179019715018E+01, 0.4609225136302542E-09, 0.3237497126982006E-09, 0.1246877035999240E+01, 0.1216245907230254E+01, 0.4603863769418564E-06, 0.3407430674789675E-06, 0.9001729460181566E+00, 0.8813458462031728E+00, 0.1180482975969687E-01, 0.1479416990810367E-01, 0.1104529286906545E+01, 0.1059103528192370E+01, 0.2554156666668993E-10, 0.3563567162644001E-10, 0.1477664469121561E+01, 0.1447032880255644E+01, 0.1331348385339719E-11, 0.1193970905752580E-12, 0.1297718296516156E+00, 0.1123091600669640E+00, 0.1316891924708087E-01, 0.2151309995104528E-01, 0.1834712583930619E+00, 0.1313415638992297E+00, 0.1499428882618218E-04, 0.2659919745982362E-04, 0.2329940574932343E+00, 0.2023431757194558E+00, 0.7306255294378852E-05, 0.5255039029347846E-05, 0.1455357420299846E+00, 0.1148988981593422E+00, 0.1331348385339719E-11, 0.1193970905752580E-12, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 9.9140240819883152E-002, + dmin1: 9.9140240819883152E-002, + dmin2: 9.9140240819883152E-002, + dn: 0.11489889815934221, + dn1: 0.20233586946416143, + dn2: 0.13132656961040354, + tau: 3.0631588831613071E-002, + ttype: -6, + g: 0.25000000000000000, + zOut: []float64{0.1805810608085708E+01, 0.1775179019715018E+01, 0.4609225136302542E-09, 0.3237497126982006E-09, 0.1246877035999240E+01, 0.1216245907230254E+01, 0.4603863769418564E-06, 0.3407430674789675E-06, 0.9001729460181566E+00, 0.8813458462031728E+00, 0.1180482975969687E-01, 0.1479416990810367E-01, 0.1104529286906545E+01, 0.1059103528192370E+01, 0.2554156666668993E-10, 0.3563567162644001E-10, 0.1477664469121561E+01, 0.1447032880255644E+01, 0.1331348385339719E-11, 0.1193970905752580E-12, 0.1297718296516156E+00, 0.1123091600669640E+00, 0.1316891924708087E-01, 0.2151309995104528E-01, 0.1834712583930619E+00, 0.1313415638992297E+00, 0.1499428882618218E-04, 0.2659919745982362E-04, 0.2329940574932343E+00, 0.2023431757194558E+00, 0.7306255294378852E-05, 0.5255039029347846E-05, 0.1455357420299846E+00, 0.1148988981593422E+00, 0.1331348385339719E-11, 0.1193970905752580E-12, 0.8046649468928653E+00}, + tauOut: 4.9545335349736611E-002, + ttypeOut: -6, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1725633684689031E+01, 0.1775179019715018E+01, 0.2281824158451768E-09, 0.3237497126982006E-09, 0.1166700912395402E+01, 0.1216245907230254E+01, 0.2574031475886406E-06, 0.3407430674789675E-06, 0.8465944233583922E+00, 0.8813458462031728E+00, 0.1850774953630535E-01, 0.1479416990810367E-01, 0.9910504433419636E+00, 0.1059103528192370E+01, 0.5203164874187830E-10, 0.3563567162644001E-10, 0.1397487544853995E+01, 0.1447032880255644E+01, 0.9595353465813834E-14, 0.1193970905752580E-12, 0.8427692466826309E-01, 0.1123091600669640E+00, 0.3352713928531350E-01, 0.2151309995104528E-01, 0.4829568846163943E-01, 0.1313415638992297E+00, 0.1114419580100731E-03, 0.2659919745982362E-04, 0.1526916534507385E+00, 0.2023431757194558E+00, 0.3954362799871079E-05, 0.5255039029347846E-05, 0.6534960844680572E-01, 0.1148988981593422E+00, 0.9595353465813834E-14, 0.1193970905752580E-12}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 4.8269089264179610E-002, + dmin1: 4.8269089264179610E-002, + dmin2: 4.8269089264179610E-002, + dn: 6.5349608446805721E-002, + dn1: 0.15268639841170917, + dn2: 4.8269089264179610E-002, + tau: 4.9545335349736611E-002, + ttype: -6, + g: 0.49975000000000003, + zOut: []float64{0.1725633684689031E+01, 0.1775179019715018E+01, 0.2281824158451768E-09, 0.3237497126982006E-09, 0.1166700912395402E+01, 0.1216245907230254E+01, 0.2574031475886406E-06, 0.3407430674789675E-06, 0.8465944233583922E+00, 0.8813458462031728E+00, 0.1850774953630535E-01, 0.1479416990810367E-01, 0.9910504433419636E+00, 0.1059103528192370E+01, 0.5203164874187830E-10, 0.3563567162644001E-10, 0.1397487544853995E+01, 0.1447032880255644E+01, 0.9595353465813834E-14, 0.1193970905752580E-12, 0.8427692466826309E-01, 0.1123091600669640E+00, 0.3352713928531350E-01, 0.2151309995104528E-01, 0.4829568846163943E-01, 0.1313415638992297E+00, 0.1114419580100731E-03, 0.2659919745982362E-04, 0.1526916534507385E+00, 0.2023431757194558E+00, 0.3954362799871079E-05, 0.5255039029347846E-05, 0.6534960844680572E-01, 0.1148988981593422E+00, 0.9595353465813834E-14, 0.1193970905752580E-12}, + tauOut: 1.2037453975339630E-002, + ttypeOut: -5, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1725633684689031E+01, 0.1713596230941874E+01, 0.2281824158451768E-09, 0.1553578538234923E-09, 0.1166700912395402E+01, 0.1154663715667853E+01, 0.2574031475886406E-06, 0.1887268702969492E-06, 0.8465944233583922E+00, 0.8530645301924875E+00, 0.1850774953630535E-01, 0.2150143715280096E-01, 0.9910504433419636E+00, 0.9575115522658546E+00, 0.5203164874187830E-10, 0.7594016059954953E-10, 0.1397487544853995E+01, 0.1385450090802725E+01, 0.9595353465813834E-14, 0.5836853211617396E-15, 0.8427692466826309E-01, 0.1057666099782364E+00, 0.3352713928531350E-01, 0.1530933320323569E-01, 0.4829568846163943E-01, 0.2106034324107419E-01, 0.1114419580100731E-03, 0.8079762346493418E-03, 0.1526916534507385E+00, 0.1398501776035494E+00, 0.3954362799871079E-05, 0.1847806452993955E-05, 0.6534960844680572E-01, 0.5331030666501309E-01, 0.9595353465813834E-14, 0.5836853211617396E-15, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 2.0948901283064113E-002, + dmin1: 2.0948901283064113E-002, + dmin2: 2.0948901283064113E-002, + dn: 5.3310306665013088E-002, + dn1: 0.13984622324074955, + dn2: 2.0948901283064113E-002, + tau: 1.2037453975339630E-002, + ttype: -5, + g: 0.49975000000000003, + zOut: []float64{0.1725633684689031E+01, 0.1713596230941874E+01, 0.2281824158451768E-09, 0.1553578538234923E-09, 0.1166700912395402E+01, 0.1154663715667853E+01, 0.2574031475886406E-06, 0.1887268702969492E-06, 0.8465944233583922E+00, 0.8530645301924875E+00, 0.1850774953630535E-01, 0.2150143715280096E-01, 0.9910504433419636E+00, 0.9575115522658546E+00, 0.5203164874187830E-10, 0.7594016059954953E-10, 0.1397487544853995E+01, 0.1385450090802725E+01, 0.9595353465813834E-14, 0.5836853211617396E-15, 0.8427692466826309E-01, 0.1057666099782364E+00, 0.3352713928531350E-01, 0.1530933320323569E-01, 0.4829568846163943E-01, 0.2106034324107419E-01, 0.1114419580100731E-03, 0.8079762346493418E-03, 0.1526916534507385E+00, 0.1398501776035494E+00, 0.3954362799871079E-05, 0.1847806452993955E-05, 0.6534960844680572E-01, 0.5331030666501309E-01, 0.9595353465813834E-14, 0.5836853211617396E-15, 0.8046649468928653E+00}, + tauOut: 1.1070386405955311E-002, + ttypeOut: -5, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1702525844691276E+01, 0.1713596230941874E+01, 0.1053646717395619E-09, 0.1553578538234923E-09, 0.1143593517883403E+01, 0.1154663715667853E+01, 0.1407809649380857E-06, 0.1887268702969492E-06, 0.8634954401583683E+00, 0.8530645301924875E+00, 0.2384248197112572E-01, 0.2150143715280096E-01, 0.9225986839647138E+00, 0.9575115522658546E+00, 0.1140379931457212E-09, 0.7594016059954953E-10, 0.1374379704282732E+01, 0.1385450090802725E+01, 0.4491802194179927E-16, 0.5836853211617396E-15, 0.1100055567755167E+00, 0.1057666099782364E+00, 0.2930941140637693E-02, 0.1530933320323569E-01, 0.7866991929130526E-02, 0.2106034324107419E-01, 0.1436325611276508E-01, 0.8079762346493418E-03, 0.1144183828912820E+00, 0.1398501776035494E+00, 0.8609379557504958E-06, 0.1847806452993955E-05, 0.4223905932110202E-01, 0.5331030666501309E-01, 0.4491802194179927E-16, 0.5836853211617396E-15}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 7.0590156944811844E-003, + dmin1: 7.0590156944811844E-003, + dmin2: 7.0590156944811844E-003, + dn: 4.2239059321102022E-002, + dn1: 0.11441653508482905, + dn2: 7.0590156944811844E-003, + tau: 1.1070386405955311E-002, + ttype: -5, + g: 0.49975000000000003, + zOut: []float64{0.1702525844691276E+01, 0.1713596230941874E+01, 0.1053646717395619E-09, 0.1553578538234923E-09, 0.1143593517883403E+01, 0.1154663715667853E+01, 0.1407809649380857E-06, 0.1887268702969492E-06, 0.8634954401583683E+00, 0.8530645301924875E+00, 0.2384248197112572E-01, 0.2150143715280096E-01, 0.9225986839647138E+00, 0.9575115522658546E+00, 0.1140379931457212E-09, 0.7594016059954953E-10, 0.1374379704282732E+01, 0.1385450090802725E+01, 0.4491802194179927E-16, 0.5836853211617396E-15, 0.1100055567755167E+00, 0.1057666099782364E+00, 0.2930941140637693E-02, 0.1530933320323569E-01, 0.7866991929130526E-02, 0.2106034324107419E-01, 0.1436325611276508E-01, 0.8079762346493418E-03, 0.1144183828912820E+00, 0.1398501776035494E+00, 0.8609379557504958E-06, 0.1847806452993955E-05, 0.4223905932110202E-01, 0.5331030666501309E-01, 0.4491802194179927E-16, 0.5836853211617396E-15}, + tauOut: 5.5670727120955849E-003, + ttypeOut: -5, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1702525844691276E+01, 0.1696958772084545E+01, 0.1053646717395619E-09, 0.7100605954454643E-10, 0.1143593517883403E+01, 0.1138026585881266E+01, 0.1407809649380857E-06, 0.1068197551738174E-06, 0.8634954401583683E+00, 0.8817707425976433E+00, 0.2384248197112572E-01, 0.2494644177488929E-01, 0.9225986839647138E+00, 0.8920851695917670E+00, 0.1140379931457212E-09, 0.1756911880603681E-09, 0.1374379704282732E+01, 0.1368812631394945E+01, 0.4491802194179927E-16, 0.3609867340226789E-17, 0.1100055567755167E+00, 0.1073694252040588E+00, 0.2930941140637693E-02, 0.2147509894397918E-03, 0.7866991929130526E-02, 0.1644842434036023E-01, 0.1436325611276508E-01, 0.9991355423895336E-01, 0.1144183828912820E+00, 0.8938616878188867E-02, 0.8609379557504958E-06, 0.4068326216494222E-05, 0.4223905932110202E-01, 0.3666791828278994E-01, 0.4491802194179927E-16, 0.3609867340226789E-17, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 2.0851682275951503E-003, + dmin1: 2.0851682275951503E-003, + dmin2: 2.0851682275951503E-003, + dn: 3.6667918282789938E-002, + dn1: 8.9377559402331157E-003, + dn2: 2.0851682275951503E-003, + tau: 5.5670727120955849E-003, + ttype: -5, + g: 0.49975000000000003, + zOut: []float64{0.1702525844691276E+01, 0.1696958772084545E+01, 0.1053646717395619E-09, 0.7100605954454643E-10, 0.1143593517883403E+01, 0.1138026585881266E+01, 0.1407809649380857E-06, 0.1068197551738174E-06, 0.8634954401583683E+00, 0.8817707425976433E+00, 0.2384248197112572E-01, 0.2494644177488929E-01, 0.9225986839647138E+00, 0.8920851695917670E+00, 0.1140379931457212E-09, 0.1756911880603681E-09, 0.1374379704282732E+01, 0.1368812631394945E+01, 0.4491802194179927E-16, 0.3609867340226789E-17, 0.1100055567755167E+00, 0.1073694252040588E+00, 0.2930941140637693E-02, 0.2147509894397918E-03, 0.7866991929130526E-02, 0.1644842434036023E-01, 0.1436325611276508E-01, 0.9991355423895336E-01, 0.1144183828912820E+00, 0.8938616878188867E-02, 0.8609379557504958E-06, 0.4068326216494222E-05, 0.4223905932110202E-01, 0.3666791828278994E-01, 0.4491802194179927E-16, 0.3609867340226789E-17, 0.8046649468928653E+00}, + tauOut: 1.1659821590613959E-003, + ttypeOut: -5, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695792789996490E+01, 0.1696958772084545E+01, 0.4765133098633433E-10, 0.7100605954454643E-10, 0.1136860710494309E+01, 0.1138026585881266E+01, 0.8285142935651389E-07, 0.1068197551738174E-06, 0.9055511193620417E+00, 0.8817707425976433E+00, 0.2457547703893446E-01, 0.2494644177488929E-01, 0.8663437105694624E+00, 0.8920851695917670E+00, 0.2775899617066991E-09, 0.1756911880603681E-09, 0.1367646648958294E+01, 0.1368812631394945E+01, 0.2833987723936393E-18, 0.3609867340226789E-17, 0.1064181940344372E+00, 0.1073694252040588E+00, 0.3319277717374952E-04, 0.2147509894397918E-03, 0.1151628036430784E+00, 0.1644842434036023E-01, 0.7755012504281143E-02, 0.9991355423895336E-01, 0.2169054106282214E-04, 0.8938616878188867E-02, 0.6877516463147774E-02, 0.4068326216494222E-05, 0.2862441966058077E-01, 0.3666791828278994E-01, 0.2833987723936393E-18, 0.3609867340226789E-17}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 1.7622214846327918E-005, + dmin1: 1.7622214846327918E-005, + dmin2: 1.5249249404125084E-002, + dn: 2.8624419660580765E-002, + dn1: 1.7622214846327918E-005, + dn2: 1.5249249404125084E-002, + tau: 1.1659821590613959E-003, + ttype: -5, + g: 0.49975000000000003, + zOut: []float64{0.1695792789996490E+01, 0.1696958772084545E+01, 0.4765133098633433E-10, 0.7100605954454643E-10, 0.1136860710494309E+01, 0.1138026585881266E+01, 0.8285142935651389E-07, 0.1068197551738174E-06, 0.9055511193620417E+00, 0.8817707425976433E+00, 0.2457547703893446E-01, 0.2494644177488929E-01, 0.8663437105694624E+00, 0.8920851695917670E+00, 0.2775899617066991E-09, 0.1756911880603681E-09, 0.1367646648958294E+01, 0.1368812631394945E+01, 0.2833987723936393E-18, 0.3609867340226789E-17, 0.1064181940344372E+00, 0.1073694252040588E+00, 0.3319277717374952E-04, 0.2147509894397918E-03, 0.1151628036430784E+00, 0.1644842434036023E-01, 0.7755012504281143E-02, 0.9991355423895336E-01, 0.2169054106282214E-04, 0.8938616878188867E-02, 0.6877516463147774E-02, 0.4068326216494222E-05, 0.2862441966058077E-01, 0.3666791828278994E-01, 0.2833987723936393E-18, 0.3609867340226789E-17}, + tauOut: 1.2076215031173109E-005, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695792789996490E+01, 0.1695780713829110E+01, 0.4765133098633433E-10, 0.3194571418305606E-10, 0.1136860710494309E+01, 0.1136848717098761E+01, 0.8285142935651389E-07, 0.6599488873594650E-07, 0.9055511193620417E+00, 0.9301144541910563E+00, 0.2457547703893446E-01, 0.2289052693567938E-01, 0.8663437105694624E+00, 0.8434411076963417E+00, 0.2775899617066991E-09, 0.4501143914475995E-09, 0.1367646648958294E+01, 0.1367634572293148E+01, 0.2833987723936393E-18, 0.2205178646452290E-19, 0.1064181940344372E+00, 0.1064393105965798E+00, 0.3319277717374952E-04, 0.3591317210346347E-04, 0.1151628036430784E+00, 0.1228698267602250E+00, 0.7755012504281143E-02, 0.1369013219942635E-05, 0.2169054106282214E-04, 0.6885761775959480E-02, 0.6877516463147774E-02, 0.2859014352646020E-01, 0.2862441966058077E-01, 0.2219991908939190E-04, 0.2833987723936393E-18, 0.2205178646452290E-19, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 8.2453128117063980E-006, + dmin1: 8.2453128117063980E-006, + dmin2: 0.10640611781940604, + dn: 2.2199919089391903E-005, + dn1: 8.2453128117063980E-006, + dn2: 0.11511481425594380, + tau: 1.2076215031173109E-005, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1695792789996490E+01, 0.1695780713829110E+01, 0.4765133098633433E-10, 0.3194571418305606E-10, 0.1136860710494309E+01, 0.1136848717098761E+01, 0.8285142935651389E-07, 0.6599488873594650E-07, 0.9055511193620417E+00, 0.9301144541910563E+00, 0.2457547703893446E-01, 0.2289052693567938E-01, 0.8663437105694624E+00, 0.8434411076963417E+00, 0.2775899617066991E-09, 0.4501143914475995E-09, 0.1367646648958294E+01, 0.1367634572293148E+01, 0.2833987723936393E-18, 0.2205178646452290E-19, 0.1064181940344372E+00, 0.1064393105965798E+00, 0.3319277717374952E-04, 0.3591317210346347E-04, 0.1151628036430784E+00, 0.1228698267602250E+00, 0.7755012504281143E-02, 0.1369013219942635E-05, 0.2169054106282214E-04, 0.6885761775959480E-02, 0.6877516463147774E-02, 0.2859014352646020E-01, 0.2862441966058077E-01, 0.2219991908939190E-04, 0.2833987723936393E-18, 0.2205178646452290E-19, 0.8046649468928653E+00}, + tauOut: 3.2770273787704380E-006, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695777436833677E+01, 0.1695780713829110E+01, 0.2141639781080129E-10, 0.3194571418305606E-10, 0.1136845506044855E+01, 0.1136848717098761E+01, 0.5399396803668456E-07, 0.6599488873594650E-07, 0.9530016501053890E+00, 0.9301144541910563E+00, 0.2025894854667596E-01, 0.2289052693567938E-01, 0.8231788825724013E+00, 0.8434411076963417E+00, 0.7478228806194929E-09, 0.4501143914475995E-09, 0.1367631294517947E+01, 0.1367634572293148E+01, 0.1716235185693175E-20, 0.2205178646452290E-19, 0.1064719467413045E+00, 0.1064393105965798E+00, 0.4144420544393849E-04, 0.3591317210346347E-04, 0.1228264745406222E+00, 0.1228698267602250E+00, 0.7674810284932935E-07, 0.1369013219942635E-05, 0.3547255152693805E-01, 0.6885761775959480E-02, 0.1789267604726782E-04, 0.2859014352646020E-01, 0.1030215663353646E-05, 0.2219991908939190E-04, 0.1716235185693175E-20, 0.2205178646452290E-19}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 1.0302156633536465E-006, + dmin1: 6.8824080004778604E-003, + dmin2: 0.10643603356920101, + dn: 1.0302156633536465E-006, + dn1: 6.8824080004778604E-003, + dn2: 0.12282510552740224, + tau: 3.2770273787704380E-006, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1695777436833677E+01, 0.1695780713829110E+01, 0.2141639781080129E-10, 0.3194571418305606E-10, 0.1136845506044855E+01, 0.1136848717098761E+01, 0.5399396803668456E-07, 0.6599488873594650E-07, 0.9530016501053890E+00, 0.9301144541910563E+00, 0.2025894854667596E-01, 0.2289052693567938E-01, 0.8231788825724013E+00, 0.8434411076963417E+00, 0.7478228806194929E-09, 0.4501143914475995E-09, 0.1367631294517947E+01, 0.1367634572293148E+01, 0.1716235185693175E-20, 0.2205178646452290E-19, 0.1064719467413045E+00, 0.1064393105965798E+00, 0.4144420544393849E-04, 0.3591317210346347E-04, 0.1228264745406222E+00, 0.1228698267602250E+00, 0.7674810284932935E-07, 0.1369013219942635E-05, 0.3547255152693805E-01, 0.6885761775959480E-02, 0.1789267604726782E-04, 0.2859014352646020E-01, 0.1030215663353646E-05, 0.2219991908939190E-04, 0.1716235185693175E-20, 0.2205178646452290E-19}, + tauOut: 1.0296962592568820E-006, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695777436833677E+01, 0.1695776407158834E+01, 0.2141639781080129E-10, 0.1435751523850387E-10, 0.1136845506044855E+01, 0.1136844530328206E+01, 0.5399396803668456E-07, 0.4526242530264241E-07, 0.9530016501053890E+00, 0.9732595236933804E+00, 0.2025894854667596E-01, 0.1713493494875720E-01, 0.8231788825724013E+00, 0.8060429186752077E+00, 0.7478228806194929E-09, 0.1268848035998799E-08, 0.1367631294517947E+01, 0.1367630263552839E+01, 0.1716235185693175E-20, 0.1336113320657127E-21, 0.1064719467413045E+00, 0.1065123612504892E+00, 0.4144420544393849E-04, 0.4779206455525695E-04, 0.1228264745406222E+00, 0.1227777295279105E+00, 0.7674810284932935E-07, 0.2217381803186623E-07, 0.3547255152693805E-01, 0.3548939233290803E-01, 0.1789267604726782E-04, 0.5194035150079302E-09, 0.1030215663353646E-05, 0.5817566277343568E-15, 0.1716235185693175E-20, 0.1336113320657127E-21, 0.8046649468928653E+00}, + i0: 1, + n0: 9, + pp: 1, + n0in: 9, + dmin: 5.8175662773435680E-016, + dmin1: 3.5471499656860764E-002, + dmin2: 0.10647091704504522, + dn: 5.8175662773435680E-016, + dn1: 3.5471499656860764E-002, + dn2: 0.12277765277980766, + tau: 1.0296962592568820E-006, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.1695777436833677E+01, 0.1695776407158834E+01, 0.2141639781080129E-10, 0.1435751523850387E-10, 0.1136845506044855E+01, 0.1136844530328206E+01, 0.5399396803668456E-07, 0.4526242530264241E-07, 0.9530016501053890E+00, 0.9732595236933804E+00, 0.2025894854667596E-01, 0.1713493494875720E-01, 0.8231788825724013E+00, 0.8060429186752077E+00, 0.7478228806194929E-09, 0.1268848035998799E-08, 0.1367631294517947E+01, 0.1367630263552839E+01, 0.1716235185693175E-20, 0.1336113320657127E-21, 0.1064719467413045E+00, 0.1065123612504892E+00, 0.4144420544393849E-04, 0.4779206455525695E-04, 0.1228264745406222E+00, 0.1227777295279105E+00, 0.7674810284932935E-07, 0.2217381803186623E-07, 0.3547255152693805E-01, 0.3548939233290803E-01, 0.1789267604726782E-04, 0.5194035150079302E-09, 0.1030215663353646E-05, 0.5817566277343568E-15, 0.1716235185693175E-20, 0.1336113320657127E-21, 0.8046649468928653E+00}, + tauOut: 5.8175661922007790E-016, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695776407173191E+01, 0.1695776407158834E+01, 0.9625244577618415E-11, 0.1435751523850387E-10, 0.1136844575581005E+01, 0.1136844530328206E+01, 0.3874943632355666E-07, 0.4526242530264241E-07, 0.9903944198927007E+00, 0.9732595236933804E+00, 0.1394544708652782E-01, 0.1713493494875720E-01, 0.7920974728575274E+00, 0.8060429186752077E+00, 0.2190784636165185E-08, 0.1268848035998799E-08, 0.1367630261362054E+01, 0.1367630263552839E+01, 0.1040577915698430E-22, 0.1336113320657127E-21, 0.1065601533150438E+00, 0.1065123612504892E+00, 0.5506562249584694E-04, 0.4779206455525695E-04, 0.1227226860792321E+00, 0.1227777295279105E+00, 0.6412305277798032E-08, 0.2217381803186623E-07, 0.3548938644000568E-01, 0.3548939233290803E-01, 0.8514276171981532E-23, 0.5194035150079302E-09, 0.2761013168273541E-29, 0.5817566277343568E-15, 0.1040577915698430E-22, 0.1336113320657127E-21}, + i0: 1, + n0: 9, + pp: 0, + n0in: 9, + dmin: 2.7610131682735413E-030, + dmin1: 3.5489385920602169E-002, + dmin2: 0.10651236125048857, + dn: 2.7610131682735413E-030, + dn1: 3.5489385920602169E-002, + dn2: 0.12272266390541409, + tau: 5.8175661922007790E-016, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.1695776407173191E+01, 0.1695776407158834E+01, 0.9625244577618415E-11, 0.1435751523850387E-10, 0.1136844575581005E+01, 0.1136844530328206E+01, 0.3874943632355666E-07, 0.4526242530264241E-07, 0.9903944198927007E+00, 0.9732595236933804E+00, 0.1394544708652782E-01, 0.1713493494875720E-01, 0.7920974728575274E+00, 0.8060429186752077E+00, 0.2190784636165185E-08, 0.1268848035998799E-08, 0.1367630261362054E+01, 0.1367630263552839E+01, 0.1040577915698430E-22, 0.1336113320657127E-21, 0.1065601533150438E+00, 0.1065123612504892E+00, 0.5506562249584694E-04, 0.4779206455525695E-04, 0.1227226860792321E+00, 0.1227777295279105E+00, 0.6412305277798032E-08, 0.2217381803186623E-07, 0.3548938644000568E-01, 0.3548939233290803E-01, 0.8514276171981532E-23, 0.5194035150079302E-09, 0.2761013168273541E-29, 0.5817566277343568E-15, 0.1040577915698430E-22, 0.1336113320657127E-21}, + tauOut: 2.7610131682735413E-030, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1695776407173191E+01, 0.1695776407182817E+01, 0.9625244577618415E-11, 0.6452741670633652E-11, 0.1136844575581005E+01, 0.1136844614323989E+01, 0.3874943632355666E-07, 0.3375767015588020E-07, 0.9903944198927007E+00, 0.1004339833221559E+01, 0.1394544708652782E-01, 0.1099842207759001E-01, 0.7920974728575274E+00, 0.7810990529707220E+00, 0.2190784636165185E-08, 0.3835855840755795E-08, 0.1367630261362054E+01, 0.1367630257526198E+01, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.1065601533150438E+00, 0.1066152189375397E+00, 0.5506562249584694E-04, 0.6338495733216447E-04, 0.1227226860792321E+00, 0.1226593075342052E+00, 0.6412305277798032E-08, 0.1855291575909163E-08, 0.3548938644000568E-01, 0.3548938458471410E-01, 0.8514276171981532E-23, 0.6623960630549781E-51, 0.9539342071687115E+00}, + i0: 1, + n0: 8, + pp: 1, + n0in: 9, + dmin: 2.7610131682735413E-030, + dmin1: 3.5489384584714102E-002, + dmin2: 0.10656015331504384, + dn: 2.7610131682735413E-030, + dn1: 3.5489384584714102E-002, + dn2: 0.12265930112189996, + tau: 0.0000000000000000, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.1695776407173191E+01, 0.1695776407182817E+01, 0.9625244577618415E-11, 0.6452741670633652E-11, 0.1136844575581005E+01, 0.1136844614323989E+01, 0.3874943632355666E-07, 0.3375767015588020E-07, 0.9903944198927007E+00, 0.1004339833221559E+01, 0.1394544708652782E-01, 0.1099842207759001E-01, 0.7920974728575274E+00, 0.7810990529707220E+00, 0.2190784636165185E-08, 0.3835855840755795E-08, 0.1367630261362054E+01, 0.1367630257526198E+01, 0.1040577915698430E-22, 0.8107757314001177E-24, 0.1065601533150438E+00, 0.1066152189375397E+00, 0.5506562249584694E-04, 0.6338495733216447E-04, 0.1227226860792321E+00, 0.1226593075342052E+00, 0.6412305277798032E-08, 0.1855291575909163E-08, 0.3548938644000568E-01, 0.3548938458471410E-01, 0.8514276171981532E-23, 0.6623960630549781E-51, 0.9539342071687115E+00}, + tauOut: 1.7744692292357051E-002, + ttypeOut: -9, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1678031714896912E+01, 0.1695776407182817E+01, 0.4371648372768990E-11, 0.6452741670633652E-11, 0.1119099955784930E+01, 0.1136844614323989E+01, 0.3029592900888367E-07, 0.3375767015588020E-07, 0.9975935327108624E+00, 0.1004339833221559E+01, 0.8611580555893368E-02, 0.1099842207759001E-01, 0.7547427839583274E+00, 0.7810990529707220E+00, 0.6950755439903452E-08, 0.3835855840755795E-08, 0.1349885558283086E+01, 0.1367630257526198E+01, 0.6403582257922030E-25, 0.8107757314001177E-24, 0.8893391160251481E-01, 0.1066152189375397E+00, 0.8742171388117141E-04, 0.6338495733216447E-04, 0.1048271953832586E+00, 0.1226593075342052E+00, 0.6281113981299557E-09, 0.1855291575909163E-08, 0.1774469166424565E-01, 0.3548938458471410E-01, 0.6403582257922030E-25, 0.8107757314001177E-24}, + i0: 1, + n0: 8, + pp: 0, + n0in: 8, + dmin: 1.7744691664245655E-002, + dmin1: 8.8870526645182649E-002, + dmin2: 8.8870526645182649E-002, + dn: 1.7744691664245655E-002, + dn1: 0.10482719352796703, + dn2: 8.8870526645182649E-002, + tau: 1.7744692292357051E-002, + ttype: -9, + g: 0.49975000000000003, + zOut: []float64{0.1678031714896912E+01, 0.1695776407182817E+01, 0.4371648372768990E-11, 0.6452741670633652E-11, 0.1119099955784930E+01, 0.1136844614323989E+01, 0.3029592900888367E-07, 0.3375767015588020E-07, 0.9975935327108624E+00, 0.1004339833221559E+01, 0.8611580555893368E-02, 0.1099842207759001E-01, 0.7547427839583274E+00, 0.7810990529707220E+00, 0.6950755439903452E-08, 0.3835855840755795E-08, 0.1349885558283086E+01, 0.1367630257526198E+01, 0.6403582257922030E-25, 0.8107757314001177E-24, 0.8893391160251481E-01, 0.1066152189375397E+00, 0.8742171388117141E-04, 0.6338495733216447E-04, 0.1048271953832586E+00, 0.1226593075342052E+00, 0.6281113981299557E-09, 0.1855291575909163E-08, 0.1774469166424565E-01, 0.3548938458471410E-01, 0.6403582257922030E-25, 0.8107757314001177E-24}, + tauOut: 1.7743283373674822E-002, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1678031714896912E+01, 0.1660288431527609E+01, 0.4371648372768990E-11, 0.2946663608425970E-11, 0.1119099955784930E+01, 0.1101356702704238E+01, 0.3029592900888367E-07, 0.2744162973950316E-07, 0.9975935327108624E+00, 0.9884618024514511E+00, 0.8611580555893368E-02, 0.6575396506892930E-02, 0.7547427839583274E+00, 0.7304241110285150E+00, 0.6950755439903452E-08, 0.1284558415558242E-07, 0.1349885558283086E+01, 0.1332142262063827E+01, 0.6403582257922030E-25, 0.4275036042946169E-26, 0.8893391160251481E-01, 0.7127804994272115E-01, 0.8742171388117141E-04, 0.1285693574547170E-03, 0.1048271953832586E+00, 0.8695534328024046E-01, 0.6281113981299557E-09, 0.1281766326273249E-09, 0.1774469166424565E-01, 0.1408162394200135E-05, 0.6403582257922030E-25, 0.4275036042946169E-26, 0.9539342071687115E+00}, + i0: 1, + n0: 8, + pp: 1, + n0in: 8, + dmin: 1.4081623942001353E-006, + dmin1: 7.1190628228839981E-002, + dmin2: 7.1190628228839981E-002, + dn: 1.4081623942001353E-006, + dn1: 8.6955342652129064E-002, + dn2: 7.1190628228839981E-002, + tau: 1.7743283373674822E-002, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1678031714896912E+01, 0.1660288431527609E+01, 0.4371648372768990E-11, 0.2946663608425970E-11, 0.1119099955784930E+01, 0.1101356702704238E+01, 0.3029592900888367E-07, 0.2744162973950316E-07, 0.9975935327108624E+00, 0.9884618024514511E+00, 0.8611580555893368E-02, 0.6575396506892930E-02, 0.7547427839583274E+00, 0.7304241110285150E+00, 0.6950755439903452E-08, 0.1284558415558242E-07, 0.1349885558283086E+01, 0.1332142262063827E+01, 0.6403582257922030E-25, 0.4275036042946169E-26, 0.8893391160251481E-01, 0.7127804994272115E-01, 0.8742171388117141E-04, 0.1285693574547170E-03, 0.1048271953832586E+00, 0.8695534328024046E-01, 0.6281113981299557E-09, 0.1281766326273249E-09, 0.1774469166424565E-01, 0.1408162394200135E-05, 0.6403582257922030E-25, 0.4275036042946169E-26, 0.9539342071687115E+00}, + tauOut: 1.4081069428512511E-006, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26, 0.7140521119323301E-01, 0.7127804994272115E-01, 0.1565683011922014E-03, 0.1285693574547170E-03, 0.8679736700028205E-01, 0.8695534328024046E-01, 0.2079481441878513E-14, 0.1281766326273249E-09, 0.5544926940271698E-10, 0.1408162394200135E-05, 0.1565683011922014E-03, 0.1285693574547170E-03}, + i0: 6, + n0: 8, + pp: 0, + n0in: 8, + dmin: 5.5449269402716976E-011, + dmin1: 7.1276641835778295E-002, + dmin2: 7.1276641835778295E-002, + dn: 5.5449269402716976E-011, + dn1: 8.6797366872105416E-002, + dn2: 7.1276641835778295E-002, + tau: 1.4081069428512511E-006, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26, 0.7140521119323301E-01, 0.7127804994272115E-01, 0.1565683011922014E-03, 0.1285693574547170E-03, 0.8679736700028205E-01, 0.8695534328024046E-01, 0.2079481441878513E-14, 0.1281766326273249E-09, 0.5544926940271698E-10, 0.1408162394200135E-05, 0.1565683011922014E-03, 0.1285693574547170E-03}, + tauOut: 5.5449260598506680E-011, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26, 0.7140521119323301E-01, 0.7156177943897596E-01, 0.1565683011922014E-03, 0.1899018778701386E-03, 0.8679736700028205E-01, 0.8660746506696473E-01, 0.2079481441878513E-14, 0.1331360138522907E-23, 0.5544926940271698E-10, 0.8804208964992894E-17, 0.1565683011922014E-03, 0.8679736700028205E-01, 0.9539342071687115E+00}, + i0: 6, + n0: 8, + pp: 1, + n0in: 8, + dmin: 8.8042089649928937E-018, + dmin1: 7.1405211137783753E-002, + dmin2: 7.1405211137783753E-002, + dn: 8.8042089649928937E-018, + dn1: 8.6607465066962652E-002, + dn2: 7.1405211137783753E-002, + tau: 5.5449260598506680E-011, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26, 0.7140521119323301E-01, 0.7156177943897596E-01, 0.1565683011922014E-03, 0.1899018778701386E-03, 0.8679736700028205E-01, 0.8660746506696473E-01, 0.2079481441878513E-14, 0.1331360138522907E-23, 0.5544926940271698E-10, 0.8804208964992894E-17, 0.1565683011922014E-03, 0.8679736700028205E-01, 0.9539342071687115E+00}, + tauOut: 8.8042089649574750E-018, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: -0.60723548073666500, + dmin1: 7.1561779438975959E-002, + dmin2: 7.1561779438975959E-002, + dn: 8.8042089649928937E-018, + dn1: 8.6378245068883266E-002, + dn2: 7.1561779438975959E-002, + tau: 0.0000000000000000, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.1660287023423613E+01, 0.1660288431527609E+01, 0.1954678721190348E-11, 0.2946663608425970E-11, 0.1101355322036970E+01, 0.1101356702704238E+01, 0.2462874809952034E-07, 0.2744162973950316E-07, 0.9950357662226532E+00, 0.9884618024514511E+00, 0.4826789459478154E-02, 0.6575396506892930E-02, 0.7255959263076781E+00, 0.7304241110285150E+00, 0.2358357443050565E-07, 0.1284558415558242E-07, 0.1332140830373310E+01, 0.1332142262063827E+01, -0.9894235909416862E+00, 0.4275036042946169E-26}, + tauOut: 0.60723548073666500, + ttypeOut: -1, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.1660287023423613E+01, 0.1053051542688903E+01, 0.1954678721190348E-11, 0.2044340400431280E-11, 0.1101355322036970E+01, 0.4941198659270088E+00, 0.2462874809952034E-07, 0.4959623550114665E-07, 0.9950357662226532E+00, 0.3926270253492309E+00, 0.4826789459478154E-02, 0.8920167341580701E-02, 0.7255959263076781E+00, 0.1094403018130068E+00, 0.2358357443050565E-07, 0.2870664819501689E-06, 0.1332140830373310E+01, 0.7249050625701626E+00, -0.9894235909416862E+00, 0.2044340400431280E-11, 0.1077066053646038E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 0.10944027822943236, + dmin1: 0.10944027822943236, + dmin2: 0.38780023588975276, + dn: 0.72490506257016263, + dn1: 0.10944027822943236, + dn2: 0.38780023588975276, + tau: 0.60723548073666500, + ttype: -1, + g: 0.49975000000000003, + zOut: []float64{0.1660287023423613E+01, 0.1053051542688903E+01, 0.1954678721190348E-11, 0.2044340400431280E-11, 0.1101355322036970E+01, 0.4941198659270088E+00, 0.2462874809952034E-07, 0.4959623550114665E-07, 0.9950357662226532E+00, 0.3926270253492309E+00, 0.4826789459478154E-02, 0.8920167341580701E-02, 0.7255959263076781E+00, 0.1094403018130068E+00, 0.2358357443050565E-07, 0.2870664819501689E-06, 0.1332140830373310E+01, 0.7249050625701626E+00, -0.9894235909416862E+00, 0.2044340400431280E-11, 0.1077066053646038E+01}, + tauOut: 9.0381042476589277E-002, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9626705002143580E+00, 0.1053051542688903E+01, 0.1049319787347115E-11, 0.2044340400431280E-11, 0.4037388730456057E+00, 0.4941198659270088E+00, 0.4823122991958101E-07, 0.4959623550114665E-07, 0.3111661019829924E+00, 0.3926270253492309E+00, 0.3137314122148422E-02, 0.8920167341580701E-02, 0.1592223228075105E-01, 0.1094403018130068E+00, 0.1306952080528672E-04, 0.2870664819501689E-06, 0.6345109505727681E+00, 0.7249050625701626E+00, 0.1049319787347115E-11, 0.2044340400431280E-11}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: 1.5921945214269095E-002, + dmin1: 1.5921945214269095E-002, + dmin2: 0.30224593464141175, + dn: 0.63451095057276807, + dn1: 1.5921945214269095E-002, + dn2: 0.30224593464141175, + tau: 9.0381042476589277E-002, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9626705002143580E+00, 0.1053051542688903E+01, 0.1049319787347115E-11, 0.2044340400431280E-11, 0.4037388730456057E+00, 0.4941198659270088E+00, 0.4823122991958101E-07, 0.4959623550114665E-07, 0.3111661019829924E+00, 0.3926270253492309E+00, 0.3137314122148422E-02, 0.8920167341580701E-02, 0.1592223228075105E-01, 0.1094403018130068E+00, 0.1306952080528672E-04, 0.2870664819501689E-06, 0.6345109505727681E+00, 0.7249050625701626E+00, 0.1049319787347115E-11, 0.2044340400431280E-11}, + tauOut: 1.4134050686447828E-002, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9626705002143580E+00, 0.9485364495289594E+00, 0.1049319787347115E-11, 0.4466366986934060E-12, 0.4037388730456057E+00, 0.3896048705899411E+00, 0.4823122991958101E-07, 0.3852088344069326E-07, 0.3111661019829924E+00, 0.3001693268978096E+00, 0.3137314122148422E-02, 0.1664162181618706E-03, 0.1592223228075105E-01, 0.1634834896946635E-02, 0.1306952080528672E-04, 0.5072533064458891E-02, 0.6345109505727681E+00, 0.6153043668218613E+00, 0.1049319787347115E-11, 0.4466366986934060E-12, 0.1077066053646038E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 1.6217653761413479E-003, + dmin1: 1.6217653761413479E-003, + dmin2: 0.29703201277566116, + dn: 0.61530436682186129, + dn1: 1.6217653761413479E-003, + dn2: 0.29703201277566116, + tau: 1.4134050686447828E-002, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9626705002143580E+00, 0.9485364495289594E+00, 0.1049319787347115E-11, 0.4466366986934060E-12, 0.4037388730456057E+00, 0.3896048705899411E+00, 0.4823122991958101E-07, 0.3852088344069326E-07, 0.3111661019829924E+00, 0.3001693268978096E+00, 0.3137314122148422E-02, 0.1664162181618706E-03, 0.1592223228075105E-01, 0.1634834896946635E-02, 0.1306952080528672E-04, 0.5072533064458891E-02, 0.6345109505727681E+00, 0.6153043668218613E+00, 0.1049319787347115E-11, 0.4466366986934060E-12, 0.1077066053646038E+01}, + tauOut: 1.5809617416939919E-003, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469554877877121E+00, 0.9485364495289594E+00, 0.1837592531426069E-12, 0.4466366986934060E-12, 0.3880239473689468E+00, 0.3896048705899411E+00, 0.2979915990315817E-07, 0.3852088344069326E-07, 0.2987547515751175E+00, 0.3001693268978096E+00, 0.9106567826436868E-06, 0.1664162181618706E-03, 0.5125495562928890E-02, 0.1634834896946635E-02, 0.6089463364253304E+00, 0.5072533064458891E-02, 0.4777068654836977E-02, 0.6153043668218613E+00, 0.1837592531426069E-12, 0.4466366986934060E-12}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: 5.2962498469998932E-005, + dmin1: 5.2962498469998932E-005, + dmin2: 0.29858833535695567, + dn: 4.7770686548369769E-003, + dn1: 5.2962498469998932E-005, + dn2: 0.29858833535695567, + tau: 1.5809617416939919E-003, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9469554877877121E+00, 0.9485364495289594E+00, 0.1837592531426069E-12, 0.4466366986934060E-12, 0.3880239473689468E+00, 0.3896048705899411E+00, 0.2979915990315817E-07, 0.3852088344069326E-07, 0.2987547515751175E+00, 0.3001693268978096E+00, 0.9106567826436868E-06, 0.1664162181618706E-03, 0.5125495562928890E-02, 0.1634834896946635E-02, 0.6089463364253304E+00, 0.5072533064458891E-02, 0.4777068654836977E-02, 0.6153043668218613E+00, 0.1837592531426069E-12, 0.4466366986934060E-12}, + tauOut: 4.7621670852039755E-005, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469554877877121E+00, 0.9469159823779022E+00, 0.1837592531426069E-12, 0.7530022947855128E-13, 0.3880239473689468E+00, 0.3879844717580378E+00, 0.2979915990315817E-07, 0.2294586835827609E-07, 0.2987547515751175E+00, 0.2987161338760382E+00, 0.9106567826436868E-06, 0.1562542751952015E-07, 0.5125495562928890E-02, 0.6140323109528382E+00, 0.6089463364253304E+00, 0.4737500623869755E-02, 0.4777068654836977E-02, 0.6262097360996939E-07, 0.1837592531426069E-12, 0.7530022947855128E-13, 0.1077066053646038E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 6.2620973609969386E-008, + dmin1: 5.0859745275077589E-003, + dmin2: 0.29871522321925559, + dn: 6.2620973609969386E-008, + dn1: 5.0859745275077589E-003, + dn2: 0.29871522321925559, + tau: 3.9505409993611756E-005, + ttype: -15, + g: 0.49975000000000003, + zOut: []float64{0.9469554877877121E+00, 0.9469159823779022E+00, 0.1837592531426069E-12, 0.7530022947855128E-13, 0.3880239473689468E+00, 0.3879844717580378E+00, 0.2979915990315817E-07, 0.2294586835827609E-07, 0.2987547515751175E+00, 0.2987161338760382E+00, 0.9106567826436868E-06, 0.1562542751952015E-07, 0.5125495562928890E-02, 0.6140323109528382E+00, 0.6089463364253304E+00, 0.4737500623869755E-02, 0.4777068654836977E-02, 0.6262097360996939E-07, 0.1837592531426069E-12, 0.7530022947855128E-13, 0.1077066053646038E+01}, + tauOut: 6.2141437994562936E-008, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469159202365395E+00, 0.9469159823779022E+00, 0.3085312975855001E-13, 0.7530022947855128E-13, 0.3879844325624373E+00, 0.3879844717580378E+00, 0.1766643326162244E-07, 0.2294586835827609E-07, 0.2987160696935945E+00, 0.2987161338760382E+00, 0.3211918722443868E-07, 0.1562542751952015E-07, 0.6187697173160828E+00, 0.6140323109528382E+00, 0.4794463808464251E-09, 0.4737500623869755E-02, 0.8923456002485611E-13, 0.6262097360996939E-07, 0.3085312975855001E-13, 0.7530022947855128E-13}, + i0: 1, + n0: 5, + pp: 0, + n0in: 5, + dmin: 8.9234560024856112E-014, + dmin1: 0.29871605406816698, + dmin2: 0.29871605406816698, + dn: 8.9234560024856112E-014, + dn1: 0.61403221669221297, + dn2: 0.29871605406816698, + tau: 6.2141437994562936E-008, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.9469159202365395E+00, 0.9469159823779022E+00, 0.3085312975855001E-13, 0.7530022947855128E-13, 0.3879844325624373E+00, 0.3879844717580378E+00, 0.1766643326162244E-07, 0.2294586835827609E-07, 0.2987160696935945E+00, 0.2987161338760382E+00, 0.3211918722443868E-07, 0.1562542751952015E-07, 0.6187697173160828E+00, 0.6140323109528382E+00, 0.4794463808464251E-09, 0.4737500623869755E-02, 0.8923456002485611E-13, 0.6262097360996939E-07, 0.3085312975855001E-13, 0.7530022947855128E-13}, + tauOut: 8.9232014685788963E-014, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469159202365395E+00, 0.9469159202364811E+00, 0.3085312975855001E-13, 0.1264160184270297E-13, 0.3879844325624373E+00, 0.3879844502287687E+00, 0.1766643326162244E-07, 0.1360169848638109E-07, 0.2987160696935945E+00, 0.2987160882109940E+00, 0.3211918722443868E-07, 0.6653267495003571E-07, 0.6187697173160828E+00, 0.6187696512627651E+00, 0.4794463808464251E-09, 0.6914234847011291E-22, 0.8923456002485611E-13, 0.2545269924803487E-17, 0.3085312975855001E-13, 0.1264160184270297E-13, 0.1077066053646038E+01}, + i0: 1, + n0: 5, + pp: 1, + n0in: 5, + dmin: 2.5452699248034865E-018, + dmin1: 0.29871605609180679, + dmin2: 0.29871605609180679, + dn: 2.5452699248034865E-018, + dn1: 0.61876965078331869, + dn2: 0.29871605609180679, + tau: 8.9232014685788963E-014, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9469159202365395E+00, 0.9469159202364811E+00, 0.3085312975855001E-13, 0.1264160184270297E-13, 0.3879844325624373E+00, 0.3879844502287687E+00, 0.1766643326162244E-07, 0.1360169848638109E-07, 0.2987160696935945E+00, 0.2987160882109940E+00, 0.3211918722443868E-07, 0.6653267495003571E-07, 0.6187697173160828E+00, 0.6187696512627651E+00, 0.4794463808464251E-09, 0.6914234847011291E-22, 0.8923456002485611E-13, 0.2545269924803487E-17, 0.3085312975855001E-13, 0.1264160184270297E-13, 0.1077066053646038E+01}, + tauOut: 2.5452699247759164E-018, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469159202364937E+00, 0.9469159202364811E+00, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.3879844638304620E+00, 0.3879844502287687E+00, 0.1047218779010850E-07, 0.1360169848638109E-07, 0.2987161442714811E+00, 0.2987160882109940E+00, 0.1378177941363543E-06, 0.6653267495003571E-07, 0.6187695134449710E+00, 0.6187696512627651E+00, 0.2844127518685707E-39, 0.6914234847011291E-22}, + i0: 1, + n0: 4, + pp: 0, + n0in: 5, + dmin: 2.5452699248034865E-018, + dmin1: 0.29871607773880621, + dmin2: 0.29871607773880621, + dn: 2.5452699248034865E-018, + dn1: 0.61876951344497100, + dn2: 0.29871607773880621, + tau: 0.0000000000000000, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.9469159202364937E+00, 0.9469159202364811E+00, 0.5179704803914515E-14, 0.1264160184270297E-13, 0.3879844638304620E+00, 0.3879844502287687E+00, 0.1047218779010850E-07, 0.1360169848638109E-07, 0.2987161442714811E+00, 0.2987160882109940E+00, 0.1378177941363543E-06, 0.6653267495003571E-07, 0.6187695134449710E+00, 0.6187696512627651E+00, 0.2844127518685707E-39, 0.6914234847011291E-22}, + tauOut: 7.4679019434701552E-002, + ttypeOut: -9, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.9469159202364937E+00, 0.8722369008017974E+00, 0.5179704803914515E-14, 0.2304012808102351E-14, 0.3879844638304620E+00, 0.3133054548679459E+00, 0.1047218779010850E-07, 0.9984542273822185E-08, 0.2987161442714811E+00, 0.2240372526700314E+00, 0.1378177941363543E-06, 0.3806395963416417E-06, 0.6187695134449710E+00, 0.5440901133706730E+00, 0.2844127518685707E-39, 0.2304012808102351E-14, 0.1702794694134603E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 0.22403711485223726, + dmin1: 0.22403711485223726, + dmin2: 0.31330544439575814, + dn: 0.54409011337067303, + dn1: 0.22403711485223726, + dn2: 0.31330544439575814, + tau: 7.4679019434701552E-002, + ttype: -9, + g: 0.49975000000000003, + zOut: []float64{0.9469159202364937E+00, 0.8722369008017974E+00, 0.5179704803914515E-14, 0.2304012808102351E-14, 0.3879844638304620E+00, 0.3133054548679459E+00, 0.1047218779010850E-07, 0.9984542273822185E-08, 0.2987161442714811E+00, 0.2240372526700314E+00, 0.1378177941363543E-06, 0.3806395963416417E-06, 0.6187695134449710E+00, 0.5440901133706730E+00, 0.2844127518685707E-39, 0.2304012808102351E-14, 0.1702794694134603E+01}, + tauOut: 0.22392121955733330, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6483156812444665E+00, 0.8722369008017974E+00, 0.1113438717814820E-14, 0.2304012808102351E-14, 0.8938424529515379E-01, 0.3133054548679459E+00, 0.2502576838690600E-07, 0.9984542273822185E-08, 0.1163887265260836E-03, 0.2240372526700314E+00, 0.1779401212715201E-02, 0.3806395963416417E-06, 0.3183894926006245E+00, 0.5440901133706730E+00, 0.1113438717814820E-14, 0.2304012808102351E-14}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 1.1600808692974196E-004, + dmin1: 1.1600808692974196E-004, + dmin2: 8.9384235310611515E-002, + dn: 0.31838949260062449, + dn1: 1.1600808692974196E-004, + dn2: 8.9384235310611515E-002, + tau: 0.22392121955733330, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6483156812444665E+00, 0.8722369008017974E+00, 0.1113438717814820E-14, 0.2304012808102351E-14, 0.8938424529515379E-01, 0.3133054548679459E+00, 0.2502576838690600E-07, 0.9984542273822185E-08, 0.1163887265260836E-03, 0.2240372526700314E+00, 0.1779401212715201E-02, 0.3806395963416417E-06, 0.3183894926006245E+00, 0.5440901133706730E+00, 0.1113438717814820E-14, 0.2304012808102351E-14}, + tauOut: 1.1589031543524988E-004, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6483156812444665E+00, 0.6482265310101248E+00, 0.1113438717814820E-14, 0.1535325610927932E-15, 0.8938424529515379E-01, 0.8929512008657929E-01, 0.2502576838690600E-07, 0.3261899765703413E-10, 0.1163887265260836E-03, 0.1806639672279546E-02, 0.1779401212715201E-02, 0.3135891777105103E+00, 0.3183894926006245E+00, 0.4711164655771408E-02, 0.1113438717814820E-14, 0.1535325610927932E-15, 0.1702794694134603E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 2.7238459564345061E-005, + dmin1: 2.7238459564345061E-005, + dmin2: 8.9295095060810903E-002, + dn: 4.7111646557714080E-003, + dn1: 2.7238459564345061E-005, + dn2: 8.9295095060810903E-002, + tau: 8.9150234342740890E-005, + ttype: -15, + g: 0.49975000000000003, + zOut: []float64{0.6483156812444665E+00, 0.6482265310101248E+00, 0.1113438717814820E-14, 0.1535325610927932E-15, 0.8938424529515379E-01, 0.8929512008657929E-01, 0.2502576838690600E-07, 0.3261899765703413E-10, 0.1163887265260836E-03, 0.1806639672279546E-02, 0.1779401212715201E-02, 0.3135891777105103E+00, 0.3183894926006245E+00, 0.4711164655771408E-02, 0.1113438717814820E-14, 0.1535325610927932E-15, 0.1702794694134603E+01}, + tauOut: 2.5005145741075717E-005, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6482015258643838E+00, 0.6482265310101248E+00, 0.2115037983241246E-16, 0.1535325610927932E-15, 0.8927011497345719E-01, 0.8929512008657929E-01, 0.6601400172354812E-12, 0.3261899765703413E-10, 0.3153708122363886E+00, 0.1806639672279546E-02, 0.4684549720964035E-02, 0.3135891777105103E+00, 0.1609789066298190E-05, 0.4711164655771408E-02, 0.2115037983241246E-16, 0.1535325610927932E-15}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 1.6097890662981897E-006, + dmin1: 1.7816345258783307E-003, + dmin2: 8.9270114940838197E-002, + dn: 1.6097890662981897E-006, + dn1: 1.7816345258783307E-003, + dn2: 8.9270114940838197E-002, + tau: 2.5005145741075717E-005, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6482015258643838E+00, 0.6482265310101248E+00, 0.2115037983241246E-16, 0.1535325610927932E-15, 0.8927011497345719E-01, 0.8929512008657929E-01, 0.6601400172354812E-12, 0.3261899765703413E-10, 0.3153708122363886E+00, 0.1806639672279546E-02, 0.4684549720964035E-02, 0.3135891777105103E+00, 0.1609789066298190E-05, 0.4711164655771408E-02, 0.2115037983241246E-16, 0.1535325610927932E-15}, + tauOut: 1.5862205428611591E-006, + ttypeOut: -2, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6482015258643838E+00, 0.6481999396438409E+00, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.8927011497345719E-01, 0.8926852875357447E-01, 0.6601400172354812E-12, 0.2332164496627946E-11, 0.3153708122363886E+00, 0.3200537757344777E+00, 0.4684549720964035E-02, 0.2356209328895529E-07, 0.1609789066298190E-05, 0.6430148075154844E-11, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.1702794694134603E+01}, + i0: 1, + n0: 4, + pp: 1, + n0in: 4, + dmin: 6.4301480751548441E-012, + dmin1: 8.9268528752914328E-002, + dmin2: 8.9268528752914328E-002, + dn: 6.4301480751548441E-012, + dn1: 0.31536922601351364, + dn2: 8.9268528752914328E-002, + tau: 1.5862205428611591E-006, + ttype: -2, + g: 0.49975000000000003, + zOut: []float64{0.6482015258643838E+00, 0.6481999396438409E+00, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.8927011497345719E-01, 0.8926852875357447E-01, 0.6601400172354812E-12, 0.2332164496627946E-11, 0.3153708122363886E+00, 0.3200537757344777E+00, 0.4684549720964035E-02, 0.2356209328895529E-07, 0.1609789066298190E-05, 0.6430148075154844E-11, 0.2115037983241246E-16, 0.2912830939801045E-17, 0.1702794694134603E+01}, + tauOut: 6.4283598105616478E-012, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6481999396374125E+00, 0.6481999396438409E+00, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.8926852874947827E-01, 0.8926852875357447E-01, 0.8361491594360282E-11, 0.2332164496627946E-11, 0.3200537992817811E+00, 0.3200537757344777E+00, 0.4733821287189426E-18, 0.2356209328895529E-07, 0.1787791211067534E-14, 0.6430148075154844E-11, 0.4011480356653261E-18, 0.2912830939801045E-17}, + i0: 1, + n0: 4, + pp: 0, + n0in: 4, + dmin: 1.7877912110675335E-015, + dmin1: 8.9268528747146109E-002, + dmin2: 8.9268528747146109E-002, + dn: 1.7877912110675335E-015, + dn1: 0.32005377571968785, + dn2: 8.9268528747146109E-002, + tau: 6.4283598105616478E-012, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6481999396374125E+00, 0.6481999396438409E+00, 0.4011480356653261E-18, 0.2912830939801045E-17, 0.8926852874947827E-01, 0.8926852875357447E-01, 0.8361491594360282E-11, 0.2332164496627946E-11, 0.3200537992817811E+00, 0.3200537757344777E+00, 0.4733821287189426E-18, 0.2356209328895529E-07, 0.1787791211067534E-14, 0.6430148075154844E-11, 0.4011480356653261E-18, 0.2912830939801045E-17}, + tauOut: 1.7877912088395813E-015, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6481999396374125E+00, 0.6481999396374107E+00, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.8926852874947827E-01, 0.8926852875783797E-01, 0.8361491594360282E-11, 0.2997839428604580E-10, 0.3200537992817811E+00, 0.3200537992518009E+00, 0.4733821287189426E-18, 0.2644269217171004E-32, 0.2001510674733695E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 4, + dmin: 2.2279522444840209E-024, + dmin1: 8.9268528749476481E-002, + dmin2: 8.9268528749476481E-002, + dn: 2.2279522444840209E-024, + dn1: 0.32005379925180094, + dn2: 8.9268528749476481E-002, + tau: 1.7877912088395813E-015, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6481999396374125E+00, 0.6481999396374107E+00, 0.4011480356653261E-18, 0.5524513774965514E-19, 0.8926852874947827E-01, 0.8926852875783797E-01, 0.8361491594360282E-11, 0.2997839428604580E-10, 0.3200537992817811E+00, 0.3200537992518009E+00, 0.4733821287189426E-18, 0.2644269217171004E-32, 0.2001510674733695E+01}, + tauOut: 2.2317132187369120E-002, + ttypeOut: -9, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6258828074500417E+00, 0.6481999396374107E+00, 0.7879513719234823E-20, 0.5524513774965514E-19, 0.6695139660044724E-01, 0.8926852875783797E-01, 0.1433084218388560E-09, 0.2997839428604580E-10, 0.2977366669211234E+00, 0.3200537992518009E+00, 0.8926852875783797E-01, 0.2644269217171004E-32}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 6.6951396570468849E-002, + dmin1: 6.6951396570468849E-002, + dmin2: 0.62588280745004166, + dn: 0.29773666692112338, + dn1: 6.6951396570468849E-002, + dn2: 0.62588280745004166, + tau: 2.2317132187369120E-002, + ttype: -9, + g: 0.49975000000000003, + zOut: []float64{0.6258828074500417E+00, 0.6481999396374107E+00, 0.7879513719234823E-20, 0.5524513774965514E-19, 0.6695139660044724E-01, 0.8926852875783797E-01, 0.1433084218388560E-09, 0.2997839428604580E-10, 0.2977366669211234E+00, 0.3200537992518009E+00, 0.8926852875783797E-01, 0.2644269217171004E-32}, + tauOut: 6.6950732596142107E-002, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.6258828074500417E+00, 0.5589320748538995E+00, 0.7879513719234823E-20, 0.9438435755776795E-21, 0.6695139660044724E-01, 0.6641476135588615E-06, 0.1433084218388560E-09, 0.6424501268835132E-04, 0.2977366669211234E+00, 0.2307216893122929E+00, 0.8926852875783797E-01, 0.6695139660044724E-01, 0.2001510674733695E+01}, + i0: 1, + n0: 3, + pp: 1, + n0in: 3, + dmin: 6.6400430513702258E-007, + dmin1: 6.6400430513702258E-007, + dmin2: 0.55893207485389951, + dn: 0.23072168931229292, + dn1: 6.6400430513702258E-007, + dn2: 0.55893207485389951, + tau: 6.6950732596142107E-002, + ttype: -4, + g: 0.49975000000000003, + zOut: []float64{0.6258828074500417E+00, 0.5589320748538995E+00, 0.7879513719234823E-20, 0.9438435755776795E-21, 0.6695139660044724E-01, 0.6641476135588615E-06, 0.1433084218388560E-09, 0.6424501268835132E-04, 0.2977366669211234E+00, 0.2307216893122929E+00, 0.8926852875783797E-01, 0.6695139660044724E-01, 0.2001510674733695E+01}, + tauOut: 6.6398937736467640E-007, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + { + z: []float64{0.5589315065851642E+00, 0.5589320748538995E+00, 0.1121517486324177E-26, 0.9438435755776795E-21, 0.6434089156657428E-04, 0.6641476135588615E-06, 0.2303778747300831E+00, 0.6424501268835132E-04, 0.3432463134744483E-03, 0.2307216893122929E+00, 0.6641476135588615E-06, 0.6695139660044724E-01}, + i0: 1, + n0: 3, + pp: 0, + n0in: 3, + dmin: 9.5878878222950548E-008, + dmin1: 9.5878878222950548E-008, + dmin2: 0.55893150658516422, + dn: 3.4324631347444829E-004, + dn1: 9.5878878222950548E-008, + dn2: 0.55893150658516422, + tau: 5.6826873533591094E-007, + ttype: -15, + g: 0.49975000000000003, + zOut: []float64{0.5589315065851642E+00, 0.5589320748538995E+00, 0.1121517486324177E-26, 0.9438435755776795E-21, 0.6434089156657428E-04, 0.6641476135588615E-06, 0.2303778747300831E+00, 0.6424501268835132E-04, 0.3432463134744483E-03, 0.2307216893122929E+00, 0.6641476135588615E-06, 0.6695139660044724E-01}, + tauOut: 9.4211902206835373E-008, + ttypeOut: -4, + gOut: 0.49975000000000003, + }, + } { + z := make([]float64, len(test.z)) + copy(z, test.z) + + // Print for fortran input + //printDlasq4FortranInput(test) + + i0 := test.i0 - 1 // zero index + n0 := test.n0 - 1 // zero index + n0in := test.n0in - 1 + + tauOut, ttypeOut, gOut := impl.Dlasq4(i0, n0, z, test.pp, n0in, test.dmin, test.dmin1, test.dmin2, test.dn, test.dn1, test.dn2, test.tau, test.ttype, test.g) + + if !floats.EqualApprox(z, test.zOut, dTol) { + t.Errorf("Z mismatch") + } + if !floats.EqualWithinAbsOrRel(tauOut, test.tauOut, dTol, dTol) { + t.Errorf("Case %d, wrong tau. Want %v, got %v", cas, test.tauOut, tauOut) + } + if ttypeOut != test.ttypeOut { + t.Errorf("Wrong ttype. Want %v, got %v", test.ttypeOut, ttypeOut) + } + if !floats.EqualWithinAbsOrRel(gOut, test.gOut, dTol, dTol) { + t.Errorf("Wrong g. Want %v, got %v", test.gOut, gOut) + } + } +} diff --git a/lapack/testlapack/dlasq5.go b/lapack/testlapack/dlasq5.go new file mode 100644 index 00000000..235b9b9e --- /dev/null +++ b/lapack/testlapack/dlasq5.go @@ -0,0 +1,1992 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlasq5er interface { + Dlasq5(i0, n0 int, z []float64, pp int, tau, sigma float64) (i0Out, n0Out, ppOut int, tauOut, sigmaOut, dmin, dmin1, dmin2, dn, dnm1, dnm2 float64) +} + +func Dlasq5Test(t *testing.T, impl Dlasq5er) { + dTol := 1e-14 + for _, test := range []struct { + z []float64 + i0, n0, pp int + tau, sigma float64 + + i0Out, n0Out, ppOut int + tauOut, sigmaOut float64 + dminOut, dmin1Out, dmin2Out float64 + dnOut, dnm1Out, dnm2Out float64 + }{ + { + z: []float64{0.1914365246180821E+01, 0.1564384297703890E+01, 0.2493389162143899E+00, 0.3499809484769305E+00, 0.1315996513131545E+01, 0.1363862112490627E+01, 0.9898466611970759E-01, 0.2014733168553078E+00, 0.6023973979587287E+00, 0.6465544792741794E+00, 0.2210033410638781E-02, 0.5482758480425683E-01, 0.9861857233678967E-01, 0.2428190810745492E-01, 0.4756321484454819E+00, 0.7654669763997353E-01, 0.2588748143677115E+00, 0.6127784069508770E+00, 0.1078611376690004E+00, 0.1217285558623164E+00, 0.6442896492255246E+00, 0.2293835804898155E+00, 0.6203230486639705E+00, 0.5227672064047094E+00, 0.3695660678607585E+00, 0.7645233184745865E+00, 0.5378838054252265E+00, 0.2253657980501426E+00, 0.3562533181264623E+00, 0.8820486722335483E+00, 0.2222132496436145E-01, 0.1208845131814035E-01, 0.1275094303021685E+01, 0.6548746852163357E+00, 0.1647324354821218E+00, 0.6424409427697111E+00, 0.1007530576543866E+01, 0.3269551736546701E+00, 0.3453881601783118E+00, 0.8453078383713172E+00, 0.2679391719153404E+00, 0.4116714838778281E+00, 0.7328677736683723E+00, 0.2016558482158241E+00, 0.8360828138307410E+00, 0.9737579452195326E+00, 0.4813660709592822E+00, 0.5951926422795808E+00, 0.6495370513676459E+00, 0.6761876248148171E+00, 0.2325475880222648E+00, 0.4547154975121112E+00, 0.1993624802893807E+00, 0.3321819367342255E+00, 0.3782318916911257E+00, 0.9972813157741996E-01, 0.9830449403503746E+00, 0.7561080996844842E+00, 0.4429733864040367E+00, 0.6051687323570161E+00, 0.1173279550602403E+01, 0.7195724480316686E+00, 0.5035524069144587E+00, 0.8966804889747714E+00, 0.3058980395058521E+00, 0.6588832353928662E+00, 0.3014634433415453E+00, 0.1505672110274446E+00, 0.1289422237567578E+01, 0.6124645310993601E+00, 0.7583364305799440E+00, 0.9784211498097629E+00, 0.4977814779461571E+00, 0.9993813577491869E+00, 0.2841468847862598E+00, 0.2567365507769143E+00, 0.9257539794205765E+00, 0.5509268385614666E+00, 0.5231355605450990E-04, 0.6589740256453697E+00, 0.2117869221381033E-04, 0.7349224826832024E-04, 0.0000000000000000E+00, 0.0000000000000000E+00}, + i0: 1, + n0: 21, + pp: 0, + tau: 0.0000000000000000, + sigma: 0.0000000000000000, + i0Out: 1, + n0Out: 21, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + dminOut: 2.1175426017541180E-005, + dmin1Out: 4.4311601260836921E-002, + dmin2Out: 4.4311601260836921E-002, + dnOut: 2.1175426017541180E-005, + dnm1Out: 0.33915960483100382, + dnm2Out: 0.16428924199195991, + }, + { + z: []float64{0.1914365246180821E+01, 0.2163704162395211E+01, 0.2493389162143899E+00, 0.1516515751224039E+00, 0.1315996513131545E+01, 0.1263329604128848E+01, 0.9898466611970759E-01, 0.4719916727467415E-01, 0.6023973979587287E+00, 0.5574082640946934E+00, 0.2210033410638781E-02, 0.3910066531356214E-03, 0.9861857233678967E-01, 0.5738597141291359E+00, 0.4756321484454819E+00, 0.2145632131068746E+00, 0.2588748143677115E+00, 0.1521727389298373E+00, 0.1078611376690004E+00, 0.4566771620366771E+00, 0.6442896492255246E+00, 0.8079355358528180E+00, 0.6203230486639705E+00, 0.2837483186776231E+00, 0.3695660678607585E+00, 0.6237015546083620E+00, 0.5378838054252265E+00, 0.3072349091217998E+00, 0.3562533181264623E+00, 0.7123973396902394E-01, 0.2222132496436145E-01, 0.3977314805803597E+00, 0.1275094303021685E+01, 0.1042095257923447E+01, 0.1647324354821218E+00, 0.1592685164190333E+00, 0.1007530576543866E+01, 0.1193650220303144E+01, 0.3453881601783118E+00, 0.7752942700755104E-01, 0.2679391719153404E+00, 0.9232775185761617E+00, 0.7328677736683723E+00, 0.6636554427529671E+00, 0.8360828138307410E+00, 0.6537934420370561E+00, 0.4813660709592822E+00, 0.4782322339990674E+00, 0.6495370513676459E+00, 0.4038524053908432E+00, 0.2325475880222648E+00, 0.1147975431483785E+00, 0.1993624802893807E+00, 0.4627968288321279E+00, 0.3782318916911257E+00, 0.8034172324482011E+00, 0.9830449403503746E+00, 0.6226010943062101E+00, 0.4429733864040367E+00, 0.8347746582554776E+00, 0.1173279550602403E+01, 0.8420572992613844E+00, 0.5035524069144587E+00, 0.1829278057427913E+00, 0.3058980395058521E+00, 0.4244336771046062E+00, 0.3014634433415453E+00, 0.9158407747236312E+00, 0.1289422237567578E+01, 0.1131917893423890E+01, 0.7583364305799440E+00, 0.3334922359541972E+00, 0.4977814779461571E+00, 0.4484361267782198E+00, 0.2841468847862598E+00, 0.5865943745895725E+00, 0.9257539794205765E+00, 0.3392119183870583E+00, 0.5231355605450990E-04, 0.3266196269153995E-08, 0.2117869221381033E-04, 0.2117542601754118E-04, 0.0000000000000000E+00, 0.3910066531356214E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + tau: 0.0000000000000000, + sigma: 0.0000000000000000, + i0Out: 1, + n0Out: 21, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + dminOut: 2.1175425069176302E-005, + dmin1Out: 2.9944624525135358E-002, + dmin2Out: 2.9944624525135358E-002, + dnOut: 2.1175425069176302E-005, + dnm1Out: 7.2928780948497918E-002, + dnm2Out: 0.16065460645225654, + }, + { + z: []float64{0.2315355737517615E+01, 0.2163704162395211E+01, 0.8274578340618610E-01, 0.1516515751224039E+00, 0.1227782987997336E+01, 0.1263329604128848E+01, 0.2142822156235013E-01, 0.4719916727467415E-01, 0.5363710491854788E+00, 0.5574082640946934E+00, 0.4183353417969536E-03, 0.3910066531356214E-03, 0.7880045918942136E+00, 0.5738597141291359E+00, 0.4143462125464707E-01, 0.2145632131068746E+00, 0.5674152797118673E+00, 0.1521727389298373E+00, 0.6502569120260687E+00, 0.4566771620366771E+00, 0.4414269425043723E+00, 0.8079355358528180E+00, 0.4009140594652070E+00, 0.2837483186776231E+00, 0.5300224042649548E+00, 0.6237015546083620E+00, 0.4129510944388858E-01, 0.3072349091217998E+00, 0.4276761051054951E+00, 0.7123973396902394E-01, 0.9691308092544145E+00, 0.3977314805803597E+00, 0.2322329650880660E+00, 0.1042095257923447E+01, 0.8186215063776209E+00, 0.1592685164190333E+00, 0.4525581409330741E+00, 0.1193650220303144E+01, 0.1581701233715052E+00, 0.7752942700755104E-01, 0.1428762837957623E+01, 0.9232775185761617E+00, 0.3036848136842134E+00, 0.6636554427529671E+00, 0.8283408623519102E+00, 0.6537934420370561E+00, 0.2331591338951825E+00, 0.4782322339990674E+00, 0.2854908146440392E+00, 0.4038524053908432E+00, 0.1860933389154074E+00, 0.1147975431483785E+00, 0.1080120722364922E+01, 0.4627968288321279E+00, 0.4631042046962229E+00, 0.8034172324482011E+00, 0.9942715478654648E+00, 0.6226010943062101E+00, 0.7069779837626068E+00, 0.8347746582554776E+00, 0.3180071212415688E+00, 0.8420572992613844E+00, 0.2441477440283845E+00, 0.1829278057427913E+00, 0.1096126707799853E+01, 0.4244336771046062E+00, 0.9457451890006905E+00, 0.9158407747236312E+00, 0.5196649403773971E+00, 0.1131917893423890E+01, 0.2877815203259632E+00, 0.3334922359541972E+00, 0.7472489810418290E+00, 0.4484361267782198E+00, 0.2662831374385604E+00, 0.5865943745895725E+00, 0.7292878421469419E-01, 0.3392119183870583E+00, 0.9483648767903632E-12, 0.3266196269153995E-08, 0.2117542506917630E-04, 0.2117542601754118E-04, 0.4183353417969536E-03, 0.3910066531356214E-03}, + i0: 1, + n0: 21, + pp: 0, + tau: 2.1175313795360271E-005, + sigma: 0.0000000000000000, + i0Out: 1, + n0Out: 21, + ppOut: 0, + tauOut: 2.1175313795360271E-005, + sigmaOut: 0.0000000000000000, + dminOut: 1.1127325659669794E-010, + dmin1Out: 3.1433071595911154E-002, + dmin2Out: 3.1433071595911154E-002, + dnOut: 1.1127325659669794E-010, + dnm1Out: 3.5896964560873705E-002, + dnm2Out: 0.25842281720128102, + }, + { + z: []float64{0.2315355737517615E+01, 0.2398080345610006E+01, 0.8274578340618610E-01, 0.4236466279397526E-01, 0.1227782987997336E+01, 0.1206825371451915E+01, 0.2142822156235013E-01, 0.9523728911788614E-02, 0.5363710491854788E+00, 0.5272444803016919E+00, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.7880045918942136E+00, 0.8287928057414093E+00, 0.4143462125464707E-01, 0.2836732781232222E-01, 0.5674152797118673E+00, 0.1189283688611819E+01, 0.6502569120260687E+00, 0.2413561400585997E+00, 0.4414269425043723E+00, 0.6009636865971842E+00, 0.4009140594652070E+00, 0.3535878097802652E+00, 0.5300224042649548E+00, 0.2177085286147829E+00, 0.4129510944388858E-01, 0.8112190955144877E-01, 0.4276761051054951E+00, 0.1315663829494665E+01, 0.9691308092544145E+00, 0.1710650671895379E+00, 0.2322329650880660E+00, 0.8797682289623537E+00, 0.8186215063776209E+00, 0.4211038940233675E+00, 0.4525581409330741E+00, 0.1896031949674164E+00, 0.1581701233715052E+00, 0.1191897606932286E+01, 0.1428762837957623E+01, 0.5405288693957555E+00, 0.3036848136842134E+00, 0.4653859482687157E+00, 0.8283408623519102E+00, 0.5960928726645816E+00, 0.2331591338951825E+00, 0.1116684901463164E+00, 0.2854908146440392E+00, 0.3598944880993349E+00, 0.1860933389154074E+00, 0.5585061130503639E+00, 0.1080120722364922E+01, 0.9846976386969850E+00, 0.4631042046962229E+00, 0.4676068229793028E+00, 0.9942715478654648E+00, 0.1233621533334973E+01, 0.7069779837626068E+00, 0.1822471700779458E+00, 0.3180071212415688E+00, 0.3798865198782122E+00, 0.2441477440283845E+00, 0.7044652781161848E+00, 0.1096126707799853E+01, 0.1337385443370563E+01, 0.9457451890006905E+00, 0.3674861422265960E+00, 0.5196649403773971E+00, 0.4399391431629689E+00, 0.2877815203259632E+00, 0.4888049885267526E+00, 0.7472489810418290E+00, 0.5247059546398414E+00, 0.2662831374385604E+00, 0.3701064434002514E-01, 0.7292878421469419E-01, 0.3589696456182207E-01, 0.9483648767903632E-12, 0.5594353069081231E-15, 0.2117542506917630E-04, 0.1112732565966979E-09, 0.4183353417969536E-03, 0.6252320936560726E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + tau: 2.1175313795360271E-005, + sigma: 2.1175313795360271E-005, + i0Out: 1, + n0Out: 21, + ppOut: 1, + tauOut: 2.1175313795360271E-005, + sigmaOut: 2.1175313795360271E-005, + dminOut: -2.1175202522103674E-005, + dmin1Out: 2.9116497146097618E-002, + dmin2Out: 4.9396687496051764E-002, + dnOut: -2.1175202522103674E-005, + dnm1Out: 2.9116497146097618E-002, + dnm2Out: 0.15954393093937583, + }, + { + z: []float64{0.2440423833090186E+01, 0.2398080345610006E+01, 0.2094994698033050E-01, 0.4236466279397526E-01, 0.1195377978069578E+01, 0.1206825371451915E+01, 0.4200624064314086E-02, 0.9523728911788614E-02, 0.5236479130172386E+00, 0.5272444803016919E+00, 0.9895730475750664E-03, 0.6252320936560726E-03, 0.8561493851923613E+00, 0.8287928057414093E+00, 0.3940527300515336E-01, 0.2836732781232222E-01, 0.1391213380351470E+01, 0.1189283688611819E+01, 0.1042588274099539E+00, 0.2413561400585997E+00, 0.8502714936537001E+00, 0.6009636865971842E+00, 0.9053470847599347E-01, 0.3535878097802652E+00, 0.2082745543764428E+00, 0.2177085286147829E+00, 0.5124445590385125E+00, 0.8112190955144877E-01, 0.9742631623318954E+00, 0.1315663829494665E+01, 0.1544732645319877E+00, 0.1710650671895379E+00, 0.1146377683139938E+01, 0.8797682289623537E+00, 0.6964776521238716E-01, 0.4211038940233675E+00, 0.1311831861373520E+01, 0.1896031949674164E+00, 0.4911110065859084E+00, 0.1191897606932286E+01, 0.5147826357647675E+00, 0.5405288693957555E+00, 0.5388939477127089E+00, 0.4653859482687157E+00, 0.1688462397843937E+00, 0.5960928726645816E+00, 0.2380205454936569E+00, 0.1116684901463164E+00, 0.6803588803422466E+00, 0.3598944880993349E+00, 0.8083375797812383E+00, 0.5585061130503639E+00, 0.6439457065812542E+00, 0.9846976386969850E+00, 0.8958050967125053E+00, 0.4676068229793028E+00, 0.5200424313866183E+00, 0.1233621533334973E+01, 0.1331299890548604E+00, 0.1822471700779458E+00, 0.9512006336257413E+00, 0.3798865198782122E+00, 0.9904762202705547E+00, 0.7044652781161848E+00, 0.7143741900128092E+00, 0.1337385443370563E+01, 0.2263121215682984E+00, 0.3674861422265960E+00, 0.7024108348076278E+00, 0.4399391431629689E+00, 0.3651408483866702E+00, 0.4888049885267526E+00, 0.1965545752794010E+00, 0.5247059546398414E+00, 0.6759292101929097E-02, 0.3701064434002514E-01, 0.2911649714609818E-01, 0.3589696456182207E-01, 0.2137969692662087E-23, 0.5594353069081231E-15, -0.2117520252210367E-04, 0.1112732565966979E-09, 0.9895730475750664E-03, 0.6252320936560726E-03, 0.1037537856266618 - 321}, + i0: 1, + n0: 21, + pp: 1, + tau: 1.1127325659669789E-010, + sigma: 2.1175313795360271E-005, + i0Out: 1, + n0Out: 21, + ppOut: 1, + tauOut: 1.1127325659669789E-010, + sigmaOut: 2.1175313795360271E-005, + dminOut: -2.0808762284537102E-024, + dmin1Out: 2.9139336744737766E-002, + dmin2Out: 4.9426557292086552E-002, + dnOut: -2.0808762284537102E-024, + dnm1Out: 2.9139336744737766E-002, + dnm2Out: 0.15959234211062134, + }, + { + z: []float64{0.2440445008292708E+01, 0.2398080345610006E+01, 0.2094976520226600E-01, 0.4236466279397526E-01, 0.1195399335050165E+01, 0.1206825371451915E+01, 0.4200549016048655E-02, 0.9523728911788614E-02, 0.5236691632680260E+00, 0.5272444803016919E+00, 0.9895328911616120E-03, 0.6252320936560726E-03, 0.8561706005512968E+00, 0.8287928057414093E+00, 0.3940429656773515E-01, 0.2836732781232222E-01, 0.1391235531991410E+01, 0.1189283688611819E+01, 0.1042571673718422E+00, 0.2413561400585997E+00, 0.8502943288943339E+00, 0.6009636865971842E+00, 0.9053227710395735E-01, 0.3535878097802652E+00, 0.2082981609510011E+00, 0.2177085286147829E+00, 0.5123864833424303E+00, 0.8112190955144877E-01, 0.9743424132304999E+00, 0.1315663829494665E+01, 0.1544607000116935E+00, 0.1710650671895379E+00, 0.1146411422862754E+01, 0.8797682289623537E+00, 0.6964571542795012E-01, 0.4211038940233675E+00, 0.1311855086360479E+01, 0.1896031949674164E+00, 0.4911023119923957E+00, 0.1191897606932286E+01, 0.5148125055608023E+00, 0.5405288693957555E+00, 0.5388626806938843E+00, 0.4653859482687157E+00, 0.1688986820057405E+00, 0.5960928726645816E+00, 0.2379466412690434E+00, 0.1116684901463164E+00, 0.6804539597693821E+00, 0.3598944880993349E+00, 0.8082246312519304E+00, 0.5585061130503639E+00, 0.6440798303130841E+00, 0.9846976386969850E+00, 0.8956185534970393E+00, 0.4676068229793028E+00, 0.5202501498046066E+00, 0.1233621533334973E+01, 0.1330768347199243E+00, 0.1822471700779458E+00, 0.9512749631631994E+00, 0.3798865198782122E+00, 0.9903988276741268E+00, 0.7044652781161848E+00, 0.7144727578117591E+00, 0.1337385443370563E+01, 0.2262808998212762E+00, 0.3674861422265960E+00, 0.7024632317571722E+00, 0.4399391431629689E+00, 0.3651136124179467E+00, 0.4888049885267526E+00, 0.1966029864506465E+00, 0.5247059546398414E+00, 0.6757627705811050E-02, 0.3701064434002514E-01, 0.2913933674473832E-01, 0.3589696456182207E-01, 0.2136293938333395E-23, 0.5594353069081231E-15, 0.0000000000000000E+00, 0.1112732565966979E-09, 0.9895328911616120E-03, 0.6252320936560726E-03}, + i0: 1, + n0: 21, + pp: 0, + tau: -0.0000000000000000, + sigma: 2.1175425068616867E-005, + i0Out: 1, + n0Out: 21, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 2.1175425068616867E-005, + dminOut: 0.0000000000000000, + dmin1Out: 2.7016889331018056E-002, + dmin2Out: 5.3061698118516694E-002, + dnOut: 0.0000000000000000, + dnm1Out: 2.7016889331018056E-002, + dnm2Out: 8.6018658784156071E-002, + }, + { + z: []float64{0.2440445008292708E+01, 0.2461394773494974E+01, 0.2094976520226600E-01, 0.1017444891892999E-01, 0.1195399335050165E+01, 0.1189425435147283E+01, 0.4200549016048655E-02, 0.1849378635683999E-02, 0.5236691632680260E+00, 0.5228093175235037E+00, 0.9895328911616120E-03, 0.1620493249248586E-02, 0.8561706005512968E+00, 0.8939544038697832E+00, 0.3940429656773515E-01, 0.6132377362967349E-01, 0.1391235531991410E+01, 0.1434168925733579E+01, 0.1042571673718422E+00, 0.6181229879703373E-01, 0.8502943288943339E+00, 0.8790143072012576E+00, 0.9053227710395735E-01, 0.2145324219750511E-01, 0.2082981609510011E+00, 0.6992314020959263E+00, 0.5123864833424303E+00, 0.7139837844669097E+00, 0.9743424132304999E+00, 0.4148193287752837E+00, 0.1544607000116935E+00, 0.4268738185358478E+00, 0.1146411422862754E+01, 0.7891833197548568E+00, 0.6964571542795012E-01, 0.1157716892137957E+00, 0.1311855086360479E+01, 0.1687185709139079E+01, 0.4911023119923957E+00, 0.1498504938454686E+00, 0.5148125055608023E+00, 0.9038246924092180E+00, 0.5388626806938843E+00, 0.1006978425303630E+00, 0.1688986820057405E+00, 0.3061474807444209E+00, 0.2379466412690434E+00, 0.5288684194677825E+00, 0.6804539597693821E+00, 0.9598101715535300E+00, 0.8082246312519304E+00, 0.5423584775195998E+00, 0.6440798303130841E+00, 0.9973399062905237E+00, 0.8956185534970393E+00, 0.4671884516860899E+00, 0.5202501498046066E+00, 0.1861385328384410E+00, 0.1330768347199243E+00, 0.6800991665489665E+00, 0.9512749631631994E+00, 0.1261574624288360E+01, 0.9903988276741268E+00, 0.5608966509936130E+00, 0.7144727578117591E+00, 0.3798570066394223E+00, 0.2262808998212762E+00, 0.4184574968871406E+00, 0.7024632317571722E+00, 0.6491193472879784E+00, 0.3651136124179467E+00, 0.1105843276664904E+00, 0.1966029864506465E+00, 0.9277628648996712E-01, 0.6757627705811050E-02, 0.2122447413720272E-02, 0.2913933674473832E-01, 0.2701688933101806E-01, 0.2136293938333395E-23, 0.0000000000000000E+00, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: -0.0000000000000000, + sigma: 2.1175425068616867E-005, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 2.1175425068616867E-005, + dminOut: 2.5763383633962696E-002, + dmin1Out: 4.3622798915905092E-002, + dmin2Out: 7.4536672467372611E-002, + dnOut: 2.5763383633962696E-002, + dnm1Out: 4.3622798915905092E-002, + dnm2Out: 9.8141518071882677E-002, + }, + { + z: []float64{0.2471569222413904E+01, 0.2461394773494974E+01, 0.4896382518051712E-02, 0.1017444891892999E-01, 0.1186378431264915E+01, 0.1189425435147283E+01, 0.8149780515932184E-03, 0.1849378635683999E-02, 0.5236148327211592E+00, 0.5228093175235037E+00, 0.2766627272719901E-02, 0.1620493249248586E-02, 0.9525115502267366E+00, 0.8939544038697832E+00, 0.9233342160256496E-01, 0.6132377362967349E-01, 0.1403647802928048E+01, 0.1434168925733579E+01, 0.3870906568602875E-01, 0.6181229879703373E-01, 0.8617584837127339E+00, 0.8790143072012576E+00, 0.1740717486950262E-01, 0.2145324219750511E-01, 0.1395808011693333E+01, 0.6992314020959263E+00, 0.2121884039551361E+00, 0.7139837844669097E+00, 0.6295047433559955E+00, 0.4148193287752837E+00, 0.5351535485381410E+00, 0.4268738185358478E+00, 0.3698014604305115E+00, 0.7891833197548568E+00, 0.5281978587564573E+00, 0.1157716892137957E+00, 0.1308838344228090E+01, 0.1687185709139079E+01, 0.1034799882693896E+00, 0.1498504938454686E+00, 0.9010425466701916E+00, 0.9038246924092180E+00, 0.3421413441684364E-01, 0.1006978425303630E+00, 0.8008017657953598E+00, 0.3061474807444209E+00, 0.6338813300623194E+00, 0.5288684194677825E+00, 0.8682873190108105E+00, 0.9598101715535300E+00, 0.6229686202966810E+00, 0.5423584775195998E+00, 0.8415597376799326E+00, 0.9973399062905237E+00, 0.1033340463692495E+00, 0.4671884516860899E+00, 0.7629036530181579E+00, 0.1861385328384410E+00, 0.1124645093942705E+01, 0.6800991665489665E+00, 0.6978261813392677E+00, 0.1261574624288360E+01, 0.3053203341720497E+00, 0.5608966509936130E+00, 0.4929941693545132E+00, 0.3798570066394223E+00, 0.5509778292160957E+00, 0.4184574968871406E+00, 0.2087258457383731E+00, 0.6491193472879784E+00, 0.4915348757406203E-01, 0.1105843276664904E+00, 0.4574524632962537E-01, 0.9277628648996712E-01, 0.1253505697055357E-02, 0.2122447413720272E-02, 0.2576338363396270E-01, 0.2701688933101806E-01, 0.8149780515932184E-03, 0.1620493249248586E-02}, + i0: 1, + n0: 20, + pp: 0, + tau: 2.0080554394878082E-002, + sigma: 2.1175425068616867E-005, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 2.0080554394878082E-002, + sigmaOut: 2.1175425068616867E-005, + dminOut: -2.1187919252575148E-003, + dmin1Out: -2.1187919252575148E-003, + dmin2Out: 3.1777270007152948E-002, + dnOut: 4.3005217031728403E-002, + dnm1Out: -2.1187919252575148E-003, + dnm2Out: 3.1777270007152948E-002, + }, + { + z: []float64{0.2471569222413904E+01, 0.2456385050537078E+01, 0.4896382518051712E-02, 0.2364842030515144E-02, 0.1186378431264915E+01, 0.1164748012891115E+01, 0.8149780515932184E-03, 0.3663750368606913E-03, 0.5236148327211592E+00, 0.5059345305621403E+00, 0.2766627272719901E-02, 0.5208666879309463E-02, 0.9525115502267366E+00, 0.1019555750555114E+01, 0.9233342160256496E-01, 0.1271177219084926E+00, 0.1403647802928048E+01, 0.1295158592310706E+01, 0.3870906568602875E-01, 0.2575581550365553E-01, 0.8617584837127339E+00, 0.8333292886837029E+00, 0.1740717486950262E-01, 0.2915663048658400E-01, 0.1395808011693333E+01, 0.1558759230767007E+01, 0.2121884039551361E+00, 0.8569226352498945E-01, 0.6295047433559955E+00, 0.1058885473974269E+01, 0.5351535485381410E+00, 0.1868951540728986E+00, 0.3698014604305115E+00, 0.6910236107191923E+00, 0.5281978587564573E+00, 0.1000437033056103E+01, 0.1308838344228090E+01, 0.3918007450464985E+00, 0.1034799882693896E+00, 0.2379777816619179E+00, 0.9010425466701916E+00, 0.6771983450302391E+00, 0.3421413441684364E-01, 0.4045895778871807E-01, 0.8008017657953598E+00, 0.1374143583674083E+01, 0.6338813300623194E+00, 0.4005339232303680E+00, 0.8682873190108105E+00, 0.1070641461682245E+01, 0.6229686202966810E+00, 0.4896740201485869E+00, 0.8415597376799326E+00, 0.4351392095057171E+00, 0.1033340463692495E+00, 0.1811694274708021E+00, 0.7629036530181579E+00, 0.1686298765095183E+01, 0.1124645093942705E+01, 0.4654019842229331E+00, 0.6978261813392677E+00, 0.5176639768935063E+00, 0.3053203341720497E+00, 0.2907699806261721E+00, 0.4929941693545132E+00, 0.7331214635495586E+00, 0.5509778292160957E+00, 0.1568680213363420E+00, 0.2087258457383731E+00, 0.8093075758121498E-01, 0.4915348757406203E-01, 0.2778348386000479E-01, 0.4574524632962537E-01, -0.8652862282021575E-03, 0.1253505697055357E-02, -0.3732238779264379E-01, 0.2576338363396270E-01, 0.4300521703172840E-01, 0.8149780515932184E-03, 0.3663750368606913E-03}, + i0: 1, + n0: 20, + pp: 0, + tau: 5.0201385987195205E-003, + sigma: 2.1175425068616867E-005, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 5.0201385987195205E-003, + sigmaOut: 2.1175425068616867E-005, + dminOut: 1.8576185384092288E-002, + dmin1Out: 1.8576185384092288E-002, + dmin2Out: 5.2365600435162571E-002, + dnOut: 1.9114649409197451E-002, + dnm1Out: 1.8576185384092288E-002, + dnm2Out: 5.2365600435162571E-002, + }, + { + z: []float64{0.2471569222413904E+01, 0.2471445466333236E+01, 0.4896382518051712E-02, 0.2350431231346416E-02, 0.1186378431264915E+01, 0.1179822839486443E+01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.5236148327211592E+00, 0.5209996276036221E+00, 0.2766627272719901E-02, 0.5058054349403302E-02, 0.9525115502267366E+00, 0.1034766778881179E+01, 0.9233342160256496E-01, 0.1252490967185870E+00, 0.1403647802928048E+01, 0.1312087633296770E+01, 0.3870906568602875E-01, 0.2542350442532051E-01, 0.8617584837127339E+00, 0.8487220155581966E+00, 0.1740717486950262E-01, 0.2862783537884150E-01, 0.1395808011693333E+01, 0.1574348441670908E+01, 0.2121884039551361E+00, 0.8484373804386666E-01, 0.6295047433559955E+00, 0.1074794415251550E+01, 0.5351535485381410E+00, 0.1841287608083240E+00, 0.3698014604305115E+00, 0.7088504197799252E+00, 0.5281978587564573E+00, 0.9752771411128711E+00, 0.1308838344228090E+01, 0.4320210527858890E+00, 0.1034799882693896E+00, 0.2158225196628609E+00, 0.9010425466701916E+00, 0.7144140228254550E+00, 0.3421413441684364E-01, 0.3835134583138245E-01, 0.8008017657953598E+00, 0.1391311611427577E+01, 0.6338813300623194E+00, 0.3955915526975877E+00, 0.8682873190108105E+00, 0.1090644248011184E+01, 0.6229686202966810E+00, 0.4806932321292802E+00, 0.8415597376799326E+00, 0.4591804133211825E+00, 0.1033340463692495E+00, 0.1716839812178710E+00, 0.7629036530181579E+00, 0.1710844627144272E+01, 0.1124645093942705E+01, 0.4587247601659613E+00, 0.6978261813392677E+00, 0.5394016167466366E+00, 0.3053203341720497E+00, 0.2790520826393697E+00, 0.4929941693545132E+00, 0.7598997773325197E+00, 0.5509778292160957E+00, 0.1513401067044909E+00, 0.2087258457383731E+00, 0.1015190880092246E+00, 0.4915348757406203E-01, 0.2214892234681356E-01, 0.4574524632962537E-01, 0.1982969108114764E-01, 0.1253505697055357E-02, 0.1628595626045726E-02, 0.2576338363396270E-01, 0.1911464940919745E-01, 0.8149780515932184E-03, 0.3616937915375072E-03, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: 5.4769133315280185E-003, + sigma: 5.0413140237881371E-003, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 5.4769133315280185E-003, + sigmaOut: 5.0413140237881371E-003, + dminOut: 9.5622848228283271E-003, + dmin1Out: 9.5622848228283271E-003, + dmin2Out: 6.9533978479808370E-002, + dnOut: 1.0856003705186750E-002, + dnm1Out: 9.5622848228283271E-003, + dnm2Out: 6.9533978479808370E-002, + }, + { + z: []float64{0.2468318984233055E+01, 0.2471445466333236E+01, 0.1123474100024551E-02, 0.2350431231346416E-02, 0.1173584145846428E+01, 0.1179822839486443E+01, 0.1605699355811189E-03, 0.3616937915375072E-03, 0.5204201986859162E+00, 0.5209996276036221E+00, 0.1005707814522541E-01, 0.5058054349403302E-02, 0.1144481884123012E+01, 0.1034766778881179E+01, 0.1435914304680996E+00, 0.1252490967185870E+00, 0.1188442793922463E+01, 0.1312087633296770E+01, 0.1815610143690141E-01, 0.2542350442532051E-01, 0.8537168361686087E+00, 0.8487220155581966E+00, 0.5279290053521807E-01, 0.2862783537884150E-01, 0.1600922365848029E+01, 0.1574348441670908E+01, 0.5696064828871891E-01, 0.8484373804386666E-01, 0.1196485614439627E+01, 0.1074794415251550E+01, 0.1090859328498209E+00, 0.1841287608083240E+00, 0.1569564714711448E+01, 0.7088504197799252E+00, 0.2684440171930437E+00, 0.9752771411128711E+00, 0.3739226419241781E+00, 0.4320210527858890E+00, 0.4123490187575627E+00, 0.2158225196628609E+00, 0.3349394365677468E+00, 0.7144140228254550E+00, 0.1593084209965356E+00, 0.3835134583138245E-01, 0.1622117829797102E+01, 0.1391311611427577E+01, 0.2659792301064862E+00, 0.3955915526975877E+00, 0.1299881336702450E+01, 0.1090644248011184E+01, 0.1698038973078534E+00, 0.4806932321292802E+00, 0.4555835838996722E+00, 0.4591804133211825E+00, 0.6447216871142054E+00, 0.1716839812178710E+00, 0.1519370786864500E+01, 0.1710844627144272E+01, 0.1628548339973444E+00, 0.4587247601659613E+00, 0.6501219520571339E+00, 0.5394016167466366E+00, 0.3261720586281595E+00, 0.2790520826393697E+00, 0.5795909120773233E+00, 0.7598997773325197E+00, 0.2650819619788820E-01, 0.1513401067044909E+00, 0.9168290082662192E-01, 0.1015190880092246E+00, 0.4790492926791300E-02, 0.2214892234681356E-01, 0.1119088044887405E-01, 0.1982969108114764E-01, 0.2781732372482683E-02, 0.1628595626045726E-02, 0.1085600370518675E-01, 0.1911464940919745E-01, 0.1605699355811189E-03, 0.3616937915375072E-03}, + i0: 1, + n0: 20, + pp: 0, + tau: 5.1216063611655054E-003, + sigma: 1.0518227355316156E-002, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 5.1216063611655054E-003, + sigmaOut: 1.0518227355316156E-002, + dminOut: 2.0601312480394186E-003, + dmin1Out: 5.4371870398960158E-003, + dmin2Out: 8.0023511442426670E-002, + dnOut: 2.0601312480394186E-003, + dnm1Out: 5.4371870398960158E-003, + dnm2Out: 8.0023511442426670E-002, + }, + { + z: []float64{0.2468318984233055E+01, 0.2464320851971913E+01, 0.1123474100024551E-02, 0.5350323562789559E-03, 0.1173584145846428E+01, 0.1168088077064565E+01, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.5204201986859162E+00, 0.5252841314829605E+00, 0.1005707814522541E-01, 0.2191222436498315E-01, 0.1144481884123012E+01, 0.1261039483864963E+01, 0.1435914304680996E+00, 0.1353250258951489E+00, 0.1188442793922463E+01, 0.1066152263103050E+01, 0.1815610143690141E-01, 0.1453842008528346E-01, 0.8537168361686087E+00, 0.8868497102573779E+00, 0.5279290053521807E-01, 0.9530062900995111E-01, 0.1600922365848029E+01, 0.1557460778765631E+01, 0.5696064828871891E-01, 0.4375878814786067E-01, 0.1196485614439627E+01, 0.1256691152780422E+01, 0.1090859328498209E+00, 0.1362446379077657E+00, 0.1569564714711448E+01, 0.1696642487635560E+01, 0.2684440171930437E+00, 0.5916231430550117E-01, 0.3739226419241781E+00, 0.7219877400150740E+00, 0.4123490187575627E+00, 0.1912940350054112E+00, 0.3349394365677468E+00, 0.2978322161977056E+00, 0.1593084209965356E+00, 0.8676597630518320E+00, 0.1622117829797102E+01, 0.1015315690490590E+01, 0.2659792301064862E+00, 0.3405260456467969E+00, 0.1299881336702450E+01, 0.1124037582002341E+01, 0.1698038973078534E+00, 0.6882320425428856E-01, 0.4555835838996722E+00, 0.1026360460398424E+01, 0.6447216871142054E+00, 0.9544125430154021E+00, 0.1519370786864500E+01, 0.7226914714852769E+00, 0.1628548339973444E+00, 0.1465016632377001E+00, 0.6501219520571339E+00, 0.8246707410864278E+00, 0.3261720586281595E+00, 0.2292385937027206E+00, 0.5795909120773233E+00, 0.3717389082113253E+00, 0.2650819619788820E-01, 0.6537783023029759E-02, 0.9168290082662192E-01, 0.8481400436921797E-01, 0.4790492926791300E-02, 0.6320870478125323E-03, 0.1119088044887405E-01, 0.8218919412378699E-02, 0.2781732372482683E-02, 0.3674266095981827E-02, 0.1085600370518675E-01, 0.2060131248039419E-02, 0.1605699355811189E-03, 0.7153898701552432E-04, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: 1.2817878169164906E-003, + sigma: 1.5639833716481661E-002, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 1.2817878169164906E-003, + sigmaOut: 1.5639833716481661E-002, + dminOut: 6.0731361153288982E-005, + dmin1Out: 6.8738708636769136E-003, + dmin2Out: 8.1489512892123819E-002, + dnOut: 6.0731361153288982E-005, + dnm1Out: 6.8738708636769136E-003, + dnm2Out: 8.1489512892123819E-002, + }, + { + z: []float64{0.2463574096511276E+01, 0.2464320851971913E+01, 0.2536822079344948E-03, 0.5350323562789559E-03, 0.1166624146026729E+01, 0.1168088077064565E+01, 0.3221114082852138E-04, 0.7153898701552432E-04, 0.5458823568901986E+00, 0.5252841314829605E+00, 0.5061929508212644E-01, 0.2191222436498315E-01, 0.1344463426861069E+01, 0.1261039483864963E+01, 0.1073120173669855E+00, 0.1353250258951489E+00, 0.9720968780044319E+00, 0.1066152263103050E+01, 0.1326348631702415E-01, 0.1453842008528346E-01, 0.9676050651333883E+00, 0.8868497102573779E+00, 0.1533962535161303E+00, 0.9530062900995111E-01, 0.1446541525580445E+01, 0.1557460778765631E+01, 0.3801569533217738E-01, 0.4375878814786067E-01, 0.1353638307539094E+01, 0.1256691152780422E+01, 0.1707682473962209E+00, 0.1362446379077657E+00, 0.1583754766727924E+01, 0.1696642487635560E+01, 0.2697037855661164E-01, 0.5916231430550117E-01, 0.8850296086469572E+00, 0.7219877400150740E+00, 0.6437471225190403E-01, 0.1912940350054112E+00, 0.1099835479180717E+01, 0.2978322161977056E+00, 0.8009821360646626E+00, 0.8676597630518320E+00, 0.5535778122558079E+00, 0.1015315690490590E+01, 0.6914368034330997E+00, 0.3405260456467969E+00, 0.5001421950066134E+00, 0.1124037582002341E+01, 0.1412346654806686E+00, 0.6882320425428856E-01, 0.1838256550116241E+01, 0.1026360460398424E+01, 0.3752173792456719E+00, 0.9544125430154021E+00, 0.4926939676603885E+00, 0.7226914714852769E+00, 0.2452143584512202E+00, 0.1465016632377001E+00, 0.8074131885210117E+00, 0.8246707410864278E+00, 0.1055431169003394E+00, 0.2292385937027206E+00, 0.2714517865170992E+00, 0.3717389082113253E+00, 0.2042703660177667E-02, 0.6537783023029759E-02, 0.8212159993993635E-01, 0.8481400436921797E-01, 0.6326073178529442E-04, 0.6320870478125323E-03, 0.1054813695965874E-01, 0.8218919412378699E-02, 0.7176120699696391E-03, 0.3674266095981827E-02, 0.6073136115328898E-04, 0.2060131248039419E-02, 0.3221114082852138E-04, 0.7153898701552432E-04}, + i0: 1, + n0: 20, + pp: 0, + tau: 5.6837241251038845E-005, + sigma: 1.6921621533398150E-002, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 5.6837241251038845E-005, + sigmaOut: 1.6921621533398150E-002, + dminOut: 3.1568086081919418E-009, + dmin1Out: 1.0483100129151506E-002, + dmin2Out: 8.1316774559040517E-002, + dnOut: 3.1568086081919418E-009, + dnm1Out: 1.0483100129151506E-002, + dnm2Out: 8.1316774559040517E-002, + }, + { + z: []float64{0.2463574096511276E+01, 0.2463770941477959E+01, 0.2536822079344948E-03, 0.1201214707955848E-03, 0.1166624146026729E+01, 0.1166479398455512E+01, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.5458823568901986E+00, 0.5964297407456295E+00, 0.5061929508212644E-01, 0.1141052940222717E+00, 0.1344463426861069E+01, 0.1337613312964532E+01, 0.1073120173669855E+00, 0.7798791776646297E-01, 0.9720968780044319E+00, 0.9073156093137420E+00, 0.1326348631702415E-01, 0.1414482062243694E-01, 0.9676050651333883E+00, 0.1106799660785830E+01, 0.1533962535161303E+00, 0.2004825791345134E+00, 0.1446541525580445E+01, 0.1284017804536858E+01, 0.3801569533217738E-01, 0.4007693764646178E-01, 0.1353638307539094E+01, 0.1484272780047602E+01, 0.1707682473962209E+00, 0.1822138285193538E+00, 0.1583754766727924E+01, 0.1428454479523931E+01, 0.2697037855661164E-01, 0.1671007646458111E-01, 0.8850296086469572E+00, 0.9326374071930291E+00, 0.6437471225190403E-01, 0.7591545433480534E-01, 0.1099835479180717E+01, 0.1824845323669324E+01, 0.8009821360646626E+00, 0.2429827519008994E+00, 0.5535778122558079E+00, 0.1001975026546757E+01, 0.6914368034330997E+00, 0.3451350696526060E+00, 0.5001421950066134E+00, 0.2961849535934249E+00, 0.1412346654806686E+00, 0.8765656248686587E+00, 0.1838256550116241E+01, 0.1336851467252003E+01, 0.3752173792456719E+00, 0.1382856239786244E+00, 0.4926939676603885E+00, 0.5995658648917332E+00, 0.2452143584512202E+00, 0.3302211126778973E+00, 0.8074131885210117E+00, 0.5826783555022028E+00, 0.1055431169003394E+00, 0.4916926700063749E-01, 0.2714517865170992E+00, 0.2242683859353883E+00, 0.2042703660177667E-02, 0.7479881396448043E-03, 0.8212159993993635E-01, 0.8138003529082581E-01, 0.6326073178529442E-04, 0.8199589256196194E-05, 0.1054813695965874E-01, 0.1120071219912114E-01, 0.7176120699696391E-03, 0.3890963093641941E-05, 0.6073136115328898E-04, 0.3156808608191942E-08, 0.3221114082852138E-04, 0.1507398544447245E-04, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: 3.1557121791797713E-009, + sigma: 1.6978458774649190E-002, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 3.1557121791797713E-009, + sigmaOut: 1.6978458774649190E-002, + dminOut: 6.9684975813366743E-017, + dmin1Out: 1.1199576261102989E-002, + dmin2Out: 8.1067607231828140E-002, + dnOut: 6.9684975813366743E-017, + dnm1Out: 1.1199576261102989E-002, + dnm2Out: 8.1067607231828140E-002, + }, + { + z: []float64{0.2463891059793043E+01, 0.2463770941477959E+01, 0.5686908130061341E-04, 0.1201214707955848E-03, 0.1166437600203943E+01, 0.1166479398455512E+01, 0.7707718980490818E-05, 0.1507398544447245E-04, 0.7105273238932086E+00, 0.5964297407456295E+00, 0.2148105431436762E+00, 0.1141052940222717E+00, 0.1200790684431606E+01, 0.1337613312964532E+01, 0.5892755169139442E-01, 0.7798791776646297E-01, 0.8625328750890724E+00, 0.9073156093137420E+00, 0.1815059242254727E-01, 0.1414482062243694E-01, 0.1289131644342084E+01, 0.1106799660785830E+01, 0.1996872873596725E+00, 0.2004825791345134E+00, 0.1124407451667935E+01, 0.1284017804536858E+01, 0.5290351604133232E-01, 0.4007693764646178E-01, 0.1613583089369911E+01, 0.1484272780047602E+01, 0.1613081850537457E+00, 0.1822138285193538E+00, 0.1283856367779054E+01, 0.1428454479523931E+01, 0.1213877407087503E-01, 0.1671007646458111E-01, 0.9964140843012472E+00, 0.9326374071930291E+00, 0.1390325207358455E+00, 0.7591545433480534E-01, 0.1928795551678665E+01, 0.1824845323669324E+01, 0.1262252233392066E+00, 0.2429827519008994E+00, 0.1220884869704444E+01, 0.1001975026546757E+01, 0.8372928285471114E-01, 0.3451350696526060E+00, 0.1089021292451660E+01, 0.2961849535934249E+00, 0.1076046951396362E+01, 0.8765656248686587E+00, 0.3990901366785531E+00, 0.1336851467252003E+01, 0.2077509116934600E+00, 0.1382856239786244E+00, 0.7220360627204584E+00, 0.5995658648917332E+00, 0.2664862668525171E+00, 0.3302211126778973E+00, 0.3653613524946110E+00, 0.5826783555022028E+00, 0.3018138637972599E-01, 0.4916926700063749E-01, 0.1948349845395949E+00, 0.2242683859353883E+00, 0.3124249032854923E-03, 0.7479881396448043E-03, 0.8107580682108434E-01, 0.8138003529082581E-01, 0.1132782305976083E-05, 0.8199589256196194E-05, 0.1120346722419663E-01, 0.1120071219912114E-01, 0.1096359327194516E-11, 0.3890963093641941E-05, 0.6968497581336674E-16, 0.3156808608191942E-08, 0.7707718980490818E-05, 0.1507398544447245E-04}, + i0: 1, + n0: 20, + pp: 0, + tau: 6.9684975806547287E-017, + sigma: 1.6978461930361368E-002, + i0Out: 1, + n0Out: 20, + ppOut: 0, + tauOut: 6.9684975806547287E-017, + sigmaOut: 1.6978461930361368E-002, + dminOut: 6.1629758220391547E-032, + dmin1Out: 1.1203310405167735E-002, + dmin2Out: 8.0927116373146771E-002, + dnOut: 6.1629758220391547E-032, + dnm1Out: 1.1203310405167735E-002, + dnm2Out: 8.0927116373146771E-002, + }, + { + z: []float64{0.2463891059793043E+01, 0.2463947928874343E+01, 0.5686908130061341E-04, 0.2692193042748079E-04, 0.1166437600203943E+01, 0.1166418385992496E+01, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.7105273238932086E+00, 0.9253331718563164E+00, 0.2148105431436762E+00, 0.2787563517334627E+00, 0.1200790684431606E+01, 0.9809618843895378E+00, 0.5892755169139442E-01, 0.5181337969514327E-01, 0.8625328750890724E+00, 0.8288700878164763E+00, 0.1815059242254727E-01, 0.2822939734392020E-01, 0.1289131644342084E+01, 0.1460589534357837E+01, 0.1996872873596725E+00, 0.1537255119449346E+00, 0.1124407451667935E+01, 0.1023585455764333E+01, 0.5290351604133232E-01, 0.8339725654733963E-01, 0.1613583089369911E+01, 0.1691494017876317E+01, 0.1613081850537457E+00, 0.1224340957564512E+00, 0.1283856367779054E+01, 0.1173561046093478E+01, 0.1213877407087503E-01, 0.1030644761994533E-01, 0.9964140843012472E+00, 0.1125140157417147E+01, 0.1390325207358455E+00, 0.2383394688796517E+00, 0.1928795551678665E+01, 0.1816681306138221E+01, 0.1262252233392066E+00, 0.8482856339700598E-01, 0.1220884869704444E+01, 0.1219785589162149E+01, 0.8372928285471114E-01, 0.7475327847832687E-01, 0.1089021292451660E+01, 0.2090314965369696E+01, 0.1076046951396362E+01, 0.2054425921547012E+00, 0.3990901366785531E+00, 0.4013984562173118E+00, 0.2077509116934600E+00, 0.3737026089221466E+00, 0.7220360627204584E+00, 0.6148197206508288E+00, 0.2664862668525171E+00, 0.1583615157552351E+00, 0.3653613524946110E+00, 0.2371812231191019E+00, 0.3018138637972599E-01, 0.2479281399828426E-01, 0.1948349845395949E+00, 0.1703545954445960E+00, 0.3124249032854923E-03, 0.1486904479375115E-03, 0.8107580682108434E-01, 0.8092824915545274E-01, 0.1132782305976083E-05, 0.1568190288260776E-06, 0.1120346722419663E-01, 0.1120331040626409E-01, 0.1096359327194516E-11, 0.6819392699821255E-26, 0.6968497581336674E-16, 0.6162975822039155E-31, 0.7707718980490818E-05, 0.4695180568393632E-05, 0.2117542506861687E-04}, + i0: 1, + n0: 20, + pp: 1, + tau: 6.1629758220391547E-032, + sigma: 1.6978461930361441E-002, + i0Out: 1, + n0Out: 20, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.6978461930361441E-002, + dminOut: 6.1629758220391547E-032, + dmin1Out: 1.1203288675083998E-002, + dmin2Out: 8.0846453894262649E-002, + dnOut: 6.1629758220391547E-032, + dnm1Out: 1.1203288675083998E-002, + dnm2Out: 8.0846453894262649E-002, + }, + { + z: []float64{0.2463974850804771E+01, 0.2463947928874343E+01, 0.1274454348702788E-04, 0.2692193042748079E-04, 0.1166410336629578E+01, 0.1166418385992496E+01, 0.3724766654883956E-05, 0.4695180568393632E-05, 0.1204085798823124E+01, 0.9253331718563164E+00, 0.2271012218143261E+00, 0.2787563517334627E+00, 0.8056740422703550E+00, 0.9809618843895378E+00, 0.5330513126246473E-01, 0.5181337969514327E-01, 0.8037943538979316E+00, 0.8288700878164763E+00, 0.5129615818002433E-01, 0.2822939734392020E-01, 0.1563018888122747E+01, 0.1460589534357837E+01, 0.1006713350698832E+00, 0.1537255119449346E+00, 0.1006311377241790E+01, 0.1023585455764333E+01, 0.1401812239704283E+00, 0.8339725654733963E-01, 0.1673746889662340E+01, 0.1691494017876317E+01, 0.8584564749956700E-01, 0.1224340957564512E+00, 0.1098021846213856E+01, 0.1173561046093478E+01, 0.1056099032774466E-01, 0.1030644761994533E-01, 0.1352918635969054E+01, 0.1125140157417147E+01, 0.3200390963041470E+00, 0.2383394688796517E+00, 0.1581470773231080E+01, 0.1816681306138221E+01, 0.6542811978092533E-01, 0.8482856339700598E-01, 0.1229110747859551E+01, 0.1219785589162149E+01, 0.1271308521106110E+00, 0.7475327847832687E-01, 0.2168626705413786E+01, 0.2090314965369696E+01, 0.3802606466401751E-01, 0.2054425921547012E+00, 0.7370750004754409E+00, 0.4013984562173118E+00, 0.3117182559112661E+00, 0.3737026089221466E+00, 0.4614629804947978E+00, 0.6148197206508288E+00, 0.8139413038408401E-01, 0.1583615157552351E+00, 0.1805799067333021E+00, 0.2371812231191019E+00, 0.2338892446571373E-01, 0.2479281399828426E-01, 0.1471143614268198E+00, 0.1703545954445960E+00, 0.8179526119010886E-04, 0.1486904479375115E-03, 0.8084661071329148E-01, 0.8092824915545274E-01, 0.2173118009582292E-07, 0.1568190288260776E-06, 0.1120328867508400E-01, 0.1120331040626409E-01, 0.3751376363572422E-55, 0.6819392699821255E-26}, + i0: 1, + n0: 19, + pp: 0, + tau: 1.1203284285913290E-002, + sigma: 1.6978461930361441E-002, + i0Out: 1, + n0Out: 19, + ppOut: 0, + tauOut: 1.1203284285913290E-002, + sigmaOut: 1.6978461930361441E-002, + dminOut: 8.9043085058082561E-010, + dmin1Out: 6.9585227169791292E-002, + dmin2Out: 0.11373841371027797, + dnOut: 8.9043085058082561E-010, + dnm1Out: 6.9585227169791292E-002, + dnm2Out: 0.11373841371027797, + }, + { + z: []float64{0.2463974850804771E+01, 0.2452784311062345E+01, 0.1274454348702788E-04, 0.6060609239813679E-05, 0.1166410336629578E+01, 0.1155204716501079E+01, 0.3724766654883956E-05, 0.3882375624867434E-05, 0.1204085798823124E+01, 0.1419979853975912E+01, 0.2271012218143261E+00, 0.1288536304732592E+00, 0.8056740422703550E+00, 0.7189222587736472E+00, 0.5330513126246473E-01, 0.5959804835594534E-01, 0.8037943538979316E+00, 0.7842891794360973E+00, 0.5129615818002433E-01, 0.1022287011292917E+00, 0.1563018888122747E+01, 0.1550258237777425E+01, 0.1006713350698832E+00, 0.6534828028921505E-01, 0.1006311377241790E+01, 0.1069941036637090E+01, 0.1401812239704283E+00, 0.2192904838448094E+00, 0.1673746889662340E+01, 0.1529098769031184E+01, 0.8584564749956700E-01, 0.6164441320989392E-01, 0.1098021846213856E+01, 0.1035735139045794E+01, 0.1056099032774466E-01, 0.1379518767882891E-01, 0.1352918635969054E+01, 0.1647959260308459E+01, 0.3200390963041470E+00, 0.3071268139247320E+00, 0.1581470773231080E+01, 0.1328568794801360E+01, 0.6542811978092533E-01, 0.6053010243026304E-01, 0.1229110747859551E+01, 0.1284508213253985E+01, 0.1271308521106110E+00, 0.2146341752620367E+00, 0.2168626705413786E+01, 0.1980815310529854E+01, 0.3802606466401751E-01, 0.1414976019284330E-01, 0.7370750004754409E+00, 0.1023440211907950E+01, 0.3117182559112661E+00, 0.1405518698344743E+00, 0.4614629804947978E+00, 0.3911019567584944E+00, 0.8139413038408401E-01, 0.3758136265851575E-01, 0.1805799067333021E+00, 0.1551841842545868E+00, 0.2338892446571373E-01, 0.2217266343062855E-01, 0.1471143614268198E+00, 0.1138202089714681E+00, 0.8179526119010886E-04, 0.5809925758690545E-04, 0.8084661071329148E-01, 0.6958524890097138E-01, 0.2173118009582292E-07, 0.3498739858072780E-08, 0.1120328867508400E-01, 0.8904308505808256E-09, 0.3751376363572422E-55, 0.3882375624867434E-05, 0.1697846193036144E-01}, + i0: 1, + n0: 19, + pp: 1, + tau: 8.9043080564395014E-010, + sigma: 2.8181746216274728E-002, + i0Out: 1, + n0Out: 19, + ppOut: 1, + tauOut: 8.9043080564395014E-010, + sigmaOut: 2.8181746216274728E-002, + dminOut: 1.3962105636374437E-019, + dmin1Out: 6.9544122471813200E-002, + dmin2Out: 9.8247027562672340E-002, + dnOut: 1.3962105636374437E-019, + dnm1Out: 6.9544122471813200E-002, + dnm2Out: 9.8247027562672340E-002, + }, + { + z: []float64{0.2452790370781154E+01, 0.2452784311062345E+01, 0.2854399814229969E-05, 0.6060609239813679E-05, 0.1155205743586459E+01, 0.1155204716501079E+01, 0.4772219324121025E-05, 0.3882375624867434E-05, 0.1548828711339416E+01, 0.1419979853975912E+01, 0.5981019230390531E-01, 0.1288536304732592E+00, 0.7187101139352565E+00, 0.7189222587736472E+00, 0.6503610222645050E-01, 0.5959804835594534E-01, 0.8214817774485077E+00, 0.7842891794360973E+00, 0.1929207566298143E+00, 0.1022287011292917E+00, 0.1422685760546395E+01, 0.1550258237777425E+01, 0.4914564318703864E-01, 0.6534828028921505E-01, 0.1240085876404429E+01, 0.1069941036637090E+01, 0.2703980549150243E+00, 0.2192904838448094E+00, 0.1320345126435623E+01, 0.1529098769031184E+01, 0.4835651195207321E-01, 0.6164441320989392E-01, 0.1001173813882118E+01, 0.1035735139045794E+01, 0.2270725319399537E-01, 0.1379518767882891E-01, 0.1932378820148765E+01, 0.1647959260308459E+01, 0.2111589595024383E+00, 0.3071268139247320E+00, 0.1177939936838754E+01, 0.1328568794801360E+01, 0.6600626338337756E-01, 0.6053010243026304E-01, 0.1433136124242214E+01, 0.1284508213253985E+01, 0.2966575563411978E+00, 0.2146341752620367E+00, 0.1698307513491068E+01, 0.1980815310529854E+01, 0.8526979628348903E-02, 0.1414976019284330E-01, 0.1155465101223645E+01, 0.1023440211907950E+01, 0.4757401262929915E-01, 0.1405518698344743E+00, 0.3811093058972801E+00, 0.3911019567584944E+00, 0.1530278326215801E-01, 0.3758136265851575E-01, 0.1620540635326265E+00, 0.1551841842545868E+00, 0.1557318051836492E-01, 0.2217266343062855E-01, 0.9830512682025924E-01, 0.1138202089714681E+00, 0.4112553872737890E-04, 0.5809925758690545E-04, 0.6954412597055305E-01, 0.6958524890097138E-01, 0.4479725446695418E-16, 0.3498739858072780E-08, 0.1396210563637444E-18, 0.8904308505808256E-09, 0.2854399814229969E-05, 0.3882375624867434E-05}, + i0: 1, + n0: 19, + pp: 0, + tau: 1.3962105636374427E-019, + sigma: 2.8181747106705537E-002, + i0Out: 1, + n0Out: 19, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 2.8181747106705537E-002, + dminOut: 1.3962105636374430E-019, + dmin1Out: 6.9512134440652351E-002, + dmin2Out: 8.9358776708560295E-002, + dnOut: 1.3962105636374430E-019, + dnm1Out: 6.9512134440652351E-002, + dnm2Out: 8.9358776708560295E-002, + }, + { + z: []float64{0.2452790370781154E+01, 0.2452793225180968E+01, 0.2854399814229969E-05, 0.1344352644992036E-05, 0.1155205743586459E+01, 0.1155209171453138E+01, 0.4772219324121025E-05, 0.6398278760815103E-05, 0.1548828711339416E+01, 0.1608632505364561E+01, 0.5981019230390531E-01, 0.2672219415054498E-01, 0.7187101139352565E+00, 0.7570240220111620E+00, 0.6503610222645050E-01, 0.7057368234283014E-01, 0.8214817774485077E+00, 0.9438288517354918E+00, 0.1929207566298143E+00, 0.2908001941945216E+00, 0.1422685760546395E+01, 0.1181031209538913E+01, 0.4914564318703864E-01, 0.5160305461093759E-01, 0.1240085876404429E+01, 0.1458880876708516E+01, 0.2703980549150243E+00, 0.2447209773632920E+00, 0.1320345126435623E+01, 0.1123980661024405E+01, 0.4835651195207321E-01, 0.4307304847484577E-01, 0.1001173813882118E+01, 0.9808080186012680E+00, 0.2270725319399537E-01, 0.4473761868138884E-01, 0.1932378820148765E+01, 0.2098800160969815E+01, 0.2111589595024383E+00, 0.1185117935689049E+00, 0.1177939936838754E+01, 0.1125434406653226E+01, 0.6600626338337756E-01, 0.8405284210411720E-01, 0.1433136124242214E+01, 0.1645740838479294E+01, 0.2966575563411978E+00, 0.3061331074057168E+00, 0.1698307513491068E+01, 0.1400701385713701E+01, 0.8526979628348903E-02, 0.7034066989504621E-02, 0.1155465101223645E+01, 0.1196005046863439E+01, 0.4757401262929915E-01, 0.1515955052150448E-01, 0.3811093058972801E+00, 0.3812525386379337E+00, 0.1530278326215801E-01, 0.6504555274179689E-02, 0.1620540635326265E+00, 0.1711226887768117E+00, 0.1557318051836492E-01, 0.8946350111698947E-02, 0.9830512682025924E-01, 0.8939990224728768E-01, 0.4112553872737890E-04, 0.3199152990069927E-04, 0.6954412597055305E-01, 0.6951213444065239E-01, 0.4479725446695418E-16, 0.8997910999570377E-34, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + tau: 6.8088572105595116E-002, + sigma: 2.8181747106705537E-002, + i0Out: 1, + n0Out: 18, + ppOut: 1, + tauOut: 6.8088572105595116E-002, + sigmaOut: 2.8181747106705537E-002, + dminOut: 1.2643548659038301E-003, + dmin1Out: 1.3935943135754067E-002, + dmin2Out: 9.9495800084882416E-002, + dnOut: 1.2643548659038301E-003, + dnm1Out: 1.3935943135754067E-002, + dnm2Out: 9.9495800084882416E-002, + }, + { + z: []float64{0.2384705997428018E+01, 0.2452793225180968E+01, 0.6512368848977837E-06, 0.1344352644992036E-05, 0.1087126346389419E+01, 0.1155209171453138E+01, 0.9467601652019932E-05, 0.6398278760815103E-05, 0.1567256659807859E+01, 0.1608632505364561E+01, 0.1290748567965171E-01, 0.2672219415054498E-01, 0.7466016465687454E+00, 0.7570240220111620E+00, 0.8921689079377818E-01, 0.7057368234283014E-01, 0.1077323583030640E+01, 0.9438288517354918E+00, 0.3187938243378626E+00, 0.2908001941945216E+00, 0.8457518677063927E+00, 0.1181031209538913E+01, 0.8901276181133644E-01, 0.5160305461093759E-01, 0.1546500520154876E+01, 0.1458880876708516E+01, 0.1778606876095877E+00, 0.2447209773632920E+00, 0.9211044497840675E+00, 0.1123980661024405E+01, 0.4586493023634136E-01, 0.4307304847484577E-01, 0.9115921349407204E+00, 0.9808080186012680E+00, 0.1030014605117353E+00, 0.4473761868138884E-01, 0.2046221921921390E+01, 0.2098800160969815E+01, 0.6518220171905387E-01, 0.1185117935689049E+00, 0.1076216474932694E+01, 0.1125434406653226E+01, 0.1285328723941422E+00, 0.8405284210411720E-01, 0.1755252501385274E+01, 0.1645740838479294E+01, 0.2442959445536252E+00, 0.3061331074057168E+00, 0.1095350936043985E+01, 0.1400701385713701E+01, 0.7680442260639305E-02, 0.7034066989504621E-02, 0.1135395583018709E+01, 0.1196005046863439E+01, 0.5090399511302622E-02, 0.1515955052150448E-01, 0.3145781222952156E+00, 0.3812525386379337E+00, 0.3538316586334169E-02, 0.6504555274179689E-02, 0.1084421501965814E+00, 0.1711226887768117E+00, 0.7375387005938499E-02, 0.8946350111698947E-02, 0.1396793466565477E-01, 0.8939990224728768E-01, 0.1592074691534444E-03, 0.3199152990069927E-04, 0.1264354865903830E-02, 0.6951213444065239E-01, 0.6512368848977837E-06, 0.1344352644992036E-05}, + i0: 1, + n0: 18, + pp: 0, + tau: 1.2463174543591322E-003, + sigma: 9.6270319212300656E-002, + i0Out: 1, + n0Out: 18, + ppOut: 0, + tauOut: 1.2463174543591322E-003, + sigmaOut: 9.6270319212300656E-002, + dminOut: 1.2236274461701734E-006, + dmin1Out: 1.1812799375517376E-002, + dmin2Out: 0.10597947881780349, + dnOut: 1.2236274461701734E-006, + dnm1Out: 1.1812799375517376E-002, + dnm2Out: 0.10597947881780349, + }, + { + z: []float64{0.2384705997428018E+01, 0.2383460331210544E+01, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.1087126346389419E+01, 0.1085889199499347E+01, 0.9467601652019932E-05, 0.1366452649899944E-04, 0.1567256659807859E+01, 0.1578904163506652E+01, 0.1290748567965171E-01, 0.6103442048115082E-02, 0.7466016465687454E+00, 0.8284687778600495E+00, 0.8921689079377818E-01, 0.1160157908485996E+00, 0.1077323583030640E+01, 0.1278855299065544E+01, 0.3187938243378626E+00, 0.2108295383723412E+00, 0.8457518677063927E+00, 0.7226887736910288E+00, 0.8901276181133644E-01, 0.1904807262171572E+00, 0.1546500520154876E+01, 0.1532634164092948E+01, 0.1778606876095877E+00, 0.1068932656188067E+00, 0.9211044497840675E+00, 0.8588297969472432E+00, 0.4586493023634136E-01, 0.4868264913684867E-01, 0.9115921349407204E+00, 0.9646646288612479E+00, 0.1030014605117353E+00, 0.2184840619043245E+00, 0.2046221921921390E+01, 0.1891673744281760E+01, 0.6518220171905387E-01, 0.3708364593761750E-01, 0.1076216474932694E+01, 0.1166419383934860E+01, 0.1285328723941422E+00, 0.1934189785315259E+00, 0.1755252501385274E+01, 0.1804883149953014E+01, 0.2442959445536252E+00, 0.1482587897978486E+00, 0.1095350936043985E+01, 0.9535262710524167E+00, 0.7680442260639305E-02, 0.9145359161143373E-02, 0.1135395583018709E+01, 0.1130094305914509E+01, 0.5090399511302622E-02, 0.1416986451145964E-02, 0.3145781222952156E+00, 0.3154531349760448E+00, 0.3538316586334169E-02, 0.1216353924418735E-02, 0.1084421501965814E+00, 0.1133548658237420E+00, 0.7375387005938499E-02, 0.9088178357782586E-03, 0.1396793466565477E-01, 0.1197200684467082E-01, 0.1592074691534444E-03, 0.1681378409852773E-04, 0.1264354865903830E-02, 0.1223627446170173E-05, 0.6512368848977837E-06, 0.2970373645586866E-06, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + tau: 1.2218877946904154E-006, + sigma: 9.7516636666659787E-002, + i0Out: 1, + n0Out: 18, + ppOut: 1, + tauOut: 1.2218877946904154E-006, + sigmaOut: 9.7516636666659787E-002, + dminOut: 9.5986727915820745E-012, + dmin1Out: 1.1875197612370336E-002, + dmin2Out: 0.11291768719739126, + dnOut: 9.5986727915820745E-012, + dnm1Out: 1.1875197612370336E-002, + dnm2Out: 0.11291768719739126, + }, + { + z: []float64{0.2383459406360114E+01, 0.2383460331210544E+01, 0.1353283656358167E-06, 0.2970373645586866E-06, 0.1085901506809686E+01, 0.1085889199499347E+01, 0.1986826396898849E-04, 0.1366452649899944E-04, 0.1584986515403004E+01, 0.1578904163506652E+01, 0.3190255011763210E-02, 0.6103442048115082E-02, 0.9412930918090910E+00, 0.8284687778600495E+00, 0.1576208411525267E+00, 0.1160157908485996E+00, 0.1332062774397564E+01, 0.1278855299065544E+01, 0.1143821023097510E+00, 0.2108295383723412E+00, 0.7987861757106404E+00, 0.7226887736910288E+00, 0.3654761154847582E+00, 0.1904807262171572E+00, 0.1274050092339202E+01, 0.1532634164092948E+01, 0.7205613198290631E-01, 0.1068932656188067E+00, 0.8354550922133908E+00, 0.8588297969472432E+00, 0.5621179414582513E-01, 0.4868264913684867E-01, 0.1126935674731953E+01, 0.9646646288612479E+00, 0.3667472533840468E+00, 0.2184840619043245E+00, 0.1562008914947536E+01, 0.1891673744281760E+01, 0.2769195683500124E-01, 0.3708364593761750E-01, 0.1332145183743590E+01, 0.1166419383934860E+01, 0.2620575140703801E+00, 0.1934189785315259E+00, 0.1691083203792688E+01, 0.1804883149953014E+01, 0.8359650824372877E-01, 0.1482587897978486E+00, 0.8790739000820365E+00, 0.9535262710524167E+00, 0.1175682535061811E-01, 0.9145359161143373E-02, 0.1119753245127243E+01, 0.1130094305914509E+01, 0.3991886785572840E-03, 0.1416986451145964E-02, 0.3162690783341116E+00, 0.3154531349760448E+00, 0.4359567385560517E-03, 0.1216353924418735E-02, 0.1138265050331695E+00, 0.1133548658237420E+00, 0.9558734450579545E-04, 0.9088178357782586E-03, 0.1189201139646886E-01, 0.1197200684467082E-01, 0.1730052806966466E-08, 0.1681378409852773E-04, 0.9598672791582074E-11, 0.1223627446170173E-05, 0.1353283656358167E-06, 0.2970373645586866E-06}, + i0: 1, + n0: 18, + pp: 0, + tau: 9.5986713933289272E-012, + sigma: 9.7517858554454467E-002, + i0Out: 1, + n0Out: 18, + ppOut: 0, + tauOut: 9.5986713933289272E-012, + sigmaOut: 9.7517858554454467E-002, + dminOut: 6.6174125886815435E-022, + dmin1Out: 1.1882019541390456E-002, + dmin2Out: 0.11366976186212303, + dnOut: 6.6174125886815435E-022, + dnm1Out: 1.1882019541390456E-002, + dnm2Out: 0.11366976186212303, + }, + { + z: []float64{0.2383459406360114E+01, 0.2383459541678881E+01, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.1085901506809686E+01, 0.1085921313408604E+01, 0.1986826396898849E-04, 0.2899927470478232E-04, 0.1584986515403004E+01, 0.1588147771130463E+01, 0.3190255011763210E-02, 0.1890859942802736E-02, 0.9412930918090910E+00, 0.1097023073009216E+01, 0.1576208411525267E+00, 0.1913914667196325E+00, 0.1332062774397564E+01, 0.1255053409978084E+01, 0.1143821023097510E+00, 0.7279916643176543E-01, 0.7987861757106404E+00, 0.1091463124754034E+01, 0.3654761154847582E+00, 0.4266153094141972E+00, 0.1274050092339202E+01, 0.9194909148983121E+00, 0.7205613198290631E-01, 0.6547064404326042E-01, 0.8354550922133908E+00, 0.8261962423063568E+00, 0.5621179414582513E-01, 0.7667315937770838E-01, 0.1126935674731953E+01, 0.1417009768728692E+01, 0.3667472533840468E+00, 0.4042756034295816E+00, 0.1562008914947536E+01, 0.1185425268343357E+01, 0.2769195683500124E-01, 0.3111938635974581E-01, 0.1332145183743590E+01, 0.1563083311444625E+01, 0.2620575140703801E+00, 0.2835172362390010E+00, 0.1691083203792688E+01, 0.1491162475787817E+01, 0.8359650824372877E-01, 0.4928202642453804E-01, 0.8790739000820365E+00, 0.8415486989985177E+00, 0.1175682535061811E-01, 0.1564347179719430E-01, 0.1119753245127243E+01, 0.1104508961999007E+01, 0.3991886785572840E-03, 0.1143051254380294E-03, 0.3162690783341116E+00, 0.3165907299376309E+00, 0.4359567385560517E-03, 0.1567431614478116E-03, 0.1138265050331695E+00, 0.1137653492066288E+00, 0.9558734450579545E-04, 0.9991845479738400E-05, 0.1189201139646886E-01, 0.1188202127144326E-01, 0.1730052806966466E-08, 0.1397591405272086E-17, 0.9598672791582074E-11, 0.6617412588681544E-21, 0.1353283656358167E-06, 0.6165545233233256E-07, 0.2818174710670554E-01}, + i0: 1, + n0: 18, + pp: 1, + tau: 6.6174125886815426E-022, + sigma: 9.7517858564053150E-002, + i0Out: 1, + n0Out: 18, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 9.7517858564053150E-002, + dminOut: 6.6174125886815426E-022, + dmin1Out: 1.1880977265773463E-002, + dmin2Out: 0.11370904624558997, + dnOut: 6.6174125886815426E-022, + dnm1Out: 1.1880977265773463E-002, + dnm2Out: 0.11370904624558997, + }, + { + z: []float64{0.2383459603334333E+01, 0.2383459541678881E+01, 0.2809066689524106E-07, 0.6165545233233256E-07, 0.1085950284592642E+01, 0.1085921313408604E+01, 0.4240998334843304E-04, 0.2899927470478232E-04, 0.1589996221089918E+01, 0.1588147771130463E+01, 0.1304604978030436E-02, 0.1890859942802736E-02, 0.1287109934750819E+01, 0.1097023073009216E+01, 0.1866247058326724E+00, 0.1913914667196325E+00, 0.1141227870577177E+01, 0.1255053409978084E+01, 0.6962466280543776E-01, 0.7279916643176543E-01, 0.1448453771362794E+01, 0.1091463124754034E+01, 0.2708190685256155E+00, 0.4266153094141972E+00, 0.7141424904159570E+00, 0.9194909148983121E+00, 0.7574342769943966E-01, 0.6547064404326042E-01, 0.8271259739846255E+00, 0.8261962423063568E+00, 0.1313543755784947E+00, 0.7667315937770838E-01, 0.1689930996579779E+01, 0.1417009768728692E+01, 0.2835846650840220E+00, 0.4042756034295816E+00, 0.9329599896190804E+00, 0.1185425268343357E+01, 0.5213749144931325E-01, 0.3111938635974581E-01, 0.1794463056234313E+01, 0.1563083311444625E+01, 0.2355970842920850E+00, 0.2835172362390010E+00, 0.1304847417920270E+01, 0.1491162475787817E+01, 0.3178396542921673E-01, 0.4928202642453804E-01, 0.8254082053664953E+00, 0.8415486989985177E+00, 0.2093310277804656E-01, 0.1564347179719430E-01, 0.1083690164346398E+01, 0.1104508961999007E+01, 0.3339325601415243E-04, 0.1143051254380294E-03, 0.3167140798430647E+00, 0.3165907299376309E+00, 0.5630296103885627E-04, 0.1567431614478116E-03, 0.1137190380910697E+00, 0.1137653492066288E+00, 0.1044005669799533E-05, 0.9991845479738400E-05, 0.1188097726577346E-01, 0.1188202127144326E-01, 0.7784240935906335E-37, 0.1397591405272086E-17}, + i0: 1, + n0: 17, + pp: 0, + tau: 1.1880832155707781E-002, + sigma: 9.7517858564053150E-002, + i0Out: 1, + n0Out: 17, + ppOut: 0, + tauOut: 1.1880832155707781E-002, + sigmaOut: 9.7517858564053150E-002, + dminOut: 2.3287035572430725E-008, + dmin1Out: 0.10181720511285566, + dmin2Out: 0.30482311636216664, + dnOut: 2.3287035572430725E-008, + dnm1Out: 0.10181720511285566, + dnm2Out: 0.30482311636216664, + }, + { + z: []float64{0.2383459603334333E+01, 0.2371578799269292E+01, 0.2809066689524106E-07, 0.1286276792433928E-07, 0.1085950284592642E+01, 0.1074111849557515E+01, 0.4240998334843304E-04, 0.6277904232066118E-04, 0.1589996221089918E+01, 0.1579357214869920E+01, 0.1304604978030436E-02, 0.1063198377376995E-02, 0.1287109934750819E+01, 0.1460790610050406E+01, 0.1866247058326724E+00, 0.1457986614708343E+00, 0.1141227870577177E+01, 0.1053173039756072E+01, 0.6962466280543776E-01, 0.9575644420574685E-01, 0.1448453771362794E+01, 0.1611635563526955E+01, 0.2708190685256155E+00, 0.1200044280642223E+00, 0.7141424904159570E+00, 0.6580006578954666E+00, 0.7574342769943966E-01, 0.9521169265880262E-01, 0.8271259739846255E+00, 0.8513878247486099E+00, 0.1313543755784947E+00, 0.2607270439790754E+00, 0.1689930996579779E+01, 0.1700907785529018E+01, 0.2835846650840220E+00, 0.1555482010511415E+00, 0.9329599896190804E+00, 0.8176684478615445E+00, 0.5213749144931325E-01, 0.1144214412274440E+00, 0.1794463056234313E+01, 0.1903757867143247E+01, 0.2355970842920850E+00, 0.1614796988702029E+00, 0.1304847417920270E+01, 0.1163270852323576E+01, 0.3178396542921673E-01, 0.2255256874351997E-01, 0.8254082053664953E+00, 0.8119079072453143E+00, 0.2093310277804656E-01, 0.2794035799797570E-01, 0.1083690164346398E+01, 0.1043902367448729E+01, 0.3339325601415243E-04, 0.1013132519024162E-04, 0.3167140798430647E+00, 0.3048794193232055E+00, 0.5630296103885627E-04, 0.2100082250625822E-04, 0.1137190380910697E+00, 0.1018182491185255E+00, 0.1044005669799533E-05, 0.1218230301111122E-06, 0.1188097726577346E-01, 0.2328703557243073E-07, 0.7784240935906335E-37, 0.1286276792433928E-07, 0.9751785856405315E-01}, + i0: 1, + n0: 17, + pp: 1, + tau: 2.3287007705477136E-008, + sigma: 0.10939869071976092, + i0Out: 1, + n0Out: 17, + ppOut: 1, + tauOut: 2.3287007705477136E-008, + sigmaOut: 0.10939869071976092, + dminOut: 2.6961654281145418E-018, + dmin1Out: 0.10181121275944585, + dmin2Out: 0.30487633314418217, + dnOut: 2.6961654281145418E-018, + dnm1Out: 0.10181121275944585, + dnm2Out: 0.30487633314418217, + }, + { + z: []float64{0.2371578788845052E+01, 0.2371578799269292E+01, 0.5825676764620370E-08, 0.1286276792433928E-07, 0.1074174599487151E+01, 0.1074111849557515E+01, 0.9230392664199863E-04, 0.6277904232066118E-04, 0.1580328086033647E+01, 0.1579357214869920E+01, 0.9827770701659698E-03, 0.1063198377376995E-02, 0.1605606471164067E+01, 0.1460790610050406E+01, 0.9563440497488795E-01, 0.1457986614708343E+00, 0.1053295055699924E+01, 0.1053173039756072E+01, 0.1465159169633776E+00, 0.9575644420574685E-01, 0.1585124051340792E+01, 0.1611635563526955E+01, 0.4981502397231050E-01, 0.1200044280642223E+00, 0.7033973032949510E+00, 0.6580006578954666E+00, 0.1152436546510613E+00, 0.9521169265880262E-01, 0.9968711907896164E+00, 0.8513878247486099E+00, 0.4448645553200346E+00, 0.2607270439790754E+00, 0.1411591407973117E+01, 0.1700907785529018E+01, 0.9010174998427344E-01, 0.1555482010511415E+00, 0.8419881158177074E+00, 0.8176684478615445E+00, 0.2587099684834221E+00, 0.1144214412274440E+00, 0.1806527574243020E+01, 0.1903757867143247E+01, 0.1039810460775319E+00, 0.1614796988702029E+00, 0.1081842351702556E+01, 0.1163270852323576E+01, 0.1692539477932339E-01, 0.2255256874351997E-01, 0.8229228471769590E+00, 0.8119079072453143E+00, 0.3544318396494814E-01, 0.2794035799797570E-01, 0.1008469291521964E+01, 0.1043902367448729E+01, 0.3062892015595061E-05, 0.1013132519024162E-04, 0.3048973339666884E+00, 0.3048794193232055E+00, 0.7013072071892081E-05, 0.2100082250625822E-04, 0.1018113345824760E+00, 0.1018182491185255E+00, 0.2786425742647189E-13, 0.1218230301111122E-06, 0.2696165428114542E-17, 0.2328703557243073E-07, 0.5825676764620370E-08, 0.1286276792433928E-07}, + i0: 1, + n0: 17, + pp: 0, + tau: 2.6961654281138038E-018, + sigma: 0.10939871400676864, + i0Out: 1, + n0Out: 17, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 0.10939871400676864, + dminOut: 2.6961654281138038E-018, + dmin1Out: 0.10180899282350273, + dmin2Out: 0.30489636738914000, + dnOut: 2.6961654281138038E-018, + dnm1Out: 0.10180899282350273, + dnm2Out: 0.30489636738914000, + }, + { + z: []float64{0.2371578788845052E+01, 0.2371578794670729E+01, 0.5825676764620370E-08, 0.2638661645752538E-08, 0.1074174599487151E+01, 0.1074266900775131E+01, 0.9230392664199863E-04, 0.1357860766428602E-03, 0.1580328086033647E+01, 0.1581175077027170E+01, 0.9827770701659698E-03, 0.9979623676695663E-03, 0.1605606471164067E+01, 0.1700242913771285E+01, 0.9563440497488795E-01, 0.5924520849284005E-01, 0.1053295055699924E+01, 0.1140565764170461E+01, 0.1465159169633776E+00, 0.2036234219705987E+00, 0.1585124051340792E+01, 0.1431315653342504E+01, 0.4981502397231050E-01, 0.2448080089382756E-01, 0.7033973032949510E+00, 0.7941601570521848E+00, 0.1152436546510613E+00, 0.1446598374682775E+00, 0.9968711907896164E+00, 0.1297075908641373E+01, 0.4448645553200346E+00, 0.4841405038964208E+00, 0.1411591407973117E+01, 0.1017552654060970E+01, 0.9010174998427344E-01, 0.7455594793877945E-01, 0.8419881158177074E+00, 0.1026142136362350E+01, 0.2587099684834221E+00, 0.4554599945126984E+00, 0.1806527574243020E+01, 0.1455048625807853E+01, 0.1039810460775319E+00, 0.7731088667813635E-01, 0.1081842351702556E+01, 0.1021456859803743E+01, 0.1692539477932339E-01, 0.1363571444815687E-01, 0.8229228471769590E+00, 0.8447303166937503E+00, 0.3544318396494814E-01, 0.4231334180394086E-01, 0.1008469291521964E+01, 0.9661590126100381E+00, 0.3062892015595061E-05, 0.9665775484099522E-06, 0.3048973339666884E+00, 0.3049033804612119E+00, 0.7013072071892081E-05, 0.2341758973227438E-05, 0.1018113345824760E+00, 0.1018089928235306E+00, 0.2786425742647189E-13, 0.7379175991216932E-30, 0.1093987140067686E+00}, + i0: 1, + n0: 16, + pp: 1, + tau: 0.10180650470263587, + sigma: 0.10939871400676864, + i0Out: 1, + n0Out: 16, + ppOut: 1, + tauOut: 0.10180650470263587, + sigmaOut: 0.10939871400676864, + dminOut: 1.3142485785350155E-006, + dmin1Out: 0.20309651253108729, + dmin2Out: 0.57610166617362735, + dnOut: 1.3142485785350155E-006, + dnm1Out: 0.20309651253108729, + dnm2Out: 0.81137144083676127, + }, + { + z: []float64{0.2269772292606755E+01, 0.2371578794670729E+01, 0.1248859578385863E-08, 0.2638661645752538E-08, 0.9725961809002787E+00, 0.1074266900775131E+01, 0.2207509801202943E-03, 0.1357860766428602E-03, 0.1480145783712083E+01, 0.1581175077027170E+01, 0.1146359002276934E-02, 0.9979623676695663E-03, 0.1656535258559212E+01, 0.1700242913771285E+01, 0.4079180092843103E-01, 0.5924520849284005E-01, 0.1201590880509993E+01, 0.1140565764170461E+01, 0.2425529321011353E+00, 0.2036234219705987E+00, 0.1111437017432560E+01, 0.1431315653342504E+01, 0.1749237822536809E-01, 0.2448080089382756E-01, 0.8195211115924584E+00, 0.7941601570521848E+00, 0.2289566278084960E+00, 0.1446598374682775E+00, 0.1450453280026662E+01, 0.1297075908641373E+01, 0.3396444831847066E+00, 0.4841405038964208E+00, 0.6506576141124067E+00, 0.1017552654060970E+01, 0.1175810411452473E+00, 0.7455594793877945E-01, 0.1262214585027166E+01, 0.1026142136362350E+01, 0.5250426092262996E+00, 0.4554599945126984E+00, 0.9055103985570538E+00, 0.1455048625807853E+01, 0.8721019179982008E-01, 0.7731088667813635E-01, 0.8460758777494440E+00, 0.1021456859803743E+01, 0.1361402882064932E-01, 0.1363571444815687E-01, 0.7716231249744060E+00, 0.8447303166937503E+00, 0.5298106707064092E-01, 0.4231334180394086E-01, 0.8113724074143097E+00, 0.9661590126100381E+00, 0.3632274887524200E-06, 0.9665775484099522E-06, 0.2030988542900605E+00, 0.3049033804612119E+00, 0.1173872316183806E-05, 0.2341758973227438E-05, 0.1314248578535016E-05, 0.1018089928235306E+00, 0.1248859578385863E-08, 0.2638661645752538E-08}, + i0: 1, + n0: 16, + pp: 0, + tau: 1.3142409824136984E-006, + sigma: 0.21120521870940451, + i0Out: 1, + n0Out: 16, + ppOut: 0, + tauOut: 1.3142409824136984E-006, + sigmaOut: 0.21120521870940451, + dminOut: 8.4118841991824567E-018, + dmin1Out: 0.20309744276965425, + dmin2Out: 0.50018599148866161, + dnOut: 8.4118841991824567E-018, + dnm1Out: 0.20309744276965425, + dnm2Out: 0.75834178007645303, + }, + { + z: []float64{0.2269772292606755E+01, 0.2269770979614632E+01, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.9725961809002787E+00, 0.9728156171042807E+00, 0.2207509801202943E-03, 0.3358741643642203E-03, 0.1480145783712083E+01, 0.1480954954309013E+01, 0.1146359002276934E-02, 0.1282269997958535E-02, 0.1656535258559212E+01, 0.1696043475248702E+01, 0.4079180092843103E-01, 0.2889964597634762E-01, 0.1201590880509993E+01, 0.1415242852393798E+01, 0.2425529321011353E+00, 0.1904848393814713E+00, 0.1111437017432560E+01, 0.9384432420354740E+00, 0.1749237822536809E-01, 0.1527569554079381E-01, 0.8195211115924584E+00, 0.1033200729619178E+01, 0.2289566278084960E+00, 0.3214195289148511E+00, 0.1450453280026662E+01, 0.1468676920055535E+01, 0.3396444831847066E+00, 0.1504703083827628E+00, 0.6506576141124067E+00, 0.6177670326339089E+00, 0.1175810411452473E+00, 0.2402402478867145E+00, 0.1262214585027166E+01, 0.1547015632125768E+01, 0.5250426092262996E+00, 0.3073217441808570E+00, 0.9055103985570538E+00, 0.6853975319350345E+00, 0.8721019179982008E-01, 0.1076549537133787E+00, 0.8460758777494440E+00, 0.7520336386157322E+00, 0.1361402882064932E-01, 0.1396865635082151E-01, 0.7716231249744060E+00, 0.8106342214532430E+00, 0.5298106707064092E-01, 0.5302931309687425E-01, 0.8113724074143097E+00, 0.7583421433039418E+00, 0.3632274887524200E-06, 0.9727942389020712E-07, 0.2030988542900605E+00, 0.2030986166419704E+00, 0.1173872316183806E-05, 0.7596112905317353E-11, 0.1314248578535016E-05, 0.8411884199182457E-17, 0.1248859578385863E-08, 0.5351359530665278E-09, 0.1093987140067686E+00}, + i0: 1, + n0: 16, + pp: 1, + tau: 8.4118841988678429E-018, + sigma: 0.21120653295038691, + i0Out: 1, + n0Out: 16, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 0.21120653295038691, + dminOut: 8.4118841988678429E-018, + dmin1Out: 0.20309858884628909, + dmin2Out: 0.53283137411117854, + dnOut: 8.4118841988678429E-018, + dnm1Out: 0.20309858884628909, + dnm2Out: 0.71080515929391042, + }, + { + z: []float64{0.2269770980149768E+01, 0.2269770979614632E+01, 0.2293573303077261E-09, 0.5351359530665278E-09, 0.9731514910392876E+00, 0.9728156171042807E+00, 0.5111377954200868E-03, 0.3358741643642203E-03, 0.1481726086511552E+01, 0.1480954954309013E+01, 0.1467737987028945E-02, 0.1282269997958535E-02, 0.1723475383238021E+01, 0.1696043475248702E+01, 0.2373112943910766E-01, 0.2889964597634762E-01, 0.1581996562336162E+01, 0.1415242852393798E+01, 0.1129959536471923E+00, 0.1904848393814713E+00, 0.8407229839290754E+00, 0.9384432420354740E+00, 0.1877296098701645E-01, 0.1527569554079381E-01, 0.1335847297547013E+01, 0.1033200729619178E+01, 0.3533797947109679E+00, 0.3214195289148511E+00, 0.1265767433727330E+01, 0.1468676920055535E+01, 0.7343813202351114E-01, 0.1504703083827628E+00, 0.7845691484971122E+00, 0.6177670326339089E+00, 0.4737063898809231E+00, 0.2402402478867145E+00, 0.1380630986425702E+01, 0.1547015632125768E+01, 0.1525661578238559E+00, 0.3073217441808570E+00, 0.6404863278245572E+00, 0.6853975319350345E+00, 0.1264041760751794E+00, 0.1076549537133787E+00, 0.6395981188913744E+00, 0.7520336386157322E+00, 0.1770404028911661E-01, 0.1396865635082151E-01, 0.8459594942610007E+00, 0.8106342214532430E+00, 0.4753698401003136E-01, 0.5302931309687425E-01, 0.7108052565733343E+00, 0.7583421433039418E+00, 0.2779568135873871E-07, 0.9727942389020712E-07, 0.2030985888538852E+00, 0.2030986166419704E+00, 0.3146138162949754E-27, 0.7596112905317353E-11, 0.8411884198867843E-17, 0.8411884199182457E-17, 0.2293573303077261E-09, 0.5351359530665278E-09}, + i0: 1, + n0: 16, + pp: 0, + tau: 8.4118841988678429E-018, + sigma: 0.21120653295038691, + i0Out: 1, + n0Out: 16, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 0.21120653295038691, + dminOut: 8.4118841988678429E-018, + dmin1Out: 0.20309858045029386, + dmin2Out: 0.51860540644834729, + dnOut: 8.4118841988678429E-018, + dnm1Out: 0.20309858045029386, + dnm2Out: 0.67176795876146822, + }, + { + z: []float64{0.2269770980149768E+01, 0.2269770980379126E+01, 0.2293573303077261E-09, 0.9833566024906726E-10, 0.9731514910392876E+00, 0.9736626287363720E+00, 0.5111377954200868E-03, 0.7778528033461282E-03, 0.1481726086511552E+01, 0.1482415971695234E+01, 0.1467737987028945E-02, 0.1706410574351102E-02, 0.1723475383238021E+01, 0.1745500102102777E+01, 0.2373112943910766E-01, 0.2150819994097728E-01, 0.1581996562336162E+01, 0.1673484316042377E+01, 0.1129959536471923E+00, 0.5676676764251993E-01, 0.8407229839290754E+00, 0.8027291772735718E+00, 0.1877296098701645E-01, 0.3124068479314146E-01, 0.1335847297547013E+01, 0.1657986407464839E+01, 0.3533797947109679E+00, 0.2697830536296953E+00, 0.1265767433727330E+01, 0.1069422512121146E+01, 0.7343813202351114E-01, 0.5387701498318342E-01, 0.7845691484971122E+00, 0.1204398523394852E+01, 0.4737063898809231E+00, 0.5430210247136315E+00, 0.1380630986425702E+01, 0.9901761195359265E+00, 0.1525661578238559E+00, 0.9868601781741700E-01, 0.6404863278245572E+00, 0.6682044860823195E+00, 0.1264041760751794E+00, 0.1209927124430272E+00, 0.6395981188913744E+00, 0.5363094467374639E+00, 0.1770404028911661E-01, 0.2792585709699239E-01, 0.8459594942610007E+00, 0.8655706211740396E+00, 0.4753698401003136E-01, 0.3903729781186600E-01, 0.7108052565733343E+00, 0.6717679865571495E+00, 0.2779568135873871E-07, 0.8403591378512072E-08, 0.2030985888538852E+00, 0.2030985804502939E+00, 0.3146138162949754E-27, 0.1303059324279677E-43, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + tau: 0.10154929022514693, + sigma: 0.21120653295038691, + i0Out: 1, + n0Out: 15, + ppOut: 1, + tauOut: 0.10154929022514693, + sigmaOut: 0.21120653295038691, + dminOut: 0.10154928703201281, + dmin1Out: 0.32391205918605420, + dmin2Out: 0.32391205918605420, + dnOut: 0.10154928703201281, + dnm1Out: 0.53450854002684800, + dnm2Out: 0.69531980574199759, + }, + { + z: []float64{0.2168221690252314E+01, 0.2269770980379126E+01, 0.4415865678637858E-10, 0.9833566024906726E-10, 0.8728911912704126E+00, 0.9736626287363720E+00, 0.1321013925721922E-02, 0.7778528033461282E-03, 0.1381252078118717E+01, 0.1482415971695234E+01, 0.2156405683614187E-02, 0.1706410574351102E-02, 0.1663302606134993E+01, 0.1745500102102777E+01, 0.2163985983955575E-01, 0.2150819994097728E-01, 0.1607061933620194E+01, 0.1673484316042377E+01, 0.2835506195054301E-01, 0.5676676764251993E-01, 0.7040655098910235E+00, 0.8027291772735718E+00, 0.7356791380810462E-01, 0.3124068479314146E-01, 0.1752652257061283E+01, 0.1657986407464839E+01, 0.1646145547572216E+00, 0.2697830536296953E+00, 0.8571356821219610E+00, 0.1069422512121146E+01, 0.7570493055431493E-01, 0.5387701498318342E-01, 0.1570165327329021E+01, 0.1204398523394852E+01, 0.3424393862982660E+00, 0.5430210247136315E+00, 0.6448734608299306E+00, 0.9901761195359265E+00, 0.1022564019526126E+00, 0.9868601781741700E-01, 0.5853915063475871E+00, 0.6682044860823195E+00, 0.1108480973262629E+00, 0.1209927124430272E+00, 0.3518379162830466E+00, 0.5363094467374639E+00, 0.6870152520689508E-01, 0.2792585709699239E-01, 0.7343571035538636E+00, 0.8655706211740396E+00, 0.3571015630515456E-01, 0.3903729781186600E-01, 0.5345085484304394E+00, 0.6717679865571495E+00, 0.3193134112956561E-08, 0.8403591378512072E-08, 0.1015492870320128E+00, 0.2030985804502939E+00, 0.4415865678637858E-10, 0.9833566024906726E-10}, + i0: 1, + n0: 15, + pp: 0, + tau: 0.10154100618138810, + sigma: 0.31275582317553385, + i0Out: 1, + n0Out: 15, + ppOut: 0, + tauOut: 0.10154100618138810, + sigmaOut: 0.31275582317553385, + dminOut: 8.2800215414347011E-006, + dmin1Out: 0.16866357962181588, + dmin2Out: 0.16866357962181588, + dnOut: 8.2800215414347011E-006, + dnm1Out: 0.39110725789187228, + dnm2Out: 0.42026820370851276, + }, + { + z: []float64{0.2168221690252314E+01, 0.2066680684115085E+01, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.8728911912704126E+00, 0.7726711989960955E+00, 0.1321013925721922E-02, 0.2361487308570419E-02, 0.1381252078118717E+01, 0.1279505990312372E+01, 0.2156405683614187E-02, 0.2803234389363145E-02, 0.1663302606134993E+01, 0.1580598225403798E+01, 0.2163985983955575E-01, 0.2200217261925751E-01, 0.1607061933620194E+01, 0.1511873816770092E+01, 0.2835506195054301E-01, 0.1320468740761088E-01, 0.7040655098910235E+00, 0.6628877301101292E+00, 0.7356791380810462E-01, 0.1945110224949301E+00, 0.1752652257061283E+01, 0.1621214783142186E+01, 0.1646145547572216E+00, 0.8703165684534678E-01, 0.8571356821219610E+00, 0.7442679496495411E+00, 0.7570493055431493E-01, 0.1597129865933493E+00, 0.1570165327329021E+01, 0.1651350720852550E+01, 0.3424393862982660E+00, 0.1337269360034139E+00, 0.6448734608299306E+00, 0.5118619205977412E+00, 0.1022564019526126E+00, 0.1169456581236225E+00, 0.5853915063475871E+00, 0.4777529393688394E+00, 0.1108480973262629E+00, 0.8163333047984263E-01, 0.3518379162830466E+00, 0.2373651048287110E+00, 0.6870152520689508E-01, 0.2125478936639627E+00, 0.7343571035538636E+00, 0.4559783600136673E+00, 0.3571015630515456E-01, 0.4186028435717903E-01, 0.5345085484304394E+00, 0.3911072610850064E+00, 0.3193134112956561E-08, 0.8290832843879624E-09, 0.1015492870320128E+00, 0.8280021541434701E-05, 0.4415865678637858E-10, 0.1865101988102620E-10, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + tau: 8.2795951083136037E-006, + sigma: 0.41429682935692197, + i0Out: 1, + n0Out: 15, + ppOut: 1, + tauOut: 8.2795951083136037E-006, + sigmaOut: 0.41429682935692197, + dminOut: 4.2641220534843968E-010, + dmin1Out: 0.19554701532405336, + dmin2Out: 0.19554701532405336, + dnOut: 4.2641220534843968E-010, + dnm1Out: 0.32821333105682254, + dnm2Out: 0.21848306981706411, + }, + { + z: []float64{0.2066672404538628E+01, 0.2066680684115085E+01, 0.6973096395115281E-11, 0.1865101988102620E-10, 0.7750244067025847E+00, 0.7726711989960955E+00, 0.3898634844569491E-02, 0.2361487308570419E-02, 0.1278402310262057E+01, 0.1279505990312372E+01, 0.3465878671879142E-02, 0.2803234389363145E-02, 0.1599126239756068E+01, 0.1580598225403798E+01, 0.2080167773382635E-01, 0.2200217261925751E-01, 0.1504268546848768E+01, 0.1511873816770092E+01, 0.5818924606767697E-02, 0.1320468740761088E-01, 0.8515715484031834E+00, 0.6628877301101292E+00, 0.3703084558710277E+00, 0.1945110224949301E+00, 0.1337929704521397E+01, 0.1621214783142186E+01, 0.4841425717359337E-01, 0.8703165684534678E-01, 0.8555583994741887E+00, 0.7442679496495411E+00, 0.3082690272254148E+00, 0.1597129865933493E+00, 0.1476800350035441E+01, 0.1651350720852550E+01, 0.4635002036444261E-01, 0.1337269360034139E+00, 0.5824492787618127E+00, 0.5118619205977412E+00, 0.9592445892242578E-01, 0.1169456581236225E+00, 0.4634535313311479E+00, 0.4777529393688394E+00, 0.4180980990954932E-01, 0.8163333047984263E-01, 0.4080949089880160E+00, 0.2373651048287110E+00, 0.2374870106014949E+00, 0.2125478936639627E+00, 0.2603433541742431E+00, 0.4559783600136673E+00, 0.6288565043307552E-01, 0.4186028435717903E-01, 0.3282133318859058E+00, 0.3911072610850064E+00, 0.2091574834858362E-13, 0.8290832843879624E-09, 0.4264122053484397E-09, 0.8280021541434701E-05, 0.6973096395115281E-11, 0.1865101988102620E-10}, + i0: 1, + n0: 15, + pp: 0, + tau: 4.2641207498271701E-010, + sigma: 0.41430510895203027, + i0Out: 1, + n0Out: 15, + ppOut: 0, + tauOut: 4.2641207498271701E-010, + sigmaOut: 0.41430510895203027, + dminOut: 1.3036568472020817E-016, + dmin1Out: 0.15841174212052453, + dmin2Out: 0.15841174212052453, + dnOut: 1.3036568472020817E-016, + dnm1Out: 0.23494558610432464, + dnm2Out: 0.15841174212052453, + }, + { + z: []float64{0.2066672404538628E+01, 0.2066672404119188E+01, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.7750244067025847E+00, 0.7789230411181270E+00, 0.3898634844569491E-02, 0.6398608757305904E-02, 0.1278402310262057E+01, 0.1275469579750218E+01, 0.3465878671879142E-02, 0.4345362379476143E-02, 0.1599126239756068E+01, 0.1615582554684006E+01, 0.2080167773382635E-01, 0.1936843737632438E-01, 0.1504268546848768E+01, 0.1490719033652799E+01, 0.5818924606767697E-02, 0.3324054047451484E-02, 0.8515715484031834E+00, 0.1218555949800348E+01, 0.3703084558710277E+00, 0.4065850919906259E+00, 0.1337929704521397E+01, 0.9797588692779520E+00, 0.4841425717359337E-01, 0.4227695780870786E-01, 0.8555583994741887E+00, 0.1121550468464483E+01, 0.3082690272254148E+00, 0.4059129037098644E+00, 0.1476800350035441E+01, 0.1117237466263607E+01, 0.4635002036444261E-01, 0.2416365074306882E-01, 0.5824492787618127E+00, 0.6542100865147574E+00, 0.9592445892242578E-01, 0.6795451513972497E-01, 0.4634535313311479E+00, 0.4373088256745602E+00, 0.4180980990954932E-01, 0.3901675330591518E-01, 0.4080949089880160E+00, 0.6065651658571838E+00, 0.2374870106014949E+00, 0.1019316116273065E+00, 0.2603433541742431E+00, 0.2212973925536000E+00, 0.6288565043307552E-01, 0.9326774535516916E-01, 0.3282133318859058E+00, 0.2349455861043456E+00, 0.2091574834858362E-13, 0.3796083394336032E-22, 0.4264122053484397E-09, 0.1303656847202082E-15, 0.6973096395115281E-11, 0.2614986238618434E-11, 0.2112065329503869E+00}, + i0: 1, + n0: 15, + pp: 1, + tau: 1.3036568471812905E-016, + sigma: 0.41430510937844234, + i0Out: 1, + n0Out: 15, + ppOut: 1, + tauOut: 1.3036568471812905E-016, + sigmaOut: 0.41430510937844234, + dminOut: 2.0791168714198411E-027, + dmin1Out: 0.15670572686712736, + dmin2Out: 0.18680490956440032, + dnOut: 2.0791168714198411E-027, + dnm1Out: 0.15670572686712736, + dnm2Out: 0.18680490956440032, + }, + { + z: []float64{0.2066672404121803E+01, 0.2066672404119188E+01, 0.9855809897129084E-12, 0.2614986238618434E-11, 0.7853216498744473E+00, 0.7789230411181270E+00, 0.1039221422709001E-01, 0.6398608757305904E-02, 0.1269422727902604E+01, 0.1275469579750218E+01, 0.5530302475095172E-02, 0.4345362379476143E-02, 0.1629420689585235E+01, 0.1615582554684006E+01, 0.1771973219288664E-01, 0.1936843737632438E-01, 0.1476323355507364E+01, 0.1490719033652799E+01, 0.2743671176012720E-02, 0.3324054047451484E-02, 0.1622397370614960E+01, 0.1218555949800348E+01, 0.2455350071499520E+00, 0.4065850919906259E+00, 0.7765008199367077E+00, 0.9797588692779520E+00, 0.6106335063429082E-01, 0.4227695780870786E-01, 0.1466400021540057E+01, 0.1121550468464483E+01, 0.3092615230516922E+00, 0.4059129037098644E+00, 0.8321395939549830E+00, 0.1117237466263607E+01, 0.1899693772291602E-01, 0.2416365074306882E-01, 0.7031676639315663E+00, 0.6542100865147574E+00, 0.4226176876348708E-01, 0.6795451513972497E-01, 0.4340638102169883E+00, 0.4373088256745602E+00, 0.5452240634477346E-01, 0.3901675330591518E-01, 0.6539743711397168E+00, 0.6065651658571838E+00, 0.3449248298919955E-01, 0.1019316116273065E+00, 0.2800726549195695E+00, 0.2212973925536000E+00, 0.7823985923721809E-01, 0.9326774535516916E-01, 0.1567057268671274E+00, 0.2349455861043456E+00, 0.3158014839988858E-37, 0.3796083394336032E-22}, + i0: 1, + n0: 14, + pp: 0, + tau: 5.2226904068357879E-002, + sigma: 0.41430510937844245, + i0Out: 1, + n0Out: 14, + ppOut: 0, + tauOut: 5.2226904068357879E-002, + sigmaOut: 0.41430510937844245, + dminOut: 6.1979733096699005E-002, + dmin1Out: 0.21025182606004778, + dmin2Out: 0.35454858327394784, + dnOut: 6.1979733096699005E-002, + dnm1Out: 0.21025182606004778, + dnm2Out: 0.51458348500658069, + }, + { + z: []float64{0.2066672404121803E+01, 0.2014445500054431E+01, 0.9855809897129084E-12, 0.3842238913414725E-12, 0.7853216498744473E+00, 0.7434869600327952E+00, 0.1039221422709001E-01, 0.1774357001838869E-01, 0.1269422727902604E+01, 0.1204982556290953E+01, 0.5530302475095172E-02, 0.7478273627729330E-02, 0.1629420689585235E+01, 0.1587435244082034E+01, 0.1771973219288664E-01, 0.1647944669694028E-01, 0.1476323355507364E+01, 0.1410360675918078E+01, 0.2743671176012720E-02, 0.3156160674217245E-02, 0.1622397370614960E+01, 0.1812549313022337E+01, 0.2455350071499520E+00, 0.1051878329628395E+00, 0.7765008199367077E+00, 0.6801494335398012E+00, 0.6106335063429082E-01, 0.1316523902981273E+00, 0.1466400021540057E+01, 0.1591782250225264E+01, 0.3092615230516922E+00, 0.1616733433116970E+00, 0.8321395939549830E+00, 0.6372362842978442E+00, 0.1899693772291602E-01, 0.2096244776016672E-01, 0.7031676639315663E+00, 0.6722400808665288E+00, 0.4226176876348708E-01, 0.2728832287468248E-01, 0.4340638102169883E+00, 0.4090709896187213E+00, 0.5452240634477346E-01, 0.8716398206477828E-01, 0.6539743711397168E+00, 0.5490759679957803E+00, 0.3449248298919955E-01, 0.1759392479116377E-01, 0.2800726549195695E+00, 0.2884916852972659E+00, 0.7823985923721809E-01, 0.4249908970207047E-01, 0.1567057268671274E+00, 0.6197973309669901E-01, 0.3158014839988858E-37, 0.3842238913414725E-12, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + tau: 4.3992746597899146E-002, + sigma: 0.46653201344680034, + i0Out: 1, + n0Out: 14, + ppOut: 1, + tauOut: 4.3992746597899146E-002, + sigmaOut: 0.46653201344680034, + dminOut: 8.3978432207528000E-003, + dmin1Out: 0.23219513064786862, + dmin2Out: 0.34734604130905122, + dnOut: 8.3978432207528000E-003, + dnm1Out: 0.23219513064786862, + dnm2Out: 0.39493697562207530, + }, + { + z: []float64{0.1970452753456916E+01, 0.2014445500054431E+01, 0.1449745254963753E-12, 0.3842238913414725E-12, 0.7172377834531399E+00, 0.7434869600327952E+00, 0.2980976860358389E-01, 0.1774357001838869E-01, 0.1138658314717199E+01, 0.1204982556290953E+01, 0.1042566937606312E-01, 0.7478273627729330E-02, 0.1549496274805013E+01, 0.1587435244082034E+01, 0.1499968987352189E-01, 0.1647944669694028E-01, 0.1354524400120875E+01, 0.1410360675918078E+01, 0.4223398900256122E-02, 0.3156160674217245E-02, 0.1869521000487022E+01, 0.1812549313022337E+01, 0.3826832915293116E-01, 0.1051878329628395E+00, 0.7295407480870981E+00, 0.6801494335398012E+00, 0.2872518617030954E+00, 0.1316523902981273E+00, 0.1422210985235967E+01, 0.1591782250225264E+01, 0.7243940711431240E-01, 0.1616733433116970E+00, 0.5417665783457993E+00, 0.6372362842978442E+00, 0.2601082853889214E-01, 0.2096244776016672E-01, 0.6295248286044199E+00, 0.6722400808665288E+00, 0.1773220171177086E-01, 0.2728832287468248E-01, 0.4345100233738295E+00, 0.4090709896187213E+00, 0.1101462457758059E+00, 0.8716398206477828E-01, 0.4125309004132391E+00, 0.5490759679957803E+00, 0.1230380805149813E-01, 0.1759392479116377E-01, 0.2746942203499391E+00, 0.2884916852972659E+00, 0.9589143278047064E-02, 0.4249908970207047E-01, 0.8397843220752800E-02, 0.6197973309669901E-01, 0.1449745254963753E-12, 0.3842238913414725E-12}, + i0: 1, + n0: 14, + pp: 0, + tau: 8.0121275381568099E-003, + sigma: 0.51052476004469949, + i0Out: 1, + n0Out: 14, + ppOut: 0, + tauOut: 8.0121275381568099E-003, + sigmaOut: 0.51052476004469949, + dminOut: 8.3015533671799979E-005, + dmin1Out: 0.25644350373773794, + dmin2Out: 0.31779880038403513, + dnOut: 8.3015533671799979E-005, + dnm1Out: 0.25644350373773794, + dnm2Out: 0.31779880038403513, + }, + { + z: []float64{0.1970452753456916E+01, 0.1962440625918904E+01, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.7172377834531399E+00, 0.7390354245185139E+00, 0.2980976860358389E-01, 0.4592897681783073E-01, 0.1138658314717199E+01, 0.1095142879737275E+01, 0.1042566937606312E-01, 0.1475107600976594E-01, 0.1549496274805013E+01, 0.1541732761130612E+01, 0.1499968987352189E-01, 0.1317831886314191E-01, 0.1354524400120875E+01, 0.1337557352619832E+01, 0.4223398900256122E-02, 0.5903098601340335E-02, 0.1869521000487022E+01, 0.1893874103500456E+01, 0.3826832915293116E-01, 0.1474137347708128E-01, 0.7295407480870981E+00, 0.9940391087749554E+00, 0.2872518617030954E+00, 0.4109825756725979E+00, 0.1422210985235967E+01, 0.1075655689139524E+01, 0.7243940711431240E-01, 0.3648495529374628E-01, 0.5417665783457993E+00, 0.5232803240527883E+00, 0.2601082853889214E-01, 0.3129195122603765E-01, 0.6295248286044199E+00, 0.6079529515519964E+00, 0.1773220171177086E-01, 0.1267338099203561E-01, 0.4345100233738295E+00, 0.5239707606194429E+00, 0.1101462457758059E+00, 0.8671997249104711E-01, 0.4125309004132391E+00, 0.3301026084355332E+00, 0.1230380805149813E-01, 0.1023858907404432E-01, 0.2746942203499391E+00, 0.2660326470157850E+00, 0.9589143278047064E-02, 0.3027001489241909E-03, 0.8397843220752800E-02, 0.8301553367179998E-04, 0.1449745254963753E-12, 0.5298565773193886E-13, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + tau: 8.2898056486573887E-005, + sigma: 0.51853688758285632, + i0Out: 1, + n0Out: 14, + ppOut: 1, + tauOut: 8.2898056486573887E-005, + sigmaOut: 0.51853688758285632, + dminOut: 1.9676836973621424E-008, + dmin1Out: 0.25663722751477031, + dmin2Out: 0.28224921557690585, + dnOut: 1.9676836973621424E-008, + dnm1Out: 0.25663722751477031, + dnm2Out: 0.28224921557690585, + }, + { + z: []float64{0.1962357727862470E+01, 0.1962440625918904E+01, 0.1995470932711637E-13, 0.5298565773193886E-13, 0.7848815032798381E+00, 0.7390354245185139E+00, 0.6408456783027588E-01, 0.4592897681783073E-01, 0.1045726489860278E+01, 0.1095142879737275E+01, 0.2174776805091989E-01, 0.1475107600976594E-01, 0.1533080413886347E+01, 0.1541732761130612E+01, 0.1149760777771624E-01, 0.1317831886314191E-01, 0.1331879945386970E+01, 0.1337557352619832E+01, 0.8393943921304423E-02, 0.5903098601340335E-02, 0.1900138634999746E+01, 0.1893874103500456E+01, 0.7711806645770664E-02, 0.1474137347708128E-01, 0.1397226979745296E+01, 0.9940391087749554E+00, 0.3163950825942626E+00, 0.4109825756725979E+00, 0.7956626637825215E+00, 0.1075655689139524E+01, 0.2399491656225486E-01, 0.3648495529374628E-01, 0.5304944606600845E+00, 0.5232803240527883E+00, 0.3586094769777509E-01, 0.3129195122603765E-01, 0.5846824867897703E+00, 0.6079529515519964E+00, 0.1135741402906866E-01, 0.1267338099203561E-01, 0.5992504210249349E+00, 0.5239707606194429E+00, 0.4777049480214081E-01, 0.8671997249104711E-01, 0.2924878046509502E+00, 0.3301026084355332E+00, 0.9312521444528056E-02, 0.1023858907404432E-01, 0.2569399276636945E+00, 0.2660326470157850E+00, 0.9780034825247492E-07, 0.3027001489241909E-03, 0.1967683697362142E-07, 0.8301553367179998E-04, 0.1995470932711637E-13, 0.5298565773193886E-13}, + i0: 1, + n0: 14, + pp: 0, + tau: 1.9676827722764296E-008, + sigma: 0.51861978563934286, + i0Out: 1, + n0Out: 14, + ppOut: 0, + tauOut: 1.9676827722764296E-008, + sigmaOut: 0.51861978563934286, + dminOut: 1.5032959860012969E-015, + dmin1Out: 0.24838793989138258, + dmin2Out: 0.27047787997045275, + dnOut: 1.5032959860012969E-015, + dnm1Out: 0.24838793989138258, + dnm2Out: 0.27047787997045275, + }, + { + z: []float64{0.1962357727862470E+01, 0.1962357708185662E+01, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.7848815032798381E+00, 0.8489660514332782E+00, 0.6408456783027588E-01, 0.7893711422056097E-01, 0.1045726489860278E+01, 0.9885371240138099E+00, 0.2174776805091989E-01, 0.3372769361380378E-01, 0.1533080413886347E+01, 0.1510850308373431E+01, 0.1149760777771624E-01, 0.1013563894066502E-01, 0.1331879945386970E+01, 0.1330138230690781E+01, 0.8393943921304423E-02, 0.1199097716077874E-01, 0.1900138634999746E+01, 0.1895859444807910E+01, 0.7711806645770664E-02, 0.5683514322519618E-02, 0.1397226979745296E+01, 0.1707938528340212E+01, 0.3163950825942626E+00, 0.1473962616612956E+00, 0.7956626637825215E+00, 0.6722612990066530E+00, 0.2399491656225486E-01, 0.1893485515094503E-01, 0.5304944606600845E+00, 0.5474205335300870E+00, 0.3586094769777509E-01, 0.3830193935796279E-01, 0.5846824867897703E+00, 0.5577379417840483E+00, 0.1135741402906866E-01, 0.1220274725600271E-01, 0.5992504210249349E+00, 0.6348181488942451E+00, 0.4777049480214081E-01, 0.2200990500366971E-01, 0.2924878046509502E+00, 0.2797904014149808E+00, 0.9312521444528056E-02, 0.8551968095484232E-02, 0.2569399276636945E+00, 0.2483880376917308E+00, 0.9780034825247492E-07, 0.7747561140265878E-14, 0.1967683697362142E-07, 0.1503295986001297E-14, 0.1995470932711637E-13, 0.7981257539768321E-14, 0.4143051093784424E+00}, + i0: 1, + n0: 14, + pp: 1, + tau: 1.5032959860012393E-015, + sigma: 0.51861980531617058, + i0Out: 1, + n0Out: 14, + ppOut: 1, + tauOut: 1.5032959860012393E-015, + sigmaOut: 0.51861980531617058, + dminOut: 9.2691156363468887E-030, + dmin1Out: 0.24076768543540897, + dmin2Out: 0.27020241256687788, + dnOut: 9.2691156363468887E-030, + dnm1Out: 0.24076768543540897, + dnm2Out: 0.27020241256687788, + }, + { + z: []float64{0.1962357708185669E+01, 0.1962357708185662E+01, 0.3452895805257589E-14, 0.7981257539768321E-14, 0.9279031656538340E+00, 0.8489660514332782E+00, 0.8409527066820451E-01, 0.7893711422056097E-01, 0.9381695469594078E+00, 0.9885371240138099E+00, 0.5431587122209677E-01, 0.3372769361380378E-01, 0.1466670076091998E+01, 0.1510850308373431E+01, 0.9192115573380727E-02, 0.1013563894066502E-01, 0.1332937092278178E+01, 0.1330138230690781E+01, 0.1705497388769041E-01, 0.1199097716077874E-01, 0.1884487985242738E+01, 0.1895859444807910E+01, 0.5151050664063701E-02, 0.5683514322519618E-02, 0.1850183739337442E+01, 0.1707938528340212E+01, 0.5355619565040129E-01, 0.1473962616612956E+00, 0.6376399585071952E+00, 0.6722612990066530E+00, 0.1625577000116482E-01, 0.1893485515094503E-01, 0.5694667028868834E+00, 0.5474205335300870E+00, 0.3751307094084999E-01, 0.3830193935796279E-01, 0.5324276180991995E+00, 0.5577379417840483E+00, 0.1454944326918194E-01, 0.1220274725600271E-01, 0.6422786106287314E+00, 0.6348181488942451E+00, 0.9587988848101409E-02, 0.2200990500366971E-01, 0.2787543806623621E+00, 0.2797904014149808E+00, 0.7620352256320365E-02, 0.8551968095484232E-02, 0.2407676854354167E+00, 0.2483880376917308E+00, 0.4837392336267432E-28, 0.7747561140265878E-14}, + i0: 1, + n0: 13, + pp: 0, + tau: 0.19361025134591583, + sigma: 0.51861980531617213, + i0Out: 1, + n0Out: 13, + ppOut: 0, + tauOut: 0.19361025134591583, + sigmaOut: 0.51861980531617213, + dminOut: 2.5949209826162500E-002, + dmin1Out: 7.8890170839591350E-002, + dmin2Out: 0.28791033268116917, + dnOut: 2.5949209826162500E-002, + dnm1Out: 7.8890170839591350E-002, + dnm2Out: 0.41777236268627749, + }, + { + z: []float64{0.1962357708185669E+01, 0.1768747456839757E+01, 0.3452895805257589E-14, 0.1811424766142649E-14, 0.9279031656538340E+00, 0.8183881849761209E+00, 0.8409527066820451E-01, 0.9640366690596863E-01, 0.9381695469594078E+00, 0.7024714999296202E+00, 0.5431587122209677E-01, 0.1134045480653624E+00, 0.1466670076091998E+01, 0.1168847392254101E+01, 0.9192115573380727E-02, 0.1048255904531585E-01, 0.1332937092278178E+01, 0.1145899255774637E+01, 0.1705497388769041E-01, 0.2804774784346500E-01, 0.1884487985242738E+01, 0.1667981036717421E+01, 0.5151050664063701E-02, 0.5713728135608638E-02, 0.1850183739337442E+01, 0.1704415955506319E+01, 0.5355619565040129E-01, 0.2003593680404179E-01, 0.6376399585071952E+00, 0.4402495403584025E+00, 0.1625577000116482E-01, 0.2102698332839761E-01, 0.5694667028868834E+00, 0.3923425391534199E+00, 0.3751307094084999E-01, 0.5090703407211448E-01, 0.5324276180991995E+00, 0.3024597759503511E+00, 0.1454944326918194E-01, 0.3089599659653809E-01, 0.6422786106287314E+00, 0.4273603515343789E+00, 0.9587988848101409E-02, 0.6253958476854957E-02, 0.2787543806623621E+00, 0.8651052309591171E-01, 0.7620352256320365E-02, 0.2120822426333837E-01, 0.2407676854354167E+00, 0.2594920982616250E-01, 0.4837392336267432E-28, 0.1811424766142649E-14, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + tau: 1.8780556192507153E-002, + sigma: 0.71223005666208794, + i0Out: 1, + n0Out: 13, + ppOut: 1, + tauOut: 1.8780556192507153E-002, + sigmaOut: 0.71223005666208794, + dminOut: 8.7653100724300811E-004, + dmin1Out: 6.6256164803006098E-002, + dmin2Out: 0.24571773655185866, + dnOut: 8.7653100724300811E-004, + dnm1Out: 6.6256164803006098E-002, + dnm2Out: 0.36084635920253871, + }, + { + z: []float64{0.1749966900647251E+01, 0.1768747456839757E+01, 0.8471295234418270E-15, 0.1811424766142649E-14, 0.8960112956895816E+00, 0.8183881849761209E+00, 0.7558032897122403E-01, 0.9640366690596863E-01, 0.7215151628312513E+00, 0.7024714999296202E+00, 0.1837142406762631E+00, 0.1134045480653624E+00, 0.9768351544306461E+00, 0.1168847392254101E+01, 0.1229681032071614E-01, 0.1048255904531585E-01, 0.1142869637104878E+01, 0.1145899255774637E+01, 0.4093477506677201E-01, 0.2804774784346500E-01, 0.1613979433593750E+01, 0.1667981036717421E+01, 0.6033886923870183E-02, 0.5713728135608638E-02, 0.1699637449193983E+01, 0.1704415955506319E+01, 0.5189819730562233E-02, 0.2003593680404179E-01, 0.4373061477637308E+00, 0.4402495403584025E+00, 0.1886499897608887E-01, 0.2102698332839761E-01, 0.4056040180569384E+00, 0.3923425391534199E+00, 0.3796148320598534E-01, 0.5090703407211448E-01, 0.2766137331483968E+00, 0.3024597759503511E+00, 0.4773343613933298E-01, 0.3089599659653809E-01, 0.3671003176793937E+00, 0.4273603515343789E+00, 0.1473802100398464E-02, 0.6253958476854957E-02, 0.8746438906634448E-01, 0.8651052309591171E-01, 0.6292122626412339E-02, 0.2120822426333837E-01, 0.8765310072430081E-03, 0.2594920982616250E-01, 0.8471295234418270E-15, 0.1811424766142649E-14}, + i0: 1, + n0: 13, + pp: 0, + tau: 8.1622622999092049E-004, + sigma: 0.73101061285459512, + i0Out: 1, + n0Out: 13, + ppOut: 0, + tauOut: 8.1622622999092049E-004, + sigmaOut: 0.73101061285459512, + dminOut: 6.9556311345050133E-007, + dmin1Out: 8.6231166987816729E-002, + dmin2Out: 0.25114202935985525, + dnOut: 6.9556311345050133E-007, + dnm1Out: 8.6231166987816729E-002, + dnm2Out: 0.30765445605457048, + }, + { + z: []float64{0.1749966900647251E+01, 0.1749150674417261E+01, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.8960112956895816E+00, 0.9707753984308143E+00, 0.7558032897122403E-01, 0.5617401661873561E-01, 0.7215151628312513E+00, 0.8482391606587878E+00, 0.1837142406762631E+00, 0.2115659556707206E+00, 0.9768351544306461E+00, 0.7767497828506508E+00, 0.1229681032071614E-01, 0.1809289356632693E-01, 0.1142869637104878E+01, 0.1164895292375332E+01, 0.4093477506677201E-01, 0.5671572845129930E-01, 0.1613979433593750E+01, 0.1562481365836330E+01, 0.6033886923870183E-02, 0.6563547191183529E-02, 0.1699637449193983E+01, 0.1697447495503371E+01, 0.5189819730562233E-02, 0.1337031089310571E-02, 0.4373061477637308E+00, 0.4540178894205181E+00, 0.1886499897608887E-01, 0.1685334336738995E-01, 0.4056040180569384E+00, 0.4258959316655428E+00, 0.3796148320598534E-01, 0.2465547755855056E-01, 0.2766137331483968E+00, 0.2988754654991882E+00, 0.4773343613933298E-01, 0.5862963539483231E-01, 0.3671003176793937E+00, 0.3091282581549689E+00, 0.1473802100398464E-02, 0.4169958485368410E-03, 0.8746438906634448E-01, 0.9252328961422907E-01, 0.6292122626412339E-02, 0.5960921413863723E-04, 0.8765310072430081E-03, 0.6955631134505013E-06, 0.8471295234418270E-15, 0.4339463906783712E-15, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + tau: 6.9511331676175615E-007, + sigma: 0.73182683908458601, + i0Out: 1, + n0Out: 13, + ppOut: 1, + tauOut: 6.9511331676175615E-007, + sigmaOut: 0.73182683908458601, + dminOut: 1.2278907249223888E-012, + dmin1Out: 9.2372077429255559E-002, + dmin2Out: 0.25591158693238830, + dnOut: 1.2278907249223888E-012, + dnm1Out: 9.2372077429255559E-002, + dnm2Out: 0.25591158693238830, + }, + { + z: []float64{0.1749149979303945E+01, 0.1749150674417261E+01, 0.2408395422307052E-15, 0.4339463906783712E-15, 0.1026948719936233E+01, 0.9707753984308143E+00, 0.4639861736277134E-01, 0.5617401661873561E-01, 0.1013405803853420E+01, 0.8482391606587878E+00, 0.1621599259654447E+00, 0.2115659556707206E+00, 0.6326820553382161E+00, 0.7767497828506508E+00, 0.3331266686486833E-01, 0.1809289356632693E-01, 0.1188297658848447E+01, 0.1164895292375332E+01, 0.7457497555020480E-01, 0.5671572845129930E-01, 0.1494469242363992E+01, 0.1562481365836330E+01, 0.7455005714048079E-02, 0.6563547191183529E-02, 0.1691328825765317E+01, 0.1697447495503371E+01, 0.3589107121045615E-03, 0.1337031089310571E-02, 0.4705116269624868E+00, 0.4540178894205181E+00, 0.1525524548983380E-01, 0.1685334336738995E-01, 0.4352954686209429E+00, 0.4258959316655428E+00, 0.1692854133253905E-01, 0.2465547755855056E-01, 0.3405758644481647E+00, 0.2988754654991882E+00, 0.5321597610926388E-01, 0.5862963539483231E-01, 0.2563285827809251E+00, 0.3091282581549689E+00, 0.1505170716567330E-03, 0.4169958485368410E-03, 0.9243168664339420E-01, 0.9252328961422907E-01, 0.4485687980202113E-09, 0.5960921413863723E-04, 0.1227890724922389E-11, 0.6955631134505013E-06, 0.2408395422307052E-15, 0.4339463906783712E-15}, + i0: 1, + n0: 13, + pp: 0, + tau: 1.2278907189544363E-012, + sigma: 0.73182753419790281, + i0Out: 1, + n0Out: 13, + ppOut: 0, + tauOut: 1.2278907189544363E-012, + sigmaOut: 0.73182753419790281, + dminOut: 4.9598525010503808E-024, + dmin1Out: 9.2368632133320736E-002, + dmin2Out: 0.22049265431403467, + dnOut: 4.9598525010503808E-024, + dnm1Out: 9.2368632133320736E-002, + dnm2Out: 0.22049265431403467, + }, + { + z: []float64{0.1749149979303945E+01, 0.1749149979302717E+01, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.1026948719936233E+01, 0.1073347337297776E+01, 0.4639861736277134E-01, 0.4380746706334982E-01, 0.1013405803853420E+01, 0.1131758262754287E+01, 0.1621599259654447E+00, 0.9065158049178278E-01, 0.6326820553382161E+00, 0.5753431417100738E+00, 0.3331266686486833E-01, 0.6880305191066147E-01, 0.1188297658848447E+01, 0.1194069582486762E+01, 0.7457497555020480E-01, 0.9333627524262254E-01, 0.1494469242363992E+01, 0.1408587972834190E+01, 0.7455005714048079E-02, 0.8951422490882578E-02, 0.1691328825765317E+01, 0.1682736313985311E+01, 0.3589107121045615E-03, 0.1003553923945662E-03, 0.4705116269624868E+00, 0.4856665170586981E+00, 0.1525524548983380E-01, 0.1367304312976171E-01, 0.4352954686209429E+00, 0.4385509668224923E+00, 0.1692854133253905E-01, 0.1314659648329904E-01, 0.3405758644481647E+00, 0.3806452440729016E+00, 0.5321597610926388E-01, 0.3583592846566260E-01, 0.2563285827809251E+00, 0.2206431713856914E+00, 0.1505170716567330E-03, 0.6305450884558253E-04, 0.9243168664339420E-01, 0.9236863258188953E-01, 0.4485687980202113E-09, 0.5962992535266723E-20, 0.1227890724922389E-11, 0.4959852501050381E-23, 0.2408395422307052E-15, 0.1414000300319855E-15, 0.5186198053161721E+00}, + i0: 1, + n0: 13, + pp: 1, + tau: 4.9598525010503808E-024, + sigma: 0.73182753419913071, + i0Out: 1, + n0Out: 13, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 0.73182753419913071, + dminOut: 4.9598525010503808E-024, + dmin1Out: 9.2339683204333278E-002, + dmin2Out: 0.20112464802017624, + dnOut: 4.9598525010503808E-024, + dnm1Out: 9.2339683204333278E-002, + dnm2Out: 0.20112464802017624, + }, + { + z: []float64{0.1749149979302717E+01, 0.1749149979302717E+01, 0.8676862906242004E-16, 0.1414000300319855E-15, 0.1117154804361126E+01, 0.1073347337297776E+01, 0.4438011869593646E-01, 0.4380746706334982E-01, 0.1178029724550133E+01, 0.1131758262754287E+01, 0.4427372589519608E-01, 0.9065158049178278E-01, 0.5998724677255393E+00, 0.5753431417100738E+00, 0.1369551627869799E+00, 0.6880305191066147E-01, 0.1150450694942405E+01, 0.1194069582486762E+01, 0.1142789997988411E+00, 0.9333627524262254E-01, 0.1303260395526232E+01, 0.1408587972834190E+01, 0.1155784656615063E-01, 0.8951422490882578E-02, 0.1671278822811555E+01, 0.1682736313985311E+01, 0.2916285016424428E-04, 0.1003553923945662E-03, 0.4993103973382956E+00, 0.4856665170586981E+00, 0.1200921574220688E-01, 0.1367304312976171E-01, 0.4396883475635844E+00, 0.4385509668224923E+00, 0.1138121911768345E-01, 0.1314659648329904E-01, 0.4050999534208807E+00, 0.3806452440729016E+00, 0.1951852336551518E-01, 0.3583592846566260E-01, 0.2011877025290218E+00, 0.2206431713856914E+00, 0.2894937755625969E-04, 0.6305450884558253E-04, 0.9233968320433328E-01, 0.9236863258188953E-01, 0.3202909346606844E-42, 0.5962992535266723E-20}, + i0: 1, + n0: 12, + pp: 0, + tau: 9.2159326345418235E-002, + sigma: 0.73182753419913071, + i0Out: 1, + n0Out: 12, + ppOut: 0, + tauOut: 9.2159326345418235E-002, + sigmaOut: 0.73182753419913071, + dminOut: 1.5272797578758102E-004, + dmin1Out: 9.6724015270930774E-002, + dmin2Out: 0.29962742013672317, + dnOut: 1.5272797578758102E-004, + dnm1Out: 9.6724015270930774E-002, + dnm2Out: 0.29962742013672317, + }, + { + z: []float64{0.1749149979302717E+01, 0.1656990652957299E+01, 0.8676862906242004E-16, 0.5850002270797901E-16, 0.1117154804361126E+01, 0.1069375596711644E+01, 0.4438011869593646E-01, 0.4888936980013561E-01, 0.1178029724550133E+01, 0.1081254754299776E+01, 0.4427372589519608E-01, 0.2456274906772994E-01, 0.5998724677255393E+00, 0.6201055550993710E+00, 0.1369551627869799E+00, 0.2540860356894923E+00, 0.1150450694942405E+01, 0.9184843327063353E+00, 0.1142789997988411E+00, 0.1621533314992303E+00, 0.1303260395526232E+01, 0.1060505584247734E+01, 0.1155784656615063E-01, 0.1821431635083262E-01, 0.1671278822811555E+01, 0.1560934342965469E+01, 0.2916285016424428E-04, 0.9328588590960435E-05, 0.4993103973382956E+00, 0.4191509581464933E+00, 0.1200921574220688E-01, 0.1259763844648080E-01, 0.4396883475635844E+00, 0.3463126018893689E+00, 0.1138121911768345E-01, 0.1331320693873929E-01, 0.4050999534208807E+00, 0.3191459435022383E+00, 0.1951852336551518E-01, 0.1230436091267282E-01, 0.2011877025290218E+00, 0.9675296464848704E-01, 0.2894937755625969E-04, 0.2762888312745317E-04, 0.9233968320433328E-01, 0.1527279757875810E-03, 0.3202909346606844E-42, 0.5850002270797901E-16, 0.7318275341991307E+00}, + i0: 1, + n0: 12, + pp: 1, + tau: 1.5267965277267402E-004, + sigma: 0.82398686054454895, + i0Out: 1, + n0Out: 12, + ppOut: 1, + tauOut: 1.5267965277267402E-004, + sigmaOut: 0.82398686054454895, + dminOut: 2.8998364833248812E-009, + dmin1Out: 9.2869952038417761E-002, + dmin2Out: 0.30683160095299705, + dnOut: 2.8998364833248812E-009, + dnm1Out: 9.2869952038417761E-002, + dnm2Out: 0.30683160095299705, + }, + { + z: []float64{0.1656837973304527E+01, 0.1656990652957299E+01, 0.3775776370348287E-16, 0.5850002270797901E-16, 0.1118112286859007E+01, 0.1069375596711644E+01, 0.4727777715386321E-01, 0.4888936980013561E-01, 0.1058387046560870E+01, 0.1081254754299776E+01, 0.1439123541326830E-01, 0.2456274906772994E-01, 0.8596476757228223E+00, 0.6201055550993710E+00, 0.2714763844897646E+00, 0.2540860356894923E+00, 0.8090086000630283E+00, 0.9184843327063353E+00, 0.2125620340079330E+00, 0.1621533314992303E+00, 0.8660051869378607E+00, 0.1060505584247734E+01, 0.3283046378299830E-01, 0.1821431635083262E-01, 0.1527960528118289E+01, 0.1560934342965469E+01, 0.2559023465659061E-05, 0.9328588590960435E-05, 0.4315933579167358E+00, 0.4191509581464933E+00, 0.1010840613748274E-01, 0.1259763844648080E-01, 0.3493647230378528E+00, 0.3463126018893689E+00, 0.1216166289646864E-01, 0.1331320693873929E-01, 0.3191359618656699E+00, 0.3191459435022383E+00, 0.3730332957296599E-02, 0.1230436091267282E-01, 0.9289758092154521E-01, 0.9675296464848704E-01, 0.4542317842367971E-07, 0.2762888312745317E-04, 0.2899836483324881E-08, 0.1527279757875810E-03, 0.3775776370348287E-16, 0.5850002270797901E-16}, + i0: 1, + n0: 12, + pp: 0, + tau: 2.8998350258011044E-009, + sigma: 0.82413954019732161, + i0Out: 1, + n0Out: 12, + ppOut: 0, + tauOut: 2.8998350258011044E-009, + sigmaOut: 0.82413954019732161, + dminOut: 2.2456987483859239E-017, + dmin1Out: 9.1786476970678488E-002, + dmin2Out: 0.30815750788579249, + dnOut: 2.2456987483859239E-017, + dnm1Out: 9.1786476970678488E-002, + dnm2Out: 0.30815750788579249, + }, + { + z: []float64{0.1656837973304527E+01, 0.1656837970404692E+01, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.1118112286859007E+01, 0.1165390061113035E+01, 0.4727777715386321E-01, 0.4293685745187325E-01, 0.1058387046560870E+01, 0.1029841421622430E+01, 0.1439123541326830E-01, 0.1201290976848257E-01, 0.8596476757228223E+00, 0.1119111147544269E+01, 0.2714763844897646E+00, 0.1962510428460807E+00, 0.8090086000630283E+00, 0.8253195883250457E+00, 0.2125620340079330E+00, 0.2230406579474441E+00, 0.8660051869378607E+00, 0.6757949898735797E+00, 0.3283046378299830E-01, 0.7422909836846008E-01, 0.1527960528118289E+01, 0.1453733985873459E+01, 0.2559023465659061E-05, 0.7597383986781573E-06, 0.4315933579167358E+00, 0.4417010014159849E+00, 0.1010840613748274E-01, 0.7995273950601426E-02, 0.3493647230378528E+00, 0.3535311090838850E+00, 0.1216166289646864E-01, 0.1097845108004235E-01, 0.3191359618656699E+00, 0.3118878408430891E+00, 0.3730332957296599E-02, 0.1111101051031713E-02, 0.9289758092154521E-01, 0.9178652239385691E-01, 0.4542317842367971E-07, 0.1435066789177947E-14, 0.2899836483324881E-08, 0.2245698748385924E-16, 0.3775776370348287E-16, 0.2548071704976161E-16, 0.7318275341991307E+00}, + i0: 1, + n0: 12, + pp: 1, + tau: 2.2456987483858885E-017, + sigma: 0.82413954309715665, + i0Out: 1, + n0Out: 12, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 0.82413954309715665, + dminOut: 2.2456987483858888E-017, + dmin1Out: 9.1450429866798411E-002, + dmin2Out: 0.30232944966555197, + dnOut: 2.2456987483858888E-017, + dnm1Out: 9.1450429866798411E-002, + dnm2Out: 0.30232944966555197, + }, + { + z: []float64{0.1656837970404692E+01, 0.1656837970404692E+01, 0.1792267857826344E-16, 0.2548071704976161E-16, 0.1208326918564908E+01, 0.1165390061113035E+01, 0.3659452888027460E-01, 0.4293685745187325E-01, 0.1005259802510638E+01, 0.1029841421622430E+01, 0.1337343958524596E-01, 0.1201290976848257E-01, 0.1301988750805104E+01, 0.1119111147544269E+01, 0.1244018658302015E+00, 0.1962510428460807E+00, 0.9239583804422884E+00, 0.8253195883250457E+00, 0.1631347930486186E+00, 0.2230406579474441E+00, 0.5868892951934211E+00, 0.6757949898735797E+00, 0.1838666404767374E+00, 0.7422909836846008E-01, 0.1269868105135121E+01, 0.1453733985873459E+01, 0.2642614694812039E-06, 0.7597383986781573E-06, 0.4496960111051168E+00, 0.4417010014159849E+00, 0.6285530663790794E-02, 0.7995273950601426E-02, 0.3582240295001366E+00, 0.3535311090838850E+00, 0.9558391177537082E-02, 0.1097845108004235E-01, 0.3034405507165837E+00, 0.3118878408430891E+00, 0.3360925270585024E-03, 0.1111101051031713E-02, 0.9145042986679984E-01, 0.9178652239385691E-01, 0.3524015903480299E-30, 0.1435066789177947E-14}, + i0: 1, + n0: 11, + pp: 0, + tau: 9.1173077708044642E-002, + sigma: 0.82413954309715665, + i0Out: 1, + n0Out: 11, + ppOut: 0, + tauOut: 9.1173077708044642E-002, + sigmaOut: 0.82413954309715665, + dminOut: 1.2510327751137640E-004, + dmin1Out: 0.20154260650453434, + dmin2Out: 0.26087886618071221, + dnOut: 1.2510327751137640E-004, + dnm1Out: 0.20154260650453434, + dnm2Out: 0.26087886618071221, + }, + { + z: []float64{0.1656837970404692E+01, 0.1565664892696647E+01, 0.1792267857826344E-16, 0.1383211380667930E-16, 0.1208326918564908E+01, 0.1153748369737138E+01, 0.3659452888027460E-01, 0.3188477647299814E-01, 0.1005259802510638E+01, 0.8955753879148407E+00, 0.1337343958524596E-01, 0.1944232516271161E-01, 0.1301988750805104E+01, 0.1315775213764550E+01, 0.1244018658302015E+00, 0.8735697805677015E-01, 0.9239583804422884E+00, 0.9085631177260922E+00, 0.1631347930486186E+00, 0.1053774491236745E+00, 0.5868892951934211E+00, 0.5742054088384394E+00, 0.1838666404767374E+00, 0.4066251880351924E+00, 0.1269868105135121E+01, 0.7720701036533529E+00, 0.2642614694812039E-06, 0.1539203864417861E-06, 0.4496960111051168E+00, 0.3648083101404764E+00, 0.6285530663790794E-02, 0.6172085611379779E-02, 0.3582240295001366E+00, 0.2704372573582493E+00, 0.9558391177537082E-02, 0.1072486650400470E-01, 0.3034405507165837E+00, 0.2018786990315928E+00, 0.3360925270585024E-03, 0.1522488812438262E-03, 0.9145042986679984E-01, 0.1251032775113764E-03, 0.3524015903480299E-30, 0.1383211380667930E-16, 0.8241395430971566E+00}, + i0: 1, + n0: 11, + pp: 1, + tau: 1.2498058228587147E-004, + sigma: 0.91531262080520126, + i0Out: 1, + n0Out: 11, + ppOut: 1, + tauOut: 1.2498058228587147E-004, + sigmaOut: 0.91531262080520126, + dminOut: 2.4554386425680716E-008, + dmin1Out: 0.19392428663386141, + dmin2Out: 0.26581143244488259, + dnOut: 2.4554386425680716E-008, + dnm1Out: 0.19392428663386141, + dnm2Out: 0.26581143244488259, + }, + { + z: []float64{0.1565539912114361E+01, 0.1565664892696647E+01, 0.1019378594629470E-16, 0.1383211380667930E-16, 0.1185508165627851E+01, 0.1153748369737138E+01, 0.2408690373149840E-01, 0.3188477647299814E-01, 0.8908058287637680E+00, 0.8955753879148407E+00, 0.2871751477260568E-01, 0.1944232516271161E-01, 0.1374289696466428E+01, 0.1315775213764550E+01, 0.5775298217141787E-01, 0.8735697805677015E-01, 0.9560626040960629E+00, 0.9085631177260922E+00, 0.6328905763825028E-01, 0.1053774491236745E+00, 0.9174165586530958E+00, 0.5742054088384394E+00, 0.3422034931823232E+00, 0.4066251880351924E+00, 0.4297417838091302E+00, 0.7720701036533529E+00, 0.1306631986684747E-06, 0.1539203864417861E-06, 0.3708552845063717E+00, 0.3648083101404764E+00, 0.4500844331080801E-02, 0.6172085611379779E-02, 0.2765362989488873E+00, 0.2704372573582493E+00, 0.7829431815445537E-02, 0.1072486650400470E-01, 0.1940765355151052E+00, 0.2018786990315928E+00, 0.9814083907923291E-07, 0.1522488812438262E-03, 0.2455438642568072E-07, 0.1251032775113764E-03, 0.1019378594629470E-16, 0.1383211380667930E-16}, + i0: 1, + n0: 11, + pp: 0, + tau: 2.4554370888251911E-008, + sigma: 0.91543760138748709, + i0Out: 1, + n0Out: 11, + ppOut: 0, + tauOut: 2.4554370888251911E-008, + sigmaOut: 0.91543760138748709, + dminOut: 2.7649302792337775E-015, + dmin1Out: 0.18866996369915248, + dmin2Out: 0.27322036360404983, + dnOut: 2.7649302792337775E-015, + dnm1Out: 0.18866996369915248, + dnm2Out: 0.27322036360404983, + }, + { + z: []float64{0.1565539912114361E+01, 0.1565539887559990E+01, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.1185508165627851E+01, 0.1209595044804978E+01, 0.2408690373149840E-01, 0.1773879145177052E-01, 0.8908058287637680E+00, 0.9017845275302323E+00, 0.2871751477260568E-01, 0.4376453959373496E-01, 0.1374289696466428E+01, 0.1388278114489740E+01, 0.5775298217141787E-01, 0.3977262621431848E-01, 0.9560626040960629E+00, 0.9795790109656241E+00, 0.6328905763825028E-01, 0.5927283946360358E-01, 0.9174165586530958E+00, 0.1200347187817445E+01, 0.3422034931823232E+00, 0.1225138368952072E+00, 0.4297417838091302E+00, 0.3072280530227507E+00, 0.1306631986684747E-06, 0.1577236754259593E-06, 0.3708552845063717E+00, 0.3753559465594062E+00, 0.4500844331080801E-02, 0.3315910790466669E-02, 0.2765362989488873E+00, 0.2810497954194954E+00, 0.7829431815445537E-02, 0.5406547261581845E-02, 0.1940765355151052E+00, 0.1886700618399915E+00, 0.9814083907923291E-07, 0.1277249852674422E-13, 0.2455438642568072E-07, 0.2764930279233778E-14, 0.1019378594629470E-16, 0.7719264500395369E-17, 0.8241395430971566E+00}, + i0: 1, + n0: 11, + pp: 1, + tau: 2.7649302792335523E-015, + sigma: 0.91543762594185796, + i0Out: 1, + n0Out: 11, + ppOut: 1, + tauOut: 2.7649302792335523E-015, + sigmaOut: 0.91543762594185796, + dminOut: 3.4709879829724519E-029, + dmin1Out: 0.18507826404867261, + dmin2Out: 0.27717487004787600, + dnOut: 3.4709879829724519E-029, + dnm1Out: 0.18507826404867261, + dnm2Out: 0.27858872904535659, + }, + { + z: []float64{0.1565539887559988E+01, 0.1565539887559990E+01, 0.5964194309842799E-17, 0.7719264500395369E-17, 0.1227333836256746E+01, 0.1209595044804978E+01, 0.1303359134714337E-01, 0.1773879145177052E-01, 0.9325154757768211E+00, 0.9017845275302323E+00, 0.6515425651042277E-01, 0.4376453959373496E-01, 0.1362896484193633E+01, 0.1388278114489740E+01, 0.2858649229958118E-01, 0.3977262621431848E-01, 0.1010265358129644E+01, 0.9795790109656241E+00, 0.7042504782685149E-01, 0.5927283946360358E-01, 0.1252435976885798E+01, 0.1200347187817445E+01, 0.3005318297487194E-01, 0.1225138368952072E+00, 0.2771750277715515E+00, 0.3072280530227507E+00, 0.2135925446109612E-06, 0.1577236754259593E-06, 0.3786716437573254E+00, 0.3753559465594062E+00, 0.2461066374135985E-02, 0.3315910790466669E-02, 0.2839952763069384E+00, 0.2810497954194954E+00, 0.3591797791316158E-02, 0.5406547261581845E-02, 0.1850782640486854E+00, 0.1886700618399915E+00, 0.1908115364037247E-27, 0.1277249852674422E-13}, + i0: 1, + n0: 10, + pp: 0, + tau: 9.2539132024336307E-002, + sigma: 0.91543762594186073, + i0Out: 1, + n0Out: 10, + ppOut: 0, + tauOut: 9.2539132024336307E-002, + sigmaOut: 0.91543762594186073, + dminOut: 8.9088074504151571E-002, + dmin1Out: 0.17705256406949207, + dmin2Out: 0.17705256406949207, + dnOut: 8.9088074504151571E-002, + dnm1Out: 0.18903428744201686, + dnm2Out: 0.28613205491191551, + }, + { + z: []float64{0.1565539887559988E+01, 0.1473000755535651E+01, 0.5964194309842799E-17, 0.4969486576955697E-17, 0.1227333836256746E+01, 0.1147828295579553E+01, 0.1303359134714337E-01, 0.1058871408116432E-01, 0.9325154757768211E+00, 0.8945418861817434E+00, 0.6515425651042277E-01, 0.9926701980086396E-01, 0.1362896484193633E+01, 0.1199676824668014E+01, 0.2858649229958118E-01, 0.2407310226126826E-01, 0.1010265358129644E+01, 0.9640781716708908E+00, 0.7042504782685149E-01, 0.9148932748822959E-01, 0.1252435976885798E+01, 0.1098460700348104E+01, 0.3005318297487194E-01, 0.7583331677723075E-02, 0.2771750277715515E+00, 0.1770527776620367E+00, 0.2135925446109612E-06, 0.4568210735249311E-06, 0.3786716437573254E+00, 0.2885931212860515E+00, 0.2461066374135985E-02, 0.2421856840585221E-02, 0.2839952763069384E+00, 0.1926260852333330E+00, 0.3591797791316158E-02, 0.3451057520197492E-02, 0.1850782640486854E+00, 0.8908807450415157E-01, 0.1908115364037247E-27, 0.4969486576955697E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + tau: 7.5387921832037685E-002, + sigma: 1.0079767579661971, + i0Out: 1, + n0Out: 10, + ppOut: 1, + tauOut: 7.5387921832037685E-002, + sigmaOut: 1.0079767579661971, + dminOut: 1.1106216559126303E-002, + dmin1Out: 0.10021441433509834, + dmin2Out: 0.10021441433509834, + dnOut: 1.1106216559126303E-002, + dnm1Out: 0.11507463320059727, + dnm2Out: 0.21320388392650824, + }, + { + z: []float64{0.1397612833703614E+01, 0.1473000755535651E+01, 0.4081328655531061E-17, 0.4969486576955697E-17, 0.1083029087828680E+01, 0.1147828295579553E+01, 0.8745885380967966E-02, 0.1058871408116432E-01, 0.9096750987696016E+00, 0.8945418861817434E+00, 0.1309130515609722E+00, 0.9926701980086396E-01, 0.1017448953536272E+01, 0.1199676824668014E+01, 0.2281033592282574E-01, 0.2407310226126826E-01, 0.9573692414042568E+00, 0.9640781716708908E+00, 0.1049724875218357E+00, 0.9148932748822959E-01, 0.9256836226719531E+00, 0.1098460700348104E+01, 0.1450441494900679E-02, 0.7583331677723075E-02, 0.1002148711561719E+00, 0.1770527776620367E+00, 0.1315527505616969E-05, 0.4568210735249311E-06, 0.2156257407670935E+00, 0.2885931212860515E+00, 0.2163530200698068E-02, 0.2421856840585221E-02, 0.1185256907207948E+00, 0.1926260852333330E+00, 0.2593936112987583E-02, 0.3451057520197492E-02, 0.1110621655912630E-01, 0.8908807450415157E-01, 0.4081328655531061E-17, 0.4969486576955697E-17}, + i0: 1, + n0: 10, + pp: 0, + tau: 9.2006637361187298E-003, + sigma: 1.0833646797982348, + i0Out: 1, + n0Out: 10, + ppOut: 0, + tauOut: 9.2006637361187298E-003, + sigmaOut: 1.0833646797982348, + dminOut: 1.6452860548183366E-003, + dmin1Out: 9.0837695870445614E-002, + dmin2Out: 9.0837695870445614E-002, + dnOut: 1.6452860548183366E-003, + dnm1Out: 0.10809563217808144, + dnm2Out: 0.20642195434625446, + }, + { + z: []float64{0.1397612833703614E+01, 0.1388412169967495E+01, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.1083029087828680E+01, 0.1082574309473529E+01, 0.8745885380967966E-02, 0.7349069784991225E-02, 0.9096750987696016E+00, 0.1024038416809464E+01, 0.1309130515609722E+00, 0.1300706547025319E+00, 0.1017448953536272E+01, 0.9009879710204475E+00, 0.2281033592282574E-01, 0.2423774201322422E-01, 0.9573692414042568E+00, 0.1028903323176749E+01, 0.1049724875218357E+00, 0.9444163542020824E-01, 0.9256836226719531E+00, 0.8234917650105269E+00, 0.1450441494900679E-02, 0.1765115496075164E-03, 0.1002148711561719E+00, 0.9083901139795122E-01, 0.1315527505616969E-05, 0.3122684720284652E-05, 0.2156257407670935E+00, 0.2085854845469525E+00, 0.2163530200698068E-02, 0.1229394806594584E-02, 0.1185256907207948E+00, 0.1106895682910690E+00, 0.2593936112987583E-02, 0.2602667681892373E-03, 0.1110621655912630E-01, 0.1645286054818337E-02, 0.4081328655531061E-17, 0.3183635051997810E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + tau: 1.5594219393746818E-003, + sigma: 1.0925653435343534, + i0Out: 1, + n0Out: 10, + ppOut: 1, + tauOut: 1.5594219393746818E-003, + sigmaOut: 1.0925653435343534, + dminOut: 8.1926049685687600E-005, + dmin1Out: 8.9258234858565516E-002, + dmin2Out: 8.9258234858565516E-002, + dnOut: 8.1926049685687600E-005, + dnm1Out: 0.10847668953277810, + dnm2Out: 0.20701876553386761, + }, + { + z: []float64{0.1386852748028120E+01, 0.1388412169967495E+01, 0.2485138759635906E-17, 0.3183635051997810E-17, 0.1088363957319145E+01, 0.1082574309473529E+01, 0.6914717946174950E-02, 0.7349069784991225E-02, 0.1145634931626446E+01, 0.1024038416809464E+01, 0.1022944500333619E+00, 0.1300706547025319E+00, 0.8213718410609353E+00, 0.9009879710204475E+00, 0.3036175828902931E-01, 0.2423774201322422E-01, 0.1091423778368554E+01, 0.1028903323176749E+01, 0.7125729765473905E-01, 0.9444163542020824E-01, 0.7508515569660207E+00, 0.8234917650105269E+00, 0.2135460001102832E-04, 0.1765115496075164E-03, 0.8926135754328580E-01, 0.9083901139795122E-01, 0.7297073710223142E-05, 0.3122684720284652E-05, 0.2082481603404622E+00, 0.2085854845469525E+00, 0.6534568189162364E-03, 0.1229394806594584E-02, 0.1087369563009673E+00, 0.1106895682910690E+00, 0.3938065757966957E-05, 0.2602667681892373E-03, 0.8192604968568760E-04, 0.1645286054818337E-02, 0.2485138759635906E-17, 0.3183635051997810E-17}, + i0: 1, + n0: 10, + pp: 0, + tau: 8.1416944590412474E-005, + sigma: 1.0941247654737283, + i0Out: 1, + n0Out: 10, + ppOut: 0, + tauOut: 8.1416944590412474E-005, + sigmaOut: 1.0941247654737283, + dminOut: 5.0612658152462498E-007, + dmin1Out: 8.9177229293753768E-002, + dmin2Out: 8.9177229293753768E-002, + dnOut: 5.0612658152462498E-007, + dnm1Out: 0.10831524323681536, + dnm2Out: 0.20814970454128662, + }, + { + z: []float64{0.1386852748028120E+01, 0.1386771331083530E+01, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.1088363957319145E+01, 0.1095197258320730E+01, 0.6914717946174950E-02, 0.7233164949324962E-02, 0.1145634931626446E+01, 0.1240614799765893E+01, 0.1022944500333619E+00, 0.6772592167212049E-01, 0.8213718410609353E+00, 0.7839262607332537E+00, 0.3036175828902931E-01, 0.4227125255215914E-01, 0.1091423778368554E+01, 0.1120328406526543E+01, 0.7125729765473905E-01, 0.4775711530437247E-01, 0.7508515569660207E+00, 0.7030343793170689E+00, 0.2135460001102832E-04, 0.2711304941630149E-05, 0.8926135754328580E-01, 0.8918452636746399E-01, 0.7297073710223142E-05, 0.1703885458517271E-04, 0.2082481603404622E+00, 0.2088031613602029E+00, 0.6534568189162364E-03, 0.3402961195615630E-03, 0.1087369563009673E+00, 0.1083191813025733E+00, 0.3938065757966957E-05, 0.2978513750500819E-08, 0.8192604968568760E-04, 0.5061265815246250E-06, 0.2485138759635906E-17, 0.1950383162890474E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + tau: 5.0604049633765406E-007, + sigma: 1.0942061824183187, + i0Out: 1, + n0Out: 10, + ppOut: 1, + tauOut: 5.0604049633765406E-007, + sigmaOut: 1.0942061824183187, + dminOut: 8.6071246971392626E-011, + dmin1Out: 8.9183660885577137E-002, + dmin2Out: 8.9183660885577137E-002, + dnOut: 8.6071246971392626E-011, + dnm1Out: 0.10814239569959758, + dnm2Out: 0.20876277035564564, + }, + { + z: []float64{0.1386770825043033E+01, 0.1386771331083530E+01, 0.1540308069724697E-17, 0.1950383162890474E-17, 0.1102429917229558E+01, 0.1095197258320730E+01, 0.8139811288713328E-02, 0.7233164949324962E-02, 0.1300200404108803E+01, 0.1240614799765893E+01, 0.4083380405309871E-01, 0.6772592167212049E-01, 0.7853632031918177E+00, 0.7839262607332537E+00, 0.6030036143936175E-01, 0.4227125255215914E-01, 0.1107784654351057E+01, 0.1120328406526543E+01, 0.3030814137396716E-01, 0.4775711530437247E-01, 0.6727284432075471E+00, 0.7030343793170689E+00, 0.3594413905024206E-06, 0.2711304941630149E-05, 0.8920069974016231E-01, 0.8918452636746399E-01, 0.3988496406087022E-04, 0.1703885458517271E-04, 0.2091030664752072E+00, 0.2088031613602029E+00, 0.1762795624794033E-03, 0.3402961195615630E-03, 0.1081423986781113E+00, 0.1083191813025733E+00, 0.1393999949133917E-13, 0.2978513750500819E-08, 0.8607124697139263E-10, 0.5061265815246250E-06, 0.1540308069724697E-17, 0.1950383162890474E-17}, + i0: 1, + n0: 10, + pp: 0, + tau: 8.6071215292546838E-011, + sigma: 1.0942066884588149, + i0Out: 1, + n0Out: 10, + ppOut: 0, + tauOut: 8.6071215292546838E-011, + sigmaOut: 1.0942066884588149, + dminOut: 3.1678834699165494E-017, + dmin1Out: 8.9200650586607991E-002, + dmin2Out: 8.9200650586607991E-002, + dnOut: 3.1678834699165494E-017, + dnm1Out: 0.10805126770967630, + dnm2Out: 0.20900961033533805, + }, + { + z: []float64{0.1386770825043033E+01, 0.1386770824956962E+01, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.1102429917229558E+01, 0.1110569728432201E+01, 0.8139811288713328E-02, 0.9529690622753703E-02, 0.1300200404108803E+01, 0.1331504517453077E+01, 0.4083380405309871E-01, 0.2408506071837550E-01, 0.7853632031918177E+00, 0.8215785038267327E+00, 0.6030036143936175E-01, 0.8130667336500198E-01, 0.1107784654351057E+01, 0.1056786122273951E+01, 0.3030814137396716E-01, 0.1929354325655847E-01, 0.6727284432075471E+00, 0.6534352593063080E+00, 0.3594413905024206E-06, 0.4906748310831983E-07, 0.8920069974016231E-01, 0.8924053555066887E-01, 0.3988496406087022E-04, 0.9345605379795243E-04, 0.2091030664752072E+00, 0.2091858898978174E+00, 0.1762795624794033E-03, 0.9113088236382798E-04, 0.1081423986781113E+00, 0.1080512677096902E+00, 0.1393999949133917E-13, 0.1110429488179469E-22, 0.8607124697139263E-10, 0.3167883469916549E-16, 0.1540308069724697E-17, 0.1224486171222500E-17, 0.9154376259418607E+00}, + i0: 1, + n0: 10, + pp: 1, + tau: 3.1678834698836348E-017, + sigma: 1.0942066885448862, + i0Out: 1, + n0Out: 10, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.0942066885448862, + dminOut: 3.1678834699165494E-017, + dmin1Out: 8.9240528714785800E-002, + dmin2Out: 8.9240528714785800E-002, + dnOut: 3.1678834699165494E-017, + dnm1Out: 0.10800416691102718, + dnm2Out: 0.20896705170504334, + }, + { + z: []float64{0.1386770824956962E+01, 0.1386770824956962E+01, 0.9806070694382835E-18, 0.1224486171222500E-17, 0.1120099419054954E+01, 0.1110569728432201E+01, 0.1132830345080667E-01, 0.9529690622753703E-02, 0.1344261274720646E+01, 0.1331504517453077E+01, 0.1472018016266302E-01, 0.2408506071837550E-01, 0.8881649970290716E+00, 0.8215785038267327E+00, 0.9674301998819117E-01, 0.8130667336500198E-01, 0.9793366455423188E+00, 0.1056786122273951E+01, 0.1287308250760436E-01, 0.1929354325655847E-01, 0.6405622258661866E+00, 0.6534352593063080E+00, 0.6835883063177366E-08, 0.4906748310831983E-07, 0.8933398476858376E-01, 0.8924053555066887E-01, 0.2188381927740679E-03, 0.9345605379795243E-04, 0.2090581825874072E+00, 0.2091858898978174E+00, 0.4710079866305792E-04, 0.9113088236382798E-04, 0.1080041669110272E+00, 0.1080512677096902E+00, 0.3257014354834561E-38, 0.1110429488179469E-22}, + i0: 1, + n0: 9, + pp: 0, + tau: 2.2310132178696450E-002, + sigma: 1.0942066885448862, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 2.2310132178696450E-002, + sigmaOut: 1.0942066885448862, + dminOut: 6.7023851586769906E-002, + dmin1Out: 6.7023851586769906E-002, + dmin2Out: 6.7023851586769906E-002, + dnOut: 8.5666701693601133E-002, + dnm1Out: 0.18606768031923254, + dnm2Out: 6.7023851586769906E-002, + }, + { + z: []float64{0.1386770824956962E+01, 0.1364460692778266E+01, 0.9806070694382835E-18, 0.8049901434408684E-18, 0.1120099419054954E+01, 0.1109117590327065E+01, 0.1132830345080667E-01, 0.1373001363427395E-01, 0.1344261274720646E+01, 0.1322941309070339E+01, 0.1472018016266302E-01, 0.9882485852396858E-02, 0.8881649970290716E+00, 0.9527153989861693E+00, 0.9674301998819117E-01, 0.9944626147083412E-01, 0.9793366455423188E+00, 0.8704533344003925E+00, 0.1287308250760436E-01, 0.9473236598617136E-02, 0.6405622258661866E+00, 0.6087788639247561E+00, 0.6835883063177366E-08, 0.1003117403762534E-08, 0.8933398476858376E-01, 0.6724268977954398E-01, 0.2188381927740679E-03, 0.6803700894781421E-03, 0.2090581825874072E+00, 0.1861147811178956E+00, 0.4710079866305792E-04, 0.2733303872960605E-04, 0.1080041669110272E+00, 0.8566670169360113E-01, 0.3257014354834561E-38, 0.8049901434408684E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + tau: 6.4730147312741043E-002, + sigma: 1.1165168207235825, + i0Out: 1, + n0Out: 9, + ppOut: 1, + tauOut: 6.4730147312741043E-002, + sigmaOut: 1.1165168207235825, + dminOut: 2.5125423409859404E-003, + dmin1Out: 2.5125423409859404E-003, + dmin2Out: 2.5125423409859404E-003, + dnOut: 2.0907912921905053E-002, + dnm1Out: 8.1725879285544201E-002, + dnm2Out: 2.5125423409859404E-003, + }, + { + z: []float64{0.1299730545465525E+01, 0.1364460692778266E+01, 0.6869337119490330E-18, 0.8049901434408684E-18, 0.1058117456648598E+01, 0.1109117590327065E+01, 0.1716633828952343E-01, 0.1373001363427395E-01, 0.1250927309320471E+01, 0.1322941309070339E+01, 0.7526573591998700E-02, 0.9882485852396858E-02, 0.9799049395522637E+00, 0.9527153989861693E+00, 0.8833849733474472E-01, 0.9944626147083412E-01, 0.7268579263515238E+00, 0.8704533344003925E+00, 0.7934296380510910E-02, 0.9473236598617136E-02, 0.5361144212346215E+00, 0.6087788639247561E+00, 0.1258170079408221E-09, 0.1003117403762534E-08, 0.3192912430464083E-02, 0.6724268977954398E-01, 0.3965875451961033E-01, 0.6803700894781421E-03, 0.8175321232427381E-01, 0.1861147811178956E+00, 0.2864145895504550E-04, 0.2733303872960605E-04, 0.2090791292190505E-01, 0.8566670169360113E-01, 0.6869337119490330E-18, 0.8049901434408684E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 2.3478378904869292E-003, + sigma: 1.1812469680363236, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 2.3478378904869292E-003, + sigmaOut: 1.1812469680363236, + dminOut: -6.4213352031532861E-004, + dmin1Out: -6.4213352031532861E-004, + dmin2Out: 8.4507453921550072E-004, + dnOut: 1.9536180783236046E-002, + dnm1Out: -6.4213352031532861E-004, + dnm2Out: 8.4507453921550072E-004, + }, + { + z: []float64{0.1299730545465525E+01, 0.1297382707575038E+01, 0.6869337119490330E-18, 0.5602483738451179E-18, 0.1058117456648598E+01, 0.1072935957047634E+01, 0.1716633828952343E-01, 0.2001409424891253E-01, 0.1250927309320471E+01, 0.1236091950773070E+01, 0.7526573591998700E-02, 0.5966648869520194E-02, 0.9799049395522637E+00, 0.1059928950127001E+01, 0.8833849733474472E-01, 0.6057909540261972E-01, 0.7268579263515238E+00, 0.6718652894389281E+00, 0.7934296380510910E-02, 0.6331166051893822E-02, 0.5361144212346215E+00, 0.5274354174180577E+00, 0.1258170079408221E-09, 0.7616528495272331E-12, 0.3192912430464083E-02, 0.4050382905882583E-01, 0.3965875451961033E-01, 0.8004750795410222E-01, 0.8175321232427381E-01, -0.6134920613602832E-03, 0.2864145895504550E-04, -0.9761057518179271E-03, 0.2090791292190505E-01, 0.1953618078323605E-01, 0.6869337119490330E-18, 0.5602483738451179E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 5.8695947262173229E-004, + sigma: 1.1812469680363236, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 5.8695947262173229E-004, + sigmaOut: 1.1812469680363236, + dminOut: 2.6059529570832572E-003, + dmin1Out: 2.6059529570832572E-003, + dmin2Out: 2.6059529570832572E-003, + dnOut: 2.0187357299561493E-002, + dnm1Out: 4.4537716273149721E-003, + dnm2Out: 2.6059529570832572E-003, + }, + { + z: []float64{0.1299730545465525E+01, 0.1299143585992903E+01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1058117456648598E+01, 0.1074696835465499E+01, 0.1716633828952343E-01, 0.1998130138542489E-01, 0.1250927309320471E+01, 0.1237885622054423E+01, 0.7526573591998700E-02, 0.5958003315736791E-02, 0.9799049395522637E+00, 0.1061698474098650E+01, 0.8833849733474472E-01, 0.6047812873071532E-01, 0.7268579263515238E+00, 0.6737271345286977E+00, 0.7934296380510910E-02, 0.6313669873066943E-02, 0.5361144212346215E+00, 0.5292137920147498E+00, 0.1258170079408221E-09, 0.7590933847144573E-12, 0.3192912430464083E-02, 0.4226470747669359E-01, 0.3965875451961033E-01, 0.7671248122433710E-01, 0.8175321232427381E-01, 0.4482413086270017E-02, 0.2864145895504550E-04, 0.1335961497218277E-03, 0.2090791292190505E-01, 0.2018735729956149E-01, 0.6869337119490330E-18, 0.5594890049187079E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + tau: 4.9324499328963489E-004, + sigma: 1.1818339275089453, + i0Out: 1, + n0Out: 9, + ppOut: 1, + tauOut: 4.9324499328963489E-004, + sigmaOut: 1.1818339275089453, + dminOut: 1.0870277779300500E-003, + dmin1Out: 1.0870277779300500E-003, + dmin2Out: 4.1771462483342674E-002, + dnOut: 1.7484624889890960E-002, + dnm1Out: 1.0870277779300500E-003, + dnm2Out: 4.1771462483342674E-002, + }, + { + z: []float64{0.1298650340999613E+01, 0.1299143585992903E+01, 0.4630045856693428E-18, 0.5594890049187079E-18, 0.1094184891857634E+01, 0.1074696835465499E+01, 0.2260547177996662E-01, 0.1998130138542489E-01, 0.1220744908596903E+01, 0.1237885622054423E+01, 0.5181756634367578E-02, 0.5958003315736791E-02, 0.1116501601201708E+01, 0.1061698474098650E+01, 0.3649413160495897E-01, 0.6047812873071532E-01, 0.6430534278035160E+00, 0.6737271345286977E+00, 0.5195962000339362E-02, 0.6313669873066943E-02, 0.5235245850218799E+00, 0.5292137920147498E+00, 0.6128243213469890E-13, 0.7590933847144573E-12, 0.1184839437076798E+00, 0.4226470747669359E-01, 0.2902140315050332E-02, 0.7671248122433710E-01, 0.1220623927651878E-02, 0.4482413086270017E-02, 0.2209487416380896E-02, 0.1335961497218277E-03, 0.1748462488989096E-01, 0.2018735729956149E-01, 0.4630045856693428E-18, 0.5594890049187079E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 8.6238530354903250E-004, + sigma: 1.1823271725022351, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 8.6238530354903250E-004, + sigmaOut: 1.1823271725022351, + dminOut: 3.2884671240747138E-004, + dmin1Out: 3.2884671240747138E-004, + dmin2Out: 0.11762155840411674, + dnOut: 1.4027859154437344E-003, + dnm1Out: 3.2884671240747138E-004, + dnm2Out: 0.11762155840411674, + }, + { + z: []float64{0.1298650340999613E+01, 0.1297787955696064E+01, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094184891857634E+01, 0.1115927978334052E+01, 0.2260547177996662E-01, 0.2472875948770642E-01, 0.1220744908596903E+01, 0.1200335520440015E+01, 0.5181756634367578E-02, 0.4819852017032840E-02, 0.1116501601201708E+01, 0.1147313495486085E+01, 0.3649413160495897E-01, 0.2045445862496274E-01, 0.6430534278035160E+00, 0.6269325458753436E+00, 0.5195962000339362E-02, 0.4338925882718484E-02, 0.5235245850218799E+00, 0.5183232738356738E+00, 0.6128243213469890E-13, 0.1400860159256393E-13, 0.1184839437076798E+00, 0.1205236987191671E+00, 0.2902140315050332E-02, 0.2939191169537379E-04, 0.1220623927651878E-02, 0.2538334128788367E-02, 0.2209487416380896E-02, 0.1521945367089819E-01, 0.1748462488989096E-01, 0.1402785915443734E-02, 0.4630045856693428E-18, 0.3903662538064461E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + tau: 1.8442717265434725E-004, + sigma: 1.1831895578057841, + i0Out: 1, + n0Out: 9, + ppOut: 1, + tauOut: 1.8442717265434725E-004, + sigmaOut: 1.1831895578057841, + dminOut: 3.4295817345512611E-006, + dmin1Out: 2.3532871395603098E-003, + dmin2Out: 0.12033927154650945, + dnOut: 3.4295817345512611E-006, + dnm1Out: 2.3532871395603098E-003, + dnm2Out: 0.12033927154650945, + }, + { + z: []float64{0.1297603528523410E+01, 0.1297787955696064E+01, 0.3357116521683426E-18, 0.3903662538064461E-18, 0.1140472310649104E+01, 0.1115927978334052E+01, 0.2602676813137004E-01, 0.2472875948770642E-01, 0.1178944177153024E+01, 0.1200335520440015E+01, 0.4690536984322235E-02, 0.4819852017032840E-02, 0.1162892989954071E+01, 0.1147313495486085E+01, 0.1102729651913737E-01, 0.2045445862496274E-01, 0.6200597480662705E+00, 0.6269325458753436E+00, 0.3627015421456806E-02, 0.4338925882718484E-02, 0.5145118312415766E+00, 0.5183232738356738E+00, 0.3281495925457712E-14, 0.1400860159256393E-13, 0.1203686634582048E+00, 0.1205236987191671E+00, 0.6198165737098726E-06, 0.2939191169537379E-04, 0.1757274081045850E-01, 0.2538334128788367E-02, 0.1214929161054836E-02, 0.1521945367089819E-01, 0.3429581734551261E-05, 0.1402785915443734E-02, 0.3357116521683426E-18, 0.3903662538064461E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 3.2077610710809750E-006, + sigma: 1.1833739849784384, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 3.2077610710809750E-006, + sigmaOut: 1.1833739849784384, + dminOut: 3.3505760549073344E-012, + dmin1Out: 1.7569442559804263E-002, + dmin2Out: 0.12036545569713296, + dnOut: 3.3505760549073344E-012, + dnm1Out: 1.7569442559804263E-002, + dnm2Out: 0.12036545569713296, + }, + { + z: []float64{0.1297603528523410E+01, 0.1297600320762339E+01, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1140472310649104E+01, 0.1166495871019403E+01, 0.2602676813137004E-01, 0.2630451380147252E-01, 0.1178944177153024E+01, 0.1157326992574803E+01, 0.4690536984322235E-02, 0.4713095445958055E-02, 0.1162892989954071E+01, 0.1169203983266179E+01, 0.1102729651913737E-01, 0.5848066547299594E-02, 0.6200597480662705E+00, 0.6178354891793567E+00, 0.3627015421456806E-02, 0.3020451850239120E-02, 0.5145118312415766E+00, 0.5114881716302697E+00, 0.3281495925457712E-14, 0.7722354114894537E-15, 0.1203686634582048E+00, 0.1203660755137067E+00, 0.6198165737098726E-06, 0.9048958315991394E-07, 0.1757274081045850E-01, 0.1878437172085910E-01, 0.1214929161054836E-02, 0.2218173128942313E-06, 0.3429581734551261E-05, 0.3350576054907334E-11, 0.3357116521683426E-18, 0.2950599175525191E-18, 0.1094206688544886E+01}, + i0: 1, + n0: 9, + pp: 1, + tau: 3.3505364896797715E-012, + sigma: 1.1833771927395094, + i0Out: 1, + n0Out: 9, + ppOut: 1, + tauOut: 3.3505364896797715E-012, + sigmaOut: 1.1833771927395094, + dminOut: 2.0335799151090034E-023, + dmin1Out: 1.8784357595683275E-002, + dmin2Out: 0.12036607551035594, + dnOut: 2.0335799151090034E-023, + dnm1Out: 1.8784357595683275E-002, + dnm2Out: 0.12036607551035594, + }, + { + z: []float64{0.1297600320758988E+01, 0.1297600320762339E+01, 0.2652482201353177E-18, 0.2950599175525191E-18, 0.1192800384817525E+01, 0.1166495871019403E+01, 0.2552222839336001E-01, 0.2630451380147252E-01, 0.1136517859624050E+01, 0.1157326992574803E+01, 0.4848643531876122E-02, 0.4713095445958055E-02, 0.1170203406278252E+01, 0.1169203983266179E+01, 0.3087619670750762E-02, 0.5848066547299594E-02, 0.6177683213554945E+00, 0.6178354891793567E+00, 0.2500816796475141E-02, 0.3020451850239120E-02, 0.5089873548304448E+00, 0.5114881716302697E+00, 0.1826193617023393E-15, 0.7722354114894537E-15, 0.1203661659999391E+00, 0.1203660755137067E+00, 0.1412182528886294E-07, 0.9048958315991394E-07, 0.1878457941299617E-01, 0.1878437172085910E-01, 0.3956520722700361E-16, 0.2218173128942313E-06, 0.2033579915109003E-22, 0.3350576054907334E-11, 0.2652482201353177E-18, 0.2950599175525191E-18}, + i0: 1, + n0: 9, + pp: 0, + tau: 2.0335799151089990E-023, + sigma: 1.1833771927428600, + i0Out: 1, + n0Out: 9, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 1.1833771927428600, + dminOut: 2.0335799151089993E-023, + dmin1Out: 1.8784577209116738E-002, + dmin2Out: 0.12036616599993906, + dnOut: 2.0335799151089993E-023, + dnm1Out: 1.8784577209116738E-002, + dnm2Out: 0.12036616599993906, + }, + { + z: []float64{0.1297600320758988E+01, 0.1297600320758988E+01, 0.2652482201353177E-18, 0.2438256017573345E-18, 0.1192800384817525E+01, 0.1218322613210885E+01, 0.2552222839336001E-01, 0.2380852827644004E-01, 0.1136517859624050E+01, 0.1117557974879486E+01, 0.4848643531876122E-02, 0.5077051306839188E-02, 0.1170203406278252E+01, 0.1168213974642164E+01, 0.3087619670750762E-02, 0.1632777609571200E-02, 0.6177683213554945E+00, 0.6186363605423986E+00, 0.2500816796475141E-02, 0.2057564358223963E-02, 0.5089873548304448E+00, 0.5069297904722210E+00, 0.1826193617023393E-15, 0.4336141378669131E-16, 0.1203661659999391E+00, 0.1203661801217644E+00, 0.1412182528886294E-07, 0.2203879431304952E-08, 0.1878457941299617E-01, 0.1878457720911678E-01, 0.3956520722700361E-16, 0.4283248425464200E-37, 0.1183377192742860E+01}, + i0: 1, + n0: 8, + pp: 1, + tau: 1.8784576682472597E-002, + sigma: 1.1833771927428600, + i0Out: 1, + n0Out: 8, + ppOut: 1, + tauOut: 1.8784576682472597E-002, + sigmaOut: 1.1833771927428600, + dminOut: 1.1910047947871760E-010, + dmin1Out: 0.10158160343929173, + dmin2Out: 0.48640978493259379, + dnOut: 1.1910047947871760E-010, + dnm1Out: 0.10158160343929173, + dnm2Out: 0.48640978493259379, + }, + { + z: []float64{0.1278815744076516E+01, 0.1297600320758988E+01, 0.2322916695987584E-18, 0.2438256017573345E-18, 0.1223346564804853E+01, 0.1218322613210885E+01, 0.2174969171530204E-01, 0.2380852827644004E-01, 0.1082100757788551E+01, 0.1117557974879486E+01, 0.5481081353963683E-02, 0.5077051306839188E-02, 0.1145581094215299E+01, 0.1168213974642164E+01, 0.8817320773368219E-03, 0.1632777609571200E-02, 0.6010276161408131E+00, 0.6186363605423986E+00, 0.1735428857154564E-02, 0.2057564358223963E-02, 0.4864097849325938E+00, 0.5069297904722210E+00, 0.1073014545319338E-16, 0.4336141378669131E-16, 0.1015816056431712E+00, 0.1203661801217644E+00, 0.4075436992240071E-09, 0.2203879431304952E-08, 0.1191004794787176E-09, 0.1878457720911678E-01, 0.2322916695987584E-18, 0.2438256017573345E-18}, + i0: 1, + n0: 8, + pp: 0, + tau: 1.1910047900088848E-010, + sigma: 1.2021617694253326, + i0Out: 1, + n0Out: 8, + ppOut: 0, + tauOut: 1.1910047900088848E-010, + sigmaOut: 1.2021617694253326, + dminOut: 0.0000000000000000, + dmin1Out: 0.10158160552407068, + dmin2Out: 0.48500827096381138, + dnOut: 0.0000000000000000, + dnm1Out: 0.10158160552407068, + dnm2Out: 0.48500827096381138, + }, + { + z: []float64{0.1278815744076516E+01, 0.1278815743957415E+01, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1223346564804853E+01, 0.1245096256401054E+01, 0.2174969171530204E-01, 0.1890244048666934E-01, 0.1082100757788551E+01, 0.1068679398536745E+01, 0.5481081353963683E-02, 0.5875497537946494E-02, 0.1145581094215299E+01, 0.1140587328635589E+01, 0.8817320773368219E-03, 0.4646249482278370E-03, 0.6010276161408131E+00, 0.6022984199306394E+00, 0.1735428857154564E-02, 0.1401513849681988E-02, 0.4864097849325938E+00, 0.4850082709638114E+00, 0.1073014545319338E-16, 0.2247354260070927E-17, 0.1015816056431712E+00, 0.1015816059316144E+00, 0.4075436992240071E-09, 0.4778291260603437E-18, 0.1191004794787176E-09, 0.0000000000000000E+00, 0.2322916695987584E-18, 0.2222159192042978E-18, 0.1183377192742860E+01}, + i0: 1, + n0: 8, + pp: 1, + tau: -0.0000000000000000, + sigma: 1.2021617695444331, + i0Out: 1, + n0Out: 8, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.2021617695444331, + dminOut: 0.0000000000000000, + dmin1Out: 0.10158160593161437, + dmin2Out: 0.48388184445926297, + dnOut: 0.0000000000000000, + dnm1Out: 0.10158160593161437, + dnm2Out: 0.48388184445926297, + }, + { + z: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2222159192042978E-18, 0.1263998696887723E+01, 0.1245096256401054E+01, 0.1598154237018549E-01, 0.1890244048666934E-01, 0.1058573353704506E+01, 0.1068679398536745E+01, 0.6330707284251229E-02, 0.5875497537946494E-02, 0.1134721246299565E+01, 0.1140587328635589E+01, 0.2466181655543824E-03, 0.4646249482278370E-03, 0.6034533156147670E+00, 0.6022984199306394E+00, 0.1126426504548419E-02, 0.1401513849681988E-02, 0.4838818444592630E+00, 0.4850082709638114E+00, 0.4717884282068346E-18, 0.2247354260070927E-17, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.4778291260603437E-18}, + i0: 1, + n0: 7, + pp: 0, + tau: -0.0000000000000000, + sigma: 1.2021617695444331, + i0Out: 1, + n0Out: 7, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 1.2021617695444331, + dminOut: 0.10158160593161437, + dmin1Out: 0.48298010023310722, + dmin2Out: 0.60332139679048247, + dnOut: 0.10158160593161437, + dnm1Out: 0.48298010023310722, + dnm2Out: 0.60332139679048247, + }, + { + z: []float64{0.1278815743957415E+01, 0.1278815743957415E+01, 0.2163565864913247E-18, 0.2138497627045302E-18, 0.1263998696887723E+01, 0.1279980239257909E+01, 0.1598154237018549E-01, 0.1321710631563048E-01, 0.1058573353704506E+01, 0.1051686954673127E+01, 0.6330707284251229E-02, 0.6830538334266978E-02, 0.1134721246299565E+01, 0.1128137326130852E+01, 0.2466181655543824E-03, 0.1319188242844840E-03, 0.6034533156147670E+00, 0.6044478232950309E+00, 0.1126426504548419E-02, 0.9017442261557238E-03, 0.4838818444592630E+00, 0.4829801002331072E+00, 0.4717884282068346E-18, 0.9922774494036444E-19, 0.1015816059316144E+00, 0.1015816059316144E+00, 0.0000000000000000E+00, 0.2138497627045302E-18, 0.1202161769544433E+01}, + i0: 1, + n0: 7, + pp: 1, + tau: 0.10158160593161437, + sigma: 1.2021617695444331, + i0Out: 1, + n0Out: 7, + ppOut: 1, + tauOut: 0.10158160593161437, + sigmaOut: 1.2021617695444331, + dminOut: 0.0000000000000000, + dmin1Out: 0.38053382595775820, + dmin2Out: 0.50278793042091730, + dnOut: 0.0000000000000000, + dnm1Out: 0.38053382595775820, + dnm2Out: 0.50278793042091730, + }, + { + z: []float64{0.1177234138025801E+01, 0.1278815743957415E+01, 0.2325140442247288E-18, 0.2138497627045302E-18, 0.1191615739641925E+01, 0.1279980239257909E+01, 0.1166505092896250E-01, 0.1321710631563048E-01, 0.9452708361468171E+00, 0.1051686954673127E+01, 0.8151933771558135E-02, 0.6830538334266978E-02, 0.1018535705251965E+01, 0.1128137326130852E+01, 0.7828694249915420E-04, 0.1319188242844840E-03, 0.5036896746470730E+00, 0.6044478232950309E+00, 0.8646683437346259E-03, 0.9017442261557238E-03, 0.3805338259577582E+00, 0.4829801002331072E+00, 0.2648835135390502E-19, 0.9922774494036444E-19, 0.0000000000000000E+00, 0.1015816059316144E+00, 0.2325140442247288E-18, 0.2138497627045302E-18}, + i0: 1, + n0: 7, + pp: 0, + tau: -0.0000000000000000, + sigma: 1.3037433754760475, + i0Out: 1, + n0Out: 7, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 1.3037433754760475, + dminOut: 0.0000000000000000, + dmin1Out: 0.37988164443454930, + dmin2Out: 0.50365062581387521, + dnOut: 0.0000000000000000, + dnm1Out: 0.37988164443454930, + dnm2Out: 0.50365062581387521, + }, + { + z: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2325140442247288E-18, 0.2353545363971710E-18, 0.1191615739641925E+01, 0.1203280790570888E+01, 0.1166505092896250E-01, 0.9163806595868684E-02, 0.9452708361468171E+00, 0.9442589633225065E+00, 0.8151933771558135E-02, 0.8793176380307672E-02, 0.1018535705251965E+01, 0.1009820815814156E+01, 0.7828694249915420E-04, 0.3904883319791864E-04, 0.5036896746470730E+00, 0.5045152941576099E+00, 0.8646683437346259E-03, 0.6521815232088979E-03, 0.3805338259577582E+00, 0.3798816444345493E+00, 0.2648835135390502E-19, 0.0000000000000000E+00, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + tau: -0.0000000000000000, + sigma: 1.3037433754760475, + i0Out: 1, + n0Out: 6, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.3037433754760475, + dminOut: 0.37939119035907048, + dmin1Out: 0.50449560273072791, + dmin2Out: 0.93712213699945368, + dnOut: 0.37939119035907048, + dnm1Out: 0.50449560273072791, + dnm2Out: 1.0004335774214996, + }, + { + z: []float64{0.1177234138025801E+01, 0.1177234138025801E+01, 0.2405618249359890E-18, 0.2353545363971710E-18, 0.1212444597166756E+01, 0.1203280790570888E+01, 0.7136826323052847E-02, 0.9163806595868684E-02, 0.9459153133797613E+00, 0.9442589633225065E+00, 0.9387238392656353E-02, 0.8793176380307672E-02, 0.1000472626254697E+01, 0.1009820815814156E+01, 0.1969142688202247E-04, 0.3904883319791864E-04, 0.5051477842539368E+00, 0.5045152941576099E+00, 0.4904540754787929E-03, 0.6521815232088979E-03, 0.3793911903590705E+00, 0.3798816444345493E+00, 0.2405618249359890E-18, 0.2353545363971710E-18}, + i0: 1, + n0: 6, + pp: 0, + tau: 0.37791671367087804, + sigma: 1.3037433754760475, + i0Out: 1, + n0Out: 6, + ppOut: 0, + tauOut: 0.37791671367087804, + sigmaOut: 1.3037433754760475, + dminOut: 1.7417124602014944E-005, + dmin1Out: 0.12721465844156904, + dmin2Out: 0.55997778901175921, + dnOut: 1.7417124602014944E-005, + dnm1Out: 0.12721465844156904, + dnm2Out: 0.60606091447901145, + }, + { + z: []float64{0.1177234138025801E+01, 0.7993174243549228E+00, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1212444597166756E+01, 0.8416647098189309E+00, 0.7136826323052847E-02, 0.8020810697124018E-02, 0.9459153133797613E+00, 0.5693650274044155E+00, 0.9387238392656353E-02, 0.1649499810480807E-01, 0.1000472626254697E+01, 0.6060806059058935E+00, 0.1969142688202247E-04, 0.1641214148963635E-04, 0.5051477842539368E+00, 0.1277051125170478E+00, 0.4904540754787929E-03, 0.1457059563590431E-02, 0.3793911903590705E+00, 0.1741712460201494E-04, 0.2405618249359890E-18, 0.3648961927279404E-18, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + tau: 1.7220607103034587E-005, + sigma: 1.6816600891469256, + i0Out: 1, + n0Out: 6, + ppOut: 1, + tauOut: 1.7220607103034587E-005, + sigmaOut: 1.6816600891469256, + dminOut: 5.8496704963934779E-012, + dmin1Out: 0.12768433261716639, + dmin2Out: 0.56397303984076830, + dnOut: 5.8496704963934779E-012, + dnm1Out: 0.12768433261716639, + dnm2Out: 0.58884056200405466, + }, + { + z: []float64{0.7993002037478197E+00, 0.7993174243549228E+00, 0.3842364192156412E-18, 0.3648961927279404E-18, 0.8496682999089519E+00, 0.8416647098189309E+00, 0.5374766956544110E-02, 0.8020810697124018E-02, 0.5804680379455763E+00, 0.5693650274044155E+00, 0.1722282329473577E-01, 0.1649499810480807E-01, 0.5888569741455443E+00, 0.6060806059058935E+00, 0.3559292778388127E-05, 0.1641214148963635E-04, 0.1291413921807568E+00, 0.1277051125170478E+00, 0.1965116493098606E-06, 0.1457059563590431E-02, 0.5849670496393478E-11, 0.1741712460201494E-04, 0.3842364192156412E-18, 0.3648961927279404E-18}, + i0: 1, + n0: 6, + pp: 0, + tau: 5.8496615949827599E-012, + sigma: 1.6816773097540285, + i0Out: 1, + n0Out: 6, + ppOut: 0, + tauOut: 5.8496615949827599E-012, + sigmaOut: 1.6816773097540285, + dminOut: 5.2413685591311719E-023, + dmin1Out: 0.12914058828956335, + dmin2Out: 0.57178448001987381, + dnOut: 5.2413685591311719E-023, + dnm1Out: 0.12914058828956335, + dnm2Out: 0.57178448001987381, + }, + { + z: []float64{0.7993002037478197E+00, 0.7993002037419701E+00, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.8496682999089519E+00, 0.8550430668596465E+00, 0.5374766956544110E-02, 0.3648799166500929E-02, 0.5804680379455763E+00, 0.5940420620679615E+00, 0.1722282329473577E-01, 0.1707249411982080E-01, 0.5888569741455443E+00, 0.5717880393126522E+00, 0.3559292778388127E-05, 0.8038853438286423E-06, 0.1291413921807568E+00, 0.1291407848012127E+00, 0.1965116493098606E-06, 0.8901358303923820E-17, 0.5849670496393478E-11, 0.5241368559131172E-22, 0.3842364192156412E-18, 0.4084491703488284E-18, 0.1303743375476047E+01}, + i0: 1, + n0: 6, + pp: 1, + tau: 5.2413685591311714E-023, + sigma: 1.6816773097598783, + i0Out: 1, + n0Out: 6, + ppOut: 1, + tauOut: 0.0000000000000000, + sigmaOut: 1.6816773097598783, + dminOut: 5.2413685591311719E-023, + dmin1Out: 0.12914059800027977, + dmin2Out: 0.55574794205624078, + dnOut: 5.2413685591311719E-023, + dnm1Out: 0.12914059800027977, + dnm2Out: 0.55574794205624078, + }, + { + z: []float64{0.7993002037419701E+00, 0.7993002037419701E+00, 0.4369342452764876E-18, 0.4084491703488284E-18, 0.8586918660261474E+00, 0.8550430668596465E+00, 0.2524235138002424E-02, 0.3648799166500929E-02, 0.6085903210497798E+00, 0.5940420620679615E+00, 0.1604009725641142E-01, 0.1707249411982080E-01, 0.5557487459415846E+00, 0.5717880393126522E+00, 0.1868009328861996E-06, 0.8038853438286423E-06, 0.1291405980002798E+00, 0.1291407848012127E+00, 0.3612752323451872E-38, 0.8901358303923820E-17}, + i0: 1, + n0: 5, + pp: 0, + tau: 0.12914051019182277, + sigma: 1.6816773097598783, + i0Out: 1, + n0Out: 5, + ppOut: 0, + tauOut: 0.12914051019182277, + sigmaOut: 1.6816773097598783, + dminOut: 2.8760335918365243E-008, + dmin1Out: 0.40854091047624980, + dmin2Out: 0.47735135942481804, + dnOut: 2.8760335918365243E-008, + dnm1Out: 0.40854091047624980, + dnm2Out: 0.47735135942481804, + }, + { + z: []float64{0.7993002037419701E+00, 0.6701596935501473E+00, 0.4369342452764876E-18, 0.5598544436768911E-18, 0.8586918660261474E+00, 0.7320755909723271E+00, 0.2524235138002424E-02, 0.2098451433139096E-02, 0.6085903210497798E+00, 0.4933914566812295E+00, 0.1604009725641142E-01, 0.1806732527351204E-01, 0.5557487459415846E+00, 0.4085410972771827E+00, 0.1868009328861996E-06, 0.5904812108429529E-07, 0.1291405980002798E+00, 0.2876033591836524E-07, 0.3612752323451872E-38, 0.5598544436768911E-18, 0.1681677309759878E+01}, + i0: 1, + n0: 5, + pp: 1, + tau: 2.8760330654564486E-008, + sigma: 1.8108178199517009, + i0Out: 1, + n0Out: 5, + ppOut: 1, + tauOut: 2.8760330654564486E-008, + sigmaOut: 1.8108178199517009, + dminOut: 9.5429721930147733E-016, + dmin1Out: 0.39406941605409296, + dmin2Out: 0.49198119275848701, + dnOut: 9.5429721930147733E-016, + dnm1Out: 0.39406941605409296, + dnm2Out: 0.49198119275848701, + }, + { + z: []float64{0.6701596647898166E+00, 0.6701596935501473E+00, 0.6115792910959321E-18, 0.5598544436768911E-18, 0.7341740136451356E+00, 0.7320755909723271E+00, 0.1410235162411720E-02, 0.2098451433139096E-02, 0.5100485180319990E+00, 0.4933914566812295E+00, 0.1447165246275905E-01, 0.1806732527351204E-01, 0.3940694751022140E+00, 0.4085410972771827E+00, 0.4309503539425748E-14, 0.5904812108429529E-07, 0.9542972193014773E-15, 0.2876033591836524E-07, 0.6115792910959321E-18, 0.5598544436768911E-18}, + i0: 1, + n0: 5, + pp: 0, + tau: 9.5429721930146451E-016, + sigma: 1.8108178487120317, + i0Out: 1, + n0Out: 5, + ppOut: 0, + tauOut: 9.5429721930146451E-016, + sigmaOut: 1.8108178487120317, + dminOut: 1.9721522630525295E-030, + dmin1Out: 0.38317668529976806, + dmin2Out: 0.50907067170667131, + dnOut: 1.9721522630525295E-030, + dnm1Out: 0.38317668529976806, + dnm2Out: 0.50907067170667131, + }, + { + z: []float64{0.6701596647898166E+00, 0.6701596647898156E+00, 0.6115792910959321E-18, 0.6699979816704878E-18, 0.7341740136451356E+00, 0.7355842488075462E+00, 0.1410235162411720E-02, 0.9778463253267723E-03, 0.5100485180319990E+00, 0.5235423241694304E+00, 0.1447165246275905E-01, 0.1089278980244500E-01, 0.3940694751022140E+00, 0.3831766852997724E+00, 0.4309503539425748E-14, 0.1073277003016631E-28, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + tau: 0.31895966905528556, + sigma: 1.8108178487120326, + i0Out: 1, + n0Out: 4, + ppOut: 1, + tauOut: 0.31895966905528556, + sigmaOut: 1.8108178487120326, + dminOut: 4.4735699115826311E-002, + dmin1Out: 0.20335674284478694, + dmin2Out: 0.35119999573453003, + dnOut: 4.4735699115826311E-002, + dnm1Out: 0.20335674284478694, + dnm2Out: 0.41662457975226058, + }, + { + z: []float64{0.3511999957345300E+00, 0.6701596647898156E+00, 0.1403302870260262E-17, 0.6699979816704878E-18, 0.4176024260775874E+00, 0.7355842488075462E+00, 0.1225912269357841E-02, 0.9778463253267723E-03, 0.2142495326472319E+00, 0.5235423241694304E+00, 0.1948131712866055E-01, 0.1089278980244500E-01, 0.4473569911582631E-01, 0.3831766852997724E+00, 0.1403302870260262E-17, 0.6699979816704878E-18}, + i0: 1, + n0: 4, + pp: 0, + tau: 3.9897804510299034E-002, + sigma: 2.1297775177673182, + i0Out: 1, + n0Out: 4, + ppOut: 0, + tauOut: 3.9897804510299034E-002, + sigmaOut: 2.1297775177673182, + dminOut: 3.2556800493375310E-004, + dmin1Out: 0.17365859019389857, + dmin2Out: 0.31130219122423097, + dnOut: 3.2556800493375310E-004, + dnm1Out: 0.17365859019389857, + dnm2Out: 0.37770462156728835, + }, + { + z: []float64{0.3511999957345300E+00, 0.3113021912242310E+00, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.4176024260775874E+00, 0.3789305338366462E+00, 0.1225912269357841E-02, 0.6931379430343076E-03, 0.2142495326472319E+00, 0.1931399073225591E+00, 0.1948131712866055E-01, 0.4512326600593524E-02, 0.4473569911582631E-01, 0.3255680049337531E-03, 0.1403302870260262E-17, 0.1882488140663987E-17, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + tau: 3.1797943619548145E-004, + sigma: 2.1696753222776173, + i0Out: 1, + n0Out: 4, + ppOut: 1, + tauOut: 3.1797943619548145E-004, + sigmaOut: 2.1696753222776173, + dminOut: 1.3065740500455263E-007, + dmin1Out: 0.19246898670783216, + dmin2Out: 0.31098421178803548, + dnOut: 1.3065740500455263E-007, + dnm1Out: 0.19246898670783216, + dnm2Out: 0.37861255440045072, + }, + { + z: []float64{0.3109842117880355E+00, 0.3113021912242310E+00, 0.2293789231233262E-17, 0.1882488140663987E-17, 0.3793056923434850E+00, 0.3789305338366462E+00, 0.3529411785314453E-03, 0.6931379430343076E-03, 0.1969813133084257E+00, 0.1931399073225591E+00, 0.7457911333267062E-05, 0.4512326600593524E-02, 0.1306574050045526E-06, 0.3255680049337531E-03, 0.2293789231233262E-17, 0.1882488140663987E-17}, + i0: 1, + n0: 4, + pp: 0, + tau: 1.3065240973281283E-007, + sigma: 2.1699933017138124, + i0Out: 1, + n0Out: 4, + ppOut: 0, + tauOut: 1.3065240973281283E-007, + sigmaOut: 2.1699933017138124, + dminOut: 4.4031878668096113E-014, + dmin1Out: 0.19679806330970273, + dmin2Out: 0.31098408113562576, + dnOut: 4.4031878668096113E-014, + dnm1Out: 0.19679806330970273, + dnm2Out: 0.37930556169107532, + }, + { + z: []float64{0.3109842117880355E+00, 0.3109840811356258E+00, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.3793056923434850E+00, 0.3796585028696068E+00, 0.3529411785314453E-03, 0.1831193463132450E-03, 0.1969813133084257E+00, 0.1968055212210360E+00, 0.7457911333267062E-05, 0.4951239861123181E-11, 0.1306574050045526E-06, 0.4403187866809611E-13, 0.2293789231233262E-17, 0.2797722987188916E-17, 0.1810817848712033E+01}, + i0: 1, + n0: 4, + pp: 1, + tau: 4.4031878666982759E-014, + sigma: 2.1699934323662222, + i0Out: 1, + n0Out: 4, + ppOut: 1, + tauOut: 4.4031878666982759E-014, + sigmaOut: 2.1699934323662222, + dminOut: 5.0676424551397798E-027, + dmin1Out: 0.19671064247077341, + dmin2Out: 0.31098408113558174, + dnOut: 5.0676424551397798E-027, + dnm1Out: 0.19671064247077341, + dnm2Out: 0.37965850286956282, + }, + { + z: []float64{0.3109840811355817E+00, 0.3109840811356258E+00, 0.3415542419024794E-17, 0.2797722987188916E-17, 0.3798416222158761E+00, 0.3796585028696068E+00, 0.9487875021856221E-04, 0.1831193463132450E-03, 0.1967106424757246E+00, 0.1968055212210360E+00, 0.1108289770587888E-23, 0.4951239861123181E-11, 0.5067642455139780E-26, 0.4403187866809611E-13, 0.3415542419024794E-17, 0.2797722987188916E-17}, + i0: 1, + n0: 4, + pp: 0, + tau: 5.0676424551397798E-027, + sigma: 2.1699934323662662, + i0Out: 1, + n0Out: 4, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 2.1699934323662662, + dminOut: 5.0676424551397798E-027, + dmin1Out: 0.19666151937261311, + dmin2Out: 0.31098408113558174, + dnOut: 5.0676424551397798E-027, + dnm1Out: 0.19666151937261311, + dnm2Out: 0.37984162221587608, + }, + { + z: []float64{0.3109840811355817E+00, 0.3109840811355817E+00, 0.3415542419024794E-17, 0.4171805735046273E-17, 0.3798416222158761E+00, 0.3799365009660947E+00, 0.9487875021856221E-04, 0.4912310311151891E-04, 0.1967106424757246E+00, 0.1966615193726131E+00, 0.1108289770587888E-23, 0.2855879641297252E-49, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + tau: 9.8330759686306557E-002, + sigma: 2.1699934323662662, + i0Out: 1, + n0Out: 3, + ppOut: 1, + tauOut: 9.8330759686306557E-002, + sigmaOut: 2.1699934323662662, + dminOut: 9.8296460175394978E-002, + dmin1Out: 0.21265332144927518, + dmin2Out: 0.21265332144927518, + dnOut: 9.8296460175394978E-002, + dnm1Out: 0.28160574127978810, + dnm2Out: 0.21265332144927518, + }, + { + z: []float64{0.2126533214492752E+00, 0.3109840811355817E+00, 0.7453545812882342E-17, 0.4171805735046273E-17, 0.2816548643828996E+00, 0.3799365009660947E+00, 0.3429951091160839E-04, 0.4912310311151891E-04, 0.9829646017539498E-01, 0.1966615193726131E+00, 0.3799365009660947E+00, 0.2855879641297252E-49}, + i0: 1, + n0: 3, + pp: 0, + tau: 9.7172513485343004E-002, + sigma: 2.2683241920525727, + i0Out: 1, + n0Out: 3, + ppOut: 0, + tauOut: 9.7172513485343004E-002, + sigmaOut: 2.2683241920525727, + dminOut: 1.1056745151512559E-003, + dmin1Out: 0.11548080796393217, + dmin2Out: 0.11548080796393217, + dnOut: 1.1056745151512559E-003, + dnm1Out: 0.18448235089755655, + dnm2Out: 0.11548080796393217, + }, + { + z: []float64{0.2126533214492752E+00, 0.1154808079639322E+00, 0.7453545812882342E-17, 0.1817901582187390E-16, 0.2816548643828996E+00, 0.1845166504084682E+00, 0.3429951091160839E-04, 0.1827217490071947E-04, 0.9829646017539498E-01, 0.1105674515151256E-02, 0.3799365009660947E+00, 0.2816548643828996E+00, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + tau: 1.0942861809085330E-003, + sigma: 2.3654967055379159, + i0Out: 1, + n0Out: 3, + ppOut: 1, + tauOut: 1.0942861809085330E-003, + sigmaOut: 2.3654967055379159, + dminOut: 1.1278200095129901E-005, + dmin1Out: 0.11438652178302365, + dmin2Out: 0.11438652178302365, + dnOut: 1.1278200095129901E-005, + dnm1Out: 0.18342236422755959, + dnm2Out: 0.11438652178302365, + }, + { + z: []float64{0.1143865217830237E+00, 0.1154808079639322E+00, 0.2932453102768040E-16, 0.1817901582187390E-16, 0.1834406364024603E+00, 0.1845166504084682E+00, 0.1101341475930520E-06, 0.1827217490071947E-04, 0.1127820009512990E-04, 0.1105674515151256E-02, 0.1845166504084682E+00, 0.2816548643828996E+00}, + i0: 1, + n0: 3, + pp: 0, + tau: 1.1269238360546607E-005, + sigma: 2.3665909917188244, + i0Out: 1, + n0Out: 3, + ppOut: 0, + tauOut: 1.1269238360546607E-005, + sigmaOut: 2.3665909917188244, + dminOut: 8.9549629620034135E-009, + dmin1Out: 0.11437525254466312, + dmin2Out: 0.11437525254466312, + dnOut: 8.9549629620034135E-009, + dnm1Out: 0.18342936716409974, + dnm2Out: 0.11437525254466312, + }, + { + z: []float64{0.1143865217830237E+00, 0.1143752525446631E+00, 0.2932453102768040E-16, 0.4703212027287794E-16, 0.1834406364024603E+00, 0.1834294772982473E+00, 0.1101341475930520E-06, 0.6771621290952006E-11, 0.1127820009512990E-04, 0.8954962962003413E-08, 0.1845166504084682E+00, 0.1834406364024603E+00, 0.2169993432366266E+01}, + i0: 1, + n0: 3, + pp: 1, + tau: 8.9549072084035346E-009, + sigma: 2.3666022609571851, + i0Out: 1, + n0Out: 3, + ppOut: 1, + tauOut: 8.9549072084035346E-009, + sigmaOut: 2.3666022609571851, + dminOut: 5.5753269291151117E-014, + dmin1Out: 0.11437524358975594, + dmin2Out: 0.11437524358975594, + dnOut: 5.5753269291151117E-014, + dnm1Out: 0.18342946834334006, + dnm2Out: 0.11437524358975594, + }, + { + z: []float64{0.1143752435897560E+00, 0.1143752525446631E+00, 0.7542783706608855E-16, 0.4703212027287794E-16, 0.1834294683501117E+00, 0.1834294772982473E+00, 0.3305882004599510E-18, 0.6771621290952006E-11, 0.5575326929115112E-13, 0.8954962962003413E-08, 0.1834294772982473E+00, 0.1834406364024603E+00}, + i0: 1, + n0: 3, + pp: 0, + tau: 5.5753269214454873E-014, + sigma: 2.3666022699120921, + i0Out: 1, + n0Out: 3, + ppOut: 0, + tauOut: 5.5753269214454873E-014, + sigmaOut: 2.3666022699120921, + dminOut: 7.6696244203643861E-023, + dmin1Out: 0.11437524358970023, + dmin2Out: 0.11437524358970023, + dnOut: 7.6696244203643861E-023, + dnm1Out: 0.18342946835005580, + dnm2Out: 0.11437524358970023, + }, + { + z: []float64{0.1648283185136998E+01, 0.1396221235720571E+01, 0.1712714336271993E+00, 0.2520619494164272E+00, 0.1510753432847732E+01, 0.1119977945086946E+01, 0.3792800633372563E+00, 0.5620469213879850E+00, 0.1328441621586708E+01, 0.1019485448443405E+01, 0.1388998759717073E+00, 0.6882362364805590E+00, 0.4466938077796418E+00, 0.2681061628164644E+00, 0.7093206047768255E+00, 0.3174875209348847E+00, 0.6843112870203156E+00, 0.9979892152967577E+00, 0.6490582981441884E+00, 0.3956426765003833E+00, 0.5085572738629487E+00, 0.1122623886995757E+01, 0.9750235054014829E-02, 0.3499168501137979E-01, 0.1364886053450573E+00, 0.1417066070690837E+00, 0.2301225778544498E-01, 0.4532233329988395E-02, 0.1646009972289452E+01, 0.6930161671496210E+00, 0.2362515608142310E+00, 0.9760060629252760E+00, 0.5818602562677768E+00, 0.3984323866837953E+00, 0.1797665269485310E-01, 0.4196794303982125E+00, 0.5600419521166516E+00, 0.2492354636952108E-01, 0.2195137569256029E+00, 0.5530950584419837E+00, 0.4184071984843414E+00, 0.2222708575473020E+00, 0.2727864547293006E+00, 0.4156500978626423E+00, 0.6774373914466536E-01, 0.2745959086613283E+00, 0.1050967099374242E+00, 0.6593428521263771E-01, 0.2040338718098096E+00, 0.1079809097801335E+00, 0.1271971985482246E+00, 0.2011496719671002E+00, 0.4444741998443960E-01, 0.1290210252363728E+00, 0.5776327498150620E+00, 0.4262359329629137E-01, 0.3402556968467140E+00, 0.6023491555328507E+00, 0.1086565805630269E+00, 0.3155392911289253E+00, 0.9382999256694983E+00, 0.1171677238805356E+00, 0.7901625299559836E+00, 0.9297887823519896E+00, 0.6095853796269167E+00, 0.7973955560628040E+00, 0.8018125008387630E+00, 0.6023523535200964E+00, 0.2443177602187348E-01, 0.8114406374558937E+00, 0.2277830378453201E+00, 0.1480363940474286E-01, 0.6969081780841352E+00, 0.3759308106650992E+00, 0.8012406122589412E-01, 0.5487604052643561E+00, 0.9781022865072954E-01, 0.1017549972519246E+00, 0.2961248981181939E-03, 0.7617929262469909E-01, 0.8408398800007548E-04, 0.3802088861182694E-03, 0.0000000000000000E+00, 0.0000000000000000E+00}, + i0: 1, + n0: 21, + pp: 0, + tau: 0.0000000000000000, + sigma: 0.0000000000000000, + i0Out: 1, + n0Out: 21, + ppOut: 0, + tauOut: 0.0000000000000000, + sigmaOut: 0.0000000000000000, + dminOut: 7.8766827084626452E-005, + dmin1Out: 1.2363512593342330E-003, + dmin2Out: 1.2363512593342330E-003, + dnOut: 7.8766827084626452E-005, + dnm1Out: 4.3867054272813191E-003, + dnm2Out: 3.7622286348031123E-003, + }, + } { + // TODO(btracey): Check other outputs + i0 := test.i0 - 1 + n0 := test.n0 - 1 + z := make([]float64, len(test.z)) + copy(z, test.z) + + i0Out, n0Out, ppOut, tauOut, sigmaOut, dminOut, dmin1Out, dmin2Out, dnOut, dnm1Out, dnm2Out := impl.Dlasq5(i0, n0, z, test.pp, test.tau, test.sigma) + + if i0Out != test.i0Out-1 { + t.Errorf("Wrong i0. Want %v, got %v", test.n0Out, n0Out) + } + if n0Out != test.n0Out-1 { + t.Errorf("Wrong n0. Want %v, got %v", test.n0Out, n0Out) + } + if ppOut != test.ppOut { + t.Errorf("Wrong pp. Want %v, got %v", test.ppOut, ppOut) + } + if !floats.EqualWithinAbsOrRel(tauOut, test.tauOut, dTol, dTol) { + t.Errorf("Wrong tau. Want %v, got %v", test.tauOut, tauOut) + } + if !floats.EqualWithinAbsOrRel(sigmaOut, test.sigmaOut, dTol, dTol) { + t.Errorf("Wrong tau. Want %v, got %v", test.sigmaOut, sigmaOut) + } + + if !floats.EqualWithinAbsOrRel(dminOut, test.dminOut, dTol, dTol) { + t.Errorf("Wrong dmin. Want %v, got %v", test.dminOut, dminOut) + } + if !floats.EqualWithinAbsOrRel(dmin1Out, test.dmin1Out, dTol, dTol) { + t.Errorf("Wrong dmin1. Want %v, got %v", test.dmin1Out, dmin1Out) + } + if !floats.EqualWithinAbsOrRel(dmin2Out, test.dmin2Out, dTol, dTol) { + t.Errorf("Wrong dmin2. Want %v, got %v", test.dmin2Out, dmin2Out) + } + if !floats.EqualWithinAbsOrRel(dnOut, test.dnOut, dTol, dTol) { + t.Errorf("Wrong dn. Want %v, got %v", test.dnOut, dnOut) + } + if !floats.EqualWithinAbsOrRel(dnm1Out, test.dnm1Out, dTol, dTol) { + t.Errorf("Wrong dnm1. Want %v, got %v", test.dnm1Out, dnm1Out) + } + if !floats.EqualWithinAbsOrRel(dnm2Out, test.dnm2Out, dTol, dTol) { + t.Errorf("Wrong dnm2. Want %v, got %v", test.dnm2Out, dnm2Out) + } + } +} diff --git a/lapack/testlapack/dlasr.go b/lapack/testlapack/dlasr.go new file mode 100644 index 00000000..87a26059 --- /dev/null +++ b/lapack/testlapack/dlasr.go @@ -0,0 +1,148 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlasrer interface { + Dlasr(side blas.Side, pivot lapack.Pivot, direct lapack.Direct, m, n int, c, s, a []float64, lda int) +} + +func DlasrTest(t *testing.T, impl Dlasrer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, pivot := range []lapack.Pivot{lapack.Variable, lapack.Top, lapack.Bottom} { + for _, direct := range []lapack.Direct{lapack.Forward, lapack.Backward} { + for _, test := range []struct { + m, n, lda int + }{ + {5, 5, 0}, + {5, 10, 0}, + {10, 5, 0}, + + {5, 5, 20}, + {5, 10, 20}, + {10, 5, 20}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + var s, c []float64 + if side == blas.Left { + s = make([]float64, m-1) + c = make([]float64, m-1) + } else { + s = make([]float64, n-1) + c = make([]float64, n-1) + } + for k := range s { + theta := rnd.Float64() * 2 * math.Pi + s[k] = math.Sin(theta) + c[k] = math.Cos(theta) + } + aCopy := make([]float64, len(a)) + copy(a, aCopy) + impl.Dlasr(side, pivot, direct, m, n, c, s, a, lda) + + pSize := m + if side == blas.Right { + pSize = n + } + p := blas64.General{ + Rows: pSize, + Cols: pSize, + Stride: pSize, + Data: make([]float64, pSize*pSize), + } + pk := blas64.General{ + Rows: pSize, + Cols: pSize, + Stride: pSize, + Data: make([]float64, pSize*pSize), + } + ptmp := blas64.General{ + Rows: pSize, + Cols: pSize, + Stride: pSize, + Data: make([]float64, pSize*pSize), + } + for i := 0; i < pSize; i++ { + p.Data[i*p.Stride+i] = 1 + ptmp.Data[i*p.Stride+i] = 1 + } + // Compare to direct computation. + for k := range s { + for i := range p.Data { + pk.Data[i] = 0 + } + for i := 0; i < pSize; i++ { + pk.Data[i*p.Stride+i] = 1 + } + if pivot == lapack.Variable { + pk.Data[k*p.Stride+k] = c[k] + pk.Data[k*p.Stride+k+1] = s[k] + pk.Data[(k+1)*p.Stride+k] = -s[k] + pk.Data[(k+1)*p.Stride+k+1] = c[k] + } else if pivot == lapack.Top { + pk.Data[0] = c[k] + pk.Data[k+1] = s[k] + pk.Data[(k+1)*p.Stride] = -s[k] + pk.Data[(k+1)*p.Stride+k+1] = c[k] + } else { + pk.Data[(pSize-1-k)*p.Stride+pSize-k-1] = c[k] + pk.Data[(pSize-1-k)*p.Stride+pSize-1] = s[k] + pk.Data[(pSize-1)*p.Stride+pSize-1-k] = -s[k] + pk.Data[(pSize-1)*p.Stride+pSize-1] = c[k] + } + if direct == lapack.Forward { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, pk, ptmp, 0, p) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, ptmp, pk, 0, p) + } + copy(ptmp.Data, p.Data) + } + + aMat := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + copy(a, aCopy) + newA := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, m*lda), + } + if side == blas.Left { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, p, aMat, 0, newA) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aMat, p, 0, newA) + } + if !floats.EqualApprox(newA.Data, a, 1e-12) { + t.Errorf("A update mismatch") + } + } + } + } + } +} diff --git a/lapack/testlapack/dlasrt.go b/lapack/testlapack/dlasrt.go new file mode 100644 index 00000000..80b1404b --- /dev/null +++ b/lapack/testlapack/dlasrt.go @@ -0,0 +1,80 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dlasrter interface { + Dlasrt(s lapack.Sort, n int, d []float64) +} + +func DlasrtTest(t *testing.T, impl Dlasrter) { + for ti, test := range []struct { + data []float64 + wantInc []float64 + wantDec []float64 + }{ + { + data: nil, + wantInc: nil, + wantDec: nil, + }, + { + data: []float64{}, + wantInc: []float64{}, + wantDec: []float64{}, + }, + { + data: []float64{1}, + wantInc: []float64{1}, + wantDec: []float64{1}, + }, + { + data: []float64{1, 2}, + wantInc: []float64{1, 2}, + wantDec: []float64{2, 1}, + }, + { + data: []float64{1, 2, -3}, + wantInc: []float64{-3, 1, 2}, + wantDec: []float64{2, 1, -3}, + }, + { + data: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, + wantInc: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, + wantDec: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, + }, + { + data: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, + wantInc: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, + wantDec: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, + }, + { + data: []float64{-2, 4, -1, 2, -4, 0, 3, 5, -5, 1, -3}, + wantInc: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, + wantDec: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, + }, + } { + n := len(test.data) + ds := make([]float64, n) + + copy(ds, test.data) + impl.Dlasrt(lapack.SortIncreasing, n, ds) + if !floats.Equal(ds, test.wantInc) { + t.Errorf("Case #%v: unexpected result of SortIncreasing", ti) + } + + copy(ds, test.data) + impl.Dlasrt(lapack.SortDecreasing, n, ds) + if !floats.Equal(ds, test.wantDec) { + t.Errorf("Case #%v: unexpected result of SortIncreasing", ti) + } + } +} diff --git a/lapack/testlapack/dlasv2.go b/lapack/testlapack/dlasv2.go new file mode 100644 index 00000000..85184e62 --- /dev/null +++ b/lapack/testlapack/dlasv2.go @@ -0,0 +1,48 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dlasv2er interface { + Dlasv2(f, g, h float64) (ssmin, ssmax, snr, csr, snl, csl float64) +} + +func Dlasv2Test(t *testing.T, impl Dlasv2er) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < 100; i++ { + f := rnd.NormFloat64() + g := rnd.NormFloat64() + h := rnd.NormFloat64() + + ssmin, ssmax, snr, csr, snl, csl := impl.Dlasv2(f, g, h) + + // tmp = + // [ csl snl] [f g] + // [-snl csl] [0 h] + tmp11 := csl * f + tmp12 := csl*g + snl*h + tmp21 := -snl * f + tmp22 := -snl*g + csl*h + // lhs = + // [tmp11 tmp12] [csr -snr] + // [tmp21 tmp22] [snr csr] + ans11 := tmp11*csr + tmp12*snr + ans12 := tmp11*-snr + tmp12*csr + ans21 := tmp21*csr + tmp22*snr + ans22 := tmp21*-snr + tmp22*csr + + lhs := []float64{ans11, ans12, ans21, ans22} + rhs := []float64{ssmax, 0, 0, ssmin} + if !floats.EqualApprox(rhs, lhs, 1e-12) { + t.Errorf("SVD mismatch. f = %v, g = %v, h = %v.\nLHS: %v\nRHS: %v", f, g, h, lhs, rhs) + } + } +} diff --git a/lapack/testlapack/dlaswp.go b/lapack/testlapack/dlaswp.go new file mode 100644 index 00000000..9d8e08d7 --- /dev/null +++ b/lapack/testlapack/dlaswp.go @@ -0,0 +1,130 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlaswper interface { + Dlaswp(n int, a []float64, lda, k1, k2 int, ipiv []int, incX int) +} + +func DlaswpTest(t *testing.T, impl Dlaswper) { + for ti, test := range []struct { + k1, k2 int + ipiv []int + incX int + + want blas64.General + }{ + { + k1: 0, + k2: 2, + ipiv: []int{0, 1, 2}, + incX: 1, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + }, + }, + }, + { + k1: 0, + k2: 2, + ipiv: []int{0, 1, 2}, + incX: -1, + want: blas64.General{ + Rows: 4, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + }, + }, + }, + { + k1: 0, + k2: 2, + ipiv: []int{1, 2, 3}, + incX: 1, + want: blas64.General{ + Rows: 5, + Cols: 3, + Stride: 3, + Data: []float64{ + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + 1, 2, 3, + 13, 14, 15, + }, + }, + }, + { + k1: 0, + k2: 2, + ipiv: []int{1, 2, 3}, + incX: -1, + want: blas64.General{ + Rows: 5, + Cols: 3, + Stride: 3, + Data: []float64{ + 10, 11, 12, + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 13, 14, 15, + }, + }, + }, + } { + m := test.want.Rows + n := test.want.Cols + k1 := test.k1 + k2 := test.k2 + if len(test.ipiv) != k2+1 { + panic("bad length of ipiv") + } + incX := test.incX + for _, extra := range []int{0, 11} { + a := zeros(m, n, n+extra) + c := 1 + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = float64(c) + c++ + } + } + + ipiv := make([]int, len(test.ipiv)) + copy(ipiv, test.ipiv) + + impl.Dlaswp(n, a.Data, a.Stride, k1, k2, ipiv, incX) + + prefix := fmt.Sprintf("Case %v (m=%v,n=%v,k1=%v,k2=%v,extra=%v)", ti, m, n, k1, k2, extra) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + + if !equalApproxGeneral(a, test.want, 0) { + t.Errorf("%v: unexpected A\n%v\n%v", prefix, a, test.want) + } + } + } +} diff --git a/lapack/testlapack/dlasy2.go b/lapack/testlapack/dlasy2.go new file mode 100644 index 00000000..7ed5ed8c --- /dev/null +++ b/lapack/testlapack/dlasy2.go @@ -0,0 +1,104 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlasy2er interface { + Dlasy2(tranl, tranr bool, isgn, n1, n2 int, tl []float64, ldtl int, tr []float64, ldtr int, b []float64, ldb int, x []float64, ldx int) (scale, xnorm float64, ok bool) +} + +func Dlasy2Test(t *testing.T, impl Dlasy2er) { + rnd := rand.New(rand.NewSource(1)) + for _, tranl := range []bool{true, false} { + for _, tranr := range []bool{true, false} { + for _, isgn := range []int{1, -1} { + for _, n1 := range []int{0, 1, 2} { + for _, n2 := range []int{0, 1, 2} { + for _, extra := range []int{0, 1, 2, 13} { + for cas := 0; cas < 1000; cas++ { + testDlasy2(t, impl, tranl, tranr, isgn, n1, n2, extra, rnd) + } + } + } + } + } + } + } +} + +func testDlasy2(t *testing.T, impl Dlasy2er, tranl, tranr bool, isgn, n1, n2, extra int, rnd *rand.Rand) { + const tol = 1e-11 + + tl := randomGeneral(n1, n1, n1+extra, rnd) + tr := randomGeneral(n2, n2, n2+extra, rnd) + b := randomGeneral(n1, n2, n2+extra, rnd) + x := randomGeneral(n1, n2, n2+extra, rnd) + + scale, xnorm, ok := impl.Dlasy2(tranl, tranr, isgn, n1, n2, tl.Data, tl.Stride, tr.Data, tr.Stride, b.Data, b.Stride, x.Data, x.Stride) + if scale > 1 { + t.Errorf("invalid value of scale, want <= 1, got %v", scale) + } + if n1 == 0 || n2 == 0 { + return + } + + prefix := fmt.Sprintf("Case n1=%v, n2=%v, isgn=%v", n1, n2, isgn) + + // Check any invalid modifications of x. + if !generalOutsideAllNaN(x) { + t.Errorf("%v: out-of-range write to x\n%v", prefix, x.Data) + } + + var xnormWant float64 + for i := 0; i < n1; i++ { + var rowsum float64 + for j := 0; j < n2; j++ { + rowsum += math.Abs(x.Data[i*x.Stride+j]) + } + if rowsum > xnormWant { + xnormWant = rowsum + } + } + if xnormWant != xnorm { + t.Errorf("%v: unexpected xnorm: want %v, got %v", prefix, xnormWant, xnorm) + } + + // Multiply b by scale to get the wanted right-hand side. + for i := 0; i < n1; i++ { + for j := 0; j < n2; j++ { + b.Data[i*b.Stride+j] *= scale + } + } + // Compute the wanted left-hand side. + lhsWant := randomGeneral(n1, n2, n2, rnd) + if tranl { + blas64.Gemm(blas.Trans, blas.NoTrans, 1, tl, x, 0, lhsWant) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tl, x, 0, lhsWant) + } + if tranr { + blas64.Gemm(blas.NoTrans, blas.Trans, float64(isgn), x, tr, 1, lhsWant) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, float64(isgn), x, tr, 1, lhsWant) + } + // Compare them. + for i := 0; i < n1; i++ { + for j := 0; j < n2; j++ { + diff := lhsWant.Data[i*lhsWant.Stride+j] - b.Data[i*b.Stride+j] + if math.Abs(diff) > tol && ok { + t.Errorf("%v: unexpected result, diff[%v,%v]=%v", prefix, i, j, diff) + } + } + } +} diff --git a/lapack/testlapack/dlatrd.go b/lapack/testlapack/dlatrd.go new file mode 100644 index 00000000..f4d3cddc --- /dev/null +++ b/lapack/testlapack/dlatrd.go @@ -0,0 +1,245 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlatrder interface { + Dlatrd(uplo blas.Uplo, n, nb int, a []float64, lda int, e, tau, w []float64, ldw int) +} + +func DlatrdTest(t *testing.T, impl Dlatrder) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, test := range []struct { + n, nb, lda, ldw int + }{ + {5, 2, 0, 0}, + {5, 5, 0, 0}, + + {5, 3, 10, 11}, + {5, 5, 10, 11}, + } { + n := test.n + nb := test.nb + lda := test.lda + if lda == 0 { + lda = n + } + ldw := test.ldw + if ldw == 0 { + ldw = nb + } + + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + e := make([]float64, n-1) + for i := range e { + e[i] = math.NaN() + } + tau := make([]float64, n-1) + for i := range tau { + tau[i] = math.NaN() + } + w := make([]float64, n*ldw) + for i := range w { + w[i] = math.NaN() + } + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + impl.Dlatrd(uplo, n, nb, a, lda, e, tau, w, ldw) + + // Construct Q. + ldq := n + q := blas64.General{ + Rows: n, + Cols: n, + Stride: ldq, + Data: make([]float64, n*ldq), + } + for i := 0; i < n; i++ { + q.Data[i*ldq+i] = 1 + } + if uplo == blas.Upper { + for i := n - 1; i >= n-nb; i-- { + if i == 0 { + continue + } + h := blas64.General{ + Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n), + } + for j := 0; j < n; j++ { + h.Data[j*n+j] = 1 + } + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + for j := 0; j < i-1; j++ { + v.Data[j] = a[j*lda+i] + } + v.Data[i-1] = 1 + + blas64.Ger(-tau[i-1], v, v, h) + + qTmp := blas64.General{ + Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n), + } + copy(qTmp.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qTmp, h, 0, q) + } + } else { + for i := 0; i < nb; i++ { + if i == n-1 { + continue + } + h := blas64.General{ + Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n), + } + for j := 0; j < n; j++ { + h.Data[j*n+j] = 1 + } + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + v.Data[i+1] = 1 + for j := i + 2; j < n; j++ { + v.Data[j] = a[j*lda+i] + } + blas64.Ger(-tau[i], v, v, h) + + qTmp := blas64.General{ + Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n), + } + copy(qTmp.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qTmp, h, 0, q) + } + } + errStr := fmt.Sprintf("isUpper = %v, n = %v, nb = %v", uplo == blas.Upper, n, nb) + if !isOrthonormal(q) { + t.Errorf("Q not orthonormal. %s", errStr) + } + aGen := genFromSym(blas64.Symmetric{N: n, Stride: lda, Uplo: uplo, Data: aCopy}) + if !dlatrdCheckDecomposition(t, uplo, n, nb, e, tau, a, lda, aGen, q) { + t.Errorf("Decomposition mismatch. %s", errStr) + } + } + } +} + +// dlatrdCheckDecomposition checks that the first nb rows have been successfully +// reduced. +func dlatrdCheckDecomposition(t *testing.T, uplo blas.Uplo, n, nb int, e, tau, a []float64, lda int, aGen, q blas64.General) bool { + // Compute Q^T * A * Q. + tmp := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + ans := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aGen, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, ans) + + // Compare with T. + if uplo == blas.Upper { + for i := n - 1; i >= n-nb; i-- { + for j := 0; j < n; j++ { + v := ans.Data[i*ans.Stride+j] + switch { + case i == j: + if math.Abs(v-a[i*lda+j]) > 1e-10 { + return false + } + case i == j-1: + if math.Abs(a[i*lda+j]-1) > 1e-10 { + return false + } + if math.Abs(v-e[i]) > 1e-10 { + return false + } + case i == j+1: + default: + if math.Abs(v) > 1e-10 { + return false + } + } + } + } + } else { + for i := 0; i < nb; i++ { + for j := 0; j < n; j++ { + v := ans.Data[i*ans.Stride+j] + switch { + case i == j: + if math.Abs(v-a[i*lda+j]) > 1e-10 { + return false + } + case i == j-1: + case i == j+1: + if math.Abs(a[i*lda+j]-1) > 1e-10 { + return false + } + if math.Abs(v-e[i-1]) > 1e-10 { + return false + } + default: + if math.Abs(v) > 1e-10 { + return false + } + } + } + } + } + return true +} + +// genFromSym constructs a (symmetric) general matrix from the data in the +// symmetric. +// TODO(btracey): Replace other constructions of this with a call to this function. +func genFromSym(a blas64.Symmetric) blas64.General { + n := a.N + lda := a.Stride + uplo := a.Uplo + b := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := a.Data[i*lda+j] + if uplo == blas.Lower { + v = a.Data[j*lda+i] + } + b.Data[i*n+j] = v + b.Data[j*n+i] = v + } + } + return b +} diff --git a/lapack/testlapack/dlatrs.go b/lapack/testlapack/dlatrs.go new file mode 100644 index 00000000..b6800895 --- /dev/null +++ b/lapack/testlapack/dlatrs.go @@ -0,0 +1,141 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dlatrser interface { + Dlatrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, normin bool, n int, a []float64, lda int, x []float64, cnorm []float64) (scale float64) +} + +func DlatrsTest(t *testing.T, impl Dlatrser) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, trans := range []blas.Transpose{blas.Trans, blas.NoTrans} { + for _, n := range []int{0, 1, 2, 3, 4, 5, 6, 7, 10, 20, 50, 100} { + for _, lda := range []int{n, 2*n + 1} { + lda = max(1, lda) + imats := []int{7, 11, 12, 13, 14, 15, 16, 17, 18} + if n < 6 { + imats = append(imats, 19) + } + for _, imat := range imats { + testDlatrs(t, impl, imat, uplo, trans, n, lda, rnd) + } + } + } + } + } +} + +func testDlatrs(t *testing.T, impl Dlatrser, imat int, uplo blas.Uplo, trans blas.Transpose, n, lda int, rnd *rand.Rand) { + const tol = 1e-14 + + a := nanSlice(n * lda) + b := nanSlice(n) + work := make([]float64, 3*n) + + // Generate triangular test matrix and right hand side. + diag := dlattr(imat, uplo, trans, n, a, lda, b, work, rnd) + if imat <= 10 { + // b has not been generated. + dlarnv(b, 3, rnd) + } + + cnorm := nanSlice(n) + x := make([]float64, n) + + // Call Dlatrs with normin=false. + copy(x, b) + scale := impl.Dlatrs(uplo, trans, diag, false, n, a, lda, x, cnorm) + prefix := fmt.Sprintf("Case imat=%v (n=%v,lda=%v,trans=%v,uplo=%v,diag=%v", imat, n, lda, trans, uplo, diag) + for i, v := range cnorm { + if math.IsNaN(v) { + t.Errorf("%v: cnorm[%v] not computed (scale=%v,normin=false)", prefix, i, scale) + } + } + resid, hasNaN := dlatrsResidual(uplo, trans, diag, n, a, lda, scale, cnorm, x, b, work[:n]) + if hasNaN { + t.Errorf("%v: unexpected NaN (scale=%v,normin=false)", prefix, scale) + } else if resid > tol { + t.Errorf("%v: residual %v too large (scale=%v,normin=false)", prefix, scale) + } + + // Call Dlatrs with normin=true because cnorm has been filled. + copy(x, b) + scale = impl.Dlatrs(uplo, trans, diag, true, n, a, lda, x, cnorm) + resid, hasNaN = dlatrsResidual(uplo, trans, diag, n, a, lda, scale, cnorm, x, b, work[:n]) + if hasNaN { + t.Errorf("%v: unexpected NaN (scale=%v,normin=true)", prefix, scale) + } else if resid > tol { + t.Errorf("%v: residual %v too large (scale=%v,normin=true)", prefix, scale) + } +} + +// dlatrsResidual returns norm(trans(A)*x-scale*b) / (norm(trans(A))*norm(x)*eps) +// and whether NaN has been encountered in the process. +func dlatrsResidual(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []float64, lda int, scale float64, cnorm []float64, x, b, work []float64) (resid float64, hasNaN bool) { + if n == 0 { + return 0, false + } + + // Compute the norm of the triangular matrix A using the column norms + // already computed by Dlatrs. + var tnorm float64 + if diag == blas.NonUnit { + for j := 0; j < n; j++ { + tnorm = math.Max(tnorm, math.Abs(a[j*lda+j])+cnorm[j]) + } + } else { + for j := 0; j < n; j++ { + tnorm = math.Max(tnorm, 1+cnorm[j]) + } + } + + eps := dlamchE + smlnum := dlamchS + bi := blas64.Implementation() + + // Compute norm(trans(A)*x-scale*b) / (norm(trans(A))*norm(x)*eps) + copy(work, x) + ix := bi.Idamax(n, work, 1) + xnorm := math.Max(1, math.Abs(work[ix])) + xscal := 1 / xnorm / float64(n) + bi.Dscal(n, xscal, work, 1) + bi.Dtrmv(uplo, trans, diag, n, a, lda, work, 1) + bi.Daxpy(n, -scale*xscal, b, 1, work, 1) + for _, v := range work { + if math.IsNaN(v) { + return 1 / eps, true + } + } + ix = bi.Idamax(n, work, 1) + resid = math.Abs(work[ix]) + ix = bi.Idamax(n, x, 1) + xnorm = math.Abs(x[ix]) + if resid*smlnum <= xnorm { + if xnorm > 0 { + resid /= xnorm + } + } else if resid > 0 { + resid = 1 / eps + } + if resid*smlnum <= tnorm { + if tnorm > 0 { + resid /= tnorm + } + } else if resid > 0 { + resid = 1 / eps + } + return resid, false +} diff --git a/lapack/testlapack/dorg2l.go b/lapack/testlapack/dorg2l.go new file mode 100644 index 00000000..e1f2f155 --- /dev/null +++ b/lapack/testlapack/dorg2l.go @@ -0,0 +1,75 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +type Dorg2ler interface { + Dorg2l(m, n, k int, a []float64, lda int, tau, work []float64) + Dgeql2er +} + +func Dorg2lTest(t *testing.T, impl Dorg2ler) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, k, lda int + }{ + {5, 4, 3, 0}, + {5, 4, 4, 0}, + {3, 3, 2, 0}, + {5, 5, 5, 0}, + } { + m := test.m + n := test.n + k := test.k + lda := test.lda + if lda == 0 { + lda = n + } + + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + tau := nanSlice(max(m, n)) + work := make([]float64, n) + impl.Dgeql2(m, n, a, lda, tau, work) + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dorg2l(m, n, k, a, lda, tau[n-k:], work) + if !hasOrthonormalColumns(m, n, a, lda) { + t.Errorf("Q is not orthonormal. m = %v, n = %v, k = %v", m, n, k) + } + } +} + +// hasOrthornormalColumns checks that the columns of a are orthonormal. +func hasOrthonormalColumns(m, n int, a []float64, lda int) bool { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dot := blas64.Dot(m, + blas64.Vector{Inc: lda, Data: a[i:]}, + blas64.Vector{Inc: lda, Data: a[j:]}, + ) + if i == j { + if math.Abs(dot-1) > 1e-10 { + return false + } + } else { + if math.Abs(dot) > 1e-10 { + return false + } + } + } + } + return true +} diff --git a/lapack/testlapack/dorg2r.go b/lapack/testlapack/dorg2r.go new file mode 100644 index 00000000..beeca34d --- /dev/null +++ b/lapack/testlapack/dorg2r.go @@ -0,0 +1,79 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dorg2rer interface { + Dgeqrfer + Dorg2r(m, n, k int, a []float64, lda int, tau []float64, work []float64) +} + +func Dorg2rTest(t *testing.T, impl Dorg2rer) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, k, lda int + }{ + {3, 3, 0, 0}, + {4, 3, 0, 0}, + {3, 3, 2, 0}, + {4, 3, 2, 0}, + + {5, 5, 0, 20}, + {5, 5, 3, 20}, + {10, 5, 0, 20}, + {10, 5, 2, 20}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + k := min(m, n) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgeqrf(m, n, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) + + k = test.k + if k == 0 { + k = n + } + q := constructQK("QR", m, n, k, a, lda, tau) + + impl.Dorg2r(m, n, k, a, lda, tau, work) + + // Check that the first n columns match. + same := true + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if !floats.EqualWithinAbsOrRel(q.Data[i*q.Stride+j], a[i*lda+j], 1e-12, 1e-12) { + same = false + break + } + } + } + if !same { + fmt.Println() + fmt.Println("a =") + printRowise(a, m, n, lda, false) + fmt.Println("q =") + printRowise(q.Data, q.Rows, q.Cols, q.Stride, false) + t.Errorf("Q mismatch") + } + } +} diff --git a/lapack/testlapack/dorgbr.go b/lapack/testlapack/dorgbr.go new file mode 100644 index 00000000..3f43fb94 --- /dev/null +++ b/lapack/testlapack/dorgbr.go @@ -0,0 +1,156 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dorgbrer interface { + Dorgbr(vect lapack.DecompUpdate, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) + Dgebrder +} + +func DorgbrTest(t *testing.T, impl Dorgbrer) { + rnd := rand.New(rand.NewSource(1)) + for _, vect := range []lapack.DecompUpdate{lapack.ApplyQ, lapack.ApplyP} { + for _, test := range []struct { + m, n, k, lda int + }{ + {5, 5, 5, 0}, + {5, 5, 3, 0}, + {5, 3, 5, 0}, + {3, 5, 5, 0}, + {3, 4, 5, 0}, + {3, 5, 4, 0}, + {4, 3, 5, 0}, + {4, 5, 3, 0}, + {5, 3, 4, 0}, + {5, 4, 3, 0}, + + {5, 5, 5, 10}, + {5, 5, 3, 10}, + {5, 3, 5, 10}, + {3, 5, 5, 10}, + {3, 4, 5, 10}, + {3, 5, 4, 10}, + {4, 3, 5, 10}, + {4, 5, 3, 10}, + {5, 3, 4, 10}, + {5, 4, 3, 10}, + } { + m := test.m + n := test.n + k := test.k + lda := test.lda + // Filter out bad tests + if vect == lapack.ApplyQ { + if m < n || n < min(m, k) || m < min(m, k) { + continue + } + } else { + if n < m || m < min(n, k) || n < min(n, k) { + continue + } + } + // Sizes for Dorgbr. + var ma, na int + if vect == lapack.ApplyQ { + if m >= k { + ma = m + na = k + } else { + ma = m + na = m + } + } else { + if n >= k { + ma = k + na = n + } else { + ma = n + na = n + } + } + // a eventually needs to store either P or Q, so it must be + // sufficiently big. + var a []float64 + if vect == lapack.ApplyQ { + lda = max(m, lda) + a = make([]float64, m*lda) + } else { + lda = max(n, lda) + a = make([]float64, n*lda) + } + for i := range a { + a[i] = rnd.NormFloat64() + } + + nTau := min(ma, na) + tauP := make([]float64, nTau) + tauQ := make([]float64, nTau) + d := make([]float64, nTau) + e := make([]float64, nTau) + lwork := -1 + work := make([]float64, 1) + impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, lwork) + work = make([]float64, int(work[0])) + lwork = len(work) + impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, lwork) + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + var tau []float64 + if vect == lapack.ApplyQ { + tau = tauQ + } else { + tau = tauP + } + + impl.Dorgbr(vect, m, n, k, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + lwork = len(work) + impl.Dorgbr(vect, m, n, k, a, lda, tau, work, lwork) + + var ans blas64.General + var nRows, nCols int + equal := true + if vect == lapack.ApplyQ { + nRows = m + nCols = m + if m >= k { + nCols = n + } + ans = constructQPBidiagonal(vect, ma, na, min(m, k), aCopy, lda, tau) + } else { + nRows = n + if k < n { + nRows = m + } + nCols = n + ansTmp := constructQPBidiagonal(vect, ma, na, min(k, n), aCopy, lda, tau) + // Dorgbr actually computes P^T + ans = transposeGeneral(ansTmp) + } + for i := 0; i < nRows; i++ { + for j := 0; j < nCols; j++ { + if !floats.EqualWithinAbsOrRel(a[i*lda+j], ans.Data[i*ans.Stride+j], 1e-8, 1e-8) { + equal = false + } + } + } + if !equal { + applyQ := vect == lapack.ApplyQ + t.Errorf("Extracted matrix mismatch. applyQ: %v, m = %v, n = %v, k = %v", applyQ, m, n, k) + } + } + } +} diff --git a/lapack/testlapack/dorghr.go b/lapack/testlapack/dorghr.go new file mode 100644 index 00000000..7311d015 --- /dev/null +++ b/lapack/testlapack/dorghr.go @@ -0,0 +1,99 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dorghrer interface { + Dorghr(n, ilo, ihi int, a []float64, lda int, tau, work []float64, lwork int) + + Dgehrder +} + +func DorghrTest(t *testing.T, impl Dorghrer) { + rnd := rand.New(rand.NewSource(1)) + + for _, n := range []int{1, 2, 3, 4, 5, 6, 7, 8, 23, 34} { + for _, extra := range []int{0, 1, 13} { + for _, optwork := range []bool{true, false} { + for cas := 0; cas < 100; cas++ { + ilo := rnd.Intn(n) + ihi := rnd.Intn(n) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + testDorghr(t, impl, n, ilo, ihi, extra, optwork, rnd) + } + } + } + } + testDorghr(t, impl, 0, 0, -1, 0, false, rnd) + testDorghr(t, impl, 0, 0, -1, 0, true, rnd) +} + +func testDorghr(t *testing.T, impl Dorghrer, n, ilo, ihi, extra int, optwork bool, rnd *rand.Rand) { + const tol = 1e-14 + + // Construct the matrix A with elementary reflectors and scalar factors tau. + a := randomGeneral(n, n, n+extra, rnd) + var tau []float64 + if n > 1 { + tau = nanSlice(n - 1) + } + work := nanSlice(max(1, n)) // Minimum work for Dgehrd. + impl.Dgehrd(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) + + // Extract Q for later comparison. + q := eye(n, n) + qCopy := cloneGeneral(q) + for j := ilo; j < ihi; j++ { + h := eye(n, n) + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + v.Data[j+1] = 1 + for i := j + 2; i < ihi+1; i++ { + v.Data[i] = a.Data[i*a.Stride+j] + } + blas64.Ger(-tau[j], v, v, h) + copy(qCopy.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q) + } + + if optwork { + work = nanSlice(1) + impl.Dorghr(n, ilo, ihi, a.Data, a.Stride, tau, work, -1) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, ihi-ilo)) + } + impl.Dorghr(n, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) + + prefix := fmt.Sprintf("Case n=%v, ilo=%v, ihi=%v, extra=%v, optwork=%v", n, ilo, ihi, extra, optwork) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A\n%v", prefix, a.Data) + } + if !isOrthonormal(a) { + t.Errorf("%v: A is not orthogonal\n%v", prefix, a.Data) + } + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + aij := a.Data[i*a.Stride+j] + qij := q.Data[i*q.Stride+j] + if math.Abs(aij-qij) > tol { + t.Errorf("%v: unexpected value of A[%v,%v]. want %v, got %v", prefix, i, j, qij, aij) + } + } + } +} diff --git a/lapack/testlapack/dorgl2.go b/lapack/testlapack/dorgl2.go new file mode 100644 index 00000000..5ae3fcb1 --- /dev/null +++ b/lapack/testlapack/dorgl2.go @@ -0,0 +1,65 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dorgl2er interface { + Dgelqfer + Dorgl2(m, n, k int, a []float64, lda int, tau []float64, work []float64) +} + +func Dorgl2Test(t *testing.T, impl Dorgl2er) { + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, n, lda int + }{ + {3, 3, 0}, + {3, 4, 0}, + + {5, 5, 20}, + {5, 10, 20}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = test.n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + k := min(m, n) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgelqf(m, n, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgelqf(m, n, a, lda, tau, work, len(work)) + + q := constructQ("LQ", m, n, a, lda, tau) + + impl.Dorgl2(m, n, k, a, lda, tau, work) + + // Check that the first m rows match. + same := true + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if !floats.EqualWithinAbsOrRel(q.Data[i*q.Stride+j], a[i*lda+j], 1e-12, 1e-12) { + same = false + break + } + } + } + if !same { + t.Errorf("Q mismatch") + } + } +} diff --git a/lapack/testlapack/dorglq.go b/lapack/testlapack/dorglq.go new file mode 100644 index 00000000..3d8bb105 --- /dev/null +++ b/lapack/testlapack/dorglq.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dorglqer interface { + Dorgl2er + Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DorglqTest(t *testing.T, impl Dorglqer) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Base tests off of nb and nx. + for _, test := range []struct{ m, n, k, lda int }{ + {10, 10, 10, 0}, + {10, 10, 10, 20}, + {10, 30, 10, 0}, + {20, 30, 10, 0}, + + {100, 100, 100, 0}, + {100, 100, 50, 0}, + {100, 130, 100, 0}, + {100, 130, 50, 0}, + {100, 100, 100, 150}, + {100, 100, 50, 150}, + {100, 130, 100, 150}, + {100, 130, 50, 150}, + + {200, 200, 200, 0}, + {200, 200, 150, 0}, + {200, 230, 200, 0}, + {200, 230, 150, 0}, + {200, 200, 200, 250}, + {200, 200, 150, 250}, + {200, 230, 200, 250}, + {200, 230, 150, 250}, + } { + m := test.m + n := test.n + k := test.k + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + work := make([]float64, 1) + tau := make([]float64, m) + for i := range tau { + tau[i] = math.NaN() + } + // Compute LQ factorization. + impl.Dgelqf(m, n, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgelqf(m, n, a, lda, tau, work, len(work)) + + aUnblocked := make([]float64, len(a)) + copy(aUnblocked, a) + for i := range work { + work[i] = math.NaN() + } + impl.Dorgl2(m, n, k, aUnblocked, lda, tau, work) + // make sure work isn't used before initialized + for i := range work { + work[i] = math.NaN() + } + impl.Dorglq(m, n, k, a, lda, tau, work, len(work)) + if !floats.EqualApprox(a, aUnblocked, 1e-10) { + t.Errorf("Q Mismatch. m = %d, n = %d, k = %d, lda = %d", m, n, k, lda) + } + } +} diff --git a/lapack/testlapack/dorgql.go b/lapack/testlapack/dorgql.go new file mode 100644 index 00000000..4cf9b22a --- /dev/null +++ b/lapack/testlapack/dorgql.go @@ -0,0 +1,130 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dorgqler interface { + Dorgql(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) + + Dlarfger +} + +func DorgqlTest(t *testing.T, impl Dorgqler) { + const tol = 1e-14 + + type Dorg2ler interface { + Dorg2l(m, n, k int, a []float64, lda int, tau, work []float64) + } + dorg2ler, hasDorg2l := impl.(Dorg2ler) + + rnd := rand.New(rand.NewSource(1)) + for _, m := range []int{0, 1, 2, 3, 4, 5, 7, 10, 15, 30, 50, 150} { + for _, extra := range []int{0, 11} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + var k int + if m >= 129 { + // For large matrices make sure that k + // is large enough to trigger blocked + // path. + k = 129 + rnd.Intn(m-129+1) + } else { + k = rnd.Intn(m + 1) + } + n := k + rnd.Intn(m-k+1) + if m == 0 || n == 0 { + m = 0 + n = 0 + k = 0 + } + + // Generate k elementary reflectors in the last + // k columns of A. + a := nanGeneral(m, n, n+extra) + tau := make([]float64, k) + for l := 0; l < k; l++ { + jj := m - k + l + v := randomSlice(jj, rnd) + _, tau[l] = impl.Dlarfg(len(v)+1, rnd.NormFloat64(), v, 1) + j := n - k + l + for i := 0; i < jj; i++ { + a.Data[i*a.Stride+j] = v[i] + } + } + aCopy := cloneGeneral(a) + + // Compute the full matrix Q by forming the + // Householder reflectors explicitly. + q := eye(m, m) + qCopy := eye(m, m) + for l := 0; l < k; l++ { + h := eye(m, m) + jj := m - k + l + j := n - k + l + v := blas64.Vector{1, make([]float64, m)} + for i := 0; i < jj; i++ { + v.Data[i] = a.Data[i*a.Stride+j] + } + v.Data[jj] = 1 + blas64.Ger(-tau[l], v, v, h) + copy(qCopy.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, qCopy, 0, q) + } + // View the last n columns of Q as 'want'. + want := blas64.General{ + Rows: m, + Cols: n, + Stride: q.Stride, + Data: q.Data[m-n:], + } + + var lwork int + switch wl { + case minimumWork: + lwork = max(1, n) + case mediumWork: + work := make([]float64, 1) + impl.Dorgql(m, n, k, nil, a.Stride, nil, work, -1) + lwork = (int(work[0]) + n) / 2 + lwork = max(1, lwork) + case optimumWork: + work := make([]float64, 1) + impl.Dorgql(m, n, k, nil, a.Stride, nil, work, -1) + lwork = int(work[0]) + } + work := make([]float64, lwork) + + // Compute the last n columns of Q by a call to + // Dorgql. + impl.Dorgql(m, n, k, a.Data, a.Stride, tau, work, len(work)) + + prefix := fmt.Sprintf("Case m=%v,n=%v,k=%v,wl=%v", m, n, k, wl) + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + if !equalApproxGeneral(want, a, tol) { + t.Errorf("%v: unexpected Q", prefix) + } + + // Compute the last n columns of Q by a call to + // Dorg2l and check that we get the same result. + if !hasDorg2l { + continue + } + dorg2ler.Dorg2l(m, n, k, aCopy.Data, aCopy.Stride, tau, work) + if !equalApproxGeneral(aCopy, a, tol) { + t.Errorf("%v: mismatch between Dorgql and Dorg2l", prefix) + } + } + } + } +} diff --git a/lapack/testlapack/dorgqr.go b/lapack/testlapack/dorgqr.go new file mode 100644 index 00000000..57306c05 --- /dev/null +++ b/lapack/testlapack/dorgqr.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dorgqrer interface { + Dorg2rer + Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DorgqrTest(t *testing.T, impl Dorgqrer) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): Base tests off of nb and nx. + for _, test := range []struct{ m, n, k, lda int }{ + {10, 10, 10, 0}, + {10, 10, 10, 20}, + {30, 10, 10, 0}, + {30, 20, 10, 20}, + + {100, 100, 100, 0}, + {100, 100, 50, 0}, + {130, 100, 100, 0}, + {130, 100, 50, 0}, + {100, 100, 100, 150}, + {100, 100, 50, 150}, + {130, 100, 100, 150}, + {130, 100, 50, 150}, + + {200, 200, 200, 0}, + {200, 200, 150, 0}, + {230, 200, 200, 0}, + {230, 200, 150, 0}, + {200, 200, 200, 250}, + {200, 200, 150, 250}, + {230, 200, 200, 250}, + {230, 200, 150, 250}, + } { + m := test.m + n := test.n + k := test.k + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rnd.Float64() + } + work := make([]float64, 1) + tau := make([]float64, n) + for i := range tau { + tau[i] = math.NaN() + } + // Compute QR factorization. + impl.Dgeqrf(m, n, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) + + aUnblocked := make([]float64, len(a)) + copy(aUnblocked, a) + for i := range work { + work[i] = math.NaN() + } + impl.Dorg2r(m, n, k, aUnblocked, lda, tau, work) + // make sure work isn't used before initialized + for i := range work { + work[i] = math.NaN() + } + impl.Dorgqr(m, n, k, a, lda, tau, work, len(work)) + if !floats.EqualApprox(a, aUnblocked, 1e-10) { + t.Errorf("Q Mismatch. m = %d, n = %d, k = %d, lda = %d", m, n, k, lda) + } + } +} diff --git a/lapack/testlapack/dorgtr.go b/lapack/testlapack/dorgtr.go new file mode 100644 index 00000000..4f49d1a4 --- /dev/null +++ b/lapack/testlapack/dorgtr.go @@ -0,0 +1,136 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dorgtrer interface { + Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, tau, work []float64, lwork int) + Dsytrder +} + +func DorgtrTest(t *testing.T, impl Dorgtrer) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {2, 0}, + {3, 0}, + {6, 0}, + {33, 0}, + {100, 0}, + + {1, 3}, + {2, 5}, + {3, 7}, + {6, 10}, + {33, 50}, + {100, 120}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + d := make([]float64, n) + e := make([]float64, n-1) + tau := make([]float64, n-1) + work := make([]float64, 1) + impl.Dsytrd(uplo, n, a, lda, d, e, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dsytrd(uplo, n, a, lda, d, e, tau, work, len(work)) + + var lwork int + switch wl { + case minimumWork: + lwork = max(1, n-1) + case mediumWork: + work := make([]float64, 1) + impl.Dorgtr(uplo, n, a, lda, tau, work, -1) + lwork = (int(work[0]) + n - 1) / 2 + lwork = max(1, lwork) + case optimumWork: + work := make([]float64, 1) + impl.Dorgtr(uplo, n, a, lda, tau, work, -1) + lwork = int(work[0]) + } + work = nanSlice(lwork) + + impl.Dorgtr(uplo, n, a, lda, tau, work, len(work)) + + q := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: a, + } + tri := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < n; i++ { + tri.Data[i*tri.Stride+i] = d[i] + if i != n-1 { + tri.Data[i*tri.Stride+i+1] = e[i] + tri.Data[(i+1)*tri.Stride+i] = e[i] + } + } + + aMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := aCopy[i*lda+j] + aMat.Data[i*aMat.Stride+j] = v + aMat.Data[j*aMat.Stride+i] = v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := aCopy[i*lda+j] + aMat.Data[i*aMat.Stride+j] = v + aMat.Data[j*aMat.Stride+i] = v + } + } + } + + tmp := blas64.General{Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n)} + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, aMat, q, 0, tmp) + + ans := blas64.General{Rows: n, Cols: n, Stride: n, Data: make([]float64, n*n)} + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, tmp, 0, ans) + + if !floats.EqualApprox(ans.Data, tri.Data, 1e-13) { + t.Errorf("Recombination mismatch. n = %v, isUpper = %v", n, uplo == blas.Upper) + } + } + } + } +} diff --git a/lapack/testlapack/dorm2r.go b/lapack/testlapack/dorm2r.go new file mode 100644 index 00000000..5e23415d --- /dev/null +++ b/lapack/testlapack/dorm2r.go @@ -0,0 +1,139 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dorm2rer interface { + Dgeqrfer + Dorm2r(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) +} + +func Dorm2rTest(t *testing.T, impl Dorm2rer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + {3, 4, 5, 6, 20}, + {3, 5, 4, 6, 20}, + {4, 3, 5, 6, 20}, + {4, 5, 3, 6, 20}, + {5, 3, 4, 6, 20}, + {5, 4, 3, 6, 20}, + {3, 4, 5, 20, 6}, + {3, 5, 4, 20, 6}, + {4, 3, 5, 20, 6}, + {4, 5, 3, 20, 6}, + {5, 3, 4, 20, 6}, + {5, 4, 3, 20, 6}, + } { + var ma, na, mc, nc int + if side == blas.Left { + ma = test.common + na = test.adim + mc = test.common + nc = test.cdim + } else { + ma = test.common + na = test.adim + mc = test.cdim + nc = test.common + } + + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + // Compute random C matrix + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute QR + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgeqrf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgeqrf(ma, na, a, lda, tau, work, len(work)) + + // Build Q from result + q := constructQ("QR", ma, na, a, lda, tau) + + cMat := blas64.General{ + Rows: mc, + Cols: nc, + Stride: ldc, + Data: make([]float64, len(c)), + } + copy(cMat.Data, c) + cMatCopy := blas64.General{ + Rows: cMat.Rows, + Cols: cMat.Cols, + Stride: cMat.Stride, + Data: make([]float64, len(cMat.Data)), + } + copy(cMatCopy.Data, cMat.Data) + switch { + default: + panic("bad test") + case side == blas.Left && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Left && trans == blas.Trans: + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Right && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMatCopy, q, 0, cMat) + case side == blas.Right && trans == blas.Trans: + blas64.Gemm(blas.NoTrans, blas.Trans, 1, cMatCopy, q, 0, cMat) + } + // Do Dorm2r ard compare + if side == blas.Left { + work = make([]float64, nc) + } else { + work = make([]float64, mc) + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + tauCopy := make([]float64, len(tau)) + copy(tauCopy, tau) + impl.Dorm2r(side, trans, mc, nc, k, a, lda, tau, c, ldc, work) + if !floats.Equal(a, aCopy) { + t.Errorf("a changed in call") + } + if !floats.Equal(tau, tauCopy) { + t.Errorf("tau changed in call") + } + if !floats.EqualApprox(cMat.Data, c, 1e-14) { + t.Errorf("Multiplication mismatch.\n Want %v \n got %v.", cMat.Data, c) + } + } + } + } +} diff --git a/lapack/testlapack/dormbr.go b/lapack/testlapack/dormbr.go new file mode 100644 index 00000000..0a44faf5 --- /dev/null +++ b/lapack/testlapack/dormbr.go @@ -0,0 +1,164 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dormbrer interface { + Dormbr(vect lapack.DecompUpdate, side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) + Dgebrder +} + +func DormbrTest(t *testing.T, impl Dormbrer) { + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, vect := range []lapack.DecompUpdate{lapack.ApplyQ, lapack.ApplyP} { + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + for _, test := range []struct { + m, n, k, lda, ldc int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + + {3, 4, 5, 10, 12}, + {3, 5, 4, 10, 12}, + {4, 3, 5, 10, 12}, + {4, 5, 3, 10, 12}, + {5, 3, 4, 10, 12}, + {5, 4, 3, 10, 12}, + + {150, 140, 130, 0, 0}, + } { + m := test.m + n := test.n + k := test.k + ldc := test.ldc + if ldc == 0 { + ldc = n + } + nq := n + nw := m + if side == blas.Left { + nq = m + nw = n + } + + // Compute a decomposition. + var ma, na int + var a []float64 + if vect == lapack.ApplyQ { + ma = nq + na = k + } else { + ma = k + na = nq + } + lda := test.lda + if lda == 0 { + lda = na + } + a = make([]float64, ma*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + nTau := min(nq, k) + tauP := make([]float64, nTau) + tauQ := make([]float64, nTau) + d := make([]float64, nTau) + e := make([]float64, nTau) + + work := make([]float64, 1) + impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, -1) + work = make([]float64, int(work[0])) + impl.Dgebrd(ma, na, a, lda, d, e, tauQ, tauP, work, len(work)) + + // Apply and compare update. + c := make([]float64, m*ldc) + for i := range c { + c[i] = rnd.NormFloat64() + } + cCopy := make([]float64, len(c)) + copy(cCopy, c) + + var lwork int + switch wl { + case minimumWork: + lwork = nw + case optimumWork: + impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauQ, c, ldc, work, -1) + lwork = int(work[0]) + case mediumWork: + work := make([]float64, 1) + impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauQ, c, ldc, work, -1) + lwork = (int(work[0]) + nw) / 2 + } + lwork = max(1, lwork) + work = make([]float64, lwork) + + if vect == lapack.ApplyQ { + impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauQ, c, ldc, work, lwork) + } else { + impl.Dormbr(vect, side, trans, m, n, k, a, lda, tauP, c, ldc, work, lwork) + } + + // Check that the multiplication was correct. + cOrig := blas64.General{ + Rows: m, + Cols: n, + Stride: ldc, + Data: make([]float64, len(cCopy)), + } + copy(cOrig.Data, cCopy) + cAns := blas64.General{ + Rows: m, + Cols: n, + Stride: ldc, + Data: make([]float64, len(cCopy)), + } + copy(cAns.Data, cCopy) + nb := min(ma, na) + var mulMat blas64.General + if vect == lapack.ApplyQ { + mulMat = constructQPBidiagonal(lapack.ApplyQ, ma, na, nb, a, lda, tauQ) + } else { + mulMat = constructQPBidiagonal(lapack.ApplyP, ma, na, nb, a, lda, tauP) + } + + mulTrans := trans + + if side == blas.Left { + bi.Dgemm(mulTrans, blas.NoTrans, m, n, m, 1, mulMat.Data, mulMat.Stride, cOrig.Data, cOrig.Stride, 0, cAns.Data, cAns.Stride) + } else { + bi.Dgemm(blas.NoTrans, mulTrans, m, n, n, 1, cOrig.Data, cOrig.Stride, mulMat.Data, mulMat.Stride, 0, cAns.Data, cAns.Stride) + } + + if !floats.EqualApprox(cAns.Data, c, 1e-13) { + isApplyQ := vect == lapack.ApplyQ + isLeft := side == blas.Left + isTrans := trans == blas.Trans + + t.Errorf("C mismatch. isApplyQ: %v, isLeft: %v, isTrans: %v, m = %v, n = %v, k = %v, lda = %v, ldc = %v", + isApplyQ, isLeft, isTrans, m, n, k, lda, ldc) + } + } + } + } + } + } +} diff --git a/lapack/testlapack/dormhr.go b/lapack/testlapack/dormhr.go new file mode 100644 index 00000000..7b908aa1 --- /dev/null +++ b/lapack/testlapack/dormhr.go @@ -0,0 +1,132 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dormhrer interface { + Dormhr(side blas.Side, trans blas.Transpose, m, n, ilo, ihi int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) + + Dgehrder +} + +func DormhrTest(t *testing.T, impl Dormhrer) { + rnd := rand.New(rand.NewSource(1)) + + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, m := range []int{1, 2, 3, 4, 5, 8, 9, 10, 23} { + for _, n := range []int{1, 2, 3, 4, 5, 8, 9, 10, 23} { + for _, extra := range []int{0, 1, 13} { + for cas := 0; cas < 10; cas++ { + nq := m + if side == blas.Right { + nq = n + } + ilo := rnd.Intn(nq) + ihi := rnd.Intn(nq) + if ilo > ihi { + ilo, ihi = ihi, ilo + } + testDormhr(t, impl, side, trans, m, n, ilo, ihi, extra, true, rnd) + testDormhr(t, impl, side, trans, m, n, ilo, ihi, extra, false, rnd) + } + } + } + } + } + } + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + testDormhr(t, impl, side, trans, 0, 0, 0, -1, 0, true, rnd) + testDormhr(t, impl, side, trans, 0, 0, 0, -1, 0, false, rnd) + } + } +} + +func testDormhr(t *testing.T, impl Dormhrer, side blas.Side, trans blas.Transpose, m, n, ilo, ihi, extra int, optwork bool, rnd *rand.Rand) { + const tol = 1e-14 + + var nq, nw int + switch side { + case blas.Left: + nq = m + nw = n + case blas.Right: + nq = n + nw = m + } + + // Compute the elementary reflectors and tau. + a := randomGeneral(nq, nq, nq+extra, rnd) + var tau []float64 + if nq > 1 { + tau = nanSlice(nq - 1) + } + work := nanSlice(max(1, nq)) // Minimum work for Dgehrd. + impl.Dgehrd(nq, ilo, ihi, a.Data, a.Stride, tau, work, len(work)) + + // Construct Q from the elementary reflectors in a and from tau. + q := eye(nq, nq) + qCopy := eye(nq, nq) + for j := ilo; j < ihi; j++ { + h := eye(nq, nq) + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, nq), + } + v.Data[j+1] = 1 + for i := j + 2; i < ihi+1; i++ { + v.Data[i] = a.Data[i*a.Stride+j] + } + blas64.Ger(-tau[j], v, v, h) + copy(qCopy.Data, q.Data) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q) + } + + c := randomGeneral(m, n, n+extra, rnd) + + // Compute the product of Q and C explicitly. + qc := randomGeneral(m, n, n+extra, rnd) + if side == blas.Left { + blas64.Gemm(trans, blas.NoTrans, 1, q, c, 0, qc) + } else { + blas64.Gemm(blas.NoTrans, trans, 1, c, q, 0, qc) + } + + // Compute the product of Q and C using Dormhr. + if optwork { + work = nanSlice(1) + impl.Dormhr(side, trans, m, n, ilo, ihi, nil, a.Stride, nil, nil, c.Stride, work, -1) + work = nanSlice(int(work[0])) + } else { + work = nanSlice(max(1, nw)) + } + impl.Dormhr(side, trans, m, n, ilo, ihi, a.Data, a.Stride, tau, c.Data, c.Stride, work, len(work)) + + // Compare the two answers. + prefix := fmt.Sprintf("Case side=%v, trans=%v, m=%v, n=%v, ilo=%v, ihi=%v, extra=%v, optwork=%v", + side, trans, m, n, ilo, ihi, extra, optwork) + if !generalOutsideAllNaN(c) { + t.Errorf("%v: out-of-range write to C\n%v", prefix, c.Data) + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + cij := c.Data[i*c.Stride+j] + qcij := qc.Data[i*qc.Stride+j] + if math.Abs(cij-qcij) > tol { + t.Errorf("%v: unexpected value of the QC product at [%v,%v]: want %v, got %v", prefix, i, j, qcij, cij) + } + } + } +} diff --git a/lapack/testlapack/dorml2.go b/lapack/testlapack/dorml2.go new file mode 100644 index 00000000..909c56e4 --- /dev/null +++ b/lapack/testlapack/dorml2.go @@ -0,0 +1,144 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dorml2er interface { + Dgelqfer + Dorml2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) +} + +func Dorml2Test(t *testing.T, impl Dorml2er) { + rnd := rand.New(rand.NewSource(1)) + // TODO(btracey): This test is not complete, because it + // doesn't test individual values of m, n, and k, instead only testing + // a specific subset of possible k values. + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + + {3, 4, 5, 6, 20}, + {3, 5, 4, 6, 20}, + {4, 3, 5, 6, 20}, + {4, 5, 3, 6, 20}, + {5, 3, 4, 6, 20}, + {5, 4, 3, 6, 20}, + {3, 4, 5, 20, 6}, + {3, 5, 4, 20, 6}, + {4, 3, 5, 20, 6}, + {4, 5, 3, 20, 6}, + {5, 3, 4, 20, 6}, + {5, 4, 3, 20, 6}, + } { + var ma, na, mc, nc int + if side == blas.Left { + ma = test.adim + na = test.common + mc = test.common + nc = test.cdim + } else { + ma = test.adim + na = test.common + mc = test.cdim + nc = test.common + } + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + // Compute random C matrix + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute LQ + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgelqf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgelqf(ma, na, a, lda, tau, work, len(work)) + + // Build Q from result + q := constructQ("LQ", ma, na, a, lda, tau) + + cMat := blas64.General{ + Rows: mc, + Cols: nc, + Stride: ldc, + Data: make([]float64, len(c)), + } + copy(cMat.Data, c) + cMatCopy := blas64.General{ + Rows: cMat.Rows, + Cols: cMat.Cols, + Stride: cMat.Stride, + Data: make([]float64, len(cMat.Data)), + } + copy(cMatCopy.Data, cMat.Data) + switch { + default: + panic("bad test") + case side == blas.Left && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Left && trans == blas.Trans: + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Right && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMatCopy, q, 0, cMat) + case side == blas.Right && trans == blas.Trans: + blas64.Gemm(blas.NoTrans, blas.Trans, 1, cMatCopy, q, 0, cMat) + } + // Do Dorm2r ard compare + if side == blas.Left { + work = make([]float64, nc) + } else { + work = make([]float64, mc) + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + tauCopy := make([]float64, len(tau)) + copy(tauCopy, tau) + impl.Dorml2(side, trans, mc, nc, k, a, lda, tau, c, ldc, work) + if !floats.Equal(a, aCopy) { + t.Errorf("a changed in call") + } + if !floats.Equal(tau, tauCopy) { + t.Errorf("tau changed in call") + } + if !floats.EqualApprox(cMat.Data, c, 1e-14) { + isLeft := side == blas.Left + isTrans := trans == blas.Trans + t.Errorf("Multiplication mismatch. IsLeft = %v. IsTrans = %v", isLeft, isTrans) + } + } + } + } +} diff --git a/lapack/testlapack/dormlq.go b/lapack/testlapack/dormlq.go new file mode 100644 index 00000000..19302e21 --- /dev/null +++ b/lapack/testlapack/dormlq.go @@ -0,0 +1,130 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dormlqer interface { + Dorml2er + Dormlq(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) +} + +func DormlqTest(t *testing.T, impl Dormlqer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {0, 0, 0, 0, 0}, + {6, 7, 8, 0, 0}, + {6, 8, 7, 0, 0}, + {7, 6, 8, 0, 0}, + {7, 8, 6, 0, 0}, + {8, 6, 7, 0, 0}, + {8, 7, 6, 0, 0}, + {100, 200, 300, 0, 0}, + {100, 300, 200, 0, 0}, + {200, 100, 300, 0, 0}, + {200, 300, 100, 0, 0}, + {300, 100, 200, 0, 0}, + {300, 200, 100, 0, 0}, + {100, 200, 300, 400, 500}, + {100, 300, 200, 400, 500}, + {200, 100, 300, 400, 500}, + {200, 300, 100, 400, 500}, + {300, 100, 200, 400, 500}, + {300, 200, 100, 400, 500}, + {100, 200, 300, 500, 400}, + {100, 300, 200, 500, 400}, + {200, 100, 300, 500, 400}, + {200, 300, 100, 500, 400}, + {300, 100, 200, 500, 400}, + {300, 200, 100, 500, 400}, + } { + var ma, na, mc, nc int + if side == blas.Left { + ma = test.adim + na = test.common + mc = test.common + nc = test.cdim + } else { + ma = test.adim + na = test.common + mc = test.cdim + nc = test.common + } + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + // Compute random C matrix + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute LQ + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgelqf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgelqf(ma, na, a, lda, tau, work, len(work)) + + cCopy := make([]float64, len(c)) + copy(cCopy, c) + ans := make([]float64, len(c)) + copy(ans, cCopy) + + var nw int + if side == blas.Left { + nw = nc + } else { + nw = mc + } + work = make([]float64, max(1, nw)) + impl.Dorml2(side, trans, mc, nc, k, a, lda, tau, ans, ldc, work) + + var lwork int + switch wl { + case minimumWork: + lwork = nw + case optimumWork: + impl.Dormlq(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, -1) + lwork = int(work[0]) + case mediumWork: + work := make([]float64, 1) + impl.Dormlq(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, -1) + lwork = (int(work[0]) + nw) / 2 + } + lwork = max(1, lwork) + work = make([]float64, lwork) + + impl.Dormlq(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, lwork) + if !floats.EqualApprox(c, ans, 1e-13) { + t.Errorf("Dormqr and Dorm2r results mismatch") + } + } + } + } + } +} diff --git a/lapack/testlapack/dormqr.go b/lapack/testlapack/dormqr.go new file mode 100644 index 00000000..cfacd81b --- /dev/null +++ b/lapack/testlapack/dormqr.go @@ -0,0 +1,154 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dormqrer interface { + Dorm2rer + Dormqr(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) +} + +func DormqrTest(t *testing.T, impl Dormqrer) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {6, 7, 8, 0, 0}, + {6, 8, 7, 0, 0}, + {7, 6, 8, 0, 0}, + {7, 8, 6, 0, 0}, + {8, 6, 7, 0, 0}, + {8, 7, 6, 0, 0}, + {100, 200, 300, 0, 0}, + {100, 300, 200, 0, 0}, + {200, 100, 300, 0, 0}, + {200, 300, 100, 0, 0}, + {300, 100, 200, 0, 0}, + {300, 200, 100, 0, 0}, + {100, 200, 300, 400, 500}, + {100, 300, 200, 400, 500}, + {200, 100, 300, 400, 500}, + {200, 300, 100, 400, 500}, + {300, 100, 200, 400, 500}, + {300, 200, 100, 400, 500}, + {100, 200, 300, 500, 400}, + {100, 300, 200, 500, 400}, + {200, 100, 300, 500, 400}, + {200, 300, 100, 500, 400}, + {300, 100, 200, 500, 400}, + {300, 200, 100, 500, 400}, + } { + var ma, na, mc, nc int + if side == blas.Left { + ma = test.common + na = test.adim + mc = test.common + nc = test.cdim + } else { + ma = test.common + na = test.adim + mc = test.cdim + nc = test.common + } + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + // Compute random C matrix + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute QR + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgeqrf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgeqrf(ma, na, a, lda, tau, work, len(work)) + + cCopy := make([]float64, len(c)) + copy(cCopy, c) + ans := make([]float64, len(c)) + copy(ans, cCopy) + + if side == blas.Left { + work = make([]float64, nc) + } else { + work = make([]float64, mc) + } + impl.Dorm2r(side, trans, mc, nc, k, a, lda, tau, ans, ldc, work) + + // Make sure Dorm2r and Dormqr match with small work + for i := range work { + work[i] = rnd.Float64() + } + copy(c, cCopy) + impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work)) + if !floats.EqualApprox(c, ans, 1e-12) { + t.Errorf("Dormqr and Dorm2r mismatch for small work") + } + + // Try with the optimum amount of work + copy(c, cCopy) + impl.Dormqr(side, trans, mc, nc, k, nil, lda, nil, nil, ldc, work, -1) + work = make([]float64, int(work[0])) + for i := range work { + work[i] = rnd.Float64() + } + impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work)) + if !floats.EqualApprox(c, ans, 1e-12) { + t.Errorf("Dormqr and Dorm2r mismatch for full work") + fmt.Println("ccopy") + for i := 0; i < mc; i++ { + fmt.Println(cCopy[i*ldc : (i+1)*ldc]) + } + fmt.Println("ans =") + for i := 0; i < mc; i++ { + fmt.Println(ans[i*ldc : (i+1)*ldc]) + } + fmt.Println("c =") + for i := 0; i < mc; i++ { + fmt.Println(c[i*ldc : (i+1)*ldc]) + } + } + + // Try with amount of work that is less than + // optimal but still long enough to use the + // blocked code. + copy(c, cCopy) + if side == blas.Left { + work = make([]float64, 3*nc) + } else { + work = make([]float64, 3*mc) + } + impl.Dormqr(side, trans, mc, nc, k, a, lda, tau, c, ldc, work, len(work)) + if !floats.EqualApprox(c, ans, 1e-12) { + t.Errorf("Dormqr and Dorm2r mismatch for medium work") + } + } + } + } +} diff --git a/lapack/testlapack/dormr2.go b/lapack/testlapack/dormr2.go new file mode 100644 index 00000000..94a13488 --- /dev/null +++ b/lapack/testlapack/dormr2.go @@ -0,0 +1,137 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dormr2er interface { + Dgerqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) + Dormr2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) +} + +func Dormr2Test(t *testing.T, impl Dormr2er) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []blas.Side{blas.Left, blas.Right} { + for _, trans := range []blas.Transpose{blas.NoTrans, blas.Trans} { + for _, test := range []struct { + common, adim, cdim, lda, ldc int + }{ + {3, 4, 5, 0, 0}, + {3, 5, 4, 0, 0}, + {4, 3, 5, 0, 0}, + {4, 5, 3, 0, 0}, + {5, 3, 4, 0, 0}, + {5, 4, 3, 0, 0}, + {3, 4, 5, 6, 20}, + {3, 5, 4, 6, 20}, + {4, 3, 5, 6, 20}, + {4, 5, 3, 6, 20}, + {5, 3, 4, 6, 20}, + {5, 4, 3, 6, 20}, + {3, 4, 5, 20, 6}, + {3, 5, 4, 20, 6}, + {4, 3, 5, 20, 6}, + {4, 5, 3, 20, 6}, + {5, 3, 4, 20, 6}, + {5, 4, 3, 20, 6}, + } { + ma := test.adim + na := test.common + var mc, nc int + if side == blas.Left { + mc = test.common + nc = test.cdim + } else { + mc = test.cdim + nc = test.common + } + + // Generate a random matrix + lda := test.lda + if lda == 0 { + lda = na + } + a := make([]float64, ma*lda) + for i := range a { + a[i] = rnd.Float64() + } + ldc := test.ldc + if ldc == 0 { + ldc = nc + } + // Compute random C matrix + c := make([]float64, mc*ldc) + for i := range c { + c[i] = rnd.Float64() + } + + // Compute RQ + k := min(ma, na) + tau := make([]float64, k) + work := make([]float64, 1) + impl.Dgerqf(ma, na, a, lda, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dgerqf(ma, na, a, lda, tau, work, len(work)) + + // Build Q from result + q := constructQ("RQ", ma, na, a, lda, tau) + + cMat := blas64.General{ + Rows: mc, + Cols: nc, + Stride: ldc, + Data: make([]float64, len(c)), + } + copy(cMat.Data, c) + cMatCopy := blas64.General{ + Rows: cMat.Rows, + Cols: cMat.Cols, + Stride: cMat.Stride, + Data: make([]float64, len(cMat.Data)), + } + copy(cMatCopy.Data, cMat.Data) + switch { + default: + panic("bad test") + case side == blas.Left && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Left && trans == blas.Trans: + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, cMatCopy, 0, cMat) + case side == blas.Right && trans == blas.NoTrans: + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMatCopy, q, 0, cMat) + case side == blas.Right && trans == blas.Trans: + blas64.Gemm(blas.NoTrans, blas.Trans, 1, cMatCopy, q, 0, cMat) + } + // Do Dorm2r ard compare + if side == blas.Left { + work = make([]float64, nc) + } else { + work = make([]float64, mc) + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + tauCopy := make([]float64, len(tau)) + copy(tauCopy, tau) + impl.Dormr2(side, trans, mc, nc, k, a[(ma-k)*lda:], lda, tau, c, ldc, work) + if !floats.Equal(a, aCopy) { + t.Errorf("a changed in call") + } + if !floats.Equal(tau, tauCopy) { + t.Errorf("tau changed in call") + } + if !floats.EqualApprox(cMat.Data, c, 1e-14) { + t.Errorf("Multiplication mismatch.\n Want %v \n got %v.", cMat.Data, c) + } + } + } + } +} diff --git a/lapack/testlapack/dpocon.go b/lapack/testlapack/dpocon.go new file mode 100644 index 00000000..87b6cca0 --- /dev/null +++ b/lapack/testlapack/dpocon.go @@ -0,0 +1,157 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "log" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dpoconer interface { + Dpotrfer + Dgeconer + Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 + Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 +} + +func DpoconTest(t *testing.T, impl Dpoconer) { + for _, test := range []struct { + a []float64 + n int + cond float64 + uplo blas.Uplo + }{ + { + a: []float64{ + 89, 59, 77, + 0, 107, 59, + 0, 0, 89, + }, + uplo: blas.Upper, + n: 3, + cond: 0.050052137643379, + }, + { + a: []float64{ + 89, 0, 0, + 59, 107, 0, + 77, 59, 89, + }, + uplo: blas.Lower, + n: 3, + cond: 0.050052137643379, + }, + // Dgecon does not match Dpocon for this case. https://github.com/xianyi/OpenBLAS/issues/664. + { + a: []float64{ + 2.9995576045549965, -2.0898894566158663, 3.965560740124006, + 0, 1.9634729526261008, -2.8681002706874104, + 0, 0, 5.502416670471008, + }, + uplo: blas.Upper, + n: 3, + cond: 0.024054837369015203, + }, + } { + n := test.n + a := make([]float64, len(test.a)) + copy(a, test.a) + lda := n + uplo := test.uplo + work := make([]float64, 3*n) + anorm := impl.Dlansy(lapack.MaxColumnSum, uplo, n, a, lda, work) + // Compute cholesky decomposition + ok := impl.Dpotrf(uplo, n, a, lda) + if !ok { + t.Errorf("Bad test, matrix not positive definite") + continue + } + iwork := make([]int, n) + cond := impl.Dpocon(uplo, n, a, lda, anorm, work, iwork) + // Error if not the same order, otherwise log the difference. + if !floats.EqualWithinAbsOrRel(cond, test.cond, 1e0, 1e0) { + t.Errorf("Cond mismatch. Want %v, got %v.", test.cond, cond) + } else if !floats.EqualWithinAbsOrRel(cond, test.cond, 1e-14, 1e-14) { + log.Printf("Dpocon cond mismatch. Want %v, got %v.", test.cond, cond) + } + } + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + // Randomized tests compared against Dgecon. + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, test := range []struct { + n, lda int + }{ + {3, 0}, + {3, 5}, + } { + for trial := 0; trial < 100; trial++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + + // Multiply a by itself to make it symmetric positive definite. + aCopy := make([]float64, len(a)) + copy(aCopy, a) + bi.Dgemm(blas.Trans, blas.NoTrans, n, n, n, 1, aCopy, lda, aCopy, lda, 0, a, lda) + + aDat := make([]float64, len(aCopy)) + copy(aDat, a) + + aDense := make([]float64, len(a)) + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := a[i*lda+j] + aDense[i*lda+j] = v + aDense[j*lda+i] = v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := a[i*lda+j] + aDense[i*lda+j] = v + aDense[j*lda+i] = v + } + } + } + work := make([]float64, 4*n) + iwork := make([]int, n) + + anorm := impl.Dlansy(lapack.MaxColumnSum, uplo, n, a, lda, work) + ok := impl.Dpotrf(uplo, n, a, lda) + if !ok { + t.Errorf("Bad test, matrix not positive definite") + continue + } + got := impl.Dpocon(uplo, n, a, lda, anorm, work, iwork) + + denseNorm := impl.Dlange(lapack.MaxColumnSum, n, n, aDense, lda, work) + ipiv := make([]int, n) + impl.Dgetrf(n, n, aDense, lda, ipiv) + want := impl.Dgecon(lapack.MaxColumnSum, n, aDense, lda, denseNorm, work, iwork) + // Error if not the same order, otherwise log the difference. + if !floats.EqualWithinAbsOrRel(want, got, 1e0, 1e0) { + t.Errorf("Dpocon and Dgecon mismatch. Dpocon %v, Dgecon %v.", got, want) + } else if !floats.EqualWithinAbsOrRel(want, got, 1e-14, 1e-14) { + log.Printf("Dpocon and Dgecon mismatch. Dpocon %v, Dgecon %v.", got, want) + } + } + } + } +} diff --git a/lapack/testlapack/dpotf2.go b/lapack/testlapack/dpotf2.go new file mode 100644 index 00000000..2a9f850e --- /dev/null +++ b/lapack/testlapack/dpotf2.go @@ -0,0 +1,118 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" +) + +type Dpotf2er interface { + Dpotf2(ul blas.Uplo, n int, a []float64, lda int) (ok bool) +} + +func Dpotf2Test(t *testing.T, impl Dpotf2er) { + for _, test := range []struct { + a [][]float64 + ul blas.Uplo + pos bool + U [][]float64 + }{ + { + a: [][]float64{ + {23, 37, 34, 32}, + {108, 71, 48, 48}, + {109, 109, 67, 58}, + {106, 107, 106, 63}, + }, + pos: true, + U: [][]float64{ + {4.795831523312719, 7.715033320111766, 7.089490077940543, 6.672461249826393}, + {0, 3.387958215439679, -1.976308959006481, -1.026654004678691}, + {0, 0, 3.582364210034111, 2.419258947036024}, + {0, 0, 0, 3.401680257083044}, + }, + }, + { + a: [][]float64{ + {8, 2}, + {2, 4}, + }, + pos: true, + U: [][]float64{ + {2.82842712474619, 0.707106781186547}, + {0, 1.870828693386971}, + }, + }, + } { + testDpotf2(t, impl, test.pos, test.a, test.U, len(test.a[0]), blas.Upper) + testDpotf2(t, impl, test.pos, test.a, test.U, len(test.a[0])+5, blas.Upper) + aT := transpose(test.a) + L := transpose(test.U) + testDpotf2(t, impl, test.pos, aT, L, len(test.a[0]), blas.Lower) + testDpotf2(t, impl, test.pos, aT, L, len(test.a[0])+5, blas.Lower) + } +} + +func testDpotf2(t *testing.T, impl Dpotf2er, testPos bool, a, ans [][]float64, stride int, ul blas.Uplo) { + aFlat := flattenTri(a, stride, ul) + ansFlat := flattenTri(ans, stride, ul) + pos := impl.Dpotf2(ul, len(a[0]), aFlat, stride) + if pos != testPos { + t.Errorf("Positive definite mismatch: Want %v, Got %v", testPos, pos) + return + } + if testPos && !floats.EqualApprox(ansFlat, aFlat, 1e-14) { + t.Errorf("Result mismatch: Want %v, Got %v", ansFlat, aFlat) + } +} + +// flattenTri with a certain stride. stride must be >= dimension. Puts repeatable +// nonce values in non-accessed places +func flattenTri(a [][]float64, stride int, ul blas.Uplo) []float64 { + m := len(a) + n := len(a[0]) + if stride < n { + panic("bad stride") + } + upper := ul == blas.Upper + v := make([]float64, m*stride) + count := 1000.0 + for i := 0; i < m; i++ { + for j := 0; j < stride; j++ { + if j >= n || (upper && j < i) || (!upper && j > i) { + // not accessed, so give a unique crazy number + v[i*stride+j] = count + count++ + continue + } + v[i*stride+j] = a[i][j] + } + } + return v +} + +func transpose(a [][]float64) [][]float64 { + m := len(a) + n := len(a[0]) + if m != n { + panic("not square") + } + aNew := make([][]float64, m) + for i := 0; i < m; i++ { + aNew[i] = make([]float64, n) + } + for i := 0; i < m; i++ { + if len(a[i]) != n { + panic("bad n size") + } + for j := 0; j < n; j++ { + aNew[j][i] = a[i][j] + } + } + return aNew +} diff --git a/lapack/testlapack/dpotrf.go b/lapack/testlapack/dpotrf.go new file mode 100644 index 00000000..d4318228 --- /dev/null +++ b/lapack/testlapack/dpotrf.go @@ -0,0 +1,135 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dpotrfer interface { + Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) +} + +func DpotrfTest(t *testing.T, impl Dpotrfer) { + const tol = 1e-13 + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for tc, test := range []struct { + n int + lda int + }{ + {1, 0}, + {2, 0}, + {3, 0}, + {10, 0}, + {30, 0}, + {63, 0}, + {65, 0}, + {127, 0}, + {129, 0}, + {500, 0}, + {1, 10}, + {2, 10}, + {3, 10}, + {10, 20}, + {30, 50}, + {63, 100}, + {65, 100}, + {127, 200}, + {129, 200}, + {500, 600}, + } { + n := test.n + + // Random diagonal matrix D with positive entries. + d := make([]float64, n) + Dlatm1(d, 4, 10000, false, 1, rnd) + + // Construct a positive definite matrix A as + // A = U * D * U^T + // where U is a random orthogonal matrix. + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + Dlagsy(n, 0, d, a, lda, rnd, make([]float64, 2*n)) + + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + ok := impl.Dpotrf(uplo, n, a, lda) + if !ok { + t.Errorf("Case %v: unexpected failure for positive definite matrix", tc) + continue + } + + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = 0 + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + a[i*lda+j] = 0 + } + } + default: + panic("bad uplo") + } + + ans := make([]float64, len(a)) + switch uplo { + case blas.Upper: + // Multiply U^T * U. + bi.Dsyrk(uplo, blas.Trans, n, n, 1, a, lda, 0, ans, lda) + case blas.Lower: + // Multiply L * L^T. + bi.Dsyrk(uplo, blas.NoTrans, n, n, 1, a, lda, 0, ans, lda) + } + + match := true + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + if !floats.EqualWithinAbsOrRel(ans[i*lda+j], aCopy[i*lda+j], tol, tol) { + match = false + } + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + if !floats.EqualWithinAbsOrRel(ans[i*lda+j], aCopy[i*lda+j], tol, tol) { + match = false + } + } + } + } + if !match { + t.Errorf("Case %v (uplo=%v,n=%v,lda=%v): unexpected result", tc, uplo, n, lda) + } + + // Make one element of D negative so that A is not + // positive definite, and check that Dpotrf fails. + d[0] *= -1 + Dlagsy(n, 0, d, a, lda, rnd, make([]float64, 2*n)) + ok = impl.Dpotrf(uplo, n, a, lda) + if ok { + t.Errorf("Case %v: unexpected success for not positive definite matrix", tc) + } + } + } +} diff --git a/lapack/testlapack/drscl.go b/lapack/testlapack/drscl.go new file mode 100644 index 00000000..df87db40 --- /dev/null +++ b/lapack/testlapack/drscl.go @@ -0,0 +1,52 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Drscler interface { + Drscl(n int, a float64, x []float64, incX int) +} + +func DrsclTest(t *testing.T, impl Drscler) { + for _, test := range []struct { + x []float64 + a float64 + }{ + { + x: []float64{1, 2, 3, 4, 5}, + a: 4, + }, + { + x: []float64{1, 2, 3, 4, 5}, + a: math.MaxFloat64, + }, + { + x: []float64{1, 2, 3, 4, 5}, + a: 1e-307, + }, + } { + xcopy := make([]float64, len(test.x)) + copy(xcopy, test.x) + + // Cannot test the scaling directly because of floating point scaling issues + // (the purpose of Drscl). Instead, check that scaling and scaling back + // yeilds approximately x. If overflow or underflow occurs then the scaling + // won't match. + impl.Drscl(len(test.x), test.a, xcopy, 1) + if floats.Equal(xcopy, test.x) { + t.Errorf("x unchanged during call to drscl. a = %v, x = %v.", test.a, test.x) + } + impl.Drscl(len(test.x), 1/test.a, xcopy, 1) + if !floats.EqualApprox(xcopy, test.x, 1e-14) { + t.Errorf("x not equal after scaling and unscaling. a = %v, x = %v.", test.a, test.x) + } + } +} diff --git a/lapack/testlapack/dsteqr.go b/lapack/testlapack/dsteqr.go new file mode 100644 index 00000000..1fffdb1e --- /dev/null +++ b/lapack/testlapack/dsteqr.go @@ -0,0 +1,171 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dsteqrer interface { + Dsteqr(compz lapack.EVComp, n int, d, e, z []float64, ldz int, work []float64) (ok bool) + Dorgtrer +} + +func DsteqrTest(t *testing.T, impl Dsteqrer) { + rnd := rand.New(rand.NewSource(1)) + for _, compz := range []lapack.EVComp{lapack.OriginalEV, lapack.TridiagEV} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {4, 0}, + {8, 0}, + {10, 0}, + + {2, 10}, + {8, 10}, + {10, 20}, + } { + for cas := 0; cas < 100; cas++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + d := make([]float64, n) + for i := range d { + d[i] = rnd.Float64() + } + e := make([]float64, n-1) + for i := range e { + e[i] = rnd.Float64() + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + } + dCopy := make([]float64, len(d)) + copy(dCopy, d) + eCopy := make([]float64, len(e)) + copy(eCopy, e) + aCopy := make([]float64, len(a)) + copy(aCopy, a) + if compz == lapack.OriginalEV { + // Compute triangular decomposition and orthonormal matrix. + uplo := blas.Upper + tau := make([]float64, n) + work := make([]float64, 1) + impl.Dsytrd(blas.Upper, n, a, lda, d, e, tau, work, -1) + work = make([]float64, int(work[0])) + impl.Dsytrd(uplo, n, a, lda, d, e, tau, work, len(work)) + impl.Dorgtr(uplo, n, a, lda, tau, work, len(work)) + } else { + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + if i == j { + a[i*lda+j] = 1 + } + } + } + } + work := make([]float64, 2*n) + + aDecomp := make([]float64, len(a)) + copy(aDecomp, a) + dDecomp := make([]float64, len(d)) + copy(dDecomp, d) + eDecomp := make([]float64, len(e)) + copy(eDecomp, e) + impl.Dsteqr(compz, n, d, e, a, lda, work) + dAns := make([]float64, len(d)) + copy(dAns, d) + + var truth blas64.General + if compz == lapack.OriginalEV { + truth = blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := aCopy[i*lda+j] + truth.Data[i*truth.Stride+j] = v + truth.Data[j*truth.Stride+i] = v + } + } + } else { + truth = blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < n; i++ { + truth.Data[i*truth.Stride+i] = dCopy[i] + if i != n-1 { + truth.Data[(i+1)*truth.Stride+i] = eCopy[i] + truth.Data[i*truth.Stride+i+1] = eCopy[i] + } + } + } + + V := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: a, + } + if !eigenDecompCorrect(d, truth, V) { + t.Errorf("Eigen reconstruction mismatch. fromFull = %v, n = %v", + compz == lapack.OriginalEV, n) + } + + // Compare eigenvalues when not computing eigenvectors. + for i := range work { + work[i] = rnd.Float64() + } + impl.Dsteqr(lapack.None, n, dDecomp, eDecomp, aDecomp, lda, work) + if !floats.EqualApprox(d, dAns, 1e-8) { + t.Errorf("Eigenvalue mismatch when eigenvectors not computed") + } + } + } + } +} + +// eigenDecompCorrect returns whether the eigen decomposition is correct. +// It checks if +// A * v ≈ λ * v +// where the eigenvalues λ are stored in values, and the eigenvectors are stored +// in the columns of v. +func eigenDecompCorrect(values []float64, A, V blas64.General) bool { + n := A.Rows + for i := 0; i < n; i++ { + lambda := values[i] + vector := make([]float64, n) + ans2 := make([]float64, n) + for j := range vector { + v := V.Data[j*V.Stride+i] + vector[j] = v + ans2[j] = lambda * v + } + v := blas64.Vector{Inc: 1, Data: vector} + ans1 := blas64.Vector{Inc: 1, Data: make([]float64, n)} + blas64.Gemv(blas.NoTrans, 1, A, v, 0, ans1) + if !floats.EqualApprox(ans1.Data, ans2, 1e-8) { + return false + } + } + return true +} diff --git a/lapack/testlapack/dsterf.go b/lapack/testlapack/dsterf.go new file mode 100644 index 00000000..66b4a9e1 --- /dev/null +++ b/lapack/testlapack/dsterf.go @@ -0,0 +1,126 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type Dsterfer interface { + Dgetrfer + Dsterf(n int, d, e []float64) (ok bool) +} + +func DsterfTest(t *testing.T, impl Dsterfer) { + // Hand coded tests. + for cas, test := range []struct { + d []float64 + e []float64 + n int + + ans []float64 + }{ + // Computed from Fortran code. + { + d: []float64{1, 3, 4, 6}, + e: []float64{2, 4, 5}, + n: 4, + ans: []float64{11.046227528488854, 4.795922173417400, -2.546379458290125, 0.704229756383872}, + }, + } { + n := test.n + d := make([]float64, len(test.d)) + copy(d, test.d) + e := make([]float64, len(test.e)) + copy(e, test.e) + ok := impl.Dsterf(n, d, e) + if !ok { + t.Errorf("Case %d, Eigenvalue decomposition failed", cas) + continue + } + ans := make([]float64, len(test.ans)) + copy(ans, test.ans) + sort.Float64s(ans) + if !floats.EqualApprox(ans, d, 1e-10) { + t.Errorf("eigenvalue mismatch") + } + } + + rnd := rand.New(rand.NewSource(1)) + // Probabilistic tests. + for _, n := range []int{4, 6, 10} { + for cas := 0; cas < 10; cas++ { + d := make([]float64, n) + for i := range d { + d[i] = rnd.NormFloat64() + } + dCopy := make([]float64, len(d)) + copy(dCopy, d) + e := make([]float64, n-1) + for i := range e { + e[i] = rnd.NormFloat64() + } + eCopy := make([]float64, len(e)) + copy(eCopy, e) + + ok := impl.Dsterf(n, d, e) + if !ok { + t.Errorf("Eigenvalue decomposition failed") + continue + } + + // Test that the eigenvalues are sorted. + if !sort.Float64sAreSorted(d) { + t.Errorf("Values are not sorted") + } + + // Construct original tridagional matrix. + lda := n + a := make([]float64, n*lda) + for i := 0; i < n; i++ { + a[i*lda+i] = dCopy[i] + if i != n-1 { + a[i*lda+i+1] = eCopy[i] + a[(i+1)*lda+i] = eCopy[i] + } + } + + asub := make([]float64, len(a)) + ipiv := make([]int, n) + + // Test that they are actually eigenvalues by computing the + // determinant of A - λI. + // TODO(btracey): Replace this test with a more numerically stable + // test. + for _, lambda := range d { + copy(asub, a) + for i := 0; i < n; i++ { + asub[i*lda+i] -= lambda + } + + // Compute LU. + ok := impl.Dgetrf(n, n, asub, lda, ipiv) + if !ok { + // Definitely singular. + continue + } + // Compute determinant. + var logdet float64 + for i := 0; i < n; i++ { + v := asub[i*lda+i] + logdet += math.Log(math.Abs(v)) + } + if math.Exp(logdet) > 2 { + t.Errorf("Incorrect singular value. n = %d, cas = %d, det = %v", n, cas, math.Exp(logdet)) + } + } + } + } +} diff --git a/lapack/testlapack/dsyev.go b/lapack/testlapack/dsyev.go new file mode 100644 index 00000000..e70088c9 --- /dev/null +++ b/lapack/testlapack/dsyev.go @@ -0,0 +1,115 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dsyever interface { + Dsyev(jobz lapack.EVJob, uplo blas.Uplo, n int, a []float64, lda int, w, work []float64, lwork int) (ok bool) +} + +func DsyevTest(t *testing.T, impl Dsyever) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {2, 0}, + {5, 0}, + {10, 0}, + {100, 0}, + + {1, 5}, + {2, 5}, + {5, 10}, + {10, 20}, + {100, 110}, + } { + for cas := 0; cas < 10; cas++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + w := make([]float64, n) + for i := range w { + w[i] = rnd.NormFloat64() + } + + work := make([]float64, 1) + impl.Dsyev(lapack.ComputeEV, uplo, n, a, lda, w, work, -1) + work = make([]float64, int(work[0])) + impl.Dsyev(lapack.ComputeEV, uplo, n, a, lda, w, work, len(work)) + + // Check that the decomposition is correct + orig := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := aCopy[i*lda+j] + orig.Data[i*orig.Stride+j] = v + orig.Data[j*orig.Stride+i] = v + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + v := aCopy[i*lda+j] + orig.Data[i*orig.Stride+j] = v + orig.Data[j*orig.Stride+i] = v + } + } + } + + V := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: a, + } + + if !eigenDecompCorrect(w, orig, V) { + t.Errorf("Decomposition mismatch") + } + + // Check that the decomposition is correct when the eigenvectors + // are not computed. + wAns := make([]float64, len(w)) + copy(wAns, w) + copy(a, aCopy) + for i := range w { + w[i] = rnd.Float64() + } + for i := range work { + work[i] = rnd.Float64() + } + impl.Dsyev(lapack.None, uplo, n, a, lda, w, work, len(work)) + if !floats.EqualApprox(w, wAns, 1e-8) { + t.Errorf("Eigenvalue mismatch when vectors not computed") + } + } + } + } +} diff --git a/lapack/testlapack/dsytd2.go b/lapack/testlapack/dsytd2.go new file mode 100644 index 00000000..af71cf1f --- /dev/null +++ b/lapack/testlapack/dsytd2.go @@ -0,0 +1,205 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dsytd2er interface { + Dsytd2(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau []float64) +} + +func Dsytd2Test(t *testing.T, impl Dsytd2er) { + rnd := rand.New(rand.NewSource(1)) + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, test := range []struct { + n, lda int + }{ + {3, 0}, + {4, 0}, + {5, 0}, + + {3, 10}, + {4, 10}, + {5, 10}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.NormFloat64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + + d := make([]float64, n) + for i := range d { + d[i] = math.NaN() + } + e := make([]float64, n-1) + for i := range e { + e[i] = math.NaN() + } + tau := make([]float64, n-1) + for i := range tau { + tau[i] = math.NaN() + } + + impl.Dsytd2(uplo, n, a, lda, d, e, tau) + + // Construct Q + qMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + qCopy := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, len(qMat.Data)), + } + // Set Q to I. + for i := 0; i < n; i++ { + qMat.Data[i*qMat.Stride+i] = 1 + } + for i := 0; i < n-1; i++ { + hMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + // Set H to I. + for i := 0; i < n; i++ { + hMat.Data[i*hMat.Stride+i] = 1 + } + var vi blas64.Vector + if uplo == blas.Upper { + vi = blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + for j := 0; j < i; j++ { + vi.Data[j] = a[j*lda+i+1] + } + vi.Data[i] = 1 + } else { + vi = blas64.Vector{ + Inc: 1, + Data: make([]float64, n), + } + vi.Data[i+1] = 1 + for j := i + 2; j < n; j++ { + vi.Data[j] = a[j*lda+i] + } + } + blas64.Ger(-tau[i], vi, vi, hMat) + copy(qCopy.Data, qMat.Data) + + // Multiply q by the new h. + if uplo == blas.Upper { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hMat, qCopy, 0, qMat) + } else { + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, hMat, 0, qMat) + } + } + // Check that Q is orthonormal + othonormal := true + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dot := blas64.Dot(n, + blas64.Vector{Inc: 1, Data: qMat.Data[i*qMat.Stride:]}, + blas64.Vector{Inc: 1, Data: qMat.Data[j*qMat.Stride:]}, + ) + if i == j { + if math.Abs(dot-1) > 1e-10 { + othonormal = false + } + } else { + if math.Abs(dot) > 1e-10 { + othonormal = false + } + } + } + } + if !othonormal { + t.Errorf("Q not orthonormal") + } + + // Compute Q^T * A * Q. + aMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, len(a)), + } + + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + v := aCopy[i*lda+j] + if uplo == blas.Lower { + v = aCopy[j*lda+i] + } + aMat.Data[i*aMat.Stride+j] = v + aMat.Data[j*aMat.Stride+i] = v + } + } + + tmp := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + ans := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + blas64.Gemm(blas.Trans, blas.NoTrans, 1, qMat, aMat, 0, tmp) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, qMat, 0, ans) + + // Compare with T. + tMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + for i := 0; i < n-1; i++ { + tMat.Data[i*tMat.Stride+i] = d[i] + tMat.Data[i*tMat.Stride+i+1] = e[i] + tMat.Data[(i+1)*tMat.Stride+i] = e[i] + } + tMat.Data[(n-1)*tMat.Stride+n-1] = d[n-1] + + same := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if math.Abs(ans.Data[i*ans.Stride+j]-tMat.Data[i*tMat.Stride+j]) > 1e-10 { + same = false + } + } + } + if !same { + t.Errorf("Matrix answer mismatch") + } + } + } +} diff --git a/lapack/testlapack/dsytrd.go b/lapack/testlapack/dsytrd.go new file mode 100644 index 00000000..74e2beba --- /dev/null +++ b/lapack/testlapack/dsytrd.go @@ -0,0 +1,160 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dsytrder interface { + Dsytrd(uplo blas.Uplo, n int, a []float64, lda int, d, e, tau, work []float64, lwork int) + + Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) + Dorgql(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) +} + +func DsytrdTest(t *testing.T, impl Dsytrder) { + const tol = 1e-13 + rnd := rand.New(rand.NewSource(1)) + for tc, test := range []struct { + n, lda int + }{ + {1, 0}, + {2, 0}, + {3, 0}, + {4, 0}, + {10, 0}, + {50, 0}, + {100, 0}, + {150, 0}, + {300, 0}, + + {1, 3}, + {2, 3}, + {3, 7}, + {4, 9}, + {10, 20}, + {50, 70}, + {100, 120}, + {150, 170}, + {300, 320}, + } { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, wl := range []worklen{minimumWork, mediumWork, optimumWork} { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := randomGeneral(n, n, lda, rnd) + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + a.Data[i*a.Stride+j] = a.Data[j*a.Stride+i] + } + } + aCopy := cloneGeneral(a) + + d := nanSlice(n) + e := nanSlice(n - 1) + tau := nanSlice(n - 1) + + var lwork int + switch wl { + case minimumWork: + lwork = 1 + case mediumWork: + work := make([]float64, 1) + impl.Dsytrd(uplo, n, a.Data, a.Stride, d, e, tau, work, -1) + lwork = (int(work[0]) + 1) / 2 + lwork = max(1, lwork) + case optimumWork: + work := make([]float64, 1) + impl.Dsytrd(uplo, n, a.Data, a.Stride, d, e, tau, work, -1) + lwork = int(work[0]) + } + work := make([]float64, lwork) + + impl.Dsytrd(uplo, n, a.Data, a.Stride, d, e, tau, work, lwork) + + prefix := fmt.Sprintf("Case #%v: uplo=%v,n=%v,lda=%v,work=%v", + tc, uplo, n, lda, wl) + + if !generalOutsideAllNaN(a) { + t.Errorf("%v: out-of-range write to A", prefix) + } + + // Extract Q by doing what Dorgtr does. + q := cloneGeneral(a) + if uplo == blas.Upper { + for j := 0; j < n-1; j++ { + for i := 0; i < j; i++ { + q.Data[i*q.Stride+j] = q.Data[i*q.Stride+j+1] + } + q.Data[(n-1)*q.Stride+j] = 0 + } + for i := 0; i < n-1; i++ { + q.Data[i*q.Stride+n-1] = 0 + } + q.Data[(n-1)*q.Stride+n-1] = 1 + if n > 1 { + work = make([]float64, n-1) + impl.Dorgql(n-1, n-1, n-1, q.Data, q.Stride, tau, work, len(work)) + } + } else { + for j := n - 1; j > 0; j-- { + q.Data[j] = 0 + for i := j + 1; i < n; i++ { + q.Data[i*q.Stride+j] = q.Data[i*q.Stride+j-1] + } + } + q.Data[0] = 1 + for i := 1; i < n; i++ { + q.Data[i*q.Stride] = 0 + } + if n > 1 { + work = make([]float64, n-1) + impl.Dorgqr(n-1, n-1, n-1, q.Data[q.Stride+1:], q.Stride, tau, work, len(work)) + } + } + if !isOrthonormal(q) { + t.Errorf("%v: Q not orthogonal", prefix) + } + + // Contruct symmetric tridiagonal T from d and e. + tMat := zeros(n, n, n) + for i := 0; i < n; i++ { + tMat.Data[i*tMat.Stride+i] = d[i] + } + if uplo == blas.Upper { + for j := 1; j < n; j++ { + tMat.Data[(j-1)*tMat.Stride+j] = e[j-1] + tMat.Data[j*tMat.Stride+j-1] = e[j-1] + } + } else { + for j := 0; j < n-1; j++ { + tMat.Data[(j+1)*tMat.Stride+j] = e[j] + tMat.Data[j*tMat.Stride+j+1] = e[j] + } + } + + // Compute Q^T * A * Q. + tmp := zeros(n, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, aCopy, 0, tmp) + got := zeros(n, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp, q, 0, got) + + // Compare with T. + if !equalApproxGeneral(got, tMat, tol) { + t.Errorf("%v: Q^T*A*Q != T", prefix) + } + } + } + } +} diff --git a/lapack/testlapack/dtgsja.go b/lapack/testlapack/dtgsja.go new file mode 100644 index 00000000..af4cec80 --- /dev/null +++ b/lapack/testlapack/dtgsja.go @@ -0,0 +1,165 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dtgsjaer interface { + Dlanger + Dtgsja(jobU, jobV, jobQ lapack.GSVDJob, m, p, n, k, l int, a []float64, lda int, b []float64, ldb int, tola, tolb float64, alpha, beta, u []float64, ldu int, v []float64, ldv int, q []float64, ldq int, work []float64) (cycles int, ok bool) +} + +func DtgsjaTest(t *testing.T, impl Dtgsjaer) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + m, p, n, k, l, lda, ldb, ldu, ldv, ldq int + + ok bool + }{ + {m: 5, p: 5, n: 5, k: 2, l: 2, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, k: 4, l: 1, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, k: 2, l: 2, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, k: 4, l: 1, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 10, k: 4, l: 2, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 5, n: 5, k: 2, l: 2, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 5, n: 5, k: 4, l: 1, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 10, n: 10, k: 5, l: 3, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 10, p: 10, n: 10, k: 6, l: 4, lda: 0, ldb: 0, ldu: 0, ldv: 0, ldq: 0, ok: true}, + {m: 5, p: 5, n: 5, k: 2, l: 2, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10, ok: true}, + {m: 5, p: 5, n: 5, k: 4, l: 1, lda: 10, ldb: 10, ldu: 10, ldv: 10, ldq: 10, ok: true}, + {m: 5, p: 5, n: 10, k: 2, l: 2, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 5, p: 5, n: 10, k: 4, l: 1, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 5, p: 5, n: 10, k: 4, l: 2, lda: 20, ldb: 20, ldu: 10, ldv: 10, ldq: 20, ok: true}, + {m: 10, p: 5, n: 5, k: 2, l: 2, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10, ok: true}, + {m: 10, p: 5, n: 5, k: 4, l: 1, lda: 10, ldb: 10, ldu: 20, ldv: 10, ldq: 10, ok: true}, + {m: 10, p: 10, n: 10, k: 5, l: 3, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20, ok: true}, + {m: 10, p: 10, n: 10, k: 6, l: 4, lda: 20, ldb: 20, ldu: 20, ldv: 20, ldq: 20, ok: true}, + } { + m := test.m + p := test.p + n := test.n + k := test.k + l := test.l + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = n + } + ldu := test.ldu + if ldu == 0 { + ldu = m + } + ldv := test.ldv + if ldv == 0 { + ldv = p + } + ldq := test.ldq + if ldq == 0 { + ldq = n + } + + a := blockedUpperTriGeneral(m, n, k, l, lda, true, rnd) + aCopy := cloneGeneral(a) + b := blockedUpperTriGeneral(p, n, k, l, ldb, false, rnd) + bCopy := cloneGeneral(b) + + tola := float64(max(m, n)) * impl.Dlange(lapack.NormFrob, m, n, a.Data, a.Stride, nil) * dlamchE + tolb := float64(max(p, n)) * impl.Dlange(lapack.NormFrob, p, n, b.Data, b.Stride, nil) * dlamchE + + alpha := make([]float64, n) + beta := make([]float64, n) + + work := make([]float64, 2*n) + + u := nanGeneral(m, m, ldu) + v := nanGeneral(p, p, ldv) + q := nanGeneral(n, n, ldq) + + _, ok := impl.Dtgsja(lapack.GSVDUnit, lapack.GSVDUnit, lapack.GSVDUnit, + m, p, n, k, l, + a.Data, a.Stride, + b.Data, b.Stride, + tola, tolb, + alpha, beta, + u.Data, u.Stride, + v.Data, v.Stride, + q.Data, q.Stride, + work) + + if !ok { + if test.ok { + t.Errorf("test %d unexpectedly did not converge", cas) + } + continue + } + + // Check orthogonality of U, V and Q. + if !isOrthonormal(u) { + t.Errorf("test %d: U is not orthogonal\n%+v", cas, u) + } + if !isOrthonormal(v) { + t.Errorf("test %d: V is not orthogonal\n%+v", cas, v) + } + if !isOrthonormal(q) { + t.Errorf("test %d: Q is not orthogonal\n%+v", cas, q) + } + + // Check C^2 + S^2 = I. + var elements []float64 + if m-k-l >= 0 { + elements = alpha[k : k+l] + } else { + elements = alpha[k:m] + } + for i := range elements { + i += k + d := alpha[i]*alpha[i] + beta[i]*beta[i] + if !floats.EqualWithinAbsOrRel(d, 1, 1e-14, 1e-14) { + t.Errorf("test %d: alpha_%d^2 + beta_%d^2 != 1: got: %v", cas, i, i, d) + } + } + + zeroR, d1, d2 := constructGSVDresults(n, p, m, k, l, a, b, alpha, beta) + + // Check U^T*A*Q = D1*[ 0 R ]. + uTmp := nanGeneral(m, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, u, aCopy, 0, uTmp) + uAns := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, uTmp, q, 0, uAns) + + d10r := nanGeneral(m, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d1, zeroR, 0, d10r) + + if !equalApproxGeneral(uAns, d10r, 1e-14) { + t.Errorf("test %d: U^T*A*Q != D1*[ 0 R ]\nU^T*A*Q:\n%+v\nD1*[ 0 R ]:\n%+v", + cas, uAns, d10r) + } + + // Check V^T*B*Q = D2*[ 0 R ]. + vTmp := nanGeneral(p, n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, v, bCopy, 0, vTmp) + vAns := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, vTmp, q, 0, vAns) + + d20r := nanGeneral(p, n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, d2, zeroR, 0, d20r) + + if !equalApproxGeneral(vAns, d20r, 1e-14) { + t.Errorf("test %d: V^T*B*Q != D2*[ 0 R ]\nV^T*B*Q:\n%+v\nD2*[ 0 R ]:\n%+v", + cas, vAns, d20r) + } + } +} diff --git a/lapack/testlapack/dtrcon.go b/lapack/testlapack/dtrcon.go new file mode 100644 index 00000000..1e490ca9 --- /dev/null +++ b/lapack/testlapack/dtrcon.go @@ -0,0 +1,184 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dtrconer interface { + Dgeconer + Dtrcon(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 +} + +func DtrconTest(t *testing.T, impl Dtrconer) { + rnd := rand.New(rand.NewSource(1)) + // Hand crafted tests. + for _, test := range []struct { + a []float64 + n int + uplo blas.Uplo + diag blas.Diag + condOne float64 + condInf float64 + }{ + { + a: []float64{ + 8, 5, 6, + 0, 7, 8, + 0, 0, 6, + }, + n: 3, + uplo: blas.Upper, + diag: blas.Unit, + condOne: 1.0 / 645, + condInf: 1.0 / 480, + }, + { + a: []float64{ + 8, 5, 6, + 0, 7, 8, + 0, 0, 6, + }, + n: 3, + uplo: blas.Upper, + diag: blas.NonUnit, + condOne: 0.137704918032787, + condInf: 0.157894736842105, + }, + { + a: []float64{ + 8, 0, 0, + 5, 7, 0, + 6, 8, 6, + }, + n: 3, + uplo: blas.Lower, + diag: blas.Unit, + condOne: 1.0 / 480, + condInf: 1.0 / 645, + }, + { + a: []float64{ + 8, 0, 0, + 5, 7, 0, + 6, 8, 6, + }, + n: 3, + uplo: blas.Lower, + diag: blas.NonUnit, + condOne: 0.157894736842105, + condInf: 0.137704918032787, + }, + } { + lda := test.n + work := make([]float64, 3*test.n) + for i := range work { + work[i] = rnd.Float64() + } + iwork := make([]int, test.n) + for i := range iwork { + iwork[i] = int(rnd.Int31()) + } + aCopy := make([]float64, len(test.a)) + copy(aCopy, test.a) + condOne := impl.Dtrcon(lapack.MaxColumnSum, test.uplo, test.diag, test.n, test.a, lda, work, iwork) + if math.Abs(condOne-test.condOne) > 1e-14 { + t.Errorf("One norm mismatch. Want %v, got %v.", test.condOne, condOne) + } + if !floats.Equal(aCopy, test.a) { + t.Errorf("a modified during call") + } + condInf := impl.Dtrcon(lapack.MaxRowSum, test.uplo, test.diag, test.n, test.a, lda, work, iwork) + if math.Abs(condInf-test.condInf) > 1e-14 { + t.Errorf("Inf norm mismatch. Want %v, got %v.", test.condInf, condInf) + } + if !floats.Equal(aCopy, test.a) { + t.Errorf("a modified during call") + } + } + + // Dtrcon does not match the Dgecon output in many cases. See + // https://github.com/xianyi/OpenBLAS/issues/636 + // TODO(btracey): Uncomment this when the mismatch between Dgecon and Dtrcon + // is understood. + /* + // Randomized tests against Dgecon. + for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { + for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { + for _, test := range []struct { + n, lda int + }{ + {3, 0}, + {4, 9}, + } { + for trial := 0; trial < 1; trial++ { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + if trial == 0 { + for i := range a { + a[i] = float64(i + 2) + } + } else { + for i := range a { + a[i] = rnd.NormFloat64() + } + } + + aDense := make([]float64, len(a)) + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + aDense[i*lda+j] = a[i*lda+j] + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + aDense[i*lda+j] = a[i*lda+j] + } + } + } + if diag == blas.Unit { + for i := 0; i < n; i++ { + aDense[i*lda+i] = 1 + } + } + + ipiv := make([]int, n) + work := make([]float64, 4*n) + denseOne := impl.Dlange(lapack.MaxColumnSum, n, n, aDense, lda, work) + denseInf := impl.Dlange(lapack.MaxRowSum, n, n, aDense, lda, work) + + aDenseLU := make([]float64, len(aDense)) + copy(aDenseLU, aDense) + impl.Dgetrf(n, n, aDenseLU, lda, ipiv) + iwork := make([]int, n) + want := impl.Dgecon(lapack.MaxColumnSum, n, aDenseLU, lda, denseOne, work, iwork) + got := impl.Dtrcon(lapack.MaxColumnSum, uplo, diag, n, a, lda, work, iwork) + if math.Abs(want-got) > 1e-14 { + t.Errorf("One norm mismatch. Upper = %v, unit = %v, want %v, got %v", uplo == blas.Upper, diag == blas.Unit, want, got) + } + want = impl.Dgecon(lapack.MaxRowSum, n, aDenseLU, lda, denseInf, work, iwork) + got = impl.Dtrcon(lapack.MaxRowSum, uplo, diag, n, a, lda, work, iwork) + if math.Abs(want-got) > 1e-14 { + t.Errorf("Inf norm mismatch. Upper = %v, unit = %v, want %v, got %v", uplo == blas.Upper, diag == blas.Unit, want, got) + } + } + } + } + } + */ +} diff --git a/lapack/testlapack/dtrevc3.go b/lapack/testlapack/dtrevc3.go new file mode 100644 index 00000000..60c51241 --- /dev/null +++ b/lapack/testlapack/dtrevc3.go @@ -0,0 +1,221 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +type Dtrevc3er interface { + Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, selected []bool, n int, t []float64, ldt int, vl []float64, ldvl int, vr []float64, ldvr int, mm int, work []float64, lwork int) int +} + +func Dtrevc3Test(t *testing.T, impl Dtrevc3er) { + rnd := rand.New(rand.NewSource(1)) + for _, side := range []lapack.EVSide{lapack.RightEV, lapack.LeftEV, lapack.RightLeftEV} { + for _, howmny := range []lapack.HowMany{lapack.AllEV, lapack.AllEVMulQ, lapack.SelectedEV} { + for _, n := range []int{0, 1, 2, 3, 4, 5, 10, 34, 100} { + for _, extra := range []int{0, 11} { + for _, optwork := range []bool{true, false} { + for cas := 0; cas < 10; cas++ { + tmat := randomSchurCanonical(n, n+extra, rnd) + testDtrevc3(t, impl, side, howmny, tmat, optwork, rnd) + } + } + } + } + } + } +} + +func testDtrevc3(t *testing.T, impl Dtrevc3er, side lapack.EVSide, howmny lapack.HowMany, tmat blas64.General, optwork bool, rnd *rand.Rand) { + const tol = 1e-14 + + n := tmat.Rows + extra := tmat.Stride - tmat.Cols + right := side != lapack.LeftEV + left := side != lapack.RightEV + + var selected, selectedWant []bool + var mWant int // How many columns will the eigenvectors occupy. + if howmny == lapack.SelectedEV { + selected = make([]bool, n) + selectedWant = make([]bool, n) + // Dtrevc3 will compute only selected eigenvectors. Pick them + // randomly disregarding whether they are real or complex. + for i := range selected { + if rnd.Float64() < 0.5 { + selected[i] = true + } + } + // Dtrevc3 will modify (standardize) the slice selected based on + // whether the corresponding eigenvalues are real or complex. Do + // the same process here to fill selectedWant. + for i := 0; i < n; { + if i == n-1 || tmat.Data[(i+1)*tmat.Stride+i] == 0 { + // Real eigenvalue. + if selected[i] { + selectedWant[i] = true + mWant++ // Real eigenvectors occupy one column. + } + i++ + } else { + // Complex eigenvalue. + if selected[i] || selected[i+1] { + // Dtrevc3 will modify selected so that + // only the first element of the pair is + // true. + selectedWant[i] = true + mWant += 2 // Complex eigenvectors occupy two columns. + } + i += 2 + } + } + } else { + // All eigenvectors occupy n columns. + mWant = n + } + + var vr blas64.General + if right { + if howmny == lapack.AllEVMulQ { + vr = eye(n, n+extra) + } else { + // VR will be overwritten. + vr = nanGeneral(n, mWant, n+extra) + } + } + + var vl blas64.General + if left { + if howmny == lapack.AllEVMulQ { + vl = eye(n, n+extra) + } else { + // VL will be overwritten. + vl = nanGeneral(n, mWant, n+extra) + } + } + + work := make([]float64, max(1, 3*n)) + if optwork { + impl.Dtrevc3(side, howmny, nil, n, nil, 1, nil, 1, nil, 1, mWant, work, -1) + work = make([]float64, int(work[0])) + } + + m := impl.Dtrevc3(side, howmny, selected, n, tmat.Data, tmat.Stride, + vl.Data, vl.Stride, vr.Data, vr.Stride, mWant, work, len(work)) + + prefix := fmt.Sprintf("Case side=%v, howmny=%v, n=%v, extra=%v, optwk=%v", + side, howmny, n, extra, optwork) + + if !generalOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T", prefix) + } + if !generalOutsideAllNaN(vl) { + t.Errorf("%v: out-of-range write to VL", prefix) + } + if !generalOutsideAllNaN(vr) { + t.Errorf("%v: out-of-range write to VR", prefix) + } + + if m != mWant { + t.Errorf("%v: unexpected value of m. Want %v, got %v", prefix, mWant, m) + } + + if howmny == lapack.SelectedEV { + for i := range selected { + if selected[i] != selectedWant[i] { + t.Errorf("%v: unexpected selected[%v]", prefix, i) + } + } + } + + // Check that the columns of VR and VL are actually eigenvectors and + // that the magnitude of their largest element is 1. + var k int + for j := 0; j < n; { + re := tmat.Data[j*tmat.Stride+j] + if j == n-1 || tmat.Data[(j+1)*tmat.Stride+j] == 0 { + if howmny == lapack.SelectedEV && !selected[j] { + j++ + continue + } + if right { + ev := columnOf(vr, k) + norm := floats.Norm(ev, math.Inf(1)) + if math.Abs(norm-1) > tol { + t.Errorf("%v: magnitude of largest element of VR[:,%v] not 1", prefix, k) + } + if !isRightEigenvectorOf(tmat, ev, nil, complex(re, 0), tol) { + t.Errorf("%v: VR[:,%v] is not real right eigenvector", prefix, k) + } + } + if left { + ev := columnOf(vl, k) + norm := floats.Norm(ev, math.Inf(1)) + if math.Abs(norm-1) > tol { + t.Errorf("%v: magnitude of largest element of VL[:,%v] not 1", prefix, k) + } + if !isLeftEigenvectorOf(tmat, ev, nil, complex(re, 0), tol) { + t.Errorf("%v: VL[:,%v] is not real left eigenvector", prefix, k) + } + } + k++ + j++ + continue + } + if howmny == lapack.SelectedEV && !selected[j] { + j += 2 + continue + } + im := math.Sqrt(math.Abs(tmat.Data[(j+1)*tmat.Stride+j])) * + math.Sqrt(math.Abs(tmat.Data[j*tmat.Stride+j+1])) + if right { + evre := columnOf(vr, k) + evim := columnOf(vr, k+1) + var evmax float64 + for i, v := range evre { + evmax = math.Max(evmax, math.Abs(v)+math.Abs(evim[i])) + } + if math.Abs(evmax-1) > tol { + t.Errorf("%v: magnitude of largest element of VR[:,%v] not 1", prefix, k) + } + if !isRightEigenvectorOf(tmat, evre, evim, complex(re, im), tol) { + t.Errorf("%v: VR[:,%v:%v] is not complex right eigenvector", prefix, k, k+1) + } + floats.Scale(-1, evim) + if !isRightEigenvectorOf(tmat, evre, evim, complex(re, -im), tol) { + t.Errorf("%v: VR[:,%v:%v] is not complex right eigenvector", prefix, k, k+1) + } + } + if left { + evre := columnOf(vl, k) + evim := columnOf(vl, k+1) + var evmax float64 + for i, v := range evre { + evmax = math.Max(evmax, math.Abs(v)+math.Abs(evim[i])) + } + if math.Abs(evmax-1) > tol { + t.Errorf("%v: magnitude of largest element of VL[:,%v] not 1", prefix, k) + } + if !isLeftEigenvectorOf(tmat, evre, evim, complex(re, im), tol) { + t.Errorf("%v: VL[:,%v:%v] is not complex left eigenvector", prefix, k, k+1) + } + floats.Scale(-1, evim) + if !isLeftEigenvectorOf(tmat, evre, evim, complex(re, -im), tol) { + t.Errorf("%v: VL[:,%v:%v] is not complex left eigenvector", prefix, k, k+1) + } + } + k += 2 + j += 2 + } +} diff --git a/lapack/testlapack/dtrexc.go b/lapack/testlapack/dtrexc.go new file mode 100644 index 00000000..855805fb --- /dev/null +++ b/lapack/testlapack/dtrexc.go @@ -0,0 +1,219 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math/cmplx" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" +) + +type Dtrexcer interface { + Dtrexc(compq lapack.EVComp, n int, t []float64, ldt int, q []float64, ldq int, ifst, ilst int, work []float64) (ifstOut, ilstOut int, ok bool) +} + +func DtrexcTest(t *testing.T, impl Dtrexcer) { + rnd := rand.New(rand.NewSource(1)) + + for _, compq := range []lapack.EVComp{lapack.None, lapack.UpdateSchur} { + for _, n := range []int{1, 2, 3, 4, 5, 6, 10, 18, 31, 53} { + for _, extra := range []int{0, 1, 11} { + for cas := 0; cas < 100; cas++ { + tmat := randomSchurCanonical(n, n+extra, rnd) + ifst := rnd.Intn(n) + ilst := rnd.Intn(n) + testDtrexc(t, impl, compq, tmat, ifst, ilst, extra, rnd) + } + } + } + } + + for _, compq := range []lapack.EVComp{lapack.None, lapack.UpdateSchur} { + for _, extra := range []int{0, 1, 11} { + tmat := randomSchurCanonical(0, extra, rnd) + testDtrexc(t, impl, compq, tmat, 0, 0, extra, rnd) + } + } +} + +func testDtrexc(t *testing.T, impl Dtrexcer, compq lapack.EVComp, tmat blas64.General, ifst, ilst, extra int, rnd *rand.Rand) { + const tol = 1e-13 + + n := tmat.Rows + fstSize, fstFirst := schurBlockSize(tmat, ifst) + lstSize, lstFirst := schurBlockSize(tmat, ilst) + + tmatCopy := cloneGeneral(tmat) + + var wantq bool + var q, qCopy blas64.General + if compq == lapack.UpdateSchur { + wantq = true + q = eye(n, n+extra) + qCopy = cloneGeneral(q) + } + + work := nanSlice(n) + + ifstGot, ilstGot, ok := impl.Dtrexc(compq, n, tmat.Data, tmat.Stride, q.Data, q.Stride, ifst, ilst, work) + + prefix := fmt.Sprintf("Case compq=%v, n=%v, ifst=%v, nbf=%v, ilst=%v, nbl=%v, extra=%v", + compq, n, ifst, fstSize, ilst, lstSize, extra) + + if !generalOutsideAllNaN(tmat) { + t.Errorf("%v: out-of-range write to T", prefix) + } + if wantq && !generalOutsideAllNaN(q) { + t.Errorf("%v: out-of-range write to Q", prefix) + } + + if !ok { + t.Logf("%v: Dtrexc returned ok=false", prefix) + } + + // Check that the index of the first block was correctly updated (if + // necessary). + ifstWant := ifst + if !fstFirst { + ifstWant = ifst - 1 + } + if ifstWant != ifstGot { + t.Errorf("%v: unexpected ifst index. Want %v, got %v ", prefix, ifstWant, ifstGot) + } + + // Check that the index of the last block is as expected when ok=true. + // When ok=false, we don't know at which block the algorithm failed, so + // we don't check. + ilstWant := ilst + if !lstFirst { + ilstWant-- + } + if ok { + if ifstWant < ilstWant { + // If the blocks are swapped backwards, these + // adjustments are not necessary, the first row of the + // last block will end up at ifst. + switch { + case fstSize == 2 && lstSize == 1: + ilstWant-- + case fstSize == 1 && lstSize == 2: + ilstWant++ + } + } + if ilstWant != ilstGot { + t.Errorf("%v: unexpected ilst index. Want %v, got %v", prefix, ilstWant, ilstGot) + } + } + + if n <= 1 || ifstGot == ilstGot { + // Too small matrix or no swapping. + // Check that T was not modified. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if tmat.Data[i*tmat.Stride+j] != tmatCopy.Data[i*tmatCopy.Stride+j] { + t.Errorf("%v: unexpected modification at T[%v,%v]", prefix, i, j) + } + } + } + if !wantq { + return + } + // Check that Q was not modified. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if q.Data[i*q.Stride+j] != qCopy.Data[i*qCopy.Stride+j] { + t.Errorf("%v: unexpected modification at Q[%v,%v]", prefix, i, j) + } + } + } + return + } + + if !isSchurCanonicalGeneral(tmat) { + t.Errorf("%v: T is not in Schur canonical form", prefix) + } + + // Check that T was not modified except above the second subdiagonal in + // rows and columns [modMin,modMax]. + modMin := min(ifstGot, ilstGot) + modMax := max(ifstGot, ilstGot) + fstSize + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if modMin <= i && i < modMax && j+1 >= i { + continue + } + if modMin <= j && j < modMax && j+1 >= i { + continue + } + diff := tmat.Data[i*tmat.Stride+j] - tmatCopy.Data[i*tmatCopy.Stride+j] + if diff != 0 { + t.Errorf("%v: unexpected modification at T[%v,%v]", prefix, i, j) + } + } + } + + // Check that the block at ifstGot was delivered to ilstGot correctly. + if fstSize == 1 { + // 1×1 blocks are swapped exactly. + got := tmat.Data[ilstGot*tmat.Stride+ilstGot] + want := tmatCopy.Data[ifstGot*tmatCopy.Stride+ifstGot] + if want != got { + t.Errorf("%v: unexpected 1×1 block at T[%v,%v]. Want %v, got %v", + prefix, want, got, ilstGot, ilstGot) + } + } else { + // Check that the swapped 2×2 block is in Schur canonical form. + a, b, c, d := extract2x2Block(tmat.Data[ilstGot*tmat.Stride+ilstGot:], tmat.Stride) + if !isSchurCanonical(a, b, c, d) { + t.Errorf("%v: 2×2 block at T[%v,%v] not in Schur canonical form", prefix, ilstGot, ilstGot) + } + ev1Got, ev2Got := schurBlockEigenvalues(a, b, c, d) + + // Check that the swapped 2×2 block has the same eigenvalues. + // The block was originally located at T[ifstGot,ifstGot]. + a, b, c, d = extract2x2Block(tmatCopy.Data[ifstGot*tmatCopy.Stride+ifstGot:], tmatCopy.Stride) + ev1Want, ev2Want := schurBlockEigenvalues(a, b, c, d) + if cmplx.Abs(ev1Got-ev1Want) > tol { + t.Errorf("%v: unexpected first eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, ilstGot, ilstGot, ev1Want, ev1Got) + } + if cmplx.Abs(ev2Got-ev2Want) > tol { + t.Errorf("%v: unexpected second eigenvalue of 2×2 block at T[%v,%v]. Want %v, got %v", + prefix, ilstGot, ilstGot, ev2Want, ev2Got) + } + } + + if !wantq { + return + } + + if !isOrthonormal(q) { + t.Errorf("%v: Q is not orthogonal", prefix) + } + // Check that Q is unchanged outside of columns [modMin,modMax]. + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if modMin <= j && j < modMax { + continue + } + if q.Data[i*q.Stride+j]-qCopy.Data[i*qCopy.Stride+j] != 0 { + t.Errorf("%v: unexpected modification of Q[%v,%v]", prefix, i, j) + } + } + } + // Check that Q^T TOrig Q == T. + tq := eye(n, n) + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmatCopy, q, 0, tq) + qtq := eye(n, n) + blas64.Gemm(blas.Trans, blas.NoTrans, 1, q, tq, 0, qtq) + if !equalApproxGeneral(qtq, tmat, tol) { + t.Errorf("%v: Q^T (initial T) Q and (final T) are not equal", prefix) + } +} diff --git a/lapack/testlapack/dtrti2.go b/lapack/testlapack/dtrti2.go new file mode 100644 index 00000000..acb8b5e9 --- /dev/null +++ b/lapack/testlapack/dtrti2.go @@ -0,0 +1,163 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" +) + +type Dtrti2er interface { + Dtrti2(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) +} + +func Dtrti2Test(t *testing.T, impl Dtrti2er) { + const tol = 1e-14 + for _, test := range []struct { + a []float64 + n int + uplo blas.Uplo + diag blas.Diag + ans []float64 + }{ + { + a: []float64{ + 2, 3, 4, + 0, 5, 6, + 8, 0, 8}, + n: 3, + uplo: blas.Upper, + diag: blas.NonUnit, + ans: []float64{ + 0.5, -0.3, -0.025, + 0, 0.2, -0.15, + 8, 0, 0.125, + }, + }, + { + a: []float64{ + 5, 3, 4, + 0, 7, 6, + 10, 0, 8}, + n: 3, + uplo: blas.Upper, + diag: blas.Unit, + ans: []float64{ + 5, -3, 14, + 0, 7, -6, + 10, 0, 8, + }, + }, + { + a: []float64{ + 2, 0, 0, + 3, 5, 0, + 4, 6, 8}, + n: 3, + uplo: blas.Lower, + diag: blas.NonUnit, + ans: []float64{ + 0.5, 0, 0, + -0.3, 0.2, 0, + -0.025, -0.15, 0.125, + }, + }, + { + a: []float64{ + 1, 0, 0, + 3, 1, 0, + 4, 6, 1}, + n: 3, + uplo: blas.Lower, + diag: blas.Unit, + ans: []float64{ + 1, 0, 0, + -3, 1, 0, + 14, -6, 1, + }, + }, + } { + impl.Dtrti2(test.uplo, test.diag, test.n, test.a, test.n) + if !floats.EqualApprox(test.ans, test.a, tol) { + t.Errorf("Matrix inverse mismatch. Want %v, got %v.", test.ans, test.a) + } + } + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { + for _, test := range []struct { + n, lda int + }{ + {1, 0}, + {2, 0}, + {3, 0}, + {1, 5}, + {2, 5}, + {3, 5}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dtrti2(uplo, diag, n, a, lda) + if uplo == blas.Upper { + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + aCopy[i*lda+j] = 0 + a[i*lda+j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + aCopy[i*lda+j] = 0 + a[i*lda+j] = 0 + } + } + } + if diag == blas.Unit { + for i := 0; i < n; i++ { + a[i*lda+i] = 1 + aCopy[i*lda+i] = 1 + } + } + ans := make([]float64, len(a)) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, a, lda, aCopy, lda, 0, ans, lda) + iseye := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i == j { + if math.Abs(ans[i*lda+i]-1) > tol { + iseye = false + break + } + } else { + if math.Abs(ans[i*lda+j]) > tol { + iseye = false + break + } + } + } + } + if !iseye { + t.Errorf("inv(A) * A != I. Upper = %v, unit = %v, ans = %v", uplo == blas.Upper, diag == blas.Unit, ans) + } + } + } + } +} diff --git a/lapack/testlapack/dtrtri.go b/lapack/testlapack/dtrtri.go new file mode 100644 index 00000000..1224b7b7 --- /dev/null +++ b/lapack/testlapack/dtrtri.go @@ -0,0 +1,95 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +type Dtrtrier interface { + Dtrconer + Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) bool +} + +func DtrtriTest(t *testing.T, impl Dtrtrier) { + const tol = 1e-6 + rnd := rand.New(rand.NewSource(1)) + bi := blas64.Implementation() + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { + for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { + for _, test := range []struct { + n, lda int + }{ + {3, 0}, + {70, 0}, + {200, 0}, + {3, 5}, + {70, 92}, + {200, 205}, + } { + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + a := make([]float64, n*lda) + for i := range a { + a[i] = rnd.Float64() + 1 // This keeps the matrices well conditioned. + } + aCopy := make([]float64, len(a)) + copy(aCopy, a) + impl.Dtrtri(uplo, diag, n, a, lda) + if uplo == blas.Upper { + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + aCopy[i*lda+j] = 0 + a[i*lda+j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + aCopy[i*lda+j] = 0 + a[i*lda+j] = 0 + } + } + } + if diag == blas.Unit { + for i := 0; i < n; i++ { + a[i*lda+i] = 1 + aCopy[i*lda+i] = 1 + } + } + ans := make([]float64, len(a)) + bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, a, lda, aCopy, lda, 0, ans, lda) + iseye := true + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i == j { + if math.Abs(ans[i*lda+i]-1) > tol { + iseye = false + break + } + } else { + if math.Abs(ans[i*lda+j]) > tol { + iseye = false + break + } + } + } + } + if !iseye { + t.Errorf("inv(A) * A != I. Upper = %v, unit = %v, n = %v, lda = %v", + uplo == blas.Upper, diag == blas.Unit, n, lda) + } + } + } + } +} diff --git a/lapack/testlapack/fortran.go b/lapack/testlapack/fortran.go new file mode 100644 index 00000000..45ea6d07 --- /dev/null +++ b/lapack/testlapack/fortran.go @@ -0,0 +1,33 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "strings" +) + +// This file implements types for helping to convert to Fortran testing capabilities. + +// fortran64 is a float64 type that prints as a double precision constant in +// Fortran format. +type fortran64 float64 + +func (f fortran64) String() string { + // Replace exponent with D + s := fmt.Sprintf("%0.16E", f) + s = strings.Replace(s, "E", "D", 1) + return s +} + +// printFortranArray prints a Go slice as an array that can be copied into a +// fortran script. +func printFortranArray(z []float64, name string) { + fmt.Printf("%s(1:%d) = (/%v, &\n", name, len(z), fortran64(z[0])) + for i := 1; i < len(z)-1; i++ { + fmt.Printf("%v, &\n", fortran64(z[i])) + } + fmt.Printf("%s/)\n", fortran64(z[len(z)-1])) +} diff --git a/lapack/testlapack/general.go b/lapack/testlapack/general.go new file mode 100644 index 00000000..4404a336 --- /dev/null +++ b/lapack/testlapack/general.go @@ -0,0 +1,1414 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "fmt" + "math" + "math/cmplx" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" +) + +const ( + // dlamchE is the machine epsilon. For IEEE this is 2^{-53}. + dlamchE = 1.0 / (1 << 53) + dlamchB = 2 + dlamchP = dlamchB * dlamchE + // dlamchS is the smallest normal number. For IEEE this is 2^{-1022}. + dlamchS = 1.0 / (1 << 256) / (1 << 256) / (1 << 256) / (1 << 254) +) + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// worklen describes how much workspace a test should use. +type worklen int + +const ( + minimumWork worklen = iota + mediumWork + optimumWork +) + +// nanSlice allocates a new slice of length n filled with NaN. +func nanSlice(n int) []float64 { + s := make([]float64, n) + for i := range s { + s[i] = math.NaN() + } + return s +} + +// randomSlice allocates a new slice of length n filled with random values. +func randomSlice(n int, rnd *rand.Rand) []float64 { + s := make([]float64, n) + for i := range s { + s[i] = rnd.NormFloat64() + } + return s +} + +// nanGeneral allocates a new r×c general matrix filled with NaN values. +func nanGeneral(r, c, stride int) blas64.General { + if r < 0 || c < 0 { + panic("bad matrix size") + } + if r == 0 || c == 0 { + return blas64.General{Stride: max(1, stride)} + } + if stride < c { + panic("bad stride") + } + return blas64.General{ + Rows: r, + Cols: c, + Stride: stride, + Data: nanSlice((r-1)*stride + c), + } +} + +// randomGeneral allocates a new r×c general matrix filled with random +// numbers. Out-of-range elements are filled with NaN values. +func randomGeneral(r, c, stride int, rnd *rand.Rand) blas64.General { + ans := nanGeneral(r, c, stride) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + ans.Data[i*ans.Stride+j] = rnd.NormFloat64() + } + } + return ans +} + +// randomHessenberg allocates a new n×n Hessenberg matrix filled with zeros +// under the first subdiagonal and with random numbers elsewhere. Out-of-range +// elements are filled with NaN values. +func randomHessenberg(n, stride int, rnd *rand.Rand) blas64.General { + ans := nanGeneral(n, n, stride) + for i := 0; i < n; i++ { + for j := 0; j < i-1; j++ { + ans.Data[i*ans.Stride+j] = 0 + } + for j := max(0, i-1); j < n; j++ { + ans.Data[i*ans.Stride+j] = rnd.NormFloat64() + } + } + return ans +} + +// randomSchurCanonical returns a random, general matrix in Schur canonical +// form, that is, block upper triangular with 1×1 and 2×2 diagonal blocks where +// each 2×2 diagonal block has its diagonal elements equal and its off-diagonal +// elements of opposite sign. +func randomSchurCanonical(n, stride int, rnd *rand.Rand) blas64.General { + t := randomGeneral(n, n, stride, rnd) + // Zero out the lower triangle. + for i := 0; i < t.Rows; i++ { + for j := 0; j < i; j++ { + t.Data[i*t.Stride+j] = 0 + } + } + // Randomly create 2×2 diagonal blocks. + for i := 0; i < t.Rows; { + if i == t.Rows-1 || rnd.Float64() < 0.5 { + // 1×1 block. + i++ + continue + } + // 2×2 block. + // Diagonal elements equal. + t.Data[(i+1)*t.Stride+i+1] = t.Data[i*t.Stride+i] + // Off-diagonal elements of opposite sign. + c := rnd.NormFloat64() + if math.Signbit(c) == math.Signbit(t.Data[i*t.Stride+i+1]) { + c *= -1 + } + t.Data[(i+1)*t.Stride+i] = c + i += 2 + } + return t +} + +// blockedUpperTriGeneral returns a normal random, general matrix in the form +// +// c-k-l k l +// A = k [ 0 A12 A13 ] if r-k-l >= 0; +// l [ 0 0 A23 ] +// r-k-l [ 0 0 0 ] +// +// c-k-l k l +// A = k [ 0 A12 A13 ] if r-k-l < 0; +// r-k [ 0 0 A23 ] +// +// where the k×k matrix A12 and l×l matrix is non-singular +// upper triangular. A23 is l×l upper triangular if r-k-l >= 0, +// otherwise A23 is (r-k)×l upper trapezoidal. +func blockedUpperTriGeneral(r, c, k, l, stride int, kblock bool, rnd *rand.Rand) blas64.General { + t := l + if kblock { + t += k + } + ans := zeros(r, c, stride) + for i := 0; i < min(r, t); i++ { + var v float64 + for v == 0 { + v = rnd.NormFloat64() + } + ans.Data[i*ans.Stride+i+(c-t)] = v + } + for i := 0; i < min(r, t); i++ { + for j := i + (c - t) + 1; j < c; j++ { + ans.Data[i*ans.Stride+j] = rnd.NormFloat64() + } + } + return ans +} + +// nanTriangular allocates a new r×c triangular matrix filled with NaN values. +func nanTriangular(uplo blas.Uplo, n, stride int) blas64.Triangular { + if n < 0 { + panic("bad matrix size") + } + if n == 0 { + return blas64.Triangular{ + Stride: max(1, stride), + Uplo: uplo, + Diag: blas.NonUnit, + } + } + if stride < n { + panic("bad stride") + } + return blas64.Triangular{ + N: n, + Stride: stride, + Data: nanSlice((n-1)*stride + n), + Uplo: uplo, + Diag: blas.NonUnit, + } +} + +// randomTriangular allocates a new r×c triangular matrix filled with random +// numbers. Out-of-triangle elements are filled with NaN values. +func randomTriangular(uplo blas.Uplo, n, stride int, rnd *rand.Rand) blas64.Triangular { + ans := nanTriangular(uplo, n, stride) + if uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + ans.Data[i*ans.Stride+j] = rnd.NormFloat64() + } + } + return ans + } + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + ans.Data[i*ans.Stride+j] = rnd.NormFloat64() + } + } + return ans +} + +// generalOutsideAllNaN returns whether all out-of-range elements have NaN +// values. +func generalOutsideAllNaN(a blas64.General) bool { + // Check after last column. + for i := 0; i < a.Rows-1; i++ { + for _, v := range a.Data[i*a.Stride+a.Cols : i*a.Stride+a.Stride] { + if !math.IsNaN(v) { + return false + } + } + } + // Check after last element. + last := (a.Rows-1)*a.Stride + a.Cols + if a.Rows == 0 || a.Cols == 0 { + last = 0 + } + for _, v := range a.Data[last:] { + if !math.IsNaN(v) { + return false + } + } + return true +} + +// triangularOutsideAllNaN returns whether all out-of-triangle elements have NaN +// values. +func triangularOutsideAllNaN(a blas64.Triangular) bool { + if a.Uplo == blas.Upper { + // Check below diagonal. + for i := 0; i < a.N; i++ { + for _, v := range a.Data[i*a.Stride : i*a.Stride+i] { + if !math.IsNaN(v) { + return false + } + } + } + // Check after last column. + for i := 0; i < a.N-1; i++ { + for _, v := range a.Data[i*a.Stride+a.N : i*a.Stride+a.Stride] { + if !math.IsNaN(v) { + return false + } + } + } + } else { + // Check above diagonal. + for i := 0; i < a.N-1; i++ { + for _, v := range a.Data[i*a.Stride+i+1 : i*a.Stride+a.Stride] { + if !math.IsNaN(v) { + return false + } + } + } + } + // Check after last element. + for _, v := range a.Data[max(0, a.N-1)*a.Stride+a.N:] { + if !math.IsNaN(v) { + return false + } + } + return true +} + +// transposeGeneral returns a new general matrix that is the transpose of the +// input. Nothing is done with data outside the {rows, cols} limit of the general. +func transposeGeneral(a blas64.General) blas64.General { + ans := blas64.General{ + Rows: a.Cols, + Cols: a.Rows, + Stride: a.Rows, + Data: make([]float64, a.Cols*a.Rows), + } + for i := 0; i < a.Rows; i++ { + for j := 0; j < a.Cols; j++ { + ans.Data[j*ans.Stride+i] = a.Data[i*a.Stride+j] + } + } + return ans +} + +// columnNorms returns the column norms of a. +func columnNorms(m, n int, a []float64, lda int) []float64 { + bi := blas64.Implementation() + norms := make([]float64, n) + for j := 0; j < n; j++ { + norms[j] = bi.Dnrm2(m, a[j:], lda) + } + return norms +} + +// extractVMat collects the single reflectors from a into a matrix. +func extractVMat(m, n int, a []float64, lda int, direct lapack.Direct, store lapack.StoreV) blas64.General { + k := min(m, n) + switch { + default: + panic("not implemented") + case direct == lapack.Forward && store == lapack.ColumnWise: + v := blas64.General{ + Rows: m, + Cols: k, + Stride: k, + Data: make([]float64, m*k), + } + for i := 0; i < k; i++ { + for j := 0; j < i; j++ { + v.Data[j*v.Stride+i] = 0 + } + v.Data[i*v.Stride+i] = 1 + for j := i + 1; j < m; j++ { + v.Data[j*v.Stride+i] = a[j*lda+i] + } + } + return v + case direct == lapack.Forward && store == lapack.RowWise: + v := blas64.General{ + Rows: k, + Cols: n, + Stride: n, + Data: make([]float64, k*n), + } + for i := 0; i < k; i++ { + for j := 0; j < i; j++ { + v.Data[i*v.Stride+j] = 0 + } + v.Data[i*v.Stride+i] = 1 + for j := i + 1; j < n; j++ { + v.Data[i*v.Stride+j] = a[i*lda+j] + } + } + return v + } +} + +// constructBidiagonal constructs a bidiagonal matrix with the given diagonal +// and off-diagonal elements. +func constructBidiagonal(uplo blas.Uplo, n int, d, e []float64) blas64.General { + bMat := blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: make([]float64, n*n), + } + + for i := 0; i < n-1; i++ { + bMat.Data[i*bMat.Stride+i] = d[i] + if uplo == blas.Upper { + bMat.Data[i*bMat.Stride+i+1] = e[i] + } else { + bMat.Data[(i+1)*bMat.Stride+i] = e[i] + } + } + bMat.Data[(n-1)*bMat.Stride+n-1] = d[n-1] + return bMat +} + +// constructVMat transforms the v matrix based on the storage. +func constructVMat(vMat blas64.General, store lapack.StoreV, direct lapack.Direct) blas64.General { + m := vMat.Rows + k := vMat.Cols + switch { + default: + panic("not implemented") + case store == lapack.ColumnWise && direct == lapack.Forward: + ldv := k + v := make([]float64, m*k) + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + if j > i { + v[i*ldv+j] = 0 + } else if j == i { + v[i*ldv+i] = 1 + } else { + v[i*ldv+j] = vMat.Data[i*vMat.Stride+j] + } + } + } + return blas64.General{ + Rows: m, + Cols: k, + Stride: k, + Data: v, + } + case store == lapack.RowWise && direct == lapack.Forward: + ldv := m + v := make([]float64, m*k) + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + if j > i { + v[j*ldv+i] = 0 + } else if j == i { + v[j*ldv+i] = 1 + } else { + v[j*ldv+i] = vMat.Data[i*vMat.Stride+j] + } + } + } + return blas64.General{ + Rows: k, + Cols: m, + Stride: m, + Data: v, + } + case store == lapack.ColumnWise && direct == lapack.Backward: + rowsv := m + ldv := k + v := make([]float64, m*k) + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + vrow := rowsv - i - 1 + vcol := k - j - 1 + if j > i { + v[vrow*ldv+vcol] = 0 + } else if j == i { + v[vrow*ldv+vcol] = 1 + } else { + v[vrow*ldv+vcol] = vMat.Data[i*vMat.Stride+j] + } + } + } + return blas64.General{ + Rows: rowsv, + Cols: ldv, + Stride: ldv, + Data: v, + } + case store == lapack.RowWise && direct == lapack.Backward: + rowsv := k + ldv := m + v := make([]float64, m*k) + for i := 0; i < m; i++ { + for j := 0; j < k; j++ { + vcol := ldv - i - 1 + vrow := k - j - 1 + if j > i { + v[vrow*ldv+vcol] = 0 + } else if j == i { + v[vrow*ldv+vcol] = 1 + } else { + v[vrow*ldv+vcol] = vMat.Data[i*vMat.Stride+j] + } + } + } + return blas64.General{ + Rows: rowsv, + Cols: ldv, + Stride: ldv, + Data: v, + } + } +} + +func constructH(tau []float64, v blas64.General, store lapack.StoreV, direct lapack.Direct) blas64.General { + m := v.Rows + k := v.Cols + if store == lapack.RowWise { + m, k = k, m + } + h := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: make([]float64, m*m), + } + for i := 0; i < m; i++ { + h.Data[i*m+i] = 1 + } + for i := 0; i < k; i++ { + vecData := make([]float64, m) + if store == lapack.ColumnWise { + for j := 0; j < m; j++ { + vecData[j] = v.Data[j*v.Cols+i] + } + } else { + for j := 0; j < m; j++ { + vecData[j] = v.Data[i*v.Cols+j] + } + } + vec := blas64.Vector{ + Inc: 1, + Data: vecData, + } + + hi := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: make([]float64, m*m), + } + for i := 0; i < m; i++ { + hi.Data[i*m+i] = 1 + } + // hi = I - tau * v * v^T + blas64.Ger(-tau[i], vec, vec, hi) + + hcopy := blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: make([]float64, m*m), + } + copy(hcopy.Data, h.Data) + if direct == lapack.Forward { + // H = H * H_I in forward mode + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hcopy, hi, 0, h) + } else { + // H = H_I * H in backward mode + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hi, hcopy, 0, h) + } + } + return h +} + +// constructQ constructs the Q matrix from the result of dgeqrf and dgeqr2. +func constructQ(kind string, m, n int, a []float64, lda int, tau []float64) blas64.General { + k := min(m, n) + return constructQK(kind, m, n, k, a, lda, tau) +} + +// constructQK constructs the Q matrix from the result of dgeqrf and dgeqr2 using +// the first k reflectors. +func constructQK(kind string, m, n, k int, a []float64, lda int, tau []float64) blas64.General { + var sz int + switch kind { + case "QR": + sz = m + case "LQ", "RQ": + sz = n + } + + q := blas64.General{ + Rows: sz, + Cols: sz, + Stride: sz, + Data: make([]float64, sz*sz), + } + for i := 0; i < sz; i++ { + q.Data[i*sz+i] = 1 + } + qCopy := blas64.General{ + Rows: q.Rows, + Cols: q.Cols, + Stride: q.Stride, + Data: make([]float64, len(q.Data)), + } + for i := 0; i < k; i++ { + h := blas64.General{ + Rows: sz, + Cols: sz, + Stride: sz, + Data: make([]float64, sz*sz), + } + for j := 0; j < sz; j++ { + h.Data[j*sz+j] = 1 + } + vVec := blas64.Vector{ + Inc: 1, + Data: make([]float64, sz), + } + switch kind { + case "QR": + vVec.Data[i] = 1 + for j := i + 1; j < sz; j++ { + vVec.Data[j] = a[lda*j+i] + } + case "LQ": + vVec.Data[i] = 1 + for j := i + 1; j < sz; j++ { + vVec.Data[j] = a[i*lda+j] + } + case "RQ": + for j := 0; j < n-k+i; j++ { + vVec.Data[j] = a[(m-k+i)*lda+j] + } + vVec.Data[n-k+i] = 1 + } + blas64.Ger(-tau[i], vVec, vVec, h) + copy(qCopy.Data, q.Data) + // Mulitply q by the new h + switch kind { + case "QR", "RQ": + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, h, 0, q) + case "LQ": + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, qCopy, 0, q) + } + } + return q +} + +// checkBidiagonal checks the bidiagonal decomposition from dlabrd and dgebd2. +// The input to this function is the answer returned from the routines, stored +// in a, d, e, tauP, and tauQ. The data of original A matrix (before +// decomposition) is input in aCopy. +// +// checkBidiagonal constructs the V and U matrices, and from them constructs Q +// and P. Using these constructions, it checks that Q^T * A * P and checks that +// the result is bidiagonal. +func checkBidiagonal(t *testing.T, m, n, nb int, a []float64, lda int, d, e, tauP, tauQ, aCopy []float64) { + // Check the answer. + // Construct V and U. + qMat := constructQPBidiagonal(lapack.ApplyQ, m, n, nb, a, lda, tauQ) + pMat := constructQPBidiagonal(lapack.ApplyP, m, n, nb, a, lda, tauP) + + // Compute Q^T * A * P + aMat := blas64.General{ + Rows: m, + Cols: n, + Stride: lda, + Data: make([]float64, len(aCopy)), + } + copy(aMat.Data, aCopy) + + tmp1 := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + blas64.Gemm(blas.Trans, blas.NoTrans, 1, qMat, aMat, 0, tmp1) + tmp2 := blas64.General{ + Rows: m, + Cols: n, + Stride: n, + Data: make([]float64, m*n), + } + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, tmp1, pMat, 0, tmp2) + + // Check that the first nb rows and cols of tm2 are upper bidiagonal + // if m >= n, and lower bidiagonal otherwise. + correctDiag := true + matchD := true + matchE := true + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if i >= nb && j >= nb { + continue + } + v := tmp2.Data[i*tmp2.Stride+j] + if i == j { + if math.Abs(d[i]-v) > 1e-12 { + matchD = false + } + continue + } + if m >= n && i == j-1 { + if math.Abs(e[j-1]-v) > 1e-12 { + matchE = false + } + continue + } + if m < n && i-1 == j { + if math.Abs(e[i-1]-v) > 1e-12 { + matchE = false + } + continue + } + if math.Abs(v) > 1e-12 { + correctDiag = false + } + } + } + if !correctDiag { + t.Errorf("Updated A not bi-diagonal") + } + if !matchD { + fmt.Println("d = ", d) + t.Errorf("D Mismatch") + } + if !matchE { + t.Errorf("E mismatch") + } +} + +// constructQPBidiagonal constructs Q or P from the Bidiagonal decomposition +// computed by dlabrd and bgebd2. +func constructQPBidiagonal(vect lapack.DecompUpdate, m, n, nb int, a []float64, lda int, tau []float64) blas64.General { + sz := n + if vect == lapack.ApplyQ { + sz = m + } + + var ldv int + var v blas64.General + if vect == lapack.ApplyQ { + ldv = nb + v = blas64.General{ + Rows: m, + Cols: nb, + Stride: ldv, + Data: make([]float64, m*ldv), + } + } else { + ldv = n + v = blas64.General{ + Rows: nb, + Cols: n, + Stride: ldv, + Data: make([]float64, m*ldv), + } + } + + if vect == lapack.ApplyQ { + if m >= n { + for i := 0; i < m; i++ { + for j := 0; j <= min(nb-1, i); j++ { + if i == j { + v.Data[i*ldv+j] = 1 + continue + } + v.Data[i*ldv+j] = a[i*lda+j] + } + } + } else { + for i := 1; i < m; i++ { + for j := 0; j <= min(nb-1, i-1); j++ { + if i-1 == j { + v.Data[i*ldv+j] = 1 + continue + } + v.Data[i*ldv+j] = a[i*lda+j] + } + } + } + } else { + if m < n { + for i := 0; i < nb; i++ { + for j := i; j < n; j++ { + if i == j { + v.Data[i*ldv+j] = 1 + continue + } + v.Data[i*ldv+j] = a[i*lda+j] + } + } + } else { + for i := 0; i < nb; i++ { + for j := i + 1; j < n; j++ { + if j-1 == i { + v.Data[i*ldv+j] = 1 + continue + } + v.Data[i*ldv+j] = a[i*lda+j] + } + } + } + } + + // The variable name is a computation of Q, but the algorithm is mostly the + // same for computing P (just with different data). + qMat := blas64.General{ + Rows: sz, + Cols: sz, + Stride: sz, + Data: make([]float64, sz*sz), + } + hMat := blas64.General{ + Rows: sz, + Cols: sz, + Stride: sz, + Data: make([]float64, sz*sz), + } + // set Q to I + for i := 0; i < sz; i++ { + qMat.Data[i*qMat.Stride+i] = 1 + } + for i := 0; i < nb; i++ { + qCopy := blas64.General{Rows: qMat.Rows, Cols: qMat.Cols, Stride: qMat.Stride, Data: make([]float64, len(qMat.Data))} + copy(qCopy.Data, qMat.Data) + + // Set g and h to I + for i := 0; i < sz; i++ { + for j := 0; j < sz; j++ { + if i == j { + hMat.Data[i*sz+j] = 1 + } else { + hMat.Data[i*sz+j] = 0 + } + } + } + var vi blas64.Vector + // H -= tauQ[i] * v[i] * v[i]^t + if vect == lapack.ApplyQ { + vi = blas64.Vector{ + Inc: v.Stride, + Data: v.Data[i:], + } + } else { + vi = blas64.Vector{ + Inc: 1, + Data: v.Data[i*v.Stride:], + } + } + blas64.Ger(-tau[i], vi, vi, hMat) + // Q = Q * G[1] + blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, qCopy, hMat, 0, qMat) + } + return qMat +} + +// printRowise prints the matrix with one row per line. This is useful for debugging. +// If beyond is true, it prints beyond the final column to lda. If false, only +// the columns are printed. +func printRowise(a []float64, m, n, lda int, beyond bool) { + for i := 0; i < m; i++ { + end := n + if beyond { + end = lda + } + fmt.Println(a[i*lda : i*lda+end]) + } +} + +// isOrthonormal checks that a general matrix is orthonormal. +func isOrthonormal(q blas64.General) bool { + n := q.Rows + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + dot := blas64.Dot(n, + blas64.Vector{Inc: 1, Data: q.Data[i*q.Stride:]}, + blas64.Vector{Inc: 1, Data: q.Data[j*q.Stride:]}, + ) + if math.IsNaN(dot) { + return false + } + if i == j { + if math.Abs(dot-1) > 1e-10 { + return false + } + } else { + if math.Abs(dot) > 1e-10 { + return false + } + } + } + } + return true +} + +// copyMatrix copies an m×n matrix src of stride n into an m×n matrix dst of stride ld. +func copyMatrix(m, n int, dst []float64, ld int, src []float64) { + for i := 0; i < m; i++ { + copy(dst[i*ld:i*ld+n], src[i*n:i*n+n]) + } +} + +func copyGeneral(dst, src blas64.General) { + r := min(dst.Rows, src.Rows) + c := min(dst.Cols, src.Cols) + for i := 0; i < r; i++ { + copy(dst.Data[i*dst.Stride:i*dst.Stride+c], src.Data[i*src.Stride:i*src.Stride+c]) + } +} + +// cloneGeneral allocates and returns an exact copy of the given general matrix. +func cloneGeneral(a blas64.General) blas64.General { + c := a + c.Data = make([]float64, len(a.Data)) + copy(c.Data, a.Data) + return c +} + +// equalApprox returns whether the matrices A and B of order n are approximately +// equal within given tolerance. +func equalApprox(m, n int, a []float64, lda int, b []float64, tol float64) bool { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + diff := a[i*lda+j] - b[i*n+j] + if math.IsNaN(diff) || math.Abs(diff) > tol { + return false + } + } + } + return true +} + +// equalApproxGeneral returns whether the general matrices a and b are +// approximately equal within given tolerance. +func equalApproxGeneral(a, b blas64.General, tol float64) bool { + if a.Rows != b.Rows || a.Cols != b.Cols { + panic("bad input") + } + for i := 0; i < a.Rows; i++ { + for j := 0; j < a.Cols; j++ { + diff := a.Data[i*a.Stride+j] - b.Data[i*b.Stride+j] + if math.IsNaN(diff) || math.Abs(diff) > tol { + return false + } + } + } + return true +} + +// equalApproxTriangular returns whether the triangular matrices A and B of +// order n are approximately equal within given tolerance. +func equalApproxTriangular(upper bool, n int, a []float64, lda int, b []float64, tol float64) bool { + if upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + diff := a[i*lda+j] - b[i*n+j] + if math.IsNaN(diff) || math.Abs(diff) > tol { + return false + } + } + } + return true + } + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + diff := a[i*lda+j] - b[i*n+j] + if math.IsNaN(diff) || math.Abs(diff) > tol { + return false + } + } + } + return true +} + +// eye returns an identity matrix of given order and stride. +func eye(n, stride int) blas64.General { + ans := nanGeneral(n, n, stride) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + ans.Data[i*ans.Stride+j] = 0 + } + ans.Data[i*ans.Stride+i] = 1 + } + return ans +} + +// zeros returns an m×n matrix with given stride filled with zeros. +func zeros(m, n, stride int) blas64.General { + a := nanGeneral(m, n, stride) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = 0 + } + } + return a +} + +// extract2x2Block returns the elements of T at [0,0], [0,1], [1,0], and [1,1]. +func extract2x2Block(t []float64, ldt int) (a, b, c, d float64) { + return t[0], t[1], t[ldt], t[ldt+1] +} + +// isSchurCanonical returns whether the 2×2 matrix [a b; c d] is in Schur +// canonical form. +func isSchurCanonical(a, b, c, d float64) bool { + return c == 0 || (a == d && math.Signbit(b) != math.Signbit(c)) +} + +// isSchurCanonicalGeneral returns whether T is block upper triangular with 1×1 +// and 2×2 diagonal blocks, each 2×2 block in Schur canonical form. The function +// checks only along the diagonal and the first subdiagonal, otherwise the lower +// triangle is not accessed. +func isSchurCanonicalGeneral(t blas64.General) bool { + if t.Rows != t.Cols { + panic("invalid matrix") + } + for i := 0; i < t.Rows-1; { + if t.Data[(i+1)*t.Stride+i] == 0 { + // 1×1 block. + i++ + continue + } + // 2×2 block. + a, b, c, d := extract2x2Block(t.Data[i*t.Stride+i:], t.Stride) + if !isSchurCanonical(a, b, c, d) { + return false + } + i += 2 + } + return true +} + +// schurBlockEigenvalues returns the two eigenvalues of the 2×2 matrix [a b; c d] +// that must be in Schur canonical form. +func schurBlockEigenvalues(a, b, c, d float64) (ev1, ev2 complex128) { + if !isSchurCanonical(a, b, c, d) { + panic("block not in Schur canonical form") + } + if c == 0 { + return complex(a, 0), complex(d, 0) + } + im := math.Sqrt(-b * c) + return complex(a, im), complex(a, -im) +} + +// schurBlockSize returns the size of the diagonal block at i-th row in the +// upper quasi-triangular matrix t in Schur canonical form, and whether i points +// to the first row of the block. For zero-sized matrices the function returns 0 +// and true. +func schurBlockSize(t blas64.General, i int) (size int, first bool) { + if t.Rows != t.Cols { + panic("matrix not square") + } + if t.Rows == 0 { + return 0, true + } + if i < 0 || t.Rows <= i { + panic("index out of range") + } + + first = true + if i > 0 && t.Data[i*t.Stride+i-1] != 0 { + // There is a non-zero element to the left, therefore i must + // point to the second row in a 2×2 diagonal block. + first = false + i-- + } + size = 1 + if i+1 < t.Rows && t.Data[(i+1)*t.Stride+i] != 0 { + // There is a non-zero element below, this must be a 2×2 + // diagonal block. + size = 2 + } + return size, first +} + +// containsComplex returns whether z is approximately equal to one of the complex +// numbers in v. If z is found, its index in v will be also returned. +func containsComplex(v []complex128, z complex128, tol float64) (found bool, index int) { + for i := range v { + if cmplx.Abs(v[i]-z) < tol { + return true, i + } + } + return false, -1 +} + +// isAllNaN returns whether x contains only NaN values. +func isAllNaN(x []float64) bool { + for _, v := range x { + if !math.IsNaN(v) { + return false + } + } + return true +} + +// isUpperHessenberg returns whether h contains only zeros below the +// subdiagonal. +func isUpperHessenberg(h blas64.General) bool { + if h.Rows != h.Cols { + panic("matrix not square") + } + n := h.Rows + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + if i > j+1 && h.Data[i*h.Stride+j] != 0 { + return false + } + } + } + return true +} + +// isUpperTriangular returns whether a contains only zeros below the diagonal. +func isUpperTriangular(a blas64.General) bool { + n := a.Rows + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + if a.Data[i*a.Stride+j] != 0 { + return false + } + } + } + return true +} + +// unbalancedSparseGeneral returns an m×n dense matrix with a random sparse +// structure consisting of nz nonzero elements. The matrix will be unbalanced by +// multiplying each element randomly by its row or column index. +func unbalancedSparseGeneral(m, n, stride int, nonzeros int, rnd *rand.Rand) blas64.General { + a := zeros(m, n, stride) + for k := 0; k < nonzeros; k++ { + i := rnd.Intn(n) + j := rnd.Intn(n) + if rnd.Float64() < 0.5 { + a.Data[i*stride+j] = float64(i+1) * rnd.NormFloat64() + } else { + a.Data[i*stride+j] = float64(j+1) * rnd.NormFloat64() + } + } + return a +} + +// columnOf returns a copy of the j-th column of a. +func columnOf(a blas64.General, j int) []float64 { + if j < 0 || a.Cols <= j { + panic("bad column index") + } + col := make([]float64, a.Rows) + for i := range col { + col[i] = a.Data[i*a.Stride+j] + } + return col +} + +// isRightEigenvectorOf returns whether the vector xRe+i*xIm, where i is the +// imaginary unit, is the right eigenvector of A corresponding to the eigenvalue +// lambda. +// +// A right eigenvector corresponding to a complex eigenvalue λ is a complex +// non-zero vector x such that +// A x = λ x. +func isRightEigenvectorOf(a blas64.General, xRe, xIm []float64, lambda complex128, tol float64) bool { + if a.Rows != a.Cols { + panic("matrix not square") + } + + if imag(lambda) != 0 && xIm == nil { + // Complex eigenvalue of a real matrix cannot have a real + // eigenvector. + return false + } + + n := a.Rows + + // Compute A real(x) and store the result into xReAns. + xReAns := make([]float64, n) + blas64.Gemv(blas.NoTrans, 1, a, blas64.Vector{1, xRe}, 0, blas64.Vector{1, xReAns}) + + if imag(lambda) == 0 && xIm == nil { + // Real eigenvalue and eigenvector. + + // Compute λx and store the result into lambdax. + lambdax := make([]float64, n) + floats.AddScaled(lambdax, real(lambda), xRe) + + if floats.Distance(xReAns, lambdax, math.Inf(1)) > tol { + return false + } + return true + } + + // Complex eigenvector, and real or complex eigenvalue. + + // Compute A imag(x) and store the result into xImAns. + xImAns := make([]float64, n) + blas64.Gemv(blas.NoTrans, 1, a, blas64.Vector{1, xIm}, 0, blas64.Vector{1, xImAns}) + + // Compute λx and store the result into lambdax. + lambdax := make([]complex128, n) + for i := range lambdax { + lambdax[i] = lambda * complex(xRe[i], xIm[i]) + } + + for i, v := range lambdax { + ax := complex(xReAns[i], xImAns[i]) + if cmplx.Abs(v-ax) > tol { + return false + } + } + return true +} + +// isLeftEigenvectorOf returns whether the vector yRe+i*yIm, where i is the +// imaginary unit, is the left eigenvector of A corresponding to the eigenvalue +// lambda. +// +// A left eigenvector corresponding to a complex eigenvalue λ is a complex +// non-zero vector y such that +// y^H A = λ y^H, +// which is equivalent for real A to +// A^T y = conj(λ) y, +func isLeftEigenvectorOf(a blas64.General, yRe, yIm []float64, lambda complex128, tol float64) bool { + if a.Rows != a.Cols { + panic("matrix not square") + } + + if imag(lambda) != 0 && yIm == nil { + // Complex eigenvalue of a real matrix cannot have a real + // eigenvector. + return false + } + + n := a.Rows + + // Compute A^T real(y) and store the result into yReAns. + yReAns := make([]float64, n) + blas64.Gemv(blas.Trans, 1, a, blas64.Vector{1, yRe}, 0, blas64.Vector{1, yReAns}) + + if imag(lambda) == 0 && yIm == nil { + // Real eigenvalue and eigenvector. + + // Compute λy and store the result into lambday. + lambday := make([]float64, n) + floats.AddScaled(lambday, real(lambda), yRe) + + if floats.Distance(yReAns, lambday, math.Inf(1)) > tol { + return false + } + return true + } + + // Complex eigenvector, and real or complex eigenvalue. + + // Compute A^T imag(y) and store the result into yImAns. + yImAns := make([]float64, n) + blas64.Gemv(blas.Trans, 1, a, blas64.Vector{1, yIm}, 0, blas64.Vector{1, yImAns}) + + // Compute conj(λ)y and store the result into lambday. + lambda = cmplx.Conj(lambda) + lambday := make([]complex128, n) + for i := range lambday { + lambday[i] = lambda * complex(yRe[i], yIm[i]) + } + + for i, v := range lambday { + ay := complex(yReAns[i], yImAns[i]) + if cmplx.Abs(v-ay) > tol { + return false + } + } + return true +} + +// rootsOfUnity returns the n complex numbers whose n-th power is equal to 1. +func rootsOfUnity(n int) []complex128 { + w := make([]complex128, n) + for i := 0; i < n; i++ { + angle := math.Pi * float64(2*i) / float64(n) + w[i] = complex(math.Cos(angle), math.Sin(angle)) + } + return w +} + +// randomOrthogonal returns an n×n random orthogonal matrix. +func randomOrthogonal(n int, rnd *rand.Rand) blas64.General { + q := eye(n, n) + x := make([]float64, n) + v := make([]float64, n) + for j := 0; j < n-1; j++ { + // x represents the j-th column of a random matrix. + for i := 0; i < j; i++ { + x[i] = 0 + } + for i := j; i < n; i++ { + x[i] = rnd.NormFloat64() + } + // Compute v that represents the elementary reflector that + // annihilates the subdiagonal elements of x. + reflector(v, x, j) + // Compute Q * H_j and store the result into Q. + applyReflector(q, q, v) + } + if !isOrthonormal(q) { + panic("Q not orthogonal") + } + return q +} + +// reflector generates a Householder reflector v that zeros out subdiagonal +// entries in the j-th column of a matrix. +func reflector(v, col []float64, j int) { + n := len(col) + if len(v) != n { + panic("slice length mismatch") + } + if j < 0 || n <= j { + panic("invalid column index") + } + + for i := range v { + v[i] = 0 + } + if j == n-1 { + return + } + s := floats.Norm(col[j:], 2) + if s == 0 { + return + } + v[j] = col[j] + math.Copysign(s, col[j]) + copy(v[j+1:], col[j+1:]) + s = floats.Norm(v[j:], 2) + floats.Scale(1/s, v[j:]) +} + +// applyReflector computes Q*H where H is a Householder matrix represented by +// the Householder reflector v. +func applyReflector(qh blas64.General, q blas64.General, v []float64) { + n := len(v) + if qh.Rows != n || qh.Cols != n { + panic("bad size of qh") + } + if q.Rows != n || q.Cols != n { + panic("bad size of q") + } + qv := make([]float64, n) + blas64.Gemv(blas.NoTrans, 1, q, blas64.Vector{1, v}, 0, blas64.Vector{1, qv}) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + qh.Data[i*qh.Stride+j] = q.Data[i*q.Stride+j] + } + } + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + qh.Data[i*qh.Stride+j] -= 2 * qv[i] * v[j] + } + } + var norm2 float64 + for _, vi := range v { + norm2 += vi * vi + } + norm2inv := 1 / norm2 + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + qh.Data[i*qh.Stride+j] *= norm2inv + } + } +} + +// constructGSVDresults returns the matrices [ 0 R ], D1 and D2 described +// in the documentation of Dtgsja and Dggsvd3, and the result matrix in +// the documentation for Dggsvp3. +func constructGSVDresults(n, p, m, k, l int, a, b blas64.General, alpha, beta []float64) (zeroR, d1, d2 blas64.General) { + // [ 0 R ] + zeroR = zeros(k+l, n, n) + dst := zeroR + dst.Rows = min(m, k+l) + dst.Cols = k + l + dst.Data = zeroR.Data[n-k-l:] + src := a + src.Rows = min(m, k+l) + src.Cols = k + l + src.Data = a.Data[n-k-l:] + copyGeneral(dst, src) + if m < k+l { + // [ 0 R ] + dst.Rows = k + l - m + dst.Cols = k + l - m + dst.Data = zeroR.Data[m*zeroR.Stride+n-(k+l-m):] + src = b + src.Rows = k + l - m + src.Cols = k + l - m + src.Data = b.Data[(m-k)*b.Stride+n+m-k-l:] + copyGeneral(dst, src) + } + + // D1 + d1 = zeros(m, k+l, k+l) + for i := 0; i < k; i++ { + d1.Data[i*d1.Stride+i] = 1 + } + for i := k; i < min(m, k+l); i++ { + d1.Data[i*d1.Stride+i] = alpha[i] + } + + // D2 + d2 = zeros(p, k+l, k+l) + for i := 0; i < min(l, m-k); i++ { + d2.Data[i*d2.Stride+i+k] = beta[k+i] + } + for i := m - k; i < l; i++ { + d2.Data[i*d2.Stride+i+k] = 1 + } + + return zeroR, d1, d2 +} + +func constructGSVPresults(n, p, m, k, l int, a, b blas64.General) (zeroA, zeroB blas64.General) { + zeroA = zeros(m, n, n) + dst := zeroA + dst.Rows = min(m, k+l) + dst.Cols = k + l + dst.Data = zeroA.Data[n-k-l:] + src := a + dst.Rows = min(m, k+l) + src.Cols = k + l + src.Data = a.Data[n-k-l:] + copyGeneral(dst, src) + + zeroB = zeros(p, n, n) + dst = zeroB + dst.Rows = l + dst.Cols = l + dst.Data = zeroB.Data[n-l:] + src = b + dst.Rows = l + src.Cols = l + src.Data = b.Data[n-l:] + copyGeneral(dst, src) + + return zeroA, zeroB +} diff --git a/lapack/testlapack/iladlc.go b/lapack/testlapack/iladlc.go new file mode 100644 index 00000000..b8a5b2b3 --- /dev/null +++ b/lapack/testlapack/iladlc.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import "testing" + +type Iladlcer interface { + Iladlc(m, n int, a []float64, lda int) int +} + +func IladlcTest(t *testing.T, impl Iladlcer) { + for i, test := range []struct { + a []float64 + m, n, lda int + ans int + }{ + { + a: []float64{0, 0, 0, 0}, + m: 1, + n: 1, + lda: 2, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 2, + n: 2, + lda: 2, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 4, + n: 1, + lda: 1, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 1, + n: 4, + lda: 4, + ans: -1, + }, + { + a: []float64{ + 1, 2, 3, 4, + 5, 6, 7, 8, + }, + m: 2, + n: 4, + lda: 4, + ans: 3, + }, + { + a: []float64{ + 1, 2, 3, 0, + 0, 0, 0, 0, + }, + m: 2, + n: 4, + lda: 4, + ans: 2, + }, + { + a: []float64{ + 0, 0, 3, 4, + 0, 0, 0, 0, + }, + m: 2, + n: 2, + lda: 4, + ans: -1, + }, + } { + ans := impl.Iladlc(test.m, test.n, test.a, test.lda) + if ans != test.ans { + t.Errorf("Column mismatch case %v. Want: %v, got: %v", i, test.ans, ans) + } + } +} diff --git a/lapack/testlapack/iladlr.go b/lapack/testlapack/iladlr.go new file mode 100644 index 00000000..bd74d28c --- /dev/null +++ b/lapack/testlapack/iladlr.go @@ -0,0 +1,83 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import "testing" + +type Iladlrer interface { + Iladlr(m, n int, a []float64, lda int) int +} + +func IladlrTest(t *testing.T, impl Iladlrer) { + for i, test := range []struct { + a []float64 + m, n, lda int + ans int + }{ + { + a: []float64{0, 0, 0, 0}, + m: 1, + n: 1, + lda: 2, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 2, + n: 2, + lda: 2, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 4, + n: 1, + lda: 1, + ans: -1, + }, + { + a: []float64{0, 0, 0, 0}, + m: 1, + n: 4, + lda: 4, + ans: -1, + }, + { + a: []float64{ + 1, 2, 3, 4, + 5, 6, 7, 8, + }, + m: 2, + n: 4, + lda: 4, + ans: 1, + }, + { + a: []float64{ + 1, 2, 3, 0, + 0, 0, 0, 0, + }, + m: 2, + n: 4, + lda: 4, + ans: 0, + }, + { + a: []float64{ + 0, 0, 3, 4, + 0, 0, 0, 0, + }, + m: 2, + n: 2, + lda: 4, + ans: -1, + }, + } { + ans := impl.Iladlr(test.m, test.n, test.a, test.lda) + if ans != test.ans { + t.Errorf("Column mismatch case %v. Want: %v, got: %v", i, test.ans, ans) + } + } +} diff --git a/lapack/testlapack/matgen.go b/lapack/testlapack/matgen.go new file mode 100644 index 00000000..b47d9270 --- /dev/null +++ b/lapack/testlapack/matgen.go @@ -0,0 +1,655 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlatm1 computes the entries of dst as specified by mode, cond and rsign. +// +// mode describes how dst will be computed: +// |mode| == 1: dst[0] = 1 and dst[1:n] = 1/cond +// |mode| == 2: dst[:n-1] = 1/cond and dst[n-1] = 1 +// |mode| == 3: dst[i] = cond^{-i/(n-1)}, i=0,...,n-1 +// |mode| == 4: dst[i] = 1 - i*(1-1/cond)/(n-1) +// |mode| == 5: dst[i] = random number in the range (1/cond, 1) such that +// their logarithms are uniformly distributed +// |mode| == 6: dst[i] = random number from the distribution given by dist +// If mode is negative, the order of the elements of dst will be reversed. +// For other values of mode Dlatm1 will panic. +// +// If rsign is true and mode is not ±6, each entry of dst will be multiplied by 1 +// or -1 with probability 0.5 +// +// dist specifies the type of distribution to be used when mode == ±6: +// dist == 1: Uniform[0,1) +// dist == 2: Uniform[-1,1) +// dist == 3: Normal(0,1) +// For other values of dist Dlatm1 will panic. +// +// rnd is used as a source of random numbers. +func Dlatm1(dst []float64, mode int, cond float64, rsign bool, dist int, rnd *rand.Rand) { + amode := mode + if amode < 0 { + amode = -amode + } + if amode < 1 || 6 < amode { + panic("testlapack: invalid mode") + } + if cond < 1 { + panic("testlapack: cond < 1") + } + if amode == 6 && (dist < 1 || 3 < dist) { + panic("testlapack: invalid dist") + } + + n := len(dst) + if n == 0 { + return + } + + switch amode { + case 1: + dst[0] = 1 + for i := 1; i < n; i++ { + dst[i] = 1 / cond + } + case 2: + for i := 0; i < n-1; i++ { + dst[i] = 1 + } + dst[n-1] = 1 / cond + case 3: + dst[0] = 1 + if n > 1 { + alpha := math.Pow(cond, -1/float64(n-1)) + for i := 1; i < n; i++ { + dst[i] = math.Pow(alpha, float64(i)) + } + } + case 4: + dst[0] = 1 + if n > 1 { + condInv := 1 / cond + alpha := (1 - condInv) / float64(n-1) + for i := 1; i < n; i++ { + dst[i] = float64(n-i-1)*alpha + condInv + } + } + case 5: + alpha := math.Log(1 / cond) + for i := range dst { + dst[i] = math.Exp(alpha * rnd.Float64()) + } + case 6: + switch dist { + case 1: + for i := range dst { + dst[i] = rnd.Float64() + } + case 2: + for i := range dst { + dst[i] = 2*rnd.Float64() - 1 + } + case 3: + for i := range dst { + dst[i] = rnd.NormFloat64() + } + } + } + + if rsign && amode != 6 { + for i, v := range dst { + if rnd.Float64() < 0.5 { + dst[i] = -v + } + } + } + + if mode < 0 { + for i := 0; i < n/2; i++ { + dst[i], dst[n-i-1] = dst[n-i-1], dst[i] + } + } +} + +// Dlagsy generates an n×n symmetric matrix A, by pre- and post- multiplying a +// real diagonal matrix D with a random orthogonal matrix: +// A = U * D * U^T. +// +// work must have length at least 2*n, otherwise Dlagsy will panic. +// +// The parameter k is unused but it must satisfy +// 0 <= k <= n-1. +func Dlagsy(n, k int, d []float64, a []float64, lda int, rnd *rand.Rand, work []float64) { + checkMatrix(n, n, a, lda) + if k < 0 || max(0, n-1) < k { + panic("testlapack: invalid value of k") + } + if len(d) != n { + panic("testlapack: bad length of d") + } + if len(work) < 2*n { + panic("testlapack: insufficient work length") + } + + // Initialize lower triangle of A to diagonal matrix. + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = 0 + } + } + for i := 0; i < n; i++ { + a[i*lda+i] = d[i] + } + + bi := blas64.Implementation() + + // Generate lower triangle of symmetric matrix. + for i := n - 2; i >= 0; i-- { + for j := 0; j < n-i; j++ { + work[j] = rnd.NormFloat64() + } + wn := bi.Dnrm2(n-i, work[:n-i], 1) + wa := math.Copysign(wn, work[0]) + var tau float64 + if wn != 0 { + wb := work[0] + wa + bi.Dscal(n-i-1, 1/wb, work[1:n-i], 1) + work[0] = 1 + tau = wb / wa + } + + // Apply random reflection to A[i:n,i:n] from the left and the + // right. + // + // Compute y := tau * A * u. + bi.Dsymv(blas.Lower, n-i, tau, a[i*lda+i:], lda, work[:n-i], 1, 0, work[n:2*n-i], 1) + + // Compute v := y - 1/2 * tau * ( y, u ) * u. + alpha := -0.5 * tau * bi.Ddot(n-i, work[n:2*n-i], 1, work[:n-i], 1) + bi.Daxpy(n-i, alpha, work[:n-i], 1, work[n:2*n-i], 1) + + // Apply the transformation as a rank-2 update to A[i:n,i:n]. + bi.Dsyr2(blas.Lower, n-i, -1, work[:n-i], 1, work[n:2*n-i], 1, a[i*lda+i:], lda) + } + + // Store full symmetric matrix. + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + a[j*lda+i] = a[i*lda+j] + } + } +} + +// Dlagge generates a real general m×n matrix A, by pre- and post-multiplying +// a real diagonal matrix D with random orthogonal matrices: +// A = U*D*V. +// +// d must have length min(m,n), and work must have length m+n, otherwise Dlagge +// will panic. +// +// The parameters ku and kl are unused but they must satisfy +// 0 <= kl <= m-1, +// 0 <= ku <= n-1. +func Dlagge(m, n, kl, ku int, d []float64, a []float64, lda int, rnd *rand.Rand, work []float64) { + checkMatrix(m, n, a, lda) + if kl < 0 || max(0, m-1) < kl { + panic("testlapack: invalid value of kl") + } + if ku < 0 || max(0, n-1) < ku { + panic("testlapack: invalid value of ku") + } + if len(d) != min(m, n) { + panic("testlapack: bad length of d") + } + if len(work) < m+n { + panic("testlapack: insufficient work length") + } + + // Initialize A to diagonal matrix. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a[i*lda+j] = 0 + } + } + for i := 0; i < min(m, n); i++ { + a[i*lda+i] = d[i] + } + + // Quick exit if the user wants a diagonal matrix. + // if kl == 0 && ku == 0 { + // return + // } + + bi := blas64.Implementation() + + // Pre- and post-multiply A by random orthogonal matrices. + for i := min(m, n) - 1; i >= 0; i-- { + if i < m-1 { + for j := 0; j < m-i; j++ { + work[j] = rnd.NormFloat64() + } + wn := bi.Dnrm2(m-i, work[:m-i], 1) + wa := math.Copysign(wn, work[0]) + var tau float64 + if wn != 0 { + wb := work[0] + wa + bi.Dscal(m-i-1, 1/wb, work[1:m-i], 1) + work[0] = 1 + tau = wb / wa + } + + // Multiply A[i:m,i:n] by random reflection from the left. + bi.Dgemv(blas.Trans, m-i, n-i, + 1, a[i*lda+i:], lda, work[:m-i], 1, + 0, work[m:m+n-i], 1) + bi.Dger(m-i, n-i, + -tau, work[:m-i], 1, work[m:m+n-i], 1, + a[i*lda+i:], lda) + } + if i < n-1 { + for j := 0; j < n-i; j++ { + work[j] = rnd.NormFloat64() + } + wn := bi.Dnrm2(n-i, work[:n-i], 1) + wa := math.Copysign(wn, work[0]) + var tau float64 + if wn != 0 { + wb := work[0] + wa + bi.Dscal(n-i-1, 1/wb, work[1:n-i], 1) + work[0] = 1 + tau = wb / wa + } + + // Multiply A[i:m,i:n] by random reflection from the right. + bi.Dgemv(blas.NoTrans, m-i, n-i, + 1, a[i*lda+i:], lda, work[:n-i], 1, + 0, work[n:n+m-i], 1) + bi.Dger(m-i, n-i, + -tau, work[n:n+m-i], 1, work[:n-i], 1, + a[i*lda+i:], lda) + } + } + + // TODO(vladimir-ch): Reduce number of subdiagonals to kl and number of + // superdiagonals to ku. +} + +// dlarnv fills dst with random numbers from a uniform or normal distribution +// specified by dist: +// dist=1: uniform(0,1), +// dist=2: uniform(-1,1), +// dist=3: normal(0,1). +// For other values of dist dlarnv will panic. +func dlarnv(dst []float64, dist int, rnd *rand.Rand) { + switch dist { + default: + panic("testlapack: invalid dist") + case 1: + for i := range dst { + dst[i] = rnd.Float64() + } + case 2: + for i := range dst { + dst[i] = 2*rnd.Float64() - 1 + } + case 3: + for i := range dst { + dst[i] = rnd.NormFloat64() + } + } +} + +// dlattr generates an n×n triangular test matrix A with its properties uniquely +// determined by imat and uplo, and returns whether A has unit diagonal. If diag +// is blas.Unit, the diagonal elements are set so that A[k,k]=k. +// +// trans specifies whether the matrix A or its transpose will be used. +// +// If imat is greater than 10, dlattr also generates the right hand side of the +// linear system A*x=b, or A^T*x=b. Valid values of imat are 7, and all between 11 +// and 19, inclusive. +// +// b mush have length n, and work must have length 3*n, and dlattr will panic +// otherwise. +func dlattr(imat int, uplo blas.Uplo, trans blas.Transpose, n int, a []float64, lda int, b, work []float64, rnd *rand.Rand) (diag blas.Diag) { + checkMatrix(n, n, a, lda) + if len(b) != n { + panic("testlapack: bad length of b") + } + if len(work) < 3*n { + panic("testlapack: insufficient length of work") + } + if uplo != blas.Upper && uplo != blas.Lower { + panic("testlapack: bad uplo") + } + if trans != blas.Trans && trans != blas.NoTrans { + panic("testlapack: bad trans") + } + + if n == 0 { + return blas.NonUnit + } + + ulp := dlamchE * dlamchB + smlnum := dlamchS + bignum := (1 - ulp) / smlnum + + bi := blas64.Implementation() + + switch imat { + default: + // TODO(vladimir-ch): Implement the remaining cases. + panic("testlapack: invalid or unimplemented imat") + case 7: + // Identity matrix. The diagonal is set to NaN. + diag = blas.Unit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + a[i*lda+i] = math.NaN() + for j := i + 1; j < n; j++ { + a[i*lda+j] = 0 + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = 0 + } + a[i*lda+i] = math.NaN() + } + } + case 11: + // Generate a triangular matrix with elements between -1 and 1, + // give the diagonal norm 2 to make it well-conditioned, and + // make the right hand side large so that it requires scaling. + diag = blas.NonUnit + switch uplo { + case blas.Upper: + for i := 0; i < n-1; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + } + case blas.Lower: + for i := 1; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + } + } + for i := 0; i < n; i++ { + a[i*lda+i] = math.Copysign(2, a[i*lda+i]) + } + // Set the right hand side so that the largest value is bignum. + dlarnv(b, 2, rnd) + imax := bi.Idamax(n, b, 1) + bscal := bignum / math.Max(1, b[imax]) + bi.Dscal(n, bscal, b, 1) + case 12: + // Make the first diagonal element in the solve small to cause + // immediate overflow when dividing by T[j,j]. The off-diagonal + // elements are small (cnorm[j] < 1). + diag = blas.NonUnit + tscal := 1 / math.Max(1, float64(n-1)) + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + bi.Dscal(n-i-1, tscal, a[i*lda+i+1:], 1) + a[i*lda+i] = math.Copysign(1, a[i*lda+i]) + } + a[(n-1)*lda+n-1] *= smlnum + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + bi.Dscal(i, tscal, a[i*lda:], 1) + a[i*lda+i] = math.Copysign(1, a[i*lda+i]) + } + a[0] *= smlnum + } + dlarnv(b, 2, rnd) + case 13: + // Make the first diagonal element in the solve small to cause + // immediate overflow when dividing by T[j,j]. The off-diagonal + // elements are O(1) (cnorm[j] > 1). + diag = blas.NonUnit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + a[i*lda+i] = math.Copysign(1, a[i*lda+i]) + } + a[(n-1)*lda+n-1] *= smlnum + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + a[i*lda+i] = math.Copysign(1, a[i*lda+i]) + } + a[0] *= smlnum + } + dlarnv(b, 2, rnd) + case 14: + // T is diagonal with small numbers on the diagonal to + // make the growth factor underflow, but a small right hand side + // chosen so that the solution does not overflow. + diag = blas.NonUnit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + a[i*lda+j] = 0 + } + if (n-1-i)&0x2 == 0 { + a[i*lda+i] = smlnum + } else { + a[i*lda+i] = 1 + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + a[i*lda+j] = 0 + } + if i&0x2 == 0 { + a[i*lda+i] = smlnum + } else { + a[i*lda+i] = 1 + } + } + } + // Set the right hand side alternately zero and small. + switch uplo { + case blas.Upper: + b[0] = 0 + for i := n - 1; i > 0; i -= 2 { + b[i] = 0 + b[i-1] = smlnum + } + case blas.Lower: + for i := 0; i < n-1; i += 2 { + b[i] = 0 + b[i+1] = smlnum + } + b[n-1] = 0 + } + case 15: + // Make the diagonal elements small to cause gradual overflow + // when dividing by T[j,j]. To control the amount of scaling + // needed, the matrix is bidiagonal. + diag = blas.NonUnit + texp := 1 / math.Max(1, float64(n-1)) + tscal := math.Pow(smlnum, texp) + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + a[i*lda+i] = tscal + if i < n-1 { + a[i*lda+i+1] = -1 + } + for j := i + 2; j < n; j++ { + a[i*lda+j] = 0 + } + } + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j < i-1; j++ { + a[i*lda+j] = 0 + } + if i > 0 { + a[i*lda+i-1] = -1 + } + a[i*lda+i] = tscal + } + } + dlarnv(b, 2, rnd) + case 16: + // One zero diagonal element. + diag = blas.NonUnit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + a[i*lda+i] = math.Copysign(2, a[i*lda+i]) + } + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + a[i*lda+i] = math.Copysign(2, a[i*lda+i]) + } + } + iy := n / 2 + a[iy*lda+iy] = 0 + dlarnv(b, 2, rnd) + bi.Dscal(n, 2, b, 1) + case 17: + // Make the offdiagonal elements large to cause overflow when + // adding a column of T. In the non-transposed case, the matrix + // is constructed to cause overflow when adding a column in + // every other step. + diag = blas.NonUnit + tscal := (1 - ulp) / (dlamchS / ulp) + texp := 1.0 + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + a[i*lda+j] = 0 + } + } + for j := n - 1; j >= 1; j -= 2 { + a[j] = -tscal / float64(n+1) + a[j*lda+j] = 1 + b[j] = texp * (1 - ulp) + a[j-1] = -tscal / float64(n+1) / float64(n+2) + a[(j-1)*lda+j-1] = 1 + b[j-1] = texp * float64(n*n+n-1) + texp *= 2 + } + b[0] = float64(n+1) / float64(n+2) * tscal + case blas.Lower: + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + a[i*lda+j] = 0 + } + } + for j := 0; j < n-1; j += 2 { + a[(n-1)*lda+j] = -tscal / float64(n+1) + a[j*lda+j] = 1 + b[j] = texp * (1 - ulp) + a[(n-1)*lda+j+1] = -tscal / float64(n+1) / float64(n+2) + a[(j+1)*lda+j+1] = 1 + b[j+1] = texp * float64(n*n+n-1) + texp *= 2 + } + b[n-1] = float64(n+1) / float64(n+2) * tscal + } + case 18: + // Generate a unit triangular matrix with elements between -1 + // and 1, and make the right hand side large so that it requires + // scaling. The diagonal is set to NaN. + diag = blas.Unit + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + a[i*lda+i] = math.NaN() + dlarnv(a[i*lda+i+1:i*lda+n], 2, rnd) + } + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i], 2, rnd) + a[i*lda+i] = math.NaN() + } + } + // Set the right hand side so that the largest value is bignum. + dlarnv(b, 2, rnd) + iy := bi.Idamax(n, b, 1) + bnorm := math.Abs(b[iy]) + bscal := bignum / math.Max(1, bnorm) + bi.Dscal(n, bscal, b, 1) + case 19: + // Generate a triangular matrix with elements between + // bignum/(n-1) and bignum so that at least one of the column + // norms will exceed bignum. + // Dlatrs cannot handle this case for (typically) n>5. + diag = blas.NonUnit + tleft := bignum / math.Max(1, float64(n-1)) + tscal := bignum * (float64(n-1) / math.Max(1, float64(n))) + switch uplo { + case blas.Upper: + for i := 0; i < n; i++ { + dlarnv(a[i*lda+i:i*lda+n], 2, rnd) + for j := i; j < n; j++ { + aij := a[i*lda+j] + a[i*lda+j] = math.Copysign(tleft, aij) + tscal*aij + } + } + case blas.Lower: + for i := 0; i < n; i++ { + dlarnv(a[i*lda:i*lda+i+1], 2, rnd) + for j := 0; j <= i; j++ { + aij := a[i*lda+j] + a[i*lda+j] = math.Copysign(tleft, aij) + tscal*aij + } + } + } + dlarnv(b, 2, rnd) + bi.Dscal(n, 2, b, 1) + } + + // Flip the matrix if the transpose will be used. + if trans == blas.Trans { + switch uplo { + case blas.Upper: + for j := 0; j < n/2; j++ { + bi.Dswap(n-2*j-1, a[j*lda+j:], 1, a[(j+1)*lda+n-j-1:], -lda) + } + case blas.Lower: + for j := 0; j < n/2; j++ { + bi.Dswap(n-2*j-1, a[j*lda+j:], lda, a[(n-j-1)*lda+j+1:], -1) + } + } + } + + return diag +} + +func checkMatrix(m, n int, a []float64, lda int) { + if m < 0 { + panic("testlapack: m < 0") + } + if n < 0 { + panic("testlapack: n < 0") + } + if lda < max(1, n) { + panic("testlapack: lda < max(1, n)") + } + if len(a) < (m-1)*lda+n { + panic("testlapack: insufficient matrix slice length") + } +} diff --git a/lapack/testlapack/matgen_test.go b/lapack/testlapack/matgen_test.go new file mode 100644 index 00000000..1bb86d3c --- /dev/null +++ b/lapack/testlapack/matgen_test.go @@ -0,0 +1,90 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +func TestDlagsy(t *testing.T) { + const tol = 1e-14 + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{0, 1, 2, 3, 4, 5, 10, 50} { + for _, lda := range []int{0, 2*n + 1} { + if lda == 0 { + lda = max(1, n) + } + d := make([]float64, n) + for i := range d { + d[i] = 1 + } + a := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: nanSlice(n * lda), + } + work := make([]float64, a.Rows+a.Cols) + + Dlagsy(a.Rows, 0, d, a.Data, a.Stride, rnd, work) + + isIdentity := true + identityLoop: + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + aij := a.Data[i*a.Stride+j] + if math.IsNaN(aij) { + isIdentity = false + } + if i == j && math.Abs(aij-1) > tol { + isIdentity = false + } + if i != j && math.Abs(aij) > tol { + isIdentity = false + } + if !isIdentity { + break identityLoop + } + } + } + if !isIdentity { + t.Errorf("Case n=%v,lda=%v: unexpected result", n, lda) + } + } + } +} + +func TestDlagge(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{0, 1, 2, 3, 4, 5, 10, 50} { + for _, lda := range []int{0, 2*n + 1} { + if lda == 0 { + lda = max(1, n) + } + d := make([]float64, n) + for i := range d { + d[i] = 1 + } + a := blas64.General{ + Rows: n, + Cols: n, + Stride: lda, + Data: nanSlice(n * lda), + } + work := make([]float64, a.Rows+a.Cols) + + Dlagge(a.Rows, a.Cols, 0, 0, d, a.Data, a.Stride, rnd, work) + + if !isOrthonormal(a) { + t.Errorf("Case n=%v,lda=%v: unexpected result", n, lda) + } + } + } + +} diff --git a/lapack/testlapack/test_matrices.go b/lapack/testlapack/test_matrices.go new file mode 100644 index 00000000..6be490b2 --- /dev/null +++ b/lapack/testlapack/test_matrices.go @@ -0,0 +1,615 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package testlapack + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/blas/blas64" +) + +// A123 is the non-symmetric singular matrix +// [ 1 2 3 ] +// A = [ 4 5 6 ] +// [ 7 8 9 ] +// It has three distinct real eigenvalues. +type A123 struct{} + +func (A123) Matrix() blas64.General { + return blas64.General{ + Rows: 3, + Cols: 3, + Stride: 3, + Data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }, + } +} + +func (A123) Eigenvalues() []complex128 { + return []complex128{16.116843969807043, -1.116843969807043, 0} +} + +func (A123) LeftEV() blas64.General { + return blas64.General{ + Rows: 3, + Cols: 3, + Stride: 3, + Data: []float64{ + -0.464547273387671, -0.570795531228578, -0.677043789069485, + -0.882905959653586, -0.239520420054206, 0.403865119545174, + 0.408248290463862, -0.816496580927726, 0.408248290463863, + }, + } +} + +func (A123) RightEV() blas64.General { + return blas64.General{ + Rows: 3, + Cols: 3, + Stride: 3, + Data: []float64{ + -0.231970687246286, -0.785830238742067, 0.408248290463864, + -0.525322093301234, -0.086751339256628, -0.816496580927726, + -0.818673499356181, 0.612327560228810, 0.408248290463863, + }, + } +} + +// AntisymRandom is a anti-symmetric random matrix. All its eigenvalues are +// imaginary with one zero if the order is odd. +type AntisymRandom struct { + mat blas64.General +} + +func NewAntisymRandom(n int, rnd *rand.Rand) AntisymRandom { + a := zeros(n, n, n) + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + r := rnd.NormFloat64() + a.Data[i*a.Stride+j] = r + a.Data[j*a.Stride+i] = -r + } + } + return AntisymRandom{a} +} + +func (a AntisymRandom) Matrix() blas64.General { + return cloneGeneral(a.mat) +} + +func (AntisymRandom) Eigenvalues() []complex128 { + return nil +} + +// Circulant is a generally non-symmetric matrix given by +// A[i,j] = 1 + (j-i+n)%n. +// For example, for n=5, +// [ 1 2 3 4 5 ] +// [ 5 1 2 3 4 ] +// A = [ 4 5 1 2 3 ] +// [ 3 4 5 1 2 ] +// [ 2 3 4 5 1 ] +// It has real and complex eigenvalues, some possibly repeated. +type Circulant int + +func (c Circulant) Matrix() blas64.General { + n := int(c) + a := zeros(n, n, n) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a.Data[i*a.Stride+j] = float64(1 + (j-i+n)%n) + } + } + return a +} + +func (c Circulant) Eigenvalues() []complex128 { + n := int(c) + w := rootsOfUnity(n) + ev := make([]complex128, n) + for k := 0; k < n; k++ { + ev[k] = complex(float64(n), 0) + } + for i := n - 1; i > 0; i-- { + for k := 0; k < n; k++ { + ev[k] = ev[k]*w[k] + complex(float64(i), 0) + } + } + return ev +} + +// Clement is a generally non-symmetric matrix given by +// A[i,j] = i+1, if j == i+1, +// = n-i, if j == i-1, +// = 0, otherwise. +// For example, for n=5, +// [ . 1 . . . ] +// [ 4 . 2 . . ] +// A = [ . 3 . 3 . ] +// [ . . 2 . 4 ] +// [ . . . 1 . ] +// It has n distinct real eigenvalues. +type Clement int + +func (c Clement) Matrix() blas64.General { + n := int(c) + a := zeros(n, n, n) + for i := 0; i < n; i++ { + if i < n-1 { + a.Data[i*a.Stride+i+1] = float64(i + 1) + } + if i > 0 { + a.Data[i*a.Stride+i-1] = float64(n - i) + } + } + return a +} + +func (c Clement) Eigenvalues() []complex128 { + n := int(c) + ev := make([]complex128, n) + for i := range ev { + ev[i] = complex(float64(-n+2*i+1), 0) + } + return ev +} + +// Creation is a singular non-symmetric matrix given by +// A[i,j] = i, if j == i-1, +// = 0, otherwise. +// For example, for n=5, +// [ . . . . . ] +// [ 1 . . . . ] +// A = [ . 2 . . . ] +// [ . . 3 . . ] +// [ . . . 4 . ] +// Zero is its only eigenvalue. +type Creation int + +func (c Creation) Matrix() blas64.General { + n := int(c) + a := zeros(n, n, n) + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = float64(i) + } + return a +} + +func (c Creation) Eigenvalues() []complex128 { + return make([]complex128, int(c)) +} + +// Diagonal is a diagonal matrix given by +// A[i,j] = i+1, if i == j, +// = 0, otherwise. +// For example, for n=5, +// [ 1 . . . . ] +// [ . 2 . . . ] +// A = [ . . 3 . . ] +// [ . . . 4 . ] +// [ . . . . 5 ] +// It has n real eigenvalues {1,...,n}. +type Diagonal int + +func (d Diagonal) Matrix() blas64.General { + n := int(d) + a := zeros(n, n, n) + for i := 0; i < n; i++ { + a.Data[i*a.Stride+i] = float64(i) + } + return a +} + +func (d Diagonal) Eigenvalues() []complex128 { + n := int(d) + ev := make([]complex128, n) + for i := range ev { + ev[i] = complex(float64(i), 0) + } + return ev +} + +// Downshift is a non-singular upper Hessenberg matrix given by +// A[i,j] = 1, if (i-j+n)%n == 1, +// = 0, otherwise. +// For example, for n=5, +// [ . . . . 1 ] +// [ 1 . . . . ] +// A = [ . 1 . . . ] +// [ . . 1 . . ] +// [ . . . 1 . ] +// Its eigenvalues are the complex roots of unity. +type Downshift int + +func (d Downshift) Matrix() blas64.General { + n := int(d) + a := zeros(n, n, n) + a.Data[n-1] = 1 + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = 1 + } + return a +} + +func (d Downshift) Eigenvalues() []complex128 { + return rootsOfUnity(int(d)) +} + +// Fibonacci is an upper Hessenberg matrix with 3 distinct real eigenvalues. For +// example, for n=5, +// [ . 1 . . . ] +// [ 1 1 . . . ] +// A = [ . 1 1 . . ] +// [ . . 1 1 . ] +// [ . . . 1 1 ] +type Fibonacci int + +func (f Fibonacci) Matrix() blas64.General { + n := int(f) + a := zeros(n, n, n) + if n > 1 { + a.Data[1] = 1 + } + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = 1 + a.Data[i*a.Stride+i] = 1 + } + return a +} + +func (f Fibonacci) Eigenvalues() []complex128 { + n := int(f) + ev := make([]complex128, n) + if n == 0 || n == 1 { + return ev + } + phi := 0.5 * (1 + math.Sqrt(5)) + ev[0] = complex(phi, 0) + for i := 1; i < n-1; i++ { + ev[i] = 1 + 0i + } + ev[n-1] = complex(1-phi, 0) + return ev +} + +// Gear is a singular non-symmetric matrix with real eigenvalues. For example, +// for n=5, +// [ . 1 . . 1 ] +// [ 1 . 1 . . ] +// A = [ . 1 . 1 . ] +// [ . . 1 . 1 ] +// [-1 . . 1 . ] +type Gear int + +func (g Gear) Matrix() blas64.General { + n := int(g) + a := zeros(n, n, n) + if n == 1 { + return a + } + for i := 0; i < n-1; i++ { + a.Data[i*a.Stride+i+1] = 1 + } + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = 1 + } + a.Data[n-1] = 1 + a.Data[(n-1)*a.Stride] = -1 + return a +} + +func (g Gear) Eigenvalues() []complex128 { + n := int(g) + ev := make([]complex128, n) + if n == 0 || n == 1 { + return ev + } + if n == 2 { + ev[0] = complex(0, 1) + ev[1] = complex(0, -1) + return ev + } + w := 0 + ev[w] = math.Pi / 2 + w++ + phi := (n - 1) / 2 + for p := 1; p <= phi; p++ { + ev[w] = complex(float64(2*p)*math.Pi/float64(n), 0) + w++ + } + phi = n / 2 + for p := 1; p <= phi; p++ { + ev[w] = complex(float64(2*p-1)*math.Pi/float64(n), 0) + w++ + } + for i, v := range ev { + ev[i] = complex(2*math.Cos(real(v)), 0) + } + return ev +} + +// Grcar is an upper Hessenberg matrix given by +// A[i,j] = -1 if i == j+1, +// = 1 if i <= j and j <= i+k, +// = 0 otherwise. +// For example, for n=5 and k=2, +// [ 1 1 1 . . ] +// [ -1 1 1 1 . ] +// A = [ . -1 1 1 1 ] +// [ . . -1 1 1 ] +// [ . . . -1 1 ] +// The matrix has sensitive eigenvalues but they are not given explicitly. +type Grcar struct { + N int + K int +} + +func (g Grcar) Matrix() blas64.General { + n := g.N + a := zeros(n, n, n) + for k := 0; k <= g.K; k++ { + for i := 0; i < n-k; i++ { + a.Data[i*a.Stride+i+k] = 1 + } + } + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = -1 + } + return a +} + +func (Grcar) Eigenvalues() []complex128 { + return nil +} + +// Hanowa is a non-symmetric non-singular matrix of even order given by +// A[i,j] = alpha if i == j, +// = -i-1 if i < n/2 and j == i + n/2, +// = i+1-n/2 if i >= n/2 and j == i - n/2, +// = 0 otherwise. +// The matrix has complex eigenvalues. +type Hanowa struct { + N int // Order of the matrix, must be even. + Alpha float64 +} + +func (h Hanowa) Matrix() blas64.General { + if h.N&0x1 != 0 { + panic("lapack: matrix order must be even") + } + n := h.N + a := zeros(n, n, n) + for i := 0; i < n; i++ { + a.Data[i*a.Stride+i] = h.Alpha + } + for i := 0; i < n/2; i++ { + a.Data[i*a.Stride+i+n/2] = float64(-i - 1) + } + for i := n / 2; i < n; i++ { + a.Data[i*a.Stride+i-n/2] = float64(i + 1 - n/2) + } + return a +} + +func (h Hanowa) Eigenvalues() []complex128 { + if h.N&0x1 != 0 { + panic("lapack: matrix order must be even") + } + n := int(h.N) + ev := make([]complex128, n) + for i := 0; i < n/2; i++ { + ev[2*i] = complex(h.Alpha, float64(-i-1)) + ev[2*i+1] = complex(h.Alpha, float64(i+1)) + } + return ev +} + +// Lesp is a tridiagonal, generally non-symmetric matrix given by +// A[i,j] = -2*i-5 if i == j, +// = 1/(i+1) if i == j-1, +// = j+1 if i == j+1. +// For example, for n=5, +// [ -5 2 . . . ] +// [ 1/2 -7 3 . . ] +// A = [ . 1/3 -9 4 . ] +// [ . . 1/4 -11 5 ] +// [ . . . 1/5 -13 ]. +// The matrix has sensitive eigenvalues but they are not given explicitly. +type Lesp int + +func (l Lesp) Matrix() blas64.General { + n := int(l) + a := zeros(n, n, n) + for i := 0; i < n; i++ { + a.Data[i*a.Stride+i] = float64(-2*i - 5) + } + for i := 0; i < n-1; i++ { + a.Data[i*a.Stride+i+1] = float64(i + 2) + } + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = 1 / float64(i+1) + } + return a +} + +func (Lesp) Eigenvalues() []complex128 { + return nil +} + +// Rutis is the 4×4 non-symmetric matrix +// [ 4 -5 0 3 ] +// A = [ 0 4 -3 -5 ] +// [ 5 -3 4 0 ] +// [ 3 0 5 4 ] +// It has two distinct real eigenvalues and a pair of complex eigenvalues. +type Rutis struct{} + +func (Rutis) Matrix() blas64.General { + return blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 4, -5, 0, 3, + 0, 4, -3, -5, + 5, -3, 4, 0, + 3, 0, 5, 4, + }, + } +} + +func (Rutis) Eigenvalues() []complex128 { + return []complex128{12, 1 + 5i, 1 - 5i, 2} +} + +// Tris is a tridiagonal matrix given by +// A[i,j] = x if i == j-1, +// = y if i == j, +// = z if i == j+1. +// If x*z is negative, the matrix has complex eigenvalues. +type Tris struct { + N int + X, Y, Z float64 +} + +func (t Tris) Matrix() blas64.General { + n := t.N + a := zeros(n, n, n) + for i := 1; i < n; i++ { + a.Data[i*a.Stride+i-1] = t.X + } + for i := 0; i < n; i++ { + a.Data[i*a.Stride+i] = t.Y + } + for i := 0; i < n-1; i++ { + a.Data[i*a.Stride+i+1] = t.Z + } + return a +} + +func (t Tris) Eigenvalues() []complex128 { + n := int(t.N) + ev := make([]complex128, n) + for i := range ev { + angle := float64(i+1) * math.Pi / float64(n+1) + arg := t.X * t.Z + if arg >= 0 { + ev[i] = complex(t.Y+2*math.Sqrt(arg)*math.Cos(angle), 0) + } else { + ev[i] = complex(t.Y, 2*math.Sqrt(-arg)*math.Cos(angle)) + } + } + return ev +} + +// Wilk4 is a 4×4 lower triangular matrix with 4 distinct real eigenvalues. +type Wilk4 struct{} + +func (Wilk4) Matrix() blas64.General { + return blas64.General{ + Rows: 4, + Cols: 4, + Stride: 4, + Data: []float64{ + 0.9143e-4, 0.0, 0.0, 0.0, + 0.8762, 0.7156e-4, 0.0, 0.0, + 0.7943, 0.8143, 0.9504e-4, 0.0, + 0.8017, 0.6123, 0.7165, 0.7123e-4, + }, + } +} + +func (Wilk4) Eigenvalues() []complex128 { + return []complex128{ + 0.9504e-4, 0.9143e-4, 0.7156e-4, 0.7123e-4, + } +} + +// Wilk12 is a 12×12 lower Hessenberg matrix with 12 distinct real eigenvalues. +type Wilk12 struct{} + +func (Wilk12) Matrix() blas64.General { + return blas64.General{ + Rows: 12, + Cols: 12, + Stride: 12, + Data: []float64{ + 12, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 11, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 10, 10, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 9, 9, 9, 8, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 7, 0, 0, 0, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 6, 0, 0, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 6, 5, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 4, 0, 0, 0, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + }, + } +} + +func (Wilk12) Eigenvalues() []complex128 { + return []complex128{ + 32.2288915015722210, + 20.1989886458770691, + 12.3110774008685340, + 6.9615330855671154, + 3.5118559485807528, + 1.5539887091319704, + 0.6435053190136506, + 0.2847497205488856, + 0.1436465181918488, + 0.0812276683076552, + 0.0495074140194613, + 0.0310280683208907, + } +} + +// Wilk20 is a 20×20 lower Hessenberg matrix. If the parameter is 0, the matrix +// has 20 distinct real eigenvalues. If the parameter is 1e-10, the matrix has 6 +// real eigenvalues and 7 pairs of complex eigenvalues. +type Wilk20 float64 + +func (w Wilk20) Matrix() blas64.General { + a := zeros(20, 20, 20) + for i := 0; i < 20; i++ { + a.Data[i*a.Stride+i] = float64(i + 1) + } + for i := 0; i < 19; i++ { + a.Data[i*a.Stride+i+1] = 20 + } + a.Data[19*a.Stride] = float64(w) + return a +} + +func (w Wilk20) Eigenvalues() []complex128 { + if float64(w) == 0 { + ev := make([]complex128, 20) + for i := range ev { + ev[i] = complex(float64(i+1), 0) + } + return ev + } + return nil +} + +// Zero is a matrix with all elements equal to zero. +type Zero int + +func (z Zero) Matrix() blas64.General { + n := int(z) + return zeros(n, n, n) +} + +func (z Zero) Eigenvalues() []complex128 { + n := int(z) + return make([]complex128, n) +} diff --git a/lapack/testlapack/testdata/dlahr2data.json.gz b/lapack/testlapack/testdata/dlahr2data.json.gz new file mode 100644 index 00000000..7652126a Binary files /dev/null and b/lapack/testlapack/testdata/dlahr2data.json.gz differ diff --git a/lapack/testlapack/testdata/dlaqr5data.json.gz b/lapack/testlapack/testdata/dlaqr5data.json.gz new file mode 100644 index 00000000..9e629480 Binary files /dev/null and b/lapack/testlapack/testdata/dlaqr5data.json.gz differ diff --git a/license/AUTHORS b/license/AUTHORS new file mode 100644 index 00000000..58181afe --- /dev/null +++ b/license/AUTHORS @@ -0,0 +1,45 @@ +# This is the official list of gonum authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. + +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# Please keep the list sorted. + +Brendan Tracey +Chih-Wei Chang +Chris Tessum +Dan Kortschak +David Samborski +Ethan Burns +Evert Lammerts +Facundo Gaich +Fazlul Shahriar +Iakov Davydov +Jalem Raj Rohit +James Bell +Jeff Juozapaitis +Jonathan J Lawlor +Jonathan Schroeder +Joseph Watson +Julien Roland +Kent English +Konstantin Shaposhnikov +Lyron Winderbaum +Matthieu Di Mercurio +Or Rikon +Pontus Melke +Renée French +Robin Eklind +Scott Holden +Sebastien Binet +Shawn Smith +Steve McCoy +The University of Adelaide +The University of Minnesota +The University of Washington +Tobin Harding +Vladimír Chalupecký +Yevgeniy Vahlis diff --git a/license/CONTRIBUTING.md b/license/CONTRIBUTING.md new file mode 100644 index 00000000..ab21f7cf --- /dev/null +++ b/license/CONTRIBUTING.md @@ -0,0 +1,132 @@ +# [](https://github.com/gonum) Contribution Guidelines +#### Introduction + +The Gonum project provides general purpose numerical computing and data science libraries for the Go programming language, and we would like you to join us in improving Gonum's quality and scope. +This document is for anyone who is contributing or interested in contributing. +Questions about Gonum or the use of its libraries can be directed to [gonum-dev](https://groups.google.com/forum/#!forum/gonum-dev). + +#### Table of Contents + +[Project Scope](#project-scope) + +[The Gonum Repositories](#the-gonum-repositories) + +[Contributing](#Contributing) + * [Working Together](#working-together) + * [Reporting Bugs](#reporting-bugs) + * [Suggesting Enhancements](#suggesting-enhancements) + * [Your First Code Contribution](#your-first-code-contribution) + * [Code Contribution](#code-contribution) + * [Code Review](#code-review) + * [What Can I Do to Help?](#what-can-i-do-to-help) + * [Style](#style) + +## Project Scope + +The purpose of the Gonum project is to provide general purpose numerical computing and data science libraries for the Go programming language. +The libraries should aim to provide building blocks for disciplinary work and advanced algorithms. +Code should be implemented in pure Go. +Calls to C, Fortran, or other languages may be justified with performance considerations, but should be opt-in for users. +Calls to assembly should be opt-out, if included. +Code should favor readability and explicitness over cleverness. +This makes code easy to review and verify, not only at submission, but also for users who want to understand how the algorithms work. +Where possible, the source of algorithms should be referenced in the comments. + +## The Gonum Repositories + +Here are the current repositories for the gonum project. +If code you want to contribute doesn't quite fit in any of them, then please start a discussion on the [mailing list](https://groups.google.com/forum/#!forum/gonum-dev). +Code can be found at [github.com/gonum/](https://github.com/gonum/)\, and documentation at godoc.org/github.com/gonum/\. + +* [matrix](https://github.com/gonum/matrix) — Implements data containers for matrix types (Dense, Symmetric), and higher-level operations using them (SVD, Linear solve) +* [plot](https://github.com/gonum/plot) — A repository for plotting and visualizing data +* [stat](https://github.com/gonum/stat) — Contains statistics routines for linear and multi-dimensional data, univariate and multivariate sampling distributions, and advanced sampling routines +* [blas](https://github.com/gonum/blas) — Native Go BLAS implementation for float64 and float32, and c-wrapper for external libraries +* [lapack](https://github.com/gonum/lapack) — Native Go implementation of many LAPACK routines and c-wrapper for LAPACKE +* [floats](https://github.com/gonum/floats) — Operations on slices of floats +* [integrate](https://github.com/gonum/integrate) — Routines for numeric evaluation of integrals (quadrature) +* [diff](https://github.com/gonum/diff) — Routines for computing derivatives +* [graph](https://github.com/gonum/graph) — Implements types and interfaces for graphs (networks), and implements higher-level routines (A-star, Kruskal) +* [optimize](https://github.com/gonum/optimize) — Package for searching for the optimal value of functions +* [unit](https://github.com/gonum/unit) — Package for converting between scientific units +* [mathext](https://github.com/gonum/mathext) — Implements basic elementary functions not included in the Go standard library +* [internal](https://github.com/gonum/internal) — Internal routines for the gonum project +* [license](https://github.com/gonum/license) — Master license, author, contributor etc information +* [talks](https://github.com/gonum/talks) — Talks given about Go and Gonum delivered by Gonum developers +* [gonum.github.io](https://github.com/gonum/gonum.github.io) — Gonum website + +## Contributing + +### Working Together + +When contributing or otherwise participating, please: + +- Be friendly and welcoming +- Be patient +- Be thoughtful +- Be respectful +- Be charitable +- Avoid destructive behavior + +Excerpted from the [Go conduct document](https://golang.org/conduct). + +### Reporting Bugs + +When you encounter a bug, please open an issue on the corresponding repository. +Start the issue title with the repository/sub-repository name, like `stat/distmv: issue name`. +Be specific about the environment you encountered the bug in. +If you are able to write a test that reproduces the bug, please include it in the issue. +As a rule we keep all tests OK. + +### Suggesting Enhancements + +If the scope of the enhancement is small, open an issue. +If it is large, such as suggesting a new repository, sub-repository, or interface refactoring, then please start a discussion on [the gonum-dev list](https://groups.google.com/forum/#!forum/gonum-dev). + +### Your First Code Contribution + +If you are a new contributor, thank you! Before your first merge, you will need to be added to the [CONTRIBUTORS](https://github.com/gonum/license/blob/master/CONTRIBUTORS) and [AUTHORS](https://github.com/gonum/license/blob/master/AUTHORS) file. +Open a pull request adding yourself to them. +All Gonum code follows the BSD license in the [license document](https://github.com/gonum/license/blob/master/LICENSE). +We prefer that code contributions do not come with additional licensing. +For exceptions, added code must also follow a BSD license. + +### Code Contribution + +If it is possible to split a large pull request into two or more smaller pull requests, please try to do so. +Pull requests should include tests for any new code before merging. +It is ok to start a pull request on partially implemented code to get feedback, and see if your approach to a problem is sound. +You don't need to have tests, or even have code that compiles to open a pull request, although both will be needed before merge. +When tests use magic numbers, please include a comment explaining the source of the number. +Benchmarks are optional for new features, but if you are submitting a pull request justified by performance improvement, you will need benchmarks to measure the impact of your change, and the pull request should include a report from [benchcmp](https://godoc.org/golang.org/x/tools/cmd/benchcmp) or, preferably, [benchstat](https://github.com/rsc/benchstat). + +### Code Review + +If you are a contributor, please be welcoming to new contributors. [Here](http://sarah.thesharps.us/2014/09/01/the-gentle-art-of-patch-review/) is a good guide. + +There are several terms code reviews may use that you should become familiar with. + + * ` LGTM ` — looks good to me + * ` SGTM ` — sounds good to me + * ` s/foo/bar/ ` — please replace ` foo ` with ` bar `; this is [sed syntax](http://en.wikipedia.org/wiki/Sed#Usage) + * ` s/foo/bar/g ` — please replace ` foo ` with ` bar ` throughout your entire change + +We follow the convention of requiring at least 1 reviewer to say LGTM before a merge. +When code is tricky or controversial, submitters and reviewers can request additional review from others and more LGTMs before merge. +You can ask for more review by saying PTAL in a comment in a pull request. +You can follow a PTAL with one or more @someone to get the attention of particular people. +If you don't know who to ask, and aren't getting enough review after saying PTAL, then PTAL @gonum/developers will get more attention. +Also note that you do not have to be the pull request submitter to request additional review. + +### What Can I Do to Help? + +If you are looking for some way to help the Gonum project, there are good places to start, depending on what you are comfortable with. +You can [search](https://github.com/issues?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+user%3Agonum) for open issues in need of resolution. +You can improve documentation, or improve examples. +You can add and improve tests. +You can improve performance, either by improving accuracy, speed, or both. +You can suggest and implement new features that you think belong in Gonum. + +### Style + +We use [Go style](https://github.com/golang/go/wiki/CodeReviewComments). diff --git a/license/CONTRIBUTORS b/license/CONTRIBUTORS new file mode 100644 index 00000000..64843546 --- /dev/null +++ b/license/CONTRIBUTORS @@ -0,0 +1,49 @@ +# This is the official list of people who can contribute +# (and typically have contributed) code to the gonum +# repository. +# +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees would be listed here +# but not in AUTHORS, because Google would hold the copyright. +# +# When adding J Random Contributor's name to this file, +# either J's name or J's organization's name should be +# added to the AUTHORS file. +# +# Names should be added to this file like so: +# Name +# +# Please keep the list sorted. + +Brendan Tracey +Chih-Wei Chang +Chris Tessum +Dan Kortschak +David Samborski +Ethan Burns +Evert Lammerts +Facundo Gaich +Fazlul Shahriar +Iakov Davydov +Jalem Raj Rohit +James Bell +Jeff Juozapaitis +Jonathan J Lawlor +Jonathan Schroeder +Joseph Watson +Julien Roland +Kent English +Konstantin Shaposhnikov +Lyron Winderbaum +Matthieu Di Mercurio +Or Rikon +Pontus Melke +Renée French +Robin Eklind +Scott Holden +Sebastien Binet +Shawn Smith +Steve McCoy +Tobin Harding +Vladimír Chalupecký +Yevgeniy Vahlis diff --git a/license/GOPHER b/license/GOPHER new file mode 100644 index 00000000..fda97996 --- /dev/null +++ b/license/GOPHER @@ -0,0 +1 @@ +The Go gopher was designed by Renee French and is licensed under the Creative Commons Attributions 3.0. diff --git a/license/LICENSE b/license/LICENSE new file mode 100644 index 00000000..76edf5ef --- /dev/null +++ b/license/LICENSE @@ -0,0 +1,23 @@ +Copyright ©2013 The gonum Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the gonum project nor the names of its authors and + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/license/gopher.png b/license/gopher.png new file mode 100644 index 00000000..1f76e7f2 Binary files /dev/null and b/license/gopher.png differ diff --git a/mathext/README.md b/mathext/README.md new file mode 100644 index 00000000..06d7055b --- /dev/null +++ b/mathext/README.md @@ -0,0 +1,2 @@ +# mathext [![Build Status](https://travis-ci.org/gonum/mathext.svg?branch=master)](https://travis-ci.org/gonum/mathext) [![Coverage Status](https://coveralls.io/repos/github/gonum/mathext/badge.svg?branch=master)](https://coveralls.io/github/gonum/mathext?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/mathext?status.svg)](https://godoc.org/github.com/gonum/mathext) +mathext implements basic elementary functions not included in the Go standard library diff --git a/mathext/airy.go b/mathext/airy.go new file mode 100644 index 00000000..1022e938 --- /dev/null +++ b/mathext/airy.go @@ -0,0 +1,37 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import "gonum.org/v1/gonum/mathext/internal/amos" + +// AiryAi returns the value of the Airy function at z. The Airy function here, +// Ai(z), is one of the two linearly independent solutions to +// y'' - y*z = 0. +// See http://mathworld.wolfram.com/AiryFunctions.html for more detailed information. +func AiryAi(z complex128) complex128 { + // id specifies the order of the derivative to compute, + // 0 for the function itself and 1 for the derivative. + // kode specifies the scaling option. See the function + // documentation for the exact behavior. + id := 0 + kode := 1 + air, aii, _ := amos.Zairy(real(z), imag(z), id, kode) + return complex(air, aii) +} + +// AiryAiDeriv returns the value of the derivative of the Airy function at z. The +// Airy function here, Ai(z), is one of the two linearly independent solutions to +// y'' - y*z = 0. +// See http://mathworld.wolfram.com/AiryFunctions.html for more detailed information. +func AiryAiDeriv(z complex128) complex128 { + // id specifies the order of the derivative to compute, + // 0 for the function itself and 1 for the derivative. + // kode specifies the scaling option. See the function + // documentation for the exact behavior. + id := 1 + kode := 1 + air, aii, _ := amos.Zairy(real(z), imag(z), id, kode) + return complex(air, aii) +} diff --git a/mathext/airy_test.go b/mathext/airy_test.go new file mode 100644 index 00000000..4359abd5 --- /dev/null +++ b/mathext/airy_test.go @@ -0,0 +1,28 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "math" + "testing" +) + +func TestAiry(t *testing.T) { + for _, test := range []struct { + z, ans complex128 + }{ + // Results computed using Octave. + {5, 1.08344428136074e-04}, + {5i, 29.9014823980070 + 21.6778315987835i}, + } { + ans := AiryAi(test.z) + if math.Abs(real(ans)-real(test.ans)) > 1e-10 { + t.Errorf("Real part mismatch. Got %v, want %v", real(ans), real(test.ans)) + } + if math.Abs(imag(ans)-imag(test.ans)) > 1e-10 { + t.Errorf("Imaginary part mismatch. Got %v, want %v", imag(ans), imag(test.ans)) + } + } +} diff --git a/mathext/beta.go b/mathext/beta.go new file mode 100644 index 00000000..03f53f09 --- /dev/null +++ b/mathext/beta.go @@ -0,0 +1,34 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import "gonum.org/v1/gonum/mathext/internal/gonum" + +// Beta returns the value of the complete beta function B(a, b). It is defined as +// Γ(a)Γ(b) / Γ(a+b) +// Special cases are: +// B(a,b) returns NaN if a or b is Inf +// B(a,b) returns NaN if a and b are 0 +// B(a,b) returns NaN if a or b is NaN +// B(a,b) returns NaN if a or b is < 0 +// B(a,b) returns +Inf if a xor b is 0. +// +// See http://mathworld.wolfram.com/BetaFunction.html for more detailed informations. +func Beta(a, b float64) float64 { + return gonum.Beta(a, b) +} + +// Lbeta returns the natural logarithm of the complete beta function B(a,b). +// Lbeta is defined as: +// Ln(Γ(a)Γ(b)/Γ(a+b)) +// Special cases are: +// Lbeta(a,b) returns NaN if a or b is Inf +// Lbeta(a,b) returns NaN if a and b are 0 +// Lbeta(a,b) returns NaN if a or b is NaN +// Lbeta(a,b) returns NaN if a or b is < 0 +// Lbeta(a,b) returns +Inf if a xor b is 0. +func Lbeta(a, b float64) float64 { + return gonum.Lbeta(a, b) +} diff --git a/mathext/beta_test.go b/mathext/beta_test.go new file mode 100644 index 00000000..7e0cd4c8 --- /dev/null +++ b/mathext/beta_test.go @@ -0,0 +1,177 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext_test + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mathext" +) + +var betaTests = []struct { + p, q float64 + want float64 +}{ + { + p: 1, + q: 2, + want: 0.5, // obtained from scipy.special.beta(1,2) (version=0.18.0) + }, + { + p: 10, + q: 20, + want: 4.9925087406346778e-09, // obtained from scipy.special.beta(10,20) (version=0.18.0) + }, + { + p: +0, + q: 10, + want: math.Inf(+1), + }, + { + p: -0, + q: 10, + want: math.Inf(+1), + }, + { + p: 0, + q: 0, + want: math.NaN(), + }, + { + p: 0, + q: math.Inf(-1), + want: math.NaN(), + }, + { + p: 10, + q: math.Inf(-1), + want: math.NaN(), + }, + { + p: 0, + q: math.Inf(+1), + want: math.NaN(), + }, + { + p: 10, + q: math.Inf(+1), + want: math.NaN(), + }, + { + p: math.NaN(), + q: 10, + want: math.NaN(), + }, + { + p: math.NaN(), + q: 0, + want: math.NaN(), + }, + { + p: -1, + q: 0, + want: math.NaN(), + }, + { + p: -1, + q: +1, + want: math.NaN(), + }, +} + +func TestBeta(t *testing.T) { + for i, test := range betaTests { + v := mathext.Beta(test.p, test.q) + testOK := func(x float64) bool { + return floats.EqualWithinAbsOrRel(x, test.want, 1e-15, 1e-15) || (math.IsNaN(test.want) && math.IsNaN(x)) + } + if !testOK(v) { + t.Errorf("test #%d: Beta(%v, %v)=%v. want=%v\n", + i, test.p, test.q, v, test.want, + ) + } + + u := mathext.Beta(test.q, test.p) + if !testOK(u) { + t.Errorf("test #%[1]d: Beta(%[2]v, %[3]v)=%[4]v != Beta(%[3]v, %[2]v)=%[5]v)\n", + i, test.p, test.q, v, u, + ) + } + + if math.IsInf(v, +1) || math.IsNaN(v) { + continue + } + + vv := mathext.Beta(test.p, test.q+1) + uu := mathext.Beta(test.p+1, test.q) + if !floats.EqualWithinAbsOrRel(v, vv+uu, 1e-15, 1e-15) { + t.Errorf( + "test #%[1]d: Beta(%[2]v, %[3]v)=%[4]v != Beta(%[2]v+1, %[3]v) + Beta(%[2]v, %[3]v+1) (=%[5]v + %[6]v = %[7]v)\n", + i, test.p, test.q, v, uu, vv, uu+vv, + ) + } + + vbeta2 := beta2(test.p, test.q) + if !floats.EqualWithinAbsOrRel(v, vbeta2, 1e-15, 1e-15) { + t.Errorf( + "test #%[1]d: Beta(%[2]v, %[3]v) != Γ(p)Γ(q) / Γ(p+q) (v=%[4]v u=%[5]v)\n", + i, test.p, test.q, v, vbeta2, + ) + } + } +} + +func beta2(x, y float64) float64 { + return math.Gamma(x) * math.Gamma(y) / math.Gamma(x+y) +} + +func BenchmarkBeta(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = mathext.Beta(10, 20) + } +} + +func BenchmarkBeta2(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = math.Gamma(10) * math.Gamma(20) / math.Gamma(10+20) + } +} + +func TestLbeta(t *testing.T) { + for i, test := range betaTests { + want := math.Log(test.want) + v := mathext.Lbeta(test.p, test.q) + + testOK := func(x float64) bool { + return floats.EqualWithinAbsOrRel(x, want, 1e-15, 1e-15) || (math.IsNaN(want) && math.IsNaN(x)) + } + if !testOK(v) { + t.Errorf("test #%d: Lbeta(%v, %v)=%v. want=%v\n", + i, test.p, test.q, v, want, + ) + } + + u := mathext.Lbeta(test.q, test.p) + if !testOK(u) { + t.Errorf("test #%[1]d: Lbeta(%[2]v, %[3]v)=%[4]v != Lbeta(%[3]v, %[2]v)=%[5]v)\n", + i, test.p, test.q, v, u, + ) + } + + if math.IsInf(v, +1) || math.IsNaN(v) { + continue + } + + vbeta2 := math.Log(beta2(test.p, test.q)) + if !floats.EqualWithinAbsOrRel(v, vbeta2, 1e-15, 1e-15) { + t.Errorf( + "test #%[1]d: Lbeta(%[2]v, %[3]v) != Log(Γ(p)Γ(q) / Γ(p+q)) (v=%[4]v u=%[5]v)\n", + i, test.p, test.q, v, vbeta2, + ) + } + } +} diff --git a/mathext/betainc.go b/mathext/betainc.go new file mode 100644 index 00000000..77791ce9 --- /dev/null +++ b/mathext/betainc.go @@ -0,0 +1,29 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import "gonum.org/v1/gonum/mathext/internal/cephes" + +// RegIncBeta returns the value of the regularized incomplete beta function +// I(x;a,b). It is defined as +// I(x;a,b) = B(x;a,b) / B(a,b) +// = Γ(a+b) / (Γ(a)*Γ(b)) * int_0^x u^(a-1) * (1-u)^(b-1) du. +// The domain of definition is 0 <= x <= 1, and the parameters a and b must be positive. +// For other values of x, a, and b RegIncBeta will panic. +func RegIncBeta(a, b float64, x float64) float64 { + return cephes.Incbet(a, b, x) +} + +// InvRegIncBeta computes the inverse of the regularized incomplete beta function. +// It returns the x for which +// y = I(x;a,b) +// The domain of definition is 0 <= y <= 1, and the parameters a and b must be +// positive. For other values of x, a, and b InvRegIncBeta will panic. +func InvRegIncBeta(a, b float64, y float64) float64 { + if y < 0 || y > 1 { + panic("mathext: parameter out of range") + } + return cephes.Incbi(a, b, y) +} diff --git a/mathext/betainc_test.go b/mathext/betainc_test.go new file mode 100644 index 00000000..f1e0c950 --- /dev/null +++ b/mathext/betainc_test.go @@ -0,0 +1,75 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestIncBeta(t *testing.T) { + tol := 1e-14 + tol2 := 1e-10 + // Test against values from scipy + for i, test := range []struct { + a, b, x, ans float64 + }{ + {1, 1, 0.8, 0.8}, + {1, 5, 0.8, 0.99968000000000001}, + {10, 10, 0.8, 0.99842087945083291}, + {10, 10, 0.1, 3.929882327128003e-06}, + {10, 2, 0.4, 0.00073400320000000028}, + {0.1, 0.2, 0.6, 0.69285678232066683}, + {1, 10, 0.7489, 0.99999900352334858}, + } { + y := RegIncBeta(test.a, test.b, test.x) + if !floats.EqualWithinAbsOrRel(y, test.ans, tol, tol) { + t.Errorf("Incomplete beta mismatch. Case %v: Got %v, want %v", i, y, test.ans) + } + + yc := 1 - RegIncBeta(test.b, test.a, 1-test.x) + if !floats.EqualWithinAbsOrRel(y, yc, tol, tol) { + t.Errorf("Incomplete beta complementary mismatch. Case %v: Got %v, want %v", i, y, yc) + } + + x := InvRegIncBeta(test.a, test.b, y) + if !floats.EqualWithinAbsOrRel(x, test.x, tol2, tol2) { + t.Errorf("Inverse incomplete beta mismatch. Case %v: Got %v, want %v", i, x, test.x) + } + } + + // Confirm that Invincbeta and Incbeta agree. Sweep over a variety of + // a, b, and y values. + tol = 1e-6 + steps := 201 + ints := make([]float64, steps) + floats.Span(ints, 0, 1) + + sz := 51 + min := 1e-2 + max := 1e2 + as := make([]float64, sz) + floats.LogSpan(as, min, max) + bs := make([]float64, sz) + floats.LogSpan(bs, min, max) + + for _, a := range as { + for _, b := range bs { + for _, yr := range ints { + x := InvRegIncBeta(a, b, yr) + if x > 1-1e-6 { + // Numerical error too large + continue + } + y := RegIncBeta(a, b, x) + if !floats.EqualWithinAbsOrRel(yr, y, tol, tol) { + t.Errorf("Mismatch between inv inc beta and inc beta. a = %v, b = %v, x = %v, got %v, want %v.", a, b, x, y, yr) + break + } + } + } + } +} diff --git a/mathext/digamma.go b/mathext/digamma.go new file mode 100644 index 00000000..81132dd1 --- /dev/null +++ b/mathext/digamma.go @@ -0,0 +1,28 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "math" +) + +// Digamma returns the logorithmic derivative of the gamma function at x. +// ψ(x) = d/dx (Ln (Γ(x)). +// Note that if x is a negative integer in [-7, 0] this function will return +// negative Inf. +func Digamma(x float64) float64 { + // This is adapted from + // http://web.science.mq.edu.au/~mjohnson/code/digamma.c + var result float64 + for ; x < 7.0; x++ { + result -= 1 / x + } + x -= 1.0 / 2.0 + xx := 1.0 / x + xx2 := xx * xx + xx4 := xx2 * xx2 + result += math.Log(x) + (1./24.)*xx2 - (7.0/960.0)*xx4 + (31.0/8064.0)*xx4*xx2 - (127.0/30720.0)*xx4*xx4 + return result +} diff --git a/mathext/digamma_test.go b/mathext/digamma_test.go new file mode 100644 index 00000000..0e113ed1 --- /dev/null +++ b/mathext/digamma_test.go @@ -0,0 +1,27 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "math" + "testing" +) + +func TestDigamma(t *testing.T) { + for i, test := range []struct { + x, want float64 + }{ + // Results computed using WolframAlpha. + {-100.5, 4.615124601338064117341315601525112558522917517910505881343}, + {.5, -1.96351002602142347944097633299875556719315960466043}, + {10, 2.251752589066721107647456163885851537211808918028330369448}, + {math.Pow10(20), 46.05170185988091368035482909368728415202202143924212618733}, + } { + + if got := Digamma(test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d Digamma(%g) failed: got %g want %g", i, test.x, got, test.want) + } + } +} diff --git a/mathext/erf.go b/mathext/erf.go new file mode 100644 index 00000000..cee4dbc2 --- /dev/null +++ b/mathext/erf.go @@ -0,0 +1,91 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import "math" + +/* +Copyright (c) 2012 The Probab Authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. +* Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// NormalQuantile computes the quantile function (inverse CDF) of the standard +// normal. NormalQuantile panics if the input p is less than 0 or greater than 1. +func NormalQuantile(p float64) float64 { + switch { + case p < 0 || 1 < p: + panic("mathext: quantile out of bounds") + case p == 1: + return math.Inf(1) + case p == 0: + return math.Inf(-1) + } + // Compute rational approximation based on the value of p. + + dp := p - 0.5 + if math.Abs(dp) <= 0.425 { + z := 0.180625 - dp*dp + z1 := ((((((zQSA[0]*z+zQSA[1])*z+zQSA[2])*z+zQSA[3])*z+zQSA[4])*z+zQSA[5])*z+zQSA[6])*z + zQSA[7] + z2 := ((((((zQSB[0]*z+zQSB[1])*z+zQSB[2])*z+zQSB[3])*z+zQSB[4])*z+zQSB[5])*z+zQSB[6])*z + zQSB[7] + return dp * z1 / z2 + } + + if p < 0.5 { + r := math.Sqrt(-math.Log(p)) + if r <= 5.0 { + z := r - 1.6 + z1 := ((((((zQIA[0]*z+zQIA[1])*z+zQIA[2])*z+zQIA[3])*z+zQIA[4])*z+zQIA[5])*z+zQIA[6])*z + zQIA[7] + z2 := ((((((zQIB[0]*z+zQIB[1])*z+zQIB[2])*z+zQIB[3])*z+zQIB[4])*z+zQIB[5])*z+zQIB[6])*z + zQIB[7] + return -z1 / z2 + } + z := r - 5 + z1 := ((((((zQTA[0]*z+zQTA[1])*z+zQTA[2])*z+zQTA[3])*z+zQTA[4])*z+zQTA[5])*z+zQTA[6])*z + zQTA[7] + z2 := ((((((zQTB[0]*z+zQTB[1])*z+zQTB[2])*z+zQTB[3])*z+zQTB[4])*z+zQTB[5])*z+zQTB[6])*z + zQTB[7] + return -z1 / z2 + } + r := math.Sqrt(-math.Log(1 - p)) + if r <= 5.0 { + z := r - 1.6 + z1 := ((((((zQIA[0]*z+zQIA[1])*z+zQIA[2])*z+zQIA[3])*z+zQIA[4])*z+zQIA[5])*z+zQIA[6])*z + zQIA[7] + z2 := ((((((zQIB[0]*z+zQIB[1])*z+zQIB[2])*z+zQIB[3])*z+zQIB[4])*z+zQIB[5])*z+zQIB[6])*z + zQIB[7] + return z1 / z2 + } + + z := r - 5 + z1 := ((((((zQTA[0]*z+zQTA[1])*z+zQTA[2])*z+zQTA[3])*z+zQTA[4])*z+zQTA[5])*z+zQTA[6])*z + zQTA[7] + z2 := ((((((zQTB[0]*z+zQTB[1])*z+zQTB[2])*z+zQTB[3])*z+zQTB[4])*z+zQTB[5])*z+zQTB[6])*z + zQTB[7] + return z1 / z2 +} + +var ( + zQSA = [...]float64{2509.0809287301226727, 33430.575583588128105, 67265.770927008700853, 45921.953931549871457, 13731.693765509461125, 1971.5909503065514427, 133.14166789178437745, 3.387132872796366608} + zQSB = [...]float64{5226.495278852854561, 28729.085735721942674, 39307.89580009271061, 21213.794301586595867, 5394.1960214247511077, 687.1870074920579083, 42.313330701600911252, 1.0} + zQIA = [...]float64{7.7454501427834140764e-4, 0.0227238449892691845833, 0.24178072517745061177, 1.27045825245236838258, 3.64784832476320460504, 5.7694972214606914055, 4.6303378461565452959, 1.42343711074968357734} + zQIB = [...]float64{1.05075007164441684324e-9, 5.475938084995344946e-4, 0.0151986665636164571966, 0.14810397642748007459, 0.68976733498510000455, 1.6763848301838038494, 2.05319162663775882187, 1.0} + zQTA = [...]float64{2.01033439929228813265e-7, 2.71155556874348757815e-5, 0.0012426609473880784386, 0.026532189526576123093, 0.29656057182850489123, 1.7848265399172913358, 5.4637849111641143699, 6.6579046435011037772} + zQTB = [...]float64{2.04426310338993978564e-15, 1.4215117583164458887e-7, 1.8463183175100546818e-5, 7.868691311456132591e-4, 0.0148753612908506148525, 0.13692988092273580531, 0.59983220655588793769, 1.0} +) diff --git a/mathext/erf_test.go b/mathext/erf_test.go new file mode 100644 index 00000000..f698e51e --- /dev/null +++ b/mathext/erf_test.go @@ -0,0 +1,69 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestNormalQuantile(t *testing.T) { + // Values from https://www.johndcook.com/blog/normal_cdf_inverse/ + p := []float64{ + 0.0000001, + 0.00001, + 0.001, + 0.05, + 0.15, + 0.25, + 0.35, + 0.45, + 0.55, + 0.65, + 0.75, + 0.85, + 0.95, + 0.999, + 0.99999, + 0.9999999, + } + ans := []float64{ + -5.199337582187471, + -4.264890793922602, + -3.090232306167813, + -1.6448536269514729, + -1.0364333894937896, + -0.6744897501960817, + -0.38532046640756773, + -0.12566134685507402, + 0.12566134685507402, + 0.38532046640756773, + 0.6744897501960817, + 1.0364333894937896, + 1.6448536269514729, + 3.090232306167813, + 4.264890793922602, + 5.199337582187471, + } + for i, v := range p { + got := NormalQuantile(v) + if !floats.EqualWithinAbsOrRel(got, ans[i], 1e-10, 1e-10) { + t.Errorf("Quantile mismatch. Case %d, want: %v, got: %v", i, ans[i], got) + } + } +} + +var nqtmp float64 + +func BenchmarkNormalQuantile(b *testing.B) { + ps := make([]float64, 1000) // ensure there are small values + floats.Span(ps, 0, 1) + for i := 0; i < b.N; i++ { + for _, v := range ps { + nqtmp = NormalQuantile(v) + } + } +} diff --git a/mathext/gamma_inc.go b/mathext/gamma_inc.go new file mode 100644 index 00000000..db16dad9 --- /dev/null +++ b/mathext/gamma_inc.go @@ -0,0 +1,50 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "gonum.org/v1/gonum/mathext/internal/cephes" +) + +// GammaInc computes the incomplete Gamma integral. +// GammaInc(a,x) = (1/ Γ(a)) \int_0^x e^{-t} t^{a-1} dt +// The input argument a must be positive and x must be non-negative or GammaInc +// will panic. +// +// See http://mathworld.wolfram.com/IncompleteGammaFunction.html +// or https://en.wikipedia.org/wiki/Incomplete_gamma_function for more detailed +// information. +func GammaInc(a, x float64) float64 { + return cephes.Igam(a, x) +} + +// GammaIncComp computes the complemented incomplete Gamma integral. +// GammaIncComp(a,x) = 1 - GammaInc(a,x) +// = (1/ Γ(a)) \int_0^\infty e^{-t} t^{a-1} dt +// The input argument a must be positive and x must be non-negative or +// GammaIncComp will panic. +func GammaIncComp(a, x float64) float64 { + return cephes.IgamC(a, x) +} + +// GammaIncInv computes the inverse of the incomplete Gamma integral. That is, +// it returns the x such that: +// GammaInc(a, x) = y +// The input argument a must be positive and y must be between 0 and 1 +// inclusive or GammaIncInv will panic. GammaIncInv should return a positive +// number, but can return NaN if there is a failure to converge. +func GammaIncInv(a, y float64) float64 { + return gammaIncInv(a, y) +} + +// GammaIncCompInv computes the inverse of the complemented incomplete Gamma +// integral. That is, it returns the x such that: +// GammaIncComp(a, x) = y +// The input argument a must be positive and y must be between 0 and 1 +// inclusive or GammaIncCompInv will panic. GammaIncCompInv should return a +// positive number, but can return 0 even with non-zero y due to underflow. +func GammaIncCompInv(a, y float64) float64 { + return cephes.IgamI(a, y) +} diff --git a/mathext/gamma_inc_inv.go b/mathext/gamma_inc_inv.go new file mode 100644 index 00000000..c17fce34 --- /dev/null +++ b/mathext/gamma_inc_inv.go @@ -0,0 +1,56 @@ +// Derived from SciPy's special/c_misc/gammaincinv.c +// https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/gammaincinv.c + +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "math" + + "gonum.org/v1/gonum/mathext/internal/cephes" +) + +const ( + allowedATol = 1e-306 + allowedRTol = 1e-6 +) + +func gammaInc(x float64, params []float64) float64 { + return cephes.Igam(params[0], x) - params[1] +} + +// gammaIncInv is the inverse of the incomplete Gamma integral. That is, it +// returns x such that: +// Igam(a, x) = y +// The input argument a must be positive and y must be between 0 and 1 +// inclusive or gammaIncInv will panic. gammaIncInv should return a +// positive number, but can return NaN if there is a failure to converge. +func gammaIncInv(a, y float64) float64 { + // For y not small, we just use + // IgamI(a, 1-y) + // (inverse of the complemented incomplete Gamma integral). For y small, + // however, 1-y is about 1, and we lose digits. + if a <= 0 || y <= 0 || y >= 0.25 { + return cephes.IgamI(a, 1-y) + } + + lo := 0.0 + flo := -y + hi := cephes.IgamI(a, 0.75) + fhi := 0.25 - y + + params := []float64{a, y} + + // Also, after we generate a small interval by bisection above, false + // position will do a large step from an interval of width ~1e-4 to ~1e-14 + // in one step (a=10, x=0.05, but similiar for other values). + result, bestX, _, errEst := falsePosition(lo, hi, flo, fhi, 2*machEp, 2*machEp, 1e-2*a, gammaInc, params) + if result == fSolveMaxIterations && errEst > allowedATol+allowedRTol*math.Abs(bestX) { + bestX = math.NaN() + } + + return bestX +} diff --git a/mathext/gamma_inc_test.go b/mathext/gamma_inc_test.go new file mode 100644 index 00000000..03d5f014 --- /dev/null +++ b/mathext/gamma_inc_test.go @@ -0,0 +1,138 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "math" + "testing" +) + +func TestGammaInc(t *testing.T) { + for i, test := range []struct { + a, x, want float64 + }{ + // Results computed using scipy.special.gamminc + {0, 0, 0}, + {0.0001, 1, 0.99997805936186279}, + {0.001, 0.005, 0.99528424172333985}, + {0.01, 10, 0.99999995718295021}, + {0.1, 10, 0.99999944520142825}, + {0.25, 0.75, 0.89993651328449831}, + {0.5, 0.5, 0.68268949213708596}, + {0.5, 2, 0.95449973610364147}, + {0.75, 2.5, 0.95053039734695643}, + {1, 0.5, 0.39346934028736652}, + {1, 1, 0.63212055882855778}, + {1.5, 0.75, 0.31772966966378746}, + {2.5, 1, 0.15085496391539038}, + {3, 0.05, 2.0067493624397931e-05}, + {3, 20, 0.99999954448504946}, + {5, 50, 1}, + {7, 10, 0.86985857911751696}, + {10, 0.9, 4.2519575433351128e-08}, + {10, 5, 0.031828057306204811}, + {25, 10, 4.6949381426799868e-05}, + } { + if got := GammaInc(test.a, test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d GammaInc(%g, %g) failed: got %g want %g", i, test.a, test.x, got, test.want) + } + } +} + +func TestGammaIncComp(t *testing.T) { + for i, test := range []struct { + a, x, want float64 + }{ + // Results computed using scipy.special.gammincc + {0.00001, 0.075, 2.0866541002417804e-05}, + {0.0001, 1, 2.1940638138146658e-05}, + {0.001, 0.005, 0.0047157582766601536}, + {0.01, 0.9, 0.0026263432520514662}, + {0.25, 0.75, 0.10006348671550169}, + {0.5, 0.5, 0.31731050786291404}, + {0.75, 0.25, 0.65343980284081038}, + {0.9, 0.01, 0.98359881081593148}, + {1, 0, 1}, + {1, 0.075, 0.92774348632855297}, + {1, 1, 0.36787944117144233}, + {1, 10, 4.5399929762484861e-05}, + {1, math.Inf(1), 0}, + {3, 20, 4.5551495055892125e-07}, + {5, 10, 0.029252688076961127}, + {10, 3, 0.99889751186988451}, + {50, 25, 0.99999304669475242}, + {100, 10, 1}, + {500, 500, 0.49405285382921321}, + {500, 550, 0.014614408126291296}, + } { + if got := GammaIncComp(test.a, test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d GammaIncComp(%g, %g) failed: got %g want %g", i, test.a, test.x, got, test.want) + } + } +} + +func TestGammaIncInv(t *testing.T) { + for i, test := range []struct { + a, x, want float64 + }{ + // Results computed using scipy.special.gammincinv + {0.001, 0.99, 2.4259428385570885e-05}, + {0.01, 0.99, 0.26505255025157959}, + {0.1, 0.5, 0.00059339110446022798}, + {0.2, 0.8, 0.26354363204872067}, + {0.25, 0.5, 0.043673802352873381}, + {0.5, 0.25, 0.050765522133810789}, + {0.5, 0.5, 0.22746821155978625}, + {0.75, 0.25, 0.15340752707472377}, + {1, 0, 0}, + {1, 0.075, 0.077961541469711862}, + {1, 1, math.Inf(1)}, + {2.5, 0.99, 7.5431362346944937}, + {10, 0.5, 9.6687146147141299}, + {25, 0.01, 14.853341349420646}, + {25, 0.99, 38.076945624506337}, + {50, 0.75, 54.570620535040511}, + {100, 0.25, 93.08583383712174}, + {1000, 0.01, 927.90815979664251}, + {1000, 0.99, 1075.0328320864389}, + {10000, 0.5, 9999.6666686420485}, + } { + if got := GammaIncInv(test.a, test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d GammaIncInv(%g, %g) failed: got %g want %g", i, test.a, test.x, got, test.want) + } + } +} + +func TestGammaIncCompInv(t *testing.T) { + for i, test := range []struct { + a, x, want float64 + }{ + // Results computed using scipy.special.gamminccinv + {0.001, 0.01, 2.4259428385570885e-05}, + {0.01, 0.01, 0.26505255025158292}, + {0.03, 0.4, 2.316980536227699e-08}, + {0.1, 0.5, 0.00059339110446022798}, + {0.1, 0.75, 5.7917132949696076e-07}, + {0.25, 0.25, 0.26062600197823282}, + {0.5, 0.1, 1.3527717270477047}, + {0.5, 0.5, 0.22746821155978625}, + {0.75, 0.25, 1.0340914067758025}, + {1, 0, math.Inf(1)}, + {1, 0.5, 0.69314718055994529}, + {1, 1, 0}, + {3, 0.75, 1.727299417860519}, + {25, 0.4, 25.945791937289371}, + {25, 0.7, 22.156653488661991}, + {10, 0.5, 9.6687146147141299}, + {100, 0.25, 106.5510925269767}, + {1000, 0.01, 1075.0328320864389}, + {1000, 0.99, 927.90815979664251}, + {10000, 0.5, 9999.6666686420485}, + } { + if got := GammaIncCompInv(test.a, test.x); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d GammaIncCompInv(%g, %g) failed: got %g want %g", i, test.a, test.x, got, test.want) + } + } +} diff --git a/mathext/internal/amos/amos.go b/mathext/internal/amos/amos.go new file mode 100644 index 00000000..b8d0f063 --- /dev/null +++ b/mathext/internal/amos/amos.go @@ -0,0 +1,2155 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package amos implements functions originally in the Netlab code by Donald Amos. +package amos + +import ( + "math" + "math/cmplx" +) + +/* +The AMOS functions are included in SLATEC, and the SLATEC guide (http://www.netlib.org/slatec/guide) explicitly states: +"The Library is in the public domain and distributed by the Energy +Science and Technology Software Center." +Mention of AMOS's inclusion in SLATEC goes back at least to this 1985 technical report from Sandia National Labs: http://infoserve.sandia.gov/sand_doc/1985/851018.pdf +*/ + +// math.NaN() are for padding to keep indexing easy. +var imach = []int{-0, 5, 6, 0, 0, 32, 4, 2, 31, 2147483647, 2, 24, -125, 127, 53, -1021, 1023} + +var dmach = []float64{math.NaN(), 2.23E-308, 1.79E-308, 1.11E-16, 2.22E-16, 0.30103000998497009} + +func abs(a int) int { + if a >= 0 { + return a + } + return -a +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func Zairy(ZR, ZI float64, ID, KODE int) (AIR, AII float64, NZ int) { + // zairy is adapted from the original Netlib code by Donald Amos. + // http://www.netlib.no/netlib/amos/zairy.f + + // Original comment: + /* + C***BEGIN PROLOGUE ZAIRY + C***DATE WRITTEN 830501 (YYMMDD) + C***REVISION DATE 890801 (YYMMDD) + C***CATEGORY NO. B5K + C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD + C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES + C***PURPOSE TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z + C***DESCRIPTION + C + C ***A DOUBLE PRECISION ROUTINE*** + C ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR + C ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON + C KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)* + C DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN + C -PI/31.0 FROM THE K BESSEL + C FUNCTIONS BY + C + C AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA) + C C=1.0/(PI*SQRT(3.0)) + C ZTA=(2/3)*Z**(3/2) + C + C WITH THE POWER SERIES FOR CABS(Z)<=1.0. + C + C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- + C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES + C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF + C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR), + C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR + C FLAG IERR=3 IS TRIGGERED WHERE UR=math.Max(dmach[4),1.0D-18) IS + C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. + C ALSO, if THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN + C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT + C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE + C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA + C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, + C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE + C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE + C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT- + C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG- + C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN + C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN + C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, + C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE + C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER + C MACHINES. + C + C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX + C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT + C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- + C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE + C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), + C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF + C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY + C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN + C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY + C SEVERAL ORDERS OF MAGNITUDE. if ONE COMPONENT IS 10**K LARGER + C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, + C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS + C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER + C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY + C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER + C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE + C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, + C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, + C OR -PI/2+P. + C + C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ + C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF + C COMMERCE, 1955. + C + C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT + C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 + C + C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX + C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- + C 1018, MAY, 1985 + C + C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX + C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. + C MATH. SOFTWARE, 1986 + */ + var AI, CONE, CSQ, CY, S1, S2, TRM1, TRM2, Z, ZTA, Z3 complex128 + var AA, AD, AK, ALIM, ATRM, AZ, AZ3, BK, + CC, CK, COEF, CONEI, CONER, CSQI, CSQR, C1, C2, DIG, + DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR, + S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI, + ZEROR, ZTAI, ZTAR, Z3I, Z3R, ALAZ, BB float64 + var IERR, IFLAG, K, K1, K2, MR, NN int + var tmp complex128 + + // Extra element for padding. + CYR := []float64{math.NaN(), 0} + CYI := []float64{math.NaN(), 0} + + _ = AI + _ = CONE + _ = CSQ + _ = CY + _ = S1 + _ = S2 + _ = TRM1 + _ = TRM2 + _ = Z + _ = ZTA + _ = Z3 + + TTH = 6.66666666666666667E-01 + C1 = 3.55028053887817240E-01 + C2 = 2.58819403792806799E-01 + COEF = 1.83776298473930683E-01 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + NZ = 0 + if ID < 0 || ID > 1 { + IERR = 1 + } + if KODE < 1 || KODE > 2 { + IERR = 1 + } + if IERR != 0 { + return + } + AZ = cmplx.Abs(complex(ZR, ZI)) + TOL = math.Max(dmach[4], 1.0E-18) + FID = float64(ID) + if AZ > 1.0E0 { + goto Seventy + } + + // POWER SERIES FOR CABS(Z)<=1. + S1R = CONER + S1I = CONEI + S2R = CONER + S2I = CONEI + if AZ < TOL { + goto OneSeventy + } + AA = AZ * AZ + if AA < TOL/AZ { + goto Fourty + } + TRM1R = CONER + TRM1I = CONEI + TRM2R = CONER + TRM2I = CONEI + ATRM = 1.0E0 + STR = ZR*ZR - ZI*ZI + STI = ZR*ZI + ZI*ZR + Z3R = STR*ZR - STI*ZI + Z3I = STR*ZI + STI*ZR + AZ3 = AZ * AA + AK = 2.0E0 + FID + BK = 3.0E0 - FID - FID + CK = 4.0E0 - FID + DK = 3.0E0 + FID + FID + D1 = AK * DK + D2 = BK * CK + AD = math.Min(D1, D2) + AK = 24.0E0 + 9.0E0*FID + BK = 30.0E0 - 9.0E0*FID + for K = 1; K <= 25; K++ { + STR = (TRM1R*Z3R - TRM1I*Z3I) / D1 + TRM1I = (TRM1R*Z3I + TRM1I*Z3R) / D1 + TRM1R = STR + S1R = S1R + TRM1R + S1I = S1I + TRM1I + STR = (TRM2R*Z3R - TRM2I*Z3I) / D2 + TRM2I = (TRM2R*Z3I + TRM2I*Z3R) / D2 + TRM2R = STR + S2R = S2R + TRM2R + S2I = S2I + TRM2I + ATRM = ATRM * AZ3 / AD + D1 = D1 + AK + D2 = D2 + BK + AD = math.Min(D1, D2) + if ATRM < TOL*AD { + goto Fourty + } + AK = AK + 18.0E0 + BK = BK + 18.0E0 + } +Fourty: + if ID == 1 { + goto Fifty + } + AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I) + AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R) + if KODE == 1 { + return + } + tmp = cmplx.Sqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + ZTAR = TTH * (ZR*STR - ZI*STI) + ZTAI = TTH * (ZR*STI + ZI*STR) + tmp = cmplx.Exp(complex(ZTAR, ZTAI)) + STR = real(tmp) + STI = imag(tmp) + PTR = AIR*STR - AII*STI + AII = AIR*STI + AII*STR + AIR = PTR + return + +Fifty: + AIR = -S2R * C2 + AII = -S2I * C2 + if AZ <= TOL { + goto Sixty + } + STR = ZR*S1R - ZI*S1I + STI = ZR*S1I + ZI*S1R + CC = C1 / (1.0E0 + FID) + AIR = AIR + CC*(STR*ZR-STI*ZI) + AII = AII + CC*(STR*ZI+STI*ZR) + +Sixty: + if KODE == 1 { + return + } + tmp = cmplx.Sqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + ZTAR = TTH * (ZR*STR - ZI*STI) + ZTAI = TTH * (ZR*STI + ZI*STR) + tmp = cmplx.Exp(complex(ZTAR, ZTAI)) + STR = real(tmp) + STI = imag(tmp) + PTR = STR*AIR - STI*AII + AII = STR*AII + STI*AIR + AIR = PTR + return + + // CASE FOR CABS(Z)>1.0. +Seventy: + FNU = (1.0E0 + FID) / 3.0E0 + + /* + SET PARAMETERS RELATED TO MACHINE CONSTANTS. + TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18. + ELIM IS THE APPROXIMATE EXPONENTIAL OVER-&&UNDERFLOW LIMIT. + EXP(-ELIM)EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR + UNDERFLOW&&OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. + RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LA>=Z. + DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). + */ + K1 = imach[15] + K2 = imach[16] + R1M5 = dmach[5] + + K = min(abs(K1), abs(K2)) + ELIM = 2.303E0 * (float64(K)*R1M5 - 3.0E0) + K1 = imach[14] - 1 + AA = R1M5 * float64(K1) + DIG = math.Min(AA, 18.0E0) + AA = AA * 2.303E0 + ALIM = ELIM + math.Max(-AA, -41.45E0) + RL = 1.2E0*DIG + 3.0E0 + ALAZ = math.Log(AZ) + + // TEST FOR PROPER RANGE. + AA = 0.5E0 / TOL + BB = float64(float32(imach[9])) * 0.5E0 + AA = math.Min(AA, BB) + AA = math.Pow(AA, TTH) + if AZ > AA { + goto TwoSixty + } + AA = math.Sqrt(AA) + if AZ > AA { + IERR = 3 + } + tmp = cmplx.Sqrt(complex(ZR, ZI)) + CSQR = real(tmp) + CSQI = imag(tmp) + ZTAR = TTH * (ZR*CSQR - ZI*CSQI) + ZTAI = TTH * (ZR*CSQI + ZI*CSQR) + + // RE(ZTA)<=0 WHEN RE(Z)<0, ESPECIALLY WHEN IM(Z) IS SMALL. + IFLAG = 0 + SFAC = 1.0E0 + AK = ZTAI + if ZR >= 0.0E0 { + goto Eighty + } + BK = ZTAR + CK = -math.Abs(BK) + ZTAR = CK + ZTAI = AK + +Eighty: + if ZI != 0.0E0 { + goto Ninety + } + if ZR > 0.0E0 { + goto Ninety + } + ZTAR = 0.0E0 + ZTAI = AK +Ninety: + AA = ZTAR + if AA >= 0.0E0 && ZR > 0.0E0 { + goto OneTen + } + if KODE == 2 { + goto OneHundred + } + + // OVERFLOW TEST. + if AA > (-ALIM) { + goto OneHundred + } + AA = -AA + 0.25E0*ALAZ + IFLAG = 1 + SFAC = TOL + if AA > ELIM { + goto TwoSeventy + } + +OneHundred: + // CBKNU AND CACON return EXP(ZTA)*K(FNU,ZTA) ON KODE=2. + MR = 1 + if ZI < 0.0E0 { + MR = -1 + } + ZTAR, ZTAI, FNU, KODE, MR, _, CYR, CYI, NN, RL, TOL, ELIM, ALIM = Zacai(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, NN, RL, TOL, ELIM, ALIM) + if NN < 0 { + goto TwoEighty + } + NZ = NZ + NN + goto OneThirty + +OneTen: + if KODE == 2 { + goto OneTwenty + } + + // UNDERFLOW TEST. + if AA < ALIM { + goto OneTwenty + } + AA = -AA - 0.25E0*ALAZ + IFLAG = 2 + SFAC = 1.0E0 / TOL + if AA < (-ELIM) { + goto TwoTen + } +OneTwenty: + ZTAR, ZTAI, FNU, KODE, _, CYR, CYI, NZ, TOL, ELIM, ALIM = Zbknu(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, TOL, ELIM, ALIM) + +OneThirty: + S1R = CYR[1] * COEF + S1I = CYI[1] * COEF + if IFLAG != 0 { + goto OneFifty + } + if ID == 1 { + goto OneFourty + } + AIR = CSQR*S1R - CSQI*S1I + AII = CSQR*S1I + CSQI*S1R + return +OneFourty: + AIR = -(ZR*S1R - ZI*S1I) + AII = -(ZR*S1I + ZI*S1R) + return +OneFifty: + S1R = S1R * SFAC + S1I = S1I * SFAC + if ID == 1 { + goto OneSixty + } + STR = S1R*CSQR - S1I*CSQI + S1I = S1R*CSQI + S1I*CSQR + S1R = STR + AIR = S1R / SFAC + AII = S1I / SFAC + return +OneSixty: + STR = -(S1R*ZR - S1I*ZI) + S1I = -(S1R*ZI + S1I*ZR) + S1R = STR + AIR = S1R / SFAC + AII = S1I / SFAC + return +OneSeventy: + AA = 1.0E+3 * dmach[1] + S1R = ZEROR + S1I = ZEROI + if ID == 1 { + goto OneNinety + } + if AZ <= AA { + goto OneEighty + } + S1R = C2 * ZR + S1I = C2 * ZI +OneEighty: + AIR = C1 - S1R + AII = -S1I + return +OneNinety: + AIR = -C2 + AII = 0.0E0 + AA = math.Sqrt(AA) + if AZ <= AA { + goto TwoHundred + } + S1R = 0.5E0 * (ZR*ZR - ZI*ZI) + S1I = ZR * ZI +TwoHundred: + AIR = AIR + C1*S1R + AII = AII + C1*S1I + return +TwoTen: + NZ = 1 + AIR = ZEROR + AII = ZEROI + return +TwoSeventy: + NZ = 0 + IERR = 2 + return +TwoEighty: + if NN == (-1) { + goto TwoSeventy + } + NZ = 0 + IERR = 5 + return +TwoSixty: + IERR = 4 + NZ = 0 + return +} + +// sbknu computes the k bessel function in the right half z plane. +func Zbknu(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) (ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + /* Old dimension comment. + DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2), + * CYI(2) + */ + + // TOOD(btracey): Find which of these are inputs/outputs/both and clean up + // the function call. + // YR and YI have length n (but n+1 with better indexing) + var AA, AK, ASCLE, A1, A2, BB, BK, CAZ, + CBI, CBR, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER, + CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CTWOR, + CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ETEST, FC, FHS, + FI, FK, FKS, FMUI, FMUR, FPI, FR, G1, G2, HPI, PI, PR, PTI, + PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI, + RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM, + TTH, T1, T2, ELM, CELMR, ZDR, ZDI, AS, ALAS, HELIM float64 + + var I, IFLAG, INU, K, KFLAG, KK, KMAX, KODED, IDUM, J, IC, INUB, NW int + + var sinh, cosh complex128 + //var sin, cos float64 + + var tmp, p complex128 + var CSSR, CSRR, BRY [4]float64 + var CYR, CYI [3]float64 + + KMAX = 30 + CZEROR = 0 + CZEROI = 0 + CONER = 1 + CONEI = 0 + CTWOR = 2 + R1 = 2 + + DPI = 3.14159265358979324E0 + RTHPI = 1.25331413731550025E0 + SPI = 1.90985931710274403E0 + HPI = 1.57079632679489662E0 + FPI = 1.89769999331517738E0 + TTH = 6.66666666666666666E-01 + + CC := [9]float64{math.NaN(), 5.77215664901532861E-01, -4.20026350340952355E-02, + -4.21977345555443367E-02, 7.21894324666309954E-03, + -2.15241674114950973E-04, -2.01348547807882387E-05, + 1.13302723198169588E-06, 6.11609510448141582E-09} + + CAZ = cmplx.Abs(complex(ZR, ZI)) + CSCLR = 1.0E0 / TOL + CRSCR = TOL + CSSR[1] = CSCLR + CSSR[2] = 1.0E0 + CSSR[3] = CRSCR + CSRR[1] = CRSCR + CSRR[2] = 1.0E0 + CSRR[3] = CSCLR + BRY[1] = 1.0E+3 * dmach[1] / TOL + BRY[2] = 1.0E0 / BRY[1] + BRY[3] = dmach[2] + NZ = 0 + IFLAG = 0 + KODED = KODE + RCAZ = 1.0E0 / CAZ + STR = ZR * RCAZ + STI = -ZI * RCAZ + RZR = (STR + STR) * RCAZ + RZI = (STI + STI) * RCAZ + INU = int(float32(FNU + 0.5)) + DNU = FNU - float64(INU) + if math.Abs(DNU) == 0.5E0 { + goto OneTen + } + DNU2 = 0.0E0 + if math.Abs(DNU) > TOL { + DNU2 = DNU * DNU + } + if CAZ > R1 { + goto OneTen + } + + // SERIES FOR CABS(Z)<=R1. + FC = 1.0E0 + tmp = cmplx.Log(complex(RZR, RZI)) + SMUR = real(tmp) + SMUI = imag(tmp) + FMUR = SMUR * DNU + FMUI = SMUI * DNU + tmp = complex(FMUR, FMUI) + sinh = cmplx.Sinh(tmp) + cosh = cmplx.Cosh(tmp) + CSHR = real(sinh) + CSHI = imag(sinh) + CCHR = real(cosh) + CCHI = imag(cosh) + if DNU == 0.0E0 { + goto Ten + } + FC = DNU * DPI + FC = FC / math.Sin(FC) + SMUR = CSHR / DNU + SMUI = CSHI / DNU +Ten: + A2 = 1.0E0 + DNU + + // GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU). + T2 = math.Exp(-dgamln(A2, IDUM)) + T1 = 1.0E0 / (T2 * FC) + if math.Abs(DNU) > 0.1E0 { + goto Fourty + } + + // SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU). + AK = 1.0E0 + S = CC[1] + for K = 2; K <= 8; K++ { + AK = AK * DNU2 + TM = CC[K] * AK + S = S + TM + if math.Abs(TM) < TOL { + goto Thirty + } + } +Thirty: + G1 = -S + goto Fifty +Fourty: + G1 = (T1 - T2) / (DNU + DNU) +Fifty: + G2 = (T1 + T2) * 0.5E0 + FR = FC * (CCHR*G1 + SMUR*G2) + FI = FC * (CCHI*G1 + SMUI*G2) + tmp = cmplx.Exp(complex(FMUR, FMUI)) + STR = real(tmp) + STI = imag(tmp) + PR = 0.5E0 * STR / T2 + PI = 0.5E0 * STI / T2 + tmp = complex(0.5, 0) / complex(STR, STI) + PTR = real(tmp) + PTI = imag(tmp) + QR = PTR / T1 + QI = PTI / T1 + S1R = FR + S1I = FI + S2R = PR + S2I = PI + AK = 1.0E0 + A1 = 1.0E0 + CKR = CONER + CKI = CONEI + BK = 1.0E0 - DNU2 + if INU > 0 || N > 1 { + goto Eighty + } + + // GENERATE K(FNU,Z), 0.0E0 <= FNU < 0.5E0 AND N=1. + if CAZ < TOL { + goto Seventy + } + tmp = complex(ZR, ZI) * complex(ZR, ZI) + CZR = real(tmp) + CZI = imag(tmp) + CZR = 0.25E0 * CZR + CZI = 0.25E0 * CZI + T1 = 0.25E0 * CAZ * CAZ +Sixty: + FR = (FR*AK + PR + QR) / BK + FI = (FI*AK + PI + QI) / BK + STR = 1.0E0 / (AK - DNU) + PR = PR * STR + PI = PI * STR + STR = 1.0E0 / (AK + DNU) + QR = QR * STR + QI = QI * STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0E0 / AK + CKI = (CKR*CZI + CKI*CZR) * RAK + CKR = STR * RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + A1 = A1 * T1 * RAK + BK = BK + AK + AK + 1.0E0 + AK = AK + 1.0E0 + if A1 > TOL { + goto Sixty + } +Seventy: + YR[1] = S1R + YI[1] = S1I + if KODED == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + tmp = cmplx.Exp(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(S1R, S1I) * complex(STR, STI) + YR[1] = real(tmp) + YI[1] = imag(tmp) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE. +Eighty: + if CAZ < TOL { + goto OneHundred + } + tmp = complex(ZR, ZI) * complex(ZR, ZI) + CZR = real(tmp) + CZI = imag(tmp) + CZR = 0.25E0 * CZR + CZI = 0.25E0 * CZI + T1 = 0.25E0 * CAZ * CAZ +Ninety: + FR = (FR*AK + PR + QR) / BK + FI = (FI*AK + PI + QI) / BK + STR = 1.0E0 / (AK - DNU) + PR = PR * STR + PI = PI * STR + STR = 1.0E0 / (AK + DNU) + QR = QR * STR + QI = QI * STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0E0 / AK + CKI = (CKR*CZI + CKI*CZR) * RAK + CKR = STR * RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + STR = PR - FR*AK + STI = PI - FI*AK + S2R = CKR*STR - CKI*STI + S2R + S2I = CKR*STI + CKI*STR + S2I + A1 = A1 * T1 * RAK + BK = BK + AK + AK + 1.0E0 + AK = AK + 1.0E0 + if A1 > TOL { + goto Ninety + } +OneHundred: + KFLAG = 2 + A1 = FNU + 1.0E0 + AK = A1 * math.Abs(SMUR) + if AK > ALIM { + KFLAG = 3 + } + STR = CSSR[KFLAG] + P2R = S2R * STR + P2I = S2I * STR + tmp = complex(P2R, P2I) * complex(RZR, RZI) + S2R = real(tmp) + S2I = imag(tmp) + S1R = S1R * STR + S1I = S1I * STR + if KODED == 1 { + goto TwoTen + } + tmp = cmplx.Exp(complex(ZR, ZI)) + FR = real(tmp) + FI = imag(tmp) + tmp = complex(S1R, S1I) * complex(FR, FI) + S1R = real(tmp) + S1I = imag(tmp) + tmp = complex(S2R, S2I) * complex(FR, FI) + S2R = real(tmp) + S2I = imag(tmp) + goto TwoTen + + // IFLAG=0 MEANS NO UNDERFLOW OCCURRED + // IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH + // KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD RECURSION +OneTen: + tmp = cmplx.Sqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(RTHPI, CZEROI) / complex(STR, STI) + COEFR = real(tmp) + COEFI = imag(tmp) + KFLAG = 2 + if KODED == 2 { + goto OneTwenty + } + if ZR > ALIM { + goto TwoNinety + } + + STR = math.Exp(-ZR) * CSSR[KFLAG] + //sin, cos = math.Sincos(ZI) + STI = -STR * math.Sin(ZI) + STR = STR * math.Cos(ZI) + tmp = complex(COEFR, COEFI) * complex(STR, STI) + COEFR = real(tmp) + COEFI = imag(tmp) +OneTwenty: + if math.Abs(DNU) == 0.5E0 { + goto ThreeHundred + } + // MILLER ALGORITHM FOR CABS(Z)>R1. + AK = math.Cos(DPI * DNU) + AK = math.Abs(AK) + if AK == CZEROR { + goto ThreeHundred + } + FHS = math.Abs(0.25E0 - DNU2) + if FHS == CZEROR { + goto ThreeHundred + } + + // COMPUTE R2=F(E). if CABS(Z)>=R2, USE FORWARD RECURRENCE TO + // DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON + // 12<=E<=60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))= + // TOL WHERE B IS THE BASE OF THE ARITHMETIC. + T1 = float64(imach[14] - 1) + T1 = T1 * dmach[5] * 3.321928094E0 + T1 = math.Max(T1, 12.0E0) + T1 = math.Min(T1, 60.0E0) + T2 = TTH*T1 - 6.0E0 + if ZR != 0.0E0 { + goto OneThirty + } + T1 = HPI + goto OneFourty +OneThirty: + T1 = math.Atan(ZI / ZR) + T1 = math.Abs(T1) +OneFourty: + if T2 > CAZ { + goto OneSeventy + } + // FORWARD RECURRENCE LOOP WHEN CABS(Z)>=R2. + ETEST = AK / (DPI * CAZ * TOL) + FK = CONER + if ETEST < CONER { + goto OneEighty + } + FKS = CTWOR + CKR = CAZ + CAZ + CTWOR + P1R = CZEROR + P2R = CONER + for I = 1; I <= KMAX; I++ { + AK = FHS / FKS + CBR = CKR / (FK + CONER) + PTR = P2R + P2R = CBR*P2R - P1R*AK + P1R = PTR + CKR = CKR + CTWOR + FKS = FKS + FK + FK + CTWOR + FHS = FHS + FK + FK + FK = FK + CONER + STR = math.Abs(P2R) * FK + if ETEST < STR { + goto OneSixty + } + } + goto ThreeTen +OneSixty: + FK = FK + SPI*T1*math.Sqrt(T2/CAZ) + FHS = math.Abs(0.25 - DNU2) + goto OneEighty +OneSeventy: + // COMPUTE BACKWARD INDEX K FOR CABS(Z) 0 || N > 1 { + goto TwoHundred + } + ZDR = ZR + ZDI = ZI + if IFLAG == 1 { + goto TwoSeventy + } + goto TwoFourty +TwoHundred: + // COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING. + TM = cmplx.Abs(complex(P2R, P2I)) + PTR = 1.0E0 / TM + P1R = P1R * PTR + P1I = P1I * PTR + P2R = P2R * PTR + P2I = -P2I * PTR + tmp = complex(P1R, P1I) * complex(P2R, P2I) + PTR = real(tmp) + PTI = imag(tmp) + STR = DNU + 0.5E0 - PTR + STI = -PTI + tmp = complex(STR, STI) / complex(ZR, ZI) + STR = real(tmp) + STI = imag(tmp) + STR = STR + 1.0E0 + tmp = complex(STR, STI) * complex(S1R, S1I) + S2R = real(tmp) + S2I = imag(tmp) + + // FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH + // SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3 +TwoTen: + STR = DNU + 1.0E0 + CKR = STR * RZR + CKI = STR * RZI + if N == 1 { + INU = INU - 1 + } + if INU > 0 { + goto TwoTwenty + } + if N > 1 { + goto TwoFifteen + } + S1R = S2R + S1I = S2I +TwoFifteen: + ZDR = ZR + ZDI = ZI + if IFLAG == 1 { + goto TwoSeventy + } + goto TwoFourty +TwoTwenty: + INUB = 1 + if IFLAG == 1 { + goto TwoSixtyOne + } +TwoTwentyFive: + P1R = CSRR[KFLAG] + ASCLE = BRY[KFLAG] + for I = INUB; I <= INU; I++ { + STR = S2R + STI = S2I + S2R = CKR*STR - CKI*STI + S1R + S2I = CKR*STI + CKI*STR + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + if KFLAG >= 3 { + continue + } + P2R = S2R * P1R + P2I = S2I * P1R + STR = math.Abs(P2R) + STI = math.Abs(P2I) + P2M = math.Max(STR, STI) + if P2M <= ASCLE { + continue + } + KFLAG = KFLAG + 1 + ASCLE = BRY[KFLAG] + S1R = S1R * P1R + S1I = S1I * P1R + S2R = P2R + S2I = P2I + STR = CSSR[KFLAG] + S1R = S1R * STR + S1I = S1I * STR + S2R = S2R * STR + S2I = S2I * STR + P1R = CSRR[KFLAG] + } + if N != 1 { + goto TwoFourty + } + S1R = S2R + S1I = S2I +TwoFourty: + STR = CSRR[KFLAG] + YR[1] = S1R * STR + YI[1] = S1I * STR + if N == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + YR[2] = S2R * STR + YI[2] = S2I * STR + if N == 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = 2 +TwoFifty: + KK = KK + 1 + if KK > N { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + P1R = CSRR[KFLAG] + ASCLE = BRY[KFLAG] + for I = KK; I <= N; I++ { + P2R = S2R + P2I = S2I + S2R = CKR*P2R - CKI*P2I + S1R + S2I = CKI*P2R + CKR*P2I + S1I + S1R = P2R + S1I = P2I + CKR = CKR + RZR + CKI = CKI + RZI + P2R = S2R * P1R + P2I = S2I * P1R + YR[I] = P2R + YI[I] = P2I + if KFLAG >= 3 { + continue + } + STR = math.Abs(P2R) + STI = math.Abs(P2I) + P2M = math.Max(STR, STI) + if P2M <= ASCLE { + continue + } + KFLAG = KFLAG + 1 + ASCLE = BRY[KFLAG] + S1R = S1R * P1R + S1I = S1I * P1R + S2R = P2R + S2I = P2I + STR = CSSR[KFLAG] + S1R = S1R * STR + S1I = S1I * STR + S2R = S2R * STR + S2I = S2I * STR + P1R = CSRR[KFLAG] + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW. +TwoSixtyOne: + HELIM = 0.5E0 * ELIM + ELM = math.Exp(-ELIM) + CELMR = ELM + ASCLE = BRY[1] + ZDR = ZR + ZDI = ZI + IC = -1 + J = 2 + for I = 1; I <= INU; I++ { + STR = S2R + STI = S2I + S2R = STR*CKR - STI*CKI + S1R + S2I = STI*CKR + STR*CKI + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + AS = cmplx.Abs(complex(S2R, S2I)) + ALAS = math.Log(AS) + P2R = -ZDR + ALAS + if P2R < (-ELIM) { + goto TwoSixtyThree + } + tmp = cmplx.Log(complex(S2R, S2I)) + STR = real(tmp) + STI = imag(tmp) + P2R = -ZDR + STR + P2I = -ZDI + STI + P2M = math.Exp(P2R) / TOL + // sin, cos = math.Sincos(P2I) + P1R = P2M * math.Cos(P2I) + P1I = P2M * math.Sin(P2I) + p = complex(P1R, P1I) + NW = Zuchk(p, ASCLE, TOL) + if NW != 0 { + goto TwoSixtyThree + } + J = 3 - J + CYR[J] = P1R + CYI[J] = P1I + if IC == (I - 1) { + goto TwoSixtyFour + } + IC = I + continue + TwoSixtyThree: + if ALAS < HELIM { + continue + } + ZDR = ZDR - ELIM + S1R = S1R * CELMR + S1I = S1I * CELMR + S2R = S2R * CELMR + S2I = S2I * CELMR + } + if N != 1 { + goto TwoSeventy + } + S1R = S2R + S1I = S2I + goto TwoSeventy +TwoSixtyFour: + KFLAG = 1 + INUB = I + 1 + S2R = CYR[J] + S2I = CYI[J] + J = 3 - J + S1R = CYR[J] + S1I = CYI[J] + if INUB <= INU { + goto TwoTwentyFive + } + if N != 1 { + goto TwoFourty + } + S1R = S2R + S1I = S2I + goto TwoFourty +TwoSeventy: + YR[1] = S1R + YI[1] = S1I + if N == 1 { + goto TwoEighty + } + YR[2] = S2R + YI[2] = S2I +TwoEighty: + ASCLE = BRY[1] + ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM = Zkscl(ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM) + INU = N - NZ + if INU <= 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = NZ + 1 + S1R = YR[KK] + S1I = YI[KK] + YR[KK] = S1R * CSRR[1] + YI[KK] = S1I * CSRR[1] + if INU == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = NZ + 2 + S2R = YR[KK] + S2I = YI[KK] + YR[KK] = S2R * CSRR[1] + YI[KK] = S2I * CSRR[1] + if INU == 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + T2 = FNU + float64(float32(KK-1)) + CKR = T2 * RZR + CKI = T2 * RZI + KFLAG = 1 + goto TwoFifty +TwoNinety: + + // SCALE BY math.Exp(Z), IFLAG = 1 CASES. + + KODED = 2 + IFLAG = 1 + KFLAG = 2 + goto OneTwenty + + // FNU=HALF ODD INTEGER CASE, DNU=-0.5 +ThreeHundred: + S1R = COEFR + S1I = COEFI + S2R = COEFR + S2I = COEFI + goto TwoTen + +ThreeTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +// SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE +// ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN +// return WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL. +func Zkscl(ZRR, ZRI, FNU float64, N int, YR, YI []float64, NZ int, RZR, RZI, ASCLE, TOL, ELIM float64) ( + ZRRout, ZRIout, FNUout float64, Nout int, YRout, YIout []float64, NZout int, RZRout, RZIout, ASCLEout, TOLout, ELIMout float64) { + var ACS, AS, CKI, CKR, CSI, CSR, FN, STR, S1I, S1R, S2I, + S2R, ZEROI, ZEROR, ZDR, ZDI, CELMR, ELM, HELIM, ALAS float64 + + var I, IC, KK, NN, NW int + var tmp, c complex128 + var CYR, CYI [3]float64 + var sin, cos float64 + + // DIMENSION YR(N), YI(N), CYR(2), CYI(2) + ZEROR = 0 + ZEROI = 0 + NZ = 0 + IC = 0 + NN = min(2, N) + for I = 1; I <= NN; I++ { + S1R = YR[I] + S1I = YI[I] + CYR[I] = S1R + CYI[I] = S1I + AS = cmplx.Abs(complex(S1R, S1I)) + ACS = -ZRR + math.Log(AS) + NZ = NZ + 1 + YR[I] = ZEROR + YI[I] = ZEROI + if ACS < (-ELIM) { + continue + } + + tmp = cmplx.Log(complex(S1R, S1I)) + CSR = real(tmp) + CSI = imag(tmp) + CSR = CSR - ZRR + CSI = CSI - ZRI + STR = math.Exp(CSR) / TOL + // sin, cos = math.Sincos(CSI) + CSR = STR * math.Cos(CSI) + CSI = STR * math.Sin(CSI) + c = complex(CSR, CSI) + NW = Zuchk(c, ASCLE, TOL) + if NW != 0 { + continue + } + YR[I] = CSR + YI[I] = CSI + IC = I + NZ = NZ - 1 + } + if N == 1 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + if IC > 1 { + goto Twenty + } + YR[1] = ZEROR + YI[1] = ZEROI + NZ = 2 +Twenty: + if N == 2 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + if NZ == 0 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + FN = FNU + 1.0E0 + CKR = FN * RZR + CKI = FN * RZI + S1R = CYR[1] + S1I = CYI[1] + S2R = CYR[2] + S2I = CYI[2] + HELIM = 0.5E0 * ELIM + ELM = math.Exp(-ELIM) + CELMR = ELM + ZDR = ZRR + ZDI = ZRI + + // FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF + // S2 GETS LARGER THAN EXP(ELIM/2) + for I = 3; I <= N; I++ { + KK = I + CSR = S2R + CSI = S2I + S2R = CKR*CSR - CKI*CSI + S1R + S2I = CKI*CSR + CKR*CSI + S1I + S1R = CSR + S1I = CSI + CKR = CKR + RZR + CKI = CKI + RZI + AS = cmplx.Abs(complex(S2R, S2I)) + ALAS = math.Log(AS) + ACS = -ZDR + ALAS + NZ = NZ + 1 + YR[I] = ZEROR + YI[I] = ZEROI + if ACS < (-ELIM) { + goto TwentyFive + } + tmp = cmplx.Log(complex(S2R, S2I)) + CSR = real(tmp) + CSI = imag(tmp) + CSR = CSR - ZDR + CSI = CSI - ZDI + STR = math.Exp(CSR) / TOL + sin, cos = math.Sincos(CSI) + CSR = STR * cos + CSI = STR * sin + c = complex(CSR, CSI) + NW = Zuchk(c, ASCLE, TOL) + if NW != 0 { + goto TwentyFive + } + YR[I] = CSR + YI[I] = CSI + NZ = NZ - 1 + if IC == KK-1 { + goto Fourty + } + IC = KK + continue + TwentyFive: + if ALAS < HELIM { + continue + } + ZDR = ZDR - ELIM + S1R = S1R * CELMR + S1I = S1I * CELMR + S2R = S2R * CELMR + S2I = S2I * CELMR + } + NZ = N + if IC == N { + NZ = N - 1 + } + goto FourtyFive +Fourty: + NZ = KK - 2 +FourtyFive: + for I = 1; I <= NZ; I++ { + YR[I] = ZEROR + YI[I] = ZEROI + } + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM +} + +// Zuchk tests whether the magnitude of the real or imaginary part would +// underflow when y is scaled by tol. +// +// y enters as a scaled quantity whose magnitude is greater than +// 1e3 + 3*dmach(1)/tol +// y is accepted if the underflow is at least one precision below the magnitude +// of the largest component. Otherwise an underflow is assumed as the phase angle +// does not have sufficient accuracy. +func Zuchk(y complex128, scale, tol float64) int { + absR := math.Abs(real(y)) + absI := math.Abs(imag(y)) + minAbs := math.Min(absR, absI) + if minAbs > scale { + return 0 + } + maxAbs := math.Max(absR, absI) + minAbs /= tol + if maxAbs < minAbs { + return 1 + } + return 0 +} + +// ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA +// +// K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN) +// MP=PI*MR*CMPLX(0.0,1.0) +// +// TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT +// HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1. +// ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND +// RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT if ZACON +// IS CALLED FROM ZAIRY. +func Zacai(ZR, ZI, FNU float64, KODE, MR, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, MRout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + var ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR, + CSPNI, C1R, C1I, C2R, C2I, DFNU, FMR, PI, + SGN, YY, ZNR, ZNI float64 + var INU, IUF, NN, NW int + var zn, c1, c2, z complex128 + var y []complex128 + //var sin, cos float64 + + CYR := []float64{math.NaN(), 0, 0} + CYI := []float64{math.NaN(), 0, 0} + + PI = math.Pi + NZ = 0 + ZNR = -ZR + ZNI = -ZI + AZ = cmplx.Abs(complex(ZR, ZI)) + NN = N + DFNU = FNU + float64(float32(N-1)) + if AZ <= 2.0E0 { + goto Ten + } + if AZ*AZ*0.25 > DFNU+1.0E0 { + goto Twenty + } +Ten: + // POWER SERIES FOR THE I FUNCTION. + z = complex(ZNR, ZNI) + y = make([]complex128, len(YR)) + for i, v := range YR { + y[i] = complex(v, YI[i]) + } + NW = Zseri(z, FNU, KODE, NN, y[1:], TOL, ELIM, ALIM) + for i, v := range y { + YR[i] = real(v) + YI[i] = imag(v) + } + goto Fourty +Twenty: + if AZ < RL { + goto Thirty + } + // ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION. + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM = Zasyi(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM) + if NW < 0 { + goto Eighty + } + goto Fourty +Thirty: + // MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL = Zmlri(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL) + if NW < 0 { + goto Eighty + } +Fourty: + // ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION. + ZNR, ZNI, FNU, KODE, _, CYR, CYI, NW, TOL, ELIM, ALIM = Zbknu(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, NW, TOL, ELIM, ALIM) + if NW != 0 { + goto Eighty + } + FMR = float64(float32(MR)) + SGN = -math.Copysign(PI, FMR) + CSGNR = 0.0E0 + CSGNI = SGN + if KODE == 1 { + goto Fifty + } + YY = -ZNI + //sin, cos = math.Sincos(YY) + CSGNR = -CSGNI * math.Sin(YY) + CSGNI = CSGNI * math.Cos(YY) +Fifty: + // CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE + // WHEN FNU IS LARGE + INU = int(float32(FNU)) + ARG = (FNU - float64(float32(INU))) * SGN + //sin, cos = math.Sincos(ARG) + CSPNR = math.Cos(ARG) + CSPNI = math.Sin(ARG) + if INU%2 == 0 { + goto Sixty + } + CSPNR = -CSPNR + CSPNI = -CSPNI +Sixty: + C1R = CYR[1] + C1I = CYI[1] + C2R = YR[1] + C2I = YI[1] + if KODE == 1 { + goto Seventy + } + IUF = 0 + ASCLE = 1.0E+3 * dmach[1] / TOL + zn = complex(ZNR, ZNI) + c1 = complex(C1R, C1I) + c2 = complex(C2R, C2I) + c1, c2, NW, IUF = Zs1s2(zn, c1, c2, ASCLE, ALIM, IUF) + C1R = real(c1) + C1I = imag(c1) + C2R = real(c2) + C2I = imag(c2) + NZ = NZ + NW +Seventy: + YR[1] = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I + YI[1] = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +Eighty: + NZ = -1 + if NW == -2 { + NZ = -2 + } + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +// ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY +// MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE +// REGION CABS(Z)>MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL return. +// NZ<0 INDICATES AN OVERFLOW ON KODE=1. +func Zasyi(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + var AA, AEZ, AK, AK1I, AK1R, ARG, ARM, ATOL, + AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI, + CZR, DFNU, DKI, DKR, DNU2, EZI, EZR, FDN, PI, P1I, + P1R, RAZ, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I, + S2R, TZI, TZR, ZEROI, ZEROR float64 + + var I, IB, IL, INU, J, JL, K, KODED, M, NN int + var tmp complex128 + // var sin, cos float64 + + PI = math.Pi + RTPI = 0.159154943091895336E0 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + NZ = 0 + AZ = cmplx.Abs(complex(ZR, ZI)) + ARM = 1.0E3 * dmach[1] + RTR1 = math.Sqrt(ARM) + IL = min(2, N) + DFNU = FNU + float64(float32(N-IL)) + + // OVERFLOW TEST + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + AK1R = RTPI * STR * RAZ + AK1I = RTPI * STI * RAZ + tmp = cmplx.Sqrt(complex(AK1R, AK1I)) + AK1R = real(tmp) + AK1I = imag(tmp) + CZR = ZR + CZI = ZI + if KODE != 2 { + goto Ten + } + CZR = ZEROR + CZI = ZI +Ten: + if math.Abs(CZR) > ELIM { + goto OneHundred + } + DNU2 = DFNU + DFNU + KODED = 1 + if (math.Abs(CZR) > ALIM) && (N > 2) { + goto Twenty + } + KODED = 0 + tmp = cmplx.Exp(complex(CZR, CZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(AK1R, AK1I) * complex(STR, STI) + AK1R = real(tmp) + AK1I = imag(tmp) +Twenty: + FDN = 0.0E0 + if DNU2 > RTR1 { + FDN = DNU2 * DNU2 + } + EZR = ZR * 8.0E0 + EZI = ZI * 8.0E0 + + // WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE + // FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE + // EXPANSION FOR THE IMAGINARY PART. + AEZ = 8.0E0 * AZ + S = TOL / AEZ + JL = int(float32(RL+RL)) + 2 + P1R = ZEROR + P1I = ZEROI + if ZI == 0.0E0 { + goto Thirty + } + + // CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF + // SIGNIFICANCE WHEN FNU OR N IS LARGE + INU = int(float32(FNU)) + ARG = (FNU - float64(float32(INU))) * PI + INU = INU + N - IL + //sin, cos = math.Sincos(ARG) + AK = -math.Sin(ARG) + BK = math.Cos(ARG) + if ZI < 0.0E0 { + BK = -BK + } + P1R = AK + P1I = BK + if INU%2 == 0 { + goto Thirty + } + P1R = -P1R + P1I = -P1I +Thirty: + for K = 1; K <= IL; K++ { + SQK = FDN - 1.0E0 + ATOL = S * math.Abs(SQK) + SGN = 1.0E0 + CS1R = CONER + CS1I = CONEI + CS2R = CONER + CS2I = CONEI + CKR = CONER + CKI = CONEI + AK = 0.0E0 + AA = 1.0E0 + BB = AEZ + DKR = EZR + DKI = EZI + // TODO(btracey): This loop is executed tens of thousands of times. Why? + // is that really necessary? + for J = 1; J <= JL; J++ { + tmp = complex(CKR, CKI) / complex(DKR, DKI) + STR = real(tmp) + STI = imag(tmp) + CKR = STR * SQK + CKI = STI * SQK + CS2R = CS2R + CKR + CS2I = CS2I + CKI + SGN = -SGN + CS1R = CS1R + CKR*SGN + CS1I = CS1I + CKI*SGN + DKR = DKR + EZR + DKI = DKI + EZI + AA = AA * math.Abs(SQK) / BB + BB = BB + AEZ + AK = AK + 8.0E0 + SQK = SQK - AK + if AA <= ATOL { + goto Fifty + } + } + goto OneTen + Fifty: + S2R = CS1R + S2I = CS1I + if ZR+ZR >= ELIM { + goto Sixty + } + TZR = ZR + ZR + TZI = ZI + ZI + tmp = cmplx.Exp(complex(-TZR, -TZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(STR, STI) * complex(P1R, P1I) + STR = real(tmp) + STI = imag(tmp) + tmp = complex(STR, STI) * complex(CS2R, CS2I) + STR = real(tmp) + STI = imag(tmp) + S2R = S2R + STR + S2I = S2I + STI + Sixty: + FDN = FDN + 8.0E0*DFNU + 4.0E0 + P1R = -P1R + P1I = -P1I + M = N - IL + K + YR[M] = S2R*AK1R - S2I*AK1I + YI[M] = S2R*AK1I + S2I*AK1R + } + if N <= 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM + } + NN = N + K = NN - 2 + AK = float64(float32(K)) + STR = ZR * RAZ + STI = -ZI * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + IB = 3 + for I = IB; I <= NN; I++ { + YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2] + YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2] + AK = AK - 1.0E0 + K = K - 1 + } + if KODED == 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM + } + tmp = cmplx.Exp(complex(CZR, CZI)) + CKR = real(tmp) + CKI = imag(tmp) + for I = 1; I <= NN; I++ { + STR = YR[I]*CKR - YI[I]*CKI + YI[I] = YR[I]*CKI + YI[I]*CKR + YR[I] = STR + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +OneHundred: + NZ = -1 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +OneTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +// ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z)>=0.0 BY THE +// MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES. +func Zmlri(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout float64) { + var ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI, + CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, PTI, PTR, P1I, + P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI, + SUMR, TFNF, TST, ZEROI, ZEROR float64 + var I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, M int + var tmp complex128 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + SCLE = dmach[1] / TOL + NZ = 0 + AZ = cmplx.Abs(complex(ZR, ZI)) + IAZ = int(float32(AZ)) + IFNU = int(float32(FNU)) + INU = IFNU + N - 1 + AT = float64(float32(IAZ)) + 1.0E0 + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + CKR = STR * AT * RAZ + CKI = STI * AT * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + ACK = (AT + 1.0E0) * RAZ + RHO = ACK + math.Sqrt(ACK*ACK-1.0E0) + RHO2 = RHO * RHO + TST = (RHO2 + RHO2) / ((RHO2 - 1.0E0) * (RHO - 1.0E0)) + TST = TST / TOL + + // COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES. + //fmt.Println("before loop", P2R, P2I, CKR, CKI, RZR, RZI, TST, AK) + AK = AT + for I = 1; I <= 80; I++ { + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR - CKI*PTI) + P2I = P1I - (CKI*PTR + CKR*PTI) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = cmplx.Abs(complex(P2R, P2I)) + if AP > TST*AK*AK { + goto Twenty + } + AK = AK + 1.0E0 + } + goto OneTen +Twenty: + I = I + 1 + K = 0 + if INU < IAZ { + goto Fourty + } + // COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS. + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + AT = float64(float32(INU)) + 1.0E0 + STR = ZR * RAZ + STI = -ZI * RAZ + CKR = STR * AT * RAZ + CKI = STI * AT * RAZ + ACK = AT * RAZ + TST = math.Sqrt(ACK / TOL) + ITIME = 1 + for K = 1; K <= 80; K++ { + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR - CKI*PTI) + P2I = P1I - (CKR*PTI + CKI*PTR) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = cmplx.Abs(complex(P2R, P2I)) + if AP < TST { + continue + } + if ITIME == 2 { + goto Fourty + } + ACK = cmplx.Abs(complex(CKR, CKI)) + FLAM = ACK + math.Sqrt(ACK*ACK-1.0E0) + FKAP = AP / cmplx.Abs(complex(P1R, P1I)) + RHO = math.Min(FLAM, FKAP) + TST = TST * math.Sqrt(RHO/(RHO*RHO-1.0E0)) + ITIME = 2 + } + goto OneTen +Fourty: + // BACKWARD RECURRENCE AND SUM NORMALIZING RELATION. + K = K + 1 + KK = max(I+IAZ, K+INU) + FKK = float64(float32(KK)) + P1R = ZEROR + P1I = ZEROI + + // SCALE P2 AND SUM BY SCLE. + P2R = SCLE + P2I = ZEROI + FNF = FNU - float64(float32(IFNU)) + TFNF = FNF + FNF + BK = dgamln(FKK+TFNF+1.0E0, IDUM) - dgamln(FKK+1.0E0, IDUM) - dgamln(TFNF+1.0E0, IDUM) + BK = math.Exp(BK) + SUMR = ZEROR + SUMI = ZEROI + KM = KK - INU + for I = 1; I <= KM; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + } + YR[N] = P2R + YI[N] = P2I + if N == 1 { + goto Seventy + } + for I = 2; I <= N; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + M = N - I + 1 + YR[M] = P2R + YI[M] = P2I + } +Seventy: + if IFNU <= 0 { + goto Ninety + } + for I = 1; I <= IFNU; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + } +Ninety: + PTR = ZR + PTI = ZI + if KODE == 2 { + PTR = ZEROR + } + tmp = cmplx.Log(complex(RZR, RZI)) + STR = real(tmp) + STI = imag(tmp) + P1R = -FNF*STR + PTR + P1I = -FNF*STI + PTI + AP = dgamln(1.0E0+FNF, IDUM) + PTR = P1R - AP + PTI = P1I + + // THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW + // IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES. + P2R = P2R + SUMR + P2I = P2I + SUMI + AP = cmplx.Abs(complex(P2R, P2I)) + P1R = 1.0E0 / AP + tmp = cmplx.Exp(complex(PTR, PTI)) + STR = real(tmp) + STI = imag(tmp) + CKR = STR * P1R + CKI = STI * P1R + PTR = P2R * P1R + PTI = -P2I * P1R + tmp = complex(CKR, CKI) * complex(PTR, PTI) + CNORMR = real(tmp) + CNORMI = imag(tmp) + for I = 1; I <= N; I++ { + STR = YR[I]*CNORMR - YI[I]*CNORMI + YI[I] = YR[I]*CNORMI + YI[I]*CNORMR + YR[I] = STR + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +OneTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +} + +// Zseri computes the I bessel function for real(z) >= 0 by means of the power +// series for large |z| in the region |z| <= 2*sqrt(fnu+1). +// +// nz = 0 is a normal return. nz > 0 means that the last nz components were set +// to zero due to underflow. nz < 0 means that underflow occurred, but the +// condition |z| <= 2*sqrt(fnu+1) was violated and the computation must be +// completed in another routine with n -= abs(nz). +func Zseri(z complex128, fnu float64, kode, n int, y []complex128, tol, elim, alim float64) (nz int) { + // TOOD(btracey): The original fortran line is "ARM = 1.0D+3*D1MACH(1)". Evidently, in Fortran + // this is interpreted as one to the power of +3*D1MACH(1). While it is possible + // this was intentional, it seems unlikely. + arm := 1000 * dmach[1] + az := cmplx.Abs(z) + if az < arm { + for i := 0; i < n; i++ { + y[i] = 0 + } + if fnu == 0 { + y[0] = 1 + n-- + } + if az == 0 { + return 0 + } + return n + } + hz := 0.5 * z + var cz complex128 + var acz float64 + if az > math.Sqrt(arm) { + cz = hz * hz + acz = cmplx.Abs(cz) + } + NN := n + ck := cmplx.Log(hz) + var ak1 complex128 + for { + dfnu := fnu + float64(NN-1) + // Underflow test. + ak1 = ck * complex(dfnu, 0) + ak := dgamln(dfnu+1, 0) + ak1 -= complex(ak, 0) + if kode == 2 { + ak1 -= complex(real(z), 0) + } + if real(ak1) > -elim { + break + } + nz++ + y[NN-1] = 0 + if acz > dfnu { + // Return with nz < 0 if abs(Z*Z/4)>fnu+u-nz-1 complete the calculation + // in cbinu with n = n - abs(nz). + nz *= -1 + return nz + } + NN-- + if NN == 0 { + return nz + } + } + crscr := 1.0 + var flag int + var scale float64 + aa := real(ak1) + if aa <= -alim { + flag = 1 + crscr = tol + scale = arm / tol + aa -= math.Log(tol) + } + var w [2]complex128 + for { + coef := cmplx.Exp(complex(aa, imag(ak1))) + atol := tol * acz / (fnu + float64(NN)) + for i := 0; i < min(2, NN); i++ { + FNUP := fnu + float64(NN-i) + s1 := 1 + 0i + if acz >= tol*FNUP { + ak2 := 1 + 0i + ak := FNUP + 2 + S := FNUP + scl := 2.0 + first := true + for first || scl > atol { + ak2 = ak2 * cz * complex(1/S, 0) + scl *= acz / S + s1 += ak2 + S += ak + ak += 2 + first = false + } + } + s2 := s1 * coef + w[i] = s2 + if flag == 1 { + if Zuchk(s2, scale, tol) != 0 { + var full bool + var dfnu float64 + // This code is similar to the code that exists above. The + // code copying is here because the original Fortran used + // a goto to solve the loop-and-a-half problem. Removing the + // goto makes the behavior of the function and variable scoping + // much clearer, but requires copying this code due to Go's + // goto rules. + for { + if full { + dfnu = fnu + float64(NN-1) + // Underflow test. + ak1 = ck * complex(dfnu, 0) + ak1 -= complex(dgamln(dfnu+1, 0), 0) + if kode == 2 { + ak1 -= complex(real(z), 0) + } + if real(ak1) > -elim { + break + } + } else { + full = true + } + nz++ + y[NN-1] = 0 + if acz > dfnu { + // Return with nz < 0 if abs(Z*Z/4)>fnu+u-nz-1 complete the calculation + // in cbinu with n = n - abs(nz). + nz *= -1 + return nz + } + NN-- + if NN == 0 { + return nz + } + } + continue + } + } + y[NN-i-1] = s2 * complex(crscr, 0) + coef /= hz + coef *= complex(FNUP-1, 0) + } + break + } + if NN <= 2 { + return nz + } + rz := complex(2*real(z)/(az*az), -2*imag(z)/(az*az)) + if flag == 0 { + for i := NN - 3; i >= 0; i-- { + y[i] = complex(float64(i+1)+fnu, 0)*rz*y[i+1] + y[i+2] + } + return nz + } + + // exp(-alim)=exp(-elim)/tol=approximately one digit of precision above the + // underflow limit, which equals scale = dmach[1)*SS*1e3. + s1 := w[0] + s2 := w[1] + for K := NN - 3; K >= 0; K-- { + s1, s2 = s2, s1+complex(float64(K+1)+fnu, 0)*(rz*s2) + ck := s2 * complex(crscr, 0) + y[K] = ck + if cmplx.Abs(ck) > scale { + for ; K >= 0; K-- { + y[K] = complex(float64(K+1)+fnu, 0)*rz*y[K+1] + y[K+2] + } + return nz + } + } + return nz +} + +// Zs1s2 tests for a possible underflow resulting from the addition of the I and +// K functions in the analytic continuation formula where s1 == K function and +// s2 == I function. +// +// When kode == 1, the I and K functions are different orders of magnitude. +// +// When kode == 2, they may both be of the same order of magnitude, but the maximum +// must be at least one precision above the underflow limit. +func Zs1s2(zr, s1, s2 complex128, scale, lim float64, iuf int) (s1o, s2o complex128, nz, iufo int) { + if s1 == 0 || math.Log(cmplx.Abs(s1))-2*real(zr) < -lim { + if cmplx.Abs(s2) > scale { + return 0, s2, 0, iuf + } + return 0, 0, 1, 0 + } + // TODO(btracey): Written like this for numerical rounding reasons. + // Fix once we're sure other changes are correct. + s1 = cmplx.Exp(cmplx.Log(s1) - zr - zr) + if math.Max(cmplx.Abs(s1), cmplx.Abs(s2)) > scale { + return s1, s2, 0, iuf + 1 + } + return 0, 0, 1, 0 +} + +func dgamln(z float64, ierr int) float64 { + //return amoslib.DgamlnFort(z) + // Go implementation. + if z < 0 { + return 0 + } + a2, _ := math.Lgamma(z) + return a2 +} diff --git a/mathext/internal/amos/amos_test.go b/mathext/internal/amos/amos_test.go new file mode 100644 index 00000000..59cdfa4f --- /dev/null +++ b/mathext/internal/amos/amos_test.go @@ -0,0 +1,521 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package amos + +import ( + "math" + "math/rand" + "strconv" + "testing" + + "gonum.org/v1/gonum/floats" +) + +type input struct { + x []float64 + is []int + kode int + id int + yr []float64 + yi []float64 + n int + tol float64 +} + +func randnum(rnd *rand.Rand) float64 { + r := 2e2 // Fortran has infinite loop if this is set higher than 2e3 + if rnd.Float64() > 0.99 { + return 0 + } + return rnd.Float64()*r - r/2 +} + +func randInput(rnd *rand.Rand) input { + x := make([]float64, 8) + for j := range x { + x[j] = randnum(rnd) + } + is := make([]int, 3) + for j := range is { + is[j] = rand.Intn(1000) + } + kode := rand.Intn(2) + 1 + id := rand.Intn(2) + n := rand.Intn(5) + 1 + yr := make([]float64, n+1) + yi := make([]float64, n+1) + for j := range yr { + yr[j] = randnum(rnd) + yi[j] = randnum(rnd) + } + tol := 1e-14 + + return input{ + x, is, kode, id, yr, yi, n, tol, + } +} + +const nInputs = 100000 + +func TestAiry(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zairytest(t, in.x, in.kode, in.id) + } +} + +func TestZacai(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zacaitest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZbknu(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zbknutest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZasyi(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zasyitest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZseri(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zseritest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZmlri(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zmlritest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi, in.kode) + } +} + +func TestZkscl(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zkscltest(t, in.x, in.is, in.tol, in.n, in.yr, in.yi) + } +} + +func TestZuchk(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zuchktest(t, in.x, in.is, in.tol) + } +} + +func TestZs1s2(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for i := 0; i < nInputs; i++ { + in := randInput(rnd) + zs1s2test(t, in.x, in.is) + } +} + +func zs1s2test(t *testing.T, x []float64, is []int) { + + type data struct { + ZRR, ZRI, S1R, S1I, S2R, S2I float64 + NZ int + ASCLE, ALIM float64 + IUF int + } + + input := data{ + x[0], x[1], x[2], x[3], x[4], x[5], + is[0], + x[6], x[7], + is[1], + } + + zr := complex(input.ZRR, input.ZRI) + s1 := complex(input.S1R, input.S1I) + s2 := complex(input.S2R, input.S2I) + impl := func(input data) data { + s1, s2, nz, iuf := Zs1s2(zr, s1, s2, input.ASCLE, input.ALIM, input.IUF) + zrr := real(zr) + zri := imag(zr) + s1r := real(s1) + s1i := imag(s1) + s2r := real(s2) + s2i := imag(s2) + alim := input.ALIM + ascle := input.ASCLE + return data{zrr, zri, s1r, s1i, s2r, s2i, nz, ascle, alim, iuf} + } + + comp := func(input data) data { + zrr, zri, s1r, s1i, s2r, s2i, nz, ascle, alim, iuf := + zs1s2Orig(input.ZRR, input.ZRI, input.S1R, input.S1I, input.S2R, input.S2I, input.NZ, input.ASCLE, input.ALIM, input.IUF) + return data{zrr, zri, s1r, s1i, s2r, s2i, nz, ascle, alim, iuf} + } + + oi := impl(input) + oc := comp(input) + + sameF64(t, "zs1s2 zrr", oc.ZRR, oi.ZRR) + sameF64(t, "zs1s2 zri", oc.ZRI, oi.ZRI) + sameF64(t, "zs1s2 s1r", oc.S1R, oi.S1R) + sameF64(t, "zs1s2 s1i", oc.S1I, oi.S1I) + sameF64(t, "zs1s2 s2r", oc.S2R, oi.S2R) + sameF64(t, "zs1s2 s2i", oc.S2I, oi.S2I) + sameF64(t, "zs1s2 ascle", oc.ASCLE, oi.ASCLE) + sameF64(t, "zs1s2 alim", oc.ALIM, oi.ALIM) + sameInt(t, "iuf", oc.IUF, oi.IUF) + sameInt(t, "nz", oc.NZ, oi.NZ) +} + +func zuchktest(t *testing.T, x []float64, is []int, tol float64) { + YR := x[0] + YI := x[1] + NZ := is[0] + ASCLE := x[2] + TOL := tol + + YRfort, YIfort, NZfort, ASCLEfort, TOLfort := zuchkOrig(YR, YI, NZ, ASCLE, TOL) + y := complex(YR, YI) + NZamos := Zuchk(y, ASCLE, TOL) + YRamos := real(y) + YIamos := imag(y) + ASCLEamos := ASCLE + TOLamos := TOL + + sameF64(t, "zuchk yr", YRfort, YRamos) + sameF64(t, "zuchk yi", YIfort, YIamos) + sameInt(t, "zuchk nz", NZfort, NZamos) + sameF64(t, "zuchk ascle", ASCLEfort, ASCLEamos) + sameF64(t, "zuchk tol", TOLfort, TOLamos) +} + +func zkscltest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64) { + ZRR := x[0] + ZRI := x[1] + FNU := x[2] + NZ := is[1] + ELIM := x[3] + ASCLE := x[4] + RZR := x[6] + RZI := x[7] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRRfort, ZRIfort, FNUfort, Nfort, YRfort, YIfort, NZfort, RZRfort, RZIfort, ASCLEfort, TOLfort, ELIMfort := + zksclOrig(ZRR, ZRI, FNU, n, yrfort, yifort, NZ, RZR, RZI, ASCLE, tol, ELIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRRamos, ZRIamos, FNUamos, Namos, YRamos, YIamos, NZamos, RZRamos, RZIamos, ASCLEamos, TOLamos, ELIMamos := + Zkscl(ZRR, ZRI, FNU, n, yramos, yiamos, NZ, RZR, RZI, ASCLE, tol, ELIM) + + sameF64(t, "zkscl zrr", ZRRfort, ZRRamos) + sameF64(t, "zkscl zri", ZRIfort, ZRIamos) + sameF64(t, "zkscl fnu", FNUfort, FNUamos) + sameInt(t, "zkscl n", Nfort, Namos) + sameInt(t, "zkscl nz", NZfort, NZamos) + sameF64(t, "zkscl rzr", RZRfort, RZRamos) + sameF64(t, "zkscl rzi", RZIfort, RZIamos) + sameF64(t, "zkscl ascle", ASCLEfort, ASCLEamos) + sameF64(t, "zkscl tol", TOLfort, TOLamos) + sameF64(t, "zkscl elim", ELIMfort, ELIMamos) + + sameF64SApprox(t, "zkscl yr", YRfort, YRamos, 1e-14) + sameF64SApprox(t, "zkscl yi", YIfort, YIamos, 1e-14) +} + +func zmlritest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, Nfort, YRfort, YIfort, NZfort, TOLfort := + zmlriOrig(ZR, ZI, FNU, KODE, n, yrfort, yifort, NZ, tol) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRamos, ZIamos, FNUamos, KODEamos, Namos, YRamos, YIamos, NZamos, TOLamos := + Zmlri(ZR, ZI, FNU, KODE, n, yramos, yiamos, NZ, tol) + + sameF64(t, "zmlri zr", ZRfort, ZRamos) + sameF64(t, "zmlri zi", ZIfort, ZIamos) + sameF64(t, "zmlri fnu", FNUfort, FNUamos) + sameInt(t, "zmlri kode", KODEfort, KODEamos) + sameInt(t, "zmlri n", Nfort, Namos) + sameInt(t, "zmlri nz", NZfort, NZamos) + sameF64(t, "zmlri tol", TOLfort, TOLamos) + + sameF64S(t, "zmlri yr", YRfort, YRamos) + sameF64S(t, "zmlri yi", YIfort, YIamos) +} + +func zseritest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + ELIM := x[3] + ALIM := x[4] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, Nfort, YRfort, YIfort, NZfort, TOLfort, ELIMfort, ALIMfort := + zseriOrig(ZR, ZI, FNU, KODE, n, yrfort, yifort, NZ, tol, ELIM, ALIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + y := make([]complex128, len(yramos)) + for i, v := range yramos { + y[i] = complex(v, yiamos[i]) + } + z := complex(ZR, ZI) + + NZamos := Zseri(z, FNU, KODE, n, y[1:], tol, ELIM, ALIM) + + ZRamos := real(z) + ZIamos := imag(z) + FNUamos := FNU + KODEamos := KODE + Namos := n + TOLamos := tol + ELIMamos := ELIM + ALIMamos := ALIM + YRamos := make([]float64, len(y)) + YIamos := make([]float64, len(y)) + for i, v := range y { + YRamos[i] = real(v) + YIamos[i] = imag(v) + } + + sameF64(t, "zseri zr", ZRfort, ZRamos) + sameF64(t, "zseri zi", ZIfort, ZIamos) + sameF64(t, "zseri fnu", FNUfort, FNUamos) + sameInt(t, "zseri kode", KODEfort, KODEamos) + sameInt(t, "zseri n", Nfort, Namos) + sameInt(t, "zseri nz", NZfort, NZamos) + sameF64(t, "zseri tol", TOLfort, TOLamos) + sameF64(t, "zseri elim", ELIMfort, ELIMamos) + sameF64(t, "zseri elim", ALIMfort, ALIMamos) + + sameF64SApprox(t, "zseri yr", YRfort, YRamos, 1e-10) + sameF64SApprox(t, "zseri yi", YIfort, YIamos, 1e-10) +} + +func zasyitest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + ELIM := x[3] + ALIM := x[4] + RL := x[5] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, Nfort, YRfort, YIfort, NZfort, RLfort, TOLfort, ELIMfort, ALIMfort := + zasyiOrig(ZR, ZI, FNU, KODE, n, yrfort, yifort, NZ, RL, tol, ELIM, ALIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRamos, ZIamos, FNUamos, KODEamos, Namos, YRamos, YIamos, NZamos, RLamos, TOLamos, ELIMamos, ALIMamos := + Zasyi(ZR, ZI, FNU, KODE, n, yramos, yiamos, NZ, RL, tol, ELIM, ALIM) + + sameF64(t, "zasyi zr", ZRfort, ZRamos) + sameF64(t, "zasyi zr", ZIfort, ZIamos) + sameF64(t, "zasyi fnu", FNUfort, FNUamos) + sameInt(t, "zasyi kode", KODEfort, KODEamos) + sameInt(t, "zasyi n", Nfort, Namos) + sameInt(t, "zasyi nz", NZfort, NZamos) + sameF64(t, "zasyi rl", RLfort, RLamos) + sameF64(t, "zasyi tol", TOLfort, TOLamos) + sameF64(t, "zasyi elim", ELIMfort, ELIMamos) + sameF64(t, "zasyi alim", ALIMfort, ALIMamos) + + sameF64SApprox(t, "zasyi yr", YRfort, YRamos, 1e-12) + sameF64SApprox(t, "zasyi yi", YIfort, YIamos, 1e-12) +} + +func zbknutest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + ELIM := x[3] + ALIM := x[4] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, Nfort, YRfort, YIfort, NZfort, TOLfort, ELIMfort, ALIMfort := + zbknuOrig(ZR, ZI, FNU, KODE, n, yrfort, yifort, NZ, tol, ELIM, ALIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRamos, ZIamos, FNUamos, KODEamos, Namos, YRamos, YIamos, NZamos, TOLamos, ELIMamos, ALIMamos := + Zbknu(ZR, ZI, FNU, KODE, n, yramos, yiamos, NZ, tol, ELIM, ALIM) + + sameF64(t, "zbknu zr", ZRfort, ZRamos) + sameF64(t, "zbknu zr", ZIfort, ZIamos) + sameF64(t, "zbknu fnu", FNUfort, FNUamos) + sameInt(t, "zbknu kode", KODEfort, KODEamos) + sameInt(t, "zbknu n", Nfort, Namos) + sameInt(t, "zbknu nz", NZfort, NZamos) + sameF64(t, "zbknu tol", TOLfort, TOLamos) + sameF64(t, "zbknu elim", ELIMfort, ELIMamos) + sameF64(t, "zbknu alim", ALIMfort, ALIMamos) + + sameF64SApprox(t, "zbknu yr", YRfort, YRamos, 1e-12) + sameF64SApprox(t, "zbknu yi", YIfort, YIamos, 1e-12) +} + +func zairytest(t *testing.T, x []float64, kode, id int) { + ZR := x[0] + ZI := x[1] + KODE := kode + ID := id + + AIRfort, AIIfort, NZfort := zairyOrig(ZR, ZI, ID, KODE) + AIRamos, AIIamos, NZamos := Zairy(ZR, ZI, ID, KODE) + + sameF64Approx(t, "zairy air", AIRfort, AIRamos, 1e-12) + sameF64Approx(t, "zairy aii", AIIfort, AIIamos, 1e-12) + sameInt(t, "zairy nz", NZfort, NZamos) +} + +func zacaitest(t *testing.T, x []float64, is []int, tol float64, n int, yr, yi []float64, kode int) { + ZR := x[0] + ZI := x[1] + FNU := x[2] + KODE := kode + NZ := is[1] + MR := is[2] + ELIM := x[3] + ALIM := x[4] + RL := x[5] + + yrfort := make([]float64, len(yr)) + copy(yrfort, yr) + yifort := make([]float64, len(yi)) + copy(yifort, yi) + ZRfort, ZIfort, FNUfort, KODEfort, MRfort, Nfort, YRfort, YIfort, NZfort, RLfort, TOLfort, ELIMfort, ALIMfort := + zacaiOrig(ZR, ZI, FNU, KODE, MR, n, yrfort, yifort, NZ, RL, tol, ELIM, ALIM) + + yramos := make([]float64, len(yr)) + copy(yramos, yr) + yiamos := make([]float64, len(yi)) + copy(yiamos, yi) + ZRamos, ZIamos, FNUamos, KODEamos, MRamos, Namos, YRamos, YIamos, NZamos, RLamos, TOLamos, ELIMamos, ALIMamos := + Zacai(ZR, ZI, FNU, KODE, MR, n, yramos, yiamos, NZ, RL, tol, ELIM, ALIM) + + sameF64(t, "zacai zr", ZRfort, ZRamos) + sameF64(t, "zacai zi", ZIfort, ZIamos) + sameF64(t, "zacai fnu", FNUfort, FNUamos) + sameInt(t, "zacai kode", KODEfort, KODEamos) + sameInt(t, "zacai mr", MRfort, MRamos) + sameInt(t, "zacai n", Nfort, Namos) + sameInt(t, "zacai nz", NZfort, NZamos) + sameF64(t, "zacai rl", RLfort, RLamos) + sameF64(t, "zacai tol", TOLfort, TOLamos) + sameF64(t, "zacai elim", ELIMfort, ELIMamos) + sameF64(t, "zacai elim", ALIMfort, ALIMamos) + + sameF64SApprox(t, "zacai yr", YRfort, YRamos, 1e-12) + sameF64SApprox(t, "zacai yi", YIfort, YIamos, 1e-12) +} + +func sameF64(t *testing.T, str string, c, native float64) { + if math.IsNaN(c) && math.IsNaN(native) { + return + } + if c == native { + return + } + cb := math.Float64bits(c) + nb := math.Float64bits(native) + t.Errorf("Case %s: Float64 mismatch. c = %v, native = %v\n cb: %v, nb: %v\n", str, c, native, cb, nb) +} + +func sameF64Approx(t *testing.T, str string, c, native, tol float64) { + if math.IsNaN(c) && math.IsNaN(native) { + return + } + if floats.EqualWithinAbsOrRel(c, native, tol, tol) { + return + } + // Have a much looser tolerance for correctness when the values are large. + // Floating point noise makes the relative tolerance difference greater for + // higher values. + if c > 1e200 && floats.EqualWithinAbsOrRel(c, native, 10, 10) { + return + } + cb := math.Float64bits(c) + nb := math.Float64bits(native) + t.Errorf("Case %s: Float64 mismatch. c = %v, native = %v\n cb: %v, nb: %v\n", str, c, native, cb, nb) +} + +func sameInt(t *testing.T, str string, c, native int) { + if c != native { + t.Errorf("Case %s: Int mismatch. c = %v, native = %v.", str, c, native) + } +} + +func sameF64S(t *testing.T, str string, c, native []float64) { + if len(c) != len(native) { + panic(str) + } + for i, v := range c { + sameF64(t, str+"_idx_"+strconv.Itoa(i), v, native[i]) + } +} + +func sameF64SApprox(t *testing.T, str string, c, native []float64, tol float64) { + if len(c) != len(native) { + panic(str) + } + for i, v := range c { + sameF64Approx(t, str+"_idx_"+strconv.Itoa(i), v, native[i], tol) + } +} diff --git a/mathext/internal/amos/amoslib/Make.files b/mathext/internal/amos/amoslib/Make.files new file mode 100644 index 00000000..81c7c715 --- /dev/null +++ b/mathext/internal/amos/amoslib/Make.files @@ -0,0 +1,5 @@ +$(CUR_SRCS) += d1mach.f zabs.f zasyi.f zbesk.f zbknu.f zexp.f zmlt.f zshch.f zuni1.f zunk2.f \ + dgamln.f zacai.f zbesh.f zbesy.f zbuni.f zkscl.f zrati.f zsqrt.f zuni2.f zuoik.f \ + i1mach.f zacon.f zbesi.f zbinu.f zbunk.f zlog.f zs1s2.f zuchk.f zunik.f zwrsk.f \ + xerror.f zairy.f zbesj.f zbiry.f zdiv.f zmlri.f zseri.f zunhj.f zunk1.f + diff --git a/mathext/internal/amos/amoslib/d1mach.f b/mathext/internal/amos/amoslib/d1mach.f new file mode 100644 index 00000000..0d344def --- /dev/null +++ b/mathext/internal/amos/amoslib/d1mach.f @@ -0,0 +1,97 @@ +*DECK D1MACH + DOUBLE PRECISION FUNCTION D1MACH(I) +C***BEGIN PROLOGUE D1MACH +C***DATE WRITTEN 750101 (YYMMDD) +C***REVISION DATE 890213 (YYMMDD) +C***CATEGORY NO. R1 +C***KEYWORDS LIBRARY=SLATEC,TYPE=DOUBLE PRECISION(R1MACH-S D1MACH-D), +C MACHINE CONSTANTS +C***AUTHOR FOX, P. A., (BELL LABS) +C HALL, A. D., (BELL LABS) +C SCHRYER, N. L., (BELL LABS) +C***PURPOSE Returns double precision machine dependent constants +C***DESCRIPTION +C +C D1MACH can be used to obtain machine-dependent parameters +C for the local machine environment. It is a function +C subprogram with one (input) argument, and can be called +C as follows, for example +C +C D = D1MACH(I) +C +C where I=1,...,5. The (output) value of D above is +C determined by the (input) value of I. The results for +C various values of I are discussed below. +C +C D1MACH( 1) = B**(EMIN-1), the smallest positive magnitude. +C D1MACH( 2) = B**EMAX*(1 - B**(-T)), the largest magnitude. +C D1MACH( 3) = B**(-T), the smallest relative spacing. +C D1MACH( 4) = B**(1-T), the largest relative spacing. +C D1MACH( 5) = LOG10(B) +C +C Assume double precision numbers are represented in the T-digit, +C base-B form +C +C sign (B**E)*( (X(1)/B) + ... + (X(T)/B**T) ) +C +C where 0 .LE. X(I) .LT. B for I=1,...,T, 0 .LT. X(1), and +C EMIN .LE. E .LE. EMAX. +C +C The values of B, T, EMIN and EMAX are provided in I1MACH as +C follows: +C I1MACH(10) = B, the base. +C I1MACH(14) = T, the number of base-B digits. +C I1MACH(15) = EMIN, the smallest exponent E. +C I1MACH(16) = EMAX, the largest exponent E. +C +C To alter this function for a particular environment, +C the desired set of DATA statements should be activated by +C removing the C from column 1. Also, the values of +C D1MACH(1) - D1MACH(4) should be checked for consistency +C with the local operating system. +C +C***REFERENCES FOX P.A., HALL A.D., SCHRYER N.L.,*FRAMEWORK FOR A +C PORTABLE LIBRARY*, ACM TRANSACTIONS ON MATHEMATICAL +C SOFTWARE, VOL. 4, NO. 2, JUNE 1978, PP. 177-188. +C***ROUTINES CALLED XERROR +C***END PROLOGUE D1MACH +C + INTEGER SMALL(4) + INTEGER LARGE(4) + INTEGER RIGHT(4) + INTEGER DIVER(4) + INTEGER LOG10(4) +C + DOUBLE PRECISION DMACH(5) + SAVE DMACH +C +C EQUIVALENCE (DMACH(1),SMALL(1)) +C EQUIVALENCE (DMACH(2),LARGE(1)) +C EQUIVALENCE (DMACH(3),RIGHT(1)) +C EQUIVALENCE (DMACH(4),DIVER(1)) +C EQUIVALENCE (DMACH(5),LOG10(1)) +C +C MACHINE CONSTANTS FOR THE IBM PC +C ASSUMES THAT ALL ARITHMETIC IS DONE IN DOUBLE PRECISION +C ON 8088, I.E., NOT IN 80 BIT FORM FOR THE 8087. +C + DATA DMACH(1) / 2.23D-308 / +C DATA SMALL(1),SMALL(2) / 2002288515, 1050897 / + DATA DMACH(2) / 1.79D-308 / +C DATA LARGE(1),LARGE(2) / 1487780761, 2146426097 / + DATA DMACH(3) / 1.11D-16 / +C DATA RIGHT(1),RIGHT(2) / -1209488034, 1017118298 / + DATA DMACH(4) / 2.22D-16 / +C DATA DIVER(1),DIVER(2) / -1209488034, 1018166874 / + DATA DMACH(5) / 0.3010299956639812 / +C DATA LOG10(1),LOG10(2) / 1352628735, 1070810131 / +C +C +C***FIRST EXECUTABLE STATEMENT D1MACH + IF (I .LT. 1 .OR. I .GT. 5) + 1 CALL XERROR ('D1MACH -- I OUT OF BOUNDS', 25, 1, 2) +C + D1MACH = DMACH(I) + RETURN +C + END diff --git a/mathext/internal/amos/amoslib/dgamln.f b/mathext/internal/amos/amoslib/dgamln.f new file mode 100644 index 00000000..792014be --- /dev/null +++ b/mathext/internal/amos/amoslib/dgamln.f @@ -0,0 +1,189 @@ + DOUBLE PRECISION FUNCTION DGAMLN(Z,IERR) +C***BEGIN PROLOGUE DGAMLN +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 830501 (YYMMDD) +C***CATEGORY NO. B5F +C***KEYWORDS GAMMA FUNCTION,LOGARITHM OF GAMMA FUNCTION +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE THE LOGARITHM OF THE GAMMA FUNCTION +C***DESCRIPTION +C +C **** A DOUBLE PRECISION ROUTINE **** +C DGAMLN COMPUTES THE NATURAL LOG OF THE GAMMA FUNCTION FOR +C Z.GT.0. THE ASYMPTOTIC EXPANSION IS USED TO GENERATE VALUES +C GREATER THAN ZMIN WHICH ARE ADJUSTED BY THE RECURSION +C G(Z+1)=Z*G(Z) FOR Z.LE.ZMIN. THE FUNCTION WAS MADE AS +C PORTABLE AS POSSIBLE BY COMPUTIMG ZMIN FROM THE NUMBER OF BASE +C 10 DIGITS IN A WORD, RLN=AMAX1(-ALOG10(R1MACH(4)),0.5E-18) +C LIMITED TO 18 DIGITS OF (RELATIVE) ACCURACY. +C +C SINCE INTEGER ARGUMENTS ARE COMMON, A TABLE LOOK UP ON 100 +C VALUES IS USED FOR SPEED OF EXECUTION. +C +C DESCRIPTION OF ARGUMENTS +C +C INPUT Z IS D0UBLE PRECISION +C Z - ARGUMENT, Z.GT.0.0D0 +C +C OUTPUT DGAMLN IS DOUBLE PRECISION +C DGAMLN - NATURAL LOG OF THE GAMMA FUNCTION AT Z.NE.0.0D0 +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN, COMPUTATION COMPLETED +C IERR=1, Z.LE.0.0D0, NO COMPUTATION +C +C +C***REFERENCES COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C***ROUTINES CALLED I1MACH,D1MACH +C***END PROLOGUE DGAMLN + DOUBLE PRECISION CF, CON, FLN, FZ, GLN, RLN, S, TLG, TRM, TST, + * T1, WDTOL, Z, ZDMY, ZINC, ZM, ZMIN, ZP, ZSQ, D1MACH + INTEGER I, IERR, I1M, K, MZ, NZ, I1MACH + DIMENSION CF(22), GLN(100) +C LNGAMMA(N), N=1,100 + DATA GLN(1), GLN(2), GLN(3), GLN(4), GLN(5), GLN(6), GLN(7), + 1 GLN(8), GLN(9), GLN(10), GLN(11), GLN(12), GLN(13), GLN(14), + 2 GLN(15), GLN(16), GLN(17), GLN(18), GLN(19), GLN(20), + 3 GLN(21), GLN(22)/ + 4 0.00000000000000000D+00, 0.00000000000000000D+00, + 5 6.93147180559945309D-01, 1.79175946922805500D+00, + 6 3.17805383034794562D+00, 4.78749174278204599D+00, + 7 6.57925121201010100D+00, 8.52516136106541430D+00, + 8 1.06046029027452502D+01, 1.28018274800814696D+01, + 9 1.51044125730755153D+01, 1.75023078458738858D+01, + A 1.99872144956618861D+01, 2.25521638531234229D+01, + B 2.51912211827386815D+01, 2.78992713838408916D+01, + C 3.06718601060806728D+01, 3.35050734501368889D+01, + D 3.63954452080330536D+01, 3.93398841871994940D+01, + E 4.23356164607534850D+01, 4.53801388984769080D+01/ + DATA GLN(23), GLN(24), GLN(25), GLN(26), GLN(27), GLN(28), + 1 GLN(29), GLN(30), GLN(31), GLN(32), GLN(33), GLN(34), + 2 GLN(35), GLN(36), GLN(37), GLN(38), GLN(39), GLN(40), + 3 GLN(41), GLN(42), GLN(43), GLN(44)/ + 4 4.84711813518352239D+01, 5.16066755677643736D+01, + 5 5.47847293981123192D+01, 5.80036052229805199D+01, + 6 6.12617017610020020D+01, 6.45575386270063311D+01, + 7 6.78897431371815350D+01, 7.12570389671680090D+01, + 8 7.46582363488301644D+01, 7.80922235533153106D+01, + 9 8.15579594561150372D+01, 8.50544670175815174D+01, + A 8.85808275421976788D+01, 9.21361756036870925D+01, + B 9.57196945421432025D+01, 9.93306124547874269D+01, + C 1.02968198614513813D+02, 1.06631760260643459D+02, + D 1.10320639714757395D+02, 1.14034211781461703D+02, + E 1.17771881399745072D+02, 1.21533081515438634D+02/ + DATA GLN(45), GLN(46), GLN(47), GLN(48), GLN(49), GLN(50), + 1 GLN(51), GLN(52), GLN(53), GLN(54), GLN(55), GLN(56), + 2 GLN(57), GLN(58), GLN(59), GLN(60), GLN(61), GLN(62), + 3 GLN(63), GLN(64), GLN(65), GLN(66)/ + 4 1.25317271149356895D+02, 1.29123933639127215D+02, + 5 1.32952575035616310D+02, 1.36802722637326368D+02, + 6 1.40673923648234259D+02, 1.44565743946344886D+02, + 7 1.48477766951773032D+02, 1.52409592584497358D+02, + 8 1.56360836303078785D+02, 1.60331128216630907D+02, + 9 1.64320112263195181D+02, 1.68327445448427652D+02, + A 1.72352797139162802D+02, 1.76395848406997352D+02, + B 1.80456291417543771D+02, 1.84533828861449491D+02, + C 1.88628173423671591D+02, 1.92739047287844902D+02, + D 1.96866181672889994D+02, 2.01009316399281527D+02, + E 2.05168199482641199D+02, 2.09342586752536836D+02/ + DATA GLN(67), GLN(68), GLN(69), GLN(70), GLN(71), GLN(72), + 1 GLN(73), GLN(74), GLN(75), GLN(76), GLN(77), GLN(78), + 2 GLN(79), GLN(80), GLN(81), GLN(82), GLN(83), GLN(84), + 3 GLN(85), GLN(86), GLN(87), GLN(88)/ + 4 2.13532241494563261D+02, 2.17736934113954227D+02, + 5 2.21956441819130334D+02, 2.26190548323727593D+02, + 6 2.30439043565776952D+02, 2.34701723442818268D+02, + 7 2.38978389561834323D+02, 2.43268849002982714D+02, + 8 2.47572914096186884D+02, 2.51890402209723194D+02, + 9 2.56221135550009525D+02, 2.60564940971863209D+02, + A 2.64921649798552801D+02, 2.69291097651019823D+02, + B 2.73673124285693704D+02, 2.78067573440366143D+02, + C 2.82474292687630396D+02, 2.86893133295426994D+02, + D 2.91323950094270308D+02, 2.95766601350760624D+02, + E 3.00220948647014132D+02, 3.04686856765668715D+02/ + DATA GLN(89), GLN(90), GLN(91), GLN(92), GLN(93), GLN(94), + 1 GLN(95), GLN(96), GLN(97), GLN(98), GLN(99), GLN(100)/ + 2 3.09164193580146922D+02, 3.13652829949879062D+02, + 3 3.18152639620209327D+02, 3.22663499126726177D+02, + 4 3.27185287703775217D+02, 3.31717887196928473D+02, + 5 3.36261181979198477D+02, 3.40815058870799018D+02, + 6 3.45379407062266854D+02, 3.49954118040770237D+02, + 7 3.54539085519440809D+02, 3.59134205369575399D+02/ +C COEFFICIENTS OF ASYMPTOTIC EXPANSION + DATA CF(1), CF(2), CF(3), CF(4), CF(5), CF(6), CF(7), CF(8), + 1 CF(9), CF(10), CF(11), CF(12), CF(13), CF(14), CF(15), + 2 CF(16), CF(17), CF(18), CF(19), CF(20), CF(21), CF(22)/ + 3 8.33333333333333333D-02, -2.77777777777777778D-03, + 4 7.93650793650793651D-04, -5.95238095238095238D-04, + 5 8.41750841750841751D-04, -1.91752691752691753D-03, + 6 6.41025641025641026D-03, -2.95506535947712418D-02, + 7 1.79644372368830573D-01, -1.39243221690590112D+00, + 8 1.34028640441683920D+01, -1.56848284626002017D+02, + 9 2.19310333333333333D+03, -3.61087712537249894D+04, + A 6.91472268851313067D+05, -1.52382215394074162D+07, + B 3.82900751391414141D+08, -1.08822660357843911D+10, + C 3.47320283765002252D+11, -1.23696021422692745D+13, + D 4.88788064793079335D+14, -2.13203339609193739D+16/ +C +C LN(2*PI) + DATA CON / 1.83787706640934548D+00/ +C +C***FIRST EXECUTABLE STATEMENT DGAMLN + IERR=0 + IF (Z.LE.0.0D0) GO TO 70 + IF (Z.GT.101.0D0) GO TO 10 + NZ = INT(SNGL(Z)) + FZ = Z - FLOAT(NZ) + IF (FZ.GT.0.0D0) GO TO 10 + IF (NZ.GT.100) GO TO 10 + DGAMLN = GLN(NZ) + RETURN + 10 CONTINUE + WDTOL = D1MACH(4) + WDTOL = DMAX1(WDTOL,0.5D-18) + I1M = I1MACH(14) + RLN = D1MACH(5)*FLOAT(I1M) + FLN = DMIN1(RLN,20.0D0) + FLN = DMAX1(FLN,3.0D0) + FLN = FLN - 3.0D0 + ZM = 1.8000D0 + 0.3875D0*FLN + MZ = INT(SNGL(ZM)) + 1 + ZMIN = FLOAT(MZ) + ZDMY = Z + ZINC = 0.0D0 + IF (Z.GE.ZMIN) GO TO 20 + ZINC = ZMIN - FLOAT(NZ) + ZDMY = Z + ZINC + 20 CONTINUE + ZP = 1.0D0/ZDMY + T1 = CF(1)*ZP + S = T1 + IF (ZP.LT.WDTOL) GO TO 40 + ZSQ = ZP*ZP + TST = T1*WDTOL + DO 30 K=2,22 + ZP = ZP*ZSQ + TRM = CF(K)*ZP + IF (DABS(TRM).LT.TST) GO TO 40 + S = S + TRM + 30 CONTINUE + 40 CONTINUE + IF (ZINC.NE.0.0D0) GO TO 50 + TLG = DLOG(Z) + DGAMLN = Z*(TLG-1.0D0) + 0.5D0*(CON-TLG) + S + RETURN + 50 CONTINUE + ZP = 1.0D0 + NZ = INT(SNGL(ZINC)) + DO 60 I=1,NZ + ZP = ZP*(Z+FLOAT(I-1)) + 60 CONTINUE + TLG = DLOG(ZDMY) + DGAMLN = ZDMY*(TLG-1.0D0) - DLOG(ZP) + 0.5D0*(CON-TLG) + S + RETURN +C +C + 70 CONTINUE + IERR=1 + RETURN + END diff --git a/mathext/internal/amos/amoslib/fortran.go b/mathext/internal/amos/amoslib/fortran.go new file mode 100644 index 00000000..52e17e1f --- /dev/null +++ b/mathext/internal/amos/amoslib/fortran.go @@ -0,0 +1,366 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build fortran +// TODO(jonlawlor): remove fortran build tag when gonum only supports go 1.7+. + +package amoslib + +/* +double mzabs_(double * ar, double * ai); +void zs1s2_(double * ZRR, double * ZRI, double * S1R, double * S1I, double * S2R, double * S2I, int* NZ, double *ASCLE, double * ALIM, int * IUF); +void zacai_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, int * MR, double * YR, double * YI, int * NZ, double * RL, double * tol, double * elim, double * alim); +void zseri_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, double * YR, double * YI, int * NZ, double * tol, double * elim, double * alim); +void zmlri_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, double * YR, double * YI, int * NZ, double * tol); +void zbknu_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, double * YR, double * YI, int * NZ, double * tol, double * elim, double * alim); +void zasyi_(double * ZR, double * ZI, double * FNU, int * KODE, int * N, double * YR, double * YI, int * NZ,double * RL, double * tol, double * elim, double * alim); +void zkscl_(double * ZRR, double * ZRI, double * FNU, int * N, double * YR, double * YI, int * NZ, double * RZR, double * RZI, double * ASCLE, double * tol, double * elim); +void zuchk_(double * YR, double * YI, int * NZ, double * ASCLE, double * TOL); +void zairy_(double * ZR, double * ZI, int * ID, int * KODE, double * AIR, double * AII, int * NZ, int * IERR); +void zlog_(double * ar, double * ai, double * br, double * bi, int * ierr); +void zexp_(double * ar, double * ai, double * br, double * bi); +void zsqrt_(double * ar, double * ai, double * br, double * bi); +void zdiv_(double * ar, double * ai, double * br, double * bi, double * cr, double * ci); +void zmlt_(double * ar, double * ai, double * br, double * bi, double * cr, double * ci); +double dgamln_(double *z, int * ierr); +void zshch_(double * zr, double * zi, double * cshr, double * cshi, double * cchr, double * cchi); +double mysqrt_(double * A); +double myexp_(double * A); +double mycos_(double * A); +double mysin_(double * A); +double mylog_(double * A); +double mytan_(double * A); +double myatan_(double * A); +double myabs_(double * A); +double mymin_(double * A, double * B); +double mymax_(double * A, double * B); +*/ +import "C" +import "unsafe" + +func MinFort(a, b float64) float64 { + ans := C.mymin_((*C.double)(&a), (*C.double)(&b)) + return float64(ans) +} + +func MaxFort(a, b float64) float64 { + ans := C.mymax_((*C.double)(&a), (*C.double)(&b)) + return float64(ans) +} + +func AbsFort(a float64) float64 { + ans := C.myabs_((*C.double)(&a)) + return float64(ans) +} + +func AtanFort(a float64) float64 { + ans := C.myatan_((*C.double)(&a)) + return float64(ans) +} + +func TanFort(a float64) float64 { + ans := C.mytan_((*C.double)(&a)) + return float64(ans) +} + +func LogFort(a float64) float64 { + ans := C.mylog_((*C.double)(&a)) + return float64(ans) +} + +func SinFort(a float64) float64 { + ans := C.mysin_((*C.double)(&a)) + return float64(ans) +} + +func CosFort(a float64) float64 { + ans := C.mycos_((*C.double)(&a)) + return float64(ans) +} + +func ExpFort(a float64) float64 { + ans := C.myexp_((*C.double)(&a)) + return float64(ans) +} + +func SqrtFort(a float64) float64 { + ans := C.mysqrt_((*C.double)(&a)) + return float64(ans) +} + +func DgamlnFort(a float64) float64 { + var ierr int + pierr := (*C.int)(unsafe.Pointer(&ierr)) + pa := (*C.double)(&a) + ans := C.dgamln_(pa, pierr) + return (float64)(ans) +} + +func ZmltFort(a, b complex128) complex128 { + ar := real(a) + ai := imag(a) + br := real(b) + bi := imag(b) + var cr, ci float64 + C.zmlt_( + (*C.double)(&ar), (*C.double)(&ai), + (*C.double)(&br), (*C.double)(&bi), + (*C.double)(&cr), (*C.double)(&ci), + ) + return complex(cr, ci) +} + +func ZdivFort(a, b complex128) complex128 { + ar := real(a) + ai := imag(a) + br := real(b) + bi := imag(b) + var cr, ci float64 + C.zdiv_( + (*C.double)(&ar), (*C.double)(&ai), + (*C.double)(&br), (*C.double)(&bi), + (*C.double)(&cr), (*C.double)(&ci), + ) + return complex(cr, ci) +} + +func ZabsFort(a complex128) float64 { + ar := real(a) + ai := imag(a) + return float64(C.mzabs_((*C.double)(&ar), (*C.double)(&ai))) +} + +func ZsqrtFort(a complex128) (b complex128) { + ar := real(a) + ai := imag(a) + + var br, bi float64 + + par := (*C.double)(&ar) + pai := (*C.double)(&ai) + pbr := (*C.double)(&br) + pbi := (*C.double)(&bi) + + C.zsqrt_(par, pai, pbr, pbi) + return complex(br, bi) +} + +func ZexpFort(a complex128) (b complex128) { + ar := real(a) + ai := imag(a) + + var br, bi float64 + + par := (*C.double)(&ar) + pai := (*C.double)(&ai) + pbr := (*C.double)(&br) + pbi := (*C.double)(&bi) + + C.zexp_(par, pai, pbr, pbi) + return complex(br, bi) +} + +func ZlogFort(a complex128) (b complex128) { + ar := real(a) + ai := imag(a) + var ierr int + var br, bi float64 + + par := (*C.double)(&ar) + pai := (*C.double)(&ai) + pbr := (*C.double)(&br) + pbi := (*C.double)(&bi) + pierr := (*C.int)(unsafe.Pointer(&ierr)) + C.zlog_(par, pai, pbr, pbi, pierr) + return complex(br, bi) +} + +func Zshch(ZR, ZI, CSHR, CSHI, CCHR, CCHI float64) (ZRout, ZIout, CSHRout, CSHIout, CCHRout, CCHIout float64) { + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pcshr := (*C.double)(&CSHR) + pcshi := (*C.double)(&CSHI) + pcchr := (*C.double)(&CCHR) + pcchi := (*C.double)(&CCHI) + + C.zshch_(pzr, pzi, pcshr, pcshi, pcchr, pcchi) + return ZR, ZI, CSHR, CSHI, CCHR, CCHI +} + +func ZairyFort(ZR, ZI float64, ID, KODE int) (AIR, AII float64, NZ int) { + var IERR int + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pid := (*C.int)(unsafe.Pointer(&ID)) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + + pair := (*C.double)(&AIR) + paii := (*C.double)(&AII) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + pierr := (*C.int)(unsafe.Pointer(&IERR)) + C.zairy_(pzr, pzi, pid, pkode, pair, paii, pnz, pierr) + + NZ = int(*pnz) + return AIR, AII, NZ +} + +func ZksclFort(ZRR, ZRI, FNU float64, N int, YR, YI []float64, NZ int, RZR, RZI, ASCLE, TOL, ELIM float64) ( + ZRout, ZIout, FNUout float64, Nout int, YRout, YIout []float64, NZout int, RZRout, RZIout, ASCLEout, TOLout, ELIMout float64) { + + pzrr := (*C.double)(&ZRR) + pzri := (*C.double)(&ZRI) + pfnu := (*C.double)(&FNU) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + przr := (*C.double)(&RZR) + przi := (*C.double)(&RZI) + pascle := (*C.double)(&ASCLE) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + + C.zkscl_(pzrr, pzri, pfnu, pn, pyr, pyi, pnz, przr, przi, pascle, ptol, pelim) + N = int(*pn) + NZ = int(*pnz) + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM +} + +func ZbknuFort(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + palim := (*C.double)(&ALIM) + + C.zbknu_(pzr, pzi, pfnu, pkode, pn, pyr, pyi, pnz, ptol, pelim, palim) + KODE = int(*pkode) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +func ZasyiFort(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + prl := (*C.double)(&RL) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + palim := (*C.double)(&ALIM) + + C.zasyi_(pzr, pzi, pfnu, pkode, pn, pyr, pyi, pnz, prl, ptol, pelim, palim) + KODE = int(*pkode) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +func ZuchkFort(YR, YI float64, NZ int, ASCLE, TOL float64) (YRout, YIout float64, NZout int, ASCLEout, TOLout float64) { + pyr := (*C.double)(&YR) + pyi := (*C.double)(&YI) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + pascle := (*C.double)(&ASCLE) + ptol := (*C.double)(&TOL) + + C.zuchk_(pyr, pyi, pnz, pascle, ptol) + return YR, YI, NZ, ASCLE, TOL +} + +func Zs1s2Fort(ZRR, ZRI, S1R, S1I, S2R, S2I float64, NZ int, ASCLE, ALIM float64, IUF int) ( + ZRRout, ZRIout, S1Rout, S1Iout, S2Rout, S2Iout float64, NZout int, ASCLEout, ALIMout float64, IUFout int) { + + pzrr := (*C.double)(&ZRR) + pzri := (*C.double)(&ZRI) + ps1r := (*C.double)(&S1R) + ps1i := (*C.double)(&S1I) + ps2r := (*C.double)(&S2R) + ps2i := (*C.double)(&S2I) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + pascle := (*C.double)(&ASCLE) + palim := (*C.double)(&ALIM) + piuf := (*C.int)(unsafe.Pointer(&IUF)) + + C.zs1s2_(pzrr, pzri, ps1r, ps1i, ps2r, ps2i, pnz, pascle, palim, piuf) + return ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, IUF +} + +func ZacaiFort(ZR, ZI, FNU float64, KODE, MR, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, MRout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pmr := (*C.int)(unsafe.Pointer(&MR)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + prl := (*C.double)(&RL) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + palim := (*C.double)(&ALIM) + + C.zacai_(pzr, pzi, pfnu, pkode, pmr, pn, pyr, pyi, pnz, prl, ptol, pelim, palim) + KODE = int(*pkode) + MR = int(*pmr) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +func ZseriFort(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + ptol := (*C.double)(&TOL) + pelim := (*C.double)(&ELIM) + palim := (*C.double)(&ALIM) + + C.zseri_(pzr, pzi, pfnu, pkode, pn, pyr, pyi, pnz, ptol, pelim, palim) + KODE = int(*pkode) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +func ZmlriFort(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout float64) { + pzr := (*C.double)(&ZR) + pzi := (*C.double)(&ZI) + pfnu := (*C.double)(&FNU) + pkode := (*C.int)(unsafe.Pointer(&KODE)) + pn := (*C.int)(unsafe.Pointer(&N)) + pyr := (*C.double)(&YR[0]) + pyi := (*C.double)(&YI[0]) + pnz := (*C.int)(unsafe.Pointer(&NZ)) + ptol := (*C.double)(&TOL) + + C.zmlri_(pzr, pzi, pfnu, pkode, pn, pyr, pyi, pnz, ptol) + KODE = int(*pkode) + N = int(*pn) + NZ = int(*pnz) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +} diff --git a/mathext/internal/amos/amoslib/i1mach.f b/mathext/internal/amos/amoslib/i1mach.f new file mode 100644 index 00000000..b9683336 --- /dev/null +++ b/mathext/internal/amos/amoslib/i1mach.f @@ -0,0 +1,113 @@ +*DECK I1MACH + INTEGER FUNCTION I1MACH(I) +C***BEGIN PROLOGUE I1MACH +C***DATE WRITTEN 750101 (YYMMDD) +C***REVISION DATE 890213 (YYMMDD) +C***CATEGORY NO. R1 +C***KEYWORDS LIBRARY=SLATEC,TYPE=INTEGER(I1MACH-I),MACHINE CONSTANTS +C***AUTHOR FOX, P. A., (BELL LABS) +C HALL, A. D., (BELL LABS) +C SCHRYER, N. L., (BELL LABS) +C***PURPOSE Returns integer machine dependent constants +C***DESCRIPTION +C +C I1MACH can be used to obtain machine-dependent parameters +C for the local machine environment. It is a function +C subroutine with one (input) argument, and can be called +C as follows, for example +C +C K = I1MACH(I) +C +C where I=1,...,16. The (output) value of K above is +C determined by the (input) value of I. The results for +C various values of I are discussed below. +C +C I/O unit numbers. +C I1MACH( 1) = the standard input unit. +C I1MACH( 2) = the standard output unit. +C I1MACH( 3) = the standard punch unit. +C I1MACH( 4) = the standard error message unit. +C +C Words. +C I1MACH( 5) = the number of bits per integer storage unit. +C I1MACH( 6) = the number of characters per integer storage unit. +C +C Integers. +C assume integers are represented in the S-digit, base-A form +C +C sign ( X(S-1)*A**(S-1) + ... + X(1)*A + X(0) ) +C +C where 0 .LE. X(I) .LT. A for I=0,...,S-1. +C I1MACH( 7) = A, the base. +C I1MACH( 8) = S, the number of base-A digits. +C I1MACH( 9) = A**S - 1, the largest magnitude. +C +C Floating-Point Numbers. +C Assume floating-point numbers are represented in the T-digit, +C base-B form +C sign (B**E)*( (X(1)/B) + ... + (X(T)/B**T) ) +C +C where 0 .LE. X(I) .LT. B for I=1,...,T, +C 0 .LT. X(1), and EMIN .LE. E .LE. EMAX. +C I1MACH(10) = B, the base. +C +C Single-Precision +C I1MACH(11) = T, the number of base-B digits. +C I1MACH(12) = EMIN, the smallest exponent E. +C I1MACH(13) = EMAX, the largest exponent E. +C +C Double-Precision +C I1MACH(14) = T, the number of base-B digits. +C I1MACH(15) = EMIN, the smallest exponent E. +C I1MACH(16) = EMAX, the largest exponent E. +C +C To alter this function for a particular environment, +C the desired set of DATA statements should be activated by +C removing the C from column 1. Also, the values of +C I1MACH(1) - I1MACH(4) should be checked for consistency +C with the local operating system. +C +C***REFERENCES FOX P.A., HALL A.D., SCHRYER N.L.,*FRAMEWORK FOR A +C PORTABLE LIBRARY*, ACM TRANSACTIONS ON MATHEMATICAL +C SOFTWARE, VOL. 4, NO. 2, JUNE 1978, PP. 177-188. +C***ROUTINES CALLED (NONE) +C***END PROLOGUE I1MACH +C + INTEGER IMACH(16),OUTPUT + SAVE IMACH + EQUIVALENCE (IMACH(4),OUTPUT) +C +C MACHINE CONSTANTS FOR THE IBM PC +C + DATA IMACH( 1) / 5 / + DATA IMACH( 2) / 6 / + DATA IMACH( 3) / 0 / + DATA IMACH( 4) / 0 / + DATA IMACH( 5) / 32 / + DATA IMACH( 6) / 4 / + DATA IMACH( 7) / 2 / + DATA IMACH( 8) / 31 / + DATA IMACH( 9) / 2147483647 / + DATA IMACH(10) / 2 / + DATA IMACH(11) / 24 / + DATA IMACH(12) / -125 / + DATA IMACH(13) / 127 / + DATA IMACH(14) / 53 / + DATA IMACH(15) / -1021 / + DATA IMACH(16) / 1023 / +C +C***FIRST EXECUTABLE STATEMENT I1MACH + IF (I .LT. 1 .OR. I .GT. 16) GO TO 10 +C + I1MACH = IMACH(I) + RETURN +C + 10 CONTINUE + WRITE (UNIT = OUTPUT, FMT = 9000) + 9000 FORMAT ('1ERROR 1 IN I1MACH - I OUT OF BOUNDS') +C +C CALL FDUMP +C +C + STOP + END diff --git a/mathext/internal/amos/amoslib/myabs.f b/mathext/internal/amos/amoslib/myabs.f new file mode 100644 index 00000000..5060195c --- /dev/null +++ b/mathext/internal/amos/amoslib/myabs.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYABS(A) + DOUBLE PRECISION A + MYABS = DABS(A) + RETURN + END diff --git a/mathext/internal/amos/amoslib/myatan.f b/mathext/internal/amos/amoslib/myatan.f new file mode 100644 index 00000000..0887fdae --- /dev/null +++ b/mathext/internal/amos/amoslib/myatan.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYATAN(A) + DOUBLE PRECISION A + MYATAN = DATAN(A) + RETURN + END diff --git a/mathext/internal/amos/amoslib/mycos.f b/mathext/internal/amos/amoslib/mycos.f new file mode 100644 index 00000000..c39e46df --- /dev/null +++ b/mathext/internal/amos/amoslib/mycos.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYCOS(A) + DOUBLE PRECISION A + MYCOS = DCOS(A) + RETURN + END diff --git a/mathext/internal/amos/amoslib/myexp.f b/mathext/internal/amos/amoslib/myexp.f new file mode 100644 index 00000000..44a2a80b --- /dev/null +++ b/mathext/internal/amos/amoslib/myexp.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYEXP(A) + DOUBLE PRECISION A + MYEXP = DEXP(A) + RETURN + END diff --git a/mathext/internal/amos/amoslib/mylog.f b/mathext/internal/amos/amoslib/mylog.f new file mode 100644 index 00000000..ac7e3a34 --- /dev/null +++ b/mathext/internal/amos/amoslib/mylog.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYLOG(A) + DOUBLE PRECISION A + MYLOG = DLOG(A) + RETURN + END diff --git a/mathext/internal/amos/amoslib/mymax.f b/mathext/internal/amos/amoslib/mymax.f new file mode 100644 index 00000000..0438eb46 --- /dev/null +++ b/mathext/internal/amos/amoslib/mymax.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYMAX(A, B) + DOUBLE PRECISION A, B + MYMAX = DMAX1(A,B) + RETURN + END diff --git a/mathext/internal/amos/amoslib/mymin.f b/mathext/internal/amos/amoslib/mymin.f new file mode 100644 index 00000000..950606c6 --- /dev/null +++ b/mathext/internal/amos/amoslib/mymin.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYMIN(A, B) + DOUBLE PRECISION A, B + MYMIN = DMIN1(A,B) + RETURN + END diff --git a/mathext/internal/amos/amoslib/mysin.f b/mathext/internal/amos/amoslib/mysin.f new file mode 100644 index 00000000..1663ed56 --- /dev/null +++ b/mathext/internal/amos/amoslib/mysin.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYSIN(A) + DOUBLE PRECISION A + MYSIN = DSIN(A) + RETURN + END diff --git a/mathext/internal/amos/amoslib/mysqrt.f b/mathext/internal/amos/amoslib/mysqrt.f new file mode 100644 index 00000000..a3998389 --- /dev/null +++ b/mathext/internal/amos/amoslib/mysqrt.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYSQRT(A) + DOUBLE PRECISION A + MYSQRT = SQRT(A) + RETURN + END diff --git a/mathext/internal/amos/amoslib/mytan.f b/mathext/internal/amos/amoslib/mytan.f new file mode 100644 index 00000000..239aa682 --- /dev/null +++ b/mathext/internal/amos/amoslib/mytan.f @@ -0,0 +1,5 @@ + DOUBLE PRECISION FUNCTION MYTAN(A) + DOUBLE PRECISION A + MYTAN = DTAN(A) + RETURN + END diff --git a/mathext/internal/amos/amoslib/xerror.f b/mathext/internal/amos/amoslib/xerror.f new file mode 100644 index 00000000..baa55067 --- /dev/null +++ b/mathext/internal/amos/amoslib/xerror.f @@ -0,0 +1,22 @@ + SUBROUTINE XERROR(MESS,NMESS,L1,L2) +C +C THIS IS A DUMMY XERROR ROUTINE TO PRINT ERROR MESSAGES WITH NMESS +C CHARACTERS. L1 AND L2 ARE DUMMY PARAMETERS TO MAKE THIS CALL +C COMPATIBLE WITH THE SLATEC XERROR ROUTINE. THIS IS A FORTRAN 77 +C ROUTINE. +C + CHARACTER*(*) MESS + NN=NMESS/70 + NR=NMESS-70*NN + IF(NR.NE.0) NN=NN+1 + K=1 + PRINT 900 + 900 FORMAT(/) + DO 10 I=1,NN + KMIN=MIN0(K+69,NMESS) + PRINT *, MESS(K:KMIN) + K=K+70 + 10 CONTINUE + PRINT 900 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zabs.f b/mathext/internal/amos/amoslib/zabs.f new file mode 100644 index 00000000..23e00a64 --- /dev/null +++ b/mathext/internal/amos/amoslib/zabs.f @@ -0,0 +1,34 @@ + DOUBLE PRECISION FUNCTION MZABS(ZR, ZI) +C***BEGIN PROLOGUE ZABS +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C ZABS COMPUTES THE ABSOLUTE VALUE OR MAGNITUDE OF A DOUBLE +C PRECISION COMPLEX VARIABLE CMPLX(ZR,ZI) +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZABS + DOUBLE PRECISION ZR, ZI, U, V, Q, S + + MZABS = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + RETURN + END + +c U = DABS(ZR) +c V = DABS(ZI) +c S = U + V +C----------------------------------------------------------------------- +C S*1.0D0 MAKES AN UNNORMALIZED UNDERFLOW ON CDC MACHINES INTO A +C TRUE FLOATING ZERO +C----------------------------------------------------------------------- +c S = S*1.0D+0 +c IF (S.EQ.0.0D+0) GO TO 20 +c IF (U.GT.V) GO TO 10 +c Q = U/V +c ZABS = V*DSQRT(1.D+0+Q*Q) +c RETURN +c 10 Q = V/U +c ZABS = U*DSQRT(1.D+0+Q*Q) +c RETURN +c 20 ZABS = 0.0D+0 +c RETURN +c END diff --git a/mathext/internal/amos/amoslib/zacai.f b/mathext/internal/amos/amoslib/zacai.f new file mode 100644 index 00000000..aa05a5c7 --- /dev/null +++ b/mathext/internal/amos/amoslib/zacai.f @@ -0,0 +1,99 @@ + SUBROUTINE ZACAI(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, + * ELIM, ALIM) +C***BEGIN PROLOGUE ZACAI +C***REFER TO ZAIRY +C +C ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA +C +C K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN) +C MP=PI*MR*CMPLX(0.0,1.0) +C +C TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT +C HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1. +C ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND +C RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT IF ZACON +C IS CALLED FROM ZAIRY. +C +C***ROUTINES CALLED ZASYI,ZBKNU,ZMLRI,ZSERI,ZS1S2,D1MACH,ZABS +C***END PROLOGUE ZACAI +C COMPLEX CSGN,CSPN,C1,C2,Y,Z,ZN,CY + DOUBLE PRECISION ALIM, ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR, + * CSPNI, C1R, C1I, C2R, C2I, CYR, CYI, DFNU, ELIM, FMR, FNU, PI, + * RL, SGN, TOL, YY, YR, YI, ZR, ZI, ZNR, ZNI, D1MACH, ZABS + INTEGER INU, IUF, KODE, MR, N, NN, NW, NZ + DIMENSION YR(N), YI(N), CYR(2), CYI(2) + DATA PI / 3.14159265358979324D0 / + NZ = 0 + ZNR = -ZR + ZNI = -ZI + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + NN = N + DFNU = FNU + DBLE(FLOAT(N-1)) + IF (AZ.LE.2.0D0) GO TO 10 + IF (AZ*AZ*0.25D0.GT.DFNU+1.0D0) GO TO 20 + 10 CONTINUE +C----------------------------------------------------------------------- +C POWER SERIES FOR THE I FUNCTION +C----------------------------------------------------------------------- + CALL ZSERI(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL, ELIM, ALIM) + GO TO 40 + 20 CONTINUE + IF (AZ.LT.RL) GO TO 30 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION +C----------------------------------------------------------------------- + CALL ZASYI(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 80 + GO TO 40 + 30 CONTINUE +C----------------------------------------------------------------------- +C MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION +C----------------------------------------------------------------------- + CALL ZMLRI(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL) + IF(NW.LT.0) GO TO 80 + 40 CONTINUE +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION +C----------------------------------------------------------------------- + CALL ZBKNU(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, NW, TOL, ELIM, ALIM) + IF (NW.NE.0) GO TO 80 + FMR = DBLE(FLOAT(MR)) + SGN = -DSIGN(PI,FMR) + CSGNR = 0.0D0 + CSGNI = SGN + IF (KODE.EQ.1) GO TO 50 + YY = -ZNI + CSGNR = -CSGNI*DSIN(YY) + CSGNI = CSGNI*DCOS(YY) + 50 CONTINUE +C----------------------------------------------------------------------- +C CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + ARG = (FNU-DBLE(FLOAT(INU)))*SGN + CSPNR = DCOS(ARG) + CSPNI = DSIN(ARG) + IF (MOD(INU,2).EQ.0) GO TO 60 + CSPNR = -CSPNR + CSPNI = -CSPNI + 60 CONTINUE + C1R = CYR(1) + C1I = CYI(1) + C2R = YR(1) + C2I = YI(1) + IF (KODE.EQ.1) GO TO 70 + IUF = 0 + ASCLE = 1.0D+3*D1MACH(1)/TOL + CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW + 70 CONTINUE + YR(1) = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I + YI(1) = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R + RETURN + 80 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zacon.f b/mathext/internal/amos/amoslib/zacon.f new file mode 100644 index 00000000..ba593590 --- /dev/null +++ b/mathext/internal/amos/amoslib/zacon.f @@ -0,0 +1,203 @@ + SUBROUTINE ZACON(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, FNUL, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZACON +C***REFER TO ZBESK,ZBESH +C +C ZACON APPLIES THE ANALYTIC CONTINUATION FORMULA +C +C K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN) +C MP=PI*MR*CMPLX(0.0,1.0) +C +C TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT +C HALF Z PLANE +C +C***ROUTINES CALLED ZBINU,ZBKNU,ZS1S2,D1MACH,ZABS,ZMLT +C***END PROLOGUE ZACON +C COMPLEX CK,CONE,CSCL,CSCR,CSGN,CSPN,CY,CZERO,C1,C2,RZ,SC1,SC2,ST, +C *S1,S2,Y,Z,ZN + DOUBLE PRECISION ALIM, ARG, ASCLE, AS2, AZN, BRY, BSCLE, CKI, + * CKR, CONER, CPN, CSCL, CSCR, CSGNI, CSGNR, CSPNI, CSPNR, + * CSR, CSRR, CSSR, CYI, CYR, C1I, C1M, C1R, C2I, C2R, ELIM, FMR, + * FN, FNU, FNUL, PI, PTI, PTR, RAZN, RL, RZI, RZR, SC1I, SC1R, + * SC2I, SC2R, SGN, SPN, STI, STR, S1I, S1R, S2I, S2R, TOL, YI, YR, + * YY, ZEROR, ZI, ZNI, ZNR, ZR, D1MACH, ZABS + INTEGER I, INU, IUF, KFLAG, KODE, MR, N, NN, NW, NZ + DIMENSION YR(N), YI(N), CYR(2), CYI(2), CSSR(3), CSRR(3), BRY(3) + DATA PI / 3.14159265358979324D0 / + DATA ZEROR,CONER / 0.0D0,1.0D0 / + NZ = 0 + ZNR = -ZR + ZNI = -ZI + NN = N + CALL ZBINU(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, FNUL, TOL, + * ELIM, ALIM) + IF (NW.LT.0) GO TO 90 +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION +C----------------------------------------------------------------------- + NN = MIN0(2,N) + CALL ZBKNU(ZNR, ZNI, FNU, KODE, NN, CYR, CYI, NW, TOL, ELIM, ALIM) + IF (NW.NE.0) GO TO 90 + S1R = CYR(1) + S1I = CYI(1) + FMR = DBLE(FLOAT(MR)) + SGN = -DSIGN(PI,FMR) + CSGNR = ZEROR + CSGNI = SGN + IF (KODE.EQ.1) GO TO 10 + YY = -ZNI + CPN = DCOS(YY) + SPN = DSIN(YY) + CALL ZMLT(CSGNR, CSGNI, CPN, SPN, CSGNR, CSGNI) + 10 CONTINUE +C----------------------------------------------------------------------- +C CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + ARG = (FNU-DBLE(FLOAT(INU)))*SGN + CPN = DCOS(ARG) + SPN = DSIN(ARG) + CSPNR = CPN + CSPNI = SPN + IF (MOD(INU,2).EQ.0) GO TO 20 + CSPNR = -CSPNR + CSPNI = -CSPNI + 20 CONTINUE + IUF = 0 + C1R = S1R + C1I = S1I + C2R = YR(1) + C2I = YI(1) + ASCLE = 1.0D+3*D1MACH(1)/TOL + IF (KODE.EQ.1) GO TO 30 + CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW + SC1R = C1R + SC1I = C1I + 30 CONTINUE + CALL ZMLT(CSPNR, CSPNI, C1R, C1I, STR, STI) + CALL ZMLT(CSGNR, CSGNI, C2R, C2I, PTR, PTI) + YR(1) = STR + PTR + YI(1) = STI + PTI + IF (N.EQ.1) RETURN + CSPNR = -CSPNR + CSPNI = -CSPNI + S2R = CYR(2) + S2I = CYI(2) + C1R = S2R + C1I = S2I + C2R = YR(2) + C2I = YI(2) + IF (KODE.EQ.1) GO TO 40 + CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW + SC2R = C1R + SC2I = C1I + 40 CONTINUE + CALL ZMLT(CSPNR, CSPNI, C1R, C1I, STR, STI) + CALL ZMLT(CSGNR, CSGNI, C2R, C2I, PTR, PTI) + YR(2) = STR + PTR + YI(2) = STI + PTI + IF (N.EQ.2) RETURN + CSPNR = -CSPNR + CSPNI = -CSPNI + AZN = ZABS(CMPLX(ZNR,ZNI,kind=KIND(1.0D0))) + RAZN = 1.0D0/AZN + STR = ZNR*RAZN + STI = -ZNI*RAZN + RZR = (STR+STR)*RAZN + RZI = (STI+STI)*RAZN + FN = FNU + 1.0D0 + CKR = FN*RZR + CKI = FN*RZI +C----------------------------------------------------------------------- +C SCALE NEAR EXPONENT EXTREMES DURING RECURRENCE ON K FUNCTIONS +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CSCR = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CSCR + CSRR(1) = CSCR + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = ASCLE + BRY(2) = 1.0D0/ASCLE + BRY(3) = D1MACH(2) + AS2 = ZABS(CMPLX(S2R,S2I,kind=KIND(1.0D0))) + KFLAG = 2 + IF (AS2.GT.BRY(1)) GO TO 50 + KFLAG = 1 + GO TO 60 + 50 CONTINUE + IF (AS2.LT.BRY(2)) GO TO 60 + KFLAG = 3 + 60 CONTINUE + BSCLE = BRY(KFLAG) + S1R = S1R*CSSR(KFLAG) + S1I = S1I*CSSR(KFLAG) + S2R = S2R*CSSR(KFLAG) + S2I = S2I*CSSR(KFLAG) + CSR = CSRR(KFLAG) + DO 80 I=3,N + STR = S2R + STI = S2I + S2R = CKR*STR - CKI*STI + S1R + S2I = CKR*STI + CKI*STR + S1I + S1R = STR + S1I = STI + C1R = S2R*CSR + C1I = S2I*CSR + STR = C1R + STI = C1I + C2R = YR(I) + C2I = YI(I) + IF (KODE.EQ.1) GO TO 70 + IF (IUF.LT.0) GO TO 70 + CALL ZS1S2(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW + SC1R = SC2R + SC1I = SC2I + SC2R = C1R + SC2I = C1I + IF (IUF.NE.3) GO TO 70 + IUF = -4 + S1R = SC1R*CSSR(KFLAG) + S1I = SC1I*CSSR(KFLAG) + S2R = SC2R*CSSR(KFLAG) + S2I = SC2I*CSSR(KFLAG) + STR = SC2R + STI = SC2I + 70 CONTINUE + PTR = CSPNR*C1R - CSPNI*C1I + PTI = CSPNR*C1I + CSPNI*C1R + YR(I) = PTR + CSGNR*C2R - CSGNI*C2I + YI(I) = PTI + CSGNR*C2I + CSGNI*C2R + CKR = CKR + RZR + CKI = CKI + RZI + CSPNR = -CSPNR + CSPNI = -CSPNI + IF (KFLAG.GE.3) GO TO 80 + PTR = DABS(C1R) + PTI = DABS(C1I) + C1M = DMAX1(PTR,PTI) + IF (C1M.LE.BSCLE) GO TO 80 + KFLAG = KFLAG + 1 + BSCLE = BRY(KFLAG) + S1R = S1R*CSR + S1I = S1I*CSR + S2R = STR + S2I = STI + S1R = S1R*CSSR(KFLAG) + S1I = S1I*CSSR(KFLAG) + S2R = S2R*CSSR(KFLAG) + S2I = S2I*CSSR(KFLAG) + CSR = CSRR(KFLAG) + 80 CONTINUE + RETURN + 90 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zairy.f b/mathext/internal/amos/amoslib/zairy.f new file mode 100644 index 00000000..6adab8f5 --- /dev/null +++ b/mathext/internal/amos/amoslib/zairy.f @@ -0,0 +1,395 @@ + SUBROUTINE ZAIRY(ZR, ZI, ID, KODE, AIR, AII, NZ, IERR) +C***BEGIN PROLOGUE ZAIRY +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR +C ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON +C KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)* +C DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN +C -PI/3.LT.ARG(Z).LT.PI/3 AND THE EXPONENTIAL GROWTH IN +C PI/3.LT.ABS(ARG(Z)).LT.PI WHERE ZTA=(2/3)*Z*CSQRT(Z). +C +C WHILE THE AIRY FUNCTIONS AI(Z) AND DAI(Z)/DZ ARE ANALYTIC IN +C THE WHOLE Z PLANE, THE CORRESPONDING SCALED FUNCTIONS DEFINED +C FOR KODE=2 HAVE A CUT ALONG THE NEGATIVE REAL AXIS. +C DEFINTIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF +C MATHEMATICAL FUNCTIONS (REF. 1). +C +C INPUT ZR,ZI ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI) +C ID - ORDER OF DERIVATIVE, ID=0 OR ID=1 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C AI=AI(Z) ON ID=0 OR +C AI=DAI(Z)/DZ ON ID=1 +C = 2 RETURNS +C AI=CEXP(ZTA)*AI(Z) ON ID=0 OR +C AI=CEXP(ZTA)*DAI(Z)/DZ ON ID=1 WHERE +C ZTA=(2/3)*Z*CSQRT(Z) +C +C OUTPUT AIR,AII ARE DOUBLE PRECISION +C AIR,AII- COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND +C KODE +C NZ - UNDERFLOW INDICATOR +C NZ= 0 , NORMAL RETURN +C NZ= 1 , AI=CMPLX(0.0D0,0.0D0) DUE TO UNDERFLOW IN +C -PI/3.LT.ARG(Z).LT.PI/3 ON KODE=1 +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, REAL(ZTA) +C TOO LARGE ON KODE=1 +C IERR=3, CABS(Z) LARGE - COMPUTATION COMPLETED +C LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION +C PRODUCE LESS THAN HALF OF MACHINE ACCURACY +C IERR=4, CABS(Z) TOO LARGE - NO COMPUTATION +C COMPLETE LOSS OF ACCURACY BY ARGUMENT +C REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C AI AND DAI ARE COMPUTED FOR CABS(Z).GT.1.0 FROM THE K BESSEL +C FUNCTIONS BY +C +C AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA) +C C=1.0/(PI*SQRT(3.0)) +C ZTA=(2/3)*Z**(3/2) +C +C WITH THE POWER SERIES FOR CABS(Z).LE.1.0. +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES +C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF +C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR), +C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR +C FLAG IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C ALSO, IF THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN +C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT +C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE +C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA +C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, +C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE +C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE +C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT- +C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG- +C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN +C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN +C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, +C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE +C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER +C MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZACAI,ZBKNU,ZEXP,ZSQRT,I1MACH,D1MACH +C***END PROLOGUE ZAIRY +C COMPLEX AI,CONE,CSQ,CY,S1,S2,TRM1,TRM2,Z,ZTA,Z3 + DOUBLE PRECISION AA, AD, AII, AIR, AK, ALIM, ATRM, AZ, AZ3, BK, + * CC, CK, COEF, CONEI, CONER, CSQI, CSQR, CYI, CYR, C1, C2, DIG, + * DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR, + * S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI, + * ZEROR, ZI, ZR, ZTAI, ZTAR, Z3I, Z3R, D1MACH, ZABS, ALAZ, BB + INTEGER ID, IERR, IFLAG, K, KODE, K1, K2, MR, NN, NZ, I1MACH + DIMENSION CYR(1), CYI(1) + DATA TTH, C1, C2, COEF /6.66666666666666667D-01, + * 3.55028053887817240D-01,2.58819403792806799D-01, + * 1.83776298473930683D-01/ + DATA ZEROR, ZEROI, CONER, CONEI /0.0D0,0.0D0,1.0D0,0.0D0/ +C***FIRST EXECUTABLE STATEMENT ZAIRY + IERR = 0 + NZ=0 + IF (ID.LT.0 .OR. ID.GT.1) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (IERR.NE.0) RETURN + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + TOL = DMAX1(D1MACH(4),1.0D-18) + FID = DBLE(FLOAT(ID)) + IF (AZ.GT.1.0D0) GO TO 70 +C----------------------------------------------------------------------- +C POWER SERIES FOR CABS(Z).LE.1. +C----------------------------------------------------------------------- + S1R = CONER + S1I = CONEI + S2R = CONER + S2I = CONEI + IF (AZ.LT.TOL) GO TO 170 + AA = AZ*AZ + IF (AA.LT.TOL/AZ) GO TO 40 + TRM1R = CONER + TRM1I = CONEI + TRM2R = CONER + TRM2I = CONEI + ATRM = 1.0D0 + STR = ZR*ZR - ZI*ZI + STI = ZR*ZI + ZI*ZR + Z3R = STR*ZR - STI*ZI + Z3I = STR*ZI + STI*ZR + AZ3 = AZ*AA + AK = 2.0D0 + FID + BK = 3.0D0 - FID - FID + CK = 4.0D0 - FID + DK = 3.0D0 + FID + FID + D1 = AK*DK + D2 = BK*CK + AD = DMIN1(D1,D2) + AK = 24.0D0 + 9.0D0*FID + BK = 30.0D0 - 9.0D0*FID + DO 30 K=1,25 + STR = (TRM1R*Z3R-TRM1I*Z3I)/D1 + TRM1I = (TRM1R*Z3I+TRM1I*Z3R)/D1 + TRM1R = STR + S1R = S1R + TRM1R + S1I = S1I + TRM1I + STR = (TRM2R*Z3R-TRM2I*Z3I)/D2 + TRM2I = (TRM2R*Z3I+TRM2I*Z3R)/D2 + TRM2R = STR + S2R = S2R + TRM2R + S2I = S2I + TRM2I + ATRM = ATRM*AZ3/AD + D1 = D1 + AK + D2 = D2 + BK + AD = DMIN1(D1,D2) + IF (ATRM.LT.TOL*AD) GO TO 40 + AK = AK + 18.0D0 + BK = BK + 18.0D0 + 30 CONTINUE + 40 CONTINUE + IF (ID.EQ.1) THEN + GO TO 50 + END IF + AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I) + AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R) + IF (KODE.EQ.1) RETURN + CALL ZSQRT(ZR, ZI, STR, STI) + ZTAR = TTH*(ZR*STR-ZI*STI) + ZTAI = TTH*(ZR*STI+ZI*STR) + CALL ZEXP(ZTAR, ZTAI, STR, STI) + PTR = AIR*STR - AII*STI + AII = AIR*STI + AII*STR + AIR = PTR + RETURN + 50 CONTINUE + AIR = -S2R*C2 + AII = -S2I*C2 + IF (AZ.LE.TOL) GO TO 60 + STR = ZR*S1R - ZI*S1I + STI = ZR*S1I + ZI*S1R + CC = C1/(1.0D0+FID) + AIR = AIR + CC*(STR*ZR-STI*ZI) + AII = AII + CC*(STR*ZI+STI*ZR) + 60 CONTINUE + IF (KODE.EQ.1) RETURN + CALL ZSQRT(ZR, ZI, STR, STI) + ZTAR = TTH*(ZR*STR-ZI*STI) + ZTAI = TTH*(ZR*STI+ZI*STR) + CALL ZEXP(ZTAR, ZTAI, STR, STI) + PTR = STR*AIR - STI*AII + AII = STR*AII + STI*AIR + AIR = PTR + RETURN +C----------------------------------------------------------------------- +C CASE FOR CABS(Z).GT.1.0 +C----------------------------------------------------------------------- + 70 CONTINUE + FNU = (1.0D0+FID)/3.0D0 +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C----------------------------------------------------------------------- + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + RL = 1.2D0*DIG + 3.0D0 + ALAZ = DLOG(AZ) +C-------------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AA=0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA=DMIN1(AA,BB) + AA=AA**TTH + IF (AZ.GT.AA) GO TO 260 + AA=DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + CALL ZSQRT(ZR, ZI, CSQR, CSQI) + ZTAR = TTH*(ZR*CSQR-ZI*CSQI) + ZTAI = TTH*(ZR*CSQI+ZI*CSQR) +C----------------------------------------------------------------------- +C RE(ZTA).LE.0 WHEN RE(Z).LT.0, ESPECIALLY WHEN IM(Z) IS SMALL +C----------------------------------------------------------------------- + IFLAG = 0 + SFAC = 1.0D0 + AK = ZTAI + IF (ZR.GE.0.0D0) GO TO 80 + BK = ZTAR + CK = -DABS(BK) + ZTAR = CK + ZTAI = AK + 80 CONTINUE + IF (ZI.NE.0.0D0) GO TO 90 + IF (ZR.GT.0.0D0) GO TO 90 + ZTAR = 0.0D0 + ZTAI = AK + 90 CONTINUE + AA = ZTAR + IF (AA.GE.0.0D0 .AND. ZR.GT.0.0D0) GO TO 110 + IF (KODE.EQ.2) GO TO 100 +C----------------------------------------------------------------------- +C OVERFLOW TEST +C----------------------------------------------------------------------- + IF (AA.GT.(-ALIM)) GO TO 100 + AA = -AA + 0.25D0*ALAZ + IFLAG = 1 + SFAC = TOL + IF (AA.GT.ELIM) GO TO 270 + 100 CONTINUE +C----------------------------------------------------------------------- +C CBKNU AND CACON RETURN EXP(ZTA)*K(FNU,ZTA) ON KODE=2 +C----------------------------------------------------------------------- + MR = 1 + IF (ZI.LT.0.0D0) MR = -1 + CALL ZACAI(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, NN, RL, TOL, + * ELIM, ALIM) + IF (NN.LT.0) GO TO 280 + NZ = NZ + NN + GO TO 130 + 110 CONTINUE + IF (KODE.EQ.2) GO TO 120 +C----------------------------------------------------------------------- +C UNDERFLOW TEST +C----------------------------------------------------------------------- + IF (AA.LT.ALIM) GO TO 120 + AA = -AA - 0.25D0*ALAZ + IFLAG = 2 + SFAC = 1.0D0/TOL + IF (AA.LT.(-ELIM)) GO TO 210 + 120 CONTINUE + CALL ZBKNU(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, TOL, ELIM, + * ALIM) + 130 CONTINUE + S1R = CYR(1)*COEF + S1I = CYI(1)*COEF + IF (IFLAG.NE.0) GO TO 150 + IF (ID.EQ.1) GO TO 140 + AIR = CSQR*S1R - CSQI*S1I + AII = CSQR*S1I + CSQI*S1R + RETURN + 140 CONTINUE + AIR = -(ZR*S1R-ZI*S1I) + AII = -(ZR*S1I+ZI*S1R) + RETURN + 150 CONTINUE + S1R = S1R*SFAC + S1I = S1I*SFAC + IF (ID.EQ.1) GO TO 160 + STR = S1R*CSQR - S1I*CSQI + S1I = S1R*CSQI + S1I*CSQR + S1R = STR + AIR = S1R/SFAC + AII = S1I/SFAC + RETURN + 160 CONTINUE + STR = -(S1R*ZR-S1I*ZI) + S1I = -(S1R*ZI+S1I*ZR) + S1R = STR + AIR = S1R/SFAC + AII = S1I/SFAC + RETURN + 170 CONTINUE + AA = 1.0D+3*D1MACH(1) + S1R = ZEROR + S1I = ZEROI + IF (ID.EQ.1) GO TO 190 + IF (AZ.LE.AA) GO TO 180 + S1R = C2*ZR + S1I = C2*ZI + 180 CONTINUE + AIR = C1 - S1R + AII = -S1I + RETURN + 190 CONTINUE + AIR = -C2 + AII = 0.0D0 + AA = DSQRT(AA) + IF (AZ.LE.AA) GO TO 200 + S1R = 0.5D0*(ZR*ZR-ZI*ZI) + S1I = ZR*ZI + 200 CONTINUE + AIR = AIR + C1*S1R + AII = AII + C1*S1I + RETURN + 210 CONTINUE + NZ = 1 + AIR = ZEROR + AII = ZEROI + RETURN + 270 CONTINUE + NZ = 0 + IERR=2 + RETURN + 280 CONTINUE + IF(NN.EQ.(-1)) GO TO 270 + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + IERR=4 + NZ=0 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zasyi.f b/mathext/internal/amos/amoslib/zasyi.f new file mode 100644 index 00000000..139d7390 --- /dev/null +++ b/mathext/internal/amos/amoslib/zasyi.f @@ -0,0 +1,169 @@ + SUBROUTINE ZASYI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZASYI +C***REFER TO ZBESI,ZBESK +C +C ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z).GE.0.0 BY +C MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE +C REGION CABS(Z).GT.MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL RETURN. +C NZ.LT.0 INDICATES AN OVERFLOW ON KODE=1. +C +C***ROUTINES CALLED D1MACH,ZABS,ZDIV,ZEXP,ZMLT,ZSQRT +C***END PROLOGUE ZASYI +C COMPLEX AK1,CK,CONE,CS1,CS2,CZ,CZERO,DK,EZ,P1,RZ,S2,Y,Z + DOUBLE PRECISION AA, AEZ, AK, AK1I, AK1R, ALIM, ARG, ARM, ATOL, + * AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI, + * CZR, DFNU, DKI, DKR, DNU2, ELIM, EZI, EZR, FDN, FNU, PI, P1I, + * P1R, RAZ, RL, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I, + * S2R, TOL, TZI, TZR, YI, YR, ZEROI, ZEROR, ZI, ZR, D1MACH, ZABS + INTEGER I, IB, IL, INU, J, JL, K, KODE, KODED, M, N, NN, NZ + DIMENSION YR(N), YI(N) + DATA PI, RTPI /3.14159265358979324D0 , 0.159154943091895336D0 / + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / +C + NZ = 0 + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + ARM = 1.0D+3*D1MACH(1) + RTR1 = DSQRT(ARM) + IL = MIN0(2,N) + DFNU = FNU + DBLE(FLOAT(N-IL)) +C----------------------------------------------------------------------- +C OVERFLOW TEST +C----------------------------------------------------------------------- + RAZ = 1.0D0/AZ + STR = ZR*RAZ + STI = -ZI*RAZ + AK1R = RTPI*STR*RAZ + AK1I = RTPI*STI*RAZ + CALL ZSQRT(AK1R, AK1I, AK1R, AK1I) + CZR = ZR + CZI = ZI + IF (KODE.NE.2) GO TO 10 + CZR = ZEROR + CZI = ZI + 10 CONTINUE + IF (DABS(CZR).GT.ELIM) GO TO 100 + DNU2 = DFNU + DFNU + KODED = 1 + IF ((DABS(CZR).GT.ALIM) .AND. (N.GT.2)) GO TO 20 + KODED = 0 + CALL ZEXP(CZR, CZI, STR, STI) + CALL ZMLT(AK1R, AK1I, STR, STI, AK1R, AK1I) + 20 CONTINUE + FDN = 0.0D0 + IF (DNU2.GT.RTR1) THEN + FDN = DNU2*DNU2 + END IF + EZR = ZR*8.0D0 + EZI = ZI*8.0D0 +C----------------------------------------------------------------------- +C WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE +C FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE +C EXPANSION FOR THE IMAGINARY PART. +C----------------------------------------------------------------------- + AEZ = 8.0D0*AZ + S = TOL/AEZ + JL = INT(SNGL(RL+RL)) + 2 + P1R = ZEROR + P1I = ZEROI + IF (ZI.EQ.0.0D0) GO TO 30 +C----------------------------------------------------------------------- +C CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF +C SIGNIFICANCE WHEN FNU OR N IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + ARG = (FNU-DBLE(FLOAT(INU)))*PI + INU = INU + N - IL + AK = -DSIN(ARG) + BK = DCOS(ARG) + IF (ZI.LT.0.0D0) BK = -BK + P1R = AK + P1I = BK + IF (MOD(INU,2).EQ.0) GO TO 30 + P1R = -P1R + P1I = -P1I + 30 CONTINUE + DO 70 K=1,IL + SQK = FDN - 1.0D0 + ATOL = S*DABS(SQK) + SGN = 1.0D0 + CS1R = CONER + CS1I = CONEI + CS2R = CONER + CS2I = CONEI + CKR = CONER + CKI = CONEI + AK = 0.0D0 + AA = 1.0D0 + BB = AEZ + DKR = EZR + DKI = EZI + DO 40 J=1,JL + CALL ZDIV(CKR, CKI, DKR, DKI, STR, STI) + CKR = STR*SQK + CKI = STI*SQK + CS2R = CS2R + CKR + CS2I = CS2I + CKI + SGN = -SGN + CS1R = CS1R + CKR*SGN + CS1I = CS1I + CKI*SGN + DKR = DKR + EZR + DKI = DKI + EZI + AA = AA*DABS(SQK)/BB + BB = BB + AEZ + AK = AK + 8.0D0 + SQK = SQK - AK + IF (AA.LE.ATOL) THEN + GO TO 50 + END IF + 40 CONTINUE + GO TO 110 + 50 CONTINUE + S2R = CS1R + S2I = CS1I + IF (ZR+ZR.GE.ELIM) GO TO 60 + TZR = ZR + ZR + TZI = ZI + ZI + CALL ZEXP(-TZR, -TZI, STR, STI) + CALL ZMLT(STR, STI, P1R, P1I, STR, STI) + CALL ZMLT(STR, STI, CS2R, CS2I, STR, STI) + S2R = S2R + STR + S2I = S2I + STI + 60 CONTINUE + FDN = FDN + 8.0D0*DFNU + 4.0D0 + P1R = -P1R + P1I = -P1I + M = N - IL + K + YR(M) = S2R*AK1R - S2I*AK1I + YI(M) = S2R*AK1I + S2I*AK1R + 70 CONTINUE + IF (N.LE.2) RETURN + NN = N + K = NN - 2 + AK = DBLE(FLOAT(K)) + STR = ZR*RAZ + STI = -ZI*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + IB = 3 + DO 80 I=IB,NN + YR(K) = (AK+FNU)*(RZR*YR(K+1)-RZI*YI(K+1)) + YR(K+2) + YI(K) = (AK+FNU)*(RZR*YI(K+1)+RZI*YR(K+1)) + YI(K+2) + AK = AK - 1.0D0 + K = K - 1 + 80 CONTINUE + IF (KODED.EQ.0) RETURN + CALL ZEXP(CZR, CZI, CKR, CKI) + DO 90 I=1,NN + STR = YR(I)*CKR - YI(I)*CKI + YI(I) = YR(I)*CKI + YI(I)*CKR + YR(I) = STR + 90 CONTINUE + RETURN + 100 CONTINUE + NZ = -1 + RETURN + 110 CONTINUE + NZ=-2 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbesh.f b/mathext/internal/amos/amoslib/zbesh.f new file mode 100644 index 00000000..a055ae46 --- /dev/null +++ b/mathext/internal/amos/amoslib/zbesh.f @@ -0,0 +1,348 @@ + SUBROUTINE ZBESH(ZR, ZI, FNU, KODE, M, N, CYR, CYI, NZ, IERR) +C***BEGIN PROLOGUE ZBESH +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS H-BESSEL FUNCTIONS,BESSEL FUNCTIONS OF COMPLEX ARGUMENT, +C BESSEL FUNCTIONS OF THIRD KIND,HANKEL FUNCTIONS +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE THE H-BESSEL FUNCTIONS OF A COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, ZBESH COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C HANKEL (BESSEL) FUNCTIONS CY(J)=H(M,FNU+J-1,Z) FOR KINDS M=1 +C OR 2, REAL, NONNEGATIVE ORDERS FNU+J-1, J=1,...,N, AND COMPLEX +C Z.NE.CMPLX(0.0,0.0) IN THE CUT PLANE -PI.LT.ARG(Z).LE.PI. +C ON KODE=2, ZBESH RETURNS THE SCALED HANKEL FUNCTIONS +C +C CY(I)=EXP(-MM*Z*I)*H(M,FNU+J-1,Z) MM=3-2*M, I**2=-1. +C +C WHICH REMOVES THE EXPONENTIAL BEHAVIOR IN BOTH THE UPPER AND +C LOWER HALF PLANES. DEFINITIONS AND NOTATION ARE FOUND IN THE +C NBS HANDBOOK OF MATHEMATICAL FUNCTIONS (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), Z.NE.CMPLX(0.0D0,0.0D0), +C -PT.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL H FUNCTION, FNU.GE.0.0D0 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(J)=H(M,FNU+J-1,Z), J=1,...,N +C = 2 RETURNS +C CY(J)=H(M,FNU+J-1,Z)*EXP(-I*Z*(3-2M)) +C J=1,...,N , I**2=-1 +C M - KIND OF HANKEL FUNCTION, M=1 OR 2 +C N - NUMBER OF MEMBERS IN THE SEQUENCE, N.GE.1 +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(J)=H(M,FNU+J-1,Z) OR +C CY(J)=H(M,FNU+J-1,Z)*EXP(-I*Z*(3-2M)) J=1,...,N +C DEPENDING ON KODE, I**2=-1. +C NZ - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW, +C NZ= 0 , NORMAL RETURN +C NZ.GT.0 , FIRST NZ COMPONENTS OF CY SET TO ZERO DUE +C TO UNDERFLOW, CY(J)=CMPLX(0.0D0,0.0D0) +C J=1,...,NZ WHEN Y.GT.0.0 AND M=1 OR +C Y.LT.0.0 AND M=2. FOR THE COMPLMENTARY +C HALF PLANES, NZ STATES ONLY THE NUMBER +C OF UNDERFLOWS. +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, FNU TOO +C LARGE OR CABS(Z) TOO SMALL OR BOTH +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C THE COMPUTATION IS CARRIED OUT BY THE RELATION +C +C H(M,FNU,Z)=(1/MP)*EXP(-MP*FNU)*K(FNU,Z*EXP(-MP)) +C MP=MM*HPI*I, MM=3-2*M, HPI=PI/2, I**2=-1 +C +C FOR M=1 OR 2 WHERE THE K BESSEL FUNCTION IS COMPUTED FOR THE +C RIGHT HALF PLANE RE(Z).GE.0.0. THE K FUNCTION IS CONTINUED +C TO THE LEFT HALF PLANE BY THE RELATION +C +C K(FNU,Z*EXP(MP)) = EXP(-MP*FNU)*K(FNU,Z)-MP*I(FNU,Z) +C MP=MR*PI*I, MR=+1 OR -1, RE(Z).GT.0, I**2=-1 +C +C WHERE I(FNU,Z) IS THE I BESSEL FUNCTION. +C +C EXPONENTIAL DECAY OF H(M,FNU,Z) OCCURS IN THE UPPER HALF Z +C PLANE FOR M=1 AND THE LOWER HALF Z PLANE FOR M=2. EXPONENTIAL +C GROWTH OCCURS IN THE COMPLEMENTARY HALF PLANES. SCALING +C BY EXP(-MM*Z*I) REMOVES THE EXPONENTIAL BEHAVIOR IN THE +C WHOLE Z PLANE FOR Z TO INFINITY. +C +C FOR NEGATIVE ORDERS,THE FORMULAE +C +C H(1,-FNU,Z) = H(1,FNU,Z)*CEXP( PI*FNU*I) +C H(2,-FNU,Z) = H(2,FNU,Z)*CEXP(-PI*FNU*I) +C I**2=-1 +C +C CAN BE USED. +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0D-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZACON,ZBKNU,ZBUNK,ZUOIK,ZABS,I1MACH,D1MACH +C***END PROLOGUE ZBESH +C +C COMPLEX CY,Z,ZN,ZT,CSGN + DOUBLE PRECISION AA, ALIM, ALN, ARG, AZ, CYI, CYR, DIG, ELIM, + * FMM, FN, FNU, FNUL, HPI, RHPI, RL, R1M5, SGN, STR, TOL, UFL, ZI, + * ZNI, ZNR, ZR, ZTI, D1MACH, ZABS, BB, ASCLE, RTOL, ATOL, STI, + * CSGNR, CSGNI + INTEGER I, IERR, INU, INUH, IR, K, KODE, K1, K2, M, + * MM, MR, N, NN, NUF, NW, NZ, I1MACH + DIMENSION CYR(N), CYI(N) +C + DATA HPI /1.57079632679489662D0/ +C +C***FIRST EXECUTABLE STATEMENT ZBESH + IERR = 0 + NZ=0 + IF (ZR.EQ.0.0D0 .AND. ZI.EQ.0.0D0) IERR=1 + IF (FNU.LT.0.0D0) IERR=1 + IF (M.LT.1 .OR. M.GT.2) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN + NN = N +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU +C----------------------------------------------------------------------- + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) + RL = 1.2D0*DIG + 3.0D0 + FN = FNU + DBLE(FLOAT(NN-1)) + MM = 3 - M - M + FMM = DBLE(FLOAT(MM)) + ZNR = FMM*ZI + ZNI = -FMM*ZR +C----------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + AA = 0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA = DMIN1(AA,BB) + IF (AZ.GT.AA) GO TO 260 + IF (FN.GT.AA) GO TO 260 + AA = DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + IF (FN.GT.AA) IERR=3 +C----------------------------------------------------------------------- +C OVERFLOW TEST ON THE LAST MEMBER OF THE SEQUENCE +C----------------------------------------------------------------------- + UFL = D1MACH(1)*1.0D+3 + IF (AZ.LT.UFL) GO TO 230 + IF (FNU.GT.FNUL) GO TO 90 + IF (FN.LE.1.0D0) GO TO 70 + IF (FN.GT.2.0D0) GO TO 60 + IF (AZ.GT.TOL) GO TO 70 + ARG = 0.5D0*AZ + ALN = -FN*DLOG(ARG) + IF (ALN.GT.ELIM) GO TO 230 + GO TO 70 + 60 CONTINUE + CALL ZUOIK(ZNR, ZNI, FNU, KODE, 2, NN, CYR, CYI, NUF, TOL, ELIM, + * ALIM) + IF (NUF.LT.0) GO TO 230 + NZ = NZ + NUF + NN = NN - NUF +C----------------------------------------------------------------------- +C HERE NN=N OR NN=0 SINCE NUF=0,NN, OR -1 ON RETURN FROM CUOIK +C IF NUF=NN, THEN CY(I)=CZERO FOR ALL I +C----------------------------------------------------------------------- + IF (NN.EQ.0) GO TO 140 + 70 CONTINUE + IF ((ZNR.LT.0.0D0) .OR. (ZNR.EQ.0.0D0 .AND. ZNI.LT.0.0D0 .AND. + * M.EQ.2)) GO TO 80 +C----------------------------------------------------------------------- +C RIGHT HALF PLANE COMPUTATION, XN.GE.0. .AND. (XN.NE.0. .OR. +C YN.GE.0. .OR. M=1) +C----------------------------------------------------------------------- + CALL ZBKNU(ZNR, ZNI, FNU, KODE, NN, CYR, CYI, NZ, TOL, ELIM, ALIM) + GO TO 110 +C----------------------------------------------------------------------- +C LEFT HALF PLANE COMPUTATION +C----------------------------------------------------------------------- + 80 CONTINUE + MR = -MM + CALL ZACON(ZNR, ZNI, FNU, KODE, MR, NN, CYR, CYI, NW, RL, FNUL, + * TOL, ELIM, ALIM) + IF (NW.LT.0) GO TO 240 + NZ=NW + GO TO 110 + 90 CONTINUE +C----------------------------------------------------------------------- +C UNIFORM ASYMPTOTIC EXPANSIONS FOR FNU.GT.FNUL +C----------------------------------------------------------------------- + MR = 0 + IF ((ZNR.GE.0.0D0) .AND. (ZNR.NE.0.0D0 .OR. ZNI.GE.0.0D0 .OR. + * M.NE.2)) GO TO 100 + MR = -MM + IF (ZNR.NE.0.0D0 .OR. ZNI.GE.0.0D0) GO TO 100 + ZNR = -ZNR + ZNI = -ZNI + 100 CONTINUE + CALL ZBUNK(ZNR, ZNI, FNU, KODE, MR, NN, CYR, CYI, NW, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 240 + NZ = NZ + NW + 110 CONTINUE +C----------------------------------------------------------------------- +C H(M,FNU,Z) = -FMM*(I/HPI)*(ZT**FNU)*K(FNU,-Z*ZT) +C +C ZT=EXP(-FMM*HPI*I) = CMPLX(0.0,-FMM), FMM=3-2*M, M=1,2 +C----------------------------------------------------------------------- + SGN = DSIGN(HPI,-FMM) +C----------------------------------------------------------------------- +C CALCULATE EXP(FNU*HPI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + INUH = INU/2 + IR = INU - 2*INUH + ARG = (FNU-DBLE(FLOAT(INU-IR)))*SGN + RHPI = 1.0D0/SGN +C ZNI = RHPI*DCOS(ARG) +C ZNR = -RHPI*DSIN(ARG) + CSGNI = RHPI*DCOS(ARG) + CSGNR = -RHPI*DSIN(ARG) + IF (MOD(INUH,2).EQ.0) GO TO 120 +C ZNR = -ZNR +C ZNI = -ZNI + CSGNR = -CSGNR + CSGNI = -CSGNI + 120 CONTINUE + ZTI = -FMM + RTOL = 1.0D0/TOL + ASCLE = UFL*RTOL + DO 130 I=1,NN +C STR = CYR(I)*ZNR - CYI(I)*ZNI +C CYI(I) = CYR(I)*ZNI + CYI(I)*ZNR +C CYR(I) = STR +C STR = -ZNI*ZTI +C ZNI = ZNR*ZTI +C ZNR = STR + AA = CYR(I) + BB = CYI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 135 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 135 CONTINUE + STR = AA*CSGNR - BB*CSGNI + STI = AA*CSGNI + BB*CSGNR + CYR(I) = STR*ATOL + CYI(I) = STI*ATOL + STR = -CSGNI*ZTI + CSGNI = CSGNR*ZTI + CSGNR = STR + 130 CONTINUE + RETURN + 140 CONTINUE + IF (ZNR.LT.0.0D0) GO TO 230 + RETURN + 230 CONTINUE + NZ=0 + IERR=2 + RETURN + 240 CONTINUE + IF(NW.EQ.(-1)) GO TO 230 + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + NZ=0 + IERR=4 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbesi.f b/mathext/internal/amos/amoslib/zbesi.f new file mode 100644 index 00000000..5f7c1407 --- /dev/null +++ b/mathext/internal/amos/amoslib/zbesi.f @@ -0,0 +1,269 @@ + SUBROUTINE ZBESI(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, IERR) +C***BEGIN PROLOGUE ZBESI +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS I-BESSEL FUNCTION,COMPLEX BESSEL FUNCTION, +C MODIFIED BESSEL FUNCTION OF THE FIRST KIND +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE I-BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, ZBESI COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C BESSEL FUNCTIONS CY(J)=I(FNU+J-1,Z) FOR REAL, NONNEGATIVE +C ORDERS FNU+J-1, J=1,...,N AND COMPLEX Z IN THE CUT PLANE +C -PI.LT.ARG(Z).LE.PI. ON KODE=2, ZBESI RETURNS THE SCALED +C FUNCTIONS +C +C CY(J)=EXP(-ABS(X))*I(FNU+J-1,Z) J = 1,...,N , X=REAL(Z) +C +C WITH THE EXPONENTIAL GROWTH REMOVED IN BOTH THE LEFT AND +C RIGHT HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION +C ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS +C (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), -PI.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL I FUNCTION, FNU.GE.0.0D0 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(J)=I(FNU+J-1,Z), J=1,...,N +C = 2 RETURNS +C CY(J)=I(FNU+J-1,Z)*EXP(-ABS(X)), J=1,...,N +C N - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1 +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(J)=I(FNU+J-1,Z) OR +C CY(J)=I(FNU+J-1,Z)*EXP(-ABS(X)) J=1,...,N +C DEPENDING ON KODE, X=REAL(Z) +C NZ - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW, +C NZ= 0 , NORMAL RETURN +C NZ.GT.0 , LAST NZ COMPONENTS OF CY SET TO ZERO +C TO UNDERFLOW, CY(J)=CMPLX(0.0D0,0.0D0) +C J = N-NZ+1,...,N +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, REAL(Z) TOO +C LARGE ON KODE=1 +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C THE COMPUTATION IS CARRIED OUT BY THE POWER SERIES FOR +C SMALL CABS(Z), THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z), +C THE MILLER ALGORITHM NORMALIZED BY THE WRONSKIAN AND A +C NEUMANN SERIES FOR IMTERMEDIATE MAGNITUDES, AND THE +C UNIFORM ASYMPTOTIC EXPANSIONS FOR I(FNU,Z) AND J(FNU,Z) +C FOR LARGE ORDERS. BACKWARD RECURRENCE IS USED TO GENERATE +C SEQUENCES OR REDUCE ORDERS WHEN NECESSARY. +C +C THE CALCULATIONS ABOVE ARE DONE IN THE RIGHT HALF PLANE AND +C CONTINUED INTO THE LEFT HALF PLANE BY THE FORMULA +C +C I(FNU,Z*EXP(M*PI)) = EXP(M*PI*FNU)*I(FNU,Z) REAL(Z).GT.0.0 +C M = +I OR -I, I**2=-1 +C +C FOR NEGATIVE ORDERS,THE FORMULA +C +C I(-FNU,Z) = I(FNU,Z) + (2/PI)*SIN(PI*FNU)*K(FNU,Z) +C +C CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO INTEGERS, THE +C THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE POSITIVE +C INTEGER,THE MAGNITUDE OF I(-FNU,Z)=I(FNU,Z) IS A LARGE +C NEGATIVE POWER OF TEN. BUT WHEN FNU IS NOT AN INTEGER, +C K(FNU,Z) DOMINATES IN MAGNITUDE WITH A LARGE POSITIVE POWER OF +C TEN AND THE MOST THAT THE SECOND TERM CAN BE REDUCED IS BY +C UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, WIDE CHANGES CAN +C OCCUR WITHIN UNIT ROUNDOFF OF A LARGE INTEGER FOR FNU. HERE, +C LARGE MEANS FNU.GT.CABS(Z). +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZBINU,I1MACH,D1MACH +C***END PROLOGUE ZBESI +C COMPLEX CONE,CSGN,CW,CY,CZERO,Z,ZN + DOUBLE PRECISION AA, ALIM, ARG, CONEI, CONER, CSGNI, CSGNR, CYI, + * CYR, DIG, ELIM, FNU, FNUL, PI, RL, R1M5, STR, TOL, ZI, ZNI, ZNR, + * ZR, D1MACH, AZ, BB, FN, ZABS, ASCLE, RTOL, ATOL, STI + INTEGER I, IERR, INU, K, KODE, K1,K2,N,NZ,NN, I1MACH + DIMENSION CYR(N), CYI(N) + DATA PI /3.14159265358979324D0/ + DATA CONER, CONEI /1.0D0,0.0D0/ +C +C***FIRST EXECUTABLE STATEMENT ZBESI + IERR = 0 + NZ=0 + IF (FNU.LT.0.0D0) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU. +C----------------------------------------------------------------------- + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + RL = 1.2D0*DIG + 3.0D0 + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) +C----------------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + FN = FNU+DBLE(FLOAT(N-1)) + AA = 0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA = DMIN1(AA,BB) + IF (AZ.GT.AA) GO TO 260 + IF (FN.GT.AA) GO TO 260 + AA = DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + IF (FN.GT.AA) IERR=3 + ZNR = ZR + ZNI = ZI + CSGNR = CONER + CSGNI = CONEI + IF (ZR.GE.0.0D0) GO TO 40 + ZNR = -ZR + ZNI = -ZI +C----------------------------------------------------------------------- +C CALCULATE CSGN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + INU = INT(SNGL(FNU)) + ARG = (FNU-DBLE(FLOAT(INU)))*PI + IF (ZI.LT.0.0D0) ARG = -ARG + CSGNR = DCOS(ARG) + CSGNI = DSIN(ARG) + IF (MOD(INU,2).EQ.0) GO TO 40 + CSGNR = -CSGNR + CSGNI = -CSGNI + 40 CONTINUE + CALL ZBINU(ZNR, ZNI, FNU, KODE, N, CYR, CYI, NZ, RL, FNUL, TOL, + * ELIM, ALIM) + IF (NZ.LT.0) GO TO 120 + IF (ZR.GE.0.0D0) RETURN +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION TO THE LEFT HALF PLANE +C----------------------------------------------------------------------- + NN = N - NZ + IF (NN.EQ.0) RETURN + RTOL = 1.0D0/TOL + ASCLE = D1MACH(1)*RTOL*1.0D+3 + DO 50 I=1,NN +C STR = CYR(I)*CSGNR - CYI(I)*CSGNI +C CYI(I) = CYR(I)*CSGNI + CYI(I)*CSGNR +C CYR(I) = STR + AA = CYR(I) + BB = CYI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 55 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 55 CONTINUE + STR = AA*CSGNR - BB*CSGNI + STI = AA*CSGNI + BB*CSGNR + CYR(I) = STR*ATOL + CYI(I) = STI*ATOL + CSGNR = -CSGNR + CSGNI = -CSGNI + 50 CONTINUE + RETURN + 120 CONTINUE + IF(NZ.EQ.(-2)) GO TO 130 + NZ = 0 + IERR=2 + RETURN + 130 CONTINUE + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + NZ=0 + IERR=4 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbesj.f b/mathext/internal/amos/amoslib/zbesj.f new file mode 100644 index 00000000..1fb217f4 --- /dev/null +++ b/mathext/internal/amos/amoslib/zbesj.f @@ -0,0 +1,266 @@ + SUBROUTINE ZBESJ(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, IERR) +C***BEGIN PROLOGUE ZBESJ +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS J-BESSEL FUNCTION,BESSEL FUNCTION OF COMPLEX ARGUMENT, +C BESSEL FUNCTION OF FIRST KIND +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE THE J-BESSEL FUNCTION OF A COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, CBESJ COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C BESSEL FUNCTIONS CY(I)=J(FNU+I-1,Z) FOR REAL, NONNEGATIVE +C ORDERS FNU+I-1, I=1,...,N AND COMPLEX Z IN THE CUT PLANE +C -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESJ RETURNS THE SCALED +C FUNCTIONS +C +C CY(I)=EXP(-ABS(Y))*J(FNU+I-1,Z) I = 1,...,N , Y=AIMAG(Z) +C +C WHICH REMOVE THE EXPONENTIAL GROWTH IN BOTH THE UPPER AND +C LOWER HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION +C ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS +C (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), -PI.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL J FUNCTION, FNU.GE.0.0D0 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(I)=J(FNU+I-1,Z), I=1,...,N +C = 2 RETURNS +C CY(I)=J(FNU+I-1,Z)EXP(-ABS(Y)), I=1,...,N +C N - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1 +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(I)=J(FNU+I-1,Z) OR +C CY(I)=J(FNU+I-1,Z)EXP(-ABS(Y)) I=1,...,N +C DEPENDING ON KODE, Y=AIMAG(Z). +C NZ - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW, +C NZ= 0 , NORMAL RETURN +C NZ.GT.0 , LAST NZ COMPONENTS OF CY SET ZERO DUE +C TO UNDERFLOW, CY(I)=CMPLX(0.0D0,0.0D0), +C I = N-NZ+1,...,N +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, AIMAG(Z) +C TOO LARGE ON KODE=1 +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C THE COMPUTATION IS CARRIED OUT BY THE FORMULA +C +C J(FNU,Z)=EXP( FNU*PI*I/2)*I(FNU,-I*Z) AIMAG(Z).GE.0.0 +C +C J(FNU,Z)=EXP(-FNU*PI*I/2)*I(FNU, I*Z) AIMAG(Z).LT.0.0 +C +C WHERE I**2 = -1 AND I(FNU,Z) IS THE I BESSEL FUNCTION. +C +C FOR NEGATIVE ORDERS,THE FORMULA +C +C J(-FNU,Z) = J(FNU,Z)*COS(PI*FNU) - Y(FNU,Z)*SIN(PI*FNU) +C +C CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO INTEGERS, THE +C THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE POSITIVE +C INTEGER,THE MAGNITUDE OF J(-FNU,Z)=J(FNU,Z)*COS(PI*FNU) IS A +C LARGE NEGATIVE POWER OF TEN. BUT WHEN FNU IS NOT AN INTEGER, +C Y(FNU,Z) DOMINATES IN MAGNITUDE WITH A LARGE POSITIVE POWER OF +C TEN AND THE MOST THAT THE SECOND TERM CAN BE REDUCED IS BY +C UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, WIDE CHANGES CAN +C OCCUR WITHIN UNIT ROUNDOFF OF A LARGE INTEGER FOR FNU. HERE, +C LARGE MEANS FNU.GT.CABS(Z). +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZBINU,I1MACH,D1MACH +C***END PROLOGUE ZBESJ +C +C COMPLEX CI,CSGN,CY,Z,ZN + DOUBLE PRECISION AA, ALIM, ARG, CII, CSGNI, CSGNR, CYI, CYR, DIG, + * ELIM, FNU, FNUL, HPI, RL, R1M5, STR, TOL, ZI, ZNI, ZNR, ZR, + * D1MACH, BB, FN, AZ, ZABS, ASCLE, RTOL, ATOL, STI + INTEGER I, IERR, INU, INUH, IR, K, KODE, K1, K2, N, NL, NZ, I1MACH + DIMENSION CYR(N), CYI(N) + DATA HPI /1.57079632679489662D0/ +C +C***FIRST EXECUTABLE STATEMENT ZBESJ + IERR = 0 + NZ=0 + IF (FNU.LT.0.0D0) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU. +C----------------------------------------------------------------------- + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + RL = 1.2D0*DIG + 3.0D0 + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) +C----------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + FN = FNU+DBLE(FLOAT(N-1)) + AA = 0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA = DMIN1(AA,BB) + IF (AZ.GT.AA) GO TO 260 + IF (FN.GT.AA) GO TO 260 + AA = DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + IF (FN.GT.AA) IERR=3 +C----------------------------------------------------------------------- +C CALCULATE CSGN=EXP(FNU*HPI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE +C WHEN FNU IS LARGE +C----------------------------------------------------------------------- + CII = 1.0D0 + INU = INT(SNGL(FNU)) + INUH = INU/2 + IR = INU - 2*INUH + ARG = (FNU-DBLE(FLOAT(INU-IR)))*HPI + CSGNR = DCOS(ARG) + CSGNI = DSIN(ARG) + IF (MOD(INUH,2).EQ.0) GO TO 40 + CSGNR = -CSGNR + CSGNI = -CSGNI + 40 CONTINUE +C----------------------------------------------------------------------- +C ZN IS IN THE RIGHT HALF PLANE +C----------------------------------------------------------------------- + ZNR = ZI + ZNI = -ZR + IF (ZI.GE.0.0D0) GO TO 50 + ZNR = -ZNR + ZNI = -ZNI + CSGNI = -CSGNI + CII = -CII + 50 CONTINUE + CALL ZBINU(ZNR, ZNI, FNU, KODE, N, CYR, CYI, NZ, RL, FNUL, TOL, + * ELIM, ALIM) + IF (NZ.LT.0) GO TO 130 + NL = N - NZ + IF (NL.EQ.0) RETURN + RTOL = 1.0D0/TOL + ASCLE = D1MACH(1)*RTOL*1.0D+3 + DO 60 I=1,NL +C STR = CYR(I)*CSGNR - CYI(I)*CSGNI +C CYI(I) = CYR(I)*CSGNI + CYI(I)*CSGNR +C CYR(I) = STR + AA = CYR(I) + BB = CYI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 55 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 55 CONTINUE + STR = AA*CSGNR - BB*CSGNI + STI = AA*CSGNI + BB*CSGNR + CYR(I) = STR*ATOL + CYI(I) = STI*ATOL + STR = -CSGNI*CII + CSGNI = CSGNR*CII + CSGNR = STR + 60 CONTINUE + RETURN + 130 CONTINUE + IF(NZ.EQ.(-2)) GO TO 140 + NZ = 0 + IERR = 2 + RETURN + 140 CONTINUE + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + NZ=0 + IERR=4 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbesk.f b/mathext/internal/amos/amoslib/zbesk.f new file mode 100644 index 00000000..c2228288 --- /dev/null +++ b/mathext/internal/amos/amoslib/zbesk.f @@ -0,0 +1,281 @@ + SUBROUTINE ZBESK(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, IERR) +C***BEGIN PROLOGUE ZBESK +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS K-BESSEL FUNCTION,COMPLEX BESSEL FUNCTION, +C MODIFIED BESSEL FUNCTION OF THE SECOND KIND, +C BESSEL FUNCTION OF THE THIRD KIND +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE K-BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C +C ON KODE=1, CBESK COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C BESSEL FUNCTIONS CY(J)=K(FNU+J-1,Z) FOR REAL, NONNEGATIVE +C ORDERS FNU+J-1, J=1,...,N AND COMPLEX Z.NE.CMPLX(0.0,0.0) +C IN THE CUT PLANE -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESK +C RETURNS THE SCALED K FUNCTIONS, +C +C CY(J)=EXP(Z)*K(FNU+J-1,Z) , J=1,...,N, +C +C WHICH REMOVE THE EXPONENTIAL BEHAVIOR IN BOTH THE LEFT AND +C RIGHT HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND +C NOTATION ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL +C FUNCTIONS (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), Z.NE.CMPLX(0.0D0,0.0D0), +C -PI.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL K FUNCTION, FNU.GE.0.0D0 +C N - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(I)=K(FNU+I-1,Z), I=1,...,N +C = 2 RETURNS +C CY(I)=K(FNU+I-1,Z)*EXP(Z), I=1,...,N +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(I)=K(FNU+I-1,Z), I=1,...,N OR +C CY(I)=K(FNU+I-1,Z)*EXP(Z), I=1,...,N +C DEPENDING ON KODE +C NZ - NUMBER OF COMPONENTS SET TO ZERO DUE TO UNDERFLOW. +C NZ= 0 , NORMAL RETURN +C NZ.GT.0 , FIRST NZ COMPONENTS OF CY SET TO ZERO DUE +C TO UNDERFLOW, CY(I)=CMPLX(0.0D0,0.0D0), +C I=1,...,N WHEN X.GE.0.0. WHEN X.LT.0.0 +C NZ STATES ONLY THE NUMBER OF UNDERFLOWS +C IN THE SEQUENCE. +C +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, FNU IS +C TOO LARGE OR CABS(Z) IS TOO SMALL OR BOTH +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C EQUATIONS OF THE REFERENCE ARE IMPLEMENTED FOR SMALL ORDERS +C DNU AND DNU+1.0 IN THE RIGHT HALF PLANE X.GE.0.0. FORWARD +C RECURRENCE GENERATES HIGHER ORDERS. K IS CONTINUED TO THE LEFT +C HALF PLANE BY THE RELATION +C +C K(FNU,Z*EXP(MP)) = EXP(-MP*FNU)*K(FNU,Z)-MP*I(FNU,Z) +C MP=MR*PI*I, MR=+1 OR -1, RE(Z).GT.0, I**2=-1 +C +C WHERE I(FNU,Z) IS THE I BESSEL FUNCTION. +C +C FOR LARGE ORDERS, FNU.GT.FNUL, THE K FUNCTION IS COMPUTED +C BY MEANS OF ITS UNIFORM ASYMPTOTIC EXPANSIONS. +C +C FOR NEGATIVE ORDERS, THE FORMULA +C +C K(-FNU,Z) = K(FNU,Z) +C +C CAN BE USED. +C +C CBESK ASSUMES THAT A SIGNIFICANT DIGIT SINH(X) FUNCTION IS +C AVAILABLE. +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983. +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZACON,ZBKNU,ZBUNK,ZUOIK,ZABS,I1MACH,D1MACH +C***END PROLOGUE ZBESK +C +C COMPLEX CY,Z + DOUBLE PRECISION AA, ALIM, ALN, ARG, AZ, CYI, CYR, DIG, ELIM, FN, + * FNU, FNUL, RL, R1M5, TOL, UFL, ZI, ZR, D1MACH, ZABS, BB + INTEGER IERR, K, KODE, K1, K2, MR, N, NN, NUF, NW, NZ, I1MACH + DIMENSION CYR(N), CYI(N) +C***FIRST EXECUTABLE STATEMENT ZBESK + IERR = 0 + NZ=0 + IF (ZI.EQ.0.0E0 .AND. ZR.EQ.0.0E0) IERR=1 + IF (FNU.LT.0.0D0) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN + NN = N +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU +C----------------------------------------------------------------------- + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) + RL = 1.2D0*DIG + 3.0D0 +C----------------------------------------------------------------------------- +C TEST FOR PROPER RANGE +C----------------------------------------------------------------------- + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + FN = FNU + DBLE(FLOAT(NN-1)) + AA = 0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA = DMIN1(AA,BB) + IF (AZ.GT.AA) GO TO 260 + IF (FN.GT.AA) GO TO 260 + AA = DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + IF (FN.GT.AA) IERR=3 +C----------------------------------------------------------------------- +C OVERFLOW TEST ON THE LAST MEMBER OF THE SEQUENCE +C----------------------------------------------------------------------- +C UFL = DEXP(-ELIM) + UFL = D1MACH(1)*1.0D+3 + IF (AZ.LT.UFL) GO TO 180 + IF (FNU.GT.FNUL) GO TO 80 + IF (FN.LE.1.0D0) GO TO 60 + IF (FN.GT.2.0D0) GO TO 50 + IF (AZ.GT.TOL) GO TO 60 + ARG = 0.5D0*AZ + ALN = -FN*DLOG(ARG) + IF (ALN.GT.ELIM) GO TO 180 + GO TO 60 + 50 CONTINUE + CALL ZUOIK(ZR, ZI, FNU, KODE, 2, NN, CYR, CYI, NUF, TOL, ELIM, + * ALIM) + IF (NUF.LT.0) GO TO 180 + NZ = NZ + NUF + NN = NN - NUF +C----------------------------------------------------------------------- +C HERE NN=N OR NN=0 SINCE NUF=0,NN, OR -1 ON RETURN FROM CUOIK +C IF NUF=NN, THEN CY(I)=CZERO FOR ALL I +C----------------------------------------------------------------------- + IF (NN.EQ.0) GO TO 100 + 60 CONTINUE + IF (ZR.LT.0.0D0) GO TO 70 +C----------------------------------------------------------------------- +C RIGHT HALF PLANE COMPUTATION, REAL(Z).GE.0. +C----------------------------------------------------------------------- + CALL ZBKNU(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, TOL, ELIM, ALIM) + IF (NW.LT.0) GO TO 200 + NZ=NW + RETURN +C----------------------------------------------------------------------- +C LEFT HALF PLANE COMPUTATION +C PI/2.LT.ARG(Z).LE.PI AND -PI.LT.ARG(Z).LT.-PI/2. +C----------------------------------------------------------------------- + 70 CONTINUE + IF (NZ.NE.0) GO TO 180 + MR = 1 + IF (ZI.LT.0.0D0) MR = -1 + CALL ZACON(ZR, ZI, FNU, KODE, MR, NN, CYR, CYI, NW, RL, FNUL, + * TOL, ELIM, ALIM) + IF (NW.LT.0) GO TO 200 + NZ=NW + RETURN +C----------------------------------------------------------------------- +C UNIFORM ASYMPTOTIC EXPANSIONS FOR FNU.GT.FNUL +C----------------------------------------------------------------------- + 80 CONTINUE + MR = 0 + IF (ZR.GE.0.0D0) GO TO 90 + MR = 1 + IF (ZI.LT.0.0D0) MR = -1 + 90 CONTINUE + CALL ZBUNK(ZR, ZI, FNU, KODE, MR, NN, CYR, CYI, NW, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 200 + NZ = NZ + NW + RETURN + 100 CONTINUE + IF (ZR.LT.0.0D0) GO TO 180 + RETURN + 180 CONTINUE + NZ = 0 + IERR=2 + RETURN + 200 CONTINUE + IF(NW.EQ.(-1)) GO TO 180 + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + NZ=0 + IERR=4 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbesy.f b/mathext/internal/amos/amoslib/zbesy.f new file mode 100644 index 00000000..05ec40be --- /dev/null +++ b/mathext/internal/amos/amoslib/zbesy.f @@ -0,0 +1,244 @@ + SUBROUTINE ZBESY(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, CWRKR, CWRKI, + * IERR) +C***BEGIN PROLOGUE ZBESY +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS Y-BESSEL FUNCTION,BESSEL FUNCTION OF COMPLEX ARGUMENT, +C BESSEL FUNCTION OF SECOND KIND +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE THE Y-BESSEL FUNCTION OF A COMPLEX ARGUMENT +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C +C ON KODE=1, CBESY COMPUTES AN N MEMBER SEQUENCE OF COMPLEX +C BESSEL FUNCTIONS CY(I)=Y(FNU+I-1,Z) FOR REAL, NONNEGATIVE +C ORDERS FNU+I-1, I=1,...,N AND COMPLEX Z IN THE CUT PLANE +C -PI.LT.ARG(Z).LE.PI. ON KODE=2, CBESY RETURNS THE SCALED +C FUNCTIONS +C +C CY(I)=EXP(-ABS(Y))*Y(FNU+I-1,Z) I = 1,...,N , Y=AIMAG(Z) +C +C WHICH REMOVE THE EXPONENTIAL GROWTH IN BOTH THE UPPER AND +C LOWER HALF PLANES FOR Z TO INFINITY. DEFINITIONS AND NOTATION +C ARE FOUND IN THE NBS HANDBOOK OF MATHEMATICAL FUNCTIONS +C (REF. 1). +C +C INPUT ZR,ZI,FNU ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI), Z.NE.CMPLX(0.0D0,0.0D0), +C -PI.LT.ARG(Z).LE.PI +C FNU - ORDER OF INITIAL Y FUNCTION, FNU.GE.0.0D0 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C CY(I)=Y(FNU+I-1,Z), I=1,...,N +C = 2 RETURNS +C CY(I)=Y(FNU+I-1,Z)*EXP(-ABS(Y)), I=1,...,N +C WHERE Y=AIMAG(Z) +C N - NUMBER OF MEMBERS OF THE SEQUENCE, N.GE.1 +C CWRKR, - DOUBLE PRECISION WORK VECTORS OF DIMENSION AT +C CWRKI AT LEAST N +C +C OUTPUT CYR,CYI ARE DOUBLE PRECISION +C CYR,CYI- DOUBLE PRECISION VECTORS WHOSE FIRST N COMPONENTS +C CONTAIN REAL AND IMAGINARY PARTS FOR THE SEQUENCE +C CY(I)=Y(FNU+I-1,Z) OR +C CY(I)=Y(FNU+I-1,Z)*EXP(-ABS(Y)) I=1,...,N +C DEPENDING ON KODE. +C NZ - NZ=0 , A NORMAL RETURN +C NZ.GT.0 , NZ COMPONENTS OF CY SET TO ZERO DUE TO +C UNDERFLOW (GENERALLY ON KODE=2) +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, FNU IS +C TOO LARGE OR CABS(Z) IS TOO SMALL OR BOTH +C IERR=3, CABS(Z) OR FNU+N-1 LARGE - COMPUTATION DONE +C BUT LOSSES OF SIGNIFCANCE BY ARGUMENT +C REDUCTION PRODUCE LESS THAN HALF OF MACHINE +C ACCURACY +C IERR=4, CABS(Z) OR FNU+N-1 TOO LARGE - NO COMPUTA- +C TION BECAUSE OF COMPLETE LOSSES OF SIGNIFI- +C CANCE BY ARGUMENT REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C THE COMPUTATION IS CARRIED OUT BY THE FORMULA +C +C Y(FNU,Z)=0.5*(H(1,FNU,Z)-H(2,FNU,Z))/I +C +C WHERE I**2 = -1 AND THE HANKEL BESSEL FUNCTIONS H(1,FNU,Z) +C AND H(2,FNU,Z) ARE CALCULATED IN CBESH. +C +C FOR NEGATIVE ORDERS,THE FORMULA +C +C Y(-FNU,Z) = Y(FNU,Z)*COS(PI*FNU) + J(FNU,Z)*SIN(PI*FNU) +C +C CAN BE USED. HOWEVER,FOR LARGE ORDERS CLOSE TO HALF ODD +C INTEGERS THE FUNCTION CHANGES RADICALLY. WHEN FNU IS A LARGE +C POSITIVE HALF ODD INTEGER,THE MAGNITUDE OF Y(-FNU,Z)=J(FNU,Z)* +C SIN(PI*FNU) IS A LARGE NEGATIVE POWER OF TEN. BUT WHEN FNU IS +C NOT A HALF ODD INTEGER, Y(FNU,Z) DOMINATES IN MAGNITUDE WITH A +C LARGE POSITIVE POWER OF TEN AND THE MOST THAT THE SECOND TERM +C CAN BE REDUCED IS BY UNIT ROUNDOFF FROM THE COEFFICIENT. THUS, +C WIDE CHANGES CAN OCCUR WITHIN UNIT ROUNDOFF OF A LARGE HALF +C ODD INTEGER. HERE, LARGE MEANS FNU.GT.CABS(Z). +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z OR FNU+N-1 IS +C LARGE, LOSSES OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. +C CONSEQUENTLY, IF EITHER ONE EXCEEDS U1=SQRT(0.5/UR), THEN +C LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR FLAG +C IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C IF EITHER IS LARGER THAN U2=0.5/UR, THEN ALL SIGNIFICANCE IS +C LOST AND IERR=4. IN ORDER TO USE THE INT FUNCTION, ARGUMENTS +C MUST BE FURTHER RESTRICTED NOT TO EXCEED THE LARGEST MACHINE +C INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF Z AND FNU+N-1 IS +C RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, AND U3 +C ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE PRECISION +C ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE PRECISION +C ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMITING IN +C THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT ONE CAN EXPECT +C TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, NO DIGITS +C IN SINGLE AND ONLY 7 DIGITS IN DOUBLE PRECISION ARITHMETIC. +C SIMILAR CONSIDERATIONS HOLD FOR OTHER MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C BY D. E. AMOS, SAND83-0083, MAY, 1983. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZBESH,I1MACH,D1MACH +C***END PROLOGUE ZBESY +C +C COMPLEX CWRK,CY,C1,C2,EX,HCI,Z,ZU,ZV + DOUBLE PRECISION CWRKI, CWRKR, CYI, CYR, C1I, C1R, C2I, C2R, + * ELIM, EXI, EXR, EY, FNU, HCII, STI, STR, TAY, ZI, ZR, DEXP, + * D1MACH, ASCLE, RTOL, ATOL, AA, BB, TOL + INTEGER I, IERR, K, KODE, K1, K2, N, NZ, NZ1, NZ2, I1MACH + DIMENSION CYR(N), CYI(N), CWRKR(N), CWRKI(N) +C***FIRST EXECUTABLE STATEMENT ZBESY + IERR = 0 + NZ=0 + IF (ZR.EQ.0.0D0 .AND. ZI.EQ.0.0D0) IERR=1 + IF (FNU.LT.0.0D0) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (N.LT.1) IERR=1 + IF (IERR.NE.0) RETURN + HCII = 0.5D0 + CALL ZBESH(ZR, ZI, FNU, KODE, 1, N, CYR, CYI, NZ1, IERR) + IF (IERR.NE.0.AND.IERR.NE.3) GO TO 170 + CALL ZBESH(ZR, ZI, FNU, KODE, 2, N, CWRKR, CWRKI, NZ2, IERR) + IF (IERR.NE.0.AND.IERR.NE.3) GO TO 170 + NZ = MIN0(NZ1,NZ2) + IF (KODE.EQ.2) GO TO 60 + DO 50 I=1,N + STR = CWRKR(I) - CYR(I) + STI = CWRKI(I) - CYI(I) + CYR(I) = -STI*HCII + CYI(I) = STR*HCII + 50 CONTINUE + RETURN + 60 CONTINUE + TOL = DMAX1(D1MACH(4),1.0D-18) + K1 = I1MACH(15) + K2 = I1MACH(16) + K = MIN0(IABS(K1),IABS(K2)) + R1M5 = D1MACH(5) +C----------------------------------------------------------------------- +C ELIM IS THE APPROXIMATE EXPONENTIAL UNDER- AND OVERFLOW LIMIT +C----------------------------------------------------------------------- + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + EXR = DCOS(ZR) + EXI = DSIN(ZR) + EY = 0.0D0 + TAY = DABS(ZI+ZI) + IF (TAY.LT.ELIM) EY = DEXP(-TAY) + IF (ZI.LT.0.0D0) GO TO 90 + C1R = EXR*EY + C1I = EXI*EY + C2R = EXR + C2I = -EXI + 70 CONTINUE + NZ = 0 + RTOL = 1.0D0/TOL + ASCLE = D1MACH(1)*RTOL*1.0D+3 + DO 80 I=1,N +C STR = C1R*CYR(I) - C1I*CYI(I) +C STI = C1R*CYI(I) + C1I*CYR(I) +C STR = -STR + C2R*CWRKR(I) - C2I*CWRKI(I) +C STI = -STI + C2R*CWRKI(I) + C2I*CWRKR(I) +C CYR(I) = -STI*HCII +C CYI(I) = STR*HCII + AA = CWRKR(I) + BB = CWRKI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 75 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 75 CONTINUE + STR = (AA*C2R - BB*C2I)*ATOL + STI = (AA*C2I + BB*C2R)*ATOL + AA = CYR(I) + BB = CYI(I) + ATOL = 1.0D0 + IF (DMAX1(DABS(AA),DABS(BB)).GT.ASCLE) GO TO 85 + AA = AA*RTOL + BB = BB*RTOL + ATOL = TOL + 85 CONTINUE + STR = STR - (AA*C1R - BB*C1I)*ATOL + STI = STI - (AA*C1I + BB*C1R)*ATOL + CYR(I) = -STI*HCII + CYI(I) = STR*HCII + IF (STR.EQ.0.0D0 .AND. STI.EQ.0.0D0 .AND. EY.EQ.0.0D0) NZ = NZ + * + 1 + 80 CONTINUE + RETURN + 90 CONTINUE + C1R = EXR + C1I = EXI + C2R = EXR*EY + C2I = -EXI*EY + GO TO 70 + 170 CONTINUE + NZ = 0 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbinu.f b/mathext/internal/amos/amoslib/zbinu.f new file mode 100644 index 00000000..b740e707 --- /dev/null +++ b/mathext/internal/amos/amoslib/zbinu.f @@ -0,0 +1,110 @@ + SUBROUTINE ZBINU(ZR, ZI, FNU, KODE, N, CYR, CYI, NZ, RL, FNUL, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZBINU +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZAIRY,ZBIRY +C +C ZBINU COMPUTES THE I FUNCTION IN THE RIGHT HALF Z PLANE +C +C***ROUTINES CALLED ZABS,ZASYI,ZBUNI,ZMLRI,ZSERI,ZUOIK,ZWRSK +C***END PROLOGUE ZBINU + DOUBLE PRECISION ALIM, AZ, CWI, CWR, CYI, CYR, DFNU, ELIM, FNU, + * FNUL, RL, TOL, ZEROI, ZEROR, ZI, ZR, ZABS + INTEGER I, INW, KODE, N, NLAST, NN, NUI, NW, NZ + DIMENSION CYR(N), CYI(N), CWR(2), CWI(2) + DATA ZEROR,ZEROI / 0.0D0, 0.0D0 / +C + NZ = 0 + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + NN = N + DFNU = FNU + DBLE(FLOAT(N-1)) + IF (AZ.LE.2.0D0) GO TO 10 + IF (AZ*AZ*0.25D0.GT.DFNU+1.0D0) GO TO 20 + 10 CONTINUE +C----------------------------------------------------------------------- +C POWER SERIES +C----------------------------------------------------------------------- + CALL ZSERI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, TOL, ELIM, ALIM) + INW = IABS(NW) + NZ = NZ + INW + NN = NN - INW + IF (NN.EQ.0) RETURN + IF (NW.GE.0) GO TO 120 + DFNU = FNU + DBLE(FLOAT(NN-1)) + 20 CONTINUE + IF (AZ.LT.RL) GO TO 40 + IF (DFNU.LE.1.0D0) GO TO 30 + IF (AZ+AZ.LT.DFNU*DFNU) GO TO 50 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR LARGE Z +C----------------------------------------------------------------------- + 30 CONTINUE + CALL ZASYI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, RL, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 130 + GO TO 120 + 40 CONTINUE + IF (DFNU.LE.1.0D0) GO TO 70 + 50 CONTINUE +C----------------------------------------------------------------------- +C OVERFLOW AND UNDERFLOW TEST ON I SEQUENCE FOR MILLER ALGORITHM +C----------------------------------------------------------------------- + CALL ZUOIK(ZR, ZI, FNU, KODE, 1, NN, CYR, CYI, NW, TOL, ELIM, + * ALIM) + IF (NW.LT.0) GO TO 130 + NZ = NZ + NW + NN = NN - NW + IF (NN.EQ.0) RETURN + DFNU = FNU+DBLE(FLOAT(NN-1)) + IF (DFNU.GT.FNUL) GO TO 110 + IF (AZ.GT.FNUL) GO TO 110 + 60 CONTINUE + IF (AZ.GT.RL) GO TO 80 + 70 CONTINUE +C----------------------------------------------------------------------- +C MILLER ALGORITHM NORMALIZED BY THE SERIES +C----------------------------------------------------------------------- + CALL ZMLRI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, TOL) + IF(NW.LT.0) GO TO 130 + GO TO 120 + 80 CONTINUE +C----------------------------------------------------------------------- +C MILLER ALGORITHM NORMALIZED BY THE WRONSKIAN +C----------------------------------------------------------------------- +C----------------------------------------------------------------------- +C OVERFLOW TEST ON K FUNCTIONS USED IN WRONSKIAN +C----------------------------------------------------------------------- + CALL ZUOIK(ZR, ZI, FNU, KODE, 2, 2, CWR, CWI, NW, TOL, ELIM, + * ALIM) + IF (NW.GE.0) GO TO 100 + NZ = NN + DO 90 I=1,NN + CYR(I) = ZEROR + CYI(I) = ZEROI + 90 CONTINUE + RETURN + 100 CONTINUE + IF (NW.GT.0) GO TO 130 + CALL ZWRSK(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, CWR, CWI, TOL, + * ELIM, ALIM) + IF (NW.LT.0) GO TO 130 + GO TO 120 + 110 CONTINUE +C----------------------------------------------------------------------- +C INCREMENT FNU+NN-1 UP TO FNUL, COMPUTE AND RECUR BACKWARD +C----------------------------------------------------------------------- + NUI = INT(SNGL(FNUL-DFNU)) + 1 + NUI = MAX0(NUI,0) + CALL ZBUNI(ZR, ZI, FNU, KODE, NN, CYR, CYI, NW, NUI, NLAST, FNUL, + * TOL, ELIM, ALIM) + IF (NW.LT.0) GO TO 130 + NZ = NZ + NW + IF (NLAST.EQ.0) GO TO 120 + NN = NLAST + GO TO 60 + 120 CONTINUE + RETURN + 130 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbiry.f b/mathext/internal/amos/amoslib/zbiry.f new file mode 100644 index 00000000..f042d824 --- /dev/null +++ b/mathext/internal/amos/amoslib/zbiry.f @@ -0,0 +1,364 @@ + SUBROUTINE ZBIRY(ZR, ZI, ID, KODE, BIR, BII, IERR) +C***BEGIN PROLOGUE ZBIRY +C***DATE WRITTEN 830501 (YYMMDD) +C***REVISION DATE 890801 (YYMMDD) +C***CATEGORY NO. B5K +C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD +C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES +C***PURPOSE TO COMPUTE AIRY FUNCTIONS BI(Z) AND DBI(Z) FOR COMPLEX Z +C***DESCRIPTION +C +C ***A DOUBLE PRECISION ROUTINE*** +C ON KODE=1, CBIRY COMPUTES THE COMPLEX AIRY FUNCTION BI(Z) OR +C ITS DERIVATIVE DBI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON +C KODE=2, A SCALING OPTION CEXP(-AXZTA)*BI(Z) OR CEXP(-AXZTA)* +C DBI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL BEHAVIOR IN +C BOTH THE LEFT AND RIGHT HALF PLANES WHERE +C ZTA=(2/3)*Z*CSQRT(Z)=CMPLX(XZTA,YZTA) AND AXZTA=ABS(XZTA). +C DEFINTIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF +C MATHEMATICAL FUNCTIONS (REF. 1). +C +C INPUT ZR,ZI ARE DOUBLE PRECISION +C ZR,ZI - Z=CMPLX(ZR,ZI) +C ID - ORDER OF DERIVATIVE, ID=0 OR ID=1 +C KODE - A PARAMETER TO INDICATE THE SCALING OPTION +C KODE= 1 RETURNS +C BI=BI(Z) ON ID=0 OR +C BI=DBI(Z)/DZ ON ID=1 +C = 2 RETURNS +C BI=CEXP(-AXZTA)*BI(Z) ON ID=0 OR +C BI=CEXP(-AXZTA)*DBI(Z)/DZ ON ID=1 WHERE +C ZTA=(2/3)*Z*CSQRT(Z)=CMPLX(XZTA,YZTA) +C AND AXZTA=ABS(XZTA) +C +C OUTPUT BIR,BII ARE DOUBLE PRECISION +C BIR,BII- COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND +C KODE +C IERR - ERROR FLAG +C IERR=0, NORMAL RETURN - COMPUTATION COMPLETED +C IERR=1, INPUT ERROR - NO COMPUTATION +C IERR=2, OVERFLOW - NO COMPUTATION, REAL(Z) +C TOO LARGE ON KODE=1 +C IERR=3, CABS(Z) LARGE - COMPUTATION COMPLETED +C LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION +C PRODUCE LESS THAN HALF OF MACHINE ACCURACY +C IERR=4, CABS(Z) TOO LARGE - NO COMPUTATION +C COMPLETE LOSS OF ACCURACY BY ARGUMENT +C REDUCTION +C IERR=5, ERROR - NO COMPUTATION, +C ALGORITHM TERMINATION CONDITION NOT MET +C +C***LONG DESCRIPTION +C +C BI AND DBI ARE COMPUTED FOR CABS(Z).GT.1.0 FROM THE I BESSEL +C FUNCTIONS BY +C +C BI(Z)=C*SQRT(Z)*( I(-1/3,ZTA) + I(1/3,ZTA) ) +C DBI(Z)=C * Z * ( I(-2/3,ZTA) + I(2/3,ZTA) ) +C C=1.0/SQRT(3.0) +C ZTA=(2/3)*Z**(3/2) +C +C WITH THE POWER SERIES FOR CABS(Z).LE.1.0. +C +C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- +C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES +C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF +C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR), +C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR +C FLAG IERR=3 IS TRIGGERED WHERE UR=DMAX1(D1MACH(4),1.0D-18) IS +C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. +C ALSO, IF THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN +C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT +C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE +C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA +C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, +C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE +C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE +C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT- +C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG- +C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN +C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN +C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, +C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE +C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER +C MACHINES. +C +C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX +C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT +C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- +C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE +C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), +C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF +C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY +C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN +C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY +C SEVERAL ORDERS OF MAGNITUDE. IF ONE COMPONENT IS 10**K LARGER +C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, +C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS +C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER +C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY +C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER +C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE +C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, +C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, +C OR -PI/2+P. +C +C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ +C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF +C COMMERCE, 1955. +C +C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT +C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 +C +C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- +C 1018, MAY, 1985 +C +C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX +C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. +C MATH. SOFTWARE, 1986 +C +C***ROUTINES CALLED ZBINU,ZABS,ZDIV,ZSQRT,D1MACH,I1MACH +C***END PROLOGUE ZBIRY +C COMPLEX BI,CONE,CSQ,CY,S1,S2,TRM1,TRM2,Z,ZTA,Z3 + DOUBLE PRECISION AA, AD, AK, ALIM, ATRM, AZ, AZ3, BB, BII, BIR, + * BK, CC, CK, COEF, CONEI, CONER, CSQI, CSQR, CYI, CYR, C1, C2, + * DIG, DK, D1, D2, EAA, ELIM, FID, FMR, FNU, FNUL, PI, RL, R1M5, + * SFAC, STI, STR, S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, + * TRM2R, TTH, ZI, ZR, ZTAI, ZTAR, Z3I, Z3R, D1MACH, ZABS + INTEGER ID, IERR, K, KODE, K1, K2, NZ, I1MACH + DIMENSION CYR(2), CYI(2) + DATA TTH, C1, C2, COEF, PI /6.66666666666666667D-01, + * 6.14926627446000736D-01,4.48288357353826359D-01, + * 5.77350269189625765D-01,3.14159265358979324D+00/ + DATA CONER, CONEI /1.0D0,0.0D0/ +C***FIRST EXECUTABLE STATEMENT ZBIRY + IERR = 0 + NZ=0 + IF (ID.LT.0 .OR. ID.GT.1) IERR=1 + IF (KODE.LT.1 .OR. KODE.GT.2) IERR=1 + IF (IERR.NE.0) RETURN + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + TOL = DMAX1(D1MACH(4),1.0D-18) + FID = DBLE(FLOAT(ID)) + IF (AZ.GT.1.0E0) GO TO 70 +C----------------------------------------------------------------------- +C POWER SERIES FOR CABS(Z).LE.1. +C----------------------------------------------------------------------- + S1R = CONER + S1I = CONEI + S2R = CONER + S2I = CONEI + IF (AZ.LT.TOL) GO TO 130 + AA = AZ*AZ + IF (AA.LT.TOL/AZ) GO TO 40 + TRM1R = CONER + TRM1I = CONEI + TRM2R = CONER + TRM2I = CONEI + ATRM = 1.0D0 + STR = ZR*ZR - ZI*ZI + STI = ZR*ZI + ZI*ZR + Z3R = STR*ZR - STI*ZI + Z3I = STR*ZI + STI*ZR + AZ3 = AZ*AA + AK = 2.0D0 + FID + BK = 3.0D0 - FID - FID + CK = 4.0D0 - FID + DK = 3.0D0 + FID + FID + D1 = AK*DK + D2 = BK*CK + AD = DMIN1(D1,D2) + AK = 24.0D0 + 9.0D0*FID + BK = 30.0D0 - 9.0D0*FID + DO 30 K=1,25 + STR = (TRM1R*Z3R-TRM1I*Z3I)/D1 + TRM1I = (TRM1R*Z3I+TRM1I*Z3R)/D1 + TRM1R = STR + S1R = S1R + TRM1R + S1I = S1I + TRM1I + STR = (TRM2R*Z3R-TRM2I*Z3I)/D2 + TRM2I = (TRM2R*Z3I+TRM2I*Z3R)/D2 + TRM2R = STR + S2R = S2R + TRM2R + S2I = S2I + TRM2I + ATRM = ATRM*AZ3/AD + D1 = D1 + AK + D2 = D2 + BK + AD = DMIN1(D1,D2) + IF (ATRM.LT.TOL*AD) GO TO 40 + AK = AK + 18.0D0 + BK = BK + 18.0D0 + 30 CONTINUE + 40 CONTINUE + IF (ID.EQ.1) GO TO 50 + BIR = C1*S1R + C2*(ZR*S2R-ZI*S2I) + BII = C1*S1I + C2*(ZR*S2I+ZI*S2R) + IF (KODE.EQ.1) RETURN + CALL ZSQRT(ZR, ZI, STR, STI) + ZTAR = TTH*(ZR*STR-ZI*STI) + ZTAI = TTH*(ZR*STI+ZI*STR) + AA = ZTAR + AA = -DABS(AA) + EAA = DEXP(AA) + BIR = BIR*EAA + BII = BII*EAA + RETURN + 50 CONTINUE + BIR = S2R*C2 + BII = S2I*C2 + IF (AZ.LE.TOL) GO TO 60 + CC = C1/(1.0D0+FID) + STR = S1R*ZR - S1I*ZI + STI = S1R*ZI + S1I*ZR + BIR = BIR + CC*(STR*ZR-STI*ZI) + BII = BII + CC*(STR*ZI+STI*ZR) + 60 CONTINUE + IF (KODE.EQ.1) RETURN + CALL ZSQRT(ZR, ZI, STR, STI) + ZTAR = TTH*(ZR*STR-ZI*STI) + ZTAI = TTH*(ZR*STI+ZI*STR) + AA = ZTAR + AA = -DABS(AA) + EAA = DEXP(AA) + BIR = BIR*EAA + BII = BII*EAA + RETURN +C----------------------------------------------------------------------- +C CASE FOR CABS(Z).GT.1.0 +C----------------------------------------------------------------------- + 70 CONTINUE + FNU = (1.0D0+FID)/3.0D0 +C----------------------------------------------------------------------- +C SET PARAMETERS RELATED TO MACHINE CONSTANTS. +C TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0E-18. +C ELIM IS THE APPROXIMATE EXPONENTIAL OVER- AND UNDERFLOW LIMIT. +C EXP(-ELIM).LT.EXP(-ALIM)=EXP(-ELIM)/TOL AND +C EXP(ELIM).GT.EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR +C UNDERFLOW AND OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. +C RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LARGE Z. +C DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). +C FNUL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC SERIES FOR LARGE FNU. +C----------------------------------------------------------------------- + K1 = I1MACH(15) + K2 = I1MACH(16) + R1M5 = D1MACH(5) + K = MIN0(IABS(K1),IABS(K2)) + ELIM = 2.303D0*(DBLE(FLOAT(K))*R1M5-3.0D0) + K1 = I1MACH(14) - 1 + AA = R1M5*DBLE(FLOAT(K1)) + DIG = DMIN1(AA,18.0D0) + AA = AA*2.303D0 + ALIM = ELIM + DMAX1(-AA,-41.45D0) + RL = 1.2D0*DIG + 3.0D0 + FNUL = 10.0D0 + 6.0D0*(DIG-3.0D0) +C----------------------------------------------------------------------- +C TEST FOR RANGE +C----------------------------------------------------------------------- + AA=0.5D0/TOL + BB=DBLE(FLOAT(I1MACH(9)))*0.5D0 + AA=DMIN1(AA,BB) + AA=AA**TTH + IF (AZ.GT.AA) GO TO 260 + AA=DSQRT(AA) + IF (AZ.GT.AA) IERR=3 + CALL ZSQRT(ZR, ZI, CSQR, CSQI) + ZTAR = TTH*(ZR*CSQR-ZI*CSQI) + ZTAI = TTH*(ZR*CSQI+ZI*CSQR) +C----------------------------------------------------------------------- +C RE(ZTA).LE.0 WHEN RE(Z).LT.0, ESPECIALLY WHEN IM(Z) IS SMALL +C----------------------------------------------------------------------- + SFAC = 1.0D0 + AK = ZTAI + IF (ZR.GE.0.0D0) GO TO 80 + BK = ZTAR + CK = -DABS(BK) + ZTAR = CK + ZTAI = AK + 80 CONTINUE + IF (ZI.NE.0.0D0 .OR. ZR.GT.0.0D0) GO TO 90 + ZTAR = 0.0D0 + ZTAI = AK + 90 CONTINUE + AA = ZTAR + IF (KODE.EQ.2) GO TO 100 +C----------------------------------------------------------------------- +C OVERFLOW TEST +C----------------------------------------------------------------------- + BB = DABS(AA) + IF (BB.LT.ALIM) GO TO 100 + BB = BB + 0.25D0*DLOG(AZ) + SFAC = TOL + IF (BB.GT.ELIM) GO TO 190 + 100 CONTINUE + FMR = 0.0D0 + IF (AA.GE.0.0D0 .AND. ZR.GT.0.0D0) GO TO 110 + FMR = PI + IF (ZI.LT.0.0D0) FMR = -PI + ZTAR = -ZTAR + ZTAI = -ZTAI + 110 CONTINUE +C----------------------------------------------------------------------- +C AA=FACTOR FOR ANALYTIC CONTINUATION OF I(FNU,ZTA) +C KODE=2 RETURNS EXP(-ABS(XZTA))*I(FNU,ZTA) FROM CBESI +C----------------------------------------------------------------------- + CALL ZBINU(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, RL, FNUL, TOL, + * ELIM, ALIM) + IF (NZ.LT.0) GO TO 200 + AA = FMR*FNU + Z3R = SFAC + STR = DCOS(AA) + STI = DSIN(AA) + S1R = (STR*CYR(1)-STI*CYI(1))*Z3R + S1I = (STR*CYI(1)+STI*CYR(1))*Z3R + FNU = (2.0D0-FID)/3.0D0 + CALL ZBINU(ZTAR, ZTAI, FNU, KODE, 2, CYR, CYI, NZ, RL, FNUL, TOL, + * ELIM, ALIM) + CYR(1) = CYR(1)*Z3R + CYI(1) = CYI(1)*Z3R + CYR(2) = CYR(2)*Z3R + CYI(2) = CYI(2)*Z3R +C----------------------------------------------------------------------- +C BACKWARD RECUR ONE STEP FOR ORDERS -1/3 OR -2/3 +C----------------------------------------------------------------------- + CALL ZDIV(CYR(1), CYI(1), ZTAR, ZTAI, STR, STI) + S2R = (FNU+FNU)*STR + CYR(2) + S2I = (FNU+FNU)*STI + CYI(2) + AA = FMR*(FNU-1.0D0) + STR = DCOS(AA) + STI = DSIN(AA) + S1R = COEF*(S1R+S2R*STR-S2I*STI) + S1I = COEF*(S1I+S2R*STI+S2I*STR) + IF (ID.EQ.1) GO TO 120 + STR = CSQR*S1R - CSQI*S1I + S1I = CSQR*S1I + CSQI*S1R + S1R = STR + BIR = S1R/SFAC + BII = S1I/SFAC + RETURN + 120 CONTINUE + STR = ZR*S1R - ZI*S1I + S1I = ZR*S1I + ZI*S1R + S1R = STR + BIR = S1R/SFAC + BII = S1I/SFAC + RETURN + 130 CONTINUE + AA = C1*(1.0D0-FID) + FID*C2 + BIR = AA + BII = 0.0D0 + RETURN + 190 CONTINUE + IERR=2 + NZ=0 + RETURN + 200 CONTINUE + IF(NZ.EQ.(-1)) GO TO 190 + NZ=0 + IERR=5 + RETURN + 260 CONTINUE + IERR=4 + NZ=0 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbknu.f b/mathext/internal/amos/amoslib/zbknu.f new file mode 100644 index 00000000..ef932d40 --- /dev/null +++ b/mathext/internal/amos/amoslib/zbknu.f @@ -0,0 +1,568 @@ + SUBROUTINE ZBKNU(ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZBKNU +C***REFER TO ZBESI,ZBESK,ZAIRY,ZBESH +C +C ZBKNU COMPUTES THE K BESSEL FUNCTION IN THE RIGHT HALF Z PLANE. +C +C***ROUTINES CALLED DGAMLN,I1MACH,D1MACH,ZKSCL,ZSHCH,ZUCHK,ZABS,ZDIV, +C ZEXP,ZLOG,ZMLT,ZSQRT +C***END PROLOGUE ZBKNU +C + DOUBLE PRECISION AA, AK, ALIM, ASCLE, A1, A2, BB, BK, BRY, CAZ, + * CBI, CBR, CC, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER, + * CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CSRR, CSSR, CTWOR, + * CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ELIM, ETEST, FC, FHS, + * FI, FK, FKS, FMUI, FMUR, FNU, FPI, FR, G1, G2, HPI, PI, PR, PTI, + * PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI, + * RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM, + * TOL, TTH, T1, T2, YI, YR, ZI, ZR, DGAMLN, D1MACH, ZABS, ELM, + * CELMR, ZDR, ZDI, AS, ALAS, HELIM, CYR, CYI + INTEGER I, IFLAG, INU, K, KFLAG, KK, KMAX, KODE, KODED, N, NZ, + * IDUM, I1MACH, J, IC, INUB, NW + DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2), + * CYI(2) +C COMPLEX Z,Y,A,B,RZ,SMU,FU,FMU,F,FLRZ,CZ,S1,S2,CSH,CCH +C COMPLEX CK,P,Q,COEF,P1,P2,CBK,PT,CZERO,CONE,CTWO,ST,EZ,CS,DK +C + DATA KMAX / 30 / + DATA CZEROR,CZEROI,CONER,CONEI,CTWOR,R1/ + 1 0.0D0 , 0.0D0 , 1.0D0 , 0.0D0 , 2.0D0 , 2.0D0 / + DATA DPI, RTHPI, SPI ,HPI, FPI, TTH / + 1 3.14159265358979324D0, 1.25331413731550025D0, + 2 1.90985931710274403D0, 1.57079632679489662D0, + 3 1.89769999331517738D0, 6.66666666666666666D-01/ + DATA CC(1), CC(2), CC(3), CC(4), CC(5), CC(6), CC(7), CC(8)/ + 1 5.77215664901532861D-01, -4.20026350340952355D-02, + 2 -4.21977345555443367D-02, 7.21894324666309954D-03, + 3 -2.15241674114950973D-04, -2.01348547807882387D-05, + 4 1.13302723198169588D-06, 6.11609510448141582D-09/ +C + CAZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + CSCLR = 1.0D0/TOL + CRSCR = TOL + CSSR(1) = CSCLR + CSSR(2) = 1.0D0 + CSSR(3) = CRSCR + CSRR(1) = CRSCR + CSRR(2) = 1.0D0 + CSRR(3) = CSCLR + BRY(1) = 1.0D+3*D1MACH(1)/TOL + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + NZ = 0 + IFLAG = 0 + KODED = KODE + RCAZ = 1.0D0/CAZ + STR = ZR*RCAZ + STI = -ZI*RCAZ + RZR = (STR+STR)*RCAZ + RZI = (STI+STI)*RCAZ + INU = INT(SNGL(FNU+0.5D0)) + DNU = FNU - DBLE(FLOAT(INU)) + IF (DABS(DNU).EQ.0.5D0) GO TO 110 + DNU2 = 0.0D0 + IF (DABS(DNU).GT.TOL) DNU2 = DNU*DNU + IF (CAZ.GT.R1) GO TO 110 +C----------------------------------------------------------------------- +C SERIES FOR CABS(Z).LE.R1 +C----------------------------------------------------------------------- + FC = 1.0D0 + CALL ZLOG(RZR, RZI, SMUR, SMUI, IDUM) + FMUR = SMUR*DNU + FMUI = SMUI*DNU + CALL ZSHCH(FMUR, FMUI, CSHR, CSHI, CCHR, CCHI) + IF (DNU.EQ.0.0D0) GO TO 10 + FC = DNU*DPI + FC = FC/DSIN(FC) + SMUR = CSHR/DNU + SMUI = CSHI/DNU + 10 CONTINUE + A2 = 1.0D0 + DNU +C----------------------------------------------------------------------- +C GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU) +C----------------------------------------------------------------------- + T2 = DEXP(-DGAMLN(A2,IDUM)) + T1 = 1.0D0/(T2*FC) + IF (DABS(DNU).GT.0.1D0) GO TO 40 +C----------------------------------------------------------------------- +C SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU) +C----------------------------------------------------------------------- + AK = 1.0D0 + S = CC(1) + DO 20 K=2,8 + AK = AK*DNU2 + TM = CC(K)*AK + S = S + TM + IF (DABS(TM).LT.TOL) GO TO 30 + 20 CONTINUE + 30 G1 = -S + GO TO 50 + 40 CONTINUE + G1 = (T1-T2)/(DNU+DNU) + 50 CONTINUE + G2 = (T1+T2)*0.5D0 + FR = FC*(CCHR*G1+SMUR*G2) + FI = FC*(CCHI*G1+SMUI*G2) + CALL ZEXP(FMUR, FMUI, STR, STI) + PR = 0.5D0*STR/T2 + PI = 0.5D0*STI/T2 + CALL ZDIV(0.5D0, 0.0D0, STR, STI, PTR, PTI) + QR = PTR/T1 + QI = PTI/T1 + S1R = FR + S1I = FI + S2R = PR + S2I = PI + AK = 1.0D0 + A1 = 1.0D0 + CKR = CONER + CKI = CONEI + BK = 1.0D0 - DNU2 + IF (INU.GT.0 .OR. N.GT.1) GO TO 80 +C----------------------------------------------------------------------- +C GENERATE K(FNU,Z), 0.0D0 .LE. FNU .LT. 0.5D0 AND N=1 +C----------------------------------------------------------------------- + IF (CAZ.LT.TOL) GO TO 70 + CALL ZMLT(ZR, ZI, ZR, ZI, CZR, CZI) + CZR = 0.25D0*CZR + CZI = 0.25D0*CZI + T1 = 0.25D0*CAZ*CAZ + 60 CONTINUE + FR = (FR*AK+PR+QR)/BK + FI = (FI*AK+PI+QI)/BK + STR = 1.0D0/(AK-DNU) + PR = PR*STR + PI = PI*STR + STR = 1.0D0/(AK+DNU) + QR = QR*STR + QI = QI*STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0D0/AK + CKI = (CKR*CZI+CKI*CZR)*RAK + CKR = STR*RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + A1 = A1*T1*RAK + BK = BK + AK + AK + 1.0D0 + AK = AK + 1.0D0 + IF (A1.GT.TOL) GO TO 60 + 70 CONTINUE + YR(1) = S1R + YI(1) = S1I + IF (KODED.EQ.1) RETURN + CALL ZEXP(ZR, ZI, STR, STI) + CALL ZMLT(S1R, S1I, STR, STI, YR(1), YI(1)) + RETURN +C----------------------------------------------------------------------- +C GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE +C----------------------------------------------------------------------- + 80 CONTINUE + IF (CAZ.LT.TOL) GO TO 100 + CALL ZMLT(ZR, ZI, ZR, ZI, CZR, CZI) + CZR = 0.25D0*CZR + CZI = 0.25D0*CZI + T1 = 0.25D0*CAZ*CAZ + 90 CONTINUE + FR = (FR*AK+PR+QR)/BK + FI = (FI*AK+PI+QI)/BK + STR = 1.0D0/(AK-DNU) + PR = PR*STR + PI = PI*STR + STR = 1.0D0/(AK+DNU) + QR = QR*STR + QI = QI*STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0D0/AK + CKI = (CKR*CZI+CKI*CZR)*RAK + CKR = STR*RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + STR = PR - FR*AK + STI = PI - FI*AK + S2R = CKR*STR - CKI*STI + S2R + S2I = CKR*STI + CKI*STR + S2I + A1 = A1*T1*RAK + BK = BK + AK + AK + 1.0D0 + AK = AK + 1.0D0 + IF (A1.GT.TOL) GO TO 90 + 100 CONTINUE + KFLAG = 2 + A1 = FNU + 1.0D0 + AK = A1*DABS(SMUR) + IF (AK.GT.ALIM) KFLAG = 3 + STR = CSSR(KFLAG) + P2R = S2R*STR + P2I = S2I*STR + CALL ZMLT(P2R, P2I, RZR, RZI, S2R, S2I) + S1R = S1R*STR + S1I = S1I*STR + IF (KODED.EQ.1) GO TO 210 + CALL ZEXP(ZR, ZI, FR, FI) + CALL ZMLT(S1R, S1I, FR, FI, S1R, S1I) + CALL ZMLT(S2R, S2I, FR, FI, S2R, S2I) + GO TO 210 +C----------------------------------------------------------------------- +C IFLAG=0 MEANS NO UNDERFLOW OCCURRED +C IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH +C KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD +C RECURSION +C----------------------------------------------------------------------- + 110 CONTINUE + CALL ZSQRT(ZR, ZI, STR, STI) + CALL ZDIV(RTHPI, CZEROI, STR, STI, COEFR, COEFI) + KFLAG = 2 + IF (KODED.EQ.2) GO TO 120 + IF (ZR.GT.ALIM) GO TO 290 +C BLANK LINE + STR = DEXP(-ZR)*CSSR(KFLAG) + STI = -STR*DSIN(ZI) + STR = STR*DCOS(ZI) + CALL ZMLT(COEFR, COEFI, STR, STI, COEFR, COEFI) + 120 CONTINUE + IF (DABS(DNU).EQ.0.5D0) GO TO 300 +C----------------------------------------------------------------------- +C MILLER ALGORITHM FOR CABS(Z).GT.R1 +C----------------------------------------------------------------------- + AK = DCOS(DPI*DNU) + AK = DABS(AK) + IF (AK.EQ.CZEROR) GO TO 300 + FHS = DABS(0.25D0-DNU2) + IF (FHS.EQ.CZEROR) GO TO 300 +C----------------------------------------------------------------------- +C COMPUTE R2=F(E). IF CABS(Z).GE.R2, USE FORWARD RECURRENCE TO +C DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON +C 12.LE.E.LE.60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))= +C TOL WHERE B IS THE BASE OF THE ARITHMETIC. +C----------------------------------------------------------------------- + T1 = DBLE(FLOAT(I1MACH(14)-1)) + T1 = T1*D1MACH(5)*3.321928094D0 + T1 = DMAX1(T1,12.0D0) + T1 = DMIN1(T1,60.0D0) + T2 = TTH*T1 - 6.0D0 + IF (ZR.NE.0.0D0) GO TO 130 + T1 = HPI + GO TO 140 + 130 CONTINUE + T1 = DATAN(ZI/ZR) + T1 = DABS(T1) + 140 CONTINUE + IF (T2.GT.CAZ) GO TO 170 +C----------------------------------------------------------------------- +C FORWARD RECURRENCE LOOP WHEN CABS(Z).GE.R2 +C----------------------------------------------------------------------- + ETEST = AK/(DPI*CAZ*TOL) + FK = CONER + IF (ETEST.LT.CONER) GO TO 180 + FKS = CTWOR + CKR = CAZ + CAZ + CTWOR + P1R = CZEROR + P2R = CONER + DO 150 I=1,KMAX + AK = FHS/FKS + CBR = CKR/(FK+CONER) + PTR = P2R + P2R = CBR*P2R - P1R*AK + P1R = PTR + CKR = CKR + CTWOR + FKS = FKS + FK + FK + CTWOR + FHS = FHS + FK + FK + FK = FK + CONER + STR = DABS(P2R)*FK + IF (ETEST.LT.STR) GO TO 160 + 150 CONTINUE + GO TO 310 + 160 CONTINUE + FK = FK + SPI*T1*DSQRT(T2/CAZ) + FHS = DABS(0.25D0-DNU2) + GO TO 180 + 170 CONTINUE +C----------------------------------------------------------------------- +C COMPUTE BACKWARD INDEX K FOR CABS(Z).LT.R2 +C----------------------------------------------------------------------- + A2 = DSQRT(CAZ) + AK = FPI*AK/(TOL*DSQRT(A2)) + AA = 3.0D0*T1/(1.0D0+CAZ) + BB = 14.7D0*T1/(28.0D0+CAZ) + AK = (DLOG(AK)+CAZ*DCOS(AA)/(1.0D0+0.008D0*CAZ))/DCOS(BB) + FK = 0.12125D0*AK*AK/CAZ + 1.5D0 + 180 CONTINUE +C----------------------------------------------------------------------- +C BACKWARD RECURRENCE LOOP FOR MILLER ALGORITHM +C----------------------------------------------------------------------- + K = INT(SNGL(FK)) + FK = DBLE(FLOAT(K)) + FKS = FK*FK + P1R = CZEROR + P1I = CZEROI + P2R = TOL + P2I = CZEROI + CSR = P2R + CSI = P2I + DO 190 I=1,K + A1 = FKS - FK + AK = (FKS+FK)/(A1+FHS) + RAK = 2.0D0/(FK+CONER) + CBR = (FK+ZR)*RAK + CBI = ZI*RAK + PTR = P2R + PTI = P2I + P2R = (PTR*CBR-PTI*CBI-P1R)*AK + P2I = (PTI*CBR+PTR*CBI-P1I)*AK + P1R = PTR + P1I = PTI + CSR = CSR + P2R + CSI = CSI + P2I + FKS = A1 - FK + CONER + FK = FK - CONER + 190 CONTINUE +C----------------------------------------------------------------------- +C COMPUTE (P2/CS)=(P2/CABS(CS))*(CONJG(CS)/CABS(CS)) FOR BETTER +C SCALING +C----------------------------------------------------------------------- + TM = ZABS(CMPLX(CSR,CSI,kind=KIND(1.0D0))) + PTR = 1.0D0/TM + S1R = P2R*PTR + S1I = P2I*PTR + CSR = CSR*PTR + CSI = -CSI*PTR + CALL ZMLT(COEFR, COEFI, S1R, S1I, STR, STI) + CALL ZMLT(STR, STI, CSR, CSI, S1R, S1I) + IF (INU.GT.0 .OR. N.GT.1) GO TO 200 + ZDR = ZR + ZDI = ZI + IF(IFLAG.EQ.1) GO TO 270 + GO TO 240 + 200 CONTINUE +C----------------------------------------------------------------------- +C COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING +C----------------------------------------------------------------------- + TM = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + PTR = 1.0D0/TM + P1R = P1R*PTR + P1I = P1I*PTR + P2R = P2R*PTR + P2I = -P2I*PTR + CALL ZMLT(P1R, P1I, P2R, P2I, PTR, PTI) + STR = DNU + 0.5D0 - PTR + STI = -PTI + CALL ZDIV(STR, STI, ZR, ZI, STR, STI) + STR = STR + 1.0D0 + CALL ZMLT(STR, STI, S1R, S1I, S2R, S2I) +C----------------------------------------------------------------------- +C FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH +C SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3 +C----------------------------------------------------------------------- + 210 CONTINUE + STR = DNU + 1.0D0 + CKR = STR*RZR + CKI = STR*RZI + IF (N.EQ.1) INU = INU - 1 + IF (INU.GT.0) GO TO 220 + IF (N.GT.1) GO TO 215 + S1R = S2R + S1I = S2I + 215 CONTINUE + ZDR = ZR + ZDI = ZI + IF(IFLAG.EQ.1) GO TO 270 + GO TO 240 + 220 CONTINUE + INUB = 1 + IF(IFLAG.EQ.1) GO TO 261 + 225 CONTINUE + P1R = CSRR(KFLAG) + ASCLE = BRY(KFLAG) + DO 230 I=INUB,INU + STR = S2R + STI = S2I + S2R = CKR*STR - CKI*STI + S1R + S2I = CKR*STI + CKI*STR + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + IF (KFLAG.GE.3) GO TO 230 + P2R = S2R*P1R + P2I = S2I*P1R + STR = DABS(P2R) + STI = DABS(P2I) + P2M = DMAX1(STR,STI) + IF (P2M.LE.ASCLE) GO TO 230 + KFLAG = KFLAG + 1 + ASCLE = BRY(KFLAG) + S1R = S1R*P1R + S1I = S1I*P1R + S2R = P2R + S2I = P2I + STR = CSSR(KFLAG) + S1R = S1R*STR + S1I = S1I*STR + S2R = S2R*STR + S2I = S2I*STR + P1R = CSRR(KFLAG) + 230 CONTINUE + IF (N.NE.1) GO TO 240 + S1R = S2R + S1I = S2I + 240 CONTINUE + STR = CSRR(KFLAG) + YR(1) = S1R*STR + YI(1) = S1I*STR + IF (N.EQ.1) RETURN + YR(2) = S2R*STR + YI(2) = S2I*STR + IF (N.EQ.2) RETURN + KK = 2 + 250 CONTINUE + KK = KK + 1 + IF (KK.GT.N) RETURN + P1R = CSRR(KFLAG) + ASCLE = BRY(KFLAG) + DO 260 I=KK,N + P2R = S2R + P2I = S2I + S2R = CKR*P2R - CKI*P2I + S1R + S2I = CKI*P2R + CKR*P2I + S1I + S1R = P2R + S1I = P2I + CKR = CKR + RZR + CKI = CKI + RZI + P2R = S2R*P1R + P2I = S2I*P1R + YR(I) = P2R + YI(I) = P2I + IF (KFLAG.GE.3) GO TO 260 + STR = DABS(P2R) + STI = DABS(P2I) + P2M = DMAX1(STR,STI) + IF (P2M.LE.ASCLE) GO TO 260 + KFLAG = KFLAG + 1 + ASCLE = BRY(KFLAG) + S1R = S1R*P1R + S1I = S1I*P1R + S2R = P2R + S2I = P2I + STR = CSSR(KFLAG) + S1R = S1R*STR + S1I = S1I*STR + S2R = S2R*STR + S2I = S2I*STR + P1R = CSRR(KFLAG) + 260 CONTINUE + RETURN +C----------------------------------------------------------------------- +C IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW +C----------------------------------------------------------------------- + 261 CONTINUE + HELIM = 0.5D0*ELIM + ELM = DEXP(-ELIM) + CELMR = ELM + ASCLE = BRY(1) + ZDR = ZR + ZDI = ZI + IC = -1 + J = 2 + DO 262 I=1,INU + STR = S2R + STI = S2I + S2R = STR*CKR-STI*CKI+S1R + S2I = STI*CKR+STR*CKI+S1I + S1R = STR + S1I = STI + CKR = CKR+RZR + CKI = CKI+RZI + AS = ZABS(CMPLX(S2R,S2I,kind=KIND(1.0D0))) + ALAS = DLOG(AS) + P2R = -ZDR+ALAS + IF(P2R.LT.(-ELIM)) GO TO 263 + CALL ZLOG(S2R,S2I,STR,STI,IDUM) + P2R = -ZDR+STR + P2I = -ZDI+STI + P2M = DEXP(P2R)/TOL + P1R = P2M*DCOS(P2I) + P1I = P2M*DSIN(P2I) + CALL ZUCHK(P1R,P1I,NW,ASCLE,TOL) + IF(NW.NE.0) GO TO 263 + J = 3 - J + CYR(J) = P1R + CYI(J) = P1I + IF(IC.EQ.(I-1)) GO TO 264 + IC = I + GO TO 262 + 263 CONTINUE + IF(ALAS.LT.HELIM) GO TO 262 + ZDR = ZDR-ELIM + S1R = S1R*CELMR + S1I = S1I*CELMR + S2R = S2R*CELMR + S2I = S2I*CELMR + 262 CONTINUE + IF(N.NE.1) GO TO 270 + S1R = S2R + S1I = S2I + GO TO 270 + 264 CONTINUE + KFLAG = 1 + INUB = I+1 + S2R = CYR(J) + S2I = CYI(J) + J = 3 - J + S1R = CYR(J) + S1I = CYI(J) + IF(INUB.LE.INU) GO TO 225 + IF(N.NE.1) GO TO 240 + S1R = S2R + S1I = S2I + GO TO 240 + 270 CONTINUE + YR(1) = S1R + YI(1) = S1I + IF(N.EQ.1) GO TO 280 + YR(2) = S2R + YI(2) = S2I + 280 CONTINUE + ASCLE = BRY(1) + CALL ZKSCL(ZDR,ZDI,FNU,N,YR,YI,NZ,RZR,RZI,ASCLE,TOL,ELIM) + INU = N - NZ + IF (INU.LE.0) RETURN + KK = NZ + 1 + S1R = YR(KK) + S1I = YI(KK) + YR(KK) = S1R*CSRR(1) + YI(KK) = S1I*CSRR(1) + IF (INU.EQ.1) RETURN + KK = NZ + 2 + S2R = YR(KK) + S2I = YI(KK) + YR(KK) = S2R*CSRR(1) + YI(KK) = S2I*CSRR(1) + IF (INU.EQ.2) RETURN + T2 = FNU + DBLE(FLOAT(KK-1)) + CKR = T2*RZR + CKI = T2*RZI + KFLAG = 1 + GO TO 250 + 290 CONTINUE +C----------------------------------------------------------------------- +C SCALE BY DEXP(Z), IFLAG = 1 CASES +C----------------------------------------------------------------------- + KODED = 2 + IFLAG = 1 + KFLAG = 2 + GO TO 120 +C----------------------------------------------------------------------- +C FNU=HALF ODD INTEGER CASE, DNU=-0.5 +C----------------------------------------------------------------------- + 300 CONTINUE + S1R = COEFR + S1I = COEFI + S2R = COEFR + S2I = COEFI + GO TO 210 +C +C + 310 CONTINUE + NZ=-2 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbuni.f b/mathext/internal/amos/amoslib/zbuni.f new file mode 100644 index 00000000..3811b89a --- /dev/null +++ b/mathext/internal/amos/amoslib/zbuni.f @@ -0,0 +1,174 @@ + SUBROUTINE ZBUNI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, NUI, NLAST, + * FNUL, TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZBUNI +C***REFER TO ZBESI,ZBESK +C +C ZBUNI COMPUTES THE I BESSEL FUNCTION FOR LARGE CABS(Z).GT. +C FNUL AND FNU+N-1.LT.FNUL. THE ORDER IS INCREASED FROM +C FNU+N-1 GREATER THAN FNUL BY ADDING NUI AND COMPUTING +C ACCORDING TO THE UNIFORM ASYMPTOTIC EXPANSION FOR I(FNU,Z) +C ON IFORM=1 AND THE EXPANSION FOR J(FNU,Z) ON IFORM=2 +C +C***ROUTINES CALLED ZUNI1,ZUNI2,ZABS,D1MACH +C***END PROLOGUE ZBUNI +C COMPLEX CSCL,CSCR,CY,RZ,ST,S1,S2,Y,Z + DOUBLE PRECISION ALIM, AX, AY, CSCLR, CSCRR, CYI, CYR, DFNU, + * ELIM, FNU, FNUI, FNUL, GNU, RAZ, RZI, RZR, STI, STR, S1I, S1R, + * S2I, S2R, TOL, YI, YR, ZI, ZR, ZABS, ASCLE, BRY, C1R, C1I, C1M, + * D1MACH + INTEGER I, IFLAG, IFORM, K, KODE, N, NL, NLAST, NUI, NW, NZ + DIMENSION YR(N), YI(N), CYR(2), CYI(2), BRY(3) + NZ = 0 + AX = DABS(ZR)*1.7321D0 + AY = DABS(ZI) + IFORM = 1 + IF (AY.GT.AX) IFORM = 2 + IF (NUI.EQ.0) GO TO 60 + FNUI = DBLE(FLOAT(NUI)) + DFNU = FNU + DBLE(FLOAT(N-1)) + GNU = DFNU + FNUI + IF (IFORM.EQ.2) GO TO 10 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR I(FNU,Z) FOR LARGE FNU APPLIED IN +C -PI/3.LE.ARG(Z).LE.PI/3 +C----------------------------------------------------------------------- + CALL ZUNI1(ZR, ZI, GNU, KODE, 2, CYR, CYI, NW, NLAST, FNUL, TOL, + * ELIM, ALIM) + GO TO 20 + 10 CONTINUE +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR J(FNU,Z*EXP(M*HPI)) FOR LARGE FNU +C APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I +C AND HPI=PI/2 +C----------------------------------------------------------------------- + CALL ZUNI2(ZR, ZI, GNU, KODE, 2, CYR, CYI, NW, NLAST, FNUL, TOL, + * ELIM, ALIM) + 20 CONTINUE + IF (NW.LT.0) GO TO 50 + IF (NW.NE.0) GO TO 90 + STR = ZABS(CMPLX(CYR(1),CYI(1),kind=KIND(1.0D0))) +C---------------------------------------------------------------------- +C SCALE BACKWARD RECURRENCE, BRY(3) IS DEFINED BUT NEVER USED +C---------------------------------------------------------------------- + BRY(1)=1.0D+3*D1MACH(1)/TOL + BRY(2) = 1.0D0/BRY(1) + BRY(3) = BRY(2) + IFLAG = 2 + ASCLE = BRY(2) + CSCLR = 1.0D0 + IF (STR.GT.BRY(1)) GO TO 21 + IFLAG = 1 + ASCLE = BRY(1) + CSCLR = 1.0D0/TOL + GO TO 25 + 21 CONTINUE + IF (STR.LT.BRY(2)) GO TO 25 + IFLAG = 3 + ASCLE=BRY(3) + CSCLR = TOL + 25 CONTINUE + CSCRR = 1.0D0/CSCLR + S1R = CYR(2)*CSCLR + S1I = CYI(2)*CSCLR + S2R = CYR(1)*CSCLR + S2I = CYI(1)*CSCLR + RAZ = 1.0D0/ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + STR = ZR*RAZ + STI = -ZI*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + DO 30 I=1,NUI + STR = S2R + STI = S2I + S2R = (DFNU+FNUI)*(RZR*STR-RZI*STI) + S1R + S2I = (DFNU+FNUI)*(RZR*STI+RZI*STR) + S1I + S1R = STR + S1I = STI + FNUI = FNUI - 1.0D0 + IF (IFLAG.GE.3) GO TO 30 + STR = S2R*CSCRR + STI = S2I*CSCRR + C1R = DABS(STR) + C1I = DABS(STI) + C1M = DMAX1(C1R,C1I) + IF (C1M.LE.ASCLE) GO TO 30 + IFLAG = IFLAG+1 + ASCLE = BRY(IFLAG) + S1R = S1R*CSCRR + S1I = S1I*CSCRR + S2R = STR + S2I = STI + CSCLR = CSCLR*TOL + CSCRR = 1.0D0/CSCLR + S1R = S1R*CSCLR + S1I = S1I*CSCLR + S2R = S2R*CSCLR + S2I = S2I*CSCLR + 30 CONTINUE + YR(N) = S2R*CSCRR + YI(N) = S2I*CSCRR + IF (N.EQ.1) RETURN + NL = N - 1 + FNUI = DBLE(FLOAT(NL)) + K = NL + DO 40 I=1,NL + STR = S2R + STI = S2I + S2R = (FNU+FNUI)*(RZR*STR-RZI*STI) + S1R + S2I = (FNU+FNUI)*(RZR*STI+RZI*STR) + S1I + S1R = STR + S1I = STI + STR = S2R*CSCRR + STI = S2I*CSCRR + YR(K) = STR + YI(K) = STI + FNUI = FNUI - 1.0D0 + K = K - 1 + IF (IFLAG.GE.3) GO TO 40 + C1R = DABS(STR) + C1I = DABS(STI) + C1M = DMAX1(C1R,C1I) + IF (C1M.LE.ASCLE) GO TO 40 + IFLAG = IFLAG+1 + ASCLE = BRY(IFLAG) + S1R = S1R*CSCRR + S1I = S1I*CSCRR + S2R = STR + S2I = STI + CSCLR = CSCLR*TOL + CSCRR = 1.0D0/CSCLR + S1R = S1R*CSCLR + S1I = S1I*CSCLR + S2R = S2R*CSCLR + S2I = S2I*CSCLR + 40 CONTINUE + RETURN + 50 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + 60 CONTINUE + IF (IFORM.EQ.2) GO TO 70 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR I(FNU,Z) FOR LARGE FNU APPLIED IN +C -PI/3.LE.ARG(Z).LE.PI/3 +C----------------------------------------------------------------------- + CALL ZUNI1(ZR, ZI, FNU, KODE, N, YR, YI, NW, NLAST, FNUL, TOL, + * ELIM, ALIM) + GO TO 80 + 70 CONTINUE +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR J(FNU,Z*EXP(M*HPI)) FOR LARGE FNU +C APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I +C AND HPI=PI/2 +C----------------------------------------------------------------------- + CALL ZUNI2(ZR, ZI, FNU, KODE, N, YR, YI, NW, NLAST, FNUL, TOL, + * ELIM, ALIM) + 80 CONTINUE + IF (NW.LT.0) GO TO 50 + NZ = NW + RETURN + 90 CONTINUE + NLAST = N + RETURN + END diff --git a/mathext/internal/amos/amoslib/zbunk.f b/mathext/internal/amos/amoslib/zbunk.f new file mode 100644 index 00000000..b20b79f3 --- /dev/null +++ b/mathext/internal/amos/amoslib/zbunk.f @@ -0,0 +1,35 @@ + SUBROUTINE ZBUNK(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZBUNK +C***REFER TO ZBESK,ZBESH +C +C ZBUNK COMPUTES THE K BESSEL FUNCTION FOR FNU.GT.FNUL. +C ACCORDING TO THE UNIFORM ASYMPTOTIC EXPANSION FOR K(FNU,Z) +C IN ZUNK1 AND THE EXPANSION FOR H(2,FNU,Z) IN ZUNK2 +C +C***ROUTINES CALLED ZUNK1,ZUNK2 +C***END PROLOGUE ZBUNK +C COMPLEX Y,Z + DOUBLE PRECISION ALIM, AX, AY, ELIM, FNU, TOL, YI, YR, ZI, ZR + INTEGER KODE, MR, N, NZ + DIMENSION YR(N), YI(N) + NZ = 0 + AX = DABS(ZR)*1.7321D0 + AY = DABS(ZI) + IF (AY.GT.AX) GO TO 10 +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR K(FNU,Z) FOR LARGE FNU APPLIED IN +C -PI/3.LE.ARG(Z).LE.PI/3 +C----------------------------------------------------------------------- + CALL ZUNK1(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, ALIM) + GO TO 20 + 10 CONTINUE +C----------------------------------------------------------------------- +C ASYMPTOTIC EXPANSION FOR H(2,FNU,Z*EXP(M*HPI)) FOR LARGE FNU +C APPLIED IN PI/3.LT.ABS(ARG(Z)).LE.PI/2 WHERE M=+I OR -I +C AND HPI=PI/2 +C----------------------------------------------------------------------- + CALL ZUNK2(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, ALIM) + 20 CONTINUE + RETURN + END diff --git a/mathext/internal/amos/amoslib/zdiv.f b/mathext/internal/amos/amoslib/zdiv.f new file mode 100644 index 00000000..ac73b86d --- /dev/null +++ b/mathext/internal/amos/amoslib/zdiv.f @@ -0,0 +1,19 @@ + SUBROUTINE ZDIV(AR, AI, BR, BI, CR, CI) +C***BEGIN PROLOGUE ZDIV +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX DIVIDE C=A/B. +C +C***ROUTINES CALLED ZABS +C***END PROLOGUE ZDIV + DOUBLE PRECISION AR, AI, BR, BI, CR, CI, BM, CA, CB, CC, CD + DOUBLE PRECISION ZABS + BM = 1.0D0/ZABS(CMPLX(BR,BI,kind=KIND(1.0D0))) + CC = BR*BM + CD = BI*BM + CA = (AR*CC+AI*CD)*BM + CB = (AI*CC-AR*CD)*BM + CR = CA + CI = CB + RETURN + END diff --git a/mathext/internal/amos/amoslib/zexp.f b/mathext/internal/amos/amoslib/zexp.f new file mode 100644 index 00000000..fcb553c1 --- /dev/null +++ b/mathext/internal/amos/amoslib/zexp.f @@ -0,0 +1,16 @@ + SUBROUTINE ZEXP(AR, AI, BR, BI) +C***BEGIN PROLOGUE ZEXP +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX EXPONENTIAL FUNCTION B=EXP(A) +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZEXP + DOUBLE PRECISION AR, AI, BR, BI, ZM, CA, CB + ZM = DEXP(AR) + CA = ZM*DCOS(AI) + CB = ZM*DSIN(AI) + BR = CA + BI = CB + RETURN + END diff --git a/mathext/internal/amos/amoslib/zkscl.f b/mathext/internal/amos/amoslib/zkscl.f new file mode 100644 index 00000000..eeda4715 --- /dev/null +++ b/mathext/internal/amos/amoslib/zkscl.f @@ -0,0 +1,121 @@ + SUBROUTINE ZKSCL(ZRR,ZRI,FNU,N,YR,YI,NZ,RZR,RZI,ASCLE,TOL,ELIM) +C***BEGIN PROLOGUE ZKSCL +C***REFER TO ZBESK +C +C SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE +C ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN +C RETURN WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL. +C +C***ROUTINES CALLED ZUCHK,ZABS,ZLOG +C***END PROLOGUE ZKSCL +C COMPLEX CK,CS,CY,CZERO,RZ,S1,S2,Y,ZR,ZD,CELM + DOUBLE PRECISION ACS, AS, ASCLE, CKI, CKR, CSI, CSR, CYI, + * CYR, ELIM, FN, FNU, RZI, RZR, STR, S1I, S1R, S2I, + * S2R, TOL, YI, YR, ZEROI, ZEROR, ZRI, ZRR, ZABS, + * ZDR, ZDI, CELMR, ELM, HELIM, ALAS + INTEGER I, IC, IDUM, KK, N, NN, NW, NZ + DIMENSION YR(N), YI(N), CYR(2), CYI(2) + DATA ZEROR,ZEROI / 0.0D0 , 0.0D0 / +C + NZ = 0 + IC = 0 + NN = MIN0(2,N) + DO 10 I=1,NN + S1R = YR(I) + S1I = YI(I) + CYR(I) = S1R + CYI(I) = S1I + AS = ZABS(CMPLX(S1R,S1I,kind=KIND(1.0D0))) + ACS = -ZRR + DLOG(AS) + NZ = NZ + 1 + YR(I) = ZEROR + YI(I) = ZEROI + IF (ACS.LT.(-ELIM)) GO TO 10 + CALL ZLOG(S1R, S1I, CSR, CSI, IDUM) + CSR = CSR - ZRR + CSI = CSI - ZRI + STR = DEXP(CSR)/TOL + CSR = STR*DCOS(CSI) + CSI = STR*DSIN(CSI) + CALL ZUCHK(CSR, CSI, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 10 + YR(I) = CSR + YI(I) = CSI + IC = I + NZ = NZ - 1 + 10 CONTINUE + IF (N.EQ.1) RETURN + IF (IC.GT.1) GO TO 20 + YR(1) = ZEROR + YI(1) = ZEROI + NZ = 2 + 20 CONTINUE + IF (N.EQ.2) RETURN + IF (NZ.EQ.0) RETURN + FN = FNU + 1.0D0 + CKR = FN*RZR + CKI = FN*RZI + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + HELIM = 0.5D0*ELIM + ELM = DEXP(-ELIM) + CELMR = ELM + ZDR = ZRR + ZDI = ZRI +C +C FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF +C S2 GETS LARGER THAN EXP(ELIM/2) +C + DO 30 I=3,N + KK = I + CSR = S2R + CSI = S2I + S2R = CKR*CSR - CKI*CSI + S1R + S2I = CKI*CSR + CKR*CSI + S1I + S1R = CSR + S1I = CSI + CKR = CKR + RZR + CKI = CKI + RZI + AS = ZABS(CMPLX(S2R,S2I,kind=KIND(1.0D0))) + ALAS = DLOG(AS) + ACS = -ZDR + ALAS + NZ = NZ + 1 + YR(I) = ZEROR + YI(I) = ZEROI + IF (ACS.LT.(-ELIM)) GO TO 25 + CALL ZLOG(S2R, S2I, CSR, CSI, IDUM) + CSR = CSR - ZDR + CSI = CSI - ZDI + STR = DEXP(CSR)/TOL + CSR = STR*DCOS(CSI) + CSI = STR*DSIN(CSI) + CALL ZUCHK(CSR, CSI, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 25 + YR(I) = CSR + YI(I) = CSI + NZ = NZ - 1 + IF (IC.EQ.KK-1) GO TO 40 + IC = KK + GO TO 30 + 25 CONTINUE + IF(ALAS.LT.HELIM) GO TO 30 + ZDR = ZDR - ELIM + S1R = S1R*CELMR + S1I = S1I*CELMR + S2R = S2R*CELMR + S2I = S2I*CELMR + 30 CONTINUE + NZ = N + IF(IC.EQ.N) NZ=N-1 + GO TO 45 + 40 CONTINUE + NZ = KK - 2 + 45 CONTINUE + DO 50 I=1,NZ + YR(I) = ZEROR + YI(I) = ZEROI + 50 CONTINUE + RETURN + END diff --git a/mathext/internal/amos/amoslib/zlog.f b/mathext/internal/amos/amoslib/zlog.f new file mode 100644 index 00000000..bb22cd01 --- /dev/null +++ b/mathext/internal/amos/amoslib/zlog.f @@ -0,0 +1,41 @@ + SUBROUTINE ZLOG(AR, AI, BR, BI, IERR) +C***BEGIN PROLOGUE ZLOG +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX LOGARITHM B=CLOG(A) +C IERR=0,NORMAL RETURN IERR=1, Z=CMPLX(0.0,0.0) +C***ROUTINES CALLED ZABS +C***END PROLOGUE ZLOG + DOUBLE PRECISION AR, AI, BR, BI, ZM, DTHETA, DPI, DHPI + DOUBLE PRECISION ZABS + DATA DPI , DHPI / 3.141592653589793238462643383D+0, + 1 1.570796326794896619231321696D+0/ +C + IERR=0 + IF (AR.EQ.0.0D+0) GO TO 10 + IF (AI.EQ.0.0D+0) GO TO 20 + DTHETA = DATAN(AI/AR) + IF (DTHETA.LE.0.0D+0) GO TO 40 + IF (AR.LT.0.0D+0) DTHETA = DTHETA - DPI + GO TO 50 + 10 IF (AI.EQ.0.0D+0) GO TO 60 + BI = DHPI + BR = DLOG(DABS(AI)) + IF (AI.LT.0.0D+0) BI = -BI + RETURN + 20 IF (AR.GT.0.0D+0) GO TO 30 + BR = DLOG(DABS(AR)) + BI = DPI + RETURN + 30 BR = DLOG(AR) + BI = 0.0D+0 + RETURN + 40 IF (AR.LT.0.0D+0) DTHETA = DTHETA + DPI + 50 ZM = ZABS(CMPLX(AR,AI,kind=KIND(1.0D0))) + BR = DLOG(ZM) + BI = DTHETA + RETURN + 60 CONTINUE + IERR=1 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zmlri.f b/mathext/internal/amos/amoslib/zmlri.f new file mode 100644 index 00000000..c112f79d --- /dev/null +++ b/mathext/internal/amos/amoslib/zmlri.f @@ -0,0 +1,206 @@ + SUBROUTINE ZMLRI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL) +C***BEGIN PROLOGUE ZMLRI +C***REFER TO ZBESI,ZBESK +C +C ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z).GE.0.0 BY THE +C MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES. +C +C***ROUTINES CALLED DGAMLN,D1MACH,ZABS,ZEXP,ZLOG,ZMLT +C***END PROLOGUE ZMLRI +C COMPLEX CK,CNORM,CONE,CTWO,CZERO,PT,P1,P2,RZ,SUM,Y,Z + DOUBLE PRECISION ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI, + * CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, FNU, PTI, PTR, P1I, + * P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI, + * SUMR, TFNF, TOL, TST, YI, YR, ZEROI, ZEROR, ZI, ZR, DGAMLN, + * D1MACH, ZABS + INTEGER I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, KODE, M, N, NZ + DIMENSION YR(N), YI(N) + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / + SCLE = D1MACH(1)/TOL + NZ=0 + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + IAZ = INT(SNGL(AZ)) + IFNU = INT(SNGL(FNU)) + INU = IFNU + N - 1 + AT = DBLE(FLOAT(IAZ)) + 1.0D0 + RAZ = 1.0D0/AZ + STR = ZR*RAZ + STI = -ZI*RAZ + CKR = STR*AT*RAZ + CKI = STI*AT*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + ACK = (AT+1.0D0)*RAZ + RHO = ACK + DSQRT(ACK*ACK-1.0D0) + RHO2 = RHO*RHO + TST = (RHO2+RHO2)/((RHO2-1.0D0)*(RHO-1.0D0)) + TST = TST/TOL +C----------------------------------------------------------------------- +C COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES +C----------------------------------------------------------------------- + AK = AT + DO 10 I=1,80 + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR-CKI*PTI) + P2I = P1I - (CKI*PTR+CKR*PTI) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + IF (AP.GT.TST*AK*AK) THEN + GO TO 20 + END IF + AK = AK + 1.0D0 + 10 CONTINUE + GO TO 110 + 20 CONTINUE + I = I + 1 + K = 0 + IF (INU.LT.IAZ) GO TO 40 +C----------------------------------------------------------------------- +C COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS +C----------------------------------------------------------------------- + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + AT = DBLE(FLOAT(INU)) + 1.0D0 + STR = ZR*RAZ + STI = -ZI*RAZ + CKR = STR*AT*RAZ + CKI = STI*AT*RAZ + ACK = AT*RAZ + TST = DSQRT(ACK/TOL) + ITIME = 1 + DO 30 K=1,80 + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR-CKI*PTI) + P2I = P1I - (CKR*PTI+CKI*PTR) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + IF (AP.LT.TST) GO TO 30 + IF (ITIME.EQ.2) GO TO 40 + ACK = ZABS(CMPLX(CKR,CKI,kind=KIND(1.0D0))) + FLAM = ACK + DSQRT(ACK*ACK-1.0D0) + FKAP = AP/ZABS(CMPLX(P1R,P1I,kind=KIND(1.0D0))) + RHO = DMIN1(FLAM,FKAP) + TST = TST*DSQRT(RHO/(RHO*RHO-1.0D0)) + ITIME = 2 + 30 CONTINUE + GO TO 110 + 40 CONTINUE +C----------------------------------------------------------------------- +C BACKWARD RECURRENCE AND SUM NORMALIZING RELATION +C----------------------------------------------------------------------- + K = K + 1 + KK = MAX0(I+IAZ,K+INU) + FKK = DBLE(FLOAT(KK)) + P1R = ZEROR + P1I = ZEROI +C----------------------------------------------------------------------- +C SCALE P2 AND SUM BY SCLE +C----------------------------------------------------------------------- + P2R = SCLE + P2I = ZEROI + FNF = FNU - DBLE(FLOAT(IFNU)) + TFNF = FNF + FNF + BK = DGAMLN(FKK+TFNF+1.0D0,IDUM) - DGAMLN(FKK+1.0D0,IDUM) - + * DGAMLN(TFNF+1.0D0,IDUM) + BK = DEXP(BK) + SUMR = ZEROR + SUMI = ZEROI + KM = KK - INU + DO 50 I=1,KM + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0D0 - TFNF/(FKK+TFNF) + ACK = BK*AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0D0 + 50 CONTINUE + YR(N) = P2R + YI(N) = P2I + IF (N.EQ.1) GO TO 70 + DO 60 I=2,N + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0D0 - TFNF/(FKK+TFNF) + ACK = BK*AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0D0 + M = N - I + 1 + YR(M) = P2R + YI(M) = P2I + 60 CONTINUE + 70 CONTINUE + IF (IFNU.LE.0) GO TO 90 + DO 80 I=1,IFNU + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR) + P1R = PTR + P1I = PTI + AK = 1.0D0 - TFNF/(FKK+TFNF) + ACK = BK*AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0D0 + 80 CONTINUE + 90 CONTINUE + PTR = ZR + PTI = ZI + IF (KODE.EQ.2) PTR = ZEROR + CALL ZLOG(RZR, RZI, STR, STI, IDUM) + P1R = -FNF*STR + PTR + P1I = -FNF*STI + PTI + AP = DGAMLN(1.0D0+FNF,IDUM) + PTR = P1R - AP + PTI = P1I +C----------------------------------------------------------------------- +C THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW +C IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES +C----------------------------------------------------------------------- + P2R = P2R + SUMR + P2I = P2I + SUMI + AP = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + P1R = 1.0D0/AP + CALL ZEXP(PTR, PTI, STR, STI) + CKR = STR*P1R + CKI = STI*P1R + PTR = P2R*P1R + PTI = -P2I*P1R + CALL ZMLT(CKR, CKI, PTR, PTI, CNORMR, CNORMI) + DO 100 I=1,N + STR = YR(I)*CNORMR - YI(I)*CNORMI + YI(I) = YR(I)*CNORMI + YI(I)*CNORMR + YR(I) = STR + 100 CONTINUE + RETURN + 110 CONTINUE + NZ=-2 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zmlt.f b/mathext/internal/amos/amoslib/zmlt.f new file mode 100644 index 00000000..3bde7d34 --- /dev/null +++ b/mathext/internal/amos/amoslib/zmlt.f @@ -0,0 +1,15 @@ + SUBROUTINE ZMLT(AR, AI, BR, BI, CR, CI) +C***BEGIN PROLOGUE ZMLT +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX MULTIPLY, C=A*B. +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZMLT + DOUBLE PRECISION AR, AI, BR, BI, CR, CI, CA, CB + CA = AR*BR - AI*BI + CB = AR*BI + AI*BR + CR = CA + CI = CB + RETURN + END diff --git a/mathext/internal/amos/amoslib/zrati.f b/mathext/internal/amos/amoslib/zrati.f new file mode 100644 index 00000000..b66bd201 --- /dev/null +++ b/mathext/internal/amos/amoslib/zrati.f @@ -0,0 +1,132 @@ + SUBROUTINE ZRATI(ZR, ZI, FNU, N, CYR, CYI, TOL) +C***BEGIN PROLOGUE ZRATI +C***REFER TO ZBESI,ZBESK,ZBESH +C +C ZRATI COMPUTES RATIOS OF I BESSEL FUNCTIONS BY BACKWARD +C RECURRENCE. THE STARTING INDEX IS DETERMINED BY FORWARD +C RECURRENCE AS DESCRIBED IN J. RES. OF NAT. BUR. OF STANDARDS-B, +C MATHEMATICAL SCIENCES, VOL 77B, P111-114, SEPTEMBER, 1973, +C BESSEL FUNCTIONS I AND J OF COMPLEX ARGUMENT AND INTEGER ORDER, +C BY D. J. SOOKNE. +C +C***ROUTINES CALLED ZABS,ZDIV +C***END PROLOGUE ZRATI +C COMPLEX Z,CY(1),CONE,CZERO,P1,P2,T1,RZ,PT,CDFNU + DOUBLE PRECISION AK, AMAGZ, AP1, AP2, ARG, AZ, CDFNUI, CDFNUR, + * CONEI, CONER, CYI, CYR, CZEROI, CZEROR, DFNU, FDNU, FLAM, FNU, + * FNUP, PTI, PTR, P1I, P1R, P2I, P2R, RAK, RAP1, RHO, RT2, RZI, + * RZR, TEST, TEST1, TOL, TTI, TTR, T1I, T1R, ZI, ZR, ZABS + INTEGER I, ID, IDNU, INU, ITIME, K, KK, MAGZ, N + DIMENSION CYR(N), CYI(N) + DATA CZEROR,CZEROI,CONER,CONEI,RT2/ + 1 0.0D0, 0.0D0, 1.0D0, 0.0D0, 1.41421356237309505D0 / + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + INU = INT(SNGL(FNU)) + IDNU = INU + N - 1 + MAGZ = INT(SNGL(AZ)) + AMAGZ = DBLE(FLOAT(MAGZ+1)) + FDNU = DBLE(FLOAT(IDNU)) + FNUP = DMAX1(AMAGZ,FDNU) + ID = IDNU - MAGZ - 1 + ITIME = 1 + K = 1 + PTR = 1.0D0/AZ + RZR = PTR*(ZR+ZR)*PTR + RZI = -PTR*(ZI+ZI)*PTR + T1R = RZR*FNUP + T1I = RZI*FNUP + P2R = -T1R + P2I = -T1I + P1R = CONER + P1I = CONEI + T1R = T1R + RZR + T1I = T1I + RZI + IF (ID.GT.0) ID = 0 + AP2 = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + AP1 = ZABS(CMPLX(P1R,P1I,kind=KIND(1.0D0))) +C----------------------------------------------------------------------- +C THE OVERFLOW TEST ON K(FNU+I-1,Z) BEFORE THE CALL TO CBKNU +C GUARANTEES THAT P2 IS ON SCALE. SCALE TEST1 AND ALL SUBSEQUENT +C P2 VALUES BY AP1 TO ENSURE THAT AN OVERFLOW DOES NOT OCCUR +C PREMATURELY. +C----------------------------------------------------------------------- + ARG = (AP2+AP2)/(AP1*TOL) + TEST1 = DSQRT(ARG) + TEST = TEST1 + RAP1 = 1.0D0/AP1 + P1R = P1R*RAP1 + P1I = P1I*RAP1 + P2R = P2R*RAP1 + P2I = P2I*RAP1 + AP2 = AP2*RAP1 + 10 CONTINUE + K = K + 1 + AP1 = AP2 + PTR = P2R + PTI = P2I + P2R = P1R - (T1R*PTR-T1I*PTI) + P2I = P1I - (T1R*PTI+T1I*PTR) + P1R = PTR + P1I = PTI + T1R = T1R + RZR + T1I = T1I + RZI + AP2 = ZABS(CMPLX(P2R,P2I,kind=KIND(1.0D0))) + IF (AP1.LE.TEST) GO TO 10 + IF (ITIME.EQ.2) GO TO 20 + AK = ZABS(CMPLX(T1R,T1I,kind=KIND(1.0D0))*0.5D0) + FLAM = AK + DSQRT(AK*AK-1.0D0) + RHO = DMIN1(AP2/AP1,FLAM) + TEST = TEST1*DSQRT(RHO/(RHO*RHO-1.0D0)) + ITIME = 2 + GO TO 10 + 20 CONTINUE + KK = K + 1 - ID + AK = DBLE(FLOAT(KK)) + T1R = AK + T1I = CZEROI + DFNU = FNU + DBLE(FLOAT(N-1)) + P1R = 1.0D0/AP2 + P1I = CZEROI + P2R = CZEROR + P2I = CZEROI + DO 30 I=1,KK + PTR = P1R + PTI = P1I + RAP1 = DFNU + T1R + TTR = RZR*RAP1 + TTI = RZI*RAP1 + P1R = (PTR*TTR-PTI*TTI) + P2R + P1I = (PTR*TTI+PTI*TTR) + P2I + P2R = PTR + P2I = PTI + T1R = T1R - CONER + 30 CONTINUE + IF (P1R.NE.CZEROR .OR. P1I.NE.CZEROI) GO TO 40 + P1R = TOL + P1I = TOL + 40 CONTINUE + CALL ZDIV(P2R, P2I, P1R, P1I, CYR(N), CYI(N)) + IF (N.EQ.1) RETURN + K = N - 1 + AK = DBLE(FLOAT(K)) + T1R = AK + T1I = CZEROI + CDFNUR = FNU*RZR + CDFNUI = FNU*RZI + DO 60 I=2,N + PTR = CDFNUR + (T1R*RZR-T1I*RZI) + CYR(K+1) + PTI = CDFNUI + (T1R*RZI+T1I*RZR) + CYI(K+1) + AK = ZABS(CMPLX(PTR,PTI,kind=KIND(1.0D0))) + IF (AK.NE.CZEROR) GO TO 50 + PTR = TOL + PTI = TOL + AK = TOL*RT2 + 50 CONTINUE + RAK = CONER/AK + CYR(K) = RAK*PTR*RAK + CYI(K) = -RAK*PTI*RAK + T1R = T1R - CONER + K = K - 1 + 60 CONTINUE + RETURN + END diff --git a/mathext/internal/amos/amoslib/zs1s2.f b/mathext/internal/amos/amoslib/zs1s2.f new file mode 100644 index 00000000..0a6da311 --- /dev/null +++ b/mathext/internal/amos/amoslib/zs1s2.f @@ -0,0 +1,51 @@ + SUBROUTINE ZS1S2(ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, + * IUF) +C***BEGIN PROLOGUE ZS1S2 +C***REFER TO ZBESK,ZAIRY +C +C ZS1S2 TESTS FOR A POSSIBLE UNDERFLOW RESULTING FROM THE +C ADDITION OF THE I AND K FUNCTIONS IN THE ANALYTIC CON- +C TINUATION FORMULA WHERE S1=K FUNCTION AND S2=I FUNCTION. +C ON KODE=1 THE I AND K FUNCTIONS ARE DIFFERENT ORDERS OF +C MAGNITUDE, BUT FOR KODE=2 THEY CAN BE OF THE SAME ORDER +C OF MAGNITUDE AND THE MAXIMUM MUST BE AT LEAST ONE +C PRECISION ABOVE THE UNDERFLOW LIMIT. +C +C***ROUTINES CALLED ZABS,ZEXP,ZLOG +C***END PROLOGUE ZS1S2 +C COMPLEX CZERO,C1,S1,S1D,S2,ZR + DOUBLE PRECISION AA, ALIM, ALN, ASCLE, AS1, AS2, C1I, C1R, S1DI, + * S1DR, S1I, S1R, S2I, S2R, ZEROI, ZEROR, ZRI, ZRR, ZABS + INTEGER IUF, IDUM, NZ + DATA ZEROR,ZEROI / 0.0D0 , 0.0D0 / + NZ = 0 + AS1 = ZABS(CMPLX(S1R,S1I,kind=KIND(1.0D0))) + AS2 = ZABS(CMPLX(S2R,S2I,kind=KIND(1.0D0))) + IF (S1R.EQ.0.0D0 .AND. S1I.EQ.0.0D0) GO TO 10 + IF (AS1.EQ.0.0D0) GO TO 10 + ALN = -ZRR - ZRR + DLOG(AS1) + S1DR = S1R + S1DI = S1I + S1R = ZEROR + S1I = ZEROI + AS1 = ZEROR + IF (ALN.LT.(-ALIM)) GO TO 10 + CALL ZLOG(S1DR, S1DI, C1R, C1I, IDUM) + C1R = C1R - ZRR - ZRR + C1I = C1I - ZRI - ZRI + CALL ZEXP(C1R, C1I, S1R, S1I) + AS1 = ZABS(CMPLX(S1R,S1I,kind=KIND(1.0D0))) + IUF = IUF + 1 + 10 CONTINUE + AA = DMAX1(AS1,AS2) + IF (AA.GT.ASCLE) THEN + RETURN + END IF + S1R = ZEROR + S1I = ZEROI + S2R = ZEROR + S2I = ZEROI + NZ = 1 + IUF = 0 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zseri.f b/mathext/internal/amos/amoslib/zseri.f new file mode 100644 index 00000000..862fbf61 --- /dev/null +++ b/mathext/internal/amos/amoslib/zseri.f @@ -0,0 +1,195 @@ + SUBROUTINE ZSERI(ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZSERI +C***REFER TO ZBESI,ZBESK +C +C ZSERI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z).GE.0.0 BY +C MEANS OF THE POWER SERIES FOR LARGE CABS(Z) IN THE +C REGION CABS(Z).LE.2*SQRT(FNU+1). NZ=0 IS A NORMAL RETURN. +C NZ.GT.0 MEANS THAT THE LAST NZ COMPONENTS WERE SET TO ZERO +C DUE TO UNDERFLOW. NZ.LT.0 MEANS UNDERFLOW OCCURRED, BUT THE +C CONDITION CABS(Z).LE.2*SQRT(FNU+1) WAS VIOLATED AND THE +C COMPUTATION MUST BE COMPLETED IN ANOTHER ROUTINE WITH N=N-ABS(NZ). +C +C***ROUTINES CALLED DGAMLN,D1MACH,ZUCHK,ZABS,ZDIV,ZLOG,ZMLT +C***END PROLOGUE ZSERI +C COMPLEX AK1,CK,COEF,CONE,CRSC,CSCL,CZ,CZERO,HZ,RZ,S1,S2,Y,Z + DOUBLE PRECISION AA, ACZ, AK, AK1I, AK1R, ALIM, ARM, ASCLE, ATOL, + * AZ, CKI, CKR, COEFI, COEFR, CONEI, CONER, CRSCR, CZI, CZR, DFNU, + * ELIM, FNU, FNUP, HZI, HZR, RAZ, RS, RTR1, RZI, RZR, S, SS, STI, + * STR, S1I, S1R, S2I, S2R, TOL, YI, YR, WI, WR, ZEROI, ZEROR, ZI, + * ZR, DGAMLN, D1MACH, ZABS + INTEGER I, IB, IDUM, IFLAG, IL, K, KODE, L, M, N, NN, NZ, NW + DIMENSION YR(N), YI(N), WR(2), WI(2) + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / +C + + NZ = 0 + AZ = ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + IF (AZ.EQ.0.0D0) GO TO 160 + ARM = 1.0D+3*D1MACH(1) + RTR1 = DSQRT(ARM) + CRSCR = 1.0D0 + IFLAG = 0 + IF (AZ.LT.ARM) THEN + GO TO 150 + END IF + HZR = 0.5D0*ZR + HZI = 0.5D0*ZI + CZR = ZEROR + CZI = ZEROI + IF (AZ.LE.RTR1) GO TO 10 + CALL ZMLT(HZR, HZI, HZR, HZI, CZR, CZI) + 10 CONTINUE + ACZ = ZABS(CMPLX(CZR,CZI,kind=KIND(1.0D0))) + NN = N + CALL ZLOG(HZR, HZI, CKR, CKI, IDUM) + 20 CONTINUE + DFNU = FNU + DBLE(FLOAT(NN-1)) + FNUP = DFNU + 1.0D0 +C----------------------------------------------------------------------- +C UNDERFLOW TEST +C----------------------------------------------------------------------- + AK1R = CKR*DFNU + AK1I = CKI*DFNU + AK = DGAMLN(FNUP,IDUM) + AK1R = AK1R - AK + IF (KODE.EQ.2) AK1R = AK1R - ZR + IF (AK1R.GT.(-ELIM)) GO TO 40 + 30 CONTINUE + NZ = NZ + 1 + YR(NN) = ZEROR + YI(NN) = ZEROI + IF (ACZ.GT.DFNU) GO TO 190 + NN = NN - 1 + IF (NN.EQ.0) RETURN + GO TO 20 + 40 CONTINUE + IF (AK1R.GT.(-ALIM)) GO TO 50 + IFLAG = 1 + SS = 1.0D0/TOL + CRSCR = TOL + ASCLE = ARM*SS + 50 CONTINUE + AA = DEXP(AK1R) + IF (IFLAG.EQ.1) AA = AA*SS + COEFR = AA*DCOS(AK1I) + COEFI = AA*DSIN(AK1I) + ATOL = TOL*ACZ/FNUP + IL = MIN0(2,NN) + DO 90 I=1,IL + DFNU = FNU + DBLE(FLOAT(NN-I)) + FNUP = DFNU + 1.0D0 + S1R = CONER + S1I = CONEI + IF (ACZ.LT.TOL*FNUP) GO TO 70 + AK1R = CONER + AK1I = CONEI + AK = FNUP + 2.0D0 + S = FNUP + AA = 2.0D0 + 60 CONTINUE + RS = 1.0D0/S + STR = AK1R*CZR - AK1I*CZI + STI = AK1R*CZI + AK1I*CZR + AK1R = STR*RS + AK1I = STI*RS + S1R = S1R + AK1R + S1I = S1I + AK1I + S = S + AK + AK = AK + 2.0D0 + AA = AA*ACZ*RS + IF (AA.GT.ATOL) GO TO 60 + 70 CONTINUE + S2R = S1R*COEFR - S1I*COEFI + S2I = S1R*COEFI + S1I*COEFR + WR(I) = S2R + WI(I) = S2I + IF (IFLAG.EQ.0) GO TO 80 + CALL ZUCHK(S2R, S2I, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 30 + 80 CONTINUE + M = NN - I + 1 + YR(M) = S2R*CRSCR + YI(M) = S2I*CRSCR + IF (I.EQ.IL) GO TO 90 + CALL ZDIV(COEFR, COEFI, HZR, HZI, STR, STI) + COEFR = STR*DFNU + COEFI = STI*DFNU + 90 CONTINUE + IF (NN.LE.2) THEN + RETURN + END IF + K = NN - 2 + AK = DBLE(FLOAT(K)) + RAZ = 1.0D0/AZ + STR = ZR*RAZ + STI = -ZI*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + IF (IFLAG.EQ.1) GO TO 120 + IB = 3 + 100 CONTINUE + DO 110 I=IB,NN + YR(K) = (AK+FNU)*(RZR*YR(K+1)-RZI*YI(K+1)) + YR(K+2) + YI(K) = (AK+FNU)*(RZR*YI(K+1)+RZI*YR(K+1)) + YI(K+2) + AK = AK - 1.0D0 + K = K - 1 + 110 CONTINUE + RETURN +C----------------------------------------------------------------------- +C RECUR BACKWARD WITH SCALED VALUES +C----------------------------------------------------------------------- + 120 CONTINUE +C----------------------------------------------------------------------- +C EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION ABOVE THE +C UNDERFLOW LIMIT = ASCLE = D1MACH(1)*SS*1.0D+3 +C----------------------------------------------------------------------- + S1R = WR(1) + S1I = WI(1) + S2R = WR(2) + S2I = WI(2) + DO 130 L=3,NN + CKR = S2R + CKI = S2I + S2R = S1R + (AK+FNU)*(RZR*CKR-RZI*CKI) + S2I = S1I + (AK+FNU)*(RZR*CKI+RZI*CKR) + S1R = CKR + S1I = CKI + CKR = S2R*CRSCR + CKI = S2I*CRSCR + YR(K) = CKR + YI(K) = CKI + AK = AK - 1.0D0 + K = K - 1 + IF (ZABS(CMPLX(CKR,CKI,kind=KIND(1.0D0))).GT.ASCLE) GO TO 140 + 130 CONTINUE + RETURN + 140 CONTINUE + IB = L + 1 + IF (IB.GT.NN) RETURN + GO TO 100 + 150 CONTINUE + NZ = N + IF (FNU.EQ.0.0D0) NZ = NZ - 1 + 160 CONTINUE + YR(1) = ZEROR + YI(1) = ZEROI + IF (FNU.NE.0.0D0) GO TO 170 + YR(1) = CONER + YI(1) = CONEI + 170 CONTINUE + IF (N.EQ.1) RETURN + DO 180 I=2,N + YR(I) = ZEROR + YI(I) = ZEROI + 180 CONTINUE + RETURN +C----------------------------------------------------------------------- +C RETURN WITH NZ.LT.0 IF CABS(Z*Z/4).GT.FNU+N-NZ-1 COMPLETE +C THE CALCULATION IN CBINU WITH N=N-IABS(NZ) +C----------------------------------------------------------------------- + 190 CONTINUE + NZ = -NZ + RETURN + END diff --git a/mathext/internal/amos/amoslib/zshch.f b/mathext/internal/amos/amoslib/zshch.f new file mode 100644 index 00000000..168e62e5 --- /dev/null +++ b/mathext/internal/amos/amoslib/zshch.f @@ -0,0 +1,22 @@ + SUBROUTINE ZSHCH(ZR, ZI, CSHR, CSHI, CCHR, CCHI) +C***BEGIN PROLOGUE ZSHCH +C***REFER TO ZBESK,ZBESH +C +C ZSHCH COMPUTES THE COMPLEX HYPERBOLIC FUNCTIONS CSH=SINH(X+I*Y) +C AND CCH=COSH(X+I*Y), WHERE I**2=-1. +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZSHCH +C + DOUBLE PRECISION CCHI, CCHR, CH, CN, CSHI, CSHR, SH, SN, ZI, ZR, + * DCOSH, DSINH + SH = DSINH(ZR) + CH = DCOSH(ZR) + SN = DSIN(ZI) + CN = DCOS(ZI) + CSHR = SH*CN + CSHI = CH*SN + CCHR = CH*CN + CCHI = SH*SN + RETURN + END diff --git a/mathext/internal/amos/amoslib/zsqrt.f b/mathext/internal/amos/amoslib/zsqrt.f new file mode 100644 index 00000000..289545cd --- /dev/null +++ b/mathext/internal/amos/amoslib/zsqrt.f @@ -0,0 +1,45 @@ + SUBROUTINE ZSQRT(AR, AI, BR, BI) +C***BEGIN PROLOGUE ZSQRT +C***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY +C +C DOUBLE PRECISION COMPLEX SQUARE ROOT, B=CSQRT(A) +C +C***ROUTINES CALLED ZABS +C***END PROLOGUE ZSQRT + DOUBLE PRECISION AR, AI, BR, BI, ZM, DTHETA, DPI, DRT + DOUBLE PRECISION ZABS + + DATA DRT , DPI / 7.071067811865475244008443621D-1, + 1 3.141592653589793238462643383D+0/ + ZM = ZABS(CMPLX(AR,AI,kind=KIND(1.0D0))) + ZM = DSQRT(ZM) + IF (AR.EQ.0.0D+0) GO TO 10 + IF (AI.EQ.0.0D+0) GO TO 20 + DTHETA = DATAN(AI/AR) + IF (DTHETA.LE.0.0D+0) GO TO 40 + IF (AR.LT.0.0D+0) DTHETA = DTHETA - DPI + GO TO 50 + 10 IF (AI.GT.0.0D+0) GO TO 60 + IF (AI.LT.0.0D+0) GO TO 70 + BR = 0.0D+0 + BI = 0.0D+0 + RETURN + 20 IF (AR.GT.0.0D+0) GO TO 30 + BR = 0.0D+0 + BI = DSQRT(DABS(AR)) + RETURN + 30 BR = DSQRT(AR) + BI = 0.0D+0 + RETURN + 40 IF (AR.LT.0.0D+0) DTHETA = DTHETA + DPI + 50 DTHETA = DTHETA*0.5D+0 + BR = ZM*DCOS(DTHETA) + BI = ZM*DSIN(DTHETA) + RETURN + 60 BR = ZM*DRT + BI = ZM*DRT + RETURN + 70 BR = ZM*DRT + BI = -ZM*DRT + RETURN + END diff --git a/mathext/internal/amos/amoslib/zuchk.f b/mathext/internal/amos/amoslib/zuchk.f new file mode 100644 index 00000000..d15dc841 --- /dev/null +++ b/mathext/internal/amos/amoslib/zuchk.f @@ -0,0 +1,28 @@ + SUBROUTINE ZUCHK(YR, YI, NZ, ASCLE, TOL) +C***BEGIN PROLOGUE ZUCHK +C***REFER TO ZSERI,ZUOIK,ZUNK1,ZUNK2,ZUNI1,ZUNI2,ZKSCL +C +C Y ENTERS AS A SCALED QUANTITY WHOSE MAGNITUDE IS GREATER THAN +C EXP(-ALIM)=ASCLE=1.0E+3*D1MACH(1)/TOL. THE TEST IS MADE TO SEE +C IF THE MAGNITUDE OF THE REAL OR IMAGINARY PART WOULD UNDERFLOW +C WHEN Y IS SCALED (BY TOL) TO ITS PROPER VALUE. Y IS ACCEPTED +C IF THE UNDERFLOW IS AT LEAST ONE PRECISION BELOW THE MAGNITUDE +C OF THE LARGEST COMPONENT; OTHERWISE THE PHASE ANGLE DOES NOT HAVE +C ABSOLUTE ACCURACY AND AN UNDERFLOW IS ASSUMED. +C +C***ROUTINES CALLED (NONE) +C***END PROLOGUE ZUCHK +C +C COMPLEX Y + DOUBLE PRECISION ASCLE, SS, ST, TOL, WR, WI, YR, YI + INTEGER NZ + NZ = 0 + WR = DABS(YR) + WI = DABS(YI) + ST = DMIN1(WR,WI) + IF (ST.GT.ASCLE) RETURN + SS = DMAX1(WR,WI) + ST = ST/TOL + IF (SS.LT.ST) NZ = 1 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zunhj.f b/mathext/internal/amos/amoslib/zunhj.f new file mode 100644 index 00000000..9b4df7a1 --- /dev/null +++ b/mathext/internal/amos/amoslib/zunhj.f @@ -0,0 +1,714 @@ + SUBROUTINE ZUNHJ(ZR, ZI, FNU, IPMTR, TOL, PHIR, PHII, ARGR, ARGI, + * ZETA1R, ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) +C***BEGIN PROLOGUE ZUNHJ +C***REFER TO ZBESI,ZBESK +C +C REFERENCES +C HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ AND I.A. +C STEGUN, AMS55, NATIONAL BUREAU OF STANDARDS, 1965, CHAPTER 9. +C +C ASYMPTOTICS AND SPECIAL FUNCTIONS BY F.W.J. OLVER, ACADEMIC +C PRESS, N.Y., 1974, PAGE 420 +C +C ABSTRACT +C ZUNHJ COMPUTES PARAMETERS FOR BESSEL FUNCTIONS C(FNU,Z) = +C J(FNU,Z), Y(FNU,Z) OR H(I,FNU,Z) I=1,2 FOR LARGE ORDERS FNU +C BY MEANS OF THE UNIFORM ASYMPTOTIC EXPANSION +C +C C(FNU,Z)=C1*PHI*( ASUM*AIRY(ARG) + C2*BSUM*DAIRY(ARG) ) +C +C FOR PROPER CHOICES OF C1, C2, AIRY AND DAIRY WHERE AIRY IS +C AN AIRY FUNCTION AND DAIRY IS ITS DERIVATIVE. +C +C (2/3)*FNU*ZETA**1.5 = ZETA1-ZETA2, +C +C ZETA1=0.5*FNU*CLOG((1+W)/(1-W)), ZETA2=FNU*W FOR SCALING +C PURPOSES IN AIRY FUNCTIONS FROM CAIRY OR CBIRY. +C +C MCONJ=SIGN OF AIMAG(Z), BUT IS AMBIGUOUS WHEN Z IS REAL AND +C MUST BE SPECIFIED. IPMTR=0 RETURNS ALL PARAMETERS. IPMTR= +C 1 COMPUTES ALL EXCEPT ASUM AND BSUM. +C +C***ROUTINES CALLED ZABS,ZDIV,ZLOG,ZSQRT,D1MACH +C***END PROLOGUE ZUNHJ +C COMPLEX ARG,ASUM,BSUM,CFNU,CONE,CR,CZERO,DR,P,PHI,PRZTH,PTFN, +C *RFN13,RTZTA,RZTH,SUMA,SUMB,TFN,T2,UP,W,W2,Z,ZA,ZB,ZC,ZETA,ZETA1, +C *ZETA2,ZTH + DOUBLE PRECISION ALFA, ANG, AP, AR, ARGI, ARGR, ASUMI, ASUMR, + * ATOL, AW2, AZTH, BETA, BR, BSUMI, BSUMR, BTOL, C, CONEI, CONER, + * CRI, CRR, DRI, DRR, EX1, EX2, FNU, FN13, FN23, GAMA, GPI, HPI, + * PHII, PHIR, PI, PP, PR, PRZTHI, PRZTHR, PTFNI, PTFNR, RAW, RAW2, + * RAZTH, RFNU, RFNU2, RFN13, RTZTI, RTZTR, RZTHI, RZTHR, STI, STR, + * SUMAI, SUMAR, SUMBI, SUMBR, TEST, TFNI, TFNR, THPI, TOL, TZAI, + * TZAR, T2I, T2R, UPI, UPR, WI, WR, W2I, W2R, ZAI, ZAR, ZBI, ZBR, + * ZCI, ZCR, ZEROI, ZEROR, ZETAI, ZETAR, ZETA1I, ZETA1R, ZETA2I, + * ZETA2R, ZI, ZR, ZTHI, ZTHR, ZABS, AC, D1MACH + INTEGER IAS, IBS, IPMTR, IS, J, JR, JU, K, KMAX, KP1, KS, L, LR, + * LRP1, L1, L2, M, IDUM + DIMENSION AR(14), BR(14), C(105), ALFA(180), BETA(210), GAMA(30), + * AP(30), PR(30), PI(30), UPR(14), UPI(14), CRR(14), CRI(14), + * DRR(14), DRI(14) + DATA AR(1), AR(2), AR(3), AR(4), AR(5), AR(6), AR(7), AR(8), + 1 AR(9), AR(10), AR(11), AR(12), AR(13), AR(14)/ + 2 1.00000000000000000D+00, 1.04166666666666667D-01, + 3 8.35503472222222222D-02, 1.28226574556327160D-01, + 4 2.91849026464140464D-01, 8.81627267443757652D-01, + 5 3.32140828186276754D+00, 1.49957629868625547D+01, + 6 7.89230130115865181D+01, 4.74451538868264323D+02, + 7 3.20749009089066193D+03, 2.40865496408740049D+04, + 8 1.98923119169509794D+05, 1.79190200777534383D+06/ + DATA BR(1), BR(2), BR(3), BR(4), BR(5), BR(6), BR(7), BR(8), + 1 BR(9), BR(10), BR(11), BR(12), BR(13), BR(14)/ + 2 1.00000000000000000D+00, -1.45833333333333333D-01, + 3 -9.87413194444444444D-02, -1.43312053915895062D-01, + 4 -3.17227202678413548D-01, -9.42429147957120249D-01, + 5 -3.51120304082635426D+00, -1.57272636203680451D+01, + 6 -8.22814390971859444D+01, -4.92355370523670524D+02, + 7 -3.31621856854797251D+03, -2.48276742452085896D+04, + 8 -2.04526587315129788D+05, -1.83844491706820990D+06/ + DATA C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10), + 1 C(11), C(12), C(13), C(14), C(15), C(16), C(17), C(18), + 2 C(19), C(20), C(21), C(22), C(23), C(24)/ + 3 1.00000000000000000D+00, -2.08333333333333333D-01, + 4 1.25000000000000000D-01, 3.34201388888888889D-01, + 5 -4.01041666666666667D-01, 7.03125000000000000D-02, + 6 -1.02581259645061728D+00, 1.84646267361111111D+00, + 7 -8.91210937500000000D-01, 7.32421875000000000D-02, + 8 4.66958442342624743D+00, -1.12070026162229938D+01, + 9 8.78912353515625000D+00, -2.36408691406250000D+00, + A 1.12152099609375000D-01, -2.82120725582002449D+01, + B 8.46362176746007346D+01, -9.18182415432400174D+01, + C 4.25349987453884549D+01, -7.36879435947963170D+00, + D 2.27108001708984375D-01, 2.12570130039217123D+02, + E -7.65252468141181642D+02, 1.05999045252799988D+03/ + DATA C(25), C(26), C(27), C(28), C(29), C(30), C(31), C(32), + 1 C(33), C(34), C(35), C(36), C(37), C(38), C(39), C(40), + 2 C(41), C(42), C(43), C(44), C(45), C(46), C(47), C(48)/ + 3 -6.99579627376132541D+02, 2.18190511744211590D+02, + 4 -2.64914304869515555D+01, 5.72501420974731445D-01, + 5 -1.91945766231840700D+03, 8.06172218173730938D+03, + 6 -1.35865500064341374D+04, 1.16553933368645332D+04, + 7 -5.30564697861340311D+03, 1.20090291321635246D+03, + 8 -1.08090919788394656D+02, 1.72772750258445740D+00, + 9 2.02042913309661486D+04, -9.69805983886375135D+04, + A 1.92547001232531532D+05, -2.03400177280415534D+05, + B 1.22200464983017460D+05, -4.11926549688975513D+04, + C 7.10951430248936372D+03, -4.93915304773088012D+02, + D 6.07404200127348304D+00, -2.42919187900551333D+05, + E 1.31176361466297720D+06, -2.99801591853810675D+06/ + DATA C(49), C(50), C(51), C(52), C(53), C(54), C(55), C(56), + 1 C(57), C(58), C(59), C(60), C(61), C(62), C(63), C(64), + 2 C(65), C(66), C(67), C(68), C(69), C(70), C(71), C(72)/ + 3 3.76327129765640400D+06, -2.81356322658653411D+06, + 4 1.26836527332162478D+06, -3.31645172484563578D+05, + 5 4.52187689813627263D+04, -2.49983048181120962D+03, + 6 2.43805296995560639D+01, 3.28446985307203782D+06, + 7 -1.97068191184322269D+07, 5.09526024926646422D+07, + 8 -7.41051482115326577D+07, 6.63445122747290267D+07, + 9 -3.75671766607633513D+07, 1.32887671664218183D+07, + A -2.78561812808645469D+06, 3.08186404612662398D+05, + B -1.38860897537170405D+04, 1.10017140269246738D+02, + C -4.93292536645099620D+07, 3.25573074185765749D+08, + D -9.39462359681578403D+08, 1.55359689957058006D+09, + E -1.62108055210833708D+09, 1.10684281682301447D+09/ + DATA C(73), C(74), C(75), C(76), C(77), C(78), C(79), C(80), + 1 C(81), C(82), C(83), C(84), C(85), C(86), C(87), C(88), + 2 C(89), C(90), C(91), C(92), C(93), C(94), C(95), C(96)/ + 3 -4.95889784275030309D+08, 1.42062907797533095D+08, + 4 -2.44740627257387285D+07, 2.24376817792244943D+06, + 5 -8.40054336030240853D+04, 5.51335896122020586D+02, + 6 8.14789096118312115D+08, -5.86648149205184723D+09, + 7 1.86882075092958249D+10, -3.46320433881587779D+10, + 8 4.12801855797539740D+10, -3.30265997498007231D+10, + 9 1.79542137311556001D+10, -6.56329379261928433D+09, + A 1.55927986487925751D+09, -2.25105661889415278D+08, + B 1.73951075539781645D+07, -5.49842327572288687D+05, + C 3.03809051092238427D+03, -1.46792612476956167D+10, + D 1.14498237732025810D+11, -3.99096175224466498D+11, + E 8.19218669548577329D+11, -1.09837515608122331D+12/ + DATA C(97), C(98), C(99), C(100), C(101), C(102), C(103), C(104), + 1 C(105)/ + 2 1.00815810686538209D+12, -6.45364869245376503D+11, + 3 2.87900649906150589D+11, -8.78670721780232657D+10, + 4 1.76347306068349694D+10, -2.16716498322379509D+09, + 5 1.43157876718888981D+08, -3.87183344257261262D+06, + 6 1.82577554742931747D+04/ + DATA ALFA(1), ALFA(2), ALFA(3), ALFA(4), ALFA(5), ALFA(6), + 1 ALFA(7), ALFA(8), ALFA(9), ALFA(10), ALFA(11), ALFA(12), + 2 ALFA(13), ALFA(14), ALFA(15), ALFA(16), ALFA(17), ALFA(18), + 3 ALFA(19), ALFA(20), ALFA(21), ALFA(22)/ + 4 -4.44444444444444444D-03, -9.22077922077922078D-04, + 5 -8.84892884892884893D-05, 1.65927687832449737D-04, + 6 2.46691372741792910D-04, 2.65995589346254780D-04, + 7 2.61824297061500945D-04, 2.48730437344655609D-04, + 8 2.32721040083232098D-04, 2.16362485712365082D-04, + 9 2.00738858762752355D-04, 1.86267636637545172D-04, + A 1.73060775917876493D-04, 1.61091705929015752D-04, + B 1.50274774160908134D-04, 1.40503497391269794D-04, + C 1.31668816545922806D-04, 1.23667445598253261D-04, + D 1.16405271474737902D-04, 1.09798298372713369D-04, + E 1.03772410422992823D-04, 9.82626078369363448D-05/ + DATA ALFA(23), ALFA(24), ALFA(25), ALFA(26), ALFA(27), ALFA(28), + 1 ALFA(29), ALFA(30), ALFA(31), ALFA(32), ALFA(33), ALFA(34), + 2 ALFA(35), ALFA(36), ALFA(37), ALFA(38), ALFA(39), ALFA(40), + 3 ALFA(41), ALFA(42), ALFA(43), ALFA(44)/ + 4 9.32120517249503256D-05, 8.85710852478711718D-05, + 5 8.42963105715700223D-05, 8.03497548407791151D-05, + 6 7.66981345359207388D-05, 7.33122157481777809D-05, + 7 7.01662625163141333D-05, 6.72375633790160292D-05, + 8 6.93735541354588974D-04, 2.32241745182921654D-04, + 9 -1.41986273556691197D-05, -1.16444931672048640D-04, + A -1.50803558053048762D-04, -1.55121924918096223D-04, + B -1.46809756646465549D-04, -1.33815503867491367D-04, + C -1.19744975684254051D-04, -1.06184319207974020D-04, + D -9.37699549891194492D-05, -8.26923045588193274D-05, + E -7.29374348155221211D-05, -6.44042357721016283D-05/ + DATA ALFA(45), ALFA(46), ALFA(47), ALFA(48), ALFA(49), ALFA(50), + 1 ALFA(51), ALFA(52), ALFA(53), ALFA(54), ALFA(55), ALFA(56), + 2 ALFA(57), ALFA(58), ALFA(59), ALFA(60), ALFA(61), ALFA(62), + 3 ALFA(63), ALFA(64), ALFA(65), ALFA(66)/ + 4 -5.69611566009369048D-05, -5.04731044303561628D-05, + 5 -4.48134868008882786D-05, -3.98688727717598864D-05, + 6 -3.55400532972042498D-05, -3.17414256609022480D-05, + 7 -2.83996793904174811D-05, -2.54522720634870566D-05, + 8 -2.28459297164724555D-05, -2.05352753106480604D-05, + 9 -1.84816217627666085D-05, -1.66519330021393806D-05, + A -1.50179412980119482D-05, -1.35554031379040526D-05, + B -1.22434746473858131D-05, -1.10641884811308169D-05, + C -3.54211971457743841D-04, -1.56161263945159416D-04, + D 3.04465503594936410D-05, 1.30198655773242693D-04, + E 1.67471106699712269D-04, 1.70222587683592569D-04/ + DATA ALFA(67), ALFA(68), ALFA(69), ALFA(70), ALFA(71), ALFA(72), + 1 ALFA(73), ALFA(74), ALFA(75), ALFA(76), ALFA(77), ALFA(78), + 2 ALFA(79), ALFA(80), ALFA(81), ALFA(82), ALFA(83), ALFA(84), + 3 ALFA(85), ALFA(86), ALFA(87), ALFA(88)/ + 4 1.56501427608594704D-04, 1.36339170977445120D-04, + 5 1.14886692029825128D-04, 9.45869093034688111D-05, + 6 7.64498419250898258D-05, 6.07570334965197354D-05, + 7 4.74394299290508799D-05, 3.62757512005344297D-05, + 8 2.69939714979224901D-05, 1.93210938247939253D-05, + 9 1.30056674793963203D-05, 7.82620866744496661D-06, + A 3.59257485819351583D-06, 1.44040049814251817D-07, + B -2.65396769697939116D-06, -4.91346867098485910D-06, + C -6.72739296091248287D-06, -8.17269379678657923D-06, + D -9.31304715093561232D-06, -1.02011418798016441D-05, + E -1.08805962510592880D-05, -1.13875481509603555D-05/ + DATA ALFA(89), ALFA(90), ALFA(91), ALFA(92), ALFA(93), ALFA(94), + 1 ALFA(95), ALFA(96), ALFA(97), ALFA(98), ALFA(99), ALFA(100), + 2 ALFA(101), ALFA(102), ALFA(103), ALFA(104), ALFA(105), + 3 ALFA(106), ALFA(107), ALFA(108), ALFA(109), ALFA(110)/ + 4 -1.17519675674556414D-05, -1.19987364870944141D-05, + 5 3.78194199201772914D-04, 2.02471952761816167D-04, + 6 -6.37938506318862408D-05, -2.38598230603005903D-04, + 7 -3.10916256027361568D-04, -3.13680115247576316D-04, + 8 -2.78950273791323387D-04, -2.28564082619141374D-04, + 9 -1.75245280340846749D-04, -1.25544063060690348D-04, + A -8.22982872820208365D-05, -4.62860730588116458D-05, + B -1.72334302366962267D-05, 5.60690482304602267D-06, + C 2.31395443148286800D-05, 3.62642745856793957D-05, + D 4.58006124490188752D-05, 5.24595294959114050D-05, + E 5.68396208545815266D-05, 5.94349820393104052D-05/ + DATA ALFA(111), ALFA(112), ALFA(113), ALFA(114), ALFA(115), + 1 ALFA(116), ALFA(117), ALFA(118), ALFA(119), ALFA(120), + 2 ALFA(121), ALFA(122), ALFA(123), ALFA(124), ALFA(125), + 3 ALFA(126), ALFA(127), ALFA(128), ALFA(129), ALFA(130)/ + 4 6.06478527578421742D-05, 6.08023907788436497D-05, + 5 6.01577894539460388D-05, 5.89199657344698500D-05, + 6 5.72515823777593053D-05, 5.52804375585852577D-05, + 7 5.31063773802880170D-05, 5.08069302012325706D-05, + 8 4.84418647620094842D-05, 4.60568581607475370D-05, + 9 -6.91141397288294174D-04, -4.29976633058871912D-04, + A 1.83067735980039018D-04, 6.60088147542014144D-04, + B 8.75964969951185931D-04, 8.77335235958235514D-04, + C 7.49369585378990637D-04, 5.63832329756980918D-04, + D 3.68059319971443156D-04, 1.88464535514455599D-04/ + DATA ALFA(131), ALFA(132), ALFA(133), ALFA(134), ALFA(135), + 1 ALFA(136), ALFA(137), ALFA(138), ALFA(139), ALFA(140), + 2 ALFA(141), ALFA(142), ALFA(143), ALFA(144), ALFA(145), + 3 ALFA(146), ALFA(147), ALFA(148), ALFA(149), ALFA(150)/ + 4 3.70663057664904149D-05, -8.28520220232137023D-05, + 5 -1.72751952869172998D-04, -2.36314873605872983D-04, + 6 -2.77966150694906658D-04, -3.02079514155456919D-04, + 7 -3.12594712643820127D-04, -3.12872558758067163D-04, + 8 -3.05678038466324377D-04, -2.93226470614557331D-04, + 9 -2.77255655582934777D-04, -2.59103928467031709D-04, + A -2.39784014396480342D-04, -2.20048260045422848D-04, + B -2.00443911094971498D-04, -1.81358692210970687D-04, + C -1.63057674478657464D-04, -1.45712672175205844D-04, + D -1.29425421983924587D-04, -1.14245691942445952D-04/ + DATA ALFA(151), ALFA(152), ALFA(153), ALFA(154), ALFA(155), + 1 ALFA(156), ALFA(157), ALFA(158), ALFA(159), ALFA(160), + 2 ALFA(161), ALFA(162), ALFA(163), ALFA(164), ALFA(165), + 3 ALFA(166), ALFA(167), ALFA(168), ALFA(169), ALFA(170)/ + 4 1.92821964248775885D-03, 1.35592576302022234D-03, + 5 -7.17858090421302995D-04, -2.58084802575270346D-03, + 6 -3.49271130826168475D-03, -3.46986299340960628D-03, + 7 -2.82285233351310182D-03, -1.88103076404891354D-03, + 8 -8.89531718383947600D-04, 3.87912102631035228D-06, + 9 7.28688540119691412D-04, 1.26566373053457758D-03, + A 1.62518158372674427D-03, 1.83203153216373172D-03, + B 1.91588388990527909D-03, 1.90588846755546138D-03, + C 1.82798982421825727D-03, 1.70389506421121530D-03, + D 1.55097127171097686D-03, 1.38261421852276159D-03/ + DATA ALFA(171), ALFA(172), ALFA(173), ALFA(174), ALFA(175), + 1 ALFA(176), ALFA(177), ALFA(178), ALFA(179), ALFA(180)/ + 2 1.20881424230064774D-03, 1.03676532638344962D-03, + 3 8.71437918068619115D-04, 7.16080155297701002D-04, + 4 5.72637002558129372D-04, 4.42089819465802277D-04, + 5 3.24724948503090564D-04, 2.20342042730246599D-04, + 6 1.28412898401353882D-04, 4.82005924552095464D-05/ + DATA BETA(1), BETA(2), BETA(3), BETA(4), BETA(5), BETA(6), + 1 BETA(7), BETA(8), BETA(9), BETA(10), BETA(11), BETA(12), + 2 BETA(13), BETA(14), BETA(15), BETA(16), BETA(17), BETA(18), + 3 BETA(19), BETA(20), BETA(21), BETA(22)/ + 4 1.79988721413553309D-02, 5.59964911064388073D-03, + 5 2.88501402231132779D-03, 1.80096606761053941D-03, + 6 1.24753110589199202D-03, 9.22878876572938311D-04, + 7 7.14430421727287357D-04, 5.71787281789704872D-04, + 8 4.69431007606481533D-04, 3.93232835462916638D-04, + 9 3.34818889318297664D-04, 2.88952148495751517D-04, + A 2.52211615549573284D-04, 2.22280580798883327D-04, + B 1.97541838033062524D-04, 1.76836855019718004D-04, + C 1.59316899661821081D-04, 1.44347930197333986D-04, + D 1.31448068119965379D-04, 1.20245444949302884D-04, + E 1.10449144504599392D-04, 1.01828770740567258D-04/ + DATA BETA(23), BETA(24), BETA(25), BETA(26), BETA(27), BETA(28), + 1 BETA(29), BETA(30), BETA(31), BETA(32), BETA(33), BETA(34), + 2 BETA(35), BETA(36), BETA(37), BETA(38), BETA(39), BETA(40), + 3 BETA(41), BETA(42), BETA(43), BETA(44)/ + 4 9.41998224204237509D-05, 8.74130545753834437D-05, + 5 8.13466262162801467D-05, 7.59002269646219339D-05, + 6 7.09906300634153481D-05, 6.65482874842468183D-05, + 7 6.25146958969275078D-05, 5.88403394426251749D-05, + 8 -1.49282953213429172D-03, -8.78204709546389328D-04, + 9 -5.02916549572034614D-04, -2.94822138512746025D-04, + A -1.75463996970782828D-04, -1.04008550460816434D-04, + B -5.96141953046457895D-05, -3.12038929076098340D-05, + C -1.26089735980230047D-05, -2.42892608575730389D-07, + D 8.05996165414273571D-06, 1.36507009262147391D-05, + E 1.73964125472926261D-05, 1.98672978842133780D-05/ + DATA BETA(45), BETA(46), BETA(47), BETA(48), BETA(49), BETA(50), + 1 BETA(51), BETA(52), BETA(53), BETA(54), BETA(55), BETA(56), + 2 BETA(57), BETA(58), BETA(59), BETA(60), BETA(61), BETA(62), + 3 BETA(63), BETA(64), BETA(65), BETA(66)/ + 4 2.14463263790822639D-05, 2.23954659232456514D-05, + 5 2.28967783814712629D-05, 2.30785389811177817D-05, + 6 2.30321976080909144D-05, 2.28236073720348722D-05, + 7 2.25005881105292418D-05, 2.20981015361991429D-05, + 8 2.16418427448103905D-05, 2.11507649256220843D-05, + 9 2.06388749782170737D-05, 2.01165241997081666D-05, + A 1.95913450141179244D-05, 1.90689367910436740D-05, + B 1.85533719641636667D-05, 1.80475722259674218D-05, + C 5.52213076721292790D-04, 4.47932581552384646D-04, + D 2.79520653992020589D-04, 1.52468156198446602D-04, + E 6.93271105657043598D-05, 1.76258683069991397D-05/ + DATA BETA(67), BETA(68), BETA(69), BETA(70), BETA(71), BETA(72), + 1 BETA(73), BETA(74), BETA(75), BETA(76), BETA(77), BETA(78), + 2 BETA(79), BETA(80), BETA(81), BETA(82), BETA(83), BETA(84), + 3 BETA(85), BETA(86), BETA(87), BETA(88)/ + 4 -1.35744996343269136D-05, -3.17972413350427135D-05, + 5 -4.18861861696693365D-05, -4.69004889379141029D-05, + 6 -4.87665447413787352D-05, -4.87010031186735069D-05, + 7 -4.74755620890086638D-05, -4.55813058138628452D-05, + 8 -4.33309644511266036D-05, -4.09230193157750364D-05, + 9 -3.84822638603221274D-05, -3.60857167535410501D-05, + A -3.37793306123367417D-05, -3.15888560772109621D-05, + B -2.95269561750807315D-05, -2.75978914828335759D-05, + C -2.58006174666883713D-05, -2.41308356761280200D-05, + D -2.25823509518346033D-05, -2.11479656768912971D-05, + E -1.98200638885294927D-05, -1.85909870801065077D-05/ + DATA BETA(89), BETA(90), BETA(91), BETA(92), BETA(93), BETA(94), + 1 BETA(95), BETA(96), BETA(97), BETA(98), BETA(99), BETA(100), + 2 BETA(101), BETA(102), BETA(103), BETA(104), BETA(105), + 3 BETA(106), BETA(107), BETA(108), BETA(109), BETA(110)/ + 4 -1.74532699844210224D-05, -1.63997823854497997D-05, + 5 -4.74617796559959808D-04, -4.77864567147321487D-04, + 6 -3.20390228067037603D-04, -1.61105016119962282D-04, + 7 -4.25778101285435204D-05, 3.44571294294967503D-05, + 8 7.97092684075674924D-05, 1.03138236708272200D-04, + 9 1.12466775262204158D-04, 1.13103642108481389D-04, + A 1.08651634848774268D-04, 1.01437951597661973D-04, + B 9.29298396593363896D-05, 8.40293133016089978D-05, + C 7.52727991349134062D-05, 6.69632521975730872D-05, + D 5.92564547323194704D-05, 5.22169308826975567D-05, + E 4.58539485165360646D-05, 4.01445513891486808D-05/ + DATA BETA(111), BETA(112), BETA(113), BETA(114), BETA(115), + 1 BETA(116), BETA(117), BETA(118), BETA(119), BETA(120), + 2 BETA(121), BETA(122), BETA(123), BETA(124), BETA(125), + 3 BETA(126), BETA(127), BETA(128), BETA(129), BETA(130)/ + 4 3.50481730031328081D-05, 3.05157995034346659D-05, + 5 2.64956119950516039D-05, 2.29363633690998152D-05, + 6 1.97893056664021636D-05, 1.70091984636412623D-05, + 7 1.45547428261524004D-05, 1.23886640995878413D-05, + 8 1.04775876076583236D-05, 8.79179954978479373D-06, + 9 7.36465810572578444D-04, 8.72790805146193976D-04, + A 6.22614862573135066D-04, 2.85998154194304147D-04, + B 3.84737672879366102D-06, -1.87906003636971558D-04, + C -2.97603646594554535D-04, -3.45998126832656348D-04, + D -3.53382470916037712D-04, -3.35715635775048757D-04/ + DATA BETA(131), BETA(132), BETA(133), BETA(134), BETA(135), + 1 BETA(136), BETA(137), BETA(138), BETA(139), BETA(140), + 2 BETA(141), BETA(142), BETA(143), BETA(144), BETA(145), + 3 BETA(146), BETA(147), BETA(148), BETA(149), BETA(150)/ + 4 -3.04321124789039809D-04, -2.66722723047612821D-04, + 5 -2.27654214122819527D-04, -1.89922611854562356D-04, + 6 -1.55058918599093870D-04, -1.23778240761873630D-04, + 7 -9.62926147717644187D-05, -7.25178327714425337D-05, + 8 -5.22070028895633801D-05, -3.50347750511900522D-05, + 9 -2.06489761035551757D-05, -8.70106096849767054D-06, + A 1.13698686675100290D-06, 9.16426474122778849D-06, + B 1.56477785428872620D-05, 2.08223629482466847D-05, + C 2.48923381004595156D-05, 2.80340509574146325D-05, + D 3.03987774629861915D-05, 3.21156731406700616D-05/ + DATA BETA(151), BETA(152), BETA(153), BETA(154), BETA(155), + 1 BETA(156), BETA(157), BETA(158), BETA(159), BETA(160), + 2 BETA(161), BETA(162), BETA(163), BETA(164), BETA(165), + 3 BETA(166), BETA(167), BETA(168), BETA(169), BETA(170)/ + 4 -1.80182191963885708D-03, -2.43402962938042533D-03, + 5 -1.83422663549856802D-03, -7.62204596354009765D-04, + 6 2.39079475256927218D-04, 9.49266117176881141D-04, + 7 1.34467449701540359D-03, 1.48457495259449178D-03, + 8 1.44732339830617591D-03, 1.30268261285657186D-03, + 9 1.10351597375642682D-03, 8.86047440419791759D-04, + A 6.73073208165665473D-04, 4.77603872856582378D-04, + B 3.05991926358789362D-04, 1.60315694594721630D-04, + C 4.00749555270613286D-05, -5.66607461635251611D-05, + D -1.32506186772982638D-04, -1.90296187989614057D-04/ + DATA BETA(171), BETA(172), BETA(173), BETA(174), BETA(175), + 1 BETA(176), BETA(177), BETA(178), BETA(179), BETA(180), + 2 BETA(181), BETA(182), BETA(183), BETA(184), BETA(185), + 3 BETA(186), BETA(187), BETA(188), BETA(189), BETA(190)/ + 4 -2.32811450376937408D-04, -2.62628811464668841D-04, + 5 -2.82050469867598672D-04, -2.93081563192861167D-04, + 6 -2.97435962176316616D-04, -2.96557334239348078D-04, + 7 -2.91647363312090861D-04, -2.83696203837734166D-04, + 8 -2.73512317095673346D-04, -2.61750155806768580D-04, + 9 6.38585891212050914D-03, 9.62374215806377941D-03, + A 7.61878061207001043D-03, 2.83219055545628054D-03, + B -2.09841352012720090D-03, -5.73826764216626498D-03, + C -7.70804244495414620D-03, -8.21011692264844401D-03, + D -7.65824520346905413D-03, -6.47209729391045177D-03/ + DATA BETA(191), BETA(192), BETA(193), BETA(194), BETA(195), + 1 BETA(196), BETA(197), BETA(198), BETA(199), BETA(200), + 2 BETA(201), BETA(202), BETA(203), BETA(204), BETA(205), + 3 BETA(206), BETA(207), BETA(208), BETA(209), BETA(210)/ + 4 -4.99132412004966473D-03, -3.45612289713133280D-03, + 5 -2.01785580014170775D-03, -7.59430686781961401D-04, + 6 2.84173631523859138D-04, 1.10891667586337403D-03, + 7 1.72901493872728771D-03, 2.16812590802684701D-03, + 8 2.45357710494539735D-03, 2.61281821058334862D-03, + 9 2.67141039656276912D-03, 2.65203073395980430D-03, + A 2.57411652877287315D-03, 2.45389126236094427D-03, + B 2.30460058071795494D-03, 2.13684837686712662D-03, + C 1.95896528478870911D-03, 1.77737008679454412D-03, + D 1.59690280765839059D-03, 1.42111975664438546D-03/ + DATA GAMA(1), GAMA(2), GAMA(3), GAMA(4), GAMA(5), GAMA(6), + 1 GAMA(7), GAMA(8), GAMA(9), GAMA(10), GAMA(11), GAMA(12), + 2 GAMA(13), GAMA(14), GAMA(15), GAMA(16), GAMA(17), GAMA(18), + 3 GAMA(19), GAMA(20), GAMA(21), GAMA(22)/ + 4 6.29960524947436582D-01, 2.51984209978974633D-01, + 5 1.54790300415655846D-01, 1.10713062416159013D-01, + 6 8.57309395527394825D-02, 6.97161316958684292D-02, + 7 5.86085671893713576D-02, 5.04698873536310685D-02, + 8 4.42600580689154809D-02, 3.93720661543509966D-02, + 9 3.54283195924455368D-02, 3.21818857502098231D-02, + A 2.94646240791157679D-02, 2.71581677112934479D-02, + B 2.51768272973861779D-02, 2.34570755306078891D-02, + C 2.19508390134907203D-02, 2.06210828235646240D-02, + D 1.94388240897880846D-02, 1.83810633800683158D-02, + E 1.74293213231963172D-02, 1.65685837786612353D-02/ + DATA GAMA(23), GAMA(24), GAMA(25), GAMA(26), GAMA(27), GAMA(28), + 1 GAMA(29), GAMA(30)/ + 2 1.57865285987918445D-02, 1.50729501494095594D-02, + 3 1.44193250839954639D-02, 1.38184805735341786D-02, + 4 1.32643378994276568D-02, 1.27517121970498651D-02, + 5 1.22761545318762767D-02, 1.18338262398482403D-02/ + DATA EX1, EX2, HPI, GPI, THPI / + 1 3.33333333333333333D-01, 6.66666666666666667D-01, + 2 1.57079632679489662D+00, 3.14159265358979324D+00, + 3 4.71238898038468986D+00/ + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / +C + RFNU = 1.0D0/FNU +C----------------------------------------------------------------------- +C OVERFLOW TEST (Z/FNU TOO SMALL) +C----------------------------------------------------------------------- + TEST = D1MACH(1)*1.0D+3 + AC = FNU*TEST + IF (DABS(ZR).GT.AC .OR. DABS(ZI).GT.AC) GO TO 15 + ZETA1R = 2.0D0*DABS(DLOG(TEST))+FNU + ZETA1I = 0.0D0 + ZETA2R = FNU + ZETA2I = 0.0D0 + PHIR = 1.0D0 + PHII = 0.0D0 + ARGR = 1.0D0 + ARGI = 0.0D0 + RETURN + 15 CONTINUE + ZBR = ZR*RFNU + ZBI = ZI*RFNU + RFNU2 = RFNU*RFNU +C----------------------------------------------------------------------- +C COMPUTE IN THE FOURTH QUADRANT +C----------------------------------------------------------------------- + FN13 = FNU**EX1 + FN23 = FN13*FN13 + RFN13 = 1.0D0/FN13 + W2R = CONER - ZBR*ZBR + ZBI*ZBI + W2I = CONEI - ZBR*ZBI - ZBR*ZBI + AW2 = ZABS(CMPLX(W2R,W2I,kind=KIND(1.0D0))) + IF (AW2.GT.0.25D0) GO TO 130 +C----------------------------------------------------------------------- +C POWER SERIES FOR CABS(W2).LE.0.25D0 +C----------------------------------------------------------------------- + K = 1 + PR(1) = CONER + PI(1) = CONEI + SUMAR = GAMA(1) + SUMAI = ZEROI + AP(1) = 1.0D0 + IF (AW2.LT.TOL) GO TO 20 + DO 10 K=2,30 + PR(K) = PR(K-1)*W2R - PI(K-1)*W2I + PI(K) = PR(K-1)*W2I + PI(K-1)*W2R + SUMAR = SUMAR + PR(K)*GAMA(K) + SUMAI = SUMAI + PI(K)*GAMA(K) + AP(K) = AP(K-1)*AW2 + IF (AP(K).LT.TOL) GO TO 20 + 10 CONTINUE + K = 30 + 20 CONTINUE + KMAX = K + ZETAR = W2R*SUMAR - W2I*SUMAI + ZETAI = W2R*SUMAI + W2I*SUMAR + ARGR = ZETAR*FN23 + ARGI = ZETAI*FN23 + CALL ZSQRT(SUMAR, SUMAI, ZAR, ZAI) + CALL ZSQRT(W2R, W2I, STR, STI) + ZETA2R = STR*FNU + ZETA2I = STI*FNU + STR = CONER + EX2*(ZETAR*ZAR-ZETAI*ZAI) + STI = CONEI + EX2*(ZETAR*ZAI+ZETAI*ZAR) + ZETA1R = STR*ZETA2R - STI*ZETA2I + ZETA1I = STR*ZETA2I + STI*ZETA2R + ZAR = ZAR + ZAR + ZAI = ZAI + ZAI + CALL ZSQRT(ZAR, ZAI, STR, STI) + PHIR = STR*RFN13 + PHII = STI*RFN13 + IF (IPMTR.EQ.1) GO TO 120 +C----------------------------------------------------------------------- +C SUM SERIES FOR ASUM AND BSUM +C----------------------------------------------------------------------- + SUMBR = ZEROR + SUMBI = ZEROI + DO 30 K=1,KMAX + SUMBR = SUMBR + PR(K)*BETA(K) + SUMBI = SUMBI + PI(K)*BETA(K) + 30 CONTINUE + ASUMR = ZEROR + ASUMI = ZEROI + BSUMR = SUMBR + BSUMI = SUMBI + L1 = 0 + L2 = 30 + BTOL = TOL*(DABS(BSUMR)+DABS(BSUMI)) + ATOL = TOL + PP = 1.0D0 + IAS = 0 + IBS = 0 + IF (RFNU2.LT.TOL) GO TO 110 + DO 100 IS=2,7 + ATOL = ATOL/RFNU2 + PP = PP*RFNU2 + IF (IAS.EQ.1) GO TO 60 + SUMAR = ZEROR + SUMAI = ZEROI + DO 40 K=1,KMAX + M = L1 + K + SUMAR = SUMAR + PR(K)*ALFA(M) + SUMAI = SUMAI + PI(K)*ALFA(M) + IF (AP(K).LT.ATOL) GO TO 50 + 40 CONTINUE + 50 CONTINUE + ASUMR = ASUMR + SUMAR*PP + ASUMI = ASUMI + SUMAI*PP + IF (PP.LT.TOL) IAS = 1 + 60 CONTINUE + IF (IBS.EQ.1) GO TO 90 + SUMBR = ZEROR + SUMBI = ZEROI + DO 70 K=1,KMAX + M = L2 + K + SUMBR = SUMBR + PR(K)*BETA(M) + SUMBI = SUMBI + PI(K)*BETA(M) + IF (AP(K).LT.ATOL) GO TO 80 + 70 CONTINUE + 80 CONTINUE + BSUMR = BSUMR + SUMBR*PP + BSUMI = BSUMI + SUMBI*PP + IF (PP.LT.BTOL) IBS = 1 + 90 CONTINUE + IF (IAS.EQ.1 .AND. IBS.EQ.1) GO TO 110 + L1 = L1 + 30 + L2 = L2 + 30 + 100 CONTINUE + 110 CONTINUE + ASUMR = ASUMR + CONER + PP = RFNU*RFN13 + BSUMR = BSUMR*PP + BSUMI = BSUMI*PP + 120 CONTINUE + RETURN +C----------------------------------------------------------------------- +C CABS(W2).GT.0.25D0 +C----------------------------------------------------------------------- + 130 CONTINUE + CALL ZSQRT(W2R, W2I, WR, WI) + IF (WR.LT.0.0D0) WR = 0.0D0 + IF (WI.LT.0.0D0) WI = 0.0D0 + STR = CONER + WR + STI = WI + CALL ZDIV(STR, STI, ZBR, ZBI, ZAR, ZAI) + CALL ZLOG(ZAR, ZAI, ZCR, ZCI, IDUM) + IF (ZCI.LT.0.0D0) ZCI = 0.0D0 + IF (ZCI.GT.HPI) ZCI = HPI + IF (ZCR.LT.0.0D0) ZCR = 0.0D0 + ZTHR = (ZCR-WR)*1.5D0 + ZTHI = (ZCI-WI)*1.5D0 + ZETA1R = ZCR*FNU + ZETA1I = ZCI*FNU + ZETA2R = WR*FNU + ZETA2I = WI*FNU + AZTH = ZABS(CMPLX(ZTHR,ZTHI,kind=KIND(1.0D0))) + ANG = THPI + IF (ZTHR.GE.0.0D0 .AND. ZTHI.LT.0.0D0) GO TO 140 + ANG = HPI + IF (ZTHR.EQ.0.0D0) GO TO 140 + ANG = DATAN(ZTHI/ZTHR) + IF (ZTHR.LT.0.0D0) ANG = ANG + GPI + 140 CONTINUE + PP = AZTH**EX2 + ANG = ANG*EX2 + ZETAR = PP*DCOS(ANG) + ZETAI = PP*DSIN(ANG) + IF (ZETAI.LT.0.0D0) ZETAI = 0.0D0 + ARGR = ZETAR*FN23 + ARGI = ZETAI*FN23 + CALL ZDIV(ZTHR, ZTHI, ZETAR, ZETAI, RTZTR, RTZTI) + CALL ZDIV(RTZTR, RTZTI, WR, WI, ZAR, ZAI) + TZAR = ZAR + ZAR + TZAI = ZAI + ZAI + CALL ZSQRT(TZAR, TZAI, STR, STI) + PHIR = STR*RFN13 + PHII = STI*RFN13 + IF (IPMTR.EQ.1) GO TO 120 + RAW = 1.0D0/DSQRT(AW2) + STR = WR*RAW + STI = -WI*RAW + TFNR = STR*RFNU*RAW + TFNI = STI*RFNU*RAW + RAZTH = 1.0D0/AZTH + STR = ZTHR*RAZTH + STI = -ZTHI*RAZTH + RZTHR = STR*RAZTH*RFNU + RZTHI = STI*RAZTH*RFNU + ZCR = RZTHR*AR(2) + ZCI = RZTHI*AR(2) + RAW2 = 1.0D0/AW2 + STR = W2R*RAW2 + STI = -W2I*RAW2 + T2R = STR*RAW2 + T2I = STI*RAW2 + STR = T2R*C(2) + C(3) + STI = T2I*C(2) + UPR(2) = STR*TFNR - STI*TFNI + UPI(2) = STR*TFNI + STI*TFNR + BSUMR = UPR(2) + ZCR + BSUMI = UPI(2) + ZCI + ASUMR = ZEROR + ASUMI = ZEROI + IF (RFNU.LT.TOL) GO TO 220 + PRZTHR = RZTHR + PRZTHI = RZTHI + PTFNR = TFNR + PTFNI = TFNI + UPR(1) = CONER + UPI(1) = CONEI + PP = 1.0D0 + BTOL = TOL*(DABS(BSUMR)+DABS(BSUMI)) + KS = 0 + KP1 = 2 + L = 3 + IAS = 0 + IBS = 0 + DO 210 LR=2,12,2 + LRP1 = LR + 1 +C----------------------------------------------------------------------- +C COMPUTE TWO ADDITIONAL CR, DR, AND UP FOR TWO MORE TERMS IN +C NEXT SUMA AND SUMB +C----------------------------------------------------------------------- + DO 160 K=LR,LRP1 + KS = KS + 1 + KP1 = KP1 + 1 + L = L + 1 + ZAR = C(L) + ZAI = ZEROI + DO 150 J=2,KP1 + L = L + 1 + STR = ZAR*T2R - T2I*ZAI + C(L) + ZAI = ZAR*T2I + ZAI*T2R + ZAR = STR + 150 CONTINUE + STR = PTFNR*TFNR - PTFNI*TFNI + PTFNI = PTFNR*TFNI + PTFNI*TFNR + PTFNR = STR + UPR(KP1) = PTFNR*ZAR - PTFNI*ZAI + UPI(KP1) = PTFNI*ZAR + PTFNR*ZAI + CRR(KS) = PRZTHR*BR(KS+1) + CRI(KS) = PRZTHI*BR(KS+1) + STR = PRZTHR*RZTHR - PRZTHI*RZTHI + PRZTHI = PRZTHR*RZTHI + PRZTHI*RZTHR + PRZTHR = STR + DRR(KS) = PRZTHR*AR(KS+2) + DRI(KS) = PRZTHI*AR(KS+2) + 160 CONTINUE + PP = PP*RFNU2 + IF (IAS.EQ.1) GO TO 180 + SUMAR = UPR(LRP1) + SUMAI = UPI(LRP1) + JU = LRP1 + DO 170 JR=1,LR + JU = JU - 1 + SUMAR = SUMAR + CRR(JR)*UPR(JU) - CRI(JR)*UPI(JU) + SUMAI = SUMAI + CRR(JR)*UPI(JU) + CRI(JR)*UPR(JU) + 170 CONTINUE + ASUMR = ASUMR + SUMAR + ASUMI = ASUMI + SUMAI + TEST = DABS(SUMAR) + DABS(SUMAI) + IF (PP.LT.TOL .AND. TEST.LT.TOL) IAS = 1 + 180 CONTINUE + IF (IBS.EQ.1) GO TO 200 + SUMBR = UPR(LR+2) + UPR(LRP1)*ZCR - UPI(LRP1)*ZCI + SUMBI = UPI(LR+2) + UPR(LRP1)*ZCI + UPI(LRP1)*ZCR + JU = LRP1 + DO 190 JR=1,LR + JU = JU - 1 + SUMBR = SUMBR + DRR(JR)*UPR(JU) - DRI(JR)*UPI(JU) + SUMBI = SUMBI + DRR(JR)*UPI(JU) + DRI(JR)*UPR(JU) + 190 CONTINUE + BSUMR = BSUMR + SUMBR + BSUMI = BSUMI + SUMBI + TEST = DABS(SUMBR) + DABS(SUMBI) + IF (PP.LT.BTOL .AND. TEST.LT.BTOL) IBS = 1 + 200 CONTINUE + IF (IAS.EQ.1 .AND. IBS.EQ.1) GO TO 220 + 210 CONTINUE + 220 CONTINUE + ASUMR = ASUMR + CONER + STR = -BSUMR*RFN13 + STI = -BSUMI*RFN13 + CALL ZDIV(STR, STI, RTZTR, RTZTI, BSUMR, BSUMI) + GO TO 120 + END diff --git a/mathext/internal/amos/amoslib/zuni1.f b/mathext/internal/amos/amoslib/zuni1.f new file mode 100644 index 00000000..f3a0f246 --- /dev/null +++ b/mathext/internal/amos/amoslib/zuni1.f @@ -0,0 +1,204 @@ + SUBROUTINE ZUNI1(ZR, ZI, FNU, KODE, N, YR, YI, NZ, NLAST, FNUL, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZUNI1 +C***REFER TO ZBESI,ZBESK +C +C ZUNI1 COMPUTES I(FNU,Z) BY MEANS OF THE UNIFORM ASYMPTOTIC +C EXPANSION FOR I(FNU,Z) IN -PI/3.LE.ARG Z.LE.PI/3. +C +C FNUL IS THE SMALLEST ORDER PERMITTED FOR THE ASYMPTOTIC +C EXPANSION. NLAST=0 MEANS ALL OF THE Y VALUES WERE SET. +C NLAST.NE.0 IS THE NUMBER LEFT TO BE COMPUTED BY ANOTHER +C FORMULA FOR ORDERS FNU TO FNU+NLAST-1 BECAUSE FNU+NLAST-1.LT.FNUL. +C Y(I)=CZERO FOR I=NLAST+1,N +C +C***ROUTINES CALLED ZUCHK,ZUNIK,ZUOIK,D1MACH,ZABS +C***END PROLOGUE ZUNI1 +C COMPLEX CFN,CONE,CRSC,CSCL,CSR,CSS,CWRK,CZERO,C1,C2,PHI,RZ,SUM,S1, +C *S2,Y,Z,ZETA1,ZETA2 + DOUBLE PRECISION ALIM, APHI, ASCLE, BRY, CONER, CRSC, + * CSCL, CSRR, CSSR, CWRKI, CWRKR, C1R, C2I, C2M, C2R, ELIM, FN, + * FNU, FNUL, PHII, PHIR, RAST, RS1, RZI, RZR, STI, STR, SUMI, + * SUMR, S1I, S1R, S2I, S2R, TOL, YI, YR, ZEROI, ZEROR, ZETA1I, + * ZETA1R, ZETA2I, ZETA2R, ZI, ZR, CYR, CYI, D1MACH, ZABS + INTEGER I, IFLAG, INIT, K, KODE, M, N, ND, NLAST, NN, NUF, NW, NZ + DIMENSION BRY(3), YR(N), YI(N), CWRKR(16), CWRKI(16), CSSR(3), + * CSRR(3), CYR(2), CYI(2) + DATA ZEROR,ZEROI,CONER / 0.0D0, 0.0D0, 1.0D0 / +C + NZ = 0 + ND = N + NLAST = 0 +C----------------------------------------------------------------------- +C COMPUTED VALUES WITH EXPONENTS BETWEEN ALIM AND ELIM IN MAG- +C NITUDE ARE SCALED TO KEEP INTERMEDIATE ARITHMETIC ON SCALE, +C EXP(ALIM)=EXP(ELIM)*TOL +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CRSC = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CRSC + CSRR(1) = CRSC + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = 1.0D+3*D1MACH(1)/TOL +C----------------------------------------------------------------------- +C CHECK FOR UNDERFLOW AND OVERFLOW ON FIRST MEMBER +C----------------------------------------------------------------------- + FN = DMAX1(FNU,1.0D0) + INIT = 0 + CALL ZUNIK(ZR, ZI, FN, 1, 1, TOL, INIT, PHIR, PHII, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) + IF (KODE.EQ.1) GO TO 10 + STR = ZR + ZETA2R + STI = ZI + ZETA2I + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZETA1R + STR + S1I = -ZETA1I + STI + GO TO 20 + 10 CONTINUE + S1R = -ZETA1R + ZETA2R + S1I = -ZETA1I + ZETA2I + 20 CONTINUE + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 130 + 30 CONTINUE + NN = MIN0(2,ND) + DO 80 I=1,NN + FN = FNU + DBLE(FLOAT(ND-I)) + INIT = 0 + CALL ZUNIK(ZR, ZI, FN, 1, 0, TOL, INIT, PHIR, PHII, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) + IF (KODE.EQ.1) GO TO 40 + STR = ZR + ZETA2R + STI = ZI + ZETA2I + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZETA1R + STR + S1I = -ZETA1I + STI + ZI + GO TO 50 + 40 CONTINUE + S1R = -ZETA1R + ZETA2R + S1I = -ZETA1I + ZETA2I + 50 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 110 + IF (I.EQ.1) IFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 60 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIR,PHII,kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) + IF (DABS(RS1).GT.ELIM) GO TO 110 + IF (I.EQ.1) IFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 60 + IF (I.EQ.1) IFLAG = 3 + 60 CONTINUE +C----------------------------------------------------------------------- +C SCALE S1 IF CABS(S1).LT.ASCLE +C----------------------------------------------------------------------- + S2R = PHIR*SUMR - PHII*SUMI + S2I = PHIR*SUMI + PHII*SUMR + STR = DEXP(S1R)*CSSR(IFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S2R*S1I + S2I*S1R + S2R = STR + IF (IFLAG.NE.1) GO TO 70 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.NE.0) GO TO 110 + 70 CONTINUE + CYR(I) = S2R + CYI(I) = S2I + M = ND - I + 1 + YR(M) = S2R*CSRR(IFLAG) + YI(M) = S2I*CSRR(IFLAG) + 80 CONTINUE + IF (ND.LE.2) GO TO 100 + RAST = 1.0D0/ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + STR = ZR*RAST + STI = -ZI*RAST + RZR = (STR+STR)*RAST + RZI = (STI+STI)*RAST + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + C1R = CSRR(IFLAG) + ASCLE = BRY(IFLAG) + K = ND - 2 + FN = DBLE(FLOAT(K)) + DO 90 I=3,ND + C2R = S2R + C2I = S2I + S2R = S1R + (FNU+FN)*(RZR*C2R-RZI*C2I) + S2I = S1I + (FNU+FN)*(RZR*C2I+RZI*C2R) + S1R = C2R + S1I = C2I + C2R = S2R*C1R + C2I = S2I*C1R + YR(K) = C2R + YI(K) = C2I + K = K - 1 + FN = FN - 1.0D0 + IF (IFLAG.GE.3) GO TO 90 + STR = DABS(C2R) + STI = DABS(C2I) + C2M = DMAX1(STR,STI) + IF (C2M.LE.ASCLE) GO TO 90 + IFLAG = IFLAG + 1 + ASCLE = BRY(IFLAG) + S1R = S1R*C1R + S1I = S1I*C1R + S2R = C2R + S2I = C2I + S1R = S1R*CSSR(IFLAG) + S1I = S1I*CSSR(IFLAG) + S2R = S2R*CSSR(IFLAG) + S2I = S2I*CSSR(IFLAG) + C1R = CSRR(IFLAG) + 90 CONTINUE + 100 CONTINUE + RETURN +C----------------------------------------------------------------------- +C SET UNDERFLOW AND UPDATE PARAMETERS +C----------------------------------------------------------------------- + 110 CONTINUE + IF (RS1.GT.0.0D0) GO TO 120 + YR(ND) = ZEROR + YI(ND) = ZEROI + NZ = NZ + 1 + ND = ND - 1 + IF (ND.EQ.0) GO TO 100 + CALL ZUOIK(ZR, ZI, FNU, KODE, 1, ND, YR, YI, NUF, TOL, ELIM, ALIM) + IF (NUF.LT.0) GO TO 120 + ND = ND - NUF + NZ = NZ + NUF + IF (ND.EQ.0) GO TO 100 + FN = FNU + DBLE(FLOAT(ND-1)) + IF (FN.GE.FNUL) GO TO 30 + NLAST = ND + RETURN + 120 CONTINUE + NZ = -1 + RETURN + 130 CONTINUE + IF (RS1.GT.0.0D0) GO TO 120 + NZ = N + DO 140 I=1,N + YR(I) = ZEROR + YI(I) = ZEROI + 140 CONTINUE + RETURN + END diff --git a/mathext/internal/amos/amoslib/zuni2.f b/mathext/internal/amos/amoslib/zuni2.f new file mode 100644 index 00000000..9e5cfcdd --- /dev/null +++ b/mathext/internal/amos/amoslib/zuni2.f @@ -0,0 +1,267 @@ + SUBROUTINE ZUNI2(ZR, ZI, FNU, KODE, N, YR, YI, NZ, NLAST, FNUL, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZUNI2 +C***REFER TO ZBESI,ZBESK +C +C ZUNI2 COMPUTES I(FNU,Z) IN THE RIGHT HALF PLANE BY MEANS OF +C UNIFORM ASYMPTOTIC EXPANSION FOR J(FNU,ZN) WHERE ZN IS Z*I +C OR -Z*I AND ZN IS IN THE RIGHT HALF PLANE ALSO. +C +C FNUL IS THE SMALLEST ORDER PERMITTED FOR THE ASYMPTOTIC +C EXPANSION. NLAST=0 MEANS ALL OF THE Y VALUES WERE SET. +C NLAST.NE.0 IS THE NUMBER LEFT TO BE COMPUTED BY ANOTHER +C FORMULA FOR ORDERS FNU TO FNU+NLAST-1 BECAUSE FNU+NLAST-1.LT.FNUL. +C Y(I)=CZERO FOR I=NLAST+1,N +C +C***ROUTINES CALLED ZAIRY,ZUCHK,ZUNHJ,ZUOIK,D1MACH,ZABS +C***END PROLOGUE ZUNI2 +C COMPLEX AI,ARG,ASUM,BSUM,CFN,CI,CID,CIP,CONE,CRSC,CSCL,CSR,CSS, +C *CZERO,C1,C2,DAI,PHI,RZ,S1,S2,Y,Z,ZB,ZETA1,ZETA2,ZN + DOUBLE PRECISION AARG, AIC, AII, AIR, ALIM, ANG, APHI, ARGI, + * ARGR, ASCLE, ASUMI, ASUMR, BRY, BSUMI, BSUMR, CIDI, CIPI, CIPR, + * CONER, CRSC, CSCL, CSRR, CSSR, C1R, C2I, C2M, C2R, DAII, + * DAIR, ELIM, FN, FNU, FNUL, HPI, PHII, PHIR, RAST, RAZ, RS1, RZI, + * RZR, STI, STR, S1I, S1R, S2I, S2R, TOL, YI, YR, ZBI, ZBR, ZEROI, + * ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, ZI, ZNI, ZNR, ZR, CYR, + * CYI, D1MACH, ZABS, CAR, SAR + INTEGER I, IFLAG, IN, INU, J, K, KODE, N, NAI, ND, NDAI, NLAST, + * NN, NUF, NW, NZ, IDUM + DIMENSION BRY(3), YR(N), YI(N), CIPR(4), CIPI(4), CSSR(3), + * CSRR(3), CYR(2), CYI(2) + DATA ZEROR,ZEROI,CONER / 0.0D0, 0.0D0, 1.0D0 / + DATA CIPR(1),CIPI(1),CIPR(2),CIPI(2),CIPR(3),CIPI(3),CIPR(4), + * CIPI(4)/ 1.0D0,0.0D0, 0.0D0,1.0D0, -1.0D0,0.0D0, 0.0D0,-1.0D0/ + DATA HPI, AIC / + 1 1.57079632679489662D+00, 1.265512123484645396D+00/ +C + NZ = 0 + ND = N + NLAST = 0 +C----------------------------------------------------------------------- +C COMPUTED VALUES WITH EXPONENTS BETWEEN ALIM AND ELIM IN MAG- +C NITUDE ARE SCALED TO KEEP INTERMEDIATE ARITHMETIC ON SCALE, +C EXP(ALIM)=EXP(ELIM)*TOL +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CRSC = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CRSC + CSRR(1) = CRSC + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = 1.0D+3*D1MACH(1)/TOL +C----------------------------------------------------------------------- +C ZN IS IN THE RIGHT HALF PLANE AFTER ROTATION BY CI OR -CI +C----------------------------------------------------------------------- + ZNR = ZI + ZNI = -ZR + ZBR = ZR + ZBI = ZI + CIDI = -CONER + INU = INT(SNGL(FNU)) + ANG = HPI*(FNU-DBLE(FLOAT(INU))) + C2R = DCOS(ANG) + C2I = DSIN(ANG) + CAR = C2R + SAR = C2I + IN = INU + N - 1 + IN = MOD(IN,4) + 1 + STR = C2R*CIPR(IN) - C2I*CIPI(IN) + C2I = C2R*CIPI(IN) + C2I*CIPR(IN) + C2R = STR + IF (ZI.GT.0.0D0) GO TO 10 + ZNR = -ZNR + ZBI = -ZBI + CIDI = -CIDI + C2I = -C2I + 10 CONTINUE +C----------------------------------------------------------------------- +C CHECK FOR UNDERFLOW AND OVERFLOW ON FIRST MEMBER +C----------------------------------------------------------------------- + FN = DMAX1(FNU,1.0D0) + CALL ZUNHJ(ZNR, ZNI, FN, 1, TOL, PHIR, PHII, ARGR, ARGI, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) + IF (KODE.EQ.1) GO TO 20 + STR = ZBR + ZETA2R + STI = ZBI + ZETA2I + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZETA1R + STR + S1I = -ZETA1I + STI + GO TO 30 + 20 CONTINUE + S1R = -ZETA1R + ZETA2R + S1I = -ZETA1I + ZETA2I + 30 CONTINUE + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 150 + 40 CONTINUE + NN = MIN0(2,ND) + DO 90 I=1,NN + FN = FNU + DBLE(FLOAT(ND-I)) + CALL ZUNHJ(ZNR, ZNI, FN, 0, TOL, PHIR, PHII, ARGR, ARGI, + * ZETA1R, ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) + IF (KODE.EQ.1) GO TO 50 + STR = ZBR + ZETA2R + STI = ZBI + ZETA2I + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZETA1R + STR + S1I = -ZETA1I + STI + DABS(ZI) + GO TO 60 + 50 CONTINUE + S1R = -ZETA1R + ZETA2R + S1I = -ZETA1I + ZETA2I + 60 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 120 + IF (I.EQ.1) IFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 70 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIR,PHII,kind=KIND(1.0D0))) + AARG = ZABS(CMPLX(ARGR,ARGI,kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) - 0.25D0*DLOG(AARG) - AIC + IF (DABS(RS1).GT.ELIM) GO TO 120 + IF (I.EQ.1) IFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 70 + IF (I.EQ.1) IFLAG = 3 + 70 CONTINUE +C----------------------------------------------------------------------- +C SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR +C EXPONENT EXTREMES +C----------------------------------------------------------------------- + CALL ZAIRY(ARGR, ARGI, 0, 2, AIR, AII, NAI, IDUM) + CALL ZAIRY(ARGR, ARGI, 1, 2, DAIR, DAII, NDAI, IDUM) + STR = DAIR*BSUMR - DAII*BSUMI + STI = DAIR*BSUMI + DAII*BSUMR + STR = STR + (AIR*ASUMR-AII*ASUMI) + STI = STI + (AIR*ASUMI+AII*ASUMR) + S2R = PHIR*STR - PHII*STI + S2I = PHIR*STI + PHII*STR + STR = DEXP(S1R)*CSSR(IFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S2R*S1I + S2I*S1R + S2R = STR + IF (IFLAG.NE.1) GO TO 80 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.NE.0) GO TO 120 + 80 CONTINUE + IF (ZI.LE.0.0D0) S2I = -S2I + STR = S2R*C2R - S2I*C2I + S2I = S2R*C2I + S2I*C2R + S2R = STR + CYR(I) = S2R + CYI(I) = S2I + J = ND - I + 1 + YR(J) = S2R*CSRR(IFLAG) + YI(J) = S2I*CSRR(IFLAG) + STR = -C2I*CIDI + C2I = C2R*CIDI + C2R = STR + 90 CONTINUE + IF (ND.LE.2) GO TO 110 + RAZ = 1.0D0/ZABS(CMPLX(ZR,ZI,kind=KIND(1.0D0))) + STR = ZR*RAZ + STI = -ZI*RAZ + RZR = (STR+STR)*RAZ + RZI = (STI+STI)*RAZ + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + C1R = CSRR(IFLAG) + ASCLE = BRY(IFLAG) + K = ND - 2 + FN = DBLE(FLOAT(K)) + DO 100 I=3,ND + C2R = S2R + C2I = S2I + S2R = S1R + (FNU+FN)*(RZR*C2R-RZI*C2I) + S2I = S1I + (FNU+FN)*(RZR*C2I+RZI*C2R) + S1R = C2R + S1I = C2I + C2R = S2R*C1R + C2I = S2I*C1R + YR(K) = C2R + YI(K) = C2I + K = K - 1 + FN = FN - 1.0D0 + IF (IFLAG.GE.3) GO TO 100 + STR = DABS(C2R) + STI = DABS(C2I) + C2M = DMAX1(STR,STI) + IF (C2M.LE.ASCLE) GO TO 100 + IFLAG = IFLAG + 1 + ASCLE = BRY(IFLAG) + S1R = S1R*C1R + S1I = S1I*C1R + S2R = C2R + S2I = C2I + S1R = S1R*CSSR(IFLAG) + S1I = S1I*CSSR(IFLAG) + S2R = S2R*CSSR(IFLAG) + S2I = S2I*CSSR(IFLAG) + C1R = CSRR(IFLAG) + 100 CONTINUE + 110 CONTINUE + RETURN + 120 CONTINUE + IF (RS1.GT.0.0D0) GO TO 140 +C----------------------------------------------------------------------- +C SET UNDERFLOW AND UPDATE PARAMETERS +C----------------------------------------------------------------------- + YR(ND) = ZEROR + YI(ND) = ZEROI + NZ = NZ + 1 + ND = ND - 1 + IF (ND.EQ.0) GO TO 110 + CALL ZUOIK(ZR, ZI, FNU, KODE, 1, ND, YR, YI, NUF, TOL, ELIM, ALIM) + IF (NUF.LT.0) GO TO 140 + ND = ND - NUF + NZ = NZ + NUF + IF (ND.EQ.0) GO TO 110 + FN = FNU + DBLE(FLOAT(ND-1)) + IF (FN.LT.FNUL) GO TO 130 +C FN = CIDI +C J = NUF + 1 +C K = MOD(J,4) + 1 +C S1R = CIPR(K) +C S1I = CIPI(K) +C IF (FN.LT.0.0D0) S1I = -S1I +C STR = C2R*S1R - C2I*S1I +C C2I = C2R*S1I + C2I*S1R +C C2R = STR + IN = INU + ND - 1 + IN = MOD(IN,4) + 1 + C2R = CAR*CIPR(IN) - SAR*CIPI(IN) + C2I = CAR*CIPI(IN) + SAR*CIPR(IN) + IF (ZI.LE.0.0D0) C2I = -C2I + GO TO 40 + 130 CONTINUE + NLAST = ND + RETURN + 140 CONTINUE + NZ = -1 + RETURN + 150 CONTINUE + IF (RS1.GT.0.0D0) GO TO 140 + NZ = N + DO 160 I=1,N + YR(I) = ZEROR + YI(I) = ZEROI + 160 CONTINUE + RETURN + END diff --git a/mathext/internal/amos/amoslib/zunik.f b/mathext/internal/amos/amoslib/zunik.f new file mode 100644 index 00000000..3e8293e3 --- /dev/null +++ b/mathext/internal/amos/amoslib/zunik.f @@ -0,0 +1,211 @@ + SUBROUTINE ZUNIK(ZRR, ZRI, FNU, IKFLG, IPMTR, TOL, INIT, PHIR, + * PHII, ZETA1R, ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) +C***BEGIN PROLOGUE ZUNIK +C***REFER TO ZBESI,ZBESK +C +C ZUNIK COMPUTES PARAMETERS FOR THE UNIFORM ASYMPTOTIC +C EXPANSIONS OF THE I AND K FUNCTIONS ON IKFLG= 1 OR 2 +C RESPECTIVELY BY +C +C W(FNU,ZR) = PHI*EXP(ZETA)*SUM +C +C WHERE ZETA=-ZETA1 + ZETA2 OR +C ZETA1 - ZETA2 +C +C THE FIRST CALL MUST HAVE INIT=0. SUBSEQUENT CALLS WITH THE +C SAME ZR AND FNU WILL RETURN THE I OR K FUNCTION ON IKFLG= +C 1 OR 2 WITH NO CHANGE IN INIT. CWRK IS A COMPLEX WORK +C ARRAY. IPMTR=0 COMPUTES ALL PARAMETERS. IPMTR=1 COMPUTES PHI, +C ZETA1,ZETA2. +C +C***ROUTINES CALLED ZDIV,ZLOG,ZSQRT,D1MACH +C***END PROLOGUE ZUNIK +C COMPLEX CFN,CON,CONE,CRFN,CWRK,CZERO,PHI,S,SR,SUM,T,T2,ZETA1, +C *ZETA2,ZN,ZR + DOUBLE PRECISION AC, C, CON, CONEI, CONER, CRFNI, CRFNR, CWRKI, + * CWRKR, FNU, PHII, PHIR, RFN, SI, SR, SRI, SRR, STI, STR, SUMI, + * SUMR, TEST, TI, TOL, TR, T2I, T2R, ZEROI, ZEROR, ZETA1I, ZETA1R, + * ZETA2I, ZETA2R, ZNI, ZNR, ZRI, ZRR, D1MACH + INTEGER I, IDUM, IKFLG, INIT, IPMTR, J, K, L + DIMENSION C(120), CWRKR(16), CWRKI(16), CON(2) + DATA ZEROR,ZEROI,CONER,CONEI / 0.0D0, 0.0D0, 1.0D0, 0.0D0 / + DATA CON(1), CON(2) / + 1 3.98942280401432678D-01, 1.25331413731550025D+00 / + DATA C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10), + 1 C(11), C(12), C(13), C(14), C(15), C(16), C(17), C(18), + 2 C(19), C(20), C(21), C(22), C(23), C(24)/ + 3 1.00000000000000000D+00, -2.08333333333333333D-01, + 4 1.25000000000000000D-01, 3.34201388888888889D-01, + 5 -4.01041666666666667D-01, 7.03125000000000000D-02, + 6 -1.02581259645061728D+00, 1.84646267361111111D+00, + 7 -8.91210937500000000D-01, 7.32421875000000000D-02, + 8 4.66958442342624743D+00, -1.12070026162229938D+01, + 9 8.78912353515625000D+00, -2.36408691406250000D+00, + A 1.12152099609375000D-01, -2.82120725582002449D+01, + B 8.46362176746007346D+01, -9.18182415432400174D+01, + C 4.25349987453884549D+01, -7.36879435947963170D+00, + D 2.27108001708984375D-01, 2.12570130039217123D+02, + E -7.65252468141181642D+02, 1.05999045252799988D+03/ + DATA C(25), C(26), C(27), C(28), C(29), C(30), C(31), C(32), + 1 C(33), C(34), C(35), C(36), C(37), C(38), C(39), C(40), + 2 C(41), C(42), C(43), C(44), C(45), C(46), C(47), C(48)/ + 3 -6.99579627376132541D+02, 2.18190511744211590D+02, + 4 -2.64914304869515555D+01, 5.72501420974731445D-01, + 5 -1.91945766231840700D+03, 8.06172218173730938D+03, + 6 -1.35865500064341374D+04, 1.16553933368645332D+04, + 7 -5.30564697861340311D+03, 1.20090291321635246D+03, + 8 -1.08090919788394656D+02, 1.72772750258445740D+00, + 9 2.02042913309661486D+04, -9.69805983886375135D+04, + A 1.92547001232531532D+05, -2.03400177280415534D+05, + B 1.22200464983017460D+05, -4.11926549688975513D+04, + C 7.10951430248936372D+03, -4.93915304773088012D+02, + D 6.07404200127348304D+00, -2.42919187900551333D+05, + E 1.31176361466297720D+06, -2.99801591853810675D+06/ + DATA C(49), C(50), C(51), C(52), C(53), C(54), C(55), C(56), + 1 C(57), C(58), C(59), C(60), C(61), C(62), C(63), C(64), + 2 C(65), C(66), C(67), C(68), C(69), C(70), C(71), C(72)/ + 3 3.76327129765640400D+06, -2.81356322658653411D+06, + 4 1.26836527332162478D+06, -3.31645172484563578D+05, + 5 4.52187689813627263D+04, -2.49983048181120962D+03, + 6 2.43805296995560639D+01, 3.28446985307203782D+06, + 7 -1.97068191184322269D+07, 5.09526024926646422D+07, + 8 -7.41051482115326577D+07, 6.63445122747290267D+07, + 9 -3.75671766607633513D+07, 1.32887671664218183D+07, + A -2.78561812808645469D+06, 3.08186404612662398D+05, + B -1.38860897537170405D+04, 1.10017140269246738D+02, + C -4.93292536645099620D+07, 3.25573074185765749D+08, + D -9.39462359681578403D+08, 1.55359689957058006D+09, + E -1.62108055210833708D+09, 1.10684281682301447D+09/ + DATA C(73), C(74), C(75), C(76), C(77), C(78), C(79), C(80), + 1 C(81), C(82), C(83), C(84), C(85), C(86), C(87), C(88), + 2 C(89), C(90), C(91), C(92), C(93), C(94), C(95), C(96)/ + 3 -4.95889784275030309D+08, 1.42062907797533095D+08, + 4 -2.44740627257387285D+07, 2.24376817792244943D+06, + 5 -8.40054336030240853D+04, 5.51335896122020586D+02, + 6 8.14789096118312115D+08, -5.86648149205184723D+09, + 7 1.86882075092958249D+10, -3.46320433881587779D+10, + 8 4.12801855797539740D+10, -3.30265997498007231D+10, + 9 1.79542137311556001D+10, -6.56329379261928433D+09, + A 1.55927986487925751D+09, -2.25105661889415278D+08, + B 1.73951075539781645D+07, -5.49842327572288687D+05, + C 3.03809051092238427D+03, -1.46792612476956167D+10, + D 1.14498237732025810D+11, -3.99096175224466498D+11, + E 8.19218669548577329D+11, -1.09837515608122331D+12/ + DATA C(97), C(98), C(99), C(100), C(101), C(102), C(103), C(104), + 1 C(105), C(106), C(107), C(108), C(109), C(110), C(111), + 2 C(112), C(113), C(114), C(115), C(116), C(117), C(118)/ + 3 1.00815810686538209D+12, -6.45364869245376503D+11, + 4 2.87900649906150589D+11, -8.78670721780232657D+10, + 5 1.76347306068349694D+10, -2.16716498322379509D+09, + 6 1.43157876718888981D+08, -3.87183344257261262D+06, + 7 1.82577554742931747D+04, 2.86464035717679043D+11, + 8 -2.40629790002850396D+12, 9.10934118523989896D+12, + 9 -2.05168994109344374D+13, 3.05651255199353206D+13, + A -3.16670885847851584D+13, 2.33483640445818409D+13, + B -1.23204913055982872D+13, 4.61272578084913197D+12, + C -1.19655288019618160D+12, 2.05914503232410016D+11, + D -2.18229277575292237D+10, 1.24700929351271032D+09/ + DATA C(119), C(120)/ + 1 -2.91883881222208134D+07, 1.18838426256783253D+05/ +C + IF (INIT.NE.0) GO TO 40 +C----------------------------------------------------------------------- +C INITIALIZE ALL VARIABLES +C----------------------------------------------------------------------- + RFN = 1.0D0/FNU +C----------------------------------------------------------------------- +C OVERFLOW TEST (ZR/FNU TOO SMALL) +C----------------------------------------------------------------------- + TEST = D1MACH(1)*1.0D+3 + AC = FNU*TEST + IF (DABS(ZRR).GT.AC .OR. DABS(ZRI).GT.AC) GO TO 15 + ZETA1R = 2.0D0*DABS(DLOG(TEST))+FNU + ZETA1I = 0.0D0 + ZETA2R = FNU + ZETA2I = 0.0D0 + PHIR = 1.0D0 + PHII = 0.0D0 + RETURN + 15 CONTINUE + TR = ZRR*RFN + TI = ZRI*RFN + SR = CONER + (TR*TR-TI*TI) + SI = CONEI + (TR*TI+TI*TR) + CALL ZSQRT(SR, SI, SRR, SRI) + STR = CONER + SRR + STI = CONEI + SRI + CALL ZDIV(STR, STI, TR, TI, ZNR, ZNI) + CALL ZLOG(ZNR, ZNI, STR, STI, IDUM) + ZETA1R = FNU*STR + ZETA1I = FNU*STI + ZETA2R = FNU*SRR + ZETA2I = FNU*SRI + CALL ZDIV(CONER, CONEI, SRR, SRI, TR, TI) + SRR = TR*RFN + SRI = TI*RFN + CALL ZSQRT(SRR, SRI, CWRKR(16), CWRKI(16)) + PHIR = CWRKR(16)*CON(IKFLG) + PHII = CWRKI(16)*CON(IKFLG) + IF (IPMTR.NE.0) RETURN + CALL ZDIV(CONER, CONEI, SR, SI, T2R, T2I) + CWRKR(1) = CONER + CWRKI(1) = CONEI + CRFNR = CONER + CRFNI = CONEI + AC = 1.0D0 + L = 1 + DO 20 K=2,15 + SR = ZEROR + SI = ZEROI + DO 10 J=1,K + L = L + 1 + STR = SR*T2R - SI*T2I + C(L) + SI = SR*T2I + SI*T2R + SR = STR + 10 CONTINUE + STR = CRFNR*SRR - CRFNI*SRI + CRFNI = CRFNR*SRI + CRFNI*SRR + CRFNR = STR + CWRKR(K) = CRFNR*SR - CRFNI*SI + CWRKI(K) = CRFNR*SI + CRFNI*SR + AC = AC*RFN + TEST = DABS(CWRKR(K)) + DABS(CWRKI(K)) + IF (AC.LT.TOL .AND. TEST.LT.TOL) GO TO 30 + 20 CONTINUE + K = 15 + 30 CONTINUE + INIT = K + 40 CONTINUE + IF (IKFLG.EQ.2) GO TO 60 +C----------------------------------------------------------------------- +C COMPUTE SUM FOR THE I FUNCTION +C----------------------------------------------------------------------- + SR = ZEROR + SI = ZEROI + DO 50 I=1,INIT + SR = SR + CWRKR(I) + SI = SI + CWRKI(I) + 50 CONTINUE + SUMR = SR + SUMI = SI + PHIR = CWRKR(16)*CON(1) + PHII = CWRKI(16)*CON(1) + RETURN + 60 CONTINUE +C----------------------------------------------------------------------- +C COMPUTE SUM FOR THE K FUNCTION +C----------------------------------------------------------------------- + SR = ZEROR + SI = ZEROI + TR = CONER + DO 70 I=1,INIT + SR = SR + TR*CWRKR(I) + SI = SI + TR*CWRKI(I) + TR = -TR + 70 CONTINUE + SUMR = SR + SUMI = SI + PHIR = CWRKR(16)*CON(2) + PHII = CWRKI(16)*CON(2) + RETURN + END diff --git a/mathext/internal/amos/amoslib/zunk1.f b/mathext/internal/amos/amoslib/zunk1.f new file mode 100644 index 00000000..6b2418dd --- /dev/null +++ b/mathext/internal/amos/amoslib/zunk1.f @@ -0,0 +1,426 @@ + SUBROUTINE ZUNK1(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZUNK1 +C***REFER TO ZBESK +C +C ZUNK1 COMPUTES K(FNU,Z) AND ITS ANALYTIC CONTINUATION FROM THE +C RIGHT HALF PLANE TO THE LEFT HALF PLANE BY MEANS OF THE +C UNIFORM ASYMPTOTIC EXPANSION. +C MR INDICATES THE DIRECTION OF ROTATION FOR ANALYTIC CONTINUATION. +C NZ=-1 MEANS AN OVERFLOW WILL OCCUR +C +C***ROUTINES CALLED ZKSCL,ZS1S2,ZUCHK,ZUNIK,D1MACH,ZABS +C***END PROLOGUE ZUNK1 +C COMPLEX CFN,CK,CONE,CRSC,CS,CSCL,CSGN,CSPN,CSR,CSS,CWRK,CY,CZERO, +C *C1,C2,PHI,PHID,RZ,SUM,SUMD,S1,S2,Y,Z,ZETA1,ZETA1D,ZETA2,ZETA2D,ZR + DOUBLE PRECISION ALIM, ANG, APHI, ASC, ASCLE, BRY, CKI, CKR, + * CONER, CRSC, CSCL, CSGNI, CSPNI, CSPNR, CSR, CSRR, CSSR, + * CWRKI, CWRKR, CYI, CYR, C1I, C1R, C2I, C2M, C2R, ELIM, FMR, FN, + * FNF, FNU, PHIDI, PHIDR, PHII, PHIR, PI, RAST, RAZR, RS1, RZI, + * RZR, SGN, STI, STR, SUMDI, SUMDR, SUMI, SUMR, S1I, S1R, S2I, + * S2R, TOL, YI, YR, ZEROI, ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, + * ZET1DI, ZET1DR, ZET2DI, ZET2DR, ZI, ZR, ZRI, ZRR, D1MACH, ZABS + INTEGER I, IB, IFLAG, IFN, IL, INIT, INU, IUF, K, KDFLG, KFLAG, + * KK, KODE, MR, N, NW, NZ, INITD, IC, IPARD, J + DIMENSION BRY(3), INIT(2), YR(N), YI(N), SUMR(2), SUMI(2), + * ZETA1R(2), ZETA1I(2), ZETA2R(2), ZETA2I(2), CYR(2), CYI(2), + * CWRKR(16,3), CWRKI(16,3), CSSR(3), CSRR(3), PHIR(2), PHII(2) + DATA ZEROR,ZEROI,CONER / 0.0D0, 0.0D0, 1.0D0 / + DATA PI / 3.14159265358979324D0 / +C + KDFLG = 1 + NZ = 0 +C----------------------------------------------------------------------- +C EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION GREATER THAN +C THE UNDERFLOW LIMIT +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CRSC = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CRSC + CSRR(1) = CRSC + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = 1.0D+3*D1MACH(1)/TOL + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + ZRR = ZR + ZRI = ZI + IF (ZR.GE.0.0D0) GO TO 10 + ZRR = -ZR + ZRI = -ZI + 10 CONTINUE + J = 2 + DO 70 I=1,N +C----------------------------------------------------------------------- +C J FLIP FLOPS BETWEEN 1 AND 2 IN J = 3 - J +C----------------------------------------------------------------------- + J = 3 - J + FN = FNU + DBLE(FLOAT(I-1)) + INIT(J) = 0 + CALL ZUNIK(ZRR, ZRI, FN, 2, 0, TOL, INIT(J), PHIR(J), PHII(J), + * ZETA1R(J), ZETA1I(J), ZETA2R(J), ZETA2I(J), SUMR(J), SUMI(J), + * CWRKR(1,J), CWRKI(1,J)) + IF (KODE.EQ.1) GO TO 20 + STR = ZRR + ZETA2R(J) + STI = ZRI + ZETA2I(J) + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = ZETA1R(J) - STR + S1I = ZETA1I(J) - STI + GO TO 30 + 20 CONTINUE + S1R = ZETA1R(J) - ZETA2R(J) + S1I = ZETA1I(J) - ZETA2I(J) + 30 CONTINUE + RS1 = S1R +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + IF (DABS(RS1).GT.ELIM) GO TO 60 + IF (KDFLG.EQ.1) KFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 40 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIR(J),PHII(J),kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) + IF (DABS(RS1).GT.ELIM) GO TO 60 + IF (KDFLG.EQ.1) KFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 40 + IF (KDFLG.EQ.1) KFLAG = 3 + 40 CONTINUE +C----------------------------------------------------------------------- +C SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR +C EXPONENT EXTREMES +C----------------------------------------------------------------------- + S2R = PHIR(J)*SUMR(J) - PHII(J)*SUMI(J) + S2I = PHIR(J)*SUMI(J) + PHII(J)*SUMR(J) + STR = DEXP(S1R)*CSSR(KFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S1R*S2I + S2R*S1I + S2R = STR + IF (KFLAG.NE.1) GO TO 50 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.NE.0) GO TO 60 + 50 CONTINUE + CYR(KDFLG) = S2R + CYI(KDFLG) = S2I + YR(I) = S2R*CSRR(KFLAG) + YI(I) = S2I*CSRR(KFLAG) + IF (KDFLG.EQ.2) GO TO 75 + KDFLG = 2 + GO TO 70 + 60 CONTINUE + IF (RS1.GT.0.0D0) GO TO 300 +C----------------------------------------------------------------------- +C FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW +C----------------------------------------------------------------------- + IF (ZR.LT.0.0D0) GO TO 300 + KDFLG = 1 + YR(I)=ZEROR + YI(I)=ZEROI + NZ=NZ+1 + IF (I.EQ.1) GO TO 70 + IF ((YR(I-1).EQ.ZEROR).AND.(YI(I-1).EQ.ZEROI)) GO TO 70 + YR(I-1)=ZEROR + YI(I-1)=ZEROI + NZ=NZ+1 + 70 CONTINUE + I = N + 75 CONTINUE + RAZR = 1.0D0/ZABS(CMPLX(ZRR,ZRI,kind=KIND(1.0D0))) + STR = ZRR*RAZR + STI = -ZRI*RAZR + RZR = (STR+STR)*RAZR + RZI = (STI+STI)*RAZR + CKR = FN*RZR + CKI = FN*RZI + IB = I + 1 + IF (N.LT.IB) GO TO 160 +C----------------------------------------------------------------------- +C TEST LAST MEMBER FOR UNDERFLOW AND OVERFLOW. SET SEQUENCE TO ZERO +C ON UNDERFLOW. +C----------------------------------------------------------------------- + FN = FNU + DBLE(FLOAT(N-1)) + IPARD = 1 + IF (MR.NE.0) IPARD = 0 + INITD = 0 + CALL ZUNIK(ZRR, ZRI, FN, 2, IPARD, TOL, INITD, PHIDR, PHIDI, + * ZET1DR, ZET1DI, ZET2DR, ZET2DI, SUMDR, SUMDI, CWRKR(1,3), + * CWRKI(1,3)) + IF (KODE.EQ.1) GO TO 80 + STR = ZRR + ZET2DR + STI = ZRI + ZET2DI + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = ZET1DR - STR + S1I = ZET1DI - STI + GO TO 90 + 80 CONTINUE + S1R = ZET1DR - ZET2DR + S1I = ZET1DI - ZET2DI + 90 CONTINUE + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 95 + IF (DABS(RS1).LT.ALIM) GO TO 100 +C---------------------------------------------------------------------------- +C REFINE ESTIMATE AND TEST +C------------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIDR,PHIDI,kind=KIND(1.0D0))) + RS1 = RS1+DLOG(APHI) + IF (DABS(RS1).LT.ELIM) GO TO 100 + 95 CONTINUE + IF (DABS(RS1).GT.0.0D0) GO TO 300 +C----------------------------------------------------------------------- +C FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW +C----------------------------------------------------------------------- + IF (ZR.LT.0.0D0) GO TO 300 + NZ = N + DO 96 I=1,N + YR(I) = ZEROR + YI(I) = ZEROI + 96 CONTINUE + RETURN +C--------------------------------------------------------------------------- +C FORWARD RECUR FOR REMAINDER OF THE SEQUENCE +C---------------------------------------------------------------------------- + 100 CONTINUE + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + C1R = CSRR(KFLAG) + ASCLE = BRY(KFLAG) + DO 120 I=IB,N + C2R = S2R + C2I = S2I + S2R = CKR*C2R - CKI*C2I + S1R + S2I = CKR*C2I + CKI*C2R + S1I + S1R = C2R + S1I = C2I + CKR = CKR + RZR + CKI = CKI + RZI + C2R = S2R*C1R + C2I = S2I*C1R + YR(I) = C2R + YI(I) = C2I + IF (KFLAG.GE.3) GO TO 120 + STR = DABS(C2R) + STI = DABS(C2I) + C2M = DMAX1(STR,STI) + IF (C2M.LE.ASCLE) GO TO 120 + KFLAG = KFLAG + 1 + ASCLE = BRY(KFLAG) + S1R = S1R*C1R + S1I = S1I*C1R + S2R = C2R + S2I = C2I + S1R = S1R*CSSR(KFLAG) + S1I = S1I*CSSR(KFLAG) + S2R = S2R*CSSR(KFLAG) + S2I = S2I*CSSR(KFLAG) + C1R = CSRR(KFLAG) + 120 CONTINUE + 160 CONTINUE + IF (MR.EQ.0) RETURN +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION FOR RE(Z).LT.0.0D0 +C----------------------------------------------------------------------- + NZ = 0 + FMR = DBLE(FLOAT(MR)) + SGN = -DSIGN(PI,FMR) +C----------------------------------------------------------------------- +C CSPN AND CSGN ARE COEFF OF K AND I FUNCTIONS RESP. +C----------------------------------------------------------------------- + CSGNI = SGN + INU = INT(SNGL(FNU)) + FNF = FNU - DBLE(FLOAT(INU)) + IFN = INU + N - 1 + ANG = FNF*SGN + CSPNR = DCOS(ANG) + CSPNI = DSIN(ANG) + IF (MOD(IFN,2).EQ.0) GO TO 170 + CSPNR = -CSPNR + CSPNI = -CSPNI + 170 CONTINUE + ASC = BRY(1) + IUF = 0 + KK = N + KDFLG = 1 + IB = IB - 1 + IC = IB - 1 + DO 270 K=1,N + FN = FNU + DBLE(FLOAT(KK-1)) +C----------------------------------------------------------------------- +C LOGIC TO SORT OUT CASES WHOSE PARAMETERS WERE SET FOR THE K +C FUNCTION ABOVE +C----------------------------------------------------------------------- + M=3 + IF (N.GT.2) GO TO 175 + 172 CONTINUE + INITD = INIT(J) + PHIDR = PHIR(J) + PHIDI = PHII(J) + ZET1DR = ZETA1R(J) + ZET1DI = ZETA1I(J) + ZET2DR = ZETA2R(J) + ZET2DI = ZETA2I(J) + SUMDR = SUMR(J) + SUMDI = SUMI(J) + M = J + J = 3 - J + GO TO 180 + 175 CONTINUE + IF ((KK.EQ.N).AND.(IB.LT.N)) GO TO 180 + IF ((KK.EQ.IB).OR.(KK.EQ.IC)) GO TO 172 + INITD = 0 + 180 CONTINUE + CALL ZUNIK(ZRR, ZRI, FN, 1, 0, TOL, INITD, PHIDR, PHIDI, + * ZET1DR, ZET1DI, ZET2DR, ZET2DI, SUMDR, SUMDI, + * CWRKR(1,M), CWRKI(1,M)) + IF (KODE.EQ.1) GO TO 200 + STR = ZRR + ZET2DR + STI = ZRI + ZET2DI + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZET1DR + STR + S1I = -ZET1DI + STI + GO TO 210 + 200 CONTINUE + S1R = -ZET1DR + ZET2DR + S1I = -ZET1DI + ZET2DI + 210 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 260 + IF (KDFLG.EQ.1) IFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 220 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIDR,PHIDI,kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) + IF (DABS(RS1).GT.ELIM) GO TO 260 + IF (KDFLG.EQ.1) IFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 220 + IF (KDFLG.EQ.1) IFLAG = 3 + 220 CONTINUE + STR = PHIDR*SUMDR - PHIDI*SUMDI + STI = PHIDR*SUMDI + PHIDI*SUMDR + S2R = -CSGNI*STI + S2I = CSGNI*STR + STR = DEXP(S1R)*CSSR(IFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S2R*S1I + S2I*S1R + S2R = STR + IF (IFLAG.NE.1) GO TO 230 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.EQ.0) GO TO 230 + S2R = ZEROR + S2I = ZEROI + 230 CONTINUE + CYR(KDFLG) = S2R + CYI(KDFLG) = S2I + C2R = S2R + C2I = S2I + S2R = S2R*CSRR(IFLAG) + S2I = S2I*CSRR(IFLAG) +C----------------------------------------------------------------------- +C ADD I AND K FUNCTIONS, K SEQUENCE IN Y(I), I=1,N +C----------------------------------------------------------------------- + S1R = YR(KK) + S1I = YI(KK) + IF (KODE.EQ.1) GO TO 250 + CALL ZS1S2(ZRR, ZRI, S1R, S1I, S2R, S2I, NW, ASC, ALIM, IUF) + NZ = NZ + NW + 250 CONTINUE + YR(KK) = S1R*CSPNR - S1I*CSPNI + S2R + YI(KK) = CSPNR*S1I + CSPNI*S1R + S2I + KK = KK - 1 + CSPNR = -CSPNR + CSPNI = -CSPNI + IF (C2R.NE.0.0D0 .OR. C2I.NE.0.0D0) GO TO 255 + KDFLG = 1 + GO TO 270 + 255 CONTINUE + IF (KDFLG.EQ.2) GO TO 275 + KDFLG = 2 + GO TO 270 + 260 CONTINUE + IF (RS1.GT.0.0D0) GO TO 300 + S2R = ZEROR + S2I = ZEROI + GO TO 230 + 270 CONTINUE + K = N + 275 CONTINUE + IL = N - K + IF (IL.EQ.0) RETURN +C----------------------------------------------------------------------- +C RECUR BACKWARD FOR REMAINDER OF I SEQUENCE AND ADD IN THE +C K FUNCTIONS, SCALING THE I SEQUENCE DURING RECURRENCE TO KEEP +C INTERMEDIATE ARITHMETIC ON SCALE NEAR EXPONENT EXTREMES. +C----------------------------------------------------------------------- + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + CSR = CSRR(IFLAG) + ASCLE = BRY(IFLAG) + FN = DBLE(FLOAT(INU+IL)) + DO 290 I=1,IL + C2R = S2R + C2I = S2I + S2R = S1R + (FN+FNF)*(RZR*C2R-RZI*C2I) + S2I = S1I + (FN+FNF)*(RZR*C2I+RZI*C2R) + S1R = C2R + S1I = C2I + FN = FN - 1.0D0 + C2R = S2R*CSR + C2I = S2I*CSR + CKR = C2R + CKI = C2I + C1R = YR(KK) + C1I = YI(KK) + IF (KODE.EQ.1) GO TO 280 + CALL ZS1S2(ZRR, ZRI, C1R, C1I, C2R, C2I, NW, ASC, ALIM, IUF) + NZ = NZ + NW + 280 CONTINUE + YR(KK) = C1R*CSPNR - C1I*CSPNI + C2R + YI(KK) = C1R*CSPNI + C1I*CSPNR + C2I + KK = KK - 1 + CSPNR = -CSPNR + CSPNI = -CSPNI + IF (IFLAG.GE.3) GO TO 290 + C2R = DABS(CKR) + C2I = DABS(CKI) + C2M = DMAX1(C2R,C2I) + IF (C2M.LE.ASCLE) GO TO 290 + IFLAG = IFLAG + 1 + ASCLE = BRY(IFLAG) + S1R = S1R*CSR + S1I = S1I*CSR + S2R = CKR + S2I = CKI + S1R = S1R*CSSR(IFLAG) + S1I = S1I*CSSR(IFLAG) + S2R = S2R*CSSR(IFLAG) + S2I = S2I*CSSR(IFLAG) + CSR = CSRR(IFLAG) + 290 CONTINUE + RETURN + 300 CONTINUE + NZ = -1 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zunk2.f b/mathext/internal/amos/amoslib/zunk2.f new file mode 100644 index 00000000..6859f5ec --- /dev/null +++ b/mathext/internal/amos/amoslib/zunk2.f @@ -0,0 +1,505 @@ + SUBROUTINE ZUNK2(ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, TOL, ELIM, + * ALIM) +C***BEGIN PROLOGUE ZUNK2 +C***REFER TO ZBESK +C +C ZUNK2 COMPUTES K(FNU,Z) AND ITS ANALYTIC CONTINUATION FROM THE +C RIGHT HALF PLANE TO THE LEFT HALF PLANE BY MEANS OF THE +C UNIFORM ASYMPTOTIC EXPANSIONS FOR H(KIND,FNU,ZN) AND J(FNU,ZN) +C WHERE ZN IS IN THE RIGHT HALF PLANE, KIND=(3-MR)/2, MR=+1 OR +C -1. HERE ZN=ZR*I OR -ZR*I WHERE ZR=Z IF Z IS IN THE RIGHT +C HALF PLANE OR ZR=-Z IF Z IS IN THE LEFT HALF PLANE. MR INDIC- +C ATES THE DIRECTION OF ROTATION FOR ANALYTIC CONTINUATION. +C NZ=-1 MEANS AN OVERFLOW WILL OCCUR +C +C***ROUTINES CALLED ZAIRY,ZKSCL,ZS1S2,ZUCHK,ZUNHJ,D1MACH,ZABS +C***END PROLOGUE ZUNK2 +C COMPLEX AI,ARG,ARGD,ASUM,ASUMD,BSUM,BSUMD,CFN,CI,CIP,CK,CONE,CRSC, +C *CR1,CR2,CS,CSCL,CSGN,CSPN,CSR,CSS,CY,CZERO,C1,C2,DAI,PHI,PHID,RZ, +C *S1,S2,Y,Z,ZB,ZETA1,ZETA1D,ZETA2,ZETA2D,ZN,ZR + DOUBLE PRECISION AARG, AIC, AII, AIR, ALIM, ANG, APHI, ARGDI, + * ARGDR, ARGI, ARGR, ASC, ASCLE, ASUMDI, ASUMDR, ASUMI, ASUMR, + * BRY, BSUMDI, BSUMDR, BSUMI, BSUMR, CAR, CIPI, CIPR, CKI, CKR, + * CONER, CRSC, CR1I, CR1R, CR2I, CR2R, CSCL, CSGNI, CSI, + * CSPNI, CSPNR, CSR, CSRR, CSSR, CYI, CYR, C1I, C1R, C2I, C2M, + * C2R, DAII, DAIR, ELIM, FMR, FN, FNF, FNU, HPI, PHIDI, PHIDR, + * PHII, PHIR, PI, PTI, PTR, RAST, RAZR, RS1, RZI, RZR, SAR, SGN, + * STI, STR, S1I, S1R, S2I, S2R, TOL, YI, YR, YY, ZBI, ZBR, ZEROI, + * ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, ZET1DI, ZET1DR, ZET2DI, + * ZET2DR, ZI, ZNI, ZNR, ZR, ZRI, ZRR, D1MACH, ZABS + INTEGER I, IB, IFLAG, IFN, IL, IN, INU, IUF, K, KDFLG, KFLAG, KK, + * KODE, MR, N, NAI, NDAI, NW, NZ, IDUM, J, IPARD, IC + DIMENSION BRY(3), YR(N), YI(N), ASUMR(2), ASUMI(2), BSUMR(2), + * BSUMI(2), PHIR(2), PHII(2), ARGR(2), ARGI(2), ZETA1R(2), + * ZETA1I(2), ZETA2R(2), ZETA2I(2), CYR(2), CYI(2), CIPR(4), + * CIPI(4), CSSR(3), CSRR(3) + DATA ZEROR,ZEROI,CONER,CR1R,CR1I,CR2R,CR2I / + 1 0.0D0, 0.0D0, 1.0D0, + 1 1.0D0,1.73205080756887729D0 , -0.5D0,-8.66025403784438647D-01 / + DATA HPI, PI, AIC / + 1 1.57079632679489662D+00, 3.14159265358979324D+00, + 1 1.26551212348464539D+00/ + DATA CIPR(1),CIPI(1),CIPR(2),CIPI(2),CIPR(3),CIPI(3),CIPR(4), + * CIPI(4) / + 1 1.0D0,0.0D0 , 0.0D0,-1.0D0 , -1.0D0,0.0D0 , 0.0D0,1.0D0 / +C + KDFLG = 1 + NZ = 0 +C----------------------------------------------------------------------- +C EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION GREATER THAN +C THE UNDERFLOW LIMIT +C----------------------------------------------------------------------- + CSCL = 1.0D0/TOL + CRSC = TOL + CSSR(1) = CSCL + CSSR(2) = CONER + CSSR(3) = CRSC + CSRR(1) = CRSC + CSRR(2) = CONER + CSRR(3) = CSCL + BRY(1) = 1.0D+3*D1MACH(1)/TOL + BRY(2) = 1.0D0/BRY(1) + BRY(3) = D1MACH(2) + ZRR = ZR + ZRI = ZI + IF (ZR.GE.0.0D0) GO TO 10 + ZRR = -ZR + ZRI = -ZI + 10 CONTINUE + YY = ZRI + ZNR = ZRI + ZNI = -ZRR + ZBR = ZRR + ZBI = ZRI + INU = INT(SNGL(FNU)) + FNF = FNU - DBLE(FLOAT(INU)) + ANG = -HPI*FNF + CAR = DCOS(ANG) + SAR = DSIN(ANG) + C2R = HPI*SAR + C2I = -HPI*CAR + KK = MOD(INU,4) + 1 + STR = C2R*CIPR(KK) - C2I*CIPI(KK) + STI = C2R*CIPI(KK) + C2I*CIPR(KK) + CSR = CR1R*STR - CR1I*STI + CSI = CR1R*STI + CR1I*STR + IF (YY.GT.0.0D0) GO TO 20 + ZNR = -ZNR + ZBI = -ZBI + 20 CONTINUE +C----------------------------------------------------------------------- +C K(FNU,Z) IS COMPUTED FROM H(2,FNU,-I*Z) WHERE Z IS IN THE FIRST +C QUADRANT. FOURTH QUADRANT VALUES (YY.LE.0.0E0) ARE COMPUTED BY +C CONJUGATION SINCE THE K FUNCTION IS REAL ON THE POSITIVE REAL AXIS +C----------------------------------------------------------------------- + J = 2 + DO 80 I=1,N +C----------------------------------------------------------------------- +C J FLIP FLOPS BETWEEN 1 AND 2 IN J = 3 - J +C----------------------------------------------------------------------- + J = 3 - J + FN = FNU + DBLE(FLOAT(I-1)) + CALL ZUNHJ(ZNR, ZNI, FN, 0, TOL, PHIR(J), PHII(J), ARGR(J), + * ARGI(J), ZETA1R(J), ZETA1I(J), ZETA2R(J), ZETA2I(J), ASUMR(J), + * ASUMI(J), BSUMR(J), BSUMI(J)) + IF (KODE.EQ.1) GO TO 30 + STR = ZBR + ZETA2R(J) + STI = ZBI + ZETA2I(J) + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = ZETA1R(J) - STR + S1I = ZETA1I(J) - STI + GO TO 40 + 30 CONTINUE + S1R = ZETA1R(J) - ZETA2R(J) + S1I = ZETA1I(J) - ZETA2I(J) + 40 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 70 + IF (KDFLG.EQ.1) KFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 50 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIR(J),PHII(J),kind=KIND(1.0D0))) + AARG = ZABS(CMPLX(ARGR(J),ARGI(J),kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) - 0.25D0*DLOG(AARG) - AIC + IF (DABS(RS1).GT.ELIM) GO TO 70 + IF (KDFLG.EQ.1) KFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 50 + IF (KDFLG.EQ.1) KFLAG = 3 + 50 CONTINUE +C----------------------------------------------------------------------- +C SCALE S1 TO KEEP INTERMEDIATE ARITHMETIC ON SCALE NEAR +C EXPONENT EXTREMES +C----------------------------------------------------------------------- + C2R = ARGR(J)*CR2R - ARGI(J)*CR2I + C2I = ARGR(J)*CR2I + ARGI(J)*CR2R + CALL ZAIRY(C2R, C2I, 0, 2, AIR, AII, NAI, IDUM) + CALL ZAIRY(C2R, C2I, 1, 2, DAIR, DAII, NDAI, IDUM) + STR = DAIR*BSUMR(J) - DAII*BSUMI(J) + STI = DAIR*BSUMI(J) + DAII*BSUMR(J) + PTR = STR*CR2R - STI*CR2I + PTI = STR*CR2I + STI*CR2R + STR = PTR + (AIR*ASUMR(J)-AII*ASUMI(J)) + STI = PTI + (AIR*ASUMI(J)+AII*ASUMR(J)) + PTR = STR*PHIR(J) - STI*PHII(J) + PTI = STR*PHII(J) + STI*PHIR(J) + S2R = PTR*CSR - PTI*CSI + S2I = PTR*CSI + PTI*CSR + STR = DEXP(S1R)*CSSR(KFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S1R*S2I + S2R*S1I + S2R = STR + IF (KFLAG.NE.1) GO TO 60 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.NE.0) GO TO 70 + 60 CONTINUE + IF (YY.LE.0.0D0) S2I = -S2I + CYR(KDFLG) = S2R + CYI(KDFLG) = S2I + YR(I) = S2R*CSRR(KFLAG) + YI(I) = S2I*CSRR(KFLAG) + STR = CSI + CSI = -CSR + CSR = STR + IF (KDFLG.EQ.2) GO TO 85 + KDFLG = 2 + GO TO 80 + 70 CONTINUE + IF (RS1.GT.0.0D0) GO TO 320 +C----------------------------------------------------------------------- +C FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW +C----------------------------------------------------------------------- + IF (ZR.LT.0.0D0) GO TO 320 + KDFLG = 1 + YR(I)=ZEROR + YI(I)=ZEROI + NZ=NZ+1 + STR = CSI + CSI =-CSR + CSR = STR + IF (I.EQ.1) GO TO 80 + IF ((YR(I-1).EQ.ZEROR).AND.(YI(I-1).EQ.ZEROI)) GO TO 80 + YR(I-1)=ZEROR + YI(I-1)=ZEROI + NZ=NZ+1 + 80 CONTINUE + I = N + 85 CONTINUE + RAZR = 1.0D0/ZABS(CMPLX(ZRR,ZRI,kind=KIND(1.0D0))) + STR = ZRR*RAZR + STI = -ZRI*RAZR + RZR = (STR+STR)*RAZR + RZI = (STI+STI)*RAZR + CKR = FN*RZR + CKI = FN*RZI + IB = I + 1 + IF (N.LT.IB) GO TO 180 +C----------------------------------------------------------------------- +C TEST LAST MEMBER FOR UNDERFLOW AND OVERFLOW. SET SEQUENCE TO ZERO +C ON UNDERFLOW. +C----------------------------------------------------------------------- + FN = FNU + DBLE(FLOAT(N-1)) + IPARD = 1 + IF (MR.NE.0) IPARD = 0 + CALL ZUNHJ(ZNR, ZNI, FN, IPARD, TOL, PHIDR, PHIDI, ARGDR, ARGDI, + * ZET1DR, ZET1DI, ZET2DR, ZET2DI, ASUMDR, ASUMDI, BSUMDR, BSUMDI) + IF (KODE.EQ.1) GO TO 90 + STR = ZBR + ZET2DR + STI = ZBI + ZET2DI + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = ZET1DR - STR + S1I = ZET1DI - STI + GO TO 100 + 90 CONTINUE + S1R = ZET1DR - ZET2DR + S1I = ZET1DI - ZET2DI + 100 CONTINUE + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 105 + IF (DABS(RS1).LT.ALIM) GO TO 120 +C---------------------------------------------------------------------------- +C REFINE ESTIMATE AND TEST +C------------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIDR,PHIDI,kind=KIND(1.0D0))) + RS1 = RS1+DLOG(APHI) + IF (DABS(RS1).LT.ELIM) GO TO 120 + 105 CONTINUE + IF (RS1.GT.0.0D0) GO TO 320 +C----------------------------------------------------------------------- +C FOR ZR.LT.0.0, THE I FUNCTION TO BE ADDED WILL OVERFLOW +C----------------------------------------------------------------------- + IF (ZR.LT.0.0D0) GO TO 320 + NZ = N + DO 106 I=1,N + YR(I) = ZEROR + YI(I) = ZEROI + 106 CONTINUE + RETURN + 120 CONTINUE + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + C1R = CSRR(KFLAG) + ASCLE = BRY(KFLAG) + DO 130 I=IB,N + C2R = S2R + C2I = S2I + S2R = CKR*C2R - CKI*C2I + S1R + S2I = CKR*C2I + CKI*C2R + S1I + S1R = C2R + S1I = C2I + CKR = CKR + RZR + CKI = CKI + RZI + C2R = S2R*C1R + C2I = S2I*C1R + YR(I) = C2R + YI(I) = C2I + IF (KFLAG.GE.3) GO TO 130 + STR = DABS(C2R) + STI = DABS(C2I) + C2M = DMAX1(STR,STI) + IF (C2M.LE.ASCLE) GO TO 130 + KFLAG = KFLAG + 1 + ASCLE = BRY(KFLAG) + S1R = S1R*C1R + S1I = S1I*C1R + S2R = C2R + S2I = C2I + S1R = S1R*CSSR(KFLAG) + S1I = S1I*CSSR(KFLAG) + S2R = S2R*CSSR(KFLAG) + S2I = S2I*CSSR(KFLAG) + C1R = CSRR(KFLAG) + 130 CONTINUE + 180 CONTINUE + IF (MR.EQ.0) RETURN +C----------------------------------------------------------------------- +C ANALYTIC CONTINUATION FOR RE(Z).LT.0.0D0 +C----------------------------------------------------------------------- + NZ = 0 + FMR = DBLE(FLOAT(MR)) + SGN = -DSIGN(PI,FMR) +C----------------------------------------------------------------------- +C CSPN AND CSGN ARE COEFF OF K AND I FUNCIONS RESP. +C----------------------------------------------------------------------- + CSGNI = SGN + IF (YY.LE.0.0D0) CSGNI = -CSGNI + IFN = INU + N - 1 + ANG = FNF*SGN + CSPNR = DCOS(ANG) + CSPNI = DSIN(ANG) + IF (MOD(IFN,2).EQ.0) GO TO 190 + CSPNR = -CSPNR + CSPNI = -CSPNI + 190 CONTINUE +C----------------------------------------------------------------------- +C CS=COEFF OF THE J FUNCTION TO GET THE I FUNCTION. I(FNU,Z) IS +C COMPUTED FROM EXP(I*FNU*HPI)*J(FNU,-I*Z) WHERE Z IS IN THE FIRST +C QUADRANT. FOURTH QUADRANT VALUES (YY.LE.0.0E0) ARE COMPUTED BY +C CONJUGATION SINCE THE I FUNCTION IS REAL ON THE POSITIVE REAL AXIS +C----------------------------------------------------------------------- + CSR = SAR*CSGNI + CSI = CAR*CSGNI + IN = MOD(IFN,4) + 1 + C2R = CIPR(IN) + C2I = CIPI(IN) + STR = CSR*C2R + CSI*C2I + CSI = -CSR*C2I + CSI*C2R + CSR = STR + ASC = BRY(1) + IUF = 0 + KK = N + KDFLG = 1 + IB = IB - 1 + IC = IB - 1 + DO 290 K=1,N + FN = FNU + DBLE(FLOAT(KK-1)) +C----------------------------------------------------------------------- +C LOGIC TO SORT OUT CASES WHOSE PARAMETERS WERE SET FOR THE K +C FUNCTION ABOVE +C----------------------------------------------------------------------- + IF (N.GT.2) GO TO 175 + 172 CONTINUE + PHIDR = PHIR(J) + PHIDI = PHII(J) + ARGDR = ARGR(J) + ARGDI = ARGI(J) + ZET1DR = ZETA1R(J) + ZET1DI = ZETA1I(J) + ZET2DR = ZETA2R(J) + ZET2DI = ZETA2I(J) + ASUMDR = ASUMR(J) + ASUMDI = ASUMI(J) + BSUMDR = BSUMR(J) + BSUMDI = BSUMI(J) + J = 3 - J + GO TO 210 + 175 CONTINUE + IF ((KK.EQ.N).AND.(IB.LT.N)) GO TO 210 + IF ((KK.EQ.IB).OR.(KK.EQ.IC)) GO TO 172 + CALL ZUNHJ(ZNR, ZNI, FN, 0, TOL, PHIDR, PHIDI, ARGDR, + * ARGDI, ZET1DR, ZET1DI, ZET2DR, ZET2DI, ASUMDR, + * ASUMDI, BSUMDR, BSUMDI) + 210 CONTINUE + IF (KODE.EQ.1) GO TO 220 + STR = ZBR + ZET2DR + STI = ZBI + ZET2DI + RAST = FN/ZABS(CMPLX(STR,STI,kind=KIND(1.0D0))) + STR = STR*RAST*RAST + STI = -STI*RAST*RAST + S1R = -ZET1DR + STR + S1I = -ZET1DI + STI + GO TO 230 + 220 CONTINUE + S1R = -ZET1DR + ZET2DR + S1I = -ZET1DI + ZET2DI + 230 CONTINUE +C----------------------------------------------------------------------- +C TEST FOR UNDERFLOW AND OVERFLOW +C----------------------------------------------------------------------- + RS1 = S1R + IF (DABS(RS1).GT.ELIM) GO TO 280 + IF (KDFLG.EQ.1) IFLAG = 2 + IF (DABS(RS1).LT.ALIM) GO TO 240 +C----------------------------------------------------------------------- +C REFINE TEST AND SCALE +C----------------------------------------------------------------------- + APHI = ZABS(CMPLX(PHIDR,PHIDI,kind=KIND(1.0D0))) + AARG = ZABS(CMPLX(ARGDR,ARGDI,kind=KIND(1.0D0))) + RS1 = RS1 + DLOG(APHI) - 0.25D0*DLOG(AARG) - AIC + IF (DABS(RS1).GT.ELIM) GO TO 280 + IF (KDFLG.EQ.1) IFLAG = 1 + IF (RS1.LT.0.0D0) GO TO 240 + IF (KDFLG.EQ.1) IFLAG = 3 + 240 CONTINUE + CALL ZAIRY(ARGDR, ARGDI, 0, 2, AIR, AII, NAI, IDUM) + CALL ZAIRY(ARGDR, ARGDI, 1, 2, DAIR, DAII, NDAI, IDUM) + STR = DAIR*BSUMDR - DAII*BSUMDI + STI = DAIR*BSUMDI + DAII*BSUMDR + STR = STR + (AIR*ASUMDR-AII*ASUMDI) + STI = STI + (AIR*ASUMDI+AII*ASUMDR) + PTR = STR*PHIDR - STI*PHIDI + PTI = STR*PHIDI + STI*PHIDR + S2R = PTR*CSR - PTI*CSI + S2I = PTR*CSI + PTI*CSR + STR = DEXP(S1R)*CSSR(IFLAG) + S1R = STR*DCOS(S1I) + S1I = STR*DSIN(S1I) + STR = S2R*S1R - S2I*S1I + S2I = S2R*S1I + S2I*S1R + S2R = STR + IF (IFLAG.NE.1) GO TO 250 + CALL ZUCHK(S2R, S2I, NW, BRY(1), TOL) + IF (NW.EQ.0) GO TO 250 + S2R = ZEROR + S2I = ZEROI + 250 CONTINUE + IF (YY.LE.0.0D0) S2I = -S2I + CYR(KDFLG) = S2R + CYI(KDFLG) = S2I + C2R = S2R + C2I = S2I + S2R = S2R*CSRR(IFLAG) + S2I = S2I*CSRR(IFLAG) +C----------------------------------------------------------------------- +C ADD I AND K FUNCTIONS, K SEQUENCE IN Y(I), I=1,N +C----------------------------------------------------------------------- + S1R = YR(KK) + S1I = YI(KK) + IF (KODE.EQ.1) GO TO 270 + CALL ZS1S2(ZRR, ZRI, S1R, S1I, S2R, S2I, NW, ASC, ALIM, IUF) + NZ = NZ + NW + 270 CONTINUE + YR(KK) = S1R*CSPNR - S1I*CSPNI + S2R + YI(KK) = S1R*CSPNI + S1I*CSPNR + S2I + KK = KK - 1 + CSPNR = -CSPNR + CSPNI = -CSPNI + STR = CSI + CSI = -CSR + CSR = STR + IF (C2R.NE.0.0D0 .OR. C2I.NE.0.0D0) GO TO 255 + KDFLG = 1 + GO TO 290 + 255 CONTINUE + IF (KDFLG.EQ.2) GO TO 295 + KDFLG = 2 + GO TO 290 + 280 CONTINUE + IF (RS1.GT.0.0D0) GO TO 320 + S2R = ZEROR + S2I = ZEROI + GO TO 250 + 290 CONTINUE + K = N + 295 CONTINUE + IL = N - K + IF (IL.EQ.0) RETURN +C----------------------------------------------------------------------- +C RECUR BACKWARD FOR REMAINDER OF I SEQUENCE AND ADD IN THE +C K FUNCTIONS, SCALING THE I SEQUENCE DURING RECURRENCE TO KEEP +C INTERMEDIATE ARITHMETIC ON SCALE NEAR EXPONENT EXTREMES. +C----------------------------------------------------------------------- + S1R = CYR(1) + S1I = CYI(1) + S2R = CYR(2) + S2I = CYI(2) + CSR = CSRR(IFLAG) + ASCLE = BRY(IFLAG) + FN = DBLE(FLOAT(INU+IL)) + DO 310 I=1,IL + C2R = S2R + C2I = S2I + S2R = S1R + (FN+FNF)*(RZR*C2R-RZI*C2I) + S2I = S1I + (FN+FNF)*(RZR*C2I+RZI*C2R) + S1R = C2R + S1I = C2I + FN = FN - 1.0D0 + C2R = S2R*CSR + C2I = S2I*CSR + CKR = C2R + CKI = C2I + C1R = YR(KK) + C1I = YI(KK) + IF (KODE.EQ.1) GO TO 300 + CALL ZS1S2(ZRR, ZRI, C1R, C1I, C2R, C2I, NW, ASC, ALIM, IUF) + NZ = NZ + NW + 300 CONTINUE + YR(KK) = C1R*CSPNR - C1I*CSPNI + C2R + YI(KK) = C1R*CSPNI + C1I*CSPNR + C2I + KK = KK - 1 + CSPNR = -CSPNR + CSPNI = -CSPNI + IF (IFLAG.GE.3) GO TO 310 + C2R = DABS(CKR) + C2I = DABS(CKI) + C2M = DMAX1(C2R,C2I) + IF (C2M.LE.ASCLE) GO TO 310 + IFLAG = IFLAG + 1 + ASCLE = BRY(IFLAG) + S1R = S1R*CSR + S1I = S1I*CSR + S2R = CKR + S2I = CKI + S1R = S1R*CSSR(IFLAG) + S1I = S1I*CSSR(IFLAG) + S2R = S2R*CSSR(IFLAG) + S2I = S2I*CSSR(IFLAG) + CSR = CSRR(IFLAG) + 310 CONTINUE + RETURN + 320 CONTINUE + NZ = -1 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zuoik.f b/mathext/internal/amos/amoslib/zuoik.f new file mode 100644 index 00000000..3715d6d4 --- /dev/null +++ b/mathext/internal/amos/amoslib/zuoik.f @@ -0,0 +1,194 @@ + SUBROUTINE ZUOIK(ZR, ZI, FNU, KODE, IKFLG, N, YR, YI, NUF, TOL, + * ELIM, ALIM) +C***BEGIN PROLOGUE ZUOIK +C***REFER TO ZBESI,ZBESK,ZBESH +C +C ZUOIK COMPUTES THE LEADING TERMS OF THE UNIFORM ASYMPTOTIC +C EXPANSIONS FOR THE I AND K FUNCTIONS AND COMPARES THEM +C (IN LOGARITHMIC FORM) TO ALIM AND ELIM FOR OVER AND UNDERFLOW +C WHERE ALIM.LT.ELIM. IF THE MAGNITUDE, BASED ON THE LEADING +C EXPONENTIAL, IS LESS THAN ALIM OR GREATER THAN -ALIM, THEN +C THE RESULT IS ON SCALE. IF NOT, THEN A REFINED TEST USING OTHER +C MULTIPLIERS (IN LOGARITHMIC FORM) IS MADE BASED ON ELIM. HERE +C EXP(-ELIM)=SMALLEST MACHINE NUMBER*1.0E+3 AND EXP(-ALIM)= +C EXP(-ELIM)/TOL +C +C IKFLG=1 MEANS THE I SEQUENCE IS TESTED +C =2 MEANS THE K SEQUENCE IS TESTED +C NUF = 0 MEANS THE LAST MEMBER OF THE SEQUENCE IS ON SCALE +C =-1 MEANS AN OVERFLOW WOULD OCCUR +C IKFLG=1 AND NUF.GT.0 MEANS THE LAST NUF Y VALUES WERE SET TO ZERO +C THE FIRST N-NUF VALUES MUST BE SET BY ANOTHER ROUTINE +C IKFLG=2 AND NUF.EQ.N MEANS ALL Y VALUES WERE SET TO ZERO +C IKFLG=2 AND 0.LT.NUF.LT.N NOT CONSIDERED. Y MUST BE SET BY +C ANOTHER ROUTINE +C +C***ROUTINES CALLED ZUCHK,ZUNHJ,ZUNIK,D1MACH,ZABS,ZLOG +C***END PROLOGUE ZUOIK +C COMPLEX ARG,ASUM,BSUM,CWRK,CZ,CZERO,PHI,SUM,Y,Z,ZB,ZETA1,ZETA2,ZN, +C *ZR + DOUBLE PRECISION AARG, AIC, ALIM, APHI, ARGI, ARGR, ASUMI, ASUMR, + * ASCLE, AX, AY, BSUMI, BSUMR, CWRKI, CWRKR, CZI, CZR, ELIM, FNN, + * FNU, GNN, GNU, PHII, PHIR, RCZ, STR, STI, SUMI, SUMR, TOL, YI, + * YR, ZBI, ZBR, ZEROI, ZEROR, ZETA1I, ZETA1R, ZETA2I, ZETA2R, ZI, + * ZNI, ZNR, ZR, ZRI, ZRR, D1MACH, ZABS + INTEGER I, IDUM, IFORM, IKFLG, INIT, KODE, N, NN, NUF, NW + DIMENSION YR(N), YI(N), CWRKR(16), CWRKI(16) + DATA ZEROR,ZEROI / 0.0D0, 0.0D0 / + DATA AIC / 1.265512123484645396D+00 / + NUF = 0 + NN = N + ZRR = ZR + ZRI = ZI + IF (ZR.GE.0.0D0) GO TO 10 + ZRR = -ZR + ZRI = -ZI + 10 CONTINUE + ZBR = ZRR + ZBI = ZRI + AX = DABS(ZR)*1.7321D0 + AY = DABS(ZI) + IFORM = 1 + IF (AY.GT.AX) IFORM = 2 + GNU = DMAX1(FNU,1.0D0) + IF (IKFLG.EQ.1) GO TO 20 + FNN = DBLE(FLOAT(NN)) + GNN = FNU + FNN - 1.0D0 + GNU = DMAX1(GNN,FNN) + 20 CONTINUE +C----------------------------------------------------------------------- +C ONLY THE MAGNITUDE OF ARG AND PHI ARE NEEDED ALONG WITH THE +C REAL PARTS OF ZETA1, ZETA2 AND ZB. NO ATTEMPT IS MADE TO GET +C THE SIGN OF THE IMAGINARY PART CORRECT. +C----------------------------------------------------------------------- + IF (IFORM.EQ.2) GO TO 30 + INIT = 0 + CALL ZUNIK(ZRR, ZRI, GNU, IKFLG, 1, TOL, INIT, PHIR, PHII, + * ZETA1R, ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) + CZR = -ZETA1R + ZETA2R + CZI = -ZETA1I + ZETA2I + GO TO 50 + 30 CONTINUE + ZNR = ZRI + ZNI = -ZRR + IF (ZI.GT.0.0D0) GO TO 40 + ZNR = -ZNR + 40 CONTINUE + CALL ZUNHJ(ZNR, ZNI, GNU, 1, TOL, PHIR, PHII, ARGR, ARGI, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) + CZR = -ZETA1R + ZETA2R + CZI = -ZETA1I + ZETA2I + AARG = ZABS(CMPLX(ARGR,ARGI,kind=KIND(1.0D0))) + 50 CONTINUE + IF (KODE.EQ.1) GO TO 60 + CZR = CZR - ZBR + CZI = CZI - ZBI + 60 CONTINUE + IF (IKFLG.EQ.1) GO TO 70 + CZR = -CZR + CZI = -CZI + 70 CONTINUE + APHI = ZABS(CMPLX(PHIR,PHII,kind=KIND(1.0D0))) + RCZ = CZR +C----------------------------------------------------------------------- +C OVERFLOW TEST +C----------------------------------------------------------------------- + IF (RCZ.GT.ELIM) GO TO 210 + IF (RCZ.LT.ALIM) GO TO 80 + RCZ = RCZ + DLOG(APHI) + IF (IFORM.EQ.2) RCZ = RCZ - 0.25D0*DLOG(AARG) - AIC + IF (RCZ.GT.ELIM) GO TO 210 + GO TO 130 + 80 CONTINUE +C----------------------------------------------------------------------- +C UNDERFLOW TEST +C----------------------------------------------------------------------- + IF (RCZ.LT.(-ELIM)) GO TO 90 + IF (RCZ.GT.(-ALIM)) GO TO 130 + RCZ = RCZ + DLOG(APHI) + IF (IFORM.EQ.2) RCZ = RCZ - 0.25D0*DLOG(AARG) - AIC + IF (RCZ.GT.(-ELIM)) GO TO 110 + 90 CONTINUE + DO 100 I=1,NN + YR(I) = ZEROR + YI(I) = ZEROI + 100 CONTINUE + NUF = NN + RETURN + 110 CONTINUE + ASCLE = 1.0D+3*D1MACH(1)/TOL + CALL ZLOG(PHIR, PHII, STR, STI, IDUM) + CZR = CZR + STR + CZI = CZI + STI + IF (IFORM.EQ.1) GO TO 120 + CALL ZLOG(ARGR, ARGI, STR, STI, IDUM) + CZR = CZR - 0.25D0*STR - AIC + CZI = CZI - 0.25D0*STI + 120 CONTINUE + AX = DEXP(RCZ)/TOL + AY = CZI + CZR = AX*DCOS(AY) + CZI = AX*DSIN(AY) + CALL ZUCHK(CZR, CZI, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 90 + 130 CONTINUE + IF (IKFLG.EQ.2) RETURN + IF (N.EQ.1) RETURN +C----------------------------------------------------------------------- +C SET UNDERFLOWS ON I SEQUENCE +C----------------------------------------------------------------------- + 140 CONTINUE + GNU = FNU + DBLE(FLOAT(NN-1)) + IF (IFORM.EQ.2) GO TO 150 + INIT = 0 + CALL ZUNIK(ZRR, ZRI, GNU, IKFLG, 1, TOL, INIT, PHIR, PHII, + * ZETA1R, ZETA1I, ZETA2R, ZETA2I, SUMR, SUMI, CWRKR, CWRKI) + CZR = -ZETA1R + ZETA2R + CZI = -ZETA1I + ZETA2I + GO TO 160 + 150 CONTINUE + CALL ZUNHJ(ZNR, ZNI, GNU, 1, TOL, PHIR, PHII, ARGR, ARGI, ZETA1R, + * ZETA1I, ZETA2R, ZETA2I, ASUMR, ASUMI, BSUMR, BSUMI) + CZR = -ZETA1R + ZETA2R + CZI = -ZETA1I + ZETA2I + AARG = ZABS(CMPLX(ARGR,ARGI,kind=KIND(1.0D0))) + 160 CONTINUE + IF (KODE.EQ.1) GO TO 170 + CZR = CZR - ZBR + CZI = CZI - ZBI + 170 CONTINUE + APHI = ZABS(CMPLX(PHIR,PHII,kind=KIND(1.0D0))) + RCZ = CZR + IF (RCZ.LT.(-ELIM)) GO TO 180 + IF (RCZ.GT.(-ALIM)) RETURN + RCZ = RCZ + DLOG(APHI) + IF (IFORM.EQ.2) RCZ = RCZ - 0.25D0*DLOG(AARG) - AIC + IF (RCZ.GT.(-ELIM)) GO TO 190 + 180 CONTINUE + YR(NN) = ZEROR + YI(NN) = ZEROI + NN = NN - 1 + NUF = NUF + 1 + IF (NN.EQ.0) RETURN + GO TO 140 + 190 CONTINUE + ASCLE = 1.0D+3*D1MACH(1)/TOL + CALL ZLOG(PHIR, PHII, STR, STI, IDUM) + CZR = CZR + STR + CZI = CZI + STI + IF (IFORM.EQ.1) GO TO 200 + CALL ZLOG(ARGR, ARGI, STR, STI, IDUM) + CZR = CZR - 0.25D0*STR - AIC + CZI = CZI - 0.25D0*STI + 200 CONTINUE + AX = DEXP(RCZ)/TOL + AY = CZI + CZR = AX*DCOS(AY) + CZI = AX*DSIN(AY) + CALL ZUCHK(CZR, CZI, NW, ASCLE, TOL) + IF (NW.NE.0) GO TO 180 + RETURN + 210 CONTINUE + NUF = -1 + RETURN + END diff --git a/mathext/internal/amos/amoslib/zwrsk.f b/mathext/internal/amos/amoslib/zwrsk.f new file mode 100644 index 00000000..37cb8d8c --- /dev/null +++ b/mathext/internal/amos/amoslib/zwrsk.f @@ -0,0 +1,94 @@ + SUBROUTINE ZWRSK(ZRR, ZRI, FNU, KODE, N, YR, YI, NZ, CWR, CWI, + * TOL, ELIM, ALIM) +C***BEGIN PROLOGUE ZWRSK +C***REFER TO ZBESI,ZBESK +C +C ZWRSK COMPUTES THE I BESSEL FUNCTION FOR RE(Z).GE.0.0 BY +C NORMALIZING THE I FUNCTION RATIOS FROM ZRATI BY THE WRONSKIAN +C +C***ROUTINES CALLED D1MACH,ZBKNU,ZRATI,ZABS +C***END PROLOGUE ZWRSK +C COMPLEX CINU,CSCL,CT,CW,C1,C2,RCT,ST,Y,ZR + DOUBLE PRECISION ACT, ACW, ALIM, ASCLE, CINUI, CINUR, CSCLR, CTI, + * CTR, CWI, CWR, C1I, C1R, C2I, C2R, ELIM, FNU, PTI, PTR, RACT, + * STI, STR, TOL, YI, YR, ZRI, ZRR, ZABS, D1MACH + INTEGER I, KODE, N, NW, NZ + DIMENSION YR(N), YI(N), CWR(2), CWI(2) +C----------------------------------------------------------------------- +C I(FNU+I-1,Z) BY BACKWARD RECURRENCE FOR RATIOS +C Y(I)=I(FNU+I,Z)/I(FNU+I-1,Z) FROM CRATI NORMALIZED BY THE +C WRONSKIAN WITH K(FNU,Z) AND K(FNU+1,Z) FROM CBKNU. +C----------------------------------------------------------------------- + NZ = 0 + CALL ZBKNU(ZRR, ZRI, FNU, KODE, 2, CWR, CWI, NW, TOL, ELIM, ALIM) + IF (NW.NE.0) GO TO 50 + CALL ZRATI(ZRR, ZRI, FNU, N, YR, YI, TOL) +C----------------------------------------------------------------------- +C RECUR FORWARD ON I(FNU+1,Z) = R(FNU,Z)*I(FNU,Z), +C R(FNU+J-1,Z)=Y(J), J=1,...,N +C----------------------------------------------------------------------- + CINUR = 1.0D0 + CINUI = 0.0D0 + IF (KODE.EQ.1) GO TO 10 + CINUR = DCOS(ZRI) + CINUI = DSIN(ZRI) + 10 CONTINUE +C----------------------------------------------------------------------- +C ON LOW EXPONENT MACHINES THE K FUNCTIONS CAN BE CLOSE TO BOTH +C THE UNDER AND OVERFLOW LIMITS AND THE NORMALIZATION MUST BE +C SCALED TO PREVENT OVER OR UNDERFLOW. CUOIK HAS DETERMINED THAT +C THE RESULT IS ON SCALE. +C----------------------------------------------------------------------- + ACW = ZABS(CMPLX(CWR(2),CWI(2),kind=KIND(1.0D0))) + ASCLE = 1.0D+3*D1MACH(1)/TOL + CSCLR = 1.0D0 + IF (ACW.GT.ASCLE) GO TO 20 + CSCLR = 1.0D0/TOL + GO TO 30 + 20 CONTINUE + ASCLE = 1.0D0/ASCLE + IF (ACW.LT.ASCLE) GO TO 30 + CSCLR = TOL + 30 CONTINUE + C1R = CWR(1)*CSCLR + C1I = CWI(1)*CSCLR + C2R = CWR(2)*CSCLR + C2I = CWI(2)*CSCLR + STR = YR(1) + STI = YI(1) +C----------------------------------------------------------------------- +C CINU=CINU*(CONJG(CT)/CABS(CT))*(1.0D0/CABS(CT) PREVENTS +C UNDER- OR OVERFLOW PREMATURELY BY SQUARING CABS(CT) +C----------------------------------------------------------------------- + PTR = STR*C1R - STI*C1I + PTI = STR*C1I + STI*C1R + PTR = PTR + C2R + PTI = PTI + C2I + CTR = ZRR*PTR - ZRI*PTI + CTI = ZRR*PTI + ZRI*PTR + ACT = ZABS(CMPLX(CTR,CTI,kind=KIND(1.0D0))) + RACT = 1.0D0/ACT + CTR = CTR*RACT + CTI = -CTI*RACT + PTR = CINUR*RACT + PTI = CINUI*RACT + CINUR = PTR*CTR - PTI*CTI + CINUI = PTR*CTI + PTI*CTR + YR(1) = CINUR*CSCLR + YI(1) = CINUI*CSCLR + IF (N.EQ.1) RETURN + DO 40 I=2,N + PTR = STR*CINUR - STI*CINUI + CINUI = STR*CINUI + STI*CINUR + CINUR = PTR + STR = YR(I) + STI = YI(I) + YR(I) = CINUR*CSCLR + YI(I) = CINUI*CSCLR + 40 CONTINUE + RETURN + 50 CONTINUE + NZ = -1 + IF(NW.EQ.(-2)) NZ=-2 + RETURN + END diff --git a/mathext/internal/amos/origcode_test.go b/mathext/internal/amos/origcode_test.go new file mode 100644 index 00000000..d1129917 --- /dev/null +++ b/mathext/internal/amos/origcode_test.go @@ -0,0 +1,2276 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package amos + +import ( + "math" + "math/cmplx" +) + +// These routines are the versions directly modified from the Fortran code. +// They are used to ensure that code style improvements do not change the +// code output. + +func iabs(a int) int { + if a >= 0 { + return a + } + return -a +} + +func min0(a, b int) int { + if a < b { + return a + } + return b +} + +func max0(a, b int) int { + if a > b { + return a + } + return b +} + +func zairyOrig(ZR, ZI float64, ID, KODE int) (AIR, AII float64, NZ int) { + // zairy is adapted from the original Netlib code by Donald Amos. + // http://www.netlib.no/netlib/amos/zairy.f + + // Original comment: + /* + C***BEGIN PROLOGUE ZAIRY + C***DATE WRITTEN 830501 (YYMMDD) + C***REVISION DATE 890801 (YYMMDD) + C***CATEGORY NO. B5K + C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD + C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES + C***PURPOSE TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z + C***DESCRIPTION + C + C ***A DOUBLE PRECISION ROUTINE*** + C ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR + C ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON + C KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)* + C DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN + C -PI/31.0 FROM THE K BESSEL + C FUNCTIONS BY + C + C AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA) + C C=1.0/(PI*SQRT(3.0)) + C ZTA=(2/3)*Z**(3/2) + C + C WITH THE POWER SERIES FOR CABS(Z)<=1.0. + C + C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE- + C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES + C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF + C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR), + C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR + C FLAG IERR=3 IS TRIGGERED WHERE UR=dmax(dmach[4),1.0D-18) IS + C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION. + C ALSO, if THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN + C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT + C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE + C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA + C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2, + C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE + C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE + C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT- + C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG- + C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN + C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN + C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES, + C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE + C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER + C MACHINES. + C + C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX + C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT + C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE- + C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE + C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))), + C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF + C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY + C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN + C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY + C SEVERAL ORDERS OF MAGNITUDE. if ONE COMPONENT IS 10**K LARGER + C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K, + C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS + C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER + C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY + C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER + C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE + C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES, + C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P, + C OR -PI/2+P. + C + C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ + C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF + C COMMERCE, 1955. + C + C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT + C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983 + C + C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX + C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85- + C 1018, MAY, 1985 + C + C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX + C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS. + C MATH. SOFTWARE, 1986 + */ + var AI, CONE, CSQ, CY, S1, S2, TRM1, TRM2, Z, ZTA, Z3 complex128 + var AA, AD, AK, ALIM, ATRM, AZ, AZ3, BK, + CC, CK, COEF, CONEI, CONER, CSQI, CSQR, C1, C2, DIG, + DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR, + S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI, + ZEROR, ZTAI, ZTAR, Z3I, Z3R, ALAZ, BB float64 + var IERR, IFLAG, K, K1, K2, MR, NN int + var tmp complex128 + + // Extra element for padding. + CYR := []float64{math.NaN(), 0} + CYI := []float64{math.NaN(), 0} + + _ = AI + _ = CONE + _ = CSQ + _ = CY + _ = S1 + _ = S2 + _ = TRM1 + _ = TRM2 + _ = Z + _ = ZTA + _ = Z3 + + TTH = 6.66666666666666667E-01 + C1 = 3.55028053887817240E-01 + C2 = 2.58819403792806799E-01 + COEF = 1.83776298473930683E-01 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + NZ = 0 + if ID < 0 || ID > 1 { + IERR = 1 + } + if KODE < 1 || KODE > 2 { + IERR = 1 + } + if IERR != 0 { + return + } + AZ = zabs(complex(ZR, ZI)) + TOL = dmax(dmach[4], 1.0E-18) + FID = float64(ID) + if AZ > 1.0E0 { + goto Seventy + } + + // POWER SERIES FOR CABS(Z)<=1. + S1R = CONER + S1I = CONEI + S2R = CONER + S2I = CONEI + if AZ < TOL { + goto OneSeventy + } + AA = AZ * AZ + if AA < TOL/AZ { + goto Fourty + } + TRM1R = CONER + TRM1I = CONEI + TRM2R = CONER + TRM2I = CONEI + ATRM = 1.0E0 + STR = ZR*ZR - ZI*ZI + STI = ZR*ZI + ZI*ZR + Z3R = STR*ZR - STI*ZI + Z3I = STR*ZI + STI*ZR + AZ3 = AZ * AA + AK = 2.0E0 + FID + BK = 3.0E0 - FID - FID + CK = 4.0E0 - FID + DK = 3.0E0 + FID + FID + D1 = AK * DK + D2 = BK * CK + AD = dmin(D1, D2) + AK = 24.0E0 + 9.0E0*FID + BK = 30.0E0 - 9.0E0*FID + for K = 1; K <= 25; K++ { + STR = (TRM1R*Z3R - TRM1I*Z3I) / D1 + TRM1I = (TRM1R*Z3I + TRM1I*Z3R) / D1 + TRM1R = STR + S1R = S1R + TRM1R + S1I = S1I + TRM1I + STR = (TRM2R*Z3R - TRM2I*Z3I) / D2 + TRM2I = (TRM2R*Z3I + TRM2I*Z3R) / D2 + TRM2R = STR + S2R = S2R + TRM2R + S2I = S2I + TRM2I + ATRM = ATRM * AZ3 / AD + D1 = D1 + AK + D2 = D2 + BK + AD = dmin(D1, D2) + if ATRM < TOL*AD { + goto Fourty + } + AK = AK + 18.0E0 + BK = BK + 18.0E0 + } +Fourty: + if ID == 1 { + goto Fifty + } + AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I) + AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R) + if KODE == 1 { + return + } + tmp = zsqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + ZTAR = TTH * (ZR*STR - ZI*STI) + ZTAI = TTH * (ZR*STI + ZI*STR) + tmp = zexp(complex(ZTAR, ZTAI)) + STR = real(tmp) + STI = imag(tmp) + PTR = AIR*STR - AII*STI + AII = AIR*STI + AII*STR + AIR = PTR + return + +Fifty: + AIR = -S2R * C2 + AII = -S2I * C2 + if AZ <= TOL { + goto Sixty + } + STR = ZR*S1R - ZI*S1I + STI = ZR*S1I + ZI*S1R + CC = C1 / (1.0E0 + FID) + AIR = AIR + CC*(STR*ZR-STI*ZI) + AII = AII + CC*(STR*ZI+STI*ZR) + +Sixty: + if KODE == 1 { + return + } + tmp = zsqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + ZTAR = TTH * (ZR*STR - ZI*STI) + ZTAI = TTH * (ZR*STI + ZI*STR) + tmp = zexp(complex(ZTAR, ZTAI)) + STR = real(tmp) + STI = imag(tmp) + PTR = STR*AIR - STI*AII + AII = STR*AII + STI*AIR + AIR = PTR + return + + // CASE FOR CABS(Z)>1.0. +Seventy: + FNU = (1.0E0 + FID) / 3.0E0 + + /* + SET PARAMETERS RELATED TO MACHINE CONSTANTS. + TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18. + ELIM IS THE APPROXIMATE EXPONENTIAL OVER-&&UNDERFLOW LIMIT. + EXP(-ELIM)EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR + UNDERFLOW&&OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE. + RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LA>=Z. + DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG). + */ + K1 = imach[15] + K2 = imach[16] + R1M5 = dmach[5] + + K = min0(iabs(K1), iabs(K2)) + ELIM = 2.303E0 * (float64(K)*R1M5 - 3.0E0) + K1 = imach[14] - 1 + AA = R1M5 * float64(K1) + DIG = dmin(AA, 18.0E0) + AA = AA * 2.303E0 + ALIM = ELIM + dmax(-AA, -41.45E0) + RL = 1.2E0*DIG + 3.0E0 + ALAZ = dlog(AZ) + + // TEST FOR PROPER RANGE. + AA = 0.5E0 / TOL + BB = float64(float32(imach[9])) * 0.5E0 + AA = dmin(AA, BB) + AA = math.Pow(AA, TTH) + if AZ > AA { + goto TwoSixty + } + AA = dsqrt(AA) + if AZ > AA { + IERR = 3 + } + tmp = zsqrt(complex(ZR, ZI)) + CSQR = real(tmp) + CSQI = imag(tmp) + ZTAR = TTH * (ZR*CSQR - ZI*CSQI) + ZTAI = TTH * (ZR*CSQI + ZI*CSQR) + + // RE(ZTA)<=0 WHEN RE(Z)<0, ESPECIALLY WHEN IM(Z) IS SMALL. + IFLAG = 0 + SFAC = 1.0E0 + AK = ZTAI + if ZR >= 0.0E0 { + goto Eighty + } + BK = ZTAR + CK = -dabs(BK) + ZTAR = CK + ZTAI = AK + +Eighty: + if ZI != 0.0E0 { + goto Ninety + } + if ZR > 0.0E0 { + goto Ninety + } + ZTAR = 0.0E0 + ZTAI = AK +Ninety: + AA = ZTAR + if AA >= 0.0E0 && ZR > 0.0E0 { + goto OneTen + } + if KODE == 2 { + goto OneHundred + } + + // OVERFLOW TEST. + if AA > (-ALIM) { + goto OneHundred + } + AA = -AA + 0.25E0*ALAZ + IFLAG = 1 + SFAC = TOL + if AA > ELIM { + goto TwoSeventy + } + +OneHundred: + // CBKNU AND CACON return EXP(ZTA)*K(FNU,ZTA) ON KODE=2. + MR = 1 + if ZI < 0.0E0 { + MR = -1 + } + ZTAR, ZTAI, FNU, KODE, MR, _, CYR, CYI, NN, RL, TOL, ELIM, ALIM = zacaiOrig(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, NN, RL, TOL, ELIM, ALIM) + if NN < 0 { + goto TwoEighty + } + NZ = NZ + NN + goto OneThirty + +OneTen: + if KODE == 2 { + goto OneTwenty + } + + // UNDERFLOW TEST. + if AA < ALIM { + goto OneTwenty + } + AA = -AA - 0.25E0*ALAZ + IFLAG = 2 + SFAC = 1.0E0 / TOL + if AA < (-ELIM) { + goto TwoTen + } +OneTwenty: + ZTAR, ZTAI, FNU, KODE, _, CYR, CYI, NZ, TOL, ELIM, ALIM = zbknuOrig(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, TOL, ELIM, ALIM) + +OneThirty: + S1R = CYR[1] * COEF + S1I = CYI[1] * COEF + if IFLAG != 0 { + goto OneFifty + } + if ID == 1 { + goto OneFourty + } + AIR = CSQR*S1R - CSQI*S1I + AII = CSQR*S1I + CSQI*S1R + return +OneFourty: + AIR = -(ZR*S1R - ZI*S1I) + AII = -(ZR*S1I + ZI*S1R) + return +OneFifty: + S1R = S1R * SFAC + S1I = S1I * SFAC + if ID == 1 { + goto OneSixty + } + STR = S1R*CSQR - S1I*CSQI + S1I = S1R*CSQI + S1I*CSQR + S1R = STR + AIR = S1R / SFAC + AII = S1I / SFAC + return +OneSixty: + STR = -(S1R*ZR - S1I*ZI) + S1I = -(S1R*ZI + S1I*ZR) + S1R = STR + AIR = S1R / SFAC + AII = S1I / SFAC + return +OneSeventy: + AA = 1.0E+3 * dmach[1] + S1R = ZEROR + S1I = ZEROI + if ID == 1 { + goto OneNinety + } + if AZ <= AA { + goto OneEighty + } + S1R = C2 * ZR + S1I = C2 * ZI +OneEighty: + AIR = C1 - S1R + AII = -S1I + return +OneNinety: + AIR = -C2 + AII = 0.0E0 + AA = dsqrt(AA) + if AZ <= AA { + goto TwoHundred + } + S1R = 0.5E0 * (ZR*ZR - ZI*ZI) + S1I = ZR * ZI +TwoHundred: + AIR = AIR + C1*S1R + AII = AII + C1*S1I + return +TwoTen: + NZ = 1 + AIR = ZEROR + AII = ZEROI + return +TwoSeventy: + NZ = 0 + IERR = 2 + return +TwoEighty: + if NN == (-1) { + goto TwoSeventy + } + NZ = 0 + IERR = 5 + return +TwoSixty: + IERR = 4 + NZ = 0 + return +} + +// sbknu computes the k bessel function in the right half z plane. +func zbknuOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) (ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + /* Old dimension comment. + DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2), + * CYI(2) + */ + + // TOOD(btracey): Find which of these are inputs/outputs/both and clean up + // the function call. + // YR and YI have length n (but n+1 with better indexing) + var AA, AK, ASCLE, A1, A2, BB, BK, CAZ, + CBI, CBR, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER, + CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CTWOR, + CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ETEST, FC, FHS, + FI, FK, FKS, FMUI, FMUR, FPI, FR, G1, G2, HPI, PI, PR, PTI, + PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI, + RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM, + TTH, T1, T2, ELM, CELMR, ZDR, ZDI, AS, ALAS, HELIM float64 + + var I, IFLAG, INU, K, KFLAG, KK, KMAX, KODED, IDUM, J, IC, INUB, NW int + + var tmp complex128 + var CSSR, CSRR, BRY [4]float64 + var CYR, CYI [3]float64 + + KMAX = 30 + CZEROR = 0 + CZEROI = 0 + CONER = 1 + CONEI = 0 + CTWOR = 2 + R1 = 2 + + DPI = 3.14159265358979324E0 + RTHPI = 1.25331413731550025E0 + SPI = 1.90985931710274403E0 + HPI = 1.57079632679489662E0 + FPI = 1.89769999331517738E0 + TTH = 6.66666666666666666E-01 + + CC := [9]float64{math.NaN(), 5.77215664901532861E-01, -4.20026350340952355E-02, + -4.21977345555443367E-02, 7.21894324666309954E-03, + -2.15241674114950973E-04, -2.01348547807882387E-05, + 1.13302723198169588E-06, 6.11609510448141582E-09} + + CAZ = zabs(complex(ZR, ZI)) + CSCLR = 1.0E0 / TOL + CRSCR = TOL + CSSR[1] = CSCLR + CSSR[2] = 1.0E0 + CSSR[3] = CRSCR + CSRR[1] = CRSCR + CSRR[2] = 1.0E0 + CSRR[3] = CSCLR + BRY[1] = 1.0E+3 * dmach[1] / TOL + BRY[2] = 1.0E0 / BRY[1] + BRY[3] = dmach[2] + NZ = 0 + IFLAG = 0 + KODED = KODE + RCAZ = 1.0E0 / CAZ + STR = ZR * RCAZ + STI = -ZI * RCAZ + RZR = (STR + STR) * RCAZ + RZI = (STI + STI) * RCAZ + INU = int(float32(FNU + 0.5)) + DNU = FNU - float64(INU) + if dabs(DNU) == 0.5E0 { + goto OneTen + } + DNU2 = 0.0E0 + if dabs(DNU) > TOL { + DNU2 = DNU * DNU + } + if CAZ > R1 { + goto OneTen + } + + // SERIES FOR CABS(Z)<=R1. + FC = 1.0E0 + tmp = zlog(complex(RZR, RZI)) + SMUR = real(tmp) + SMUI = imag(tmp) + FMUR = SMUR * DNU + FMUI = SMUI * DNU + FMUR, FMUI, CSHR, CSHI, CCHR, CCHI = zshchOrig(FMUR, FMUI, CSHR, CSHI, CCHR, CCHI) + if DNU == 0.0E0 { + goto Ten + } + FC = DNU * DPI + FC = FC / dsin(FC) + SMUR = CSHR / DNU + SMUI = CSHI / DNU +Ten: + A2 = 1.0E0 + DNU + + // GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU). + T2 = dexp(-dgamln(A2, IDUM)) + T1 = 1.0E0 / (T2 * FC) + if dabs(DNU) > 0.1E0 { + goto Fourty + } + + // SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU). + AK = 1.0E0 + S = CC[1] + for K = 2; K <= 8; K++ { + AK = AK * DNU2 + TM = CC[K] * AK + S = S + TM + if dabs(TM) < TOL { + goto Thirty + } + } +Thirty: + G1 = -S + goto Fifty +Fourty: + G1 = (T1 - T2) / (DNU + DNU) +Fifty: + G2 = (T1 + T2) * 0.5E0 + FR = FC * (CCHR*G1 + SMUR*G2) + FI = FC * (CCHI*G1 + SMUI*G2) + tmp = zexp(complex(FMUR, FMUI)) + STR = real(tmp) + STI = imag(tmp) + PR = 0.5E0 * STR / T2 + PI = 0.5E0 * STI / T2 + tmp = zdiv(complex(0.5, 0), complex(STR, STI)) + PTR = real(tmp) + PTI = imag(tmp) + QR = PTR / T1 + QI = PTI / T1 + S1R = FR + S1I = FI + S2R = PR + S2I = PI + AK = 1.0E0 + A1 = 1.0E0 + CKR = CONER + CKI = CONEI + BK = 1.0E0 - DNU2 + if INU > 0 || N > 1 { + goto Eighty + } + + // GENERATE K(FNU,Z), 0.0E0 <= FNU < 0.5E0 AND N=1. + if CAZ < TOL { + goto Seventy + } + tmp = zmlt(complex(ZR, ZI), complex(ZR, ZI)) + CZR = real(tmp) + CZI = imag(tmp) + CZR = 0.25E0 * CZR + CZI = 0.25E0 * CZI + T1 = 0.25E0 * CAZ * CAZ +Sixty: + FR = (FR*AK + PR + QR) / BK + FI = (FI*AK + PI + QI) / BK + STR = 1.0E0 / (AK - DNU) + PR = PR * STR + PI = PI * STR + STR = 1.0E0 / (AK + DNU) + QR = QR * STR + QI = QI * STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0E0 / AK + CKI = (CKR*CZI + CKI*CZR) * RAK + CKR = STR * RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + A1 = A1 * T1 * RAK + BK = BK + AK + AK + 1.0E0 + AK = AK + 1.0E0 + if A1 > TOL { + goto Sixty + } +Seventy: + YR[1] = S1R + YI[1] = S1I + if KODED == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + tmp = zexp(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = zmlt(complex(S1R, S1I), complex(STR, STI)) + YR[1] = real(tmp) + YI[1] = imag(tmp) + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE. +Eighty: + if CAZ < TOL { + goto OneHundred + } + tmp = zmlt(complex(ZR, ZI), complex(ZR, ZI)) + CZR = real(tmp) + CZI = imag(tmp) + CZR = 0.25E0 * CZR + CZI = 0.25E0 * CZI + T1 = 0.25E0 * CAZ * CAZ +Ninety: + FR = (FR*AK + PR + QR) / BK + FI = (FI*AK + PI + QI) / BK + STR = 1.0E0 / (AK - DNU) + PR = PR * STR + PI = PI * STR + STR = 1.0E0 / (AK + DNU) + QR = QR * STR + QI = QI * STR + STR = CKR*CZR - CKI*CZI + RAK = 1.0E0 / AK + CKI = (CKR*CZI + CKI*CZR) * RAK + CKR = STR * RAK + S1R = CKR*FR - CKI*FI + S1R + S1I = CKR*FI + CKI*FR + S1I + STR = PR - FR*AK + STI = PI - FI*AK + S2R = CKR*STR - CKI*STI + S2R + S2I = CKR*STI + CKI*STR + S2I + A1 = A1 * T1 * RAK + BK = BK + AK + AK + 1.0E0 + AK = AK + 1.0E0 + if A1 > TOL { + goto Ninety + } +OneHundred: + KFLAG = 2 + A1 = FNU + 1.0E0 + AK = A1 * dabs(SMUR) + if AK > ALIM { + KFLAG = 3 + } + STR = CSSR[KFLAG] + P2R = S2R * STR + P2I = S2I * STR + tmp = zmlt(complex(P2R, P2I), complex(RZR, RZI)) + S2R = real(tmp) + S2I = imag(tmp) + S1R = S1R * STR + S1I = S1I * STR + if KODED == 1 { + goto TwoTen + } + tmp = zexp(complex(ZR, ZI)) + FR = real(tmp) + FI = imag(tmp) + tmp = zmlt(complex(S1R, S1I), complex(FR, FI)) + S1R = real(tmp) + S1I = imag(tmp) + tmp = zmlt(complex(S2R, S2I), complex(FR, FI)) + S2R = real(tmp) + S2I = imag(tmp) + goto TwoTen + + // IFLAG=0 MEANS NO UNDERFLOW OCCURRED + // IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH + // KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD RECURSION +OneTen: + tmp = zsqrt(complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = zdiv(complex(RTHPI, CZEROI), complex(STR, STI)) + COEFR = real(tmp) + COEFI = imag(tmp) + KFLAG = 2 + if KODED == 2 { + goto OneTwenty + } + if ZR > ALIM { + goto TwoNinety + } + + STR = dexp(-ZR) * CSSR[KFLAG] + STI = -STR * dsin(ZI) + STR = STR * dcos(ZI) + tmp = zmlt(complex(COEFR, COEFI), complex(STR, STI)) + COEFR = real(tmp) + COEFI = imag(tmp) +OneTwenty: + if dabs(DNU) == 0.5E0 { + goto ThreeHundred + } + // MILLER ALGORITHM FOR CABS(Z)>R1. + AK = dcos(DPI * DNU) + AK = dabs(AK) + if AK == CZEROR { + goto ThreeHundred + } + FHS = dabs(0.25E0 - DNU2) + if FHS == CZEROR { + goto ThreeHundred + } + + // COMPUTE R2=F(E). if CABS(Z)>=R2, USE FORWARD RECURRENCE TO + // DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON + // 12<=E<=60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))= + // TOL WHERE B IS THE BASE OF THE ARITHMETIC. + T1 = float64(imach[14] - 1) + T1 = T1 * dmach[5] * 3.321928094E0 + T1 = dmax(T1, 12.0E0) + T1 = dmin(T1, 60.0E0) + T2 = TTH*T1 - 6.0E0 + if ZR != 0.0E0 { + goto OneThirty + } + T1 = HPI + goto OneFourty +OneThirty: + T1 = datan(ZI / ZR) + T1 = dabs(T1) +OneFourty: + if T2 > CAZ { + goto OneSeventy + } + // FORWARD RECURRENCE LOOP WHEN CABS(Z)>=R2. + ETEST = AK / (DPI * CAZ * TOL) + FK = CONER + if ETEST < CONER { + goto OneEighty + } + FKS = CTWOR + CKR = CAZ + CAZ + CTWOR + P1R = CZEROR + P2R = CONER + for I = 1; I <= KMAX; I++ { + AK = FHS / FKS + CBR = CKR / (FK + CONER) + PTR = P2R + P2R = CBR*P2R - P1R*AK + P1R = PTR + CKR = CKR + CTWOR + FKS = FKS + FK + FK + CTWOR + FHS = FHS + FK + FK + FK = FK + CONER + STR = dabs(P2R) * FK + if ETEST < STR { + goto OneSixty + } + } + goto ThreeTen +OneSixty: + FK = FK + SPI*T1*dsqrt(T2/CAZ) + FHS = dabs(0.25 - DNU2) + goto OneEighty +OneSeventy: + // COMPUTE BACKWARD INDEX K FOR CABS(Z) 0 || N > 1 { + goto TwoHundred + } + ZDR = ZR + ZDI = ZI + if IFLAG == 1 { + goto TwoSeventy + } + goto TwoFourty +TwoHundred: + // COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING. + TM = zabs(complex(P2R, P2I)) + PTR = 1.0E0 / TM + P1R = P1R * PTR + P1I = P1I * PTR + P2R = P2R * PTR + P2I = -P2I * PTR + tmp = zmlt(complex(P1R, P1I), complex(P2R, P2I)) + PTR = real(tmp) + PTI = imag(tmp) + STR = DNU + 0.5E0 - PTR + STI = -PTI + tmp = zdiv(complex(STR, STI), complex(ZR, ZI)) + STR = real(tmp) + STI = imag(tmp) + STR = STR + 1.0E0 + tmp = zmlt(complex(STR, STI), complex(S1R, S1I)) + S2R = real(tmp) + S2I = imag(tmp) + + // FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH + // SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3 +TwoTen: + STR = DNU + 1.0E0 + CKR = STR * RZR + CKI = STR * RZI + if N == 1 { + INU = INU - 1 + } + if INU > 0 { + goto TwoTwenty + } + if N > 1 { + goto TwoFifteen + } + S1R = S2R + S1I = S2I +TwoFifteen: + ZDR = ZR + ZDI = ZI + if IFLAG == 1 { + goto TwoSeventy + } + goto TwoFourty +TwoTwenty: + INUB = 1 + if IFLAG == 1 { + goto TwoSixtyOne + } +TwoTwentyFive: + P1R = CSRR[KFLAG] + ASCLE = BRY[KFLAG] + for I = INUB; I <= INU; I++ { + STR = S2R + STI = S2I + S2R = CKR*STR - CKI*STI + S1R + S2I = CKR*STI + CKI*STR + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + if KFLAG >= 3 { + continue + } + P2R = S2R * P1R + P2I = S2I * P1R + STR = dabs(P2R) + STI = dabs(P2I) + P2M = dmax(STR, STI) + if P2M <= ASCLE { + continue + } + KFLAG = KFLAG + 1 + ASCLE = BRY[KFLAG] + S1R = S1R * P1R + S1I = S1I * P1R + S2R = P2R + S2I = P2I + STR = CSSR[KFLAG] + S1R = S1R * STR + S1I = S1I * STR + S2R = S2R * STR + S2I = S2I * STR + P1R = CSRR[KFLAG] + } + if N != 1 { + goto TwoFourty + } + S1R = S2R + S1I = S2I +TwoFourty: + STR = CSRR[KFLAG] + YR[1] = S1R * STR + YI[1] = S1I * STR + if N == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + YR[2] = S2R * STR + YI[2] = S2I * STR + if N == 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = 2 +TwoFifty: + KK = KK + 1 + if KK > N { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + P1R = CSRR[KFLAG] + ASCLE = BRY[KFLAG] + for I = KK; I <= N; I++ { + P2R = S2R + P2I = S2I + S2R = CKR*P2R - CKI*P2I + S1R + S2I = CKI*P2R + CKR*P2I + S1I + S1R = P2R + S1I = P2I + CKR = CKR + RZR + CKI = CKI + RZI + P2R = S2R * P1R + P2I = S2I * P1R + YR[I] = P2R + YI[I] = P2I + if KFLAG >= 3 { + continue + } + STR = dabs(P2R) + STI = dabs(P2I) + P2M = dmax(STR, STI) + if P2M <= ASCLE { + continue + } + KFLAG = KFLAG + 1 + ASCLE = BRY[KFLAG] + S1R = S1R * P1R + S1I = S1I * P1R + S2R = P2R + S2I = P2I + STR = CSSR[KFLAG] + S1R = S1R * STR + S1I = S1I * STR + S2R = S2R * STR + S2I = S2I * STR + P1R = CSRR[KFLAG] + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW. +TwoSixtyOne: + HELIM = 0.5E0 * ELIM + ELM = dexp(-ELIM) + CELMR = ELM + ASCLE = BRY[1] + ZDR = ZR + ZDI = ZI + IC = -1 + J = 2 + for I = 1; I <= INU; I++ { + STR = S2R + STI = S2I + S2R = STR*CKR - STI*CKI + S1R + S2I = STI*CKR + STR*CKI + S1I + S1R = STR + S1I = STI + CKR = CKR + RZR + CKI = CKI + RZI + AS = zabs(complex(S2R, S2I)) + ALAS = dlog(AS) + P2R = -ZDR + ALAS + if P2R < (-ELIM) { + goto TwoSixtyThree + } + tmp = zlog(complex(S2R, S2I)) + STR = real(tmp) + STI = imag(tmp) + P2R = -ZDR + STR + P2I = -ZDI + STI + P2M = dexp(P2R) / TOL + P1R = P2M * dcos(P2I) + P1I = P2M * dsin(P2I) + P1R, P1I, NW, ASCLE, TOL = zuchkOrig(P1R, P1I, NW, ASCLE, TOL) + if NW != 0 { + goto TwoSixtyThree + } + J = 3 - J + CYR[J] = P1R + CYI[J] = P1I + if IC == (I - 1) { + goto TwoSixtyFour + } + IC = I + continue + TwoSixtyThree: + if ALAS < HELIM { + continue + } + ZDR = ZDR - ELIM + S1R = S1R * CELMR + S1I = S1I * CELMR + S2R = S2R * CELMR + S2I = S2I * CELMR + } + if N != 1 { + goto TwoSeventy + } + S1R = S2R + S1I = S2I + goto TwoSeventy +TwoSixtyFour: + KFLAG = 1 + INUB = I + 1 + S2R = CYR[J] + S2I = CYI[J] + J = 3 - J + S1R = CYR[J] + S1I = CYI[J] + if INUB <= INU { + goto TwoTwentyFive + } + if N != 1 { + goto TwoFourty + } + S1R = S2R + S1I = S2I + goto TwoFourty +TwoSeventy: + YR[1] = S1R + YI[1] = S1I + if N == 1 { + goto TwoEighty + } + YR[2] = S2R + YI[2] = S2I +TwoEighty: + ASCLE = BRY[1] + ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM = zksclOrig(ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM) + INU = N - NZ + if INU <= 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = NZ + 1 + S1R = YR[KK] + S1I = YI[KK] + YR[KK] = S1R * CSRR[1] + YI[KK] = S1I * CSRR[1] + if INU == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + KK = NZ + 2 + S2R = YR[KK] + S2I = YI[KK] + YR[KK] = S2R * CSRR[1] + YI[KK] = S2I * CSRR[1] + if INU == 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + T2 = FNU + float64(float32(KK-1)) + CKR = T2 * RZR + CKI = T2 * RZI + KFLAG = 1 + goto TwoFifty +TwoNinety: + + // SCALE BY dexp(Z), IFLAG = 1 CASES. + + KODED = 2 + IFLAG = 1 + KFLAG = 2 + goto OneTwenty + + // FNU=HALF ODD INTEGER CASE, DNU=-0.5 +ThreeHundred: + S1R = COEFR + S1I = COEFI + S2R = COEFR + S2I = COEFI + goto TwoTen + +ThreeTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +// SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE +// ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN +// return WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL. +func zksclOrig(ZRR, ZRI, FNU float64, N int, YR, YI []float64, NZ int, RZR, RZI, ASCLE, TOL, ELIM float64) ( + ZRRout, ZRIout, FNUout float64, Nout int, YRout, YIout []float64, NZout int, RZRout, RZIout, ASCLEout, TOLout, ELIMout float64) { + var ACS, AS, CKI, CKR, CSI, CSR, FN, STR, S1I, S1R, S2I, + S2R, ZEROI, ZEROR, ZDR, ZDI, CELMR, ELM, HELIM, ALAS float64 + + var I, IC, KK, NN, NW int + var tmp complex128 + var CYR, CYI [3]float64 + // DIMENSION YR(N), YI(N), CYR(2), CYI(2) + ZEROR = 0 + ZEROI = 0 + NZ = 0 + IC = 0 + NN = min0(2, N) + for I = 1; I <= NN; I++ { + S1R = YR[I] + S1I = YI[I] + CYR[I] = S1R + CYI[I] = S1I + AS = zabs(complex(S1R, S1I)) + ACS = -ZRR + dlog(AS) + NZ = NZ + 1 + YR[I] = ZEROR + YI[I] = ZEROI + if ACS < (-ELIM) { + continue + } + + tmp = zlog(complex(S1R, S1I)) + CSR = real(tmp) + CSI = imag(tmp) + CSR = CSR - ZRR + CSI = CSI - ZRI + STR = dexp(CSR) / TOL + CSR = STR * dcos(CSI) + CSI = STR * dsin(CSI) + CSR, CSI, NW, ASCLE, TOL = zuchkOrig(CSR, CSI, NW, ASCLE, TOL) + if NW != 0 { + continue + } + YR[I] = CSR + YI[I] = CSI + IC = I + NZ = NZ - 1 + } + if N == 1 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + if IC > 1 { + goto Twenty + } + YR[1] = ZEROR + YI[1] = ZEROI + NZ = 2 +Twenty: + if N == 2 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + if NZ == 0 { + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM + } + FN = FNU + 1.0E0 + CKR = FN * RZR + CKI = FN * RZI + S1R = CYR[1] + S1I = CYI[1] + S2R = CYR[2] + S2I = CYI[2] + HELIM = 0.5E0 * ELIM + ELM = dexp(-ELIM) + CELMR = ELM + ZDR = ZRR + ZDI = ZRI + + // FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF + // S2 GETS LARGER THAN EXP(ELIM/2) + for I = 3; I <= N; I++ { + KK = I + CSR = S2R + CSI = S2I + S2R = CKR*CSR - CKI*CSI + S1R + S2I = CKI*CSR + CKR*CSI + S1I + S1R = CSR + S1I = CSI + CKR = CKR + RZR + CKI = CKI + RZI + AS = zabs(complex(S2R, S2I)) + ALAS = dlog(AS) + ACS = -ZDR + ALAS + NZ = NZ + 1 + YR[I] = ZEROR + YI[I] = ZEROI + if ACS < (-ELIM) { + goto TwentyFive + } + tmp = zlog(complex(S2R, S2I)) + CSR = real(tmp) + CSI = imag(tmp) + CSR = CSR - ZDR + CSI = CSI - ZDI + STR = dexp(CSR) / TOL + CSR = STR * dcos(CSI) + CSI = STR * dsin(CSI) + CSR, CSI, NW, ASCLE, TOL = zuchkOrig(CSR, CSI, NW, ASCLE, TOL) + if NW != 0 { + goto TwentyFive + } + YR[I] = CSR + YI[I] = CSI + NZ = NZ - 1 + if IC == KK-1 { + goto Fourty + } + IC = KK + continue + TwentyFive: + if ALAS < HELIM { + continue + } + ZDR = ZDR - ELIM + S1R = S1R * CELMR + S1I = S1I * CELMR + S2R = S2R * CELMR + S2I = S2I * CELMR + } + NZ = N + if IC == N { + NZ = N - 1 + } + goto FourtyFive +Fourty: + NZ = KK - 2 +FourtyFive: + for I = 1; I <= NZ; I++ { + YR[I] = ZEROR + YI[I] = ZEROI + } + return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM +} + +// Y ENTERS AS A SCALED QUANTITY WHOSE MAGNITUDE IS GREATER THAN +// EXP(-ALIM)=ASCLE=1.0E+3*dmach[1)/TOL. THE TEST IS MADE TO SEE +// if THE MAGNITUDE OF THE REAL OR IMAGINARY PART WOULD UNDERFLOW +// WHEN Y IS SCALED (BY TOL) TO ITS PROPER VALUE. Y IS ACCEPTED +// if THE UNDERFLOW IS AT LEAST ONE PRECISION BELOW THE MAGNITUDE +// OF THE LARGEST COMPONENT; OTHERWISE THE PHASE ANGLE DOES NOT HAVE +// ABSOLUTE ACCURACY AND AN UNDERFLOW IS ASSUMED. +func zuchkOrig(YR, YI float64, NZ int, ASCLE, TOL float64) (YRout, YIout float64, NZout int, ASCLEout, TOLout float64) { + var SS, ST, WR, WI float64 + NZ = 0 + WR = dabs(YR) + WI = dabs(YI) + ST = dmin(WR, WI) + if ST > ASCLE { + return YR, YI, NZ, ASCLE, TOL + } + SS = dmax(WR, WI) + ST = ST / TOL + if SS < ST { + NZ = 1 + } + return YR, YI, NZ, ASCLE, TOL +} + +// ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA +// +// K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN) +// MP=PI*MR*CMPLX(0.0,1.0) +// +// TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT +// HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1. +// ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND +// RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT if ZACON +// IS CALLED FROM ZAIRY. +func zacaiOrig(ZR, ZI, FNU float64, KODE, MR, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, MRout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + var ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR, + CSPNI, C1R, C1I, C2R, C2I, DFNU, FMR, PI, + SGN, YY, ZNR, ZNI float64 + var INU, IUF, NN, NW int + CYR := []float64{math.NaN(), 0, 0} + CYI := []float64{math.NaN(), 0, 0} + + PI = math.Pi + NZ = 0 + ZNR = -ZR + ZNI = -ZI + AZ = zabs(complex(ZR, ZI)) + NN = N + DFNU = FNU + float64(float32(N-1)) + if AZ <= 2.0E0 { + goto Ten + } + if AZ*AZ*0.25 > DFNU+1.0E0 { + goto Twenty + } +Ten: + // POWER SERIES FOR THE I FUNCTION. + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL, ELIM, ALIM = zseriOrig(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL, ELIM, ALIM) + goto Fourty +Twenty: + if AZ < RL { + goto Thirty + } + // ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION. + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM = zasyiOrig(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM) + if NW < 0 { + goto Eighty + } + goto Fourty +Thirty: + // MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION + ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL = zmlriOrig(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL) + if NW < 0 { + goto Eighty + } +Fourty: + // ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION. + ZNR, ZNI, FNU, KODE, _, CYR, CYI, NW, TOL, ELIM, ALIM = zbknuOrig(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, NW, TOL, ELIM, ALIM) + if NW != 0 { + goto Eighty + } + FMR = float64(float32(MR)) + SGN = -math.Copysign(PI, FMR) + CSGNR = 0.0E0 + CSGNI = SGN + if KODE == 1 { + goto Fifty + } + YY = -ZNI + CSGNR = -CSGNI * dsin(YY) + CSGNI = CSGNI * dcos(YY) +Fifty: + // CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE + // WHEN FNU IS LARGE + INU = int(float32(FNU)) + ARG = (FNU - float64(float32(INU))) * SGN + CSPNR = dcos(ARG) + CSPNI = dsin(ARG) + if INU%2 == 0 { + goto Sixty + } + CSPNR = -CSPNR + CSPNI = -CSPNI +Sixty: + C1R = CYR[1] + C1I = CYI[1] + C2R = YR[1] + C2I = YI[1] + if KODE == 1 { + goto Seventy + } + IUF = 0 + ASCLE = 1.0E+3 * dmach[1] / TOL + ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF = zs1s2Orig(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF) + NZ = NZ + NW +Seventy: + YR[1] = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I + YI[1] = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +Eighty: + NZ = -1 + if NW == -2 { + NZ = -2 + } + return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +// ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY +// MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE +// REGION CABS(Z)>MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL return. +// NZ<0 INDICATES AN OVERFLOW ON KODE=1. +func zasyiOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) { + var AA, AEZ, AK, AK1I, AK1R, ARG, ARM, ATOL, + AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI, + CZR, DFNU, DKI, DKR, DNU2, EZI, EZR, FDN, PI, P1I, + P1R, RAZ, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I, + S2R, TZI, TZR, ZEROI, ZEROR float64 + + var I, IB, IL, INU, J, JL, K, KODED, M, NN int + var tmp complex128 + + PI = math.Pi + RTPI = 0.159154943091895336E0 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + NZ = 0 + AZ = zabs(complex(ZR, ZI)) + ARM = 1.0E3 * dmach[1] + RTR1 = dsqrt(ARM) + IL = min0(2, N) + DFNU = FNU + float64(float32(N-IL)) + + // OVERFLOW TEST + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + AK1R = RTPI * STR * RAZ + AK1I = RTPI * STI * RAZ + tmp = zsqrt(complex(AK1R, AK1I)) + AK1R = real(tmp) + AK1I = imag(tmp) + CZR = ZR + CZI = ZI + if KODE != 2 { + goto Ten + } + CZR = ZEROR + CZI = ZI +Ten: + if dabs(CZR) > ELIM { + goto OneHundred + } + DNU2 = DFNU + DFNU + KODED = 1 + if (dabs(CZR) > ALIM) && (N > 2) { + goto Twenty + } + KODED = 0 + tmp = zexp(complex(CZR, CZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = zmlt(complex(AK1R, AK1I), complex(STR, STI)) + AK1R = real(tmp) + AK1I = imag(tmp) +Twenty: + FDN = 0.0E0 + if DNU2 > RTR1 { + FDN = DNU2 * DNU2 + } + EZR = ZR * 8.0E0 + EZI = ZI * 8.0E0 + + // WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE + // FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE + // EXPANSION FOR THE IMAGINARY PART. + AEZ = 8.0E0 * AZ + S = TOL / AEZ + JL = int(float32(RL+RL)) + 2 + P1R = ZEROR + P1I = ZEROI + if ZI == 0.0E0 { + goto Thirty + } + + // CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF + // SIGNIFICANCE WHEN FNU OR N IS LARGE + INU = int(float32(FNU)) + ARG = (FNU - float64(float32(INU))) * PI + INU = INU + N - IL + AK = -dsin(ARG) + BK = dcos(ARG) + if ZI < 0.0E0 { + BK = -BK + } + P1R = AK + P1I = BK + if INU%2 == 0 { + goto Thirty + } + P1R = -P1R + P1I = -P1I +Thirty: + for K = 1; K <= IL; K++ { + SQK = FDN - 1.0E0 + ATOL = S * dabs(SQK) + SGN = 1.0E0 + CS1R = CONER + CS1I = CONEI + CS2R = CONER + CS2I = CONEI + CKR = CONER + CKI = CONEI + AK = 0.0E0 + AA = 1.0E0 + BB = AEZ + DKR = EZR + DKI = EZI + // TODO(btracey): This loop is executed tens of thousands of times. Why? + // is that really necessary? + for J = 1; J <= JL; J++ { + tmp = zdiv(complex(CKR, CKI), complex(DKR, DKI)) + STR = real(tmp) + STI = imag(tmp) + CKR = STR * SQK + CKI = STI * SQK + CS2R = CS2R + CKR + CS2I = CS2I + CKI + SGN = -SGN + CS1R = CS1R + CKR*SGN + CS1I = CS1I + CKI*SGN + DKR = DKR + EZR + DKI = DKI + EZI + AA = AA * dabs(SQK) / BB + BB = BB + AEZ + AK = AK + 8.0E0 + SQK = SQK - AK + if AA <= ATOL { + goto Fifty + } + } + goto OneTen + Fifty: + S2R = CS1R + S2I = CS1I + if ZR+ZR >= ELIM { + goto Sixty + } + TZR = ZR + ZR + TZI = ZI + ZI + tmp = zexp(complex(-TZR, -TZI)) + STR = real(tmp) + STI = imag(tmp) + tmp = zmlt(complex(STR, STI), complex(P1R, P1I)) + STR = real(tmp) + STI = imag(tmp) + tmp = zmlt(complex(STR, STI), complex(CS2R, CS2I)) + STR = real(tmp) + STI = imag(tmp) + S2R = S2R + STR + S2I = S2I + STI + Sixty: + FDN = FDN + 8.0E0*DFNU + 4.0E0 + P1R = -P1R + P1I = -P1I + M = N - IL + K + YR[M] = S2R*AK1R - S2I*AK1I + YI[M] = S2R*AK1I + S2I*AK1R + } + if N <= 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM + } + NN = N + K = NN - 2 + AK = float64(float32(K)) + STR = ZR * RAZ + STI = -ZI * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + IB = 3 + for I = IB; I <= NN; I++ { + YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2] + YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2] + AK = AK - 1.0E0 + K = K - 1 + } + if KODED == 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM + } + tmp = zexp(complex(CZR, CZI)) + CKR = real(tmp) + CKI = imag(tmp) + for I = 1; I <= NN; I++ { + STR = YR[I]*CKR - YI[I]*CKI + YI[I] = YR[I]*CKI + YI[I]*CKR + YR[I] = STR + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +OneHundred: + NZ = -1 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +OneTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM +} + +// ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z)>=0.0 BY THE +// MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES. +func zmlriOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout float64) { + var ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI, + CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, PTI, PTR, P1I, + P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI, + SUMR, TFNF, TST, ZEROI, ZEROR float64 + var I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, M int + var tmp complex128 + ZEROR = 0 + ZEROI = 0 + CONER = 1 + CONEI = 0 + + SCLE = dmach[1] / TOL + NZ = 0 + AZ = zabs(complex(ZR, ZI)) + IAZ = int(float32(AZ)) + IFNU = int(float32(FNU)) + INU = IFNU + N - 1 + AT = float64(float32(IAZ)) + 1.0E0 + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + CKR = STR * AT * RAZ + CKI = STI * AT * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + ACK = (AT + 1.0E0) * RAZ + RHO = ACK + dsqrt(ACK*ACK-1.0E0) + RHO2 = RHO * RHO + TST = (RHO2 + RHO2) / ((RHO2 - 1.0E0) * (RHO - 1.0E0)) + TST = TST / TOL + + // COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES. + //fmt.Println("before loop", P2R, P2I, CKR, CKI, RZR, RZI, TST, AK) + AK = AT + for I = 1; I <= 80; I++ { + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR - CKI*PTI) + P2I = P1I - (CKI*PTR + CKR*PTI) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = zabs(complex(P2R, P2I)) + if AP > TST*AK*AK { + goto Twenty + } + AK = AK + 1.0E0 + } + goto OneTen +Twenty: + I = I + 1 + K = 0 + if INU < IAZ { + goto Fourty + } + // COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS. + P1R = ZEROR + P1I = ZEROI + P2R = CONER + P2I = CONEI + AT = float64(float32(INU)) + 1.0E0 + STR = ZR * RAZ + STI = -ZI * RAZ + CKR = STR * AT * RAZ + CKI = STI * AT * RAZ + ACK = AT * RAZ + TST = dsqrt(ACK / TOL) + ITIME = 1 + for K = 1; K <= 80; K++ { + PTR = P2R + PTI = P2I + P2R = P1R - (CKR*PTR - CKI*PTI) + P2I = P1I - (CKR*PTI + CKI*PTR) + P1R = PTR + P1I = PTI + CKR = CKR + RZR + CKI = CKI + RZI + AP = zabs(complex(P2R, P2I)) + if AP < TST { + continue + } + if ITIME == 2 { + goto Fourty + } + ACK = zabs(complex(CKR, CKI)) + FLAM = ACK + dsqrt(ACK*ACK-1.0E0) + FKAP = AP / zabs(complex(P1R, P1I)) + RHO = dmin(FLAM, FKAP) + TST = TST * dsqrt(RHO/(RHO*RHO-1.0E0)) + ITIME = 2 + } + goto OneTen +Fourty: + // BACKWARD RECURRENCE AND SUM NORMALIZING RELATION. + K = K + 1 + KK = max0(I+IAZ, K+INU) + FKK = float64(float32(KK)) + P1R = ZEROR + P1I = ZEROI + + // SCALE P2 AND SUM BY SCLE. + P2R = SCLE + P2I = ZEROI + FNF = FNU - float64(float32(IFNU)) + TFNF = FNF + FNF + BK = dgamln(FKK+TFNF+1.0E0, IDUM) - dgamln(FKK+1.0E0, IDUM) - dgamln(TFNF+1.0E0, IDUM) + BK = dexp(BK) + SUMR = ZEROR + SUMI = ZEROI + KM = KK - INU + for I = 1; I <= KM; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + } + YR[N] = P2R + YI[N] = P2I + if N == 1 { + goto Seventy + } + for I = 2; I <= N; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + M = N - I + 1 + YR[M] = P2R + YI[M] = P2I + } +Seventy: + if IFNU <= 0 { + goto Ninety + } + for I = 1; I <= IFNU; I++ { + PTR = P2R + PTI = P2I + P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI) + P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR) + P1R = PTR + P1I = PTI + AK = 1.0E0 - TFNF/(FKK+TFNF) + ACK = BK * AK + SUMR = SUMR + (ACK+BK)*P1R + SUMI = SUMI + (ACK+BK)*P1I + BK = ACK + FKK = FKK - 1.0E0 + } +Ninety: + PTR = ZR + PTI = ZI + if KODE == 2 { + PTR = ZEROR + } + tmp = zlog(complex(RZR, RZI)) + STR = real(tmp) + STI = imag(tmp) + P1R = -FNF*STR + PTR + P1I = -FNF*STI + PTI + AP = dgamln(1.0E0+FNF, IDUM) + PTR = P1R - AP + PTI = P1I + + // THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW + // IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES. + P2R = P2R + SUMR + P2I = P2I + SUMI + AP = zabs(complex(P2R, P2I)) + P1R = 1.0E0 / AP + tmp = zexp(complex(PTR, PTI)) + STR = real(tmp) + STI = imag(tmp) + CKR = STR * P1R + CKI = STI * P1R + PTR = P2R * P1R + PTI = -P2I * P1R + tmp = zmlt(complex(CKR, CKI), complex(PTR, PTI)) + CNORMR = real(tmp) + CNORMI = imag(tmp) + for I = 1; I <= N; I++ { + STR = YR[I]*CNORMR - YI[I]*CNORMI + YI[I] = YR[I]*CNORMI + YI[I]*CNORMR + YR[I] = STR + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +OneTen: + NZ = -2 + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL +} + +// ZSERI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY +// MEANS OF THE POWER SERIES FOR LARGE CABS(Z) IN THE +// REGION CABS(Z)<=2*SQRT(FNU+1). NZ=0 IS A NORMAL return. +// NZ>0 MEANS THAT THE LAST NZ COMPONENTS WERE SET TO ZERO +// DUE TO UNDERFLOW. NZ<0 MEANS UNDERFLOW OCCURRED, BUT THE +// CONDITION CABS(Z)<=2*SQRT(FNU+1) WAS VIOLATED AND THE +// COMPUTATION MUST BE COMPLETED IN ANOTHER ROUTINE WITH N=N-ABS(NZ). +func zseriOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) ( + ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) { + var AA, ACZ, AK, AK1I, AK1R, ARM, ASCLE, ATOL, + AZ, CKI, CKR, COEFI, COEFR, CONEI, CONER, CRSCR, CZI, CZR, DFNU, + FNUP, HZI, HZR, RAZ, RS, RTR1, RZI, RZR, S, SS, STI, + STR, S1I, S1R, S2I, S2R, ZEROI, ZEROR float64 + var I, IB, IDUM, IFLAG, IL, K, L, M, NN, NW int + var WR, WI [3]float64 + var tmp complex128 + + CONER = 1.0 + NZ = 0 + AZ = zabs(complex(ZR, ZI)) + if AZ == 0.0E0 { + goto OneSixty + } + // TODO(btracey) + // The original fortran line is "ARM = 1.0D+3*D1MACH(1)". Evidently, in Fortran + // this is interpreted as one to the power of +3*D1MACH(1). While it is possible + // this was intentional, it seems unlikely. + //ARM = 1.0E0 + 3*dmach[1] + //math.Pow(1, 3*dmach[1]) + ARM = 1000 * dmach[1] + RTR1 = dsqrt(ARM) + CRSCR = 1.0E0 + IFLAG = 0 + if AZ < ARM { + goto OneFifty + } + HZR = 0.5E0 * ZR + HZI = 0.5E0 * ZI + CZR = ZEROR + CZI = ZEROI + if AZ <= RTR1 { + goto Ten + } + tmp = zmlt(complex(HZR, HZI), complex(HZR, HZI)) + CZR = real(tmp) + CZI = imag(tmp) +Ten: + ACZ = zabs(complex(CZR, CZI)) + NN = N + tmp = zlog(complex(HZR, HZI)) + CKR = real(tmp) + CKI = imag(tmp) +Twenty: + DFNU = FNU + float64(float32(NN-1)) + FNUP = DFNU + 1.0E0 + + // UNDERFLOW TEST. + AK1R = CKR * DFNU + AK1I = CKI * DFNU + AK = dgamln(FNUP, IDUM) + AK1R = AK1R - AK + if KODE == 2 { + AK1R = AK1R - ZR + } + if AK1R > (-ELIM) { + goto Fourty + } +Thirty: + NZ = NZ + 1 + YR[NN] = ZEROR + YI[NN] = ZEROI + if ACZ > DFNU { + goto OneNinety + } + NN = NN - 1 + if NN == 0 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + goto Twenty +Fourty: + if AK1R > (-ALIM) { + goto Fifty + } + IFLAG = 1 + SS = 1.0E0 / TOL + CRSCR = TOL + ASCLE = ARM * SS +Fifty: + AA = dexp(AK1R) + if IFLAG == 1 { + AA = AA * SS + } + COEFR = AA * dcos(AK1I) + COEFI = AA * dsin(AK1I) + ATOL = TOL * ACZ / FNUP + IL = min0(2, NN) + for I = 1; I <= IL; I++ { + DFNU = FNU + float64(float32(NN-I)) + FNUP = DFNU + 1.0E0 + S1R = CONER + S1I = CONEI + if ACZ < TOL*FNUP { + goto Seventy + } + AK1R = CONER + AK1I = CONEI + AK = FNUP + 2.0E0 + S = FNUP + AA = 2.0E0 + Sixty: + RS = 1.0E0 / S + STR = AK1R*CZR - AK1I*CZI + STI = AK1R*CZI + AK1I*CZR + AK1R = STR * RS + AK1I = STI * RS + S1R = S1R + AK1R + S1I = S1I + AK1I + S = S + AK + AK = AK + 2.0E0 + AA = AA * ACZ * RS + if AA > ATOL { + goto Sixty + } + Seventy: + S2R = S1R*COEFR - S1I*COEFI + S2I = S1R*COEFI + S1I*COEFR + WR[I] = S2R + WI[I] = S2I + if IFLAG == 0 { + goto Eighty + } + S2R, S2I, NW, ASCLE, TOL = zuchkOrig(S2R, S2I, NW, ASCLE, TOL) + if NW != 0 { + goto Thirty + } + Eighty: + M = NN - I + 1 + YR[M] = S2R * CRSCR + YI[M] = S2I * CRSCR + if I == IL { + continue + } + tmp = zdiv(complex(COEFR, COEFI), complex(HZR, HZI)) + STR = real(tmp) + STI = imag(tmp) + COEFR = STR * DFNU + COEFI = STI * DFNU + } + if NN <= 2 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + K = NN - 2 + AK = float64(float32(K)) + RAZ = 1.0E0 / AZ + STR = ZR * RAZ + STI = -ZI * RAZ + RZR = (STR + STR) * RAZ + RZI = (STI + STI) * RAZ + if IFLAG == 1 { + goto OneTwenty + } + IB = 3 +OneHundred: + for I = IB; I <= NN; I++ { + YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2] + YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2] + AK = AK - 1.0E0 + K = K - 1 + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // RECUR BACKWARD WITH SCALED VALUES. +OneTwenty: + // EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION ABOVE THE + // UNDERFLOW LIMIT = ASCLE = dmach[1)*SS*1.0D+3. + S1R = WR[1] + S1I = WI[1] + S2R = WR[2] + S2I = WI[2] + for L = 3; L <= NN; L++ { + CKR = S2R + CKI = S2I + S2R = S1R + (AK+FNU)*(RZR*CKR-RZI*CKI) + S2I = S1I + (AK+FNU)*(RZR*CKI+RZI*CKR) + S1R = CKR + S1I = CKI + CKR = S2R * CRSCR + CKI = S2I * CRSCR + YR[K] = CKR + YI[K] = CKI + AK = AK - 1.0E0 + K = K - 1 + if zabs(complex(CKR, CKI)) > ASCLE { + goto OneFourty + } + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +OneFourty: + IB = L + 1 + if IB > NN { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + goto OneHundred +OneFifty: + NZ = N + if FNU == 0.0E0 { + NZ = NZ - 1 + } +OneSixty: + YR[1] = ZEROR + YI[1] = ZEROI + if FNU != 0.0E0 { + goto OneSeventy + } + YR[1] = CONER + YI[1] = CONEI +OneSeventy: + if N == 1 { + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + } + for I = 2; I <= N; I++ { + YR[I] = ZEROR + YI[I] = ZEROI + } + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM + + // return WITH NZ<0 if CABS(Z*Z/4)>FNU+N-NZ-1 COMPLETE + // THE CALCULATION IN CBINU WITH N=N-IABS(NZ) + +OneNinety: + NZ = -NZ + return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM +} + +// ZS1S2 TESTS FOR A POSSIBLE UNDERFLOW RESULTING FROM THE +// ADDITION OF THE I AND K FUNCTIONS IN THE ANALYTIC CON- +// TINUATION FORMULA WHERE S1=K FUNCTION AND S2=I FUNCTION. +// ON KODE=1 THE I AND K FUNCTIONS ARE DIFFERENT ORDERS OF +// MAGNITUDE, BUT FOR KODE=2 THEY CAN BE OF THE SAME ORDER +// OF MAGNITUDE AND THE MAXIMUM MUST BE AT LEAST ONE +// PRECISION ABOVE THE UNDERFLOW LIMIT. +func zs1s2Orig(ZRR, ZRI, S1R, S1I, S2R, S2I float64, NZ int, ASCLE, ALIM float64, IUF int) ( + ZRRout, ZRIout, S1Rout, S1Iout, S2Rout, S2Iout float64, NZout int, ASCLEout, ALIMout float64, IUFout int) { + var AA, ALN, AS1, AS2, C1I, C1R, S1DI, S1DR, ZEROI, ZEROR float64 + var tmp complex128 + + ZEROR = 0 + ZEROI = 0 + NZ = 0 + AS1 = zabs(complex(S1R, S1I)) + AS2 = zabs(complex(S2R, S2I)) + if S1R == 0.0E0 && S1I == 0.0E0 { + goto Ten + } + if AS1 == 0.0E0 { + goto Ten + } + ALN = -ZRR - ZRR + dlog(AS1) + S1DR = S1R + S1DI = S1I + S1R = ZEROR + S1I = ZEROI + AS1 = ZEROR + if ALN < (-ALIM) { + goto Ten + } + tmp = zlog(complex(S1DR, S1DI)) + C1R = real(tmp) + C1I = imag(tmp) + + C1R = C1R - ZRR - ZRR + C1I = C1I - ZRI - ZRI + tmp = zexp(complex(C1R, C1I)) + S1R = real(tmp) + S1I = imag(tmp) + AS1 = zabs(complex(S1R, S1I)) + IUF = IUF + 1 +Ten: + AA = dmax(AS1, AS2) + if AA > ASCLE { + return ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, IUF + } + S1R = ZEROR + S1I = ZEROI + S2R = ZEROR + S2I = ZEROI + NZ = 1 + IUF = 0 + return ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, IUF +} + +// ZSHCH COMPUTES THE COMPLEX HYPERBOLIC FUNCTIONS CSH=SINH(X+iY) AND +// CCH=COSH(X+I*Y), WHERE I**2=-1. +// TODO(btracey): use cmplx.Sinh and cmplx.Cosh. +func zshchOrig(ZR, ZI, CSHR, CSHI, CCHR, CCHI float64) (ZRout, ZIout, CSHRout, CSHIout, CCHRout, CCHIout float64) { + var CH, CN, SH, SN float64 + SH = math.Sinh(ZR) + CH = math.Cosh(ZR) + SN = dsin(ZI) + CN = dcos(ZI) + CSHR = SH * CN + CSHI = CH * SN + CCHR = CH * CN + CCHI = SH * SN + return ZR, ZI, CSHR, CSHI, CCHR, CCHI +} + +func dmax(a, b float64) float64 { + return math.Max(a, b) +} + +func dmin(a, b float64) float64 { + return math.Min(a, b) +} + +func dabs(a float64) float64 { + return math.Abs(a) +} + +func datan(a float64) float64 { + return math.Atan(a) +} + +func dtan(a float64) float64 { + return math.Tan(a) +} + +func dlog(a float64) float64 { + return math.Log(a) +} + +func dsin(a float64) float64 { + return math.Sin(a) +} + +func dcos(a float64) float64 { + return math.Cos(a) +} + +func dexp(a float64) float64 { + return math.Exp(a) +} + +func dsqrt(a float64) float64 { + return math.Sqrt(a) +} + +func zmlt(a, b complex128) complex128 { + return a * b +} + +func zdiv(a, b complex128) complex128 { + return a / b +} + +func zabs(a complex128) float64 { + return cmplx.Abs(a) +} + +func zsqrt(a complex128) complex128 { + return cmplx.Sqrt(a) +} + +func zexp(a complex128) complex128 { + return cmplx.Exp(a) +} + +func zlog(a complex128) complex128 { + return cmplx.Log(a) +} + +// Zshch computes the hyperbolic sin and cosine of the input z. +func Zshch(z complex128) (sinh, cosh complex128) { + return cmplx.Sinh(z), cmplx.Cosh(z) +} diff --git a/mathext/internal/cephes/cephes.go b/mathext/internal/cephes/cephes.go new file mode 100644 index 00000000..3dfab9d0 --- /dev/null +++ b/mathext/internal/cephes/cephes.go @@ -0,0 +1,29 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cephes implements functions originally in the Netlib code by Stephen Mosher. +package cephes + +import "math" + +/* +Additional copyright information: + +Code in this package is adapted from the Cephes library (http://www.netlib.org/cephes/). +There is no explicit licence on Netlib, but the author has agreed to a BSD release. +See https://github.com/deepmind/torch-cephes/blob/master/LICENSE.txt and +https://lists.debian.org/debian-legal/2004/12/msg00295.html +*/ + +var ( + badParamOutOfBounds = "cephes: parameter out of bounds" + badParamFunctionSingularity = "cephes: function singularity" +) + +const ( + machEp = 1.0 / (1 << 53) + maxLog = 1024 * math.Ln2 + minLog = -1075 * math.Ln2 + maxIter = 2000 +) diff --git a/mathext/internal/cephes/igam.go b/mathext/internal/cephes/igam.go new file mode 100644 index 00000000..8b9fdf98 --- /dev/null +++ b/mathext/internal/cephes/igam.go @@ -0,0 +1,311 @@ +// Derived from SciPy's special/cephes/igam.c and special/cephes/igam.h +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/igam.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/igam.h +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1985, ©1987 by Stephen L. Moshier +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +const ( + igamDimK = 25 + igamDimN = 25 + igam = 1 + igamC = 0 + igamSmall = 20 + igamLarge = 200 + igamSmallRatio = 0.3 + igamLargeRatio = 4.5 +) + +var igamCoefs = [igamDimK][igamDimN]float64{ + [igamDimN]float64{-3.3333333333333333e-1, 8.3333333333333333e-2, -1.4814814814814815e-2, 1.1574074074074074e-3, 3.527336860670194e-4, -1.7875514403292181e-4, 3.9192631785224378e-5, -2.1854485106799922e-6, -1.85406221071516e-6, 8.296711340953086e-7, -1.7665952736826079e-7, 6.7078535434014986e-9, 1.0261809784240308e-8, -4.3820360184533532e-9, 9.1476995822367902e-10, -2.551419399494625e-11, -5.8307721325504251e-11, 2.4361948020667416e-11, -5.0276692801141756e-12, 1.1004392031956135e-13, 3.3717632624009854e-13, -1.3923887224181621e-13, 2.8534893807047443e-14, -5.1391118342425726e-16, -1.9752288294349443e-15}, + [igamDimN]float64{-1.8518518518518519e-3, -3.4722222222222222e-3, 2.6455026455026455e-3, -9.9022633744855967e-4, 2.0576131687242798e-4, -4.0187757201646091e-7, -1.8098550334489978e-5, 7.6491609160811101e-6, -1.6120900894563446e-6, 4.6471278028074343e-9, 1.378633446915721e-7, -5.752545603517705e-8, 1.1951628599778147e-8, -1.7543241719747648e-11, -1.0091543710600413e-9, 4.1627929918425826e-10, -8.5639070264929806e-11, 6.0672151016047586e-14, 7.1624989648114854e-12, -2.9331866437714371e-12, 5.9966963656836887e-13, -2.1671786527323314e-16, -4.9783399723692616e-14, 2.0291628823713425e-14, -4.13125571381061e-15}, + [igamDimN]float64{4.1335978835978836e-3, -2.6813271604938272e-3, 7.7160493827160494e-4, 2.0093878600823045e-6, -1.0736653226365161e-4, 5.2923448829120125e-5, -1.2760635188618728e-5, 3.4235787340961381e-8, 1.3721957309062933e-6, -6.298992138380055e-7, 1.4280614206064242e-7, -2.0477098421990866e-10, -1.4092529910867521e-8, 6.228974084922022e-9, -1.3670488396617113e-9, 9.4283561590146782e-13, 1.2872252400089318e-10, -5.5645956134363321e-11, 1.1975935546366981e-11, -4.1689782251838635e-15, -1.0940640427884594e-12, 4.6622399463901357e-13, -9.905105763906906e-14, 1.8931876768373515e-17, 8.8592218725911273e-15}, + [igamDimN]float64{6.4943415637860082e-4, 2.2947209362139918e-4, -4.6918949439525571e-4, 2.6772063206283885e-4, -7.5618016718839764e-5, -2.3965051138672967e-7, 1.1082654115347302e-5, -5.6749528269915966e-6, 1.4230900732435884e-6, -2.7861080291528142e-11, -1.6958404091930277e-7, 8.0994649053880824e-8, -1.9111168485973654e-8, 2.3928620439808118e-12, 2.0620131815488798e-9, -9.4604966618551322e-10, 2.1541049775774908e-10, -1.388823336813903e-14, -2.1894761681963939e-11, 9.7909989511716851e-12, -2.1782191880180962e-12, 6.2088195734079014e-17, 2.126978363279737e-13, -9.3446887915174333e-14, 2.0453671226782849e-14}, + [igamDimN]float64{-8.618882909167117e-4, 7.8403922172006663e-4, -2.9907248030319018e-4, -1.4638452578843418e-6, 6.6414982154651222e-5, -3.9683650471794347e-5, 1.1375726970678419e-5, 2.5074972262375328e-10, -1.6954149536558306e-6, 8.9075075322053097e-7, -2.2929348340008049e-7, 2.956794137544049e-11, 2.8865829742708784e-8, -1.4189739437803219e-8, 3.4463580499464897e-9, -2.3024517174528067e-13, -3.9409233028046405e-10, 1.8602338968504502e-10, -4.356323005056618e-11, 1.2786001016296231e-15, 4.6792750266579195e-12, -2.1492464706134829e-12, 4.9088156148096522e-13, -6.3385914848915603e-18, -5.0453320690800944e-14}, + [igamDimN]float64{-3.3679855336635815e-4, -6.9728137583658578e-5, 2.7727532449593921e-4, -1.9932570516188848e-4, 6.7977804779372078e-5, 1.419062920643967e-7, -1.3594048189768693e-5, 8.0184702563342015e-6, -2.2914811765080952e-6, -3.252473551298454e-10, 3.4652846491085265e-7, -1.8447187191171343e-7, 4.8240967037894181e-8, -1.7989466721743515e-14, -6.3061945000135234e-9, 3.1624176287745679e-9, -7.8409242536974293e-10, 5.1926791652540407e-15, 9.3589442423067836e-11, -4.5134262161632782e-11, 1.0799129993116827e-11, -3.661886712685252e-17, -1.210902069055155e-12, 5.6807435849905643e-13, -1.3249659916340829e-13}, + [igamDimN]float64{5.3130793646399222e-4, -5.9216643735369388e-4, 2.7087820967180448e-4, 7.9023532326603279e-7, -8.1539693675619688e-5, 5.6116827531062497e-5, -1.8329116582843376e-5, -3.0796134506033048e-9, 3.4651553688036091e-6, -2.0291327396058604e-6, 5.7887928631490037e-7, 2.338630673826657e-13, -8.8286007463304835e-8, 4.7435958880408128e-8, -1.2545415020710382e-8, 8.6496488580102925e-14, 1.6846058979264063e-9, -8.5754928235775947e-10, 2.1598224929232125e-10, -7.6132305204761539e-16, -2.6639822008536144e-11, 1.3065700536611057e-11, -3.1799163902367977e-12, 4.7109761213674315e-18, 3.6902800842763467e-13}, + [igamDimN]float64{3.4436760689237767e-4, 5.1717909082605922e-5, -3.3493161081142236e-4, 2.812695154763237e-4, -1.0976582244684731e-4, -1.2741009095484485e-7, 2.7744451511563644e-5, -1.8263488805711333e-5, 5.7876949497350524e-6, 4.9387589339362704e-10, -1.0595367014026043e-6, 6.1667143761104075e-7, -1.7562973359060462e-7, -1.2974473287015439e-12, 2.695423606288966e-8, -1.4578352908731271e-8, 3.887645959386175e-9, -3.8810022510194121e-17, -5.3279941738772867e-10, 2.7437977643314845e-10, -6.9957960920705679e-11, 2.5899863874868481e-17, 8.8566890996696381e-12, -4.403168815871311e-12, 1.0865561947091654e-12}, + [igamDimN]float64{-6.5262391859530942e-4, 8.3949872067208728e-4, -4.3829709854172101e-4, -6.969091458420552e-7, 1.6644846642067548e-4, -1.2783517679769219e-4, 4.6299532636913043e-5, 4.5579098679227077e-9, -1.0595271125805195e-5, 6.7833429048651666e-6, -2.1075476666258804e-6, -1.7213731432817145e-11, 3.7735877416110979e-7, -2.1867506700122867e-7, 6.2202288040189269e-8, 6.5977038267330006e-16, -9.5903864974256858e-9, 5.2132144922808078e-9, -1.3991589583935709e-9, 5.382058999060575e-16, 1.9484714275467745e-10, -1.0127287556389682e-10, 2.6077347197254926e-11, -5.0904186999932993e-18, -3.3721464474854592e-12}, + [igamDimN]float64{-5.9676129019274625e-4, -7.2048954160200106e-5, 6.7823088376673284e-4, -6.4014752602627585e-4, 2.7750107634328704e-4, 1.8197008380465151e-7, -8.4795071170685032e-5, 6.105192082501531e-5, -2.1073920183404862e-5, -8.8585890141255994e-10, 4.5284535953805377e-6, -2.8427815022504408e-6, 8.7082341778646412e-7, 3.6886101871706965e-12, -1.5344695190702061e-7, 8.862466778790695e-8, -2.5184812301826817e-8, -1.0225912098215092e-14, 3.8969470758154777e-9, -2.1267304792235635e-9, 5.7370135528051385e-10, -1.887749850169741e-19, -8.0931538694657866e-11, 4.2382723283449199e-11, -1.1002224534207726e-11}, + [igamDimN]float64{1.3324454494800656e-3, -1.9144384985654775e-3, 1.1089369134596637e-3, 9.932404122642299e-7, -5.0874501293093199e-4, 4.2735056665392884e-4, -1.6858853767910799e-4, -8.1301893922784998e-9, 4.5284402370562147e-5, -3.127053674781734e-5, 1.044986828530338e-5, 4.8435226265680926e-11, -2.1482565873456258e-6, 1.329369701097492e-6, -4.0295693092101029e-7, -1.7567877666323291e-13, 7.0145043163668257e-8, -4.040787734999483e-8, 1.1474026743371963e-8, 3.9642746853563325e-18, -1.7804938269892714e-9, 9.7480262548731646e-10, -2.6405338676507616e-10, 5.794875163403742e-18, 3.7647749553543836e-11}, + [igamDimN]float64{1.579727660730835e-3, 1.6251626278391582e-4, -2.0633421035543276e-3, 2.1389686185689098e-3, -1.0108559391263003e-3, -3.9912705529919201e-7, 3.6235025084764691e-4, -2.8143901463712154e-4, 1.0449513336495887e-4, 2.1211418491830297e-9, -2.5779417251947842e-5, 1.7281818956040463e-5, -5.6413773872904282e-6, -1.1024320105776174e-11, 1.1223224418895175e-6, -6.8693396379526735e-7, 2.0653236975414887e-7, 4.6714772409838506e-14, -3.5609886164949055e-8, 2.0470855345905963e-8, -5.8091738633283358e-9, -1.332821287582869e-16, 9.0354604391335133e-10, -4.9598782517330834e-10, 1.3481607129399749e-10}, + [igamDimN]float64{-4.0725121195140166e-3, 6.4033628338080698e-3, -4.0410161081676618e-3, -2.183732802866233e-6, 2.1740441801254639e-3, -1.9700440518418892e-3, 8.3595469747962458e-4, 1.9445447567109655e-8, -2.5779387120421696e-4, 1.9009987368139304e-4, -6.7696499937438965e-5, -1.4440629666426572e-10, 1.5712512518742269e-5, -1.0304008744776893e-5, 3.304517767401387e-6, 7.9829760242325709e-13, -6.4097794149313004e-7, 3.8894624761300056e-7, -1.1618347644948869e-7, -2.816808630596451e-15, 1.9878012911297093e-8, -1.1407719956357511e-8, 3.2355857064185555e-9, 4.1759468293455945e-20, -5.0423112718105824e-10}, + [igamDimN]float64{-5.9475779383993003e-3, -5.4016476789260452e-4, 8.7910413550767898e-3, -9.8576315587856125e-3, 5.0134695031021538e-3, 1.2807521786221875e-6, -2.0626019342754683e-3, 1.7109128573523058e-3, -6.7695312714133799e-4, -6.9011545676562133e-9, 1.8855128143995902e-4, -1.3395215663491969e-4, 4.6263183033528039e-5, 4.0034230613321351e-11, -1.0255652921494033e-5, 6.612086372797651e-6, -2.0913022027253008e-6, -2.0951775649603837e-13, 3.9756029041993247e-7, -2.3956211978815887e-7, 7.1182883382145864e-8, 8.925574873053455e-16, -1.2101547235064676e-8, 6.9350618248334386e-9, -1.9661464453856102e-9}, + [igamDimN]float64{1.7402027787522711e-2, -2.9527880945699121e-2, 2.0045875571402799e-2, 7.0289515966903407e-6, -1.2375421071343148e-2, 1.1976293444235254e-2, -5.4156038466518525e-3, -6.3290893396418616e-8, 1.8855118129005065e-3, -1.473473274825001e-3, 5.5515810097708387e-4, 5.2406834412550662e-10, -1.4357913535784836e-4, 9.9181293224943297e-5, -3.3460834749478311e-5, -3.5755837291098993e-12, 7.1560851960630076e-6, -4.5516802628155526e-6, 1.4236576649271475e-6, 1.8803149082089664e-14, -2.6623403898929211e-7, 1.5950642189595716e-7, -4.7187514673841102e-8, -6.5107872958755177e-17, 7.9795091026746235e-9}, + [igamDimN]float64{3.0249124160905891e-2, 2.4817436002649977e-3, -4.9939134373457022e-2, 5.9915643009307869e-2, -3.2483207601623391e-2, -5.7212968652103441e-6, 1.5085251778569354e-2, -1.3261324005088445e-2, 5.5515262632426148e-3, 3.0263182257030016e-8, -1.7229548406756723e-3, 1.2893570099929637e-3, -4.6845138348319876e-4, -1.830259937893045e-10, 1.1449739014822654e-4, -7.7378565221244477e-5, 2.5625836246985201e-5, 1.0766165333192814e-12, -5.3246809282422621e-6, 3.349634863064464e-6, -1.0381253128684018e-6, -5.608909920621128e-15, 1.9150821930676591e-7, -1.1418365800203486e-7, 3.3654425209171788e-8}, + [igamDimN]float64{-9.9051020880159045e-2, 1.7954011706123486e-1, -1.2989606383463778e-1, -3.1478872752284357e-5, 9.0510635276848131e-2, -9.2828824411184397e-2, 4.4412112839877808e-2, 2.7779236316835888e-7, -1.7229543805449697e-2, 1.4182925050891573e-2, -5.6214161633747336e-3, -2.39598509186381e-9, 1.6029634366079908e-3, -1.1606784674435773e-3, 4.1001337768153873e-4, 1.8365800754090661e-11, -9.5844256563655903e-5, 6.3643062337764708e-5, -2.076250624489065e-5, -1.1806020912804483e-13, 4.2131808239120649e-6, -2.6262241337012467e-6, 8.0770620494930662e-7, 6.0125912123632725e-16, -1.4729737374018841e-7}, + [igamDimN]float64{-1.9994542198219728e-1, -1.5056113040026424e-2, 3.6470239469348489e-1, -4.6435192311733545e-1, 2.6640934719197893e-1, 3.4038266027147191e-5, -1.3784338709329624e-1, 1.276467178337056e-1, -5.6213828755200985e-2, -1.753150885483011e-7, 1.9235592956768113e-2, -1.5088821281095315e-2, 5.7401854451350123e-3, 1.0622382710310225e-9, -1.5335082692563998e-3, 1.0819320643228214e-3, -3.7372510193945659e-4, -6.6170909729031985e-12, 8.4263617380909628e-5, -5.5150706827483479e-5, 1.7769536448348069e-5, 3.8827923210205533e-14, -3.53513697488768e-6, 2.1865832130045269e-6, -6.6812849447625594e-7}, + [igamDimN]float64{7.2438608504029431e-1, -1.3918010932653375, 1.0654143352413968, 1.876173868950258e-4, -8.2705501176152696e-1, 8.9352433347828414e-1, -4.4971003995291339e-1, -1.6107401567546652e-6, 1.9235590165271091e-1, -1.6597702160042609e-1, 6.8882222681814333e-2, 1.3910091724608687e-8, -2.146911561508663e-2, 1.6228980898865892e-2, -5.9796016172584256e-3, -1.1287469112826745e-10, 1.5167451119784857e-3, -1.0478634293553899e-3, 3.5539072889126421e-4, 8.1704322111801517e-13, -7.7773013442452395e-5, 5.0291413897007722e-5, -1.6035083867000518e-5, 1.2469354315487605e-14, 3.1369106244517615e-6}, + [igamDimN]float64{1.6668949727276811, 1.165462765994632e-1, -3.3288393225018906, 4.4692325482864037, -2.6977693045875807, -2.600667859891061e-4, 1.5389017615694539, -1.4937962361134612, 6.8881964633233148e-1, 1.3077482004552385e-6, -2.5762963325596288e-1, 2.1097676102125449e-1, -8.3714408359219882e-2, -7.7920428881354753e-9, 2.4267923064833599e-2, -1.7813678334552311e-2, 6.3970330388900056e-3, 4.9430807090480523e-11, -1.5554602758465635e-3, 1.0561196919903214e-3, -3.5277184460472902e-4, 9.3002334645022459e-14, 7.5285855026557172e-5, -4.8186515569156351e-5, 1.5227271505597605e-5}, + [igamDimN]float64{-6.6188298861372935, 1.3397985455142589e+1, -1.0789350606845146e+1, -1.4352254537875018e-3, 9.2333694596189809, -1.0456552819547769e+1, 5.5105526029033471, 1.2024439690716742e-5, -2.5762961164755816, 2.3207442745387179, -1.0045728797216284, -1.0207833290021914e-7, 3.3975092171169466e-1, -2.6720517450757468e-1, 1.0235252851562706e-1, 8.4329730484871625e-10, -2.7998284958442595e-2, 2.0066274144976813e-2, -7.0554368915086242e-3, 1.9402238183698188e-12, 1.6562888105449611e-3, -1.1082898580743683e-3, 3.654545161310169e-4, -5.1290032026971794e-11, -7.6340103696869031e-5}, + [igamDimN]float64{-1.7112706061976095e+1, -1.1208044642899116, 3.7131966511885444e+1, -5.2298271025348962e+1, 3.3058589696624618e+1, 2.4791298976200222e-3, -2.061089403411526e+1, 2.088672775145582e+1, -1.0045703956517752e+1, -1.2238783449063012e-5, 4.0770134274221141, -3.473667358470195, 1.4329352617312006, 7.1359914411879712e-8, -4.4797257159115612e-1, 3.4112666080644461e-1, -1.2699786326594923e-1, -2.8953677269081528e-10, 3.3125776278259863e-2, -2.3274087021036101e-2, 8.0399993503648882e-3, -1.177805216235265e-9, -1.8321624891071668e-3, 1.2108282933588665e-3, -3.9479941246822517e-4}, + [igamDimN]float64{7.389033153567425e+1, -1.5680141270402273e+2, 1.322177542759164e+2, 1.3692876877324546e-2, -1.2366496885920151e+2, 1.4620689391062729e+2, -8.0365587724865346e+1, -1.1259851148881298e-4, 4.0770132196179938e+1, -3.8210340013273034e+1, 1.719522294277362e+1, 9.3519707955168356e-7, -6.2716159907747034, 5.1168999071852637, -2.0319658112299095, -4.9507215582761543e-9, 5.9626397294332597e-1, -4.4220765337238094e-1, 1.6079998700166273e-1, -2.4733786203223402e-8, -4.0307574759979762e-2, 2.7849050747097869e-2, -9.4751858992054221e-3, 6.419922235909132e-6, 2.1250180774699461e-3}, + [igamDimN]float64{2.1216837098382522e+2, 1.3107863022633868e+1, -4.9698285932871748e+2, 7.3121595266969204e+2, -4.8213821720890847e+2, -2.8817248692894889e-2, 3.2616720302947102e+2, -3.4389340280087117e+2, 1.7195193870816232e+2, 1.4038077378096158e-4, -7.52594195897599e+1, 6.651969984520934e+1, -2.8447519748152462e+1, -7.613702615875391e-7, 9.5402237105304373, -7.5175301113311376, 2.8943997568871961, -4.6612194999538201e-7, -8.0615149598794088e-1, 5.8483006570631029e-1, -2.0845408972964956e-1, 1.4765818959305817e-4, 5.1000433863753019e-2, -3.3066252141883665e-2, 1.5109265210467774e-2}, + [igamDimN]float64{-9.8959643098322368e+2, 2.1925555360905233e+3, -1.9283586782723356e+3, -1.5925738122215253e-1, 1.9569985945919857e+3, -2.4072514765081556e+3, 1.3756149959336496e+3, 1.2920735237496668e-3, -7.525941715948055e+2, 7.3171668742208716e+2, -3.4137023466220065e+2, -9.9857390260608043e-6, 1.3356313181291573e+2, -1.1276295161252794e+2, 4.6310396098204458e+1, -7.9237387133614756e-6, -1.4510726927018646e+1, 1.1111771248100563e+1, -4.1690817945270892, 3.1008219800117808e-3, 1.1220095449981468, -7.6052379926149916e-1, 3.6262236505085254e-1, 2.216867741940747e-1, 4.8683443692930507e-1}, +} + +// Igam computes the incomplete Gamma integral. +// Igam(a,x) = (1/ Γ(a)) \int_0^x e^{-t} t^{a-1} dt +// The input argument a must be positive and x must be non-negative or Igam +// will panic. +func Igam(a, x float64) float64 { + // The integral is evaluated by either a power series or continued fraction + // expansion, depending on the relative values of a and x. + // Sources: + // [1] "The Digital Library of Mathematical Functions", dlmf.nist.gov + // [2] Maddock et. al., "Incomplete Gamma Functions", + // http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/sf_gamma/igamma.html + + // Check zero integration limit first + if x == 0 { + return 0 + } + + if x < 0 || a <= 0 { + panic(badParamOutOfBounds) + } + + // Asymptotic regime where a ~ x; see [2]. + absxmaA := math.Abs(x-a) / a + if (igamSmall < a && a < igamLarge && absxmaA < igamSmallRatio) || + (igamLarge < a && absxmaA < igamLargeRatio/math.Sqrt(a)) { + return asymptoticSeries(a, x, igam) + } + + if x > 1 && x > a { + return 1 - IgamC(a, x) + } + + return igamSeries(a, x) +} + +// IgamC computes the complemented incomplete Gamma integral. +// IgamC(a,x) = 1 - Igam(a,x) +// = (1/ Γ(a)) \int_0^\infty e^{-t} t^{a-1} dt +// The input argument a must be positive and x must be non-negative or +// IgamC will panic. +func IgamC(a, x float64) float64 { + // The integral is evaluated by either a power series or continued fraction + // expansion, depending on the relative values of a and x. + // Sources: + // [1] "The Digital Library of Mathematical Functions", dlmf.nist.gov + // [2] Maddock et. al., "Incomplete Gamma Functions", + // http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/sf_gamma/igamma.html + + switch { + case x < 0, a <= 0: + panic(badParamOutOfBounds) + case x == 0: + return 1 + case math.IsInf(x, 0): + return 0 + } + + // Asymptotic regime where a ~ x; see [2]. + absxmaA := math.Abs(x-a) / a + if (igamSmall < a && a < igamLarge && absxmaA < igamSmallRatio) || + (igamLarge < a && absxmaA < igamLargeRatio/math.Sqrt(a)) { + return asymptoticSeries(a, x, igamC) + } + + // Everywhere else; see [2]. + if x > 1.1 { + if x < a { + return 1 - igamSeries(a, x) + } + return igamCContinuedFraction(a, x) + } else if x <= 0.5 { + if -0.4/math.Log(x) < a { + return 1 - igamSeries(a, x) + } + return igamCSeries(a, x) + } + + if x*1.1 < a { + return 1 - igamSeries(a, x) + } + return igamCSeries(a, x) +} + +// igamFac computes +// x^a * e^{-x} / Γ(a) +// corrected from (15) and (16) in [2] by replacing +// e^{x - a} +// with +// e^{a - x} +func igamFac(a, x float64) float64 { + if math.Abs(a-x) > 0.4*math.Abs(a) { + ax := a*math.Log(x) - x - lgam(a) + return math.Exp(ax) + } + + fac := a + lanczosG - 0.5 + res := math.Sqrt(fac/math.Exp(1)) / lanczosSumExpgScaled(a) + + if a < 200 && x < 200 { + res *= math.Exp(a-x) * math.Pow(x/fac, a) + } else { + num := x - a - lanczosG + 0.5 + res *= math.Exp(a*log1pmx(num/fac) + x*(0.5-lanczosG)/fac) + } + + return res +} + +// igamCContinuedFraction computes IgamC using DLMF 8.9.2. +func igamCContinuedFraction(a, x float64) float64 { + ax := igamFac(a, x) + if ax == 0 { + return 0 + } + + // Continued fraction + y := 1 - a + z := x + y + 1 + c := 0.0 + pkm2 := 1.0 + qkm2 := x + pkm1 := x + 1.0 + qkm1 := z * x + ans := pkm1 / qkm1 + + for i := 0; i < maxIter; i++ { + c += 1.0 + y += 1.0 + z += 2.0 + yc := y * c + pk := pkm1*z - pkm2*yc + qk := qkm1*z - qkm2*yc + var t float64 + if qk != 0 { + r := pk / qk + t = math.Abs((ans - r) / r) + ans = r + } else { + t = 1.0 + } + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + if math.Abs(pk) > big { + pkm2 *= biginv + pkm1 *= biginv + qkm2 *= biginv + qkm1 *= biginv + } + if t <= machEp { + break + } + } + + return ans * ax +} + +// igamSeries computes Igam using DLMF 8.11.4. +func igamSeries(a, x float64) float64 { + ax := igamFac(a, x) + if ax == 0 { + return 0 + } + + // Power series + r := a + c := 1.0 + ans := 1.0 + + for i := 0; i < maxIter; i++ { + r += 1.0 + c *= x / r + ans += c + if c <= machEp*ans { + break + } + } + + return ans * ax / a +} + +// igamCSeries computes IgamC using DLMF 8.7.3. This is related to the series +// in igamSeries but extra care is taken to avoid cancellation. +func igamCSeries(a, x float64) float64 { + fac := 1.0 + sum := 0.0 + + for n := 1; n < maxIter; n++ { + fac *= -x / float64(n) + term := fac / (a + float64(n)) + sum += term + if math.Abs(term) <= machEp*math.Abs(sum) { + break + } + } + + logx := math.Log(x) + term := -expm1(a*logx - lgam1p(a)) + return term - math.Exp(a*logx-lgam(a))*sum +} + +// asymptoticSeries computes Igam/IgamC using DLMF 8.12.3/8.12.4. +func asymptoticSeries(a, x float64, fun int) float64 { + maxpow := 0 + lambda := x / a + sigma := (x - a) / a + absoldterm := math.MaxFloat64 + etapow := [igamDimN]float64{1} + sum := 0.0 + afac := 1.0 + + var sgn float64 + if fun == igam { + sgn = -1 + } else { + sgn = 1 + } + + var eta float64 + if lambda > 1 { + eta = math.Sqrt(-2 * log1pmx(sigma)) + } else if lambda < 1 { + eta = -math.Sqrt(-2 * log1pmx(sigma)) + } else { + eta = 0 + } + res := 0.5 * math.Erfc(sgn*eta*math.Sqrt(a/2)) + + for k := 0; k < igamDimK; k++ { + ck := igamCoefs[k][0] + for n := 1; n < igamDimN; n++ { + if n > maxpow { + etapow[n] = eta * etapow[n-1] + maxpow++ + } + ckterm := igamCoefs[k][n] * etapow[n] + ck += ckterm + if math.Abs(ckterm) < machEp*math.Abs(ck) { + break + } + } + term := ck * afac + absterm := math.Abs(term) + if absterm > absoldterm { + break + } + sum += term + if absterm < machEp*math.Abs(sum) { + break + } + absoldterm = absterm + afac /= a + } + res += sgn * math.Exp(-0.5*a*eta*eta) * sum / math.Sqrt(2*math.Pi*a) + + return res +} diff --git a/mathext/internal/cephes/igami.go b/mathext/internal/cephes/igami.go new file mode 100644 index 00000000..5a8d9a91 --- /dev/null +++ b/mathext/internal/cephes/igami.go @@ -0,0 +1,153 @@ +// Derived from SciPy's special/cephes/igami.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/igami.c +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1984, ©1987, ©1995 by Stephen L. Moshier +// Portions Copyright ©2017 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +// IgamI computes the inverse of the incomplete Gamma function. That is, it +// returns the x such that: +// IgamC(a, x) = p +// The input argument a must be positive and p must be between 0 and 1 +// inclusive or IgamI will panic. IgamI should return a positive number, but +// can return 0 even with non-zero y due to underflow. +func IgamI(a, p float64) float64 { + // Bound the solution + x0 := math.MaxFloat64 + yl := 0.0 + x1 := 0.0 + yh := 1.0 + dithresh := 5.0 * machEp + + if p < 0 || p > 1 || a <= 0 { + panic(badParamOutOfBounds) + } + + if p == 0 { + return math.Inf(1) + } + + if p == 1 { + return 0.0 + } + + // Starting with the approximate value + // x = a y^3 + // where + // y = 1 - d - ndtri(p) sqrt(d) + // and + // d = 1/9a + // the routine performs up to 10 Newton iterations to find the root of + // IgamC(a, x) - p = 0 + d := 1.0 / (9.0 * a) + y := 1.0 - d - Ndtri(p)*math.Sqrt(d) + x := a * y * y * y + + lgm := lgam(a) + + for i := 0; i < 10; i++ { + if x > x0 || x < x1 { + break + } + + y = IgamC(a, x) + + if y < yl || y > yh { + break + } + + if y < p { + x0 = x + yl = y + } else { + x1 = x + yh = y + } + + // Compute the derivative of the function at this point + d = (a-1)*math.Log(x) - x - lgm + if d < -maxLog { + break + } + d = -math.Exp(d) + + // Compute the step to the next approximation of x + d = (y - p) / d + if math.Abs(d/x) < machEp { + return x + } + x = x - d + } + + d = 0.0625 + if x0 == math.MaxFloat64 { + if x <= 0 { + x = 1 + } + for x0 == math.MaxFloat64 { + x = (1 + d) * x + y = IgamC(a, x) + if y < p { + x0 = x + yl = y + break + } + d = d + d + } + } + + d = 0.5 + dir := 0 + for i := 0; i < 400; i++ { + x = x1 + d*(x0-x1) + y = IgamC(a, x) + + lgm = (x0 - x1) / (x1 + x0) + if math.Abs(lgm) < dithresh { + break + } + + lgm = (y - p) / p + if math.Abs(lgm) < dithresh { + break + } + + if x <= 0 { + break + } + + if y >= p { + x1 = x + yh = y + if dir < 0 { + dir = 0 + d = 0.5 + } else if dir > 1 { + d = 0.5*d + 0.5 + } else { + d = (p - yl) / (yh - yl) + } + dir++ + } else { + x0 = x + yl = y + if dir > 0 { + dir = 0 + d = 0.5 + } else if dir < -1 { + d = 0.5 * d + } else { + d = (p - yl) / (yh - yl) + } + dir-- + } + } + + return x +} diff --git a/mathext/internal/cephes/incbeta.go b/mathext/internal/cephes/incbeta.go new file mode 100644 index 00000000..cbe46c47 --- /dev/null +++ b/mathext/internal/cephes/incbeta.go @@ -0,0 +1,312 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * Cephes Math Library, Release 2.3: March, 1995 + * Copyright 1984, 1995 by Stephen L. Moshier + */ + +package cephes + +import ( + "math" + + "gonum.org/v1/gonum/mathext/internal/gonum" +) + +const ( + maxGam = 171.624376956302725 + big = 4.503599627370496e15 + biginv = 2.22044604925031308085e-16 +) + +// Incbet computes the regularized incomplete beta function. +func Incbet(aa, bb, xx float64) float64 { + if aa <= 0 || bb <= 0 { + panic(badParamOutOfBounds) + } + if xx <= 0 || xx >= 1 { + if xx == 0 { + return 0 + } + if xx == 1 { + return 1 + } + panic(badParamOutOfBounds) + } + + var flag int + if bb*xx <= 1 && xx <= 0.95 { + t := pseries(aa, bb, xx) + return transformT(t, flag) + } + + w := 1 - xx + + // Reverse a and b if x is greater than the mean. + var a, b, xc, x float64 + if xx > aa/(aa+bb) { + flag = 1 + a = bb + b = aa + xc = xx + x = w + } else { + a = aa + b = bb + xc = w + x = xx + } + + if flag == 1 && (b*x) <= 1.0 && x <= 0.95 { + t := pseries(a, b, x) + return transformT(t, flag) + } + + // Choose expansion for better convergence. + y := x*(a+b-2.0) - (a - 1.0) + if y < 0.0 { + w = incbcf(a, b, x) + } else { + w = incbd(a, b, x) / xc + } + + // Multiply w by the factor + // x^a * (1-x)^b * Γ(a+b) / (a*Γ(a)*Γ(b)) + var t float64 + y = a * math.Log(x) + t = b * math.Log(xc) + if (a+b) < maxGam && math.Abs(y) < maxLog && math.Abs(t) < maxLog { + t = math.Pow(xc, b) + t *= math.Pow(x, a) + t /= a + t *= w + t *= 1.0 / gonum.Beta(a, b) + return transformT(t, flag) + } + + // Resort to logarithms. + y += t - gonum.Lbeta(a, b) + y += math.Log(w / a) + if y < minLog { + t = 0.0 + } else { + t = math.Exp(y) + } + + return transformT(t, flag) +} + +func transformT(t float64, flag int) float64 { + if flag == 1 { + if t <= machEp { + t = 1.0 - machEp + } else { + t = 1.0 - t + } + } + return t +} + +// incbcf returns the incomplete beta integral evaluated by a continued fraction +// expansion. +func incbcf(a, b, x float64) float64 { + var xk, pk, pkm1, pkm2, qk, qkm1, qkm2 float64 + var k1, k2, k3, k4, k5, k6, k7, k8 float64 + var r, t, ans, thresh float64 + var n int + + k1 = a + k2 = a + b + k3 = a + k4 = a + 1.0 + k5 = 1.0 + k6 = b - 1.0 + k7 = k4 + k8 = a + 2.0 + + pkm2 = 0.0 + qkm2 = 1.0 + pkm1 = 1.0 + qkm1 = 1.0 + ans = 1.0 + r = 1.0 + thresh = 3.0 * machEp + + for n = 0; n <= 300; n++ { + + xk = -(x * k1 * k2) / (k3 * k4) + pk = pkm1 + pkm2*xk + qk = qkm1 + qkm2*xk + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + + xk = (x * k5 * k6) / (k7 * k8) + pk = pkm1 + pkm2*xk + qk = qkm1 + qkm2*xk + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + + if qk != 0 { + r = pk / qk + } + if r != 0 { + t = math.Abs((ans - r) / r) + ans = r + } else { + t = 1.0 + } + + if t < thresh { + return ans + } + + k1 += 1.0 + k2 += 1.0 + k3 += 2.0 + k4 += 2.0 + k5 += 1.0 + k6 -= 1.0 + k7 += 2.0 + k8 += 2.0 + + if (math.Abs(qk) + math.Abs(pk)) > big { + pkm2 *= biginv + pkm1 *= biginv + qkm2 *= biginv + qkm1 *= biginv + } + if (math.Abs(qk) < biginv) || (math.Abs(pk) < biginv) { + pkm2 *= big + pkm1 *= big + qkm2 *= big + qkm1 *= big + } + } + + return ans +} + +// incbd returns the incomplete beta integral evaluated by a continued fraction +// expansion. +func incbd(a, b, x float64) float64 { + var xk, pk, pkm1, pkm2, qk, qkm1, qkm2 float64 + var k1, k2, k3, k4, k5, k6, k7, k8 float64 + var r, t, ans, z, thresh float64 + var n int + + k1 = a + k2 = b - 1.0 + k3 = a + k4 = a + 1.0 + k5 = 1.0 + k6 = a + b + k7 = a + 1.0 + k8 = a + 2.0 + + pkm2 = 0.0 + qkm2 = 1.0 + pkm1 = 1.0 + qkm1 = 1.0 + z = x / (1.0 - x) + ans = 1.0 + r = 1.0 + thresh = 3.0 * machEp + for n = 0; n <= 300; n++ { + + xk = -(z * k1 * k2) / (k3 * k4) + pk = pkm1 + pkm2*xk + qk = qkm1 + qkm2*xk + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + + xk = (z * k5 * k6) / (k7 * k8) + pk = pkm1 + pkm2*xk + qk = qkm1 + qkm2*xk + pkm2 = pkm1 + pkm1 = pk + qkm2 = qkm1 + qkm1 = qk + + if qk != 0 { + r = pk / qk + } + if r != 0 { + t = math.Abs((ans - r) / r) + ans = r + } else { + t = 1.0 + } + + if t < thresh { + return ans + } + + k1 += 1.0 + k2 -= 1.0 + k3 += 2.0 + k4 += 2.0 + k5 += 1.0 + k6 += 1.0 + k7 += 2.0 + k8 += 2.0 + + if (math.Abs(qk) + math.Abs(pk)) > big { + pkm2 *= biginv + pkm1 *= biginv + qkm2 *= biginv + qkm1 *= biginv + } + if (math.Abs(qk) < biginv) || (math.Abs(pk) < biginv) { + pkm2 *= big + pkm1 *= big + qkm2 *= big + qkm1 *= big + } + } + return ans +} + +// pseries returns the incomplete beta integral evaluated by a power series. Use +// when b*x is small and x not too close to 1. +func pseries(a, b, x float64) float64 { + var s, t, u, v, n, t1, z, ai float64 + ai = 1.0 / a + u = (1.0 - b) * x + v = u / (a + 1.0) + t1 = v + t = u + n = 2.0 + s = 0.0 + z = machEp * ai + for math.Abs(v) > z { + u = (n - b) * x / n + t *= u + v = t / (a + n) + s += v + n += 1.0 + } + s += t1 + s += ai + + u = a * math.Log(x) + if (a+b) < maxGam && math.Abs(u) < maxLog { + t = 1.0 / gonum.Beta(a, b) + s = s * t * math.Pow(x, a) + } else { + t = -gonum.Lbeta(a, b) + u + math.Log(s) + if t < minLog { + s = 0.0 + } else { + s = math.Exp(t) + } + } + return (s) +} diff --git a/mathext/internal/cephes/incbi.go b/mathext/internal/cephes/incbi.go new file mode 100644 index 00000000..06037867 --- /dev/null +++ b/mathext/internal/cephes/incbi.go @@ -0,0 +1,248 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * Cephes Math Library Release 2.4: March,1996 + * Copyright 1984, 1996 by Stephen L. Moshier + */ + +package cephes + +import "math" + +// Incbi computes the inverse of the regularized incomplete beta integral. +func Incbi(aa, bb, yy0 float64) float64 { + var a, b, y0, d, y, x, x0, x1, lgm, yp, di, dithresh, yl, yh, xt float64 + var i, rflg, dir, nflg int + + i = 0 + if yy0 <= 0 { + return (0.0) + } + if yy0 >= 1.0 { + return (1.0) + } + x0 = 0.0 + yl = 0.0 + x1 = 1.0 + yh = 1.0 + nflg = 0 + + if aa <= 1.0 || bb <= 1.0 { + dithresh = 1.0e-6 + rflg = 0 + a = aa + b = bb + y0 = yy0 + x = a / (a + b) + y = Incbet(a, b, x) + goto ihalve + } else { + dithresh = 1.0e-4 + } + // Approximation to inverse function + yp = -Ndtri(yy0) + + if yy0 > 0.5 { + rflg = 1 + a = bb + b = aa + y0 = 1.0 - yy0 + yp = -yp + } else { + rflg = 0 + a = aa + b = bb + y0 = yy0 + } + + lgm = (yp*yp - 3.0) / 6.0 + x = 2.0 / (1.0/(2.0*a-1.0) + 1.0/(2.0*b-1.0)) + d = yp*math.Sqrt(x+lgm)/x - (1.0/(2.0*b-1.0)-1.0/(2.0*a-1.0))*(lgm+5.0/6.0-2.0/(3.0*x)) + d = 2.0 * d + if d < minLog { + // mtherr("incbi", UNDERFLOW) + x = 0 + goto done + } + x = a / (a + b*math.Exp(d)) + y = Incbet(a, b, x) + yp = (y - y0) / y0 + if math.Abs(yp) < 0.2 { + goto newt + } + + /* Resort to interval halving if not close enough. */ +ihalve: + + dir = 0 + di = 0.5 + for i = 0; i < 100; i++ { + if i != 0 { + x = x0 + di*(x1-x0) + if x == 1.0 { + x = 1.0 - machEp + } + if x == 0.0 { + di = 0.5 + x = x0 + di*(x1-x0) + if x == 0.0 { + // mtherr("incbi", UNDERFLOW) + goto done + } + } + y = Incbet(a, b, x) + yp = (x1 - x0) / (x1 + x0) + if math.Abs(yp) < dithresh { + goto newt + } + yp = (y - y0) / y0 + if math.Abs(yp) < dithresh { + goto newt + } + } + if y < y0 { + x0 = x + yl = y + if dir < 0 { + dir = 0 + di = 0.5 + } else if dir > 3 { + di = 1.0 - (1.0-di)*(1.0-di) + } else if dir > 1 { + di = 0.5*di + 0.5 + } else { + di = (y0 - y) / (yh - yl) + } + dir += 1 + if x0 > 0.75 { + if rflg == 1 { + rflg = 0 + a = aa + b = bb + y0 = yy0 + } else { + rflg = 1 + a = bb + b = aa + y0 = 1.0 - yy0 + } + x = 1.0 - x + y = Incbet(a, b, x) + x0 = 0.0 + yl = 0.0 + x1 = 1.0 + yh = 1.0 + goto ihalve + } + } else { + x1 = x + if rflg == 1 && x1 < machEp { + x = 0.0 + goto done + } + yh = y + if dir > 0 { + dir = 0 + di = 0.5 + } else if dir < -3 { + di = di * di + } else if dir < -1 { + di = 0.5 * di + } else { + di = (y - y0) / (yh - yl) + } + dir -= 1 + } + } + // mtherr("incbi", PLOSS) + if x0 >= 1.0 { + x = 1.0 - machEp + goto done + } + if x <= 0.0 { + // mtherr("incbi", UNDERFLOW) + x = 0.0 + goto done + } + +newt: + if nflg > 0 { + goto done + } + nflg = 1 + lgm = lgam(a+b) - lgam(a) - lgam(b) + + for i = 0; i < 8; i++ { + /* Compute the function at this point. */ + if i != 0 { + y = Incbet(a, b, x) + } + if y < yl { + x = x0 + y = yl + } else if y > yh { + x = x1 + y = yh + } else if y < y0 { + x0 = x + yl = y + } else { + x1 = x + yh = y + } + if x == 1.0 || x == 0.0 { + break + } + /* Compute the derivative of the function at this point. */ + d = (a-1.0)*math.Log(x) + (b-1.0)*math.Log(1.0-x) + lgm + if d < minLog { + goto done + } + if d > maxLog { + break + } + d = math.Exp(d) + /* Compute the step to the next approximation of x. */ + d = (y - y0) / d + xt = x - d + if xt <= x0 { + y = (x - x0) / (x1 - x0) + xt = x0 + 0.5*y*(x-x0) + if xt <= 0.0 { + break + } + } + if xt >= x1 { + y = (x1 - x) / (x1 - x0) + xt = x1 - 0.5*y*(x1-x) + if xt >= 1.0 { + break + } + } + x = xt + if math.Abs(d/x) < 128.0*machEp { + goto done + } + } + /* Did not converge. */ + dithresh = 256.0 * machEp + goto ihalve + +done: + + if rflg > 0 { + if x <= machEp { + x = 1.0 - machEp + } else { + x = 1.0 - x + } + } + return (x) +} + +func lgam(a float64) float64 { + lg, _ := math.Lgamma(a) + return lg +} diff --git a/mathext/internal/cephes/lanczos.go b/mathext/internal/cephes/lanczos.go new file mode 100644 index 00000000..c32909b5 --- /dev/null +++ b/mathext/internal/cephes/lanczos.go @@ -0,0 +1,153 @@ +// Derived from SciPy's special/cephes/lanczos.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/lanczos.c + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©2006 John Maddock +// Portions Copyright ©2003 Boost +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +// Optimal values for G for each N are taken from +// http://web.mala.bc.ca/pughg/phdThesis/phdThesis.pdf, +// as are the theoretical error bounds. + +// Constants calculated using the method described by Godfrey +// http://my.fit.edu/~gabdo/gamma.txt and elaborated by Toth at +// http://www.rskey.org/gamma.htm using NTL::RR at 1000 bit precision. + +var lanczosNum = [...]float64{ + 2.506628274631000270164908177133837338626, + 210.8242777515793458725097339207133627117, + 8071.672002365816210638002902272250613822, + 186056.2653952234950402949897160456992822, + 2876370.628935372441225409051620849613599, + 31426415.58540019438061423162831820536287, + 248874557.8620541565114603864132294232163, + 1439720407.311721673663223072794912393972, + 6039542586.35202800506429164430729792107, + 17921034426.03720969991975575445893111267, + 35711959237.35566804944018545154716670596, + 42919803642.64909876895789904700198885093, + 23531376880.41075968857200767445163675473, +} + +var lanczosDenom = [...]float64{ + 1, + 66, + 1925, + 32670, + 357423, + 2637558, + 13339535, + 45995730, + 105258076, + 150917976, + 120543840, + 39916800, + 0, +} + +var lanczosSumExpgScaledNum = [...]float64{ + 0.006061842346248906525783753964555936883222, + 0.5098416655656676188125178644804694509993, + 19.51992788247617482847860966235652136208, + 449.9445569063168119446858607650988409623, + 6955.999602515376140356310115515198987526, + 75999.29304014542649875303443598909137092, + 601859.6171681098786670226533699352302507, + 3481712.15498064590882071018964774556468, + 14605578.08768506808414169982791359218571, + 43338889.32467613834773723740590533316085, + 86363131.28813859145546927288977868422342, + 103794043.1163445451906271053616070238554, + 56906521.91347156388090791033559122686859, +} + +var lanczosSumExpgScaledDenom = [...]float64{ + 1, + 66, + 1925, + 32670, + 357423, + 2637558, + 13339535, + 45995730, + 105258076, + 150917976, + 120543840, + 39916800, + 0, +} + +var lanczosSumNear1D = [...]float64{ + 0.3394643171893132535170101292240837927725e-9, + -0.2499505151487868335680273909354071938387e-8, + 0.8690926181038057039526127422002498960172e-8, + -0.1933117898880828348692541394841204288047e-7, + 0.3075580174791348492737947340039992829546e-7, + -0.2752907702903126466004207345038327818713e-7, + -0.1515973019871092388943437623825208095123e-5, + 0.004785200610085071473880915854204301886437, + -0.1993758927614728757314233026257810172008, + 1.483082862367253753040442933770164111678, + -3.327150580651624233553677113928873034916, + 2.208709979316623790862569924861841433016, +} + +var lanczosSumNear2D = [...]float64{ + 0.1009141566987569892221439918230042368112e-8, + -0.7430396708998719707642735577238449585822e-8, + 0.2583592566524439230844378948704262291927e-7, + -0.5746670642147041587497159649318454348117e-7, + 0.9142922068165324132060550591210267992072e-7, + -0.8183698410724358930823737982119474130069e-7, + -0.4506604409707170077136555010018549819192e-5, + 0.01422519127192419234315002746252160965831, + -0.5926941084905061794445733628891024027949, + 4.408830289125943377923077727900630927902, + -9.8907772644920670589288081640128194231, + 6.565936202082889535528455955485877361223, +} + +const lanczosG = 6.024680040776729583740234375 + +func lanczosSum(x float64) float64 { + return ratevl(x, + lanczosNum[:], + len(lanczosNum)-1, + lanczosDenom[:], + len(lanczosDenom)-1) +} + +func lanczosSumExpgScaled(x float64) float64 { + return ratevl(x, + lanczosSumExpgScaledNum[:], + len(lanczosSumExpgScaledNum)-1, + lanczosSumExpgScaledDenom[:], + len(lanczosSumExpgScaledDenom)-1) +} + +func lanczosSumNear1(dx float64) float64 { + var result float64 + + for i, val := range lanczosSumNear1D { + k := float64(i + 1) + result += (-val * dx) / (k*dx + k*k) + } + + return result +} + +func lanczosSumNear2(dx float64) float64 { + var result float64 + x := dx + 2 + + for i, val := range lanczosSumNear2D { + k := float64(i + 1) + result += (-val * dx) / (x + k*x + k*k - 1) + } + + return result +} diff --git a/mathext/internal/cephes/ndtri.go b/mathext/internal/cephes/ndtri.go new file mode 100644 index 00000000..1b26abdc --- /dev/null +++ b/mathext/internal/cephes/ndtri.go @@ -0,0 +1,150 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * Cephes Math Library Release 2.1: January, 1989 + * Copyright 1984, 1987, 1989 by Stephen L. Moshier + * Direct inquiries to 30 Frost Street, Cambridge, MA 02140 + */ + +package cephes + +import "math" + +// TODO(btracey): There is currently an implementation of this functionality +// in gonum/stat/distuv. Find out which implementation is better, and rectify +// by having distuv call this, or moving this implementation into +// gonum/mathext/internal/gonum. + +// math.Sqrt(2*pi) +const s2pi = 2.50662827463100050242E0 + +// approximation for 0 <= |y - 0.5| <= 3/8 +var P0 = [5]float64{ + -5.99633501014107895267E1, + 9.80010754185999661536E1, + -5.66762857469070293439E1, + 1.39312609387279679503E1, + -1.23916583867381258016E0, +} + +var Q0 = [8]float64{ + /* 1.00000000000000000000E0, */ + 1.95448858338141759834E0, + 4.67627912898881538453E0, + 8.63602421390890590575E1, + -2.25462687854119370527E2, + 2.00260212380060660359E2, + -8.20372256168333339912E1, + 1.59056225126211695515E1, + -1.18331621121330003142E0, +} + +// Approximation for interval z = math.Sqrt(-2 log y ) between 2 and 8 +// i.e., y between exp(-2) = .135 and exp(-32) = 1.27e-14. +var P1 = [9]float64{ + 4.05544892305962419923E0, + 3.15251094599893866154E1, + 5.71628192246421288162E1, + 4.40805073893200834700E1, + 1.46849561928858024014E1, + 2.18663306850790267539E0, + -1.40256079171354495875E-1, + -3.50424626827848203418E-2, + -8.57456785154685413611E-4, +} + +var Q1 = [8]float64{ + /* 1.00000000000000000000E0, */ + 1.57799883256466749731E1, + 4.53907635128879210584E1, + 4.13172038254672030440E1, + 1.50425385692907503408E1, + 2.50464946208309415979E0, + -1.42182922854787788574E-1, + -3.80806407691578277194E-2, + -9.33259480895457427372E-4, +} + +// Approximation for interval z = math.Sqrt(-2 log y ) between 8 and 64 +// i.e., y between exp(-32) = 1.27e-14 and exp(-2048) = 3.67e-890. +var P2 = [9]float64{ + 3.23774891776946035970E0, + 6.91522889068984211695E0, + 3.93881025292474443415E0, + 1.33303460815807542389E0, + 2.01485389549179081538E-1, + 1.23716634817820021358E-2, + 3.01581553508235416007E-4, + 2.65806974686737550832E-6, + 6.23974539184983293730E-9, +} + +var Q2 = [8]float64{ + /* 1.00000000000000000000E0, */ + 6.02427039364742014255E0, + 3.67983563856160859403E0, + 1.37702099489081330271E0, + 2.16236993594496635890E-1, + 1.34204006088543189037E-2, + 3.28014464682127739104E-4, + 2.89247864745380683936E-6, + 6.79019408009981274425E-9, +} + +// Ndtri returns the argument, x, for which the area under the +// Gaussian probability density function (integrated from +// minus infinity to x) is equal to y. +func Ndtri(y0 float64) float64 { + // For small arguments 0 < y < exp(-2), the program computes + // z = math.Sqrt( -2.0 * math.Log(y) ); then the approximation is + // x = z - math.Log(z)/z - (1/z) P(1/z) / Q(1/z). + // There are two rational functions P/Q, one for 0 < y < exp(-32) + // and the other for y up to exp(-2). For larger arguments, + // w = y - 0.5, and x/math.Sqrt(2pi) = w + w**3 R(w**2)/S(w**2)). + var x, y, z, y2, x0, x1 float64 + var code int + + if y0 <= 0.0 { + if y0 < 0 { + panic(badParamOutOfBounds) + } + return math.Inf(-1) + } + if y0 >= 1.0 { + if y0 > 1 { + panic(badParamOutOfBounds) + } + return math.Inf(1) + } + code = 1 + y = y0 + if y > (1.0 - 0.13533528323661269189) { /* 0.135... = exp(-2) */ + y = 1.0 - y + code = 0 + } + + if y > 0.13533528323661269189 { + y = y - 0.5 + y2 = y * y + x = y + y*(y2*polevl(y2, P0[:], 4)/p1evl(y2, Q0[:], 8)) + x = x * s2pi + return (x) + } + + x = math.Sqrt(-2.0 * math.Log(y)) + x0 = x - math.Log(x)/x + + z = 1.0 / x + if x < 8.0 { /* y > exp(-32) = 1.2664165549e-14 */ + x1 = z * polevl(z, P1[:], 8) / p1evl(z, Q1[:], 8) + } else { + x1 = z * polevl(z, P2[:], 8) / p1evl(z, Q2[:], 8) + } + x = x0 - x1 + if code != 0 { + x = -x + } + return (x) +} diff --git a/mathext/internal/cephes/polevl.go b/mathext/internal/cephes/polevl.go new file mode 100644 index 00000000..5cbd8cbb --- /dev/null +++ b/mathext/internal/cephes/polevl.go @@ -0,0 +1,82 @@ +// Derived from SciPy's special/cephes/polevl.h +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/polevl.h +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1984, ©1987, ©1988 by Stephen L. Moshier +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +// polevl evaluates a polynomial of degree N +// y = c_0 + c_1 x_1 + c_2 x_2^2 ... +// where the coefficients are stored in reverse order, i.e. coef[0] = c_n and +// coef[n] = c_0. +func polevl(x float64, coef []float64, n int) float64 { + ans := coef[0] + for i := 1; i <= n; i++ { + ans = ans*x + coef[i] + } + return ans +} + +// p1evl is the same as polevl, except c_n is assumed to be 1 and is not included +// in the slice. +func p1evl(x float64, coef []float64, n int) float64 { + ans := x + coef[0] + for i := 1; i <= n-1; i++ { + ans = ans*x + coef[i] + } + return ans +} + +// ratevl evaluates a rational function +func ratevl(x float64, num []float64, m int, denom []float64, n int) float64 { + // Source: Holin et. al., "Polynomial and Rational Function Evaluation", + // http://www.boost.org/doc/libs/1_61_0/libs/math/doc/html/math_toolkit/roots/rational.html + absx := math.Abs(x) + + var dir, idx int + var y float64 + if absx > 1 { + // Evaluate as a polynomial in 1/x + dir = -1 + idx = m + y = 1 / x + } else { + dir = 1 + idx = 0 + y = x + } + + // Evaluate the numerator + numAns := num[idx] + idx += dir + for i := 0; i < m; i++ { + numAns = numAns*y + num[idx] + idx += dir + } + + // Evaluate the denominator + if absx > 1 { + idx = n + } else { + idx = 0 + } + + denomAns := denom[idx] + idx += dir + for i := 0; i < n; i++ { + denomAns = denomAns*y + denom[idx] + idx += dir + } + + if absx > 1 { + pow := float64(n - m) + return math.Pow(x, pow) * numAns / denomAns + } + return numAns / denomAns +} diff --git a/mathext/internal/cephes/unity.go b/mathext/internal/cephes/unity.go new file mode 100644 index 00000000..1333dd1d --- /dev/null +++ b/mathext/internal/cephes/unity.go @@ -0,0 +1,170 @@ +// Derived from SciPy's special/cephes/unity.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/unity.c +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1984, ©1996 by Stephen L. Moshier +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +// Relative error approximations for function arguments near unity. +// log1p(x) = log(1+x) +// expm1(x) = exp(x) - 1 +// cosm1(x) = cos(x) - 1 +// lgam1p(x) = lgam(1+x) + +const ( + invSqrt2 = 1 / math.Sqrt2 + pi4 = math.Pi / 4 + euler = 0.577215664901532860606512090082402431 // Euler constant +) + +// Coefficients for +// log(1+x) = x - \frac{x^2}{2} + \frac{x^3 lP(x)}{lQ(x)} +// for +// \frac{1}{\sqrt{2}} <= x < \sqrt{2} +// Theoretical peak relative error = 2.32e-20 +var lP = [...]float64{ + 4.5270000862445199635215E-5, + 4.9854102823193375972212E-1, + 6.5787325942061044846969E0, + 2.9911919328553073277375E1, + 6.0949667980987787057556E1, + 5.7112963590585538103336E1, + 2.0039553499201281259648E1, +} + +var lQ = [...]float64{ + 1.5062909083469192043167E1, + 8.3047565967967209469434E1, + 2.2176239823732856465394E2, + 3.0909872225312059774938E2, + 2.1642788614495947685003E2, + 6.0118660497603843919306E1, +} + +// log1p computes +// log(1 + x) +func log1p(x float64) float64 { + z := 1 + x + if z < invSqrt2 || z > math.Sqrt2 { + return math.Log(z) + } + z = x * x + z = -0.5*z + x*(z*polevl(x, lP[:], 6)/p1evl(x, lQ[:], 6)) + return x + z +} + +// log1pmx computes +// log(1 + x) - x +func log1pmx(x float64) float64 { + if math.Abs(x) < 0.5 { + xfac := x + res := 0.0 + + var term float64 + for n := 2; n < maxIter; n++ { + xfac *= -x + term = xfac / float64(n) + res += term + if math.Abs(term) < machEp*math.Abs(res) { + break + } + } + return res + } + return log1p(x) - x +} + +// Coefficients for +// e^x = 1 + \frac{2x eP(x^2)}{eQ(x^2) - eP(x^2)} +// for +// -0.5 <= x <= 0.5 +var eP = [...]float64{ + 1.2617719307481059087798E-4, + 3.0299440770744196129956E-2, + 9.9999999999999999991025E-1, +} + +var eQ = [...]float64{ + 3.0019850513866445504159E-6, + 2.5244834034968410419224E-3, + 2.2726554820815502876593E-1, + 2.0000000000000000000897E0, +} + +// expm1 computes +// expm1(x) = e^x - 1 +func expm1(x float64) float64 { + if math.IsInf(x, 0) { + if math.IsNaN(x) || x > 0 { + return x + } + return -1 + } + if x < -0.5 || x > 0.5 { + return math.Exp(x) - 1 + } + xx := x * x + r := x * polevl(xx, eP[:], 2) + r = r / (polevl(xx, eQ[:], 3) - r) + return r + r +} + +var coscof = [...]float64{ + 4.7377507964246204691685E-14, + -1.1470284843425359765671E-11, + 2.0876754287081521758361E-9, + -2.7557319214999787979814E-7, + 2.4801587301570552304991E-5, + -1.3888888888888872993737E-3, + 4.1666666666666666609054E-2, +} + +// cosm1 computes +// cosm1(x) = cos(x) - 1 +func cosm1(x float64) float64 { + if x < -pi4 || x > pi4 { + return math.Cos(x) - 1 + } + xx := x * x + xx = -0.5*xx + xx*xx*polevl(xx, coscof[:], 6) + return xx +} + +// lgam1pTayler computes +// lgam(x + 1) +//around x = 0 using its Taylor series. +func lgam1pTaylor(x float64) float64 { + if x == 0 { + return 0 + } + res := -euler * x + xfac := -x + for n := 2; n < 42; n++ { + nf := float64(n) + xfac *= -x + coeff := Zeta(nf, 1) * xfac / nf + res += coeff + if math.Abs(coeff) < machEp*math.Abs(res) { + break + } + } + + return res +} + +// lgam1p computes +// lgam(x + 1) +func lgam1p(x float64) float64 { + if math.Abs(x) <= 0.5 { + return lgam1pTaylor(x) + } else if math.Abs(x-1) < 0.5 { + return math.Log(x) + lgam1pTaylor(x-1) + } + return lgam(x + 1) +} diff --git a/mathext/internal/cephes/zeta.go b/mathext/internal/cephes/zeta.go new file mode 100644 index 00000000..14a41b6f --- /dev/null +++ b/mathext/internal/cephes/zeta.go @@ -0,0 +1,110 @@ +// Derived from SciPy's special/cephes/zeta.c +// https://github.com/scipy/scipy/blob/master/scipy/special/cephes/zeta.c +// Made freely available by Stephen L. Moshier without support or guarantee. + +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Copyright ©1984, ©1987 by Stephen L. Moshier +// Portions Copyright ©2016 The gonum Authors. All rights reserved. + +package cephes + +import "math" + +// zetaCoegs are the expansion coefficients for Euler-Maclaurin summation +// formula: +// \frac{(2k)!}{B_{2k}} +// where +// B_{2k} +// are Bernoulli numbers. +var zetaCoefs = [...]float64{ + 12.0, + -720.0, + 30240.0, + -1209600.0, + 47900160.0, + -1.307674368e12 / 691, + 7.47242496e10, + -1.067062284288e16 / 3617, + 5.109094217170944e18 / 43867, + -8.028576626982912e20 / 174611, + 1.5511210043330985984e23 / 854513, + -1.6938241367317436694528e27 / 236364091, +} + +// Zeta computes the Riemann zeta function of two arguments. +// Zeta(x,q) = \sum_{k=0}^{\infty} (k+q)^{-x} +// Note that Zeta returns +Inf if x is 1 and will panic if x is less than 1, +// q is either zero or a negative integer, or q is negative and x is not an +// integer. +// +// Note that: +// zeta(x,1) = zetac(x) + 1 +func Zeta(x, q float64) float64 { + // REFERENCE: Gradshteyn, I. S., and I. M. Ryzhik, Tables of Integrals, Series, + // and Products, p. 1073; Academic Press, 1980. + if x == 1 { + return math.Inf(1) + } + + if x < 1 { + panic(badParamOutOfBounds) + } + + if q <= 0 { + if q == math.Floor(q) { + panic(badParamFunctionSingularity) + } + if x != math.Floor(x) { + panic(badParamOutOfBounds) // Because q^-x not defined + } + } + + // Asymptotic expansion: http://dlmf.nist.gov/25.11#E43 + if q > 1e8 { + return (1/(x-1) + 1/(2*q)) * math.Pow(q, 1-x) + } + + // The Euler-Maclaurin summation formula is used to obtain the expansion: + // Zeta(x,q) = \sum_{k=1}^n (k+q)^{-x} + \frac{(n+q)^{1-x}}{x-1} - \frac{1}{2(n+q)^x} + \sum_{j=1}^{\infty} \frac{B_{2j}x(x+1)...(x+2j)}{(2j)! (n+q)^{x+2j+1}} + // where + // B_{2j} + // are Bernoulli numbers. + // Permit negative q but continue sum until n+q > 9. This case should be + // handled by a reflection formula. If q<0 and x is an integer, there is a + // relation to the polyGamma function. + s := math.Pow(q, -x) + a := q + i := 0 + b := 0.0 + for i < 9 || a <= 9 { + i++ + a += 1.0 + b = math.Pow(a, -x) + s += b + if math.Abs(b/s) < machEp { + return s + } + } + + w := a + s += b * w / (x - 1) + s -= 0.5 * b + a = 1.0 + k := 0.0 + for _, coef := range zetaCoefs { + a *= x + k + b /= w + t := a * b / coef + s = s + t + t = math.Abs(t / s) + if t < machEp { + return s + } + k += 1.0 + a *= x + k + b /= w + k += 1.0 + } + return s +} diff --git a/mathext/internal/gonum/beta.go b/mathext/internal/gonum/beta.go new file mode 100644 index 00000000..7038c08f --- /dev/null +++ b/mathext/internal/gonum/beta.go @@ -0,0 +1,52 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gonum + +import ( + "math" +) + +// Beta returns the value of the complete beta function B(a, b). It is defined as +// Γ(a)Γ(b) / Γ(a+b) +// Special cases are: +// B(a,b) returns NaN if a or b is Inf +// B(a,b) returns NaN if a and b are 0 +// B(a,b) returns NaN if a or b is NaN +// B(a,b) returns NaN if a or b is < 0 +// B(a,b) returns +Inf if a xor b is 0. +// +// See http://mathworld.wolfram.com/BetaFunction.html for more detailed information. +func Beta(a, b float64) float64 { + return math.Exp(Lbeta(a, b)) +} + +// Lbeta returns the natural logarithm of the complete beta function B(a,b). +// Lbeta is defined as: +// Ln(Γ(a)Γ(b)/Γ(a+b)) +// Special cases are: +// Lbeta(a,b) returns NaN if a or b is Inf +// Lbeta(a,b) returns NaN if a and b are 0 +// Lbeta(a,b) returns NaN if a or b is NaN +// Lbeta(a,b) returns NaN if a or b is < 0 +// Lbeta(a,b) returns +Inf if a xor b is 0. +func Lbeta(a, b float64) float64 { + switch { + case math.IsInf(a, +1) || math.IsInf(b, +1): + return math.NaN() + case a == 0 && b == 0: + return math.NaN() + case a < 0 || b < 0: + return math.NaN() + case math.IsNaN(a) || math.IsNaN(b): + return math.NaN() + case a == 0 || b == 0: + return math.Inf(+1) + } + + la, _ := math.Lgamma(a) + lb, _ := math.Lgamma(b) + lab, _ := math.Lgamma(a + b) + return la + lb - lab +} diff --git a/mathext/internal/gonum/gonum.go b/mathext/internal/gonum/gonum.go new file mode 100644 index 00000000..2aa56ca9 --- /dev/null +++ b/mathext/internal/gonum/gonum.go @@ -0,0 +1,7 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package gonum contains functions implemented by the gonum team. It is here to +// avoid circular imports and/or double coding of functions. +package gonum diff --git a/mathext/mvgamma.go b/mathext/mvgamma.go new file mode 100644 index 00000000..c18b37ad --- /dev/null +++ b/mathext/mvgamma.go @@ -0,0 +1,32 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import "math" + +const ( + logPi = 1.14472988584940017414342735135305871164729481 // http://oeis.org/A053510 +) + +// MvLgamma returns the log of the multivariate Gamma function. Dim +// must be greater than zero, and MvLgamma will return NaN if v < (dim-1)/2. +// +// See https://en.wikipedia.org/wiki/Multivariate_gamma_function for more +// information. +func MvLgamma(v float64, dim int) float64 { + if dim < 1 { + panic("mathext: negative dimension") + } + df := float64(dim) + if v < (df-1)*0.5 { + return math.NaN() + } + ans := df * (df - 1) * 0.25 * logPi + for i := 1; i <= dim; i++ { + lg, _ := math.Lgamma(v + float64(1-i)*0.5) + ans += lg + } + return ans +} diff --git a/mathext/mvgamma_test.go b/mathext/mvgamma_test.go new file mode 100644 index 00000000..f7d309c8 --- /dev/null +++ b/mathext/mvgamma_test.go @@ -0,0 +1,27 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "math" + "testing" +) + +func TestMvLgamma(t *testing.T) { + // Values compared with scipy + for i, test := range []struct { + v float64 + dim int + ans float64 + }{ + {10, 5, 58.893841851237397}, + {3, 1, 0.69314718055994529}, + } { + ans := MvLgamma(test.v, test.dim) + if math.Abs(test.ans-ans) > 1e-14 { + t.Errorf("Case %v. got=%v want=%v.", i, ans, test.ans) + } + } +} diff --git a/mathext/roots.go b/mathext/roots.go new file mode 100644 index 00000000..a5cd329d --- /dev/null +++ b/mathext/roots.go @@ -0,0 +1,178 @@ +// Derived from SciPy's special/c_misc/fsolve.c and special/c_misc/misc.h +// https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/fsolve.c +// https://github.com/scipy/scipy/blob/master/scipy/special/c_misc/misc.h + +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import "math" + +type objectiveFunc func(float64, []float64) float64 + +type fSolveResult uint8 + +const ( + // An exact solution was found, in which case the first point on the + // interval is the value + fSolveExact fSolveResult = iota + 1 + // Interval width is less than the tolerance + fSolveConverged + // Root-finding didn't converge in a set number of iterations + fSolveMaxIterations +) + +const ( + machEp = 1.0 / (1 << 53) +) + +// falsePosition uses a combination of bisection and false position to find a +// root of a function within a given interval. This is guaranteed to converge, +// and always keeps a bounding interval, unlike Newton's method. Inputs are: +// x1, x2: initial bounding interval +// f1, f2: value of f() at x1 and x2 +// absErr, relErr: absolute and relative errors on the bounding interval +// bisectTil: if > 0.0, perform bisection until the width of the bounding +// interval is less than this +// f, fExtra: function to find root of is f(x, fExtra) +// Returns: +// result: whether an exact root was found, the process converged to a +// bounding interval small than the required error, or the max number +// of iterations was hit +// bestX: best root approximation +// bestF: function value at bestX +// errEst: error estimation +func falsePosition(x1, x2, f1, f2, absErr, relErr, bisectTil float64, f objectiveFunc, fExtra []float64) (fSolveResult, float64, float64, float64) { + // The false position steps are either unmodified, or modified with the + // Anderson-Bjorck method as appropiate. Theoretically, this has a "speed of + // convergence" of 1.7 (bisection is 1, Newton is 2). + // Note that this routine was designed initially to work with gammaincinv, so + // it may not be tuned right for other problems. Don't use it blindly. + + if f1*f2 >= 0 { + panic("Initial interval is not a bounding interval") + } + + const ( + maxIterations = 100 + bisectIter = 4 + bisectWidth = 4.0 + ) + + const ( + bisect = iota + 1 + falseP + ) + + var state uint8 + if bisectTil > 0 { + state = bisect + } else { + state = falseP + } + + gamma := 1.0 + + w := math.Abs(x2 - x1) + lastBisectWidth := w + + var nFalseP int + var x3, f3, bestX, bestF float64 + for i := 0; i < maxIterations; i++ { + switch state { + case bisect: + x3 = 0.5 * (x1 + x2) + if x3 == x1 || x3 == x2 { + // i.e., x1 and x2 are successive floating-point numbers + bestX = x3 + if x3 == x1 { + bestF = f1 + } else { + bestF = f2 + } + return fSolveConverged, bestX, bestF, w + } + + f3 = f(x3, fExtra) + if f3 == 0 { + return fSolveExact, x3, f3, w + } + + if f3*f2 < 0 { + x1 = x2 + f1 = f2 + } + x2 = x3 + f2 = f3 + w = math.Abs(x2 - x1) + lastBisectWidth = w + if bisectTil > 0 { + if w < bisectTil { + bisectTil = -1.0 + gamma = 1.0 + nFalseP = 0 + state = falseP + } + } else { + gamma = 1.0 + nFalseP = 0 + state = falseP + } + case falseP: + s12 := (f2 - gamma*f1) / (x2 - x1) + x3 = x2 - f2/s12 + f3 = f(x3, fExtra) + if f3 == 0 { + return fSolveExact, x3, f3, w + } + + nFalseP++ + if f3*f2 < 0 { + gamma = 1.0 + x1 = x2 + f1 = f2 + } else { + // Anderson-Bjorck method + g := 1.0 - f3/f2 + if g <= 0 { + g = 0.5 + } + gamma *= g + } + x2 = x3 + f2 = f3 + w = math.Abs(x2 - x1) + + // Sanity check. For every 4 false position checks, see if we really are + // decreasing the interval by comparing to what bisection would have + // achieved (or, rather, a bit more lenient than that -- interval + // decreased by 4 instead of by 16, as the fp could be decreasing gamma + // for a bit). Note that this should guarantee convergence, as it makes + // sure that we always end up decreasing the interval width with a + // bisection. + if nFalseP > bisectIter { + if w*bisectWidth > lastBisectWidth { + state = bisect + } + nFalseP = 0 + lastBisectWidth = w + } + } + + tol := absErr + relErr*math.Max(math.Max(math.Abs(x1), math.Abs(x2)), 1.0) + if w <= tol { + if math.Abs(f1) < math.Abs(f2) { + bestX = x1 + bestF = f1 + } else { + bestX = x2 + bestF = f2 + } + return fSolveConverged, bestX, bestF, w + } + } + + return fSolveMaxIterations, x3, f3, w +} diff --git a/mathext/zeta.go b/mathext/zeta.go new file mode 100644 index 00000000..920a7e6e --- /dev/null +++ b/mathext/zeta.go @@ -0,0 +1,20 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import "gonum.org/v1/gonum/mathext/internal/cephes" + +// Zeta computes the Riemann zeta function of two arguments. +// Zeta(x,q) = \sum_{k=0}^{\infty} (k+q)^{-x} +// Note that Zeta returns +Inf if x is 1 and will panic if x is less than 1, +// q is either zero or a negative integer, or q is negative and x is not an +// integer. +// +// See http://mathworld.wolfram.com/HurwitzZetaFunction.html +// or https://en.wikipedia.org/wiki/Multiple_zeta_function#Two_parameters_case +// for more detailed information. +func Zeta(x, q float64) float64 { + return cephes.Zeta(x, q) +} diff --git a/mathext/zeta_test.go b/mathext/zeta_test.go new file mode 100644 index 00000000..e415818f --- /dev/null +++ b/mathext/zeta_test.go @@ -0,0 +1,42 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mathext + +import ( + "math" + "testing" +) + +func TestZeta(t *testing.T) { + for i, test := range []struct { + x, q, want float64 + }{ + // Results computed using scipy.special.zeta + {1, 1, math.Inf(1)}, + {1.00001, 0.5, 100001.96352290553}, + {1.0001, 25, 9996.8017690244506}, + {1.001, 1, 1000.5772884760117}, + {1.01, 10, 97.773405639173305}, + {1.5, 2, 1.6123753486854886}, + {1.5, 20, 0.45287361712938717}, + {2, -0.7, 14.28618087263834}, + {2.5, 0.5, 6.2471106345688137}, + {5, 2.5, 0.013073166646113805}, + {7.5, 5, 7.9463377443314306e-06}, + {10, -0.5, 2048.0174503557578}, + {10, 0.5, 1024.0174503557578}, + {10, 7.5, 2.5578265694201971e-9}, + {12, 2.5, 1.7089167198843551e-5}, + {17, 0.5, 131072.00101513157}, + {20, -2.5, 2097152.0006014798}, + {20, 0.75, 315.3368689825316}, + {25, 0.25, 1125899906842624.0}, + {30, 1, 1.0000000009313275}, + } { + if got := Zeta(test.x, test.q); math.Abs(got-test.want) > 1e-10 { + t.Errorf("test %d Zeta(%g, %g) failed: got %g want %g", i, test.x, test.q, got, test.want) + } + } +} diff --git a/matrix/.travis/check-generate.sh b/matrix/.travis/check-generate.sh new file mode 100755 index 00000000..446d5d95 --- /dev/null +++ b/matrix/.travis/check-generate.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +go generate github.com/gonum/matrix +if [ -n "$(git diff)" ]; then + exit 1 +fi diff --git a/matrix/README.md b/matrix/README.md new file mode 100644 index 00000000..f89313da --- /dev/null +++ b/matrix/README.md @@ -0,0 +1,13 @@ +# Gonum Matrix [![Build Status](https://travis-ci.org/gonum/matrix.svg?branch=master)](https://travis-ci.org/gonum/matrix) [![Coverage Status](https://coveralls.io/repos/gonum/matrix/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/matrix?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/matrix?status.svg)](https://godoc.org/github.com/gonum/matrix) + +This is a matrix package for the Go language. + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/matrix/cmat128/doc.go b/matrix/cmat128/doc.go new file mode 100644 index 00000000..c47b8ffd --- /dev/null +++ b/matrix/cmat128/doc.go @@ -0,0 +1,95 @@ +// Generated by running +// go generate github.com/gonum/matrix +// DO NOT EDIT. + +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cmat128 provides implementations of complex128 matrix structures and +// linear algebra operations on them. +// +// Overview +// +// This section provides a quick overview of the cmat128 package. The following +// sections provide more in depth commentary. +// +// cmat128 provides: +// - Interfaces for a complex Matrix +// +// BLAS and LAPACK +// +// BLAS and LAPACK are the standard APIs for linear algebra routines. Many +// operations in cmat128 are implemented using calls to the wrapper functions +// in gonum/blas/cblas128 and gonum/lapack/clapack128. By default, cblas128 and +// clapack128 call the native Go implementations of the routines. Alternatively, +// it is possible to use C-based implementations of the APIs through the respective +// cgo packages and "Use" functions. The Go implementation of LAPACK makes calls +// through cblas128, so if a cgo BLAS implementation is registered, the clapack128 +// calls will be partially executed in Go and partially executed in C. +// +// Type Switching +// +// The Matrix abstraction enables efficiency as well as interoperability. Go's +// type reflection capabilities are used to choose the most efficient routine +// given the specific concrete types. For example, in +// c.Mul(a, b) +// if a and b both implement RawMatrixer, that is, they can be represented as a +// cblas128.General, cblas128.Gemm (general matrix multiplication) is called, while +// instead if b is a RawSymmetricer cblas128.Symm is used (general-symmetric +// multiplication), and if b is a *Vector cblas128.Gemv is used. +// +// There are many possible type combinations and special cases. No specific guarantees +// are made about the performance of any method, and in particular, note that an +// abstract matrix type may be copied into a concrete type of the corresponding +// value. If there are specific special cases that are needed, please submit a +// pull-request or file an issue. +// +// Invariants +// +// Matrix input arguments to functions are never directly modified. If an operation +// changes Matrix data, the mutated matrix will be the receiver of a function. +// +// For convenience, a matrix may be used as both a receiver and as an input, e.g. +// a.Pow(a, 6) +// v.SolveVec(a.T(), v) +// though in many cases this will cause an allocation (see Element Aliasing). +// An exception to this rule is Copy, which does not allow a.Copy(a.T()). +// +// Element Aliasing +// +// Most methods in cmat128 modify receiver data. It is forbidden for the modified +// data region of the receiver to overlap the used data area of the input +// arguments. The exception to this rule is when the method receiver is equal to one +// of the input arguments, as in the a.Pow(a, 6) call above, or its implicit transpose. +// +// This prohibition is to help avoid subtle mistakes when the method needs to read +// from and write to the same data region. There are ways to make mistakes using the +// cmat128 API, and cmat128 functions will detect and complain about those. +// There are many ways to make mistakes by excursion from the cmat128 API via +// interaction with raw matrix values. +// +// If you need to read the rest of this section to understand the behavior of +// your program, you are being clever. Don't be clever. If you must be clever, +// cblas128 and clapack128 may be used to call the behavior directly. +// +// cmat128 will use the following rules to detect overlap between the receiver and one +// of the inputs: +// - the input implements one of the Raw methods, and +// - the Raw type matches that of the receiver or +// one is a RawMatrixer and the other is a RawVectorer, and +// - the address ranges of the backing data slices overlap, and +// - the strides differ or there is an overlap in the used data elements. +// If such an overlap is detected, the method will panic. +// +// The following cases will not panic: +// - the data slices do not overlap, +// - there is pointer identity between the receiver and input values after +// the value has been untransposed if necessary. +// +// cmat128 will not attempt to detect element overlap if the input does not implement a +// Raw method, or if the Raw method differs from that of the receiver except when a +// conversion has occurred through a cmat128 API function. Method behavior is undefined +// if there is undetected overlap. +// +package cmat128 diff --git a/matrix/cmat128/matrix.go b/matrix/cmat128/matrix.go new file mode 100644 index 00000000..cfe5ec80 --- /dev/null +++ b/matrix/cmat128/matrix.go @@ -0,0 +1,71 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cmat128 + +// Matrix is the basic matrix interface type. +type Matrix interface { + // Dims returns the dimensions of a Matrix. + Dims() (r, c int) + + // At returns the value of a matrix element at row i, column j. + // It will panic if i or j are out of bounds for the matrix. + At(i, j int) complex128 + + // H returns the conjugate transpose of the Matrix. Whether H + // returns a copy of the underlying data is implementation dependent. + // This method may be implemented using the Conjugate type, which + // provides an implicit matrix conjugate transpose. + H() Matrix +} + +var ( + _ Matrix = Conjugate{} + _ Unconjugator = Conjugate{} +) + +// Conjugate is a type for performing an implicit matrix conjugate transpose. +// It implements the Matrix interface, returning values from the conjugate +// transpose of the matrix within. +type Conjugate struct { + Matrix Matrix +} + +// At returns the value of the element at row i and column j of the transposed +// matrix, that is, row j and column i of the Matrix field. +func (t Conjugate) At(i, j int) complex128 { + z := t.Matrix.At(j, i) + return complex(real(z), -imag(z)) +} + +// Dims returns the dimensions of the transposed matrix. The number of rows returned +// is the number of columns in the Matrix field, and the number of columns is +// the number of rows in the Matrix field. +func (t Conjugate) Dims() (r, c int) { + c, r = t.Matrix.Dims() + return r, c +} + +// H performs an implicit conjugate transpose by returning the Matrix field. +func (t Conjugate) H() Matrix { + return t.Matrix +} + +// Unconjugate returns the Matrix field. +func (t Conjugate) Unconjugate() Matrix { + return t.Matrix +} + +// Unconjugator is a type that can undo an implicit conjugate transpose. +type Unconjugator interface { + // Note: This interface is needed to unify all of the Conjugate types. In + // the cmat128 methods, we need to test if the Matrix has been implicitly + // transposed. If this is checked by testing for the specific Conjugate type + // then the behavior will be different if the user uses H() or HTri() for a + // triangular matrix. + + // Unconjugate returns the underlying Matrix stored for the implicit + // conjugate transpose. + Unconjugate() Matrix +} diff --git a/matrix/consts.go b/matrix/consts.go new file mode 100644 index 00000000..b288b272 --- /dev/null +++ b/matrix/consts.go @@ -0,0 +1,54 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package matrix + +// TriKind represents the triangularity of the matrix. +type TriKind bool + +const ( + // Upper specifies an upper triangular matrix. + Upper TriKind = true + // Lower specifies a lower triangular matrix. + Lower TriKind = false +) + +// SVDKind specifies the treatment of singular vectors during an SVD +// factorization. +type SVDKind int + +const ( + // SVDNone specifies that no singular vectors should be computed during + // the decomposition. + SVDNone SVDKind = iota + 1 + // SVDThin computes the thin singular vectors, that is, it computes + // A = U~ * Σ * V~^T + // where U~ is of size m×min(m,n), Σ is a diagonal matrix of size min(m,n)×min(m,n) + // and V~ is of size n×min(m,n). + SVDThin + // SVDFull computes the full singular value decomposition, + // A = U * Σ * V^T + // where U is of size m×m, Σ is an m×n diagonal matrix, and V is an n×n matrix. + SVDFull +) + +// GSVDKind specifies the treatment of singular vectors during a GSVD +// factorization. +type GSVDKind int + +const ( + // GSVDU specifies that the U singular vectors should be computed during + // the decomposition. + GSVDU GSVDKind = 1 << iota + // GSVDV specifies that the V singular vectors should be computed during + // the decomposition. + GSVDV + // GSVDQ specifies that the Q singular vectors should be computed during + // the decomposition. + GSVDQ + + // GSVDNone specifies that no singular vector should be computed during + // the decomposition. + GSVDNone +) diff --git a/matrix/conv/conv.go b/matrix/conv/conv.go new file mode 100644 index 00000000..4b691123 --- /dev/null +++ b/matrix/conv/conv.go @@ -0,0 +1,142 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package conv provides matrix type interconversion utilities. +package conv + +import ( + "gonum.org/v1/gonum/matrix" + "gonum.org/v1/gonum/matrix/cmat128" + "gonum.org/v1/gonum/matrix/mat64" +) + +// Complex is a complex matrix constructed from two real matrices. +type Complex struct { + // r and i are not exposed to ensure that + // their dimensions can not be altered by + // clients behind our back. + r, i mat64.Matrix + + // imagSign holds the sign of the imaginary + // part of the Complex. Valid values are 1 and -1. + imagSign float64 +} + +var ( + _ Realer = Complex{} + _ Imager = Complex{} +) + +// NewComplex returns a complex matrix constructed from r and i. At least one of +// r or i must be non-nil otherwise NewComplex will panic. If one of the inputs +// is nil, that part of the complex number will be zero when returned by At. +// If both are non-nil but differ in their sizes, NewComplex will panic. +func NewComplex(r, i mat64.Matrix) Complex { + if r == nil && i == nil { + panic("conv: no matrix") + } else if r != nil && i != nil { + rr, rc := r.Dims() + ir, ic := i.Dims() + if rr != ir || rc != ic { + panic(matrix.ErrShape) + } + } + return Complex{r: r, i: i, imagSign: 1} +} + +// Dims returns the number of rows and columns in the matrix. +func (m Complex) Dims() (r, c int) { + if m.r == nil { + return m.i.Dims() + } + return m.r.Dims() +} + +// At returns the element at row i, column j. +func (m Complex) At(i, j int) complex128 { + if m.i == nil { + return complex(m.r.At(i, j), 0) + } + if m.r == nil { + return complex(0, m.imagSign*m.i.At(i, j)) + } + return complex(m.r.At(i, j), m.imagSign*m.i.At(i, j)) +} + +// H performs an implicit transpose. +func (m Complex) H() cmat128.Matrix { + if m.i == nil { + return Complex{r: m.r.T()} + } + if m.r == nil { + return Complex{i: m.i.T(), imagSign: -m.imagSign} + } + return Complex{r: m.r.T(), i: m.i.T(), imagSign: -m.imagSign} +} + +// Real returns the real part of the receiver. +func (m Complex) Real() mat64.Matrix { return m.r } + +// Imag returns the imaginary part of the receiver. +func (m Complex) Imag() mat64.Matrix { return m.i } + +// Realer is a complex matrix that can return its real part. +type Realer interface { + Real() mat64.Matrix +} + +// Imager is a complex matrix that can return its imaginary part. +type Imager interface { + Imag() mat64.Matrix +} + +// Real is the real part of a complex matrix. +type Real struct { + matrix cmat128.Matrix +} + +// NewReal returns a mat64.Matrix representing the real part of m. If m is a Realer, +// the real part is returned. +func NewReal(m cmat128.Matrix) mat64.Matrix { + if m, ok := m.(Realer); ok { + return m.Real() + } + return Real{m} +} + +// Dims returns the number of rows and columns in the matrix. +func (m Real) Dims() (r, c int) { return m.matrix.Dims() } + +// At returns the element at row i, column j. +func (m Real) At(i, j int) float64 { return real(m.matrix.At(i, j)) } + +// T performs an implicit transpose. +func (m Real) T() mat64.Matrix { return Real{m.matrix.H()} } + +// Imag is the imaginary part of a complex matrix. +type Imag struct { + matrix cmat128.Matrix + + // conjSign holds the sign of the matrix. + // Valid values are 1 and -1. + conjSign float64 +} + +// NewImag returns a mat64.Matrix representing the imaginary part of m. If m is an Imager, +// the imaginary part is returned. +func NewImag(m cmat128.Matrix) mat64.Matrix { + if m, ok := m.(Imager); ok { + return m.Imag() + } + return Imag{matrix: m, conjSign: 1} +} + +// Dims returns the number of rows and columns in the matrix. +func (m Imag) Dims() (r, c int) { return m.matrix.Dims() } + +// At returns the element at row i, column j. +func (m Imag) At(i, j int) float64 { return m.conjSign * imag(m.matrix.At(i, j)) } + +// T performs an implicit transpose. +func (m Imag) T() mat64.Matrix { return Imag{matrix: m.matrix.H(), conjSign: -m.conjSign} } diff --git a/matrix/doc.go b/matrix/doc.go new file mode 100644 index 00000000..c94f8df1 --- /dev/null +++ b/matrix/doc.go @@ -0,0 +1,103 @@ +// Generated by running +// go generate github.com/gonum/matrix +// DO NOT EDIT. + +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package matrix provides common error handling mechanisms for matrix operations +// in mat64 and cmat128. +// +// Overview +// +// This section provides a quick overview of the matrix package. The following +// sections provide more in depth commentary. +// +// matrix provides: +// - Error type definitions +// - Error recovery mechanisms +// - Common constants used by mat64 and cmat128 +// +// Errors +// +// The mat64 and cmat128 matrix packages share a common set of errors +// provided by matrix via the matrix.Error type. +// +// Errors are either returned directly or used as the parameter of a panic +// depending on the class of error encountered. Returned errors indicate +// that a call was not able to complete successfully while panics generally +// indicate a programmer or unrecoverable error. +// +// Examples of each type are found in the mat64 Solve methods, which find +// x such that A*x = b. +// +// An error value is returned from the function or method when the operation +// can meaningfully fail. The Solve operation cannot complete if A is +// singular. However, determining the singularity of A is most easily +// discovered during the Solve procedure itself and is a valid result from +// the operation, so in this case an error is returned. +// +// A function will panic when the input parameters are inappropriate for +// the function. In Solve, for example, the number of rows of each input +// matrix must be equal because of the rules of matrix multiplication. +// Similarly, for solving A*x = b, a non-zero receiver must have the same +// number of rows as A has columns and must have the same number of columns +// as b. In all cases where a function will panic, conditions that would +// lead to a panic can easily be checked prior to a call. +// +// Error Recovery +// +// When a matrix.Error is the parameter of a panic, the panic can be +// recovered by a Maybe function, which will then return the error. +// Panics that are not of type matrix.Error are re-panicked by the +// Maybe functions. +// +// Invariants +// +// Matrix input arguments to functions are never directly modified. If an operation +// changes Matrix data, the mutated matrix will be the receiver of a function. +// +// For convenience, a matrix may be used as both a receiver and as an input, e.g. +// a.Pow(a, 6) +// v.SolveVec(a.T(), v) +// though in many cases this will cause an allocation (see Element Aliasing). +// An exception to this rule is Copy, which does not allow a.Copy(a.T()). +// +// Element Aliasing +// +// Most methods in the matrix packages modify receiver data. It is forbidden for the modified +// data region of the receiver to overlap the used data area of the input +// arguments. The exception to this rule is when the method receiver is equal to one +// of the input arguments, as in the a.Pow(a, 6) call above, or its implicit transpose. +// +// This prohibition is to help avoid subtle mistakes when the method needs to read +// from and write to the same data region. There are ways to make mistakes using the +// matrix API, and matrix functions will detect and complain about those. +// There are many ways to make mistakes by excursion from the matrix API via +// interaction with raw matrix values. +// +// If you need to read the rest of this section to understand the behavior of +// your program, you are being clever. Don't be clever. If you must be clever, +// blas64/cblas128 and lapack64/clapack128 may be used to call the behavior directly. +// +// The matrix packages will use the following rules to detect overlap between the receiver and one +// of the inputs: +// - the input implements one of the Raw methods, and +// - the Raw type matches that of the receiver or +// one is a RawMatrixer and the other is a RawVectorer, and +// - the address ranges of the backing data slices overlap, and +// - the strides differ or there is an overlap in the used data elements. +// If such an overlap is detected, the method will panic. +// +// The following cases will not panic: +// - the data slices do not overlap, +// - there is pointer identity between the receiver and input values after +// the value has been untransposed if necessary. +// +// The matrix packages will not attempt to detect element overlap if the input does not implement a +// Raw method, or if the Raw method differs from that of the receiver except when a +// conversion has occurred through a matrix API function. Method behavior is undefined +// if there is undetected overlap. +// +package matrix diff --git a/matrix/errors.go b/matrix/errors.go new file mode 100644 index 00000000..ea0f92c9 --- /dev/null +++ b/matrix/errors.go @@ -0,0 +1,147 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package matrix + +import ( + "fmt" + "runtime" + + "gonum.org/v1/gonum/lapack" +) + +// Condition is the condition number of a matrix. The condition +// number is defined as ||A|| * ||A^-1||. +// +// One important use of Condition is during linear solve routines (finding x such +// that A * x = b). The condition number of A indicates the accuracy of +// the computed solution. A Condition error will be returned if the condition +// number of A is sufficiently large. If A is exactly singular to working precision, +// Condition == ∞, and the solve algorithm may have completed early. If Condition +// is large and finite the solve algorithm will be performed, but the computed +// solution may be innacurate. Due to the nature of finite precision arithmetic, +// the value of Condition is only an approximate test of singularity. +type Condition float64 + +func (c Condition) Error() string { + return fmt.Sprintf("matrix singular or near-singular with condition number %.4e", c) +} + +// ConditionTolerance is the tolerance limit of the condition number. If the +// condition number is above this value, the matrix is considered singular. +const ConditionTolerance = 1e16 + +const ( + // CondNorm is the matrix norm used for computing the condition number by routines + // in the matrix packages. + CondNorm = lapack.MaxRowSum + + // CondNormTrans is the norm used to compute on A^T to get the same result as + // computing CondNorm on A. + CondNormTrans = lapack.MaxColumnSum +) + +const stackTraceBufferSize = 1 << 20 + +// Maybe will recover a panic with a type mat64.Error from fn, and return this error +// as the Err field of an ErrorStack. The stack trace for the panicking function will be +// recovered and placed in the StackTrace field. Any other error is re-panicked. +func Maybe(fn func()) (err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(Error); ok { + if e.string == "" { + panic("mat64: invalid error") + } + buf := make([]byte, stackTraceBufferSize) + n := runtime.Stack(buf, false) + err = ErrorStack{Err: e, StackTrace: string(buf[:n])} + return + } + panic(r) + } + }() + fn() + return +} + +// MaybeFloat will recover a panic with a type mat64.Error from fn, and return this error +// as the Err field of an ErrorStack. The stack trace for the panicking function will be +// recovered and placed in the StackTrace field. Any other error is re-panicked. +func MaybeFloat(fn func() float64) (f float64, err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(Error); ok { + if e.string == "" { + panic("mat64: invalid error") + } + buf := make([]byte, stackTraceBufferSize) + n := runtime.Stack(buf, false) + err = ErrorStack{Err: e, StackTrace: string(buf[:n])} + return + } + panic(r) + } + }() + return fn(), nil +} + +// MaybeComplex will recover a panic with a type mat64.Error from fn, and return this error +// as the Err field of an ErrorStack. The stack trace for the panicking function will be +// recovered and placed in the StackTrace field. Any other error is re-panicked. +func MaybeComplex(fn func() complex128) (f complex128, err error) { + defer func() { + if r := recover(); r != nil { + if e, ok := r.(Error); ok { + if e.string == "" { + panic("mat64: invalid error") + } + buf := make([]byte, stackTraceBufferSize) + n := runtime.Stack(buf, false) + err = ErrorStack{Err: e, StackTrace: string(buf[:n])} + return + } + panic(r) + } + }() + return fn(), nil +} + +// Error represents matrix handling errors. These errors can be recovered by Maybe wrappers. +type Error struct{ string } + +func (err Error) Error() string { return err.string } + +var ( + ErrIndexOutOfRange = Error{"matrix: index out of range"} + ErrRowAccess = Error{"matrix: row index out of range"} + ErrColAccess = Error{"matrix: column index out of range"} + ErrVectorAccess = Error{"matrix: vector index out of range"} + ErrZeroLength = Error{"matrix: zero length in matrix definition"} + ErrRowLength = Error{"matrix: row length mismatch"} + ErrColLength = Error{"matrix: col length mismatch"} + ErrSquare = Error{"matrix: expect square matrix"} + ErrNormOrder = Error{"matrix: invalid norm order for matrix"} + ErrSingular = Error{"matrix: matrix is singular"} + ErrShape = Error{"matrix: dimension mismatch"} + ErrIllegalStride = Error{"matrix: illegal stride"} + ErrPivot = Error{"matrix: malformed pivot list"} + ErrTriangle = Error{"matrix: triangular storage mismatch"} + ErrTriangleSet = Error{"matrix: triangular set out of bounds"} + ErrSliceLengthMismatch = Error{"matrix: input slice length mismatch"} + ErrNotPSD = Error{"matrix: input not positive symmetric definite"} + ErrFailedEigen = Error{"matrix: eigendecomposition not successful"} +) + +// ErrorStack represents matrix handling errors that have been recovered by Maybe wrappers. +type ErrorStack struct { + Err error + + // StackTrace is the stack trace + // recovered by Maybe, MaybeFloat + // or MaybeComplex. + StackTrace string +} + +func (err ErrorStack) Error() string { return err.Err.Error() } diff --git a/matrix/errors_test.go b/matrix/errors_test.go new file mode 100644 index 00000000..c144a2e6 --- /dev/null +++ b/matrix/errors_test.go @@ -0,0 +1,56 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package matrix + +import "testing" + +func leaksPanic(fn func()) (panicked bool) { + defer func() { + r := recover() + panicked = r != nil + }() + Maybe(fn) + return +} + +func TestMaybe(t *testing.T) { + for i, test := range []struct { + fn func() + panics bool + errors bool + }{ + { + fn: func() {}, + panics: false, + errors: false, + }, + { + fn: func() { panic("panic") }, + panics: true, + errors: false, + }, + { + fn: func() { panic(Error{"panic"}) }, + panics: false, + errors: true, + }, + } { + panicked := leaksPanic(test.fn) + if panicked != test.panics { + t.Errorf("unexpected panic state for test %d: got: panicked=%t want: panicked=%t", + i, panicked, test.panics) + } + if test.errors { + err := Maybe(test.fn) + stack, ok := err.(ErrorStack) + if !ok { + t.Errorf("unexpected error type: got:%T want:%T", stack, ErrorStack{}) + } + if stack.StackTrace == "" { + t.Error("expected non-empty stack trace") + } + } + } +} diff --git a/matrix/gendoc.go b/matrix/gendoc.go new file mode 100644 index 00000000..f82b6b20 --- /dev/null +++ b/matrix/gendoc.go @@ -0,0 +1,343 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build ignore + +// gendoc creates the matrix, mat64 and cmat128 package doc comments. +package main + +import ( + "fmt" + "log" + "os" + "path/filepath" + "strings" + "text/template" + "unicode/utf8" +) + +var docs = template.Must(template.New("docs").Funcs(funcs).Parse(`{{define "common"}}// Generated by running +// go generate github.com/gonum/matrix +// DO NOT EDIT. + +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package {{.Name}} provides {{.Provides}} +// +// Overview +// +// This section provides a quick overview of the {{.Name}} package. The following +// sections provide more in depth commentary. +// +{{.Overview}} +//{{end}} +{{define "interfaces"}}// The Matrix Interfaces +// +// The Matrix interface is the common link between the concrete types. The Matrix +// interface is defined by three functions: Dims, which returns the dimensions +// of the Matrix, At, which returns the element in the specified location, and +// T for returning a Transpose (discussed later). All of the concrete types can +// perform these behaviors and so implement the interface. Methods and functions +// are designed to use this interface, so in particular the method +// func (m *Dense) Mul(a, b Matrix) +// constructs a *Dense from the result of a multiplication with any Matrix types, +// not just *Dense. Where more restrictive requirements must be met, there are also the +// Symmetric and Triangular interfaces. For example, in +// func (s *SymDense) AddSym(a, b Symmetric) +// the Symmetric interface guarantees a symmetric result. +// +// Transposes +// +// The T method is used for transposition. For example, c.Mul(a.T(), b) computes +// c = a^T * b. The {{if .ExamplePackage}}{{.ExamplePackage}}{{else}}{{.Name}}{{end}} types implement this method using an implicit transpose — +// see the Transpose type for more details. Note that some operations have a +// transpose as part of their definition, as in *SymDense.SymOuterK. +//{{end}} +{{define "factorization"}}// Matrix Factorization +// +// Matrix factorizations, such as the LU decomposition, typically have their own +// specific data storage, and so are each implemented as a specific type. The +// factorization can be computed through a call to Factorize +// var lu {{if .ExamplePackage}}{{.ExamplePackage}}{{else}}{{.Name}}{{end}}.LU +// lu.Factorize(a) +// The elements of the factorization can be extracted through methods on the +// appropriate type, i.e. *TriDense.LFromLU and *TriDense.UFromLU. Alternatively, +// they can be used directly, as in *Dense.SolveLU. Some factorizations can be +// updated directly, without needing to update the original matrix and refactorize, +// as in *LU.RankOne. +//{{end}} +{{define "blas"}}// BLAS and LAPACK +// +// BLAS and LAPACK are the standard APIs for linear algebra routines. Many +// operations in {{if .Description}}{{.Description}}{{else}}{{.Name}}{{end}} are implemented using calls to the wrapper functions +// in gonum/blas/{{.BLAS|alts}} and gonum/lapack/{{.LAPACK|alts}}. By default, {{.BLAS|join "/"}} and +// {{.LAPACK|join "/"}} call the native Go implementations of the routines. Alternatively, +// it is possible to use C-based implementations of the APIs through the respective +// cgo packages and "Use" functions. The Go implementation of LAPACK makes calls +// through {{.BLAS|join "/"}}, so if a cgo BLAS implementation is registered, the {{.LAPACK|join "/"}} +// calls will be partially executed in Go and partially executed in C. +//{{end}} +{{define "switching"}}// Type Switching +// +// The Matrix abstraction enables efficiency as well as interoperability. Go's +// type reflection capabilities are used to choose the most efficient routine +// given the specific concrete types. For example, in +// c.Mul(a, b) +// if a and b both implement RawMatrixer, that is, they can be represented as a +// {{.BLAS|alts}}.General, {{.BLAS|alts}}.Gemm (general matrix multiplication) is called, while +// instead if b is a RawSymmetricer {{.BLAS|alts}}.Symm is used (general-symmetric +// multiplication), and if b is a *Vector {{.BLAS|alts}}.Gemv is used. +// +// There are many possible type combinations and special cases. No specific guarantees +// are made about the performance of any method, and in particular, note that an +// abstract matrix type may be copied into a concrete type of the corresponding +// value. If there are specific special cases that are needed, please submit a +// pull-request or file an issue. +//{{end}} +{{define "invariants"}}// Invariants +// +// Matrix input arguments to functions are never directly modified. If an operation +// changes Matrix data, the mutated matrix will be the receiver of a function. +// +// For convenience, a matrix may be used as both a receiver and as an input, e.g. +// a.Pow(a, 6) +// v.SolveVec(a.T(), v) +// though in many cases this will cause an allocation (see Element Aliasing). +// An exception to this rule is Copy, which does not allow a.Copy(a.T()). +//{{end}} +{{define "aliasing"}}// Element Aliasing +// +// Most methods in {{if .Description}}{{.Description}}{{else}}{{.Name}}{{end}} modify receiver data. It is forbidden for the modified +// data region of the receiver to overlap the used data area of the input +// arguments. The exception to this rule is when the method receiver is equal to one +// of the input arguments, as in the a.Pow(a, 6) call above, or its implicit transpose. +// +// This prohibition is to help avoid subtle mistakes when the method needs to read +// from and write to the same data region. There are ways to make mistakes using the +// {{.Name}} API, and {{.Name}} functions will detect and complain about those. +// There are many ways to make mistakes by excursion from the {{.Name}} API via +// interaction with raw matrix values. +// +// If you need to read the rest of this section to understand the behavior of +// your program, you are being clever. Don't be clever. If you must be clever, +// {{.BLAS|join "/"}} and {{.LAPACK|join "/"}} may be used to call the behavior directly. +// +// {{if .Description}}{{.Description|sentence}}{{else}}{{.Name}}{{end}} will use the following rules to detect overlap between the receiver and one +// of the inputs: +// - the input implements one of the Raw methods, and +// - the Raw type matches that of the receiver or +// one is a RawMatrixer and the other is a RawVectorer, and +// - the address ranges of the backing data slices overlap, and +// - the strides differ or there is an overlap in the used data elements. +// If such an overlap is detected, the method will panic. +// +// The following cases will not panic: +// - the data slices do not overlap, +// - there is pointer identity between the receiver and input values after +// the value has been untransposed if necessary. +// +// {{if .Description}}{{.Description|sentence}}{{else}}{{.Name}}{{end}} will not attempt to detect element overlap if the input does not implement a +// Raw method, or if the Raw method differs from that of the receiver except when a +// conversion has occurred through a {{.Name}} API function. Method behavior is undefined +// if there is undetected overlap. +//{{end}}`)) + +type Package struct { + path string + + Name string + Provides string + Description string + ExamplePackage string + Overview string + + BLAS []string + LAPACK []string + + template string +} + +var pkgs = []Package{ + { + path: ".", + + Name: "matrix", + Description: "the matrix packages", + Provides: `common error handling mechanisms for matrix operations +// in mat64 and cmat128.`, + ExamplePackage: "mat64", + + Overview: `// matrix provides: +// - Error type definitions +// - Error recovery mechanisms +// - Common constants used by mat64 and cmat128 +// +// Errors +// +// The mat64 and cmat128 matrix packages share a common set of errors +// provided by matrix via the matrix.Error type. +// +// Errors are either returned directly or used as the parameter of a panic +// depending on the class of error encountered. Returned errors indicate +// that a call was not able to complete successfully while panics generally +// indicate a programmer or unrecoverable error. +// +// Examples of each type are found in the mat64 Solve methods, which find +// x such that A*x = b. +// +// An error value is returned from the function or method when the operation +// can meaningfully fail. The Solve operation cannot complete if A is +// singular. However, determining the singularity of A is most easily +// discovered during the Solve procedure itself and is a valid result from +// the operation, so in this case an error is returned. +// +// A function will panic when the input parameters are inappropriate for +// the function. In Solve, for example, the number of rows of each input +// matrix must be equal because of the rules of matrix multiplication. +// Similarly, for solving A*x = b, a non-zero receiver must have the same +// number of rows as A has columns and must have the same number of columns +// as b. In all cases where a function will panic, conditions that would +// lead to a panic can easily be checked prior to a call. +// +// Error Recovery +// +// When a matrix.Error is the parameter of a panic, the panic can be +// recovered by a Maybe function, which will then return the error. +// Panics that are not of type matrix.Error are re-panicked by the +// Maybe functions.`, + BLAS: []string{"blas64", "cblas128"}, + LAPACK: []string{"lapack64", "clapack128"}, + + template: `{{template "common" .}} +{{template "invariants" .}} +{{template "aliasing" .}} +package {{.Name}} +`, + }, + { + path: "mat64", + + Name: "mat64", + Provides: `implementations of float64 matrix structures and +// linear algebra operations on them.`, + + Overview: `// mat64 provides: +// - Interfaces for Matrix classes (Matrix, Symmetric, Triangular) +// - Concrete implementations (Dense, SymDense, TriDense) +// - Methods and functions for using matrix data (Add, Trace, SymRankOne) +// - Types for constructing and using matrix factorizations (QR, LU) +// +// A matrix may be constructed through the corresponding New function. If no +// backing array is provided the matrix will be initialized to all zeros. +// // Allocate a zeroed matrix of size 3×5 +// zero := mat64.NewDense(3, 5, nil) +// If a backing data slice is provided, the matrix will have those elements. +// Matrices are all stored in row-major format. +// // Generate a 6×6 matrix of random values. +// data := make([]float64, 36) +// for i := range data { +// data[i] = rand.NormFloat64() +// } +// a := mat64.NewDense(6, 6, data) +// +// Operations involving matrix data are implemented as functions when the values +// of the matrix remain unchanged +// tr := mat64.Trace(a) +// and are implemented as methods when the operation modifies the receiver. +// zero.Copy(a) +// +// Receivers must be the correct size for the matrix operations, otherwise the +// operation will panic. As a special case for convenience, a zero-sized matrix +// will be modified to have the correct size, allocating data if necessary. +// var c mat64.Dense // construct a new zero-sized matrix +// c.Mul(a, a) // c is automatically adjusted to be 6×6`, + + BLAS: []string{"blas64"}, + LAPACK: []string{"lapack64"}, + + template: `{{template "common" .}} +{{template "interfaces" .}} +{{template "factorization" .}} +{{template "blas" .}} +{{template "switching" .}} +{{template "invariants" .}} +{{template "aliasing" .}} +package {{.Name}} +`, + }, + { + path: "cmat128", + + Name: "cmat128", + Provides: `implementations of complex128 matrix structures and +// linear algebra operations on them.`, + + Overview: `// cmat128 provides: +// - Interfaces for a complex Matrix`, + + BLAS: []string{"cblas128"}, + LAPACK: []string{"clapack128"}, + + template: `{{template "common" . }} +{{template "blas" .}} +{{template "switching" .}} +{{template "invariants" .}} +{{template "aliasing" .}} +package {{.Name}} +`, + }, +} + +var funcs = template.FuncMap{ + "sentence": sentence, + "alts": alts, + "join": join, +} + +// sentence converts a string to sentence case where the string is the prefix of the sentence. +func sentence(s string) string { + if len(s) == 0 { + return "" + } + _, size := utf8.DecodeRune([]byte(s)) + return strings.ToUpper(s[:size]) + s[size:] +} + +// alts renders a []string as a glob alternatives list. +func alts(s []string) string { + switch len(s) { + case 0: + return "" + case 1: + return s[0] + default: + return fmt.Sprintf("{%s}", strings.Join(s, ",")) + } +} + +// join is strings.Join with the parameter order changed. +func join(sep string, s []string) string { + return strings.Join(s, sep) +} + +func main() { + for _, pkg := range pkgs { + t, err := template.Must(docs.Clone()).Parse(pkg.template) + if err != nil { + log.Fatalf("failed to parse template: %v", err) + } + file := filepath.Join(pkg.path, "doc.go") + f, err := os.Create(file) + if err != nil { + log.Fatalf("failed to create %q: %v", file, err) + } + err = t.Execute(f, pkg) + if err != nil { + log.Fatalf("failed to execute template: %v", err) + } + f.Close() + } +} diff --git a/matrix/generate.go b/matrix/generate.go new file mode 100644 index 00000000..068fb261 --- /dev/null +++ b/matrix/generate.go @@ -0,0 +1,7 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gendoc.go + +package matrix diff --git a/matrix/mat64/cblas_test.go b/matrix/mat64/cblas_test.go new file mode 100644 index 00000000..aa4a596d --- /dev/null +++ b/matrix/mat64/cblas_test.go @@ -0,0 +1,16 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build cblas + +package mat64 + +import ( + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/blas/cgo" +) + +func init() { + blas64.Use(cgo.Implementation{}) +} diff --git a/matrix/mat64/cholesky.go b/matrix/mat64/cholesky.go new file mode 100644 index 00000000..4175a51b --- /dev/null +++ b/matrix/mat64/cholesky.go @@ -0,0 +1,452 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on the CholeskyDecomposition class from Jama 1.0.3. + +package mat64 + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +const ( + badTriangle = "mat64: invalid triangle" + badCholesky = "mat64: invalid Cholesky factorization" +) + +// Cholesky is a type for creating and using the Cholesky factorization of a +// symmetric positive definite matrix. +// +// Cholesky methods may only be called on a value that has been successfully +// initialized by a call to Factorize that has returned true. Calls to methods +// of an unsuccessful Cholesky factorization will panic. +type Cholesky struct { + // The chol pointer must never be retained as a pointer outside the Cholesky + // struct, either by returning chol outside the struct or by setting it to + // a pointer coming from outside. The same prohibition applies to the data + // slice within chol. + chol *TriDense + cond float64 +} + +// updateCond updates the condition number of the Cholesky decomposition. If +// norm > 0, then that norm is used as the norm of the original matrix A, otherwise +// the norm is estimated from the decomposition. +func (c *Cholesky) updateCond(norm float64) { + n := c.chol.mat.N + work := make([]float64, 3*n) + if norm < 0 { + // This is an approximation. By the definition of a norm, ||AB|| <= ||A|| ||B||. + // Here, A = U^T * U. + // The condition number is ||A|| || A^-1||, so this will underestimate + // the condition number somewhat. + // The norm of the original factorized matrix cannot be stored because of + // update possibilities. + unorm := lapack64.Lantr(matrix.CondNorm, c.chol.mat, work) + lnorm := lapack64.Lantr(matrix.CondNormTrans, c.chol.mat, work) + norm = unorm * lnorm + } + sym := c.chol.asSymBlas() + iwork := make([]int, n) + v := lapack64.Pocon(sym, norm, work, iwork) + c.cond = 1 / v +} + +// Factorize calculates the Cholesky decomposition of the matrix A and returns +// whether the matrix is positive definite. If Factorize returns false, the +// factorization must not be used. +func (c *Cholesky) Factorize(a Symmetric) (ok bool) { + n := a.Symmetric() + if c.isZero() { + c.chol = NewTriDense(n, matrix.Upper, nil) + } else { + c.chol = NewTriDense(n, matrix.Upper, use(c.chol.mat.Data, n*n)) + } + copySymIntoTriangle(c.chol, a) + + sym := c.chol.asSymBlas() + work := make([]float64, c.chol.mat.N) + norm := lapack64.Lansy(matrix.CondNorm, sym, work) + _, ok = lapack64.Potrf(sym) + if ok { + c.updateCond(norm) + } else { + c.Reset() + } + return ok +} + +// Reset resets the factorization so that it can be reused as the receiver of a +// dimensionally restricted operation. +func (c *Cholesky) Reset() { + if !c.isZero() { + c.chol.Reset() + } + c.cond = math.Inf(1) +} + +// SetFromU sets the Cholesky decomposition from the given triangular matrix. +// SetFromU panics if t is not upper triangular. Note that t is copied into, +// not stored inside, the receiver. +func (c *Cholesky) SetFromU(t *TriDense) { + n, kind := t.Triangle() + if kind != matrix.Upper { + panic("cholesky: matrix must be upper triangular") + } + if c.isZero() { + c.chol = NewTriDense(n, matrix.Upper, nil) + } else { + c.chol = NewTriDense(n, matrix.Upper, use(c.chol.mat.Data, n*n)) + } + c.chol.Copy(t) + c.updateCond(-1) +} + +// Clone makes a copy of the input Cholesky into the receiver, overwriting the +// previous value of the receiver. Clone does not place any restrictions on receiver +// shape. Clone panics if the input Cholesky is not the result of a valid decomposition. +func (c *Cholesky) Clone(chol *Cholesky) { + if !chol.valid() { + panic(badCholesky) + } + n := chol.Size() + if c.isZero() { + c.chol = NewTriDense(n, matrix.Upper, nil) + } else { + c.chol = NewTriDense(n, matrix.Upper, use(c.chol.mat.Data, n*n)) + } + c.chol.Copy(chol.chol) + c.cond = chol.cond +} + +// Size returns the dimension of the factorized matrix. +func (c *Cholesky) Size() int { + if !c.valid() { + panic(badCholesky) + } + return c.chol.mat.N +} + +// Det returns the determinant of the matrix that has been factorized. +func (c *Cholesky) Det() float64 { + if !c.valid() { + panic(badCholesky) + } + return math.Exp(c.LogDet()) +} + +// LogDet returns the log of the determinant of the matrix that has been factorized. +func (c *Cholesky) LogDet() float64 { + if !c.valid() { + panic(badCholesky) + } + var det float64 + for i := 0; i < c.chol.mat.N; i++ { + det += 2 * math.Log(c.chol.mat.Data[i*c.chol.mat.Stride+i]) + } + return det +} + +// SolveCholesky finds the matrix m that solves A * m = b where A is represented +// by the Cholesky decomposition, placing the result in the receiver. +func (m *Dense) SolveCholesky(chol *Cholesky, b Matrix) error { + if !chol.valid() { + panic(badCholesky) + } + n := chol.chol.mat.N + bm, bn := b.Dims() + if n != bm { + panic(matrix.ErrShape) + } + + m.reuseAs(bm, bn) + if b != m { + m.Copy(b) + } + blas64.Trsm(blas.Left, blas.Trans, 1, chol.chol.mat, m.mat) + blas64.Trsm(blas.Left, blas.NoTrans, 1, chol.chol.mat, m.mat) + if chol.cond > matrix.ConditionTolerance { + return matrix.Condition(chol.cond) + } + return nil +} + +// TODO(kortschak): Export this as SolveTwoChol. +// solveTwoChol finds the matrix m that solves A * m = B where A and B are represented +// by their Cholesky decompositions a and b, placing the result in the receiver. +func (m *Dense) solveTwoChol(a, b *Cholesky) error { + if !a.valid() || !b.valid() { + panic(badCholesky) + } + bn := b.chol.mat.N + if a.chol.mat.N != bn { + panic(matrix.ErrShape) + } + + m.reuseAsZeroed(bn, bn) + m.Copy(b.chol.T()) + blas64.Trsm(blas.Left, blas.Trans, 1, a.chol.mat, m.mat) + blas64.Trsm(blas.Left, blas.NoTrans, 1, a.chol.mat, m.mat) + blas64.Trmm(blas.Right, blas.NoTrans, 1, b.chol.mat, m.mat) + if a.cond > matrix.ConditionTolerance { + return matrix.Condition(a.cond) + } + return nil +} + +// SolveCholeskyVec finds the vector v that solves A * v = b where A is represented +// by the Cholesky decomposition, placing the result in the receiver. +func (v *Vector) SolveCholeskyVec(chol *Cholesky, b *Vector) error { + if !chol.valid() { + panic(badCholesky) + } + n := chol.chol.mat.N + vn := b.Len() + if vn != n { + panic(matrix.ErrShape) + } + if v != b { + v.checkOverlap(b.mat) + } + v.reuseAs(n) + if v != b { + v.CopyVec(b) + } + blas64.Trsv(blas.Trans, chol.chol.mat, v.mat) + blas64.Trsv(blas.NoTrans, chol.chol.mat, v.mat) + if chol.cond > matrix.ConditionTolerance { + return matrix.Condition(chol.cond) + } + return nil + +} + +// UFromCholesky extracts the n×n upper triangular matrix U from a Cholesky +// decomposition +// A = U^T * U. +func (t *TriDense) UFromCholesky(chol *Cholesky) { + if !chol.valid() { + panic(badCholesky) + } + n := chol.chol.mat.N + t.reuseAs(n, matrix.Upper) + t.Copy(chol.chol) +} + +// LFromCholesky extracts the n×n lower triangular matrix L from a Cholesky +// decomposition +// A = L * L^T. +func (t *TriDense) LFromCholesky(chol *Cholesky) { + if !chol.valid() { + panic(badCholesky) + } + n := chol.chol.mat.N + t.reuseAs(n, matrix.Lower) + t.Copy(chol.chol.TTri()) +} + +// FromCholesky reconstructs the original positive definite matrix given its +// Cholesky decomposition. +func (s *SymDense) FromCholesky(chol *Cholesky) { + if !chol.valid() { + panic(badCholesky) + } + n := chol.chol.mat.N + s.reuseAs(n) + s.SymOuterK(1, chol.chol.T()) +} + +// InverseCholesky computes the inverse of the matrix represented by its Cholesky +// factorization and stores the result into the receiver. If the factorized +// matrix is ill-conditioned, a Condition error will be returned. +// Note that matrix inversion is numerically unstable, and should generally be +// avoided where possible, for example by using the Solve routines. +func (s *SymDense) InverseCholesky(chol *Cholesky) error { + if !chol.valid() { + panic(badCholesky) + } + // TODO(btracey): Replace this code with a direct call to Dpotri when it + // is available. + s.reuseAs(chol.chol.mat.N) + // If: + // chol(A) = U^T * U + // Then: + // chol(A^-1) = S * S^T + // where S = U^-1 + var t TriDense + err := t.InverseTri(chol.chol) + s.SymOuterK(1, &t) + return err +} + +// SymRankOne performs a rank-1 update of the original matrix A and refactorizes +// its Cholesky factorization, storing the result into the reciever. That is, if +// in the original Cholesky factorization +// U^T * U = A, +// in the updated factorization +// U'^T * U' = A + alpha * x * x^T = A'. +// +// Note that when alpha is negative, the updating problem may be ill-conditioned +// and the results may be inaccurate, or the updated matrix A' may not be +// positive definite and not have a Cholesky factorization. SymRankOne returns +// whether the updated matrix A' is positive definite. +// +// SymRankOne updates a Cholesky factorization in O(n²) time. The Cholesky +// factorization computation from scratch is O(n³). +func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x *Vector) (ok bool) { + if !orig.valid() { + panic(badCholesky) + } + n := orig.Size() + if x.Len() != n { + panic(matrix.ErrShape) + } + if orig != c { + if c.isZero() { + c.chol = NewTriDense(n, matrix.Upper, nil) + } else if c.chol.mat.N != n { + panic(matrix.ErrShape) + } + c.chol.Copy(orig.chol) + } + + if alpha == 0 { + return true + } + + // Algorithms for updating and downdating the Cholesky factorization are + // described, for example, in + // - J. J. Dongarra, J. R. Bunch, C. B. Moler, G. W. Stewart: LINPACK + // Users' Guide. SIAM (1979), pages 10.10--10.14 + // or + // - P. E. Gill, G. H. Golub, W. Murray, and M. A. Saunders: Methods for + // modifying matrix factorizations. Mathematics of Computation 28(126) + // (1974), Method C3 on page 521 + // + // The implementation is based on LINPACK code + // http://www.netlib.org/linpack/dchud.f + // http://www.netlib.org/linpack/dchdd.f + // and + // https://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=2&t=2646 + // + // According to http://icl.cs.utk.edu/lapack-forum/archives/lapack/msg00301.html + // LINPACK is released under BSD license. + // + // See also: + // - M. A. Saunders: Large-scale Linear Programming Using the Cholesky + // Factorization. Technical Report Stanford University (1972) + // http://i.stanford.edu/pub/cstr/reports/cs/tr/72/252/CS-TR-72-252.pdf + // - Matthias Seeger: Low rank updates for the Cholesky decomposition. + // EPFL Technical Report 161468 (2004) + // http://infoscience.epfl.ch/record/161468 + + work := make([]float64, n) + blas64.Copy(n, x.RawVector(), blas64.Vector{1, work}) + + if alpha > 0 { + // Compute rank-1 update. + if alpha != 1 { + blas64.Scal(n, math.Sqrt(alpha), blas64.Vector{1, work}) + } + umat := c.chol.mat + stride := umat.Stride + for i := 0; i < n; i++ { + // Compute parameters of the Givens matrix that zeroes + // the i-th element of x. + c, s, r, _ := blas64.Rotg(umat.Data[i*stride+i], work[i]) + if r < 0 { + // Multiply by -1 to have positive diagonal + // elemnts. + r *= -1 + c *= -1 + s *= -1 + } + umat.Data[i*stride+i] = r + if i < n-1 { + // Multiply the extended factorization matrix by + // the Givens matrix from the left. Only + // the i-th row and x are modified. + blas64.Rot(n-i-1, + blas64.Vector{1, umat.Data[i*stride+i+1 : i*stride+n]}, + blas64.Vector{1, work[i+1 : n]}, + c, s) + } + } + c.updateCond(-1) + return true + } + + // Compute rank-1 downdate. + alpha = math.Sqrt(-alpha) + if alpha != 1 { + blas64.Scal(n, alpha, blas64.Vector{1, work}) + } + // Solve U^T * p = x storing the result into work. + ok = lapack64.Trtrs(blas.Trans, c.chol.RawTriangular(), blas64.General{ + Rows: n, + Cols: 1, + Stride: 1, + Data: work, + }) + if !ok { + // The original matrix is singular. Should not happen, because + // the factorization is valid. + panic(badCholesky) + } + norm := blas64.Nrm2(n, blas64.Vector{1, work}) + if norm >= 1 { + // The updated matrix is not positive definite. + return false + } + norm = math.Sqrt((1 + norm) * (1 - norm)) + cos := make([]float64, n) + sin := make([]float64, n) + for i := n - 1; i >= 0; i-- { + // Compute parameters of Givens matrices that zero elements of p + // backwards. + cos[i], sin[i], norm, _ = blas64.Rotg(norm, work[i]) + if norm < 0 { + norm *= -1 + cos[i] *= -1 + sin[i] *= -1 + } + } + umat := c.chol.mat + stride := umat.Stride + for i := n - 1; i >= 0; i-- { + // Apply Givens matrices to U. + // TODO(vladimir-ch): Use workspace to avoid modifying the + // receiver in case an invalid factorization is created. + blas64.Rot(n-i, blas64.Vector{1, work[i:n]}, blas64.Vector{1, umat.Data[i*stride+i : i*stride+n]}, cos[i], sin[i]) + if umat.Data[i*stride+i] == 0 { + // The matrix is singular (may rarely happen due to + // floating-point effects?). + ok = false + } else if umat.Data[i*stride+i] < 0 { + // Diagonal elements should be positive. If it happens + // that on the i-th row the diagonal is negative, + // multiply U from the left by an identity matrix that + // has -1 on the i-th row. + blas64.Scal(n-i, -1, blas64.Vector{1, umat.Data[i*stride+i : i*stride+n]}) + } + } + if ok { + c.updateCond(-1) + } else { + c.Reset() + } + return ok +} + +func (c *Cholesky) isZero() bool { + return c.chol == nil +} + +func (c *Cholesky) valid() bool { + return !c.isZero() && !c.chol.isZero() +} diff --git a/matrix/mat64/cholesky_example_test.go b/matrix/mat64/cholesky_example_test.go new file mode 100644 index 00000000..4249474b --- /dev/null +++ b/matrix/mat64/cholesky_example_test.go @@ -0,0 +1,123 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64_test + +import ( + "fmt" + + "gonum.org/v1/gonum/matrix/mat64" +) + +func ExampleCholesky() { + // Construct a symmetric positive definite matrix. + tmp := mat64.NewDense(4, 4, []float64{ + 2, 6, 8, -4, + 1, 8, 7, -2, + 2, 2, 1, 7, + 8, -2, -2, 1, + }) + var a mat64.SymDense + a.SymOuterK(1, tmp) + + fmt.Printf("a = %0.4v\n", mat64.Formatted(&a, mat64.Prefix(" "))) + + // Compute the cholesky factorization. + var chol mat64.Cholesky + if ok := chol.Factorize(&a); !ok { + fmt.Println("a matrix is not positive semi-definite.") + } + + // Find the determinant. + fmt.Printf("\nThe determinant of a is %0.4g\n\n", chol.Det()) + + // Use the factorization to solve the system of equations a * x = b. + b := mat64.NewVector(4, []float64{1, 2, 3, 4}) + var x mat64.Vector + if err := x.SolveCholeskyVec(&chol, b); err != nil { + fmt.Println("Matrix is near singular: ", err) + } + fmt.Println("Solve a * x = b") + fmt.Printf("x = %0.4v\n", mat64.Formatted(&x, mat64.Prefix(" "))) + + // Extract the factorization and check that it equals the original matrix. + var t mat64.TriDense + t.LFromCholesky(&chol) + var test mat64.Dense + test.Mul(&t, t.T()) + fmt.Println() + fmt.Printf("L * L^T = %0.4v\n", mat64.Formatted(&a, mat64.Prefix(" "))) + + // Output: + // a = ⎡120 114 -4 -16⎤ + // ⎢114 118 11 -24⎥ + // ⎢ -4 11 58 17⎥ + // ⎣-16 -24 17 73⎦ + // + // The determinant of a is 1.543e+06 + // + // Solve a * x = b + // x = ⎡ -0.239⎤ + // ⎢ 0.2732⎥ + // ⎢-0.04681⎥ + // ⎣ 0.1031⎦ + // + // L * L^T = ⎡120 114 -4 -16⎤ + // ⎢114 118 11 -24⎥ + // ⎢ -4 11 58 17⎥ + // ⎣-16 -24 17 73⎦ +} + +func ExampleCholeskySymRankOne() { + a := mat64.NewSymDense(4, []float64{ + 1, 1, 1, 1, + 0, 2, 3, 4, + 0, 0, 6, 10, + 0, 0, 0, 20, + }) + fmt.Printf("A = %0.4v\n", mat64.Formatted(a, mat64.Prefix(" "))) + + // Compute the Cholesky factorization. + var chol mat64.Cholesky + if ok := chol.Factorize(a); !ok { + fmt.Println("matrix a is not positive definite.") + } + + x := mat64.NewVector(4, []float64{0, 0, 0, 1}) + fmt.Printf("\nx = %0.4v\n", mat64.Formatted(x, mat64.Prefix(" "))) + + // Rank-1 update the factorization. + chol.SymRankOne(&chol, 1, x) + // Rank-1 update the matrix a. + a.SymRankOne(a, 1, x) + + var au mat64.SymDense + au.FromCholesky(&chol) + + // Print the matrix that was updated directly. + fmt.Printf("\nA' = %0.4v\n", mat64.Formatted(a, mat64.Prefix(" "))) + // Print the matrix recovered from the factorization. + fmt.Printf("\nU'^T * U' = %0.4v\n", mat64.Formatted(&au, mat64.Prefix(" "))) + + // Output: + // A = ⎡ 1 1 1 1⎤ + // ⎢ 1 2 3 4⎥ + // ⎢ 1 3 6 10⎥ + // ⎣ 1 4 10 20⎦ + // + // x = ⎡0⎤ + // ⎢0⎥ + // ⎢0⎥ + // ⎣1⎦ + // + // A' = ⎡ 1 1 1 1⎤ + // ⎢ 1 2 3 4⎥ + // ⎢ 1 3 6 10⎥ + // ⎣ 1 4 10 21⎦ + // + // U'^T * U' = ⎡ 1 1 1 1⎤ + // ⎢ 1 2 3 4⎥ + // ⎢ 1 3 6 10⎥ + // ⎣ 1 4 10 21⎦ +} diff --git a/matrix/mat64/cholesky_test.go b/matrix/mat64/cholesky_test.go new file mode 100644 index 00000000..2d64e95b --- /dev/null +++ b/matrix/mat64/cholesky_test.go @@ -0,0 +1,457 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/testblas" + "gonum.org/v1/gonum/matrix" +) + +func TestCholesky(t *testing.T) { + for _, test := range []struct { + a *SymDense + + cond float64 + want *TriDense + posdef bool + }{ + { + a: NewSymDense(3, []float64{ + 4, 1, 1, + 0, 2, 3, + 0, 0, 6, + }), + cond: 37, + want: NewTriDense(3, true, []float64{ + 2, 0.5, 0.5, + 0, 1.3228756555322954, 2.0788046015507495, + 0, 0, 1.195228609334394, + }), + posdef: true, + }, + } { + _, n := test.a.Dims() + for _, chol := range []*Cholesky{ + {}, + {chol: NewTriDense(n-1, true, nil)}, + {chol: NewTriDense(n, true, nil)}, + {chol: NewTriDense(n+1, true, nil)}, + } { + ok := chol.Factorize(test.a) + if ok != test.posdef { + t.Errorf("unexpected return from Cholesky factorization: got: ok=%t want: ok=%t", ok, test.posdef) + } + fc := DenseCopyOf(chol.chol) + if !Equal(fc, test.want) { + t.Error("incorrect Cholesky factorization") + } + if math.Abs(test.cond-chol.cond) > 1e-13 { + t.Errorf("Condition number mismatch: Want %v, got %v", test.cond, chol.cond) + } + var U TriDense + U.UFromCholesky(chol) + aCopy := DenseCopyOf(test.a) + var a Dense + a.Mul(U.TTri(), &U) + if !EqualApprox(&a, aCopy, 1e-14) { + t.Error("unexpected Cholesky factor product") + } + + var L TriDense + L.LFromCholesky(chol) + a.Mul(&L, L.TTri()) + if !EqualApprox(&a, aCopy, 1e-14) { + t.Error("unexpected Cholesky factor product") + } + } + } +} + +func TestCholeskySolve(t *testing.T) { + for _, test := range []struct { + a *SymDense + b *Dense + ans *Dense + }{ + { + a: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + b: NewDense(2, 1, []float64{5, 6}), + ans: NewDense(2, 1, []float64{5, 6}), + }, + { + a: NewSymDense(3, []float64{ + 53, 59, 37, + 0, 83, 71, + 37, 71, 101, + }), + b: NewDense(3, 1, []float64{5, 6, 7}), + ans: NewDense(3, 1, []float64{0.20745069393718094, -0.17421475529583694, 0.11577794010226464}), + }, + } { + var chol Cholesky + ok := chol.Factorize(test.a) + if !ok { + t.Fatal("unexpected Cholesky factorization failure: not positive definite") + } + + var x Dense + x.SolveCholesky(&chol, test.b) + if !EqualApprox(&x, test.ans, 1e-12) { + t.Error("incorrect Cholesky solve solution") + } + + var ans Dense + ans.Mul(test.a, &x) + if !EqualApprox(&ans, test.b, 1e-12) { + t.Error("incorrect Cholesky solve solution product") + } + } +} + +func TestSolveTwoChol(t *testing.T) { + for _, test := range []struct { + a, b *SymDense + }{ + { + a: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + b: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + }, + { + a: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + b: NewSymDense(2, []float64{ + 2, 0, + 0, 2, + }), + }, + { + a: NewSymDense(3, []float64{ + 53, 59, 37, + 59, 83, 71, + 37, 71, 101, + }), + b: NewSymDense(3, []float64{ + 2, -1, 0, + -1, 2, -1, + 0, -1, 2, + }), + }, + } { + var chola, cholb Cholesky + ok := chola.Factorize(test.a) + if !ok { + t.Fatal("unexpected Cholesky factorization failure for a: not positive definite") + } + ok = cholb.Factorize(test.b) + if !ok { + t.Fatal("unexpected Cholesky factorization failure for b: not positive definite") + } + + var x Dense + x.solveTwoChol(&chola, &cholb) + + var ans Dense + ans.Mul(test.a, &x) + if !EqualApprox(&ans, test.b, 1e-12) { + var y Dense + y.Solve(test.a, test.b) + t.Errorf("incorrect Cholesky solve solution product\ngot solution:\n%.4v\nwant solution\n%.4v", + Formatted(&x), Formatted(&y)) + } + } +} + +func TestCholeskySolveVec(t *testing.T) { + for _, test := range []struct { + a *SymDense + b *Vector + ans *Vector + }{ + { + a: NewSymDense(2, []float64{ + 1, 0, + 0, 1, + }), + b: NewVector(2, []float64{5, 6}), + ans: NewVector(2, []float64{5, 6}), + }, + { + a: NewSymDense(3, []float64{ + 53, 59, 37, + 0, 83, 71, + 0, 0, 101, + }), + b: NewVector(3, []float64{5, 6, 7}), + ans: NewVector(3, []float64{0.20745069393718094, -0.17421475529583694, 0.11577794010226464}), + }, + } { + var chol Cholesky + ok := chol.Factorize(test.a) + if !ok { + t.Fatal("unexpected Cholesky factorization failure: not positive definite") + } + + var x Vector + x.SolveCholeskyVec(&chol, test.b) + if !EqualApprox(&x, test.ans, 1e-12) { + t.Error("incorrect Cholesky solve solution") + } + + var ans Vector + ans.MulVec(test.a, &x) + if !EqualApprox(&ans, test.b, 1e-12) { + t.Error("incorrect Cholesky solve solution product") + } + } +} + +func TestFromCholesky(t *testing.T) { + for _, test := range []*SymDense{ + NewSymDense(3, []float64{ + 53, 59, 37, + 0, 83, 71, + 0, 0, 101, + }), + } { + var chol Cholesky + ok := chol.Factorize(test) + if !ok { + t.Fatal("unexpected Cholesky factorization failure: not positive definite") + } + var s SymDense + s.FromCholesky(&chol) + + if !EqualApprox(&s, test, 1e-12) { + t.Errorf("Cholesky reconstruction not equal to original matrix.\nWant:\n% v\nGot:\n% v\n", Formatted(test), Formatted(&s)) + } + } +} + +func TestCloneCholesky(t *testing.T) { + for _, test := range []*SymDense{ + NewSymDense(3, []float64{ + 53, 59, 37, + 0, 83, 71, + 0, 0, 101, + }), + } { + var chol Cholesky + ok := chol.Factorize(test) + if !ok { + panic("bad test") + } + var chol2 Cholesky + chol2.Clone(&chol) + + if chol.cond != chol2.cond { + t.Errorf("condition number mismatch from zero") + } + if !Equal(chol.chol, chol2.chol) { + t.Errorf("chol mismatch from zero") + } + + // Corrupt chol2 and try again + chol2.cond = math.NaN() + chol2.chol = NewTriDense(2, matrix.Upper, nil) + chol2.Clone(&chol) + if chol.cond != chol2.cond { + t.Errorf("condition number mismatch from non-zero") + } + if !Equal(chol.chol, chol2.chol) { + t.Errorf("chol mismatch from non-zero") + } + } +} + +func TestInverseCholesky(t *testing.T) { + for _, n := range []int{1, 3, 5, 9} { + data := make([]float64, n*n) + for i := range data { + data[i] = rand.NormFloat64() + } + var s SymDense + s.SymOuterK(1, NewDense(n, n, data)) + + var chol Cholesky + ok := chol.Factorize(&s) + if !ok { + t.Errorf("Bad test, cholesky decomposition failed") + } + + var sInv SymDense + sInv.InverseCholesky(&chol) + + var ans Dense + ans.Mul(&sInv, &s) + if !equalApprox(eye(n), &ans, 1e-8, false) { + var diff Dense + diff.Sub(eye(n), &ans) + t.Errorf("SymDense times Cholesky inverse not identity. Norm diff = %v", Norm(&diff, 2)) + } + } +} + +func TestCholeskySymRankOne(t *testing.T) { + rand.Seed(1) + for _, n := range []int{1, 2, 3, 4, 5, 7, 10, 20, 50, 100} { + for k := 0; k < 10; k++ { + data := make([]float64, n*n) + for i := range data { + data[i] = rand.NormFloat64() + } + + var a SymDense + a.SymOuterK(1, NewDense(n, n, data)) + + xdata := make([]float64, n) + for i := range xdata { + xdata[i] = rand.NormFloat64() + } + x := NewVector(n, xdata) + + var chol Cholesky + ok := chol.Factorize(&a) + if !ok { + t.Errorf("Bad random test, Cholesky factorization failed") + continue + } + + alpha := rand.Float64() + ok = chol.SymRankOne(&chol, alpha, x) + if !ok { + t.Errorf("n=%v, alpha=%v: unexpected failure", n, alpha) + continue + } + a.SymRankOne(&a, alpha, x) + + var achol SymDense + achol.FromCholesky(&chol) + if !EqualApprox(&achol, &a, 1e-13) { + t.Errorf("n=%v, alpha=%v: mismatch between updated matrix and from Cholesky:\nupdated:\n%v\nfrom Cholesky:\n%v", + n, alpha, Formatted(&a), Formatted(&achol)) + } + } + } + + for i, test := range []struct { + a *SymDense + alpha float64 + x []float64 + + wantOk bool + }{ + { + // Update (to positive definite matrix). + a: NewSymDense(4, []float64{ + 1, 1, 1, 1, + 0, 2, 3, 4, + 0, 0, 6, 10, + 0, 0, 0, 20, + }), + alpha: 1, + x: []float64{0, 0, 0, 1}, + wantOk: true, + }, + { + // Downdate to singular matrix. + a: NewSymDense(4, []float64{ + 1, 1, 1, 1, + 0, 2, 3, 4, + 0, 0, 6, 10, + 0, 0, 0, 20, + }), + alpha: -1, + x: []float64{0, 0, 0, 1}, + wantOk: false, + }, + { + // Downdate to positive definite matrix. + a: NewSymDense(4, []float64{ + 1, 1, 1, 1, + 0, 2, 3, 4, + 0, 0, 6, 10, + 0, 0, 0, 20, + }), + alpha: -1 / 2, + x: []float64{0, 0, 0, 1}, + wantOk: true, + }, + } { + var chol Cholesky + ok := chol.Factorize(test.a) + if !ok { + t.Errorf("Case %v: bad test, Cholesky factorization failed", i) + continue + } + + x := NewVector(len(test.x), test.x) + ok = chol.SymRankOne(&chol, test.alpha, x) + if !ok { + if test.wantOk { + t.Errorf("Case %v: unexpected failure from SymRankOne", i) + } + continue + } + if ok && !test.wantOk { + t.Errorf("Case %v: expected a failure from SymRankOne", i) + } + + a := test.a + a.SymRankOne(a, test.alpha, x) + + var achol SymDense + achol.FromCholesky(&chol) + if !EqualApprox(&achol, a, 1e-13) { + t.Errorf("Case %v: mismatch between updated matrix and from Cholesky:\nupdated:\n%v\nfrom Cholesky:\n%v", + i, Formatted(a), Formatted(&achol)) + } + } +} + +func BenchmarkCholeskySmall(b *testing.B) { + benchmarkCholesky(b, 2) +} + +func BenchmarkCholeskyMedium(b *testing.B) { + benchmarkCholesky(b, testblas.MediumMat) +} + +func BenchmarkCholeskyLarge(b *testing.B) { + benchmarkCholesky(b, testblas.LargeMat) +} + +func benchmarkCholesky(b *testing.B, n int) { + base := make([]float64, n*n) + for i := range base { + base[i] = rand.Float64() + } + bm := NewDense(n, n, base) + bm.Mul(bm.T(), bm) + am := NewSymDense(n, bm.mat.Data) + + var chol Cholesky + b.ResetTimer() + for i := 0; i < b.N; i++ { + ok := chol.Factorize(am) + if !ok { + panic("not pos def") + } + } +} diff --git a/matrix/mat64/dense.go b/matrix/mat64/dense.go new file mode 100644 index 00000000..b48d6a3b --- /dev/null +++ b/matrix/mat64/dense.go @@ -0,0 +1,543 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/matrix" +) + +var ( + dense *Dense + + _ Matrix = dense + _ Mutable = dense + + _ Cloner = dense + _ Viewer = dense + _ RowViewer = dense + _ ColViewer = dense + _ RawRowViewer = dense + _ Grower = dense + + _ RawMatrixSetter = dense + _ RawMatrixer = dense + + _ Reseter = dense +) + +// Dense is a dense matrix representation. +type Dense struct { + mat blas64.General + + capRows, capCols int +} + +// NewDense creates a new Dense matrix with r rows and c columns. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == r*c, data is +// used as the backing slice, and changes to the elements of the returned Dense +// will be reflected in data. If neither of these is true, NewDense will panic. +// +// The data must be arranged in row-major order, i.e. the (i*c + j)-th +// element in the data slice is the {i, j}-th element in the matrix. +func NewDense(r, c int, data []float64) *Dense { + if data != nil && r*c != len(data) { + panic(matrix.ErrShape) + } + if data == nil { + data = make([]float64, r*c) + } + return &Dense{ + mat: blas64.General{ + Rows: r, + Cols: c, + Stride: c, + Data: data, + }, + capRows: r, + capCols: c, + } +} + +// reuseAs resizes an empty matrix to a r×c matrix, +// or checks that a non-empty matrix is r×c. +// +// reuseAs must be kept in sync with reuseAsZeroed. +func (m *Dense) reuseAs(r, c int) { + if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { + // Panic as a string, not a mat64.Error. + panic("mat64: caps not correctly set") + } + if m.isZero() { + m.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: c, + Data: use(m.mat.Data, r*c), + } + m.capRows = r + m.capCols = c + return + } + if r != m.mat.Rows || c != m.mat.Cols { + panic(matrix.ErrShape) + } +} + +// reuseAsZeroed resizes an empty matrix to a r×c matrix, +// or checks that a non-empty matrix is r×c. It zeroes +// all the elements of the matrix. +// +// reuseAsZeroed must be kept in sync with reuseAs. +func (m *Dense) reuseAsZeroed(r, c int) { + if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { + // Panic as a string, not a mat64.Error. + panic("mat64: caps not correctly set") + } + if m.isZero() { + m.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: c, + Data: useZeroed(m.mat.Data, r*c), + } + m.capRows = r + m.capCols = c + return + } + if r != m.mat.Rows || c != m.mat.Cols { + panic(matrix.ErrShape) + } + for i := 0; i < r; i++ { + zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) + } +} + +// untranspose untransposes a matrix if applicable. If a is an Untransposer, then +// untranspose returns the underlying matrix and true. If it is not, then it returns +// the input matrix and false. +func untranspose(a Matrix) (Matrix, bool) { + if ut, ok := a.(Untransposer); ok { + return ut.Untranspose(), true + } + return a, false +} + +// isolatedWorkspace returns a new dense matrix w with the size of a and +// returns a callback to defer which performs cleanup at the return of the call. +// This should be used when a method receiver is the same pointer as an input argument. +func (m *Dense) isolatedWorkspace(a Matrix) (w *Dense, restore func()) { + r, c := a.Dims() + w = getWorkspace(r, c, false) + return w, func() { + m.Copy(w) + putWorkspace(w) + } +} + +// Reset zeros the dimensions of the matrix so that it can be reused as the +// receiver of a dimensionally restricted operation. +// +// See the Reseter interface for more information. +func (m *Dense) Reset() { + // Row, Cols and Stride must be zeroed in unison. + m.mat.Rows, m.mat.Cols, m.mat.Stride = 0, 0, 0 + m.capRows, m.capCols = 0, 0 + m.mat.Data = m.mat.Data[:0] +} + +func (m *Dense) isZero() bool { + // It must be the case that m.Dims() returns + // zeros in this case. See comment in Reset(). + return m.mat.Stride == 0 +} + +// asTriDense returns a TriDense with the given size and side. The backing data +// of the TriDense is the same as the receiver. +func (m *Dense) asTriDense(n int, diag blas.Diag, uplo blas.Uplo) *TriDense { + return &TriDense{ + mat: blas64.Triangular{ + N: n, + Stride: m.mat.Stride, + Data: m.mat.Data, + Uplo: uplo, + Diag: diag, + }, + cap: n, + } +} + +// DenseCopyOf returns a newly allocated copy of the elements of a. +func DenseCopyOf(a Matrix) *Dense { + d := &Dense{} + d.Clone(a) + return d +} + +// SetRawMatrix sets the underlying blas64.General used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in b. +func (m *Dense) SetRawMatrix(b blas64.General) { + m.capRows, m.capCols = b.Rows, b.Cols + m.mat = b +} + +// RawMatrix returns the underlying blas64.General used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in returned blas64.General. +func (m *Dense) RawMatrix() blas64.General { return m.mat } + +// Dims returns the number of rows and columns in the matrix. +func (m *Dense) Dims() (r, c int) { return m.mat.Rows, m.mat.Cols } + +// Caps returns the number of rows and columns in the backing matrix. +func (m *Dense) Caps() (r, c int) { return m.capRows, m.capCols } + +// T performs an implicit transpose by returning the receiver inside a Transpose. +func (m *Dense) T() Matrix { + return Transpose{m} +} + +// ColView returns a Vector reflecting the column j, backed by the matrix data. +// +// See ColViewer for more information. +func (m *Dense) ColView(j int) *Vector { + if j >= m.mat.Cols || j < 0 { + panic(matrix.ErrColAccess) + } + return &Vector{ + mat: blas64.Vector{ + Inc: m.mat.Stride, + Data: m.mat.Data[j : (m.mat.Rows-1)*m.mat.Stride+j+1], + }, + n: m.mat.Rows, + } +} + +// SetCol sets the values in the specified column of the matrix to the values +// in src. len(src) must equal the number of rows in the receiver. +func (m *Dense) SetCol(j int, src []float64) { + if j >= m.mat.Cols || j < 0 { + panic(matrix.ErrColAccess) + } + if len(src) != m.mat.Rows { + panic(matrix.ErrColLength) + } + + blas64.Copy(m.mat.Rows, + blas64.Vector{Inc: 1, Data: src}, + blas64.Vector{Inc: m.mat.Stride, Data: m.mat.Data[j:]}, + ) +} + +// SetRow sets the values in the specified rows of the matrix to the values +// in src. len(src) must equal the number of columns in the receiver. +func (m *Dense) SetRow(i int, src []float64) { + if i >= m.mat.Rows || i < 0 { + panic(matrix.ErrRowAccess) + } + if len(src) != m.mat.Cols { + panic(matrix.ErrRowLength) + } + + copy(m.rawRowView(i), src) +} + +// RowView returns row i of the matrix data represented as a column vector, +// backed by the matrix data. +// +// See RowViewer for more information. +func (m *Dense) RowView(i int) *Vector { + if i >= m.mat.Rows || i < 0 { + panic(matrix.ErrRowAccess) + } + return &Vector{ + mat: blas64.Vector{ + Inc: 1, + Data: m.rawRowView(i), + }, + n: m.mat.Cols, + } +} + +// RawRowView returns a slice backed by the same array as backing the +// receiver. +func (m *Dense) RawRowView(i int) []float64 { + if i >= m.mat.Rows || i < 0 { + panic(matrix.ErrRowAccess) + } + return m.rawRowView(i) +} + +func (m *Dense) rawRowView(i int) []float64 { + return m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+m.mat.Cols] +} + +// View returns a new Matrix that shares backing data with the receiver. +// The new matrix is located from row i, column j extending r rows and c +// columns. View panics if the view is outside the bounds of the receiver. +// +// View is deprecated and should not be used. It will be removed at a later date. +func (m *Dense) View(i, j, r, c int) Matrix { + return m.Slice(i, i+r, j, j+c) +} + +// Slice returns a new Matrix that shares backing data with the receiver. +// The returned matrix starts at {i,j} of the recevier and extends k-i rows +// and l-j columns. The final row in the resulting matrix is k-1 and the +// final column is l-1. +// Slice panics with ErrIndexOutOfRange if the slice is outside the bounds +// of the receiver. +func (m *Dense) Slice(i, k, j, l int) Matrix { + mr, mc := m.Dims() + if i < 0 || mr <= i || j < 0 || mc <= j || k <= i || mr < k || l <= j || mc < l { + panic(matrix.ErrIndexOutOfRange) + } + t := *m + t.mat.Data = t.mat.Data[i*t.mat.Stride+j : (k-1)*t.mat.Stride+l] + t.mat.Rows = k - i + t.mat.Cols = l - j + t.capRows -= i + t.capCols -= j + return &t +} + +// Grow returns the receiver expanded by r rows and c columns. If the dimensions +// of the expanded matrix are outside the capacities of the receiver a new +// allocation is made, otherwise not. Note the receiver itself is not modified +// during the call to Grow. +func (m *Dense) Grow(r, c int) Matrix { + if r < 0 || c < 0 { + panic(matrix.ErrIndexOutOfRange) + } + if r == 0 && c == 0 { + return m + } + + r += m.mat.Rows + c += m.mat.Cols + + var t Dense + switch { + case m.mat.Rows == 0 || m.mat.Cols == 0: + t.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: c, + // We zero because we don't know how the matrix will be used. + // In other places, the mat is immediately filled with a result; + // this is not the case here. + Data: useZeroed(m.mat.Data, r*c), + } + case r > m.capRows || c > m.capCols: + cr := max(r, m.capRows) + cc := max(c, m.capCols) + t.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: cc, + Data: make([]float64, cr*cc), + } + t.capRows = cr + t.capCols = cc + // Copy the complete matrix over to the new matrix. + // Including elements not currently visible. Use a temporary structure + // to avoid modifying the receiver. + var tmp Dense + tmp.mat = blas64.General{ + Rows: m.mat.Rows, + Cols: m.mat.Cols, + Stride: m.mat.Stride, + Data: m.mat.Data, + } + tmp.capRows = m.capRows + tmp.capCols = m.capCols + t.Copy(&tmp) + return &t + default: + t.mat = blas64.General{ + Data: m.mat.Data[:(r-1)*m.mat.Stride+c], + Rows: r, + Cols: c, + Stride: m.mat.Stride, + } + } + t.capRows = r + t.capCols = c + return &t +} + +// Clone makes a copy of a into the receiver, overwriting the previous value of +// the receiver. The clone operation does not make any restriction on shape and +// will not cause shadowing. +// +// See the Cloner interface for more information. +func (m *Dense) Clone(a Matrix) { + r, c := a.Dims() + mat := blas64.General{ + Rows: r, + Cols: c, + Stride: c, + } + m.capRows, m.capCols = r, c + + aU, trans := untranspose(a) + switch aU := aU.(type) { + case RawMatrixer: + amat := aU.RawMatrix() + mat.Data = make([]float64, r*c) + if trans { + for i := 0; i < r; i++ { + blas64.Copy(c, + blas64.Vector{Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, + blas64.Vector{Inc: 1, Data: mat.Data[i*c : (i+1)*c]}) + } + } else { + for i := 0; i < r; i++ { + copy(mat.Data[i*c:(i+1)*c], amat.Data[i*amat.Stride:i*amat.Stride+c]) + } + } + case *Vector: + amat := aU.mat + mat.Data = make([]float64, aU.n) + blas64.Copy(aU.n, + blas64.Vector{Inc: amat.Inc, Data: amat.Data}, + blas64.Vector{Inc: 1, Data: mat.Data}) + default: + mat.Data = make([]float64, r*c) + w := *m + w.mat = mat + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + w.set(i, j, a.At(i, j)) + } + } + *m = w + return + } + m.mat = mat +} + +// Copy makes a copy of elements of a into the receiver. It is similar to the +// built-in copy; it copies as much as the overlap between the two matrices and +// returns the number of rows and columns it copied. If a aliases the receiver +// and is a transposed Dense or Vector, with a non-unitary increment, Copy will +// panic. +// +// See the Copier interface for more information. +func (m *Dense) Copy(a Matrix) (r, c int) { + r, c = a.Dims() + if a == m { + return r, c + } + r = min(r, m.mat.Rows) + c = min(c, m.mat.Cols) + if r == 0 || c == 0 { + return 0, 0 + } + + aU, trans := untranspose(a) + switch aU := aU.(type) { + case RawMatrixer: + amat := aU.RawMatrix() + if trans { + if amat.Stride != 1 { + m.checkOverlap(amat) + } + for i := 0; i < r; i++ { + blas64.Copy(c, + blas64.Vector{Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, + blas64.Vector{Inc: 1, Data: m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]}) + } + } else { + switch o := offset(m.mat.Data, amat.Data); { + case o < 0: + for i := r - 1; i >= 0; i-- { + copy(m.mat.Data[i*m.mat.Stride:i*m.mat.Stride+c], amat.Data[i*amat.Stride:i*amat.Stride+c]) + } + case o > 0: + for i := 0; i < r; i++ { + copy(m.mat.Data[i*m.mat.Stride:i*m.mat.Stride+c], amat.Data[i*amat.Stride:i*amat.Stride+c]) + } + default: + // Nothing to do. + } + } + case *Vector: + var n, stride int + amat := aU.mat + if trans { + if amat.Inc != 1 { + m.checkOverlap(aU.asGeneral()) + } + n = c + stride = 1 + } else { + n = r + stride = m.mat.Stride + } + if amat.Inc == 1 && stride == 1 { + copy(m.mat.Data, amat.Data[:n]) + break + } + switch o := offset(m.mat.Data, amat.Data); { + case o < 0: + blas64.Copy(n, + blas64.Vector{Inc: -amat.Inc, Data: amat.Data}, + blas64.Vector{Inc: -stride, Data: m.mat.Data}) + case o > 0: + blas64.Copy(n, + blas64.Vector{Inc: amat.Inc, Data: amat.Data}, + blas64.Vector{Inc: stride, Data: m.mat.Data}) + default: + // Nothing to do. + } + default: + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + m.set(i, j, a.At(i, j)) + } + } + } + + return r, c +} + +// Stack appends the rows of b onto the rows of a, placing the result into the +// receiver with b placed in the greater indexed rows. Stack will panic if the +// two input matrices do not have the same number of columns or the constructed +// stacked matrix is not the same shape as the receiver. +func (m *Dense) Stack(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ac != bc || m == a || m == b { + panic(matrix.ErrShape) + } + + m.reuseAs(ar+br, ac) + + m.Copy(a) + w := m.Slice(ar, ar+br, 0, bc).(*Dense) + w.Copy(b) +} + +// Augment creates the augmented matrix of a and b, where b is placed in the +// greater indexed columns. Augment will panic if the two input matrices do +// not have the same number of rows or the constructed augmented matrix is +// not the same shape as the receiver. +func (m *Dense) Augment(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || m == a || m == b { + panic(matrix.ErrShape) + } + + m.reuseAs(ar, ac+bc) + + m.Copy(a) + w := m.Slice(0, br, ac, ac+bc).(*Dense) + w.Copy(b) +} diff --git a/matrix/mat64/dense_arithmetic.go b/matrix/mat64/dense_arithmetic.go new file mode 100644 index 00000000..8b94bbb9 --- /dev/null +++ b/matrix/mat64/dense_arithmetic.go @@ -0,0 +1,715 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +// Add adds a and b element-wise, placing the result in the receiver. Add +// will panic if the two matrices do not have the same shape. +func (m *Dense) Add(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + panic(matrix.ErrShape) + } + + aU, _ := untranspose(a) + bU, _ := untranspose(b) + m.reuseAs(ar, ac) + + if arm, ok := a.(RawMatrixer); ok { + if brm, ok := b.(RawMatrixer); ok { + amat, bmat := arm.RawMatrix(), brm.RawMatrix() + if m != aU { + m.checkOverlap(amat) + } + if m != bU { + m.checkOverlap(bmat) + } + for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v + bmat.Data[i+jb] + } + } + return + } + } + + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, a.At(r, c)+b.At(r, c)) + } + } +} + +// Sub subtracts the matrix b from a, placing the result in the receiver. Sub +// will panic if the two matrices do not have the same shape. +func (m *Dense) Sub(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + panic(matrix.ErrShape) + } + + aU, _ := untranspose(a) + bU, _ := untranspose(b) + m.reuseAs(ar, ac) + + if arm, ok := a.(RawMatrixer); ok { + if brm, ok := b.(RawMatrixer); ok { + amat, bmat := arm.RawMatrix(), brm.RawMatrix() + if m != aU { + m.checkOverlap(amat) + } + if m != bU { + m.checkOverlap(bmat) + } + for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v - bmat.Data[i+jb] + } + } + return + } + } + + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, a.At(r, c)-b.At(r, c)) + } + } +} + +// MulElem performs element-wise multiplication of a and b, placing the result +// in the receiver. MulElem will panic if the two matrices do not have the same +// shape. +func (m *Dense) MulElem(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + panic(matrix.ErrShape) + } + + aU, _ := untranspose(a) + bU, _ := untranspose(b) + m.reuseAs(ar, ac) + + if arm, ok := a.(RawMatrixer); ok { + if brm, ok := b.(RawMatrixer); ok { + amat, bmat := arm.RawMatrix(), brm.RawMatrix() + if m != aU { + m.checkOverlap(amat) + } + if m != bU { + m.checkOverlap(bmat) + } + for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v * bmat.Data[i+jb] + } + } + return + } + } + + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, a.At(r, c)*b.At(r, c)) + } + } +} + +// DivElem performs element-wise division of a by b, placing the result +// in the receiver. DivElem will panic if the two matrices do not have the same +// shape. +func (m *Dense) DivElem(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + panic(matrix.ErrShape) + } + + aU, _ := untranspose(a) + bU, _ := untranspose(b) + m.reuseAs(ar, ac) + + if arm, ok := a.(RawMatrixer); ok { + if brm, ok := b.(RawMatrixer); ok { + amat, bmat := arm.RawMatrix(), brm.RawMatrix() + if m != aU { + m.checkOverlap(amat) + } + if m != bU { + m.checkOverlap(bmat) + } + for ja, jb, jm := 0, 0, 0; ja < ar*amat.Stride; ja, jb, jm = ja+amat.Stride, jb+bmat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v / bmat.Data[i+jb] + } + } + return + } + } + + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, a.At(r, c)/b.At(r, c)) + } + } +} + +// Inverse computes the inverse of the matrix a, storing the result into the +// receiver. If a is ill-conditioned, a Condition error will be returned. +// Note that matrix inversion is numerically unstable, and should generally +// be avoided where possible, for example by using the Solve routines. +func (m *Dense) Inverse(a Matrix) error { + // TODO(btracey): Special case for RawTriangular, etc. + r, c := a.Dims() + if r != c { + panic(matrix.ErrSquare) + } + m.reuseAs(a.Dims()) + aU, aTrans := untranspose(a) + switch rm := aU.(type) { + case RawMatrixer: + if m != aU || aTrans { + if m == aU || m.checkOverlap(rm.RawMatrix()) { + tmp := getWorkspace(r, c, false) + tmp.Copy(a) + m.Copy(tmp) + putWorkspace(tmp) + break + } + m.Copy(a) + } + default: + m.Copy(a) + } + ipiv := make([]int, r) + ok := lapack64.Getrf(m.mat, ipiv) + if !ok { + return matrix.Condition(math.Inf(1)) + } + work := make([]float64, 1, 4*r) // must be at least 4*r for cond. + lapack64.Getri(m.mat, ipiv, work, -1) + if int(work[0]) > 4*r { + work = make([]float64, int(work[0])) + } else { + work = work[:4*r] + } + lapack64.Getri(m.mat, ipiv, work, len(work)) + norm := lapack64.Lange(matrix.CondNorm, m.mat, work) + rcond := lapack64.Gecon(matrix.CondNorm, m.mat, norm, work, ipiv) // reuse ipiv + if rcond == 0 { + return matrix.Condition(math.Inf(1)) + } + cond := 1 / rcond + if cond > matrix.ConditionTolerance { + return matrix.Condition(cond) + } + return nil +} + +// Mul takes the matrix product of a and b, placing the result in the receiver. +// If the number of columns in a does not equal the number of rows in b, Mul will panic. +func (m *Dense) Mul(a, b Matrix) { + ar, ac := a.Dims() + br, bc := b.Dims() + + if ac != br { + panic(matrix.ErrShape) + } + + aU, aTrans := untranspose(a) + bU, bTrans := untranspose(b) + m.reuseAs(ar, bc) + var restore func() + if m == aU { + m, restore = m.isolatedWorkspace(aU) + defer restore() + } else if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } + aT := blas.NoTrans + if aTrans { + aT = blas.Trans + } + bT := blas.NoTrans + if bTrans { + bT = blas.Trans + } + + // Some of the cases do not have a transpose option, so create + // temporary memory. + // C = A^T * B = (B^T * A)^T + // C^T = B^T * A. + if aUrm, ok := aU.(RawMatrixer); ok { + amat := aUrm.RawMatrix() + if restore == nil { + m.checkOverlap(amat) + } + if bUrm, ok := bU.(RawMatrixer); ok { + bmat := bUrm.RawMatrix() + if restore == nil { + m.checkOverlap(bmat) + } + blas64.Gemm(aT, bT, 1, amat, bmat, 0, m.mat) + return + } + if bU, ok := bU.(RawSymmetricer); ok { + bmat := bU.RawSymmetric() + if aTrans { + c := getWorkspace(ac, ar, false) + blas64.Symm(blas.Left, 1, bmat, amat, 0, c.mat) + strictCopy(m, c.T()) + putWorkspace(c) + return + } + blas64.Symm(blas.Right, 1, bmat, amat, 0, m.mat) + return + } + if bU, ok := bU.(RawTriangular); ok { + // Trmm updates in place, so copy aU first. + bmat := bU.RawTriangular() + if aTrans { + c := getWorkspace(ac, ar, false) + var tmp Dense + tmp.SetRawMatrix(amat) + c.Copy(&tmp) + bT := blas.Trans + if bTrans { + bT = blas.NoTrans + } + blas64.Trmm(blas.Left, bT, 1, bmat, c.mat) + strictCopy(m, c.T()) + putWorkspace(c) + return + } + m.Copy(a) + blas64.Trmm(blas.Right, bT, 1, bmat, m.mat) + return + } + if bU, ok := bU.(*Vector); ok { + m.checkOverlap(bU.asGeneral()) + bvec := bU.RawVector() + if bTrans { + // {ar,1} x {1,bc}, which is not a vector. + // Instead, construct B as a General. + bmat := blas64.General{ + Rows: bc, + Cols: 1, + Stride: bvec.Inc, + Data: bvec.Data, + } + blas64.Gemm(aT, bT, 1, amat, bmat, 0, m.mat) + return + } + cvec := blas64.Vector{ + Inc: m.mat.Stride, + Data: m.mat.Data, + } + blas64.Gemv(aT, 1, amat, bvec, 0, cvec) + return + } + } + if bUrm, ok := bU.(RawMatrixer); ok { + bmat := bUrm.RawMatrix() + if restore == nil { + m.checkOverlap(bmat) + } + if aU, ok := aU.(RawSymmetricer); ok { + amat := aU.RawSymmetric() + if bTrans { + c := getWorkspace(bc, br, false) + blas64.Symm(blas.Right, 1, amat, bmat, 0, c.mat) + strictCopy(m, c.T()) + putWorkspace(c) + return + } + blas64.Symm(blas.Left, 1, amat, bmat, 0, m.mat) + return + } + if aU, ok := aU.(RawTriangular); ok { + // Trmm updates in place, so copy bU first. + amat := aU.RawTriangular() + if bTrans { + c := getWorkspace(bc, br, false) + var tmp Dense + tmp.SetRawMatrix(bmat) + c.Copy(&tmp) + aT := blas.Trans + if aTrans { + aT = blas.NoTrans + } + blas64.Trmm(blas.Right, aT, 1, amat, c.mat) + strictCopy(m, c.T()) + putWorkspace(c) + return + } + m.Copy(b) + blas64.Trmm(blas.Left, aT, 1, amat, m.mat) + return + } + if aU, ok := aU.(*Vector); ok { + m.checkOverlap(aU.asGeneral()) + avec := aU.RawVector() + if aTrans { + // {1,ac} x {ac, bc} + // Transpose B so that the vector is on the right. + cvec := blas64.Vector{ + Inc: 1, + Data: m.mat.Data, + } + bT := blas.Trans + if bTrans { + bT = blas.NoTrans + } + blas64.Gemv(bT, 1, bmat, avec, 0, cvec) + return + } + // {ar,1} x {1,bc} which is not a vector result. + // Instead, construct A as a General. + amat := blas64.General{ + Rows: ar, + Cols: 1, + Stride: avec.Inc, + Data: avec.Data, + } + blas64.Gemm(aT, bT, 1, amat, bmat, 0, m.mat) + return + } + } + + row := make([]float64, ac) + for r := 0; r < ar; r++ { + for i := range row { + row[i] = a.At(r, i) + } + for c := 0; c < bc; c++ { + var v float64 + for i, e := range row { + v += e * b.At(i, c) + } + m.mat.Data[r*m.mat.Stride+c] = v + } + } +} + +// strictCopy copies a into m panicking if the shape of a and m differ. +func strictCopy(m *Dense, a Matrix) { + r, c := m.Copy(a) + if r != m.mat.Rows || c != m.mat.Cols { + // Panic with a string since this + // is not a user-facing panic. + panic(matrix.ErrShape.Error()) + } +} + +// Exp calculates the exponential of the matrix a, e^a, placing the result +// in the receiver. Exp will panic with matrix.ErrShape if a is not square. +// +// Exp uses the scaling and squaring method described in section 3 of +// http://www.cs.cornell.edu/cv/researchpdf/19ways+.pdf. +func (m *Dense) Exp(a Matrix) { + r, c := a.Dims() + if r != c { + panic(matrix.ErrShape) + } + + var w *Dense + if m.isZero() { + m.reuseAsZeroed(r, r) + w = m + } else { + w = getWorkspace(r, r, true) + } + for i := 0; i < r*r; i += r + 1 { + w.mat.Data[i] = 1 + } + + const ( + terms = 10 + scaling = 4 + ) + + small := getWorkspace(r, r, false) + small.Scale(math.Pow(2, -scaling), a) + power := getWorkspace(r, r, false) + power.Copy(small) + + var ( + tmp = getWorkspace(r, r, false) + factI = 1. + ) + for i := 1.; i < terms; i++ { + factI *= i + + // This is OK to do because power and tmp are + // new Dense values so all rows are contiguous. + // TODO(kortschak) Make this explicit in the NewDense doc comment. + for j, v := range power.mat.Data { + tmp.mat.Data[j] = v / factI + } + + w.Add(w, tmp) + if i < terms-1 { + tmp.Mul(power, small) + tmp, power = power, tmp + } + } + putWorkspace(small) + putWorkspace(power) + for i := 0; i < scaling; i++ { + tmp.Mul(w, w) + tmp, w = w, tmp + } + putWorkspace(tmp) + + if w != m { + m.Copy(w) + putWorkspace(w) + } +} + +// Pow calculates the integral power of the matrix a to n, placing the result +// in the receiver. Pow will panic if n is negative or if a is not square. +func (m *Dense) Pow(a Matrix, n int) { + if n < 0 { + panic("matrix: illegal power") + } + r, c := a.Dims() + if r != c { + panic(matrix.ErrShape) + } + + m.reuseAs(r, c) + + // Take possible fast paths. + switch n { + case 0: + for i := 0; i < r; i++ { + zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) + m.mat.Data[i*m.mat.Stride+i] = 1 + } + return + case 1: + m.Copy(a) + return + case 2: + m.Mul(a, a) + return + } + + // Perform iterative exponentiation by squaring in work space. + w := getWorkspace(r, r, false) + w.Copy(a) + s := getWorkspace(r, r, false) + s.Copy(a) + x := getWorkspace(r, r, false) + for n--; n > 0; n >>= 1 { + if n&1 != 0 { + x.Mul(w, s) + w, x = x, w + } + if n != 1 { + x.Mul(s, s) + s, x = x, s + } + } + m.Copy(w) + putWorkspace(w) + putWorkspace(s) + putWorkspace(x) +} + +// Scale multiplies the elements of a by f, placing the result in the receiver. +// +// See the Scaler interface for more information. +func (m *Dense) Scale(f float64, a Matrix) { + ar, ac := a.Dims() + + m.reuseAs(ar, ac) + + aU, aTrans := untranspose(a) + if rm, ok := aU.(RawMatrixer); ok { + amat := rm.RawMatrix() + if m == aU || m.checkOverlap(amat) { + var restore func() + m, restore = m.isolatedWorkspace(a) + defer restore() + } + if !aTrans { + for ja, jm := 0, 0; ja < ar*amat.Stride; ja, jm = ja+amat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = v * f + } + } + } else { + for ja, jm := 0, 0; ja < ac*amat.Stride; ja, jm = ja+amat.Stride, jm+1 { + for i, v := range amat.Data[ja : ja+ar] { + m.mat.Data[i*m.mat.Stride+jm] = v * f + } + } + } + return + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, f*a.At(r, c)) + } + } +} + +// Apply applies the function fn to each of the elements of a, placing the +// resulting matrix in the receiver. The function fn takes a row/column +// index and element value and returns some function of that tuple. +func (m *Dense) Apply(fn func(i, j int, v float64) float64, a Matrix) { + ar, ac := a.Dims() + + m.reuseAs(ar, ac) + + aU, aTrans := untranspose(a) + if rm, ok := aU.(RawMatrixer); ok { + amat := rm.RawMatrix() + if m == aU || m.checkOverlap(amat) { + var restore func() + m, restore = m.isolatedWorkspace(a) + defer restore() + } + if !aTrans { + for j, ja, jm := 0, 0, 0; ja < ar*amat.Stride; j, ja, jm = j+1, ja+amat.Stride, jm+m.mat.Stride { + for i, v := range amat.Data[ja : ja+ac] { + m.mat.Data[i+jm] = fn(j, i, v) + } + } + } else { + for j, ja, jm := 0, 0, 0; ja < ac*amat.Stride; j, ja, jm = j+1, ja+amat.Stride, jm+1 { + for i, v := range amat.Data[ja : ja+ar] { + m.mat.Data[i*m.mat.Stride+jm] = fn(i, j, v) + } + } + } + return + } + + for r := 0; r < ar; r++ { + for c := 0; c < ac; c++ { + m.set(r, c, fn(r, c, a.At(r, c))) + } + } +} + +// RankOne performs a rank-one update to the matrix a and stores the result +// in the receiver. If a is zero, see Outer. +// m = a + alpha * x * y' +func (m *Dense) RankOne(a Matrix, alpha float64, x, y *Vector) { + ar, ac := a.Dims() + if x.Len() != ar { + panic(matrix.ErrShape) + } + if y.Len() != ac { + panic(matrix.ErrShape) + } + + m.checkOverlap(x.asGeneral()) + m.checkOverlap(y.asGeneral()) + + var w Dense + if m == a { + w = *m + } + w.reuseAs(ar, ac) + + // Copy over to the new memory if necessary + if m != a { + w.Copy(a) + } + blas64.Ger(alpha, x.mat, y.mat, w.mat) + *m = w +} + +// Outer calculates the outer product of x and y, and stores the result +// in the receiver. +// m = alpha * x * y' +// In order to update an existing matrix, see RankOne. +func (m *Dense) Outer(alpha float64, x, y *Vector) { + r := x.Len() + c := y.Len() + + // Copied from reuseAs with use replaced by useZeroed + // and a final zero of the matrix elements if we pass + // the shape checks. + // TODO(kortschak): Factor out into reuseZeroedAs if + // we find another case that needs it. + if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { + // Panic as a string, not a mat64.Error. + panic("mat64: caps not correctly set") + } + if m.isZero() { + m.mat = blas64.General{ + Rows: r, + Cols: c, + Stride: c, + Data: useZeroed(m.mat.Data, r*c), + } + m.capRows = r + m.capCols = c + } else if r != m.mat.Rows || c != m.mat.Cols { + panic(matrix.ErrShape) + } else { + m.checkOverlap(x.asGeneral()) + m.checkOverlap(y.asGeneral()) + for i := 0; i < r; i++ { + zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) + } + } + + blas64.Ger(alpha, x.mat, y.mat, m.mat) +} diff --git a/matrix/mat64/dense_test.go b/matrix/mat64/dense_test.go new file mode 100644 index 00000000..3fc9a382 --- /dev/null +++ b/matrix/mat64/dense_test.go @@ -0,0 +1,2007 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "fmt" + "math" + "math/rand" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix" +) + +func asBasicMatrix(d *Dense) Matrix { return (*basicMatrix)(d) } +func asBasicSymmetric(s *SymDense) Matrix { return (*basicSymmetric)(s) } +func asBasicTriangular(t *TriDense) Triangular { return (*basicTriangular)(t) } + +func TestNewDense(t *testing.T) { + for i, test := range []struct { + a []float64 + rows, cols int + min, max float64 + fro float64 + mat *Dense + }{ + { + []float64{ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + }, + 3, 3, + 0, 0, + 0, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 3, + Stride: 3, + Data: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + capRows: 3, capCols: 3, + }, + }, + { + []float64{ + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + }, + 3, 3, + 1, 1, + 3, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 3, + Stride: 3, + Data: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1}, + }, + capRows: 3, capCols: 3, + }, + }, + { + []float64{ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + }, + 3, 3, + 0, 1, + 1.7320508075688772, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 3, + Stride: 3, + Data: []float64{1, 0, 0, 0, 1, 0, 0, 0, 1}, + }, + capRows: 3, capCols: 3, + }, + }, + { + []float64{ + -1, 0, 0, + 0, -1, 0, + 0, 0, -1, + }, + 3, 3, + -1, 0, + 1.7320508075688772, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 3, + Stride: 3, + Data: []float64{-1, 0, 0, 0, -1, 0, 0, 0, -1}, + }, + capRows: 3, capCols: 3, + }, + }, + { + []float64{ + 1, 2, 3, + 4, 5, 6, + }, + 2, 3, + 1, 6, + 9.539392014169458, + &Dense{ + mat: blas64.General{ + Rows: 2, Cols: 3, + Stride: 3, + Data: []float64{1, 2, 3, 4, 5, 6}, + }, + capRows: 2, capCols: 3, + }, + }, + { + []float64{ + 1, 2, + 3, 4, + 5, 6, + }, + 3, 2, + 1, 6, + 9.539392014169458, + &Dense{ + mat: blas64.General{ + Rows: 3, Cols: 2, + Stride: 2, + Data: []float64{1, 2, 3, 4, 5, 6}, + }, + capRows: 3, capCols: 2, + }, + }, + } { + m := NewDense(test.rows, test.cols, test.a) + rows, cols := m.Dims() + if rows != test.rows { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.rows) + } + if cols != test.cols { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.cols) + } + if min := Min(m); min != test.min { + t.Errorf("unexpected min for test %d: got: %v want: %v", i, min, test.min) + } + if max := Max(m); max != test.max { + t.Errorf("unexpected max for test %d: got: %v want: %v", i, max, test.max) + } + if fro := Norm(m, 2); math.Abs(Norm(m, 2)-test.fro) > 1e-14 { + t.Errorf("unexpected Frobenius norm for test %d: got: %v want: %v", i, fro, test.fro) + } + if !reflect.DeepEqual(m, test.mat) { + t.Errorf("unexpected matrix for test %d", i) + } + if !Equal(m, test.mat) { + t.Errorf("matrix does not equal expected matrix for test %d", i) + } + } +} + +func TestAtSet(t *testing.T) { + for test, af := range [][][]float64{ + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // even + {{1, 2}, {4, 5}, {7, 8}}, // wide + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, //skinny + } { + m := NewDense(flatten(af)) + rows, cols := m.Dims() + for i := 0; i < rows; i++ { + for j := 0; j < cols; j++ { + if m.At(i, j) != af[i][j] { + t.Errorf("unexpected value for At(%d, %d) for test %d: got: %v want: %v", + i, j, test, m.At(i, j), af[i][j]) + } + + v := float64(i * j) + m.Set(i, j, v) + if m.At(i, j) != v { + t.Errorf("unexpected value for At(%d, %d) after Set(%[1]d, %d, %v) for test %d: got: %v want: %[3]v", + i, j, v, test, m.At(i, j)) + } + } + } + // Check access out of bounds fails + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { m.At(row, 0) }) + if !panicked || message != matrix.ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { m.At(0, col) }) + if !panicked || message != matrix.ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + // Check Set out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { m.Set(row, 0, 1.2) }) + if !panicked || message != matrix.ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { m.Set(0, col, 1.2) }) + if !panicked || message != matrix.ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + } +} + +func TestSetRowColumn(t *testing.T) { + for _, as := range [][][]float64{ + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}, + {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, + } { + for ri, row := range as { + a := NewDense(flatten(as)) + m := &Dense{} + m.Clone(a) + a.SetRow(ri, make([]float64, a.mat.Cols)) + m.Sub(m, a) + nt := Norm(m, 2) + nr := floats.Norm(row, 2) + if math.Abs(nt-nr) > 1e-14 { + t.Errorf("Row %d norm mismatch, want: %g, got: %g", ri, nr, nt) + } + } + + for ci := range as[0] { + a := NewDense(flatten(as)) + m := &Dense{} + m.Clone(a) + a.SetCol(ci, make([]float64, a.mat.Rows)) + col := make([]float64, a.mat.Rows) + for j := range col { + col[j] = float64(ci + 1 + j*a.mat.Cols) + } + m.Sub(m, a) + nt := Norm(m, 2) + nc := floats.Norm(col, 2) + if math.Abs(nt-nc) > 1e-14 { + t.Errorf("Column %d norm mismatch, want: %g, got: %g", ci, nc, nt) + } + } + } +} + +func TestRowColView(t *testing.T) { + for _, test := range []struct { + mat [][]float64 + }{ + { + mat: [][]float64{ + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10}, + {11, 12, 13, 14, 15}, + {16, 17, 18, 19, 20}, + {21, 22, 23, 24, 25}, + }, + }, + { + mat: [][]float64{ + {1, 2, 3, 4}, + {6, 7, 8, 9}, + {11, 12, 13, 14}, + {16, 17, 18, 19}, + {21, 22, 23, 24}, + }, + }, + { + mat: [][]float64{ + {1, 2, 3, 4, 5}, + {6, 7, 8, 9, 10}, + {11, 12, 13, 14, 15}, + {16, 17, 18, 19, 20}, + }, + }, + } { + // This over cautious approach to building a matrix data + // slice is to ensure that changes to flatten in the future + // do not mask a regression to the issue identified in + // gonum/matrix#110. + rows, cols, flat := flatten(test.mat) + m := NewDense(rows, cols, flat[:len(flat):len(flat)]) + + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { m.At(row, 0) }) + if !panicked || message != matrix.ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access rows=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { m.At(0, col) }) + if !panicked || message != matrix.ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access cols=%d c=%d", cols, col) + } + } + + for i := 0; i < rows; i++ { + vr := m.RowView(i) + if vr.Len() != cols { + t.Errorf("unexpected number of columns: got: %d want: %d", vr.Len(), cols) + } + for j := 0; j < cols; j++ { + if got := vr.At(j, 0); got != test.mat[i][j] { + t.Errorf("unexpected value for row.At(%d, 0): got: %v want: %v", + j, got, test.mat[i][j]) + } + } + } + for j := 0; j < cols; j++ { + vc := m.ColView(j) + if vc.Len() != rows { + t.Errorf("unexpected number of rows: got: %d want: %d", vc.Len(), rows) + } + for i := 0; i < rows; i++ { + if got := vc.At(i, 0); got != test.mat[i][j] { + t.Errorf("unexpected value for col.At(%d, 0): got: %v want: %v", + i, got, test.mat[i][j]) + } + } + } + m = m.Slice(1, rows-1, 1, cols-1).(*Dense) + for i := 1; i < rows-1; i++ { + vr := m.RowView(i - 1) + if vr.Len() != cols-2 { + t.Errorf("unexpected number of columns: got: %d want: %d", vr.Len(), cols-2) + } + for j := 1; j < cols-1; j++ { + if got := vr.At(j-1, 0); got != test.mat[i][j] { + t.Errorf("unexpected value for row.At(%d, 0): got: %v want: %v", + j-1, got, test.mat[i][j]) + } + } + } + for j := 1; j < cols-1; j++ { + vc := m.ColView(j - 1) + if vc.Len() != rows-2 { + t.Errorf("unexpected number of rows: got: %d want: %d", vc.Len(), rows-2) + } + for i := 1; i < rows-1; i++ { + if got := vc.At(i-1, 0); got != test.mat[i][j] { + t.Errorf("unexpected value for col.At(%d, 0): got: %v want: %v", + i-1, got, test.mat[i][j]) + } + } + } + } +} + +func TestGrow(t *testing.T) { + m := &Dense{} + m = m.Grow(10, 10).(*Dense) + rows, cols := m.Dims() + capRows, capCols := m.Caps() + if rows != 10 { + t.Errorf("unexpected value for rows: got: %d want: 10", rows) + } + if cols != 10 { + t.Errorf("unexpected value for cols: got: %d want: 10", cols) + } + if capRows != 10 { + t.Errorf("unexpected value for capRows: got: %d want: 10", capRows) + } + if capCols != 10 { + t.Errorf("unexpected value for capCols: got: %d want: 10", capCols) + } + + // Test grow within caps is in-place. + m.Set(1, 1, 1) + v := m.Slice(1, 5, 1, 5).(*Dense) + if v.At(0, 0) != m.At(1, 1) { + t.Errorf("unexpected viewed element value: got: %v want: %v", v.At(0, 0), m.At(1, 1)) + } + v = v.Grow(5, 5).(*Dense) + if !Equal(v, m.Slice(1, 10, 1, 10)) { + t.Error("unexpected view value after grow") + } + + // Test grow bigger than caps copies. + v = v.Grow(5, 5).(*Dense) + if !Equal(v.Slice(0, 9, 0, 9), m.Slice(1, 10, 1, 10)) { + t.Error("unexpected mismatched common view value after grow") + } + v.Set(0, 0, 0) + if Equal(v.Slice(0, 9, 0, 9), m.Slice(1, 10, 1, 10)) { + t.Error("unexpected matching view value after grow past capacity") + } + + // Test grow uses existing data slice when matrix is zero size. + v.Reset() + p, l := &v.mat.Data[:1][0], cap(v.mat.Data) + *p = 1 // This element is at position (-1, -1) relative to v and so should not be visible. + v = v.Grow(5, 5).(*Dense) + if &v.mat.Data[:1][0] != p { + t.Error("grow unexpectedly copied slice within cap limit") + } + if cap(v.mat.Data) != l { + t.Errorf("unexpected change in data slice capacity: got: %d want: %d", cap(v.mat.Data), l) + } + if v.At(0, 0) != 0 { + t.Errorf("unexpected value for At(0, 0): got: %v want: 0", v.At(0, 0)) + } +} + +func TestAdd(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{2, 2, 2}, {2, 2, 2}, {2, 2, 2}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{2, 0, 0}, {0, 2, 0}, {0, 0, 2}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-2, 0, 0}, {0, -2, 0}, {0, 0, -2}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{2, 4, 6}, {8, 10, 12}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.Add(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Add for test %d %v Add %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.Add(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Add for test %d %v Add %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.Add(a, b) }) + if !panicked || message != "runtime error: index out of range" { + t.Error("exected runtime panic for nil data slice") + } + + a.Add(a, b) + if !Equal(a, r) { + t.Errorf("unexpected result from Add for test %d %v Add %v: got: %v want: %v", + i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r) + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).Add(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type Adder interface { + Add(a, b Matrix) + } + rd := receiver.(Adder) + rd.Add(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Add(a, b) + } + testTwoInput(t, "Add", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14) +} + +func TestSub(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{0, 0, 0}, {0, 0, 0}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.Sub(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Sub for test %d %v Sub %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.Sub(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Sub for test %d %v Sub %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.Sub(a, b) }) + if !panicked || message != "runtime error: index out of range" { + t.Error("exected runtime panic for nil data slice") + } + + a.Sub(a, b) + if !Equal(a, r) { + t.Errorf("unexpected result from Sub for test %d %v Sub %v: got: %v want: %v", + i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r) + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).Sub(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type Suber interface { + Sub(a, b Matrix) + } + rd := receiver.(Suber) + rd.Sub(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Sub(a, b) + } + testTwoInput(t, "Sub", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14) +} + +func TestMulElem(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 4, 9}, {16, 25, 36}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.MulElem(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from MulElem for test %d %v MulElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.MulElem(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from MulElem for test %d %v MulElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.MulElem(a, b) }) + if !panicked || message != "runtime error: index out of range" { + t.Error("exected runtime panic for nil data slice") + } + + a.MulElem(a, b) + if !Equal(a, r) { + t.Errorf("unexpected result from MulElem for test %d %v MulElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r) + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).MulElem(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type ElemMuler interface { + MulElem(a, b Matrix) + } + rd := receiver.(ElemMuler) + rd.MulElem(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.MulElem(a, b) + } + testTwoInput(t, "MulElem", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14) +} + +// A comparison that treats NaNs as equal, for testing. +func (m *Dense) same(b Matrix) bool { + br, bc := b.Dims() + if br != m.mat.Rows || bc != m.mat.Cols { + return false + } + for r := 0; r < br; r++ { + for c := 0; c < bc; c++ { + if av, bv := m.At(r, c), b.At(r, c); av != bv && !(math.IsNaN(av) && math.IsNaN(bv)) { + return false + } + } + } + return true +} + +func TestDivElem(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{math.Inf(1), math.NaN(), math.NaN()}, {math.NaN(), math.Inf(1), math.NaN()}, {math.NaN(), math.NaN(), math.Inf(1)}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, math.NaN(), math.NaN()}, {math.NaN(), 1, math.NaN()}, {math.NaN(), math.NaN(), 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{1, math.NaN(), math.NaN()}, {math.NaN(), 1, math.NaN()}, {math.NaN(), math.NaN(), 1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 1, 1}, {1, 1, 1}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.DivElem(a, b) + if !temp.same(r) { + t.Errorf("unexpected result from DivElem for test %d %v DivElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.DivElem(a, b) + if !temp.same(r) { + t.Errorf("unexpected result from DivElem for test %d %v DivElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.DivElem(a, b) }) + if !panicked || message != "runtime error: index out of range" { + t.Error("exected runtime panic for nil data slice") + } + + a.DivElem(a, b) + if !a.same(r) { + t.Errorf("unexpected result from DivElem for test %d %v DivElem %v: got: %v want: %v", + i, test.a, test.b, unflatten(a.mat.Rows, a.mat.Cols, a.mat.Data), test.r) + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).DivElem(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type ElemDiver interface { + DivElem(a, b Matrix) + } + rd := receiver.(ElemDiver) + rd.DivElem(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.DivElem(a, b) + } + testTwoInput(t, "DivElem", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameRectangular, 1e-14) +} + +func TestMul(t *testing.T) { + for i, test := range []struct { + a, b, r [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{3, 3, 3}, {3, 3, 3}, {3, 3, 3}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2}, {3, 4}, {5, 6}}, + [][]float64{{22, 28}, {49, 64}}, + }, + { + [][]float64{{0, 1, 1}, {0, 1, 1}, {0, 1, 1}}, + [][]float64{{0, 1, 1}, {0, 1, 1}, {0, 1, 1}}, + [][]float64{{0, 2, 2}, {0, 2, 2}, {0, 2, 2}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + r := NewDense(flatten(test.r)) + + var temp Dense + temp.Mul(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Mul for test %d %v Mul %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + zero(temp.mat.Data) + temp.Mul(a, b) + if !Equal(&temp, r) { + t.Errorf("unexpected result from Mul for test %d %v Mul %v: got: %v want: %v", + i, test.a, test.b, unflatten(temp.mat.Rows, temp.mat.Cols, temp.mat.Data), test.r) + } + + // These probably warrant a better check and failure. They should never happen in the wild though. + temp.mat.Data = nil + panicked, message := panics(func() { temp.Mul(a, b) }) + if !panicked || message != "blas: insufficient matrix slice length" { + if message != "" { + t.Errorf("expected runtime panic for nil data slice: got %q", message) + } else { + t.Error("expected runtime panic for nil data slice") + } + } + } + + panicked, message := panics(func() { + m := NewDense(10, 10, nil) + a := NewDense(5, 5, nil) + m.Slice(1, 6, 1, 6).(*Dense).Mul(a, m.Slice(2, 7, 2, 7)) + }) + if !panicked { + t.Error("expected panic for overlapping matrices") + } + if message != regionOverlap { + t.Errorf("unexpected panic message: got: %q want: %q", message, regionOverlap) + } + + method := func(receiver, a, b Matrix) { + type Muler interface { + Mul(a, b Matrix) + } + rd := receiver.(Muler) + rd.Mul(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Mul(a, b) + } + legalSizeMul := func(ar, ac, br, bc int) bool { + return ac == br + } + testTwoInput(t, "Mul", &Dense{}, method, denseComparison, legalTypesAll, legalSizeMul, 1e-14) +} + +func randDense(size int, rho float64, rnd func() float64) (*Dense, error) { + if size == 0 { + return nil, matrix.ErrZeroLength + } + d := &Dense{ + mat: blas64.General{ + Rows: size, Cols: size, Stride: size, + Data: make([]float64, size*size), + }, + capRows: size, capCols: size, + } + for i := 0; i < size; i++ { + for j := 0; j < size; j++ { + if rand.Float64() < rho { + d.Set(i, j, rnd()) + } + } + } + return d, nil +} + +func TestExp(t *testing.T) { + for i, test := range []struct { + a [][]float64 + want [][]float64 + mod func(*Dense) + }{ + { + a: [][]float64{{-49, 24}, {-64, 31}}, + want: [][]float64{{-0.7357587581474017, 0.5518190996594223}, {-1.4715175990917921, 1.103638240717339}}, + }, + { + a: [][]float64{{-49, 24}, {-64, 31}}, + want: [][]float64{{-0.7357587581474017, 0.5518190996594223}, {-1.4715175990917921, 1.103638240717339}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 3, 1, 3).(*Dense) + }, + }, + { + a: [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + want: [][]float64{{2.71828182845905, 0, 0}, {0, 2.71828182845905, 0}, {0, 0, 2.71828182845905}}, + }, + } { + var got Dense + if test.mod != nil { + test.mod(&got) + } + got.Exp(NewDense(flatten(test.a))) + if !EqualApprox(&got, NewDense(flatten(test.want)), 1e-12) { + t.Errorf("unexpected result for Exp test %d", i) + } + } +} + +func TestPow(t *testing.T) { + for i, test := range []struct { + a [][]float64 + n int + mod func(*Dense) + want [][]float64 + }{ + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 0, + want: [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 0, + want: [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 1, + want: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 1, + want: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 2, + want: [][]float64{{30, 36, 42}, {66, 81, 96}, {102, 126, 150}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 2, + want: [][]float64{{30, 36, 42}, {66, 81, 96}, {102, 126, 150}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 3, + want: [][]float64{{468, 576, 684}, {1062, 1305, 1548}, {1656, 2034, 2412}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + n: 3, + want: [][]float64{{468, 576, 684}, {1062, 1305, 1548}, {1656, 2034, 2412}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + } { + var got Dense + if test.mod != nil { + test.mod(&got) + } + got.Pow(NewDense(flatten(test.a)), test.n) + if !EqualApprox(&got, NewDense(flatten(test.want)), 1e-12) { + t.Errorf("unexpected result for Pow test %d", i) + } + } +} + +func TestScale(t *testing.T) { + for _, f := range []float64{0.5, 1, 3} { + method := func(receiver, a Matrix) { + type Scaler interface { + Scale(f float64, a Matrix) + } + rd := receiver.(Scaler) + rd.Scale(f, a) + } + denseComparison := func(receiver, a *Dense) { + receiver.Scale(f, a) + } + testOneInput(t, "Scale", &Dense{}, method, denseComparison, isAnyType, isAnySize, 1e-14) + } +} + +func TestPowN(t *testing.T) { + for i, test := range []struct { + a [][]float64 + mod func(*Dense) + want [][]float64 + }{ + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, + mod: func(a *Dense) { + d := make([]float64, 100) + for i := range d { + d[i] = math.NaN() + } + *a = *NewDense(10, 10, d).Slice(1, 4, 1, 4).(*Dense) + }, + }, + } { + for n := 1; n <= 14; n++ { + var got, want Dense + if test.mod != nil { + test.mod(&got) + } + got.Pow(NewDense(flatten(test.a)), n) + want.iterativePow(NewDense(flatten(test.a)), n) + if !Equal(&got, &want) { + t.Errorf("unexpected result for iterative Pow test %d", i) + } + } + } +} + +func (m *Dense) iterativePow(a Matrix, n int) { + m.Clone(a) + for i := 1; i < n; i++ { + m.Mul(m, a) + } +} + +func TestCloneT(t *testing.T) { + for i, test := range []struct { + a, want [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 4}, {2, 5}, {3, 6}}, + }, + } { + a := NewDense(flatten(test.a)) + want := NewDense(flatten(test.want)) + + var got, gotT Dense + + for j := 0; j < 2; j++ { + got.Clone(a.T()) + if !Equal(&got, want) { + t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v", + i, j, test.a, test.want) + } + gotT.Clone(got.T()) + if !Equal(&gotT, a) { + t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v", + i, j, test.a, test.want) + } + + zero(got.mat.Data) + } + } +} + +func TestCopyT(t *testing.T) { + for i, test := range []struct { + a, want [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 4}, {2, 5}, {3, 6}}, + }, + } { + a := NewDense(flatten(test.a)) + want := NewDense(flatten(test.want)) + + ar, ac := a.Dims() + got := NewDense(ac, ar, nil) + rr := NewDense(ar, ac, nil) + + for j := 0; j < 2; j++ { + got.Copy(a.T()) + if !Equal(got, want) { + t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v", + i, j, test.a, test.want) + } + rr.Copy(got.T()) + if !Equal(rr, a) { + t.Errorf("expected transpose for test %d iteration %d: %v transpose = %v", + i, j, test.a, test.want) + } + + zero(got.mat.Data) + } + } +} + +func TestCopyDenseAlias(t *testing.T) { + for _, trans := range []bool{false, true} { + for di := 0; di < 2; di++ { + for dj := 0; dj < 2; dj++ { + for si := 0; si < 2; si++ { + for sj := 0; sj < 2; sj++ { + a := NewDense(3, 3, []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }) + src := a.Slice(si, si+2, sj, sj+2) + want := DenseCopyOf(src) + got := a.Slice(di, di+2, dj, dj+2).(*Dense) + + if trans { + panicked, _ := panics(func() { got.Copy(src.T()) }) + if !panicked { + t.Errorf("expected panic for transpose aliased copy with offsets dst(%d,%d) src(%d,%d):\ngot:\n%v\nwant:\n%v", + di, dj, si, sj, Formatted(got), Formatted(want), + ) + } + continue + } + + got.Copy(src) + if !Equal(got, want) { + t.Errorf("unexpected aliased copy result with offsets dst(%d,%d) src(%d,%d):\ngot:\n%v\nwant:\n%v", + di, dj, si, sj, Formatted(got), Formatted(want), + ) + } + } + } + } + } + } +} + +func TestCopyVectorAlias(t *testing.T) { + for _, horiz := range []bool{false, true} { + for do := 0; do < 2; do++ { + for di := 0; di < 3; di++ { + for si := 0; si < 3; si++ { + a := NewDense(3, 3, []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }) + var src *Vector + var want *Dense + if horiz { + src = a.RowView(si) + want = DenseCopyOf(a.Slice(si, si+1, 0, 2)) + } else { + src = a.ColView(si) + want = DenseCopyOf(a.Slice(0, 2, si, si+1)) + } + + var got *Dense + if horiz { + got = a.Slice(di, di+1, do, do+2).(*Dense) + got.Copy(src.T()) + } else { + got = a.Slice(do, do+2, di, di+1).(*Dense) + got.Copy(src) + } + + if !Equal(got, want) { + t.Errorf("unexpected aliased copy result with offsets dst(%d) src(%d):\ngot:\n%v\nwant:\n%v", + di, si, Formatted(got), Formatted(want), + ) + } + } + } + } + } +} + +func identity(r, c int, v float64) float64 { return v } + +func TestApply(t *testing.T) { + for i, test := range []struct { + a, want [][]float64 + fn func(r, c int, v float64) float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + identity, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + identity, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + identity, + }, + { + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + [][]float64{{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, + identity, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{1, 2, 3}, {4, 5, 6}}, + identity, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{2, 4, 6}, {8, 10, 12}}, + func(r, c int, v float64) float64 { return v * 2 }, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{0, 2, 0}, {0, 5, 0}}, + func(r, c int, v float64) float64 { + if c == 1 { + return v + } + return 0 + }, + }, + { + [][]float64{{1, 2, 3}, {4, 5, 6}}, + [][]float64{{0, 0, 0}, {4, 5, 6}}, + func(r, c int, v float64) float64 { + if r == 1 { + return v + } + return 0 + }, + }, + } { + a := NewDense(flatten(test.a)) + want := NewDense(flatten(test.want)) + + var got Dense + + for j := 0; j < 2; j++ { + got.Apply(test.fn, a) + if !Equal(&got, want) { + t.Errorf("unexpected result for test %d iteration %d: got: %v want: %v", i, j, got.mat.Data, want.mat.Data) + } + } + } + + for _, fn := range []func(r, c int, v float64) float64{ + identity, + func(r, c int, v float64) float64 { + if r < c { + return v + } + return -v + }, + func(r, c int, v float64) float64 { + if r%2 == 0 && c%2 == 0 { + return v + } + return -v + }, + func(_, _ int, v float64) float64 { return v * v }, + func(_, _ int, v float64) float64 { return -v }, + } { + method := func(receiver, x Matrix) { + type Applier interface { + Apply(func(r, c int, v float64) float64, Matrix) + } + rd := receiver.(Applier) + rd.Apply(fn, x) + } + denseComparison := func(receiver, x *Dense) { + receiver.Apply(fn, x) + } + testOneInput(t, "Apply", &Dense{}, method, denseComparison, isAnyType, isAnySize, 0) + } +} + +func TestClone(t *testing.T) { + for i, test := range []struct { + a [][]float64 + i, j int + v float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + 1, 1, + 1, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + 0, 0, + 0, + }, + } { + a := NewDense(flatten(test.a)) + b := *a + a.Clone(a) + a.Set(test.i, test.j, test.v) + + if Equal(&b, a) { + t.Errorf("unexpected mirror of write to cloned matrix for test %d: %v cloned and altered = %v", + i, a, &b) + } + } +} + +// TODO(kortschak) Roll this into testOneInput when it exists. +func TestCopyPanic(t *testing.T) { + for _, a := range []*Dense{ + {}, + {mat: blas64.General{Rows: 1}}, + {mat: blas64.General{Cols: 1}}, + } { + var rows, cols int + m := NewDense(1, 1, nil) + panicked, message := panics(func() { rows, cols = m.Copy(a) }) + if panicked { + t.Errorf("unexpected panic: %v", message) + } + if rows != 0 { + t.Errorf("unexpected rows: got: %d want: 0", rows) + } + if cols != 0 { + t.Errorf("unexpected cols: got: %d want: 0", cols) + } + } +} + +func TestStack(t *testing.T) { + for i, test := range []struct { + a, b, e [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{0, 1, 0}, {0, 0, 1}, {1, 0, 0}}, + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {0, 1, 0}, {0, 0, 1}, {1, 0, 0}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + + var s Dense + s.Stack(a, b) + + if !Equal(&s, NewDense(flatten(test.e))) { + t.Errorf("unexpected result for Stack test %d: %v stack %v = %v", i, a, b, s) + } + } + + method := func(receiver, a, b Matrix) { + type Stacker interface { + Stack(a, b Matrix) + } + rd := receiver.(Stacker) + rd.Stack(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Stack(a, b) + } + testTwoInput(t, "Stack", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameWidth, 0) +} + +func TestAugment(t *testing.T) { + for i, test := range []struct { + a, b, e [][]float64 + }{ + { + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, + [][]float64{{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}}, + }, + { + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + [][]float64{{1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1}}, + }, + { + [][]float64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + [][]float64{{0, 1, 0}, {0, 0, 1}, {1, 0, 0}}, + [][]float64{{1, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 1}, {0, 0, 1, 1, 0, 0}}, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + + var s Dense + s.Augment(a, b) + + if !Equal(&s, NewDense(flatten(test.e))) { + t.Errorf("unexpected result for Augment test %d: %v augment %v = %v", i, a, b, s) + } + } + + method := func(receiver, a, b Matrix) { + type Augmenter interface { + Augment(a, b Matrix) + } + rd := receiver.(Augmenter) + rd.Augment(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Augment(a, b) + } + testTwoInput(t, "Augment", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSameHeight, 0) +} + +func TestRankOne(t *testing.T) { + for i, test := range []struct { + x []float64 + y []float64 + m [][]float64 + alpha float64 + }{ + { + x: []float64{5}, + y: []float64{10}, + m: [][]float64{{2}}, + alpha: -3, + }, + { + x: []float64{5, 6, 1}, + y: []float64{10}, + m: [][]float64{{2}, {-3}, {5}}, + alpha: -3, + }, + + { + x: []float64{5}, + y: []float64{10, 15, 8}, + m: [][]float64{{2, -3, 5}}, + alpha: -3, + }, + { + x: []float64{1, 5}, + y: []float64{10, 15}, + m: [][]float64{ + {2, -3}, + {4, -1}, + }, + alpha: -3, + }, + { + x: []float64{2, 3, 9}, + y: []float64{8, 9}, + m: [][]float64{ + {2, 3}, + {4, 5}, + {6, 7}, + }, + alpha: -3, + }, + { + x: []float64{2, 3}, + y: []float64{8, 9, 9}, + m: [][]float64{ + {2, 3, 6}, + {4, 5, 7}, + }, + alpha: -3, + }, + } { + want := &Dense{} + xm := NewDense(len(test.x), 1, test.x) + ym := NewDense(1, len(test.y), test.y) + + want.Mul(xm, ym) + want.Scale(test.alpha, want) + want.Add(want, NewDense(flatten(test.m))) + + a := NewDense(flatten(test.m)) + m := &Dense{} + // Check with a new matrix + m.RankOne(a, test.alpha, NewVector(len(test.x), test.x), NewVector(len(test.y), test.y)) + if !Equal(m, want) { + t.Errorf("unexpected result for RankOne test %d iteration 0: got: %+v want: %+v", i, m, want) + } + // Check with the same matrix + a.RankOne(a, test.alpha, NewVector(len(test.x), test.x), NewVector(len(test.y), test.y)) + if !Equal(a, want) { + t.Errorf("unexpected result for Outer test %d iteration 1: got: %+v want: %+v", i, m, want) + } + } +} + +func TestOuter(t *testing.T) { + for i, test := range []struct { + x []float64 + y []float64 + }{ + { + x: []float64{5}, + y: []float64{10}, + }, + { + x: []float64{5, 6, 1}, + y: []float64{10}, + }, + + { + x: []float64{5}, + y: []float64{10, 15, 8}, + }, + { + x: []float64{1, 5}, + y: []float64{10, 15}, + }, + { + x: []float64{2, 3, 9}, + y: []float64{8, 9}, + }, + { + x: []float64{2, 3}, + y: []float64{8, 9, 9}, + }, + } { + for _, f := range []float64{0.5, 1, 3} { + want := &Dense{} + xm := NewDense(len(test.x), 1, test.x) + ym := NewDense(1, len(test.y), test.y) + + want.Mul(xm, ym) + want.Scale(f, want) + + var m Dense + for j := 0; j < 2; j++ { + // Check with a new matrix - and then again. + m.Outer(f, NewVector(len(test.x), test.x), NewVector(len(test.y), test.y)) + if !Equal(&m, want) { + t.Errorf("unexpected result for Outer test %d iteration %d scale %v: got: %+v want: %+v", i, j, f, m, want) + } + } + } + } +} + +func TestInverse(t *testing.T) { + for i, test := range []struct { + a Matrix + want Matrix // nil indicates that a is singular. + tol float64 + }{ + { + a: NewDense(3, 3, []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + }), + want: NewDense(3, 3, []float64{ + 0.147222222222222, -0.144444444444444, 0.063888888888889, + -0.061111111111111, 0.022222222222222, 0.105555555555556, + -0.019444444444444, 0.188888888888889, -0.102777777777778, + }), + tol: 1e-14, + }, + { + a: NewDense(3, 3, []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + }).T(), + want: NewDense(3, 3, []float64{ + 0.147222222222222, -0.144444444444444, 0.063888888888889, + -0.061111111111111, 0.022222222222222, 0.105555555555556, + -0.019444444444444, 0.188888888888889, -0.102777777777778, + }).T(), + tol: 1e-14, + }, + + // This case does not fail, but we do not guarantee that. The success + // is because the receiver and the input are aligned in the call to + // inverse. If there was a misalignment, the result would likely be + // incorrect and no shadowing panic would occur. + { + a: asBasicMatrix(NewDense(3, 3, []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + })), + want: NewDense(3, 3, []float64{ + 0.147222222222222, -0.144444444444444, 0.063888888888889, + -0.061111111111111, 0.022222222222222, 0.105555555555556, + -0.019444444444444, 0.188888888888889, -0.102777777777778, + }), + tol: 1e-14, + }, + + // The following case fails as it does not follow the shadowing rules. + // Specifically, the test extracts the underlying *Dense, and uses + // it as a receiver with the basicMatrix as input. The basicMatrix type + // allows shadowing of the input data without providing the Raw method + // required for detection of shadowing. + // + // We specifically state we do not check this case. + // + // { + // a: asBasicMatrix(NewDense(3, 3, []float64{ + // 8, 1, 6, + // 3, 5, 7, + // 4, 9, 2, + // })).T(), + // want: NewDense(3, 3, []float64{ + // 0.147222222222222, -0.144444444444444, 0.063888888888889, + // -0.061111111111111, 0.022222222222222, 0.105555555555556, + // -0.019444444444444, 0.188888888888889, -0.102777777777778, + // }).T(), + // tol: 1e-14, + // }, + + { + a: NewDense(4, 4, []float64{ + 5, 2, 8, 7, + 4, 5, 8, 2, + 8, 5, 3, 2, + 8, 7, 7, 5, + }), + want: NewDense(4, 4, []float64{ + 0.100548446069470, 0.021937842778793, 0.334552102376599, -0.283363802559415, + -0.226691042047532, -0.067641681901280, -0.281535648994515, 0.457038391224863, + 0.080438756855576, 0.217550274223035, 0.067641681901280, -0.226691042047532, + 0.043875685557587, -0.244972577696527, -0.235831809872029, 0.330895795246801, + }), + tol: 1e-14, + }, + + // Tests with singular matrix. + { + a: NewDense(1, 1, []float64{ + 0, + }), + }, + { + a: NewDense(2, 2, []float64{ + 0, 0, + 0, 0, + }), + }, + { + a: NewDense(2, 2, []float64{ + 0, 0, + 0, 1, + }), + }, + { + a: NewDense(3, 3, []float64{ + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + }), + }, + { + a: NewDense(4, 4, []float64{ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + }), + }, + { + a: NewDense(4, 4, []float64{ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 20, 20, + 0, 0, 20, 20, + }), + }, + { + a: NewDense(4, 4, []float64{ + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + 0, 0, 0, 0, + }), + }, + { + a: NewDense(4, 4, []float64{ + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + }), + }, + { + a: NewDense(5, 5, []float64{ + 0, 1, 0, 0, 0, + 4, 0, 2, 0, 0, + 0, 3, 0, 3, 0, + 0, 0, 2, 0, 4, + 0, 0, 0, 1, 0, + }), + }, + { + a: NewDense(5, 5, []float64{ + 4, -1, -1, -1, -1, + -1, 4, -1, -1, -1, + -1, -1, 4, -1, -1, + -1, -1, -1, 4, -1, + -1, -1, -1, -1, 4, + }), + }, + { + a: NewDense(5, 5, []float64{ + 2, -1, 0, 0, -1, + -1, 2, -1, 0, 0, + 0, -1, 2, -1, 0, + 0, 0, -1, 2, -1, + -1, 0, 0, -1, 2, + }), + }, + { + a: NewDense(5, 5, []float64{ + 1, 2, 3, 5, 8, + 2, 3, 5, 8, 13, + 3, 5, 8, 13, 21, + 5, 8, 13, 21, 34, + 8, 13, 21, 34, 55, + }), + }, + { + a: NewDense(8, 8, []float64{ + 611, 196, -192, 407, -8, -52, -49, 29, + 196, 899, 113, -192, -71, -43, -8, -44, + -192, 113, 899, 196, 61, 49, 8, 52, + 407, -192, 196, 611, 8, 44, 59, -23, + -8, -71, 61, 8, 411, -599, 208, 208, + -52, -43, 49, 44, -599, 411, 208, 208, + -49, -8, 8, 59, 208, 208, 99, -911, + 29, -44, 52, -23, 208, 208, -911, 99, + }), + }, + } { + var got Dense + err := got.Inverse(test.a) + if test.want == nil { + if err == nil { + t.Errorf("Case %d: expected error for singular matrix", i) + } + continue + } + if err != nil { + t.Errorf("Case %d: unexpected error: %v", i, err) + continue + } + if !equalApprox(&got, test.want, test.tol, false) { + t.Errorf("Case %d, inverse mismatch.", i) + } + var m Dense + m.Mul(&got, test.a) + r, _ := test.a.Dims() + d := make([]float64, r*r) + for i := 0; i < r*r; i += r + 1 { + d[i] = 1 + } + eye := NewDense(r, r, d) + if !equalApprox(eye, &m, 1e-14, false) { + t.Errorf("Case %d, A^-1 * A != I", i) + } + + var tmp Dense + tmp.Clone(test.a) + aU, transposed := untranspose(test.a) + if transposed { + switch aU := aU.(type) { + case *Dense: + err = aU.Inverse(test.a) + case *basicMatrix: + err = (*Dense)(aU).Inverse(test.a) + default: + continue + } + m.Mul(aU, &tmp) + } else { + switch a := test.a.(type) { + case *Dense: + err = a.Inverse(test.a) + m.Mul(a, &tmp) + case *basicMatrix: + err = (*Dense)(a).Inverse(test.a) + m.Mul(a, &tmp) + default: + continue + } + } + if err != nil { + t.Errorf("Error computing inverse: %v", err) + } + if !equalApprox(eye, &m, 1e-14, false) { + t.Errorf("Case %d, A^-1 * A != I", i) + fmt.Println(Formatted(&m)) + } + } +} + +var ( + wd *Dense +) + +func BenchmarkMulDense100Half(b *testing.B) { denseMulBench(b, 100, 0.5) } +func BenchmarkMulDense100Tenth(b *testing.B) { denseMulBench(b, 100, 0.1) } +func BenchmarkMulDense1000Half(b *testing.B) { denseMulBench(b, 1000, 0.5) } +func BenchmarkMulDense1000Tenth(b *testing.B) { denseMulBench(b, 1000, 0.1) } +func BenchmarkMulDense1000Hundredth(b *testing.B) { denseMulBench(b, 1000, 0.01) } +func BenchmarkMulDense1000Thousandth(b *testing.B) { denseMulBench(b, 1000, 0.001) } +func denseMulBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + d, _ := randDense(size, rho, rand.NormFloat64) + b.StartTimer() + for i := 0; i < b.N; i++ { + var n Dense + n.Mul(a, d) + wd = &n + } +} + +func BenchmarkPreMulDense100Half(b *testing.B) { densePreMulBench(b, 100, 0.5) } +func BenchmarkPreMulDense100Tenth(b *testing.B) { densePreMulBench(b, 100, 0.1) } +func BenchmarkPreMulDense1000Half(b *testing.B) { densePreMulBench(b, 1000, 0.5) } +func BenchmarkPreMulDense1000Tenth(b *testing.B) { densePreMulBench(b, 1000, 0.1) } +func BenchmarkPreMulDense1000Hundredth(b *testing.B) { densePreMulBench(b, 1000, 0.01) } +func BenchmarkPreMulDense1000Thousandth(b *testing.B) { densePreMulBench(b, 1000, 0.001) } +func densePreMulBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + d, _ := randDense(size, rho, rand.NormFloat64) + wd = NewDense(size, size, nil) + b.StartTimer() + for i := 0; i < b.N; i++ { + wd.Mul(a, d) + } +} + +func BenchmarkRow10(b *testing.B) { rowBench(b, 10) } +func BenchmarkRow100(b *testing.B) { rowBench(b, 100) } +func BenchmarkRow1000(b *testing.B) { rowBench(b, 1000) } + +func rowBench(b *testing.B, size int) { + a, _ := randDense(size, 1, rand.NormFloat64) + _, c := a.Dims() + dst := make([]float64, c) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + Row(dst, 0, a) + } +} + +func BenchmarkExp10(b *testing.B) { expBench(b, 10) } +func BenchmarkExp100(b *testing.B) { expBench(b, 100) } +func BenchmarkExp1000(b *testing.B) { expBench(b, 1000) } + +func expBench(b *testing.B, size int) { + a, _ := randDense(size, 1, rand.NormFloat64) + + b.ResetTimer() + var m Dense + for i := 0; i < b.N; i++ { + m.Exp(a) + } +} + +func BenchmarkPow10_3(b *testing.B) { powBench(b, 10, 3) } +func BenchmarkPow100_3(b *testing.B) { powBench(b, 100, 3) } +func BenchmarkPow1000_3(b *testing.B) { powBench(b, 1000, 3) } +func BenchmarkPow10_4(b *testing.B) { powBench(b, 10, 4) } +func BenchmarkPow100_4(b *testing.B) { powBench(b, 100, 4) } +func BenchmarkPow1000_4(b *testing.B) { powBench(b, 1000, 4) } +func BenchmarkPow10_5(b *testing.B) { powBench(b, 10, 5) } +func BenchmarkPow100_5(b *testing.B) { powBench(b, 100, 5) } +func BenchmarkPow1000_5(b *testing.B) { powBench(b, 1000, 5) } +func BenchmarkPow10_6(b *testing.B) { powBench(b, 10, 6) } +func BenchmarkPow100_6(b *testing.B) { powBench(b, 100, 6) } +func BenchmarkPow1000_6(b *testing.B) { powBench(b, 1000, 6) } +func BenchmarkPow10_7(b *testing.B) { powBench(b, 10, 7) } +func BenchmarkPow100_7(b *testing.B) { powBench(b, 100, 7) } +func BenchmarkPow1000_7(b *testing.B) { powBench(b, 1000, 7) } +func BenchmarkPow10_8(b *testing.B) { powBench(b, 10, 8) } +func BenchmarkPow100_8(b *testing.B) { powBench(b, 100, 8) } +func BenchmarkPow1000_8(b *testing.B) { powBench(b, 1000, 8) } +func BenchmarkPow10_9(b *testing.B) { powBench(b, 10, 9) } +func BenchmarkPow100_9(b *testing.B) { powBench(b, 100, 9) } +func BenchmarkPow1000_9(b *testing.B) { powBench(b, 1000, 9) } + +func powBench(b *testing.B, size, n int) { + a, _ := randDense(size, 1, rand.NormFloat64) + + b.ResetTimer() + var m Dense + for i := 0; i < b.N; i++ { + m.Pow(a, n) + } +} + +func BenchmarkMulTransDense100Half(b *testing.B) { denseMulTransBench(b, 100, 0.5) } +func BenchmarkMulTransDense100Tenth(b *testing.B) { denseMulTransBench(b, 100, 0.1) } +func BenchmarkMulTransDense1000Half(b *testing.B) { denseMulTransBench(b, 1000, 0.5) } +func BenchmarkMulTransDense1000Tenth(b *testing.B) { denseMulTransBench(b, 1000, 0.1) } +func BenchmarkMulTransDense1000Hundredth(b *testing.B) { denseMulTransBench(b, 1000, 0.01) } +func BenchmarkMulTransDense1000Thousandth(b *testing.B) { denseMulTransBench(b, 1000, 0.001) } +func denseMulTransBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + d, _ := randDense(size, rho, rand.NormFloat64) + b.StartTimer() + for i := 0; i < b.N; i++ { + var n Dense + n.Mul(a, d.T()) + wd = &n + } +} + +func BenchmarkMulTransDenseSym100Half(b *testing.B) { denseMulTransSymBench(b, 100, 0.5) } +func BenchmarkMulTransDenseSym100Tenth(b *testing.B) { denseMulTransSymBench(b, 100, 0.1) } +func BenchmarkMulTransDenseSym1000Half(b *testing.B) { denseMulTransSymBench(b, 1000, 0.5) } +func BenchmarkMulTransDenseSym1000Tenth(b *testing.B) { denseMulTransSymBench(b, 1000, 0.1) } +func BenchmarkMulTransDenseSym1000Hundredth(b *testing.B) { denseMulTransSymBench(b, 1000, 0.01) } +func BenchmarkMulTransDenseSym1000Thousandth(b *testing.B) { denseMulTransSymBench(b, 1000, 0.001) } +func denseMulTransSymBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + b.StartTimer() + for i := 0; i < b.N; i++ { + var n Dense + n.Mul(a, a.T()) + wd = &n + } +} diff --git a/matrix/mat64/doc.go b/matrix/mat64/doc.go new file mode 100644 index 00000000..61335708 --- /dev/null +++ b/matrix/mat64/doc.go @@ -0,0 +1,158 @@ +// Generated by running +// go generate github.com/gonum/matrix +// DO NOT EDIT. + +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package mat64 provides implementations of float64 matrix structures and +// linear algebra operations on them. +// +// Overview +// +// This section provides a quick overview of the mat64 package. The following +// sections provide more in depth commentary. +// +// mat64 provides: +// - Interfaces for Matrix classes (Matrix, Symmetric, Triangular) +// - Concrete implementations (Dense, SymDense, TriDense) +// - Methods and functions for using matrix data (Add, Trace, SymRankOne) +// - Types for constructing and using matrix factorizations (QR, LU) +// +// A matrix may be constructed through the corresponding New function. If no +// backing array is provided the matrix will be initialized to all zeros. +// // Allocate a zeroed matrix of size 3×5 +// zero := mat64.NewDense(3, 5, nil) +// If a backing data slice is provided, the matrix will have those elements. +// Matrices are all stored in row-major format. +// // Generate a 6×6 matrix of random values. +// data := make([]float64, 36) +// for i := range data { +// data[i] = rand.NormFloat64() +// } +// a := mat64.NewDense(6, 6, data) +// +// Operations involving matrix data are implemented as functions when the values +// of the matrix remain unchanged +// tr := mat64.Trace(a) +// and are implemented as methods when the operation modifies the receiver. +// zero.Copy(a) +// +// Receivers must be the correct size for the matrix operations, otherwise the +// operation will panic. As a special case for convenience, a zero-sized matrix +// will be modified to have the correct size, allocating data if necessary. +// var c mat64.Dense // construct a new zero-sized matrix +// c.Mul(a, a) // c is automatically adjusted to be 6×6 +// +// The Matrix Interfaces +// +// The Matrix interface is the common link between the concrete types. The Matrix +// interface is defined by three functions: Dims, which returns the dimensions +// of the Matrix, At, which returns the element in the specified location, and +// T for returning a Transpose (discussed later). All of the concrete types can +// perform these behaviors and so implement the interface. Methods and functions +// are designed to use this interface, so in particular the method +// func (m *Dense) Mul(a, b Matrix) +// constructs a *Dense from the result of a multiplication with any Matrix types, +// not just *Dense. Where more restrictive requirements must be met, there are also the +// Symmetric and Triangular interfaces. For example, in +// func (s *SymDense) AddSym(a, b Symmetric) +// the Symmetric interface guarantees a symmetric result. +// +// Transposes +// +// The T method is used for transposition. For example, c.Mul(a.T(), b) computes +// c = a^T * b. The mat64 types implement this method using an implicit transpose — +// see the Transpose type for more details. Note that some operations have a +// transpose as part of their definition, as in *SymDense.SymOuterK. +// +// Matrix Factorization +// +// Matrix factorizations, such as the LU decomposition, typically have their own +// specific data storage, and so are each implemented as a specific type. The +// factorization can be computed through a call to Factorize +// var lu mat64.LU +// lu.Factorize(a) +// The elements of the factorization can be extracted through methods on the +// appropriate type, i.e. *TriDense.LFromLU and *TriDense.UFromLU. Alternatively, +// they can be used directly, as in *Dense.SolveLU. Some factorizations can be +// updated directly, without needing to update the original matrix and refactorize, +// as in *LU.RankOne. +// +// BLAS and LAPACK +// +// BLAS and LAPACK are the standard APIs for linear algebra routines. Many +// operations in mat64 are implemented using calls to the wrapper functions +// in gonum/blas/blas64 and gonum/lapack/lapack64. By default, blas64 and +// lapack64 call the native Go implementations of the routines. Alternatively, +// it is possible to use C-based implementations of the APIs through the respective +// cgo packages and "Use" functions. The Go implementation of LAPACK makes calls +// through blas64, so if a cgo BLAS implementation is registered, the lapack64 +// calls will be partially executed in Go and partially executed in C. +// +// Type Switching +// +// The Matrix abstraction enables efficiency as well as interoperability. Go's +// type reflection capabilities are used to choose the most efficient routine +// given the specific concrete types. For example, in +// c.Mul(a, b) +// if a and b both implement RawMatrixer, that is, they can be represented as a +// blas64.General, blas64.Gemm (general matrix multiplication) is called, while +// instead if b is a RawSymmetricer blas64.Symm is used (general-symmetric +// multiplication), and if b is a *Vector blas64.Gemv is used. +// +// There are many possible type combinations and special cases. No specific guarantees +// are made about the performance of any method, and in particular, note that an +// abstract matrix type may be copied into a concrete type of the corresponding +// value. If there are specific special cases that are needed, please submit a +// pull-request or file an issue. +// +// Invariants +// +// Matrix input arguments to functions are never directly modified. If an operation +// changes Matrix data, the mutated matrix will be the receiver of a function. +// +// For convenience, a matrix may be used as both a receiver and as an input, e.g. +// a.Pow(a, 6) +// v.SolveVec(a.T(), v) +// though in many cases this will cause an allocation (see Element Aliasing). +// An exception to this rule is Copy, which does not allow a.Copy(a.T()). +// +// Element Aliasing +// +// Most methods in mat64 modify receiver data. It is forbidden for the modified +// data region of the receiver to overlap the used data area of the input +// arguments. The exception to this rule is when the method receiver is equal to one +// of the input arguments, as in the a.Pow(a, 6) call above, or its implicit transpose. +// +// This prohibition is to help avoid subtle mistakes when the method needs to read +// from and write to the same data region. There are ways to make mistakes using the +// mat64 API, and mat64 functions will detect and complain about those. +// There are many ways to make mistakes by excursion from the mat64 API via +// interaction with raw matrix values. +// +// If you need to read the rest of this section to understand the behavior of +// your program, you are being clever. Don't be clever. If you must be clever, +// blas64 and lapack64 may be used to call the behavior directly. +// +// mat64 will use the following rules to detect overlap between the receiver and one +// of the inputs: +// - the input implements one of the Raw methods, and +// - the Raw type matches that of the receiver or +// one is a RawMatrixer and the other is a RawVectorer, and +// - the address ranges of the backing data slices overlap, and +// - the strides differ or there is an overlap in the used data elements. +// If such an overlap is detected, the method will panic. +// +// The following cases will not panic: +// - the data slices do not overlap, +// - there is pointer identity between the receiver and input values after +// the value has been untransposed if necessary. +// +// mat64 will not attempt to detect element overlap if the input does not implement a +// Raw method, or if the Raw method differs from that of the receiver except when a +// conversion has occurred through a mat64 API function. Method behavior is undefined +// if there is undetected overlap. +// +package mat64 diff --git a/matrix/mat64/eigen.go b/matrix/mat64/eigen.go new file mode 100644 index 00000000..d256f570 --- /dev/null +++ b/matrix/mat64/eigen.go @@ -0,0 +1,270 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on the EigenvalueDecomposition class from Jama 1.0.3. + +package mat64 + +import ( + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +const ( + badFact = "mat64: use without successful factorization" + badNoVect = "mat64: eigenvectors not computed" +) + +func symmetric(m *Dense) bool { + n, _ := m.Dims() + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + if m.at(i, j) != m.at(j, i) { + return false + } + } + } + return true +} + +// EigenSym is a type for creating and manipulating the Eigen decomposition of +// symmetric matrices. +type EigenSym struct { + vectorsComputed bool + + values []float64 + vectors *Dense +} + +// Factorize computes the eigenvalue decomposition of the symmetric matrix a. +// The Eigen decomposition is defined as +// A = P * D * P^-1 +// where D is a diagonal matrix containing the eigenvalues of the matrix, and +// P is a matrix of the eigenvectors of A. If the vectors input argument is +// false, the eigenvectors are not computed. +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, methods that require a successful factorization will panic. +func (e *EigenSym) Factorize(a Symmetric, vectors bool) (ok bool) { + n := a.Symmetric() + sd := NewSymDense(n, nil) + sd.CopySym(a) + + jobz := lapack.EVJob(lapack.None) + if vectors { + jobz = lapack.ComputeEV + } + w := make([]float64, n) + work := make([]float64, 1) + lapack64.Syev(jobz, sd.mat, w, work, -1) + + work = make([]float64, int(work[0])) + ok = lapack64.Syev(jobz, sd.mat, w, work, len(work)) + if !ok { + e.vectorsComputed = false + e.values = nil + e.vectors = nil + return false + } + e.vectorsComputed = vectors + e.values = w + e.vectors = NewDense(n, n, sd.mat.Data) + return true +} + +// succFact returns whether the receiver contains a successful factorization. +func (e *EigenSym) succFact() bool { + return len(e.values) != 0 +} + +// Values extracts the eigenvalues of the factorized matrix. If dst is +// non-nil, the values are stored in-place into dst. In this case +// dst must have length n, otherwise Values will panic. If dst is +// nil, then a new slice will be allocated of the proper length and filled +// with the eigenvalues. +// +// Values panics if the Eigen decomposition was not successful. +func (e *EigenSym) Values(dst []float64) []float64 { + if !e.succFact() { + panic(badFact) + } + if dst == nil { + dst = make([]float64, len(e.values)) + } + if len(dst) != len(e.values) { + panic(matrix.ErrSliceLengthMismatch) + } + copy(dst, e.values) + return dst +} + +// EigenvectorsSym extracts the eigenvectors of the factorized matrix and stores +// them in the receiver. Each eigenvector is a column corresponding to the +// respective eigenvalue returned by e.Values. +// +// EigenvectorsSym panics if the factorization was not successful or if the +// decomposition did not compute the eigenvectors. +func (m *Dense) EigenvectorsSym(e *EigenSym) { + if !e.succFact() { + panic(badFact) + } + if !e.vectorsComputed { + panic(badNoVect) + } + m.reuseAs(len(e.values), len(e.values)) + m.Copy(e.vectors) +} + +// Eigen is a type for creating and using the eigenvalue decomposition of a dense matrix. +type Eigen struct { + n int // The size of the factorized matrix. + + right bool // have the right eigenvectors been computed + left bool // have the left eigenvectors been computed + + values []complex128 + rVectors *Dense + lVectors *Dense +} + +// succFact returns whether the receiver contains a successful factorization. +func (e *Eigen) succFact() bool { + return len(e.values) != 0 +} + +// Factorize computes the eigenvalues of the square matrix a, and optionally +// the eigenvectors. +// +// A right eigenvalue/eigenvector combination is defined by +// A * x_r = λ * x_r +// where x_r is the column vector called an eigenvector, and λ is the corresponding +// eigenvector. +// +// Similarly, a left eigenvalue/eigenvector combination is defined by +// x_l * A = λ * x_l +// The eigenvalues, but not the eigenvectors, are the same for both decompositions. +// +// Typically eigenvectors refer to right eigenvectors. +// +// In all cases, Eigen computes the eigenvalues of the matrix. If right and left +// are true, then the right and left eigenvectors will be computed, respectively. +// Eigen panics if the input matrix is not square. +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, methods that require a successful factorization will panic. +func (e *Eigen) Factorize(a Matrix, left, right bool) (ok bool) { + // TODO(btracey): Change implementation to store Vectors as a *CMat when + // #308 is resolved. + + // Copy a because it is modified during the Lapack call. + r, c := a.Dims() + if r != c { + panic(matrix.ErrShape) + } + var sd Dense + sd.Clone(a) + + var vl, vr Dense + var jobvl lapack.LeftEVJob = lapack.None + var jobvr lapack.RightEVJob = lapack.None + if left { + vl = *NewDense(r, r, nil) + jobvl = lapack.ComputeLeftEV + } + if right { + vr = *NewDense(c, c, nil) + jobvr = lapack.ComputeRightEV + } + + wr := make([]float64, c) + wi := make([]float64, c) + + work := make([]float64, 1) + lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, -1) + work = make([]float64, int(work[0])) + first := lapack64.Geev(jobvl, jobvr, sd.mat, wr, wi, vl.mat, vr.mat, work, len(work)) + + if first != 0 { + e.values = nil + return false + } + e.n = r + e.right = right + e.left = left + e.lVectors = &vl + e.rVectors = &vr + values := make([]complex128, r) + for i, v := range wr { + values[i] = complex(v, wi[i]) + } + e.values = values + return true +} + +// Values extracts the eigenvalues of the factorized matrix. If dst is +// non-nil, the values are stored in-place into dst. In this case +// dst must have length n, otherwise Values will panic. If dst is +// nil, then a new slice will be allocated of the proper length and +// filed with the eigenvalues. +// +// Values panics if the Eigen decomposition was not successful. +func (e *Eigen) Values(dst []complex128) []complex128 { + if !e.succFact() { + panic(badFact) + } + if dst == nil { + dst = make([]complex128, e.n) + } + if len(dst) != e.n { + panic(matrix.ErrSliceLengthMismatch) + } + copy(dst, e.values) + return dst +} + +// Vectors returns the right eigenvectors of the decomposition. Vectors +// will panic if the right eigenvectors were not computed during the factorization, +// or if the factorization was not successful. +// +// The returned matrix will contain the right eigenvectors of the decomposition +// in the columns of the n×n matrix in the same order as their eigenvalues. +// If the j-th eigenvalue is real, then +// u_j = VL[:,j], +// v_j = VR[:,j], +// and if it is not real, then j and j+1 form a complex conjugate pair and the +// eigenvectors can be recovered as +// u_j = VL[:,j] + i*VL[:,j+1], +// u_{j+1} = VL[:,j] - i*VL[:,j+1], +// v_j = VR[:,j] + i*VR[:,j+1], +// v_{j+1} = VR[:,j] - i*VR[:,j+1], +// where i is the imaginary unit. The computed eigenvectors are normalized to +// have Euclidean norm equal to 1 and largest component real. +// +// BUG: This signature and behavior will change when issue #308 is resolved. +func (e *Eigen) Vectors() *Dense { + if !e.succFact() { + panic(badFact) + } + if !e.right { + panic(badNoVect) + } + return DenseCopyOf(e.rVectors) +} + +// LeftVectors returns the left eigenvectors of the decomposition. LeftVectors +// will panic if the left eigenvectors were not computed during the factorization. +// or if the factorization was not successful. +// +// See the documentation in lapack64.Geev for the format of the vectors. +// +// BUG: This signature and behavior will change when issue #308 is resolved. +func (e *Eigen) LeftVectors() *Dense { + if !e.succFact() { + panic(badFact) + } + if !e.left { + panic(badNoVect) + } + return DenseCopyOf(e.lVectors) +} diff --git a/matrix/mat64/eigen_test.go b/matrix/mat64/eigen_test.go new file mode 100644 index 00000000..83a3acdc --- /dev/null +++ b/matrix/mat64/eigen_test.go @@ -0,0 +1,164 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestEigen(t *testing.T) { + for i, test := range []struct { + a *Dense + + values []complex128 + left *Dense + right *Dense + }{ + { + a: NewDense(3, 3, []float64{ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + }), + values: []complex128{1, 1, 1}, + left: NewDense(3, 3, []float64{ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + }), + right: NewDense(3, 3, []float64{ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + }), + }, + } { + var e1, e2, e3, e4 Eigen + ok := e1.Factorize(test.a, true, true) + if !ok { + panic("bad factorization") + } + e2.Factorize(test.a, false, true) + e3.Factorize(test.a, true, false) + e4.Factorize(test.a, false, false) + + v1 := e1.Values(nil) + if !cmplxEqual(v1, test.values) { + t.Errorf("eigenvector mismatch. Case %v", i) + } + if !Equal(e1.LeftVectors(), test.left) { + t.Errorf("left eigenvector mismatch. Case %v", i) + } + if !Equal(e1.Vectors(), test.right) { + t.Errorf("right eigenvector mismatch. Case %v", i) + } + + // Check that the eigenvectors and values are the same in all combinations. + if !cmplxEqual(v1, e2.Values(nil)) { + t.Errorf("eigenvector mismatch. Case %v", i) + } + if !cmplxEqual(v1, e3.Values(nil)) { + t.Errorf("eigenvector mismatch. Case %v", i) + } + if !cmplxEqual(v1, e4.Values(nil)) { + t.Errorf("eigenvector mismatch. Case %v", i) + } + if !Equal(e1.Vectors(), e2.Vectors()) { + t.Errorf("right eigenvector mismatch. Case %v", i) + } + if !Equal(e1.LeftVectors(), e3.LeftVectors()) { + t.Errorf("right eigenvector mismatch. Case %v", i) + } + + // TODO(btracey): Also add in a test for correctness when #308 is + // resolved and we have a CMat.Mul(). + } +} + +func cmplxEqual(v1, v2 []complex128) bool { + for i, v := range v1 { + if v != v2[i] { + return false + } + } + return true +} + +func TestSymEigen(t *testing.T) { + // Hand coded tests with results from lapack. + for _, test := range []struct { + mat *SymDense + + values []float64 + vectors *Dense + }{ + { + mat: NewSymDense(3, []float64{8, 2, 4, 2, 6, 10, 4, 10, 5}), + values: []float64{-4.707679201365891, 6.294580208480216, 17.413098992885672}, + vectors: NewDense(3, 3, []float64{ + -0.127343483135656, -0.902414161226903, -0.411621572466779, + -0.664177720955769, 0.385801900032553, -0.640331827193739, + 0.736648893495999, 0.191847792659746, -0.648492738712395, + }), + }, + } { + var es EigenSym + ok := es.Factorize(test.mat, true) + if !ok { + t.Errorf("bad factorization") + } + if !floats.EqualApprox(test.values, es.values, 1e-14) { + t.Errorf("Eigenvalue mismatch") + } + if !EqualApprox(test.vectors, es.vectors, 1e-14) { + t.Errorf("Eigenvector mismatch") + } + + var es2 EigenSym + es2.Factorize(test.mat, false) + if !floats.EqualApprox(es2.values, es.values, 1e-14) { + t.Errorf("Eigenvalue mismatch when no vectors computed") + } + } + + // Randomized tests + rnd := rand.New(rand.NewSource(1)) + for _, n := range []int{3, 5, 10, 70} { + for cas := 0; cas < 10; cas++ { + a := make([]float64, n*n) + for i := range a { + a[i] = rnd.NormFloat64() + } + s := NewSymDense(n, a) + var es EigenSym + ok := es.Factorize(s, true) + if !ok { + t.Errorf("Bad test") + } + + // Check that the eigenvectors are orthonormal. + if !isOrthonormal(es.vectors, 1e-8) { + t.Errorf("Eigenvectors not orthonormal") + } + + // Check that the eigenvalues are actually eigenvalues. + for i := 0; i < n; i++ { + v := NewVector(n, Col(nil, i, es.vectors)) + var m Vector + m.MulVec(s, v) + + var scal Vector + scal.ScaleVec(es.values[i], v) + + if !EqualApprox(&m, &scal, 1e-8) { + t.Errorf("Eigenvalue does not match") + } + } + } + } +} diff --git a/matrix/mat64/fao_data_test.go b/matrix/mat64/fao_data_test.go new file mode 100644 index 00000000..1b01387f --- /dev/null +++ b/matrix/mat64/fao_data_test.go @@ -0,0 +1,122 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64_test + +import "gonum.org/v1/gonum/matrix/mat64" + +// FAO is a dataset extracted from Food and Agriculture Organization of the +// United Nations "FAO Statistical Pocketbook: World Food and Agriculture 2015". +// pp49-52. +var FAO = struct { + Africa *mat64.Dense + Asia *mat64.Dense + LatinAmericaCaribbean *mat64.Dense + Oceania *mat64.Dense +}{ + Africa: mat64.NewDense(21, 3, []float64{ + // 1990, 2000, 2014 + 35.3, 38, 30.7, // Employment in agriculture (%) + 9.2, 20.3, 25.2, // Employment in agriculture, female (%) + 3163, 14718, 20667, // Energy consump, power irrigation (mln kWh) + + 2597, 2717, 2903, // Dietary energy supply (kcal/pc/day) + 113, 116, 123, // Average dietary energy supply adequacy (%) + 58, 55, 52, // Dietary en supp, cereals/roots/tubers (%) + 18.6, 15, 10.8, // Prevalence of undernourishment (%) + 8832, 10241, 13915, // GDP per capita (US$, PPP) + -0.4, -0.2, 50.7, // Cereal import dependency ratio (%) + 78.5, 83, 88.7, // Improved water source (% pop) + + // Production indices (2004-06=100) + 73, 90, 121, // Net food + 72, 89, 123, // Net crops + 82, 92, 123, // Cereals + 51, 77, 141, // Vegetable oils + 74, 94, 119, // Roots and tubers + 58, 86, 127, // Fruit and vegetables + 86, 93, 132, // Sugar + 76, 92, 115, // Livestock + 83, 89, 114, // Milk + 74, 91, 118, // Meat + 72, 92, 119, // Fish + }), + + Asia: mat64.NewDense(21, 3, []float64{ + // 1990, 2000, 2014 + 30.9, 24.5, 27.6, // Employment in agriculture (%) + 40.9, 29.4, 31.1, // Employment in agriculture, female (%) + 7614, 38316, 82411, // Energy consump, power irrigation (mln kWh) + + 2320, 2402, 2581, // Dietary energy supply (kcal/pc/day) + 107, 110, 117, // Average dietary energy supply adequacy (%) + 66, 65, 63, // Dietary en supp, cereals/roots/tubers (%) + 27.6, 25.7, 19.8, // Prevalence of undernourishment (%) + 3315, 3421, 4575, // GDP per capita (US$, PPP) + 25.9, 28.1, 42, // Cereal import dependency ratio (%) + 55.5, 61.1, 68.7, // Improved water source (% pop) + + // Production indices (2004-06=100) + 60, 82, 129, // Net food + 59, 82, 127, // Net crops + 66, 79, 131, // Cereals + 58, 79, 128, // Vegetable oils + 50, 80, 133, // Roots and tubers + 58, 82, 124, // Fruit and vegetables + 76, 94, 114, // Sugar + 65, 84, 126, // Livestock + 59, 77, 125, // Milk + 67, 87, 127, // Meat + 65, 90, 119, // Fish + }), + + LatinAmericaCaribbean: mat64.NewDense(14, 3, []float64{ + // 1990, 2000, 2014 + 19.5, 14.2, 15.8, // Employment in agriculture (%) + 13.7, 6.2, 7.6, // Employment in agriculture, female (%) + + 2669, 2787, 3069, // Dietary energy supply (kcal/pc/day) + 117, 120, 129, // Average dietary energy supply adequacy (%) + 42, 41, 40, // Dietary en supp, cereals/roots/tubers (%) + 14.7, 12.1, 5.5, // Prevalence of undernourishment (%) + 9837, 10976, 13915, // GDP per capita (US$, PPP) + 13, 12, 49.7, // Cereal import dependency ratio (%) + 85.1, 89.8, 94, // Improved water source (% pop) + + // Production indices (2004-06=100) + 60, 83, 129, // Net food + 64, 83, 131, // Net crops + 62, 88, 139, // Cereals + 58, 84, 123, // Livestock + 82, 107, 71, // Fish + }), + + Oceania: mat64.NewDense(21, 3, []float64{ + // 1990, 2000, 2014 + 6.2, 17.1, 3.8, // Employment in agriculture (%) + 4.5, 3.9, 4.4, // Employment in agriculture, female (%) + 415, 1028, 8667, // Energy consump, power irrigation (mln kWh) + + 2454, 2436, 2542, // Dietary energy supply (kcal/pc/day) + 113, 112, 114, // Average dietary energy supply adequacy (%) + 49, 50, 48, // Dietary en supp, cereals/roots/tubers (%) + 15.7, 16.1, 14.2, // Prevalence of undernourishment (%) + 2269, 2536, 3110, // GDP per capita (US$, PPP) + 95.2, 95.9, 95.4, // Cereal import dependency ratio (%) + 49.7, 53.2, 55.5, // Improved water source (% pop) + + // Production indices (2004-06=100) + 72, 99, 116, // Net food + 69, 105, 126, // Net crops + 77, 113, 117, // Cereals + 41, 122, 215, // Vegetable oils + 80, 90, 110, // Roots and tubers + 66, 88, 104, // Fruit and vegetables + 70, 104, 71, // Sugar + 79, 97, 107, // Livestock + 56, 92, 113, // Milk + 79, 96, 105, // Meat + 51, 78, 85, // Fish + }), +} diff --git a/matrix/mat64/format.go b/matrix/mat64/format.go new file mode 100644 index 00000000..5d01247d --- /dev/null +++ b/matrix/mat64/format.go @@ -0,0 +1,238 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "fmt" + "strconv" +) + +// Formatted returns a fmt.Formatter for the matrix m using the given options. +func Formatted(m Matrix, options ...FormatOption) fmt.Formatter { + f := formatter{ + matrix: m, + dot: '.', + } + for _, o := range options { + o(&f) + } + return f +} + +type formatter struct { + matrix Matrix + prefix string + margin int + dot byte + squeeze bool +} + +// FormatOption is a functional option for matrix formatting. +type FormatOption func(*formatter) + +// Prefix sets the formatted prefix to the string p. Prefix is a string that is prepended to +// each line of output. +func Prefix(p string) FormatOption { + return func(f *formatter) { f.prefix = p } +} + +// Excerpt sets the maximum number of rows and columns to print at the margins of the matrix +// to m. If m is zero or less all elements are printed. +func Excerpt(m int) FormatOption { + return func(f *formatter) { f.margin = m } +} + +// DotByte sets the dot character to b. The dot character is used to replace zero elements +// if the result is printed with the fmt ' ' verb flag. Without a DotByte option, the default +// dot character is '.'. +func DotByte(b byte) FormatOption { + return func(f *formatter) { f.dot = b } +} + +// Squeeze sets the printing behaviour to minimise column width for each individual column. +func Squeeze() FormatOption { + return func(f *formatter) { f.squeeze = true } +} + +// Format satisfies the fmt.Formatter interface. +func (f formatter) Format(fs fmt.State, c rune) { + if c == 'v' && fs.Flag('#') { + fmt.Fprintf(fs, "%#v", f.matrix) + return + } + format(f.matrix, f.prefix, f.margin, f.dot, f.squeeze, fs, c) +} + +// format prints a pretty representation of m to the fs io.Writer. The format character c +// specifies the numerical representation of of elements; valid values are those for float64 +// specified in the fmt package, with their associated flags. In addition to this, a space +// preceding a verb indicates that zero values should be represented by the dot character. +// The printed range of the matrix can be limited by specifying a positive value for margin; +// If margin is greater than zero, only the first and last margin rows/columns of the matrix +// are output. If squeeze is true, column widths are determined on a per-column basis. +// +// format will not provide Go syntax output. +func format(m Matrix, prefix string, margin int, dot byte, squeeze bool, fs fmt.State, c rune) { + rows, cols := m.Dims() + + var printed int + if margin <= 0 { + printed = rows + if cols > printed { + printed = cols + } + } else { + printed = margin + } + + prec, pOk := fs.Precision() + if !pOk { + prec = -1 + } + + var ( + maxWidth int + widths widther + buf, pad []byte + ) + if squeeze { + widths = make(columnWidth, cols) + } else { + widths = new(uniformWidth) + } + switch c { + case 'v', 'e', 'E', 'f', 'F', 'g', 'G': + if c == 'v' { + buf, maxWidth = maxCellWidth(m, 'g', printed, prec, widths) + } else { + buf, maxWidth = maxCellWidth(m, c, printed, prec, widths) + } + default: + fmt.Fprintf(fs, "%%!%c(%T=Dims(%d, %d))", c, m, rows, cols) + return + } + width, _ := fs.Width() + width = max(width, maxWidth) + pad = make([]byte, max(width, 2)) + for i := range pad { + pad[i] = ' ' + } + + first := true + if rows > 2*printed || cols > 2*printed { + first = false + fmt.Fprintf(fs, "Dims(%d, %d)\n", rows, cols) + } + + skipZero := fs.Flag(' ') + for i := 0; i < rows; i++ { + if !first { + fmt.Fprint(fs, prefix) + } + first = false + var el string + switch { + case rows == 1: + fmt.Fprint(fs, "[") + el = "]" + case i == 0: + fmt.Fprint(fs, "⎡") + el = "⎤\n" + case i < rows-1: + fmt.Fprint(fs, "⎢") + el = "⎥\n" + default: + fmt.Fprint(fs, "⎣") + el = "⎦" + } + + for j := 0; j < cols; j++ { + if j >= printed && j < cols-printed { + j = cols - printed - 1 + if i == 0 || i == rows-1 { + fmt.Fprint(fs, "... ... ") + } else { + fmt.Fprint(fs, " ") + } + continue + } + + v := m.At(i, j) + if v == 0 && skipZero { + buf = buf[:1] + buf[0] = dot + } else { + if c == 'v' { + buf = strconv.AppendFloat(buf[:0], v, 'g', prec, 64) + } else { + buf = strconv.AppendFloat(buf[:0], v, byte(c), prec, 64) + } + } + if fs.Flag('-') { + fs.Write(buf) + fs.Write(pad[:widths.width(j)-len(buf)]) + } else { + fs.Write(pad[:widths.width(j)-len(buf)]) + fs.Write(buf) + } + + if j < cols-1 { + fs.Write(pad[:2]) + } + } + + fmt.Fprint(fs, el) + + if i >= printed-1 && i < rows-printed && 2*printed < rows { + i = rows - printed - 1 + fmt.Fprintf(fs, "%s .\n%[1]s .\n%[1]s .\n", prefix) + continue + } + } +} + +func maxCellWidth(m Matrix, c rune, printed, prec int, w widther) ([]byte, int) { + var ( + buf = make([]byte, 0, 64) + rows, cols = m.Dims() + max int + ) + for i := 0; i < rows; i++ { + if i >= printed-1 && i < rows-printed && 2*printed < rows { + i = rows - printed - 1 + continue + } + for j := 0; j < cols; j++ { + if j >= printed && j < cols-printed { + continue + } + + buf = strconv.AppendFloat(buf, m.At(i, j), byte(c), prec, 64) + if len(buf) > max { + max = len(buf) + } + if len(buf) > w.width(j) { + w.setWidth(j, len(buf)) + } + buf = buf[:0] + } + } + return buf, max +} + +type widther interface { + width(i int) int + setWidth(i, w int) +} + +type uniformWidth int + +func (u *uniformWidth) width(_ int) int { return int(*u) } +func (u *uniformWidth) setWidth(_, w int) { *u = uniformWidth(w) } + +type columnWidth []int + +func (c columnWidth) width(i int) int { return c[i] } +func (c columnWidth) setWidth(i, w int) { c[i] = w } diff --git a/matrix/mat64/format_example_test.go b/matrix/mat64/format_example_test.go new file mode 100644 index 00000000..dc31cbcd --- /dev/null +++ b/matrix/mat64/format_example_test.go @@ -0,0 +1,112 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64_test + +import ( + "fmt" + + "gonum.org/v1/gonum/matrix/mat64" +) + +func ExampleFormatted() { + a := mat64.NewDense(3, 3, []float64{1, 2, 3, 0, 4, 5, 0, 0, 6}) + + // Create a matrix formatting value with a prefix and calculating each column + // width individually... + fa := mat64.Formatted(a, mat64.Prefix(" "), mat64.Squeeze()) + + // and then print with and without zero value elements. + fmt.Printf("with all values:\na = %v\n\n", fa) + fmt.Printf("with only non-zero values:\na = % v\n\n", fa) + + // Modify the matrix... + a.Set(0, 2, 0) + + // and print it without zero value elements. + fmt.Printf("after modification with only non-zero values:\na = % v\n\n", fa) + + // Modify the matrix again... + a.Set(0, 2, 123.456) + + // and print it using scientific notation for large exponents. + fmt.Printf("after modification with scientific notation:\na = %.2g\n\n", fa) + // See golang.org/pkg/fmt/ floating-point verbs for a comprehensive list. + + // Output: + // with all values: + // a = ⎡1 2 3⎤ + // ⎢0 4 5⎥ + // ⎣0 0 6⎦ + // + // with only non-zero values: + // a = ⎡1 2 3⎤ + // ⎢. 4 5⎥ + // ⎣. . 6⎦ + // + // after modification with only non-zero values: + // a = ⎡1 2 .⎤ + // ⎢. 4 5⎥ + // ⎣. . 6⎦ + // + // after modification with scientific notation: + // a = ⎡1 2 1.2e+02⎤ + // ⎢0 4 5⎥ + // ⎣0 0 6⎦ +} + +func ExampleExcerpt() { + // Excerpt allows diagnostic display of very large + // matrices and vectors. + + // The big matrix is too large to properly print... + big := mat64.NewDense(100, 100, nil) + for i := 0; i < 100; i++ { + big.Set(i, i, 1) + } + + // so only print corner excerpts of the matrix. + fmt.Printf("excerpt big identity matrix: %v\n\n", + mat64.Formatted(big, mat64.Prefix(" "), mat64.Excerpt(3))) + + // The long vector is also too large, ... + long := mat64.NewVector(100, nil) + for i := 0; i < 100; i++ { + long.SetVec(i, float64(i)) + } + + // ... so print end excerpts of the vector, + fmt.Printf("excerpt long column vector: %v\n\n", + mat64.Formatted(long, mat64.Prefix(" "), mat64.Excerpt(3))) + // or its transpose. + fmt.Printf("excerpt long row vector: %v\n", + mat64.Formatted(long.T(), mat64.Prefix(" "), mat64.Excerpt(3))) + + // Output: + // excerpt big identity matrix: Dims(100, 100) + // ⎡1 0 0 ... ... 0 0 0⎤ + // ⎢0 1 0 0 0 0⎥ + // ⎢0 0 1 0 0 0⎥ + // . + // . + // . + // ⎢0 0 0 1 0 0⎥ + // ⎢0 0 0 0 1 0⎥ + // ⎣0 0 0 ... ... 0 0 1⎦ + // + // excerpt long column vector: Dims(100, 1) + // ⎡ 0⎤ + // ⎢ 1⎥ + // ⎢ 2⎥ + // . + // . + // . + // ⎢97⎥ + // ⎢98⎥ + // ⎣99⎦ + // + // excerpt long row vector: Dims(1, 100) + // [ 0 1 2 ... ... 97 98 99] + +} diff --git a/matrix/mat64/format_test.go b/matrix/mat64/format_test.go new file mode 100644 index 00000000..6ddbcf6b --- /dev/null +++ b/matrix/mat64/format_test.go @@ -0,0 +1,150 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "fmt" + "math" + "testing" +) + +func TestFormat(t *testing.T) { + type rp struct { + format string + output string + } + sqrt := func(_, _ int, v float64) float64 { return math.Sqrt(v) } + for i, test := range []struct { + m fmt.Formatter + rep []rp + }{ + // Dense matrix representation + { + Formatted(NewDense(3, 3, []float64{0, 0, 0, 0, 0, 0, 0, 0, 0})), + []rp{ + {"%v", "⎡0 0 0⎤\n⎢0 0 0⎥\n⎣0 0 0⎦"}, + {"% f", "⎡. . .⎤\n⎢. . .⎥\n⎣. . .⎦"}, + {"%#v", "&mat64.Dense{mat:blas64.General{Rows:3, Cols:3, Stride:3, Data:[]float64{0, 0, 0, 0, 0, 0, 0, 0, 0}}, capRows:3, capCols:3}"}, + {"%s", "%!s(*mat64.Dense=Dims(3, 3))"}, + }, + }, + { + Formatted(NewDense(3, 3, []float64{1, 1, 1, 1, 1, 1, 1, 1, 1})), + []rp{ + {"%v", "⎡1 1 1⎤\n⎢1 1 1⎥\n⎣1 1 1⎦"}, + {"% f", "⎡1 1 1⎤\n⎢1 1 1⎥\n⎣1 1 1⎦"}, + {"%#v", "&mat64.Dense{mat:blas64.General{Rows:3, Cols:3, Stride:3, Data:[]float64{1, 1, 1, 1, 1, 1, 1, 1, 1}}, capRows:3, capCols:3}"}, + }, + }, + { + Formatted(NewDense(3, 3, []float64{1, 1, 1, 1, 1, 1, 1, 1, 1}), Prefix("\t")), + []rp{ + {"%v", "⎡1 1 1⎤\n\t⎢1 1 1⎥\n\t⎣1 1 1⎦"}, + {"% f", "⎡1 1 1⎤\n\t⎢1 1 1⎥\n\t⎣1 1 1⎦"}, + {"%#v", "&mat64.Dense{mat:blas64.General{Rows:3, Cols:3, Stride:3, Data:[]float64{1, 1, 1, 1, 1, 1, 1, 1, 1}}, capRows:3, capCols:3}"}, + }, + }, + { + Formatted(NewDense(3, 3, []float64{1, 0, 0, 0, 1, 0, 0, 0, 1})), + []rp{ + {"%v", "⎡1 0 0⎤\n⎢0 1 0⎥\n⎣0 0 1⎦"}, + {"% f", "⎡1 . .⎤\n⎢. 1 .⎥\n⎣. . 1⎦"}, + {"%#v", "&mat64.Dense{mat:blas64.General{Rows:3, Cols:3, Stride:3, Data:[]float64{1, 0, 0, 0, 1, 0, 0, 0, 1}}, capRows:3, capCols:3}"}, + }, + }, + { + Formatted(NewDense(2, 3, []float64{1, 2, 3, 4, 5, 6})), + []rp{ + {"%v", "⎡1 2 3⎤\n⎣4 5 6⎦"}, + {"% f", "⎡1 2 3⎤\n⎣4 5 6⎦"}, + {"%#v", "&mat64.Dense{mat:blas64.General{Rows:2, Cols:3, Stride:3, Data:[]float64{1, 2, 3, 4, 5, 6}}, capRows:2, capCols:3}"}, + }, + }, + { + Formatted(NewDense(3, 2, []float64{1, 2, 3, 4, 5, 6})), + []rp{ + {"%v", "⎡1 2⎤\n⎢3 4⎥\n⎣5 6⎦"}, + {"% f", "⎡1 2⎤\n⎢3 4⎥\n⎣5 6⎦"}, + {"%#v", "&mat64.Dense{mat:blas64.General{Rows:3, Cols:2, Stride:2, Data:[]float64{1, 2, 3, 4, 5, 6}}, capRows:3, capCols:2}"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(2, 3, []float64{0, 1, 2, 3, 4, 5}) + m.Apply(sqrt, m) + return Formatted(m) + }(), + []rp{ + {"%v", "⎡ 0 1 1.4142135623730951⎤\n⎣1.7320508075688772 2 2.23606797749979⎦"}, + {"%.2f", "⎡0.00 1.00 1.41⎤\n⎣1.73 2.00 2.24⎦"}, + {"% f", "⎡ . 1 1.4142135623730951⎤\n⎣1.7320508075688772 2 2.23606797749979⎦"}, + {"%#v", "&mat64.Dense{mat:blas64.General{Rows:2, Cols:3, Stride:3, Data:[]float64{0, 1, 1.4142135623730951, 1.7320508075688772, 2, 2.23606797749979}}, capRows:2, capCols:3}"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(3, 2, []float64{0, 1, 2, 3, 4, 5}) + m.Apply(sqrt, m) + return Formatted(m) + }(), + []rp{ + {"%v", "⎡ 0 1⎤\n⎢1.4142135623730951 1.7320508075688772⎥\n⎣ 2 2.23606797749979⎦"}, + {"%.2f", "⎡0.00 1.00⎤\n⎢1.41 1.73⎥\n⎣2.00 2.24⎦"}, + {"% f", "⎡ . 1⎤\n⎢1.4142135623730951 1.7320508075688772⎥\n⎣ 2 2.23606797749979⎦"}, + {"%#v", "&mat64.Dense{mat:blas64.General{Rows:3, Cols:2, Stride:2, Data:[]float64{0, 1, 1.4142135623730951, 1.7320508075688772, 2, 2.23606797749979}}, capRows:3, capCols:2}"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(2, 3, []float64{0, 1, 2, 3, 4, 5}) + m.Apply(sqrt, m) + return Formatted(m, Squeeze()) + }(), + []rp{ + {"%v", "⎡ 0 1 1.4142135623730951⎤\n⎣1.7320508075688772 2 2.23606797749979⎦"}, + {"%.2f", "⎡0.00 1.00 1.41⎤\n⎣1.73 2.00 2.24⎦"}, + {"% f", "⎡ . 1 1.4142135623730951⎤\n⎣1.7320508075688772 2 2.23606797749979⎦"}, + {"%#v", "&mat64.Dense{mat:blas64.General{Rows:2, Cols:3, Stride:3, Data:[]float64{0, 1, 1.4142135623730951, 1.7320508075688772, 2, 2.23606797749979}}, capRows:2, capCols:3}"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(1, 10, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + return Formatted(m, Excerpt(3)) + }(), + []rp{ + {"%v", "Dims(1, 10)\n[ 1 2 3 ... ... 8 9 10]"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(10, 1, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + return Formatted(m, Excerpt(3)) + }(), + []rp{ + {"%v", "Dims(10, 1)\n⎡ 1⎤\n⎢ 2⎥\n⎢ 3⎥\n .\n .\n .\n⎢ 8⎥\n⎢ 9⎥\n⎣10⎦"}, + }, + }, + { + func() fmt.Formatter { + m := NewDense(10, 10, nil) + for i := 0; i < 10; i++ { + m.Set(i, i, 1) + } + return Formatted(m, Excerpt(3)) + }(), + []rp{ + {"%v", "Dims(10, 10)\n⎡1 0 0 ... ... 0 0 0⎤\n⎢0 1 0 0 0 0⎥\n⎢0 0 1 0 0 0⎥\n .\n .\n .\n⎢0 0 0 1 0 0⎥\n⎢0 0 0 0 1 0⎥\n⎣0 0 0 ... ... 0 0 1⎦"}, + }, + }, + } { + for j, rp := range test.rep { + got := fmt.Sprintf(rp.format, test.m) + if got != rp.output { + t.Errorf("unexpected format result test %d part %d:\ngot:\n%s\nwant:\n%s", i, j, got, rp.output) + } + } + } +} diff --git a/matrix/mat64/gsvd.go b/matrix/mat64/gsvd.go new file mode 100644 index 00000000..7eb98da3 --- /dev/null +++ b/matrix/mat64/gsvd.go @@ -0,0 +1,325 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on the SingularValueDecomposition class from Jama 1.0.3. + +package mat64 + +import ( + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +// GSVD is a type for creating and using the Generalized Singular Value Decomposition +// (GSVD) of a matrix. +// +// The factorization is a linear transformation of the data sets from the given +// variable×sample spaces to reduced and diagonalized "eigenvariable"×"eigensample" +// spaces. +type GSVD struct { + kind matrix.GSVDKind + + r, p, c, k, l int + s1, s2 []float64 + a, b, u, v, q blas64.General + + work []float64 + iwork []int +} + +// Factorize computes the generalized singular value decomposition (GSVD) of the input +// the r×c matrix A and the p×c matrix B. The singular values of A and B are computed +// in all cases, while the singular vectors are optionally computed depending on the +// input kind. +// +// The full singular value decomposition (kind == GSVDU|GSVDV|GSVDQ) deconstructs A and B as +// A = U * Σ₁ * [ 0 R ] * Q^T +// +// B = V * Σ₂ * [ 0 R ] * Q^T +// where Σ₁ and Σ₂ are r×(k+l) and p×(k+l) diagonal matrices of singular values, and +// U, V and Q are r×r, p×p and c×c orthogonal matrices of singular vectors. k+l is the +// effective numerical rank of the matrix [ A^T B^T ]^T. +// +// It is frequently not necessary to compute the full GSVD. Computation time and +// storage costs can be reduced using the appropriate kind. Either only the singular +// values can be computed (kind == SVDNone), or in conjunction with specific singular +// vectors (kind bit set according to matrix.GSVDU, matrix.GSVDV and matrix.GSVDQ). +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, routines that require a successful factorization will panic. +func (gsvd *GSVD) Factorize(a, b Matrix, kind matrix.GSVDKind) (ok bool) { + r, c := a.Dims() + gsvd.r, gsvd.c = r, c + p, c := b.Dims() + gsvd.p = p + if gsvd.c != c { + panic(matrix.ErrShape) + } + var jobU, jobV, jobQ lapack.GSVDJob + switch { + default: + panic("gsvd: bad input kind") + case kind == matrix.GSVDNone: + jobU = lapack.GSVDNone + jobV = lapack.GSVDNone + jobQ = lapack.GSVDNone + case (matrix.GSVDU|matrix.GSVDV|matrix.GSVDQ)&kind != 0: + if matrix.GSVDU&kind != 0 { + jobU = lapack.GSVDU + gsvd.u = blas64.General{ + Rows: r, + Cols: r, + Stride: r, + Data: use(gsvd.u.Data, r*r), + } + } + if matrix.GSVDV&kind != 0 { + jobV = lapack.GSVDV + gsvd.v = blas64.General{ + Rows: p, + Cols: p, + Stride: p, + Data: use(gsvd.v.Data, p*p), + } + } + if matrix.GSVDQ&kind != 0 { + jobQ = lapack.GSVDQ + gsvd.q = blas64.General{ + Rows: c, + Cols: c, + Stride: c, + Data: use(gsvd.q.Data, c*c), + } + } + } + + // A and B are destroyed on call, so copy the matrices. + aCopy := DenseCopyOf(a) + bCopy := DenseCopyOf(b) + + gsvd.s1 = use(gsvd.s1, c) + gsvd.s2 = use(gsvd.s2, c) + + gsvd.iwork = useInt(gsvd.iwork, c) + + gsvd.work = use(gsvd.work, 1) + lapack64.Ggsvd3(jobU, jobV, jobQ, aCopy.mat, bCopy.mat, gsvd.s1, gsvd.s2, gsvd.u, gsvd.v, gsvd.q, gsvd.work, -1, gsvd.iwork) + gsvd.work = use(gsvd.work, int(gsvd.work[0])) + gsvd.k, gsvd.l, ok = lapack64.Ggsvd3(jobU, jobV, jobQ, aCopy.mat, bCopy.mat, gsvd.s1, gsvd.s2, gsvd.u, gsvd.v, gsvd.q, gsvd.work, len(gsvd.work), gsvd.iwork) + if ok { + gsvd.a = aCopy.mat + gsvd.b = bCopy.mat + gsvd.kind = kind + } + return ok +} + +// Kind returns the matrix.GSVDKind of the decomposition. If no decomposition has been +// computed, Kind returns 0. +func (gsvd *GSVD) Kind() matrix.GSVDKind { + return gsvd.kind +} + +// Rank returns the k and l terms of the rank of [ A^T B^T ]^T. +func (gsvd *GSVD) Rank() (k, l int) { + return gsvd.k, gsvd.l +} + +// GeneralizedValues returns the generalized singular values of the factorized matrices. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length min(r,c)-k, and GeneralizedValues will +// panic with matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// GeneralizedValues will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) GeneralizedValues(v []float64) []float64 { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + c := gsvd.c + k := gsvd.k + d := min(r, c) + if v == nil { + v = make([]float64, d-k) + } + if len(v) != d-k { + panic(matrix.ErrSliceLengthMismatch) + } + floats.DivTo(v, gsvd.s1[k:d], gsvd.s2[k:d]) + return v +} + +// ValuesA returns the singular values of the factorized A matrix. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length min(r,c)-k, and ValuesA will panic with +// matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// ValuesA will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) ValuesA(s []float64) []float64 { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + c := gsvd.c + k := gsvd.k + d := min(r, c) + if s == nil { + s = make([]float64, d-k) + } + if len(s) != d-k { + panic(matrix.ErrSliceLengthMismatch) + } + copy(s, gsvd.s1[k:min(r, c)]) + return s +} + +// ValuesB returns the singular values of the factorized B matrix. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length min(r,c)-k, and ValuesB will panic with +// matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// ValuesB will panic if the receiver does not contain a successful factorization. +func (gsvd *GSVD) ValuesB(s []float64) []float64 { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + c := gsvd.c + k := gsvd.k + d := min(r, c) + if s == nil { + s = make([]float64, d-k) + } + if len(s) != d-k { + panic(matrix.ErrSliceLengthMismatch) + } + copy(s, gsvd.s2[k:d]) + return s +} + +// ZeroRFromGSVD extracts the matrix [ 0 R ] from the singular value decomposition, storing +// the result in-place into the receiver. [ 0 R ] is size (k+l)×c. +func (m *Dense) ZeroRFromGSVD(gsvd *GSVD) { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + c := gsvd.c + k := gsvd.k + l := gsvd.l + h := min(k+l, r) + m.reuseAsZeroed(k+l, c) + a := Dense{ + mat: gsvd.a, + capRows: r, + capCols: c, + } + m.Slice(0, h, c-k-l, c).(*Dense). + Copy(a.Slice(0, h, c-k-l, c)) + if r < k+l { + b := Dense{ + mat: gsvd.b, + capRows: gsvd.p, + capCols: c, + } + m.Slice(r, k+l, c+r-k-l, c).(*Dense). + Copy(b.Slice(r-k, l, c+r-k-l, c)) + } +} + +// SigmaAFromGSVD extracts the matrix Σ₁ from the singular value decomposition, storing +// the result in-place into the receiver. Σ₁ is size r×(k+l). +func (m *Dense) SigmaAFromGSVD(gsvd *GSVD) { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + k := gsvd.k + l := gsvd.l + m.reuseAsZeroed(r, k+l) + for i := 0; i < k; i++ { + m.set(i, i, 1) + } + for i := k; i < min(r, k+l); i++ { + m.set(i, i, gsvd.s1[i]) + } +} + +// SigmaBFromGSVD extracts the matrix Σ₂ from the singular value decomposition, storing +// the result in-place into the receiver. Σ₂ is size p×(k+l). +func (m *Dense) SigmaBFromGSVD(gsvd *GSVD) { + if gsvd.kind == 0 { + panic("gsvd: no decomposition computed") + } + r := gsvd.r + p := gsvd.p + k := gsvd.k + l := gsvd.l + m.reuseAsZeroed(p, k+l) + for i := 0; i < min(l, r-k); i++ { + m.set(i, i+k, gsvd.s2[k+i]) + } + for i := r - k; i < l; i++ { + m.set(i, i+k, 1) + } +} + +// UFromGSVD extracts the matrix U from the singular value decomposition, storing +// the result in-place into the receiver. U is size r×r. +func (m *Dense) UFromGSVD(gsvd *GSVD) { + if gsvd.kind&matrix.GSVDU == 0 { + panic("mat64: improper GSVD kind") + } + r := gsvd.u.Rows + c := gsvd.u.Cols + m.reuseAs(r, c) + + tmp := &Dense{ + mat: gsvd.u, + capRows: r, + capCols: c, + } + m.Copy(tmp) +} + +// VFromGSVD extracts the matrix V from the singular value decomposition, storing +// the result in-place into the receiver. V is size p×p. +func (m *Dense) VFromGSVD(gsvd *GSVD) { + if gsvd.kind&matrix.GSVDV == 0 { + panic("mat64: improper GSVD kind") + } + r := gsvd.v.Rows + c := gsvd.v.Cols + m.reuseAs(r, c) + + tmp := &Dense{ + mat: gsvd.v, + capRows: r, + capCols: c, + } + m.Copy(tmp) +} + +// QFromGSVD extracts the matrix Q from the singular value decomposition, storing +// the result in-place into the receiver. Q is size c×c. +func (m *Dense) QFromGSVD(gsvd *GSVD) { + if gsvd.kind&matrix.GSVDQ == 0 { + panic("mat64: improper GSVD kind") + } + r := gsvd.q.Rows + c := gsvd.q.Cols + m.reuseAs(r, c) + + tmp := &Dense{ + mat: gsvd.q, + capRows: r, + capCols: c, + } + m.Copy(tmp) +} diff --git a/matrix/mat64/gsvd_example_test.go b/matrix/mat64/gsvd_example_test.go new file mode 100644 index 00000000..d85a820e --- /dev/null +++ b/matrix/mat64/gsvd_example_test.go @@ -0,0 +1,89 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64_test + +import ( + "fmt" + "log" + "math" + + "gonum.org/v1/gonum/matrix" + "gonum.org/v1/gonum/matrix/mat64" +) + +func ExampleGSVD() { + // Perform a GSVD factorization on food production/consumption data for the + // three years 1990, 2000 and 2014, for Africa and Latin America/Caribbean. + // + // See Lee et al. doi:10.1371/journal.pone.0030098 and + // Alter at al. doi:10.1073/pnas.0530258100 for more details. + var gsvd mat64.GSVD + ok := gsvd.Factorize(FAO.Africa, FAO.LatinAmericaCaribbean, matrix.GSVDU|matrix.GSVDV|matrix.GSVDQ) + if !ok { + log.Fatal("GSVD factorization failed") + } + + var u, v mat64.Dense + u.UFromGSVD(&gsvd) + v.VFromGSVD(&gsvd) + + s1 := gsvd.ValuesA(nil) + s2 := gsvd.ValuesB(nil) + + fmt.Printf("Africa\n\ts1 = %.4f\n\n\tU = %.4f\n\n", + s1, mat64.Formatted(&u, mat64.Prefix("\t "), mat64.Excerpt(2))) + fmt.Printf("Latin America/Caribbean\n\ts2 = %.4f\n\n\tV = %.4f\n", + s2, mat64.Formatted(&v, mat64.Prefix("\t "), mat64.Excerpt(2))) + + var zeroR, q mat64.Dense + zeroR.ZeroRFromGSVD(&gsvd) + q.QFromGSVD(&gsvd) + q.Mul(&zeroR, &q) + fmt.Printf("\nCommon basis vectors\n\n\tQ^T = %.4f\n", + mat64.Formatted(q.T(), mat64.Prefix("\t "))) + + // Calculate the antisymmetric angular distances for each eigenvariable. + fmt.Println("\nSignificance:") + for i := 0; i < 3; i++ { + fmt.Printf("\teigenvar_%d: %+.4f\n", i, math.Atan(s1[i]/s2[i])-math.Pi/4) + } + + // Output: + // + // Africa + // s1 = [1.0000 0.9344 0.5118] + // + // U = Dims(21, 21) + // ⎡-0.0005 0.0142 ... ... -0.0060 -0.0055⎤ + // ⎢-0.0010 0.0019 0.0071 0.0075⎥ + // . + // . + // . + // ⎢-0.0007 -0.0024 0.9999 -0.0001⎥ + // ⎣-0.0010 -0.0016 ... ... -0.0001 0.9999⎦ + // + // Latin America/Caribbean + // s2 = [0.0047 0.3563 0.8591] + // + // V = Dims(14, 14) + // ⎡ 0.1362 0.0008 ... ... 0.0700 0.2636⎤ + // ⎢ 0.1830 -0.0040 0.2908 0.7834⎥ + // . + // . + // . + // ⎢-0.2598 -0.0324 0.9339 -0.2170⎥ + // ⎣-0.8386 0.1494 ... ... -0.1639 0.4121⎦ + // + // Common basis vectors + // + // Q^T = ⎡ -8172.4084 -4524.2933 4813.9616⎤ + // ⎢ 22581.8020 12397.1070 -16364.8933⎥ + // ⎣ -8910.8462 -10902.1488 15762.8719⎦ + // + // Significance: + // eigenvar_0: +0.7807 + // eigenvar_1: +0.4211 + // eigenvar_2: -0.2482 +} diff --git a/matrix/mat64/gsvd_test.go b/matrix/mat64/gsvd_test.go new file mode 100644 index 00000000..bb5532c1 --- /dev/null +++ b/matrix/mat64/gsvd_test.go @@ -0,0 +1,119 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix" +) + +func TestGSVD(t *testing.T) { + const tol = 1e-10 + rnd := rand.New(rand.NewSource(1)) + for _, test := range []struct { + m, p, n int + }{ + {5, 3, 5}, + {5, 3, 3}, + {3, 3, 5}, + {5, 5, 5}, + {5, 5, 3}, + {3, 5, 5}, + {150, 150, 150}, + {200, 150, 150}, + {150, 150, 200}, + {150, 200, 150}, + {200, 200, 150}, + {150, 200, 200}, + } { + m := test.m + p := test.p + n := test.n + for trial := 0; trial < 10; trial++ { + a := NewDense(m, n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rnd.NormFloat64() + } + aCopy := DenseCopyOf(a) + + b := NewDense(p, n, nil) + for i := range b.mat.Data { + b.mat.Data[i] = rnd.NormFloat64() + } + bCopy := DenseCopyOf(b) + + // Test Full decomposition. + var gsvd GSVD + ok := gsvd.Factorize(a, b, matrix.GSVDU|matrix.GSVDV|matrix.GSVDQ) + if !ok { + t.Errorf("GSVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to GSVD.Factorize with GSVDU|GSVDV|GSVDQ") + } + if !Equal(b, bCopy) { + t.Errorf("B changed during call to GSVD.Factorize with GSVDU|GSVDV|GSVDQ") + } + c, s, sigma1, sigma2, zeroR, u, v, q := extractGSVD(&gsvd) + var ansU, ansV, d1R, d2R Dense + ansU.Product(u.T(), a, q) + ansV.Product(v.T(), b, q) + d1R.Mul(sigma1, zeroR) + d2R.Mul(sigma2, zeroR) + if !EqualApprox(&ansU, &d1R, tol) { + t.Errorf("Answer mismatch with GSVDU|GSVDV|GSVDQ\nU^T * A * Q:\n% 0.2f\nΣ₁ * [ 0 R ]:\n% 0.2f", + Formatted(&ansU), Formatted(&d1R)) + } + if !EqualApprox(&ansV, &d2R, tol) { + t.Errorf("Answer mismatch with GSVDU|GSVDV|GSVDQ\nV^T * B *Q:\n% 0.2f\nΣ₂ * [ 0 R ]:\n% 0.2f", + Formatted(&d2R), Formatted(&ansV)) + } + + // Check C^2 + S^2 = I. + for i := range c { + d := c[i]*c[i] + s[i]*s[i] + if !floats.EqualWithinAbsOrRel(d, 1, 1e-14, 1e-14) { + t.Errorf("c_%d^2 + s_%d^2 != 1: got: %v", i, i, d) + } + } + + // Test None decomposition. + ok = gsvd.Factorize(a, b, matrix.GSVDNone) + if !ok { + t.Errorf("GSVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to GSVD with GSVDNone") + } + if !Equal(b, bCopy) { + t.Errorf("B changed during call to GSVD with GSVDNone") + } + cNone := gsvd.ValuesA(nil) + if !floats.EqualApprox(c, cNone, tol) { + t.Errorf("Singular value mismatch between GSVDU|GSVDV|GSVDQ and GSVDNone decomposition") + } + sNone := gsvd.ValuesB(nil) + if !floats.EqualApprox(s, sNone, tol) { + t.Errorf("Singular value mismatch between GSVDU|GSVDV|GSVDQ and GSVDNone decomposition") + } + } + } +} + +func extractGSVD(gsvd *GSVD) (c, s []float64, s1, s2, zR, u, v, q *Dense) { + var s1m, s2m, zeroR, um, vm, qm Dense + s1m.SigmaAFromGSVD(gsvd) + s2m.SigmaBFromGSVD(gsvd) + zeroR.ZeroRFromGSVD(gsvd) + um.UFromGSVD(gsvd) + vm.VFromGSVD(gsvd) + qm.QFromGSVD(gsvd) + c = gsvd.ValuesA(nil) + s = gsvd.ValuesB(nil) + return c, s, &s1m, &s2m, &zeroR, &um, &vm, &qm +} diff --git a/matrix/mat64/hogsvd.go b/matrix/mat64/hogsvd.go new file mode 100644 index 00000000..641d8bdd --- /dev/null +++ b/matrix/mat64/hogsvd.go @@ -0,0 +1,200 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on the SingularValueDecomposition class from Jama 1.0.3. + +package mat64 + +import ( + "errors" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/matrix" +) + +// HOGSVD is a type for creating and using the Higher Order Generalized Singular Value +// Decomposition (HOGSVD) of a set of matrices. +// +// The factorization is a linear transformation of the data sets from the given +// variable×sample spaces to reduced and diagonalized "eigenvariable"×"eigensample" +// spaces. +type HOGSVD struct { + n int + v *Dense + b []Dense + + err error +} + +// Factorize computes the higher order generalized singular value decomposition (HOGSVD) +// of the n input r_i×c column tall matrices in m. HOGSV extends the GSVD case from 2 to n +// input matrices. +// +// M_0 = U_0 * Σ_0 * V^T +// M_1 = U_1 * Σ_1 * V^T +// . +// . +// . +// M_{n-1} = U_{n-1} * Σ_{n-1} * V^T +// +// where U_i are r_i×c matrices of singular vectors, Σ are c×c matrices singular values, and V +// is a c×c matrix of singular vectors. +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, routines that require a successful factorization will panic. +func (gsvd *HOGSVD) Factorize(m ...Matrix) (ok bool) { + // Factorize performs the HOGSVD factorisation + // essentially as described by Ponnapalli et al. + // https://doi.org/10.1371/journal.pone.0028072 + + if len(m) < 2 { + panic("hogsvd: too few matrices") + } + gsvd.n = 0 + + r, c := m[0].Dims() + a := make([]Cholesky, len(m)) + var ts SymDense + for i, d := range m { + rd, cd := d.Dims() + if rd < cd { + gsvd.err = matrix.ErrShape + return false + } + if rd > r { + r = rd + } + if cd != c { + panic(matrix.ErrShape) + } + ts.Reset() + ts.SymOuterK(1, d.T()) + ok = a[i].Factorize(&ts) + if !ok { + gsvd.err = errors.New("hogsvd: cholesky decomposition failed") + return false + } + } + + s := getWorkspace(c, c, true) + defer putWorkspace(s) + sij := getWorkspace(c, c, false) + defer putWorkspace(sij) + for i, ai := range a { + for _, aj := range a[i+1:] { + gsvd.err = sij.solveTwoChol(&ai, &aj) + if gsvd.err != nil { + return false + } + s.Add(s, sij) + + gsvd.err = sij.solveTwoChol(&aj, &ai) + if gsvd.err != nil { + return false + } + s.Add(s, sij) + } + } + s.Scale(1/float64(len(m)*(len(m)-1)), s) + + var eig Eigen + ok = eig.Factorize(s.T(), false, true) + if !ok { + gsvd.err = errors.New("hogsvd: eigen decomposition failed") + return false + } + v := eig.Vectors() + for j := 0; j < c; j++ { + cv := v.ColView(j) + cv.ScaleVec(1/blas64.Nrm2(c, cv.mat), cv) + } + + b := make([]Dense, len(m)) + biT := getWorkspace(c, r, false) + defer putWorkspace(biT) + for i, d := range m { + // All calls to reset will leave a zeroed + // matrix with capacity to store the result + // without additional allocation. + biT.Reset() + gsvd.err = biT.Solve(v, d.T()) + if gsvd.err != nil { + return false + } + b[i].Clone(biT.T()) + } + + gsvd.n = len(m) + gsvd.v = v + gsvd.b = b + return true +} + +// Err returns the reason for a factorization failure. +func (gsvd *HOGSVD) Err() error { + return gsvd.err +} + +// Len returns the number of matrices that have been factorized. If Len returns +// zero, the factorization was not successful. +func (gsvd *HOGSVD) Len() int { + return gsvd.n +} + +// UFromHOGSVD extracts the matrix U_n from the singular value decomposition, storing +// the result in-place into the receiver. U_n is size r×c. +// +// UFromHOGSVD will panic if the receiver does not contain a successful factorization. +func (m *Dense) UFromHOGSVD(gsvd *HOGSVD, n int) { + if gsvd.n == 0 { + panic("hogsvd: unsuccessful factorization") + } + if n < 0 || gsvd.n <= n { + panic("hogsvd: invalid index") + } + + m.reuseAs(gsvd.b[n].Dims()) + m.Copy(&gsvd.b[n]) + for j, f := range gsvd.Values(nil, n) { + v := m.ColView(j) + v.ScaleVec(1/f, v) + } +} + +// Values returns the nth set of singular values of the factorized system. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length c, and Values will panic with +// matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// Values will panic if the receiver does not contain a successful factorization. +func (gsvd *HOGSVD) Values(s []float64, n int) []float64 { + if gsvd.n == 0 { + panic("hogsvd: unsuccessful factorization") + } + if n < 0 || gsvd.n <= n { + panic("hogsvd: invalid index") + } + + r, c := gsvd.b[n].Dims() + if s == nil { + s = make([]float64, c) + } else if len(s) != c { + panic(matrix.ErrSliceLengthMismatch) + } + for j := 0; j < c; j++ { + s[j] = blas64.Nrm2(r, gsvd.b[n].ColView(j).mat) + } + return s +} + +// VFromHOGSVD extracts the matrix V from the singular value decomposition, storing +// the result in-place into the receiver. V is size c×c. +// +// VFromHOGSVD will panic if the receiver does not contain a successful factorization. +func (m *Dense) VFromHOGSVD(gsvd *HOGSVD) { + if gsvd.n == 0 { + panic("hogsvd: unsuccessful factorization") + } + *m = *DenseCopyOf(gsvd.v) +} diff --git a/matrix/mat64/hogsvd_example_test.go b/matrix/mat64/hogsvd_example_test.go new file mode 100644 index 00000000..e785a2ea --- /dev/null +++ b/matrix/mat64/hogsvd_example_test.go @@ -0,0 +1,136 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64_test + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/matrix/mat64" +) + +func ExampleHOGSVD() { + // Perform an HOGSVD factorization on food production/consumption data for the + // three years 1990, 2000 and 2014. + // + // See Ponnapalli et al. doi:10.1371/journal.pone.0028072 and + // Alter at al. doi:10.1073/pnas.0530258100 for more details. + var gsvd mat64.HOGSVD + ok := gsvd.Factorize(FAO.Africa, FAO.Asia, FAO.LatinAmericaCaribbean, FAO.Oceania) + if !ok { + log.Fatal("HOGSVD factorization failed: %v", gsvd.Err()) + } + + for i, n := range []string{"Africa", "Asia", "Latin America/Caribbean", "Oceania"} { + var u mat64.Dense + u.UFromHOGSVD(&gsvd, i) + s := gsvd.Values(nil, i) + fmt.Printf("%s\n\ts_%d = %.4f\n\n\tU_%[2]d = %.4[4]f\n", + n, i, s, mat64.Formatted(&u, mat64.Prefix("\t "))) + } + + var v mat64.Dense + v.VFromHOGSVD(&gsvd) + fmt.Printf("\nCommon basis vectors\n\n\tV^T = %.4f", + mat64.Formatted(v.T(), mat64.Prefix("\t "))) + + // Output: + // + // Africa + // s_0 = [45507.3278 18541.9293 21503.0778] + // + // U_0 = ⎡-0.0005 -0.0039 -0.0019⎤ + // ⎢-0.0010 -0.0007 -0.0012⎥ + // ⎢-1.0000 -0.0507 -0.9964⎥ + // ⎢-0.0022 -0.2906 -0.0415⎥ + // ⎢ 0.0001 -0.0127 -0.0016⎥ + // ⎢ 0.0003 -0.0067 -0.0010⎥ + // ⎢ 0.0003 -0.0022 -0.0003⎥ + // ⎢-0.0086 -0.9550 0.0734⎥ + // ⎢ 0.0017 0.0002 0.0059⎥ + // ⎢-0.0002 -0.0088 -0.0014⎥ + // ⎢-0.0006 -0.0078 -0.0001⎥ + // ⎢-0.0005 -0.0076 0.0003⎥ + // ⎢ 0.0001 -0.0090 0.0008⎥ + // ⎢-0.0005 -0.0050 0.0029⎥ + // ⎢-0.0011 -0.0078 -0.0012⎥ + // ⎢-0.0014 -0.0058 -0.0002⎥ + // ⎢ 0.0007 -0.0095 0.0020⎥ + // ⎢-0.0008 -0.0081 -0.0009⎥ + // ⎢ 0.0004 -0.0092 0.0006⎥ + // ⎢-0.0007 -0.0079 -0.0006⎥ + // ⎣-0.0011 -0.0076 -0.0010⎦ + // Asia + // s_1 = [77228.2804 8413.7024 14711.1879] + // + // U_1 = ⎡ 0.0005 -0.0080 0.0011⎤ + // ⎢ 0.0008 -0.0108 0.0016⎥ + // ⎢-0.9998 0.0612 0.9949⎥ + // ⎢ 0.0007 -0.5734 -0.0468⎥ + // ⎢ 0.0001 -0.0265 -0.0022⎥ + // ⎢ 0.0001 -0.0165 -0.0019⎥ + // ⎢ 0.0000 -0.0070 -0.0013⎥ + // ⎢ 0.0196 -0.8148 0.0893⎥ + // ⎢ 0.0002 -0.0063 0.0012⎥ + // ⎢-0.0001 -0.0135 -0.0013⎥ + // ⎢-0.0004 -0.0135 0.0019⎥ + // ⎢-0.0005 -0.0132 0.0014⎥ + // ⎢ 0.0003 -0.0155 0.0045⎥ + // ⎢-0.0003 -0.0130 0.0025⎥ + // ⎢-0.0007 -0.0105 0.0016⎥ + // ⎢-0.0006 -0.0129 0.0007⎥ + // ⎢-0.0006 -0.0178 -0.0023⎥ + // ⎢-0.0003 -0.0149 0.0016⎥ + // ⎢-0.0001 -0.0134 0.0030⎥ + // ⎢-0.0004 -0.0154 0.0010⎥ + // ⎣-0.0009 -0.0147 -0.0019⎦ + // Latin America/Caribbean + // s_2 = [274.1364 20736.3116 729.6947] + // + // U_2 = ⎡ 0.1060 -0.0021 0.0174⎤ + // ⎢ 0.1415 -0.0016 0.0289⎥ + // ⎢ 0.2350 -0.2669 -0.9212⎥ + // ⎢ 0.0290 -0.0118 -0.0429⎥ + // ⎢ 0.0226 -0.0043 -0.0213⎥ + // ⎢ 0.0117 -0.0016 -0.0197⎥ + // ⎢-0.6263 -0.9635 0.2234⎥ + // ⎢ 0.2334 -0.0013 0.1275⎥ + // ⎢-0.0358 -0.0085 -0.0498⎥ + // ⎢-0.1238 -0.0054 0.0313⎥ + // ⎢-0.0421 -0.0059 0.0528⎥ + // ⎢-0.1471 -0.0056 0.0350⎥ + // ⎢-0.2158 -0.0052 -0.0044⎥ + // ⎣-0.6154 -0.0078 -0.2717⎦ + // Oceania + // s_3 = [8954.1914 6942.6316 17233.0561] + // + // U_3 = ⎡-0.0080 -0.0012 -0.0040⎤ + // ⎢ 0.0004 -0.0014 0.0001⎥ + // ⎢ 0.9973 -0.0315 0.9991⎥ + // ⎢ 0.0473 -0.7426 -0.0359⎥ + // ⎢ 0.0018 -0.0342 -0.0020⎥ + // ⎢-0.0005 -0.0148 -0.0016⎥ + // ⎢-0.0004 -0.0047 -0.0007⎥ + // ⎢-0.0246 -0.6642 -0.0138⎥ + // ⎢ 0.0003 -0.0287 -0.0023⎥ + // ⎢-0.0011 -0.0148 -0.0014⎥ + // ⎢-0.0108 -0.0198 -0.0039⎥ + // ⎢-0.0149 -0.0183 -0.0048⎥ + // ⎢-0.0178 -0.0208 -0.0075⎥ + // ⎢-0.0266 -0.0063 -0.0016⎥ + // ⎢-0.0012 -0.0234 -0.0006⎥ + // ⎢-0.0084 -0.0184 -0.0030⎥ + // ⎢-0.0232 -0.0191 -0.0124⎥ + // ⎢-0.0072 -0.0226 -0.0035⎥ + // ⎢-0.0150 -0.0144 -0.0045⎥ + // ⎢-0.0068 -0.0227 -0.0034⎥ + // ⎣-0.0127 -0.0136 -0.0049⎦ + // + // Common basis vectors + // + // V^T = ⎡-0.0897 -0.4460 -0.8905⎤ + // ⎢-0.4911 -0.5432 -0.6810⎥ + // ⎣ 0.0644 0.2841 0.9566⎦ +} diff --git a/matrix/mat64/hogsvd_test.go b/matrix/mat64/hogsvd_test.go new file mode 100644 index 00000000..5af166e1 --- /dev/null +++ b/matrix/mat64/hogsvd_test.go @@ -0,0 +1,89 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math/rand" + "testing" +) + +func TestHOGSVD(t *testing.T) { + const tol = 1e-10 + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + r, c int + }{ + {5, 3}, + {5, 5}, + {150, 150}, + {200, 150}, + + // Calculating A_i*A_j^T and A_j*A_i^T fails for wide matrices. + {3, 5}, + } { + r := test.r + c := test.c + for n := 3; n < 6; n++ { + data := make([]Matrix, n) + dataCopy := make([]*Dense, n) + for trial := 0; trial < 10; trial++ { + for i := range data { + d := NewDense(r, c, nil) + for j := range d.mat.Data { + d.mat.Data[j] = rnd.Float64() + } + data[i] = d + dataCopy[i] = DenseCopyOf(d) + } + + var gsvd HOGSVD + ok := gsvd.Factorize(data...) + if r >= c { + if !ok { + t.Errorf("HOGSVD factorization failed for %d %d×%d matrices: %v", n, r, c, gsvd.Err()) + continue + } + } else { + if ok { + t.Errorf("HOGSVD factorization unexpectedly succeeded for for %d %d×%d matrices", n, r, c) + } + continue + } + for i := range data { + if !Equal(data[i], dataCopy[i]) { + t.Errorf("A changed during call to HOGSVD.Factorize") + } + } + u, s, v := extractHOGSVD(&gsvd) + for i, want := range data { + var got Dense + sigma := NewDense(c, c, nil) + for j := 0; j < c; j++ { + sigma.Set(j, j, s[i][j]) + } + + got.Product(u[i], sigma, v.T()) + if !EqualApprox(&got, want, tol) { + t.Errorf("test %d n=%d trial %d: unexpected answer\nU_%[4]d * S_%[4]d * V^T:\n% 0.2f\nD_%d:\n% 0.2f", + cas, n, trial, i, Formatted(&got, Excerpt(5)), i, Formatted(want, Excerpt(5))) + } + } + } + } + } +} + +func extractHOGSVD(gsvd *HOGSVD) (u []*Dense, s [][]float64, v *Dense) { + u = make([]*Dense, gsvd.Len()) + s = make([][]float64, gsvd.Len()) + for i := 0; i < gsvd.Len(); i++ { + u[i] = &Dense{} + u[i].UFromHOGSVD(gsvd, i) + s[i] = gsvd.Values(nil, i) + } + v = &Dense{} + v.VFromHOGSVD(gsvd) + return u, s, v +} diff --git a/matrix/mat64/index_bound_checks.go b/matrix/mat64/index_bound_checks.go new file mode 100644 index 00000000..33726c9d --- /dev/null +++ b/matrix/mat64/index_bound_checks.go @@ -0,0 +1,145 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file must be kept in sync with index_no_bound_checks.go. + +//+build bounds + +package mat64 + +import "gonum.org/v1/gonum/matrix" + +// At returns the element at row i, column j. +func (m *Dense) At(i, j int) float64 { + return m.at(i, j) +} + +func (m *Dense) at(i, j int) float64 { + if uint(i) >= uint(m.mat.Rows) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(matrix.ErrColAccess) + } + return m.mat.Data[i*m.mat.Stride+j] +} + +// Set sets the element at row i, column j to the value v. +func (m *Dense) Set(i, j int, v float64) { + m.set(i, j, v) +} + +func (m *Dense) set(i, j int, v float64) { + if uint(i) >= uint(m.mat.Rows) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(matrix.ErrColAccess) + } + m.mat.Data[i*m.mat.Stride+j] = v +} + +// At returns the element at row i. +// It panics if i is out of bounds or if j is not zero. +func (v *Vector) At(i, j int) float64 { + if j != 0 { + panic(matrix.ErrColAccess) + } + return v.at(i) +} + +func (v *Vector) at(i int) float64 { + if uint(i) >= uint(v.n) { + panic(matrix.ErrRowAccess) + } + return v.mat.Data[i*v.mat.Inc] +} + +// SetVec sets the element at row i to the value val. +// It panics if i is out of bounds. +func (v *Vector) SetVec(i int, val float64) { + v.setVec(i, val) +} + +func (v *Vector) setVec(i int, val float64) { + if uint(i) >= uint(v.n) { + panic(matrix.ErrVectorAccess) + } + v.mat.Data[i*v.mat.Inc] = val +} + +// At returns the element at row i and column j. +func (t *SymDense) At(i, j int) float64 { + return t.at(i, j) +} + +func (t *SymDense) at(i, j int) float64 { + if uint(i) >= uint(t.mat.N) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(matrix.ErrColAccess) + } + if i > j { + i, j = j, i + } + return t.mat.Data[i*t.mat.Stride+j] +} + +// SetSym sets the elements at (i,j) and (j,i) to the value v. +func (t *SymDense) SetSym(i, j int, v float64) { + t.set(i, j, v) +} + +func (t *SymDense) set(i, j int, v float64) { + if uint(i) >= uint(t.mat.N) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(matrix.ErrColAccess) + } + if i > j { + i, j = j, i + } + t.mat.Data[i*t.mat.Stride+j] = v +} + +// At returns the element at row i, column j. +func (t *TriDense) At(i, j int) float64 { + return t.at(i, j) +} + +func (t *TriDense) at(i, j int) float64 { + if uint(i) >= uint(t.mat.N) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(matrix.ErrColAccess) + } + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + return 0 + } + return t.mat.Data[i*t.mat.Stride+j] +} + +// SetTri sets the element of the triangular matrix at row i, column j to the value v. +// It panics if the location is outside the appropriate half of the matrix. +func (t *TriDense) SetTri(i, j int, v float64) { + t.set(i, j, v) +} + +func (t *TriDense) set(i, j int, v float64) { + if uint(i) >= uint(t.mat.N) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(matrix.ErrColAccess) + } + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + panic(matrix.ErrTriangleSet) + } + t.mat.Data[i*t.mat.Stride+j] = v +} diff --git a/matrix/mat64/index_no_bound_checks.go b/matrix/mat64/index_no_bound_checks.go new file mode 100644 index 00000000..5e346fbf --- /dev/null +++ b/matrix/mat64/index_no_bound_checks.go @@ -0,0 +1,145 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file must be kept in sync with index_bound_checks.go. + +//+build !bounds + +package mat64 + +import "gonum.org/v1/gonum/matrix" + +// At returns the element at row i, column j. +func (m *Dense) At(i, j int) float64 { + if uint(i) >= uint(m.mat.Rows) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(matrix.ErrColAccess) + } + return m.at(i, j) +} + +func (m *Dense) at(i, j int) float64 { + return m.mat.Data[i*m.mat.Stride+j] +} + +// Set sets the element at row i, column j to the value v. +func (m *Dense) Set(i, j int, v float64) { + if uint(i) >= uint(m.mat.Rows) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(matrix.ErrColAccess) + } + m.set(i, j, v) +} + +func (m *Dense) set(i, j int, v float64) { + m.mat.Data[i*m.mat.Stride+j] = v +} + +// At returns the element at row i. +// It panics if i is out of bounds or if j is not zero. +func (v *Vector) At(i, j int) float64 { + if uint(i) >= uint(v.n) { + panic(matrix.ErrRowAccess) + } + if j != 0 { + panic(matrix.ErrColAccess) + } + return v.at(i) +} + +func (v *Vector) at(i int) float64 { + return v.mat.Data[i*v.mat.Inc] +} + +// SetVec sets the element at row i to the value val. +// It panics if i is out of bounds. +func (v *Vector) SetVec(i int, val float64) { + if uint(i) >= uint(v.n) { + panic(matrix.ErrVectorAccess) + } + v.setVec(i, val) +} + +func (v *Vector) setVec(i int, val float64) { + v.mat.Data[i*v.mat.Inc] = val +} + +// At returns the element at row i and column j. +func (s *SymDense) At(i, j int) float64 { + if uint(i) >= uint(s.mat.N) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(s.mat.N) { + panic(matrix.ErrColAccess) + } + return s.at(i, j) +} + +func (s *SymDense) at(i, j int) float64 { + if i > j { + i, j = j, i + } + return s.mat.Data[i*s.mat.Stride+j] +} + +// SetSym sets the elements at (i,j) and (j,i) to the value v. +func (s *SymDense) SetSym(i, j int, v float64) { + if uint(i) >= uint(s.mat.N) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(s.mat.N) { + panic(matrix.ErrColAccess) + } + s.set(i, j, v) +} + +func (s *SymDense) set(i, j int, v float64) { + if i > j { + i, j = j, i + } + s.mat.Data[i*s.mat.Stride+j] = v +} + +// At returns the element at row i, column j. +func (t *TriDense) At(i, j int) float64 { + if uint(i) >= uint(t.mat.N) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(matrix.ErrColAccess) + } + return t.at(i, j) +} + +func (t *TriDense) at(i, j int) float64 { + isUpper := t.triKind() + if (isUpper && i > j) || (!isUpper && i < j) { + return 0 + } + return t.mat.Data[i*t.mat.Stride+j] +} + +// SetTri sets the element at row i, column j to the value v. +// It panics if the location is outside the appropriate half of the matrix. +func (t *TriDense) SetTri(i, j int, v float64) { + if uint(i) >= uint(t.mat.N) { + panic(matrix.ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(matrix.ErrColAccess) + } + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + panic(matrix.ErrTriangleSet) + } + t.set(i, j, v) +} + +func (t *TriDense) set(i, j int, v float64) { + t.mat.Data[i*t.mat.Stride+j] = v +} diff --git a/matrix/mat64/inner.go b/matrix/mat64/inner.go new file mode 100644 index 00000000..085ce6a5 --- /dev/null +++ b/matrix/mat64/inner.go @@ -0,0 +1,103 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/f64" + "gonum.org/v1/gonum/matrix" +) + +// Inner computes the generalized inner product +// x^T A y +// between vectors x and y with matrix A. This is only a true inner product if +// A is symmetric positive definite, though the operation works for any matrix A. +// +// Inner panics if x.Len != m or y.Len != n when A is an m x n matrix. +func Inner(x *Vector, A Matrix, y *Vector) float64 { + m, n := A.Dims() + if x.Len() != m { + panic(matrix.ErrShape) + } + if y.Len() != n { + panic(matrix.ErrShape) + } + if m == 0 || n == 0 { + return 0 + } + + var sum float64 + + switch b := A.(type) { + case RawSymmetricer: + bmat := b.RawSymmetric() + if bmat.Uplo != blas.Upper { + // Panic as a string not a mat64.Error. + panic(badSymTriangle) + } + for i := 0; i < x.Len(); i++ { + xi := x.at(i) + if xi != 0 { + if y.mat.Inc == 1 { + sum += xi * f64.DotUnitary( + bmat.Data[i*bmat.Stride+i:i*bmat.Stride+n], + y.mat.Data[i:], + ) + } else { + sum += xi * f64.DotInc( + bmat.Data[i*bmat.Stride+i:i*bmat.Stride+n], + y.mat.Data[i*y.mat.Inc:], uintptr(n-i), + 1, uintptr(y.mat.Inc), + 0, 0, + ) + } + } + yi := y.at(i) + if i != n-1 && yi != 0 { + if x.mat.Inc == 1 { + sum += yi * f64.DotUnitary( + bmat.Data[i*bmat.Stride+i+1:i*bmat.Stride+n], + x.mat.Data[i+1:], + ) + } else { + sum += yi * f64.DotInc( + bmat.Data[i*bmat.Stride+i+1:i*bmat.Stride+n], + x.mat.Data[(i+1)*x.mat.Inc:], uintptr(n-i-1), + 1, uintptr(x.mat.Inc), + 0, 0, + ) + } + } + } + case RawMatrixer: + bmat := b.RawMatrix() + for i := 0; i < x.Len(); i++ { + xi := x.at(i) + if xi != 0 { + if y.mat.Inc == 1 { + sum += xi * f64.DotUnitary( + bmat.Data[i*bmat.Stride:i*bmat.Stride+n], + y.mat.Data, + ) + } else { + sum += xi * f64.DotInc( + bmat.Data[i*bmat.Stride:i*bmat.Stride+n], + y.mat.Data, uintptr(n), + 1, uintptr(y.mat.Inc), + 0, 0, + ) + } + } + } + default: + for i := 0; i < x.Len(); i++ { + xi := x.at(i) + for j := 0; j < y.Len(); j++ { + sum += xi * A.At(i, j) * y.at(j) + } + } + } + return sum +} diff --git a/matrix/mat64/inner_test.go b/matrix/mat64/inner_test.go new file mode 100644 index 00000000..19a2ebc9 --- /dev/null +++ b/matrix/mat64/inner_test.go @@ -0,0 +1,181 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/blas/testblas" +) + +func TestInner(t *testing.T) { + for i, test := range []struct { + x []float64 + y []float64 + m [][]float64 + }{ + { + x: []float64{5}, + y: []float64{10}, + m: [][]float64{{2}}, + }, + { + x: []float64{5, 6, 1}, + y: []float64{10}, + m: [][]float64{{2}, {-3}, {5}}, + }, + { + x: []float64{5}, + y: []float64{10, 15}, + m: [][]float64{{2, -3}}, + }, + { + x: []float64{1, 5}, + y: []float64{10, 15}, + m: [][]float64{ + {2, -3}, + {4, -1}, + }, + }, + { + x: []float64{2, 3, 9}, + y: []float64{8, 9}, + m: [][]float64{ + {2, 3}, + {4, 5}, + {6, 7}, + }, + }, + { + x: []float64{2, 3}, + y: []float64{8, 9, 9}, + m: [][]float64{ + {2, 3, 6}, + {4, 5, 7}, + }, + }, + } { + for _, inc := range []struct{ x, y int }{ + {1, 1}, + {1, 2}, + {2, 1}, + {2, 2}, + } { + x := NewDense(1, len(test.x), test.x) + m := NewDense(flatten(test.m)) + mWant := NewDense(flatten(test.m)) + y := NewDense(len(test.y), 1, test.y) + + var tmp, cell Dense + tmp.Mul(mWant, y) + cell.Mul(x, &tmp) + + rm, cm := cell.Dims() + if rm != 1 { + t.Errorf("Test %d result doesn't have 1 row", i) + } + if cm != 1 { + t.Errorf("Test %d result doesn't have 1 column", i) + } + + want := cell.At(0, 0) + got := Inner(makeVectorInc(inc.x, test.x), m, makeVectorInc(inc.y, test.y)) + if got != want { + t.Errorf("Test %v: want %v, got %v", i, want, got) + } + } + } +} + +func TestInnerSym(t *testing.T) { + for _, inc := range []struct{ x, y int }{ + {1, 1}, + {1, 2}, + {2, 1}, + {2, 2}, + } { + n := 10 + xData := make([]float64, n) + yData := make([]float64, n) + data := make([]float64, n*n) + for i := 0; i < n; i++ { + xData[i] = float64(i) + yData[i] = float64(i) + for j := i; j < n; j++ { + data[i*n+j] = float64(i*n + j) + data[j*n+i] = data[i*n+j] + } + } + x := makeVectorInc(inc.x, xData) + y := makeVectorInc(inc.y, yData) + m := NewDense(n, n, data) + ans := Inner(x, m, y) + sym := NewSymDense(n, data) + // Poison the lower half of data to ensure it is not used. + for i := 1; i < n; i++ { + for j := 0; j < i; j++ { + data[i*n+j] = math.NaN() + } + } + + if math.Abs(Inner(x, sym, y)-ans) > 1e-14 { + t.Error("inner different symmetric and dense") + } + } +} + +func makeVectorInc(inc int, f []float64) *Vector { + v := &Vector{ + n: len(f), + mat: blas64.Vector{ + Inc: inc, + Data: make([]float64, (len(f)-1)*inc+1), + }, + } + + // Contaminate backing data in all positions... + const base = 100 + for i := range v.mat.Data { + v.mat.Data[i] = float64(i + base) + } + + // then write real elements. + for i := range f { + v.mat.Data[i*inc] = f[i] + } + return v +} + +func benchmarkInner(b *testing.B, m, n int) { + x := NewVector(m, nil) + randomSlice(x.mat.Data) + y := NewVector(n, nil) + randomSlice(y.mat.Data) + data := make([]float64, m*n) + randomSlice(data) + mat := &Dense{mat: blas64.General{Rows: m, Cols: n, Stride: n, Data: data}, capRows: m, capCols: n} + b.ResetTimer() + for i := 0; i < b.N; i++ { + Inner(x, mat, y) + } +} + +func BenchmarkInnerSmSm(b *testing.B) { + benchmarkInner(b, testblas.SmallMat, testblas.SmallMat) +} + +func BenchmarkInnerMedMed(b *testing.B) { + benchmarkInner(b, testblas.MediumMat, testblas.MediumMat) +} + +func BenchmarkInnerLgLg(b *testing.B) { + benchmarkInner(b, testblas.LargeMat, testblas.LargeMat) +} + +func BenchmarkInnerLgSm(b *testing.B) { + benchmarkInner(b, testblas.LargeMat, testblas.SmallMat) +} diff --git a/matrix/mat64/io.go b/matrix/mat64/io.go new file mode 100644 index 00000000..903cdc7d --- /dev/null +++ b/matrix/mat64/io.go @@ -0,0 +1,360 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "encoding/binary" + "errors" + "io" + "math" +) + +const ( + // maxLen is the biggest slice/array len one can create on a 32/64b platform. + maxLen = int64(int(^uint(0) >> 1)) +) + +var ( + sizeInt64 = binary.Size(int64(0)) + sizeFloat64 = binary.Size(float64(0)) + + errTooBig = errors.New("mat64: resulting data slice too big") + errTooSmall = errors.New("mat64: input slice too small") + errBadBuffer = errors.New("mat64: data buffer size mismatch") + errBadSize = errors.New("mat64: invalid dimension") +) + +// MarshalBinary encodes the receiver into a binary form and returns the result. +// +// Dense is little-endian encoded as follows: +// 0 - 7 number of rows (int64) +// 8 - 15 number of columns (int64) +// 16 - .. matrix data elements (float64) +// [0,0] [0,1] ... [0,ncols-1] +// [1,0] [1,1] ... [1,ncols-1] +// ... +// [nrows-1,0] ... [nrows-1,ncols-1] +func (m Dense) MarshalBinary() ([]byte, error) { + bufLen := int64(m.mat.Rows)*int64(m.mat.Cols)*int64(sizeFloat64) + 2*int64(sizeInt64) + if bufLen <= 0 { + // bufLen is too big and has wrapped around. + return nil, errTooBig + } + + p := 0 + buf := make([]byte, bufLen) + binary.LittleEndian.PutUint64(buf[p:p+sizeInt64], uint64(m.mat.Rows)) + p += sizeInt64 + binary.LittleEndian.PutUint64(buf[p:p+sizeInt64], uint64(m.mat.Cols)) + p += sizeInt64 + + r, c := m.Dims() + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + binary.LittleEndian.PutUint64(buf[p:p+sizeFloat64], math.Float64bits(m.at(i, j))) + p += sizeFloat64 + } + } + + return buf, nil +} + +// MarshalBinaryTo encodes the receiver into a binary form and writes it into w. +// MarshalBinaryTo returns the number of bytes written into w and an error, if any. +// +// See MarshalBinary for the on-disk layout. +func (m Dense) MarshalBinaryTo(w io.Writer) (int, error) { + var n int + var buf [8]byte + binary.LittleEndian.PutUint64(buf[:], uint64(m.mat.Rows)) + nn, err := w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + binary.LittleEndian.PutUint64(buf[:], uint64(m.mat.Cols)) + nn, err = w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + + r, c := m.Dims() + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + binary.LittleEndian.PutUint64(buf[:], math.Float64bits(m.at(i, j))) + nn, err = w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + } + } + + return n, nil +} + +// UnmarshalBinary decodes the binary form into the receiver. +// It panics if the receiver is a non-zero Dense matrix. +// +// See MarshalBinary for the on-disk layout. +// +// Limited checks on the validity of the binary input are performed: +// - matrix.ErrShape is returned if the number of rows or columns is negative, +// - an error is returned if the resulting Dense matrix is too +// big for the current architecture (e.g. a 16GB matrix written by a +// 64b application and read back from a 32b application.) +// UnmarshalBinary does not limit the size of the unmarshaled matrix, and so +// it should not be used on untrusted data. +func (m *Dense) UnmarshalBinary(data []byte) error { + if !m.isZero() { + panic("mat64: unmarshal into non-zero matrix") + } + + if len(data) < 2*sizeInt64 { + return errTooSmall + } + + p := 0 + rows := int64(binary.LittleEndian.Uint64(data[p : p+sizeInt64])) + p += sizeInt64 + cols := int64(binary.LittleEndian.Uint64(data[p : p+sizeInt64])) + p += sizeInt64 + if rows < 0 || cols < 0 { + return errBadSize + } + + size := rows * cols + if int(size) < 0 || size > maxLen { + return errTooBig + } + + if len(data) != int(size)*sizeFloat64+2*sizeInt64 { + return errBadBuffer + } + + m.reuseAs(int(rows), int(cols)) + for i := range m.mat.Data { + m.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(data[p : p+sizeFloat64])) + p += sizeFloat64 + } + + return nil +} + +// UnmarshalBinaryFrom decodes the binary form into the receiver and returns +// the number of bytes read and an error if any. +// It panics if the receiver is a non-zero Dense matrix. +// +// See MarshalBinary for the on-disk layout. +// +// Limited checks on the validity of the binary input are performed: +// - matrix.ErrShape is returned if the number of rows or columns is negative, +// - an error is returned if the resulting Dense matrix is too +// big for the current architecture (e.g. a 16GB matrix written by a +// 64b application and read back from a 32b application.) +// UnmarshalBinary does not limit the size of the unmarshaled matrix, and so +// it should not be used on untrusted data. +func (m *Dense) UnmarshalBinaryFrom(r io.Reader) (int, error) { + if !m.isZero() { + panic("mat64: unmarshal into non-zero matrix") + } + + var ( + n int + buf [8]byte + ) + nn, err := readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + rows := int64(binary.LittleEndian.Uint64(buf[:])) + + nn, err = readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + cols := int64(binary.LittleEndian.Uint64(buf[:])) + if rows < 0 || cols < 0 { + return n, errBadSize + } + + size := rows * cols + if int(size) < 0 || size > maxLen { + return n, errTooBig + } + + m.reuseAs(int(rows), int(cols)) + for i := range m.mat.Data { + nn, err = readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + m.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(buf[:])) + } + + return n, nil +} + +// MarshalBinary encodes the receiver into a binary form and returns the result. +// +// Vector is little-endian encoded as follows: +// 0 - 7 number of elements (int64) +// 8 - .. vector's data elements (float64) +func (v Vector) MarshalBinary() ([]byte, error) { + bufLen := int64(sizeInt64) + int64(v.n)*int64(sizeFloat64) + if bufLen <= 0 { + // bufLen is too big and has wrapped around. + return nil, errTooBig + } + + p := 0 + buf := make([]byte, bufLen) + binary.LittleEndian.PutUint64(buf[p:p+sizeInt64], uint64(v.n)) + p += sizeInt64 + + for i := 0; i < v.n; i++ { + binary.LittleEndian.PutUint64(buf[p:p+sizeFloat64], math.Float64bits(v.at(i))) + p += sizeFloat64 + } + + return buf, nil +} + +// MarshalBinaryTo encodes the receiver into a binary form, writes it to w and +// returns the number of bytes written and an error if any. +// +// See MarshalBainry for the on-disk format. +func (v Vector) MarshalBinaryTo(w io.Writer) (int, error) { + var ( + n int + buf [8]byte + ) + + binary.LittleEndian.PutUint64(buf[:], uint64(v.n)) + nn, err := w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + + for i := 0; i < v.n; i++ { + binary.LittleEndian.PutUint64(buf[:], math.Float64bits(v.at(i))) + nn, err = w.Write(buf[:]) + n += nn + if err != nil { + return n, err + } + } + + return n, nil +} + +// UnmarshalBinary decodes the binary form into the receiver. +// It panics if the receiver is a non-zero Vector. +// +// See MarshalBinary for the on-disk layout. +// +// Limited checks on the validity of the binary input are performed: +// - matrix.ErrShape is returned if the number of rows is negative, +// - an error is returned if the resulting Vector is too +// big for the current architecture (e.g. a 16GB vector written by a +// 64b application and read back from a 32b application.) +// UnmarshalBinary does not limit the size of the unmarshaled vector, and so +// it should not be used on untrusted data. +func (v *Vector) UnmarshalBinary(data []byte) error { + if !v.isZero() { + panic("mat64: unmarshal into non-zero vector") + } + + p := 0 + n := int64(binary.LittleEndian.Uint64(data[p : p+sizeInt64])) + p += sizeInt64 + if n < 0 { + return errBadSize + } + if n > maxLen { + return errTooBig + } + if len(data) != int(n)*sizeFloat64+sizeInt64 { + return errBadBuffer + } + + v.reuseAs(int(n)) + for i := range v.mat.Data { + v.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(data[p : p+sizeFloat64])) + p += sizeFloat64 + } + + return nil +} + +// UnmarshalBinaryFrom decodes the binary form into the receiver, from the +// io.Reader and returns the number of bytes read and an error if any. +// It panics if the receiver is a non-zero Vector. +// +// See MarshalBinary for the on-disk layout. +// See UnmarshalBinary for the list of sanity checks performed on the input. +func (v *Vector) UnmarshalBinaryFrom(r io.Reader) (int, error) { + if !v.isZero() { + panic("mat64: unmarshal into non-zero vector") + } + + var ( + n int + buf [8]byte + ) + nn, err := readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + sz := int64(binary.LittleEndian.Uint64(buf[:])) + if sz < 0 { + return n, errBadSize + } + if sz > maxLen { + return n, errTooBig + } + + v.reuseAs(int(sz)) + for i := range v.mat.Data { + nn, err = readFull(r, buf[:]) + n += nn + if err != nil { + return n, err + } + v.mat.Data[i] = math.Float64frombits(binary.LittleEndian.Uint64(buf[:])) + } + + if n != sizeInt64+int(sz)*sizeFloat64 { + return n, io.ErrUnexpectedEOF + } + + return n, nil +} + +// readFull reads from r into buf until it has read len(buf). +// It returns the number of bytes copied and an error if fewer bytes were read. +// If an EOF happens after reading fewer than len(buf) bytes, io.ErrUnexpectedEOF is returned. +func readFull(r io.Reader, buf []byte) (int, error) { + var n int + var err error + for n < len(buf) && err == nil { + var nn int + nn, err = r.Read(buf[n:]) + n += nn + } + if n == len(buf) { + return n, nil + } + if err == io.EOF { + return n, io.ErrUnexpectedEOF + } + return n, err +} diff --git a/matrix/mat64/io_test.go b/matrix/mat64/io_test.go new file mode 100644 index 00000000..5893b4c0 --- /dev/null +++ b/matrix/mat64/io_test.go @@ -0,0 +1,731 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "bytes" + "encoding" + "io" + "io/ioutil" + "math" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +var ( + _ encoding.BinaryMarshaler = (*Dense)(nil) + _ encoding.BinaryUnmarshaler = (*Dense)(nil) + _ encoding.BinaryMarshaler = (*Vector)(nil) + _ encoding.BinaryUnmarshaler = (*Vector)(nil) +) + +var denseData = []struct { + raw []byte + want *Dense + eq func(got, want Matrix) bool +}{ + { + raw: []byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), + want: NewDense(0, 0, []float64{}), + eq: Equal, + }, + { + raw: []byte("\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@"), + want: NewDense(2, 2, []float64{1, 2, 3, 4}), + eq: Equal, + }, + { + raw: []byte("\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@"), + want: NewDense(2, 3, []float64{1, 2, 3, 4, 5, 6}), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@"), + want: NewDense(3, 2, []float64{1, 2, 3, 4, 5, 6}), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00\x1c@\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x00\"@"), + want: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}), + eq: Equal, + }, + { + raw: []byte("\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@"), + want: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).Slice(0, 2, 0, 2).(*Dense), + eq: Equal, + }, + { + raw: []byte("\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x00\"@"), + want: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).Slice(1, 3, 1, 3).(*Dense), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x00\"@"), + want: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).Slice(0, 3, 1, 3).(*Dense), + eq: Equal, + }, + { + raw: []byte("\x01\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xff\x00\x00\x00\x00\x00\x00\xf0\u007f\x01\x00\x00\x00\x00\x00\xf8\u007f"), + want: NewDense(1, 4, []float64{0, math.Inf(-1), math.Inf(+1), math.NaN()}), + eq: func(got, want Matrix) bool { + for _, v := range []bool{ + got.At(0, 0) == 0, + math.IsInf(got.At(0, 1), -1), + math.IsInf(got.At(0, 2), +1), + math.IsNaN(got.At(0, 3)), + } { + if !v { + return false + } + } + return true + }, + }, +} + +func TestDenseMarshal(t *testing.T) { + for i, test := range denseData { + buf, err := test.want.MarshalBinary() + if err != nil { + t.Errorf("error encoding test-%d: %v\n", i, err) + continue + } + + nrows, ncols := test.want.Dims() + sz := nrows*ncols*sizeFloat64 + 2*sizeInt64 + if len(buf) != sz { + t.Errorf("encoded size test-%d: want=%d got=%d\n", i, sz, len(buf)) + } + + if !bytes.Equal(buf, test.raw) { + t.Errorf("error encoding test-%d: bytes mismatch.\n got=%q\nwant=%q\n", + i, + string(buf), + string(test.raw), + ) + continue + } + } +} + +func TestDenseMarshalTo(t *testing.T) { + for i, test := range denseData { + buf := new(bytes.Buffer) + n, err := test.want.MarshalBinaryTo(buf) + if err != nil { + t.Errorf("error encoding test-%d: %v\n", i, err) + continue + } + + nrows, ncols := test.want.Dims() + sz := nrows*ncols*sizeFloat64 + 2*sizeInt64 + if n != sz { + t.Errorf("encoded size test-%d: want=%d got=%d\n", i, sz, n) + } + + if !bytes.Equal(buf.Bytes(), test.raw) { + t.Errorf("error encoding test-%d: bytes mismatch.\n got=%q\nwant=%q\n", + i, + string(buf.Bytes()), + string(test.raw), + ) + continue + } + } +} + +func TestDenseUnmarshal(t *testing.T) { + for i, test := range denseData { + var v Dense + err := v.UnmarshalBinary(test.raw) + if err != nil { + t.Errorf("error decoding test-%d: %v\n", i, err) + continue + } + if !test.eq(&v, test.want) { + t.Errorf("error decoding test-%d: values differ.\n got=%v\nwant=%v\n", + i, + &v, + test.want, + ) + } + } +} + +func TestDenseUnmarshalFrom(t *testing.T) { + for i, test := range denseData { + var v Dense + buf := bytes.NewReader(test.raw) + n, err := v.UnmarshalBinaryFrom(buf) + if err != nil { + t.Errorf("error decoding test-%d: %v\n", i, err) + continue + } + if n != len(test.raw) { + t.Errorf("error decoding test-%d: lengths differ.\n got=%d\nwant=%d\n", + i, n, len(test.raw), + ) + } + if !test.eq(&v, test.want) { + t.Errorf("error decoding test-%d: values differ.\n got=%v\nwant=%v\n", + i, + &v, + test.want, + ) + } + } +} + +func TestDenseUnmarshalFromError(t *testing.T) { + test := denseData[1] + for i, tt := range []struct { + beg int + end int + }{ + { + beg: 0, + end: len(test.raw) - 1, + }, + { + beg: 0, + end: len(test.raw) - sizeFloat64, + }, + { + beg: 0, + end: 0, + }, + { + beg: 0, + end: 1, + }, + { + beg: 0, + end: sizeInt64, + }, + { + beg: 0, + end: sizeInt64 - 1, + }, + { + beg: 0, + end: sizeInt64 + 1, + }, + { + beg: 0, + end: 2*sizeInt64 - 1, + }, + { + beg: 0, + end: 2 * sizeInt64, + }, + { + beg: 0, + end: 2*sizeInt64 + 1, + }, + { + beg: 0, + end: 2*sizeInt64 + sizeFloat64 - 1, + }, + { + beg: 0, + end: 2*sizeInt64 + sizeFloat64, + }, + { + beg: 0, + end: 2*sizeInt64 + sizeFloat64 + 1, + }, + } { + buf := bytes.NewReader(test.raw[tt.beg:tt.end]) + var m Dense + _, err := m.UnmarshalBinaryFrom(buf) + if err != io.ErrUnexpectedEOF { + t.Errorf("test #%d: error decoding. got=%v. want=%v\n", i, err, io.ErrUnexpectedEOF) + } + } +} + +func TestDenseIORoundTrip(t *testing.T) { + for i, test := range denseData { + buf, err := test.want.MarshalBinary() + if err != nil { + t.Errorf("error encoding test #%d: %v\n", i, err) + } + + var got Dense + err = got.UnmarshalBinary(buf) + if err != nil { + t.Errorf("error decoding test #%d: %v\n", i, err) + } + + if !test.eq(&got, test.want) { + t.Errorf("r/w test #%d failed\n got=%#v\nwant=%#v\n", i, &got, test.want) + } + + wbuf := new(bytes.Buffer) + _, err = test.want.MarshalBinaryTo(wbuf) + if err != nil { + t.Errorf("error encoding test #%d: %v\n", i, err) + } + + if !bytes.Equal(buf, wbuf.Bytes()) { + t.Errorf("encoding via MarshalBinary and MarshalBinaryTo differ:\nwith-stream: %q\n no-stream: %q\n", + i, wbuf.Bytes(), buf, + ) + } + + var wgot Dense + _, err = wgot.UnmarshalBinaryFrom(wbuf) + if err != nil { + t.Errorf("error decoding test #%d: %v\n", i, err) + } + + if !test.eq(&wgot, test.want) { + t.Errorf("r/w test #%d failed\n got=%#v\nwant=%#v\n", i, &wgot, test.want) + } + } +} + +var vectorData = []struct { + raw []byte + want *Vector + eq func(got, want Matrix) bool +}{ + { + raw: []byte("\x00\x00\x00\x00\x00\x00\x00\x00"), + want: NewVector(0, []float64{}), + eq: Equal, + }, + { + raw: []byte("\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@"), + want: NewVector(4, []float64{1, 2, 3, 4}), + eq: Equal, + }, + { + raw: []byte("\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@"), + want: NewVector(6, []float64{1, 2, 3, 4, 5, 6}), + eq: Equal, + }, + { + raw: []byte("\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00\x1c@\x00\x00\x00\x00\x00\x00 @\x00\x00\x00\x00\x00\x00\"@"), + want: NewVector(9, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@"), + want: NewVector(9, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).SliceVec(0, 3), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@"), + want: NewVector(9, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).SliceVec(1, 4), + eq: Equal, + }, + { + raw: []byte("\b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x10@\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x00\x18@\x00\x00\x00\x00\x00\x00\x1c@\x00\x00\x00\x00\x00\x00 @"), + want: NewVector(9, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}).SliceVec(0, 8), + eq: Equal, + }, + { + raw: []byte("\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b@\x00\x00\x00\x00\x00\x00\x18@"), + want: &Vector{ + mat: blas64.Vector{ + Data: []float64{0, 1, 2, 3, 4, 5, 6}, + Inc: 3, + }, + n: 3, + }, + eq: Equal, + }, + { + raw: []byte("\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xff\x00\x00\x00\x00\x00\x00\xf0\u007f\x01\x00\x00\x00\x00\x00\xf8\u007f"), + want: NewVector(4, []float64{0, math.Inf(-1), math.Inf(+1), math.NaN()}), + eq: func(got, want Matrix) bool { + for _, v := range []bool{ + got.At(0, 0) == 0, + math.IsInf(got.At(1, 0), -1), + math.IsInf(got.At(2, 0), +1), + math.IsNaN(got.At(3, 0)), + } { + if !v { + return false + } + } + return true + }, + }, +} + +func TestVectorMarshal(t *testing.T) { + for i, test := range vectorData { + buf, err := test.want.MarshalBinary() + if err != nil { + t.Errorf("error encoding test-%d: %v\n", i, err) + continue + } + + nrows, ncols := test.want.Dims() + sz := nrows*ncols*sizeFloat64 + sizeInt64 + if len(buf) != sz { + t.Errorf("encoded size test-%d: want=%d got=%d\n", i, sz, len(buf)) + } + + if !bytes.Equal(buf, test.raw) { + t.Errorf("error encoding test-%d: bytes mismatch.\n got=%q\nwant=%q\n", + i, + string(buf), + string(test.raw), + ) + continue + } + } +} + +func TestVectorMarshalTo(t *testing.T) { + for i, test := range vectorData { + buf := new(bytes.Buffer) + n, err := test.want.MarshalBinaryTo(buf) + if err != nil { + t.Errorf("error encoding test-%d: %v\n", i, err) + continue + } + + nrows, ncols := test.want.Dims() + sz := nrows*ncols*sizeFloat64 + sizeInt64 + if n != sz { + t.Errorf("encoded size test-%d: want=%d got=%d\n", i, sz, n) + } + + if !bytes.Equal(buf.Bytes(), test.raw) { + t.Errorf("error encoding test-%d: bytes mismatch.\n got=%q\nwant=%q\n", + i, + string(buf.Bytes()), + string(test.raw), + ) + continue + } + } +} + +func TestVectorUnmarshal(t *testing.T) { + for i, test := range vectorData { + var v Vector + err := v.UnmarshalBinary(test.raw) + if err != nil { + t.Errorf("error decoding test-%d: %v\n", i, err) + continue + } + if !test.eq(&v, test.want) { + t.Errorf("error decoding test-%d: values differ.\n got=%v\nwant=%v\n", + i, + &v, + test.want, + ) + } + } +} + +func TestVectorUnmarshalFrom(t *testing.T) { + for i, test := range vectorData { + var v Vector + buf := bytes.NewReader(test.raw) + n, err := v.UnmarshalBinaryFrom(buf) + if err != nil { + t.Errorf("error decoding test-%d: %v\n", i, err) + continue + } + if n != len(test.raw) { + t.Errorf("error decoding test-%d: lengths differ.\n got=%d\nwant=%d\n", + i, + n, + len(test.raw), + ) + } + if !test.eq(&v, test.want) { + t.Errorf("error decoding test-%d: values differ.\n got=%v\nwant=%v\n", + i, + &v, + test.want, + ) + } + } +} + +func TestVectorUnmarshalFromError(t *testing.T) { + test := vectorData[1] + for i, tt := range []struct { + beg int + end int + }{ + { + beg: 0, + end: len(test.raw) - 1, + }, + { + beg: 0, + end: len(test.raw) - sizeFloat64, + }, + { + beg: 0, + end: 0, + }, + { + beg: 0, + end: 1, + }, + { + beg: 0, + end: sizeInt64, + }, + { + beg: 0, + end: sizeInt64 - 1, + }, + { + beg: 0, + end: sizeInt64 + 1, + }, + { + beg: 0, + end: sizeInt64 + sizeFloat64 - 1, + }, + { + beg: 0, + end: sizeInt64 + sizeFloat64, + }, + { + beg: 0, + end: sizeInt64 + sizeFloat64 + 1, + }, + } { + buf := bytes.NewReader(test.raw[tt.beg:tt.end]) + var v Vector + _, err := v.UnmarshalBinaryFrom(buf) + if err != io.ErrUnexpectedEOF { + t.Errorf("test #%d: error decoding. got=%v. want=%v\n", i, err, io.ErrUnexpectedEOF) + } + } +} + +func TestVectorIORoundTrip(t *testing.T) { + for i, test := range vectorData { + buf, err := test.want.MarshalBinary() + if err != nil { + t.Errorf("error encoding test #%d: %v\n", i, err) + } + + var got Vector + err = got.UnmarshalBinary(buf) + if err != nil { + t.Errorf("error decoding test #%d: %v\n", i, err) + } + if !test.eq(&got, test.want) { + t.Errorf("r/w test #%d failed\n got=%#v\nwant=%#v\n", i, &got, test.want) + } + + wbuf := new(bytes.Buffer) + _, err = test.want.MarshalBinaryTo(wbuf) + if err != nil { + t.Errorf("error encoding test #%d: %v\n", i, err) + } + + if !bytes.Equal(buf, wbuf.Bytes()) { + t.Errorf("encoding via MarshalBinary and MarshalBinaryTo differ:\nwith-stream: %q\n no-stream: %q\n", + i, wbuf.Bytes(), buf, + ) + } + + var wgot Vector + _, err = wgot.UnmarshalBinaryFrom(wbuf) + if err != nil { + t.Errorf("error decoding test #%d: %v\n", i, err) + } + + if !test.eq(&wgot, test.want) { + t.Errorf("r/w test #%d failed\n got=%#v\nwant=%#v\n", i, &wgot, test.want) + } + } +} + +func BenchmarkMarshalDense10(b *testing.B) { marshalBinaryBenchDense(b, 10) } +func BenchmarkMarshalDense100(b *testing.B) { marshalBinaryBenchDense(b, 100) } +func BenchmarkMarshalDense1000(b *testing.B) { marshalBinaryBenchDense(b, 1000) } +func BenchmarkMarshalDense10000(b *testing.B) { marshalBinaryBenchDense(b, 10000) } + +func marshalBinaryBenchDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + m := NewDense(1, size, data) + b.ResetTimer() + + for n := 0; n < b.N; n++ { + m.MarshalBinary() + } +} + +func BenchmarkUnmarshalDense10(b *testing.B) { unmarshalBinaryBenchDense(b, 10) } +func BenchmarkUnmarshalDense100(b *testing.B) { unmarshalBinaryBenchDense(b, 100) } +func BenchmarkUnmarshalDense1000(b *testing.B) { unmarshalBinaryBenchDense(b, 1000) } +func BenchmarkUnmarshalDense10000(b *testing.B) { unmarshalBinaryBenchDense(b, 10000) } + +func unmarshalBinaryBenchDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + buf, err := NewDense(1, size, data).MarshalBinary() + if err != nil { + b.Fatalf("error creating binary buffer (size=%d): %v\n", size, err) + } + b.ResetTimer() + + for n := 0; n < b.N; n++ { + var m Dense + m.UnmarshalBinary(buf) + } +} + +func BenchmarkMarshalToDense10(b *testing.B) { marshalBinaryToBenchDense(b, 10) } +func BenchmarkMarshalToDense100(b *testing.B) { marshalBinaryToBenchDense(b, 100) } +func BenchmarkMarshalToDense1000(b *testing.B) { marshalBinaryToBenchDense(b, 1000) } +func BenchmarkMarshalToDense10000(b *testing.B) { marshalBinaryToBenchDense(b, 10000) } + +func marshalBinaryToBenchDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + m := NewDense(1, size, data) + w := ioutil.Discard + b.ResetTimer() + + for n := 0; n < b.N; n++ { + m.MarshalBinaryTo(w) + } +} + +type readerTest struct { + buf []byte + pos int +} + +func (r *readerTest) Read(data []byte) (int, error) { + n := copy(data, r.buf[r.pos:r.pos+len(data)]) + r.pos += n + return n, nil +} + +func (r *readerTest) reset() { + r.pos = 0 +} + +func BenchmarkUnmarshalFromDense10(b *testing.B) { unmarshalBinaryFromBenchDense(b, 10) } +func BenchmarkUnmarshalFromDense100(b *testing.B) { unmarshalBinaryFromBenchDense(b, 100) } +func BenchmarkUnmarshalFromDense1000(b *testing.B) { unmarshalBinaryFromBenchDense(b, 1000) } +func BenchmarkUnmarshalFromDense10000(b *testing.B) { unmarshalBinaryFromBenchDense(b, 10000) } + +func unmarshalBinaryFromBenchDense(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + buf, err := NewDense(1, size, data).MarshalBinary() + if err != nil { + b.Fatalf("error creating binary buffer (size=%d): %v\n", size, err) + } + r := &readerTest{buf: buf} + b.ResetTimer() + + for n := 0; n < b.N; n++ { + var m Dense + m.UnmarshalBinaryFrom(r) + r.reset() + } +} + +func BenchmarkMarshalVector10(b *testing.B) { marshalBinaryBenchVector(b, 10) } +func BenchmarkMarshalVector100(b *testing.B) { marshalBinaryBenchVector(b, 100) } +func BenchmarkMarshalVector1000(b *testing.B) { marshalBinaryBenchVector(b, 1000) } +func BenchmarkMarshalVector10000(b *testing.B) { marshalBinaryBenchVector(b, 10000) } + +func marshalBinaryBenchVector(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + vec := NewVector(size, data) + b.ResetTimer() + + for n := 0; n < b.N; n++ { + vec.MarshalBinary() + } +} + +func BenchmarkUnmarshalVector10(b *testing.B) { unmarshalBinaryBenchVector(b, 10) } +func BenchmarkUnmarshalVector100(b *testing.B) { unmarshalBinaryBenchVector(b, 100) } +func BenchmarkUnmarshalVector1000(b *testing.B) { unmarshalBinaryBenchVector(b, 1000) } +func BenchmarkUnmarshalVector10000(b *testing.B) { unmarshalBinaryBenchVector(b, 10000) } + +func unmarshalBinaryBenchVector(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + buf, err := NewVector(size, data).MarshalBinary() + if err != nil { + b.Fatalf("error creating binary buffer (size=%d): %v\n", size, err) + } + b.ResetTimer() + + for n := 0; n < b.N; n++ { + var vec Vector + vec.UnmarshalBinary(buf) + } +} + +func BenchmarkMarshalToVector10(b *testing.B) { marshalBinaryToBenchVector(b, 10) } +func BenchmarkMarshalToVector100(b *testing.B) { marshalBinaryToBenchVector(b, 100) } +func BenchmarkMarshalToVector1000(b *testing.B) { marshalBinaryToBenchVector(b, 1000) } +func BenchmarkMarshalToVector10000(b *testing.B) { marshalBinaryToBenchVector(b, 10000) } + +func marshalBinaryToBenchVector(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + vec := NewVector(size, data) + w := ioutil.Discard + b.ResetTimer() + + for n := 0; n < b.N; n++ { + vec.MarshalBinaryTo(w) + } +} + +func BenchmarkUnmarshalFromVector10(b *testing.B) { unmarshalBinaryFromBenchVector(b, 10) } +func BenchmarkUnmarshalFromVector100(b *testing.B) { unmarshalBinaryFromBenchVector(b, 100) } +func BenchmarkUnmarshalFromVector1000(b *testing.B) { unmarshalBinaryFromBenchVector(b, 1000) } +func BenchmarkUnmarshalFromVector10000(b *testing.B) { unmarshalBinaryFromBenchVector(b, 10000) } + +func unmarshalBinaryFromBenchVector(b *testing.B, size int) { + data := make([]float64, size) + for i := range data { + data[i] = float64(i) + } + buf, err := NewVector(size, data).MarshalBinary() + if err != nil { + b.Fatalf("error creating binary buffer (size=%d): %v\n", size, err) + } + r := &readerTest{buf: buf} + b.ResetTimer() + + for n := 0; n < b.N; n++ { + var vec Vector + vec.UnmarshalBinaryFrom(r) + r.reset() + } +} diff --git a/matrix/mat64/list_test.go b/matrix/mat64/list_test.go new file mode 100644 index 00000000..8f21b200 --- /dev/null +++ b/matrix/mat64/list_test.go @@ -0,0 +1,1152 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "fmt" + "math" + "math/rand" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix" +) + +// legalSizeSameRectangular returns whether the two matrices have the same rectangular shape. +func legalSizeSameRectangular(ar, ac, br, bc int) bool { + if ar != br { + return false + } + if ac != bc { + return false + } + return true +} + +// legalSizeSameSquare returns whether the two matrices have the same square shape. +func legalSizeSameSquare(ar, ac, br, bc int) bool { + if ar != br { + return false + } + if ac != bc { + return false + } + if ar != ac { + return false + } + return true +} + +// legalSizeSameHeight returns whether the two matrices have the same number of rows. +func legalSizeSameHeight(ar, _, br, _ int) bool { + return ar == br +} + +// legalSizeSameWidth returns whether the two matrices have the same number of columns. +func legalSizeSameWidth(_, ac, _, bc int) bool { + return ac == bc +} + +// legalSizeSolve returns whether the two matrices can be used in a linear solve. +func legalSizeSolve(ar, ac, br, bc int) bool { + return ar == br +} + +// legalSizeSameVec returns whether the two matrices are column vectors of the +// same dimension. +func legalSizeSameVec(ar, ac, br, bc int) bool { + return ac == 1 && bc == 1 && ar == br +} + +// isAnySize returns true for all matrix sizes. +func isAnySize(ar, ac int) bool { + return true +} + +// isAnySize2 returns true for all matrix sizes. +func isAnySize2(ar, ac, br, bc int) bool { + return true +} + +// isAnyVector returns true for any column vector sizes. +func isAnyVector(ar, ac int) bool { + return ac == 1 +} + +// isSquare returns whether the input matrix is square. +func isSquare(r, c int) bool { + return r == c +} + +// sameAnswerFloat returns whether the two inputs are both NaN or are equal. +func sameAnswerFloat(a, b interface{}) bool { + if math.IsNaN(a.(float64)) { + return math.IsNaN(b.(float64)) + } + return a.(float64) == b.(float64) +} + +// sameAnswerFloatApproxTol returns a function that determines whether its two +// inputs are both NaN or within tol of each other. +func sameAnswerFloatApproxTol(tol float64) func(a, b interface{}) bool { + return func(a, b interface{}) bool { + if math.IsNaN(a.(float64)) { + return math.IsNaN(b.(float64)) + } + return floats.EqualWithinAbsOrRel(a.(float64), b.(float64), tol, tol) + } +} + +func sameAnswerF64SliceOfSlice(a, b interface{}) bool { + for i, v := range a.([][]float64) { + if same := floats.Same(v, b.([][]float64)[i]); !same { + return false + } + } + return true +} + +// sameAnswerBool returns whether the two inputs have the same value. +func sameAnswerBool(a, b interface{}) bool { + return a.(bool) == b.(bool) +} + +// isAnyType returns true for all Matrix types. +func isAnyType(Matrix) bool { + return true +} + +// legalTypesAll returns true for all Matrix types. +func legalTypesAll(a, b Matrix) bool { + return true +} + +// legalTypeSym returns whether a is a Symmetric. +func legalTypeSym(a Matrix) bool { + _, ok := a.(Symmetric) + return ok +} + +// legalTypesSym returns whether both input arguments are Symmetric. +func legalTypesSym(a, b Matrix) bool { + if _, ok := a.(Symmetric); !ok { + return false + } + if _, ok := b.(Symmetric); !ok { + return false + } + return true +} + +// legalTypeVec returns whether v is a *Vector. +func legalTypeVec(v Matrix) bool { + _, ok := v.(*Vector) + return ok +} + +// legalTypesVecVec returns whether both inputs are *Vector. +func legalTypesVecVec(a, b Matrix) bool { + if _, ok := a.(*Vector); !ok { + return false + } + if _, ok := b.(*Vector); !ok { + return false + } + return true +} + +// legalTypesNotVecVec returns whether the first input is an arbitrary Matrix +// and the second input is a *Vector. +func legalTypesNotVecVec(a, b Matrix) bool { + _, ok := b.(*Vector) + return ok +} + +// legalDims returns whether {m,n} is a valid dimension of the given matrix type. +func legalDims(a Matrix, m, n int) bool { + switch t := a.(type) { + default: + panic("legal dims type not coded") + case Untransposer: + return legalDims(t.Untranspose(), n, m) + case *Dense, *basicMatrix: + if m < 0 || n < 0 { + return false + } + return true + case *SymDense, *TriDense, *basicSymmetric, *basicTriangular: + if m < 0 || n < 0 || m != n { + return false + } + return true + case *Vector: + if m < 0 || n < 0 { + return false + } + return n == 1 + } +} + +// returnAs returns the matrix a with the type of t. Used for making a concrete +// type and changing to the basic form. +func returnAs(a, t Matrix) Matrix { + switch mat := a.(type) { + default: + panic("unknown type for a") + case *Dense: + switch t.(type) { + default: + panic("bad type") + case *Dense: + return mat + case *basicMatrix: + return asBasicMatrix(mat) + } + case *SymDense: + switch t.(type) { + default: + panic("bad type") + case *SymDense: + return mat + case *basicSymmetric: + return asBasicSymmetric(mat) + } + case *TriDense: + switch t.(type) { + default: + panic("bad type") + case *TriDense: + return mat + case *basicTriangular: + return asBasicTriangular(mat) + } + } +} + +// retranspose returns the matrix m inside an Untransposer of the type +// of a. +func retranspose(a, m Matrix) Matrix { + switch a.(type) { + case TransposeTri: + return TransposeTri{m.(Triangular)} + case Transpose: + return Transpose{m} + case Untransposer: + panic("unknown transposer type") + default: + panic("a is not an untransposer") + } +} + +// makeRandOf returns a new randomly filled m×n matrix of the underlying matrix type. +func makeRandOf(a Matrix, m, n int) Matrix { + var rMatrix Matrix + switch t := a.(type) { + default: + panic("unknown type for make rand of") + case Untransposer: + rMatrix = retranspose(a, makeRandOf(t.Untranspose(), n, m)) + case *Dense, *basicMatrix: + mat := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + mat.Set(i, j, rand.NormFloat64()) + } + } + rMatrix = returnAs(mat, t) + case *Vector: + if m == 0 && n == 0 { + return &Vector{} + } + if n != 1 { + panic(fmt.Sprintf("bad vector size: m = %v, n = %v", m, n)) + } + length := m + inc := 1 + if t.mat.Inc != 0 { + inc = t.mat.Inc + } + mat := &Vector{ + mat: blas64.Vector{ + Inc: inc, + Data: make([]float64, inc*(length-1)+1), + }, + n: length, + } + for i := 0; i < length; i++ { + mat.SetVec(i, rand.NormFloat64()) + } + return mat + case *SymDense, *basicSymmetric: + if m != n { + panic("bad size") + } + mat := NewSymDense(n, nil) + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + mat.SetSym(i, j, rand.NormFloat64()) + } + } + rMatrix = returnAs(mat, t) + case *TriDense, *basicTriangular: + if m != n { + panic("bad size") + } + + // This is necessary because we are making + // a triangle from the zero value, which + // always returns upper as true. + var triKind matrix.TriKind + switch t := t.(type) { + case *TriDense: + triKind = t.triKind() + case *basicTriangular: + triKind = (*TriDense)(t).triKind() + } + + mat := NewTriDense(n, triKind, nil) + if triKind == matrix.Upper { + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + mat.SetTri(i, j, rand.NormFloat64()) + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j <= i; j++ { + mat.SetTri(i, j, rand.NormFloat64()) + } + } + } + rMatrix = returnAs(mat, t) + } + if mr, mc := rMatrix.Dims(); mr != m || mc != n { + panic(fmt.Sprintf("makeRandOf for %T returns wrong size: %d×%d != %d×%d", a, m, n, mr, mc)) + } + return rMatrix +} + +// makeCopyOf returns a copy of the matrix. +func makeCopyOf(a Matrix) Matrix { + switch t := a.(type) { + default: + panic("unknown type in makeCopyOf") + case Untransposer: + return retranspose(a, makeCopyOf(t.Untranspose())) + case *Dense, *basicMatrix: + var m Dense + m.Clone(a) + return returnAs(&m, t) + case *SymDense, *basicSymmetric: + n := t.(Symmetric).Symmetric() + m := NewSymDense(n, nil) + m.CopySym(t.(Symmetric)) + return returnAs(m, t) + case *TriDense, *basicTriangular: + n, upper := t.(Triangular).Triangle() + m := NewTriDense(n, upper, nil) + if upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + m.SetTri(i, j, t.At(i, j)) + } + } + } else { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + m.SetTri(i, j, t.At(i, j)) + } + } + } + return returnAs(m, t) + case *Vector: + m := &Vector{ + mat: blas64.Vector{ + Inc: t.mat.Inc, + Data: make([]float64, t.mat.Inc*(t.n-1)+1), + }, + n: t.n, + } + copy(m.mat.Data, t.mat.Data) + return m + } +} + +// sameType returns true if a and b have the same underlying type. +func sameType(a, b Matrix) bool { + return reflect.ValueOf(a).Type() == reflect.ValueOf(b).Type() +} + +// maybeSame returns true if the two matrices could be represented by the same +// pointer. +func maybeSame(receiver, a Matrix) bool { + rr, rc := receiver.Dims() + u, trans := a.(Untransposer) + if trans { + a = u.Untranspose() + } + if !sameType(receiver, a) { + return false + } + ar, ac := a.Dims() + if rr != ar || rc != ac { + return false + } + if _, ok := a.(Triangular); ok { + // They are both triangular types. The TriType needs to match + _, aKind := a.(Triangular).Triangle() + _, rKind := receiver.(Triangular).Triangle() + if aKind != rKind { + return false + } + } + return true +} + +// equalApprox returns whether the elements of a and b are the same to within +// the tolerance. If ignoreNaN is true the test is relaxed such that NaN == NaN. +func equalApprox(a, b Matrix, tol float64, ignoreNaN bool) bool { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br { + return false + } + if ac != bc { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if !floats.EqualWithinAbsOrRel(a.At(i, j), b.At(i, j), tol, tol) { + if ignoreNaN && math.IsNaN(a.At(i, j)) && math.IsNaN(b.At(i, j)) { + continue + } + return false + } + } + } + return true +} + +// equal returns true if the matrices have equal entries. +func equal(a, b Matrix) bool { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br { + return false + } + if ac != bc { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.At(i, j) != b.At(i, j) { + return false + } + } + } + return true +} + +// isDiagonal returns whether a is a diagonal matrix. +func isDiagonal(a Matrix) bool { + r, c := a.Dims() + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + if a.At(i, j) != 0 && i != j { + return false + } + } + } + return true +} + +// equalDiagonal returns whether a and b are equal on the diagonal. +func equalDiagonal(a, b Matrix) bool { + ar, ac := a.Dims() + br, bc := a.Dims() + if min(ar, ac) != min(br, bc) { + return false + } + for i := 0; i < min(ar, ac); i++ { + if a.At(i, i) != b.At(i, i) { + return false + } + } + return true +} + +// underlyingData extracts the underlying data of the matrix a. +func underlyingData(a Matrix) []float64 { + switch t := a.(type) { + default: + panic("matrix type not implemented for extracting underlying data") + case Untransposer: + return underlyingData(t.Untranspose()) + case *Dense: + return t.mat.Data + case *SymDense: + return t.mat.Data + case *TriDense: + return t.mat.Data + case *Vector: + return t.mat.Data + } +} + +// testMatrices is a list of matrix types to test. +// The TriDense types have actual sizes because the return from Triangular is +// only valid when n == 0. +var testMatrices = []Matrix{ + &Dense{}, + &SymDense{}, + NewTriDense(3, true, nil), + NewTriDense(3, false, nil), + NewVector(0, nil), + &Vector{mat: blas64.Vector{Inc: 10}}, + &basicMatrix{}, + &basicSymmetric{}, + &basicTriangular{cap: 3, mat: blas64.Triangular{N: 3, Stride: 3, Uplo: blas.Upper}}, + &basicTriangular{cap: 3, mat: blas64.Triangular{N: 3, Stride: 3, Uplo: blas.Lower}}, + + Transpose{&Dense{}}, + Transpose{NewTriDense(3, true, nil)}, + TransposeTri{NewTriDense(3, true, nil)}, + Transpose{NewTriDense(3, false, nil)}, + TransposeTri{NewTriDense(3, false, nil)}, + Transpose{NewVector(0, nil)}, + Transpose{&Vector{mat: blas64.Vector{Inc: 10}}}, + Transpose{&basicMatrix{}}, + Transpose{&basicSymmetric{}}, + Transpose{&basicTriangular{cap: 3, mat: blas64.Triangular{N: 3, Stride: 3, Uplo: blas.Upper}}}, + Transpose{&basicTriangular{cap: 3, mat: blas64.Triangular{N: 3, Stride: 3, Uplo: blas.Lower}}}, +} + +var sizes = []struct { + ar, ac int +}{ + {1, 1}, + {1, 3}, + {3, 1}, + + {6, 6}, + {6, 11}, + {11, 6}, +} + +func testOneInputFunc(t *testing.T, + // name is the name of the function being tested. + name string, + + // f is the function being tested. + f func(a Matrix) interface{}, + + // denseComparison performs the same operation, but using Dense matrices for + // comparison. + denseComparison func(a *Dense) interface{}, + + // sameAnswer compares the result from two different evaluations of the function + // and returns true if they are the same. The specific function being tested + // determines the definition of "same". It may mean identical or it may mean + // approximately equal. + sameAnswer func(a, b interface{}) bool, + + // legalType returns true if the type of the input is a legal type for the + // input of the function. + legalType func(a Matrix) bool, + + // legalSize returns true if the size is valid for the function. + legalSize func(r, c int) bool, +) { + for _, aMat := range testMatrices { + for _, test := range sizes { + // Skip the test if the argument would not be assignable to the + // method's corresponding input parameter or it is not possible + // to construct an argument of the requested size. + if !legalType(aMat) { + continue + } + if !legalDims(aMat, test.ar, test.ac) { + continue + } + a := makeRandOf(aMat, test.ar, test.ac) + + // Compute the true answer if the sizes are legal. + dimsOK := legalSize(test.ar, test.ac) + var want interface{} + if dimsOK { + var aDense Dense + aDense.Clone(a) + want = denseComparison(&aDense) + } + aCopy := makeCopyOf(a) + // Test the method for a zero-value of the receiver. + aType, aTrans := untranspose(a) + errStr := fmt.Sprintf("%v(%T), size: %#v, atrans %t", name, aType, test, aTrans) + var got interface{} + panicked, err := panics(func() { got = f(a) }) + if !dimsOK && !panicked { + t.Errorf("Did not panic with illegal size: %s", errStr) + continue + } + if dimsOK && panicked { + t.Errorf("Panicked with legal size: %s: %v", errStr, err) + continue + } + if !equal(a, aCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !dimsOK { + continue + } + if !sameAnswer(want, got) { + t.Errorf("Answer mismatch: %s", errStr) + } + } + } +} + +var sizePairs = []struct { + ar, ac, br, bc int +}{ + {1, 1, 1, 1}, + {6, 6, 6, 6}, + {7, 7, 7, 7}, + + {1, 1, 1, 5}, + {1, 1, 5, 1}, + {1, 5, 1, 1}, + {5, 1, 1, 1}, + + {5, 5, 5, 1}, + {5, 5, 1, 5}, + {5, 1, 5, 5}, + {1, 5, 5, 5}, + + {6, 6, 6, 11}, + {6, 6, 11, 6}, + {6, 11, 6, 6}, + {11, 6, 6, 6}, + {11, 11, 11, 6}, + {11, 11, 6, 11}, + {11, 6, 11, 11}, + {6, 11, 11, 11}, + + {1, 1, 5, 5}, + {1, 5, 1, 5}, + {1, 5, 5, 1}, + {5, 1, 1, 5}, + {5, 1, 5, 1}, + {5, 5, 1, 1}, + {6, 6, 11, 11}, + {6, 11, 6, 11}, + {6, 11, 11, 6}, + {11, 6, 6, 11}, + {11, 6, 11, 6}, + {11, 11, 6, 6}, + + {1, 1, 17, 11}, + {1, 1, 11, 17}, + {1, 11, 1, 17}, + {1, 17, 1, 11}, + {1, 11, 17, 1}, + {1, 17, 11, 1}, + {11, 1, 1, 17}, + {17, 1, 1, 11}, + {11, 1, 17, 1}, + {17, 1, 11, 1}, + {11, 17, 1, 1}, + {17, 11, 1, 1}, + + {6, 6, 1, 11}, + {6, 6, 11, 1}, + {6, 11, 6, 1}, + {6, 1, 6, 11}, + {6, 11, 1, 6}, + {6, 1, 11, 6}, + {11, 6, 6, 1}, + {1, 6, 6, 11}, + {11, 6, 1, 6}, + {1, 6, 11, 6}, + {11, 1, 6, 6}, + {1, 11, 6, 6}, + + {6, 6, 17, 1}, + {6, 6, 1, 17}, + {6, 1, 6, 17}, + {6, 17, 6, 1}, + {6, 1, 17, 6}, + {6, 17, 1, 6}, + {1, 6, 6, 17}, + {17, 6, 6, 1}, + {1, 6, 17, 6}, + {17, 6, 1, 6}, + {1, 17, 6, 6}, + {17, 1, 6, 6}, + + {6, 6, 17, 11}, + {6, 6, 11, 17}, + {6, 11, 6, 17}, + {6, 17, 6, 11}, + {6, 11, 17, 6}, + {6, 17, 11, 6}, + {11, 6, 6, 17}, + {17, 6, 6, 11}, + {11, 6, 17, 6}, + {17, 6, 11, 6}, + {11, 17, 6, 6}, + {17, 11, 6, 6}, +} + +func testTwoInputFunc(t *testing.T, + // name is the name of the function being tested. + name string, + + // f is the function being tested. + f func(a, b Matrix) interface{}, + + // denseComparison performs the same operation, but using Dense matrices for + // comparison. + denseComparison func(a, b *Dense) interface{}, + + // sameAnswer compares the result from two different evaluations of the function + // and returns true if they are the same. The specific function being tested + // determines the definition of "same". It may mean identical or it may mean + // approximately equal. + sameAnswer func(a, b interface{}) bool, + + // legalType returns true if the types of the inputs are legal for the + // input of the function. + legalType func(a, b Matrix) bool, + + // legalSize returns true if the sizes are valid for the function. + legalSize func(ar, ac, br, bc int) bool, +) { + for _, aMat := range testMatrices { + for _, bMat := range testMatrices { + // Loop over all of the size combinations (bigger, smaller, etc.). + for _, test := range sizePairs { + // Skip the test if the argument would not be assignable to the + // method's corresponding input parameter or it is not possible + // to construct an argument of the requested size. + if !legalType(aMat, bMat) { + continue + } + if !legalDims(aMat, test.ar, test.ac) { + continue + } + if !legalDims(bMat, test.br, test.bc) { + continue + } + a := makeRandOf(aMat, test.ar, test.ac) + b := makeRandOf(bMat, test.br, test.bc) + + // Compute the true answer if the sizes are legal. + dimsOK := legalSize(test.ar, test.ac, test.br, test.bc) + var want interface{} + if dimsOK { + var aDense, bDense Dense + aDense.Clone(a) + bDense.Clone(b) + want = denseComparison(&aDense, &bDense) + } + aCopy := makeCopyOf(a) + bCopy := makeCopyOf(b) + // Test the method for a zero-value of the receiver. + aType, aTrans := untranspose(a) + bType, bTrans := untranspose(b) + errStr := fmt.Sprintf("%v(%T, %T), size: %#v, atrans %t, btrans %t", name, aType, bType, test, aTrans, bTrans) + var got interface{} + panicked, err := panics(func() { got = f(a, b) }) + if !dimsOK && !panicked { + t.Errorf("Did not panic with illegal size: %s", errStr) + continue + } + if dimsOK && panicked { + t.Errorf("Panicked with legal size: %s: %v", errStr, err) + continue + } + if !equal(a, aCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !equal(b, bCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !dimsOK { + continue + } + if !sameAnswer(want, got) { + t.Errorf("Answer mismatch: %s", errStr) + } + } + } + } +} + +// testOneInput tests a method that has one matrix input argument +func testOneInput(t *testing.T, + // name is the name of the method being tested. + name string, + + // receiver is a value of the receiver type. + receiver Matrix, + + // method is the generalized receiver.Method(a). + method func(receiver, a Matrix), + + // denseComparison performs the same operation as method, but with dense + // matrices for comparison with the result. + denseComparison func(receiver, a *Dense), + + // legalTypes returns whether the concrete types in Matrix are valid for + // the method. + legalType func(a Matrix) bool, + + // legalSize returns whether the matrix sizes are valid for the method. + legalSize func(ar, ac int) bool, + + // tol is the tolerance for equality when comparing method results. + tol float64, +) { + for _, aMat := range testMatrices { + for _, test := range sizes { + // Skip the test if the argument would not be assignable to the + // method's corresponding input parameter or it is not possible + // to construct an argument of the requested size. + if !legalType(aMat) { + continue + } + if !legalDims(aMat, test.ar, test.ac) { + continue + } + a := makeRandOf(aMat, test.ar, test.ac) + + // Compute the true answer if the sizes are legal. + dimsOK := legalSize(test.ar, test.ac) + var want Dense + if dimsOK { + var aDense Dense + aDense.Clone(a) + denseComparison(&want, &aDense) + } + aCopy := makeCopyOf(a) + + // Test the method for a zero-value of the receiver. + aType, aTrans := untranspose(a) + errStr := fmt.Sprintf("%T.%s(%T), size: %#v, atrans %v", receiver, name, aType, test, aTrans) + zero := makeRandOf(receiver, 0, 0) + panicked, err := panics(func() { method(zero, a) }) + if !dimsOK && !panicked { + t.Errorf("Did not panic with illegal size: %s", errStr) + continue + } + if dimsOK && panicked { + t.Errorf("Panicked with legal size: %s: %v", errStr, err) + continue + } + if !equal(a, aCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !dimsOK { + continue + } + if !equalApprox(zero, &want, tol, false) { + t.Errorf("Answer mismatch with zero receiver: %s.\nGot:\n% v\nWant:\n% v\n", errStr, Formatted(zero), Formatted(&want)) + continue + } + + // Test the method with a non-zero-value of the receiver. + // The receiver has been overwritten in place so use its size + // to construct a new random matrix. + rr, rc := zero.Dims() + neverZero := makeRandOf(receiver, rr, rc) + panicked, _ = panics(func() { method(neverZero, a) }) + if panicked { + t.Errorf("Panicked with non-zero receiver: %s", errStr) + } + if !equalApprox(neverZero, &want, tol, false) { + t.Errorf("Answer mismatch non-zero receiver: %s", errStr) + } + + // Test with an incorrectly sized matrix. + switch receiver.(type) { + default: + panic("matrix type not coded for incorrect receiver size") + case *Dense: + wrongSize := makeRandOf(receiver, rr+1, rc) + panicked, _ = panics(func() { method(wrongSize, a) }) + if !panicked { + t.Errorf("Did not panic with wrong number of rows: %s", errStr) + } + wrongSize = makeRandOf(receiver, rr, rc+1) + panicked, _ = panics(func() { method(wrongSize, a) }) + if !panicked { + t.Errorf("Did not panic with wrong number of columns: %s", errStr) + } + case *TriDense, *SymDense: + // Add to the square size. + wrongSize := makeRandOf(receiver, rr+1, rc+1) + panicked, _ = panics(func() { method(wrongSize, a) }) + if !panicked { + t.Errorf("Did not panic with wrong size: %s", errStr) + } + case *Vector: + // Add to the column length. + wrongSize := makeRandOf(receiver, rr+1, rc) + panicked, _ = panics(func() { method(wrongSize, a) }) + if !panicked { + t.Errorf("Did not panic with wrong number of rows: %s", errStr) + } + } + + // The receiver and the input may share a matrix pointer + // if the type and size of the receiver and one of the + // arguments match. Test the method works properly + // when this is the case. + aMaybeSame := maybeSame(neverZero, a) + if aMaybeSame { + aSame := makeCopyOf(a) + receiver = aSame + u, ok := aSame.(Untransposer) + if ok { + receiver = u.Untranspose() + } + preData := underlyingData(receiver) + panicked, err = panics(func() { method(receiver, aSame) }) + if panicked { + t.Errorf("Panics when a maybeSame: %s: %v", errStr, err) + } else { + if !equalApprox(receiver, &want, tol, false) { + t.Errorf("Wrong answer when a maybeSame: %s", errStr) + } + postData := underlyingData(receiver) + if !floats.Equal(preData, postData) { + t.Errorf("Original data slice not modified when a maybeSame: %s", errStr) + } + } + } + } + } +} + +// testTwoInput tests a method that has two input arguments. +func testTwoInput(t *testing.T, + // name is the name of the method being tested. + name string, + + // receiver is a value of the receiver type. + receiver Matrix, + + // method is the generalized receiver.Method(a, b). + method func(receiver, a, b Matrix), + + // denseComparison performs the same operation as method, but with dense + // matrices for comparison with the result. + denseComparison func(receiver, a, b *Dense), + + // legalTypes returns whether the concrete types in Matrix are valid for + // the method. + legalTypes func(a, b Matrix) bool, + + // legalSize returns whether the matrix sizes are valid for the method. + legalSize func(ar, ac, br, bc int) bool, + + // tol is the tolerance for equality when comparing method results. + tol float64, +) { + for _, aMat := range testMatrices { + for _, bMat := range testMatrices { + // Loop over all of the size combinations (bigger, smaller, etc.). + for _, test := range sizePairs { + // Skip the test if any argument would not be assignable to the + // method's corresponding input parameter or it is not possible + // to construct an argument of the requested size. + if !legalTypes(aMat, bMat) { + continue + } + if !legalDims(aMat, test.ar, test.ac) { + continue + } + if !legalDims(bMat, test.br, test.bc) { + continue + } + a := makeRandOf(aMat, test.ar, test.ac) + b := makeRandOf(bMat, test.br, test.bc) + + // Compute the true answer if the sizes are legal. + dimsOK := legalSize(test.ar, test.ac, test.br, test.bc) + var want Dense + if dimsOK { + var aDense, bDense Dense + aDense.Clone(a) + bDense.Clone(b) + denseComparison(&want, &aDense, &bDense) + } + aCopy := makeCopyOf(a) + bCopy := makeCopyOf(b) + + // Test the method for a zero-value of the receiver. + aType, aTrans := untranspose(a) + bType, bTrans := untranspose(b) + errStr := fmt.Sprintf("%T.%s(%T, %T), sizes: %#v, atrans %v, btrans %v", receiver, name, aType, bType, test, aTrans, bTrans) + zero := makeRandOf(receiver, 0, 0) + panicked, err := panics(func() { method(zero, a, b) }) + if !dimsOK && !panicked { + t.Errorf("Did not panic with illegal size: %s", errStr) + continue + } + if dimsOK && panicked { + t.Errorf("Panicked with legal size: %s: %v", errStr, err) + continue + } + if !equal(a, aCopy) { + t.Errorf("First input argument changed in call: %s", errStr) + } + if !equal(b, bCopy) { + t.Errorf("Second input argument changed in call: %s", errStr) + } + if !dimsOK { + continue + } + wasZero, zero := zero, nil // Nil-out zero so we detect illegal use. + // NaN equality is allowed because of 0/0 in DivElem test. + if !equalApprox(wasZero, &want, tol, true) { + t.Errorf("Answer mismatch with zero receiver: %s", errStr) + continue + } + + // Test the method with a non-zero-value of the receiver. + // The receiver has been overwritten in place so use its size + // to construct a new random matrix. + rr, rc := wasZero.Dims() + neverZero := makeRandOf(receiver, rr, rc) + panicked, message := panics(func() { method(neverZero, a, b) }) + if panicked { + t.Errorf("Panicked with non-zero receiver: %s: %s", errStr, message) + } + // NaN equality is allowed because of 0/0 in DivElem test. + if !equalApprox(neverZero, &want, tol, true) { + t.Errorf("Answer mismatch non-zero receiver: %s", errStr) + } + + // Test with an incorrectly sized matrix. + switch receiver.(type) { + default: + panic("matrix type not coded for incorrect receiver size") + case *Dense: + wrongSize := makeRandOf(receiver, rr+1, rc) + panicked, _ = panics(func() { method(wrongSize, a, b) }) + if !panicked { + t.Errorf("Did not panic with wrong number of rows: %s", errStr) + } + wrongSize = makeRandOf(receiver, rr, rc+1) + panicked, _ = panics(func() { method(wrongSize, a, b) }) + if !panicked { + t.Errorf("Did not panic with wrong number of columns: %s", errStr) + } + case *TriDense, *SymDense: + // Add to the square size. + wrongSize := makeRandOf(receiver, rr+1, rc+1) + panicked, _ = panics(func() { method(wrongSize, a, b) }) + if !panicked { + t.Errorf("Did not panic with wrong size: %s", errStr) + } + case *Vector: + // Add to the column length. + wrongSize := makeRandOf(receiver, rr+1, rc) + panicked, _ = panics(func() { method(wrongSize, a, b) }) + if !panicked { + t.Errorf("Did not panic with wrong number of rows: %s", errStr) + } + } + + // The receiver and an input may share a matrix pointer + // if the type and size of the receiver and one of the + // arguments match. Test the method works properly + // when this is the case. + aMaybeSame := maybeSame(neverZero, a) + bMaybeSame := maybeSame(neverZero, b) + if aMaybeSame { + aSame := makeCopyOf(a) + receiver = aSame + u, ok := aSame.(Untransposer) + if ok { + receiver = u.Untranspose() + } + preData := underlyingData(receiver) + panicked, err = panics(func() { method(receiver, aSame, b) }) + if panicked { + t.Errorf("Panics when a maybeSame: %s: %v", errStr, err) + } else { + if !equalApprox(receiver, &want, tol, false) { + t.Errorf("Wrong answer when a maybeSame: %s", errStr) + } + postData := underlyingData(receiver) + if !floats.Equal(preData, postData) { + t.Errorf("Original data slice not modified when a maybeSame: %s", errStr) + } + } + } + if bMaybeSame { + bSame := makeCopyOf(b) + receiver = bSame + u, ok := bSame.(Untransposer) + if ok { + receiver = u.Untranspose() + } + preData := underlyingData(receiver) + panicked, err = panics(func() { method(receiver, a, bSame) }) + if panicked { + t.Errorf("Panics when b maybeSame: %s: %v", errStr, err) + } else { + if !equalApprox(receiver, &want, tol, false) { + t.Errorf("Wrong answer when b maybeSame: %s", errStr) + } + postData := underlyingData(receiver) + if !floats.Equal(preData, postData) { + t.Errorf("Original data slice not modified when b maybeSame: %s", errStr) + } + } + } + if aMaybeSame && bMaybeSame { + aSame := makeCopyOf(a) + receiver = aSame + u, ok := aSame.(Untransposer) + if ok { + receiver = u.Untranspose() + } + // Ensure that b is the correct transpose type if applicable. + // The receiver is always a concrete type so use it. + bSame := receiver + u, ok = b.(Untransposer) + if ok { + bSame = retranspose(b, receiver) + } + // Compute the real answer for this case. It is different + // from the initial answer since now a and b have the + // same data. + zero = makeRandOf(wasZero, 0, 0) + method(zero, aSame, bSame) + wasZero, zero = zero, nil // Nil-out zero so we detect illegal use. + preData := underlyingData(receiver) + panicked, err = panics(func() { method(receiver, aSame, bSame) }) + if panicked { + t.Errorf("Panics when both maybeSame: %s: %v", errStr, err) + } else { + if !equalApprox(receiver, wasZero, tol, false) { + t.Errorf("Wrong answer when both maybeSame: %s", errStr) + } + postData := underlyingData(receiver) + if !floats.Equal(preData, postData) { + t.Errorf("Original data slice not modified when both maybeSame: %s", errStr) + } + } + } + } + } + } +} diff --git a/matrix/mat64/lq.go b/matrix/mat64/lq.go new file mode 100644 index 00000000..5fe9766c --- /dev/null +++ b/matrix/mat64/lq.go @@ -0,0 +1,217 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +// LQ is a type for creating and using the LQ factorization of a matrix. +type LQ struct { + lq *Dense + tau []float64 + cond float64 +} + +func (lq *LQ) updateCond() { + // A = LQ, where Q is orthonormal. Orthonormal multiplications do not change + // the condition number. Thus, ||A|| = ||L|| ||Q|| = ||Q||. + m := lq.lq.mat.Rows + work := make([]float64, 3*m) + iwork := make([]int, m) + l := lq.lq.asTriDense(m, blas.NonUnit, blas.Lower) + v := lapack64.Trcon(matrix.CondNorm, l.mat, work, iwork) + lq.cond = 1 / v +} + +// Factorize computes the LQ factorization of an m×n matrix a where n <= m. The LQ +// factorization always exists even if A is singular. +// +// The LQ decomposition is a factorization of the matrix A such that A = L * Q. +// The matrix Q is an orthonormal n×n matrix, and L is an m×n upper triangular matrix. +// L and Q can be extracted from the LFromLQ and QFromLQ methods on Dense. +func (lq *LQ) Factorize(a Matrix) { + m, n := a.Dims() + if m > n { + panic(matrix.ErrShape) + } + k := min(m, n) + if lq.lq == nil { + lq.lq = &Dense{} + } + lq.lq.Clone(a) + work := make([]float64, 1) + lq.tau = make([]float64, k) + lapack64.Gelqf(lq.lq.mat, lq.tau, work, -1) + work = make([]float64, int(work[0])) + lapack64.Gelqf(lq.lq.mat, lq.tau, work, len(work)) + lq.updateCond() +} + +// TODO(btracey): Add in the "Reduced" forms for extracting the m×m orthogonal +// and upper triangular matrices. + +// LFromLQ extracts the m×n lower trapezoidal matrix from a LQ decomposition. +func (m *Dense) LFromLQ(lq *LQ) { + r, c := lq.lq.Dims() + m.reuseAs(r, c) + + // Disguise the LQ as a lower triangular + t := &TriDense{ + mat: blas64.Triangular{ + N: r, + Stride: lq.lq.mat.Stride, + Data: lq.lq.mat.Data, + Uplo: blas.Lower, + Diag: blas.NonUnit, + }, + cap: lq.lq.capCols, + } + m.Copy(t) + + if r == c { + return + } + // Zero right of the triangular. + for i := 0; i < r; i++ { + zero(m.mat.Data[i*m.mat.Stride+r : i*m.mat.Stride+c]) + } +} + +// QFromLQ extracts the n×n orthonormal matrix Q from an LQ decomposition. +func (m *Dense) QFromLQ(lq *LQ) { + r, c := lq.lq.Dims() + m.reuseAs(c, c) + + // Set Q = I. + for i := 0; i < c; i++ { + v := m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c] + zero(v) + v[i] = 1 + } + + // Construct Q from the elementary reflectors. + h := blas64.General{ + Rows: c, + Cols: c, + Stride: c, + Data: make([]float64, c*c), + } + qCopy := getWorkspace(c, c, false) + v := blas64.Vector{ + Inc: 1, + Data: make([]float64, c), + } + for i := 0; i < r; i++ { + // Set h = I. + zero(h.Data) + for j := 0; j < len(h.Data); j += c + 1 { + h.Data[j] = 1 + } + + // Set the vector data as the elementary reflector. + for j := 0; j < i; j++ { + v.Data[j] = 0 + } + v.Data[i] = 1 + for j := i + 1; j < c; j++ { + v.Data[j] = lq.lq.mat.Data[i*lq.lq.mat.Stride+j] + } + + // Compute the multiplication matrix. + blas64.Ger(-lq.tau[i], v, v, h) + qCopy.Copy(m) + blas64.Gemm(blas.NoTrans, blas.NoTrans, + 1, h, qCopy.mat, + 0, m.mat) + } +} + +// SolveLQ finds a minimum-norm solution to a system of linear equations defined +// by the matrices A and b, where A is an m×n matrix represented in its LQ factorized +// form. If A is singular or near-singular a Condition error is returned. Please +// see the documentation for Condition for more information. +// +// The minimization problem solved depends on the input parameters. +// If trans == false, find the minimum norm solution of A * X = b. +// If trans == true, find X such that ||A*X - b||_2 is minimized. +// The solution matrix, X, is stored in place into the receiver. +func (m *Dense) SolveLQ(lq *LQ, trans bool, b Matrix) error { + r, c := lq.lq.Dims() + br, bc := b.Dims() + + // The LQ solve algorithm stores the result in-place into the right hand side. + // The storage for the answer must be large enough to hold both b and x. + // However, this method's receiver must be the size of x. Copy b, and then + // copy the result into m at the end. + if trans { + if c != br { + panic(matrix.ErrShape) + } + m.reuseAs(r, bc) + } else { + if r != br { + panic(matrix.ErrShape) + } + m.reuseAs(c, bc) + } + // Do not need to worry about overlap between m and b because x has its own + // independent storage. + x := getWorkspace(max(r, c), bc, false) + x.Copy(b) + t := lq.lq.asTriDense(lq.lq.mat.Rows, blas.NonUnit, blas.Lower).mat + if trans { + work := make([]float64, 1) + lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, x.mat, work, -1) + work = make([]float64, int(work[0])) + lapack64.Ormlq(blas.Left, blas.NoTrans, lq.lq.mat, lq.tau, x.mat, work, len(work)) + + ok := lapack64.Trtrs(blas.Trans, t, x.mat) + if !ok { + return matrix.Condition(math.Inf(1)) + } + } else { + ok := lapack64.Trtrs(blas.NoTrans, t, x.mat) + if !ok { + return matrix.Condition(math.Inf(1)) + } + for i := r; i < c; i++ { + zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc]) + } + work := make([]float64, 1) + lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, x.mat, work, -1) + work = make([]float64, int(work[0])) + lapack64.Ormlq(blas.Left, blas.Trans, lq.lq.mat, lq.tau, x.mat, work, len(work)) + } + // M was set above to be the correct size for the result. + m.Copy(x) + putWorkspace(x) + if lq.cond > matrix.ConditionTolerance { + return matrix.Condition(lq.cond) + } + return nil +} + +// SolveLQVec finds a minimum-norm solution to a system of linear equations. +// Please see Dense.SolveLQ for the full documentation. +func (v *Vector) SolveLQVec(lq *LQ, trans bool, b *Vector) error { + if v != b { + v.checkOverlap(b.mat) + } + r, c := lq.lq.Dims() + // The Solve implementation is non-trivial, so rather than duplicate the code, + // instead recast the Vectors as Dense and call the matrix code. + if trans { + v.reuseAs(r) + } else { + v.reuseAs(c) + } + return v.asDense().SolveLQ(lq, trans, b.asDense()) +} diff --git a/matrix/mat64/lq_test.go b/matrix/mat64/lq_test.go new file mode 100644 index 00000000..05478ced --- /dev/null +++ b/matrix/mat64/lq_test.go @@ -0,0 +1,180 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math/rand" + "testing" +) + +func TestLQ(t *testing.T) { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {5, 10}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + var want Dense + want.Clone(a) + + lq := &LQ{} + lq.Factorize(a) + var l, q Dense + q.QFromLQ(lq) + + if !isOrthonormal(&q, 1e-10) { + t.Errorf("Q is not orthonormal: m = %v, n = %v", m, n) + } + + l.LFromLQ(lq) + + var got Dense + got.Mul(&l, &q) + if !EqualApprox(&got, &want, 1e-12) { + t.Errorf("LQ does not equal original matrix. \nWant: %v\nGot: %v", want, got) + } + } +} + +func TestSolveLQ(t *testing.T) { + for _, trans := range []bool{false, true} { + for _, test := range []struct { + m, n, bc int + }{ + {5, 5, 1}, + {5, 10, 1}, + {5, 5, 3}, + {5, 10, 3}, + } { + m := test.m + n := test.n + bc := test.bc + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + if trans { + br = n + } + b := NewDense(br, bc, nil) + for i := 0; i < br; i++ { + for j := 0; j < bc; j++ { + b.Set(i, j, rand.Float64()) + } + } + var x Dense + lq := &LQ{} + lq.Factorize(a) + x.SolveLQ(lq, trans, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b if !trans + // A * A^T * x = A * b if trans + var lhs Dense + var rhs Dense + if trans { + var tmp Dense + tmp.Mul(a, a.T()) + lhs.Mul(&tmp, &x) + rhs.Mul(a, b) + } else { + var tmp Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + } + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + } + // TODO(btracey): Add in testOneInput when it exists. +} + +func TestSolveLQVec(t *testing.T) { + for _, trans := range []bool{false, true} { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {5, 10}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + if trans { + br = n + } + b := NewVector(br, nil) + for i := 0; i < br; i++ { + b.SetVec(i, rand.Float64()) + } + var x Vector + lq := &LQ{} + lq.Factorize(a) + x.SolveLQVec(lq, trans, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b if !trans + // A * A^T * x = A * b if trans + var lhs Dense + var rhs Dense + if trans { + var tmp Dense + tmp.Mul(a, a.T()) + lhs.Mul(&tmp, &x) + rhs.Mul(a, b) + } else { + var tmp Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + } + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + } + // TODO(btracey): Add in testOneInput when it exists. +} + +func TestSolveLQCond(t *testing.T) { + for _, test := range []*Dense{ + NewDense(2, 2, []float64{1, 0, 0, 1e-20}), + NewDense(2, 3, []float64{1, 0, 0, 0, 1e-20, 0}), + } { + m, _ := test.Dims() + var lq LQ + lq.Factorize(test) + b := NewDense(m, 2, nil) + var x Dense + if err := x.SolveLQ(&lq, false, b); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + + bvec := NewVector(m, nil) + var xvec Vector + if err := xvec.SolveLQVec(&lq, false, bvec); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + } +} diff --git a/matrix/mat64/lu.go b/matrix/mat64/lu.go new file mode 100644 index 00000000..69f2daf0 --- /dev/null +++ b/matrix/mat64/lu.go @@ -0,0 +1,340 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +const badSliceLength = "mat64: improper slice length" + +// LU is a type for creating and using the LU factorization of a matrix. +type LU struct { + lu *Dense + pivot []int + cond float64 +} + +// updateCond updates the stored condition number of the matrix. Norm is the +// norm of the original matrix. If norm is negative it will be estimated. +func (lu *LU) updateCond(norm float64) { + n := lu.lu.mat.Cols + work := make([]float64, 4*n) + iwork := make([]int, n) + if norm < 0 { + // This is an approximation. By the definition of a norm, ||AB|| <= ||A|| ||B||. + // The condition number is ||A|| || A^-1||, so this will underestimate + // the condition number somewhat. + // The norm of the original factorized matrix cannot be stored because of + // update possibilities, e.g. RankOne. + u := lu.lu.asTriDense(n, blas.NonUnit, blas.Upper) + l := lu.lu.asTriDense(n, blas.Unit, blas.Lower) + unorm := lapack64.Lantr(matrix.CondNorm, u.mat, work) + lnorm := lapack64.Lantr(matrix.CondNorm, l.mat, work) + norm = unorm * lnorm + } + v := lapack64.Gecon(matrix.CondNorm, lu.lu.mat, norm, work, iwork) + lu.cond = 1 / v +} + +// Factorize computes the LU factorization of the square matrix a and stores the +// result. The LU decomposition will complete regardless of the singularity of a. +// +// The LU factorization is computed with pivoting, and so really the decomposition +// is a PLU decomposition where P is a permutation matrix. The individual matrix +// factors can be extracted from the factorization using the Permutation method +// on Dense, and the LFrom and UFrom methods on TriDense. +func (lu *LU) Factorize(a Matrix) { + r, c := a.Dims() + if r != c { + panic(matrix.ErrSquare) + } + if lu.lu == nil { + lu.lu = NewDense(r, r, nil) + } else { + lu.lu.Reset() + lu.lu.reuseAs(r, r) + } + lu.lu.Copy(a) + if cap(lu.pivot) < r { + lu.pivot = make([]int, r) + } + lu.pivot = lu.pivot[:r] + work := make([]float64, r) + anorm := lapack64.Lange(matrix.CondNorm, lu.lu.mat, work) + lapack64.Getrf(lu.lu.mat, lu.pivot) + lu.updateCond(anorm) +} + +// Reset resets the factorization so that it can be reused as the receiver of a +// dimensionally restricted operation. +func (lu *LU) Reset() { + if lu.lu != nil { + lu.lu.Reset() + } + lu.pivot = lu.pivot[:0] +} + +func (lu *LU) isZero() bool { + return len(lu.pivot) == 0 +} + +// Det returns the determinant of the matrix that has been factorized. In many +// expressions, using LogDet will be more numerically stable. +func (lu *LU) Det() float64 { + det, sign := lu.LogDet() + return math.Exp(det) * sign +} + +// LogDet returns the log of the determinant and the sign of the determinant +// for the matrix that has been factorized. Numerical stability in product and +// division expressions is generally improved by working in log space. +func (lu *LU) LogDet() (det float64, sign float64) { + _, n := lu.lu.Dims() + logDiag := make([]float64, n) + sign = 1.0 + for i := 0; i < n; i++ { + v := lu.lu.at(i, i) + if v < 0 { + sign *= -1 + } + if lu.pivot[i] != i { + sign *= -1 + } + logDiag[i] = math.Log(math.Abs(v)) + } + return floats.Sum(logDiag), sign +} + +// Pivot returns pivot indices that enable the construction of the permutation +// matrix P (see Dense.Permutation). If swaps == nil, then new memory will be +// allocated, otherwise the length of the input must be equal to the size of the +// factorized matrix. +func (lu *LU) Pivot(swaps []int) []int { + _, n := lu.lu.Dims() + if swaps == nil { + swaps = make([]int, n) + } + if len(swaps) != n { + panic(badSliceLength) + } + // Perform the inverse of the row swaps in order to find the final + // row swap position. + for i := range swaps { + swaps[i] = i + } + for i := n - 1; i >= 0; i-- { + v := lu.pivot[i] + swaps[i], swaps[v] = swaps[v], swaps[i] + } + return swaps +} + +// RankOne updates an LU factorization as if a rank-one update had been applied to +// the original matrix A, storing the result into the receiver. That is, if in +// the original LU decomposition P * L * U = A, in the updated decomposition +// P * L * U = A + alpha * x * y^T. +func (lu *LU) RankOne(orig *LU, alpha float64, x, y *Vector) { + // RankOne uses algorithm a1 on page 28 of "Multiple-Rank Updates to Matrix + // Factorizations for Nonlinear Analysis and Circuit Design" by Linzhong Deng. + // http://web.stanford.edu/group/SOL/dissertations/Linzhong-Deng-thesis.pdf + _, n := orig.lu.Dims() + if x.Len() != n { + panic(matrix.ErrShape) + } + if y.Len() != n { + panic(matrix.ErrShape) + } + if orig != lu { + if lu.isZero() { + if cap(lu.pivot) < n { + lu.pivot = make([]int, n) + } + lu.pivot = lu.pivot[:n] + if lu.lu == nil { + lu.lu = NewDense(n, n, nil) + } else { + lu.lu.reuseAs(n, n) + } + } else if len(lu.pivot) != n { + panic(matrix.ErrShape) + } + copy(lu.pivot, orig.pivot) + lu.lu.Copy(orig.lu) + } + + xs := make([]float64, n) + ys := make([]float64, n) + for i := 0; i < n; i++ { + xs[i] = x.at(i) + ys[i] = y.at(i) + } + + // Adjust for the pivoting in the LU factorization + for i, v := range lu.pivot { + xs[i], xs[v] = xs[v], xs[i] + } + + lum := lu.lu.mat + omega := alpha + for j := 0; j < n; j++ { + ujj := lum.Data[j*lum.Stride+j] + ys[j] /= ujj + theta := 1 + xs[j]*ys[j]*omega + beta := omega * ys[j] / theta + gamma := omega * xs[j] + omega -= beta * gamma + lum.Data[j*lum.Stride+j] *= theta + for i := j + 1; i < n; i++ { + xs[i] -= lum.Data[i*lum.Stride+j] * xs[j] + tmp := ys[i] + ys[i] -= lum.Data[j*lum.Stride+i] * ys[j] + lum.Data[i*lum.Stride+j] += beta * xs[i] + lum.Data[j*lum.Stride+i] += gamma * tmp + } + } + lu.updateCond(-1) +} + +// LFromLU extracts the lower triangular matrix from an LU factorization. +func (t *TriDense) LFromLU(lu *LU) { + _, n := lu.lu.Dims() + t.reuseAs(n, false) + // Extract the lower triangular elements. + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + t.mat.Data[i*t.mat.Stride+j] = lu.lu.mat.Data[i*lu.lu.mat.Stride+j] + } + } + // Set ones on the diagonal. + for i := 0; i < n; i++ { + t.mat.Data[i*t.mat.Stride+i] = 1 + } +} + +// UFromLU extracts the upper triangular matrix from an LU factorization. +func (t *TriDense) UFromLU(lu *LU) { + _, n := lu.lu.Dims() + t.reuseAs(n, true) + // Extract the upper triangular elements. + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + t.mat.Data[i*t.mat.Stride+j] = lu.lu.mat.Data[i*lu.lu.mat.Stride+j] + } + } +} + +// Permutation constructs an r×r permutation matrix with the given row swaps. +// A permutation matrix has exactly one element equal to one in each row and column +// and all other elements equal to zero. swaps[i] specifies the row with which +// i will be swapped, which is equivalent to the non-zero column of row i. +func (m *Dense) Permutation(r int, swaps []int) { + m.reuseAs(r, r) + for i := 0; i < r; i++ { + zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+r]) + v := swaps[i] + if v < 0 || v >= r { + panic(matrix.ErrRowAccess) + } + m.mat.Data[i*m.mat.Stride+v] = 1 + } +} + +// SolveLU solves a system of linear equations using the LU decomposition of a matrix. +// It computes +// A * x = b if trans == false +// A^T * x = b if trans == true +// In both cases, A is represented in LU factorized form, and the matrix x is +// stored into the receiver. +// +// If A is singular or near-singular a Condition error is returned. Please see +// the documentation for Condition for more information. +func (m *Dense) SolveLU(lu *LU, trans bool, b Matrix) error { + _, n := lu.lu.Dims() + br, bc := b.Dims() + if br != n { + panic(matrix.ErrShape) + } + // TODO(btracey): Should test the condition number instead of testing that + // the determinant is exactly zero. + if lu.Det() == 0 { + return matrix.Condition(math.Inf(1)) + } + + m.reuseAs(n, bc) + bU, _ := untranspose(b) + var restore func() + if m == bU { + m, restore = m.isolatedWorkspace(bU) + defer restore() + } else if rm, ok := bU.(RawMatrixer); ok { + m.checkOverlap(rm.RawMatrix()) + } + + m.Copy(b) + t := blas.NoTrans + if trans { + t = blas.Trans + } + lapack64.Getrs(t, lu.lu.mat, m.mat, lu.pivot) + if lu.cond > matrix.ConditionTolerance { + return matrix.Condition(lu.cond) + } + return nil +} + +// SolveLUVec solves a system of linear equations using the LU decomposition of a matrix. +// It computes +// A * x = b if trans == false +// A^T * x = b if trans == true +// In both cases, A is represented in LU factorized form, and the matrix x is +// stored into the receiver. +// +// If A is singular or near-singular a Condition error is returned. Please see +// the documentation for Condition for more information. +func (v *Vector) SolveLUVec(lu *LU, trans bool, b *Vector) error { + _, n := lu.lu.Dims() + bn := b.Len() + if bn != n { + panic(matrix.ErrShape) + } + if v != b { + v.checkOverlap(b.mat) + } + // TODO(btracey): Should test the condition number instead of testing that + // the determinant is exactly zero. + if lu.Det() == 0 { + return matrix.Condition(math.Inf(1)) + } + + v.reuseAs(n) + var restore func() + if v == b { + v, restore = v.isolatedWorkspace(b) + defer restore() + } + v.CopyVec(b) + vMat := blas64.General{ + Rows: n, + Cols: 1, + Stride: v.mat.Inc, + Data: v.mat.Data, + } + t := blas.NoTrans + if trans { + t = blas.Trans + } + lapack64.Getrs(t, lu.lu.mat, vMat, lu.pivot) + if lu.cond > matrix.ConditionTolerance { + return matrix.Condition(lu.cond) + } + return nil +} diff --git a/matrix/mat64/lu_test.go b/matrix/mat64/lu_test.go new file mode 100644 index 00000000..ed7dd6df --- /dev/null +++ b/matrix/mat64/lu_test.go @@ -0,0 +1,191 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math/rand" + "testing" +) + +func TestLUD(t *testing.T) { + for _, n := range []int{1, 5, 10, 11, 50} { + a := NewDense(n, n, nil) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + var want Dense + want.Clone(a) + + lu := &LU{} + lu.Factorize(a) + + var l, u TriDense + l.LFromLU(lu) + u.UFromLU(lu) + var p Dense + pivot := lu.Pivot(nil) + p.Permutation(n, pivot) + var got Dense + got.Mul(&p, &l) + got.Mul(&got, &u) + if !EqualApprox(&got, &want, 1e-12) { + t.Errorf("PLU does not equal original matrix.\nWant: %v\n Got: %v", want, got) + } + } +} + +func TestLURankOne(t *testing.T) { + for _, pivoting := range []bool{true} { + for _, n := range []int{3, 10, 50} { + // Construct a random LU factorization + lu := &LU{} + lu.lu = NewDense(n, n, nil) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + lu.lu.Set(i, j, rand.Float64()) + } + } + lu.pivot = make([]int, n) + for i := range lu.pivot { + lu.pivot[i] = i + } + if pivoting { + // For each row, randomly swap with itself or a row after (like is done) + // in the actual LU factorization. + for i := range lu.pivot { + idx := i + rand.Intn(n-i) + lu.pivot[i], lu.pivot[idx] = lu.pivot[idx], lu.pivot[i] + } + } + // Apply a rank one update. Ensure the update magnitude is larger than + // the equal tolerance. + alpha := rand.Float64() + 1 + x := NewVector(n, nil) + y := NewVector(n, nil) + for i := 0; i < n; i++ { + x.setVec(i, rand.Float64()+1) + y.setVec(i, rand.Float64()+1) + } + a := luReconstruct(lu) + a.RankOne(a, alpha, x, y) + + var luNew LU + luNew.RankOne(lu, alpha, x, y) + lu.RankOne(lu, alpha, x, y) + + aR1New := luReconstruct(&luNew) + aR1 := luReconstruct(lu) + + if !Equal(aR1, aR1New) { + t.Error("Different answer when new receiver") + } + if !EqualApprox(aR1, a, 1e-10) { + t.Errorf("Rank one mismatch, pivot %v.\nWant: %v\nGot:%v\n", pivoting, a, aR1) + } + } + } +} + +// luReconstruct reconstructs the original A matrix from an LU decomposition. +func luReconstruct(lu *LU) *Dense { + var L, U TriDense + L.LFromLU(lu) + U.UFromLU(lu) + var P Dense + pivot := lu.Pivot(nil) + P.Permutation(len(pivot), pivot) + + var a Dense + a.Mul(&L, &U) + a.Mul(&P, &a) + return &a +} + +func TestSolveLU(t *testing.T) { + for _, test := range []struct { + n, bc int + }{ + {5, 5}, + {5, 10}, + {10, 5}, + } { + n := test.n + bc := test.bc + a := NewDense(n, n, nil) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + b := NewDense(n, bc, nil) + for i := 0; i < n; i++ { + for j := 0; j < bc; j++ { + b.Set(i, j, rand.NormFloat64()) + } + } + var lu LU + lu.Factorize(a) + var x Dense + if err := x.SolveLU(&lu, false, b); err != nil { + continue + } + var got Dense + got.Mul(a, &x) + if !EqualApprox(&got, b, 1e-12) { + t.Errorf("Solve mismatch for non-singular matrix. n = %v, bc = %v.\nWant: %v\nGot: %v", n, bc, b, got) + } + } + // TODO(btracey): Add testOneInput test when such a function exists. +} + +func TestSolveLUCond(t *testing.T) { + for _, test := range []*Dense{ + NewDense(2, 2, []float64{1, 0, 0, 1e-20}), + } { + m, _ := test.Dims() + var lu LU + lu.Factorize(test) + b := NewDense(m, 2, nil) + var x Dense + if err := x.SolveLU(&lu, false, b); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + + bvec := NewVector(m, nil) + var xvec Vector + if err := xvec.SolveLUVec(&lu, false, bvec); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + } +} + +func TestSolveLUVec(t *testing.T) { + for _, n := range []int{5, 10} { + a := NewDense(n, n, nil) + for i := 0; i < n; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + b := NewVector(n, nil) + for i := 0; i < n; i++ { + b.SetVec(i, rand.NormFloat64()) + } + var lu LU + lu.Factorize(a) + var x Vector + if err := x.SolveLUVec(&lu, false, b); err != nil { + continue + } + var got Vector + got.MulVec(a, &x) + if !EqualApprox(&got, b, 1e-12) { + t.Errorf("Solve mismatch n = %v.\nWant: %v\nGot: %v", n, b, got) + } + } + // TODO(btracey): Add testOneInput test when such a function exists. +} diff --git a/matrix/mat64/matrix.go b/matrix/mat64/matrix.go new file mode 100644 index 00000000..54d87d92 --- /dev/null +++ b/matrix/mat64/matrix.go @@ -0,0 +1,894 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +// Matrix is the basic matrix interface type. +type Matrix interface { + // Dims returns the dimensions of a Matrix. + Dims() (r, c int) + + // At returns the value of a matrix element at row i, column j. + // It will panic if i or j are out of bounds for the matrix. + At(i, j int) float64 + + // T returns the transpose of the Matrix. Whether T returns a copy of the + // underlying data is implementation dependent. + // This method may be implemented using the Transpose type, which + // provides an implicit matrix transpose. + T() Matrix +} + +var ( + _ Matrix = Transpose{} + _ Untransposer = Transpose{} +) + +// Transpose is a type for performing an implicit matrix transpose. It implements +// the Matrix interface, returning values from the transpose of the matrix within. +type Transpose struct { + Matrix Matrix +} + +// At returns the value of the element at row i and column j of the transposed +// matrix, that is, row j and column i of the Matrix field. +func (t Transpose) At(i, j int) float64 { + return t.Matrix.At(j, i) +} + +// Dims returns the dimensions of the transposed matrix. The number of rows returned +// is the number of columns in the Matrix field, and the number of columns is +// the number of rows in the Matrix field. +func (t Transpose) Dims() (r, c int) { + c, r = t.Matrix.Dims() + return r, c +} + +// T performs an implicit transpose by returning the Matrix field. +func (t Transpose) T() Matrix { + return t.Matrix +} + +// Untranspose returns the Matrix field. +func (t Transpose) Untranspose() Matrix { + return t.Matrix +} + +// Untransposer is a type that can undo an implicit transpose. +type Untransposer interface { + // Note: This interface is needed to unify all of the Transpose types. In + // the mat64 methods, we need to test if the Matrix has been implicitly + // transposed. If this is checked by testing for the specific Transpose type + // then the behavior will be different if the user uses T() or TTri() for a + // triangular matrix. + + // Untranspose returns the underlying Matrix stored for the implicit transpose. + Untranspose() Matrix +} + +// UntransposeTrier is a type that can undo an implicit triangular transpose. +type UntransposeTrier interface { + // Untranspose returns the underlying Triangular stored for the implicit transpose. + UntransposeTri() Triangular +} + +// Mutable is a matrix interface type that allows elements to be altered. +type Mutable interface { + // Set alters the matrix element at row i, column j to v. + // It will panic if i or j are out of bounds for the matrix. + Set(i, j int, v float64) + + Matrix +} + +// A RowViewer can return a Vector reflecting a row that is backed by the matrix +// data. The Vector returned will have length equal to the number of columns. +type RowViewer interface { + RowView(i int) *Vector +} + +// A RawRowViewer can return a slice of float64 reflecting a row that is backed by the matrix +// data. +type RawRowViewer interface { + RawRowView(i int) []float64 +} + +// A ColViewer can return a Vector reflecting a column that is backed by the matrix +// data. The Vector returned will have length equal to the number of rows. +type ColViewer interface { + ColView(j int) *Vector +} + +// A RawColViewer can return a slice of float64 reflecting a column that is backed by the matrix +// data. +type RawColViewer interface { + RawColView(j int) []float64 +} + +// A Cloner can make a copy of a into the receiver, overwriting the previous value of the +// receiver. The clone operation does not make any restriction on shape and will not cause +// shadowing. +type Cloner interface { + Clone(a Matrix) +} + +// A Reseter can reset the matrix so that it can be reused as the receiver of a dimensionally +// restricted operation. This is commonly used when the matrix is being used as a workspace +// or temporary matrix. +// +// If the matrix is a view, using the reset matrix may result in data corruption in elements +// outside the view. +type Reseter interface { + Reset() +} + +// A Copier can make a copy of elements of a into the receiver. The submatrix copied +// starts at row and column 0 and has dimensions equal to the minimum dimensions of +// the two matrices. The number of row and columns copied is returned. +// Copy will copy from a source that aliases the receiver unless the source is transposed; +// an aliasing transpose copy will panic with the exception for a special case when +// the source data has a unitary increment or stride. +type Copier interface { + Copy(a Matrix) (r, c int) +} + +// A Viewer returns a submatrix view of the Matrix parameter, starting at row i, column j +// and extending r rows and c columns. If i or j are out of range, or r or c are zero or +// extend beyond the bounds of the matrix View will panic with ErrIndexOutOfRange. The +// returned matrix must retain the receiver's reference to the original matrix such that +// changes in the elements of the submatrix are reflected in the original and vice versa. +type Viewer interface { + View(i, j, r, c int) Matrix +} + +// A Grower can grow the size of the represented matrix by the given number of rows and columns. +// Growing beyond the size given by the Caps method will result in the allocation of a new +// matrix and copying of the elements. If Grow is called with negative increments it will +// panic with ErrIndexOutOfRange. +type Grower interface { + Caps() (r, c int) + Grow(r, c int) Matrix +} + +// A BandWidther represents a banded matrix and can return the left and right half-bandwidths, k1 and +// k2. +type BandWidther interface { + BandWidth() (k1, k2 int) +} + +// A RawMatrixSetter can set the underlying blas64.General used by the receiver. There is no restriction +// on the shape of the receiver. Changes to the receiver's elements will be reflected in the blas64.General.Data. +type RawMatrixSetter interface { + SetRawMatrix(a blas64.General) +} + +// A RawMatrixer can return a blas64.General representation of the receiver. Changes to the blas64.General.Data +// slice will be reflected in the original matrix, changes to the Rows, Cols and Stride fields will not. +type RawMatrixer interface { + RawMatrix() blas64.General +} + +// A RawVectorer can return a blas64.Vector representation of the receiver. Changes to the blas64.Vector.Data +// slice will be reflected in the original matrix, changes to the Inc field will not. +type RawVectorer interface { + RawVector() blas64.Vector +} + +// TODO(btracey): Consider adding CopyCol/CopyRow if the behavior seems useful. +// TODO(btracey): Add in fast paths to Row/Col for the other concrete types +// (TriDense, etc.) as well as relevant interfaces (RowColer, RawRowViewer, etc.) + +// Col copies the elements in the jth column of the matrix into the slice dst. +// The length of the provided slice must equal the number of rows, unless the +// slice is nil in which case a new slice is first allocated. +func Col(dst []float64, j int, a Matrix) []float64 { + r, c := a.Dims() + if j < 0 || j >= c { + panic(matrix.ErrColAccess) + } + if dst == nil { + dst = make([]float64, r) + } else { + if len(dst) != r { + panic(matrix.ErrColLength) + } + } + aU, aTrans := untranspose(a) + if rm, ok := aU.(RawMatrixer); ok { + m := rm.RawMatrix() + if aTrans { + copy(dst, m.Data[j*m.Stride:j*m.Stride+m.Cols]) + return dst + } + blas64.Copy(r, + blas64.Vector{Inc: m.Stride, Data: m.Data[j:]}, + blas64.Vector{Inc: 1, Data: dst}, + ) + return dst + } + for i := 0; i < r; i++ { + dst[i] = a.At(i, j) + } + return dst +} + +// Row copies the elements in the jth column of the matrix into the slice dst. +// The length of the provided slice must equal the number of columns, unless the +// slice is nil in which case a new slice is first allocated. +func Row(dst []float64, i int, a Matrix) []float64 { + r, c := a.Dims() + if i < 0 || i >= r { + panic(matrix.ErrColAccess) + } + if dst == nil { + dst = make([]float64, c) + } else { + if len(dst) != c { + panic(matrix.ErrRowLength) + } + } + aU, aTrans := untranspose(a) + if rm, ok := aU.(RawMatrixer); ok { + m := rm.RawMatrix() + if aTrans { + blas64.Copy(c, + blas64.Vector{Inc: m.Stride, Data: m.Data[i:]}, + blas64.Vector{Inc: 1, Data: dst}, + ) + return dst + } + copy(dst, m.Data[i*m.Stride:i*m.Stride+m.Cols]) + return dst + } + for j := 0; j < c; j++ { + dst[j] = a.At(i, j) + } + return dst +} + +// Cond returns the condition number of the given matrix under the given norm. +// The condition number must be based on the 1-norm, 2-norm or ∞-norm. +// Cond will panic with matrix.ErrShape if the matrix has zero size. +// +// BUG(btracey): The computation of the 1-norm and ∞-norm for non-square matrices +// is innacurate, although is typically the right order of magnitude. See +// https://github.com/xianyi/OpenBLAS/issues/636. While the value returned will +// change with the resolution of this bug, the result from Cond will match the +// condition number used internally. +func Cond(a Matrix, norm float64) float64 { + m, n := a.Dims() + if m == 0 || n == 0 { + panic(matrix.ErrShape) + } + var lnorm lapack.MatrixNorm + switch norm { + default: + panic("mat64: bad norm value") + case 1: + lnorm = lapack.MaxColumnSum + case 2: + var svd SVD + ok := svd.Factorize(a, matrix.SVDNone) + if !ok { + return math.Inf(1) + } + return svd.Cond() + case math.Inf(1): + lnorm = lapack.MaxRowSum + } + if m == n { + // Use the LU decomposition to compute the condition number. + tmp := getWorkspace(m, n, false) + tmp.Copy(a) + work := make([]float64, 4*n) + aNorm := lapack64.Lange(lnorm, tmp.mat, work) + pivot := make([]int, m) + lapack64.Getrf(tmp.mat, pivot) + iwork := make([]int, n) + v := lapack64.Gecon(lnorm, tmp.mat, aNorm, work, iwork) + putWorkspace(tmp) + return 1 / v + } + if m > n { + // Use the QR factorization to compute the condition number. + tmp := getWorkspace(m, n, false) + tmp.Copy(a) + work := make([]float64, 3*n) + tau := make([]float64, min(m, n)) + lapack64.Geqrf(tmp.mat, tau, work, -1) + if int(work[0]) > len(work) { + work = make([]float64, int(work[0])) + } + lapack64.Geqrf(tmp.mat, tau, work, len(work)) + + iwork := make([]int, n) + r := tmp.asTriDense(n, blas.NonUnit, blas.Upper) + v := lapack64.Trcon(lnorm, r.mat, work, iwork) + putWorkspace(tmp) + return 1 / v + } + // Use the LQ factorization to compute the condition number. + tmp := getWorkspace(m, n, false) + tmp.Copy(a) + work := make([]float64, 3*m) + tau := make([]float64, min(m, n)) + lapack64.Gelqf(tmp.mat, tau, work, -1) + if int(work[0]) > len(work) { + work = make([]float64, int(work[0])) + } + lapack64.Gelqf(tmp.mat, tau, work, len(work)) + + iwork := make([]int, m) + l := tmp.asTriDense(m, blas.NonUnit, blas.Lower) + v := lapack64.Trcon(lnorm, l.mat, work, iwork) + putWorkspace(tmp) + return 1 / v +} + +// Det returns the determinant of the matrix a. In many expressions using LogDet +// will be more numerically stable. +func Det(a Matrix) float64 { + det, sign := LogDet(a) + return math.Exp(det) * sign +} + +// Dot returns the sum of the element-wise product of a and b. +// Dot panics if the matrix sizes are unequal. +func Dot(a, b *Vector) float64 { + la := a.Len() + lb := b.Len() + if la != lb { + panic(matrix.ErrShape) + } + return blas64.Dot(la, a.mat, b.mat) +} + +// Equal returns whether the matrices a and b have the same size +// and are element-wise equal. +func Equal(a, b Matrix) bool { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + return false + } + aU, aTrans := untranspose(a) + bU, bTrans := untranspose(b) + if rma, ok := aU.(RawMatrixer); ok { + if rmb, ok := bU.(RawMatrixer); ok { + ra := rma.RawMatrix() + rb := rmb.RawMatrix() + if aTrans == bTrans { + for i := 0; i < ra.Rows; i++ { + for j := 0; j < ra.Cols; j++ { + if ra.Data[i*ra.Stride+j] != rb.Data[i*rb.Stride+j] { + return false + } + } + } + return true + } + for i := 0; i < ra.Rows; i++ { + for j := 0; j < ra.Cols; j++ { + if ra.Data[i*ra.Stride+j] != rb.Data[j*rb.Stride+i] { + return false + } + } + } + return true + } + } + if rma, ok := aU.(RawSymmetricer); ok { + if rmb, ok := bU.(RawSymmetricer); ok { + ra := rma.RawSymmetric() + rb := rmb.RawSymmetric() + // Symmetric matrices are always upper and equal to their transpose. + for i := 0; i < ra.N; i++ { + for j := i; j < ra.N; j++ { + if ra.Data[i*ra.Stride+j] != rb.Data[i*rb.Stride+j] { + return false + } + } + } + return true + } + } + if ra, ok := aU.(*Vector); ok { + if rb, ok := bU.(*Vector); ok { + // If the raw vectors are the same length they must either both be + // transposed or both not transposed (or have length 1). + for i := 0; i < ra.n; i++ { + if ra.mat.Data[i*ra.mat.Inc] != rb.mat.Data[i*rb.mat.Inc] { + return false + } + } + return true + } + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if a.At(i, j) != b.At(i, j) { + return false + } + } + } + return true +} + +// EqualApprox returns whether the matrices a and b have the same size and contain all equal +// elements with tolerance for element-wise equality specified by epsilon. Matrices +// with non-equal shapes are not equal. +func EqualApprox(a, b Matrix, epsilon float64) bool { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + return false + } + aU, aTrans := untranspose(a) + bU, bTrans := untranspose(b) + if rma, ok := aU.(RawMatrixer); ok { + if rmb, ok := bU.(RawMatrixer); ok { + ra := rma.RawMatrix() + rb := rmb.RawMatrix() + if aTrans == bTrans { + for i := 0; i < ra.Rows; i++ { + for j := 0; j < ra.Cols; j++ { + if !floats.EqualWithinAbsOrRel(ra.Data[i*ra.Stride+j], rb.Data[i*rb.Stride+j], epsilon, epsilon) { + return false + } + } + } + return true + } + for i := 0; i < ra.Rows; i++ { + for j := 0; j < ra.Cols; j++ { + if !floats.EqualWithinAbsOrRel(ra.Data[i*ra.Stride+j], rb.Data[j*rb.Stride+i], epsilon, epsilon) { + return false + } + } + } + return true + } + } + if rma, ok := aU.(RawSymmetricer); ok { + if rmb, ok := bU.(RawSymmetricer); ok { + ra := rma.RawSymmetric() + rb := rmb.RawSymmetric() + // Symmetric matrices are always upper and equal to their transpose. + for i := 0; i < ra.N; i++ { + for j := i; j < ra.N; j++ { + if !floats.EqualWithinAbsOrRel(ra.Data[i*ra.Stride+j], rb.Data[i*rb.Stride+j], epsilon, epsilon) { + return false + } + } + } + return true + } + } + if ra, ok := aU.(*Vector); ok { + if rb, ok := bU.(*Vector); ok { + // If the raw vectors are the same length they must either both be + // transposed or both not transposed (or have length 1). + for i := 0; i < ra.n; i++ { + if !floats.EqualWithinAbsOrRel(ra.mat.Data[i*ra.mat.Inc], rb.mat.Data[i*rb.mat.Inc], epsilon, epsilon) { + return false + } + } + return true + } + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if !floats.EqualWithinAbsOrRel(a.At(i, j), b.At(i, j), epsilon, epsilon) { + return false + } + } + } + return true +} + +// LogDet returns the log of the determinant and the sign of the determinant +// for the matrix that has been factorized. Numerical stability in product and +// division expressions is generally improved by working in log space. +func LogDet(a Matrix) (det float64, sign float64) { + // TODO(btracey): Add specialized routines for TriDense, etc. + var lu LU + lu.Factorize(a) + return lu.LogDet() +} + +// Max returns the largest element value of the matrix A. +// Max will panic with matrix.ErrShape if the matrix has zero size. +func Max(a Matrix) float64 { + r, c := a.Dims() + if r == 0 || c == 0 { + panic(matrix.ErrShape) + } + // Max(A) = Max(A^T) + aU, _ := untranspose(a) + switch m := aU.(type) { + case RawMatrixer: + rm := m.RawMatrix() + max := math.Inf(-1) + for i := 0; i < rm.Rows; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] { + if v > max { + max = v + } + } + } + return max + case RawTriangular: + rm := m.RawTriangular() + // The max of a triangular is at least 0 unless the size is 1. + if rm.N == 1 { + return rm.Data[0] + } + max := 0.0 + if rm.Uplo == blas.Upper { + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { + if v > max { + max = v + } + } + } + return max + } + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+i+1] { + if v > max { + max = v + } + } + } + return max + case RawSymmetricer: + rm := m.RawSymmetric() + if rm.Uplo != blas.Upper { + panic(badSymTriangle) + } + max := math.Inf(-1) + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { + if v > max { + max = v + } + } + } + return max + default: + r, c := aU.Dims() + max := math.Inf(-1) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + v := aU.At(i, j) + if v > max { + max = v + } + } + } + return max + } +} + +// Min returns the smallest element value of the matrix A. +// Min will panic with matrix.ErrShape if the matrix has zero size. +func Min(a Matrix) float64 { + r, c := a.Dims() + if r == 0 || c == 0 { + panic(matrix.ErrShape) + } + // Min(A) = Min(A^T) + aU, _ := untranspose(a) + switch m := aU.(type) { + case RawMatrixer: + rm := m.RawMatrix() + min := math.Inf(1) + for i := 0; i < rm.Rows; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] { + if v < min { + min = v + } + } + } + return min + case RawTriangular: + rm := m.RawTriangular() + // The min of a triangular is at most 0 unless the size is 1. + if rm.N == 1 { + return rm.Data[0] + } + min := 0.0 + if rm.Uplo == blas.Upper { + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { + if v < min { + min = v + } + } + } + return min + } + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+i+1] { + if v < min { + min = v + } + } + } + return min + case RawSymmetricer: + rm := m.RawSymmetric() + if rm.Uplo != blas.Upper { + panic(badSymTriangle) + } + min := math.Inf(1) + for i := 0; i < rm.N; i++ { + for _, v := range rm.Data[i*rm.Stride+i : i*rm.Stride+rm.N] { + if v < min { + min = v + } + } + } + return min + default: + r, c := aU.Dims() + min := math.Inf(1) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + v := aU.At(i, j) + if v < min { + min = v + } + } + } + return min + } +} + +// Norm returns the specified (induced) norm of the matrix a. See +// https://en.wikipedia.org/wiki/Matrix_norm for the definition of an induced norm. +// +// Valid norms are: +// 1 - The maximum absolute column sum +// 2 - Frobenius norm, the square root of the sum of the squares of the elements. +// Inf - The maximum absolute row sum. +// Norm will panic with ErrNormOrder if an illegal norm order is specified and +// with matrix.ErrShape if the matrix has zero size. +func Norm(a Matrix, norm float64) float64 { + r, c := a.Dims() + if r == 0 || c == 0 { + panic(matrix.ErrShape) + } + aU, aTrans := untranspose(a) + var work []float64 + switch rma := aU.(type) { + case RawMatrixer: + rm := rma.RawMatrix() + n := normLapack(norm, aTrans) + if n == lapack.MaxColumnSum { + work = make([]float64, rm.Cols) + } + return lapack64.Lange(n, rm, work) + case RawTriangular: + rm := rma.RawTriangular() + n := normLapack(norm, aTrans) + if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { + work = make([]float64, rm.N) + } + return lapack64.Lantr(n, rm, work) + case RawSymmetricer: + rm := rma.RawSymmetric() + n := normLapack(norm, aTrans) + if n == lapack.MaxRowSum || n == lapack.MaxColumnSum { + work = make([]float64, rm.N) + } + return lapack64.Lansy(n, rm, work) + case *Vector: + rv := rma.RawVector() + switch norm { + default: + panic("unreachable") + case 1: + if aTrans { + imax := blas64.Iamax(rma.n, rv) + return math.Abs(rma.At(imax, 0)) + } + return blas64.Asum(rma.n, rv) + case 2: + return blas64.Nrm2(rma.n, rv) + case math.Inf(1): + if aTrans { + return blas64.Asum(rma.n, rv) + } + imax := blas64.Iamax(rma.n, rv) + return math.Abs(rma.At(imax, 0)) + } + } + switch norm { + default: + panic("unreachable") + case 1: + var max float64 + for j := 0; j < c; j++ { + var sum float64 + for i := 0; i < r; i++ { + sum += math.Abs(a.At(i, j)) + } + if sum > max { + max = sum + } + } + return max + case 2: + var sum float64 + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + v := a.At(i, j) + sum += v * v + } + } + return math.Sqrt(sum) + case math.Inf(1): + var max float64 + for i := 0; i < r; i++ { + var sum float64 + for j := 0; j < c; j++ { + sum += math.Abs(a.At(i, j)) + } + if sum > max { + max = sum + } + } + return max + } +} + +// normLapack converts the float64 norm input in Norm to a lapack.MatrixNorm. +func normLapack(norm float64, aTrans bool) lapack.MatrixNorm { + switch norm { + case 1: + n := lapack.MaxColumnSum + if aTrans { + n = lapack.MaxRowSum + } + return n + case 2: + return lapack.NormFrob + case math.Inf(1): + n := lapack.MaxRowSum + if aTrans { + n = lapack.MaxColumnSum + } + return n + default: + panic(matrix.ErrNormOrder) + } +} + +// Sum returns the sum of the elements of the matrix. +func Sum(a Matrix) float64 { + // TODO(btracey): Add a fast path for the other supported matrix types. + + r, c := a.Dims() + var sum float64 + aU, _ := untranspose(a) + if rma, ok := aU.(RawMatrixer); ok { + rm := rma.RawMatrix() + for i := 0; i < rm.Rows; i++ { + for _, v := range rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] { + sum += v + } + } + return sum + } + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + sum += a.At(i, j) + } + } + return sum +} + +// Trace returns the trace of the matrix. Trace will panic if the +// matrix is not square. +func Trace(a Matrix) float64 { + r, c := a.Dims() + if r != c { + panic(matrix.ErrSquare) + } + + aU, _ := untranspose(a) + switch m := aU.(type) { + case RawMatrixer: + rm := m.RawMatrix() + var t float64 + for i := 0; i < r; i++ { + t += rm.Data[i*rm.Stride+i] + } + return t + case RawTriangular: + rm := m.RawTriangular() + var t float64 + for i := 0; i < r; i++ { + t += rm.Data[i*rm.Stride+i] + } + return t + case RawSymmetricer: + rm := m.RawSymmetric() + var t float64 + for i := 0; i < r; i++ { + t += rm.Data[i*rm.Stride+i] + } + return t + default: + var t float64 + for i := 0; i < r; i++ { + t += a.At(i, i) + } + return t + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +// use returns a float64 slice with l elements, using f if it +// has the necessary capacity, otherwise creating a new slice. +func use(f []float64, l int) []float64 { + if l <= cap(f) { + return f[:l] + } + return make([]float64, l) +} + +// useZeroed returns a float64 slice with l elements, using f if it +// has the necessary capacity, otherwise creating a new slice. The +// elements of the returned slice are guaranteed to be zero. +func useZeroed(f []float64, l int) []float64 { + if l <= cap(f) { + f = f[:l] + zero(f) + return f + } + return make([]float64, l) +} + +// zero zeros the given slice's elements. +func zero(f []float64) { + for i := range f { + f[i] = 0 + } +} + +// useInt returns an int slice with l elements, using i if it +// has the necessary capacity, otherwise creating a new slice. +func useInt(i []int, l int) []int { + if l <= cap(i) { + return i[:l] + } + return make([]int, l) +} diff --git a/matrix/mat64/matrix_test.go b/matrix/mat64/matrix_test.go new file mode 100644 index 00000000..35ea4abf --- /dev/null +++ b/matrix/mat64/matrix_test.go @@ -0,0 +1,524 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "fmt" + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix" +) + +func panics(fn func()) (panicked bool, message string) { + defer func() { + r := recover() + panicked = r != nil + message = fmt.Sprint(r) + }() + fn() + return +} + +func flatten(f [][]float64) (r, c int, d []float64) { + r = len(f) + if r == 0 { + panic("bad test: no row") + } + c = len(f[0]) + d = make([]float64, 0, r*c) + for _, row := range f { + if len(row) != c { + panic("bad test: ragged input") + } + d = append(d, row...) + } + return r, c, d +} + +func unflatten(r, c int, d []float64) [][]float64 { + m := make([][]float64, r) + for i := 0; i < r; i++ { + m[i] = d[i*c : (i+1)*c] + } + return m +} + +// eye returns a new identity matrix of size n×n. +func eye(n int) *Dense { + d := make([]float64, n*n) + for i := 0; i < n*n; i += n + 1 { + d[i] = 1 + } + return NewDense(n, n, d) +} + +func TestCol(t *testing.T) { + for id, af := range [][][]float64{ + { + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + }, + { + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + {10, 11, 12}, + }, + { + {1, 2, 3, 4}, + {5, 6, 7, 8}, + {9, 10, 11, 12}, + }, + } { + a := NewDense(flatten(af)) + col := make([]float64, a.mat.Rows) + for j := range af[0] { + for i := range col { + col[i] = float64(i*a.mat.Cols + j + 1) + } + + if got := Col(nil, j, a); !reflect.DeepEqual(got, col) { + t.Errorf("test %d: unexpected values returned for dense col %d: got: %v want: %v", + id, j, got, col) + } + + got := make([]float64, a.mat.Rows) + if Col(got, j, a); !reflect.DeepEqual(got, col) { + t.Errorf("test %d: unexpected values filled for dense col %d: got: %v want: %v", + id, j, got, col) + } + } + } + + denseComparison := func(a *Dense) interface{} { + r, c := a.Dims() + ans := make([][]float64, c) + for j := range ans { + ans[j] = make([]float64, r) + for i := range ans[j] { + ans[j][i] = a.At(i, j) + } + } + return ans + } + + f := func(a Matrix) interface{} { + _, c := a.Dims() + ans := make([][]float64, c) + for j := range ans { + ans[j] = Col(nil, j, a) + } + return ans + } + testOneInputFunc(t, "Col", f, denseComparison, sameAnswerF64SliceOfSlice, isAnyType, isAnySize) + + f = func(a Matrix) interface{} { + r, c := a.Dims() + ans := make([][]float64, c) + for j := range ans { + ans[j] = make([]float64, r) + Col(ans[j], j, a) + } + return ans + } + testOneInputFunc(t, "Col", f, denseComparison, sameAnswerF64SliceOfSlice, isAnyType, isAnySize) +} + +func TestRow(t *testing.T) { + for id, af := range [][][]float64{ + { + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + }, + { + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + {10, 11, 12}, + }, + { + {1, 2, 3, 4}, + {5, 6, 7, 8}, + {9, 10, 11, 12}, + }, + } { + a := NewDense(flatten(af)) + for i, row := range af { + if got := Row(nil, i, a); !reflect.DeepEqual(got, row) { + t.Errorf("test %d: unexpected values returned for dense row %d: got: %v want: %v", + id, i, got, row) + } + + got := make([]float64, len(row)) + if Row(got, i, a); !reflect.DeepEqual(got, row) { + t.Errorf("test %d: unexpected values filled for dense row %d: got: %v want: %v", + id, i, got, row) + } + } + } + + denseComparison := func(a *Dense) interface{} { + r, c := a.Dims() + ans := make([][]float64, r) + for i := range ans { + ans[i] = make([]float64, c) + for j := range ans[i] { + ans[i][j] = a.At(i, j) + } + } + return ans + } + + f := func(a Matrix) interface{} { + r, _ := a.Dims() + ans := make([][]float64, r) + for i := range ans { + ans[i] = Row(nil, i, a) + } + return ans + } + testOneInputFunc(t, "Row", f, denseComparison, sameAnswerF64SliceOfSlice, isAnyType, isAnySize) + + f = func(a Matrix) interface{} { + r, c := a.Dims() + ans := make([][]float64, r) + for i := range ans { + ans[i] = make([]float64, c) + Row(ans[i], i, a) + } + return ans + } + testOneInputFunc(t, "Row", f, denseComparison, sameAnswerF64SliceOfSlice, isAnyType, isAnySize) +} + +func TestCond(t *testing.T) { + for i, test := range []struct { + a *Dense + condOne float64 + condTwo float64 + condInf float64 + }{ + { + a: NewDense(3, 3, []float64{ + 8, 1, 6, + 3, 5, 7, + 4, 9, 2, + }), + condOne: 16.0 / 3.0, + condTwo: 4.330127018922192, + condInf: 16.0 / 3.0, + }, + { + a: NewDense(4, 4, []float64{ + 2, 9, 3, 2, + 10, 9, 9, 3, + 1, 1, 5, 2, + 8, 4, 10, 2, + }), + condOne: 1 / 0.024740155174938, + condTwo: 34.521576567075087, + condInf: 1 / 0.012034465570035, + }, + { + a: NewDense(3, 3, []float64{ + 5, 6, 7, + 8, -2, 1, + 7, 7, 7}), + condOne: 30.769230769230749, + condTwo: 21.662689498448440, + condInf: 31.153846153846136, + }, + } { + condOne := Cond(test.a, 1) + if !floats.EqualWithinAbsOrRel(test.condOne, condOne, 1e-13, 1e-13) { + t.Errorf("Case %d: inf norm mismatch. Want %v, got %v", i, test.condOne, condOne) + } + condTwo := Cond(test.a, 2) + if !floats.EqualWithinAbsOrRel(test.condTwo, condTwo, 1e-13, 1e-13) { + t.Errorf("Case %d: inf norm mismatch. Want %v, got %v", i, test.condTwo, condTwo) + } + condInf := Cond(test.a, math.Inf(1)) + if !floats.EqualWithinAbsOrRel(test.condInf, condInf, 1e-13, 1e-13) { + t.Errorf("Case %d: inf norm mismatch. Want %v, got %v", i, test.condInf, condInf) + } + } + + for _, test := range []struct { + name string + norm float64 + }{ + { + name: "CondOne", + norm: 1, + }, + { + name: "CondTwo", + norm: 2, + }, + { + name: "CondInf", + norm: math.Inf(1), + }, + } { + f := func(a Matrix) interface{} { + return Cond(a, test.norm) + } + denseComparison := func(a *Dense) interface{} { + return Cond(a, test.norm) + } + testOneInputFunc(t, test.name, f, denseComparison, sameAnswerFloatApproxTol(1e-12), isAnyType, isAnySize) + } +} + +func TestDet(t *testing.T) { + for c, test := range []struct { + a *Dense + ans float64 + }{ + { + a: NewDense(2, 2, []float64{1, 0, 0, 1}), + ans: 1, + }, + { + a: NewDense(2, 2, []float64{1, 0, 0, -1}), + ans: -1, + }, + { + a: NewDense(3, 3, []float64{ + 1, 2, 0, + 0, 1, 2, + 0, 2, 1, + }), + ans: -3, + }, + { + a: NewDense(3, 3, []float64{ + 1, 2, 3, + 5, 7, 9, + 6, 9, 12, + }), + ans: 0, + }, + } { + a := DenseCopyOf(test.a) + det := Det(a) + if !Equal(a, test.a) { + t.Errorf("Input matrix changed during Det. Case %d.", c) + } + if !floats.EqualWithinAbsOrRel(det, test.ans, 1e-14, 1e-14) { + t.Errorf("Det mismatch case %d. Got %v, want %v", c, det, test.ans) + } + } + // Perform the normal list test to ensure it works for all types. + f := func(a Matrix) interface{} { + return Det(a) + } + denseComparison := func(a *Dense) interface{} { + return Det(a) + } + testOneInputFunc(t, "Det", f, denseComparison, sameAnswerFloatApproxTol(1e-12), isAnyType, isSquare) + + // Check that it gives approximately the same answer as Cholesky + // Ensure the input matrices are wider than tall so they are full rank + isWide := func(ar, ac int) bool { + return ar <= ac + } + f = func(a Matrix) interface{} { + ar, ac := a.Dims() + if !isWide(ar, ac) { + panic(matrix.ErrShape) + } + var tmp Dense + tmp.Mul(a, a.T()) + return Det(&tmp) + } + denseComparison = func(a *Dense) interface{} { + ar, ac := a.Dims() + if !isWide(ar, ac) { + panic(matrix.ErrShape) + } + var tmp SymDense + tmp.SymOuterK(1, a) + var chol Cholesky + ok := chol.Factorize(&tmp) + if !ok { + panic("bad chol test") + } + return chol.Det() + } + testOneInputFunc(t, "DetVsChol", f, denseComparison, sameAnswerFloatApproxTol(1e-10), isAnyType, isWide) +} + +func TestDot(t *testing.T) { + f := func(a, b Matrix) interface{} { + return Dot(a.(*Vector), b.(*Vector)) + } + denseComparison := func(a, b *Dense) interface{} { + ra, ca := a.Dims() + rb, cb := b.Dims() + if ra != rb || ca != cb { + panic(matrix.ErrShape) + } + var sum float64 + for i := 0; i < ra; i++ { + for j := 0; j < ca; j++ { + sum += a.At(i, j) * b.At(i, j) + } + } + return sum + } + testTwoInputFunc(t, "Dot", f, denseComparison, sameAnswerFloatApproxTol(1e-12), legalTypesVecVec, legalSizeSameVec) +} + +func TestEqual(t *testing.T) { + f := func(a, b Matrix) interface{} { + return Equal(a, b) + } + denseComparison := func(a, b *Dense) interface{} { + return Equal(a, b) + } + testTwoInputFunc(t, "Equal", f, denseComparison, sameAnswerBool, legalTypesAll, isAnySize2) +} + +func TestMax(t *testing.T) { + // A direct test of Max with *Dense arguments is in TestNewDense. + f := func(a Matrix) interface{} { + return Max(a) + } + denseComparison := func(a *Dense) interface{} { + return Max(a) + } + testOneInputFunc(t, "Max", f, denseComparison, sameAnswerFloat, isAnyType, isAnySize) +} + +func TestMin(t *testing.T) { + // A direct test of Min with *Dense arguments is in TestNewDense. + f := func(a Matrix) interface{} { + return Min(a) + } + denseComparison := func(a *Dense) interface{} { + return Min(a) + } + testOneInputFunc(t, "Min", f, denseComparison, sameAnswerFloat, isAnyType, isAnySize) +} + +func TestNorm(t *testing.T) { + for i, test := range []struct { + a [][]float64 + ord float64 + norm float64 + }{ + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}, + ord: 1, + norm: 30, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}, + ord: 2, + norm: 25.495097567963924, + }, + { + a: [][]float64{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}, + ord: math.Inf(1), + norm: 33, + }, + { + a: [][]float64{{1, -2, -2}, {-4, 5, 6}}, + ord: 1, + norm: 8, + }, + { + a: [][]float64{{1, -2, -2}, {-4, 5, 6}}, + ord: math.Inf(1), + norm: 15, + }, + } { + a := NewDense(flatten(test.a)) + if math.Abs(Norm(a, test.ord)-test.norm) > 1e-14 { + t.Errorf("Mismatch test %d: %v norm = %f", i, test.a, test.norm) + } + } + + for _, test := range []struct { + name string + norm float64 + }{ + {"NormOne", 1}, + {"NormTwo", 2}, + {"NormInf", math.Inf(1)}, + } { + f := func(a Matrix) interface{} { + return Norm(a, test.norm) + } + denseComparison := func(a *Dense) interface{} { + return Norm(a, test.norm) + } + testOneInputFunc(t, test.name, f, denseComparison, sameAnswerFloatApproxTol(1e-12), isAnyType, isAnySize) + } +} + +func TestNormZero(t *testing.T) { + for _, a := range []Matrix{ + &Dense{}, + &SymDense{}, + &SymDense{mat: blas64.Symmetric{Uplo: blas.Upper}}, + &TriDense{}, + &TriDense{mat: blas64.Triangular{Uplo: blas.Upper, Diag: blas.NonUnit}}, + &Vector{}, + } { + for _, norm := range []float64{1, 2, math.Inf(1)} { + panicked, message := panics(func() { Norm(a, norm) }) + if !panicked { + t.Errorf("expected panic for Norm(&%T{}, %v)", a, norm) + } + if message != matrix.ErrShape.Error() { + t.Errorf("unexpected panic string for Norm(&%T{}, %v): got:%s want:%s", + a, norm, message, matrix.ErrShape.Error()) + } + } + } +} + +func TestSum(t *testing.T) { + f := func(a Matrix) interface{} { + return Sum(a) + } + denseComparison := func(a *Dense) interface{} { + return Sum(a) + } + testOneInputFunc(t, "Sum", f, denseComparison, sameAnswerFloatApproxTol(1e-12), isAnyType, isAnySize) +} + +func TestTrace(t *testing.T) { + for _, test := range []struct { + a *Dense + trace float64 + }{ + { + a: NewDense(3, 3, []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}), + trace: 15, + }, + } { + trace := Trace(test.a) + if trace != test.trace { + t.Errorf("Trace mismatch. Want %v, got %v", test.trace, trace) + } + } + f := func(a Matrix) interface{} { + return Trace(a) + } + denseComparison := func(a *Dense) interface{} { + return Trace(a) + } + testOneInputFunc(t, "Trace", f, denseComparison, sameAnswerFloat, isAnyType, isSquare) +} diff --git a/matrix/mat64/mul_test.go b/matrix/mat64/mul_test.go new file mode 100644 index 00000000..f0088a63 --- /dev/null +++ b/matrix/mat64/mul_test.go @@ -0,0 +1,285 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix" +) + +// TODO: Need to add tests where one is overwritten. +func TestMulTypes(t *testing.T) { + for _, test := range []struct { + ar int + ac int + br int + bc int + Panics bool + }{ + { + ar: 5, + ac: 5, + br: 5, + bc: 5, + Panics: false, + }, + { + ar: 10, + ac: 5, + br: 5, + bc: 3, + Panics: false, + }, + { + ar: 10, + ac: 5, + br: 5, + bc: 8, + Panics: false, + }, + { + ar: 8, + ac: 10, + br: 10, + bc: 3, + Panics: false, + }, + { + ar: 8, + ac: 3, + br: 3, + bc: 10, + Panics: false, + }, + { + ar: 5, + ac: 8, + br: 8, + bc: 10, + Panics: false, + }, + { + ar: 5, + ac: 12, + br: 12, + bc: 8, + Panics: false, + }, + { + ar: 5, + ac: 7, + br: 8, + bc: 10, + Panics: true, + }, + } { + ar := test.ar + ac := test.ac + br := test.br + bc := test.bc + + // Generate random matrices + avec := make([]float64, ar*ac) + randomSlice(avec) + a := NewDense(ar, ac, avec) + + bvec := make([]float64, br*bc) + randomSlice(bvec) + + b := NewDense(br, bc, bvec) + + // Check that it panics if it is supposed to + if test.Panics { + c := NewDense(0, 0, nil) + fn := func() { + c.Mul(a, b) + } + pan, _ := panics(fn) + if !pan { + t.Errorf("Mul did not panic with dimension mismatch") + } + continue + } + + cvec := make([]float64, ar*bc) + + // Get correct matrix multiply answer from blas64.Gemm + blas64.Gemm(blas.NoTrans, blas.NoTrans, + 1, a.mat, b.mat, + 0, blas64.General{Rows: ar, Cols: bc, Stride: bc, Data: cvec}, + ) + + avecCopy := append([]float64{}, avec...) + bvecCopy := append([]float64{}, bvec...) + cvecCopy := append([]float64{}, cvec...) + + acomp := matComp{r: ar, c: ac, data: avecCopy} + bcomp := matComp{r: br, c: bc, data: bvecCopy} + ccomp := matComp{r: ar, c: bc, data: cvecCopy} + + // Do normal multiply with empty dense + d := NewDense(0, 0, nil) + + testMul(t, a, b, d, acomp, bcomp, ccomp, false, "zero receiver") + + // Normal multiply with existing receiver + c := NewDense(ar, bc, cvec) + randomSlice(cvec) + testMul(t, a, b, c, acomp, bcomp, ccomp, false, "existing receiver") + + // Cast a as a basic matrix + am := (*basicMatrix)(a) + bm := (*basicMatrix)(b) + d.Reset() + testMul(t, am, b, d, acomp, bcomp, ccomp, true, "a is basic, receiver is zero") + d.Reset() + testMul(t, a, bm, d, acomp, bcomp, ccomp, true, "b is basic, receiver is zero") + d.Reset() + testMul(t, am, bm, d, acomp, bcomp, ccomp, true, "both basic, receiver is zero") + randomSlice(cvec) + testMul(t, am, b, d, acomp, bcomp, ccomp, true, "a is basic, receiver is full") + randomSlice(cvec) + testMul(t, a, bm, d, acomp, bcomp, ccomp, true, "b is basic, receiver is full") + randomSlice(cvec) + testMul(t, am, bm, d, acomp, bcomp, ccomp, true, "both basic, receiver is full") + } +} + +func randomSlice(s []float64) { + for i := range s { + s[i] = rand.NormFloat64() + } +} + +type matComp struct { + r, c int + data []float64 +} + +func testMul(t *testing.T, a, b Matrix, c *Dense, acomp, bcomp, ccomp matComp, cvecApprox bool, name string) { + c.Mul(a, b) + var aDense *Dense + switch t := a.(type) { + case *Dense: + aDense = t + case *basicMatrix: + aDense = (*Dense)(t) + } + + var bDense *Dense + switch t := b.(type) { + case *Dense: + bDense = t + case *basicMatrix: + bDense = (*Dense)(t) + } + + if !denseEqual(aDense, acomp) { + t.Errorf("a changed unexpectedly for %v", name) + } + if !denseEqual(bDense, bcomp) { + t.Errorf("b changed unexpectedly for %v", name) + } + if cvecApprox { + if !denseEqualApprox(c, ccomp, 1e-14) { + t.Errorf("mul answer not within tol for %v", name) + } + return + } + + if !denseEqual(c, ccomp) { + t.Errorf("mul answer not equal for %v", name) + } + return +} + +type basicMatrix Dense + +func (m *basicMatrix) At(r, c int) float64 { + return (*Dense)(m).At(r, c) +} + +func (m *basicMatrix) Dims() (r, c int) { + return (*Dense)(m).Dims() +} + +func (m *basicMatrix) T() Matrix { + return Transpose{m} +} + +type basicSymmetric SymDense + +var _ Symmetric = &basicSymmetric{} + +func (m *basicSymmetric) At(r, c int) float64 { + return (*SymDense)(m).At(r, c) +} + +func (m *basicSymmetric) Dims() (r, c int) { + return (*SymDense)(m).Dims() +} + +func (m *basicSymmetric) T() Matrix { + return m +} + +func (m *basicSymmetric) Symmetric() int { + return (*SymDense)(m).Symmetric() +} + +type basicTriangular TriDense + +func (m *basicTriangular) At(r, c int) float64 { + return (*TriDense)(m).At(r, c) +} + +func (m *basicTriangular) Dims() (r, c int) { + return (*TriDense)(m).Dims() +} + +func (m *basicTriangular) T() Matrix { + return Transpose{m} +} + +func (m *basicTriangular) Triangle() (int, matrix.TriKind) { + return (*TriDense)(m).Triangle() +} + +func (m *basicTriangular) TTri() Triangular { + return TransposeTri{m} +} + +func denseEqual(a *Dense, acomp matComp) bool { + ar2, ac2 := a.Dims() + if ar2 != acomp.r { + return false + } + if ac2 != acomp.c { + return false + } + if !floats.Equal(a.mat.Data, acomp.data) { + return false + } + return true +} + +func denseEqualApprox(a *Dense, acomp matComp, tol float64) bool { + ar2, ac2 := a.Dims() + if ar2 != acomp.r { + return false + } + if ac2 != acomp.c { + return false + } + if !floats.EqualApprox(a.mat.Data, acomp.data, tol) { + return false + } + return true +} diff --git a/matrix/mat64/offset.go b/matrix/mat64/offset.go new file mode 100644 index 00000000..45707f15 --- /dev/null +++ b/matrix/mat64/offset.go @@ -0,0 +1,20 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build !appengine + +package mat64 + +import "unsafe" + +// offset returns the number of float64 values b[0] is after a[0]. +func offset(a, b []float64) int { + if &a[0] == &b[0] { + return 0 + } + // This expression must be atomic with respect to GC moves. + // At this stage this is true, because the GC does not + // move. See https://golang.org/issue/12445. + return int(uintptr(unsafe.Pointer(&b[0]))-uintptr(unsafe.Pointer(&a[0]))) / int(unsafe.Sizeof(float64(0))) +} diff --git a/matrix/mat64/offset_appengine.go b/matrix/mat64/offset_appengine.go new file mode 100644 index 00000000..584ef8bb --- /dev/null +++ b/matrix/mat64/offset_appengine.go @@ -0,0 +1,24 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//+build appengine + +package mat64 + +import "reflect" + +var sizeOfFloat64 = int(reflect.TypeOf(float64(0)).Size()) + +// offset returns the number of float64 values b[0] is after a[0]. +func offset(a, b []float64) int { + va0 := reflect.ValueOf(a).Index(0) + vb0 := reflect.ValueOf(b).Index(0) + if va0.Addr() == vb0.Addr() { + return 0 + } + // This expression must be atomic with respect to GC moves. + // At this stage this is true, because the GC does not + // move. See https://golang.org/issue/12445. + return int(vb0.UnsafeAddr()-va0.UnsafeAddr()) / sizeOfFloat64 +} diff --git a/matrix/mat64/pool.go b/matrix/mat64/pool.go new file mode 100644 index 00000000..53f04df4 --- /dev/null +++ b/matrix/mat64/pool.go @@ -0,0 +1,184 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "sync" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/matrix" +) + +var tab64 = [64]byte{ + 0x3f, 0x00, 0x3a, 0x01, 0x3b, 0x2f, 0x35, 0x02, + 0x3c, 0x27, 0x30, 0x1b, 0x36, 0x21, 0x2a, 0x03, + 0x3d, 0x33, 0x25, 0x28, 0x31, 0x12, 0x1c, 0x14, + 0x37, 0x1e, 0x22, 0x0b, 0x2b, 0x0e, 0x16, 0x04, + 0x3e, 0x39, 0x2e, 0x34, 0x26, 0x1a, 0x20, 0x29, + 0x32, 0x24, 0x11, 0x13, 0x1d, 0x0a, 0x0d, 0x15, + 0x38, 0x2d, 0x19, 0x1f, 0x23, 0x10, 0x09, 0x0c, + 0x2c, 0x18, 0x0f, 0x08, 0x17, 0x07, 0x06, 0x05, +} + +// bits returns the ceiling of base 2 log of v. +// Approach based on http://stackoverflow.com/a/11398748. +func bits(v uint64) byte { + if v == 0 { + return 0 + } + v <<= 2 + v-- + v |= v >> 1 + v |= v >> 2 + v |= v >> 4 + v |= v >> 8 + v |= v >> 16 + v |= v >> 32 + return tab64[((v-(v>>1))*0x07EDD5E59A4E28C2)>>58] - 1 +} + +var ( + // pool contains size stratified workspace Dense pools. + // Each pool element i returns sized matrices with a data + // slice capped at 1<= 2*len(w.mat.Data) { + t.Errorf("r: %d c: %d -> len: %d cap: %d", i, j, len(w.mat.Data), cap(w.mat.Data)) + } + w.Set(0, 0, math.NaN()) + work[l] = w + } + for _, w := range work { + putWorkspace(w) + } + } + } + } +} + +var benchmat *Dense + +func poolBenchmark(n, r, c int, clear bool) { + for i := 0; i < n; i++ { + benchmat = getWorkspace(r, c, clear) + putWorkspace(benchmat) + } +} + +func newBenchmark(n, r, c int) { + for i := 0; i < n; i++ { + benchmat = NewDense(r, c, nil) + } +} + +func BenchmarkPool10by10Uncleared(b *testing.B) { poolBenchmark(b.N, 10, 10, false) } +func BenchmarkPool10by10Cleared(b *testing.B) { poolBenchmark(b.N, 10, 10, true) } +func BenchmarkNew10by10(b *testing.B) { newBenchmark(b.N, 10, 10) } +func BenchmarkPool100by100Uncleared(b *testing.B) { poolBenchmark(b.N, 100, 100, false) } +func BenchmarkPool100by100Cleared(b *testing.B) { poolBenchmark(b.N, 100, 100, true) } +func BenchmarkNew100by100(b *testing.B) { newBenchmark(b.N, 100, 100) } + +func BenchmarkMulWorkspaceDense100Half(b *testing.B) { denseMulWorkspaceBench(b, 100, 0.5) } +func BenchmarkMulWorkspaceDense100Tenth(b *testing.B) { denseMulWorkspaceBench(b, 100, 0.1) } +func BenchmarkMulWorkspaceDense1000Half(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.5) } +func BenchmarkMulWorkspaceDense1000Tenth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.1) } +func BenchmarkMulWorkspaceDense1000Hundredth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.01) } +func BenchmarkMulWorkspaceDense1000Thousandth(b *testing.B) { denseMulWorkspaceBench(b, 1000, 0.001) } +func denseMulWorkspaceBench(b *testing.B, size int, rho float64) { + b.StopTimer() + a, _ := randDense(size, rho, rand.NormFloat64) + d, _ := randDense(size, rho, rand.NormFloat64) + b.StartTimer() + for i := 0; i < b.N; i++ { + a.Mul(a, d) + } +} diff --git a/matrix/mat64/product.go b/matrix/mat64/product.go new file mode 100644 index 00000000..f06d6ee5 --- /dev/null +++ b/matrix/mat64/product.go @@ -0,0 +1,197 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "fmt" + + "gonum.org/v1/gonum/matrix" +) + +// Product calculates the product of the given factors and places the result in +// the receiver. The order of multiplication operations is optimized to minimize +// the number of floating point operations on the basis that all matrix +// multiplications are general. +func (m *Dense) Product(factors ...Matrix) { + // The operation order optimisation is the naive O(n^3) dynamic + // programming approach and does not take into consideration + // finer-grained optimisations that might be available. + // + // TODO(kortschak) Consider using the O(nlogn) or O(mlogn) + // algorithms that are available. e.g. + // + // e.g. http://www.jofcis.com/publishedpapers/2014_10_10_4299_4306.pdf + // + // In the case that this is replaced, retain this code in + // tests to compare against. + + r, c := m.Dims() + switch len(factors) { + case 0: + if r != 0 || c != 0 { + panic(matrix.ErrShape) + } + return + case 1: + m.reuseAs(factors[0].Dims()) + m.Copy(factors[0]) + return + case 2: + // Don't do work that we know the answer to. + m.Mul(factors[0], factors[1]) + return + } + + p := newMultiplier(m, factors) + p.optimize() + result := p.multiply() + m.reuseAs(result.Dims()) + m.Copy(result) + putWorkspace(result) +} + +// debugProductWalk enables debugging output for Product. +const debugProductWalk = false + +// multiplier performs operation order optimisation and tree traversal. +type multiplier struct { + // factors is the ordered set of + // factors to multiply. + factors []Matrix + // dims is the chain of factor + // dimensions. + dims []int + + // table contains the dynamic + // programming costs and subchain + // division indices. + table table +} + +func newMultiplier(m *Dense, factors []Matrix) *multiplier { + // Check size early, but don't yet + // allocate data for m. + r, c := m.Dims() + fr, fc := factors[0].Dims() // newMultiplier is only called with len(factors) > 2. + if !m.isZero() { + if fr != r { + panic(matrix.ErrShape) + } + if _, lc := factors[len(factors)-1].Dims(); lc != c { + panic(matrix.ErrShape) + } + } + + dims := make([]int, len(factors)+1) + dims[0] = r + dims[len(dims)-1] = c + pc := fc + for i, f := range factors[1:] { + cr, cc := f.Dims() + dims[i+1] = cr + if pc != cr { + panic(matrix.ErrShape) + } + pc = cc + } + + return &multiplier{ + factors: factors, + dims: dims, + table: newTable(len(factors)), + } +} + +// optimize determines an optimal matrix multiply operation order. +func (p *multiplier) optimize() { + if debugProductWalk { + fmt.Printf("chain dims: %v\n", p.dims) + } + const maxInt = int(^uint(0) >> 1) + for f := 1; f < len(p.factors); f++ { + for i := 0; i < len(p.factors)-f; i++ { + j := i + f + p.table.set(i, j, entry{cost: maxInt}) + for k := i; k < j; k++ { + cost := p.table.at(i, k).cost + p.table.at(k+1, j).cost + p.dims[i]*p.dims[k+1]*p.dims[j+1] + if cost < p.table.at(i, j).cost { + p.table.set(i, j, entry{cost: cost, k: k}) + } + } + } + } +} + +// multiply walks the optimal operation tree found by optimize, +// leaving the final result in the stack. It returns the +// product, which may be copied but should be returned to +// the workspace pool. +func (p *multiplier) multiply() *Dense { + result, _ := p.multiplySubchain(0, len(p.factors)-1) + if debugProductWalk { + r, c := result.Dims() + fmt.Printf("\tpop result (%d×%d) cost=%d\n", r, c, p.table.at(0, len(p.factors)-1).cost) + } + return result.(*Dense) +} + +func (p *multiplier) multiplySubchain(i, j int) (m Matrix, intermediate bool) { + if i == j { + return p.factors[i], false + } + + a, aTmp := p.multiplySubchain(i, p.table.at(i, j).k) + b, bTmp := p.multiplySubchain(p.table.at(i, j).k+1, j) + + ar, ac := a.Dims() + br, bc := b.Dims() + if ac != br { + // Panic with a string since this + // is not a user-facing panic. + panic(matrix.ErrShape.Error()) + } + + if debugProductWalk { + fmt.Printf("\tpush f[%d] (%d×%d)%s * f[%d] (%d×%d)%s\n", + i, ar, ac, result(aTmp), j, br, bc, result(bTmp)) + } + + r := getWorkspace(ar, bc, false) + r.Mul(a, b) + if aTmp { + putWorkspace(a.(*Dense)) + } + if bTmp { + putWorkspace(b.(*Dense)) + } + return r, true +} + +type entry struct { + k int // is the chain subdivision index. + cost int // cost is the cost of the operation. +} + +// table is a row major n×n dynamic programming table. +type table struct { + n int + entries []entry +} + +func newTable(n int) table { + return table{n: n, entries: make([]entry, n*n)} +} + +func (t table) at(i, j int) entry { return t.entries[i*t.n+j] } +func (t table) set(i, j int, e entry) { t.entries[i*t.n+j] = e } + +type result bool + +func (r result) String() string { + if r { + return " (popped result)" + } + return "" +} diff --git a/matrix/mat64/product_test.go b/matrix/mat64/product_test.go new file mode 100644 index 00000000..4a101634 --- /dev/null +++ b/matrix/mat64/product_test.go @@ -0,0 +1,251 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "fmt" + "math/rand" + "testing" +) + +type dims struct{ r, c int } + +var productTests = []struct { + n int + factors []dims + product dims + panics bool +}{ + { + n: 1, + factors: []dims{{3, 4}}, + product: dims{3, 4}, + panics: false, + }, + { + n: 1, + factors: []dims{{2, 4}}, + product: dims{3, 4}, + panics: true, + }, + { + n: 3, + factors: []dims{{10, 30}, {30, 5}, {5, 60}}, + product: dims{10, 60}, + panics: false, + }, + { + n: 3, + factors: []dims{{100, 30}, {30, 5}, {5, 60}}, + product: dims{10, 60}, + panics: true, + }, + { + n: 7, + factors: []dims{{60, 5}, {5, 5}, {5, 4}, {4, 10}, {10, 22}, {22, 45}, {45, 10}}, + product: dims{60, 10}, + panics: false, + }, + { + n: 7, + factors: []dims{{60, 5}, {5, 5}, {5, 400}, {4, 10}, {10, 22}, {22, 45}, {45, 10}}, + product: dims{60, 10}, + panics: true, + }, + { + n: 3, + factors: []dims{{1, 1000}, {1000, 2}, {2, 2}}, + product: dims{1, 2}, + panics: false, + }, + + // Random chains. + { + n: 0, + product: dims{0, 0}, + panics: false, + }, + { + n: 2, + product: dims{60, 10}, + panics: false, + }, + { + n: 3, + product: dims{60, 10}, + panics: false, + }, + { + n: 4, + product: dims{60, 10}, + panics: false, + }, + { + n: 10, + product: dims{60, 10}, + panics: false, + }, +} + +func TestProduct(t *testing.T) { + for _, test := range productTests { + dimensions := test.factors + if dimensions == nil && test.n > 0 { + dimensions = make([]dims, test.n) + for i := range dimensions { + if i != 0 { + dimensions[i].r = dimensions[i-1].c + } + dimensions[i].c = rand.Intn(50) + 1 + } + dimensions[0].r = test.product.r + dimensions[test.n-1].c = test.product.c + } + factors := make([]Matrix, test.n) + for i, d := range dimensions { + data := make([]float64, d.r*d.c) + for i := range data { + data[i] = rand.Float64() + } + factors[i] = NewDense(d.r, d.c, data) + } + + want := &Dense{} + if !test.panics { + a := &Dense{} + for i, b := range factors { + if i == 0 { + want.Clone(b) + continue + } + a, want = want, &Dense{} + want.Mul(a, b) + } + } + + got := NewDense(test.product.r, test.product.c, nil) + panicked, message := panics(func() { + got.Product(factors...) + }) + if test.panics { + if !panicked { + t.Errorf("fail to panic with product chain dimensions: %+v result dimension: %+v", + dimensions, test.product) + } + continue + } else if panicked { + t.Errorf("unexpected panic %q with product chain dimensions: %+v result dimension: %+v", + message, dimensions, test.product) + continue + } + + if len(factors) > 0 { + p := newMultiplier(NewDense(test.product.r, test.product.c, nil), factors) + p.optimize() + gotCost := p.table.at(0, len(factors)-1).cost + expr, wantCost, ok := bestExpressionFor(dimensions) + if !ok { + t.Fatal("unexpected number of expressions in brute force expression search") + } + if gotCost != wantCost { + t.Errorf("unexpected cost for chain dimensions: %+v got: %v want: %v\n%s", + dimensions, got, want, expr) + } + } + + if !EqualApprox(got, want, 1e-14) { + t.Errorf("unexpected result from product chain dimensions: %+v", dimensions) + } + } +} + +// node is a subexpression node. +type node struct { + dims + left, right *node +} + +func (n *node) String() string { + if n.left == nil || n.right == nil { + rows, cols := n.shape() + return fmt.Sprintf("[%d×%d]", rows, cols) + } + rows, cols := n.shape() + return fmt.Sprintf("(%s * %s):[%d×%d]", n.left, n.right, rows, cols) +} + +// shape returns the dimensions of the result of the subexpression. +func (n *node) shape() (rows, cols int) { + if n.left == nil || n.right == nil { + return n.r, n.c + } + rows, _ = n.left.shape() + _, cols = n.right.shape() + return rows, cols +} + +// cost returns the cost to evaluate the subexpression. +func (n *node) cost() int { + if n.left == nil || n.right == nil { + return 0 + } + lr, lc := n.left.shape() + _, rc := n.right.shape() + return lr*lc*rc + n.left.cost() + n.right.cost() +} + +// expressionsFor returns a channel that can be used to iterate over all +// expressions of the given factor dimensions. +func expressionsFor(factors []dims) chan *node { + if len(factors) == 1 { + c := make(chan *node, 1) + c <- &node{dims: factors[0]} + close(c) + return c + } + c := make(chan *node) + go func() { + for i := 1; i < len(factors); i++ { + for left := range expressionsFor(factors[:i]) { + for right := range expressionsFor(factors[i:]) { + c <- &node{left: left, right: right} + } + } + } + close(c) + }() + return c +} + +// catalan returns the nth 0-based Catalan number. +func catalan(n int) int { + p := 1 + for k := n + 1; k < 2*n+1; k++ { + p *= k + } + for k := 2; k < n+2; k++ { + p /= k + } + return p +} + +// bestExpressonFor returns the lowest cost expression for the given expression +// factor dimensions, the cost of the expression and whether the number of +// expressions searched matches the Catalan number for the number of factors. +func bestExpressionFor(factors []dims) (exp *node, cost int, ok bool) { + const maxInt = int(^uint(0) >> 1) + min := maxInt + var best *node + var n int + for exp := range expressionsFor(factors) { + n++ + cost := exp.cost() + if cost < min { + min = cost + best = exp + } + } + return best, min, n == catalan(len(factors)-1) +} diff --git a/matrix/mat64/qr.go b/matrix/mat64/qr.go new file mode 100644 index 00000000..15b3a8ea --- /dev/null +++ b/matrix/mat64/qr.go @@ -0,0 +1,184 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on the QRDecomposition class from Jama 1.0.3. + +package mat64 + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +// QR is a type for creating and using the QR factorization of a matrix. +type QR struct { + qr *Dense + tau []float64 + cond float64 +} + +func (qr *QR) updateCond() { + // A = QR, where Q is orthonormal. Orthonormal multiplications do not change + // the condition number. Thus, ||A|| = ||Q|| ||R|| = ||R||. + n := qr.qr.mat.Cols + work := make([]float64, 3*n) + iwork := make([]int, n) + r := qr.qr.asTriDense(n, blas.NonUnit, blas.Upper) + v := lapack64.Trcon(matrix.CondNorm, r.mat, work, iwork) + qr.cond = 1 / v +} + +// Factorize computes the QR factorization of an m×n matrix a where m >= n. The QR +// factorization always exists even if A is singular. +// +// The QR decomposition is a factorization of the matrix A such that A = Q * R. +// The matrix Q is an orthonormal m×m matrix, and R is an m×n upper triangular matrix. +// Q and R can be extracted from the QFromQR and RFromQR methods on Dense. +func (qr *QR) Factorize(a Matrix) { + m, n := a.Dims() + if m < n { + panic(matrix.ErrShape) + } + k := min(m, n) + if qr.qr == nil { + qr.qr = &Dense{} + } + qr.qr.Clone(a) + work := make([]float64, 1) + qr.tau = make([]float64, k) + lapack64.Geqrf(qr.qr.mat, qr.tau, work, -1) + + work = make([]float64, int(work[0])) + lapack64.Geqrf(qr.qr.mat, qr.tau, work, len(work)) + qr.updateCond() +} + +// TODO(btracey): Add in the "Reduced" forms for extracting the n×n orthogonal +// and upper triangular matrices. + +// RFromQR extracts the m×n upper trapezoidal matrix from a QR decomposition. +func (m *Dense) RFromQR(qr *QR) { + r, c := qr.qr.Dims() + m.reuseAs(r, c) + + // Disguise the QR as an upper triangular + t := &TriDense{ + mat: blas64.Triangular{ + N: c, + Stride: qr.qr.mat.Stride, + Data: qr.qr.mat.Data, + Uplo: blas.Upper, + Diag: blas.NonUnit, + }, + cap: qr.qr.capCols, + } + m.Copy(t) + + // Zero below the triangular. + for i := r; i < c; i++ { + zero(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) + } +} + +// QFromQR extracts the m×m orthonormal matrix Q from a QR decomposition. +func (m *Dense) QFromQR(qr *QR) { + r, _ := qr.qr.Dims() + m.reuseAsZeroed(r, r) + + // Set Q = I. + for i := 0; i < r*r; i += r + 1 { + m.mat.Data[i] = 1 + } + + // Construct Q from the elementary reflectors. + work := make([]float64, 1) + lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, m.mat, work, -1) + work = make([]float64, int(work[0])) + lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, m.mat, work, len(work)) +} + +// SolveQR finds a minimum-norm solution to a system of linear equations defined +// by the matrices A and b, where A is an m×n matrix represented in its QR factorized +// form. If A is singular or near-singular a Condition error is returned. Please +// see the documentation for Condition for more information. +// +// The minimization problem solved depends on the input parameters. +// If trans == false, find X such that ||A*X - b||_2 is minimized. +// If trans == true, find the minimum norm solution of A^T * X = b. +// The solution matrix, X, is stored in place into the receiver. +func (m *Dense) SolveQR(qr *QR, trans bool, b Matrix) error { + r, c := qr.qr.Dims() + br, bc := b.Dims() + + // The QR solve algorithm stores the result in-place into the right hand side. + // The storage for the answer must be large enough to hold both b and x. + // However, this method's receiver must be the size of x. Copy b, and then + // copy the result into m at the end. + if trans { + if c != br { + panic(matrix.ErrShape) + } + m.reuseAs(r, bc) + } else { + if r != br { + panic(matrix.ErrShape) + } + m.reuseAs(c, bc) + } + // Do not need to worry about overlap between m and b because x has its own + // independent storage. + x := getWorkspace(max(r, c), bc, false) + x.Copy(b) + t := qr.qr.asTriDense(qr.qr.mat.Cols, blas.NonUnit, blas.Upper).mat + if trans { + ok := lapack64.Trtrs(blas.Trans, t, x.mat) + if !ok { + return matrix.Condition(math.Inf(1)) + } + for i := c; i < r; i++ { + zero(x.mat.Data[i*x.mat.Stride : i*x.mat.Stride+bc]) + } + work := make([]float64, 1) + lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, -1) + work = make([]float64, int(work[0])) + lapack64.Ormqr(blas.Left, blas.NoTrans, qr.qr.mat, qr.tau, x.mat, work, len(work)) + } else { + work := make([]float64, 1) + lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, -1) + work = make([]float64, int(work[0])) + lapack64.Ormqr(blas.Left, blas.Trans, qr.qr.mat, qr.tau, x.mat, work, len(work)) + + ok := lapack64.Trtrs(blas.NoTrans, t, x.mat) + if !ok { + return matrix.Condition(math.Inf(1)) + } + } + // M was set above to be the correct size for the result. + m.Copy(x) + putWorkspace(x) + if qr.cond > matrix.ConditionTolerance { + return matrix.Condition(qr.cond) + } + return nil +} + +// SolveQRVec finds a minimum-norm solution to a system of linear equations. +// Please see Dense.SolveQR for the full documentation. +func (v *Vector) SolveQRVec(qr *QR, trans bool, b *Vector) error { + if v != b { + v.checkOverlap(b.mat) + } + r, c := qr.qr.Dims() + // The Solve implementation is non-trivial, so rather than duplicate the code, + // instead recast the Vectors as Dense and call the matrix code. + if trans { + v.reuseAs(r) + } else { + v.reuseAs(c) + } + return v.asDense().SolveQR(qr, trans, b.asDense()) +} diff --git a/matrix/mat64/qr_test.go b/matrix/mat64/qr_test.go new file mode 100644 index 00000000..82e9cb25 --- /dev/null +++ b/matrix/mat64/qr_test.go @@ -0,0 +1,206 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas/blas64" +) + +func TestQR(t *testing.T) { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {10, 5}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.NormFloat64()) + } + } + var want Dense + want.Clone(a) + + qr := &QR{} + qr.Factorize(a) + var q, r Dense + q.QFromQR(qr) + + if !isOrthonormal(&q, 1e-10) { + t.Errorf("Q is not orthonormal: m = %v, n = %v", m, n) + } + + r.RFromQR(qr) + + var got Dense + got.Mul(&q, &r) + if !EqualApprox(&got, &want, 1e-12) { + t.Errorf("QR does not equal original matrix. \nWant: %v\nGot: %v", want, got) + } + } +} + +func isOrthonormal(q *Dense, tol float64) bool { + m, n := q.Dims() + if m != n { + return false + } + for i := 0; i < m; i++ { + for j := i; j < m; j++ { + dot := blas64.Dot(m, + blas64.Vector{Inc: 1, Data: q.mat.Data[i*q.mat.Stride:]}, + blas64.Vector{Inc: 1, Data: q.mat.Data[j*q.mat.Stride:]}, + ) + // Dot product should be 1 if i == j and 0 otherwise. + if i == j && math.Abs(dot-1) > tol { + return false + } + if i != j && math.Abs(dot) > tol { + return false + } + } + } + return true +} + +func TestSolveQR(t *testing.T) { + for _, trans := range []bool{false, true} { + for _, test := range []struct { + m, n, bc int + }{ + {5, 5, 1}, + {10, 5, 1}, + {5, 5, 3}, + {10, 5, 3}, + } { + m := test.m + n := test.n + bc := test.bc + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + if trans { + br = n + } + b := NewDense(br, bc, nil) + for i := 0; i < br; i++ { + for j := 0; j < bc; j++ { + b.Set(i, j, rand.Float64()) + } + } + var x Dense + qr := &QR{} + qr.Factorize(a) + x.SolveQR(qr, trans, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b if !trans + // A * A^T * x = A * b if trans + var lhs Dense + var rhs Dense + if trans { + var tmp Dense + tmp.Mul(a, a.T()) + lhs.Mul(&tmp, &x) + rhs.Mul(a, b) + } else { + var tmp Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + } + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + } + // TODO(btracey): Add in testOneInput when it exists. +} + +func TestSolveQRVec(t *testing.T) { + for _, trans := range []bool{false, true} { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {10, 5}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + if trans { + br = n + } + b := NewVector(br, nil) + for i := 0; i < br; i++ { + b.SetVec(i, rand.Float64()) + } + var x Vector + qr := &QR{} + qr.Factorize(a) + x.SolveQRVec(qr, trans, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b if !trans + // A * A^T * x = A * b if trans + var lhs Dense + var rhs Dense + if trans { + var tmp Dense + tmp.Mul(a, a.T()) + lhs.Mul(&tmp, &x) + rhs.Mul(a, b) + } else { + var tmp Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + } + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + } + // TODO(btracey): Add in testOneInput when it exists. +} + +func TestSolveQRCond(t *testing.T) { + for _, test := range []*Dense{ + NewDense(2, 2, []float64{1, 0, 0, 1e-20}), + NewDense(3, 2, []float64{1, 0, 0, 1e-20, 0, 0}), + } { + m, _ := test.Dims() + var qr QR + qr.Factorize(test) + b := NewDense(m, 2, nil) + var x Dense + if err := x.SolveQR(&qr, false, b); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + + bvec := NewVector(m, nil) + var xvec Vector + if err := xvec.SolveQRVec(&qr, false, bvec); err == nil { + t.Error("No error for near-singular matrix in matrix solve.") + } + } +} diff --git a/matrix/mat64/shadow.go b/matrix/mat64/shadow.go new file mode 100644 index 00000000..53355c6d --- /dev/null +++ b/matrix/mat64/shadow.go @@ -0,0 +1,281 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +const ( + // regionOverlap is the panic string used for the general case + // of a matrix region overlap between a source and destination. + regionOverlap = "mat64: bad region: overlap" + + // regionIdentity is the panic string used for the specific + // case of complete agreement between a source and a destination. + regionIdentity = "mat64: bad region: identical" + + // mismatchedStrides is the panic string used for overlapping + // data slices with differing strides. + mismatchedStrides = "mat64: bad region: different strides" +) + +// checkOverlap returns false if the receiver does not overlap data elements +// referenced by the parameter and panics otherwise. +// +// checkOverlap methods return a boolean to allow the check call to be added to a +// boolean expression, making use of short-circuit operators. + +func (m *Dense) checkOverlap(a blas64.General) bool { + mat := m.RawMatrix() + if cap(mat.Data) == 0 || cap(a.Data) == 0 { + return false + } + + off := offset(mat.Data[:1], a.Data[:1]) + + if off == 0 { + // At least one element overlaps. + if mat.Cols == a.Cols && mat.Rows == a.Rows && mat.Stride == a.Stride { + panic(regionIdentity) + } + panic(regionOverlap) + } + + if off > 0 && len(mat.Data) <= off { + // We know m is completely before a. + return false + } + if off < 0 && len(a.Data) <= -off { + // We know m is completely after a. + return false + } + + if mat.Stride != a.Stride { + // Too hard, so assume the worst. + panic(mismatchedStrides) + } + + if off < 0 { + off = -off + mat.Cols, a.Cols = a.Cols, mat.Cols + } + if rectanglesOverlap(off, mat.Cols, a.Cols, mat.Stride) { + panic(regionOverlap) + } + return false +} + +func (s *SymDense) checkOverlap(a blas64.Symmetric) bool { + mat := s.RawSymmetric() + if cap(mat.Data) == 0 || cap(a.Data) == 0 { + return false + } + + off := offset(mat.Data[:1], a.Data[:1]) + + if off == 0 { + // At least one element overlaps. + if mat.N == a.N && mat.Stride == a.Stride { + panic(regionIdentity) + } + panic(regionOverlap) + } + + if off > 0 && len(mat.Data) <= off { + // We know s is completely before a. + return false + } + if off < 0 && len(a.Data) <= -off { + // We know s is completely after a. + return false + } + + if mat.Stride != a.Stride { + // Too hard, so assume the worst. + panic(mismatchedStrides) + } + + if off < 0 { + off = -off + mat.N, a.N = a.N, mat.N + // If we created the matrix it will always + // be in the upper triangle, but don't trust + // that this is the case. + mat.Uplo, a.Uplo = a.Uplo, mat.Uplo + } + if trianglesOverlap(off, mat.N, a.N, mat.Stride, mat.Uplo == blas.Upper, a.Uplo == blas.Upper) { + panic(regionOverlap) + } + return false +} + +func (t *TriDense) checkOverlap(a blas64.Triangular) bool { + mat := t.RawTriangular() + if cap(mat.Data) == 0 || cap(a.Data) == 0 { + return false + } + + off := offset(mat.Data[:1], a.Data[:1]) + + if off == 0 { + // At least one element overlaps. + if mat.N == a.N && mat.Stride == a.Stride { + panic(regionIdentity) + } + panic(regionOverlap) + } + + if off > 0 && len(mat.Data) <= off { + // We know t is completely before a. + return false + } + if off < 0 && len(a.Data) <= -off { + // We know t is completely after a. + return false + } + + if mat.Stride != a.Stride { + // Too hard, so assume the worst. + panic(mismatchedStrides) + } + + if off < 0 { + off = -off + mat.N, a.N = a.N, mat.N + mat.Uplo, a.Uplo = a.Uplo, mat.Uplo + } + if trianglesOverlap(off, mat.N, a.N, mat.Stride, mat.Uplo == blas.Upper, a.Uplo == blas.Upper) { + panic(regionOverlap) + } + return false +} + +func (v *Vector) checkOverlap(a blas64.Vector) bool { + mat := v.mat + if cap(mat.Data) == 0 || cap(a.Data) == 0 { + return false + } + + off := offset(mat.Data[:1], a.Data[:1]) + + if off == 0 { + // At least one element overlaps. + if mat.Inc == a.Inc && len(mat.Data) == len(a.Data) { + panic(regionIdentity) + } + panic(regionOverlap) + } + + if off > 0 && len(mat.Data) <= off { + // We know v is completely before a. + return false + } + if off < 0 && len(a.Data) <= -off { + // We know v is completely after a. + return false + } + + if mat.Inc != a.Inc { + // Too hard, so assume the worst. + panic(mismatchedStrides) + } + + if mat.Inc == 1 || off&mat.Inc == 0 { + panic(regionOverlap) + } + return false +} + +// rectanglesOverlap returns whether the strided rectangles a and b overlap +// when b is offset by off elements after a but has at least one element before +// the end of a. off must be positive. a and b have aCols and bCols respectively. +// +// rectanglesOverlap works by shifting both matrices left such that the left +// column of a is at 0. The column indexes are flattened by obtaining the shifted +// relative left and right column positions modulo the common stride. This allows +// direct comparison of the column offsets when the matrix backing data slices +// are known to overlap. +func rectanglesOverlap(off, aCols, bCols, stride int) bool { + if stride == 1 { + // Unit stride means overlapping data + // slices must overlap as matrices. + return true + } + + // Flatten the shifted matrix column positions + // so a starts at 0, modulo the common stride. + const aFrom = 0 + aTo := aCols + // The mod stride operations here make the from + // and to indexes comparable between a and b when + // the data slices of a and b overlap. + bFrom := off % stride + bTo := (bFrom + bCols) % stride + + if bTo == 0 || bFrom < bTo { + // b matrix is not wrapped: compare for + // simple overlap. + return bFrom < aTo + } + + // b strictly wraps and so must overlap with a. + return true +} + +// trianglesOverlap returns whether the strided triangles a and b overlap +// when b is offset by off elements after a but has at least one element before +// the end of a. off must be positive. a and b are aSize×aSize and bSize×bSize +// respectively. +func trianglesOverlap(off, aSize, bSize, stride int, aUpper, bUpper bool) bool { + if !rectanglesOverlap(off, aSize, bSize, stride) { + // Fast return if bounding rectangles do not overlap. + return false + } + + // Find location of b relative to a. + rowOffset := off / stride + colOffset := off % stride + if (off+bSize)%stride < colOffset { + // We have wrapped, so readjust offsets. + rowOffset++ + colOffset -= stride + } + + if aUpper { + // Check whether the upper left of b + // is in the triangle of a + if rowOffset >= 0 && rowOffset <= colOffset { + return true + } + // Check whether the upper right of b + // is in the triangle of a. + return bUpper && rowOffset < colOffset+bSize + } + + // Check whether the upper left of b + // is in the triangle of a + if colOffset >= 0 && rowOffset >= colOffset { + return true + } + if bUpper { + // Check whether the upper right corner of b + // is in a or the upper row of b spans a row + // of a. + return rowOffset > colOffset+bSize || colOffset < 0 + } + if colOffset < 0 { + // Check whether the lower left of a + // is in the triangle of b or below + // the diagonal of a. This requires a + // swap of reference origin. + return -rowOffset+aSize > -colOffset + } + // Check whether the lower left of b + // is in the triangle of a or below + // the diagonal of a. + return rowOffset+bSize > colOffset +} diff --git a/matrix/mat64/shadow_test.go b/matrix/mat64/shadow_test.go new file mode 100644 index 00000000..465fadff --- /dev/null +++ b/matrix/mat64/shadow_test.go @@ -0,0 +1,282 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/matrix" +) + +func TestDenseOverlaps(t *testing.T) { + type view struct { + i, j, r, c int + *Dense + } + + rnd := rand.New(rand.NewSource(1)) + + for r := 1; r < 20; r++ { + for c := 1; c < 20; c++ { + m := NewDense(r, c, nil) + panicked, message := panics(func() { m.checkOverlap(m.RawMatrix()) }) + if !panicked { + t.Error("expected matrix overlap with self") + } + if message != regionIdentity { + t.Errorf("unexpected panic message for self overlap: got: %q want: %q", message, regionIdentity) + } + + for i := 0; i < 1000; i++ { + var views [2]view + for k := range views { + if r > 1 { + views[k].i = rnd.Intn(r - 1) + views[k].r = rnd.Intn(r-views[k].i-1) + 1 + } else { + views[k].r = 1 + } + if c > 1 { + views[k].j = rnd.Intn(c - 1) + views[k].c = rnd.Intn(c-views[k].j-1) + 1 + } else { + views[k].c = 1 + } + views[k].Dense = m.Slice(views[k].i, views[k].i+views[k].r, views[k].j, views[k].j+views[k].c).(*Dense) + + panicked, _ = panics(func() { m.checkOverlap(views[k].RawMatrix()) }) + if !panicked { + t.Errorf("expected matrix (%d×%d) overlap with view {rows=%d:%d, cols=%d:%d}", + r, c, views[k].i, views[k].i+views[k].r, views[k].j, views[k].j+views[k].c) + } + panicked, _ = panics(func() { views[k].checkOverlap(m.RawMatrix()) }) + if !panicked { + t.Errorf("expected view {rows=%d:%d, cols=%d:%d} overlap with parent (%d×%d)", + views[k].i, views[k].i+views[k].r, views[k].j, views[k].j+views[k].c, r, c) + } + } + + overlapRows := intervalsOverlap( + interval{views[0].i, views[0].i + views[0].r}, + interval{views[1].i, views[1].i + views[1].r}, + ) + overlapCols := intervalsOverlap( + interval{views[0].j, views[0].j + views[0].c}, + interval{views[1].j, views[1].j + views[1].c}, + ) + want := overlapRows && overlapCols + + for k, v := range views { + w := views[1-k] + got, _ := panics(func() { v.checkOverlap(w.RawMatrix()) }) + if got != want { + t.Errorf("unexpected result for overlap test for {rows=%d:%d, cols=%d:%d} with {rows=%d:%d, cols=%d:%d}: got: %t want: %t", + v.i, v.i+v.r, v.j, v.j+v.c, + w.i, w.i+w.r, w.j, w.j+w.c, + got, want) + } + } + } + } + } +} + +func TestTriDenseOverlaps(t *testing.T) { + type view struct { + i, j, n int + *TriDense + } + + rnd := rand.New(rand.NewSource(1)) + + for _, parentKind := range []matrix.TriKind{matrix.Upper, matrix.Lower} { + for n := 1; n < 20; n++ { + data := make([]float64, n*n) + for i := range data { + data[i] = float64(i + 1) + } + m := NewDense(n, n, data) + mt := denseAsTriDense(m, parentKind) + panicked, message := panics(func() { mt.checkOverlap(mt.RawTriangular()) }) + if !panicked { + t.Error("expected matrix overlap with self") + } + if message != regionIdentity { + t.Errorf("unexpected panic message for self overlap: got: %q want: %q", message, regionIdentity) + } + + for i := 0; i < 1000; i++ { + var views [2]view + for k := range views { + if n > 1 { + views[k].i = rnd.Intn(n - 1) + views[k].j = rnd.Intn(n - 1) + views[k].n = rnd.Intn(n-max(views[k].i, views[k].j)-1) + 1 + } else { + views[k].n = 1 + } + viewKind := []matrix.TriKind{matrix.Upper, matrix.Lower}[rnd.Intn(2)] + views[k].TriDense = denseAsTriDense( + m.Slice(views[k].i, views[k].i+views[k].n, views[k].j, views[k].j+views[k].n).(*Dense), + viewKind) + + wantPanick := overlapsParentTriangle(views[k].i, views[k].j, views[k].n, parentKind, viewKind) + + panicked, _ = panics(func() { mt.checkOverlap(views[k].RawTriangular()) }) + if panicked != wantPanick { + t.Errorf("unexpected (%d×%d)%s overlap with view {rows=%d:%d, cols=%d:%d}%s got:%t want:%t\n% v\n\n% v\n", + n, n, kindString(parentKind), + views[k].i, views[k].i+views[k].n, views[k].j, views[k].j+views[k].n, kindString(viewKind), + panicked, wantPanick, + Formatted(mt), Formatted(views[k].TriDense)) + } + panicked, _ = panics(func() { views[k].checkOverlap(mt.RawTriangular()) }) + if panicked != wantPanick { + t.Errorf("unexpected {rows=%d:%d, cols=%d:%d}%s overlap with parent (%d×%d)%s got:%t want:%t\n% v\n\n% v\n", + views[k].i, views[k].i+views[k].n, views[k].j, views[k].j+views[k].n, kindString(viewKind), + n, n, kindString(parentKind), + panicked, wantPanick, + Formatted(views[k].TriDense), Formatted(mt)) + } + } + + want := overlapSiblingTriangles( + views[0].i, views[0].j, views[0].n, views[0].mat.Uplo == blas.Upper, + views[1].i, views[1].j, views[1].n, views[1].mat.Uplo == blas.Upper, + ) + + for k, v := range views { + w := views[1-k] + got, _ := panics(func() { v.checkOverlap(w.RawTriangular()) }) + if got != want { + t.Errorf("unexpected result for overlap test for {rows=%d:%d, cols=%d:%d}%s with {rows=%d:%d, cols=%d:%d}%s: got:%t want:%t\n% v\n\n% v\n", + v.i, v.i+v.n, v.j, v.j+v.n, kindString(v.mat.Uplo == blas.Upper), + w.i, w.i+w.n, w.j, w.j+w.n, kindString(w.mat.Uplo == blas.Upper), + got, want, + Formatted(v.TriDense), Formatted(w.TriDense)) + } + } + } + } + } +} + +type interval struct{ from, to int } + +func intervalsOverlap(a, b interval) bool { + return a.to > b.from && b.to > a.from +} + +func overlapsParentTriangle(i, j, n int, parent, view matrix.TriKind) bool { + switch parent { + case matrix.Upper: + if i <= j { + return true + } + if view == matrix.Upper { + return i < j+n + } + + case matrix.Lower: + if i >= j { + return true + } + if view == matrix.Lower { + return i+n > j + } + } + + return false +} + +func overlapSiblingTriangles(ai, aj, an int, aKind matrix.TriKind, bi, bj, bn int, bKind matrix.TriKind) bool { + for i := max(ai, bi); i < min(ai+an, bi+bn); i++ { + var a, b interval + + if aKind == matrix.Upper { + a = interval{from: aj - ai + i, to: aj + an} + } else { + a = interval{from: aj, to: aj - ai + i + 1} + } + + if bKind == matrix.Upper { + b = interval{from: bj - bi + i, to: bj + bn} + } else { + b = interval{from: bj, to: bj - bi + i + 1} + } + + if intervalsOverlap(a, b) { + return true + } + } + return false +} + +func abs(a int) int { + if a < 0 { + return -a + } + return a +} + +func kindString(k matrix.TriKind) string { + if k == matrix.Upper { + return "U" + } + return "L" +} + +// See https://github.com/gonum/matrix/issues/359 for details. +func TestIssue359(t *testing.T) { + for xi := 0; xi < 2; xi++ { + for xj := 0; xj < 2; xj++ { + for yi := 0; yi < 2; yi++ { + for yj := 0; yj < 2; yj++ { + a := NewDense(3, 3, []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }) + x := a.Slice(xi, xi+2, xj, xj+2).(*Dense) + y := a.Slice(yi, yi+2, yj, yj+2).(*Dense) + + panicked, _ := panics(func() { x.checkOverlap(y.mat) }) + if !panicked { + t.Errorf("expected panic for aliased with offsets x(%d,%d) y(%d,%d):\nx:\n%v\ny:\n%v", + xi, xj, yi, yj, Formatted(x), Formatted(y), + ) + } + } + } + } + } +} + +// denseAsTriDense returns a triangular matrix derived from the +// square matrix m, with the orientation specified by kind. +func denseAsTriDense(m *Dense, kind matrix.TriKind) *TriDense { + r, c := m.Dims() + if r != c { + panic(matrix.ErrShape) + } + n := r + uplo := blas.Lower + if kind == matrix.Upper { + uplo = blas.Upper + } + return &TriDense{ + mat: blas64.Triangular{ + N: n, + Stride: m.mat.Stride, + Data: m.mat.Data, + Uplo: uplo, + Diag: blas.NonUnit, + }, + cap: n, + } +} diff --git a/matrix/mat64/solve.go b/matrix/mat64/solve.go new file mode 100644 index 00000000..001ed330 --- /dev/null +++ b/matrix/mat64/solve.go @@ -0,0 +1,126 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +// Solve finds a minimum-norm solution to a system of linear equations defined +// by the matrices a and b. If A is singular or near-singular, a Condition error +// is returned. Please see the documentation for Condition for more information. +// +// The minimization problem solved depends on the input parameters: +// - if m >= n, find X such that ||A*X - B||_2 is minimized, +// - if m < n, find the minimum norm solution of A * X = B. +// The solution matrix, X, is stored in-place into the receiver. +func (m *Dense) Solve(a, b Matrix) error { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br { + panic(matrix.ErrShape) + } + m.reuseAs(ac, bc) + + // TODO(btracey): Add special cases for SymDense, etc. + aU, aTrans := untranspose(a) + bU, bTrans := untranspose(b) + switch rma := aU.(type) { + case RawTriangular: + side := blas.Left + tA := blas.NoTrans + if aTrans { + tA = blas.Trans + } + + switch rm := bU.(type) { + case RawMatrixer: + if m != bU || bTrans { + if m == bU || m.checkOverlap(rm.RawMatrix()) { + tmp := getWorkspace(br, bc, false) + tmp.Copy(b) + m.Copy(tmp) + putWorkspace(tmp) + break + } + m.Copy(b) + } + default: + if m != bU { + m.Copy(b) + } else if bTrans { + // m and b share data so Copy cannot be used directly. + tmp := getWorkspace(br, bc, false) + tmp.Copy(b) + m.Copy(tmp) + putWorkspace(tmp) + } + } + + rm := rma.RawTriangular() + blas64.Trsm(side, tA, 1, rm, m.mat) + work := make([]float64, 3*rm.N) + iwork := make([]int, rm.N) + cond := lapack64.Trcon(matrix.CondNorm, rm, work, iwork) + if cond > matrix.ConditionTolerance { + return matrix.Condition(cond) + } + return nil + } + + switch { + case ar == ac: + if a == b { + // x = I. + if ar == 1 { + m.mat.Data[0] = 1 + return nil + } + for i := 0; i < ar; i++ { + v := m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+ac] + zero(v) + v[i] = 1 + } + return nil + } + var lu LU + lu.Factorize(a) + return m.SolveLU(&lu, false, b) + case ar > ac: + var qr QR + qr.Factorize(a) + return m.SolveQR(&qr, false, b) + default: + var lq LQ + lq.Factorize(a) + return m.SolveLQ(&lq, false, b) + } +} + +// SolveVec finds a minimum-norm solution to a system of linear equations defined +// by the matrix a and the right-hand side vector b. If A is singular or +// near-singular, a Condition error is returned. Please see the documentation for +// Dense.Solve for more information. +func (v *Vector) SolveVec(a Matrix, b *Vector) error { + if v != b { + v.checkOverlap(b.mat) + } + _, c := a.Dims() + // The Solve implementation is non-trivial, so rather than duplicate the code, + // instead recast the Vectors as Dense and call the matrix code. + v.reuseAs(c) + m := v.asDense() + // We conditionally create bm as m when b and v are identical + // to prevent the overlap detection code from identifying m + // and bm as overlapping but not identical. + bm := m + if v != b { + bm = b.asDense() + } + return m.Solve(a, bm) +} diff --git a/matrix/mat64/solve_test.go b/matrix/mat64/solve_test.go new file mode 100644 index 00000000..7f013978 --- /dev/null +++ b/matrix/mat64/solve_test.go @@ -0,0 +1,296 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math/rand" + "testing" +) + +func TestSolve(t *testing.T) { + // Hand-coded cases. + for _, test := range []struct { + a [][]float64 + b [][]float64 + ans [][]float64 + shouldErr bool + }{ + { + a: [][]float64{{6}}, + b: [][]float64{{3}}, + ans: [][]float64{{0.5}}, + shouldErr: false, + }, + { + a: [][]float64{ + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + }, + b: [][]float64{ + {3}, + {2}, + {1}, + }, + ans: [][]float64{ + {3}, + {2}, + {1}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0.8147, 0.9134, 0.5528}, + {0.9058, 0.6324, 0.8723}, + {0.1270, 0.0975, 0.7612}, + }, + b: [][]float64{ + {0.278}, + {0.547}, + {0.958}, + }, + ans: [][]float64{ + {-0.932687281002860}, + {0.303963920182067}, + {1.375216503507109}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0.8147, 0.9134, 0.5528}, + {0.9058, 0.6324, 0.8723}, + }, + b: [][]float64{ + {0.278}, + {0.547}, + }, + ans: [][]float64{ + {0.25919787248965376}, + {-0.25560256266441034}, + {0.5432324059702451}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0.8147, 0.9134, 0.9}, + {0.9058, 0.6324, 0.9}, + {0.1270, 0.0975, 0.1}, + {1.6, 2.8, -3.5}, + }, + b: [][]float64{ + {0.278}, + {0.547}, + {-0.958}, + {1.452}, + }, + ans: [][]float64{ + {0.820970340787782}, + {-0.218604626527306}, + {-0.212938815234215}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0.8147, 0.9134, 0.231, -1.65}, + {0.9058, 0.6324, 0.9, 0.72}, + {0.1270, 0.0975, 0.1, 1.723}, + {1.6, 2.8, -3.5, 0.987}, + {7.231, 9.154, 1.823, 0.9}, + }, + b: [][]float64{ + {0.278, 8.635}, + {0.547, 9.125}, + {-0.958, -0.762}, + {1.452, 1.444}, + {1.999, -7.234}, + }, + ans: [][]float64{ + {1.863006789511373, 44.467887791812750}, + {-1.127270935407224, -34.073794226035126}, + {-0.527926457947330, -8.032133759788573}, + {-0.248621916204897, -2.366366415805275}, + }, + shouldErr: false, + }, + { + a: [][]float64{ + {0, 0}, + {0, 0}, + }, + b: [][]float64{ + {3}, + {2}, + }, + ans: nil, + shouldErr: true, + }, + { + a: [][]float64{ + {0, 0}, + {0, 0}, + {0, 0}, + }, + b: [][]float64{ + {3}, + {2}, + {1}, + }, + ans: nil, + shouldErr: true, + }, + { + a: [][]float64{ + {0, 0, 0}, + {0, 0, 0}, + }, + b: [][]float64{ + {3}, + {2}, + }, + ans: nil, + shouldErr: true, + }, + } { + a := NewDense(flatten(test.a)) + b := NewDense(flatten(test.b)) + + var ans *Dense + if test.ans != nil { + ans = NewDense(flatten(test.ans)) + } + + var x Dense + err := x.Solve(a, b) + if err != nil { + if !test.shouldErr { + t.Errorf("Unexpected solve error: %s", err) + } + continue + } + if err == nil && test.shouldErr { + t.Errorf("Did not error during solve.") + continue + } + if !EqualApprox(&x, ans, 1e-12) { + t.Errorf("Solve answer mismatch. Want %v, got %v", ans, x) + } + } + + // Random Cases. + for _, test := range []struct { + m, n, bc int + }{ + {5, 5, 1}, + {5, 10, 1}, + {10, 5, 1}, + {5, 5, 7}, + {5, 10, 7}, + {10, 5, 7}, + {5, 5, 12}, + {5, 10, 12}, + {10, 5, 12}, + } { + m := test.m + n := test.n + bc := test.bc + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + b := NewDense(br, bc, nil) + for i := 0; i < br; i++ { + for j := 0; j < bc; j++ { + b.Set(i, j, rand.Float64()) + } + } + var x Dense + x.Solve(a, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b + var tmp, lhs, rhs Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + + // Use testTwoInput. + method := func(receiver, a, b Matrix) { + type Solver interface { + Solve(a, b Matrix) error + } + rd := receiver.(Solver) + rd.Solve(a, b) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Solve(a, b) + } + testTwoInput(t, "Solve", &Dense{}, method, denseComparison, legalTypesAll, legalSizeSolve, 1e-7) +} + +func TestSolveVec(t *testing.T) { + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {5, 10}, + {10, 5}, + {5, 5}, + {5, 10}, + {10, 5}, + {5, 5}, + {5, 10}, + {10, 5}, + } { + m := test.m + n := test.n + a := NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, rand.Float64()) + } + } + br := m + b := NewVector(br, nil) + for i := 0; i < br; i++ { + b.SetVec(i, rand.Float64()) + } + var x Vector + x.SolveVec(a, b) + + // Test that the normal equations hold. + // A^T * A * x = A^T * b + var tmp, lhs, rhs Dense + tmp.Mul(a.T(), a) + lhs.Mul(&tmp, &x) + rhs.Mul(a.T(), b) + if !EqualApprox(&lhs, &rhs, 1e-10) { + t.Errorf("Normal equations do not hold.\nLHS: %v\n, RHS: %v\n", lhs, rhs) + } + } + + // Use testTwoInput + method := func(receiver, a, b Matrix) { + type SolveVecer interface { + SolveVec(a Matrix, b *Vector) error + } + rd := receiver.(SolveVecer) + rd.SolveVec(a, b.(*Vector)) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Solve(a, b) + } + testTwoInput(t, "SolveVec", &Vector{}, method, denseComparison, legalTypesNotVecVec, legalSizeSolve, 1e-12) +} diff --git a/matrix/mat64/svd.go b/matrix/mat64/svd.go new file mode 100644 index 00000000..87498f73 --- /dev/null +++ b/matrix/mat64/svd.go @@ -0,0 +1,179 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on the SingularValueDecomposition class from Jama 1.0.3. + +package mat64 + +import ( + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +// SVD is a type for creating and using the Singular Value Decomposition (SVD) +// of a matrix. +type SVD struct { + kind matrix.SVDKind + + s []float64 + u blas64.General + vt blas64.General +} + +// Factorize computes the singular value decomposition (SVD) of the input matrix +// A. The singular values of A are computed in all cases, while the singular +// vectors are optionally computed depending on the input kind. +// +// The full singular value decomposition (kind == SVDFull) deconstructs A as +// A = U * Σ * V^T +// where Σ is an m×n diagonal matrix of singular vectors, U is an m×m unitary +// matrix of left singular vectors, and V is an n×n matrix of right singular vectors. +// +// It is frequently not necessary to compute the full SVD. Computation time and +// storage costs can be reduced using the appropriate kind. Only the singular +// values can be computed (kind == SVDNone), or a "thin" representation of the +// singular vectors (kind = SVDThin). The thin representation can save a significant +// amount of memory if m >> n. See the documentation for the lapack.SVDKind values +// for more information. +// +// Factorize returns whether the decomposition succeeded. If the decomposition +// failed, routines that require a successful factorization will panic. +func (svd *SVD) Factorize(a Matrix, kind matrix.SVDKind) (ok bool) { + m, n := a.Dims() + var jobU, jobVT lapack.SVDJob + switch kind { + default: + panic("svd: bad input kind") + case matrix.SVDNone: + jobU = lapack.SVDNone + jobVT = lapack.SVDNone + case matrix.SVDFull: + // TODO(btracey): This code should be modified to have the smaller + // matrix written in-place into aCopy when the lapack/native/dgesvd + // implementation is complete. + svd.u = blas64.General{ + Rows: m, + Cols: m, + Stride: m, + Data: use(svd.u.Data, m*m), + } + svd.vt = blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: use(svd.vt.Data, n*n), + } + jobU = lapack.SVDAll + jobVT = lapack.SVDAll + case matrix.SVDThin: + // TODO(btracey): This code should be modified to have the larger + // matrix written in-place into aCopy when the lapack/native/dgesvd + // implementation is complete. + svd.u = blas64.General{ + Rows: m, + Cols: min(m, n), + Stride: min(m, n), + Data: use(svd.u.Data, m*min(m, n)), + } + svd.vt = blas64.General{ + Rows: min(m, n), + Cols: n, + Stride: n, + Data: use(svd.vt.Data, min(m, n)*n), + } + jobU = lapack.SVDInPlace + jobVT = lapack.SVDInPlace + } + + // A is destroyed on call, so copy the matrix. + aCopy := DenseCopyOf(a) + svd.kind = kind + svd.s = use(svd.s, min(m, n)) + + work := make([]float64, 1) + lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, -1) + work = make([]float64, int(work[0])) + ok = lapack64.Gesvd(jobU, jobVT, aCopy.mat, svd.u, svd.vt, svd.s, work, len(work)) + if !ok { + svd.kind = 0 + } + return ok +} + +// Kind returns the matrix.SVDKind of the decomposition. If no decomposition has been +// computed, Kind returns 0. +func (svd *SVD) Kind() matrix.SVDKind { + return svd.kind +} + +// Cond returns the 2-norm condition number for the factorized matrix. Cond will +// panic if the receiver does not contain a successful factorization. +func (svd *SVD) Cond() float64 { + if svd.kind == 0 { + panic("svd: no decomposition computed") + } + return svd.s[0] / svd.s[len(svd.s)-1] +} + +// Values returns the singular values of the factorized matrix in decreasing order. +// If the input slice is non-nil, the values will be stored in-place into the slice. +// In this case, the slice must have length min(m,n), and Values will panic with +// matrix.ErrSliceLengthMismatch otherwise. If the input slice is nil, +// a new slice of the appropriate length will be allocated and returned. +// +// Values will panic if the receiver does not contain a successful factorization. +func (svd *SVD) Values(s []float64) []float64 { + if svd.kind == 0 { + panic("svd: no decomposition computed") + } + if s == nil { + s = make([]float64, len(svd.s)) + } + if len(s) != len(svd.s) { + panic(matrix.ErrSliceLengthMismatch) + } + copy(s, svd.s) + return s +} + +// UFromSVD extracts the matrix U from the singular value decomposition, storing +// the result in-place into the receiver. U is size m×m if svd.Kind() == SVDFull, +// of size m×min(m,n) if svd.Kind() == SVDThin, and UFromSVD panics otherwise. +func (m *Dense) UFromSVD(svd *SVD) { + kind := svd.kind + if kind != matrix.SVDFull && kind != matrix.SVDThin { + panic("mat64: improper SVD kind") + } + r := svd.u.Rows + c := svd.u.Cols + m.reuseAs(r, c) + + tmp := &Dense{ + mat: svd.u, + capRows: r, + capCols: c, + } + m.Copy(tmp) +} + +// VFromSVD extracts the matrix V from the singular value decomposition, storing +// the result in-place into the receiver. V is size n×n if svd.Kind() == SVDFull, +// of size n×min(m,n) if svd.Kind() == SVDThin, and VFromSVD panics otherwise. +func (m *Dense) VFromSVD(svd *SVD) { + kind := svd.kind + if kind != matrix.SVDFull && kind != matrix.SVDThin { + panic("mat64: improper SVD kind") + } + r := svd.vt.Rows + c := svd.vt.Cols + m.reuseAs(c, r) + + tmp := &Dense{ + mat: svd.vt, + capRows: r, + capCols: c, + } + m.Copy(tmp.T()) +} diff --git a/matrix/mat64/svd_test.go b/matrix/mat64/svd_test.go new file mode 100644 index 00000000..fb342486 --- /dev/null +++ b/matrix/mat64/svd_test.go @@ -0,0 +1,177 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix" +) + +func TestSVD(t *testing.T) { + // Hand coded tests + for _, test := range []struct { + a *Dense + u *Dense + v *Dense + s []float64 + }{ + { + a: NewDense(4, 2, []float64{2, 4, 1, 3, 0, 0, 0, 0}), + u: NewDense(4, 2, []float64{ + -0.8174155604703632, -0.5760484367663209, + -0.5760484367663209, 0.8174155604703633, + 0, 0, + 0, 0, + }), + v: NewDense(2, 2, []float64{ + -0.4045535848337571, -0.9145142956773044, + -0.9145142956773044, 0.4045535848337571, + }), + s: []float64{5.464985704219041, 0.365966190626258}, + }, + { + // Issue #5. + a: NewDense(3, 11, []float64{ + 1, 1, 0, 1, 0, 0, 0, 0, 0, 11, 1, + 1, 0, 0, 0, 0, 0, 1, 0, 0, 12, 2, + 1, 1, 0, 0, 0, 0, 0, 0, 1, 13, 3, + }), + u: NewDense(3, 3, []float64{ + -0.5224167862273765, 0.7864430360363114, 0.3295270133658976, + -0.5739526766688285, -0.03852203026050301, -0.8179818935216693, + -0.6306021141833781, -0.6164603833618163, 0.4715056408282468, + }), + v: NewDense(11, 3, []float64{ + -0.08123293141915189, 0.08528085505260324, -0.013165501690885152, + -0.05423546426886932, 0.1102707844980355, 0.622210623111631, + 0, 0, 0, + -0.0245733326078166, 0.510179651760153, 0.25596360803140994, + 0, 0, 0, + 0, 0, 0, + -0.026997467150282436, -0.024989929445430496, -0.6353761248025164, + 0, 0, 0, + -0.029662131661052707, -0.3999088672621176, 0.3662470150802212, + -0.9798839760830571, 0.11328174160898856, -0.047702613241813366, + -0.16755466189153964, -0.7395268089170608, 0.08395240366704032, + }), + s: []float64{21.259500881097434, 1.5415021616856566, 1.2873979074613628}, + }, + } { + var svd SVD + ok := svd.Factorize(test.a, matrix.SVDThin) + if !ok { + t.Errorf("SVD failed") + } + s, u, v := extractSVD(&svd) + if !floats.EqualApprox(s, test.s, 1e-10) { + t.Errorf("Singular value mismatch. Got %v, want %v.", s, test.s) + } + if !EqualApprox(u, test.u, 1e-10) { + t.Errorf("U mismatch.\nGot:\n%v\nWant:\n%v", Formatted(u), Formatted(test.u)) + } + if !EqualApprox(v, test.v, 1e-10) { + t.Errorf("V mismatch.\nGot:\n%v\nWant:\n%v", Formatted(v), Formatted(test.v)) + } + m, n := test.a.Dims() + sigma := NewDense(min(m, n), min(m, n), nil) + for i := 0; i < min(m, n); i++ { + sigma.Set(i, i, s[i]) + } + + var ans Dense + ans.Product(u, sigma, v.T()) + if !EqualApprox(test.a, &ans, 1e-10) { + t.Errorf("A reconstruction mismatch.\nGot:\n%v\nWant:\n%v\n", Formatted(&ans), Formatted(test.a)) + } + } + + for _, test := range []struct { + m, n int + }{ + {5, 5}, + {5, 3}, + {3, 5}, + {150, 150}, + {200, 150}, + {150, 200}, + } { + m := test.m + n := test.n + for trial := 0; trial < 10; trial++ { + a := NewDense(m, n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.NormFloat64() + } + aCopy := DenseCopyOf(a) + + // Test Full decomposition. + var svd SVD + ok := svd.Factorize(a, matrix.SVDFull) + if !ok { + t.Errorf("SVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to SVD with full") + } + s, u, v := extractSVD(&svd) + sigma := NewDense(m, n, nil) + for i := 0; i < min(m, n); i++ { + sigma.Set(i, i, s[i]) + } + var ansFull Dense + ansFull.Product(u, sigma, v.T()) + if !EqualApprox(&ansFull, a, 1e-8) { + t.Errorf("Answer mismatch when SVDFull") + } + + // Test Thin decomposition. + ok = svd.Factorize(a, matrix.SVDThin) + if !ok { + t.Errorf("SVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to SVD with Thin") + } + sThin, u, v := extractSVD(&svd) + if !floats.EqualApprox(s, sThin, 1e-8) { + t.Errorf("Singular value mismatch between Full and Thin decomposition") + } + sigma = NewDense(min(m, n), min(m, n), nil) + for i := 0; i < min(m, n); i++ { + sigma.Set(i, i, sThin[i]) + } + ansFull.Reset() + ansFull.Product(u, sigma, v.T()) + if !EqualApprox(&ansFull, a, 1e-8) { + t.Errorf("Answer mismatch when SVDFull") + } + + // Test None decomposition. + ok = svd.Factorize(a, matrix.SVDNone) + if !ok { + t.Errorf("SVD factorization failed") + } + if !Equal(a, aCopy) { + t.Errorf("A changed during call to SVD with none") + } + sNone := make([]float64, min(m, n)) + svd.Values(sNone) + if !floats.EqualApprox(s, sNone, 1e-8) { + t.Errorf("Singular value mismatch between Full and None decomposition") + } + } + } +} + +func extractSVD(svd *SVD) (s []float64, u, v *Dense) { + var um, vm Dense + um.UFromSVD(svd) + vm.VFromSVD(svd) + s = svd.Values(nil) + return s, &um, &vm +} diff --git a/matrix/mat64/symmetric.go b/matrix/mat64/symmetric.go new file mode 100644 index 00000000..e72f5165 --- /dev/null +++ b/matrix/mat64/symmetric.go @@ -0,0 +1,504 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/matrix" +) + +var ( + symDense *SymDense + + _ Matrix = symDense + _ Symmetric = symDense + _ RawSymmetricer = symDense + _ MutableSymmetric = symDense +) + +const ( + badSymTriangle = "mat64: blas64.Symmetric not upper" + badSymCap = "mat64: bad capacity for SymDense" +) + +// SymDense is a symmetric matrix that uses dense storage. SymDense +// matrices are stored in the upper triangle. +type SymDense struct { + mat blas64.Symmetric + cap int +} + +// Symmetric represents a symmetric matrix (where the element at {i, j} equals +// the element at {j, i}). Symmetric matrices are always square. +type Symmetric interface { + Matrix + // Symmetric returns the number of rows/columns in the matrix. + Symmetric() int +} + +// A RawSymmetricer can return a view of itself as a BLAS Symmetric matrix. +type RawSymmetricer interface { + RawSymmetric() blas64.Symmetric +} + +type MutableSymmetric interface { + Symmetric + SetSym(i, j int, v float64) +} + +// NewSymDense creates a new Symmetric matrix with n rows and columns. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == n*n, data is +// used as the backing slice, and changes to the elements of the returned SymDense +// will be reflected in data. If neither of these is true, NewSymDense will panic. +// +// The data must be arranged in row-major order, i.e. the (i*c + j)-th +// element in the data slice is the {i, j}-th element in the matrix. +// Only the values in the upper triangular portion of the matrix are used. +func NewSymDense(n int, data []float64) *SymDense { + if n < 0 { + panic("mat64: negative dimension") + } + if data != nil && n*n != len(data) { + panic(matrix.ErrShape) + } + if data == nil { + data = make([]float64, n*n) + } + return &SymDense{ + mat: blas64.Symmetric{ + N: n, + Stride: n, + Data: data, + Uplo: blas.Upper, + }, + cap: n, + } +} + +func (s *SymDense) Dims() (r, c int) { + return s.mat.N, s.mat.N +} + +// T implements the Matrix interface. Symmetric matrices, by definition, are +// equal to their transpose, and this is a no-op. +func (s *SymDense) T() Matrix { + return s +} + +func (s *SymDense) Symmetric() int { + return s.mat.N +} + +// RawSymmetric returns the matrix as a blas64.Symmetric. The returned +// value must be stored in upper triangular format. +func (s *SymDense) RawSymmetric() blas64.Symmetric { + return s.mat +} + +// SetRawSymmetric sets the underlying blas64.Symmetric used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in b. SetRawSymmetric will panic if b is not an upper-encoded symmetric +// matrix. +func (s *SymDense) SetRawSymmetric(b blas64.Symmetric) { + if b.Uplo != blas.Upper { + panic(badSymTriangle) + } + s.mat = b +} + +// Reset zeros the dimensions of the matrix so that it can be reused as the +// receiver of a dimensionally restricted operation. +// +// See the Reseter interface for more information. +func (s *SymDense) Reset() { + // N and Stride must be zeroed in unison. + s.mat.N, s.mat.Stride = 0, 0 + s.mat.Data = s.mat.Data[:0] +} + +func (s *SymDense) isZero() bool { + // It must be the case that m.Dims() returns + // zeros in this case. See comment in Reset(). + return s.mat.N == 0 +} + +// reuseAs resizes an empty matrix to a n×n matrix, +// or checks that a non-empty matrix is n×n. +func (s *SymDense) reuseAs(n int) { + if s.mat.N > s.cap { + panic(badSymCap) + } + if s.isZero() { + s.mat = blas64.Symmetric{ + N: n, + Stride: n, + Data: use(s.mat.Data, n*n), + Uplo: blas.Upper, + } + s.cap = n + return + } + if s.mat.Uplo != blas.Upper { + panic(badSymTriangle) + } + if s.mat.N != n { + panic(matrix.ErrShape) + } +} + +func (s *SymDense) isolatedWorkspace(a Symmetric) (w *SymDense, restore func()) { + n := a.Symmetric() + w = getWorkspaceSym(n, false) + return w, func() { + s.CopySym(w) + putWorkspaceSym(w) + } +} + +func (s *SymDense) AddSym(a, b Symmetric) { + n := a.Symmetric() + if n != b.Symmetric() { + panic(matrix.ErrShape) + } + s.reuseAs(n) + + if a, ok := a.(RawSymmetricer); ok { + if b, ok := b.(RawSymmetricer); ok { + amat, bmat := a.RawSymmetric(), b.RawSymmetric() + if s != a { + s.checkOverlap(amat) + } + if s != b { + s.checkOverlap(bmat) + } + for i := 0; i < n; i++ { + btmp := bmat.Data[i*bmat.Stride+i : i*bmat.Stride+n] + stmp := s.mat.Data[i*s.mat.Stride+i : i*s.mat.Stride+n] + for j, v := range amat.Data[i*amat.Stride+i : i*amat.Stride+n] { + stmp[j] = v + btmp[j] + } + } + return + } + } + + for i := 0; i < n; i++ { + stmp := s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+n] + for j := i; j < n; j++ { + stmp[j] = a.At(i, j) + b.At(i, j) + } + } +} + +func (s *SymDense) CopySym(a Symmetric) int { + n := a.Symmetric() + n = min(n, s.mat.N) + if n == 0 { + return 0 + } + switch a := a.(type) { + case RawSymmetricer: + amat := a.RawSymmetric() + if amat.Uplo != blas.Upper { + panic(badSymTriangle) + } + for i := 0; i < n; i++ { + copy(s.mat.Data[i*s.mat.Stride+i:i*s.mat.Stride+n], amat.Data[i*amat.Stride+i:i*amat.Stride+n]) + } + default: + for i := 0; i < n; i++ { + stmp := s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+n] + for j := i; j < n; j++ { + stmp[j] = a.At(i, j) + } + } + } + return n +} + +// SymRankOne performs a symetric rank-one update to the matrix a and stores +// the result in the receiver +// s = a + alpha * x * x' +func (s *SymDense) SymRankOne(a Symmetric, alpha float64, x *Vector) { + n := x.Len() + if a.Symmetric() != n { + panic(matrix.ErrShape) + } + s.reuseAs(n) + if s != a { + if rs, ok := a.(RawSymmetricer); ok { + s.checkOverlap(rs.RawSymmetric()) + } + s.CopySym(a) + } + blas64.Syr(alpha, x.mat, s.mat) +} + +// SymRankK performs a symmetric rank-k update to the matrix a and stores the +// result into the receiver. If a is zero, see SymOuterK. +// s = a + alpha * x * x' +func (s *SymDense) SymRankK(a Symmetric, alpha float64, x Matrix) { + n := a.Symmetric() + r, _ := x.Dims() + if r != n { + panic(matrix.ErrShape) + } + xMat, aTrans := untranspose(x) + var g blas64.General + if rm, ok := xMat.(RawMatrixer); ok { + g = rm.RawMatrix() + } else { + g = DenseCopyOf(x).mat + aTrans = false + } + if a != s { + if rs, ok := a.(RawSymmetricer); ok { + s.checkOverlap(rs.RawSymmetric()) + } + s.reuseAs(n) + s.CopySym(a) + } + t := blas.NoTrans + if aTrans { + t = blas.Trans + } + blas64.Syrk(t, alpha, g, 1, s.mat) +} + +// SymOuterK calculates the outer product of x with itself and stores +// the result into the receiver. It is equivalent to the matrix +// multiplication +// s = alpha * x * x'. +// In order to update an existing matrix, see SymRankOne. +func (s *SymDense) SymOuterK(alpha float64, x Matrix) { + n, _ := x.Dims() + switch { + case s.isZero(): + s.mat = blas64.Symmetric{ + N: n, + Stride: n, + Data: useZeroed(s.mat.Data, n*n), + Uplo: blas.Upper, + } + s.cap = n + s.SymRankK(s, alpha, x) + case s.mat.Uplo != blas.Upper: + panic(badSymTriangle) + case s.mat.N == n: + if s == x { + w := getWorkspaceSym(n, true) + w.SymRankK(w, alpha, x) + s.CopySym(w) + putWorkspaceSym(w) + } else { + if rs, ok := x.(RawSymmetricer); ok { + s.checkOverlap(rs.RawSymmetric()) + } + // Only zero the upper triangle. + for i := 0; i < n; i++ { + ri := i * s.mat.Stride + zero(s.mat.Data[ri+i : ri+n]) + } + s.SymRankK(s, alpha, x) + } + default: + panic(matrix.ErrShape) + } +} + +// RankTwo performs a symmmetric rank-two update to the matrix a and stores +// the result in the receiver +// m = a + alpha * (x * y' + y * x') +func (s *SymDense) RankTwo(a Symmetric, alpha float64, x, y *Vector) { + n := s.mat.N + if x.Len() != n { + panic(matrix.ErrShape) + } + if y.Len() != n { + panic(matrix.ErrShape) + } + var w SymDense + if s == a { + w = *s + } + w.reuseAs(n) + if s != a { + if rs, ok := a.(RawSymmetricer); ok { + s.checkOverlap(rs.RawSymmetric()) + } + w.CopySym(a) + } + blas64.Syr2(alpha, x.mat, y.mat, w.mat) + *s = w + return +} + +// ScaleSym multiplies the elements of a by f, placing the result in the receiver. +func (s *SymDense) ScaleSym(f float64, a Symmetric) { + n := a.Symmetric() + s.reuseAs(n) + if a, ok := a.(RawSymmetricer); ok { + amat := a.RawSymmetric() + if s != a { + s.checkOverlap(amat) + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.mat.Data[i*s.mat.Stride+j] = f * amat.Data[i*amat.Stride+j] + } + } + return + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.mat.Data[i*s.mat.Stride+j] = f * a.At(i, j) + } + } +} + +// SubsetSym extracts a subset of the rows and columns of the matrix a and stores +// the result in-place into the receiver. The resulting matrix size is +// len(set)×len(set). Specifically, at the conclusion of SubsetSym, +// s.At(i, j) equals a.At(set[i], set[j]). Note that the supplied set does not +// have to be a strict subset, dimension repeats are allowed. +func (s *SymDense) SubsetSym(a Symmetric, set []int) { + n := len(set) + na := a.Symmetric() + s.reuseAs(n) + var restore func() + if a == s { + s, restore = s.isolatedWorkspace(a) + defer restore() + } + + if a, ok := a.(RawSymmetricer); ok { + raw := a.RawSymmetric() + if s != a { + s.checkOverlap(raw) + } + for i := 0; i < n; i++ { + ssub := s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+n] + r := set[i] + rsub := raw.Data[r*raw.Stride : r*raw.Stride+na] + for j := i; j < n; j++ { + c := set[j] + if r <= c { + ssub[j] = rsub[c] + } else { + ssub[j] = raw.Data[c*raw.Stride+r] + } + } + } + return + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.mat.Data[i*s.mat.Stride+j] = a.At(set[i], set[j]) + } + } +} + +// ViewSquare returns a view of the submatrix starting at {i, i} and extending +// for n rows and columns. ViewSquare panics if the view is outside the bounds +// of the receiver. +// +// ViewSquare is deprecated and should not be used. It will be removed at a later date. +func (s *SymDense) ViewSquare(i, n int) Matrix { + return s.SliceSquare(i, i+n) +} + +// SliceSquare returns a new Matrix that shares backing data with the receiver. +// The returned matrix starts at {i,i} of the recevier and extends k-i rows +// and columns. The final row and column in the resulting matrix is k-1. +// SliceSquare panics with ErrIndexOutOfRange if the slice is outside the bounds +// of the receiver. +func (s *SymDense) SliceSquare(i, k int) Matrix { + sz := s.Symmetric() + if i < 0 || sz < i || k < i || sz < k { + panic(matrix.ErrIndexOutOfRange) + } + v := *s + v.mat.Data = s.mat.Data[i*s.mat.Stride+i : (k-1)*s.mat.Stride+k] + v.mat.N = k - i + v.cap = s.cap - i + return &v +} + +// GrowSquare returns the receiver expanded by n rows and n columns. If the +// dimensions of the expanded matrix are outside the capacity of the receiver +// a new allocation is made, otherwise not. Note that the receiver itself is +// not modified during the call to GrowSquare. +func (s *SymDense) GrowSquare(n int) Matrix { + if n < 0 { + panic(matrix.ErrIndexOutOfRange) + } + if n == 0 { + return s + } + var v SymDense + n += s.mat.N + if n > s.cap { + v.mat = blas64.Symmetric{ + N: n, + Stride: n, + Uplo: blas.Upper, + Data: make([]float64, n*n), + } + v.cap = n + // Copy elements, including those not currently visible. Use a temporary + // structure to avoid modifying the receiver. + var tmp SymDense + tmp.mat = blas64.Symmetric{ + N: s.cap, + Stride: s.mat.Stride, + Data: s.mat.Data, + Uplo: s.mat.Uplo, + } + tmp.cap = s.cap + v.CopySym(&tmp) + return &v + } + v.mat = blas64.Symmetric{ + N: n, + Stride: s.mat.Stride, + Uplo: blas.Upper, + Data: s.mat.Data[:(n-1)*s.mat.Stride+n], + } + v.cap = s.cap + return &v +} + +// PowPSD computes a^pow where a is a positive symmetric definite matrix. +// +// PowPSD returns an error if the matrix is not not positive symmetric definite +// or the Eigendecomposition is not successful. +func (s *SymDense) PowPSD(a Symmetric, pow float64) error { + dim := a.Symmetric() + s.reuseAs(dim) + + var eigen EigenSym + ok := eigen.Factorize(a, true) + if !ok { + return matrix.ErrFailedEigen + } + values := eigen.Values(nil) + for i, v := range values { + if v <= 0 { + return matrix.ErrNotPSD + } + values[i] = math.Pow(v, pow) + } + var u Dense + u.EigenvectorsSym(&eigen) + + s.SymOuterK(values[0], u.ColView(0)) + for i := 1; i < dim; i++ { + s.SymRankOne(s, values[i], u.ColView(i)) + } + return nil +} diff --git a/matrix/mat64/symmetric_example_test.go b/matrix/mat64/symmetric_example_test.go new file mode 100644 index 00000000..f545da0a --- /dev/null +++ b/matrix/mat64/symmetric_example_test.go @@ -0,0 +1,50 @@ +package mat64_test + +import ( + "fmt" + + "gonum.org/v1/gonum/matrix/mat64" +) + +func ExampleSymDense_SubsetSym() { + n := 5 + s := mat64.NewSymDense(5, nil) + count := 1.0 + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.SetSym(i, j, count) + count++ + } + } + fmt.Println("Original matrix:") + fmt.Printf("%0.4v\n\n", mat64.Formatted(s)) + + // Take the subset {0, 2, 4} + var sub mat64.SymDense + sub.SubsetSym(s, []int{0, 2, 4}) + fmt.Println("Subset {0, 2, 4}") + fmt.Printf("%0.4v\n\n", mat64.Formatted(&sub)) + + // Take the subset {0, 0, 4} + sub.SubsetSym(s, []int{0, 0, 4}) + fmt.Println("Subset {0, 0, 4}") + fmt.Printf("%0.4v\n\n", mat64.Formatted(&sub)) + + // Output: + // Original matrix: + // ⎡ 1 2 3 4 5⎤ + // ⎢ 2 6 7 8 9⎥ + // ⎢ 3 7 10 11 12⎥ + // ⎢ 4 8 11 13 14⎥ + // ⎣ 5 9 12 14 15⎦ + // + // Subset {0, 2, 4} + // ⎡ 1 3 5⎤ + // ⎢ 3 10 12⎥ + // ⎣ 5 12 15⎦ + // + // Subset {0, 0, 4} + // ⎡ 1 1 5⎤ + // ⎢ 1 1 5⎥ + // ⎣ 5 5 15⎦ +} diff --git a/matrix/mat64/symmetric_test.go b/matrix/mat64/symmetric_test.go new file mode 100644 index 00000000..06be63f0 --- /dev/null +++ b/matrix/mat64/symmetric_test.go @@ -0,0 +1,695 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "fmt" + "math/rand" + "os" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix" +) + +func TestNewSymmetric(t *testing.T) { + for i, test := range []struct { + data []float64 + n int + mat *SymDense + }{ + { + data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }, + n: 3, + mat: &SymDense{ + mat: blas64.Symmetric{ + N: 3, + Stride: 3, + Uplo: blas.Upper, + Data: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + }, + cap: 3, + }, + }, + } { + sym := NewSymDense(test.n, test.data) + rows, cols := sym.Dims() + + if rows != test.n { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.n) + } + if cols != test.n { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.n) + } + if !reflect.DeepEqual(sym, test.mat) { + t.Errorf("unexpected data slice for test %d: got: %v want: %v", i, sym, test.mat) + } + + m := NewDense(test.n, test.n, test.data) + if !reflect.DeepEqual(sym.mat.Data, m.mat.Data) { + t.Errorf("unexpected data slice mismatch for test %d: got: %v want: %v", i, sym.mat.Data, m.mat.Data) + } + } + + panicked, message := panics(func() { NewSymDense(3, []float64{1, 2}) }) + if !panicked || message != matrix.ErrShape.Error() { + t.Error("expected panic for invalid data slice length") + } +} + +func TestSymAtSet(t *testing.T) { + sym := &SymDense{ + mat: blas64.Symmetric{ + N: 3, + Stride: 3, + Uplo: blas.Upper, + Data: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + }, + cap: 3, + } + rows, cols := sym.Dims() + + // Check At out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { sym.At(row, 0) }) + if !panicked || message != matrix.ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { sym.At(0, col) }) + if !panicked || message != matrix.ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + // Check Set out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { sym.SetSym(row, 0, 1.2) }) + if !panicked || message != matrix.ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { sym.SetSym(0, col, 1.2) }) + if !panicked || message != matrix.ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + for _, st := range []struct { + row, col int + orig, new float64 + }{ + {row: 1, col: 2, orig: 6, new: 15}, + {row: 2, col: 1, orig: 15, new: 12}, + } { + if e := sym.At(st.row, st.col); e != st.orig { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", st.row, st.col, e, st.orig) + } + if e := sym.At(st.col, st.row); e != st.orig { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", st.col, st.row, e, st.orig) + } + sym.SetSym(st.row, st.col, st.new) + if e := sym.At(st.row, st.col); e != st.new { + t.Errorf("unexpected value for At(%d, %d) after SetSym(%[1]d, %[2]d, %[4]v): got: %[3]v want: %v", st.row, st.col, e, st.new) + } + if e := sym.At(st.col, st.row); e != st.new { + t.Errorf("unexpected value for At(%d, %d) after SetSym(%[2]d, %[1]d, %[4]v): got: %[3]v want: %v", st.col, st.row, e, st.new) + } + } +} + +func TestSymAdd(t *testing.T) { + for _, test := range []struct { + n int + }{ + {n: 1}, + {n: 2}, + {n: 3}, + {n: 4}, + {n: 5}, + {n: 10}, + } { + n := test.n + a := NewSymDense(n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.Float64() + } + b := NewSymDense(n, nil) + for i := range a.mat.Data { + b.mat.Data[i] = rand.Float64() + } + var m Dense + m.Add(a, b) + + // Check with new receiver + var s SymDense + s.AddSym(a, b) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := m.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + + // Check with equal receiver + s.CopySym(a) + s.AddSym(&s, b) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := m.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + } + + method := func(receiver, a, b Matrix) { + type addSymer interface { + AddSym(a, b Symmetric) + } + rd := receiver.(addSymer) + rd.AddSym(a.(Symmetric), b.(Symmetric)) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Add(a, b) + } + testTwoInput(t, "AddSym", &SymDense{}, method, denseComparison, legalTypesSym, legalSizeSameSquare, 1e-14) +} + +func TestCopy(t *testing.T) { + for _, test := range []struct { + n int + }{ + {n: 1}, + {n: 2}, + {n: 3}, + {n: 4}, + {n: 5}, + {n: 10}, + } { + n := test.n + a := NewSymDense(n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.Float64() + } + s := NewSymDense(n, nil) + s.CopySym(a) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := a.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + } +} + +// TODO(kortschak) Roll this into testOneInput when it exists. +// https://github.com/gonum/matrix/issues/171 +func TestSymCopyPanic(t *testing.T) { + var ( + a SymDense + n int + ) + m := NewSymDense(1, nil) + panicked, message := panics(func() { n = m.CopySym(&a) }) + if panicked { + t.Errorf("unexpected panic: %v", message) + } + if n != 0 { + t.Errorf("unexpected n: got: %d want: 0", n) + } +} + +func TestSymRankOne(t *testing.T) { + for _, test := range []struct { + n int + }{ + {n: 1}, + {n: 2}, + {n: 3}, + {n: 4}, + {n: 5}, + {n: 10}, + } { + n := test.n + alpha := 2.0 + a := NewSymDense(n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.Float64() + } + x := make([]float64, n) + for i := range x { + x[i] = rand.Float64() + } + + xMat := NewDense(n, 1, x) + var m Dense + m.Mul(xMat, xMat.T()) + m.Scale(alpha, &m) + m.Add(&m, a) + + // Check with new receiver + s := NewSymDense(n, nil) + s.SymRankOne(a, alpha, NewVector(len(x), x)) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := m.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + + // Check with reused receiver + copy(s.mat.Data, a.mat.Data) + s.SymRankOne(s, alpha, NewVector(len(x), x)) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + want := m.At(i, j) + if got := s.At(i, j); got != want { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", i, j, got, want) + } + } + } + } + + alpha := 3.0 + method := func(receiver, a, b Matrix) { + type SymRankOner interface { + SymRankOne(a Symmetric, alpha float64, x *Vector) + } + rd := receiver.(SymRankOner) + rd.SymRankOne(a.(Symmetric), alpha, b.(*Vector)) + } + denseComparison := func(receiver, a, b *Dense) { + var tmp Dense + tmp.Mul(b, b.T()) + tmp.Scale(alpha, &tmp) + receiver.Add(a, &tmp) + } + legalTypes := func(a, b Matrix) bool { + _, ok := a.(Symmetric) + if !ok { + return false + } + _, ok = b.(*Vector) + return ok + } + legalSize := func(ar, ac, br, bc int) bool { + if ar != ac { + return false + } + return br == ar + } + testTwoInput(t, "SymRankOne", &SymDense{}, method, denseComparison, legalTypes, legalSize, 1e-14) +} + +func TestIssue250SymRankOne(t *testing.T) { + x := NewVector(5, []float64{1, 2, 3, 4, 5}) + var s1, s2 SymDense + s1.SymRankOne(NewSymDense(5, nil), 1, x) + s2.SymRankOne(NewSymDense(5, nil), 1, x) + s2.SymRankOne(NewSymDense(5, nil), 1, x) + if !Equal(&s1, &s2) { + t.Error("unexpected result from repeat") + } +} + +func TestRankTwo(t *testing.T) { + for _, test := range []struct { + n int + }{ + {n: 1}, + {n: 2}, + {n: 3}, + {n: 4}, + {n: 5}, + {n: 10}, + } { + n := test.n + alpha := 2.0 + a := NewSymDense(n, nil) + for i := range a.mat.Data { + a.mat.Data[i] = rand.Float64() + } + x := make([]float64, n) + y := make([]float64, n) + for i := range x { + x[i] = rand.Float64() + y[i] = rand.Float64() + } + + xMat := NewDense(n, 1, x) + yMat := NewDense(n, 1, y) + var m Dense + m.Mul(xMat, yMat.T()) + var tmp Dense + tmp.Mul(yMat, xMat.T()) + m.Add(&m, &tmp) + m.Scale(alpha, &m) + m.Add(&m, a) + + // Check with new receiver + s := NewSymDense(n, nil) + s.RankTwo(a, alpha, NewVector(len(x), x), NewVector(len(y), y)) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + if !floats.EqualWithinAbsOrRel(s.At(i, j), m.At(i, j), 1e-14, 1e-14) { + t.Errorf("unexpected element value at (%d,%d): got: %f want: %f", i, j, m.At(i, j), s.At(i, j)) + } + } + } + + // Check with reused receiver + copy(s.mat.Data, a.mat.Data) + s.RankTwo(s, alpha, NewVector(len(x), x), NewVector(len(y), y)) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + if !floats.EqualWithinAbsOrRel(s.At(i, j), m.At(i, j), 1e-14, 1e-14) { + t.Errorf("unexpected element value at (%d,%d): got: %f want: %f", i, j, m.At(i, j), s.At(i, j)) + } + } + } + } +} + +func TestSymRankK(t *testing.T) { + alpha := 3.0 + method := func(receiver, a, b Matrix) { + type SymRankKer interface { + SymRankK(a Symmetric, alpha float64, x Matrix) + } + rd := receiver.(SymRankKer) + rd.SymRankK(a.(Symmetric), alpha, b) + } + denseComparison := func(receiver, a, b *Dense) { + var tmp Dense + tmp.Mul(b, b.T()) + tmp.Scale(alpha, &tmp) + receiver.Add(a, &tmp) + } + legalTypes := func(a, b Matrix) bool { + _, ok := a.(Symmetric) + return ok + } + legalSize := func(ar, ac, br, bc int) bool { + if ar != ac { + return false + } + return br == ar + } + testTwoInput(t, "SymRankK", &SymDense{}, method, denseComparison, legalTypes, legalSize, 1e-14) +} + +func TestSymOuterK(t *testing.T) { + for _, f := range []float64{0.5, 1, 3} { + method := func(receiver, x Matrix) { + type SymOuterKer interface { + SymOuterK(alpha float64, x Matrix) + } + rd := receiver.(SymOuterKer) + rd.SymOuterK(f, x) + } + denseComparison := func(receiver, x *Dense) { + receiver.Mul(x, x.T()) + receiver.Scale(f, receiver) + } + testOneInput(t, "SymOuterK", &SymDense{}, method, denseComparison, isAnyType, isAnySize, 1e-14) + } +} + +func TestIssue250SymOuterK(t *testing.T) { + x := NewVector(5, []float64{1, 2, 3, 4, 5}) + var s1, s2 SymDense + s1.SymOuterK(1, x) + s2.SymOuterK(1, x) + s2.SymOuterK(1, x) + if !Equal(&s1, &s2) { + t.Error("unexpected result from repeat") + } +} + +func TestScaleSym(t *testing.T) { + for _, f := range []float64{0.5, 1, 3} { + method := func(receiver, a Matrix) { + type ScaleSymer interface { + ScaleSym(f float64, a Symmetric) + } + rd := receiver.(ScaleSymer) + rd.ScaleSym(f, a.(Symmetric)) + } + denseComparison := func(receiver, a *Dense) { + receiver.Scale(f, a) + } + testOneInput(t, "ScaleSym", &SymDense{}, method, denseComparison, legalTypeSym, isSquare, 1e-14) + } +} + +func TestSubsetSym(t *testing.T) { + for _, test := range []struct { + a *SymDense + dims []int + ans *SymDense + }{ + { + a: NewSymDense(3, []float64{ + 1, 2, 3, + 0, 4, 5, + 0, 0, 6, + }), + dims: []int{0, 2}, + ans: NewSymDense(2, []float64{ + 1, 3, + 0, 6, + }), + }, + { + a: NewSymDense(3, []float64{ + 1, 2, 3, + 0, 4, 5, + 0, 0, 6, + }), + dims: []int{2, 0}, + ans: NewSymDense(2, []float64{ + 6, 3, + 0, 1, + }), + }, + { + a: NewSymDense(3, []float64{ + 1, 2, 3, + 0, 4, 5, + 0, 0, 6, + }), + dims: []int{1, 1, 1}, + ans: NewSymDense(3, []float64{ + 4, 4, 4, + 0, 4, 4, + 0, 0, 4, + }), + }, + } { + var s SymDense + s.SubsetSym(test.a, test.dims) + if !Equal(&s, test.ans) { + t.Errorf("SubsetSym mismatch dims %v\nGot:\n% v\nWant:\n% v\n", test.dims, s, test.ans) + } + } + + dims := []int{0, 2} + maxDim := dims[0] + for _, v := range dims { + if maxDim < v { + maxDim = v + } + } + method := func(receiver, a Matrix) { + type SubsetSymer interface { + SubsetSym(a Symmetric, set []int) + } + rd := receiver.(SubsetSymer) + rd.SubsetSym(a.(Symmetric), dims) + } + denseComparison := func(receiver, a *Dense) { + *receiver = *NewDense(len(dims), len(dims), nil) + sz := len(dims) + for i := 0; i < sz; i++ { + for j := 0; j < sz; j++ { + receiver.Set(i, j, a.At(dims[i], dims[j])) + } + } + } + legalSize := func(ar, ac int) bool { + return ar == ac && ar > maxDim + } + + testOneInput(t, "SubsetSym", &SymDense{}, method, denseComparison, legalTypeSym, legalSize, 0) +} + +func TestViewGrowSquare(t *testing.T) { + // n is the size of the original SymDense. + // The first view uses start1, span1. The second view uses start2, span2 on + // the first view. + for _, test := range []struct { + n, start1, span1, start2, span2 int + }{ + {10, 0, 10, 0, 10}, + {10, 0, 8, 0, 8}, + {10, 2, 8, 0, 6}, + {10, 2, 7, 4, 2}, + {10, 2, 6, 0, 5}, + } { + n := test.n + s := NewSymDense(n, nil) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + s.SetSym(i, j, float64((i+1)*n+j+1)) + } + } + + // Take a subset and check the view matches. + start1 := test.start1 + span1 := test.span1 + v := s.SliceSquare(start1, start1+span1).(*SymDense) + for i := 0; i < span1; i++ { + for j := i; j < span1; j++ { + if v.At(i, j) != s.At(start1+i, start1+j) { + t.Errorf("View mismatch") + } + } + } + + start2 := test.start2 + span2 := test.span2 + v2 := v.SliceSquare(start2, start2+span2).(*SymDense) + + for i := 0; i < span2; i++ { + for j := i; j < span2; j++ { + if v2.At(i, j) != s.At(start1+start2+i, start1+start2+j) { + t.Errorf("Second view mismatch") + } + } + } + + // Check that a write to the view is reflected in the original. + v2.SetSym(0, 0, 1.2) + if s.At(start1+start2, start1+start2) != 1.2 { + t.Errorf("Write to view not reflected in original") + } + + // Grow the matrix back to the original view + gn := n - start1 - start2 + g := v2.GrowSquare(gn - v2.Symmetric()).(*SymDense) + g.SetSym(1, 1, 2.2) + + for i := 0; i < gn; i++ { + for j := 0; j < gn; j++ { + if g.At(i, j) != s.At(start1+start2+i, start1+start2+j) { + t.Errorf("Grow mismatch") + + fmt.Printf("g=\n% v\n", Formatted(g)) + fmt.Printf("s=\n% v\n", Formatted(s)) + os.Exit(1) + } + } + } + + // View g, then grow it and make sure all the elements were copied. + gv := g.SliceSquare(0, gn-1).(*SymDense) + + gg := gv.GrowSquare(2) + for i := 0; i < gn; i++ { + for j := 0; j < gn; j++ { + if g.At(i, j) != gg.At(i, j) { + t.Errorf("Expand mismatch") + } + } + } + } +} + +func TestPowPSD(t *testing.T) { + for cas, test := range []struct { + a *SymDense + pow float64 + ans *SymDense + }{ + // Comparison with Matlab. + { + a: NewSymDense(2, []float64{10, 5, 5, 12}), + pow: 0.5, + ans: NewSymDense(2, []float64{3.065533767740645, 0.776210486171016, 0.776210486171016, 3.376017962209052}), + }, + { + a: NewSymDense(2, []float64{11, -1, -1, 8}), + pow: 0.5, + ans: NewSymDense(2, []float64{3.312618742210524, -0.162963396980939, -0.162963396980939, 2.823728551267709}), + }, + { + a: NewSymDense(2, []float64{10, 5, 5, 12}), + pow: -0.5, + ans: NewSymDense(2, []float64{0.346372134547712, -0.079637515547296, -0.079637515547296, 0.314517128328794}), + }, + { + a: NewSymDense(3, []float64{15, -1, -3, -1, 8, 6, -3, 6, 14}), + pow: 0.6, + ans: NewSymDense(3, []float64{ + 5.051214323034288, -0.163162161893975, -0.612153996497505, + -0.163162161893976, 3.283474884617009, 1.432842761381493, + -0.612153996497505, 1.432842761381494, 4.695873060862573, + }), + }, + } { + var s SymDense + err := s.PowPSD(test.a, test.pow) + if err != nil { + panic("bad test") + } + if !EqualApprox(&s, test.ans, 1e-10) { + t.Errorf("Case %d, pow mismatch", cas) + fmt.Println(Formatted(&s)) + fmt.Println(Formatted(test.ans)) + } + } + + // Compare with Dense.Pow + rnd := rand.New(rand.NewSource(1)) + for dim := 2; dim < 10; dim++ { + for pow := 2; pow < 6; pow++ { + a := NewDense(dim, dim, nil) + for i := 0; i < dim; i++ { + for j := 0; j < dim; j++ { + a.Set(i, j, rnd.Float64()) + } + } + var mat SymDense + mat.SymOuterK(1, a) + + var sym SymDense + sym.PowPSD(&mat, float64(pow)) + + var dense Dense + dense.Pow(&mat, pow) + + if !EqualApprox(&sym, &dense, 1e-10) { + t.Errorf("Dim %d: pow mismatch") + } + } + } +} diff --git a/matrix/mat64/triangular.go b/matrix/mat64/triangular.go new file mode 100644 index 00000000..76016e83 --- /dev/null +++ b/matrix/mat64/triangular.go @@ -0,0 +1,450 @@ +package mat64 + +import ( + "math" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/lapack/lapack64" + "gonum.org/v1/gonum/matrix" +) + +var ( + triDense *TriDense + _ Matrix = triDense + _ Triangular = triDense + _ RawTriangular = triDense +) + +const badTriCap = "mat64: bad capacity for TriDense" + +// TriDense represents an upper or lower triangular matrix in dense storage +// format. +type TriDense struct { + mat blas64.Triangular + cap int +} + +type Triangular interface { + Matrix + // Triangular returns the number of rows/columns in the matrix and its + // orientation. + Triangle() (n int, kind matrix.TriKind) + + // TTri is the equivalent of the T() method in the Matrix interface but + // guarantees the transpose is of triangular type. + TTri() Triangular +} + +type RawTriangular interface { + RawTriangular() blas64.Triangular +} + +var ( + _ Matrix = TransposeTri{} + _ Triangular = TransposeTri{} + _ UntransposeTrier = TransposeTri{} +) + +// TransposeTri is a type for performing an implicit transpose of a Triangular +// matrix. It implements the Triangular interface, returning values from the +// transpose of the matrix within. +type TransposeTri struct { + Triangular Triangular +} + +// At returns the value of the element at row i and column j of the transposed +// matrix, that is, row j and column i of the Triangular field. +func (t TransposeTri) At(i, j int) float64 { + return t.Triangular.At(j, i) +} + +// Dims returns the dimensions of the transposed matrix. Triangular matrices are +// square and thus this is the same size as the original Triangular. +func (t TransposeTri) Dims() (r, c int) { + c, r = t.Triangular.Dims() + return r, c +} + +// T performs an implicit transpose by returning the Triangular field. +func (t TransposeTri) T() Matrix { + return t.Triangular +} + +// Triangle returns the number of rows/columns in the matrix and its orientation. +func (t TransposeTri) Triangle() (int, matrix.TriKind) { + n, upper := t.Triangular.Triangle() + return n, !upper +} + +// TTri performs an implicit transpose by returning the Triangular field. +func (t TransposeTri) TTri() Triangular { + return t.Triangular +} + +// Untranspose returns the Triangular field. +func (t TransposeTri) Untranspose() Matrix { + return t.Triangular +} + +func (t TransposeTri) UntransposeTri() Triangular { + return t.Triangular +} + +// NewTriDense creates a new Triangular matrix with n rows and columns. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == n*n, data is +// used as the backing slice, and changes to the elements of the returned TriDense +// will be reflected in data. If neither of these is true, NewTriDense will panic. +// +// The data must be arranged in row-major order, i.e. the (i*c + j)-th +// element in the data slice is the {i, j}-th element in the matrix. +// Only the values in the triangular portion corresponding to kind are used. +func NewTriDense(n int, kind matrix.TriKind, data []float64) *TriDense { + if n < 0 { + panic("mat64: negative dimension") + } + if data != nil && len(data) != n*n { + panic(matrix.ErrShape) + } + if data == nil { + data = make([]float64, n*n) + } + uplo := blas.Lower + if kind == matrix.Upper { + uplo = blas.Upper + } + return &TriDense{ + mat: blas64.Triangular{ + N: n, + Stride: n, + Data: data, + Uplo: uplo, + Diag: blas.NonUnit, + }, + cap: n, + } +} + +func (t *TriDense) Dims() (r, c int) { + return t.mat.N, t.mat.N +} + +// Triangle returns the dimension of t and its orientation. The returned +// orientation is only valid when n is not zero. +func (t *TriDense) Triangle() (n int, kind matrix.TriKind) { + return t.mat.N, matrix.TriKind(!t.isZero()) && t.triKind() +} + +func (t *TriDense) isUpper() bool { + return isUpperUplo(t.mat.Uplo) +} + +func (t *TriDense) triKind() matrix.TriKind { + return matrix.TriKind(isUpperUplo(t.mat.Uplo)) +} + +func isUpperUplo(u blas.Uplo) bool { + switch u { + case blas.Upper: + return true + case blas.Lower: + return false + default: + panic(badTriangle) + } +} + +// asSymBlas returns the receiver restructured as a blas64.Symmetric with the +// same backing memory. Panics if the receiver is unit. +// This returns a blas64.Symmetric and not a *SymDense because SymDense can only +// be upper triangular. +func (t *TriDense) asSymBlas() blas64.Symmetric { + if t.mat.Diag == blas.Unit { + panic("mat64: cannot convert unit TriDense into blas64.Symmetric") + } + return blas64.Symmetric{ + N: t.mat.N, + Stride: t.mat.Stride, + Data: t.mat.Data, + Uplo: t.mat.Uplo, + } +} + +// T performs an implicit transpose by returning the receiver inside a Transpose. +func (t *TriDense) T() Matrix { + return Transpose{t} +} + +// TTri performs an implicit transpose by returning the receiver inside a TransposeTri. +func (t *TriDense) TTri() Triangular { + return TransposeTri{t} +} + +func (t *TriDense) RawTriangular() blas64.Triangular { + return t.mat +} + +// Reset zeros the dimensions of the matrix so that it can be reused as the +// receiver of a dimensionally restricted operation. +// +// See the Reseter interface for more information. +func (t *TriDense) Reset() { + // N and Stride must be zeroed in unison. + t.mat.N, t.mat.Stride = 0, 0 + // Defensively zero Uplo to ensure + // it is set correctly later. + t.mat.Uplo = 0 + t.mat.Data = t.mat.Data[:0] +} + +func (t *TriDense) isZero() bool { + // It must be the case that t.Dims() returns + // zeros in this case. See comment in Reset(). + return t.mat.Stride == 0 +} + +// untranspose untransposes a matrix if applicable. If a is an Untransposer, then +// untranspose returns the underlying matrix and true. If it is not, then it returns +// the input matrix and false. +func untransposeTri(a Triangular) (Triangular, bool) { + if ut, ok := a.(UntransposeTrier); ok { + return ut.UntransposeTri(), true + } + return a, false +} + +// reuseAs resizes a zero receiver to an n×n triangular matrix with the given +// orientation. If the receiver is non-zero, reuseAs checks that the receiver +// is the correct size and orientation. +func (t *TriDense) reuseAs(n int, kind matrix.TriKind) { + ul := blas.Lower + if kind == matrix.Upper { + ul = blas.Upper + } + if t.mat.N > t.cap { + panic(badTriCap) + } + if t.isZero() { + t.mat = blas64.Triangular{ + N: n, + Stride: n, + Diag: blas.NonUnit, + Data: use(t.mat.Data, n*n), + Uplo: ul, + } + t.cap = n + return + } + if t.mat.N != n { + panic(matrix.ErrShape) + } + if t.mat.Uplo != ul { + panic(matrix.ErrTriangle) + } +} + +// isolatedWorkspace returns a new TriDense matrix w with the size of a and +// returns a callback to defer which performs cleanup at the return of the call. +// This should be used when a method receiver is the same pointer as an input argument. +func (t *TriDense) isolatedWorkspace(a Triangular) (w *TriDense, restore func()) { + n, kind := a.Triangle() + if n == 0 { + panic("zero size") + } + w = getWorkspaceTri(n, kind, false) + return w, func() { + t.Copy(w) + putWorkspaceTri(w) + } +} + +// Copy makes a copy of elements of a into the receiver. It is similar to the +// built-in copy; it copies as much as the overlap between the two matrices and +// returns the number of rows and columns it copied. Only elements within the +// receiver's non-zero triangle are set. +// +// See the Copier interface for more information. +func (t *TriDense) Copy(a Matrix) (r, c int) { + r, c = a.Dims() + r = min(r, t.mat.N) + c = min(c, t.mat.N) + if r == 0 || c == 0 { + return 0, 0 + } + + switch a := a.(type) { + case RawMatrixer: + amat := a.RawMatrix() + if t.isUpper() { + for i := 0; i < r; i++ { + copy(t.mat.Data[i*t.mat.Stride+i:i*t.mat.Stride+c], amat.Data[i*amat.Stride+i:i*amat.Stride+c]) + } + } else { + for i := 0; i < r; i++ { + copy(t.mat.Data[i*t.mat.Stride:i*t.mat.Stride+i+1], amat.Data[i*amat.Stride:i*amat.Stride+i+1]) + } + } + case RawTriangular: + amat := a.RawTriangular() + aIsUpper := isUpperUplo(amat.Uplo) + tIsUpper := t.isUpper() + switch { + case tIsUpper && aIsUpper: + for i := 0; i < r; i++ { + copy(t.mat.Data[i*t.mat.Stride+i:i*t.mat.Stride+c], amat.Data[i*amat.Stride+i:i*amat.Stride+c]) + } + case !tIsUpper && !aIsUpper: + for i := 0; i < r; i++ { + copy(t.mat.Data[i*t.mat.Stride:i*t.mat.Stride+i+1], amat.Data[i*amat.Stride:i*amat.Stride+i+1]) + } + default: + for i := 0; i < r; i++ { + t.set(i, i, amat.Data[i*amat.Stride+i]) + } + } + default: + isUpper := t.isUpper() + for i := 0; i < r; i++ { + if isUpper { + for j := i; j < c; j++ { + t.set(i, j, a.At(i, j)) + } + } else { + for j := 0; j <= i; j++ { + t.set(i, j, a.At(i, j)) + } + } + } + } + + return r, c +} + +// InverseTri computes the inverse of the triangular matrix a, storing the result +// into the receiver. If a is ill-conditioned, a Condition error will be returned. +// Note that matrix inversion is numerically unstable, and should generally be +// avoided where possible, for example by using the Solve routines. +func (t *TriDense) InverseTri(a Triangular) error { + if rt, ok := a.(RawTriangular); ok { + t.checkOverlap(rt.RawTriangular()) + } + n, _ := a.Triangle() + t.reuseAs(a.Triangle()) + t.Copy(a) + work := make([]float64, 3*n) + iwork := make([]int, n) + cond := lapack64.Trcon(matrix.CondNorm, t.mat, work, iwork) + if math.IsInf(cond, 1) { + return matrix.Condition(cond) + } + ok := lapack64.Trtri(t.mat) + if !ok { + return matrix.Condition(math.Inf(1)) + } + if cond > matrix.ConditionTolerance { + return matrix.Condition(cond) + } + return nil +} + +// MulTri takes the product of triangular matrices a and b and places the result +// in the receiver. The size of a and b must match, and they both must have the +// same TriKind, or Mul will panic. +func (t *TriDense) MulTri(a, b Triangular) { + n, kind := a.Triangle() + nb, kindb := b.Triangle() + if n != nb { + panic(matrix.ErrShape) + } + if kind != kindb { + panic(matrix.ErrTriangle) + } + + aU, _ := untransposeTri(a) + bU, _ := untransposeTri(b) + t.reuseAs(n, kind) + var restore func() + if t == aU { + t, restore = t.isolatedWorkspace(aU) + defer restore() + } else if t == bU { + t, restore = t.isolatedWorkspace(bU) + defer restore() + } + + // TODO(btracey): Improve the set of fast-paths. + if kind == matrix.Upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + var v float64 + for k := i; k <= j; k++ { + v += a.At(i, k) * b.At(k, j) + } + t.SetTri(i, j, v) + } + } + return + } + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + var v float64 + for k := j; k <= i; k++ { + v += a.At(i, k) * b.At(k, j) + } + t.SetTri(i, j, v) + } + } +} + +// copySymIntoTriangle copies a symmetric matrix into a TriDense +func copySymIntoTriangle(t *TriDense, s Symmetric) { + n, upper := t.Triangle() + ns := s.Symmetric() + if n != ns { + panic("mat64: triangle size mismatch") + } + ts := t.mat.Stride + if rs, ok := s.(RawSymmetricer); ok { + sd := rs.RawSymmetric() + ss := sd.Stride + if upper { + if sd.Uplo == blas.Upper { + for i := 0; i < n; i++ { + copy(t.mat.Data[i*ts+i:i*ts+n], sd.Data[i*ss+i:i*ss+n]) + } + return + } + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + t.mat.Data[i*ts+j] = sd.Data[j*ss+i] + } + return + } + } + if sd.Uplo == blas.Upper { + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + t.mat.Data[i*ts+j] = sd.Data[j*ss+i] + } + } + return + } + for i := 0; i < n; i++ { + copy(t.mat.Data[i*ts:i*ts+i+1], sd.Data[i*ss:i*ss+i+1]) + } + return + } + if upper { + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + t.mat.Data[i*ts+j] = s.At(i, j) + } + } + return + } + for i := 0; i < n; i++ { + for j := 0; j <= i; j++ { + t.mat.Data[i*ts+j] = s.At(i, j) + } + } +} diff --git a/matrix/mat64/triangular_test.go b/matrix/mat64/triangular_test.go new file mode 100644 index 00000000..29e929a7 --- /dev/null +++ b/matrix/mat64/triangular_test.go @@ -0,0 +1,317 @@ +package mat64 + +import ( + "math" + "math/rand" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/matrix" +) + +func TestNewTriangular(t *testing.T) { + for i, test := range []struct { + data []float64 + n int + kind matrix.TriKind + mat *TriDense + }{ + { + data: []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }, + n: 3, + kind: matrix.Upper, + mat: &TriDense{ + mat: blas64.Triangular{ + N: 3, + Stride: 3, + Uplo: blas.Upper, + Data: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + Diag: blas.NonUnit, + }, + cap: 3, + }, + }, + } { + tri := NewTriDense(test.n, test.kind, test.data) + rows, cols := tri.Dims() + + if rows != test.n { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.n) + } + if cols != test.n { + t.Errorf("unexpected number of cols for test %d: got: %d want: %d", i, cols, test.n) + } + if !reflect.DeepEqual(tri, test.mat) { + t.Errorf("unexpected data slice for test %d: got: %v want: %v", i, tri, test.mat) + } + } + + for _, kind := range []matrix.TriKind{matrix.Lower, matrix.Upper} { + panicked, message := panics(func() { NewTriDense(3, kind, []float64{1, 2}) }) + if !panicked || message != matrix.ErrShape.Error() { + t.Errorf("expected panic for invalid data slice length for upper=%t", kind) + } + } +} + +func TestTriAtSet(t *testing.T) { + tri := &TriDense{ + mat: blas64.Triangular{ + N: 3, + Stride: 3, + Uplo: blas.Upper, + Data: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9}, + Diag: blas.NonUnit, + }, + cap: 3, + } + + rows, cols := tri.Dims() + + // Check At out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { tri.At(row, 0) }) + if !panicked || message != matrix.ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { tri.At(0, col) }) + if !panicked || message != matrix.ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + // Check Set out of bounds + for _, row := range []int{-1, rows, rows + 1} { + panicked, message := panics(func() { tri.SetTri(row, 0, 1.2) }) + if !panicked || message != matrix.ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access N=%d r=%d", rows, row) + } + } + for _, col := range []int{-1, cols, cols + 1} { + panicked, message := panics(func() { tri.SetTri(0, col, 1.2) }) + if !panicked || message != matrix.ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access N=%d c=%d", cols, col) + } + } + + for _, st := range []struct { + row, col int + uplo blas.Uplo + }{ + {row: 2, col: 1, uplo: blas.Upper}, + {row: 1, col: 2, uplo: blas.Lower}, + } { + tri.mat.Uplo = st.uplo + panicked, message := panics(func() { tri.SetTri(st.row, st.col, 1.2) }) + if !panicked || message != matrix.ErrTriangleSet.Error() { + t.Errorf("expected panic for %+v", st) + } + } + + for _, st := range []struct { + row, col int + uplo blas.Uplo + orig, new float64 + }{ + {row: 2, col: 1, uplo: blas.Lower, orig: 8, new: 15}, + {row: 1, col: 2, uplo: blas.Upper, orig: 6, new: 15}, + } { + tri.mat.Uplo = st.uplo + if e := tri.At(st.row, st.col); e != st.orig { + t.Errorf("unexpected value for At(%d, %d): got: %v want: %v", st.row, st.col, e, st.orig) + } + tri.SetTri(st.row, st.col, st.new) + if e := tri.At(st.row, st.col); e != st.new { + t.Errorf("unexpected value for At(%d, %d) after SetTri(%[1]d, %d, %v): got: %v want: %[3]v", st.row, st.col, st.new, e) + } + } +} + +func TestTriDenseCopy(t *testing.T) { + for i := 0; i < 100; i++ { + size := rand.Intn(100) + r, err := randDense(size, 0.9, rand.NormFloat64) + if size == 0 { + if err != matrix.ErrZeroLength { + t.Fatalf("expected error %v: got: %v", matrix.ErrZeroLength, err) + } + continue + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + u := NewTriDense(size, true, nil) + l := NewTriDense(size, false, nil) + + for _, typ := range []Matrix{r, (*basicMatrix)(r)} { + for j := range u.mat.Data { + u.mat.Data[j] = math.NaN() + l.mat.Data[j] = math.NaN() + } + u.Copy(typ) + l.Copy(typ) + for m := 0; m < size; m++ { + for n := 0; n < size; n++ { + want := typ.At(m, n) + switch { + case m < n: // Upper triangular matrix. + if got := u.At(m, n); got != want { + t.Errorf("unexpected upper value for At(%d, %d) for test %d: got: %v want: %v", m, n, i, got, want) + } + case m == n: // Diagonal matrix. + if got := u.At(m, n); got != want { + t.Errorf("unexpected upper value for At(%d, %d) for test %d: got: %v want: %v", m, n, i, got, want) + } + if got := l.At(m, n); got != want { + t.Errorf("unexpected diagonal value for At(%d, %d) for test %d: got: %v want: %v", m, n, i, got, want) + } + case m < n: // Lower triangular matrix. + if got := l.At(m, n); got != want { + t.Errorf("unexpected lower value for At(%d, %d) for test %d: got: %v want: %v", m, n, i, got, want) + } + } + } + } + } + } +} + +func TestTriTriDenseCopy(t *testing.T) { + for i := 0; i < 100; i++ { + size := rand.Intn(100) + r, err := randDense(size, 1, rand.NormFloat64) + if size == 0 { + if err != matrix.ErrZeroLength { + t.Fatalf("expected error %v: got: %v", matrix.ErrZeroLength, err) + } + continue + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + ur := NewTriDense(size, true, nil) + lr := NewTriDense(size, false, nil) + + ur.Copy(r) + lr.Copy(r) + + u := NewTriDense(size, true, nil) + u.Copy(ur) + if !equal(u, ur) { + t.Fatal("unexpected result for U triangle copy of U triangle: not equal") + } + + l := NewTriDense(size, false, nil) + l.Copy(lr) + if !equal(l, lr) { + t.Fatal("unexpected result for L triangle copy of L triangle: not equal") + } + + zero(u.mat.Data) + u.Copy(lr) + if !isDiagonal(u) { + t.Fatal("unexpected result for U triangle copy of L triangle: off diagonal non-zero element") + } + if !equalDiagonal(u, lr) { + t.Fatal("unexpected result for U triangle copy of L triangle: diagonal not equal") + } + + zero(l.mat.Data) + l.Copy(ur) + if !isDiagonal(l) { + t.Fatal("unexpected result for L triangle copy of U triangle: off diagonal non-zero element") + } + if !equalDiagonal(l, ur) { + t.Fatal("unexpected result for L triangle copy of U triangle: diagonal not equal") + } + } +} + +func TestTriInverse(t *testing.T) { + for _, kind := range []matrix.TriKind{matrix.Upper, matrix.Lower} { + for _, n := range []int{1, 3, 5, 9} { + data := make([]float64, n*n) + for i := range data { + data[i] = rand.NormFloat64() + } + a := NewTriDense(n, kind, data) + var tr TriDense + err := tr.InverseTri(a) + if err != nil { + t.Errorf("Bad test: %s", err) + } + var d Dense + d.Mul(a, &tr) + if !equalApprox(eye(n), &d, 1e-8, false) { + var diff Dense + diff.Sub(eye(n), &d) + t.Errorf("Tri times inverse is not identity. Norm of difference: %v", Norm(&diff, 2)) + } + } + } +} + +func TestTriMul(t *testing.T) { + method := func(receiver, a, b Matrix) { + type MulTrier interface { + MulTri(a, b Triangular) + } + receiver.(MulTrier).MulTri(a.(Triangular), b.(Triangular)) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Mul(a, b) + } + legalSizeTriMul := func(ar, ac, br, bc int) bool { + // Need both to be square and the sizes to be the same + return ar == ac && br == bc && ar == br + } + + // The legal types are triangles with the same TriKind. + // legalTypesTri returns whether both input arguments are Triangular. + legalTypes := func(a, b Matrix) bool { + at, ok := a.(Triangular) + if !ok { + return false + } + bt, ok := b.(Triangular) + if !ok { + return false + } + _, ak := at.Triangle() + _, bk := bt.Triangle() + return ak == bk + } + legalTypesLower := func(a, b Matrix) bool { + legal := legalTypes(a, b) + if !legal { + return false + } + _, kind := a.(Triangular).Triangle() + r := kind == matrix.Lower + return r + } + receiver := NewTriDense(3, matrix.Lower, nil) + testTwoInput(t, "TriMul", receiver, method, denseComparison, legalTypesLower, legalSizeTriMul, 1e-14) + + legalTypesUpper := func(a, b Matrix) bool { + legal := legalTypes(a, b) + if !legal { + return false + } + _, kind := a.(Triangular).Triangle() + r := kind == matrix.Upper + return r + } + receiver = NewTriDense(3, matrix.Upper, nil) + testTwoInput(t, "TriMul", receiver, method, denseComparison, legalTypesUpper, legalSizeTriMul, 1e-14) +} diff --git a/matrix/mat64/vector.go b/matrix/mat64/vector.go new file mode 100644 index 00000000..28da7cb3 --- /dev/null +++ b/matrix/mat64/vector.go @@ -0,0 +1,468 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat64 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/internal/asm/f64" + "gonum.org/v1/gonum/matrix" +) + +var ( + vector *Vector + + _ Matrix = vector + + _ Reseter = vector +) + +// Vector represents a column vector. +type Vector struct { + mat blas64.Vector + n int + // A BLAS vector can have a negative increment, but allowing this + // in the mat64 type complicates a lot of code, and doesn't gain anything. + // Vector must have positive increment in this package. +} + +// NewVector creates a new Vector of length n. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == n, data is +// used as the backing slice, and changes to the elements of the returned Vector +// will be reflected in data. If neither of these is true, NewVector will panic. +func NewVector(n int, data []float64) *Vector { + if len(data) != n && data != nil { + panic(matrix.ErrShape) + } + if data == nil { + data = make([]float64, n) + } + return &Vector{ + mat: blas64.Vector{ + Inc: 1, + Data: data, + }, + n: n, + } +} + +// ViewVec returns a sub-vector view of the receiver starting at element i and +// extending n rows. If i is out of range, n is zero, or the view extends +// beyond the bounds of the Vector, ViewVec will panic with ErrIndexOutOfRange. +// The returned Vector retains reference to the underlying vector. +// +// ViewVec is deprecated and should not be used. It will be removed at a later date. +func (v *Vector) ViewVec(i, n int) *Vector { + return v.SliceVec(i, i+n) +} + +// SliceVec returns a new Vector that shares backing data with the receiver. +// The returned matrix starts at i of the recevier and extends k-i elements. +// SliceVec panics with ErrIndexOutOfRange if the slice is outside the bounds +// of the receiver. +func (v *Vector) SliceVec(i, k int) *Vector { + if i < 0 || k <= i || v.n < k { + panic(matrix.ErrIndexOutOfRange) + } + return &Vector{ + n: k - i, + mat: blas64.Vector{ + Inc: v.mat.Inc, + Data: v.mat.Data[i*v.mat.Inc : (k-1)*v.mat.Inc+1], + }, + } +} + +func (v *Vector) Dims() (r, c int) { + if v.isZero() { + return 0, 0 + } + return v.n, 1 +} + +// Len returns the length of the vector. +func (v *Vector) Len() int { + return v.n +} + +// T performs an implicit transpose by returning the receiver inside a Transpose. +func (v *Vector) T() Matrix { + return Transpose{v} +} + +// Reset zeros the length of the vector so that it can be reused as the +// receiver of a dimensionally restricted operation. +// +// See the Reseter interface for more information. +func (v *Vector) Reset() { + // No change of Inc or n to 0 may be + // made unless both are set to 0. + v.mat.Inc = 0 + v.n = 0 + v.mat.Data = v.mat.Data[:0] +} + +// CloneVec makes a copy of a into the receiver, overwriting the previous value +// of the receiver. +func (v *Vector) CloneVec(a *Vector) { + if v == a { + return + } + v.n = a.n + v.mat = blas64.Vector{ + Inc: 1, + Data: use(v.mat.Data, v.n), + } + blas64.Copy(v.n, a.mat, v.mat) +} + +func (v *Vector) RawVector() blas64.Vector { + return v.mat +} + +// CopyVec makes a copy of elements of a into the receiver. It is similar to the +// built-in copy; it copies as much as the overlap between the two vectors and +// returns the number of elements it copied. +func (v *Vector) CopyVec(a *Vector) int { + n := min(v.Len(), a.Len()) + if v != a { + blas64.Copy(n, a.mat, v.mat) + } + return n +} + +// ScaleVec scales the vector a by alpha, placing the result in the receiver. +func (v *Vector) ScaleVec(alpha float64, a *Vector) { + n := a.Len() + if v != a { + v.reuseAs(n) + if v.mat.Inc == 1 && a.mat.Inc == 1 { + f64.ScalUnitaryTo(v.mat.Data, alpha, a.mat.Data) + return + } + f64.ScalIncTo(v.mat.Data, uintptr(v.mat.Inc), + alpha, a.mat.Data, uintptr(n), uintptr(a.mat.Inc)) + return + } + if v.mat.Inc == 1 { + f64.ScalUnitary(alpha, v.mat.Data) + return + } + f64.ScalInc(alpha, v.mat.Data, uintptr(n), uintptr(v.mat.Inc)) +} + +// AddScaledVec adds the vectors a and alpha*b, placing the result in the receiver. +func (v *Vector) AddScaledVec(a *Vector, alpha float64, b *Vector) { + if alpha == 1 { + v.AddVec(a, b) + return + } + if alpha == -1 { + v.SubVec(a, b) + return + } + + ar := a.Len() + br := b.Len() + + if ar != br { + panic(matrix.ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + switch { + case alpha == 0: // v <- a + v.CopyVec(a) + case v == a && v == b: // v <- v + alpha * v = (alpha + 1) * v + blas64.Scal(ar, alpha+1, v.mat) + case v == a && v != b: // v <- v + alpha * b + if v.mat.Inc == 1 && b.mat.Inc == 1 { + // Fast path for a common case. + f64.AxpyUnitaryTo(v.mat.Data, alpha, b.mat.Data, a.mat.Data) + } else { + f64.AxpyInc(alpha, b.mat.Data, v.mat.Data, + uintptr(ar), uintptr(b.mat.Inc), uintptr(v.mat.Inc), 0, 0) + } + default: // v <- a + alpha * b or v <- a + alpha * v + if v.mat.Inc == 1 && a.mat.Inc == 1 && b.mat.Inc == 1 { + // Fast path for a common case. + f64.AxpyUnitaryTo(v.mat.Data, alpha, b.mat.Data, a.mat.Data) + } else { + f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, + alpha, b.mat.Data, a.mat.Data, + uintptr(ar), uintptr(b.mat.Inc), uintptr(a.mat.Inc), 0, 0) + } + } +} + +// AddVec adds the vectors a and b, placing the result in the receiver. +func (v *Vector) AddVec(a, b *Vector) { + ar := a.Len() + br := b.Len() + + if ar != br { + panic(matrix.ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + if v.mat.Inc == 1 && a.mat.Inc == 1 && b.mat.Inc == 1 { + // Fast path for a common case. + f64.AxpyUnitaryTo(v.mat.Data, 1, b.mat.Data, a.mat.Data) + return + } + f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, + 1, b.mat.Data, a.mat.Data, + uintptr(ar), uintptr(b.mat.Inc), uintptr(a.mat.Inc), 0, 0) +} + +// SubVec subtracts the vector b from a, placing the result in the receiver. +func (v *Vector) SubVec(a, b *Vector) { + ar := a.Len() + br := b.Len() + + if ar != br { + panic(matrix.ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + if v.mat.Inc == 1 && a.mat.Inc == 1 && b.mat.Inc == 1 { + // Fast path for a common case. + f64.AxpyUnitaryTo(v.mat.Data, -1, b.mat.Data, a.mat.Data) + return + } + f64.AxpyIncTo(v.mat.Data, uintptr(v.mat.Inc), 0, + -1, b.mat.Data, a.mat.Data, + uintptr(ar), uintptr(b.mat.Inc), uintptr(a.mat.Inc), 0, 0) +} + +// MulElemVec performs element-wise multiplication of a and b, placing the result +// in the receiver. +func (v *Vector) MulElemVec(a, b *Vector) { + ar := a.Len() + br := b.Len() + + if ar != br { + panic(matrix.ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + amat, bmat := a.RawVector(), b.RawVector() + for i := 0; i < v.n; i++ { + v.mat.Data[i*v.mat.Inc] = amat.Data[i*amat.Inc] * bmat.Data[i*bmat.Inc] + } +} + +// DivElemVec performs element-wise division of a by b, placing the result +// in the receiver. +func (v *Vector) DivElemVec(a, b *Vector) { + ar := a.Len() + br := b.Len() + + if ar != br { + panic(matrix.ErrShape) + } + + if v != a { + v.checkOverlap(a.mat) + } + if v != b { + v.checkOverlap(b.mat) + } + + v.reuseAs(ar) + + amat, bmat := a.RawVector(), b.RawVector() + for i := 0; i < v.n; i++ { + v.mat.Data[i*v.mat.Inc] = amat.Data[i*amat.Inc] / bmat.Data[i*bmat.Inc] + } +} + +// MulVec computes a * b. The result is stored into the receiver. +// MulVec panics if the number of columns in a does not equal the number of rows in b. +func (v *Vector) MulVec(a Matrix, b *Vector) { + r, c := a.Dims() + br := b.Len() + if c != br { + panic(matrix.ErrShape) + } + + if v != b { + v.checkOverlap(b.mat) + } + + a, trans := untranspose(a) + ar, ac := a.Dims() + v.reuseAs(r) + var restore func() + if v == a { + v, restore = v.isolatedWorkspace(a.(*Vector)) + defer restore() + } else if v == b { + v, restore = v.isolatedWorkspace(b) + defer restore() + } + + switch a := a.(type) { + case *Vector: + if v != a { + v.checkOverlap(a.mat) + } + + if a.Len() == 1 { + // {1,1} x {1,n} + av := a.At(0, 0) + for i := 0; i < b.Len(); i++ { + v.mat.Data[i*v.mat.Inc] = av * b.mat.Data[i*b.mat.Inc] + } + return + } + if b.Len() == 1 { + // {1,n} x {1,1} + bv := b.At(0, 0) + for i := 0; i < a.Len(); i++ { + v.mat.Data[i*v.mat.Inc] = bv * a.mat.Data[i*a.mat.Inc] + } + return + } + // {n,1} x {1,n} + var sum float64 + for i := 0; i < c; i++ { + sum += a.At(i, 0) * b.At(i, 0) + } + v.SetVec(0, sum) + return + case RawSymmetricer: + amat := a.RawSymmetric() + blas64.Symv(1, amat, b.mat, 0, v.mat) + case RawTriangular: + v.CopyVec(b) + amat := a.RawTriangular() + ta := blas.NoTrans + if trans { + ta = blas.Trans + } + blas64.Trmv(ta, amat, v.mat) + case RawMatrixer: + amat := a.RawMatrix() + // We don't know that a is a *Dense, so make + // a temporary Dense to check overlap. + (&Dense{mat: amat}).checkOverlap(v.asGeneral()) + t := blas.NoTrans + if trans { + t = blas.Trans + } + blas64.Gemv(t, 1, amat, b.mat, 0, v.mat) + default: + if trans { + col := make([]float64, ar) + for c := 0; c < ac; c++ { + for i := range col { + col[i] = a.At(i, c) + } + var f float64 + for i, e := range col { + f += e * b.mat.Data[i*b.mat.Inc] + } + v.mat.Data[c*v.mat.Inc] = f + } + } else { + row := make([]float64, ac) + for r := 0; r < ar; r++ { + for i := range row { + row[i] = a.At(r, i) + } + var f float64 + for i, e := range row { + f += e * b.mat.Data[i*b.mat.Inc] + } + v.mat.Data[r*v.mat.Inc] = f + } + } + } +} + +// reuseAs resizes an empty vector to a r×1 vector, +// or checks that a non-empty matrix is r×1. +func (v *Vector) reuseAs(r int) { + if v.isZero() { + v.mat = blas64.Vector{ + Inc: 1, + Data: use(v.mat.Data, r), + } + v.n = r + return + } + if r != v.n { + panic(matrix.ErrShape) + } +} + +func (v *Vector) isZero() bool { + // It must be the case that v.Dims() returns + // zeros in this case. See comment in Reset(). + return v.mat.Inc == 0 +} + +func (v *Vector) isolatedWorkspace(a *Vector) (n *Vector, restore func()) { + l := a.Len() + n = getWorkspaceVec(l, false) + return n, func() { + v.CopyVec(n) + putWorkspaceVec(n) + } +} + +// asDense returns a Dense representation of the receiver with the same +// underlying data. +func (v *Vector) asDense() *Dense { + return &Dense{ + mat: v.asGeneral(), + capRows: v.n, + capCols: 1, + } +} + +// asGeneral returns a blas64.General representation of the receiver with the +// same underlying data. +func (v *Vector) asGeneral() blas64.General { + return blas64.General{ + Rows: v.n, + Cols: 1, + Stride: v.mat.Inc, + Data: v.mat.Data, + } +} diff --git a/matrix/mat64/vector_test.go b/matrix/mat64/vector_test.go new file mode 100644 index 00000000..cc4c6f21 --- /dev/null +++ b/matrix/mat64/vector_test.go @@ -0,0 +1,463 @@ +package mat64 + +import ( + "math/rand" + "reflect" + "testing" + + "gonum.org/v1/gonum/blas/blas64" + "gonum.org/v1/gonum/matrix" +) + +func TestNewVector(t *testing.T) { + for i, test := range []struct { + n int + data []float64 + vector *Vector + }{ + { + n: 3, + data: []float64{4, 5, 6}, + vector: &Vector{ + mat: blas64.Vector{ + Data: []float64{4, 5, 6}, + Inc: 1, + }, + n: 3, + }, + }, + { + n: 3, + data: nil, + vector: &Vector{ + mat: blas64.Vector{ + Data: []float64{0, 0, 0}, + Inc: 1, + }, + n: 3, + }, + }, + } { + v := NewVector(test.n, test.data) + rows, cols := v.Dims() + if rows != test.n { + t.Errorf("unexpected number of rows for test %d: got: %d want: %d", i, rows, test.n) + } + if cols != 1 { + t.Errorf("unexpected number of cols for test %d: got: %d want: 1", i, cols) + } + if !reflect.DeepEqual(v, test.vector) { + t.Errorf("unexpected data slice for test %d: got: %v want: %v", i, v, test.vector) + } + } +} + +func TestVectorAtSet(t *testing.T) { + for i, test := range []struct { + vector *Vector + }{ + { + vector: &Vector{ + mat: blas64.Vector{ + Data: []float64{0, 1, 2}, + Inc: 1, + }, + n: 3, + }, + }, + { + vector: &Vector{ + mat: blas64.Vector{ + Data: []float64{0, 10, 10, 1, 10, 10, 2}, + Inc: 3, + }, + n: 3, + }, + }, + } { + v := test.vector + n := test.vector.n + + for _, row := range []int{-1, n} { + panicked, message := panics(func() { v.At(row, 0) }) + if !panicked || message != matrix.ErrRowAccess.Error() { + t.Errorf("expected panic for invalid row access for test %d n=%d r=%d", i, n, row) + } + } + for _, col := range []int{-1, 1} { + panicked, message := panics(func() { v.At(0, col) }) + if !panicked || message != matrix.ErrColAccess.Error() { + t.Errorf("expected panic for invalid column access for test %d n=%d c=%d", i, n, col) + } + } + + for _, row := range []int{0, 1, n - 1} { + if e := v.At(row, 0); e != float64(row) { + t.Errorf("unexpected value for At(%d, 0) for test %d : got: %v want: %v", row, i, e, float64(row)) + } + } + + for _, row := range []int{-1, n} { + panicked, message := panics(func() { v.SetVec(row, 100) }) + if !panicked || message != matrix.ErrVectorAccess.Error() { + t.Errorf("expected panic for invalid row access for test %d n=%d r=%d", i, n, row) + } + } + + for inc, row := range []int{0, 2} { + v.SetVec(row, 100+float64(inc)) + if e := v.At(row, 0); e != 100+float64(inc) { + t.Errorf("unexpected value for At(%d, 0) after SetVec(%[1]d, %v) for test %d: got: %v want: %[2]v", row, 100+float64(inc), i, e) + } + } + } +} + +func TestVectorMul(t *testing.T) { + method := func(receiver, a, b Matrix) { + type mulVecer interface { + MulVec(a Matrix, b *Vector) + } + rd := receiver.(mulVecer) + rd.MulVec(a, b.(*Vector)) + } + denseComparison := func(receiver, a, b *Dense) { + receiver.Mul(a, b) + } + legalSizeMulVec := func(ar, ac, br, bc int) bool { + var legal bool + if bc != 1 { + legal = false + } else { + legal = ac == br + } + return legal + } + testTwoInput(t, "MulVec", &Vector{}, method, denseComparison, legalTypesNotVecVec, legalSizeMulVec, 1e-14) +} + +func TestVectorScale(t *testing.T) { + for i, test := range []struct { + a *Vector + alpha float64 + want *Vector + }{ + { + a: NewVector(3, []float64{0, 1, 2}), + alpha: 0, + want: NewVector(3, []float64{0, 0, 0}), + }, + { + a: NewVector(3, []float64{0, 1, 2}), + alpha: 1, + want: NewVector(3, []float64{0, 1, 2}), + }, + { + a: NewVector(3, []float64{0, 1, 2}), + alpha: -2, + want: NewVector(3, []float64{0, -2, -4}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + alpha: 0, + want: NewVector(3, []float64{0, 0, 0}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + alpha: 1, + want: NewVector(3, []float64{0, 1, 2}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + alpha: -2, + want: NewVector(3, []float64{0, -2, -4}), + }, + { + a: NewDense(3, 3, []float64{ + 0, 1, 2, + 3, 4, 5, + 6, 7, 8, + }).ColView(1), + alpha: -2, + want: NewVector(3, []float64{-2, -8, -14}), + }, + } { + var v Vector + v.ScaleVec(test.alpha, test.a) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("test %d: unexpected result for v = alpha * a: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + + v.CopyVec(test.a) + v.ScaleVec(test.alpha, &v) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("test %d: unexpected result for v = alpha * v: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } + + for _, alpha := range []float64{0, 1, -1, 2.3, -2.3} { + method := func(receiver, a Matrix) { + type scaleVecer interface { + ScaleVec(float64, *Vector) + } + v := receiver.(scaleVecer) + v.ScaleVec(alpha, a.(*Vector)) + } + denseComparison := func(receiver, a *Dense) { + receiver.Scale(alpha, a) + } + testOneInput(t, "ScaleVec", &Vector{}, method, denseComparison, legalTypeVec, isAnyVector, 0) + } +} + +func TestVectorAddScaled(t *testing.T) { + for _, alpha := range []float64{0, 1, -1, 2.3, -2.3} { + method := func(receiver, a, b Matrix) { + type addScaledVecer interface { + AddScaledVec(*Vector, float64, *Vector) + } + v := receiver.(addScaledVecer) + v.AddScaledVec(a.(*Vector), alpha, b.(*Vector)) + } + denseComparison := func(receiver, a, b *Dense) { + var sb Dense + sb.Scale(alpha, b) + receiver.Add(a, &sb) + } + testTwoInput(t, "AddScaledVec", &Vector{}, method, denseComparison, legalTypesVecVec, legalSizeSameVec, 1e-14) + } +} + +func TestVectorAdd(t *testing.T) { + for i, test := range []struct { + a, b *Vector + want *Vector + }{ + { + a: NewVector(3, []float64{0, 1, 2}), + b: NewVector(3, []float64{0, 2, 3}), + want: NewVector(3, []float64{0, 3, 5}), + }, + { + a: NewVector(3, []float64{0, 1, 2}), + b: NewDense(3, 1, []float64{0, 2, 3}).ColView(0), + want: NewVector(3, []float64{0, 3, 5}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + b: NewDense(3, 1, []float64{0, 2, 3}).ColView(0), + want: NewVector(3, []float64{0, 3, 5}), + }, + } { + var v Vector + v.AddVec(test.a, test.b) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("unexpected result for test %d: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } +} + +func TestVectorSub(t *testing.T) { + for i, test := range []struct { + a, b *Vector + want *Vector + }{ + { + a: NewVector(3, []float64{0, 1, 2}), + b: NewVector(3, []float64{0, 0.5, 1}), + want: NewVector(3, []float64{0, 0.5, 1}), + }, + { + a: NewVector(3, []float64{0, 1, 2}), + b: NewDense(3, 1, []float64{0, 0.5, 1}).ColView(0), + want: NewVector(3, []float64{0, 0.5, 1}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + b: NewDense(3, 1, []float64{0, 0.5, 1}).ColView(0), + want: NewVector(3, []float64{0, 0.5, 1}), + }, + } { + var v Vector + v.SubVec(test.a, test.b) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("unexpected result for test %d: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } +} + +func TestVectorMulElem(t *testing.T) { + for i, test := range []struct { + a, b *Vector + want *Vector + }{ + { + a: NewVector(3, []float64{0, 1, 2}), + b: NewVector(3, []float64{0, 2, 3}), + want: NewVector(3, []float64{0, 2, 6}), + }, + { + a: NewVector(3, []float64{0, 1, 2}), + b: NewDense(3, 1, []float64{0, 2, 3}).ColView(0), + want: NewVector(3, []float64{0, 2, 6}), + }, + { + a: NewDense(3, 1, []float64{0, 1, 2}).ColView(0), + b: NewDense(3, 1, []float64{0, 2, 3}).ColView(0), + want: NewVector(3, []float64{0, 2, 6}), + }, + } { + var v Vector + v.MulElemVec(test.a, test.b) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("unexpected result for test %d: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } +} + +func TestVectorDivElem(t *testing.T) { + for i, test := range []struct { + a, b *Vector + want *Vector + }{ + { + a: NewVector(3, []float64{0.5, 1, 2}), + b: NewVector(3, []float64{0.5, 0.5, 1}), + want: NewVector(3, []float64{1, 2, 2}), + }, + { + a: NewVector(3, []float64{0.5, 1, 2}), + b: NewDense(3, 1, []float64{0.5, 0.5, 1}).ColView(0), + want: NewVector(3, []float64{1, 2, 2}), + }, + { + a: NewDense(3, 1, []float64{0.5, 1, 2}).ColView(0), + b: NewDense(3, 1, []float64{0.5, 0.5, 1}).ColView(0), + want: NewVector(3, []float64{1, 2, 2}), + }, + } { + var v Vector + v.DivElemVec(test.a, test.b) + if !reflect.DeepEqual(v.RawVector(), test.want.RawVector()) { + t.Errorf("unexpected result for test %d: got: %v want: %v", i, v.RawVector(), test.want.RawVector()) + } + } +} + +func BenchmarkAddScaledVec10Inc1(b *testing.B) { addScaledVecBench(b, 10, 1) } +func BenchmarkAddScaledVec100Inc1(b *testing.B) { addScaledVecBench(b, 100, 1) } +func BenchmarkAddScaledVec1000Inc1(b *testing.B) { addScaledVecBench(b, 1000, 1) } +func BenchmarkAddScaledVec10000Inc1(b *testing.B) { addScaledVecBench(b, 10000, 1) } +func BenchmarkAddScaledVec100000Inc1(b *testing.B) { addScaledVecBench(b, 100000, 1) } +func BenchmarkAddScaledVec10Inc2(b *testing.B) { addScaledVecBench(b, 10, 2) } +func BenchmarkAddScaledVec100Inc2(b *testing.B) { addScaledVecBench(b, 100, 2) } +func BenchmarkAddScaledVec1000Inc2(b *testing.B) { addScaledVecBench(b, 1000, 2) } +func BenchmarkAddScaledVec10000Inc2(b *testing.B) { addScaledVecBench(b, 10000, 2) } +func BenchmarkAddScaledVec100000Inc2(b *testing.B) { addScaledVecBench(b, 100000, 2) } +func BenchmarkAddScaledVec10Inc20(b *testing.B) { addScaledVecBench(b, 10, 20) } +func BenchmarkAddScaledVec100Inc20(b *testing.B) { addScaledVecBench(b, 100, 20) } +func BenchmarkAddScaledVec1000Inc20(b *testing.B) { addScaledVecBench(b, 1000, 20) } +func BenchmarkAddScaledVec10000Inc20(b *testing.B) { addScaledVecBench(b, 10000, 20) } +func BenchmarkAddScaledVec100000Inc20(b *testing.B) { addScaledVecBench(b, 100000, 20) } +func addScaledVecBench(b *testing.B, size, inc int) { + x := randVector(size, inc, 1, rand.NormFloat64) + y := randVector(size, inc, 1, rand.NormFloat64) + b.ResetTimer() + var v Vector + for i := 0; i < b.N; i++ { + v.AddScaledVec(y, 2, x) + } +} + +func BenchmarkScaleVec10Inc1(b *testing.B) { scaleVecBench(b, 10, 1) } +func BenchmarkScaleVec100Inc1(b *testing.B) { scaleVecBench(b, 100, 1) } +func BenchmarkScaleVec1000Inc1(b *testing.B) { scaleVecBench(b, 1000, 1) } +func BenchmarkScaleVec10000Inc1(b *testing.B) { scaleVecBench(b, 10000, 1) } +func BenchmarkScaleVec100000Inc1(b *testing.B) { scaleVecBench(b, 100000, 1) } +func BenchmarkScaleVec10Inc2(b *testing.B) { scaleVecBench(b, 10, 2) } +func BenchmarkScaleVec100Inc2(b *testing.B) { scaleVecBench(b, 100, 2) } +func BenchmarkScaleVec1000Inc2(b *testing.B) { scaleVecBench(b, 1000, 2) } +func BenchmarkScaleVec10000Inc2(b *testing.B) { scaleVecBench(b, 10000, 2) } +func BenchmarkScaleVec100000Inc2(b *testing.B) { scaleVecBench(b, 100000, 2) } +func BenchmarkScaleVec10Inc20(b *testing.B) { scaleVecBench(b, 10, 20) } +func BenchmarkScaleVec100Inc20(b *testing.B) { scaleVecBench(b, 100, 20) } +func BenchmarkScaleVec1000Inc20(b *testing.B) { scaleVecBench(b, 1000, 20) } +func BenchmarkScaleVec10000Inc20(b *testing.B) { scaleVecBench(b, 10000, 20) } +func BenchmarkScaleVec100000Inc20(b *testing.B) { scaleVecBench(b, 100000, 20) } +func scaleVecBench(b *testing.B, size, inc int) { + x := randVector(size, inc, 1, rand.NormFloat64) + b.ResetTimer() + var v Vector + for i := 0; i < b.N; i++ { + v.ScaleVec(2, x) + } +} + +func BenchmarkAddVec10Inc1(b *testing.B) { addVecBench(b, 10, 1) } +func BenchmarkAddVec100Inc1(b *testing.B) { addVecBench(b, 100, 1) } +func BenchmarkAddVec1000Inc1(b *testing.B) { addVecBench(b, 1000, 1) } +func BenchmarkAddVec10000Inc1(b *testing.B) { addVecBench(b, 10000, 1) } +func BenchmarkAddVec100000Inc1(b *testing.B) { addVecBench(b, 100000, 1) } +func BenchmarkAddVec10Inc2(b *testing.B) { addVecBench(b, 10, 2) } +func BenchmarkAddVec100Inc2(b *testing.B) { addVecBench(b, 100, 2) } +func BenchmarkAddVec1000Inc2(b *testing.B) { addVecBench(b, 1000, 2) } +func BenchmarkAddVec10000Inc2(b *testing.B) { addVecBench(b, 10000, 2) } +func BenchmarkAddVec100000Inc2(b *testing.B) { addVecBench(b, 100000, 2) } +func BenchmarkAddVec10Inc20(b *testing.B) { addVecBench(b, 10, 20) } +func BenchmarkAddVec100Inc20(b *testing.B) { addVecBench(b, 100, 20) } +func BenchmarkAddVec1000Inc20(b *testing.B) { addVecBench(b, 1000, 20) } +func BenchmarkAddVec10000Inc20(b *testing.B) { addVecBench(b, 10000, 20) } +func BenchmarkAddVec100000Inc20(b *testing.B) { addVecBench(b, 100000, 20) } +func addVecBench(b *testing.B, size, inc int) { + x := randVector(size, inc, 1, rand.NormFloat64) + y := randVector(size, inc, 1, rand.NormFloat64) + b.ResetTimer() + var v Vector + for i := 0; i < b.N; i++ { + v.AddVec(x, y) + } +} + +func BenchmarkSubVec10Inc1(b *testing.B) { subVecBench(b, 10, 1) } +func BenchmarkSubVec100Inc1(b *testing.B) { subVecBench(b, 100, 1) } +func BenchmarkSubVec1000Inc1(b *testing.B) { subVecBench(b, 1000, 1) } +func BenchmarkSubVec10000Inc1(b *testing.B) { subVecBench(b, 10000, 1) } +func BenchmarkSubVec100000Inc1(b *testing.B) { subVecBench(b, 100000, 1) } +func BenchmarkSubVec10Inc2(b *testing.B) { subVecBench(b, 10, 2) } +func BenchmarkSubVec100Inc2(b *testing.B) { subVecBench(b, 100, 2) } +func BenchmarkSubVec1000Inc2(b *testing.B) { subVecBench(b, 1000, 2) } +func BenchmarkSubVec10000Inc2(b *testing.B) { subVecBench(b, 10000, 2) } +func BenchmarkSubVec100000Inc2(b *testing.B) { subVecBench(b, 100000, 2) } +func BenchmarkSubVec10Inc20(b *testing.B) { subVecBench(b, 10, 20) } +func BenchmarkSubVec100Inc20(b *testing.B) { subVecBench(b, 100, 20) } +func BenchmarkSubVec1000Inc20(b *testing.B) { subVecBench(b, 1000, 20) } +func BenchmarkSubVec10000Inc20(b *testing.B) { subVecBench(b, 10000, 20) } +func BenchmarkSubVec100000Inc20(b *testing.B) { subVecBench(b, 100000, 20) } +func subVecBench(b *testing.B, size, inc int) { + x := randVector(size, inc, 1, rand.NormFloat64) + y := randVector(size, inc, 1, rand.NormFloat64) + b.ResetTimer() + var v Vector + for i := 0; i < b.N; i++ { + v.SubVec(x, y) + } +} + +func randVector(size, inc int, rho float64, rnd func() float64) *Vector { + if size <= 0 { + panic("bad vector size") + } + data := make([]float64, size*inc) + for i := range data { + if rand.Float64() < rho { + data[i] = rnd() + } + } + return &Vector{ + mat: blas64.Vector{ + Inc: inc, + Data: data, + }, + n: size, + } +} diff --git a/optimize/README.md b/optimize/README.md new file mode 100644 index 00000000..4a887466 --- /dev/null +++ b/optimize/README.md @@ -0,0 +1,13 @@ +# Gonum Optimize [![Build Status](https://travis-ci.org/gonum/optimize.svg?branch=master)](https://travis-ci.org/gonum/optimize) [![Coverage Status](https://coveralls.io/repos/gonum/optimize/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/optimize?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/optimize?status.svg)](https://godoc.org/github.com/gonum/optimize) + +This is an optimization package for the Go language. More documentation can be seen at godoc.org/github.com/gonum/optimize + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/optimize/backtracking.go b/optimize/backtracking.go new file mode 100644 index 00000000..313077f3 --- /dev/null +++ b/optimize/backtracking.go @@ -0,0 +1,82 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +const ( + defaultBacktrackingContraction = 0.5 + defaultBacktrackingDecrease = 1e-4 + minimumBacktrackingStepSize = 1e-20 +) + +// Backtracking is a Linesearcher that uses backtracking to find a point that +// satisfies the Armijo condition with the given decrease factor. If the Armijo +// condition has not been met, the step size is decreased by ContractionFactor. +// +// The Armijo condition only requires the gradient at the beginning of each +// major iteration (not at successive step locations), and so Backtracking may +// be a good linesearch for functions with expensive gradients. Backtracking is +// not appropriate for optimizers that require the Wolfe conditions to be met, +// such as BFGS. +// +// Both DecreaseFactor and ContractionFactor must be between zero and one, and +// Backtracking will panic otherwise. If either DecreaseFactor or +// ContractionFactor are zero, it will be set to a reasonable default. +type Backtracking struct { + DecreaseFactor float64 // Constant factor in the sufficient decrease (Armijo) condition. + ContractionFactor float64 // Step size multiplier at each iteration (step *= ContractionFactor). + + stepSize float64 + initF float64 + initG float64 + + lastOp Operation +} + +func (b *Backtracking) Init(f, g float64, step float64) Operation { + if step <= 0 { + panic("backtracking: bad step size") + } + if g >= 0 { + panic("backtracking: initial derivative is non-negative") + } + + if b.ContractionFactor == 0 { + b.ContractionFactor = defaultBacktrackingContraction + } + if b.DecreaseFactor == 0 { + b.DecreaseFactor = defaultBacktrackingDecrease + } + if b.ContractionFactor <= 0 || b.ContractionFactor >= 1 { + panic("backtracking: ContractionFactor must be between 0 and 1") + } + if b.DecreaseFactor <= 0 || b.DecreaseFactor >= 1 { + panic("backtracking: DecreaseFactor must be between 0 and 1") + } + + b.stepSize = step + b.initF = f + b.initG = g + + b.lastOp = FuncEvaluation + return b.lastOp +} + +func (b *Backtracking) Iterate(f, _ float64) (Operation, float64, error) { + if b.lastOp != FuncEvaluation { + panic("backtracking: Init has not been called") + } + + if ArmijoConditionMet(f, b.initF, b.initG, b.stepSize, b.DecreaseFactor) { + b.lastOp = MajorIteration + return b.lastOp, b.stepSize, nil + } + b.stepSize *= b.ContractionFactor + if b.stepSize < minimumBacktrackingStepSize { + b.lastOp = NoOperation + return b.lastOp, b.stepSize, ErrLinesearcherFailure + } + b.lastOp = FuncEvaluation + return b.lastOp, b.stepSize, nil +} diff --git a/optimize/bfgs.go b/optimize/bfgs.go new file mode 100644 index 00000000..5d320ac7 --- /dev/null +++ b/optimize/bfgs.go @@ -0,0 +1,160 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "math" + + "gonum.org/v1/gonum/matrix/mat64" +) + +// BFGS implements the Broyden–Fletcher–Goldfarb–Shanno optimization method. It +// is a quasi-Newton method that performs successive rank-one updates to an +// estimate of the inverse Hessian of the objective function. It exhibits +// super-linear convergence when in proximity to a local minimum. It has memory +// cost that is O(n^2) relative to the input dimension. +type BFGS struct { + // Linesearcher selects suitable steps along the descent direction. + // Accepted steps should satisfy the strong Wolfe conditions. + // If Linesearcher == nil, an appropriate default is chosen. + Linesearcher Linesearcher + + ls *LinesearchMethod + + dim int + x mat64.Vector // Location of the last major iteration. + grad mat64.Vector // Gradient at the last major iteration. + s mat64.Vector // Difference between locations in this and the previous iteration. + y mat64.Vector // Difference between gradients in this and the previous iteration. + tmp mat64.Vector + + invHess *mat64.SymDense + + first bool // Indicator of the first iteration. +} + +func (b *BFGS) Init(loc *Location) (Operation, error) { + if b.Linesearcher == nil { + b.Linesearcher = &Bisection{} + } + if b.ls == nil { + b.ls = &LinesearchMethod{} + } + b.ls.Linesearcher = b.Linesearcher + b.ls.NextDirectioner = b + + return b.ls.Init(loc) +} + +func (b *BFGS) Iterate(loc *Location) (Operation, error) { + return b.ls.Iterate(loc) +} + +func (b *BFGS) InitDirection(loc *Location, dir []float64) (stepSize float64) { + dim := len(loc.X) + b.dim = dim + b.first = true + + x := mat64.NewVector(dim, loc.X) + grad := mat64.NewVector(dim, loc.Gradient) + b.x.CloneVec(x) + b.grad.CloneVec(grad) + + b.y.Reset() + b.s.Reset() + b.tmp.Reset() + + if b.invHess == nil || cap(b.invHess.RawSymmetric().Data) < dim*dim { + b.invHess = mat64.NewSymDense(dim, nil) + } else { + b.invHess = mat64.NewSymDense(dim, b.invHess.RawSymmetric().Data[:dim*dim]) + } + // The values of the inverse Hessian are initialized in the first call to + // NextDirection. + + // Initial direction is just negative of the gradient because the Hessian + // is an identity matrix. + d := mat64.NewVector(dim, dir) + d.ScaleVec(-1, grad) + return 1 / mat64.Norm(d, 2) +} + +func (b *BFGS) NextDirection(loc *Location, dir []float64) (stepSize float64) { + dim := b.dim + if len(loc.X) != dim { + panic("bfgs: unexpected size mismatch") + } + if len(loc.Gradient) != dim { + panic("bfgs: unexpected size mismatch") + } + if len(dir) != dim { + panic("bfgs: unexpected size mismatch") + } + + x := mat64.NewVector(dim, loc.X) + grad := mat64.NewVector(dim, loc.Gradient) + + // s = x_{k+1} - x_{k} + b.s.SubVec(x, &b.x) + // y = g_{k+1} - g_{k} + b.y.SubVec(grad, &b.grad) + + sDotY := mat64.Dot(&b.s, &b.y) + + if b.first { + // Rescale the initial Hessian. + // From: Nocedal, J., Wright, S.: Numerical Optimization (2nd ed). + // Springer (2006), page 143, eq. 6.20. + yDotY := mat64.Dot(&b.y, &b.y) + scale := sDotY / yDotY + for i := 0; i < dim; i++ { + for j := i; j < dim; j++ { + if i == j { + b.invHess.SetSym(i, i, scale) + } else { + b.invHess.SetSym(i, j, 0) + } + } + } + b.first = false + } + + if math.Abs(sDotY) != 0 { + // Update the inverse Hessian according to the formula + // + // B_{k+1}^-1 = B_k^-1 + // + (s_k^T y_k + y_k^T B_k^-1 y_k) / (s_k^T y_k)^2 * (s_k s_k^T) + // - (B_k^-1 y_k s_k^T + s_k y_k^T B_k^-1) / (s_k^T y_k). + // + // Note that y_k^T B_k^-1 y_k is a scalar, and that the third term is a + // rank-two update where B_k^-1 y_k is one vector and s_k is the other. + yBy := mat64.Inner(&b.y, b.invHess, &b.y) + b.tmp.MulVec(b.invHess, &b.y) + scale := (1 + yBy/sDotY) / sDotY + b.invHess.SymRankOne(b.invHess, scale, &b.s) + b.invHess.RankTwo(b.invHess, -1/sDotY, &b.tmp, &b.s) + } + + // Update the stored BFGS data. + b.x.CopyVec(x) + b.grad.CopyVec(grad) + + // New direction is stored in dir. + d := mat64.NewVector(dim, dir) + d.MulVec(b.invHess, grad) + d.ScaleVec(-1, d) + + return 1 +} + +func (*BFGS) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, false} +} diff --git a/optimize/bisection.go b/optimize/bisection.go new file mode 100644 index 00000000..6dfe8652 --- /dev/null +++ b/optimize/bisection.go @@ -0,0 +1,146 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import "math" + +const ( + defaultBisectionCurvature = 0.9 +) + +// Bisection is a Linesearcher that uses a bisection to find a point that +// satisfies the strong Wolfe conditions with the given curvature factor and +// a decrease factor of zero. +type Bisection struct { + // CurvatureFactor is the constant factor in the curvature condition. + // Smaller values result in a more exact line search. + // A set value must be in the interval (0, 1), otherwise Init will panic. + // If it is zero, it will be defaulted to 0.9. + CurvatureFactor float64 + + minStep float64 + maxStep float64 + currStep float64 + + initF float64 + minF float64 + maxF float64 + lastF float64 + + initGrad float64 + + lastOp Operation +} + +func (b *Bisection) Init(f, g float64, step float64) Operation { + if step <= 0 { + panic("bisection: bad step size") + } + if g >= 0 { + panic("bisection: initial derivative is non-negative") + } + + if b.CurvatureFactor == 0 { + b.CurvatureFactor = defaultBisectionCurvature + } + if b.CurvatureFactor <= 0 || b.CurvatureFactor >= 1 { + panic("bisection: CurvatureFactor not between 0 and 1") + } + + b.minStep = 0 + b.maxStep = math.Inf(1) + b.currStep = step + + b.initF = f + b.minF = f + b.maxF = math.NaN() + + b.initGrad = g + + // Only evaluate the gradient when necessary. + b.lastOp = FuncEvaluation + return b.lastOp +} + +func (b *Bisection) Iterate(f, g float64) (Operation, float64, error) { + if b.lastOp != FuncEvaluation && b.lastOp != GradEvaluation { + panic("bisection: Init has not been called") + } + minF := b.initF + if b.maxF < minF { + minF = b.maxF + } + if b.minF < minF { + minF = b.minF + } + if b.lastOp == FuncEvaluation { + // See if the function value is good enough to make progress. If it is, + // evaluate the gradient. If not, set it to the upper bound if the bound + // has not yet been found, otherwise iterate toward the minimum location. + if f <= minF { + b.lastF = f + b.lastOp = GradEvaluation + return b.lastOp, b.currStep, nil + } + if math.IsInf(b.maxStep, 1) { + b.maxStep = b.currStep + b.maxF = f + return b.nextStep((b.minStep + b.maxStep) / 2) + } + if b.minF <= b.maxF { + b.maxStep = b.currStep + b.maxF = f + } else { + b.minStep = b.currStep + b.minF = f + } + return b.nextStep((b.minStep + b.maxStep) / 2) + } + f = b.lastF + // The function value was lower. Check if this location is sufficient to + // converge the linesearch, otherwise iterate. + if StrongWolfeConditionsMet(f, g, minF, b.initGrad, b.currStep, 0, b.CurvatureFactor) { + b.lastOp = MajorIteration + return b.lastOp, b.currStep, nil + } + if math.IsInf(b.maxStep, 1) { + // The function value is lower. If the gradient is positive, an upper bound + // of the minimum been found. If the gradient is negative, search farther + // in that direction. + if g > 0 { + b.maxStep = b.currStep + b.maxF = f + return b.nextStep((b.minStep + b.maxStep) / 2) + } + b.minStep = b.currStep + b.minF = f + return b.nextStep(b.currStep * 2) + } + // The interval has been bounded, and we have found a new lowest value. Use + // the gradient to decide which direction. + if g < 0 { + b.minStep = b.currStep + b.minF = f + } else { + b.maxStep = b.currStep + b.maxF = f + } + return b.nextStep((b.minStep + b.maxStep) / 2) +} + +// nextStep checks if the new step is equal to the old step. +// This can happen if min and max are the same, or if the step size is infinity, +// both of which indicate the minimization must stop. If the steps are different, +// it sets the new step size and returns the evaluation type and the step. If the steps +// are the same, it returns an error. +func (b *Bisection) nextStep(step float64) (Operation, float64, error) { + if b.currStep == step { + b.lastOp = NoOperation + return b.lastOp, b.currStep, ErrLinesearcherFailure + } + b.currStep = step + b.lastOp = FuncEvaluation + return b.lastOp, b.currStep, nil +} diff --git a/optimize/cg.go b/optimize/cg.go new file mode 100644 index 00000000..88612d3f --- /dev/null +++ b/optimize/cg.go @@ -0,0 +1,313 @@ +package optimize + +import ( + "math" + + "gonum.org/v1/gonum/floats" +) + +const ( + iterationRestartFactor = 6 + angleRestartThreshold = -0.9 +) + +// CGVariant calculates the scaling parameter, β, used for updating the +// conjugate direction in the nonlinear conjugate gradient (CG) method. +type CGVariant interface { + // Init is called at the first iteration and provides a way to initialize + // any internal state. + Init(loc *Location) + // Beta returns the value of the scaling parameter that is computed + // according to the particular variant of the CG method. + Beta(grad, gradPrev, dirPrev []float64) float64 +} + +// CG implements the nonlinear conjugate gradient method for solving nonlinear +// unconstrained optimization problems. It is a line search method that +// generates the search directions d_k according to the formula +// d_{k+1} = -∇f_{k+1} + β_k*d_k, d_0 = -∇f_0. +// Variants of the conjugate gradient method differ in the choice of the +// parameter β_k. The conjugate gradient method usually requires fewer function +// evaluations than the gradient descent method and no matrix storage, but +// L-BFGS is usually more efficient. +// +// CG implements a restart strategy that takes the steepest descent direction +// (i.e., d_{k+1} = -∇f_{k+1}) whenever any of the following conditions holds: +// +// - A certain number of iterations has elapsed without a restart. This number +// is controllable via IterationRestartFactor and if equal to 0, it is set to +// a reasonable default based on the problem dimension. +// - The angle between the gradients at two consecutive iterations ∇f_k and +// ∇f_{k+1} is too large. +// - The direction d_{k+1} is not a descent direction. +// - β_k returned from CGVariant.Beta is equal to zero. +// +// The line search for CG must yield step sizes that satisfy the strong Wolfe +// conditions at every iteration, otherwise the generated search direction +// might fail to be a descent direction. The line search should be more +// stringent compared with those for Newton-like methods, which can be achieved +// by setting the gradient constant in the strong Wolfe conditions to a small +// value. +// +// See also William Hager, Hongchao Zhang, A survey of nonlinear conjugate +// gradient methods. Pacific Journal of Optimization, 2 (2006), pp. 35-58, and +// references therein. +type CG struct { + // Linesearcher must satisfy the strong Wolfe conditions at every iteration. + // If Linesearcher == nil, an appropriate default is chosen. + Linesearcher Linesearcher + // Variant implements the particular CG formula for computing β_k. + // If Variant is nil, an appropriate default is chosen. + Variant CGVariant + // InitialStep estimates the initial line search step size, because the CG + // method does not generate well-scaled search directions. + // If InitialStep is nil, an appropriate default is chosen. + InitialStep StepSizer + + // IterationRestartFactor determines the frequency of restarts based on the + // problem dimension. The negative gradient direction is taken whenever + // ceil(IterationRestartFactor*(problem dimension)) iterations have elapsed + // without a restart. For medium and large-scale problems + // IterationRestartFactor should be set to 1, low-dimensional problems a + // larger value should be chosen. Note that if the ceil function returns 1, + // CG will be identical to gradient descent. + // If IterationRestartFactor is 0, it will be set to 6. + // CG will panic if IterationRestartFactor is negative. + IterationRestartFactor float64 + // AngleRestartThreshold sets the threshold angle for restart. The method + // is restarted if the cosine of the angle between two consecutive + // gradients is smaller than or equal to AngleRestartThreshold, that is, if + // ∇f_k·∇f_{k+1} / (|∇f_k| |∇f_{k+1}|) <= AngleRestartThreshold. + // A value of AngleRestartThreshold closer to -1 (successive gradients in + // exact opposite directions) will tend to reduce the number of restarts. + // If AngleRestartThreshold is 0, it will be set to -0.9. + // CG will panic if AngleRestartThreshold is not in the interval [-1, 0]. + AngleRestartThreshold float64 + + ls *LinesearchMethod + + restartAfter int + iterFromRestart int + + dirPrev []float64 + gradPrev []float64 + gradPrevNorm float64 +} + +func (cg *CG) Init(loc *Location) (Operation, error) { + if cg.IterationRestartFactor < 0 { + panic("cg: IterationRestartFactor is negative") + } + if cg.AngleRestartThreshold < -1 || cg.AngleRestartThreshold > 0 { + panic("cg: AngleRestartThreshold not in [-1, 0]") + } + + if cg.Linesearcher == nil { + cg.Linesearcher = &MoreThuente{CurvatureFactor: 0.1} + } + if cg.Variant == nil { + cg.Variant = &HestenesStiefel{} + } + if cg.InitialStep == nil { + cg.InitialStep = &FirstOrderStepSize{} + } + + if cg.IterationRestartFactor == 0 { + cg.IterationRestartFactor = iterationRestartFactor + } + if cg.AngleRestartThreshold == 0 { + cg.AngleRestartThreshold = angleRestartThreshold + } + + if cg.ls == nil { + cg.ls = &LinesearchMethod{} + } + cg.ls.Linesearcher = cg.Linesearcher + cg.ls.NextDirectioner = cg + + return cg.ls.Init(loc) +} + +func (cg *CG) Iterate(loc *Location) (Operation, error) { + return cg.ls.Iterate(loc) +} + +func (cg *CG) InitDirection(loc *Location, dir []float64) (stepSize float64) { + dim := len(loc.X) + + cg.restartAfter = int(math.Ceil(cg.IterationRestartFactor * float64(dim))) + cg.iterFromRestart = 0 + + // The initial direction is always the negative gradient. + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + + cg.dirPrev = resize(cg.dirPrev, dim) + copy(cg.dirPrev, dir) + cg.gradPrev = resize(cg.gradPrev, dim) + copy(cg.gradPrev, loc.Gradient) + cg.gradPrevNorm = floats.Norm(loc.Gradient, 2) + + cg.Variant.Init(loc) + return cg.InitialStep.Init(loc, dir) +} + +func (cg *CG) NextDirection(loc *Location, dir []float64) (stepSize float64) { + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + + cg.iterFromRestart++ + var restart bool + if cg.iterFromRestart == cg.restartAfter { + // Restart because too many iterations have been taken without a restart. + restart = true + } + + gDot := floats.Dot(loc.Gradient, cg.gradPrev) + gNorm := floats.Norm(loc.Gradient, 2) + if gDot <= cg.AngleRestartThreshold*gNorm*cg.gradPrevNorm { + // Restart because the angle between the last two gradients is too large. + restart = true + } + + // Compute the scaling factor β_k even when restarting, because cg.Variant + // may be keeping an inner state that needs to be updated at every iteration. + beta := cg.Variant.Beta(loc.Gradient, cg.gradPrev, cg.dirPrev) + if beta == 0 { + // β_k == 0 means that the steepest descent direction will be taken, so + // indicate that the method is in fact being restarted. + restart = true + } + if !restart { + // The method is not being restarted, so update the descent direction. + floats.AddScaled(dir, beta, cg.dirPrev) + if floats.Dot(loc.Gradient, dir) >= 0 { + // Restart because the new direction is not a descent direction. + restart = true + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + } + } + + // Get the initial line search step size from the StepSizer even if the + // method was restarted, because StepSizers need to see every iteration. + stepSize = cg.InitialStep.StepSize(loc, dir) + if restart { + // The method was restarted and since the steepest descent direction is + // not related to the previous direction, discard the estimated step + // size from cg.InitialStep and use step size of 1 instead. + stepSize = 1 + // Reset to 0 the counter of iterations taken since the last restart. + cg.iterFromRestart = 0 + } + + copy(cg.gradPrev, loc.Gradient) + copy(cg.dirPrev, dir) + cg.gradPrevNorm = gNorm + return stepSize +} + +func (*CG) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, false} +} + +// FletcherReeves implements the Fletcher-Reeves variant of the CG method that +// computes the scaling parameter β_k according to the formula +// β_k = |∇f_{k+1}|^2 / |∇f_k|^2. +type FletcherReeves struct { + prevNorm float64 +} + +func (fr *FletcherReeves) Init(loc *Location) { + fr.prevNorm = floats.Norm(loc.Gradient, 2) +} + +func (fr *FletcherReeves) Beta(grad, _, _ []float64) (beta float64) { + norm := floats.Norm(grad, 2) + beta = (norm / fr.prevNorm) * (norm / fr.prevNorm) + fr.prevNorm = norm + return beta +} + +// PolakRibierePolyak implements the Polak-Ribiere-Polyak variant of the CG +// method that computes the scaling parameter β_k according to the formula +// β_k = max(0, ∇f_{k+1}·y_k / |∇f_k|^2), +// where y_k = ∇f_{k+1} - ∇f_k. +type PolakRibierePolyak struct { + prevNorm float64 +} + +func (pr *PolakRibierePolyak) Init(loc *Location) { + pr.prevNorm = floats.Norm(loc.Gradient, 2) +} + +func (pr *PolakRibierePolyak) Beta(grad, gradPrev, _ []float64) (beta float64) { + norm := floats.Norm(grad, 2) + dot := floats.Dot(grad, gradPrev) + beta = (norm*norm - dot) / (pr.prevNorm * pr.prevNorm) + pr.prevNorm = norm + return math.Max(0, beta) +} + +// HestenesStiefel implements the Hestenes-Stiefel variant of the CG method +// that computes the scaling parameter β_k according to the formula +// β_k = max(0, ∇f_{k+1}·y_k / d_k·y_k), +// where y_k = ∇f_{k+1} - ∇f_k. +type HestenesStiefel struct { + y []float64 +} + +func (hs *HestenesStiefel) Init(loc *Location) { + hs.y = resize(hs.y, len(loc.Gradient)) +} + +func (hs *HestenesStiefel) Beta(grad, gradPrev, dirPrev []float64) (beta float64) { + floats.SubTo(hs.y, grad, gradPrev) + beta = floats.Dot(grad, hs.y) / floats.Dot(dirPrev, hs.y) + return math.Max(0, beta) +} + +// DaiYuan implements the Dai-Yuan variant of the CG method that computes the +// scaling parameter β_k according to the formula +// β_k = |∇f_{k+1}|^2 / d_k·y_k, +// where y_k = ∇f_{k+1} - ∇f_k. +type DaiYuan struct { + y []float64 +} + +func (dy *DaiYuan) Init(loc *Location) { + dy.y = resize(dy.y, len(loc.Gradient)) +} + +func (dy *DaiYuan) Beta(grad, gradPrev, dirPrev []float64) (beta float64) { + floats.SubTo(dy.y, grad, gradPrev) + norm := floats.Norm(grad, 2) + return norm * norm / floats.Dot(dirPrev, dy.y) +} + +// HagerZhang implements the Hager-Zhang variant of the CG method that computes the +// scaling parameter β_k according to the formula +// β_k = (y_k - 2 d_k |y_k|^2/(d_k·y_k))·∇f_{k+1} / (d_k·y_k), +// where y_k = ∇f_{k+1} - ∇f_k. +type HagerZhang struct { + y []float64 +} + +func (hz *HagerZhang) Init(loc *Location) { + hz.y = resize(hz.y, len(loc.Gradient)) +} + +func (hz *HagerZhang) Beta(grad, gradPrev, dirPrev []float64) (beta float64) { + floats.SubTo(hz.y, grad, gradPrev) + dirDotY := floats.Dot(dirPrev, hz.y) + gDotY := floats.Dot(grad, hz.y) + gDotDir := floats.Dot(grad, dirPrev) + yNorm := floats.Norm(hz.y, 2) + return (gDotY - 2*gDotDir*yNorm*yNorm/dirDotY) / dirDotY +} diff --git a/optimize/convex/lp/convert.go b/optimize/convex/lp/convert.go new file mode 100644 index 00000000..5f2178c1 --- /dev/null +++ b/optimize/convex/lp/convert.go @@ -0,0 +1,141 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package lp + +import ( + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +// TODO(btracey): Have some sort of preprocessing step for helping to fix A to make it +// full rank? +// TODO(btracey): Reduce rows? Get rid of all zeros, places where only one variable +// is there, etc. Could be implemented with a Reduce function. +// TODO(btracey): Provide method of artificial variables for help when problem +// is infeasible? +// TODO(btracey): Add an lp.Solve that solves an LP in non-standard form. + +// Convert converts a General-form LP into a standard form LP. +// The general form of an LP is: +// minimize c^T * x +// s.t G * x <= h +// A * x = b +// And the standard form is: +// minimize cNew^T * x +// s.t aNew * x = bNew +// x >= 0 +// If there are no constraints of the given type, the inputs may be nil. +func Convert(c []float64, g mat64.Matrix, h []float64, a mat64.Matrix, b []float64) (cNew []float64, aNew *mat64.Dense, bNew []float64) { + nVar := len(c) + nIneq := len(h) + + // Check input sizes. + if g == nil { + if nIneq != 0 { + panic(badShape) + } + } else { + gr, gc := g.Dims() + if gr != nIneq { + panic(badShape) + } + if gc != nVar { + panic(badShape) + } + } + + nEq := len(b) + if a == nil { + if nEq != 0 { + panic(badShape) + } + } else { + ar, ac := a.Dims() + if ar != nEq { + panic(badShape) + } + if ac != nVar { + panic(badShape) + } + } + + // Convert the general form LP. + // Derivation: + // 0. Start with general form + // min. c^T * x + // s.t. G * x <= h + // A * x = b + // 1. Introduce slack variables for each constraint + // min. c^T * x + // s.t. G * x + s = h + // A * x = b + // s >= 0 + // 2. Add non-negativity constraints for x by splitting x + // into positive and negative components. + // x = xp - xn + // xp >= 0, xn >= 0 + // This makes the LP + // min. c^T * xp - c^T xn + // s.t. G * xp - G * xn + s = h + // A * xp - A * xn = b + // xp >= 0, xn >= 0, s >= 0 + // 3. Write the above in standard form: + // xt = [xp + // xn + // s ] + // min. [c^T, -c^T, 0] xt + // s.t. [G, -G, I] xt = h + // [A, -A, 0] xt = b + // x >= 0 + + // In summary: + // Original LP: + // min. c^T * x + // s.t. G * x <= h + // A * x = b + // Standard Form: + // xt = [xp; xn; s] + // min. [c^T, -c^T, 0] xt + // s.t. [G, -G, I] xt = h + // [A, -A, 0] xt = b + // x >= 0 + + // New size of x is [xp, xn, s] + nNewVar := nVar + nVar + nIneq + + // Construct cNew = [c; -c; 0] + cNew = make([]float64, nNewVar) + copy(cNew, c) + copy(cNew[nVar:], c) + floats.Scale(-1, cNew[nVar:2*nVar]) + + // New number of equality constraints is the number of total constraints. + nNewEq := nIneq + nEq + + // Construct bNew = [h, b]. + bNew = make([]float64, nNewEq) + copy(bNew, h) + copy(bNew[nIneq:], b) + + // Construct aNew = [G, -G, I; A, -A, 0]. + aNew = mat64.NewDense(nNewEq, nNewVar, nil) + if nIneq != 0 { + aView := (aNew.View(0, 0, nIneq, nVar)).(*mat64.Dense) + aView.Copy(g) + aView = (aNew.View(0, nVar, nIneq, nVar)).(*mat64.Dense) + aView.Scale(-1, g) + aView = (aNew.View(0, 2*nVar, nIneq, nIneq)).(*mat64.Dense) + for i := 0; i < nIneq; i++ { + aView.Set(i, i, 1) + } + } + if nEq != 0 { + aView := (aNew.View(nIneq, 0, nEq, nVar)).(*mat64.Dense) + aView.Copy(a) + aView = (aNew.View(nIneq, nVar, nEq, nVar)).(*mat64.Dense) + aView.Scale(-1, a) + } + return cNew, aNew, bNew +} diff --git a/optimize/convex/lp/simplex.go b/optimize/convex/lp/simplex.go new file mode 100644 index 00000000..41caf67e --- /dev/null +++ b/optimize/convex/lp/simplex.go @@ -0,0 +1,619 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package lp implements routines for solving linear programs. +package lp + +import ( + "errors" + "fmt" + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +// TODO(btracey): Could have a solver structure with an abstract factorizer. With +// this transformation the same high-level code could handle both Dense and Sparse. +// TODO(btracey): Need to improve error handling. Only want to panic if condition number inf. +// TODO(btracey): Performance enhancements. There are currently lots of linear +// solves that can be improved by doing rank-one updates. For example, the swap +// step is just a rank-one update. +// TODO(btracey): Better handling on the linear solve errors. If the condition +// number is not inf and the equation solved "well", should keep moving. + +var ( + ErrBland = errors.New("lp: bland: all replacements are negative or cause ill-conditioned ab") + ErrInfeasible = errors.New("lp: problem is infeasible") + ErrLinSolve = errors.New("lp: linear solve failure") + ErrUnbounded = errors.New("lp: problem is unbounded") + ErrSingular = errors.New("lp: A is singular") + ErrZeroColumn = errors.New("lp: A has a column of all zeros") + ErrZeroRow = errors.New("lp: A has a row of all zeros") +) + +var ( + badShape = "lp: size mismatch" +) + +// TODO(btracey): Should these tolerances be part of a settings struct? + +const ( + // initPosTol is the tolerance on the initial condition being feasible. Strictly, + // the x should be positive, but instead it must be greater than -initPosTol. + initPosTol = 1e-13 + // blandNegTol is the tolerance on the value being greater than 0 in the bland test. + blandNegTol = 1e-14 + // rRoundTol is the tolerance for rounding values to zero when testing if + // constraints are met. + rRoundTol = 1e-13 + // dRoundTol is the tolerance for testing if values are zero for the problem + // being unbounded. + dRoundTol = 1e-13 + // phaseIZeroTol tests if the Phase I problem returned a feasible solution. + phaseIZeroTol = 1e-12 + // blandZeroTol is the tolerance on testing if the bland solution can move. + blandZeroTol = 1e-12 +) + +// Simplex solves a linear program in standard form using Danzig's Simplex +// algorithm. The standard form of a linear program is: +// minimize c^T x +// s.t. A*x = b +// x >= 0 . +// The input tol sets how close to the optimal solution is found (specifically, +// when the maximal reduced cost is below tol). An error will be returned if the +// problem is infeasible or unbounded. In rare cases, numeric errors can cause +// the Simplex to fail. In this case, an error will be returned along with the +// most recently found feasible solution. +// +// The Convert function can be used to transform a general LP into standard form. +// +// The input matrix A must have full rank and may not contain any columns with +// all zeros. Furthermore, len(c) must equal the number of columns of A, and len(b) +// must equal the number of rows of A. Simplex will panic if these conditions are +// not met. +// +// initialBasic can be used to set the initial set of indices for a feasible +// solution to the LP. If an initial feasible solution is not known, initialBasic +// may be nil. If initialBasic is non-nil, len(initialBasic) must equal the number +// of rows of A and must be an actual feasible solution to the LP, otherwise +// Simplex will panic. +// +// A description of the Simplex algorithm can be found in Ch. 8 of +// Strang, Gilbert. "Linear Algebra and Applications." Academic, New York (1976). +// For a detailed video introduction, see lectures 11-13 of UC Math 352 +// https://www.youtube.com/watch?v=ESzYPFkY3og&index=11&list=PLh464gFUoJWOmBYla3zbZbc4nv2AXez6X. +func Simplex(c []float64, A mat64.Matrix, b []float64, tol float64, initialBasic []int) (optF float64, optX []float64, err error) { + ans, x, _, err := simplex(initialBasic, c, A, b, tol) + return ans, x, err +} + +func simplex(initialBasic []int, c []float64, A mat64.Matrix, b []float64, tol float64) (float64, []float64, []int, error) { + err := verifyInputs(initialBasic, c, A, b) + if err != nil { + if err == ErrUnbounded { + return math.Inf(-1), nil, nil, ErrUnbounded + } + return math.NaN(), nil, nil, err + } + m, n := A.Dims() + + // There is at least one optimal solution to the LP which is at the intersection + // to a set of constraint boundaries. For a standard form LP with m variables + // and n equality constraints, at least m-n elements of x must equal zero + // at optimality. The Simplex algorithm solves the standard-form LP by starting + // at an initial constraint vertex and successively moving to adjacent constraint + // vertices. At every vertex, the set of non-zero x values is the "basic + // feasible solution". The list of non-zero x's are maintained in basicIdxs, + // the respective columns of A are in ab, and the actual non-zero values of + // x are in xb. + // + // The LP is equality constrained such that A * x = b. This can be expanded + // to + // ab * xb + an * xn = b + // where ab are the columns of a in the basic set, and an are all of the + // other columns. Since each element of xn is zero by definition, this means + // that for all feasible solutions xb = ab^-1 * b. + // + // Before the simplex algorithm can start, an initial feasible solution must + // be found. If initialBasic is non-nil a feasible solution has been supplied. + // Otherwise the "Phase I" problem must be solved to find an initial feasible + // solution. + + var basicIdxs []int // The indices of the non-zero x values. + var ab *mat64.Dense // The subset of columns of A listed in basicIdxs. + var xb []float64 // The non-zero elements of x. xb = ab^-1 b + + if initialBasic != nil { + // InitialBasic supplied. Panic if incorrect length or infeasible. + if len(initialBasic) != m { + panic("lp: incorrect number of initial vectors") + } + ab = mat64.NewDense(m, len(initialBasic), nil) + extractColumns(ab, A, initialBasic) + xb = make([]float64, m) + err = initializeFromBasic(xb, ab, b) + if err != nil { + panic(err) + } + basicIdxs = make([]int, len(initialBasic)) + copy(basicIdxs, initialBasic) + } else { + // No inital basis supplied. Solve the PhaseI problem. + basicIdxs, ab, xb, err = findInitialBasic(A, b) + if err != nil { + return math.NaN(), nil, nil, err + } + } + + // basicIdxs contains the indexes for an initial feasible solution, + // ab contains the extracted columns of A, and xb contains the feasible + // solution. All x not in the basic set are 0 by construction. + + // nonBasicIdx is the set of nonbasic variables. + nonBasicIdx := make([]int, 0, n-m) + inBasic := make(map[int]struct{}) + for _, v := range basicIdxs { + inBasic[v] = struct{}{} + } + for i := 0; i < n; i++ { + _, ok := inBasic[i] + if !ok { + nonBasicIdx = append(nonBasicIdx, i) + } + } + + // cb is the subset of c for the basic variables. an and cn + // are the equivalents to ab and cb but for the nonbasic variables. + cb := make([]float64, len(basicIdxs)) + for i, idx := range basicIdxs { + cb[i] = c[idx] + } + cn := make([]float64, len(nonBasicIdx)) + for i, idx := range nonBasicIdx { + cn[i] = c[idx] + } + an := mat64.NewDense(m, len(nonBasicIdx), nil) + extractColumns(an, A, nonBasicIdx) + + bVec := mat64.NewVector(len(b), b) + cbVec := mat64.NewVector(len(cb), cb) + + // Temporary data needed each iteration. (Described later) + r := make([]float64, n-m) + move := make([]float64, m) + + // Solve the linear program starting from the initial feasible set. This is + // the "Phase 2" problem. + // + // Algorithm: + // 1) Compute the "reduced costs" for the non-basic variables. The reduced + // costs are the lagrange multipliers of the constraints. + // r = cn - an^T * ab^-T * cb + // 2) If all of the reduced costs are positive, no improvement is possible, + // and the solution is optimal (xn can only increase because of + // non-negativity constraints). Otherwise, the solution can be improved and + // one element will be exchanged in the basic set. + // 3) Choose the x_n with the most negative value of r. Call this value xe. + // This variable will be swapped into the basic set. + // 4) Increase xe until the next constraint boundary is met. This will happen + // when the first element in xb becomes 0. The distance xe can increase before + // a given element in xb becomes negative can be found from + // xb = Ab^-1 b - Ab^-1 An xn + // = Ab^-1 b - Ab^-1 Ae xe + // = bhat + d x_e + // xe = bhat_i / - d_i + // where Ae is the column of A corresponding to xe. + // The constraining basic index is the first index for which this is true, + // so remove the element which is min_i (bhat_i / -d_i), assuming d_i is negative. + // If no d_i is less than 0, then the problem is unbounded. + // 5) If the new xe is 0 (that is, bhat_i == 0), then this location is at + // the intersection of several constraints. Use the Bland rule instead + // of the rule in step 4 to avoid cycling. + for { + // Compute reduced costs -- r = cn - an^T ab^-T cb + var tmp mat64.Vector + err = tmp.SolveVec(ab.T(), cbVec) + if err != nil { + break + } + data := make([]float64, n-m) + tmp2 := mat64.NewVector(n-m, data) + tmp2.MulVec(an.T(), &tmp) + floats.SubTo(r, cn, data) + + // Replace the most negative element in the simplex. If there are no + // negative entries then the optimal solution has been found. + minIdx := floats.MinIdx(r) + if r[minIdx] >= -tol { + break + } + + for i, v := range r { + if math.Abs(v) < rRoundTol { + r[i] = 0 + } + } + + // Compute the moving distance. + err = computeMove(move, minIdx, A, ab, xb, nonBasicIdx) + if err != nil { + if err == ErrUnbounded { + return math.Inf(-1), nil, nil, ErrUnbounded + } + break + } + + // Replace the basic index along the tightest constraint. + replace := floats.MinIdx(move) + if move[replace] <= 0 { + replace, minIdx, err = replaceBland(A, ab, xb, basicIdxs, nonBasicIdx, r, move) + if err != nil { + if err == ErrUnbounded { + return math.Inf(-1), nil, nil, ErrUnbounded + } + break + } + } + + // Replace the constrained basicIdx with the newIdx. + basicIdxs[replace], nonBasicIdx[minIdx] = nonBasicIdx[minIdx], basicIdxs[replace] + cb[replace], cn[minIdx] = cn[minIdx], cb[replace] + tmpCol1 := mat64.Col(nil, replace, ab) + tmpCol2 := mat64.Col(nil, minIdx, an) + ab.SetCol(replace, tmpCol2) + an.SetCol(minIdx, tmpCol1) + + // Compute the new xb. + xbVec := mat64.NewVector(len(xb), xb) + err = xbVec.SolveVec(ab, bVec) + if err != nil { + break + } + } + // Found the optimum successfully or died trying. The basic variables get + // their values, and the non-basic variables are all zero. + opt := floats.Dot(cb, xb) + xopt := make([]float64, n) + for i, v := range basicIdxs { + xopt[v] = xb[i] + } + return opt, xopt, basicIdxs, err +} + +// computeMove computes how far can be moved replacing each index. The results +// are stored into move. +func computeMove(move []float64, minIdx int, A mat64.Matrix, ab *mat64.Dense, xb []float64, nonBasicIdx []int) error { + // Find ae. + col := mat64.Col(nil, nonBasicIdx[minIdx], A) + aCol := mat64.NewVector(len(col), col) + + // d = - Ab^-1 Ae + nb, _ := ab.Dims() + d := make([]float64, nb) + dVec := mat64.NewVector(nb, d) + err := dVec.SolveVec(ab, aCol) + if err != nil { + return ErrLinSolve + } + floats.Scale(-1, d) + + for i, v := range d { + if math.Abs(v) < dRoundTol { + d[i] = 0 + } + } + + // If no di < 0, then problem is unbounded. + if floats.Min(d) >= 0 { + return ErrUnbounded + } + + // move = bhat_i / - d_i, assuming d is negative. + bHat := xb // ab^-1 b + for i, v := range d { + if v >= 0 { + move[i] = math.Inf(1) + } else { + move[i] = bHat[i] / math.Abs(v) + } + } + return nil +} + +// replaceBland uses the Bland rule to find the indices to swap if the minimum +// move is 0. The indices to be swapped are replace and minIdx (following the +// nomenclature in the main routine). +func replaceBland(A mat64.Matrix, ab *mat64.Dense, xb []float64, basicIdxs, nonBasicIdx []int, r, move []float64) (replace, minIdx int, err error) { + m, _ := A.Dims() + // Use the traditional bland rule, except don't replace a constraint which + // causes the new ab to be singular. + for i, v := range r { + if v > -blandNegTol { + continue + } + minIdx = i + err = computeMove(move, minIdx, A, ab, xb, nonBasicIdx) + if err != nil { + // Either unbounded or something went wrong. + return -1, -1, err + } + replace = floats.MinIdx(move) + if math.Abs(move[replace]) > blandZeroTol { + // Large enough that it shouldn't be a problem + return replace, minIdx, nil + } + // Find a zero index where replacement is non-singular. + biCopy := make([]int, len(basicIdxs)) + for replace, v := range move { + if v > blandZeroTol { + continue + } + copy(biCopy, basicIdxs) + biCopy[replace] = nonBasicIdx[minIdx] + abTmp := mat64.NewDense(m, len(biCopy), nil) + extractColumns(abTmp, A, biCopy) + // If the condition number is reasonable, use this index. + if mat64.Cond(abTmp, 1) < 1e16 { + return replace, minIdx, nil + } + } + } + return -1, -1, ErrBland +} + +func verifyInputs(initialBasic []int, c []float64, A mat64.Matrix, b []float64) error { + m, n := A.Dims() + if len(c) != n { + panic("lp: c vector incorrect length") + } + if len(b) != m { + panic("lp: b vector incorrect length") + } + if len(c) != n { + panic("lp: c vector incorrect length") + } + if len(initialBasic) != 0 && len(initialBasic) != m { + panic("lp: initialBasic incorrect length") + } + + // Do some sanity checks so that ab does not become singular during the + // simplex solution. If the ZeroRow checks are removed then the code for + // finding a set of linearly indepent columns must be improved. + + // Check that if a row of A only has zero elements that corresponding + // element in b is zero, otherwise the problem is infeasible. + // Otherwise return ErrZeroRow. + for i := 0; i < m; i++ { + isZero := true + for j := 0; j < n; j++ { + if A.At(i, j) != 0 { + isZero = false + break + } + } + if isZero && b[i] != 0 { + // Infeasible + return ErrInfeasible + } else if isZero { + return ErrZeroRow + } + } + // Check that if a column only has zero elements that the respective C vector + // is positive (otherwise unbounded). Otherwise return ErrZeroColumn. + for j := 0; j < n; j++ { + isZero := true + for i := 0; i < m; i++ { + if A.At(i, j) != 0 { + isZero = false + break + } + } + if isZero && c[j] < 0 { + return ErrUnbounded + } else if isZero { + return ErrZeroColumn + } + } + return nil +} + +// initializeFromBasic initializes the basic feasible solution given a set of +// basic indices. It extracts the columns of A specified by basicIdxs and finds +// the x values at that location. These are stored into xb. +// +// If the columns of A are not linearly independent or if the initial set is not +// feasible, an error is returned. +func initializeFromBasic(xb []float64, ab *mat64.Dense, b []float64) error { + m, _ := ab.Dims() + if len(xb) != m { + panic("simplex: bad xb length") + } + xbMat := mat64.NewVector(m, xb) + + err := xbMat.SolveVec(ab, mat64.NewVector(m, b)) + if err != nil { + return errors.New("lp: subcolumns of A for supplied initial basic singular") + } + // The solve ensures that the equality constraints are met (ab * xb = b). + // Thus, the solution is feasible if and only if all of the x's are positive. + allPos := true + for _, v := range xb { + if v < -initPosTol { + allPos = false + break + } + } + if !allPos { + return errors.New("lp: supplied subcolumns not a feasible solution") + } + return nil +} + +// extractColumns copies the columns specified by cols into the columns of dst. +func extractColumns(dst *mat64.Dense, A mat64.Matrix, cols []int) { + r, c := dst.Dims() + ra, _ := A.Dims() + if ra != r { + panic("simplex: row mismatch") + } + if c != len(cols) { + panic("simplex: column mismatch") + } + col := make([]float64, r) + for j, idx := range cols { + mat64.Col(col, idx, A) + dst.SetCol(j, col) + } +} + +// findInitialBasic finds an initial basic solution, and returns the basic +// indices, ab, and xb. +func findInitialBasic(A mat64.Matrix, b []float64) ([]int, *mat64.Dense, []float64, error) { + m, n := A.Dims() + basicIdxs := findLinearlyIndependent(A) + if len(basicIdxs) != m { + return nil, nil, nil, ErrSingular + } + + // It may be that this linearly independent basis is also a feasible set. If + // so, the Phase I problem can be avoided. + ab := mat64.NewDense(m, len(basicIdxs), nil) + extractColumns(ab, A, basicIdxs) + xb := make([]float64, m) + err := initializeFromBasic(xb, ab, b) + if err == nil { + return basicIdxs, ab, xb, nil + } + + // This set was not feasible. Instead the "Phase I" problem must be solved + // to find an initial feasible set of basis. + // + // Method: Construct an LP whose optimal solution is a feasible solution + // to the original LP. + // 1) Introduce an artificial variable x_{n+1}. + // 2) Let x_j be the most negative element of x_b (largest constraint violation). + // 3) Add the artificial variable to A with: + // a_{n+1} = b - \sum_{i in basicIdxs} a_i + a_j + // swap j with n+1 in the basicIdxs. + // 4) Define a new LP: + // minimize x_{n+1} + // subject to [A A_{n+1}][x_1 ... x_{n+1}] = b + // x, x_{n+1} >= 0 + // 5) Solve this LP. If x_{n+1} != 0, then the problem is infeasible, otherwise + // the found basis can be used as an initial basis for phase II. + // + // The extra column in Step 3 is defined such that the vector of 1s is an + // initial feasible solution. + + // Find the largest constraint violator. + // Compute a_{n+1} = b - \sum{i in basicIdxs}a_i + a_j. j is in basicIDx, so + // instead just subtract the basicIdx columns that are not minIDx. + minIdx := floats.MinIdx(xb) + aX1 := make([]float64, m) + copy(aX1, b) + col := make([]float64, m) + for i, v := range basicIdxs { + if i == minIdx { + continue + } + mat64.Col(col, v, A) + floats.Sub(aX1, col) + } + + // Construct the new LP. + // aNew = [A, a_{n+1}] + // bNew = b + // cNew = 1 for x_{n+1} + aNew := mat64.NewDense(m, n+1, nil) + aNew.Copy(A) + aNew.SetCol(n, aX1) + basicIdxs[minIdx] = n // swap minIdx with n in the basic set. + c := make([]float64, n+1) + c[n] = 1 + + // Solve the Phase I linear program. + _, xOpt, newBasic, err := simplex(basicIdxs, c, aNew, b, 1e-10) + if err != nil { + return nil, nil, nil, errors.New(fmt.Sprintf("lp: error finding feasible basis: %s", err)) + } + + // The original LP is infeasible if the added variable has non-zero value + // in the optimal solution to the Phase I problem. + if math.Abs(xOpt[n]) > phaseIZeroTol { + return nil, nil, nil, ErrInfeasible + } + + // The basis found in Phase I is a feasible solution to the original LP if + // the added variable is not in the basis. + addedIdx := -1 + for i, v := range newBasic { + if v == n { + addedIdx = i + } + xb[i] = xOpt[v] + } + if addedIdx == -1 { + extractColumns(ab, A, newBasic) + return newBasic, ab, xb, nil + } + + // The value of the added variable is in the basis, but it has a zero value. + // See if exchanging another variable into the basic set finds a feasible + // solution. + basicMap := make(map[int]struct{}) + for _, v := range newBasic { + basicMap[v] = struct{}{} + } + var set bool + for i := range xOpt { + if _, inBasic := basicMap[i]; inBasic { + continue + } + newBasic[addedIdx] = i + if set { + mat64.Col(col, i, A) + ab.SetCol(addedIdx, col) + } else { + extractColumns(ab, A, newBasic) + set = true + } + err := initializeFromBasic(xb, ab, b) + if err == nil { + return newBasic, ab, xb, nil + } + } + return nil, nil, nil, ErrInfeasible +} + +// findLinearlyIndependnt finds a set of linearly independent columns of A, and +// returns the column indexes of the linearly independent columns. +func findLinearlyIndependent(A mat64.Matrix) []int { + m, n := A.Dims() + idxs := make([]int, 0, m) + columns := mat64.NewDense(m, m, nil) + newCol := make([]float64, m) + // Walk in reverse order because slack variables are typically the last columns + // of A. + for i := n - 1; i >= 0; i-- { + if len(idxs) == m { + break + } + mat64.Col(newCol, i, A) + columns.SetCol(len(idxs), newCol) + if len(idxs) == 0 { + // A column is linearly independent from the null set. + // If all-zero column of A are allowed, this code needs to be adjusted. + idxs = append(idxs, i) + continue + } + if mat64.Cond(columns.View(0, 0, m, len(idxs)+1), 1) > 1e12 { + // Not linearly independent. + continue + } + idxs = append(idxs, i) + } + return idxs +} diff --git a/optimize/convex/lp/simplex_test.go b/optimize/convex/lp/simplex_test.go new file mode 100644 index 00000000..33d4359c --- /dev/null +++ b/optimize/convex/lp/simplex_test.go @@ -0,0 +1,272 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package lp + +import ( + "fmt" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +const convergenceTol = 1e-10 + +func TestSimplex(t *testing.T) { + // First test specific inputs. These were collected from failures + // during randomized testing. + // TODO(btracey): Test specific problems with known solutions. + for _, test := range []struct { + A mat64.Matrix + b []float64 + c []float64 + tol float64 + initialBasic []int + }{ + { + // Basic feasible LP + A: mat64.NewDense(2, 4, []float64{ + -1, 2, 1, 0, + 3, 1, 0, 1, + }), + b: []float64{4, 9}, + c: []float64{-1, -2, 0, 0}, + //initialBasic: nil, + tol: 0, + }, + { + // Zero row that caused linear solver failure + A: mat64.NewDense(3, 5, []float64{0.09917822373225804, 0, 0, -0.2588175087223661, -0.5935518220870567, 1.301111422556007, 0.12220247487326946, 0, 0, -1.9194869979254463, 0, 0, 0, 0, -0.8588221231396473}), + b: []float64{0, 0, 0}, + c: []float64{0, 0.598992624019304, 0, 0, 0}, + }, + { + // Case that caused linear solver failure + A: mat64.NewDense(13, 26, []float64{-0.7001209024399848, -0.7027502615621812, -0, 0.7354444798695736, -0, 0.476457578966189, 0.7001209024399848, 0.7027502615621812, 0, -0.7354444798695736, 0, -0.476457578966189, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.8446087238391438, -0, -0, 0.7705609478497938, -0, -0, -2.7311218710244463, 0, 0, -0.7705609478497938, 0, 0, 2.7311218710244463, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -0, 0.8332519091897401, 0.7762132098737671, -0, -0, -0.052470638647269585, 0, -0.8332519091897401, -0.7762132098737671, 0, 0, 0.052470638647269585, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.9898577208292023, 0.31653724289408824, -0, -0, 0.17797227766447388, 1.2702427184954932, -0.7998764021535656, -0.31653724289408824, 0, 0, -0.17797227766447388, -1.2702427184954932, 0.7998764021535656, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -0, -0, -0, -0, 0.4206278126213235, -0.7253374879437113, 0, 0, 0, 0, -0.4206278126213235, 0.7253374879437113, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -0, -0.7567988418466963, 0.3304567624749696, 0.8385927625193501, -0.0021606686026376387, -0, 0, 0.7567988418466963, -0.3304567624749696, -0.8385927625193501, 0.0021606686026376387, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -2.230107839590404, -0.9897104202085316, -0, 0.24703471683023603, -0, -2.382860345431941, 0.6206871648345162, 0.9897104202085316, 0, -0.24703471683023603, 0, 2.382860345431941, -0.6206871648345162, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 1.4350469221322282, -0.9730343818431852, -0, 2.326429855201535, -0, -0.14347849887004038, -1.4350469221322282, 0.9730343818431852, 0, -2.326429855201535, 0, 0.14347849887004038, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -0.7943912888763849, -0.13735037357335078, -0.5101161104860161, -0, -0, -1.4790634590370297, 0.050911195996747316, 0.13735037357335078, 0.5101161104860161, 0, 0, 1.4790634590370297, -0.050911195996747316, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, -0, -0.2515400440591492, 0.2058339272568599, -0, -0, -1.314023802253438, 0, 0.2515400440591492, -0.2058339272568599, 0, 0, 1.314023802253438, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0.08279503413614919, -0.16669071891829756, -0, -0.6208413721884664, -0, -0.6348258970402827, -0.08279503413614919, 0.16669071891829756, 0, 0.6208413721884664, 0, 0.6348258970402827, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, -0, -0, 0.49634739711260845, -0, -0, -0, 0, 0, -0.49634739711260845, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, -0.2797437186631715, -0.8356683570259136, 1.8970426594969672, -0.4095711945594497, 0.45831284820623924, -0.6109615338552246, 0.2797437186631715, 0.8356683570259136, -1.8970426594969672, 0.4095711945594497, -0.45831284820623924, 0.6109615338552246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1}), + b: []float64{-0.8446087238391436, 0, 1.9898577208292023, 0, 0, -2.230107839590404, 0, 0.20560871112361512, 0, 0, 0, 0, 0}, + c: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + }, + { + // Phase 1 of the above that panicked + A: mat64.NewDense(26, 52, []float64{0.7001209024399848, -0, -0, -0.31653724289408824, -0, -0, 0.9897104202085316, -1.4350469221322282, 0.13735037357335078, -0, -0.08279503413614919, -0, 0.2797437186631715, -0.7001209024399848, 0, 0, 0.31653724289408824, 0, 0, -0.9897104202085316, 1.4350469221322282, -0.13735037357335078, 0, 0.08279503413614919, 0, -0.2797437186631715, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7027502615621812, -0, -0.8332519091897401, -0, -0, 0.7567988418466963, -0, 0.9730343818431852, 0.5101161104860161, 0.2515400440591492, 0.16669071891829756, -0, 0.8356683570259136, -0.7027502615621812, 0, 0.8332519091897401, 0, 0, -0.7567988418466963, 0, -0.9730343818431852, -0.5101161104860161, -0.2515400440591492, -0.16669071891829756, 0, -0.8356683570259136, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0.7705609478497938, -0.7762132098737671, -0, -0, -0.3304567624749696, -0.24703471683023603, -0, -0, -0.2058339272568599, -0, -0.49634739711260845, -1.8970426594969672, 0, 0.7705609478497938, 0.7762132098737671, 0, 0, 0.3304567624749696, 0.24703471683023603, 0, 0, 0.2058339272568599, 0, 0.49634739711260845, 1.8970426594969672, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7354444798695736, -0, -0, -0.17797227766447388, -0, -0.8385927625193501, -0, -2.326429855201535, -0, -0, 0.6208413721884664, -0, 0.4095711945594497, 0.7354444798695736, 0, 0, 0.17797227766447388, 0, 0.8385927625193501, 0, 2.326429855201535, 0, 0, -0.6208413721884664, 0, -0.4095711945594497, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -1.2702427184954932, -0.4206278126213235, 0.0021606686026376387, 2.382860345431941, -0, 1.4790634590370297, -0, -0, -0, -0.45831284820623924, 0, 0, 0, 1.2702427184954932, 0.4206278126213235, -0.0021606686026376387, -2.382860345431941, 0, -1.4790634590370297, 0, 0, 0, 0.45831284820623924, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.476457578966189, 2.7311218710244463, 0.052470638647269585, 0.7998764021535656, 0.7253374879437113, -0, -0.6206871648345162, 0.14347849887004038, -0.050911195996747316, 1.314023802253438, 0.6348258970402827, -0, 0.6109615338552246, 0.476457578966189, -2.7311218710244463, -0.052470638647269585, -0.7998764021535656, -0.7253374879437113, 0, 0.6206871648345162, -0.14347849887004038, 0.050911195996747316, -1.314023802253438, -0.6348258970402827, 0, -0.6109615338552246, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7001209024399848, -0, -0, 0.31653724289408824, -0, -0, -0.9897104202085316, 1.4350469221322282, -0.13735037357335078, -0, 0.08279503413614919, -0, -0.2797437186631715, 0.7001209024399848, 0, 0, -0.31653724289408824, 0, 0, 0.9897104202085316, -1.4350469221322282, 0.13735037357335078, 0, -0.08279503413614919, 0, 0.2797437186631715, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.7027502615621812, -0, 0.8332519091897401, -0, -0, -0.7567988418466963, -0, -0.9730343818431852, -0.5101161104860161, -0.2515400440591492, -0.16669071891829756, -0, -0.8356683570259136, 0.7027502615621812, 0, -0.8332519091897401, 0, 0, 0.7567988418466963, 0, 0.9730343818431852, 0.5101161104860161, 0.2515400440591492, 0.16669071891829756, 0, 0.8356683570259136, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0.7705609478497938, 0.7762132098737671, -0, -0, 0.3304567624749696, 0.24703471683023603, -0, -0, 0.2058339272568599, -0, 0.49634739711260845, 1.8970426594969672, 0, -0.7705609478497938, -0.7762132098737671, 0, 0, -0.3304567624749696, -0.24703471683023603, 0, 0, -0.2058339272568599, 0, -0.49634739711260845, -1.8970426594969672, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.7354444798695736, -0, -0, 0.17797227766447388, -0, 0.8385927625193501, -0, 2.326429855201535, -0, -0, -0.6208413721884664, -0, -0.4095711945594497, -0.7354444798695736, 0, 0, -0.17797227766447388, 0, -0.8385927625193501, 0, -2.326429855201535, 0, 0, 0.6208413721884664, 0, 0.4095711945594497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, 1.2702427184954932, 0.4206278126213235, -0.0021606686026376387, -2.382860345431941, -0, -1.4790634590370297, -0, -0, -0, 0.45831284820623924, 0, 0, 0, -1.2702427184954932, -0.4206278126213235, 0.0021606686026376387, 2.382860345431941, 0, 1.4790634590370297, 0, 0, 0, -0.45831284820623924, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.476457578966189, -2.7311218710244463, -0.052470638647269585, -0.7998764021535656, -0.7253374879437113, -0, 0.6206871648345162, -0.14347849887004038, 0.050911195996747316, -1.314023802253438, -0.6348258970402827, -0, -0.6109615338552246, -0.476457578966189, 2.7311218710244463, 0.052470638647269585, 0.7998764021535656, 0.7253374879437113, 0, -0.6206871648345162, 0.14347849887004038, -0.050911195996747316, 1.314023802253438, 0.6348258970402827, 0, 0.6109615338552246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -1, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -1, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -1, -0, -0, -0, -0, -0, -0, -0, -0, -0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -1, -0, -0, -0, -0, -0, -0, -0, -0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -1, -0, -0, -0, -0, -0, -0, -0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -1, -0, -0, -0, -0, -0, -0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -1, -0, -0, -0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -1, -0, -0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -1, -0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -1, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -1, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1.8446087238391438, 1, -0.9898577208292023, 1, 1, 2.230107839590404, 1, 0.7943912888763849, 1, 1, 1, 1, 1, -1.8446087238391438, -1, 0.9898577208292023, -1, -1, -2.230107839590404, -1, -0.7943912888763849, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), + b: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + c: []float64{-0.8446087238391436, 0, 1.9898577208292023, 0, 0, -2.230107839590404, 0, 0.20560871112361512, 0, 0, 0, 0, 0, 0.8446087238391436, -0, -1.9898577208292023, -0, -0, 2.230107839590404, -0, -0.20560871112361512, -0, -0, -0, -0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + // Dense case that panicked. + A: mat64.NewDense(6, 15, []float64{0.3279477313560112, 0.04126296122557327, 0.24121743535067522, -0.8676933623438741, -0.3279477313560112, -0.04126296122557327, -0.24121743535067522, 0.8676933623438741, 1, 0, 0, 0, 0, 0, 1.3702148909442915, 0.43713186538468607, 0.8613818492485417, -0.9298615442657688, -0.037784779008231184, -0.43713186538468607, -0.8613818492485417, 0.9298615442657688, 0.037784779008231184, 0, 1, 0, 0, 0, 0, 0.3478112701177931, -0, 0.748352668598051, -0.4294796840343912, -0, 0, -0.748352668598051, 0.4294796840343912, 0, 0, 0, 1, 0, 0, 0, -1, -0, 1.1913912184457485, 1.732132186658447, 0.4026384828544584, 0, -1.1913912184457485, -1.732132186658447, -0.4026384828544584, 0, 0, 0, 1, 0, 0, -0.4598555419763902, -0, 1.2088959976921831, -0.7297794575275871, 1.9835614149566971, 0, -1.2088959976921831, 0.7297794575275871, -1.9835614149566971, 0, 0, 0, 0, 1, 0, 0.5986809560819324, 0.19738159369304414, -1.0647198575836367, -0, -0.7264943883762761, -0.19738159369304414, 1.0647198575836367, 0, 0.7264943883762761, 0, 0, 0, 0, 0, 1, 0.36269644970561576}), + b: []float64{2.3702148909442915, 1.3478112701177931, 0, -0.4598555419763902, 1.5986809560819324, 1.3626964497056158}, + c: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + }, + { + A: mat64.NewDense(6, 11, []float64{-0.036551083288733854, -0.8967234664797694, 0.036551083288733854, 0.8967234664797694, 1, 0, 0, 0, 0, 0, -0.719908817815329, -1.9043311904524263, -0, 1.9043311904524263, 0, 0, 1, 0, 0, 0, 0, -1.142213296802784, -0, 0.17584914855696687, 0, -0.17584914855696687, 0, 0, 1, 0, 0, 0, -0.5423586338987796, -0.21663357118058713, -0.4815354890024489, 0.21663357118058713, 0.4815354890024489, 0, 0, 0, 1, 0, 0, -0.6864090947259134, -0, -0, 0, 0, 0, 0, 0, 0, 1, 0, 0.4091621839837596, -1.1853040616164046, -0.11374085137543871, 1.1853040616164046, 0.11374085137543871, 0, 0, 0, 0, 0, 1, -1.7416078575675549}), + b: []float64{0.28009118218467105, -0.14221329680278405, 0.4576413661012204, 0.3135909052740866, 1.4091621839837596, -1.7416078575675549}, + c: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + initialBasic: []int{10, 8, 7, 6, 5, 4}, + }, + { + A: mat64.NewDense(6, 10, []float64{-0.036551083288733854, -0.8967234664797694, 0.036551083288733854, 0.8967234664797694, 1, 0, 0, 0, 0, 0, -1.9043311904524263, -0, 1.9043311904524263, 0, 0, 1, 0, 0, 0, 0, -0, 0.17584914855696687, 0, -0.17584914855696687, 0, 0, 1, 0, 0, 0, -0.21663357118058713, -0.4815354890024489, 0.21663357118058713, 0.4815354890024489, 0, 0, 0, 1, 0, 0, -0, -0, 0, 0, 0, 0, 0, 0, 1, 0, -1.1853040616164046, -0.11374085137543871, 1.1853040616164046, 0.11374085137543871, 0, 0, 0, 0, 0, 1}), + b: []float64{0.28009118218467105, -0.14221329680278405, 0.4576413661012204, 0.3135909052740866, 1.4091621839837596, -1.7416078575675549}, + c: []float64{-1.1951160054922971, -1.354633418345746, 1.1951160054922971, 1.354633418345746, 0, 0, 0, 0, 0, 0}, + initialBasic: []int{0, 8, 7, 6, 5, 4}, + }, + { + A: mat64.NewDense(6, 14, []float64{-0.4398035705048233, -0, -1.1190414559968929, -0, 0.4398035705048233, 0, 1.1190414559968929, 0, 1, 0, 0, 0, 0, 0, -0, 0.45892918156139395, -0, -0, 0, -0.45892918156139395, 0, 0, 0, 1, 0, 0, 0, 0, -0, -0, -0.3163051515958635, -0, 0, 0, 0.3163051515958635, 0, 0, 0, 1, 0, 0, 0, -0, -0, -1.8226051692445888, -0.8154477101733032, 0, 0, 1.8226051692445888, 0.8154477101733032, 0, 0, 0, 1, 0, 0, -0, 1.0020104354806922, -2.80863692523519, -0.8493721031516384, 0, -1.0020104354806922, 2.80863692523519, 0.8493721031516384, 0, 0, 0, 0, 1, 0, -0.8292937871394104, -1.4615144665021647, -0, -0, 0.8292937871394104, 1.4615144665021647, 0, 0, 0, 0, 0, 0, 0, 1}), + b: []float64{0, -1.0154749704172474, 0, 0, 0, -1.5002324315812783}, + c: []float64{1.0665389045026794, 0.097366273706136, 0, 2.7928153636989954, -1.0665389045026794, -0.097366273706136, -0, -2.7928153636989954, 0, 0, 0, 0, 0, 0}, + initialBasic: []int{5, 12, 11, 10, 0, 8}, + }, + { + // Bad Phase I setup. + A: mat64.NewDense(6, 7, []float64{1.4009742075419371, 0, 0.05737255493210325, -2.5954004393412915, 0, 1.561789236911904, 0, 0.17152506517602673, 0, 0, 0, 0, 0, -0.3458126550149948, 1.900744052464951, -0.32773164134097343, -0.9648201331251137, 0, 0, 0, 0, -1.3229549190526497, 0.0692227703722903, 0, 0, -0.1024297720479933, 0.4550740188869777, 0, 0.013599438965679167, 0, 0, 0, 0, 0, -0.1164365105021209, 0, 0, 0.4077091957443405, 1.5682816151954875, 0.8411734682369051, 0.22379142247562167, 1.2206581060250778}), + b: []float64{0.3293809220378252, 0, -0.5688424847664554, 0, 0, 1.4832526082339592}, + c: []float64{0.5246370956983506, -0.36608819899109946, 1.5854141981237713, 0.5170486527020665, 0, 1.4006819866163691, 0.7733814538809437}, + }, + { + // The problem is feasible, but the PhaseI problem keeps the last + // variable in the basis. + A: mat64.NewDense(2, 3, []float64{0.7171320440380402, 0, 0.22818288617480836, 0, -0.10030202006494793, -0.3282372661549324}), + b: []float64{0.8913013436978257, 0}, + c: []float64{0, 0, 1.16796158316812}, + initialBasic: nil, + }, + { + // Case where primal was returned as feasible, but the dual was returned + // as infeasible. This is the dual. + // Here, the phase I problem returns the value in the basis but equal + // to epsilon and not 0. + A: mat64.NewDense(5, 11, []float64{0.48619717875196006, 0.5089083769874058, 1.4064796473022745, -0.48619717875196006, -0.5089083769874058, -1.4064796473022745, 1, 0, 0, 0, 0, 1.5169837857318682, -0, -0, -1.5169837857318682, 0, 0, 0, 1, 0, 0, 0, -1.3096160896447528, 0.12600426735917414, 0.296082394213142, 1.3096160896447528, -0.12600426735917414, -0.296082394213142, 0, 0, 1, 0, 0, -0, -0, 1.9870800277141467, 0, 0, -1.9870800277141467, 0, 0, 0, 1, 0, -0.3822356988571877, -0, -0.1793908926957139, 0.3822356988571877, 0, 0.1793908926957139, 0, 0, 0, 0, 1}), + b: []float64{0.6015865977347667, 0, -1.5648780993757594, 0, 0}, + c: []float64{-0.642801659201449, -0.5412741400343285, -1.4634460998530177, 0.642801659201449, 0.5412741400343285, 1.4634460998530177, 0, 0, 0, 0, 0}, + }, + { + // Caused linear solve error. The error is because replacing the minimum + // index in Bland causes the new basis to be singular. This + // necessitates the ending loop in bland over possible moves. + A: mat64.NewDense(9, 23, []float64{-0.898219823758102, -0, -0, -0, 1.067555075209233, 1.581598470243863, -1.0656096883610071, 0.898219823758102, 0, 0, 0, -1.067555075209233, -1.581598470243863, 1.0656096883610071, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1.5657353278668433, 0.5798888118401012, -0, 0.14560553520321928, -0, -0, -0, 1.5657353278668433, -0.5798888118401012, 0, -0.14560553520321928, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -0, -0, -1.5572250142582087, -0, -0, -0, -0, 0, 0, 1.5572250142582087, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0, -0, -0, -1.1266215512973428, -0, 1.0661059397023553, -0, 0, 0, 0, 1.1266215512973428, 0, -1.0661059397023553, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -0, -2.060232129551813, 1.756900609902372, -0, -0, -0, -0, 0, 2.060232129551813, -1.756900609902372, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1.0628806512935949, -0, -0, 0.3306985942820342, -0, 0.5013194822231914, -0, -1.0628806512935949, 0, 0, -0.3306985942820342, 0, -0.5013194822231914, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -0.02053916418367785, 2.0967009672108627, -0, 1.276296057052031, -0, -0.8396554873675388, -0, 0.02053916418367785, -2.0967009672108627, 0, -1.276296057052031, 0, 0.8396554873675388, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1.5173172721095745, -0, -0, -0, -0, -0.7781977786718928, -0.08927683907374018, 1.5173172721095745, 0, 0, 0, 0, 0.7781977786718928, 0.08927683907374018, 0, 0, 0, 0, 0, 0, 0, 1, 0, -0, -0, -0, -0, -0, 0.39773149008355624, -0, 0, 0, 0, 0, 0, -0.39773149008355624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), + b: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + c: []float64{0.24547850255842107, -0.9373919913433648, 0, 0, 0, 0.2961224049153204, 0, -0.24547850255842107, 0.9373919913433648, -0, -0, -0, -0.2961224049153204, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + // Caused error because ALL of the possible replacements in Bland cause. + // ab to be singular. This necessitates outer loop in bland over possible + // moves. + A: mat64.NewDense(9, 23, []float64{0.6595219196440785, -0, -0, -1.8259394918781682, -0, -0, 0.005457361044175046, -0.6595219196440785, 0, 0, 1.8259394918781682, 0, 0, -0.005457361044175046, 1, 0, 0, 0, 0, 0, 0, 0, 0, -0, -0.10352878714214864, -0, -0, -0, -0, 0.5945016966696087, 0, 0.10352878714214864, 0, 0, 0, 0, -0.5945016966696087, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0.31734882842876444, -0, -0, -0, -0, -0, -0.716633126367685, -0.31734882842876444, 0, 0, 0, 0, 0, 0.716633126367685, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0.7769812182932578, -0, -0.17370050158829553, 0.19405062263734607, -0, 1.1472330031002533, -0.6776631768730962, 0.7769812182932578, 0, 0.17370050158829553, -0.19405062263734607, 0, -1.1472330031002533, 0.6776631768730962, 0, 0, 0, 1, 0, 0, 0, 0, 0, -0, 0.8285611486611473, -0, -0, -0, -0, -0, 0, -0.8285611486611473, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -2.088953453647358, 1.3286488791152795, -0, -0, -0, -0, 0.9147833235021142, 2.088953453647358, -1.3286488791152795, 0, 0, 0, 0, -0.9147833235021142, 0, 0, 0, 0, 0, 1, 0, 0, 0, -0, -0, -0, -0, 0.6560365621262937, -0, -0, 0, 0, 0, 0, -0.6560365621262937, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0.8957188338098074, -0, -0, -0, -0, -0, -0, -0.8957188338098074, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -0.2761381891117365, -0, -0, -0, 1.1154921426237823, 0.06429872020552618, -0, 0.2761381891117365, 0, 0, 0, -1.1154921426237823, -0.06429872020552618, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), + b: []float64{0, 0, 0, 0, 0.5046208538522362, 1.0859412982429362, -2.066283584195025, 0, -0.2604305274353169}, + c: []float64{0, 0, 0, 0, 0, 0, -0.05793762969330718, -0, -0, -0, -0, -0, -0, 0.05793762969330718, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + initialBasic: []int{22, 11, 7, 19, 18, 17, 16, 15, 14}, + }, + { + // Caused initial supplied basis of Phase I to be singular. + A: mat64.NewDense(7, 11, []float64{0, 0, 0, 0, 0, 0.6667874223914787, -0.04779440888372957, -0.810020924434026, 0, 1.4190243477163373, 0, 0, 1.0452496826112936, 1.1966134226828076, 0, 0, 0, 0, -0.676136041089015, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.123232807871834, 0.2795467733707712, 0.21997115467272987, 0, -0.1572003980840453, 0, 0, 0, 0, 0.5130196002804861, 0, -0.005957174211761673, 0.3262874931735277, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.5582052881594286, 0, 0.3544026193217651, 0, -1.0761986709145068, 0, 0.2438593072108347, 0, 0, 0, 0, 1.387509848081664, 0, 0, 0.3958750570508226, 1.6281679612990678, 0, 0, -0.24638311667922103, 0, 0, 0, 0, 0, 0, -0.628850893994423}), + b: []float64{0.4135281763629115, 0, 0, 0, 0, 0, 0}, + c: []float64{0.5586772876113472, 0, 0.14261332948424457, 0, -0.016394076753000086, -0.506087285562544, 0, 0.37619482505459145, 1.2943822852419233, 0.5887960293578207, 0}, + }, + } { + testSimplex(t, test.initialBasic, test.c, test.A, test.b, convergenceTol) + } + + rnd := rand.New(rand.NewSource(1)) + // Randomized tests + testRandomSimplex(t, 20000, 0.7, 10, rnd) + testRandomSimplex(t, 20000, 0, 10, rnd) + testRandomSimplex(t, 200, 0, 100, rnd) + testRandomSimplex(t, 2, 0, 400, rnd) +} + +func testRandomSimplex(t *testing.T, nTest int, pZero float64, maxN int, rnd *rand.Rand) { + // Try a bunch of random LPs + for i := 0; i < nTest; i++ { + n := rnd.Intn(maxN) + 2 // n must be at least two. + m := rnd.Intn(n-1) + 1 // m must be between 1 and n + if m == 0 || n == 0 { + continue + } + randValue := func() float64 { + //var pZero float64 + v := rnd.Float64() + if v < pZero { + return 0 + } + return rnd.NormFloat64() + } + a := mat64.NewDense(m, n, nil) + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + a.Set(i, j, randValue()) + } + } + b := make([]float64, m) + for i := range b { + b[i] = randValue() + } + + c := make([]float64, n) + for i := range c { + c[i] = randValue() + } + + testSimplex(t, nil, c, a, b, convergenceTol) + } +} + +func testSimplex(t *testing.T, initialBasic []int, c []float64, a mat64.Matrix, b []float64, convergenceTol float64) error { + primalOpt, primalX, _, errPrimal := simplex(initialBasic, c, a, b, convergenceTol) + if errPrimal == nil { + // No error solving the simplex, check that the solution is feasible. + var bCheck mat64.Vector + bCheck.MulVec(a, mat64.NewVector(len(primalX), primalX)) + if !mat64.EqualApprox(&bCheck, mat64.NewVector(len(b), b), 1e-10) { + t.Errorf("No error in primal but solution infeasible") + } + } + + primalInfeasible := errPrimal == ErrInfeasible + primalUnbounded := errPrimal == ErrUnbounded + primalBounded := errPrimal == nil + primalASingular := errPrimal == ErrSingular + primalZeroRow := errPrimal == ErrZeroRow + primalZeroCol := errPrimal == ErrZeroColumn + + primalBad := !primalInfeasible && !primalUnbounded && !primalBounded && !primalASingular && !primalZeroRow && !primalZeroCol + + // It's an error if it's not one of the known returned errors. If it's + // singular the problem is undefined and so the result cannot be compared + // to the dual. + if errPrimal == ErrSingular || primalBad { + if primalBad { + t.Errorf("non-known error returned: %s", errPrimal) + } + return errPrimal + } + + // Compare the result to the answer found from solving the dual LP. + + // Construct and solve the dual LP. + // Standard Form: + // minimize c^T * x + // subject to A * x = b, x >= 0 + // The dual of this problem is + // maximize -b^T * nu + // subject to A^T * nu + c >= 0 + // Which is + // minimize b^T * nu + // subject to -A^T * nu <= c + + negAT := &mat64.Dense{} + negAT.Clone(a.T()) + negAT.Scale(-1, negAT) + cNew, aNew, bNew := Convert(b, negAT, c, nil, nil) + + dualOpt, dualX, _, errDual := simplex(nil, cNew, aNew, bNew, convergenceTol) + if errDual == nil { + // Check that the dual is feasible + var bCheck mat64.Vector + bCheck.MulVec(aNew, mat64.NewVector(len(dualX), dualX)) + if !mat64.EqualApprox(&bCheck, mat64.NewVector(len(bNew), bNew), 1e-10) { + t.Errorf("No error in dual but solution infeasible") + } + } + + // Check about the zero status. + if errPrimal == ErrZeroRow || errPrimal == ErrZeroColumn { + return errPrimal + } + + // If the primal problem is feasible, then the primal and the dual should + // be the same answer. We have flopped the sign in the dual (minimizing + // b^T *nu instead of maximizing -b^T*nu), so flip it back. + if errPrimal == nil { + if errDual != nil { + fmt.Println("errDual", errDual) + panic("here") + t.Errorf("Primal feasible but dual errored: %s", errDual) + } + dualOpt *= -1 + if !floats.EqualWithinAbsOrRel(dualOpt, primalOpt, convergenceTol, convergenceTol) { + t.Errorf("Primal and dual value mismatch. Primal %v, dual %v.", primalOpt, dualOpt) + } + } + // If the primal problem is unbounded, then the dual should be infeasible. + if errPrimal == ErrUnbounded && errDual != ErrInfeasible { + t.Errorf("Primal unbounded but dual not infeasible. ErrDual = %s", errDual) + } + + // If the dual is unbounded, then the primal should be infeasible. + if errDual == ErrUnbounded && errPrimal != ErrInfeasible { + t.Errorf("Dual unbounded but primal not infeasible. ErrDual = %s", errPrimal) + } + + // If the primal is infeasible, then the dual should be either infeasible + // or unbounded. + if errPrimal == ErrInfeasible { + if errDual != ErrUnbounded && errDual != ErrInfeasible && errDual != ErrZeroColumn { + t.Errorf("Primal infeasible but dual not infeasible or unbounded: %s", errDual) + } + } + + return errPrimal +} diff --git a/optimize/convex/lp/simplexexample_test.go b/optimize/convex/lp/simplexexample_test.go new file mode 100644 index 00000000..ea8dc6c9 --- /dev/null +++ b/optimize/convex/lp/simplexexample_test.go @@ -0,0 +1,29 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package lp_test + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/optimize/convex/lp" +) + +func ExampleSimplex() { + c := []float64{-1, -2, 0, 0} + A := mat64.NewDense(2, 4, []float64{-1, 2, 1, 0, 3, 1, 0, 1}) + b := []float64{4, 9} + + opt, x, err := lp.Simplex(c, A, b, 0, nil) + if err != nil { + log.Fatal(err) + } + fmt.Printf("opt: %v\n", opt) + fmt.Printf("x: %v\n", x) + // Output: + // opt: -8 + // x: [2 3 0 0] +} diff --git a/optimize/doc.go b/optimize/doc.go new file mode 100644 index 00000000..c1ad2820 --- /dev/null +++ b/optimize/doc.go @@ -0,0 +1,6 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package optimize implements algorithms for finding the optimum value of functions. +package optimize diff --git a/optimize/errors.go b/optimize/errors.go new file mode 100644 index 00000000..07bf5df9 --- /dev/null +++ b/optimize/errors.go @@ -0,0 +1,72 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "errors" + "fmt" + "math" +) + +var ( + // ErrZeroDimensional signifies an optimization was called with an input of length 0. + ErrZeroDimensional = errors.New("optimize: zero dimensional input") + + // ErrLinesearcherFailure signifies that a Linesearcher has iterated too + // many times. This may occur if the gradient tolerance is set too low. + ErrLinesearcherFailure = errors.New("linesearch: failed to converge") + + // ErrNonDescentDirection signifies that LinesearchMethod has received a + // search direction from a NextDirectioner in which the function is not + // decreasing. + ErrNonDescentDirection = errors.New("linesearch: non-descent search direction") + + // ErrNoProgress signifies that LinesearchMethod cannot make further + // progress because there is no change in location after Linesearcher step + // due to floating-point arithmetic. + ErrNoProgress = errors.New("linesearch: no change in location after Linesearcher step") + + // ErrLinesearcherBound signifies that a Linesearcher reached a step that + // lies out of allowed bounds. + ErrLinesearcherBound = errors.New("linesearch: step out of bounds") +) + +// ErrFunc is returned when an initial function value is invalid. The error +// state may be either +Inf or NaN. ErrFunc satisfies the error interface. +type ErrFunc float64 + +func (err ErrFunc) Error() string { + switch { + case math.IsInf(float64(err), 1): + return "optimize: initial function value is infinite" + case math.IsNaN(float64(err)): + return "optimize: initial function value is NaN" + default: + panic("optimize: bad ErrFunc") + } +} + +// ErrGrad is returned when an initial gradient is invalid. The error gradient +// may be either ±Inf or NaN. ErrGrad satisfies the error interface. +type ErrGrad struct { + Grad float64 // Grad is the invalid gradient value. + Index int // Index is the position at which the invalid gradient was found. +} + +func (err ErrGrad) Error() string { + switch { + case math.IsInf(err.Grad, 0): + return fmt.Sprintf("optimize: initial gradient is infinite at position %d", err.Index) + case math.IsNaN(err.Grad): + return fmt.Sprintf("optimize: initial gradient is NaN at position %d", err.Index) + default: + panic("optimize: bad ErrGrad") + } +} + +// List of shared panic strings +var ( + badProblem = "optimize: objective function is undefined" +) diff --git a/optimize/functionconvergence.go b/optimize/functionconvergence.go new file mode 100644 index 00000000..c532072d --- /dev/null +++ b/optimize/functionconvergence.go @@ -0,0 +1,40 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import "math" + +// FunctionConverge tests for the convergence of function values. See comment +// in Settings. +type FunctionConverge struct { + Absolute float64 + Relative float64 + Iterations int + + best float64 + iter int +} + +func (fc *FunctionConverge) Init(f float64) { + fc.best = f + fc.iter = 0 +} + +func (fc *FunctionConverge) FunctionConverged(f float64) Status { + if fc.Iterations == 0 { + return NotTerminated + } + maxAbs := math.Max(math.Abs(f), math.Abs(fc.best)) + if f < fc.best && fc.best-f > fc.Relative*maxAbs+fc.Absolute { + fc.best = f + fc.iter = 0 + return NotTerminated + } + fc.iter++ + if fc.iter < fc.Iterations { + return NotTerminated + } + return FunctionConvergence +} diff --git a/optimize/functions/functions.go b/optimize/functions/functions.go new file mode 100644 index 00000000..0c98aa5a --- /dev/null +++ b/optimize/functions/functions.go @@ -0,0 +1,1778 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package functions + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +// Beale implements the Beale's function. +// +// Standard starting points: +// Easy: [1, 1] +// Hard: [1, 4] +// +// References: +// - Beale, E.: On an Iterative Method for Finding a Local Minimum of a +// Function of More than One Variable. Technical Report 25, Statistical +// Techniques Research Group, Princeton University (1958) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Beale struct{} + +func (Beale) Func(x []float64) float64 { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + + f1 := 1.5 - x[0]*(1-x[1]) + f2 := 2.25 - x[0]*(1-x[1]*x[1]) + f3 := 2.625 - x[0]*(1-x[1]*x[1]*x[1]) + return f1*f1 + f2*f2 + f3*f3 +} + +func (Beale) Grad(grad, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + t1 := 1 - x[1] + t2 := 1 - x[1]*x[1] + t3 := 1 - x[1]*x[1]*x[1] + + f1 := 1.5 - x[0]*t1 + f2 := 2.25 - x[0]*t2 + f3 := 2.625 - x[0]*t3 + + grad[0] = -2 * (f1*t1 + f2*t2 + f3*t3) + grad[1] = 2 * x[0] * (f1 + 2*f2*x[1] + 3*f3*x[1]*x[1]) +} + +func (Beale) Hess(hess mat64.MutableSymmetric, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + t1 := 1 - x[1] + t2 := 1 - x[1]*x[1] + t3 := 1 - x[1]*x[1]*x[1] + f1 := 1.5 - x[1]*t1 + f2 := 2.25 - x[1]*t2 + f3 := 2.625 - x[1]*t3 + + h00 := 2 * (t1*t1 + t2*t2 + t3*t3) + h01 := 2 * (f1 + x[1]*(2*f2+3*x[1]*f3) - x[0]*(t1+x[1]*(2*t2+3*x[1]*t3))) + h11 := 2 * x[0] * (x[0] + 2*f2 + x[1]*(6*f3+x[0]*x[1]*(4+9*x[1]*x[1]))) + hess.SetSym(0, 0, h00) + hess.SetSym(0, 1, h01) + hess.SetSym(1, 1, h11) +} + +func (Beale) Minima() []Minimum { + return []Minimum{ + { + X: []float64{3, 0.5}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP2 implements the the Biggs' EXP2 function. +// +// Standard starting point: +// [1, 2] +// +// Reference: +// Biggs, M.C.: Minimization algorithms making use of non-quadratic properties +// of the objective function. IMA J Appl Math 8 (1971), 315-327; doi:10.1093/imamat/8.3.315 +type BiggsEXP2 struct{} + +func (BiggsEXP2) Func(x []float64) (sum float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := math.Exp(-x[0]*z) - 5*math.Exp(-x[1]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP2) Grad(grad, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := math.Exp(-x[0]*z) - 5*math.Exp(-x[1]*z) - y + + dfdx0 := -z * math.Exp(-x[0]*z) + dfdx1 := 5 * z * math.Exp(-x[1]*z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + } +} + +func (BiggsEXP2) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP3 implements the the Biggs' EXP3 function. +// +// Standard starting point: +// [1, 2, 1] +// +// Reference: +// Biggs, M.C.: Minimization algorithms making use of non-quadratic properties +// of the objective function. IMA J Appl Math 8 (1971), 315-327; doi:10.1093/imamat/8.3.315 +type BiggsEXP3 struct{} + +func (BiggsEXP3) Func(x []float64) (sum float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := math.Exp(-x[0]*z) - x[2]*math.Exp(-x[1]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP3) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := math.Exp(-x[0]*z) - x[2]*math.Exp(-x[1]*z) - y + + dfdx0 := -z * math.Exp(-x[0]*z) + dfdx1 := x[2] * z * math.Exp(-x[1]*z) + dfdx2 := -math.Exp(-x[1] * z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + grad[2] += 2 * f * dfdx2 + } +} + +func (BiggsEXP3) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 5}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP4 implements the the Biggs' EXP4 function. +// +// Standard starting point: +// [1, 2, 1, 1] +// +// Reference: +// Biggs, M.C.: Minimization algorithms making use of non-quadratic properties +// of the objective function. IMA J Appl Math 8 (1971), 315-327; doi:10.1093/imamat/8.3.315 +type BiggsEXP4 struct{} + +func (BiggsEXP4) Func(x []float64) (sum float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP4) Grad(grad, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 10; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) - y + + dfdx0 := -z * x[2] * math.Exp(-x[0]*z) + dfdx1 := z * x[3] * math.Exp(-x[1]*z) + dfdx2 := math.Exp(-x[0] * z) + dfdx3 := -math.Exp(-x[1] * z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + grad[2] += 2 * f * dfdx2 + grad[3] += 2 * f * dfdx3 + } +} + +func (BiggsEXP4) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 1, 5}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP5 implements the the Biggs' EXP5 function. +// +// Standard starting point: +// [1, 2, 1, 1, 1] +// +// Reference: +// Biggs, M.C.: Minimization algorithms making use of non-quadratic properties +// of the objective function. IMA J Appl Math 8 (1971), 315-327; doi:10.1093/imamat/8.3.315 +type BiggsEXP5 struct{} + +func (BiggsEXP5) Func(x []float64) (sum float64) { + if len(x) != 5 { + panic("dimension of the problem must be 5") + } + + for i := 1; i <= 11; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + 3*math.Exp(-4*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) + 3*math.Exp(-x[4]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP5) Grad(grad, x []float64) { + if len(x) != 5 { + panic("dimension of the problem must be 5") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 11; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + 3*math.Exp(-4*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) + 3*math.Exp(-x[4]*z) - y + + dfdx0 := -z * x[2] * math.Exp(-x[0]*z) + dfdx1 := z * x[3] * math.Exp(-x[1]*z) + dfdx2 := math.Exp(-x[0] * z) + dfdx3 := -math.Exp(-x[1] * z) + dfdx4 := -3 * z * math.Exp(-x[4]*z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + grad[2] += 2 * f * dfdx2 + grad[3] += 2 * f * dfdx3 + grad[4] += 2 * f * dfdx4 + } +} + +func (BiggsEXP5) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 1, 5, 4}, + F: 0, + Global: true, + }, + } +} + +// BiggsEXP6 implements the the Biggs' EXP6 function. +// +// Standard starting point: +// [1, 2, 1, 1, 1, 1] +// +// References: +// - Biggs, M.C.: Minimization algorithms making use of non-quadratic +// properties of the objective function. IMA J Appl Math 8 (1971), 315-327; +// doi:10.1093/imamat/8.3.315 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type BiggsEXP6 struct{} + +func (BiggsEXP6) Func(x []float64) (sum float64) { + if len(x) != 6 { + panic("dimension of the problem must be 6") + } + + for i := 1; i <= 13; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + 3*math.Exp(-4*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) + x[5]*math.Exp(-x[4]*z) - y + sum += f * f + } + return sum +} + +func (BiggsEXP6) Grad(grad, x []float64) { + if len(x) != 6 { + panic("dimension of the problem must be 6") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 13; i++ { + z := float64(i) / 10 + y := math.Exp(-z) - 5*math.Exp(-10*z) + 3*math.Exp(-4*z) + f := x[2]*math.Exp(-x[0]*z) - x[3]*math.Exp(-x[1]*z) + x[5]*math.Exp(-x[4]*z) - y + + dfdx0 := -z * x[2] * math.Exp(-x[0]*z) + dfdx1 := z * x[3] * math.Exp(-x[1]*z) + dfdx2 := math.Exp(-x[0] * z) + dfdx3 := -math.Exp(-x[1] * z) + dfdx4 := -z * x[5] * math.Exp(-x[4]*z) + dfdx5 := math.Exp(-x[4] * z) + + grad[0] += 2 * f * dfdx0 + grad[1] += 2 * f * dfdx1 + grad[2] += 2 * f * dfdx2 + grad[3] += 2 * f * dfdx3 + grad[4] += 2 * f * dfdx4 + grad[5] += 2 * f * dfdx5 + } +} + +func (BiggsEXP6) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 1, 5, 4, 3}, + F: 0, + Global: true, + }, + { + X: []float64{1.7114159947956764, 17.68319817846745, 1.1631436609697268, + 5.1865615510738605, 1.7114159947949301, 1.1631436609697998}, + F: 0.005655649925499929, + Global: false, + }, + { + // X: []float64{1.22755594752403, X[1] >> 0, 0.83270306333466, X[3] << 0, X[4] = X[0], X[5] = X[2]}, + X: []float64{1.22755594752403, 1000, 0.83270306333466, -1000, 1.22755594752403, 0.83270306333466}, + F: 0.306366772624790, + Global: false, + }, + } +} + +// Box3D implements the Box' three-dimensional function. +// +// Standard starting point: +// [0, 10, 20] +// +// References: +// - Box, M.J.: A comparison of several current optimization methods, and the +// use of transformations in constrained problems. Comput J 9 (1966), 67-77 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Box3D struct{} + +func (Box3D) Func(x []float64) (sum float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + + for i := 1; i <= 10; i++ { + c := -float64(i) / 10 + y := math.Exp(c) - math.Exp(10*c) + f := math.Exp(c*x[0]) - math.Exp(c*x[1]) - x[2]*y + sum += f * f + } + return sum +} + +func (Box3D) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + grad[0] = 0 + grad[1] = 0 + grad[2] = 0 + for i := 1; i <= 10; i++ { + c := -float64(i) / 10 + y := math.Exp(c) - math.Exp(10*c) + f := math.Exp(c*x[0]) - math.Exp(c*x[1]) - x[2]*y + grad[0] += 2 * f * c * math.Exp(c*x[0]) + grad[1] += -2 * f * c * math.Exp(c*x[1]) + grad[2] += -2 * f * y + } +} + +func (Box3D) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 10, 1}, + F: 0, + Global: true, + }, + { + X: []float64{10, 1, -1}, + F: 0, + Global: true, + }, + { + // Any point at the line {a, a, 0}. + X: []float64{1, 1, 0}, + F: 0, + Global: true, + }, + } +} + +// BrownBadlyScaled implements the Brown's badly scaled function. +// +// Standard starting point: +// [1, 1] +// +// References: +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type BrownBadlyScaled struct{} + +func (BrownBadlyScaled) Func(x []float64) float64 { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + + f1 := x[0] - 1e6 + f2 := x[1] - 2e-6 + f3 := x[0]*x[1] - 2 + return f1*f1 + f2*f2 + f3*f3 +} + +func (BrownBadlyScaled) Grad(grad, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + f1 := x[0] - 1e6 + f2 := x[1] - 2e-6 + f3 := x[0]*x[1] - 2 + grad[0] = 2*f1 + 2*f3*x[1] + grad[1] = 2*f2 + 2*f3*x[0] +} + +func (BrownBadlyScaled) Hess(hess mat64.MutableSymmetric, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + h00 := 2 + 2*x[1]*x[1] + h01 := 4*x[0]*x[1] - 4 + h11 := 2 + 2*x[0]*x[0] + hess.SetSym(0, 0, h00) + hess.SetSym(0, 1, h01) + hess.SetSym(1, 1, h11) +} + +func (BrownBadlyScaled) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1e6, 2e-6}, + F: 0, + Global: true, + }, + } +} + +// BrownAndDennis implements the Brown and Dennis function. +// +// Standard starting point: +// [25, 5, -5, -1] +// +// References: +// - Brown, K.M., Dennis, J.E.: New computational algorithms for minimizing a +// sum of squares of nonlinear functions. Research Report Number 71-6, Yale +// University (1971) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type BrownAndDennis struct{} + +func (BrownAndDennis) Func(x []float64) (sum float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + + for i := 1; i <= 20; i++ { + c := float64(i) / 5 + f1 := x[0] + c*x[1] - math.Exp(c) + f2 := x[2] + x[3]*math.Sin(c) - math.Cos(c) + f := f1*f1 + f2*f2 + sum += f * f + } + return sum +} + +func (BrownAndDennis) Grad(grad, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 20; i++ { + c := float64(i) / 5 + f1 := x[0] + c*x[1] - math.Exp(c) + f2 := x[2] + x[3]*math.Sin(c) - math.Cos(c) + f := f1*f1 + f2*f2 + grad[0] += 4 * f * f1 + grad[1] += 4 * f * f1 * c + grad[2] += 4 * f * f2 + grad[3] += 4 * f * f2 * math.Sin(c) + } +} + +func (BrownAndDennis) Hess(hess mat64.MutableSymmetric, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + for i := 0; i < 4; i++ { + for j := i; j < 4; j++ { + hess.SetSym(i, j, 0) + } + } + for i := 1; i <= 20; i++ { + d1 := float64(i) / 5 + d2 := math.Sin(d1) + t1 := x[0] + d1*x[1] - math.Exp(d1) + t2 := x[2] + d2*x[3] - math.Cos(d1) + t := t1*t1 + t2*t2 + s3 := 2 * t1 * t2 + r1 := t + 2*t1*t1 + r2 := t + 2*t2*t2 + hess.SetSym(0, 0, hess.At(0, 0)+r1) + hess.SetSym(0, 1, hess.At(0, 1)+d1*r1) + hess.SetSym(1, 1, hess.At(1, 1)+d1*d1*r1) + hess.SetSym(0, 2, hess.At(0, 2)+s3) + hess.SetSym(1, 2, hess.At(1, 2)+d1*s3) + hess.SetSym(2, 2, hess.At(2, 2)+r2) + hess.SetSym(0, 3, hess.At(0, 3)+d2*s3) + hess.SetSym(1, 3, hess.At(1, 3)+d1*d2*s3) + hess.SetSym(2, 3, hess.At(2, 3)+d2*r2) + hess.SetSym(3, 3, hess.At(3, 3)+d2*d2*r2) + } + for i := 0; i < 4; i++ { + for j := i; j < 4; j++ { + hess.SetSym(i, j, 4*hess.At(i, j)) + } + } +} + +func (BrownAndDennis) Minima() []Minimum { + return []Minimum{ + { + X: []float64{-11.594439904762162, 13.203630051207202, -0.4034394881768612, 0.2367787744557347}, + F: 85822.20162635634, + Global: true, + }, + } +} + +// ExtendedPowellSingular implements the extended Powell's function. +// Its Hessian matrix is singular at the minimizer. +// +// Standard starting point: +// [3, -1, 0, 3, 3, -1, 0, 3, ..., 3, -1, 0, 3] +// +// References: +// - Spedicato E.: Computational experience with quasi-Newton algorithms for +// minimization problems of moderatly large size. Towards Global +// Optimization 2 (1978), 209-219 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type ExtendedPowellSingular struct{} + +func (ExtendedPowellSingular) Func(x []float64) (sum float64) { + if len(x)%4 != 0 { + panic("dimension of the problem must be a multiple of 4") + } + + for i := 0; i < len(x); i += 4 { + f1 := x[i] + 10*x[i+1] + f2 := x[i+2] - x[i+3] + t := x[i+1] - 2*x[i+2] + f3 := t * t + t = x[i] - x[i+3] + f4 := t * t + sum += f1*f1 + 5*f2*f2 + f3*f3 + 10*f4*f4 + } + return sum +} + +func (ExtendedPowellSingular) Grad(grad, x []float64) { + if len(x)%4 != 0 { + panic("dimension of the problem must be a multiple of 4") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := 0; i < len(x); i += 4 { + f1 := x[i] + 10*x[i+1] + f2 := x[i+2] - x[i+3] + t1 := x[i+1] - 2*x[i+2] + f3 := t1 * t1 + t2 := x[i] - x[i+3] + f4 := t2 * t2 + grad[i] = 2*f1 + 40*f4*t2 + grad[i+1] = 20*f1 + 4*f3*t1 + grad[i+2] = 10*f2 - 8*f3*t1 + grad[i+3] = -10*f2 - 40*f4*t2 + } +} + +func (ExtendedPowellSingular) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0, 0, 0, 0}, + F: 0, + Global: true, + }, + { + X: []float64{0, 0, 0, 0, 0, 0, 0, 0}, + F: 0, + Global: true, + }, + { + X: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + F: 0, + Global: true, + }, + } +} + +// ExtendedRosenbrock implements the extended, multidimensional Rosenbrock +// function. +// +// Standard starting point: +// Easy: [-1.2, 1, -1.2, 1, ...] +// Hard: any point far from the minimum +// +// References: +// - Rosenbrock, H.H.: An Automatic Method for Finding the Greatest or Least +// Value of a Function. Computer J 3 (1960), 175-184 +// - http://en.wikipedia.org/wiki/Rosenbrock_function +type ExtendedRosenbrock struct{} + +func (ExtendedRosenbrock) Func(x []float64) (sum float64) { + for i := 0; i < len(x)-1; i++ { + a := 1 - x[i] + b := x[i+1] - x[i]*x[i] + sum += a*a + 100*b*b + } + return sum +} + +func (ExtendedRosenbrock) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + dim := len(x) + for i := range grad { + grad[i] = 0 + } + for i := 0; i < dim-1; i++ { + grad[i] -= 2 * (1 - x[i]) + grad[i] -= 400 * (x[i+1] - x[i]*x[i]) * x[i] + } + for i := 1; i < dim; i++ { + grad[i] += 200 * (x[i] - x[i-1]*x[i-1]) + } +} + +func (ExtendedRosenbrock) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{-0.7756592265653526, 0.6130933654850433, + 0.38206284633839305, 0.14597201855219452}, + F: 3.701428610430017, + Global: false, + }, + { + X: []float64{1, 1, 1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{-0.9620510206947502, 0.9357393959767103, + 0.8807136041943204, 0.7778776758544063, 0.6050936785926526}, + F: 3.930839434133027, + Global: false, + }, + { + X: []float64{-0.9865749795709938, 0.9833982288361819, 0.972106670053092, + 0.9474374368264362, 0.8986511848517299, 0.8075739520354182}, + F: 3.973940500930295, + Global: false, + }, + { + X: []float64{-0.9917225725614055, 0.9935553935033712, 0.992173321594692, + 0.9868987626903134, 0.975164756608872, 0.9514319827049906, 0.9052228177139495}, + F: 3.9836005364248543, + Global: false, + }, + { + X: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + F: 0, + Global: true, + }, + } +} + +// Gaussian implements the Gaussian function. +// The function has one global minimum and a number of false local minima +// caused by the finite floating point precision. +// +// Standard starting point: +// [0.4, 1, 0] +// +// Reference: +// More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained optimization +// software. ACM Trans Math Softw 7 (1981), 17-41 +type Gaussian struct{} + +func (Gaussian) y(i int) (yi float64) { + switch i { + case 1, 15: + yi = 0.0009 + case 2, 14: + yi = 0.0044 + case 3, 13: + yi = 0.0175 + case 4, 12: + yi = 0.0540 + case 5, 11: + yi = 0.1295 + case 6, 10: + yi = 0.2420 + case 7, 9: + yi = 0.3521 + case 8: + yi = 0.3989 + } + return yi +} + +func (g Gaussian) Func(x []float64) (sum float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + + for i := 1; i <= 15; i++ { + c := 0.5 * float64(8-i) + b := c - x[2] + d := b * b + e := math.Exp(-0.5 * x[1] * d) + f := x[0]*e - g.y(i) + sum += f * f + } + return sum +} + +func (g Gaussian) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + grad[0] = 0 + grad[1] = 0 + grad[2] = 0 + for i := 1; i <= 15; i++ { + c := 0.5 * float64(8-i) + b := c - x[2] + d := b * b + e := math.Exp(-0.5 * x[1] * d) + f := x[0]*e - g.y(i) + grad[0] += 2 * f * e + grad[1] -= f * e * d * x[0] + grad[2] += 2 * f * e * x[0] * x[1] * b + } +} + +func (Gaussian) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0.398956137837997, 1.0000190844805048, 0}, + F: 1.12793276961912e-08, + Global: true, + }, + } +} + +// GulfResearchAndDevelopment implements the Gulf Research and Development function. +// +// Standard starting point: +// [5, 2.5, 0.15] +// +// References: +// - Cox, R.A.: Comparison of the performance of seven optimization algorithms +// on twelve unconstrained minimization problems. Ref. 1335CNO4, Gulf +// Research and Development Company, Pittsburg (1969) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type GulfResearchAndDevelopment struct{} + +func (GulfResearchAndDevelopment) Func(x []float64) (sum float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + + for i := 1; i <= 99; i++ { + arg := float64(i) / 100 + r := math.Pow(-50*math.Log(arg), 2.0/3.0) + 25 - x[1] + t1 := math.Pow(math.Abs(r), x[2]) / x[0] + t2 := math.Exp(-t1) + t := t2 - arg + sum += t * t + } + return sum +} + +func (GulfResearchAndDevelopment) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 99; i++ { + arg := float64(i) / 100 + r := math.Pow(-50*math.Log(arg), 2.0/3.0) + 25 - x[1] + t1 := math.Pow(math.Abs(r), x[2]) / x[0] + t2 := math.Exp(-t1) + t := t2 - arg + s1 := t1 * t2 * t + grad[0] += s1 + grad[1] += s1 / r + grad[2] -= s1 * math.Log(math.Abs(r)) + } + grad[0] *= 2 / x[0] + grad[1] *= 2 * x[2] + grad[2] *= 2 +} + +func (GulfResearchAndDevelopment) Minima() []Minimum { + return []Minimum{ + { + X: []float64{50, 25, 1.5}, + F: 0, + Global: true, + }, + { + X: []float64{99.89529935174151, 60.61453902799833, 9.161242695144592}, + F: 32.8345, + Global: false, + }, + { + X: []float64{201.662589489426, 60.61633150468155, 10.224891158488965}, + F: 32.8345, + Global: false, + }, + } +} + +// HelicalValley implements the helical valley function of Fletcher and Powell. +// Function is not defined at x[0] = 0. +// +// Standard starting point: +// [-1, 0, 0] +// +// References: +// - Fletcher, R., Powell, M.J.D.: A rapidly convergent descent method for +// minimization. Comput J 6 (1963), 163-168 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type HelicalValley struct{} + +func (HelicalValley) Func(x []float64) float64 { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if x[0] == 0 { + panic("function not defined at x[0] = 0") + } + + theta := 0.5 * math.Atan(x[1]/x[0]) / math.Pi + if x[0] < 0 { + theta += 0.5 + } + f1 := 10 * (x[2] - 10*theta) + f2 := 10 * (math.Hypot(x[0], x[1]) - 1) + f3 := x[2] + return f1*f1 + f2*f2 + f3*f3 +} + +func (HelicalValley) Grad(grad, x []float64) { + if len(x) != 3 { + panic("dimension of the problem must be 3") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + if x[0] == 0 { + panic("function not defined at x[0] = 0") + } + + theta := 0.5 * math.Atan(x[1]/x[0]) / math.Pi + if x[0] < 0 { + theta += 0.5 + } + h := math.Hypot(x[0], x[1]) + r := 1 / h + q := r * r / math.Pi + s := x[2] - 10*theta + grad[0] = 200 * (5*s*q*x[1] + (h-1)*r*x[0]) + grad[1] = 200 * (-5*s*q*x[0] + (h-1)*r*x[1]) + grad[2] = 2 * (100*s + x[2]) +} + +func (HelicalValley) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 0, 0}, + F: 0, + Global: true, + }, + } +} + +// Linear implements a linear function. +type Linear struct{} + +func (Linear) Func(x []float64) float64 { + return floats.Sum(x) +} + +func (Linear) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 1 + } +} + +// PenaltyI implements the first penalty function by Gill, Murray and Pitfield. +// +// Standard starting point: +// [1, ..., n] +// +// References: +// - Gill, P.E., Murray, W., Pitfield, R.A.: The implementation of two revised +// quasi-Newton algorithms for unconstrained optimization. Report NAC 11, +// National Phys Lab (1972), 82-83 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type PenaltyI struct{} + +func (PenaltyI) Func(x []float64) (sum float64) { + for _, v := range x { + sum += (v - 1) * (v - 1) + } + sum *= 1e-5 + + var s float64 + for _, v := range x { + s += v * v + } + sum += (s - 0.25) * (s - 0.25) + return sum +} + +func (PenaltyI) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + s := -0.25 + for _, v := range x { + s += v * v + } + for i, v := range x { + grad[i] = 2 * (2*s*v + 1e-5*(v-1)) + } +} + +func (PenaltyI) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0.2500074995875379, 0.2500074995875379, 0.2500074995875379, 0.2500074995875379}, + F: 2.2499775008999372e-05, + Global: true, + }, + { + X: []float64{0.15812230111311634, 0.15812230111311634, 0.15812230111311634, + 0.15812230111311634, 0.15812230111311634, 0.15812230111311634, + 0.15812230111311634, 0.15812230111311634, 0.15812230111311634, 0.15812230111311634}, + F: 7.087651467090369e-05, + Global: true, + }, + } +} + +// PenaltyII implements the second penalty function by Gill, Murray and Pitfield. +// +// Standard starting point: +// [0.5, ..., 0.5] +// +// References: +// - Gill, P.E., Murray, W., Pitfield, R.A.: The implementation of two revised +// quasi-Newton algorithms for unconstrained optimization. Report NAC 11, +// National Phys Lab (1972), 82-83 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type PenaltyII struct{} + +func (PenaltyII) Func(x []float64) (sum float64) { + dim := len(x) + s := -1.0 + for i, v := range x { + s += float64(dim-i) * v * v + } + for i := 1; i < dim; i++ { + yi := math.Exp(float64(i+1)/10) + math.Exp(float64(i)/10) + f := math.Exp(x[i]/10) + math.Exp(x[i-1]/10) - yi + sum += f * f + } + for i := 1; i < dim; i++ { + f := math.Exp(x[i]/10) - math.Exp(-1.0/10) + sum += f * f + } + sum *= 1e-5 + sum += (x[0] - 0.2) * (x[0] - 0.2) + sum += s * s + return sum +} + +func (PenaltyII) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + dim := len(x) + s := -1.0 + for i, v := range x { + s += float64(dim-i) * v * v + } + for i, v := range x { + grad[i] = 4 * s * float64(dim-i) * v + } + for i := 1; i < dim; i++ { + yi := math.Exp(float64(i+1)/10) + math.Exp(float64(i)/10) + f := math.Exp(x[i]/10) + math.Exp(x[i-1]/10) - yi + grad[i] += 1e-5 * f * math.Exp(x[i]/10) / 5 + grad[i-1] += 1e-5 * f * math.Exp(x[i-1]/10) / 5 + } + for i := 1; i < dim; i++ { + f := math.Exp(x[i]/10) - math.Exp(-1.0/10) + grad[i] += 1e-5 * f * math.Exp(x[i]/10) / 5 + } + grad[0] += 2 * (x[0] - 0.2) +} + +func (PenaltyII) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0.19999933335, 0.19131670128566283, 0.4801014860897, 0.5188454026659}, + F: 9.376293007355449e-06, + Global: true, + }, + { + X: []float64{0.19998360520892217, 0.010350644318663525, + 0.01960493546891094, 0.03208906550305253, 0.04993267593895693, + 0.07651399534454084, 0.11862407118600789, 0.1921448731780023, + 0.3473205862372022, 0.36916437893066273}, + F: 0.00029366053745674594, + Global: true, + }, + } +} + +// PowellBadlyScaled implements the Powell's badly scaled function. +// The function is very flat near the minimum. A satisfactory solution is one +// that gives f(x) ≅ 1e-13. +// +// Standard starting point: +// [0, 1] +// +// References: +// - Powell, M.J.D.: A Hybrid Method for Nonlinear Equations. Numerical +// Methods for Nonlinear Algebraic Equations, P. Rabinowitz (ed.), Gordon +// and Breach (1970) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type PowellBadlyScaled struct{} + +func (PowellBadlyScaled) Func(x []float64) float64 { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + + f1 := 1e4*x[0]*x[1] - 1 + f2 := math.Exp(-x[0]) + math.Exp(-x[1]) - 1.0001 + return f1*f1 + f2*f2 +} + +func (PowellBadlyScaled) Grad(grad, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + f1 := 1e4*x[0]*x[1] - 1 + f2 := math.Exp(-x[0]) + math.Exp(-x[1]) - 1.0001 + grad[0] = 2 * (1e4*f1*x[1] - f2*math.Exp(-x[0])) + grad[1] = 2 * (1e4*f1*x[0] - f2*math.Exp(-x[1])) +} + +func (PowellBadlyScaled) Hess(hess mat64.MutableSymmetric, x []float64) { + if len(x) != 2 { + panic("dimension of the problem must be 2") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + t1 := 1e4*x[0]*x[1] - 1 + s1 := math.Exp(-x[0]) + s2 := math.Exp(-x[1]) + t2 := s1 + s2 - 1.0001 + + h00 := 2 * (1e8*x[1]*x[1] + s1*(s1+t2)) + h01 := 2 * (1e4*(1+2*t1) + s1*s2) + h11 := 2 * (1e8*x[0]*x[0] + s2*(s2+t2)) + hess.SetSym(0, 0, h00) + hess.SetSym(0, 1, h01) + hess.SetSym(1, 1, h11) +} + +func (PowellBadlyScaled) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1.0981593296997149e-05, 9.106146739867375}, + F: 0, + Global: true, + }, + } +} + +// Trigonometric implements the trigonometric function. +// +// Standard starting point: +// [1/dim, ..., 1/dim] +// +// References: +// - Spedicato E.: Computational experience with quasi-Newton algorithms for +// minimization problems of moderatly large size. Towards Global +// Optimization 2 (1978), 209-219 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Trigonometric struct{} + +func (Trigonometric) Func(x []float64) (sum float64) { + var s1 float64 + for _, v := range x { + s1 += math.Cos(v) + } + for i, v := range x { + f := float64(len(x)+i+1) - float64(i+1)*math.Cos(v) - math.Sin(v) - s1 + sum += f * f + } + return sum +} + +func (Trigonometric) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + var s1 float64 + for _, v := range x { + s1 += math.Cos(v) + } + + var s2 float64 + for i, v := range x { + f := float64(len(x)+i+1) - float64(i+1)*math.Cos(v) - math.Sin(v) - s1 + s2 += f + grad[i] = 2 * f * (float64(i+1)*math.Sin(v) - math.Cos(v)) + } + + for i, v := range x { + grad[i] += 2 * s2 * math.Sin(v) + } +} + +func (Trigonometric) Minima() []Minimum { + return []Minimum{ + { + X: []float64{0.04296456438227447, 0.043976287478192246, + 0.045093397949095684, 0.04633891624617569, 0.047744381782831, + 0.04935473251330618, 0.05123734850076505, 0.19520946391410446, + 0.1649776652761741, 0.06014857783799575}, + F: 0, + Global: true, + }, + { + // TODO(vladimir-ch): If we knew the location of this minimum more + // accurately, we could decrease defaultGradTol. + X: []float64{0.05515090434047145, 0.05684061730812344, + 0.05876400231100774, 0.060990608903034337, 0.06362621381044778, + 0.06684318087364617, 0.2081615177172172, 0.16436309604419047, + 0.08500689695564931, 0.09143145386293675}, + F: 2.795056121876575e-05, + Global: false, + }, + } +} + +// VariablyDimensioned implements a variably dimensioned function. +// +// Standard starting point: +// [..., (dim-i)/dim, ...], i=1,...,dim +// +// References: +// More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained optimization +// software. ACM Trans Math Softw 7 (1981), 17-41 +type VariablyDimensioned struct{} + +func (VariablyDimensioned) Func(x []float64) (sum float64) { + for _, v := range x { + t := v - 1 + sum += t * t + } + + var s float64 + for i, v := range x { + s += float64(i+1) * (v - 1) + } + s *= s + sum += s + s *= s + sum += s + return sum +} + +func (VariablyDimensioned) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + var s float64 + for i, v := range x { + s += float64(i+1) * (v - 1) + } + for i, v := range x { + grad[i] = 2 * (v - 1 + s*float64(i+1)*(1+2*s*s)) + } +} + +func (VariablyDimensioned) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1, 1, 1}, + F: 0, + Global: true, + }, + { + X: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + F: 0, + Global: true, + }, + } +} + +// Watson implements the Watson's function. +// Dimension of the problem should be 2 <= dim <= 31. For dim == 9, the problem +// of minimizing the function is very ill conditioned. +// +// Standard starting point: +// [0, ..., 0] +// +// References: +// - Kowalik, J.S., Osborne, M.R.: Methods for Unconstrained Optimization +// Problems. Elsevier North-Holland, New York, 1968 +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Watson struct{} + +func (Watson) Func(x []float64) (sum float64) { + for i := 1; i <= 29; i++ { + d1 := float64(i) / 29 + + d2 := 1.0 + var s1 float64 + for j := 1; j < len(x); j++ { + s1 += float64(j) * d2 * x[j] + d2 *= d1 + } + + d2 = 1.0 + var s2 float64 + for _, v := range x { + s2 += d2 * v + d2 *= d1 + } + + t := s1 - s2*s2 - 1 + sum += t * t + } + t := x[1] - x[0]*x[0] - 1 + sum += x[0]*x[0] + t*t + return sum +} + +func (Watson) Grad(grad, x []float64) { + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + for i := range grad { + grad[i] = 0 + } + for i := 1; i <= 29; i++ { + d1 := float64(i) / 29 + + d2 := 1.0 + var s1 float64 + for j := 1; j < len(x); j++ { + s1 += float64(j) * d2 * x[j] + d2 *= d1 + } + + d2 = 1.0 + var s2 float64 + for _, v := range x { + s2 += d2 * v + d2 *= d1 + } + + t := s1 - s2*s2 - 1 + s3 := 2 * d1 * s2 + d2 = 2 / d1 + for j := range x { + grad[j] += d2 * (float64(j) - s3) * t + d2 *= d1 + } + } + t := x[1] - x[0]*x[0] - 1 + grad[0] += x[0] * (2 - 4*t) + grad[1] += 2 * t +} + +func (Watson) Hess(hess mat64.MutableSymmetric, x []float64) { + dim := len(x) + if dim != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + for j := 0; j < dim; j++ { + for k := j; k < dim; k++ { + hess.SetSym(j, k, 0) + } + } + for i := 1; i <= 29; i++ { + d1 := float64(i) / 29 + d2 := 1.0 + var s1 float64 + for j := 1; j < dim; j++ { + s1 += float64(j) * d2 * x[j] + d2 *= d1 + } + + d2 = 1.0 + var s2 float64 + for _, v := range x { + s2 += d2 * v + d2 *= d1 + } + + t := s1 - s2*s2 - 1 + s3 := 2 * d1 * s2 + d2 = 2 / d1 + th := 2 * d1 * d1 * t + for j := 0; j < dim; j++ { + v := float64(j) - s3 + d3 := 1 / d1 + for k := 0; k <= j; k++ { + hess.SetSym(k, j, hess.At(k, j)+d2*d3*(v*(float64(k)-s3)-th)) + d3 *= d1 + } + d2 *= d1 + } + } + t1 := x[1] - x[0]*x[0] - 1 + hess.SetSym(0, 0, hess.At(0, 0)+8*x[0]*x[0]+2-4*t1) + hess.SetSym(0, 1, hess.At(0, 1)-4*x[0]) + hess.SetSym(1, 1, hess.At(1, 1)+2) +} + +func (Watson) Minima() []Minimum { + return []Minimum{ + { + X: []float64{-0.01572508644590686, 1.012434869244884, -0.23299162372002916, + 1.2604300800978554, -1.51372891341701, 0.9929964286340117}, + F: 0.0022876700535523838, + Global: true, + }, + { + X: []float64{-1.5307036521992127e-05, 0.9997897039319495, 0.01476396369355022, + 0.14634232829939883, 1.0008211030046426, -2.617731140519101, 4.104403164479245, + -3.1436122785568514, 1.0526264080103074}, + F: 1.399760138096796e-06, + Global: true, + }, + // TODO(vladimir-ch): More, Garbow, Hillstrom list just the value, but + // not the location. Our minimizers find a minimum, but the value is + // different. + // { + // // For dim == 12 + // F: 4.72238e-10, + // Global: true, + // }, + // TODO(vladimir-ch): netlib/uncon report a value of 2.48631d-20 for dim == 20. + } +} + +// Wood implements the Wood's function. +// +// Standard starting point: +// [-3, -1, -3, -1] +// +// References: +// - Colville, A.R.: A comparative study of nonlinear programming codes. +// Report 320-2949, IBM New York Scientific Center (1968) +// - More, J., Garbow, B.S., Hillstrom, K.E.: Testing unconstrained +// optimization software. ACM Trans Math Softw 7 (1981), 17-41 +type Wood struct{} + +func (Wood) Func(x []float64) (sum float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + + f1 := x[1] - x[0]*x[0] + f2 := 1 - x[0] + f3 := x[3] - x[2]*x[2] + f4 := 1 - x[2] + f5 := x[1] + x[3] - 2 + f6 := x[1] - x[3] + return 100*f1*f1 + f2*f2 + 90*f3*f3 + f4*f4 + 10*f5*f5 + 0.1*f6*f6 +} + +func (Wood) Grad(grad, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + + f1 := x[1] - x[0]*x[0] + f2 := 1 - x[0] + f3 := x[3] - x[2]*x[2] + f4 := 1 - x[2] + f5 := x[1] + x[3] - 2 + f6 := x[1] - x[3] + grad[0] = -2 * (200*f1*x[0] + f2) + grad[1] = 2 * (100*f1 + 10*f5 + 0.1*f6) + grad[2] = -2 * (180*f3*x[2] + f4) + grad[3] = 2 * (90*f3 + 10*f5 - 0.1*f6) +} + +func (Wood) Hess(hess mat64.MutableSymmetric, x []float64) { + if len(x) != 4 { + panic("dimension of the problem must be 4") + } + if len(x) != hess.Symmetric() { + panic("incorrect size of the Hessian") + } + + hess.SetSym(0, 0, 400*(3*x[0]*x[0]-x[1])+2) + hess.SetSym(0, 1, -400*x[0]) + hess.SetSym(1, 1, 220.2) + hess.SetSym(0, 2, 0) + hess.SetSym(1, 2, 0) + hess.SetSym(2, 2, 360*(3*x[2]*x[2]-x[3])+2) + hess.SetSym(0, 3, 0) + hess.SetSym(1, 3, 19.8) + hess.SetSym(2, 3, -360*x[2]) + hess.SetSym(3, 3, 200.2) +} + +func (Wood) Minima() []Minimum { + return []Minimum{ + { + X: []float64{1, 1, 1, 1}, + F: 0, + Global: true, + }, + } +} + +// ConcaveRight implements an univariate function that is concave to the right +// of the minimizer which is located at x=sqrt(2). +// +// References: +// More, J.J., and Thuente, D.J.: Line Search Algorithms with Guaranteed Sufficient Decrease. +// ACM Transactions on Mathematical Software 20(3) (1994), 286–307, eq. (5.1) +type ConcaveRight struct{} + +func (ConcaveRight) Func(x []float64) float64 { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + return -x[0] / (x[0]*x[0] + 2) +} + +func (ConcaveRight) Grad(grad, x []float64) { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + xSqr := x[0] * x[0] + grad[0] = (xSqr - 2) / (xSqr + 2) / (xSqr + 2) +} + +// ConcaveLeft implements an univariate function that is concave to the left of +// the minimizer which is located at x=399/250=1.596. +// +// References: +// More, J.J., and Thuente, D.J.: Line Search Algorithms with Guaranteed Sufficient Decrease. +// ACM Transactions on Mathematical Software 20(3) (1994), 286–307, eq. (5.2) +type ConcaveLeft struct{} + +func (ConcaveLeft) Func(x []float64) float64 { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + return math.Pow(x[0]+0.004, 4) * (x[0] - 1.996) +} + +func (ConcaveLeft) Grad(grad, x []float64) { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + grad[0] = math.Pow(x[0]+0.004, 3) * (5*x[0] - 7.98) +} + +// Plassmann implements an univariate oscillatory function where the value of L +// controls the number of oscillations. The value of Beta controls the size of +// the derivative at zero and the size of the interval where the strong Wolfe +// conditions can hold. For small values of Beta this function represents a +// difficult test problem for linesearchers also because the information based +// on the derivative is unreliable due to the oscillations. +// +// References: +// More, J.J., and Thuente, D.J.: Line Search Algorithms with Guaranteed Sufficient Decrease. +// ACM Transactions on Mathematical Software 20(3) (1994), 286–307, eq. (5.3) +type Plassmann struct { + L float64 // Number of oscillations for |x-1| ≥ Beta. + Beta float64 // Size of the derivative at zero, f'(0) = -Beta. +} + +func (f Plassmann) Func(x []float64) float64 { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + a := x[0] + b := f.Beta + l := f.L + r := 2 * (1 - b) / l / math.Pi * math.Sin(l*math.Pi/2*a) + switch { + case a <= 1-b: + r += 1 - a + case 1-b < a && a <= 1+b: + r += 0.5 * ((a-1)*(a-1)/b + b) + default: // a > 1+b + r += a - 1 + } + return r +} + +func (f Plassmann) Grad(grad, x []float64) { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + a := x[0] + b := f.Beta + l := f.L + grad[0] = (1 - b) * math.Cos(l*math.Pi/2*a) + switch { + case a <= 1-b: + grad[0] -= 1 + case 1-b < a && a <= 1+b: + grad[0] += (a - 1) / b + default: // a > 1+b + grad[0] += 1 + } +} + +// YanaiOzawaKaneko is an univariate convex function where the values of Beta1 +// and Beta2 control the curvature around the minimum. Far away from the +// minimum the function approximates an absolute value function. Near the +// minimum, the function can either be sharply curved or flat, controlled by +// the parameter values. +// +// References: +// - More, J.J., and Thuente, D.J.: Line Search Algorithms with Guaranteed Sufficient Decrease. +// ACM Transactions on Mathematical Software 20(3) (1994), 286–307, eq. (5.4) +// - Yanai, H., Ozawa, M., and Kaneko, S.: Interpolation methods in one dimensional +// optimization. Computing 27 (1981), 155–163 +type YanaiOzawaKaneko struct { + Beta1 float64 + Beta2 float64 +} + +func (f YanaiOzawaKaneko) Func(x []float64) float64 { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + a := x[0] + b1 := f.Beta1 + b2 := f.Beta2 + g1 := math.Sqrt(1+b1*b1) - b1 + g2 := math.Sqrt(1+b2*b2) - b2 + return g1*math.Sqrt((a-1)*(a-1)+b2*b2) + g2*math.Sqrt(a*a+b1*b1) +} + +func (f YanaiOzawaKaneko) Grad(grad, x []float64) { + if len(x) != 1 { + panic("dimension of the problem must be 1") + } + if len(x) != len(grad) { + panic("incorrect size of the gradient") + } + a := x[0] + b1 := f.Beta1 + b2 := f.Beta2 + g1 := math.Sqrt(1+b1*b1) - b1 + g2 := math.Sqrt(1+b2*b2) - b2 + grad[0] = g1*(a-1)/math.Sqrt(b2*b2+(a-1)*(a-1)) + g2*a/math.Sqrt(b1*b1+a*a) +} diff --git a/optimize/functions/functions_test.go b/optimize/functions/functions_test.go new file mode 100644 index 00000000..0912ab96 --- /dev/null +++ b/optimize/functions/functions_test.go @@ -0,0 +1,326 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package functions + +import "testing" + +func TestBeale(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 1}, + F: 14.203125, + Gradient: []float64{0, 27.75}, + }, + { + X: []float64{1, 4}, + F: 4624.453125, + Gradient: []float64{8813.25, 6585}, + }, + } + testFunction(Beale{}, tests, t) +} + +func TestBiggsEXP2(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2}, + F: 32.26255055084012, + Gradient: []float64{8.308203800550878, -25.32607145221645}, + }, + } + testFunction(BiggsEXP2{}, tests, t) +} + +func TestBiggsEXP3(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 1}, + F: 1.598844540607779, + Gradient: []float64{1.0633795027631927, -0.5196392672262664, -0.3180919155433357}, + }, + } + testFunction(BiggsEXP3{}, tests, t) +} + +func TestBiggsEXP4(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 1, 1}, + F: 1.598844540607779, + Gradient: []float64{1.0633795027631927, -0.5196392672262664, + -0.44245622408151464, -0.3180919155433357}, + }, + } + testFunction(BiggsEXP4{}, tests, t) +} + +func TestBiggsEXP5(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 1, 1, 1}, + F: 13.386420552801937, + Gradient: []float64{-6.54665204477596, 3.5259856535515293, + 14.36984212995392, -9.522506150695783, -19.639956134327882}, + }, + } + testFunction(BiggsEXP5{}, tests, t) +} + +func TestBiggsEXP6(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 1, 1, 1, 1}, + F: 0.77907007565597, + Gradient: []float64{-0.149371887533426, -0.183163468182936, + -1.483958013575642, 1.428277503849742, -0.149371887533426, + -1.483958013575642}, + }, + } + testFunction(BiggsEXP6{}, tests, t) +} + +func TestBox3D(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0, 10, 20}, + F: 1031.1538106093985, + Gradient: []float64{98.22343149849218, -2.11937420675874, 112.38817362220350}, + }, + } + testFunction(Box3D{}, tests, t) +} + +func TestBrownBadlyScaled(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 1}, + F: 999998000003, + Gradient: []float64{-2e+6, -4e-6}, + }, + } + testFunction(BrownBadlyScaled{}, tests, t) +} + +// TODO(vladimir-ch): The minimum of BrownAndDennis is not known accurately +// enough, which would force defaultGradTol to be unnecessarily large for the +// tests to pass. This is the only function that causes problems, so disable +// this test until the minimum is more accurate. +// func TestBrownAndDennis(t *testing.T) { +// tests := []funcTest{ +// { +// X: []float64{25, 5, -5, -1}, +// F: 7926693.33699744, +// Gradient: []float64{1149322.836365895, 1779291.674339785, -254579.585463521, -173400.429253115}, +// }, +// } +// testFunction(BrownAndDennis{}, tests, t) +// } + +func TestExtendedPowellSingular(t *testing.T) { + tests := []funcTest{ + { + X: []float64{3, -1, 0, 3}, + F: 95, + Gradient: []float64{-14, -144, -22, 30}, + }, + { + X: []float64{3, -1, 0, 3, 3, -1, 0, 3}, + F: 190, + Gradient: []float64{-14, -144, -22, 30, -14, -144, -22, 30}, + }, + } + testFunction(ExtendedPowellSingular{}, tests, t) +} + +func TestExtendedRosenbrock(t *testing.T) { + tests := []funcTest{ + { + X: []float64{-1.2, 1}, + F: 24.2, + Gradient: []float64{-215.6, -88}, + }, + { + X: []float64{-1.2, 1, -1.2}, + F: 508.2, + Gradient: []float64{-215.6, 792, -440}, + }, + { + X: []float64{-1.2, 1, -1.2, 1}, + F: 532.4, + Gradient: []float64{-215.6, 792, -655.6, -88}, + }, + } + testFunction(ExtendedRosenbrock{}, tests, t) +} + +func TestGaussian(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0.4, 1, 0}, + F: 3.88810699116688e-06, + Gradient: []float64{7.41428466839991e-03, -7.44126392165149e-04, -5.30189685421989e-20}, + }, + } + testFunction(Gaussian{}, tests, t) +} + +func TestGulfResearchAndDevelopment(t *testing.T) { + tests := []funcTest{ + { + X: []float64{5, 2.5, 0.15}, + F: 12.11070582556949, + Gradient: []float64{2.0879783574289799, 0.0345792619697154, -39.6766801029386400}, + }, + } + testFunction(GulfResearchAndDevelopment{}, tests, t) +} + +func TestHelicalValley(t *testing.T) { + tests := []funcTest{ + { + X: []float64{-1, 0, 0}, + F: 2500, + Gradient: []float64{0, -1.59154943091895e+03, -1e+03}, + }, + } + testFunction(HelicalValley{}, tests, t) +} + +func TestPenaltyI(t *testing.T) { + tests := []funcTest{ + { + X: []float64{1, 2, 3, 4}, + F: 885.06264, + Gradient: []float64{119, 238.00002, 357.00004, 476.00006}, + }, + { + X: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + F: 148032.56535, + Gradient: []float64{1539, 3078.00002, 4617.00004, 6156.00006, + 7695.00008, 9234.0001, 10773.00012, 12312.00014, 13851.00016, 15390.00018}, + }, + } + testFunction(PenaltyI{}, tests, t) +} + +func TestPenaltyII(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0.5, 0.5, 0.5, 0.5}, + F: 2.34000880546302, + Gradient: []float64{12.59999952896435, 8.99999885134508, + 5.99999776830493, 2.99999875380719}, + }, + { + X: []float64{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}, + F: 162.65277656596712, + Gradient: []float64{255.5999995289644, 229.4999988513451, + 203.9999977683049, 178.4999965713605, 152.9999952485322, + 127.4999937865809, 101.9999921708749, 76.4999903852436, + 50.9999884118158, 25.4999938418451}, + }, + } + testFunction(PenaltyII{}, tests, t) +} + +func TestPowelBadlyScaled(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0, 1}, + F: 1.13526171734838, + Gradient: []float64{-2.00007355588823e+04, -2.70596990584991e-01}, + }, + } + testFunction(PowellBadlyScaled{}, tests, t) +} + +func TestTrigonometric(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0.5, 0.5}, + F: 0.0126877761614045, + Gradient: []float64{-0.00840962732040673, -0.09606967736232540}, + }, + { + X: []float64{0.2, 0.2, 0.2, 0.2, 0.2}, + F: 0.0116573789904718, + Gradient: []float64{0.04568602319608119, -0.00896259022885634, + -0.04777056509084983, -0.07073790138989976, -0.07786459912600564}, + }, + { + X: []float64{0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}, + F: 0.00707575946622261, + Gradient: []float64{0.03562782195259399, 0.01872017956076182, + 0.00380754216611998, -0.00911009023133202, -0.02003271763159338, + -0.02896034003466506, -0.03589295744054654, -0.04083056984923782, + -0.04377317726073873, -0.04472077967504980}, + }, + } + testFunction(Trigonometric{}, tests, t) +} + +func TestVariablyDimensioned(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0.5, 0}, + F: 46.5625, + Gradient: []float64{-68.5, -137}, + }, + { + X: []float64{2.0 / 3, 1.0 / 3, 0}, + F: 497.60493827160514, + Gradient: []float64{-416.518518518519, -833.037037037037, -1249.555555555556}, + }, + { + X: []float64{0.75, 0.5, 0.25, 0}, + F: 3222.1875, + Gradient: []float64{-1703, -3406, -5109, -6812}, + }, + } + testFunction(VariablyDimensioned{}, tests, t) +} + +func TestWatson(t *testing.T) { + tests := []funcTest{ + { + X: []float64{0, 0}, + F: 30, + Gradient: []float64{0, -60}, + }, + { + X: []float64{0, 0, 0, 0, 0, 0}, + F: 30, + Gradient: []float64{0, -60, -60, -61.034482758620697, + -62.068965517241381, -63.114928861371936}, + }, + { + X: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + F: 30, + Gradient: []float64{0, -60, -60, -61.034482758620697, + -62.068965517241381, -63.114928861371936, -64.172372791012350, + -65.241283655050239, -66.321647802373235}, + }, + { + X: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + F: 30, + Gradient: []float64{0, -60, -60, -61.034482758620697, + -62.068965517241381, -63.114928861371936, -64.172372791012350, + -65.241283655050239, -66.321647802373235, -67.413448880864095, + -68.516667837400661, -69.631282933991471}, + }, + } + testFunction(Watson{}, tests, t) +} + +func TestWood(t *testing.T) { + tests := []funcTest{ + { + X: []float64{-3, -1, -3, -1}, + F: 19192, + Gradient: []float64{-12008, -2080, -10808, -1880}, + }, + } + testFunction(Wood{}, tests, t) +} diff --git a/optimize/functions/minsurf.go b/optimize/functions/minsurf.go new file mode 100644 index 00000000..d975bfdb --- /dev/null +++ b/optimize/functions/minsurf.go @@ -0,0 +1,252 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package functions + +import ( + "fmt" + "math" +) + +// MinimalSurface implements a finite element approximation to a minimal +// surface problem: determine the surface with minimal area and given boundary +// values in a unit square centered at the origin. +// +// References: +// Averick, M.B., Carter, R.G., Moré, J.J., Xue, G.-L.: The Minpack-2 Test +// Problem Collection. Preprint MCS-P153-0692, Argonne National Laboratory (1992) +type MinimalSurface struct { + bottom, top []float64 + left, right []float64 + origin, step [2]float64 +} + +// NewMinimalSurface creates a new discrete minimal surface problem and +// precomputes its boundary values. The problem is discretized on a rectilinear +// grid with nx×ny nodes which means that the problem dimension is (nx-2)(ny-2). +func NewMinimalSurface(nx, ny int) *MinimalSurface { + ms := &MinimalSurface{ + bottom: make([]float64, nx), + top: make([]float64, nx), + left: make([]float64, ny), + right: make([]float64, ny), + origin: [2]float64{-0.5, -0.5}, + step: [2]float64{1 / float64(nx-1), 1 / float64(ny-1)}, + } + + ms.initBoundary(ms.bottom, ms.origin[0], ms.origin[1], ms.step[0], 0) + startY := ms.origin[1] + float64(ny-1)*ms.step[1] + ms.initBoundary(ms.top, ms.origin[0], startY, ms.step[0], 0) + ms.initBoundary(ms.left, ms.origin[0], ms.origin[1], 0, ms.step[1]) + startX := ms.origin[0] + float64(nx-1)*ms.step[0] + ms.initBoundary(ms.right, startX, ms.origin[1], 0, ms.step[1]) + + return ms +} + +// Func returns the area of the surface represented by the vector x. +func (ms *MinimalSurface) Func(x []float64) (area float64) { + nx, ny := ms.Dims() + if len(x) != (nx-2)*(ny-2) { + panic("functions: problem size mismatch") + } + + hx, hy := ms.Steps() + for j := 0; j < ny-1; j++ { + for i := 0; i < nx-1; i++ { + vLL := ms.at(i, j, x) + vLR := ms.at(i+1, j, x) + vUL := ms.at(i, j+1, x) + vUR := ms.at(i+1, j+1, x) + + dvLdx := (vLR - vLL) / hx + dvLdy := (vUL - vLL) / hy + dvUdx := (vUR - vUL) / hx + dvUdy := (vUR - vLR) / hy + + fL := math.Sqrt(1 + dvLdx*dvLdx + dvLdy*dvLdy) + fU := math.Sqrt(1 + dvUdx*dvUdx + dvUdy*dvUdy) + area += fL + fU + } + } + area *= 0.5 * hx * hy + return area +} + +// Grad evaluates the area gradient of the surface represented by the vector. +func (ms *MinimalSurface) Grad(grad, x []float64) { + nx, ny := ms.Dims() + if len(x) != (nx-2)*(ny-2) { + panic("functions: problem size mismatch") + } + if grad != nil && len(x) != len(grad) { + panic("functions: unexpected size mismatch") + } + + for i := range grad { + grad[i] = 0 + } + hx, hy := ms.Steps() + for j := 0; j < ny-1; j++ { + for i := 0; i < nx-1; i++ { + vLL := ms.at(i, j, x) + vLR := ms.at(i+1, j, x) + vUL := ms.at(i, j+1, x) + vUR := ms.at(i+1, j+1, x) + + dvLdx := (vLR - vLL) / hx + dvLdy := (vUL - vLL) / hy + dvUdx := (vUR - vUL) / hx + dvUdy := (vUR - vLR) / hy + + fL := math.Sqrt(1 + dvLdx*dvLdx + dvLdy*dvLdy) + fU := math.Sqrt(1 + dvUdx*dvUdx + dvUdy*dvUdy) + + if grad != nil { + if i > 0 { + if j > 0 { + grad[ms.index(i, j)] -= (dvLdx/hx + dvLdy/hy) / fL + } + if j < ny-2 { + grad[ms.index(i, j+1)] += (dvLdy/hy)/fL - (dvUdx/hx)/fU + } + } + if i < nx-2 { + if j > 0 { + grad[ms.index(i+1, j)] += (dvLdx/hx)/fL - (dvUdy/hy)/fU + } + if j < ny-2 { + grad[ms.index(i+1, j+1)] += (dvUdx/hx + dvUdy/hy) / fU + } + } + } + } + + } + cellSize := 0.5 * hx * hy + for i := range grad { + grad[i] *= cellSize + } +} + +// InitX returns a starting location for the minimization problem. Length of +// the returned slice is (nx-2)(ny-2). +func (ms *MinimalSurface) InitX() []float64 { + nx, ny := ms.Dims() + x := make([]float64, (nx-2)*(ny-2)) + for j := 1; j < ny-1; j++ { + for i := 1; i < nx-1; i++ { + x[ms.index(i, j)] = (ms.left[j] + ms.bottom[i]) / 2 + } + } + return x +} + +// ExactX returns the exact solution to the _continuous_ minimization problem +// projected on the interior nodes of the grid. Length of the returned slice is +// (nx-2)(ny-2). +func (ms *MinimalSurface) ExactX() []float64 { + nx, ny := ms.Dims() + v := make([]float64, (nx-2)*(ny-2)) + for j := 1; j < ny-1; j++ { + for i := 1; i < nx-1; i++ { + v[ms.index(i, j)] = ms.ExactSolution(ms.x(i), ms.y(j)) + } + } + return v +} + +// ExactSolution returns the value of the exact solution to the minimal surface +// problem at (x,y). The exact solution is +// F_exact(x,y) = U^2(x,y) - V^2(x,y), +// where U and V are the unique solutions to the equations +// x = u + uv^2 - u^3/3, +// y = -v - u^2v + v^3/3. +func (ms *MinimalSurface) ExactSolution(x, y float64) float64 { + var u = [2]float64{x, -y} + var f [2]float64 + var jac [2][2]float64 + for k := 0; k < 100; k++ { + f[0] = u[0] + u[0]*u[1]*u[1] - u[0]*u[0]*u[0]/3 - x + f[1] = -u[1] - u[0]*u[0]*u[1] + u[1]*u[1]*u[1]/3 - y + fNorm := math.Hypot(f[0], f[1]) + if fNorm < 1e-13 { + break + } + jac[0][0] = 1 + u[1]*u[1] - u[0]*u[0] + jac[0][1] = 2 * u[0] * u[1] + jac[1][0] = -2 * u[0] * u[1] + jac[1][1] = -1 - u[0]*u[0] + u[1]*u[1] + det := jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0] + u[0] -= (jac[1][1]*f[0] - jac[0][1]*f[1]) / det + u[1] -= (jac[0][0]*f[1] - jac[1][0]*f[0]) / det + } + return u[0]*u[0] - u[1]*u[1] +} + +// Dims returns the size of the underlying rectilinear grid. +func (ms *MinimalSurface) Dims() (nx, ny int) { + return len(ms.bottom), len(ms.left) +} + +// Steps returns the spatial step sizes of the underlying rectilinear grid. +func (ms *MinimalSurface) Steps() (hx, hy float64) { + return ms.step[0], ms.step[1] +} + +func (ms *MinimalSurface) x(i int) float64 { + return ms.origin[0] + float64(i)*ms.step[0] +} + +func (ms *MinimalSurface) y(j int) float64 { + return ms.origin[1] + float64(j)*ms.step[1] +} + +func (ms *MinimalSurface) at(i, j int, x []float64) float64 { + nx, ny := ms.Dims() + if i < 0 || i >= nx { + panic(fmt.Sprintf("node [%v,%v] not on grid", i, j)) + } + if j < 0 || j >= ny { + panic(fmt.Sprintf("node [%v,%v] not on grid", i, j)) + } + + if i == 0 { + return ms.left[j] + } + if j == 0 { + return ms.bottom[i] + } + if i == nx-1 { + return ms.right[j] + } + if j == ny-1 { + return ms.top[i] + } + return x[ms.index(i, j)] +} + +// index maps an interior grid node (i, j) to a one-dimensional index and +// returns it. +func (ms *MinimalSurface) index(i, j int) int { + nx, ny := ms.Dims() + if i <= 0 || i >= nx-1 { + panic(fmt.Sprintf("[%v,%v] is not an interior node", i, j)) + } + if j <= 0 || j >= ny-1 { + panic(fmt.Sprintf("[%v,%v] is not an interior node", i, j)) + } + + return i - 1 + (j-1)*(nx-2) +} + +// initBoundary initializes with the exact solution the boundary b whose i-th +// element b[i] is located at [startX+i×hx, startY+i×hy]. +func (ms *MinimalSurface) initBoundary(b []float64, startX, startY, hx, hy float64) { + for i := range b { + x := startX + float64(i)*hx + y := startY + float64(i)*hy + b[i] = ms.ExactSolution(x, y) + } +} diff --git a/optimize/functions/minsurf_test.go b/optimize/functions/minsurf_test.go new file mode 100644 index 00000000..2f123545 --- /dev/null +++ b/optimize/functions/minsurf_test.go @@ -0,0 +1,48 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package functions + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/diff/fd" + "gonum.org/v1/gonum/floats" +) + +func TestMinimalSurface(t *testing.T) { + for _, size := range [][2]int{ + {20, 30}, + {30, 30}, + {50, 40}, + } { + f := NewMinimalSurface(size[0], size[1]) + x0 := f.InitX() + grad := make([]float64, len(x0)) + f.Grad(grad, x0) + fdGrad := fd.Gradient(nil, f.Func, x0, &fd.Settings{Formula: fd.Central}) + + // Test that the numerical and analytical gradients agree. + dist := floats.Distance(grad, fdGrad, math.Inf(1)) + if dist > 1e-9 { + t.Errorf("grid %v x %v: numerical and analytical gradient do not match. |fdGrad - grad|_∞ = %v", + size[0], size[1], dist) + } + + // Test that the gradient at the minimum is small enough. + // In some sense this test is not completely correct because ExactX + // returns the exact solution to the continuous problem projected on the + // grid, not the exact solution to the discrete problem which we are + // solving. This is the reason why a relatively loose tolerance 1e-4 + // must be used. + xSol := f.ExactX() + f.Grad(grad, xSol) + norm := floats.Norm(grad, math.Inf(1)) + if norm > 1e-4 { + t.Errorf("grid %v x %v: gradient at the minimum not small enough. |grad|_∞ = %v", + size[0], size[1], norm) + } + } +} diff --git a/optimize/functions/validate.go b/optimize/functions/validate.go new file mode 100644 index 00000000..1182d431 --- /dev/null +++ b/optimize/functions/validate.go @@ -0,0 +1,133 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package functions provides objective functions for testing optimization +// algorithms. +// +// We encourage outside contributions of additional test functions that exhibit +// properties not already covered in the testing suite or that have +// significance due to prior use as benchmark cases. +package functions + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/diff/fd" + "gonum.org/v1/gonum/floats" +) + +// function represents an objective function. +type function interface { + Func(x []float64) float64 +} + +type gradient interface { + Grad(grad, x []float64) +} + +// minimumer is an objective function that can also provide information about +// its minima. +type minimumer interface { + function + + // Minima returns _known_ minima of the function. + Minima() []Minimum +} + +// Minimum represents information about an optimal location of a function. +type Minimum struct { + // X is the location of the minimum. X may not be nil. + X []float64 + // F is the value of the objective function at X. + F float64 + // Global indicates if the location is a global minimum. + Global bool +} + +type funcTest struct { + X []float64 + + // F is the expected function value at X. + F float64 + // Gradient is the expected gradient at X. If nil, it is not evaluated. + Gradient []float64 +} + +// TODO(vladimir-ch): Decide and implement an exported testing function: +// func Test(f Function, ??? ) ??? { +// } + +const ( + defaultTol = 1e-12 + defaultGradTol = 1e-9 + defaultFDGradTol = 1e-5 +) + +// testFunction checks that the function can evaluate itself (and its gradient) +// correctly. +func testFunction(f function, ftests []funcTest, t *testing.T) { + // Make a copy of tests because we may append to the slice. + tests := make([]funcTest, len(ftests)) + copy(tests, ftests) + + // Get information about the function. + fMinima, isMinimumer := f.(minimumer) + fGradient, isGradient := f.(gradient) + + // If the function is a Minimumer, append its minima to the tests. + if isMinimumer { + for _, minimum := range fMinima.Minima() { + // Allocate gradient only if the function can evaluate it. + var grad []float64 + if isGradient { + grad = make([]float64, len(minimum.X)) + } + tests = append(tests, funcTest{ + X: minimum.X, + F: minimum.F, + Gradient: grad, + }) + } + } + + for i, test := range tests { + F := f.Func(test.X) + + // Check that the function value is as expected. + if math.Abs(F-test.F) > defaultTol { + t.Errorf("Test #%d: function value given by Func is incorrect. Want: %v, Got: %v", + i, test.F, F) + } + + if test.Gradient == nil { + continue + } + + // Evaluate the finite difference gradient. + fdGrad := fd.Gradient(nil, f.Func, test.X, &fd.Settings{ + Formula: fd.Central, + Step: 1e-6, + }) + + // Check that the finite difference and expected gradients match. + if !floats.EqualApprox(fdGrad, test.Gradient, defaultFDGradTol) { + dist := floats.Distance(fdGrad, test.Gradient, math.Inf(1)) + t.Errorf("Test #%d: numerical and expected gradients do not match. |fdGrad - WantGrad|_∞ = %v", + i, dist) + } + + // If the function is a Gradient, check that it computes the gradient correctly. + if isGradient { + grad := make([]float64, len(test.Gradient)) + fGradient.Grad(grad, test.X) + + if !floats.EqualApprox(grad, test.Gradient, defaultGradTol) { + dist := floats.Distance(grad, test.Gradient, math.Inf(1)) + t.Errorf("Test #%d: gradient given by Grad is incorrect. |grad - WantGrad|_∞ = %v", + i, dist) + } + } + } +} diff --git a/optimize/global.go b/optimize/global.go new file mode 100644 index 00000000..f80701f1 --- /dev/null +++ b/optimize/global.go @@ -0,0 +1,240 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "math" + "sync" + "time" +) + +// GlobalMethod is a global optimizer. Typically will require more function +// evaluations and no sense of local convergence +type GlobalMethod interface { + // Global tells method the max number of tasks, method returns how many it wants. + // This is needed to sync the Global goroutines and inside goroutines. + InitGlobal(dim, tasks int) int + // Global method may assume that the same task id always has the same pointer with it. + IterateGlobal(task int, loc *Location) (Operation, error) + Needser + // Done communicates to the optimization method that the optimization has + // concluded to allow for shutdown. + Done() +} + +// Global uses a global optimizer to search for the gloabl minimum of a +// function. A maximization problem can be transformed into a +// minimization problem by multiplying the function by -1. +// +// The first argument represents the problem to be minimized. Its fields are +// routines that evaluate the objective function, gradient, and other +// quantities related to the problem. The objective function, p.Func, must not +// be nil. The optimization method used may require other fields to be non-nil +// as specified by method.Needs. Global will panic if these are not met. The +// method can be determined automatically from the supplied problem which is +// described below. +// +// If p.Status is not nil, it is called before every evaluation. If the +// returned Status is not NotTerminated or the error is not nil, the +// optimization run is terminated. +// +// The third argument contains the settings for the minimization. The +// DefaultGlobalSettings function can be called for a Settings struct with the +// default values initialized. If settings == nil, the default settings are used. +// Global optimization methods typically do not make assumptions about the number +// and location of local minima. Thus, the only convergence metric used is the +// function values found at major iterations of the optimization. Bounds on the +// length of optimization are obeyed, such as the number of allowed function +// evaluations. +// +// The final argument is the optimization method to use. If method == nil, then +// an appropriate default is chosen based on the properties of the other arguments +// (dimension, gradient-free or gradient-based, etc.). +// +// If method implements Statuser, method.Status is called before every call +// to method.Iterate. If the returned Status is not NotTerminated or the +// error is non-nil, the optimization run is terminated. +// +// Global returns a Result struct and any error that occurred. See the +// documentation of Result for more information. +// +// Be aware that the default behavior of Global is to find the minimum. +// For certain functions and optimization methods, this process can take many +// function evaluations. If you would like to put limits on this, for example +// maximum runtime or maximum function evaluations, modify the Settings +// input struct. +// +// Something about Global cannot guarantee strict bounds on function evaluations, +// iterations, etc. in the precense of concurrency. +func Global(p Problem, dim int, settings *Settings, method GlobalMethod) (*Result, error) { + startTime := time.Now() + if method == nil { + method = &GuessAndCheck{} + } + if settings == nil { + settings = DefaultSettingsGlobal() + } + stats := &Stats{} + err := checkOptimization(p, dim, method, settings.Recorder) + if err != nil { + return nil, err + } + + optLoc := newLocation(dim, method) + optLoc.F = math.Inf(1) + + if settings.FunctionConverge != nil { + settings.FunctionConverge.Init(optLoc.F) + } + + stats.Runtime = time.Since(startTime) + + // Send initial location to Recorder + if settings.Recorder != nil { + err = settings.Recorder.Record(optLoc, InitIteration, stats) + if err != nil { + return nil, err + } + } + + // Run optimization + var status Status + status, err = minimizeGlobal(&p, method, settings, stats, optLoc, startTime) + + // Cleanup and collect results + if settings.Recorder != nil && err == nil { + err = settings.Recorder.Record(optLoc, PostIteration, stats) + } + stats.Runtime = time.Since(startTime) + return &Result{ + Location: *optLoc, + Stats: *stats, + Status: status, + }, err +} + +func minimizeGlobal(p *Problem, method GlobalMethod, settings *Settings, stats *Stats, optLoc *Location, startTime time.Time) (status Status, err error) { + dim := len(optLoc.X) + statuser, _ := method.(Statuser) + gs := &globalStatus{ + mux: &sync.RWMutex{}, + stats: stats, + status: NotTerminated, + p: p, + startTime: startTime, + optLoc: optLoc, + settings: settings, + statuser: statuser, + } + + nTasks := settings.Concurrent + nTasks = method.InitGlobal(dim, nTasks) + + // Launch optimization workers + var wg sync.WaitGroup + for task := 0; task < nTasks; task++ { + wg.Add(1) + go func(task int) { + defer wg.Done() + loc := newLocation(dim, method) + x := make([]float64, dim) + globalWorker(task, method, gs, loc, x) + }(task) + } + wg.Wait() + method.Done() + return gs.status, gs.err +} + +type globalStatus struct { + mux *sync.RWMutex + stats *Stats + status Status + p *Problem + startTime time.Time + optLoc *Location + settings *Settings + method GlobalMethod + statuser Statuser + err error +} + +func globalWorker(task int, m GlobalMethod, g *globalStatus, loc *Location, x []float64) { + for { + // Find Evaluation location + op, err := m.IterateGlobal(task, loc) + if err != nil { + // TODO(btracey): Figure out how to handle errors properly. Shut + // everything down? Pass to globalStatus so it can shut everything down? + g.mux.Lock() + g.err = err + g.status = Failure + g.mux.Unlock() + break + } + + // Evaluate location and/or update stats. + status := g.globalOperation(op, loc, x) + if status != NotTerminated { + break + } + } +} + +// globalOperation updates handles the status received by an individual worker. +// It uses a mutex to protect updates where necessary. +func (g *globalStatus) globalOperation(op Operation, loc *Location, x []float64) Status { + // Do a quick check to see if one of the other workers converged in the meantime. + var status Status + var err error + g.mux.RLock() + status = g.status + g.mux.RUnlock() + if status != NotTerminated { + return status + } + switch op { + case NoOperation: + case InitIteration: + panic("optimize: Method returned InitIteration") + case PostIteration: + panic("optimize: Method returned PostIteration") + case MajorIteration: + g.mux.Lock() + g.stats.MajorIterations++ + copyLocation(g.optLoc, loc) + g.mux.Unlock() + + g.mux.RLock() + status = checkConvergence(g.optLoc, g.settings, false) + g.mux.RUnlock() + default: // Any of the Evaluation operations. + status, err = evaluate(g.p, loc, op, x) + g.mux.Lock() + updateStats(g.stats, op) + g.mux.Unlock() + } + + g.mux.Lock() + status, err = iterCleanup(status, err, g.stats, g.settings, g.statuser, g.startTime, loc, op) + // Update the termination status if it hasn't already terminated. + if g.status == NotTerminated { + g.status = status + g.err = err + } + g.mux.Unlock() + + return status +} + +func DefaultSettingsGlobal() *Settings { + return &Settings{ + FunctionThreshold: math.Inf(-1), + FunctionConverge: &FunctionConverge{ + Absolute: 1e-10, + Iterations: 100, + }, + } +} diff --git a/optimize/gradientdescent.go b/optimize/gradientdescent.go new file mode 100644 index 00000000..292bf5c9 --- /dev/null +++ b/optimize/gradientdescent.go @@ -0,0 +1,63 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import "gonum.org/v1/gonum/floats" + +// GradientDescent implements the steepest descent optimization method that +// performs successive steps along the direction of the negative gradient. +type GradientDescent struct { + // Linesearcher selects suitable steps along the descent direction. + // If Linesearcher is nil, a reasonable default will be chosen. + Linesearcher Linesearcher + // StepSizer determines the initial step size along each direction. + // If StepSizer is nil, a reasonable default will be chosen. + StepSizer StepSizer + + ls *LinesearchMethod +} + +func (g *GradientDescent) Init(loc *Location) (Operation, error) { + if g.Linesearcher == nil { + g.Linesearcher = &Backtracking{} + } + if g.StepSizer == nil { + g.StepSizer = &QuadraticStepSize{} + } + + if g.ls == nil { + g.ls = &LinesearchMethod{} + } + g.ls.Linesearcher = g.Linesearcher + g.ls.NextDirectioner = g + + return g.ls.Init(loc) +} + +func (g *GradientDescent) Iterate(loc *Location) (Operation, error) { + return g.ls.Iterate(loc) +} + +func (g *GradientDescent) InitDirection(loc *Location, dir []float64) (stepSize float64) { + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + return g.StepSizer.Init(loc, dir) +} + +func (g *GradientDescent) NextDirection(loc *Location, dir []float64) (stepSize float64) { + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + return g.StepSizer.StepSize(loc, dir) +} + +func (*GradientDescent) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, false} +} diff --git a/optimize/guessandcheck.go b/optimize/guessandcheck.go new file mode 100644 index 00000000..e08fc4c6 --- /dev/null +++ b/optimize/guessandcheck.go @@ -0,0 +1,60 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "math" + "sync" + + "gonum.org/v1/gonum/stat/distmv" +) + +// GuessAndCheck is a global optimizer that evaluates the function at random +// locations. Not a good optimizer, but useful for comparison and debugging. +type GuessAndCheck struct { + Rander distmv.Rander + + eval []bool + + mux *sync.Mutex + bestF float64 + bestX []float64 +} + +func (g *GuessAndCheck) Needs() struct{ Gradient, Hessian bool } { + return struct{ Gradient, Hessian bool }{false, false} +} + +func (g *GuessAndCheck) Done() { + // No cleanup needed +} + +func (g *GuessAndCheck) InitGlobal(dim, tasks int) int { + g.eval = make([]bool, tasks) + g.bestF = math.Inf(1) + g.bestX = resize(g.bestX, dim) + g.mux = &sync.Mutex{} + return tasks +} + +func (g *GuessAndCheck) IterateGlobal(task int, loc *Location) (Operation, error) { + // Task is true if it contains a new function evaluation. + if g.eval[task] { + g.eval[task] = false + g.mux.Lock() + if loc.F < g.bestF { + g.bestF = loc.F + copy(g.bestX, loc.X) + } else { + loc.F = g.bestF + copy(loc.X, g.bestX) + } + g.mux.Unlock() + return MajorIteration, nil + } + g.eval[task] = true + g.Rander.Rand(loc.X) + return FuncEvaluation, nil +} diff --git a/optimize/guessandcheck_test.go b/optimize/guessandcheck_test.go new file mode 100644 index 00000000..3b7fd910 --- /dev/null +++ b/optimize/guessandcheck_test.go @@ -0,0 +1,34 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "testing" + + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/optimize/functions" + "gonum.org/v1/gonum/stat/distmv" +) + +func TestGuessAndCheck(t *testing.T) { + dim := 3000 + problem := Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + } + mu := make([]float64, dim) + sigma := mat64.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigma.SetSym(i, i, 1) + } + d, ok := distmv.NewNormal(mu, sigma, nil) + if !ok { + panic("bad test") + } + Global(problem, dim, nil, &GuessAndCheck{Rander: d}) + settings := DefaultSettingsGlobal() + settings.Concurrent = 5 + settings.MajorIterations = 15 + Global(problem, dim, settings, &GuessAndCheck{Rander: d}) +} diff --git a/optimize/interfaces.go b/optimize/interfaces.go new file mode 100644 index 00000000..e28ed3a1 --- /dev/null +++ b/optimize/interfaces.go @@ -0,0 +1,130 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +// A Method can optimize an objective function. +// +// It uses a reverse-communication interface between the optimization method +// and the caller. Method acts as a client that asks the caller to perform +// needed operations via Operation returned from Init and Iterate methods. +// This provides independence of the optimization algorithm on user-supplied +// data and their representation, and enables automation of common operations +// like checking for (various types of) convergence and maintaining statistics. +// +// A Method can command an Evaluation, a MajorIteration or NoOperation operations. +// +// An evaluation operation is one or more of the Evaluation operations +// (FuncEvaluation, GradEvaluation, etc.) which can be combined with +// the bitwise or operator. In an evaluation operation, the requested fields of +// Problem will be evaluated at the point specified in Location.X. +// The corresponding fields of Location will be filled with the results that +// can be retrieved upon the next call to Iterate. The Method interface +// requires that entries of Location are not modified aside from the commanded +// evaluations. Thus, the type implementing Method may use multiple Operations +// to set the Location fields at a particular x value. +// +// Instead of an Evaluation, a Method may declare MajorIteration. In +// a MajorIteration, the values in the fields of Location are treated as +// a potential optimizer. The convergence of the optimization routine +// (GradientThreshold, etc.) is checked at this new best point. In +// a MajorIteration, the fields of Location must be valid and consistent. +// +// A Method must not return InitIteration and PostIteration operations. These are +// reserved for the clients to be passed to Recorders. A Method must also not +// combine the Evaluation operations with the Iteration operations. +type Method interface { + // Init initializes the method based on the initial data in loc, updates it + // and returns the first operation to be carried out by the caller. + // The initial location must be valid as specified by Needs. + Init(loc *Location) (Operation, error) + + // Iterate retrieves data from loc, performs one iteration of the method, + // updates loc and returns the next operation. + Iterate(loc *Location) (Operation, error) + + Needser +} + +type Needser interface { + // Needs specifies information about the objective function needed by the + // optimizer beyond just the function value. The information is used + // internally for initialization and must match evaluation types returned + // by Init and Iterate during the optimization process. + Needs() struct { + Gradient bool + Hessian bool + } +} + +// Statuser can report the status and any error. It is intended for methods as +// an additional error reporting mechanism apart from the errors returned from +// Init and Iterate. +type Statuser interface { + Status() (Status, error) +} + +// Linesearcher is a type that can perform a line search. It tries to find an +// (approximate) minimum of the objective function along the search direction +// dir_k starting at the most recent location x_k, i.e., it tries to minimize +// the function +// φ(step) := f(x_k + step * dir_k) where step > 0. +// Typically, a Linesearcher will be used in conjuction with LinesearchMethod +// for performing gradient-based optimization through sequential line searches. +type Linesearcher interface { + // Init initializes the Linesearcher and a new line search. Value and + // derivative contain φ(0) and φ'(0), respectively, and step contains the + // first trial step length. It returns an Operation that must be one of + // FuncEvaluation, GradEvaluation, FuncEvaluation|GradEvaluation. The + // caller must evaluate φ(step), φ'(step), or both, respectively, and pass + // the result to Linesearcher in value and derivative arguments to Iterate. + Init(value, derivative float64, step float64) Operation + + // Iterate takes in the values of φ and φ' evaluated at the previous step + // and returns the next operation. + // + // If op is one of FuncEvaluation, GradEvaluation, + // FuncEvaluation|GradEvaluation, the caller must evaluate φ(step), + // φ'(step), or both, respectively, and pass the result to Linesearcher in + // value and derivative arguments on the next call to Iterate. + // + // If op is MajorIteration, a sufficiently accurate minimum of φ has been + // found at the previous step and the line search has concluded. Init must + // be called again to initialize a new line search. + // + // If err is nil, op must not specify another operation. If err is not nil, + // the values of op and step are undefined. + Iterate(value, derivative float64) (op Operation, step float64, err error) +} + +// NextDirectioner implements a strategy for computing a new line search +// direction at each major iteration. Typically, a NextDirectioner will be +// used in conjuction with LinesearchMethod for performing gradient-based +// optimization through sequential line searches. +type NextDirectioner interface { + // InitDirection initializes the NextDirectioner at the given starting location, + // putting the initial direction in place into dir, and returning the initial + // step size. InitDirection must not modify Location. + InitDirection(loc *Location, dir []float64) (step float64) + + // NextDirection updates the search direction and step size. Location is + // the location seen at the conclusion of the most recent linesearch. The + // next search direction is put in place into dir, and the next step size + // is returned. NextDirection must not modify Location. + NextDirection(loc *Location, dir []float64) (step float64) +} + +// StepSizer can set the next step size of the optimization given the last Location. +// Returned step size must be positive. +type StepSizer interface { + Init(loc *Location, dir []float64) float64 + StepSize(loc *Location, dir []float64) float64 +} + +// A Recorder can record the progress of the optimization, for example to print +// the progress to StdOut or to a log file. A Recorder must not modify any data. +type Recorder interface { + Init() error + Record(*Location, Operation, *Stats) error +} diff --git a/optimize/lbfgs.go b/optimize/lbfgs.go new file mode 100644 index 00000000..5c549377 --- /dev/null +++ b/optimize/lbfgs.go @@ -0,0 +1,167 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "gonum.org/v1/gonum/floats" +) + +// LBFGS implements the limited-memory BFGS method for gradient-based +// unconstrained minimization. +// +// It stores a modified version of the inverse Hessian approximation H +// implicitly from the last Store iterations while the normal BFGS method +// stores and manipulates H directly as a dense matrix. Therefore LBFGS is more +// appropriate than BFGS for large problems as the cost of LBFGS scales as +// O(Store * dim) while BFGS scales as O(dim^2). The "forgetful" nature of +// LBFGS may also make it perform better than BFGS for functions with Hessians +// that vary rapidly spatially. +type LBFGS struct { + // Linesearcher selects suitable steps along the descent direction. + // Accepted steps should satisfy the strong Wolfe conditions. + // If Linesearcher is nil, a reasonable default will be chosen. + Linesearcher Linesearcher + // Store is the size of the limited-memory storage. + // If Store is 0, it will be defaulted to 15. + Store int + + ls *LinesearchMethod + + dim int // Dimension of the problem + x []float64 // Location at the last major iteration + grad []float64 // Gradient at the last major iteration + + // History + oldest int // Index of the oldest element of the history + y [][]float64 // Last Store values of y + s [][]float64 // Last Store values of s + rho []float64 // Last Store values of rho + a []float64 // Cache of Hessian updates +} + +func (l *LBFGS) Init(loc *Location) (Operation, error) { + if l.Linesearcher == nil { + l.Linesearcher = &Bisection{} + } + if l.Store == 0 { + l.Store = 15 + } + + if l.ls == nil { + l.ls = &LinesearchMethod{} + } + l.ls.Linesearcher = l.Linesearcher + l.ls.NextDirectioner = l + + return l.ls.Init(loc) +} + +func (l *LBFGS) Iterate(loc *Location) (Operation, error) { + return l.ls.Iterate(loc) +} + +func (l *LBFGS) InitDirection(loc *Location, dir []float64) (stepSize float64) { + dim := len(loc.X) + l.dim = dim + l.oldest = 0 + + l.a = resize(l.a, l.Store) + l.rho = resize(l.rho, l.Store) + l.y = l.initHistory(l.y) + l.s = l.initHistory(l.s) + + l.x = resize(l.x, dim) + copy(l.x, loc.X) + + l.grad = resize(l.grad, dim) + copy(l.grad, loc.Gradient) + + copy(dir, loc.Gradient) + floats.Scale(-1, dir) + return 1 / floats.Norm(dir, 2) +} + +func (l *LBFGS) initHistory(hist [][]float64) [][]float64 { + c := cap(hist) + if c < l.Store { + n := make([][]float64, l.Store-c) + hist = append(hist[:c], n...) + } + hist = hist[:l.Store] + for i := range hist { + hist[i] = resize(hist[i], l.dim) + for j := range hist[i] { + hist[i][j] = 0 + } + } + return hist +} + +func (l *LBFGS) NextDirection(loc *Location, dir []float64) (stepSize float64) { + // Uses two-loop correction as described in + // Nocedal, J., Wright, S.: Numerical Optimization (2nd ed). Springer (2006), chapter 7, page 178. + + if len(loc.X) != l.dim { + panic("lbfgs: unexpected size mismatch") + } + if len(loc.Gradient) != l.dim { + panic("lbfgs: unexpected size mismatch") + } + if len(dir) != l.dim { + panic("lbfgs: unexpected size mismatch") + } + + y := l.y[l.oldest] + floats.SubTo(y, loc.Gradient, l.grad) + s := l.s[l.oldest] + floats.SubTo(s, loc.X, l.x) + sDotY := floats.Dot(s, y) + l.rho[l.oldest] = 1 / sDotY + + l.oldest = (l.oldest + 1) % l.Store + + copy(l.x, loc.X) + copy(l.grad, loc.Gradient) + copy(dir, loc.Gradient) + + // Start with the most recent element and go backward, + for i := 0; i < l.Store; i++ { + idx := l.oldest - i - 1 + if idx < 0 { + idx += l.Store + } + l.a[idx] = l.rho[idx] * floats.Dot(l.s[idx], dir) + floats.AddScaled(dir, -l.a[idx], l.y[idx]) + } + + // Scale the initial Hessian. + gamma := sDotY / floats.Dot(y, y) + floats.Scale(gamma, dir) + + // Start with the oldest element and go forward. + for i := 0; i < l.Store; i++ { + idx := i + l.oldest + if idx >= l.Store { + idx -= l.Store + } + beta := l.rho[idx] * floats.Dot(l.y[idx], dir) + floats.AddScaled(dir, l.a[idx]-beta, l.s[idx]) + } + + // dir contains H^{-1} * g, so flip the direction for minimization. + floats.Scale(-1, dir) + + return 1 +} + +func (*LBFGS) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, false} +} diff --git a/optimize/linesearch.go b/optimize/linesearch.go new file mode 100644 index 00000000..37ccb90e --- /dev/null +++ b/optimize/linesearch.go @@ -0,0 +1,218 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "math" + + "gonum.org/v1/gonum/floats" +) + +// LinesearchMethod represents an abstract optimization method in which a +// function is optimized through successive line search optimizations. +type LinesearchMethod struct { + // NextDirectioner specifies the search direction of each linesearch. + NextDirectioner NextDirectioner + // Linesearcher performs a linesearch along the search direction. + Linesearcher Linesearcher + + x []float64 // Starting point for the current iteration. + dir []float64 // Search direction for the current iteration. + + first bool // Indicator of the first iteration. + nextMajor bool // Indicates that MajorIteration must be commanded at the next call to Iterate. + eval Operation // Indicator of valid fields in Location. + + lastStep float64 // Step taken from x in the previous call to Iterate. + lastOp Operation // Operation returned from the previous call to Iterate. +} + +func (ls *LinesearchMethod) Init(loc *Location) (Operation, error) { + if loc.Gradient == nil { + panic("linesearch: gradient is nil") + } + + dim := len(loc.X) + ls.x = resize(ls.x, dim) + ls.dir = resize(ls.dir, dim) + + ls.first = true + ls.nextMajor = false + + // Indicate that all fields of loc are valid. + ls.eval = FuncEvaluation | GradEvaluation + if loc.Hessian != nil { + ls.eval |= HessEvaluation + } + + ls.lastStep = math.NaN() + ls.lastOp = NoOperation + + return ls.initNextLinesearch(loc) +} + +func (ls *LinesearchMethod) Iterate(loc *Location) (Operation, error) { + switch ls.lastOp { + case NoOperation: + // TODO(vladimir-ch): Either Init has not been called, or the caller is + // trying to resume the optimization run after Iterate previously + // returned with an error. Decide what is the proper thing to do. See also #125. + + case MajorIteration: + // The previous updated location did not converge the full + // optimization. Initialize a new Linesearch. + return ls.initNextLinesearch(loc) + + default: + // Update the indicator of valid fields of loc. + ls.eval |= ls.lastOp + + if ls.nextMajor { + ls.nextMajor = false + + // Linesearcher previously finished, and the invalid fields of loc + // have now been validated. Announce MajorIteration. + ls.lastOp = MajorIteration + return ls.lastOp, nil + } + } + + // Continue the linesearch. + + f := math.NaN() + if ls.eval&FuncEvaluation != 0 { + f = loc.F + } + projGrad := math.NaN() + if ls.eval&GradEvaluation != 0 { + projGrad = floats.Dot(loc.Gradient, ls.dir) + } + op, step, err := ls.Linesearcher.Iterate(f, projGrad) + if err != nil { + return ls.error(err) + } + + switch op { + case MajorIteration: + // Linesearch has been finished. + + ls.lastOp = complementEval(loc, ls.eval) + if ls.lastOp == NoOperation { + // loc is complete, MajorIteration can be declared directly. + ls.lastOp = MajorIteration + } else { + // Declare MajorIteration on the next call to Iterate. + ls.nextMajor = true + } + + case FuncEvaluation, GradEvaluation, FuncEvaluation | GradEvaluation: + if step != ls.lastStep { + // We are moving to a new location, and not, say, evaluating extra + // information at the current location. + + // Compute the next evaluation point and store it in loc.X. + floats.AddScaledTo(loc.X, ls.x, step, ls.dir) + if floats.Equal(ls.x, loc.X) { + // Step size has become so small that the next evaluation point is + // indistinguishable from the starting point for the current + // iteration due to rounding errors. + return ls.error(ErrNoProgress) + } + ls.lastStep = step + ls.eval = NoOperation // Indicate all invalid fields of loc. + } + ls.lastOp = op + + default: + panic("linesearch: Linesearcher returned invalid operation") + } + + return ls.lastOp, nil +} + +func (ls *LinesearchMethod) error(err error) (Operation, error) { + ls.lastOp = NoOperation + return ls.lastOp, err +} + +// initNextLinesearch initializes the next linesearch using the previous +// complete location stored in loc. It fills loc.X and returns an evaluation +// to be performed at loc.X. +func (ls *LinesearchMethod) initNextLinesearch(loc *Location) (Operation, error) { + copy(ls.x, loc.X) + + var step float64 + if ls.first { + ls.first = false + step = ls.NextDirectioner.InitDirection(loc, ls.dir) + } else { + step = ls.NextDirectioner.NextDirection(loc, ls.dir) + } + + projGrad := floats.Dot(loc.Gradient, ls.dir) + if projGrad >= 0 { + return ls.error(ErrNonDescentDirection) + } + + op := ls.Linesearcher.Init(loc.F, projGrad, step) + switch op { + case FuncEvaluation, GradEvaluation, FuncEvaluation | GradEvaluation: + default: + panic("linesearch: Linesearcher returned invalid operation") + } + + floats.AddScaledTo(loc.X, ls.x, step, ls.dir) + if floats.Equal(ls.x, loc.X) { + // Step size is so small that the next evaluation point is + // indistinguishable from the starting point for the current iteration + // due to rounding errors. + return ls.error(ErrNoProgress) + } + + ls.lastStep = step + ls.eval = NoOperation // Invalidate all fields of loc. + + ls.lastOp = op + return ls.lastOp, nil +} + +// ArmijoConditionMet returns true if the Armijo condition (aka sufficient +// decrease) has been met. Under normal conditions, the following should be +// true, though this is not enforced: +// - initGrad < 0 +// - step > 0 +// - 0 < decrease < 1 +func ArmijoConditionMet(currObj, initObj, initGrad, step, decrease float64) bool { + return currObj <= initObj+decrease*step*initGrad +} + +// StrongWolfeConditionsMet returns true if the strong Wolfe conditions have been met. +// The strong Wolfe conditions ensure sufficient decrease in the function +// value, and sufficient decrease in the magnitude of the projected gradient. +// Under normal conditions, the following should be true, though this is not +// enforced: +// - initGrad < 0 +// - step > 0 +// - 0 <= decrease < curvature < 1 +func StrongWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, decrease, curvature float64) bool { + if currObj > initObj+decrease*step*initGrad { + return false + } + return math.Abs(currGrad) < curvature*math.Abs(initGrad) +} + +// WeakWolfeConditionsMet returns true if the weak Wolfe conditions have been met. +// The weak Wolfe conditions ensure sufficient decrease in the function value, +// and sufficient decrease in the value of the projected gradient. Under normal +// conditions, the following should be true, though this is not enforced: +// - initGrad < 0 +// - step > 0 +// - 0 <= decrease < curvature< 1 +func WeakWolfeConditionsMet(currObj, currGrad, initObj, initGrad, step, decrease, curvature float64) bool { + if currObj > initObj+decrease*step*initGrad { + return false + } + return currGrad >= curvature*initGrad +} diff --git a/optimize/linesearcher_test.go b/optimize/linesearcher_test.go new file mode 100644 index 00000000..e1693108 --- /dev/null +++ b/optimize/linesearcher_test.go @@ -0,0 +1,136 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "fmt" + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/optimize/functions" +) + +func TestMoreThuente(t *testing.T) { + d := 0.001 + c := 0.001 + ls := &MoreThuente{ + DecreaseFactor: d, + CurvatureFactor: c, + } + testLinesearcher(t, ls, d, c, true) +} + +func TestBisection(t *testing.T) { + c := 0.1 + ls := &Bisection{ + CurvatureFactor: c, + } + testLinesearcher(t, ls, 0, c, true) +} + +func TestBacktracking(t *testing.T) { + d := 0.001 + ls := &Backtracking{ + DecreaseFactor: d, + } + testLinesearcher(t, ls, d, 0, false) +} + +type funcGrader interface { + Func([]float64) float64 + Grad([]float64, []float64) +} + +type linesearcherTest struct { + name string + f func(float64) float64 + g func(float64) float64 +} + +func newLinesearcherTest(name string, fg funcGrader) linesearcherTest { + grad := make([]float64, 1) + return linesearcherTest{ + name: name, + f: func(x float64) float64 { + return fg.Func([]float64{x}) + }, + g: func(x float64) float64 { + fg.Grad(grad, []float64{x}) + return grad[0] + }, + } +} + +func testLinesearcher(t *testing.T, ls Linesearcher, decrease, curvature float64, strongWolfe bool) { + for i, prob := range []linesearcherTest{ + newLinesearcherTest("Concave-to-the-right function", functions.ConcaveRight{}), + newLinesearcherTest("Concave-to-the-left function", functions.ConcaveLeft{}), + newLinesearcherTest("Plassmann wiggly function (l=39, beta=0.01)", functions.Plassmann{39, 0.01}), + newLinesearcherTest("Yanai-Ozawa-Kaneko function (beta1=0.001, beta2=0.001)", functions.YanaiOzawaKaneko{0.001, 0.001}), + newLinesearcherTest("Yanai-Ozawa-Kaneko function (beta1=0.01, beta2=0.001)", functions.YanaiOzawaKaneko{0.01, 0.001}), + newLinesearcherTest("Yanai-Ozawa-Kaneko function (beta1=0.001, beta2=0.01)", functions.YanaiOzawaKaneko{0.001, 0.01}), + } { + for _, initStep := range []float64{0.001, 0.1, 1, 10, 1000} { + prefix := fmt.Sprintf("test %d (%v started from %v)", i, prob.name, initStep) + + f0 := prob.f(0) + g0 := prob.g(0) + if g0 >= 0 { + panic("bad test function") + } + + op := ls.Init(f0, g0, initStep) + if !op.isEvaluation() { + t.Errorf("%v: Linesearcher.Init returned non-evaluating operation %v", op) + continue + } + + var ( + err error + k int + f, g float64 + step float64 + ) + loop: + for { + switch op { + case MajorIteration: + if f > f0+step*decrease*g0 { + t.Errorf("%v: %v found step %v that does not satisfy the sufficient decrease condition", + prefix, reflect.TypeOf(ls), step) + } + if strongWolfe && math.Abs(g) > curvature*(-g0) { + t.Errorf("%v: %v found step %v that does not satisfy the curvature condition", + prefix, reflect.TypeOf(ls), step) + } + break loop + case FuncEvaluation: + f = prob.f(step) + case GradEvaluation: + g = prob.g(step) + case FuncEvaluation | GradEvaluation: + f = prob.f(step) + g = prob.g(step) + default: + t.Errorf("%v: Linesearcher returned an invalid operation %v", op) + break loop + } + + k++ + if k == 1000 { + t.Errorf("%v: %v did not finish", prefix, reflect.TypeOf(ls)) + break + } + + op, step, err = ls.Iterate(f, g) + if err != nil { + t.Errorf("%v: %v failed at step %v with %v", prefix, reflect.TypeOf(ls), step, err) + break + } + } + } + } +} diff --git a/optimize/local.go b/optimize/local.go new file mode 100644 index 00000000..706229db --- /dev/null +++ b/optimize/local.go @@ -0,0 +1,226 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "math" + "time" +) + +// Local finds a local minimum of a minimization problem using a sequential +// algorithm. A maximization problem can be transformed into a minimization +// problem by multiplying the function by -1. +// +// The first argument represents the problem to be minimized. Its fields are +// routines that evaluate the objective function, gradient, and other +// quantities related to the problem. The objective function, p.Func, must not +// be nil. The optimization method used may require other fields to be non-nil +// as specified by method.Needs. Local will panic if these are not met. The +// method can be determined automatically from the supplied problem which is +// described below. +// +// If p.Status is not nil, it is called before every evaluation. If the +// returned Status is not NotTerminated or the error is not nil, the +// optimization run is terminated. +// +// The second argument is the initial location at which to start the minimization. +// The initial location must be supplied, and must have a length equal to the +// problem dimension. +// +// The third argument contains the settings for the minimization. It is here that +// gradient tolerance, etc. are specified. The DefaultSettings function +// can be called for a Settings struct with the default values initialized. +// If settings == nil, the default settings are used. See the documentation +// for the Settings structure for more information. The optimization Method used +// may also contain settings, see documentation for the appropriate optimizer. +// +// The final argument is the optimization method to use. If method == nil, then +// an appropriate default is chosen based on the properties of the other arguments +// (dimension, gradient-free or gradient-based, etc.). The optimization +// methods in this package are designed such that reasonable defaults occur +// if options are not specified explicitly. For example, the code +// method := &optimize.BFGS{} +// creates a pointer to a new BFGS struct. When Local is called, the settings +// in the method will be populated with default values. The methods are also +// designed such that they can be reused in future calls to Local. +// +// If method implements Statuser, method.Status is called before every call +// to method.Iterate. If the returned Status is not NotTerminated or the +// error is non-nil, the optimization run is terminated. +// +// Local returns a Result struct and any error that occurred. See the +// documentation of Result for more information. +// +// Be aware that the default behavior of Local is to find the minimum. +// For certain functions and optimization methods, this process can take many +// function evaluations. If you would like to put limits on this, for example +// maximum runtime or maximum function evaluations, modify the Settings +// input struct. +func Local(p Problem, initX []float64, settings *Settings, method Method) (*Result, error) { + startTime := time.Now() + dim := len(initX) + if method == nil { + method = getDefaultMethod(&p) + } + if settings == nil { + settings = DefaultSettings() + } + + stats := &Stats{} + + err := checkOptimization(p, dim, method, settings.Recorder) + if err != nil { + return nil, err + } + + optLoc, err := getStartingLocation(&p, method, initX, stats, settings) + if err != nil { + return nil, err + } + + if settings.FunctionConverge != nil { + settings.FunctionConverge.Init(optLoc.F) + } + + stats.Runtime = time.Since(startTime) + + // Send initial location to Recorder + if settings.Recorder != nil { + err = settings.Recorder.Record(optLoc, InitIteration, stats) + if err != nil { + return nil, err + } + } + + // Check if the starting location satisfies the convergence criteria. + status := checkConvergence(optLoc, settings, true) + + // Run optimization + if status == NotTerminated && err == nil { + // The starting location is not good enough, we need to perform a + // minimization. The optimal location will be stored in-place in + // optLoc. + status, err = minimize(&p, method, settings, stats, optLoc, startTime) + } + + // Cleanup and collect results + if settings.Recorder != nil && err == nil { + // Send the optimal location to Recorder. + err = settings.Recorder.Record(optLoc, PostIteration, stats) + } + stats.Runtime = time.Since(startTime) + return &Result{ + Location: *optLoc, + Stats: *stats, + Status: status, + }, err +} + +func minimize(p *Problem, method Method, settings *Settings, stats *Stats, optLoc *Location, startTime time.Time) (status Status, err error) { + loc := &Location{} + copyLocation(loc, optLoc) + x := make([]float64, len(loc.X)) + + statuser, _ := method.(Statuser) + + var op Operation + op, err = method.Init(loc) + if err != nil { + status = Failure + return + } + + for { + // Sequentially call method.Iterate, performing the operations it has + // commanded, until convergence. + + switch op { + case NoOperation: + case InitIteration: + panic("optimize: Method returned InitIteration") + case PostIteration: + panic("optimize: Method returned PostIteration") + case MajorIteration: + copyLocation(optLoc, loc) + stats.MajorIterations++ + status = checkConvergence(optLoc, settings, true) + default: // Any of the Evaluation operations. + status, err = evaluate(p, loc, op, x) + updateStats(stats, op) + } + + status, err = iterCleanup(status, err, stats, settings, statuser, startTime, loc, op) + if status != NotTerminated || err != nil { + return + } + + op, err = method.Iterate(loc) + if err != nil { + status = Failure + return + } + } + panic("optimize: unreachable") +} + +func getDefaultMethod(p *Problem) Method { + if p.Grad != nil { + return &BFGS{} + } + return &NelderMead{} +} + +// getStartingLocation allocates and initializes the starting location for the minimization. +func getStartingLocation(p *Problem, method Method, initX []float64, stats *Stats, settings *Settings) (*Location, error) { + dim := len(initX) + loc := newLocation(dim, method) + copy(loc.X, initX) + + if settings.UseInitialData { + loc.F = settings.InitialValue + if loc.Gradient != nil { + initG := settings.InitialGradient + if initG == nil { + panic("optimize: initial gradient is nil") + } + if len(initG) != dim { + panic("optimize: initial gradient size mismatch") + } + copy(loc.Gradient, initG) + } + if loc.Hessian != nil { + initH := settings.InitialHessian + if initH == nil { + panic("optimize: initial Hessian is nil") + } + if initH.Symmetric() != dim { + panic("optimize: initial Hessian size mismatch") + } + loc.Hessian.CopySym(initH) + } + } else { + eval := FuncEvaluation + if loc.Gradient != nil { + eval |= GradEvaluation + } + if loc.Hessian != nil { + eval |= HessEvaluation + } + x := make([]float64, len(loc.X)) + evaluate(p, loc, eval, x) + updateStats(stats, eval) + } + + if math.IsInf(loc.F, 1) || math.IsNaN(loc.F) { + return loc, ErrFunc(loc.F) + } + for i, v := range loc.Gradient { + if math.IsInf(v, 0) || math.IsNaN(v) { + return loc, ErrGrad{Grad: v, Index: i} + } + } + + return loc, nil +} diff --git a/optimize/local_example_test.go b/optimize/local_example_test.go new file mode 100644 index 00000000..64940388 --- /dev/null +++ b/optimize/local_example_test.go @@ -0,0 +1,43 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize_test + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/optimize" + "gonum.org/v1/gonum/optimize/functions" +) + +func ExampleLocal() { + p := optimize.Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + } + + x := []float64{1.3, 0.7, 0.8, 1.9, 1.2} + settings := optimize.DefaultSettings() + settings.Recorder = nil + settings.GradientThreshold = 1e-12 + settings.FunctionConverge = nil + + result, err := optimize.Local(p, x, settings, &optimize.BFGS{}) + if err != nil { + log.Fatal(err) + } + if err = result.Status.Err(); err != nil { + log.Fatal(err) + } + fmt.Printf("result.Status: %v\n", result.Status) + fmt.Printf("result.X: %v\n", result.X) + fmt.Printf("result.F: %v\n", result.F) + fmt.Printf("result.Stats.FuncEvaluations: %d\n", result.Stats.FuncEvaluations) + // Output: + // result.Status: GradientThreshold + // result.X: [1 1 1 1 1] + // result.F: 0 + // result.Stats.FuncEvaluations: 35 +} diff --git a/optimize/minimize.go b/optimize/minimize.go new file mode 100644 index 00000000..b49a7728 --- /dev/null +++ b/optimize/minimize.go @@ -0,0 +1,202 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "fmt" + "math" + "time" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +// newLocation allocates a new locatian structure of the appropriate size. It +// allocates memory based on the dimension and the values in Needs. The initial +// function value is set to math.Inf(1). +func newLocation(dim int, method Needser) *Location { + // TODO(btracey): combine this with Local. + loc := &Location{ + X: make([]float64, dim), + } + loc.F = math.Inf(1) + if method.Needs().Gradient { + loc.Gradient = make([]float64, dim) + } + if method.Needs().Hessian { + loc.Hessian = mat64.NewSymDense(dim, nil) + } + return loc +} + +func copyLocation(dst, src *Location) { + dst.X = resize(dst.X, len(src.X)) + copy(dst.X, src.X) + + dst.F = src.F + + dst.Gradient = resize(dst.Gradient, len(src.Gradient)) + copy(dst.Gradient, src.Gradient) + + if src.Hessian != nil { + if dst.Hessian == nil || dst.Hessian.Symmetric() != len(src.X) { + dst.Hessian = mat64.NewSymDense(len(src.X), nil) + } + dst.Hessian.CopySym(src.Hessian) + } +} + +func checkOptimization(p Problem, dim int, method Needser, recorder Recorder) error { + if p.Func == nil { + panic("optimize: objective function is undefined") + } + if dim <= 0 { + panic("optimize: impossible problem dimension") + } + if err := p.satisfies(method); err != nil { + return err + } + if p.Status != nil { + _, err := p.Status() + if err != nil { + return err + } + } + if recorder != nil { + err := recorder.Init() + if err != nil { + return err + } + } + return nil +} + +// evaluate evaluates the routines specified by the Operation at loc.X, and stores +// the answer into loc. loc.X is copied into x before +// evaluating in order to prevent the routines from modifying it. +func evaluate(p *Problem, loc *Location, op Operation, x []float64) (Status, error) { + if !op.isEvaluation() { + panic(fmt.Sprintf("optimize: invalid evaluation %v", op)) + } + if p.Status != nil { + status, err := p.Status() + if err != nil || status != NotTerminated { + return status, err + } + } + copy(x, loc.X) + if op&FuncEvaluation != 0 { + loc.F = p.Func(x) + } + if op&GradEvaluation != 0 { + p.Grad(loc.Gradient, x) + } + if op&HessEvaluation != 0 { + p.Hess(loc.Hessian, x) + } + return NotTerminated, nil +} + +// checkConvergence returns NotTerminated if the Location does not satisfy the +// convergence criteria given by settings. Otherwise a corresponding status is +// returned. +// Unlike checkLimits, checkConvergence is called only at MajorIterations. +// +// If local is true, gradient convergence is also checked. +func checkConvergence(loc *Location, settings *Settings, local bool) Status { + if local && loc.Gradient != nil { + norm := floats.Norm(loc.Gradient, math.Inf(1)) + if norm < settings.GradientThreshold { + return GradientThreshold + } + } + if loc.F < settings.FunctionThreshold { + return FunctionThreshold + } + if settings.FunctionConverge != nil { + return settings.FunctionConverge.FunctionConverged(loc.F) + } + return NotTerminated +} + +// updateStats updates the statistics based on the operation. +func updateStats(stats *Stats, op Operation) { + if op&FuncEvaluation != 0 { + stats.FuncEvaluations++ + } + if op&GradEvaluation != 0 { + stats.GradEvaluations++ + } + if op&HessEvaluation != 0 { + stats.HessEvaluations++ + } +} + +// checkLimits returns NotTerminated status if the various limits given by +// settings have not been reached. Otherwise it returns a corresponding status. +// Unlike checkConvergence, checkLimits is called by Local and Global at _every_ +// iteration. +func checkLimits(loc *Location, stats *Stats, settings *Settings) Status { + // Check the objective function value for negative infinity because it + // could break the linesearches and -inf is the best we can do anyway. + if math.IsInf(loc.F, -1) { + return FunctionNegativeInfinity + } + + if settings.MajorIterations > 0 && stats.MajorIterations >= settings.MajorIterations { + return IterationLimit + } + + if settings.FuncEvaluations > 0 && stats.FuncEvaluations >= settings.FuncEvaluations { + return FunctionEvaluationLimit + } + + if settings.GradEvaluations > 0 && stats.GradEvaluations >= settings.GradEvaluations { + return GradientEvaluationLimit + } + + if settings.HessEvaluations > 0 && stats.HessEvaluations >= settings.HessEvaluations { + return HessianEvaluationLimit + } + + // TODO(vladimir-ch): It would be nice to update Runtime here. + if settings.Runtime > 0 && stats.Runtime >= settings.Runtime { + return RuntimeLimit + } + + return NotTerminated +} + +// TODO(btracey): better name +func iterCleanup(status Status, err error, stats *Stats, settings *Settings, statuser Statuser, startTime time.Time, loc *Location, op Operation) (Status, error) { + if status != NotTerminated || err != nil { + return status, err + } + + if settings.Recorder != nil { + stats.Runtime = time.Since(startTime) + err = settings.Recorder.Record(loc, op, stats) + if err != nil { + if status == NotTerminated { + status = Failure + } + return status, err + } + } + + stats.Runtime = time.Since(startTime) + status = checkLimits(loc, stats, settings) + if status != NotTerminated { + return status, nil + } + + if statuser != nil { + status, err = statuser.Status() + if err != nil || status != NotTerminated { + return status, err + } + } + return status, nil +} diff --git a/optimize/morethuente.go b/optimize/morethuente.go new file mode 100644 index 00000000..ec23167b --- /dev/null +++ b/optimize/morethuente.go @@ -0,0 +1,385 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import "math" + +// MoreThuente is a Linesearcher that finds steps that satisfy both the +// sufficient decrease and curvature conditions (the strong Wolfe conditions). +// +// References: +// - More, J.J. and D.J. Thuente: Line Search Algorithms with Guaranteed Sufficient +// Decrease. ACM Transactions on Mathematical Software 20(3) (1994), 286-307 +type MoreThuente struct { + // DecreaseFactor is the constant factor in the sufficient decrease + // (Armijo) condition. + // It must be in the interval [0, 1). The default value is 0. + DecreaseFactor float64 + // CurvatureFactor is the constant factor in the Wolfe conditions. Smaller + // values result in a more exact line search. + // A set value must be in the interval (0, 1). If it is zero, it will be + // defaulted to 0.9. + CurvatureFactor float64 + // StepTolerance sets the minimum acceptable width for the linesearch + // interval. If the relative interval length is less than this value, + // ErrLinesearcherFailure is returned. + // It must be non-negative. If it is zero, it will be defaulted to 1e-10. + StepTolerance float64 + + // MinimumStep is the minimum step that the linesearcher will take. + // It must be non-negative and less than MaximumStep. Defaults to no + // minimum (a value of 0). + MinimumStep float64 + // MaximumStep is the maximum step that the linesearcher will take. + // It must be greater than MinimumStep. If it is zero, it will be defaulted + // to 1e20. + MaximumStep float64 + + bracketed bool // Indicates if a minimum has been bracketed. + fInit float64 // Function value at step = 0. + gInit float64 // Derivative value at step = 0. + + // When stage is 1, the algorithm updates the interval given by x and y + // so that it contains a minimizer of the modified function + // psi(step) = f(step) - f(0) - DecreaseFactor * step * f'(0). + // When stage is 2, the interval is updated so that it contains a minimizer + // of f. + stage int + + step float64 // Current step. + lower, upper float64 // Lower and upper bounds on the next step. + x float64 // Endpoint of the interval with a lower function value. + fx, gx float64 // Data at x. + y float64 // The other endpoint. + fy, gy float64 // Data at y. + width [2]float64 // Width of the interval at two previous iterations. +} + +const ( + mtMinGrowthFactor float64 = 1.1 + mtMaxGrowthFactor float64 = 4 +) + +func (mt *MoreThuente) Init(f, g float64, step float64) Operation { + // Based on the original Fortran code that is available, for example, from + // http://ftp.mcs.anl.gov/pub/MINPACK-2/csrch/ + // as part of + // MINPACK-2 Project. November 1993. + // Argonne National Laboratory and University of Minnesota. + // Brett M. Averick, Richard G. Carter, and Jorge J. Moré. + + if g >= 0 { + panic("morethuente: initial derivative is non-negative") + } + if step <= 0 { + panic("morethuente: invalid initial step") + } + + if mt.CurvatureFactor == 0 { + mt.CurvatureFactor = 0.9 + } + if mt.StepTolerance == 0 { + mt.StepTolerance = 1e-10 + } + if mt.MaximumStep == 0 { + mt.MaximumStep = 1e20 + } + + if mt.MinimumStep < 0 { + panic("morethuente: minimum step is negative") + } + if mt.MaximumStep <= mt.MinimumStep { + panic("morethuente: maximum step is not greater than minimum step") + } + if mt.DecreaseFactor < 0 || mt.DecreaseFactor >= 1 { + panic("morethuente: invalid decrease factor") + } + if mt.CurvatureFactor <= 0 || mt.CurvatureFactor >= 1 { + panic("morethuente: invalid curvature factor") + } + if mt.StepTolerance <= 0 { + panic("morethuente: step tolerance is not positive") + } + + if step < mt.MinimumStep { + step = mt.MinimumStep + } + if step > mt.MaximumStep { + step = mt.MaximumStep + } + + mt.bracketed = false + mt.stage = 1 + mt.fInit = f + mt.gInit = g + + mt.x, mt.fx, mt.gx = 0, f, g + mt.y, mt.fy, mt.gy = 0, f, g + + mt.lower = 0 + mt.upper = step + mtMaxGrowthFactor*step + + mt.width[0] = mt.MaximumStep - mt.MinimumStep + mt.width[1] = 2 * mt.width[0] + + mt.step = step + return FuncEvaluation | GradEvaluation +} + +func (mt *MoreThuente) Iterate(f, g float64) (Operation, float64, error) { + if mt.stage == 0 { + panic("morethuente: Init has not been called") + } + + gTest := mt.DecreaseFactor * mt.gInit + fTest := mt.fInit + mt.step*gTest + + if mt.bracketed { + if mt.step <= mt.lower || mt.step >= mt.upper || mt.upper-mt.lower <= mt.StepTolerance*mt.upper { + // step contains the best step found (see below). + return NoOperation, mt.step, ErrLinesearcherFailure + } + } + if mt.step == mt.MaximumStep && f <= fTest && g <= gTest { + return NoOperation, mt.step, ErrLinesearcherBound + } + if mt.step == mt.MinimumStep && (f > fTest || g >= gTest) { + return NoOperation, mt.step, ErrLinesearcherFailure + } + + // Test for convergence. + if f <= fTest && math.Abs(g) <= mt.CurvatureFactor*(-mt.gInit) { + mt.stage = 0 + return MajorIteration, mt.step, nil + } + + if mt.stage == 1 && f <= fTest && g >= 0 { + mt.stage = 2 + } + + if mt.stage == 1 && f <= mt.fx && f > fTest { + // Lower function value but the decrease is not sufficient . + + // Compute values and derivatives of the modified function at step, x, y. + fm := f - mt.step*gTest + fxm := mt.fx - mt.x*gTest + fym := mt.fy - mt.y*gTest + gm := g - gTest + gxm := mt.gx - gTest + gym := mt.gy - gTest + // Update x, y and step. + mt.nextStep(fxm, gxm, fym, gym, fm, gm) + // Recover values and derivates of the non-modified function at x and y. + mt.fx = fxm + mt.x*gTest + mt.fy = fym + mt.y*gTest + mt.gx = gxm + gTest + mt.gy = gym + gTest + } else { + // Update x, y and step. + mt.nextStep(mt.fx, mt.gx, mt.fy, mt.gy, f, g) + } + + if mt.bracketed { + // Monitor the length of the bracketing interval. If the interval has + // not been reduced sufficiently after two steps, use bisection to + // force its length to zero. + width := mt.y - mt.x + if math.Abs(width) >= 2.0/3*mt.width[1] { + mt.step = mt.x + 0.5*width + } + mt.width[0], mt.width[1] = math.Abs(width), mt.width[0] + } + + if mt.bracketed { + mt.lower = math.Min(mt.x, mt.y) + mt.upper = math.Max(mt.x, mt.y) + } else { + mt.lower = mt.step + mtMinGrowthFactor*(mt.step-mt.x) + mt.upper = mt.step + mtMaxGrowthFactor*(mt.step-mt.x) + } + + // Force the step to be in [MinimumStep, MaximumStep]. + mt.step = math.Max(mt.MinimumStep, math.Min(mt.step, mt.MaximumStep)) + + if mt.bracketed { + if mt.step <= mt.lower || mt.step >= mt.upper || mt.upper-mt.lower <= mt.StepTolerance*mt.upper { + // If further progress is not possible, set step to the best step + // obtained during the search. + mt.step = mt.x + } + } + + return FuncEvaluation | GradEvaluation, mt.step, nil +} + +// nextStep computes the next safeguarded step and updates the interval that +// contains a step that satisfies the sufficient decrease and curvature +// conditions. +func (mt *MoreThuente) nextStep(fx, gx, fy, gy, f, g float64) { + x := mt.x + y := mt.y + step := mt.step + + gNeg := g < 0 + if gx < 0 { + gNeg = !gNeg + } + + var next float64 + var bracketed bool + switch { + case f > fx: + // A higher function value. The minimum is bracketed between x and step. + // We want the next step to be closer to x because the function value + // there is lower. + + theta := 3*(fx-f)/(step-x) + gx + g + s := math.Max(math.Abs(gx), math.Abs(g)) + s = math.Max(s, math.Abs(theta)) + gamma := s * math.Sqrt((theta/s)*(theta/s)-(gx/s)*(g/s)) + if step < x { + gamma *= -1 + } + p := gamma - gx + theta + q := gamma - gx + gamma + g + r := p / q + stpc := x + r*(step-x) + stpq := x + gx/((fx-f)/(step-x)+gx)/2*(step-x) + + if math.Abs(stpc-x) < math.Abs(stpq-x) { + // The cubic step is closer to x than the quadratic step. + // Take the cubic step. + next = stpc + } else { + // If f is much larger than fx, then the quadratic step may be too + // close to x. Therefore heuristically take the average of the + // cubic and quadratic steps. + next = stpc + (stpq-stpc)/2 + } + bracketed = true + + case gNeg: + // A lower function value and derivatives of opposite sign. The minimum + // is bracketed between x and step. If we choose a step that is far + // from step, the next iteration will also likely fall in this case. + + theta := 3*(fx-f)/(step-x) + gx + g + s := math.Max(math.Abs(gx), math.Abs(g)) + s = math.Max(s, math.Abs(theta)) + gamma := s * math.Sqrt((theta/s)*(theta/s)-(gx/s)*(g/s)) + if step > x { + gamma *= -1 + } + p := gamma - g + theta + q := gamma - g + gamma + gx + r := p / q + stpc := step + r*(x-step) + stpq := step + g/(g-gx)*(x-step) + + if math.Abs(stpc-step) > math.Abs(stpq-step) { + // The cubic step is farther from x than the quadratic step. + // Take the cubic step. + next = stpc + } else { + // Take the quadratic step. + next = stpq + } + bracketed = true + + case math.Abs(g) < math.Abs(gx): + // A lower function value, derivatives of the same sign, and the + // magnitude of the derivative decreases. Extrapolate function values + // at x and step so that the next step lies between step and y. + + theta := 3*(fx-f)/(step-x) + gx + g + s := math.Max(math.Abs(gx), math.Abs(g)) + s = math.Max(s, math.Abs(theta)) + gamma := s * math.Sqrt(math.Max(0, (theta/s)*(theta/s)-(gx/s)*(g/s))) + if step > x { + gamma *= -1 + } + p := gamma - g + theta + q := gamma + gx - g + gamma + r := p / q + var stpc float64 + switch { + case r < 0 && gamma != 0: + stpc = step + r*(x-step) + case step > x: + stpc = mt.upper + default: + stpc = mt.lower + } + stpq := step + g/(g-gx)*(x-step) + + if mt.bracketed { + // We are extrapolating so be cautious and take the step that + // is closer to step. + if math.Abs(stpc-step) < math.Abs(stpq-step) { + next = stpc + } else { + next = stpq + } + // Modify next if it is close to or beyond y. + if step > x { + next = math.Min(step+2.0/3*(y-step), next) + } else { + next = math.Max(step+2.0/3*(y-step), next) + } + } else { + // Minimum has not been bracketed so take the larger step... + if math.Abs(stpc-step) > math.Abs(stpq-step) { + next = stpc + } else { + next = stpq + } + // ...but within reason. + next = math.Max(mt.lower, math.Min(next, mt.upper)) + } + + default: + // A lower function value, derivatives of the same sign, and the + // magnitude of the derivative does not decrease. The function seems to + // decrease rapidly in the direction of the step. + + switch { + case mt.bracketed: + theta := 3*(f-fy)/(y-step) + gy + g + s := math.Max(math.Abs(gy), math.Abs(g)) + s = math.Max(s, math.Abs(theta)) + gamma := s * math.Sqrt((theta/s)*(theta/s)-(gy/s)*(g/s)) + if step > y { + gamma *= -1 + } + p := gamma - g + theta + q := gamma - g + gamma + gy + r := p / q + next = step + r*(y-step) + case step > x: + next = mt.upper + default: + next = mt.lower + } + } + + if f > fx { + // x is still the best step. + mt.y = step + mt.fy = f + mt.gy = g + } else { + // step is the new best step. + if gNeg { + mt.y = x + mt.fy = fx + mt.gy = gx + } + mt.x = step + mt.fx = f + mt.gx = g + } + mt.bracketed = bracketed + mt.step = next +} diff --git a/optimize/neldermead.go b/optimize/neldermead.go new file mode 100644 index 00000000..18964773 --- /dev/null +++ b/optimize/neldermead.go @@ -0,0 +1,314 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "sort" + + "gonum.org/v1/gonum/floats" +) + +// nmIterType is a Nelder-Mead evaluation kind +type nmIterType int + +const ( + nmReflected = iota + nmExpanded + nmContractedInside + nmContractedOutside + nmInitialize + nmShrink + nmMajor +) + +type nmVertexSorter struct { + vertices [][]float64 + values []float64 +} + +func (n nmVertexSorter) Len() int { + return len(n.values) +} + +func (n nmVertexSorter) Less(i, j int) bool { + return n.values[i] < n.values[j] +} + +func (n nmVertexSorter) Swap(i, j int) { + n.values[i], n.values[j] = n.values[j], n.values[i] + n.vertices[i], n.vertices[j] = n.vertices[j], n.vertices[i] +} + +// NelderMead is an implementation of the Nelder-Mead simplex algorithm for +// gradient-free nonlinear optimization (not to be confused with Danzig's +// simplex algorithm for linear programming). The implementation follows the +// algorithm described in +// +// http://epubs.siam.org/doi/pdf/10.1137/S1052623496303470 +// +// If an initial simplex is provided, it is used and initLoc is ignored. If +// InitialVertices and InitialValues are both nil, an initial simplex will be +// generated automatically using the initial location as one vertex, and each +// additional vertex as SimplexSize away in one dimension. +// +// If the simplex update parameters (Reflection, etc.) +// are zero, they will be set automatically based on the dimension according to +// the recommendations in +// +// http://www.webpages.uidaho.edu/~fuchang/res/ANMS.pdf +type NelderMead struct { + InitialVertices [][]float64 + InitialValues []float64 + Reflection float64 // Reflection parameter (>0) + Expansion float64 // Expansion parameter (>1) + Contraction float64 // Contraction parameter (>0, <1) + Shrink float64 // Shrink parameter (>0, <1) + SimplexSize float64 // size of auto-constructed initial simplex + + reflection float64 + expansion float64 + contraction float64 + shrink float64 + + vertices [][]float64 // location of the vertices sorted in ascending f + values []float64 // function values at the vertices sorted in ascending f + centroid []float64 // centroid of all but the worst vertex + + fillIdx int // index for filling the simplex during initialization and shrinking + lastIter nmIterType // Last iteration + reflectedPoint []float64 // Storage of the reflected point location + reflectedValue float64 // Value at the last reflection point +} + +func (n *NelderMead) Init(loc *Location) (Operation, error) { + dim := len(loc.X) + if cap(n.vertices) < dim+1 { + n.vertices = make([][]float64, dim+1) + } + n.vertices = n.vertices[:dim+1] + for i := range n.vertices { + n.vertices[i] = resize(n.vertices[i], dim) + } + n.values = resize(n.values, dim+1) + n.centroid = resize(n.centroid, dim) + n.reflectedPoint = resize(n.reflectedPoint, dim) + + if n.SimplexSize == 0 { + n.SimplexSize = 0.05 + } + + // Default parameter choices are chosen in a dimension-dependent way + // from http://www.webpages.uidaho.edu/~fuchang/res/ANMS.pdf + n.reflection = n.Reflection + if n.reflection == 0 { + n.reflection = 1 + } + n.expansion = n.Expansion + if n.expansion == 0 { + n.expansion = 1 + 2/float64(dim) + } + n.contraction = n.Contraction + if n.contraction == 0 { + n.contraction = 0.75 - 1/(2*float64(dim)) + } + n.shrink = n.Shrink + if n.shrink == 0 { + n.shrink = 1 - 1/float64(dim) + } + + if n.InitialVertices != nil { + // Initial simplex provided. Copy the locations and values, and sort them. + if len(n.InitialVertices) != dim+1 { + panic("neldermead: incorrect number of vertices in initial simplex") + } + if len(n.InitialValues) != dim+1 { + panic("neldermead: incorrect number of values in initial simplex") + } + for i := range n.InitialVertices { + if len(n.InitialVertices[i]) != dim { + panic("neldermead: vertex size mismatch") + } + copy(n.vertices[i], n.InitialVertices[i]) + } + copy(n.values, n.InitialValues) + sort.Sort(nmVertexSorter{n.vertices, n.values}) + computeCentroid(n.vertices, n.centroid) + return n.returnNext(nmMajor, loc) + } + + // No simplex provided. Begin initializing initial simplex. First simplex + // entry is the initial location, then step 1 in every direction. + copy(n.vertices[dim], loc.X) + n.values[dim] = loc.F + n.fillIdx = 0 + loc.X[n.fillIdx] += n.SimplexSize + n.lastIter = nmInitialize + return FuncEvaluation, nil +} + +// computeCentroid computes the centroid of all the simplex vertices except the +// final one +func computeCentroid(vertices [][]float64, centroid []float64) { + dim := len(centroid) + for i := range centroid { + centroid[i] = 0 + } + for i := 0; i < dim; i++ { + vertex := vertices[i] + for j, v := range vertex { + centroid[j] += v + } + } + for i := range centroid { + centroid[i] /= float64(dim) + } +} + +func (n *NelderMead) Iterate(loc *Location) (Operation, error) { + dim := len(loc.X) + switch n.lastIter { + case nmInitialize: + n.values[n.fillIdx] = loc.F + copy(n.vertices[n.fillIdx], loc.X) + n.fillIdx++ + if n.fillIdx == dim { + // Successfully finished building initial simplex. + sort.Sort(nmVertexSorter{n.vertices, n.values}) + computeCentroid(n.vertices, n.centroid) + return n.returnNext(nmMajor, loc) + } + copy(loc.X, n.vertices[dim]) + loc.X[n.fillIdx] += n.SimplexSize + return FuncEvaluation, nil + case nmMajor: + // Nelder Mead iterations start with Reflection step + return n.returnNext(nmReflected, loc) + case nmReflected: + n.reflectedValue = loc.F + switch { + case loc.F >= n.values[0] && loc.F < n.values[dim-1]: + n.replaceWorst(loc.X, loc.F) + return n.returnNext(nmMajor, loc) + case loc.F < n.values[0]: + return n.returnNext(nmExpanded, loc) + default: + if loc.F < n.values[dim] { + return n.returnNext(nmContractedOutside, loc) + } + return n.returnNext(nmContractedInside, loc) + } + case nmExpanded: + if loc.F < n.reflectedValue { + n.replaceWorst(loc.X, loc.F) + } else { + n.replaceWorst(n.reflectedPoint, n.reflectedValue) + } + return n.returnNext(nmMajor, loc) + case nmContractedOutside: + if loc.F <= n.reflectedValue { + n.replaceWorst(loc.X, loc.F) + return n.returnNext(nmMajor, loc) + } + n.fillIdx = 1 + return n.returnNext(nmShrink, loc) + case nmContractedInside: + if loc.F < n.values[dim] { + n.replaceWorst(loc.X, loc.F) + return n.returnNext(nmMajor, loc) + } + n.fillIdx = 1 + return n.returnNext(nmShrink, loc) + case nmShrink: + copy(n.vertices[n.fillIdx], loc.X) + n.values[n.fillIdx] = loc.F + n.fillIdx++ + if n.fillIdx != dim+1 { + return n.returnNext(nmShrink, loc) + } + sort.Sort(nmVertexSorter{n.vertices, n.values}) + computeCentroid(n.vertices, n.centroid) + return n.returnNext(nmMajor, loc) + default: + panic("unreachable") + } +} + +// returnNext updates the location based on the iteration type and the current +// simplex, and returns the next operation. +func (n *NelderMead) returnNext(iter nmIterType, loc *Location) (Operation, error) { + n.lastIter = iter + switch iter { + case nmMajor: + // Fill loc with the current best point and value, + // and command a convergence check. + copy(loc.X, n.vertices[0]) + loc.F = n.values[0] + return MajorIteration, nil + case nmReflected, nmExpanded, nmContractedOutside, nmContractedInside: + // x_new = x_centroid + scale * (x_centroid - x_worst) + var scale float64 + switch iter { + case nmReflected: + scale = n.reflection + case nmExpanded: + scale = n.reflection * n.expansion + case nmContractedOutside: + scale = n.reflection * n.contraction + case nmContractedInside: + scale = -n.contraction + } + dim := len(loc.X) + floats.SubTo(loc.X, n.centroid, n.vertices[dim]) + floats.Scale(scale, loc.X) + floats.Add(loc.X, n.centroid) + if iter == nmReflected { + copy(n.reflectedPoint, loc.X) + } + return FuncEvaluation, nil + case nmShrink: + // x_shrink = x_best + delta * (x_i + x_best) + floats.SubTo(loc.X, n.vertices[n.fillIdx], n.vertices[0]) + floats.Scale(n.shrink, loc.X) + floats.Add(loc.X, n.vertices[0]) + return FuncEvaluation, nil + default: + panic("unreachable") + } +} + +// replaceWorst removes the worst location in the simplex and adds the new +// {x, f} pair maintaining sorting. +func (n *NelderMead) replaceWorst(x []float64, f float64) { + dim := len(x) + if f >= n.values[dim] { + panic("increase in simplex value") + } + copy(n.vertices[dim], x) + n.values[dim] = f + + // Sort the newly-added value. + for i := dim - 1; i >= 0; i-- { + if n.values[i] < f { + break + } + n.vertices[i], n.vertices[i+1] = n.vertices[i+1], n.vertices[i] + n.values[i], n.values[i+1] = n.values[i+1], n.values[i] + } + + // Update the location of the centroid. Only one point has been replaced, so + // subtract the worst point and add the new one. + floats.AddScaled(n.centroid, -1/float64(dim), n.vertices[dim]) + floats.AddScaled(n.centroid, 1/float64(dim), x) +} + +func (*NelderMead) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{false, false} +} diff --git a/optimize/newton.go b/optimize/newton.go new file mode 100644 index 00000000..f213067f --- /dev/null +++ b/optimize/newton.go @@ -0,0 +1,147 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "math" + + "gonum.org/v1/gonum/matrix/mat64" +) + +const maxNewtonModifications = 20 + +// Newton implements a modified Newton's method for Hessian-based unconstrained +// minimization. It applies regularization when the Hessian is not positive +// definite, and it can converge to a local minimum from any starting point. +// +// Newton iteratively forms a quadratic model to the objective function f and +// tries to minimize this approximate model. It generates a sequence of +// locations x_k by means of +// solve H_k d_k = -∇f_k for d_k, +// x_{k+1} = x_k + α_k d_k, +// where H_k is the Hessian matrix of f at x_k and α_k is a step size found by +// a line search. +// +// Away from a minimizer H_k may not be positive definite and d_k may not be a +// descent direction. Newton implements a Hessian modification strategy that +// adds successively larger multiples of identity to H_k until it becomes +// positive definite. Note that the repeated trial factorization of the +// modified Hessian involved in this process can be computationally expensive. +// +// If the Hessian matrix cannot be formed explicitly or if the computational +// cost of its factorization is prohibitive, BFGS or L-BFGS quasi-Newton method +// can be used instead. +type Newton struct { + // Linesearcher is used for selecting suitable steps along the descent + // direction d. Accepted steps should satisfy at least one of the Wolfe, + // Goldstein or Armijo conditions. + // If Linesearcher == nil, an appropriate default is chosen. + Linesearcher Linesearcher + // Increase is the factor by which a scalar tau is successively increased + // so that (H + tau*I) is positive definite. Larger values reduce the + // number of trial Hessian factorizations, but also reduce the second-order + // information in H. + // Increase must be greater than 1. If Increase is 0, it is defaulted to 5. + Increase float64 + + ls *LinesearchMethod + + hess *mat64.SymDense // Storage for a copy of the Hessian matrix. + chol mat64.Cholesky // Storage for the Cholesky factorization. + tau float64 +} + +func (n *Newton) Init(loc *Location) (Operation, error) { + if n.Increase == 0 { + n.Increase = 5 + } + if n.Increase <= 1 { + panic("optimize: Newton.Increase must be greater than 1") + } + if n.Linesearcher == nil { + n.Linesearcher = &Bisection{} + } + if n.ls == nil { + n.ls = &LinesearchMethod{} + } + n.ls.Linesearcher = n.Linesearcher + n.ls.NextDirectioner = n + + return n.ls.Init(loc) +} + +func (n *Newton) Iterate(loc *Location) (Operation, error) { + return n.ls.Iterate(loc) +} + +func (n *Newton) InitDirection(loc *Location, dir []float64) (stepSize float64) { + dim := len(loc.X) + n.hess = resizeSymDense(n.hess, dim) + n.tau = 0 + return n.NextDirection(loc, dir) +} + +func (n *Newton) NextDirection(loc *Location, dir []float64) (stepSize float64) { + // This method implements Algorithm 3.3 (Cholesky with Added Multiple of + // the Identity) from Nocedal, Wright (2006), 2nd edition. + + dim := len(loc.X) + d := mat64.NewVector(dim, dir) + grad := mat64.NewVector(dim, loc.Gradient) + n.hess.CopySym(loc.Hessian) + + // Find the smallest diagonal entry of the Hessian. + minA := n.hess.At(0, 0) + for i := 1; i < dim; i++ { + a := n.hess.At(i, i) + if a < minA { + minA = a + } + } + // If the smallest diagonal entry is positive, the Hessian may be positive + // definite, and so first attempt to apply the Cholesky factorization to + // the un-modified Hessian. If the smallest entry is negative, use the + // final tau from the last iteration if regularization was needed, + // otherwise guess an appropriate value for tau. + if minA > 0 { + n.tau = 0 + } else if n.tau == 0 { + n.tau = -minA + 0.001 + } + + for k := 0; k < maxNewtonModifications; k++ { + if n.tau != 0 { + // Add a multiple of identity to the Hessian. + for i := 0; i < dim; i++ { + n.hess.SetSym(i, i, loc.Hessian.At(i, i)+n.tau) + } + } + // Try to apply the Cholesky factorization. + pd := n.chol.Factorize(n.hess) + if pd { + // Store the solution in d's backing array, dir. + d.SolveCholeskyVec(&n.chol, grad) + d.ScaleVec(-1, d) + return 1 + } + // Modified Hessian is not PD, so increase tau. + n.tau = math.Max(n.Increase*n.tau, 0.001) + } + + // Hessian modification failed to get a PD matrix. Return the negative + // gradient as the descent direction. + d.ScaleVec(-1, grad) + return 1 +} + +func (n *Newton) Needs() struct { + Gradient bool + Hessian bool +} { + return struct { + Gradient bool + Hessian bool + }{true, true} +} diff --git a/optimize/printer.go b/optimize/printer.go new file mode 100644 index 00000000..56800f3c --- /dev/null +++ b/optimize/printer.go @@ -0,0 +1,106 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "fmt" + "io" + "math" + "os" + "time" + + "gonum.org/v1/gonum/floats" +) + +var printerHeadings = [...]string{ + "Iter", + "Runtime", + "FuncEvals", + "Func", + "GradEvals", + "|Gradient|∞", + "HessEvals", +} + +const ( + printerBaseTmpl = "%9v %16v %9v %22v" // Base template for headings and values that are always printed. + printerGradTmpl = " %9v %22v" // Appended to base template when loc.Gradient != nil. + printerHessTmpl = " %9v" // Appended to base template when loc.Hessian != nil. +) + +// Printer writes column-format output to the specified writer as the optimization +// progresses. By default, it writes to os.Stdout. +type Printer struct { + Writer io.Writer + HeadingInterval int + ValueInterval time.Duration + + lastHeading int + lastValue time.Time +} + +func NewPrinter() *Printer { + return &Printer{ + Writer: os.Stdout, + HeadingInterval: 30, + ValueInterval: 500 * time.Millisecond, + } +} + +func (p *Printer) Init() error { + p.lastHeading = p.HeadingInterval // So the headings are printed the first time. + p.lastValue = time.Now().Add(-p.ValueInterval) // So the values are printed the first time. + return nil +} + +func (p *Printer) Record(loc *Location, op Operation, stats *Stats) error { + if op != MajorIteration && op != InitIteration && op != PostIteration { + return nil + } + + // Print values always on PostIteration or when ValueInterval has elapsed. + printValues := time.Since(p.lastValue) > p.ValueInterval || op == PostIteration + if !printValues { + // Return early if not printing anything. + return nil + } + + // Print heading when HeadingInterval lines have been printed, but never on PostIteration. + printHeading := p.lastHeading >= p.HeadingInterval && op != PostIteration + if printHeading { + p.lastHeading = 1 + } else { + p.lastHeading++ + } + + if printHeading { + headings := "\n" + fmt.Sprintf(printerBaseTmpl, printerHeadings[0], printerHeadings[1], printerHeadings[2], printerHeadings[3]) + if loc.Gradient != nil { + headings += fmt.Sprintf(printerGradTmpl, printerHeadings[4], printerHeadings[5]) + } + if loc.Hessian != nil { + headings += fmt.Sprintf(printerHessTmpl, printerHeadings[6]) + } + _, err := fmt.Fprintln(p.Writer, headings) + if err != nil { + return err + } + } + + values := fmt.Sprintf(printerBaseTmpl, stats.MajorIterations, stats.Runtime, stats.FuncEvaluations, loc.F) + if loc.Gradient != nil { + values += fmt.Sprintf(printerGradTmpl, stats.GradEvaluations, floats.Norm(loc.Gradient, math.Inf(1))) + } + if loc.Hessian != nil { + values += fmt.Sprintf(printerHessTmpl, stats.HessEvaluations) + } + _, err := fmt.Fprintln(p.Writer, values) + if err != nil { + return err + } + + p.lastValue = time.Now() + return nil +} diff --git a/optimize/stepsizers.go b/optimize/stepsizers.go new file mode 100644 index 00000000..487c158c --- /dev/null +++ b/optimize/stepsizers.go @@ -0,0 +1,185 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "math" + + "gonum.org/v1/gonum/floats" +) + +const ( + initialStepFactor = 1 + + quadraticMinimumStepSize = 1e-3 + quadraticMaximumStepSize = 1 + quadraticThreshold = 1e-12 + + firstOrderMinimumStepSize = quadraticMinimumStepSize + firstOrderMaximumStepSize = quadraticMaximumStepSize +) + +// ConstantStepSize is a StepSizer that returns the same step size for +// every iteration. +type ConstantStepSize struct { + Size float64 +} + +func (c ConstantStepSize) Init(_ *Location, _ []float64) float64 { + return c.Size +} + +func (c ConstantStepSize) StepSize(_ *Location, _ []float64) float64 { + return c.Size +} + +// QuadraticStepSize estimates the initial line search step size as the minimum +// of a quadratic that interpolates f(x_{k-1}), f(x_k) and ∇f_k⋅p_k. +// This is useful for line search methods that do not produce well-scaled +// descent directions, such as gradient descent or conjugate gradient methods. +// The step size is bounded away from zero. +type QuadraticStepSize struct { + // Threshold determines that the initial step size should be estimated by + // quadratic interpolation when the relative change in the objective + // function is larger than Threshold. Otherwise the initial step size is + // set to 2*previous step size. + // If Threshold is zero, it will be set to 1e-12. + Threshold float64 + // InitialStepFactor sets the step size for the first iteration to be InitialStepFactor / |g|_∞. + // If InitialStepFactor is zero, it will be set to one. + InitialStepFactor float64 + // MinStepSize is the lower bound on the estimated step size. + // MinStepSize times GradientAbsTol should always be greater than machine epsilon. + // If MinStepSize is zero, it will be set to 1e-3. + MinStepSize float64 + // MaxStepSize is the upper bound on the estimated step size. + // If MaxStepSize is zero, it will be set to 1. + MaxStepSize float64 + + fPrev float64 + dirPrevNorm float64 + projGradPrev float64 + xPrev []float64 +} + +func (q *QuadraticStepSize) Init(loc *Location, dir []float64) (stepSize float64) { + if q.Threshold == 0 { + q.Threshold = quadraticThreshold + } + if q.InitialStepFactor == 0 { + q.InitialStepFactor = initialStepFactor + } + if q.MinStepSize == 0 { + q.MinStepSize = quadraticMinimumStepSize + } + if q.MaxStepSize == 0 { + q.MaxStepSize = quadraticMaximumStepSize + } + if q.MaxStepSize <= q.MinStepSize { + panic("optimize: MinStepSize not smaller than MaxStepSize") + } + + gNorm := floats.Norm(loc.Gradient, math.Inf(1)) + stepSize = math.Max(q.MinStepSize, math.Min(q.InitialStepFactor/gNorm, q.MaxStepSize)) + + q.fPrev = loc.F + q.dirPrevNorm = floats.Norm(dir, 2) + q.projGradPrev = floats.Dot(loc.Gradient, dir) + q.xPrev = resize(q.xPrev, len(loc.X)) + copy(q.xPrev, loc.X) + return stepSize +} + +func (q *QuadraticStepSize) StepSize(loc *Location, dir []float64) (stepSize float64) { + stepSizePrev := floats.Distance(loc.X, q.xPrev, 2) / q.dirPrevNorm + projGrad := floats.Dot(loc.Gradient, dir) + + stepSize = 2 * stepSizePrev + if !floats.EqualWithinRel(q.fPrev, loc.F, q.Threshold) { + // Two consecutive function values are not relatively equal, so + // computing the minimum of a quadratic interpolant might make sense + + df := (loc.F - q.fPrev) / stepSizePrev + quadTest := df - q.projGradPrev + if quadTest > 0 { + // There is a chance of approximating the function well by a + // quadratic only if the finite difference (f_k-f_{k-1})/stepSizePrev + // is larger than ∇f_{k-1}⋅p_{k-1} + + // Set the step size to the minimizer of the quadratic function that + // interpolates f_{k-1}, ∇f_{k-1}⋅p_{k-1} and f_k + stepSize = -q.projGradPrev * stepSizePrev / quadTest / 2 + } + } + // Bound the step size to lie in [MinStepSize, MaxStepSize] + stepSize = math.Max(q.MinStepSize, math.Min(stepSize, q.MaxStepSize)) + + q.fPrev = loc.F + q.dirPrevNorm = floats.Norm(dir, 2) + q.projGradPrev = projGrad + copy(q.xPrev, loc.X) + return stepSize +} + +// FirstOrderStepSize estimates the initial line search step size based on the +// assumption that the first-order change in the function will be the same as +// that obtained at the previous iteration. That is, the initial step size s^0_k +// is chosen so that +// s^0_k ∇f_k⋅p_k = s_{k-1} ∇f_{k-1}⋅p_{k-1} +// This is useful for line search methods that do not produce well-scaled +// descent directions, such as gradient descent or conjugate gradient methods. +type FirstOrderStepSize struct { + // InitialStepFactor sets the step size for the first iteration to be InitialStepFactor / |g|_∞. + // If InitialStepFactor is zero, it will be set to one. + InitialStepFactor float64 + // MinStepSize is the lower bound on the estimated step size. + // MinStepSize times GradientAbsTol should always be greater than machine epsilon. + // If MinStepSize is zero, it will be set to 1e-3. + MinStepSize float64 + // MaxStepSize is the upper bound on the estimated step size. + // If MaxStepSize is zero, it will be set to 1. + MaxStepSize float64 + + dirPrevNorm float64 + projGradPrev float64 + xPrev []float64 +} + +func (fo *FirstOrderStepSize) Init(loc *Location, dir []float64) (stepSize float64) { + if fo.InitialStepFactor == 0 { + fo.InitialStepFactor = initialStepFactor + } + if fo.MinStepSize == 0 { + fo.MinStepSize = firstOrderMinimumStepSize + } + if fo.MaxStepSize == 0 { + fo.MaxStepSize = firstOrderMaximumStepSize + } + if fo.MaxStepSize <= fo.MinStepSize { + panic("optimize: MinStepSize not smaller than MaxStepSize") + } + + gNorm := floats.Norm(loc.Gradient, math.Inf(1)) + stepSize = math.Max(fo.MinStepSize, math.Min(fo.InitialStepFactor/gNorm, fo.MaxStepSize)) + + fo.dirPrevNorm = floats.Norm(dir, 2) + fo.projGradPrev = floats.Dot(loc.Gradient, dir) + fo.xPrev = resize(fo.xPrev, len(loc.X)) + copy(fo.xPrev, loc.X) + return stepSize +} + +func (fo *FirstOrderStepSize) StepSize(loc *Location, dir []float64) (stepSize float64) { + stepSizePrev := floats.Distance(loc.X, fo.xPrev, 2) / fo.dirPrevNorm + projGrad := floats.Dot(loc.Gradient, dir) + + stepSize = stepSizePrev * fo.projGradPrev / projGrad + stepSize = math.Max(fo.MinStepSize, math.Min(stepSize, fo.MaxStepSize)) + + fo.dirPrevNorm = floats.Norm(dir, 2) + fo.projGradPrev = floats.Dot(loc.Gradient, dir) + copy(fo.xPrev, loc.X) + return stepSize +} diff --git a/optimize/termination.go b/optimize/termination.go new file mode 100644 index 00000000..43c2df68 --- /dev/null +++ b/optimize/termination.go @@ -0,0 +1,119 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import "errors" + +// Status represents the status of the optimization. Programs +// should not rely on the underlying numeric value of the Status being constant. +type Status int + +const ( + NotTerminated Status = iota + Success + FunctionThreshold + FunctionConvergence + GradientThreshold + StepConvergence + FunctionNegativeInfinity + Failure + IterationLimit + RuntimeLimit + FunctionEvaluationLimit + GradientEvaluationLimit + HessianEvaluationLimit +) + +func (s Status) String() string { + return statuses[s].name +} + +// Early returns true if the status indicates the optimization ended before a +// minimum was found. As an example, if the maximum iterations was reached, a +// minimum was not found, but if the gradient norm was reached then a minimum +// was found. +func (s Status) Early() bool { + return statuses[s].early +} + +// Err returns the error associated with an early ending to the minimization. If +// Early returns false, Err will return nil. +func (s Status) Err() error { + return statuses[s].err +} + +var statuses = []struct { + name string + early bool + err error +}{ + { + name: "NotTerminated", + }, + { + name: "Success", + }, + { + name: "FunctionThreshold", + }, + { + name: "FunctionConvergence", + }, + { + name: "GradientThreshold", + }, + { + name: "StepConvergence", + }, + { + name: "FunctionNegativeInfinity", + }, + { + name: "Failure", + early: true, + err: errors.New("optimize: termination ended in failure"), + }, + { + name: "IterationLimit", + early: true, + err: errors.New("optimize: maximum number of major iterations reached"), + }, + { + name: "RuntimeLimit", + early: true, + err: errors.New("optimize: maximum runtime reached"), + }, + { + name: "FunctionEvaluationLimit", + early: true, + err: errors.New("optimize: maximum number of function evaluations reached"), + }, + { + name: "GradientEvaluationLimit", + early: true, + err: errors.New("optimize: maximum number of gradient evaluations reached"), + }, + { + name: "HessianEvaluationLimit", + early: true, + err: errors.New("optimize: maximum number of Hessian evaluations reached"), + }, +} + +// NewStatus returns a unique Status variable to represent a custom status. +// NewStatus is intended to be called only during package initialization, and +// calls to NewStatus are not thread safe. +// +// NewStatus takes in three arguments, the string that should be output from +// Status.String, a boolean if the status indicates early optimization conclusion, +// and the error to return from Err (if any). +func NewStatus(name string, early bool, err error) Status { + statuses = append(statuses, struct { + name string + early bool + err error + }{name, early, err}) + return Status(len(statuses) - 1) +} diff --git a/optimize/types.go b/optimize/types.go new file mode 100644 index 00000000..4316f9cf --- /dev/null +++ b/optimize/types.go @@ -0,0 +1,262 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "errors" + "fmt" + "math" + "time" + + "gonum.org/v1/gonum/matrix/mat64" +) + +const defaultGradientAbsTol = 1e-6 + +// Operation represents the set of operations commanded by Method at each +// iteration. It is a bitmap of various Iteration and Evaluation constants. +// Individual constants must NOT be combined together by the binary OR operator +// except for the Evaluation operations. +type Operation uint64 + +// Supported Operations. +const ( + // NoOperation specifies that no evaluation or convergence check should + // take place. + NoOperation Operation = 0 + // InitIteration is sent to Recorder to indicate the initial location. + // All fields of the location to record must be valid. + // Method must not return it. + InitIteration Operation = 1 << (iota - 1) + // PostIteration is sent to Recorder to indicate the final location + // reached during an optimization run. + // All fields of the location to record must be valid. + // Method must not return it. + PostIteration + // MajorIteration indicates that the next candidate location for + // an optimum has been found and convergence should be checked. + MajorIteration + // FuncEvaluation specifies that the objective function + // should be evaluated. + FuncEvaluation + // GradEvaluation specifies that the gradient + // of the objective function should be evaluated. + GradEvaluation + // HessEvaluation specifies that the Hessian + // of the objective function should be evaluated. + HessEvaluation + + // Mask for the evaluating operations. + evalMask = FuncEvaluation | GradEvaluation | HessEvaluation +) + +func (op Operation) isEvaluation() bool { + return op&evalMask != 0 && op&^evalMask == 0 +} + +func (op Operation) String() string { + if op&evalMask != 0 { + return fmt.Sprintf("Evaluation(Func: %t, Grad: %t, Hess: %t, Extra: 0b%b)", + op&FuncEvaluation != 0, + op&GradEvaluation != 0, + op&HessEvaluation != 0, + op&^(evalMask)) + } + s, ok := operationNames[op] + if ok { + return s + } + return fmt.Sprintf("Operation(%d)", op) +} + +var operationNames = map[Operation]string{ + NoOperation: "NoOperation", + InitIteration: "InitIteration", + MajorIteration: "MajorIteration", + PostIteration: "PostIteration", +} + +// Location represents a location in the optimization procedure. +type Location struct { + X []float64 + F float64 + Gradient []float64 + Hessian *mat64.SymDense +} + +// Result represents the answer of an optimization run. It contains the optimum +// location as well as the Status at convergence and Statistics taken during the +// run. +type Result struct { + Location + Stats + Status Status +} + +// Stats contains the statistics of the run. +type Stats struct { + MajorIterations int // Total number of major iterations + FuncEvaluations int // Number of evaluations of Func + GradEvaluations int // Number of evaluations of Grad + HessEvaluations int // Number of evaluations of Hess + Runtime time.Duration // Total runtime of the optimization +} + +// complementEval returns an evaluating operation that evaluates fields of loc +// not evaluated by eval. +func complementEval(loc *Location, eval Operation) (complEval Operation) { + if eval&FuncEvaluation == 0 { + complEval = FuncEvaluation + } + if loc.Gradient != nil && eval&GradEvaluation == 0 { + complEval |= GradEvaluation + } + if loc.Hessian != nil && eval&HessEvaluation == 0 { + complEval |= HessEvaluation + } + return complEval +} + +// Problem describes the optimization problem to be solved. +type Problem struct { + // Func evaluates the objective function at the given location. Func + // must not modify x. + Func func(x []float64) float64 + + // Grad evaluates the gradient at x and stores the result in-place in grad. + // Grad must not modify x. + Grad func(grad []float64, x []float64) + + // Hess evaluates the Hessian at x and stores the result in-place in hess. + // Hess must not modify x. + Hess func(hess mat64.MutableSymmetric, x []float64) + + // Status reports the status of the objective function being optimized and any + // error. This can be used to terminate early, for example when the function is + // not able to evaluate itself. The user can use one of the pre-provided Status + // constants, or may call NewStatus to create a custom Status value. + Status func() (Status, error) +} + +// TODO(btracey): Think about making this an exported function when the +// constraint interface is designed. +func (p Problem) satisfies(method Needser) error { + if method.Needs().Gradient && p.Grad == nil { + return errors.New("optimize: problem does not provide needed Grad function") + } + if method.Needs().Hessian && p.Hess == nil { + return errors.New("optimize: problem does not provide needed Hess function") + } + return nil +} + +// Settings represents settings of the optimization run. It contains initial +// settings, convergence information, and Recorder information. In general, users +// should use DefaultSettings rather than constructing a Settings literal. +// +// If UseInitData is true, InitialValue, InitialGradient and InitialHessian +// specify function information at the initial location. +// +// If Recorder is nil, no information will be recorded. +type Settings struct { + UseInitialData bool // Use supplied information about the conditions at the initial x. + InitialValue float64 // Function value at the initial x. + InitialGradient []float64 // Gradient at the initial x. + InitialHessian *mat64.SymDense // Hessian at the initial x. + + // FunctionThreshold is the threshold for acceptably small values of the + // objective function. FunctionThreshold status is returned if + // the objective function is less than this value. + // The default value is -inf. + FunctionThreshold float64 + + // GradientThreshold determines the accuracy to which the minimum is found. + // GradientThreshold status is returned if the infinity norm of + // the gradient is less than this value. + // Has no effect if gradient information is not used. + // The default value is 1e-6. + GradientThreshold float64 + + // FunctionConverge tests that the function value decreases by a + // significant amount over the specified number of iterations. + // + // If f < f_best and + // f_best - f > FunctionConverge.Relative * maxabs(f, f_best) + FunctionConverge.Absolute + // then a significant decrease has occured, and f_best is updated. + // + // If there is no significant decrease for FunctionConverge.Iterations + // major iterations, FunctionConvergence status is returned. + // + // If this is nil or if FunctionConverge.Iterations == 0, it has no effect. + FunctionConverge *FunctionConverge + + // MajorIterations is the maximum number of iterations allowed. + // IterationLimit status is returned if the number of major iterations + // equals or exceeds this value. + // If it equals zero, this setting has no effect. + // The default value is 0. + MajorIterations int + + // Runtime is the maximum runtime allowed. RuntimeLimit status is returned + // if the duration of the run is longer than this value. Runtime is only + // checked at iterations of the Method. + // If it equals zero, this setting has no effect. + // The default value is 0. + Runtime time.Duration + + // FuncEvaluations is the maximum allowed number of function evaluations. + // FunctionEvaluationLimit status is returned if the total number of calls + // to Func equals or exceeds this number. + // If it equals zero, this setting has no effect. + // The default value is 0. + FuncEvaluations int + + // GradEvaluations is the maximum allowed number of gradient evaluations. + // GradientEvaluationLimit status is returned if the total number of calls + // to Grad equals or exceeds this number. + // If it equals zero, this setting has no effect. + // The default value is 0. + GradEvaluations int + + // HessEvaluations is the maximum allowed number of Hessian evaluations. + // HessianEvaluationLimit status is returned if the total number of calls + // to Hess equals or exceeds this number. + // If it equals zero, this setting has no effect. + // The default value is 0. + HessEvaluations int + + Recorder Recorder + + // Concurrent represents how many concurrent evaluations are possible. + Concurrent int +} + +// DefaultSettings returns a new Settings struct containing the default settings. +func DefaultSettings() *Settings { + return &Settings{ + GradientThreshold: defaultGradientAbsTol, + FunctionThreshold: math.Inf(-1), + FunctionConverge: &FunctionConverge{ + Absolute: 1e-10, + Iterations: 20, + }, + } +} + +// resize takes x and returns a slice of length dim. It returns a resliced x +// if cap(x) >= dim, and a new slice otherwise. +func resize(x []float64, dim int) []float64 { + if dim > cap(x) { + return make([]float64, dim) + } + return x[:dim] +} + +func resizeSymDense(m *mat64.SymDense, dim int) *mat64.SymDense { + if m == nil || cap(m.RawSymmetric().Data) < dim*dim { + return mat64.NewSymDense(dim, nil) + } + return mat64.NewSymDense(dim, m.RawSymmetric().Data[:dim*dim]) +} diff --git a/optimize/unconstrained_test.go b/optimize/unconstrained_test.go new file mode 100644 index 00000000..8ff16329 --- /dev/null +++ b/optimize/unconstrained_test.go @@ -0,0 +1,1305 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package optimize + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/optimize/functions" +) + +type unconstrainedTest struct { + // name is the name of the test. + name string + // p is the optimization problem to be solved. + p Problem + // x is the initial guess. + x []float64 + // gradTol is the absolute gradient tolerance for the test. If gradTol == 0, + // the default value of 1e-12 will be used. + gradTol float64 + // fAbsTol is the absolute function convergence for the test. If fAbsTol == 0, + // the default value of 1e-12 will be used. + fAbsTol float64 + // fIter is the number of iterations for function convergence. If fIter == 0, + // the default value of 20 will be used. + fIter int + // long indicates that the test takes long time to finish and will be + // excluded if testing.Short returns true. + long bool +} + +func (t unconstrainedTest) String() string { + dim := len(t.x) + if dim <= 10 { + // Print the initial X only for small-dimensional problems. + return fmt.Sprintf("F: %v\nDim: %v\nInitial X: %v\nGradientThreshold: %v", + t.name, dim, t.x, t.gradTol) + } + return fmt.Sprintf("F: %v\nDim: %v\nGradientThreshold: %v", + t.name, dim, t.gradTol) +} + +var gradFreeTests = []unconstrainedTest{ + { + name: "Beale", + p: Problem{ + Func: functions.Beale{}.Func, + }, + x: []float64{1, 1}, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + }, + { + name: "BrownAndDennis", + p: Problem{ + Func: functions.BrownAndDennis{}.Func, + }, + x: []float64{25, 5, -5, -1}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + }, + x: []float64{-10, 10}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + }, + x: []float64{-5, 4, 16, 3}, + }, +} + +var gradientDescentTests = []unconstrainedTest{ + { + name: "Beale", + p: Problem{ + Func: functions.Beale{}.Func, + Grad: functions.Beale{}.Grad, + }, + x: []float64{1, 1}, + }, + { + name: "Beale", + p: Problem{ + Func: functions.Beale{}.Func, + Grad: functions.Beale{}.Grad, + }, + x: []float64{3.00001, 0.50001}, + }, + { + name: "BiggsEXP2", + p: Problem{ + Func: functions.BiggsEXP2{}.Func, + Grad: functions.BiggsEXP2{}.Grad, + }, + x: []float64{1, 2}, + }, + { + name: "BiggsEXP2", + p: Problem{ + Func: functions.BiggsEXP2{}.Func, + Grad: functions.BiggsEXP2{}.Grad, + }, + x: []float64{1.00001, 10.00001}, + }, + { + name: "BiggsEXP3", + p: Problem{ + Func: functions.BiggsEXP3{}.Func, + Grad: functions.BiggsEXP3{}.Grad, + }, + x: []float64{1, 2, 1}, + }, + { + name: "BiggsEXP3", + p: Problem{ + Func: functions.BiggsEXP3{}.Func, + Grad: functions.BiggsEXP3{}.Grad, + }, + x: []float64{1.00001, 10.00001, 3.00001}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-1.2, 1}, + gradTol: 1e-10, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1.00001, 1.00001}, + gradTol: 1e-10, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-1.2, 1, -1.2}, + gradTol: 1e-10, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-120, 100, 50}, + long: true, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1, 1, 1}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1.00001, 1.00001, 1.00001}, + gradTol: 1e-8, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.4, 1, 0}, + gradTol: 1e-9, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.3989561, 1.0000191, 0}, + gradTol: 1e-9, + }, + { + name: "HelicalValley", + p: Problem{ + Func: functions.HelicalValley{}.Func, + Grad: functions.HelicalValley{}.Grad, + }, + x: []float64{-1, 0, 0}, + }, + { + name: "HelicalValley", + p: Problem{ + Func: functions.HelicalValley{}.Func, + Grad: functions.HelicalValley{}.Grad, + }, + x: []float64{1.00001, 0.00001, 0.00001}, + }, + { + name: "Trigonometric", + p: Problem{ + Func: functions.Trigonometric{}.Func, + Grad: functions.Trigonometric{}.Grad, + }, + x: []float64{0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}, + gradTol: 1e-7, + }, + { + name: "Trigonometric", + p: Problem{ + Func: functions.Trigonometric{}.Func, + Grad: functions.Trigonometric{}.Grad, + }, + x: []float64{0.042964, 0.043976, 0.045093, 0.046338, 0.047744, + 0.049354, 0.051237, 0.195209, 0.164977, 0.060148}, + gradTol: 1e-8, + }, + newVariablyDimensioned(2, 0), + { + name: "VariablyDimensioned", + p: Problem{ + Func: functions.VariablyDimensioned{}.Func, + Grad: functions.VariablyDimensioned{}.Grad, + }, + x: []float64{1.00001, 1.00001}, + }, + newVariablyDimensioned(10, 0), + { + name: "VariablyDimensioned", + p: Problem{ + Func: functions.VariablyDimensioned{}.Func, + Grad: functions.VariablyDimensioned{}.Grad, + }, + x: []float64{1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001}, + }, +} + +var cgTests = []unconstrainedTest{ + { + name: "BiggsEXP4", + p: Problem{ + Func: functions.BiggsEXP4{}.Func, + Grad: functions.BiggsEXP4{}.Grad, + }, + x: []float64{1, 2, 1, 1}, + }, + { + name: "BiggsEXP4", + p: Problem{ + Func: functions.BiggsEXP4{}.Func, + Grad: functions.BiggsEXP4{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001}, + }, + { + name: "BiggsEXP5", + p: Problem{ + Func: functions.BiggsEXP5{}.Func, + Grad: functions.BiggsEXP5{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1}, + gradTol: 1e-7, + }, + { + name: "BiggsEXP5", + p: Problem{ + Func: functions.BiggsEXP5{}.Func, + Grad: functions.BiggsEXP5{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001}, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + gradTol: 1e-7, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, + gradTol: 1e-8, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{0, 10, 20}, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001}, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{100.00001, 100.00001, 0.00001}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{3, -1, 0, 3}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{0.00001, 0.00001, 0.00001, 0.00001}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{3, -1, 0, 3, 3, -1, 0, 3}, + gradTol: 1e-8, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-1.2, 1, -1.2, 1}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1e4, 1e4}, + gradTol: 1e-10, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1.00001, 1.00001, 1.00001, 1.00001}, + gradTol: 1e-10, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + gradTol: 1e-9, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{0.250007, 0.250007, 0.250007, 0.250007}, + gradTol: 1e-10, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{0.1581, 0.1581, 0.1581, 0.1581, 0.1581, 0.1581, + 0.1581, 0.1581, 0.1581, 0.1581}, + gradTol: 1e-10, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.5, 0.5, 0.5, 0.5}, + gradTol: 1e-8, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.19999, 0.19131, 0.4801, 0.51884}, + gradTol: 1e-8, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.19998, 0.01035, 0.01960, 0.03208, 0.04993, 0.07651, + 0.11862, 0.19214, 0.34732, 0.36916}, + gradTol: 1e-6, + }, + { + name: "PowellBadlyScaled", + p: Problem{ + Func: functions.PowellBadlyScaled{}.Func, + Grad: functions.PowellBadlyScaled{}.Grad, + }, + x: []float64{1.09815e-05, 9.10614}, + gradTol: 1e-8, + }, + newVariablyDimensioned(100, 1e-10), + newVariablyDimensioned(1000, 1e-7), + newVariablyDimensioned(10000, 1e-4), + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{0, 0, 0, 0, 0, 0}, + gradTol: 1e-6, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{-0.01572, 1.01243, -0.23299, 1.26043, -1.51372, 0.99299}, + gradTol: 1e-6, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + gradTol: 1e-6, + long: true, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{-1.53070e-05, 0.99978, 0.01476, 0.14634, 1.00082, + -2.61773, 4.10440, -3.14361, 1.05262}, + gradTol: 1e-6, + }, + { + name: "Wood", + p: Problem{ + Func: functions.Wood{}.Func, + Grad: functions.Wood{}.Grad, + }, + x: []float64{-3, -1, -3, -1}, + gradTol: 1e-6, + }, +} + +var quasiNewtonTests = []unconstrainedTest{ + { + name: "BiggsEXP4", + p: Problem{ + Func: functions.BiggsEXP4{}.Func, + Grad: functions.BiggsEXP4{}.Grad, + }, + x: []float64{1, 2, 1, 1}, + }, + { + name: "BiggsEXP4", + p: Problem{ + Func: functions.BiggsEXP4{}.Func, + Grad: functions.BiggsEXP4{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001}, + }, + { + name: "BiggsEXP5", + p: Problem{ + Func: functions.BiggsEXP5{}.Func, + Grad: functions.BiggsEXP5{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1}, + gradTol: 1e-10, + }, + { + name: "BiggsEXP5", + p: Problem{ + Func: functions.BiggsEXP5{}.Func, + Grad: functions.BiggsEXP5{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001}, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + gradTol: 1e-8, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, + gradTol: 1e-8, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{0, 10, 20}, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001}, + }, + { + name: "Box3D", + p: Problem{ + Func: functions.Box3D{}.Func, + Grad: functions.Box3D{}.Grad, + }, + x: []float64{100.00001, 100.00001, 0.00001}, + }, + { + name: "BrownBadlyScaled", + p: Problem{ + Func: functions.BrownBadlyScaled{}.Func, + Grad: functions.BrownBadlyScaled{}.Grad, + }, + x: []float64{1, 1}, + }, + { + name: "BrownBadlyScaled", + p: Problem{ + Func: functions.BrownBadlyScaled{}.Func, + Grad: functions.BrownBadlyScaled{}.Grad, + }, + x: []float64{1.000001e6, 2.01e-6}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{3, -1, 0, 3}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{0.00001, 0.00001, 0.00001, 0.00001}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{3, -1, 0, 3, 3, -1, 0, 3}, + }, + { + name: "ExtendedPowellSingular", + p: Problem{ + Func: functions.ExtendedPowellSingular{}.Func, + Grad: functions.ExtendedPowellSingular{}.Grad, + }, + x: []float64{0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001, 0.00001}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{-1.2, 1, -1.2, 1}, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1.00001, 1.00001, 1.00001, 1.00001}, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.4, 1, 0}, + gradTol: 1e-11, + }, + { + name: "GulfResearchAndDevelopment", + p: Problem{ + Func: functions.GulfResearchAndDevelopment{}.Func, + Grad: functions.GulfResearchAndDevelopment{}.Grad, + }, + x: []float64{5, 2.5, 0.15}, + }, + { + name: "GulfResearchAndDevelopment", + p: Problem{ + Func: functions.GulfResearchAndDevelopment{}.Func, + Grad: functions.GulfResearchAndDevelopment{}.Grad, + }, + x: []float64{50.00001, 25.00001, 1.50001}, + }, + { + name: "GulfResearchAndDevelopment", + p: Problem{ + Func: functions.GulfResearchAndDevelopment{}.Func, + Grad: functions.GulfResearchAndDevelopment{}.Grad, + }, + x: []float64{99.89529, 60.61453, 9.16124}, + }, + { + name: "GulfResearchAndDevelopment", + p: Problem{ + Func: functions.GulfResearchAndDevelopment{}.Func, + Grad: functions.GulfResearchAndDevelopment{}.Grad, + }, + x: []float64{201.66258, 60.61633, 10.22489}, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{0.250007, 0.250007, 0.250007, 0.250007}, + gradTol: 1e-9, + }, + { + name: "PenaltyI", + p: Problem{ + Func: functions.PenaltyI{}.Func, + Grad: functions.PenaltyI{}.Grad, + }, + x: []float64{0.1581, 0.1581, 0.1581, 0.1581, 0.1581, 0.1581, + 0.1581, 0.1581, 0.1581, 0.1581}, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.5, 0.5, 0.5, 0.5}, + gradTol: 1e-10, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.19999, 0.19131, 0.4801, 0.51884}, + gradTol: 1e-10, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}, + gradTol: 1e-9, + }, + { + name: "PenaltyII", + p: Problem{ + Func: functions.PenaltyII{}.Func, + Grad: functions.PenaltyII{}.Grad, + }, + x: []float64{0.19998, 0.01035, 0.01960, 0.03208, 0.04993, 0.07651, + 0.11862, 0.19214, 0.34732, 0.36916}, + gradTol: 1e-9, + }, + { + name: "PowellBadlyScaled", + p: Problem{ + Func: functions.PowellBadlyScaled{}.Func, + Grad: functions.PowellBadlyScaled{}.Grad, + }, + x: []float64{0, 1}, + }, + { + name: "PowellBadlyScaled", + p: Problem{ + Func: functions.PowellBadlyScaled{}.Func, + Grad: functions.PowellBadlyScaled{}.Grad, + }, + x: []float64{1.09815e-05, 9.10614}, + gradTol: 1e-10, + }, + newVariablyDimensioned(100, 1e-10), + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{0, 0, 0, 0, 0, 0}, + gradTol: 1e-7, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{-0.01572, 1.01243, -0.23299, 1.26043, -1.51372, 0.99299}, + gradTol: 1e-7, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0}, + gradTol: 1e-8, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + }, + x: []float64{-1.53070e-05, 0.99978, 0.01476, 0.14634, 1.00082, + -2.61773, 4.10440, -3.14361, 1.05262}, + gradTol: 1e-8, + }, +} + +var bfgsTests = []unconstrainedTest{ + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + gradTol: 1e-10, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, + gradTol: 1e-10, + }, + { + name: "BrownAndDennis", + p: Problem{ + Func: functions.BrownAndDennis{}.Func, + Grad: functions.BrownAndDennis{}.Grad, + }, + x: []float64{25, 5, -5, -1}, + gradTol: 1e-5, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1e5, 1e5}, + gradTol: 1e-10, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.398, 1, 0}, + gradTol: 1e-11, + }, + { + name: "Wood", + p: Problem{ + Func: functions.Wood{}.Func, + Grad: functions.Wood{}.Grad, + }, + x: []float64{-3, -1, -3, -1}, + }, +} + +var lbfgsTests = []unconstrainedTest{ + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1, 2, 1, 1, 1, 1}, + gradTol: 1e-8, + }, + { + name: "BiggsEXP6", + p: Problem{ + Func: functions.BiggsEXP6{}.Func, + Grad: functions.BiggsEXP6{}.Grad, + }, + x: []float64{1.00001, 10.00001, 1.00001, 5.00001, 4.00001, 3.00001}, + gradTol: 1e-8, + }, + { + name: "ExtendedRosenbrock", + p: Problem{ + Func: functions.ExtendedRosenbrock{}.Func, + Grad: functions.ExtendedRosenbrock{}.Grad, + }, + x: []float64{1e7, 1e6}, + gradTol: 1e-10, + }, + { + name: "Gaussian", + p: Problem{ + Func: functions.Gaussian{}.Func, + Grad: functions.Gaussian{}.Grad, + }, + x: []float64{0.398, 1, 0}, + gradTol: 1e-10, + }, + newVariablyDimensioned(1000, 1e-8), + newVariablyDimensioned(10000, 1e-5), +} + +var newtonTests = []unconstrainedTest{ + { + name: "Beale", + p: Problem{ + Func: functions.Beale{}.Func, + Grad: functions.Beale{}.Grad, + Hess: functions.Beale{}.Hess, + }, + x: []float64{1, 1}, + }, + { + name: "BrownAndDennis", + p: Problem{ + Func: functions.BrownAndDennis{}.Func, + Grad: functions.BrownAndDennis{}.Grad, + Hess: functions.BrownAndDennis{}.Hess, + }, + x: []float64{25, 5, -5, -1}, + gradTol: 1e-10, + }, + { + name: "BrownBadlyScaled", + p: Problem{ + Func: functions.BrownBadlyScaled{}.Func, + Grad: functions.BrownBadlyScaled{}.Grad, + Hess: functions.BrownBadlyScaled{}.Hess, + }, + x: []float64{1, 1}, + }, + { + name: "PowellBadlyScaled", + p: Problem{ + Func: functions.PowellBadlyScaled{}.Func, + Grad: functions.PowellBadlyScaled{}.Grad, + Hess: functions.PowellBadlyScaled{}.Hess, + }, + x: []float64{0, 1}, + gradTol: 1e-10, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + Hess: functions.Watson{}.Hess, + }, + x: []float64{0, 0, 0, 0, 0, 0}, + }, + { + name: "Watson", + p: Problem{ + Func: functions.Watson{}.Func, + Grad: functions.Watson{}.Grad, + Hess: functions.Watson{}.Hess, + }, + x: []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + name: "Wood", + p: Problem{ + Func: functions.Wood{}.Func, + Grad: functions.Wood{}.Grad, + Hess: functions.Wood{}.Hess, + }, + x: []float64{-3, -1, -3, -1}, + }, +} + +func newVariablyDimensioned(dim int, gradTol float64) unconstrainedTest { + x := make([]float64, dim) + for i := range x { + x[i] = float64(dim-i-1) / float64(dim) + } + return unconstrainedTest{ + name: "VariablyDimensioned", + p: Problem{ + Func: functions.VariablyDimensioned{}.Func, + Grad: functions.VariablyDimensioned{}.Grad, + }, + x: x, + gradTol: gradTol, + } +} + +func TestLocal(t *testing.T) { + var tests []unconstrainedTest + // Mix of functions with and without Grad method. + tests = append(tests, gradFreeTests...) + tests = append(tests, gradientDescentTests...) + testLocal(t, gradientDescentTests, nil) +} + +func TestNelderMead(t *testing.T) { + var tests []unconstrainedTest + // Mix of functions with and without Grad method. + tests = append(tests, gradFreeTests...) + tests = append(tests, gradientDescentTests...) + testLocal(t, tests, &NelderMead{}) +} + +func TestGradientDescent(t *testing.T) { + testLocal(t, gradientDescentTests, &GradientDescent{}) +} + +func TestGradientDescentBacktracking(t *testing.T) { + testLocal(t, gradientDescentTests, &GradientDescent{ + Linesearcher: &Backtracking{ + DecreaseFactor: 0.1, + }, + }) +} + +func TestGradientDescentBisection(t *testing.T) { + testLocal(t, gradientDescentTests, &GradientDescent{ + Linesearcher: &Bisection{}, + }) +} + +func TestCG(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{}) +} + +func TestFletcherReevesQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &FletcherReeves{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestFletcherReevesFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &FletcherReeves{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestHestenesStiefelQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &HestenesStiefel{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestHestenesStiefelFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &HestenesStiefel{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestPolakRibiereQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &PolakRibierePolyak{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestPolakRibiereFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &PolakRibierePolyak{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestDaiYuanQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &DaiYuan{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestDaiYuanFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &DaiYuan{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestHagerZhangQuadStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &HagerZhang{}, + InitialStep: &QuadraticStepSize{}, + }) +} + +func TestHagerZhangFirstOrderStep(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, cgTests...) + testLocal(t, tests, &CG{ + Variant: &HagerZhang{}, + InitialStep: &FirstOrderStepSize{}, + }) +} + +func TestBFGS(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, quasiNewtonTests...) + tests = append(tests, bfgsTests...) + testLocal(t, tests, &BFGS{}) +} + +func TestLBFGS(t *testing.T) { + var tests []unconstrainedTest + tests = append(tests, gradientDescentTests...) + tests = append(tests, quasiNewtonTests...) + tests = append(tests, lbfgsTests...) + testLocal(t, tests, &LBFGS{}) +} + +func TestNewton(t *testing.T) { + testLocal(t, newtonTests, &Newton{}) +} + +func testLocal(t *testing.T, tests []unconstrainedTest, method Method) { + for _, test := range tests { + if test.long && testing.Short() { + continue + } + + settings := DefaultSettings() + settings.Recorder = nil + if method != nil && method.Needs().Gradient { + // Turn off function convergence checks for gradient-based methods. + settings.FunctionConverge = nil + } else { + if test.fIter == 0 { + test.fIter = 20 + } + settings.FunctionConverge.Iterations = test.fIter + if test.fAbsTol == 0 { + test.fAbsTol = 1e-12 + } + settings.FunctionConverge.Absolute = test.fAbsTol + } + if test.gradTol == 0 { + test.gradTol = 1e-12 + } + settings.GradientThreshold = test.gradTol + + result, err := Local(test.p, test.x, settings, method) + if err != nil { + t.Errorf("error finding minimum (%v) for:\n%v", err, test) + continue + } + if result == nil { + t.Errorf("nil result without error for:\n%v", test) + continue + } + + // Check that the function value at the found optimum location is + // equal to result.F. + optF := test.p.Func(result.X) + if optF != result.F { + t.Errorf("Function value at the optimum location %v not equal to the returned value %v for:\n%v", + optF, result.F, test) + } + if result.Gradient != nil { + // Evaluate the norm of the gradient at the found optimum location. + g := make([]float64, len(test.x)) + test.p.Grad(g, result.X) + + if !floats.Equal(result.Gradient, g) { + t.Errorf("Gradient at the optimum location not equal to the returned value for:\n%v", test) + } + + optNorm := floats.Norm(g, math.Inf(1)) + // Check that the norm of the gradient at the found optimum location is + // smaller than the tolerance. + if optNorm >= settings.GradientThreshold { + t.Errorf("Norm of the gradient at the optimum location %v not smaller than tolerance %v for:\n%v", + optNorm, settings.GradientThreshold, test) + } + } + + if method == nil { + // The tests below make sense only if the method used is known. + continue + } + + if !method.Needs().Gradient && !method.Needs().Hessian { + // Gradient-free tests can correctly terminate only with + // FunctionConvergence status. + if result.Status != FunctionConvergence { + t.Errorf("Status not %v, %v instead", FunctionConvergence, result.Status) + } + } + + // We are going to restart the solution using known initial data, so + // evaluate them. + settings.UseInitialData = true + settings.InitialValue = test.p.Func(test.x) + if method.Needs().Gradient { + settings.InitialGradient = resize(settings.InitialGradient, len(test.x)) + test.p.Grad(settings.InitialGradient, test.x) + } + if method.Needs().Hessian { + settings.InitialHessian = mat64.NewSymDense(len(test.x), nil) + test.p.Hess(settings.InitialHessian, test.x) + } + + // Rerun the test again to make sure that it gets the same answer with + // the same starting condition. Moreover, we are using the initial data. + result2, err2 := Local(test.p, test.x, settings, method) + if err2 != nil { + t.Errorf("error finding minimum second time (%v) for:\n%v", err2, test) + continue + } + if result2 == nil { + t.Errorf("second time nil result without error for:\n%v", test) + continue + } + + // At the moment all the optimizers are deterministic, so check that we + // get _exactly_ the same answer second time as well. + if result.F != result2.F || !floats.Equal(result.X, result2.X) { + t.Errorf("Different minimum second time for:\n%v", test) + } + + // Check that providing initial data reduces the number of evaluations exactly by one. + if result.FuncEvaluations != result2.FuncEvaluations+1 { + t.Errorf("Providing initial data does not reduce the number of Func calls for:\n%v", test) + continue + } + if method.Needs().Gradient { + if result.GradEvaluations != result2.GradEvaluations+1 { + t.Errorf("Providing initial data does not reduce the number of Grad calls for:\n%v", test) + continue + } + } + if method.Needs().Hessian { + if result.HessEvaluations != result2.HessEvaluations+1 { + t.Errorf("Providing initial data does not reduce the number of Hess calls for:\n%v", test) + continue + } + } + } +} + +func TestIssue76(t *testing.T) { + p := Problem{ + Func: functions.BrownAndDennis{}.Func, + Grad: functions.BrownAndDennis{}.Grad, + } + // Location very close to the minimum. + x := []float64{-11.594439904886773, 13.203630051265385, -0.40343948776868443, 0.2367787746745986} + s := &Settings{ + FunctionThreshold: math.Inf(-1), + GradientThreshold: 1e-14, + MajorIterations: 1000000, + } + m := &GradientDescent{ + Linesearcher: &Backtracking{}, + } + // We are not interested in the error, only in the returned status. + r, _ := Local(p, x, s, m) + // With the above stringent tolerance, the optimizer will never + // successfully reach the minimum. Check if it terminated in a finite + // number of steps. + if r.Status == IterationLimit { + t.Error("Issue https://github.com/gonum/optimize/issues/76 not fixed") + } +} diff --git a/stat/README.md b/stat/README.md new file mode 100644 index 00000000..4efcc125 --- /dev/null +++ b/stat/README.md @@ -0,0 +1,13 @@ +# Gonum Stat [![Build Status](https://travis-ci.org/gonum/stat.svg?branch=master)](https://travis-ci.org/gonum/stat) [![Coverage Status](https://coveralls.io/repos/gonum/stat/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/stat?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/stat?status.svg)](https://godoc.org/github.com/gonum/stat) + +This is a statistics package for the Go language. + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/stat/boston_data_test.go b/stat/boston_data_test.go new file mode 100644 index 00000000..092bacae --- /dev/null +++ b/stat/boston_data_test.go @@ -0,0 +1,531 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat_test + +import "gonum.org/v1/gonum/matrix/mat64" + +// Boston Housing Data of Harrison and Rubinfeld (1978) +// http://dx.doi.org/10.1016/0095-0696(78)90006-2 +// http://lib.stat.cmu.edu/datasets/boston +// Columns are; +// per capita crime rate by town, +// proportion of non-retail business acres per town, +// nitric oxide concentration (parts per 10 million), +// weighted distances to Boston employment centers, +// index of accessibility to radial highways, +// pupil-teacher ratio by town, +// proportion of blacks by town, +// average number of rooms per dwelling, +// proportion of owner-occupied units built prior to 1940, +// full-value property-tax rate per $10000, +// median value of owner-occupied homes in $1000s. +var bostonData = mat64.NewDense(506, 11, []float64{ + 0.00632, 2.31000, 0.53800, 4.09000, 1.00000, 15.30000, 396.90000, 6.57500, 65.20000, 296.00000, 24.00000, + 0.02731, 7.07000, 0.46900, 4.96710, 2.00000, 17.80000, 396.90000, 6.42100, 78.90000, 242.00000, 21.60000, + 0.02729, 7.07000, 0.46900, 4.96710, 2.00000, 17.80000, 392.83000, 7.18500, 61.10000, 242.00000, 34.70000, + 0.03237, 2.18000, 0.45800, 6.06220, 3.00000, 18.70000, 394.63000, 6.99800, 45.80000, 222.00000, 33.40000, + 0.06905, 2.18000, 0.45800, 6.06220, 3.00000, 18.70000, 396.90000, 7.14700, 54.20000, 222.00000, 36.20000, + 0.02985, 2.18000, 0.45800, 6.06220, 3.00000, 18.70000, 394.12000, 6.43000, 58.70000, 222.00000, 28.70000, + 0.08829, 7.87000, 0.52400, 5.56050, 5.00000, 15.20000, 395.60000, 6.01200, 66.60000, 311.00000, 22.90000, + 0.14455, 7.87000, 0.52400, 5.95050, 5.00000, 15.20000, 396.90000, 6.17200, 96.10000, 311.00000, 27.10000, + 0.21124, 7.87000, 0.52400, 6.08210, 5.00000, 15.20000, 386.63000, 5.63100, 100.00000, 311.00000, 16.50000, + 0.17004, 7.87000, 0.52400, 6.59210, 5.00000, 15.20000, 386.71000, 6.00400, 85.90000, 311.00000, 18.90000, + 0.22489, 7.87000, 0.52400, 6.34670, 5.00000, 15.20000, 392.52000, 6.37700, 94.30000, 311.00000, 15.00000, + 0.11747, 7.87000, 0.52400, 6.22670, 5.00000, 15.20000, 396.90000, 6.00900, 82.90000, 311.00000, 18.90000, + 0.09378, 7.87000, 0.52400, 5.45090, 5.00000, 15.20000, 390.50000, 5.88900, 39.00000, 311.00000, 21.70000, + 0.62976, 8.14000, 0.53800, 4.70750, 4.00000, 21.00000, 396.90000, 5.94900, 61.80000, 307.00000, 20.40000, + 0.63796, 8.14000, 0.53800, 4.46190, 4.00000, 21.00000, 380.02000, 6.09600, 84.50000, 307.00000, 18.20000, + 0.62739, 8.14000, 0.53800, 4.49860, 4.00000, 21.00000, 395.62000, 5.83400, 56.50000, 307.00000, 19.90000, + 1.05393, 8.14000, 0.53800, 4.49860, 4.00000, 21.00000, 386.85000, 5.93500, 29.30000, 307.00000, 23.10000, + 0.78420, 8.14000, 0.53800, 4.25790, 4.00000, 21.00000, 386.75000, 5.99000, 81.70000, 307.00000, 17.50000, + 0.80271, 8.14000, 0.53800, 3.79650, 4.00000, 21.00000, 288.99000, 5.45600, 36.60000, 307.00000, 20.20000, + 0.72580, 8.14000, 0.53800, 3.79650, 4.00000, 21.00000, 390.95000, 5.72700, 69.50000, 307.00000, 18.20000, + 1.25179, 8.14000, 0.53800, 3.79790, 4.00000, 21.00000, 376.57000, 5.57000, 98.10000, 307.00000, 13.60000, + 0.85204, 8.14000, 0.53800, 4.01230, 4.00000, 21.00000, 392.53000, 5.96500, 89.20000, 307.00000, 19.60000, + 1.23247, 8.14000, 0.53800, 3.97690, 4.00000, 21.00000, 396.90000, 6.14200, 91.70000, 307.00000, 15.20000, + 0.98843, 8.14000, 0.53800, 4.09520, 4.00000, 21.00000, 394.54000, 5.81300, 100.00000, 307.00000, 14.50000, + 0.75026, 8.14000, 0.53800, 4.39960, 4.00000, 21.00000, 394.33000, 5.92400, 94.10000, 307.00000, 15.60000, + 0.84054, 8.14000, 0.53800, 4.45460, 4.00000, 21.00000, 303.42000, 5.59900, 85.70000, 307.00000, 13.90000, + 0.67191, 8.14000, 0.53800, 4.68200, 4.00000, 21.00000, 376.88000, 5.81300, 90.30000, 307.00000, 16.60000, + 0.95577, 8.14000, 0.53800, 4.45340, 4.00000, 21.00000, 306.38000, 6.04700, 88.80000, 307.00000, 14.80000, + 0.77299, 8.14000, 0.53800, 4.45470, 4.00000, 21.00000, 387.94000, 6.49500, 94.40000, 307.00000, 18.40000, + 1.00245, 8.14000, 0.53800, 4.23900, 4.00000, 21.00000, 380.23000, 6.67400, 87.30000, 307.00000, 21.00000, + 1.13081, 8.14000, 0.53800, 4.23300, 4.00000, 21.00000, 360.17000, 5.71300, 94.10000, 307.00000, 12.70000, + 1.35472, 8.14000, 0.53800, 4.17500, 4.00000, 21.00000, 376.73000, 6.07200, 100.00000, 307.00000, 14.50000, + 1.38799, 8.14000, 0.53800, 3.99000, 4.00000, 21.00000, 232.60000, 5.95000, 82.00000, 307.00000, 13.20000, + 1.15172, 8.14000, 0.53800, 3.78720, 4.00000, 21.00000, 358.77000, 5.70100, 95.00000, 307.00000, 13.10000, + 1.61282, 8.14000, 0.53800, 3.75980, 4.00000, 21.00000, 248.31000, 6.09600, 96.90000, 307.00000, 13.50000, + 0.06417, 5.96000, 0.49900, 3.36030, 5.00000, 19.20000, 396.90000, 5.93300, 68.20000, 279.00000, 18.90000, + 0.09744, 5.96000, 0.49900, 3.37790, 5.00000, 19.20000, 377.56000, 5.84100, 61.40000, 279.00000, 20.00000, + 0.08014, 5.96000, 0.49900, 3.93420, 5.00000, 19.20000, 396.90000, 5.85000, 41.50000, 279.00000, 21.00000, + 0.17505, 5.96000, 0.49900, 3.84730, 5.00000, 19.20000, 393.43000, 5.96600, 30.20000, 279.00000, 24.70000, + 0.02763, 2.95000, 0.42800, 5.40110, 3.00000, 18.30000, 395.63000, 6.59500, 21.80000, 252.00000, 30.80000, + 0.03359, 2.95000, 0.42800, 5.40110, 3.00000, 18.30000, 395.62000, 7.02400, 15.80000, 252.00000, 34.90000, + 0.12744, 6.91000, 0.44800, 5.72090, 3.00000, 17.90000, 385.41000, 6.77000, 2.90000, 233.00000, 26.60000, + 0.14150, 6.91000, 0.44800, 5.72090, 3.00000, 17.90000, 383.37000, 6.16900, 6.60000, 233.00000, 25.30000, + 0.15936, 6.91000, 0.44800, 5.72090, 3.00000, 17.90000, 394.46000, 6.21100, 6.50000, 233.00000, 24.70000, + 0.12269, 6.91000, 0.44800, 5.72090, 3.00000, 17.90000, 389.39000, 6.06900, 40.00000, 233.00000, 21.20000, + 0.17142, 6.91000, 0.44800, 5.10040, 3.00000, 17.90000, 396.90000, 5.68200, 33.80000, 233.00000, 19.30000, + 0.18836, 6.91000, 0.44800, 5.10040, 3.00000, 17.90000, 396.90000, 5.78600, 33.30000, 233.00000, 20.00000, + 0.22927, 6.91000, 0.44800, 5.68940, 3.00000, 17.90000, 392.74000, 6.03000, 85.50000, 233.00000, 16.60000, + 0.25387, 6.91000, 0.44800, 5.87000, 3.00000, 17.90000, 396.90000, 5.39900, 95.30000, 233.00000, 14.40000, + 0.21977, 6.91000, 0.44800, 6.08770, 3.00000, 17.90000, 396.90000, 5.60200, 62.00000, 233.00000, 19.40000, + 0.08873, 5.64000, 0.43900, 6.81470, 4.00000, 16.80000, 395.56000, 5.96300, 45.70000, 243.00000, 19.70000, + 0.04337, 5.64000, 0.43900, 6.81470, 4.00000, 16.80000, 393.97000, 6.11500, 63.00000, 243.00000, 20.50000, + 0.05360, 5.64000, 0.43900, 6.81470, 4.00000, 16.80000, 396.90000, 6.51100, 21.10000, 243.00000, 25.00000, + 0.04981, 5.64000, 0.43900, 6.81470, 4.00000, 16.80000, 396.90000, 5.99800, 21.40000, 243.00000, 23.40000, + 0.01360, 4.00000, 0.41000, 7.31970, 3.00000, 21.10000, 396.90000, 5.88800, 47.60000, 469.00000, 18.90000, + 0.01311, 1.22000, 0.40300, 8.69660, 5.00000, 17.90000, 395.93000, 7.24900, 21.90000, 226.00000, 35.40000, + 0.02055, 0.74000, 0.41000, 9.18760, 2.00000, 17.30000, 396.90000, 6.38300, 35.70000, 313.00000, 24.70000, + 0.01432, 1.32000, 0.41100, 8.32480, 5.00000, 15.10000, 392.90000, 6.81600, 40.50000, 256.00000, 31.60000, + 0.15445, 5.13000, 0.45300, 7.81480, 8.00000, 19.70000, 390.68000, 6.14500, 29.20000, 284.00000, 23.30000, + 0.10328, 5.13000, 0.45300, 6.93200, 8.00000, 19.70000, 396.90000, 5.92700, 47.20000, 284.00000, 19.60000, + 0.14932, 5.13000, 0.45300, 7.22540, 8.00000, 19.70000, 395.11000, 5.74100, 66.20000, 284.00000, 18.70000, + 0.17171, 5.13000, 0.45300, 6.81850, 8.00000, 19.70000, 378.08000, 5.96600, 93.40000, 284.00000, 16.00000, + 0.11027, 5.13000, 0.45300, 7.22550, 8.00000, 19.70000, 396.90000, 6.45600, 67.80000, 284.00000, 22.20000, + 0.12650, 5.13000, 0.45300, 7.98090, 8.00000, 19.70000, 395.58000, 6.76200, 43.40000, 284.00000, 25.00000, + 0.01951, 1.38000, 0.41610, 9.22290, 3.00000, 18.60000, 393.24000, 7.10400, 59.50000, 216.00000, 33.00000, + 0.03584, 3.37000, 0.39800, 6.61150, 4.00000, 16.10000, 396.90000, 6.29000, 17.80000, 337.00000, 23.50000, + 0.04379, 3.37000, 0.39800, 6.61150, 4.00000, 16.10000, 396.90000, 5.78700, 31.10000, 337.00000, 19.40000, + 0.05789, 6.07000, 0.40900, 6.49800, 4.00000, 18.90000, 396.21000, 5.87800, 21.40000, 345.00000, 22.00000, + 0.13554, 6.07000, 0.40900, 6.49800, 4.00000, 18.90000, 396.90000, 5.59400, 36.80000, 345.00000, 17.40000, + 0.12816, 6.07000, 0.40900, 6.49800, 4.00000, 18.90000, 396.90000, 5.88500, 33.00000, 345.00000, 20.90000, + 0.08826, 10.81000, 0.41300, 5.28730, 4.00000, 19.20000, 383.73000, 6.41700, 6.60000, 305.00000, 24.20000, + 0.15876, 10.81000, 0.41300, 5.28730, 4.00000, 19.20000, 376.94000, 5.96100, 17.50000, 305.00000, 21.70000, + 0.09164, 10.81000, 0.41300, 5.28730, 4.00000, 19.20000, 390.91000, 6.06500, 7.80000, 305.00000, 22.80000, + 0.19539, 10.81000, 0.41300, 5.28730, 4.00000, 19.20000, 377.17000, 6.24500, 6.20000, 305.00000, 23.40000, + 0.07896, 12.83000, 0.43700, 4.25150, 5.00000, 18.70000, 394.92000, 6.27300, 6.00000, 398.00000, 24.10000, + 0.09512, 12.83000, 0.43700, 4.50260, 5.00000, 18.70000, 383.23000, 6.28600, 45.00000, 398.00000, 21.40000, + 0.10153, 12.83000, 0.43700, 4.05220, 5.00000, 18.70000, 373.66000, 6.27900, 74.50000, 398.00000, 20.00000, + 0.08707, 12.83000, 0.43700, 4.09050, 5.00000, 18.70000, 386.96000, 6.14000, 45.80000, 398.00000, 20.80000, + 0.05646, 12.83000, 0.43700, 5.01410, 5.00000, 18.70000, 386.40000, 6.23200, 53.70000, 398.00000, 21.20000, + 0.08387, 12.83000, 0.43700, 4.50260, 5.00000, 18.70000, 396.06000, 5.87400, 36.60000, 398.00000, 20.30000, + 0.04113, 4.86000, 0.42600, 5.40070, 4.00000, 19.00000, 396.90000, 6.72700, 33.50000, 281.00000, 28.00000, + 0.04462, 4.86000, 0.42600, 5.40070, 4.00000, 19.00000, 395.63000, 6.61900, 70.40000, 281.00000, 23.90000, + 0.03659, 4.86000, 0.42600, 5.40070, 4.00000, 19.00000, 396.90000, 6.30200, 32.20000, 281.00000, 24.80000, + 0.03551, 4.86000, 0.42600, 5.40070, 4.00000, 19.00000, 390.64000, 6.16700, 46.70000, 281.00000, 22.90000, + 0.05059, 4.49000, 0.44900, 4.77940, 3.00000, 18.50000, 396.90000, 6.38900, 48.00000, 247.00000, 23.90000, + 0.05735, 4.49000, 0.44900, 4.43770, 3.00000, 18.50000, 392.30000, 6.63000, 56.10000, 247.00000, 26.60000, + 0.05188, 4.49000, 0.44900, 4.42720, 3.00000, 18.50000, 395.99000, 6.01500, 45.10000, 247.00000, 22.50000, + 0.07151, 4.49000, 0.44900, 3.74760, 3.00000, 18.50000, 395.15000, 6.12100, 56.80000, 247.00000, 22.20000, + 0.05660, 3.41000, 0.48900, 3.42170, 2.00000, 17.80000, 396.90000, 7.00700, 86.30000, 270.00000, 23.60000, + 0.05302, 3.41000, 0.48900, 3.41450, 2.00000, 17.80000, 396.06000, 7.07900, 63.10000, 270.00000, 28.70000, + 0.04684, 3.41000, 0.48900, 3.09230, 2.00000, 17.80000, 392.18000, 6.41700, 66.10000, 270.00000, 22.60000, + 0.03932, 3.41000, 0.48900, 3.09210, 2.00000, 17.80000, 393.55000, 6.40500, 73.90000, 270.00000, 22.00000, + 0.04203, 15.04000, 0.46400, 3.66590, 4.00000, 18.20000, 395.01000, 6.44200, 53.60000, 270.00000, 22.90000, + 0.02875, 15.04000, 0.46400, 3.66590, 4.00000, 18.20000, 396.33000, 6.21100, 28.90000, 270.00000, 25.00000, + 0.04294, 15.04000, 0.46400, 3.61500, 4.00000, 18.20000, 396.90000, 6.24900, 77.30000, 270.00000, 20.60000, + 0.12204, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 357.98000, 6.62500, 57.80000, 276.00000, 28.40000, + 0.11504, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 391.83000, 6.16300, 69.60000, 276.00000, 21.40000, + 0.12083, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 396.90000, 8.06900, 76.00000, 276.00000, 38.70000, + 0.08187, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 393.53000, 7.82000, 36.90000, 276.00000, 43.80000, + 0.06860, 2.89000, 0.44500, 3.49520, 2.00000, 18.00000, 396.90000, 7.41600, 62.50000, 276.00000, 33.20000, + 0.14866, 8.56000, 0.52000, 2.77780, 5.00000, 20.90000, 394.76000, 6.72700, 79.90000, 384.00000, 27.50000, + 0.11432, 8.56000, 0.52000, 2.85610, 5.00000, 20.90000, 395.58000, 6.78100, 71.30000, 384.00000, 26.50000, + 0.22876, 8.56000, 0.52000, 2.71470, 5.00000, 20.90000, 70.80000, 6.40500, 85.40000, 384.00000, 18.60000, + 0.21161, 8.56000, 0.52000, 2.71470, 5.00000, 20.90000, 394.47000, 6.13700, 87.40000, 384.00000, 19.30000, + 0.13960, 8.56000, 0.52000, 2.42100, 5.00000, 20.90000, 392.69000, 6.16700, 90.00000, 384.00000, 20.10000, + 0.13262, 8.56000, 0.52000, 2.10690, 5.00000, 20.90000, 394.05000, 5.85100, 96.70000, 384.00000, 19.50000, + 0.17120, 8.56000, 0.52000, 2.21100, 5.00000, 20.90000, 395.67000, 5.83600, 91.90000, 384.00000, 19.50000, + 0.13117, 8.56000, 0.52000, 2.12240, 5.00000, 20.90000, 387.69000, 6.12700, 85.20000, 384.00000, 20.40000, + 0.12802, 8.56000, 0.52000, 2.43290, 5.00000, 20.90000, 395.24000, 6.47400, 97.10000, 384.00000, 19.80000, + 0.26363, 8.56000, 0.52000, 2.54510, 5.00000, 20.90000, 391.23000, 6.22900, 91.20000, 384.00000, 19.40000, + 0.10793, 8.56000, 0.52000, 2.77780, 5.00000, 20.90000, 393.49000, 6.19500, 54.40000, 384.00000, 21.70000, + 0.10084, 10.01000, 0.54700, 2.67750, 6.00000, 17.80000, 395.59000, 6.71500, 81.60000, 432.00000, 22.80000, + 0.12329, 10.01000, 0.54700, 2.35340, 6.00000, 17.80000, 394.95000, 5.91300, 92.90000, 432.00000, 18.80000, + 0.22212, 10.01000, 0.54700, 2.54800, 6.00000, 17.80000, 396.90000, 6.09200, 95.40000, 432.00000, 18.70000, + 0.14231, 10.01000, 0.54700, 2.25650, 6.00000, 17.80000, 388.74000, 6.25400, 84.20000, 432.00000, 18.50000, + 0.17134, 10.01000, 0.54700, 2.46310, 6.00000, 17.80000, 344.91000, 5.92800, 88.20000, 432.00000, 18.30000, + 0.13158, 10.01000, 0.54700, 2.73010, 6.00000, 17.80000, 393.30000, 6.17600, 72.50000, 432.00000, 21.20000, + 0.15098, 10.01000, 0.54700, 2.74740, 6.00000, 17.80000, 394.51000, 6.02100, 82.60000, 432.00000, 19.20000, + 0.13058, 10.01000, 0.54700, 2.47750, 6.00000, 17.80000, 338.63000, 5.87200, 73.10000, 432.00000, 20.40000, + 0.14476, 10.01000, 0.54700, 2.75920, 6.00000, 17.80000, 391.50000, 5.73100, 65.20000, 432.00000, 19.30000, + 0.06899, 25.65000, 0.58100, 2.25770, 2.00000, 19.10000, 389.15000, 5.87000, 69.70000, 188.00000, 22.00000, + 0.07165, 25.65000, 0.58100, 2.19740, 2.00000, 19.10000, 377.67000, 6.00400, 84.10000, 188.00000, 20.30000, + 0.09299, 25.65000, 0.58100, 2.08690, 2.00000, 19.10000, 378.09000, 5.96100, 92.90000, 188.00000, 20.50000, + 0.15038, 25.65000, 0.58100, 1.94440, 2.00000, 19.10000, 370.31000, 5.85600, 97.00000, 188.00000, 17.30000, + 0.09849, 25.65000, 0.58100, 2.00630, 2.00000, 19.10000, 379.38000, 5.87900, 95.80000, 188.00000, 18.80000, + 0.16902, 25.65000, 0.58100, 1.99290, 2.00000, 19.10000, 385.02000, 5.98600, 88.40000, 188.00000, 21.40000, + 0.38735, 25.65000, 0.58100, 1.75720, 2.00000, 19.10000, 359.29000, 5.61300, 95.60000, 188.00000, 15.70000, + 0.25915, 21.89000, 0.62400, 1.78830, 4.00000, 21.20000, 392.11000, 5.69300, 96.00000, 437.00000, 16.20000, + 0.32543, 21.89000, 0.62400, 1.81250, 4.00000, 21.20000, 396.90000, 6.43100, 98.80000, 437.00000, 18.00000, + 0.88125, 21.89000, 0.62400, 1.97990, 4.00000, 21.20000, 396.90000, 5.63700, 94.70000, 437.00000, 14.30000, + 0.34006, 21.89000, 0.62400, 2.11850, 4.00000, 21.20000, 395.04000, 6.45800, 98.90000, 437.00000, 19.20000, + 1.19294, 21.89000, 0.62400, 2.27100, 4.00000, 21.20000, 396.90000, 6.32600, 97.70000, 437.00000, 19.60000, + 0.59005, 21.89000, 0.62400, 2.32740, 4.00000, 21.20000, 385.76000, 6.37200, 97.90000, 437.00000, 23.00000, + 0.32982, 21.89000, 0.62400, 2.46990, 4.00000, 21.20000, 388.69000, 5.82200, 95.40000, 437.00000, 18.40000, + 0.97617, 21.89000, 0.62400, 2.34600, 4.00000, 21.20000, 262.76000, 5.75700, 98.40000, 437.00000, 15.60000, + 0.55778, 21.89000, 0.62400, 2.11070, 4.00000, 21.20000, 394.67000, 6.33500, 98.20000, 437.00000, 18.10000, + 0.32264, 21.89000, 0.62400, 1.96690, 4.00000, 21.20000, 378.25000, 5.94200, 93.50000, 437.00000, 17.40000, + 0.35233, 21.89000, 0.62400, 1.84980, 4.00000, 21.20000, 394.08000, 6.45400, 98.40000, 437.00000, 17.10000, + 0.24980, 21.89000, 0.62400, 1.66860, 4.00000, 21.20000, 392.04000, 5.85700, 98.20000, 437.00000, 13.30000, + 0.54452, 21.89000, 0.62400, 1.66870, 4.00000, 21.20000, 396.90000, 6.15100, 97.90000, 437.00000, 17.80000, + 0.29090, 21.89000, 0.62400, 1.61190, 4.00000, 21.20000, 388.08000, 6.17400, 93.60000, 437.00000, 14.00000, + 1.62864, 21.89000, 0.62400, 1.43940, 4.00000, 21.20000, 396.90000, 5.01900, 100.00000, 437.00000, 14.40000, + 3.32105, 19.58000, 0.87100, 1.32160, 5.00000, 14.70000, 396.90000, 5.40300, 100.00000, 403.00000, 13.40000, + 4.09740, 19.58000, 0.87100, 1.41180, 5.00000, 14.70000, 396.90000, 5.46800, 100.00000, 403.00000, 15.60000, + 2.77974, 19.58000, 0.87100, 1.34590, 5.00000, 14.70000, 396.90000, 4.90300, 97.80000, 403.00000, 11.80000, + 2.37934, 19.58000, 0.87100, 1.41910, 5.00000, 14.70000, 172.91000, 6.13000, 100.00000, 403.00000, 13.80000, + 2.15505, 19.58000, 0.87100, 1.51660, 5.00000, 14.70000, 169.27000, 5.62800, 100.00000, 403.00000, 15.60000, + 2.36862, 19.58000, 0.87100, 1.46080, 5.00000, 14.70000, 391.71000, 4.92600, 95.70000, 403.00000, 14.60000, + 2.33099, 19.58000, 0.87100, 1.52960, 5.00000, 14.70000, 356.99000, 5.18600, 93.80000, 403.00000, 17.80000, + 2.73397, 19.58000, 0.87100, 1.52570, 5.00000, 14.70000, 351.85000, 5.59700, 94.90000, 403.00000, 15.40000, + 1.65660, 19.58000, 0.87100, 1.61800, 5.00000, 14.70000, 372.80000, 6.12200, 97.30000, 403.00000, 21.50000, + 1.49632, 19.58000, 0.87100, 1.59160, 5.00000, 14.70000, 341.60000, 5.40400, 100.00000, 403.00000, 19.60000, + 1.12658, 19.58000, 0.87100, 1.61020, 5.00000, 14.70000, 343.28000, 5.01200, 88.00000, 403.00000, 15.30000, + 2.14918, 19.58000, 0.87100, 1.62320, 5.00000, 14.70000, 261.95000, 5.70900, 98.50000, 403.00000, 19.40000, + 1.41385, 19.58000, 0.87100, 1.74940, 5.00000, 14.70000, 321.02000, 6.12900, 96.00000, 403.00000, 17.00000, + 3.53501, 19.58000, 0.87100, 1.74550, 5.00000, 14.70000, 88.01000, 6.15200, 82.60000, 403.00000, 15.60000, + 2.44668, 19.58000, 0.87100, 1.73640, 5.00000, 14.70000, 88.63000, 5.27200, 94.00000, 403.00000, 13.10000, + 1.22358, 19.58000, 0.60500, 1.87730, 5.00000, 14.70000, 363.43000, 6.94300, 97.40000, 403.00000, 41.30000, + 1.34284, 19.58000, 0.60500, 1.75730, 5.00000, 14.70000, 353.89000, 6.06600, 100.00000, 403.00000, 24.30000, + 1.42502, 19.58000, 0.87100, 1.76590, 5.00000, 14.70000, 364.31000, 6.51000, 100.00000, 403.00000, 23.30000, + 1.27346, 19.58000, 0.60500, 1.79840, 5.00000, 14.70000, 338.92000, 6.25000, 92.60000, 403.00000, 27.00000, + 1.46336, 19.58000, 0.60500, 1.97090, 5.00000, 14.70000, 374.43000, 7.48900, 90.80000, 403.00000, 50.00000, + 1.83377, 19.58000, 0.60500, 2.04070, 5.00000, 14.70000, 389.61000, 7.80200, 98.20000, 403.00000, 50.00000, + 1.51902, 19.58000, 0.60500, 2.16200, 5.00000, 14.70000, 388.45000, 8.37500, 93.90000, 403.00000, 50.00000, + 2.24236, 19.58000, 0.60500, 2.42200, 5.00000, 14.70000, 395.11000, 5.85400, 91.80000, 403.00000, 22.70000, + 2.92400, 19.58000, 0.60500, 2.28340, 5.00000, 14.70000, 240.16000, 6.10100, 93.00000, 403.00000, 25.00000, + 2.01019, 19.58000, 0.60500, 2.04590, 5.00000, 14.70000, 369.30000, 7.92900, 96.20000, 403.00000, 50.00000, + 1.80028, 19.58000, 0.60500, 2.42590, 5.00000, 14.70000, 227.61000, 5.87700, 79.20000, 403.00000, 23.80000, + 2.30040, 19.58000, 0.60500, 2.10000, 5.00000, 14.70000, 297.09000, 6.31900, 96.10000, 403.00000, 23.80000, + 2.44953, 19.58000, 0.60500, 2.26250, 5.00000, 14.70000, 330.04000, 6.40200, 95.20000, 403.00000, 22.30000, + 1.20742, 19.58000, 0.60500, 2.42590, 5.00000, 14.70000, 292.29000, 5.87500, 94.60000, 403.00000, 17.40000, + 2.31390, 19.58000, 0.60500, 2.38870, 5.00000, 14.70000, 348.13000, 5.88000, 97.30000, 403.00000, 19.10000, + 0.13914, 4.05000, 0.51000, 2.59610, 5.00000, 16.60000, 396.90000, 5.57200, 88.50000, 296.00000, 23.10000, + 0.09178, 4.05000, 0.51000, 2.64630, 5.00000, 16.60000, 395.50000, 6.41600, 84.10000, 296.00000, 23.60000, + 0.08447, 4.05000, 0.51000, 2.70190, 5.00000, 16.60000, 393.23000, 5.85900, 68.70000, 296.00000, 22.60000, + 0.06664, 4.05000, 0.51000, 3.13230, 5.00000, 16.60000, 390.96000, 6.54600, 33.10000, 296.00000, 29.40000, + 0.07022, 4.05000, 0.51000, 3.55490, 5.00000, 16.60000, 393.23000, 6.02000, 47.20000, 296.00000, 23.20000, + 0.05425, 4.05000, 0.51000, 3.31750, 5.00000, 16.60000, 395.60000, 6.31500, 73.40000, 296.00000, 24.60000, + 0.06642, 4.05000, 0.51000, 2.91530, 5.00000, 16.60000, 391.27000, 6.86000, 74.40000, 296.00000, 29.90000, + 0.05780, 2.46000, 0.48800, 2.82900, 3.00000, 17.80000, 396.90000, 6.98000, 58.40000, 193.00000, 37.20000, + 0.06588, 2.46000, 0.48800, 2.74100, 3.00000, 17.80000, 395.56000, 7.76500, 83.30000, 193.00000, 39.80000, + 0.06888, 2.46000, 0.48800, 2.59790, 3.00000, 17.80000, 396.90000, 6.14400, 62.20000, 193.00000, 36.20000, + 0.09103, 2.46000, 0.48800, 2.70060, 3.00000, 17.80000, 394.12000, 7.15500, 92.20000, 193.00000, 37.90000, + 0.10008, 2.46000, 0.48800, 2.84700, 3.00000, 17.80000, 396.90000, 6.56300, 95.60000, 193.00000, 32.50000, + 0.08308, 2.46000, 0.48800, 2.98790, 3.00000, 17.80000, 391.00000, 5.60400, 89.80000, 193.00000, 26.40000, + 0.06047, 2.46000, 0.48800, 3.27970, 3.00000, 17.80000, 387.11000, 6.15300, 68.80000, 193.00000, 29.60000, + 0.05602, 2.46000, 0.48800, 3.19920, 3.00000, 17.80000, 392.63000, 7.83100, 53.60000, 193.00000, 50.00000, + 0.07875, 3.44000, 0.43700, 3.78860, 5.00000, 15.20000, 393.87000, 6.78200, 41.10000, 398.00000, 32.00000, + 0.12579, 3.44000, 0.43700, 4.56670, 5.00000, 15.20000, 382.84000, 6.55600, 29.10000, 398.00000, 29.80000, + 0.08370, 3.44000, 0.43700, 4.56670, 5.00000, 15.20000, 396.90000, 7.18500, 38.90000, 398.00000, 34.90000, + 0.09068, 3.44000, 0.43700, 6.47980, 5.00000, 15.20000, 377.68000, 6.95100, 21.50000, 398.00000, 37.00000, + 0.06911, 3.44000, 0.43700, 6.47980, 5.00000, 15.20000, 389.71000, 6.73900, 30.80000, 398.00000, 30.50000, + 0.08664, 3.44000, 0.43700, 6.47980, 5.00000, 15.20000, 390.49000, 7.17800, 26.30000, 398.00000, 36.40000, + 0.02187, 2.93000, 0.40100, 6.21960, 1.00000, 15.60000, 393.37000, 6.80000, 9.90000, 265.00000, 31.10000, + 0.01439, 2.93000, 0.40100, 6.21960, 1.00000, 15.60000, 376.70000, 6.60400, 18.80000, 265.00000, 29.10000, + 0.01381, 0.46000, 0.42200, 5.64840, 4.00000, 14.40000, 394.23000, 7.87500, 32.00000, 255.00000, 50.00000, + 0.04011, 1.52000, 0.40400, 7.30900, 2.00000, 12.60000, 396.90000, 7.28700, 34.10000, 329.00000, 33.30000, + 0.04666, 1.52000, 0.40400, 7.30900, 2.00000, 12.60000, 354.31000, 7.10700, 36.60000, 329.00000, 30.30000, + 0.03768, 1.52000, 0.40400, 7.30900, 2.00000, 12.60000, 392.20000, 7.27400, 38.30000, 329.00000, 34.60000, + 0.03150, 1.47000, 0.40300, 7.65340, 3.00000, 17.00000, 396.90000, 6.97500, 15.30000, 402.00000, 34.90000, + 0.01778, 1.47000, 0.40300, 7.65340, 3.00000, 17.00000, 384.30000, 7.13500, 13.90000, 402.00000, 32.90000, + 0.03445, 2.03000, 0.41500, 6.27000, 2.00000, 14.70000, 393.77000, 6.16200, 38.40000, 348.00000, 24.10000, + 0.02177, 2.03000, 0.41500, 6.27000, 2.00000, 14.70000, 395.38000, 7.61000, 15.70000, 348.00000, 42.30000, + 0.03510, 2.68000, 0.41610, 5.11800, 4.00000, 14.70000, 392.78000, 7.85300, 33.20000, 224.00000, 48.50000, + 0.02009, 2.68000, 0.41610, 5.11800, 4.00000, 14.70000, 390.55000, 8.03400, 31.90000, 224.00000, 50.00000, + 0.13642, 10.59000, 0.48900, 3.94540, 4.00000, 18.60000, 396.90000, 5.89100, 22.30000, 277.00000, 22.60000, + 0.22969, 10.59000, 0.48900, 4.35490, 4.00000, 18.60000, 394.87000, 6.32600, 52.50000, 277.00000, 24.40000, + 0.25199, 10.59000, 0.48900, 4.35490, 4.00000, 18.60000, 389.43000, 5.78300, 72.70000, 277.00000, 22.50000, + 0.13587, 10.59000, 0.48900, 4.23920, 4.00000, 18.60000, 381.32000, 6.06400, 59.10000, 277.00000, 24.40000, + 0.43571, 10.59000, 0.48900, 3.87500, 4.00000, 18.60000, 396.90000, 5.34400, 100.00000, 277.00000, 20.00000, + 0.17446, 10.59000, 0.48900, 3.87710, 4.00000, 18.60000, 393.25000, 5.96000, 92.10000, 277.00000, 21.70000, + 0.37578, 10.59000, 0.48900, 3.66500, 4.00000, 18.60000, 395.24000, 5.40400, 88.60000, 277.00000, 19.30000, + 0.21719, 10.59000, 0.48900, 3.65260, 4.00000, 18.60000, 390.94000, 5.80700, 53.80000, 277.00000, 22.40000, + 0.14052, 10.59000, 0.48900, 3.94540, 4.00000, 18.60000, 385.81000, 6.37500, 32.30000, 277.00000, 28.10000, + 0.28955, 10.59000, 0.48900, 3.58750, 4.00000, 18.60000, 348.93000, 5.41200, 9.80000, 277.00000, 23.70000, + 0.19802, 10.59000, 0.48900, 3.94540, 4.00000, 18.60000, 393.63000, 6.18200, 42.40000, 277.00000, 25.00000, + 0.04560, 13.89000, 0.55000, 3.11210, 5.00000, 16.40000, 392.80000, 5.88800, 56.00000, 276.00000, 23.30000, + 0.07013, 13.89000, 0.55000, 3.42110, 5.00000, 16.40000, 392.78000, 6.64200, 85.10000, 276.00000, 28.70000, + 0.11069, 13.89000, 0.55000, 2.88930, 5.00000, 16.40000, 396.90000, 5.95100, 93.80000, 276.00000, 21.50000, + 0.11425, 13.89000, 0.55000, 3.36330, 5.00000, 16.40000, 393.74000, 6.37300, 92.40000, 276.00000, 23.00000, + 0.35809, 6.20000, 0.50700, 2.86170, 8.00000, 17.40000, 391.70000, 6.95100, 88.50000, 307.00000, 26.70000, + 0.40771, 6.20000, 0.50700, 3.04800, 8.00000, 17.40000, 395.24000, 6.16400, 91.30000, 307.00000, 21.70000, + 0.62356, 6.20000, 0.50700, 3.27210, 8.00000, 17.40000, 390.39000, 6.87900, 77.70000, 307.00000, 27.50000, + 0.61470, 6.20000, 0.50700, 3.27210, 8.00000, 17.40000, 396.90000, 6.61800, 80.80000, 307.00000, 30.10000, + 0.31533, 6.20000, 0.50400, 2.89440, 8.00000, 17.40000, 385.05000, 8.26600, 78.30000, 307.00000, 44.80000, + 0.52693, 6.20000, 0.50400, 2.89440, 8.00000, 17.40000, 382.00000, 8.72500, 83.00000, 307.00000, 50.00000, + 0.38214, 6.20000, 0.50400, 3.21570, 8.00000, 17.40000, 387.38000, 8.04000, 86.50000, 307.00000, 37.60000, + 0.41238, 6.20000, 0.50400, 3.21570, 8.00000, 17.40000, 372.08000, 7.16300, 79.90000, 307.00000, 31.60000, + 0.29819, 6.20000, 0.50400, 3.37510, 8.00000, 17.40000, 377.51000, 7.68600, 17.00000, 307.00000, 46.70000, + 0.44178, 6.20000, 0.50400, 3.37510, 8.00000, 17.40000, 380.34000, 6.55200, 21.40000, 307.00000, 31.50000, + 0.53700, 6.20000, 0.50400, 3.67150, 8.00000, 17.40000, 378.35000, 5.98100, 68.10000, 307.00000, 24.30000, + 0.46296, 6.20000, 0.50400, 3.67150, 8.00000, 17.40000, 376.14000, 7.41200, 76.90000, 307.00000, 31.70000, + 0.57529, 6.20000, 0.50700, 3.83840, 8.00000, 17.40000, 385.91000, 8.33700, 73.30000, 307.00000, 41.70000, + 0.33147, 6.20000, 0.50700, 3.65190, 8.00000, 17.40000, 378.95000, 8.24700, 70.40000, 307.00000, 48.30000, + 0.44791, 6.20000, 0.50700, 3.65190, 8.00000, 17.40000, 360.20000, 6.72600, 66.50000, 307.00000, 29.00000, + 0.33045, 6.20000, 0.50700, 3.65190, 8.00000, 17.40000, 376.75000, 6.08600, 61.50000, 307.00000, 24.00000, + 0.52058, 6.20000, 0.50700, 4.14800, 8.00000, 17.40000, 388.45000, 6.63100, 76.50000, 307.00000, 25.10000, + 0.51183, 6.20000, 0.50700, 4.14800, 8.00000, 17.40000, 390.07000, 7.35800, 71.60000, 307.00000, 31.50000, + 0.08244, 4.93000, 0.42800, 6.18990, 6.00000, 16.60000, 379.41000, 6.48100, 18.50000, 300.00000, 23.70000, + 0.09252, 4.93000, 0.42800, 6.18990, 6.00000, 16.60000, 383.78000, 6.60600, 42.20000, 300.00000, 23.30000, + 0.11329, 4.93000, 0.42800, 6.33610, 6.00000, 16.60000, 391.25000, 6.89700, 54.30000, 300.00000, 22.00000, + 0.10612, 4.93000, 0.42800, 6.33610, 6.00000, 16.60000, 394.62000, 6.09500, 65.10000, 300.00000, 20.10000, + 0.10290, 4.93000, 0.42800, 7.03550, 6.00000, 16.60000, 372.75000, 6.35800, 52.90000, 300.00000, 22.20000, + 0.12757, 4.93000, 0.42800, 7.03550, 6.00000, 16.60000, 374.71000, 6.39300, 7.80000, 300.00000, 23.70000, + 0.20608, 5.86000, 0.43100, 7.95490, 7.00000, 19.10000, 372.49000, 5.59300, 76.50000, 330.00000, 17.60000, + 0.19133, 5.86000, 0.43100, 7.95490, 7.00000, 19.10000, 389.13000, 5.60500, 70.20000, 330.00000, 18.50000, + 0.33983, 5.86000, 0.43100, 8.05550, 7.00000, 19.10000, 390.18000, 6.10800, 34.90000, 330.00000, 24.30000, + 0.19657, 5.86000, 0.43100, 8.05550, 7.00000, 19.10000, 376.14000, 6.22600, 79.20000, 330.00000, 20.50000, + 0.16439, 5.86000, 0.43100, 7.82650, 7.00000, 19.10000, 374.71000, 6.43300, 49.10000, 330.00000, 24.50000, + 0.19073, 5.86000, 0.43100, 7.82650, 7.00000, 19.10000, 393.74000, 6.71800, 17.50000, 330.00000, 26.20000, + 0.14030, 5.86000, 0.43100, 7.39670, 7.00000, 19.10000, 396.28000, 6.48700, 13.00000, 330.00000, 24.40000, + 0.21409, 5.86000, 0.43100, 7.39670, 7.00000, 19.10000, 377.07000, 6.43800, 8.90000, 330.00000, 24.80000, + 0.08221, 5.86000, 0.43100, 8.90670, 7.00000, 19.10000, 386.09000, 6.95700, 6.80000, 330.00000, 29.60000, + 0.36894, 5.86000, 0.43100, 8.90670, 7.00000, 19.10000, 396.90000, 8.25900, 8.40000, 330.00000, 42.80000, + 0.04819, 3.64000, 0.39200, 9.22030, 1.00000, 16.40000, 392.89000, 6.10800, 32.00000, 315.00000, 21.90000, + 0.03548, 3.64000, 0.39200, 9.22030, 1.00000, 16.40000, 395.18000, 5.87600, 19.10000, 315.00000, 20.90000, + 0.01538, 3.75000, 0.39400, 6.33610, 3.00000, 15.90000, 386.34000, 7.45400, 34.20000, 244.00000, 44.00000, + 0.61154, 3.97000, 0.64700, 1.80100, 5.00000, 13.00000, 389.70000, 8.70400, 86.90000, 264.00000, 50.00000, + 0.66351, 3.97000, 0.64700, 1.89460, 5.00000, 13.00000, 383.29000, 7.33300, 100.00000, 264.00000, 36.00000, + 0.65665, 3.97000, 0.64700, 2.01070, 5.00000, 13.00000, 391.93000, 6.84200, 100.00000, 264.00000, 30.10000, + 0.54011, 3.97000, 0.64700, 2.11210, 5.00000, 13.00000, 392.80000, 7.20300, 81.80000, 264.00000, 33.80000, + 0.53412, 3.97000, 0.64700, 2.13980, 5.00000, 13.00000, 388.37000, 7.52000, 89.40000, 264.00000, 43.10000, + 0.52014, 3.97000, 0.64700, 2.28850, 5.00000, 13.00000, 386.86000, 8.39800, 91.50000, 264.00000, 48.80000, + 0.82526, 3.97000, 0.64700, 2.07880, 5.00000, 13.00000, 393.42000, 7.32700, 94.50000, 264.00000, 31.00000, + 0.55007, 3.97000, 0.64700, 1.93010, 5.00000, 13.00000, 387.89000, 7.20600, 91.60000, 264.00000, 36.50000, + 0.76162, 3.97000, 0.64700, 1.98650, 5.00000, 13.00000, 392.40000, 5.56000, 62.80000, 264.00000, 22.80000, + 0.78570, 3.97000, 0.64700, 2.13290, 5.00000, 13.00000, 384.07000, 7.01400, 84.60000, 264.00000, 30.70000, + 0.57834, 3.97000, 0.57500, 2.42160, 5.00000, 13.00000, 384.54000, 8.29700, 67.00000, 264.00000, 50.00000, + 0.54050, 3.97000, 0.57500, 2.87200, 5.00000, 13.00000, 390.30000, 7.47000, 52.60000, 264.00000, 43.50000, + 0.09065, 6.96000, 0.46400, 3.91750, 3.00000, 18.60000, 391.34000, 5.92000, 61.50000, 223.00000, 20.70000, + 0.29916, 6.96000, 0.46400, 4.42900, 3.00000, 18.60000, 388.65000, 5.85600, 42.10000, 223.00000, 21.10000, + 0.16211, 6.96000, 0.46400, 4.42900, 3.00000, 18.60000, 396.90000, 6.24000, 16.30000, 223.00000, 25.20000, + 0.11460, 6.96000, 0.46400, 3.91750, 3.00000, 18.60000, 394.96000, 6.53800, 58.70000, 223.00000, 24.40000, + 0.22188, 6.96000, 0.46400, 4.36650, 3.00000, 18.60000, 390.77000, 7.69100, 51.80000, 223.00000, 35.20000, + 0.05644, 6.41000, 0.44700, 4.07760, 4.00000, 17.60000, 396.90000, 6.75800, 32.90000, 254.00000, 32.40000, + 0.09604, 6.41000, 0.44700, 4.26730, 4.00000, 17.60000, 396.90000, 6.85400, 42.80000, 254.00000, 32.00000, + 0.10469, 6.41000, 0.44700, 4.78720, 4.00000, 17.60000, 389.25000, 7.26700, 49.00000, 254.00000, 33.20000, + 0.06127, 6.41000, 0.44700, 4.86280, 4.00000, 17.60000, 393.45000, 6.82600, 27.60000, 254.00000, 33.10000, + 0.07978, 6.41000, 0.44700, 4.14030, 4.00000, 17.60000, 396.90000, 6.48200, 32.10000, 254.00000, 29.10000, + 0.21038, 3.33000, 0.44290, 4.10070, 5.00000, 14.90000, 396.90000, 6.81200, 32.20000, 216.00000, 35.10000, + 0.03578, 3.33000, 0.44290, 4.69470, 5.00000, 14.90000, 387.31000, 7.82000, 64.50000, 216.00000, 45.40000, + 0.03705, 3.33000, 0.44290, 5.24470, 5.00000, 14.90000, 392.23000, 6.96800, 37.20000, 216.00000, 35.40000, + 0.06129, 3.33000, 0.44290, 5.21190, 5.00000, 14.90000, 377.07000, 7.64500, 49.70000, 216.00000, 46.00000, + 0.01501, 1.21000, 0.40100, 5.88500, 1.00000, 13.60000, 395.52000, 7.92300, 24.80000, 198.00000, 50.00000, + 0.00906, 2.97000, 0.40000, 7.30730, 1.00000, 15.30000, 394.72000, 7.08800, 20.80000, 285.00000, 32.20000, + 0.01096, 2.25000, 0.38900, 7.30730, 1.00000, 15.30000, 394.72000, 6.45300, 31.90000, 300.00000, 22.00000, + 0.01965, 1.76000, 0.38500, 9.08920, 1.00000, 18.20000, 341.60000, 6.23000, 31.50000, 241.00000, 20.10000, + 0.03871, 5.32000, 0.40500, 7.31720, 6.00000, 16.60000, 396.90000, 6.20900, 31.30000, 293.00000, 23.20000, + 0.04590, 5.32000, 0.40500, 7.31720, 6.00000, 16.60000, 396.90000, 6.31500, 45.60000, 293.00000, 22.30000, + 0.04297, 5.32000, 0.40500, 7.31720, 6.00000, 16.60000, 371.72000, 6.56500, 22.90000, 293.00000, 24.80000, + 0.03502, 4.95000, 0.41100, 5.11670, 4.00000, 19.20000, 396.90000, 6.86100, 27.90000, 245.00000, 28.50000, + 0.07886, 4.95000, 0.41100, 5.11670, 4.00000, 19.20000, 396.90000, 7.14800, 27.70000, 245.00000, 37.30000, + 0.03615, 4.95000, 0.41100, 5.11670, 4.00000, 19.20000, 396.90000, 6.63000, 23.40000, 245.00000, 27.90000, + 0.08265, 13.92000, 0.43700, 5.50270, 4.00000, 16.00000, 396.90000, 6.12700, 18.40000, 289.00000, 23.90000, + 0.08199, 13.92000, 0.43700, 5.50270, 4.00000, 16.00000, 396.90000, 6.00900, 42.30000, 289.00000, 21.70000, + 0.12932, 13.92000, 0.43700, 5.96040, 4.00000, 16.00000, 396.90000, 6.67800, 31.10000, 289.00000, 28.60000, + 0.05372, 13.92000, 0.43700, 5.96040, 4.00000, 16.00000, 392.85000, 6.54900, 51.00000, 289.00000, 27.10000, + 0.14103, 13.92000, 0.43700, 6.32000, 4.00000, 16.00000, 396.90000, 5.79000, 58.00000, 289.00000, 20.30000, + 0.06466, 2.24000, 0.40000, 7.82780, 5.00000, 14.80000, 368.24000, 6.34500, 20.10000, 358.00000, 22.50000, + 0.05561, 2.24000, 0.40000, 7.82780, 5.00000, 14.80000, 371.58000, 7.04100, 10.00000, 358.00000, 29.00000, + 0.04417, 2.24000, 0.40000, 7.82780, 5.00000, 14.80000, 390.86000, 6.87100, 47.40000, 358.00000, 24.80000, + 0.03537, 6.09000, 0.43300, 5.49170, 7.00000, 16.10000, 395.75000, 6.59000, 40.40000, 329.00000, 22.00000, + 0.09266, 6.09000, 0.43300, 5.49170, 7.00000, 16.10000, 383.61000, 6.49500, 18.40000, 329.00000, 26.40000, + 0.10000, 6.09000, 0.43300, 5.49170, 7.00000, 16.10000, 390.43000, 6.98200, 17.70000, 329.00000, 33.10000, + 0.05515, 2.18000, 0.47200, 4.02200, 7.00000, 18.40000, 393.68000, 7.23600, 41.10000, 222.00000, 36.10000, + 0.05479, 2.18000, 0.47200, 3.37000, 7.00000, 18.40000, 393.36000, 6.61600, 58.10000, 222.00000, 28.40000, + 0.07503, 2.18000, 0.47200, 3.09920, 7.00000, 18.40000, 396.90000, 7.42000, 71.90000, 222.00000, 33.40000, + 0.04932, 2.18000, 0.47200, 3.18270, 7.00000, 18.40000, 396.90000, 6.84900, 70.30000, 222.00000, 28.20000, + 0.49298, 9.90000, 0.54400, 3.31750, 4.00000, 18.40000, 396.90000, 6.63500, 82.50000, 304.00000, 22.80000, + 0.34940, 9.90000, 0.54400, 3.10250, 4.00000, 18.40000, 396.24000, 5.97200, 76.70000, 304.00000, 20.30000, + 2.63548, 9.90000, 0.54400, 2.51940, 4.00000, 18.40000, 350.45000, 4.97300, 37.80000, 304.00000, 16.10000, + 0.79041, 9.90000, 0.54400, 2.64030, 4.00000, 18.40000, 396.90000, 6.12200, 52.80000, 304.00000, 22.10000, + 0.26169, 9.90000, 0.54400, 2.83400, 4.00000, 18.40000, 396.30000, 6.02300, 90.40000, 304.00000, 19.40000, + 0.26938, 9.90000, 0.54400, 3.26280, 4.00000, 18.40000, 393.39000, 6.26600, 82.80000, 304.00000, 21.60000, + 0.36920, 9.90000, 0.54400, 3.60230, 4.00000, 18.40000, 395.69000, 6.56700, 87.30000, 304.00000, 23.80000, + 0.25356, 9.90000, 0.54400, 3.94500, 4.00000, 18.40000, 396.42000, 5.70500, 77.70000, 304.00000, 16.20000, + 0.31827, 9.90000, 0.54400, 3.99860, 4.00000, 18.40000, 390.70000, 5.91400, 83.20000, 304.00000, 17.80000, + 0.24522, 9.90000, 0.54400, 4.03170, 4.00000, 18.40000, 396.90000, 5.78200, 71.70000, 304.00000, 19.80000, + 0.40202, 9.90000, 0.54400, 3.53250, 4.00000, 18.40000, 395.21000, 6.38200, 67.20000, 304.00000, 23.10000, + 0.47547, 9.90000, 0.54400, 4.00190, 4.00000, 18.40000, 396.23000, 6.11300, 58.80000, 304.00000, 21.00000, + 0.16760, 7.38000, 0.49300, 4.54040, 5.00000, 19.60000, 396.90000, 6.42600, 52.30000, 287.00000, 23.80000, + 0.18159, 7.38000, 0.49300, 4.54040, 5.00000, 19.60000, 396.90000, 6.37600, 54.30000, 287.00000, 23.10000, + 0.35114, 7.38000, 0.49300, 4.72110, 5.00000, 19.60000, 396.90000, 6.04100, 49.90000, 287.00000, 20.40000, + 0.28392, 7.38000, 0.49300, 4.72110, 5.00000, 19.60000, 391.13000, 5.70800, 74.30000, 287.00000, 18.50000, + 0.34109, 7.38000, 0.49300, 4.72110, 5.00000, 19.60000, 396.90000, 6.41500, 40.10000, 287.00000, 25.00000, + 0.19186, 7.38000, 0.49300, 5.41590, 5.00000, 19.60000, 393.68000, 6.43100, 14.70000, 287.00000, 24.60000, + 0.30347, 7.38000, 0.49300, 5.41590, 5.00000, 19.60000, 396.90000, 6.31200, 28.90000, 287.00000, 23.00000, + 0.24103, 7.38000, 0.49300, 5.41590, 5.00000, 19.60000, 396.90000, 6.08300, 43.70000, 287.00000, 22.20000, + 0.06617, 3.24000, 0.46000, 5.21460, 4.00000, 16.90000, 382.44000, 5.86800, 25.80000, 430.00000, 19.30000, + 0.06724, 3.24000, 0.46000, 5.21460, 4.00000, 16.90000, 375.21000, 6.33300, 17.20000, 430.00000, 22.60000, + 0.04544, 3.24000, 0.46000, 5.87360, 4.00000, 16.90000, 368.57000, 6.14400, 32.20000, 430.00000, 19.80000, + 0.05023, 6.06000, 0.43790, 6.64070, 1.00000, 16.90000, 394.02000, 5.70600, 28.40000, 304.00000, 17.10000, + 0.03466, 6.06000, 0.43790, 6.64070, 1.00000, 16.90000, 362.25000, 6.03100, 23.30000, 304.00000, 19.40000, + 0.05083, 5.19000, 0.51500, 6.45840, 5.00000, 20.20000, 389.71000, 6.31600, 38.10000, 224.00000, 22.20000, + 0.03738, 5.19000, 0.51500, 6.45840, 5.00000, 20.20000, 389.40000, 6.31000, 38.50000, 224.00000, 20.70000, + 0.03961, 5.19000, 0.51500, 5.98530, 5.00000, 20.20000, 396.90000, 6.03700, 34.50000, 224.00000, 21.10000, + 0.03427, 5.19000, 0.51500, 5.23110, 5.00000, 20.20000, 396.90000, 5.86900, 46.30000, 224.00000, 19.50000, + 0.03041, 5.19000, 0.51500, 5.61500, 5.00000, 20.20000, 394.81000, 5.89500, 59.60000, 224.00000, 18.50000, + 0.03306, 5.19000, 0.51500, 4.81220, 5.00000, 20.20000, 396.14000, 6.05900, 37.30000, 224.00000, 20.60000, + 0.05497, 5.19000, 0.51500, 4.81220, 5.00000, 20.20000, 396.90000, 5.98500, 45.40000, 224.00000, 19.00000, + 0.06151, 5.19000, 0.51500, 4.81220, 5.00000, 20.20000, 396.90000, 5.96800, 58.50000, 224.00000, 18.70000, + 0.01301, 1.52000, 0.44200, 7.03790, 1.00000, 15.50000, 394.74000, 7.24100, 49.30000, 284.00000, 32.70000, + 0.02498, 1.89000, 0.51800, 6.26690, 1.00000, 15.90000, 389.96000, 6.54000, 59.70000, 422.00000, 16.50000, + 0.02543, 3.78000, 0.48400, 5.73210, 5.00000, 17.60000, 396.90000, 6.69600, 56.40000, 370.00000, 23.90000, + 0.03049, 3.78000, 0.48400, 6.46540, 5.00000, 17.60000, 387.97000, 6.87400, 28.10000, 370.00000, 31.20000, + 0.03113, 4.39000, 0.44200, 8.01360, 3.00000, 18.80000, 385.64000, 6.01400, 48.50000, 352.00000, 17.50000, + 0.06162, 4.39000, 0.44200, 8.01360, 3.00000, 18.80000, 364.61000, 5.89800, 52.30000, 352.00000, 17.20000, + 0.01870, 4.15000, 0.42900, 8.53530, 4.00000, 17.90000, 392.43000, 6.51600, 27.70000, 351.00000, 23.10000, + 0.01501, 2.01000, 0.43500, 8.34400, 4.00000, 17.00000, 390.94000, 6.63500, 29.70000, 280.00000, 24.50000, + 0.02899, 1.25000, 0.42900, 8.79210, 1.00000, 19.70000, 389.85000, 6.93900, 34.50000, 335.00000, 26.60000, + 0.06211, 1.25000, 0.42900, 8.79210, 1.00000, 19.70000, 396.90000, 6.49000, 44.40000, 335.00000, 22.90000, + 0.07950, 1.69000, 0.41100, 10.71030, 4.00000, 18.30000, 370.78000, 6.57900, 35.90000, 411.00000, 24.10000, + 0.07244, 1.69000, 0.41100, 10.71030, 4.00000, 18.30000, 392.33000, 5.88400, 18.50000, 411.00000, 18.60000, + 0.01709, 2.02000, 0.41000, 12.12650, 5.00000, 17.00000, 384.46000, 6.72800, 36.10000, 187.00000, 30.10000, + 0.04301, 1.91000, 0.41300, 10.58570, 4.00000, 22.00000, 382.80000, 5.66300, 21.90000, 334.00000, 18.20000, + 0.10659, 1.91000, 0.41300, 10.58570, 4.00000, 22.00000, 376.04000, 5.93600, 19.50000, 334.00000, 20.60000, + 8.98296, 18.10000, 0.77000, 2.12220, 24.00000, 20.20000, 377.73000, 6.21200, 97.40000, 666.00000, 17.80000, + 3.84970, 18.10000, 0.77000, 2.50520, 24.00000, 20.20000, 391.34000, 6.39500, 91.00000, 666.00000, 21.70000, + 5.20177, 18.10000, 0.77000, 2.72270, 24.00000, 20.20000, 395.43000, 6.12700, 83.40000, 666.00000, 22.70000, + 4.26131, 18.10000, 0.77000, 2.50910, 24.00000, 20.20000, 390.74000, 6.11200, 81.30000, 666.00000, 22.60000, + 4.54192, 18.10000, 0.77000, 2.51820, 24.00000, 20.20000, 374.56000, 6.39800, 88.00000, 666.00000, 25.00000, + 3.83684, 18.10000, 0.77000, 2.29550, 24.00000, 20.20000, 350.65000, 6.25100, 91.10000, 666.00000, 19.90000, + 3.67822, 18.10000, 0.77000, 2.10360, 24.00000, 20.20000, 380.79000, 5.36200, 96.20000, 666.00000, 20.80000, + 4.22239, 18.10000, 0.77000, 1.90470, 24.00000, 20.20000, 353.04000, 5.80300, 89.00000, 666.00000, 16.80000, + 3.47428, 18.10000, 0.71800, 1.90470, 24.00000, 20.20000, 354.55000, 8.78000, 82.90000, 666.00000, 21.90000, + 4.55587, 18.10000, 0.71800, 1.61320, 24.00000, 20.20000, 354.70000, 3.56100, 87.90000, 666.00000, 27.50000, + 3.69695, 18.10000, 0.71800, 1.75230, 24.00000, 20.20000, 316.03000, 4.96300, 91.40000, 666.00000, 21.90000, + 13.52220, 18.10000, 0.63100, 1.51060, 24.00000, 20.20000, 131.42000, 3.86300, 100.00000, 666.00000, 23.10000, + 4.89822, 18.10000, 0.63100, 1.33250, 24.00000, 20.20000, 375.52000, 4.97000, 100.00000, 666.00000, 50.00000, + 5.66998, 18.10000, 0.63100, 1.35670, 24.00000, 20.20000, 375.33000, 6.68300, 96.80000, 666.00000, 50.00000, + 6.53876, 18.10000, 0.63100, 1.20240, 24.00000, 20.20000, 392.05000, 7.01600, 97.50000, 666.00000, 50.00000, + 9.23230, 18.10000, 0.63100, 1.16910, 24.00000, 20.20000, 366.15000, 6.21600, 100.00000, 666.00000, 50.00000, + 8.26725, 18.10000, 0.66800, 1.12960, 24.00000, 20.20000, 347.88000, 5.87500, 89.60000, 666.00000, 50.00000, + 11.10810, 18.10000, 0.66800, 1.17420, 24.00000, 20.20000, 396.90000, 4.90600, 100.00000, 666.00000, 13.80000, + 18.49820, 18.10000, 0.66800, 1.13700, 24.00000, 20.20000, 396.90000, 4.13800, 100.00000, 666.00000, 13.80000, + 19.60910, 18.10000, 0.67100, 1.31630, 24.00000, 20.20000, 396.90000, 7.31300, 97.90000, 666.00000, 15.00000, + 15.28800, 18.10000, 0.67100, 1.34490, 24.00000, 20.20000, 363.02000, 6.64900, 93.30000, 666.00000, 13.90000, + 9.82349, 18.10000, 0.67100, 1.35800, 24.00000, 20.20000, 396.90000, 6.79400, 98.80000, 666.00000, 13.30000, + 23.64820, 18.10000, 0.67100, 1.38610, 24.00000, 20.20000, 396.90000, 6.38000, 96.20000, 666.00000, 13.10000, + 17.86670, 18.10000, 0.67100, 1.38610, 24.00000, 20.20000, 393.74000, 6.22300, 100.00000, 666.00000, 10.20000, + 88.97620, 18.10000, 0.67100, 1.41650, 24.00000, 20.20000, 396.90000, 6.96800, 91.90000, 666.00000, 10.40000, + 15.87440, 18.10000, 0.67100, 1.51920, 24.00000, 20.20000, 396.90000, 6.54500, 99.10000, 666.00000, 10.90000, + 9.18702, 18.10000, 0.70000, 1.58040, 24.00000, 20.20000, 396.90000, 5.53600, 100.00000, 666.00000, 11.30000, + 7.99248, 18.10000, 0.70000, 1.53310, 24.00000, 20.20000, 396.90000, 5.52000, 100.00000, 666.00000, 12.30000, + 20.08490, 18.10000, 0.70000, 1.43950, 24.00000, 20.20000, 285.83000, 4.36800, 91.20000, 666.00000, 8.80000, + 16.81180, 18.10000, 0.70000, 1.42610, 24.00000, 20.20000, 396.90000, 5.27700, 98.10000, 666.00000, 7.20000, + 24.39380, 18.10000, 0.70000, 1.46720, 24.00000, 20.20000, 396.90000, 4.65200, 100.00000, 666.00000, 10.50000, + 22.59710, 18.10000, 0.70000, 1.51840, 24.00000, 20.20000, 396.90000, 5.00000, 89.50000, 666.00000, 7.40000, + 14.33370, 18.10000, 0.70000, 1.58950, 24.00000, 20.20000, 372.92000, 4.88000, 100.00000, 666.00000, 10.20000, + 8.15174, 18.10000, 0.70000, 1.72810, 24.00000, 20.20000, 396.90000, 5.39000, 98.90000, 666.00000, 11.50000, + 6.96215, 18.10000, 0.70000, 1.92650, 24.00000, 20.20000, 394.43000, 5.71300, 97.00000, 666.00000, 15.10000, + 5.29305, 18.10000, 0.70000, 2.16780, 24.00000, 20.20000, 378.38000, 6.05100, 82.50000, 666.00000, 23.20000, + 11.57790, 18.10000, 0.70000, 1.77000, 24.00000, 20.20000, 396.90000, 5.03600, 97.00000, 666.00000, 9.70000, + 8.64476, 18.10000, 0.69300, 1.79120, 24.00000, 20.20000, 396.90000, 6.19300, 92.60000, 666.00000, 13.80000, + 13.35980, 18.10000, 0.69300, 1.78210, 24.00000, 20.20000, 396.90000, 5.88700, 94.70000, 666.00000, 12.70000, + 8.71675, 18.10000, 0.69300, 1.72570, 24.00000, 20.20000, 391.98000, 6.47100, 98.80000, 666.00000, 13.10000, + 5.87205, 18.10000, 0.69300, 1.67680, 24.00000, 20.20000, 396.90000, 6.40500, 96.00000, 666.00000, 12.50000, + 7.67202, 18.10000, 0.69300, 1.63340, 24.00000, 20.20000, 393.10000, 5.74700, 98.90000, 666.00000, 8.50000, + 38.35180, 18.10000, 0.69300, 1.48960, 24.00000, 20.20000, 396.90000, 5.45300, 100.00000, 666.00000, 5.00000, + 9.91655, 18.10000, 0.69300, 1.50040, 24.00000, 20.20000, 338.16000, 5.85200, 77.80000, 666.00000, 6.30000, + 25.04610, 18.10000, 0.69300, 1.58880, 24.00000, 20.20000, 396.90000, 5.98700, 100.00000, 666.00000, 5.60000, + 14.23620, 18.10000, 0.69300, 1.57410, 24.00000, 20.20000, 396.90000, 6.34300, 100.00000, 666.00000, 7.20000, + 9.59571, 18.10000, 0.69300, 1.63900, 24.00000, 20.20000, 376.11000, 6.40400, 100.00000, 666.00000, 12.10000, + 24.80170, 18.10000, 0.69300, 1.70280, 24.00000, 20.20000, 396.90000, 5.34900, 96.00000, 666.00000, 8.30000, + 41.52920, 18.10000, 0.69300, 1.60740, 24.00000, 20.20000, 329.46000, 5.53100, 85.40000, 666.00000, 8.50000, + 67.92080, 18.10000, 0.69300, 1.42540, 24.00000, 20.20000, 384.97000, 5.68300, 100.00000, 666.00000, 5.00000, + 20.71620, 18.10000, 0.65900, 1.17810, 24.00000, 20.20000, 370.22000, 4.13800, 100.00000, 666.00000, 11.90000, + 11.95110, 18.10000, 0.65900, 1.28520, 24.00000, 20.20000, 332.09000, 5.60800, 100.00000, 666.00000, 27.90000, + 7.40389, 18.10000, 0.59700, 1.45470, 24.00000, 20.20000, 314.64000, 5.61700, 97.90000, 666.00000, 17.20000, + 14.43830, 18.10000, 0.59700, 1.46550, 24.00000, 20.20000, 179.36000, 6.85200, 100.00000, 666.00000, 27.50000, + 51.13580, 18.10000, 0.59700, 1.41300, 24.00000, 20.20000, 2.60000, 5.75700, 100.00000, 666.00000, 15.00000, + 14.05070, 18.10000, 0.59700, 1.52750, 24.00000, 20.20000, 35.05000, 6.65700, 100.00000, 666.00000, 17.20000, + 18.81100, 18.10000, 0.59700, 1.55390, 24.00000, 20.20000, 28.79000, 4.62800, 100.00000, 666.00000, 17.90000, + 28.65580, 18.10000, 0.59700, 1.58940, 24.00000, 20.20000, 210.97000, 5.15500, 100.00000, 666.00000, 16.30000, + 45.74610, 18.10000, 0.69300, 1.65820, 24.00000, 20.20000, 88.27000, 4.51900, 100.00000, 666.00000, 7.00000, + 18.08460, 18.10000, 0.67900, 1.83470, 24.00000, 20.20000, 27.25000, 6.43400, 100.00000, 666.00000, 7.20000, + 10.83420, 18.10000, 0.67900, 1.81950, 24.00000, 20.20000, 21.57000, 6.78200, 90.80000, 666.00000, 7.50000, + 25.94060, 18.10000, 0.67900, 1.64750, 24.00000, 20.20000, 127.36000, 5.30400, 89.10000, 666.00000, 10.40000, + 73.53410, 18.10000, 0.67900, 1.80260, 24.00000, 20.20000, 16.45000, 5.95700, 100.00000, 666.00000, 8.80000, + 11.81230, 18.10000, 0.71800, 1.79400, 24.00000, 20.20000, 48.45000, 6.82400, 76.50000, 666.00000, 8.40000, + 11.08740, 18.10000, 0.71800, 1.85890, 24.00000, 20.20000, 318.75000, 6.41100, 100.00000, 666.00000, 16.70000, + 7.02259, 18.10000, 0.71800, 1.87460, 24.00000, 20.20000, 319.98000, 6.00600, 95.30000, 666.00000, 14.20000, + 12.04820, 18.10000, 0.61400, 1.95120, 24.00000, 20.20000, 291.55000, 5.64800, 87.60000, 666.00000, 20.80000, + 7.05042, 18.10000, 0.61400, 2.02180, 24.00000, 20.20000, 2.52000, 6.10300, 85.10000, 666.00000, 13.40000, + 8.79212, 18.10000, 0.58400, 2.06350, 24.00000, 20.20000, 3.65000, 5.56500, 70.60000, 666.00000, 11.70000, + 15.86030, 18.10000, 0.67900, 1.90960, 24.00000, 20.20000, 7.68000, 5.89600, 95.40000, 666.00000, 8.30000, + 12.24720, 18.10000, 0.58400, 1.99760, 24.00000, 20.20000, 24.65000, 5.83700, 59.70000, 666.00000, 10.20000, + 37.66190, 18.10000, 0.67900, 1.86290, 24.00000, 20.20000, 18.82000, 6.20200, 78.70000, 666.00000, 10.90000, + 7.36711, 18.10000, 0.67900, 1.93560, 24.00000, 20.20000, 96.73000, 6.19300, 78.10000, 666.00000, 11.00000, + 9.33889, 18.10000, 0.67900, 1.96820, 24.00000, 20.20000, 60.72000, 6.38000, 95.60000, 666.00000, 9.50000, + 8.49213, 18.10000, 0.58400, 2.05270, 24.00000, 20.20000, 83.45000, 6.34800, 86.10000, 666.00000, 14.50000, + 10.06230, 18.10000, 0.58400, 2.08820, 24.00000, 20.20000, 81.33000, 6.83300, 94.30000, 666.00000, 14.10000, + 6.44405, 18.10000, 0.58400, 2.20040, 24.00000, 20.20000, 97.95000, 6.42500, 74.80000, 666.00000, 16.10000, + 5.58107, 18.10000, 0.71300, 2.31580, 24.00000, 20.20000, 100.19000, 6.43600, 87.90000, 666.00000, 14.30000, + 13.91340, 18.10000, 0.71300, 2.22220, 24.00000, 20.20000, 100.63000, 6.20800, 95.00000, 666.00000, 11.70000, + 11.16040, 18.10000, 0.74000, 2.12470, 24.00000, 20.20000, 109.85000, 6.62900, 94.60000, 666.00000, 13.40000, + 14.42080, 18.10000, 0.74000, 2.00260, 24.00000, 20.20000, 27.49000, 6.46100, 93.30000, 666.00000, 9.60000, + 15.17720, 18.10000, 0.74000, 1.91420, 24.00000, 20.20000, 9.32000, 6.15200, 100.00000, 666.00000, 8.70000, + 13.67810, 18.10000, 0.74000, 1.82060, 24.00000, 20.20000, 68.95000, 5.93500, 87.90000, 666.00000, 8.40000, + 9.39063, 18.10000, 0.74000, 1.81720, 24.00000, 20.20000, 396.90000, 5.62700, 93.90000, 666.00000, 12.80000, + 22.05110, 18.10000, 0.74000, 1.86620, 24.00000, 20.20000, 391.45000, 5.81800, 92.40000, 666.00000, 10.50000, + 9.72418, 18.10000, 0.74000, 2.06510, 24.00000, 20.20000, 385.96000, 6.40600, 97.20000, 666.00000, 17.10000, + 5.66637, 18.10000, 0.74000, 2.00480, 24.00000, 20.20000, 395.69000, 6.21900, 100.00000, 666.00000, 18.40000, + 9.96654, 18.10000, 0.74000, 1.97840, 24.00000, 20.20000, 386.73000, 6.48500, 100.00000, 666.00000, 15.40000, + 12.80230, 18.10000, 0.74000, 1.89560, 24.00000, 20.20000, 240.52000, 5.85400, 96.60000, 666.00000, 10.80000, + 10.67180, 18.10000, 0.74000, 1.98790, 24.00000, 20.20000, 43.06000, 6.45900, 94.80000, 666.00000, 11.80000, + 6.28807, 18.10000, 0.74000, 2.07200, 24.00000, 20.20000, 318.01000, 6.34100, 96.40000, 666.00000, 14.90000, + 9.92485, 18.10000, 0.74000, 2.19800, 24.00000, 20.20000, 388.52000, 6.25100, 96.60000, 666.00000, 12.60000, + 9.32909, 18.10000, 0.71300, 2.26160, 24.00000, 20.20000, 396.90000, 6.18500, 98.70000, 666.00000, 14.10000, + 7.52601, 18.10000, 0.71300, 2.18500, 24.00000, 20.20000, 304.21000, 6.41700, 98.30000, 666.00000, 13.00000, + 6.71772, 18.10000, 0.71300, 2.32360, 24.00000, 20.20000, 0.32000, 6.74900, 92.60000, 666.00000, 13.40000, + 5.44114, 18.10000, 0.71300, 2.35520, 24.00000, 20.20000, 355.29000, 6.65500, 98.20000, 666.00000, 15.20000, + 5.09017, 18.10000, 0.71300, 2.36820, 24.00000, 20.20000, 385.09000, 6.29700, 91.80000, 666.00000, 16.10000, + 8.24809, 18.10000, 0.71300, 2.45270, 24.00000, 20.20000, 375.87000, 7.39300, 99.30000, 666.00000, 17.80000, + 9.51363, 18.10000, 0.71300, 2.49610, 24.00000, 20.20000, 6.68000, 6.72800, 94.10000, 666.00000, 14.90000, + 4.75237, 18.10000, 0.71300, 2.43580, 24.00000, 20.20000, 50.92000, 6.52500, 86.50000, 666.00000, 14.10000, + 4.66883, 18.10000, 0.71300, 2.58060, 24.00000, 20.20000, 10.48000, 5.97600, 87.90000, 666.00000, 12.70000, + 8.20058, 18.10000, 0.71300, 2.77920, 24.00000, 20.20000, 3.50000, 5.93600, 80.30000, 666.00000, 13.50000, + 7.75223, 18.10000, 0.71300, 2.78310, 24.00000, 20.20000, 272.21000, 6.30100, 83.70000, 666.00000, 14.90000, + 6.80117, 18.10000, 0.71300, 2.71750, 24.00000, 20.20000, 396.90000, 6.08100, 84.40000, 666.00000, 20.00000, + 4.81213, 18.10000, 0.71300, 2.59750, 24.00000, 20.20000, 255.23000, 6.70100, 90.00000, 666.00000, 16.40000, + 3.69311, 18.10000, 0.71300, 2.56710, 24.00000, 20.20000, 391.43000, 6.37600, 88.40000, 666.00000, 17.70000, + 6.65492, 18.10000, 0.71300, 2.73440, 24.00000, 20.20000, 396.90000, 6.31700, 83.00000, 666.00000, 19.50000, + 5.82115, 18.10000, 0.71300, 2.80160, 24.00000, 20.20000, 393.82000, 6.51300, 89.90000, 666.00000, 20.20000, + 7.83932, 18.10000, 0.65500, 2.96340, 24.00000, 20.20000, 396.90000, 6.20900, 65.40000, 666.00000, 21.40000, + 3.16360, 18.10000, 0.65500, 3.06650, 24.00000, 20.20000, 334.40000, 5.75900, 48.20000, 666.00000, 19.90000, + 3.77498, 18.10000, 0.65500, 2.87150, 24.00000, 20.20000, 22.01000, 5.95200, 84.70000, 666.00000, 19.00000, + 4.42228, 18.10000, 0.58400, 2.54030, 24.00000, 20.20000, 331.29000, 6.00300, 94.50000, 666.00000, 19.10000, + 15.57570, 18.10000, 0.58000, 2.90840, 24.00000, 20.20000, 368.74000, 5.92600, 71.00000, 666.00000, 19.10000, + 13.07510, 18.10000, 0.58000, 2.82370, 24.00000, 20.20000, 396.90000, 5.71300, 56.70000, 666.00000, 20.10000, + 4.34879, 18.10000, 0.58000, 3.03340, 24.00000, 20.20000, 396.90000, 6.16700, 84.00000, 666.00000, 19.90000, + 4.03841, 18.10000, 0.53200, 3.09930, 24.00000, 20.20000, 395.33000, 6.22900, 90.70000, 666.00000, 19.60000, + 3.56868, 18.10000, 0.58000, 2.89650, 24.00000, 20.20000, 393.37000, 6.43700, 75.00000, 666.00000, 23.20000, + 4.64689, 18.10000, 0.61400, 2.53290, 24.00000, 20.20000, 374.68000, 6.98000, 67.60000, 666.00000, 29.80000, + 8.05579, 18.10000, 0.58400, 2.42980, 24.00000, 20.20000, 352.58000, 5.42700, 95.40000, 666.00000, 13.80000, + 6.39312, 18.10000, 0.58400, 2.20600, 24.00000, 20.20000, 302.76000, 6.16200, 97.40000, 666.00000, 13.30000, + 4.87141, 18.10000, 0.61400, 2.30530, 24.00000, 20.20000, 396.21000, 6.48400, 93.60000, 666.00000, 16.70000, + 15.02340, 18.10000, 0.61400, 2.10070, 24.00000, 20.20000, 349.48000, 5.30400, 97.30000, 666.00000, 12.00000, + 10.23300, 18.10000, 0.61400, 2.17050, 24.00000, 20.20000, 379.70000, 6.18500, 96.70000, 666.00000, 14.60000, + 14.33370, 18.10000, 0.61400, 1.95120, 24.00000, 20.20000, 383.32000, 6.22900, 88.00000, 666.00000, 21.40000, + 5.82401, 18.10000, 0.53200, 3.42420, 24.00000, 20.20000, 396.90000, 6.24200, 64.70000, 666.00000, 23.00000, + 5.70818, 18.10000, 0.53200, 3.33170, 24.00000, 20.20000, 393.07000, 6.75000, 74.90000, 666.00000, 23.70000, + 5.73116, 18.10000, 0.53200, 3.41060, 24.00000, 20.20000, 395.28000, 7.06100, 77.00000, 666.00000, 25.00000, + 2.81838, 18.10000, 0.53200, 4.09830, 24.00000, 20.20000, 392.92000, 5.76200, 40.30000, 666.00000, 21.80000, + 2.37857, 18.10000, 0.58300, 3.72400, 24.00000, 20.20000, 370.73000, 5.87100, 41.90000, 666.00000, 20.60000, + 3.67367, 18.10000, 0.58300, 3.99170, 24.00000, 20.20000, 388.62000, 6.31200, 51.90000, 666.00000, 21.20000, + 5.69175, 18.10000, 0.58300, 3.54590, 24.00000, 20.20000, 392.68000, 6.11400, 79.80000, 666.00000, 19.10000, + 4.83567, 18.10000, 0.58300, 3.15230, 24.00000, 20.20000, 388.22000, 5.90500, 53.20000, 666.00000, 20.60000, + 0.15086, 27.74000, 0.60900, 1.82090, 4.00000, 20.10000, 395.09000, 5.45400, 92.70000, 711.00000, 15.20000, + 0.18337, 27.74000, 0.60900, 1.75540, 4.00000, 20.10000, 344.05000, 5.41400, 98.30000, 711.00000, 7.00000, + 0.20746, 27.74000, 0.60900, 1.82260, 4.00000, 20.10000, 318.43000, 5.09300, 98.00000, 711.00000, 8.10000, + 0.10574, 27.74000, 0.60900, 1.86810, 4.00000, 20.10000, 390.11000, 5.98300, 98.80000, 711.00000, 13.60000, + 0.11132, 27.74000, 0.60900, 2.10990, 4.00000, 20.10000, 396.90000, 5.98300, 83.50000, 711.00000, 20.10000, + 0.17331, 9.69000, 0.58500, 2.38170, 6.00000, 19.20000, 396.90000, 5.70700, 54.00000, 391.00000, 21.80000, + 0.27957, 9.69000, 0.58500, 2.38170, 6.00000, 19.20000, 396.90000, 5.92600, 42.60000, 391.00000, 24.50000, + 0.17899, 9.69000, 0.58500, 2.79860, 6.00000, 19.20000, 393.29000, 5.67000, 28.80000, 391.00000, 23.10000, + 0.28960, 9.69000, 0.58500, 2.79860, 6.00000, 19.20000, 396.90000, 5.39000, 72.90000, 391.00000, 19.70000, + 0.26838, 9.69000, 0.58500, 2.89270, 6.00000, 19.20000, 396.90000, 5.79400, 70.60000, 391.00000, 18.30000, + 0.23912, 9.69000, 0.58500, 2.40910, 6.00000, 19.20000, 396.90000, 6.01900, 65.30000, 391.00000, 21.20000, + 0.17783, 9.69000, 0.58500, 2.39990, 6.00000, 19.20000, 395.77000, 5.56900, 73.50000, 391.00000, 17.50000, + 0.22438, 9.69000, 0.58500, 2.49820, 6.00000, 19.20000, 396.90000, 6.02700, 79.70000, 391.00000, 16.80000, + 0.06263, 11.93000, 0.57300, 2.47860, 1.00000, 21.00000, 391.99000, 6.59300, 69.10000, 273.00000, 22.40000, + 0.04527, 11.93000, 0.57300, 2.28750, 1.00000, 21.00000, 396.90000, 6.12000, 76.70000, 273.00000, 20.60000, + 0.06076, 11.93000, 0.57300, 2.16750, 1.00000, 21.00000, 396.90000, 6.97600, 91.00000, 273.00000, 23.90000, + 0.10959, 11.93000, 0.57300, 2.38890, 1.00000, 21.00000, 393.45000, 6.79400, 89.30000, 273.00000, 22.00000, + 0.04741, 11.93000, 0.57300, 2.50500, 1.00000, 21.00000, 396.90000, 6.03000, 80.80000, 273.00000, 11.90000, +}) diff --git a/stat/car_data_test.go b/stat/car_data_test.go new file mode 100644 index 00000000..d8761a24 --- /dev/null +++ b/stat/car_data_test.go @@ -0,0 +1,406 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat_test + +import "gonum.org/v1/gonum/matrix/mat64" + +// ASA Car Exposition Data of Ramos and Donoho (1983) +// http://lib.stat.cmu.edu/datasets/cars.desc +// http://lib.stat.cmu.edu/datasets/cars.data +// Columns are: displacement, horsepower, weight, acceleration, MPG. +var carData = mat64.NewDense(392, 5, []float64{ + 307.0, 130.0, 3504.0, 12.0, 18.0, + 350.0, 165.0, 3693.0, 11.5, 15.0, + 318.0, 150.0, 3436.0, 11.0, 18.0, + 304.0, 150.0, 3433.0, 12.0, 16.0, + 302.0, 140.0, 3449.0, 10.5, 17.0, + 429.0, 198.0, 4341.0, 10.0, 15.0, + 454.0, 220.0, 4354.0, 9.0, 14.0, + 440.0, 215.0, 4312.0, 8.5, 14.0, + 455.0, 225.0, 4425.0, 10.0, 14.0, + 390.0, 190.0, 3850.0, 8.5, 15.0, + 383.0, 170.0, 3563.0, 10.0, 15.0, + 340.0, 160.0, 3609.0, 8.0, 14.0, + 400.0, 150.0, 3761.0, 9.5, 15.0, + 455.0, 225.0, 3086.0, 10.0, 14.0, + 113.0, 95.0, 2372.0, 15.0, 24.0, + 198.0, 95.0, 2833.0, 15.5, 22.0, + 199.0, 97.0, 2774.0, 15.5, 18.0, + 200.0, 85.0, 2587.0, 16.0, 21.0, + 97.0, 88.0, 2130.0, 14.5, 27.0, + 97.0, 46.0, 1835.0, 20.5, 26.0, + 110.0, 87.0, 2672.0, 17.5, 25.0, + 107.0, 90.0, 2430.0, 14.5, 24.0, + 104.0, 95.0, 2375.0, 17.5, 25.0, + 121.0, 113.0, 2234.0, 12.5, 26.0, + 199.0, 90.0, 2648.0, 15.0, 21.0, + 360.0, 215.0, 4615.0, 14.0, 10.0, + 307.0, 200.0, 4376.0, 15.0, 10.0, + 318.0, 210.0, 4382.0, 13.5, 11.0, + 304.0, 193.0, 4732.0, 18.5, 9.0, + 97.0, 88.0, 2130.0, 14.5, 27.0, + 140.0, 90.0, 2264.0, 15.5, 28.0, + 113.0, 95.0, 2228.0, 14.0, 25.0, + 232.0, 100.0, 2634.0, 13.0, 19.0, + 225.0, 105.0, 3439.0, 15.5, 16.0, + 250.0, 100.0, 3329.0, 15.5, 17.0, + 250.0, 88.0, 3302.0, 15.5, 19.0, + 232.0, 100.0, 3288.0, 15.5, 18.0, + 350.0, 165.0, 4209.0, 12.0, 14.0, + 400.0, 175.0, 4464.0, 11.5, 14.0, + 351.0, 153.0, 4154.0, 13.5, 14.0, + 318.0, 150.0, 4096.0, 13.0, 14.0, + 383.0, 180.0, 4955.0, 11.5, 12.0, + 400.0, 170.0, 4746.0, 12.0, 13.0, + 400.0, 175.0, 5140.0, 12.0, 13.0, + 258.0, 110.0, 2962.0, 13.5, 18.0, + 140.0, 72.0, 2408.0, 19.0, 22.0, + 250.0, 100.0, 3282.0, 15.0, 19.0, + 250.0, 88.0, 3139.0, 14.5, 18.0, + 122.0, 86.0, 2220.0, 14.0, 23.0, + 116.0, 90.0, 2123.0, 14.0, 28.0, + 79.0, 70.0, 2074.0, 19.5, 30.0, + 88.0, 76.0, 2065.0, 14.5, 30.0, + 71.0, 65.0, 1773.0, 19.0, 31.0, + 72.0, 69.0, 1613.0, 18.0, 35.0, + 97.0, 60.0, 1834.0, 19.0, 27.0, + 91.0, 70.0, 1955.0, 20.5, 26.0, + 113.0, 95.0, 2278.0, 15.5, 24.0, + 97.5, 80.0, 2126.0, 17.0, 25.0, + 97.0, 54.0, 2254.0, 23.5, 23.0, + 140.0, 90.0, 2408.0, 19.5, 20.0, + 122.0, 86.0, 2226.0, 16.5, 21.0, + 350.0, 165.0, 4274.0, 12.0, 13.0, + 400.0, 175.0, 4385.0, 12.0, 14.0, + 318.0, 150.0, 4135.0, 13.5, 15.0, + 351.0, 153.0, 4129.0, 13.0, 14.0, + 304.0, 150.0, 3672.0, 11.5, 17.0, + 429.0, 208.0, 4633.0, 11.0, 11.0, + 350.0, 155.0, 4502.0, 13.5, 13.0, + 350.0, 160.0, 4456.0, 13.5, 12.0, + 400.0, 190.0, 4422.0, 12.5, 13.0, + 70.0, 97.0, 2330.0, 13.5, 19.0, + 304.0, 150.0, 3892.0, 12.5, 15.0, + 307.0, 130.0, 4098.0, 14.0, 13.0, + 302.0, 140.0, 4294.0, 16.0, 13.0, + 318.0, 150.0, 4077.0, 14.0, 14.0, + 121.0, 112.0, 2933.0, 14.5, 18.0, + 121.0, 76.0, 2511.0, 18.0, 22.0, + 120.0, 87.0, 2979.0, 19.5, 21.0, + 96.0, 69.0, 2189.0, 18.0, 26.0, + 122.0, 86.0, 2395.0, 16.0, 22.0, + 97.0, 92.0, 2288.0, 17.0, 28.0, + 120.0, 97.0, 2506.0, 14.5, 23.0, + 98.0, 80.0, 2164.0, 15.0, 28.0, + 97.0, 88.0, 2100.0, 16.5, 27.0, + 350.0, 175.0, 4100.0, 13.0, 13.0, + 304.0, 150.0, 3672.0, 11.5, 14.0, + 350.0, 145.0, 3988.0, 13.0, 13.0, + 302.0, 137.0, 4042.0, 14.5, 14.0, + 318.0, 150.0, 3777.0, 12.5, 15.0, + 429.0, 198.0, 4952.0, 11.5, 12.0, + 400.0, 150.0, 4464.0, 12.0, 13.0, + 351.0, 158.0, 4363.0, 13.0, 13.0, + 318.0, 150.0, 4237.0, 14.5, 14.0, + 440.0, 215.0, 4735.0, 11.0, 13.0, + 455.0, 225.0, 4951.0, 11.0, 12.0, + 360.0, 175.0, 3821.0, 11.0, 13.0, + 225.0, 105.0, 3121.0, 16.5, 18.0, + 250.0, 100.0, 3278.0, 18.0, 16.0, + 232.0, 100.0, 2945.0, 16.0, 18.0, + 250.0, 88.0, 3021.0, 16.5, 18.0, + 198.0, 95.0, 2904.0, 16.0, 23.0, + 97.0, 46.0, 1950.0, 21.0, 26.0, + 400.0, 150.0, 4997.0, 14.0, 11.0, + 400.0, 167.0, 4906.0, 12.5, 12.0, + 360.0, 170.0, 4654.0, 13.0, 13.0, + 350.0, 180.0, 4499.0, 12.5, 12.0, + 232.0, 100.0, 2789.0, 15.0, 18.0, + 97.0, 88.0, 2279.0, 19.0, 20.0, + 140.0, 72.0, 2401.0, 19.5, 21.0, + 108.0, 94.0, 2379.0, 16.5, 22.0, + 70.0, 90.0, 2124.0, 13.5, 18.0, + 122.0, 85.0, 2310.0, 18.5, 19.0, + 155.0, 107.0, 2472.0, 14.0, 21.0, + 98.0, 90.0, 2265.0, 15.5, 26.0, + 350.0, 145.0, 4082.0, 13.0, 15.0, + 400.0, 230.0, 4278.0, 9.5, 16.0, + 68.0, 49.0, 1867.0, 19.5, 29.0, + 116.0, 75.0, 2158.0, 15.5, 24.0, + 114.0, 91.0, 2582.0, 14.0, 20.0, + 121.0, 112.0, 2868.0, 15.5, 19.0, + 318.0, 150.0, 3399.0, 11.0, 15.0, + 121.0, 110.0, 2660.0, 14.0, 24.0, + 156.0, 122.0, 2807.0, 13.5, 20.0, + 350.0, 180.0, 3664.0, 11.0, 11.0, + 198.0, 95.0, 3102.0, 16.5, 20.0, + 232.0, 100.0, 2901.0, 16.0, 19.0, + 250.0, 100.0, 3336.0, 17.0, 15.0, + 79.0, 67.0, 1950.0, 19.0, 31.0, + 122.0, 80.0, 2451.0, 16.5, 26.0, + 71.0, 65.0, 1836.0, 21.0, 32.0, + 140.0, 75.0, 2542.0, 17.0, 25.0, + 250.0, 100.0, 3781.0, 17.0, 16.0, + 258.0, 110.0, 3632.0, 18.0, 16.0, + 225.0, 105.0, 3613.0, 16.5, 18.0, + 302.0, 140.0, 4141.0, 14.0, 16.0, + 350.0, 150.0, 4699.0, 14.5, 13.0, + 318.0, 150.0, 4457.0, 13.5, 14.0, + 302.0, 140.0, 4638.0, 16.0, 14.0, + 304.0, 150.0, 4257.0, 15.5, 14.0, + 98.0, 83.0, 2219.0, 16.5, 29.0, + 79.0, 67.0, 1963.0, 15.5, 26.0, + 97.0, 78.0, 2300.0, 14.5, 26.0, + 76.0, 52.0, 1649.0, 16.5, 31.0, + 83.0, 61.0, 2003.0, 19.0, 32.0, + 90.0, 75.0, 2125.0, 14.5, 28.0, + 90.0, 75.0, 2108.0, 15.5, 24.0, + 116.0, 75.0, 2246.0, 14.0, 26.0, + 120.0, 97.0, 2489.0, 15.0, 24.0, + 108.0, 93.0, 2391.0, 15.5, 26.0, + 79.0, 67.0, 2000.0, 16.0, 31.0, + 225.0, 95.0, 3264.0, 16.0, 19.0, + 250.0, 105.0, 3459.0, 16.0, 18.0, + 250.0, 72.0, 3432.0, 21.0, 15.0, + 250.0, 72.0, 3158.0, 19.5, 15.0, + 400.0, 170.0, 4668.0, 11.5, 16.0, + 350.0, 145.0, 4440.0, 14.0, 15.0, + 318.0, 150.0, 4498.0, 14.5, 16.0, + 351.0, 148.0, 4657.0, 13.5, 14.0, + 231.0, 110.0, 3907.0, 21.0, 17.0, + 250.0, 105.0, 3897.0, 18.5, 16.0, + 258.0, 110.0, 3730.0, 19.0, 15.0, + 225.0, 95.0, 3785.0, 19.0, 18.0, + 231.0, 110.0, 3039.0, 15.0, 21.0, + 262.0, 110.0, 3221.0, 13.5, 20.0, + 302.0, 129.0, 3169.0, 12.0, 13.0, + 97.0, 75.0, 2171.0, 16.0, 29.0, + 140.0, 83.0, 2639.0, 17.0, 23.0, + 232.0, 100.0, 2914.0, 16.0, 20.0, + 140.0, 78.0, 2592.0, 18.5, 23.0, + 134.0, 96.0, 2702.0, 13.5, 24.0, + 90.0, 71.0, 2223.0, 16.5, 25.0, + 119.0, 97.0, 2545.0, 17.0, 24.0, + 171.0, 97.0, 2984.0, 14.5, 18.0, + 90.0, 70.0, 1937.0, 14.0, 29.0, + 232.0, 90.0, 3211.0, 17.0, 19.0, + 115.0, 95.0, 2694.0, 15.0, 23.0, + 120.0, 88.0, 2957.0, 17.0, 23.0, + 121.0, 98.0, 2945.0, 14.5, 22.0, + 121.0, 115.0, 2671.0, 13.5, 25.0, + 91.0, 53.0, 1795.0, 17.5, 33.0, + 107.0, 86.0, 2464.0, 15.5, 28.0, + 116.0, 81.0, 2220.0, 16.9, 25.0, + 140.0, 92.0, 2572.0, 14.9, 25.0, + 98.0, 79.0, 2255.0, 17.7, 26.0, + 101.0, 83.0, 2202.0, 15.3, 27.0, + 305.0, 140.0, 4215.0, 13.0, 17.5, + 318.0, 150.0, 4190.0, 13.0, 16.0, + 304.0, 120.0, 3962.0, 13.9, 15.5, + 351.0, 152.0, 4215.0, 12.8, 14.5, + 225.0, 100.0, 3233.0, 15.4, 22.0, + 250.0, 105.0, 3353.0, 14.5, 22.0, + 200.0, 81.0, 3012.0, 17.6, 24.0, + 232.0, 90.0, 3085.0, 17.6, 22.5, + 85.0, 52.0, 2035.0, 22.2, 29.0, + 98.0, 60.0, 2164.0, 22.1, 24.5, + 90.0, 70.0, 1937.0, 14.2, 29.0, + 91.0, 53.0, 1795.0, 17.4, 33.0, + 225.0, 100.0, 3651.0, 17.7, 20.0, + 250.0, 78.0, 3574.0, 21.0, 18.0, + 250.0, 110.0, 3645.0, 16.2, 18.5, + 258.0, 95.0, 3193.0, 17.8, 17.5, + 97.0, 71.0, 1825.0, 12.2, 29.5, + 85.0, 70.0, 1990.0, 17.0, 32.0, + 97.0, 75.0, 2155.0, 16.4, 28.0, + 140.0, 72.0, 2565.0, 13.6, 26.5, + 130.0, 102.0, 3150.0, 15.7, 20.0, + 318.0, 150.0, 3940.0, 13.2, 13.0, + 120.0, 88.0, 3270.0, 21.9, 19.0, + 156.0, 108.0, 2930.0, 15.5, 19.0, + 168.0, 120.0, 3820.0, 16.7, 16.5, + 350.0, 180.0, 4380.0, 12.1, 16.5, + 350.0, 145.0, 4055.0, 12.0, 13.0, + 302.0, 130.0, 3870.0, 15.0, 13.0, + 318.0, 150.0, 3755.0, 14.0, 13.0, + 98.0, 68.0, 2045.0, 18.5, 31.5, + 111.0, 80.0, 2155.0, 14.8, 30.0, + 79.0, 58.0, 1825.0, 18.6, 36.0, + 122.0, 96.0, 2300.0, 15.5, 25.5, + 85.0, 70.0, 1945.0, 16.8, 33.5, + 305.0, 145.0, 3880.0, 12.5, 17.5, + 260.0, 110.0, 4060.0, 19.0, 17.0, + 318.0, 145.0, 4140.0, 13.7, 15.5, + 302.0, 130.0, 4295.0, 14.9, 15.0, + 250.0, 110.0, 3520.0, 16.4, 17.5, + 231.0, 105.0, 3425.0, 16.9, 20.5, + 225.0, 100.0, 3630.0, 17.7, 19.0, + 250.0, 98.0, 3525.0, 19.0, 18.5, + 400.0, 180.0, 4220.0, 11.1, 16.0, + 350.0, 170.0, 4165.0, 11.4, 15.5, + 400.0, 190.0, 4325.0, 12.2, 15.5, + 351.0, 149.0, 4335.0, 14.5, 16.0, + 97.0, 78.0, 1940.0, 14.5, 29.0, + 151.0, 88.0, 2740.0, 16.0, 24.5, + 97.0, 75.0, 2265.0, 18.2, 26.0, + 140.0, 89.0, 2755.0, 15.8, 25.5, + 98.0, 63.0, 2051.0, 17.0, 30.5, + 98.0, 83.0, 2075.0, 15.9, 33.5, + 97.0, 67.0, 1985.0, 16.4, 30.0, + 97.0, 78.0, 2190.0, 14.1, 30.5, + 146.0, 97.0, 2815.0, 14.5, 22.0, + 121.0, 110.0, 2600.0, 12.8, 21.5, + 80.0, 110.0, 2720.0, 13.5, 21.5, + 90.0, 48.0, 1985.0, 21.5, 43.1, + 98.0, 66.0, 1800.0, 14.4, 36.1, + 78.0, 52.0, 1985.0, 19.4, 32.8, + 85.0, 70.0, 2070.0, 18.6, 39.4, + 91.0, 60.0, 1800.0, 16.4, 36.1, + 260.0, 110.0, 3365.0, 15.5, 19.9, + 318.0, 140.0, 3735.0, 13.2, 19.4, + 302.0, 139.0, 3570.0, 12.8, 20.2, + 231.0, 105.0, 3535.0, 19.2, 19.2, + 200.0, 95.0, 3155.0, 18.2, 20.5, + 200.0, 85.0, 2965.0, 15.8, 20.2, + 140.0, 88.0, 2720.0, 15.4, 25.1, + 225.0, 100.0, 3430.0, 17.2, 20.5, + 232.0, 90.0, 3210.0, 17.2, 19.4, + 231.0, 105.0, 3380.0, 15.8, 20.6, + 200.0, 85.0, 3070.0, 16.7, 20.8, + 225.0, 110.0, 3620.0, 18.7, 18.6, + 258.0, 120.0, 3410.0, 15.1, 18.1, + 305.0, 145.0, 3425.0, 13.2, 19.2, + 231.0, 165.0, 3445.0, 13.4, 17.7, + 302.0, 139.0, 3205.0, 11.2, 18.1, + 318.0, 140.0, 4080.0, 13.7, 17.5, + 98.0, 68.0, 2155.0, 16.5, 30.0, + 134.0, 95.0, 2560.0, 14.2, 27.5, + 119.0, 97.0, 2300.0, 14.7, 27.2, + 105.0, 75.0, 2230.0, 14.5, 30.9, + 134.0, 95.0, 2515.0, 14.8, 21.1, + 156.0, 105.0, 2745.0, 16.7, 23.2, + 151.0, 85.0, 2855.0, 17.6, 23.8, + 119.0, 97.0, 2405.0, 14.9, 23.9, + 131.0, 103.0, 2830.0, 15.9, 20.3, + 163.0, 125.0, 3140.0, 13.6, 17.0, + 121.0, 115.0, 2795.0, 15.7, 21.6, + 163.0, 133.0, 3410.0, 15.8, 16.2, + 89.0, 71.0, 1990.0, 14.9, 31.5, + 98.0, 68.0, 2135.0, 16.6, 29.5, + 231.0, 115.0, 3245.0, 15.4, 21.5, + 200.0, 85.0, 2990.0, 18.2, 19.8, + 140.0, 88.0, 2890.0, 17.3, 22.3, + 232.0, 90.0, 3265.0, 18.2, 20.2, + 225.0, 110.0, 3360.0, 16.6, 20.6, + 305.0, 130.0, 3840.0, 15.4, 17.0, + 302.0, 129.0, 3725.0, 13.4, 17.6, + 351.0, 138.0, 3955.0, 13.2, 16.5, + 318.0, 135.0, 3830.0, 15.2, 18.2, + 350.0, 155.0, 4360.0, 14.9, 16.9, + 351.0, 142.0, 4054.0, 14.3, 15.5, + 267.0, 125.0, 3605.0, 15.0, 19.2, + 360.0, 150.0, 3940.0, 13.0, 18.5, + 89.0, 71.0, 1925.0, 14.0, 31.9, + 86.0, 65.0, 1975.0, 15.2, 34.1, + 98.0, 80.0, 1915.0, 14.4, 35.7, + 121.0, 80.0, 2670.0, 15.0, 27.4, + 183.0, 77.0, 3530.0, 20.1, 25.4, + 350.0, 125.0, 3900.0, 17.4, 23.0, + 141.0, 71.0, 3190.0, 24.8, 27.2, + 260.0, 90.0, 3420.0, 22.2, 23.9, + 105.0, 70.0, 2200.0, 13.2, 34.2, + 105.0, 70.0, 2150.0, 14.9, 34.5, + 85.0, 65.0, 2020.0, 19.2, 31.8, + 91.0, 69.0, 2130.0, 14.7, 37.3, + 151.0, 90.0, 2670.0, 16.0, 28.4, + 173.0, 115.0, 2595.0, 11.3, 28.8, + 173.0, 115.0, 2700.0, 12.9, 26.8, + 151.0, 90.0, 2556.0, 13.2, 33.5, + 98.0, 76.0, 2144.0, 14.7, 41.5, + 89.0, 60.0, 1968.0, 18.8, 38.1, + 98.0, 70.0, 2120.0, 15.5, 32.1, + 86.0, 65.0, 2019.0, 16.4, 37.2, + 151.0, 90.0, 2678.0, 16.5, 28.0, + 140.0, 88.0, 2870.0, 18.1, 26.4, + 151.0, 90.0, 3003.0, 20.1, 24.3, + 225.0, 90.0, 3381.0, 18.7, 19.1, + 97.0, 78.0, 2188.0, 15.8, 34.3, + 134.0, 90.0, 2711.0, 15.5, 29.8, + 120.0, 75.0, 2542.0, 17.5, 31.3, + 119.0, 92.0, 2434.0, 15.0, 37.0, + 108.0, 75.0, 2265.0, 15.2, 32.2, + 86.0, 65.0, 2110.0, 17.9, 46.6, + 156.0, 105.0, 2800.0, 14.4, 27.9, + 85.0, 65.0, 2110.0, 19.2, 40.8, + 90.0, 48.0, 2085.0, 21.7, 44.3, + 90.0, 48.0, 2335.0, 23.7, 43.4, + 121.0, 67.0, 2950.0, 19.9, 36.4, + 146.0, 67.0, 3250.0, 21.8, 30.0, + 91.0, 67.0, 1850.0, 13.8, 44.6, + 97.0, 67.0, 2145.0, 18.0, 33.8, + 89.0, 62.0, 1845.0, 15.3, 29.8, + 168.0, 132.0, 2910.0, 11.4, 32.7, + 70.0, 100.0, 2420.0, 12.5, 23.7, + 122.0, 88.0, 2500.0, 15.1, 35.0, + 107.0, 72.0, 2290.0, 17.0, 32.4, + 135.0, 84.0, 2490.0, 15.7, 27.2, + 151.0, 84.0, 2635.0, 16.4, 26.6, + 156.0, 92.0, 2620.0, 14.4, 25.8, + 173.0, 110.0, 2725.0, 12.6, 23.5, + 135.0, 84.0, 2385.0, 12.9, 30.0, + 79.0, 58.0, 1755.0, 16.9, 39.1, + 86.0, 64.0, 1875.0, 16.4, 39.0, + 81.0, 60.0, 1760.0, 16.1, 35.1, + 97.0, 67.0, 2065.0, 17.8, 32.3, + 85.0, 65.0, 1975.0, 19.4, 37.0, + 89.0, 62.0, 2050.0, 17.3, 37.7, + 91.0, 68.0, 1985.0, 16.0, 34.1, + 105.0, 63.0, 2215.0, 14.9, 34.7, + 98.0, 65.0, 2045.0, 16.2, 34.4, + 98.0, 65.0, 2380.0, 20.7, 29.9, + 105.0, 74.0, 2190.0, 14.2, 33.0, + 107.0, 75.0, 2210.0, 14.4, 33.7, + 108.0, 75.0, 2350.0, 16.8, 32.4, + 119.0, 100.0, 2615.0, 14.8, 32.9, + 120.0, 74.0, 2635.0, 18.3, 31.6, + 141.0, 80.0, 3230.0, 20.4, 28.1, + 145.0, 76.0, 3160.0, 19.6, 30.7, + 168.0, 116.0, 2900.0, 12.6, 25.4, + 146.0, 120.0, 2930.0, 13.8, 24.2, + 231.0, 110.0, 3415.0, 15.8, 22.4, + 350.0, 105.0, 3725.0, 19.0, 26.6, + 200.0, 88.0, 3060.0, 17.1, 20.2, + 225.0, 85.0, 3465.0, 16.6, 17.6, + 112.0, 88.0, 2605.0, 19.6, 28.0, + 112.0, 88.0, 2640.0, 18.6, 27.0, + 112.0, 88.0, 2395.0, 18.0, 34.0, + 112.0, 85.0, 2575.0, 16.2, 31.0, + 135.0, 84.0, 2525.0, 16.0, 29.0, + 151.0, 90.0, 2735.0, 18.0, 27.0, + 140.0, 92.0, 2865.0, 16.4, 24.0, + 105.0, 74.0, 1980.0, 15.3, 36.0, + 91.0, 68.0, 2025.0, 18.2, 37.0, + 91.0, 68.0, 1970.0, 17.6, 31.0, + 105.0, 63.0, 2125.0, 14.7, 38.0, + 98.0, 70.0, 2125.0, 17.3, 36.0, + 120.0, 88.0, 2160.0, 14.5, 36.0, + 107.0, 75.0, 2205.0, 14.5, 36.0, + 108.0, 70.0, 2245.0, 16.9, 34.0, + 91.0, 67.0, 1965.0, 15.0, 38.0, + 91.0, 67.0, 1965.0, 15.7, 32.0, + 91.0, 67.0, 1995.0, 16.2, 38.0, + 181.0, 110.0, 2945.0, 16.4, 25.0, + 262.0, 85.0, 3015.0, 17.0, 38.0, + 156.0, 92.0, 2585.0, 14.5, 26.0, + 232.0, 112.0, 2835.0, 14.7, 22.0, + 144.0, 96.0, 2665.0, 13.9, 32.0, + 135.0, 84.0, 2370.0, 13.0, 36.0, + 151.0, 90.0, 2950.0, 17.3, 27.0, + 140.0, 86.0, 2790.0, 15.6, 27.0, + 97.0, 52.0, 2130.0, 24.6, 44.0, + 135.0, 84.0, 2295.0, 11.6, 32.0, + 120.0, 79.0, 2625.0, 18.6, 28.0, + 119.0, 82.0, 2720.0, 19.4, 31.0, +}) diff --git a/stat/cca_example_test.go b/stat/cca_example_test.go new file mode 100644 index 00000000..3d311f02 --- /dev/null +++ b/stat/cca_example_test.go @@ -0,0 +1,165 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat_test + +import ( + "fmt" + "log" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat" +) + +// symView is a helper for getting a View of a SymDense. +type symView struct { + sym *mat64.SymDense + + i, j, r, c int +} + +func (s symView) Dims() (r, c int) { return s.r, s.c } + +func (s symView) At(i, j int) float64 { + if i < 0 || s.r <= i { + panic("i out of bounds") + } + if j < 0 || s.c <= j { + panic("j out of bounds") + } + return s.sym.At(s.i+i, s.j+j) +} + +func (s symView) T() mat64.Matrix { return mat64.Transpose{s} } + +func ExampleCC() { + // This example is directly analogous to Example 3.5 on page 87 of + // Koch, Inge. Analysis of multivariate and high-dimensional data. + // Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939 + + // bostonData is the Boston Housing Data of Harrison and Rubinfeld (1978) + n, _ := bostonData.Dims() + var xd, yd = 7, 4 + // The variables (columns) of bostonData can be partitioned into two sets: + // those that deal with environmental/social variables (xdata), and those + // that contain information regarding the individual (ydata). Because the + // variables can be naturally partitioned in this way, these data are + // appropriate for canonical correlation analysis. The columns (variables) + // of xdata are, in order: + // per capita crime rate by town, + // proportion of non-retail business acres per town, + // nitric oxide concentration (parts per 10 million), + // weighted distances to Boston employment centres, + // index of accessibility to radial highways, + // pupil-teacher ratio by town, and + // proportion of blacks by town. + xdata := bostonData.Slice(0, n, 0, xd) + + // The columns (variables) of ydata are, in order: + // average number of rooms per dwelling, + // proportion of owner-occupied units built prior to 1940, + // full-value property-tax rate per $10000, and + // median value of owner-occupied homes in $1000s. + ydata := bostonData.Slice(0, n, xd, xd+yd) + + // For comparison, calculate the correlation matrix for the original data. + var cor mat64.SymDense + stat.CorrelationMatrix(&cor, bostonData, nil) + + // Extract just those correlations that are between xdata and ydata. + var corRaw = symView{sym: &cor, i: 0, j: xd, r: xd, c: yd} + + // Note that the strongest correlation between individual variables is 0.91 + // between the 5th variable of xdata (index of accessibility to radial + // highways) and the 3rd variable of ydata (full-value property-tax rate per + // $10000). + fmt.Printf("corRaw = %.4f", mat64.Formatted(corRaw, mat64.Prefix(" "))) + + // Calculate the canonical correlations. + var cc stat.CC + err := cc.CanonicalCorrelations(xdata, ydata, nil) + if err != nil { + log.Fatal(err) + } + + // Unpack cc. + ccors := cc.Corrs(nil) + pVecs := cc.Left(nil, true) + qVecs := cc.Right(nil, true) + phiVs := cc.Left(nil, false) + psiVs := cc.Right(nil, false) + + // Canonical Correlation Matrix, or the correlations between the sphered + // data. + var corSph mat64.Dense + corSph.Clone(pVecs) + col := make([]float64, xd) + for j := 0; j < yd; j++ { + mat64.Col(col, j, &corSph) + floats.Scale(ccors[j], col) + corSph.SetCol(j, col) + } + corSph.Product(&corSph, qVecs.T()) + fmt.Printf("\n\ncorSph = %.4f", mat64.Formatted(&corSph, mat64.Prefix(" "))) + + // Canonical Correlations. Note that the first canonical correlation is + // 0.95, stronger than the greatest correlation in the original data, and + // much stronger than the greatest correlation in the sphered data. + fmt.Printf("\n\nccors = %.4f", ccors) + + // Left and right eigenvectors of the canonical correlation matrix. + fmt.Printf("\n\npVecs = %.4f", mat64.Formatted(pVecs, mat64.Prefix(" "))) + fmt.Printf("\n\nqVecs = %.4f", mat64.Formatted(qVecs, mat64.Prefix(" "))) + + // Canonical Correlation Transforms. These can be useful as they represent + // the canonical variables as linear combinations of the original variables. + fmt.Printf("\n\nphiVs = %.4f", mat64.Formatted(phiVs, mat64.Prefix(" "))) + fmt.Printf("\n\npsiVs = %.4f", mat64.Formatted(psiVs, mat64.Prefix(" "))) + + // Output: + // corRaw = ⎡-0.2192 0.3527 0.5828 -0.3883⎤ + // ⎢-0.3917 0.6448 0.7208 -0.4837⎥ + // ⎢-0.3022 0.7315 0.6680 -0.4273⎥ + // ⎢ 0.2052 -0.7479 -0.5344 0.2499⎥ + // ⎢-0.2098 0.4560 0.9102 -0.3816⎥ + // ⎢-0.3555 0.2615 0.4609 -0.5078⎥ + // ⎣ 0.1281 -0.2735 -0.4418 0.3335⎦ + // + // corSph = ⎡ 0.0118 0.0525 0.2300 -0.1363⎤ + // ⎢-0.1810 0.3213 0.3814 -0.1412⎥ + // ⎢ 0.0166 0.2241 0.0104 -0.2235⎥ + // ⎢ 0.0346 -0.5481 -0.0034 -0.1994⎥ + // ⎢ 0.0303 -0.0956 0.7152 0.2039⎥ + // ⎢-0.0298 -0.0022 0.0739 -0.3703⎥ + // ⎣-0.1226 -0.0746 -0.3899 0.1541⎦ + // + // ccors = [0.9451 0.6787 0.5714 0.2010] + // + // pVecs = ⎡-0.2574 0.0158 0.2122 -0.0946⎤ + // ⎢-0.4837 0.3837 0.1474 0.6597⎥ + // ⎢-0.0801 0.3494 0.3287 -0.2862⎥ + // ⎢ 0.1278 -0.7337 0.4851 0.2248⎥ + // ⎢-0.6969 -0.4342 -0.3603 0.0291⎥ + // ⎢-0.0991 0.0503 0.6384 0.1022⎥ + // ⎣ 0.4260 0.0323 -0.2290 0.6419⎦ + // + // qVecs = ⎡ 0.0182 -0.1583 -0.0067 -0.9872⎤ + // ⎢-0.2348 0.9483 -0.1462 -0.1554⎥ + // ⎢-0.9701 -0.2406 -0.0252 0.0209⎥ + // ⎣ 0.0593 -0.1330 -0.9889 0.0291⎦ + // + // phiVs = ⎡-0.0027 0.0093 0.0490 -0.0155⎤ + // ⎢-0.0429 -0.0242 0.0361 0.1839⎥ + // ⎢-1.2248 5.6031 5.8094 -4.7927⎥ + // ⎢-0.0044 -0.3424 0.4470 0.1150⎥ + // ⎢-0.0742 -0.1193 -0.1116 0.0022⎥ + // ⎢-0.0233 0.1046 0.3853 -0.0161⎥ + // ⎣ 0.0001 0.0005 -0.0030 0.0082⎦ + // + // psiVs = ⎡ 0.0302 -0.3002 0.0878 -1.9583⎤ + // ⎢-0.0065 0.0392 -0.0118 -0.0061⎥ + // ⎢-0.0052 -0.0046 -0.0023 0.0008⎥ + // ⎣ 0.0020 0.0037 -0.1293 0.1038⎦ +} diff --git a/stat/cca_test.go b/stat/cca_test.go new file mode 100644 index 00000000..149f37da --- /dev/null +++ b/stat/cca_test.go @@ -0,0 +1,191 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat_test + +import ( + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat" +) + +func TestCanonicalCorrelations(t *testing.T) { +tests: + for i, test := range []struct { + xdata mat64.Matrix + ydata mat64.Matrix + weights []float64 + wantCorrs []float64 + wantpVecs *mat64.Dense + wantqVecs *mat64.Dense + wantphiVs *mat64.Dense + wantpsiVs *mat64.Dense + epsilon float64 + }{ + // Test results verified using R. + { // Truncated iris data, Sepal vs Petal measurements. + xdata: mat64.NewDense(10, 2, []float64{ + 5.1, 3.5, + 4.9, 3.0, + 4.7, 3.2, + 4.6, 3.1, + 5.0, 3.6, + 5.4, 3.9, + 4.6, 3.4, + 5.0, 3.4, + 4.4, 2.9, + 4.9, 3.1, + }), + ydata: mat64.NewDense(10, 2, []float64{ + 1.4, 0.2, + 1.4, 0.2, + 1.3, 0.2, + 1.5, 0.2, + 1.4, 0.2, + 1.7, 0.4, + 1.4, 0.3, + 1.5, 0.2, + 1.4, 0.2, + 1.5, 0.1, + }), + wantCorrs: []float64{0.7250624174504773, 0.5547679185730191}, + wantpVecs: mat64.NewDense(2, 2, []float64{ + 0.0765914610875867, 0.9970625597666721, + 0.9970625597666721, -0.0765914610875868, + }), + wantqVecs: mat64.NewDense(2, 2, []float64{ + 0.3075184850910837, 0.9515421069649439, + 0.9515421069649439, -0.3075184850910837, + }), + wantphiVs: mat64.NewDense(2, 2, []float64{ + -1.9794877596804641, 5.2016325219025124, + 4.5211829944066553, -2.7263663170835697, + }), + wantpsiVs: mat64.NewDense(2, 2, []float64{ + -0.0613084818030103, 10.8514169865438941, + 12.7209032660734298, -7.6793888180353775, + }), + epsilon: 1e-12, + }, + // Test results compared to those results presented in examples by + // Koch, Inge. Analysis of multivariate and high-dimensional data. + // Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939 + { // ASA Car Exposition Data of Ramos and Donoho (1983) + // Displacement, Horsepower, Weight + xdata: carData.Slice(0, 392, 0, 3), + // Acceleration, MPG + ydata: carData.Slice(0, 392, 3, 5), + wantCorrs: []float64{0.8782187384352336, 0.6328187219216761}, + wantpVecs: mat64.NewDense(3, 2, []float64{ + 0.3218296374829181, 0.3947540257657075, + 0.4162807660635797, 0.7573719053303306, + 0.8503740401982725, -0.5201509936144236, + }), + wantqVecs: mat64.NewDense(2, 2, []float64{ + -0.5161984172278830, -0.8564690269072364, + -0.8564690269072364, 0.5161984172278830, + }), + wantphiVs: mat64.NewDense(3, 2, []float64{ + 0.0025033152994308, 0.0047795464118615, + 0.0201923608080173, 0.0409150208725958, + -0.0000247374128745, -0.0026766435161875, + }), + wantpsiVs: mat64.NewDense(2, 2, []float64{ + -0.1666196759760772, -0.3637393866139658, + -0.0915512109649727, 0.1077863777929168, + }), + epsilon: 1e-12, + }, + // Test results compared to those results presented in examples by + // Koch, Inge. Analysis of multivariate and high-dimensional data. + // Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939 + { // Boston Housing Data of Harrison and Rubinfeld (1978) + // Per capita crime rate by town, + // Proportion of non-retail business acres per town, + // Nitric oxide concentration (parts per 10 million), + // Weighted distances to Boston employment centres, + // Index of accessibility to radial highways, + // Pupil-teacher ratio by town, Proportion of blacks by town + xdata: bostonData.Slice(0, 506, 0, 7), + // Average number of rooms per dwelling, + // Proportion of owner-occupied units built prior to 1940, + // Full-value property-tax rate per $10000, + // Median value of owner-occupied homes in $1000s + ydata: bostonData.Slice(0, 506, 7, 11), + wantCorrs: []float64{0.9451239443886021, 0.6786622733370654, 0.5714338361583764, 0.2009739704710440}, + wantpVecs: mat64.NewDense(7, 4, []float64{ + -0.2574391924541903, 0.0158477516621194, 0.2122169934631024, -0.0945733803894706, + -0.4836594430018478, 0.3837101908138468, 0.1474448317415911, 0.6597324886718275, + -0.0800776365873296, 0.3493556742809252, 0.3287336458109373, -0.2862040444334655, + 0.1277586360386374, -0.7337427663667596, 0.4851134819037011, 0.2247964865970192, + -0.6969432006136684, -0.4341748776002893, -0.3602872887636357, 0.0290661608626292, + -0.0990903250057199, 0.0503411215453873, 0.6384330631742202, 0.1022367136218303, + 0.4260459963765036, 0.0323334351308141, -0.2289527516030810, 0.6419232947608805, + }), + wantqVecs: mat64.NewDense(4, 4, []float64{ + 0.0181660502363264, -0.1583489460479038, -0.0066723577642883, -0.9871935400650649, + -0.2347699045986119, 0.9483314614936594, -0.1462420505631345, -0.1554470767919033, + -0.9700704038477141, -0.2406071741000039, -0.0251838984227037, 0.0209134074358349, + 0.0593000682318482, -0.1330460003097728, -0.9889057151969489, 0.0291161494720761, + }), + wantphiVs: mat64.NewDense(7, 4, []float64{ + -0.0027462234108197, 0.0093444513500898, 0.0489643932714296, -0.0154967189805819, + -0.0428564455279537, -0.0241708702119420, 0.0360723472093996, 0.1838983230588095, + -1.2248435648802380, 5.6030921364723980, 5.8094144583797025, -4.7926812190419676, + -0.0043684825094649, -0.3424101164977618, 0.4469961215717917, 0.1150161814353696, + -0.0741534069521954, -0.1193135794923700, -0.1115518305471460, 0.0021638758323088, + -0.0233270323101624, 0.1046330818178399, 0.3853045975077387, -0.0160927870102877, + 0.0001293051387859, 0.0004540746921446, -0.0030296315865440, 0.0081895477974654, + }), + wantpsiVs: mat64.NewDense(4, 4, []float64{ + 0.0301593362017375, -0.3002219289647127, 0.0878217377593682, -1.9583226531517062, + -0.0065483104073892, 0.0392212086716247, -0.0117570776209991, -0.0061113064481860, + -0.0052075523350125, -0.0045770200452960, -0.0022762313289592, 0.0008441873006821, + 0.0020111735096327, 0.0037352799829930, -0.1292578071621794, 0.1037709056329765, + }), + epsilon: 1e-12, + }, + } { + var cc stat.CC + var corrs []float64 + var pVecs, qVecs *mat64.Dense + var phiVs, psiVs *mat64.Dense + for j := 0; j < 2; j++ { + err := cc.CanonicalCorrelations(test.xdata, test.ydata, test.weights) + if err != nil { + t.Errorf("%d use %d: unexpected error: %v", i, j, err) + continue tests + } + + corrs = cc.Corrs(corrs) + pVecs = cc.Left(pVecs, true) + qVecs = cc.Right(qVecs, true) + phiVs = cc.Left(phiVs, false) + psiVs = cc.Right(psiVs, false) + + if !floats.EqualApprox(corrs, test.wantCorrs, test.epsilon) { + t.Errorf("%d use %d: unexpected variance result got:%v, want:%v", + i, j, corrs, test.wantCorrs) + } + if !mat64.EqualApprox(pVecs, test.wantpVecs, test.epsilon) { + t.Errorf("%d use %d: unexpected CCA result got:\n%v\nwant:\n%v", + i, j, mat64.Formatted(pVecs), mat64.Formatted(test.wantpVecs)) + } + if !mat64.EqualApprox(qVecs, test.wantqVecs, test.epsilon) { + t.Errorf("%d use %d: unexpected CCA result got:\n%v\nwant:\n%v", + i, j, mat64.Formatted(qVecs), mat64.Formatted(test.wantqVecs)) + } + if !mat64.EqualApprox(phiVs, test.wantphiVs, test.epsilon) { + t.Errorf("%d use %d: unexpected CCA result got:\n%v\nwant:\n%v", + i, j, mat64.Formatted(phiVs), mat64.Formatted(test.wantphiVs)) + } + if !mat64.EqualApprox(psiVs, test.wantpsiVs, test.epsilon) { + t.Errorf("%d use %d: unexpected CCA result got:\n%v\nwant:\n%v", + i, j, mat64.Formatted(psiVs), mat64.Formatted(test.wantpsiVs)) + } + } + } +} diff --git a/stat/combin/combin.go b/stat/combin/combin.go new file mode 100644 index 00000000..4dba68f2 --- /dev/null +++ b/stat/combin/combin.go @@ -0,0 +1,183 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package combin implements routines involving combinatorics (permutations, +// combinations, etc.). +package combin + +import "math" + +const ( + badNegInput = "combin: negative input" + badSetSize = "combin: n < k" + badInput = "combin: wrong input slice length" +) + +// Binomial returns the binomial coefficient of (n,k), also commonly referred to +// as "n choose k". +// +// The binomial coefficient, C(n,k), is the number of unordered combinations of +// k elements in a set that is n elements big, and is defined as +// +// C(n,k) = n!/((n-k)!k!) +// +// n and k must be non-negative with n >= k, otherwise Binomial will panic. +// No check is made for overflow. +func Binomial(n, k int) int { + if n < 0 || k < 0 { + panic(badNegInput) + } + if n < k { + panic(badSetSize) + } + // (n,k) = (n, n-k) + if k > n/2 { + k = n - k + } + b := 1 + for i := 1; i <= k; i++ { + b = (n - k + i) * b / i + } + return b +} + +// GeneralizedBinomial returns the generalized binomial coefficient of (n, k), +// defined as +// Γ(n+1) / (Γ(k+1) Γ(n-k+1)) +// where Γ is the Gamma function. GeneralizedBinomial is useful for continuous +// relaxations of the binomial coefficient, or when the binomial coefficient value +// may overflow int. In the latter case, one may use math/big for an exact +// computation. +// +// n and k must be non-negative with n >= k, otherwise GeneralizedBinomial will panic. +func GeneralizedBinomial(n, k float64) float64 { + return math.Exp(LogGeneralizedBinomial(n, k)) +} + +// LogGeneralizedBinomial returns the log of the generalized binomial coefficient. +// See GeneralizedBinomial for more information. +func LogGeneralizedBinomial(n, k float64) float64 { + if n < 0 || k < 0 { + panic(badNegInput) + } + if n < k { + panic(badSetSize) + } + a, _ := math.Lgamma(n + 1) + b, _ := math.Lgamma(k + 1) + c, _ := math.Lgamma(n - k + 1) + return a - b - c +} + +// CombinationGenerator generates combinations iteratively. Combinations may be +// called to generate all combinations collectively. +type CombinationGenerator struct { + n int + k int + previous []int + remaining int +} + +// NewCombinationGenerator returns a CombinationGenerator for generating the +// combinations of k elements from a set of size n. +// +// n and k must be non-negative with n >= k, otherwise NewCombinationGenerator +// will panic. +func NewCombinationGenerator(n, k int) *CombinationGenerator { + return &CombinationGenerator{ + n: n, + k: k, + remaining: Binomial(n, k), + } +} + +// Next advances the iterator if there are combinations remaining to be generated, +// and returns false if all combinations have been generated. Next must be called +// to initialize the first value before calling Combination or Combination will +// panic. The value returned by Combination is only changed during calls to Next. +func (c *CombinationGenerator) Next() bool { + if c.remaining <= 0 { + // Next is called before combination, so c.remaining is set to zero before + // Combination is called. Thus, Combination cannot panic on zero, and a + // second sentinel value is needed. + c.remaining = -1 + return false + } + if c.previous == nil { + c.previous = make([]int, c.k) + for i := range c.previous { + c.previous[i] = i + } + } else { + nextCombination(c.previous, c.n, c.k) + } + c.remaining-- + return true +} + +// Combination generates the next combination. If next is non-nil, it must have +// length k and the result will be stored in-place into combination. If combination +// is nil a new slice will be allocated and returned. If all of the combinations +// have already been constructed (Next() returns false), Combination will panic. +// +// Next must be called to initialize the first value before calling Combination +// or Combination will panic. The value returned by Combination is only changed +// during calls to Next. +func (c *CombinationGenerator) Combination(combination []int) []int { + if c.remaining == -1 { + panic("combin: all combinations have been generated") + } + if c.previous == nil { + panic("combin: Combination called before Next") + } + if combination == nil { + combination = make([]int, c.k) + } + if len(combination) != c.k { + panic(badInput) + } + copy(combination, c.previous) + return combination +} + +// Combinations generates all of the combinations of k elements from a +// set of size n. The returned slice has length Binomial(n,k) and each inner slice +// has length k. +// +// n and k must be non-negative with n >= k, otherwise Combinations will panic. +// +// CombinationGenerator may alternatively be used to generate the combinations +// iteratively instead of collectively. +func Combinations(n, k int) [][]int { + combins := Binomial(n, k) + data := make([][]int, combins) + if len(data) == 0 { + return data + } + data[0] = make([]int, k) + for i := range data[0] { + data[0][i] = i + } + for i := 1; i < combins; i++ { + next := make([]int, k) + copy(next, data[i-1]) + nextCombination(next, n, k) + data[i] = next + } + return data +} + +// nextCombination generates the combination after s, overwriting the input value. +func nextCombination(s []int, n, k int) { + for j := k - 1; j >= 0; j-- { + if s[j] == n+j-k { + continue + } + s[j]++ + for l := j + 1; l < k; l++ { + s[l] = s[j] + l - j + } + break + } +} diff --git a/stat/combin/combin_test.go b/stat/combin/combin_test.go new file mode 100644 index 00000000..8226a675 --- /dev/null +++ b/stat/combin/combin_test.go @@ -0,0 +1,181 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package combin + +import ( + "math/big" + "testing" + + "gonum.org/v1/gonum/floats" +) + +// intSosMatch returns true if the two slices of slices are equal. +func intSosMatch(a, b [][]int) bool { + if len(a) != len(b) { + return false + } + for i, s := range a { + if len(s) != len(b[i]) { + return false + } + for j, v := range s { + if v != b[i][j] { + return false + } + } + } + return true +} + +var binomialTests = []struct { + n, k, ans int +}{ + {0, 0, 1}, + {5, 0, 1}, + {5, 1, 5}, + {5, 2, 10}, + {5, 3, 10}, + {5, 4, 5}, + {5, 5, 1}, + + {6, 0, 1}, + {6, 1, 6}, + {6, 2, 15}, + {6, 3, 20}, + {6, 4, 15}, + {6, 5, 6}, + {6, 6, 1}, + + {20, 0, 1}, + {20, 1, 20}, + {20, 2, 190}, + {20, 3, 1140}, + {20, 4, 4845}, + {20, 5, 15504}, + {20, 6, 38760}, + {20, 7, 77520}, + {20, 8, 125970}, + {20, 9, 167960}, + {20, 10, 184756}, + {20, 11, 167960}, + {20, 12, 125970}, + {20, 13, 77520}, + {20, 14, 38760}, + {20, 15, 15504}, + {20, 16, 4845}, + {20, 17, 1140}, + {20, 18, 190}, + {20, 19, 20}, + {20, 20, 1}, +} + +func TestBinomial(t *testing.T) { + for cas, test := range binomialTests { + ans := Binomial(test.n, test.k) + if ans != test.ans { + t.Errorf("Case %v: Binomial mismatch. Got %v, want %v.", cas, ans, test.ans) + } + } + var ( + n = 61 + want big.Int + got big.Int + ) + for k := 0; k <= n; k++ { + want.Binomial(int64(n), int64(k)) + got.SetInt64(int64(Binomial(n, k))) + if want.Cmp(&got) != 0 { + t.Errorf("Case n=%v,k=%v: Binomial mismatch for large n. Got %v, want %v.", n, k, got, want) + } + } +} + +func TestGeneralizedBinomial(t *testing.T) { + for cas, test := range binomialTests { + ans := GeneralizedBinomial(float64(test.n), float64(test.k)) + if !floats.EqualWithinAbsOrRel(ans, float64(test.ans), 1e-14, 1e-14) { + t.Errorf("Case %v: Binomial mismatch. Got %v, want %v.", cas, ans, test.ans) + } + } +} + +func TestCombinations(t *testing.T) { + for cas, test := range []struct { + n, k int + data [][]int + }{ + { + n: 1, + k: 1, + data: [][]int{{0}}, + }, + { + n: 2, + k: 1, + data: [][]int{{0}, {1}}, + }, + { + n: 2, + k: 2, + data: [][]int{{0, 1}}, + }, + { + n: 3, + k: 1, + data: [][]int{{0}, {1}, {2}}, + }, + { + n: 3, + k: 2, + data: [][]int{{0, 1}, {0, 2}, {1, 2}}, + }, + { + n: 3, + k: 3, + data: [][]int{{0, 1, 2}}, + }, + { + n: 4, + k: 1, + data: [][]int{{0}, {1}, {2}, {3}}, + }, + { + n: 4, + k: 2, + data: [][]int{{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}}, + }, + { + n: 4, + k: 3, + data: [][]int{{0, 1, 2}, {0, 1, 3}, {0, 2, 3}, {1, 2, 3}}, + }, + { + n: 4, + k: 4, + data: [][]int{{0, 1, 2, 3}}, + }, + } { + data := Combinations(test.n, test.k) + if !intSosMatch(data, test.data) { + t.Errorf("Cas %v: Generated combinations mismatch. Got %v, want %v.", cas, data, test.data) + } + } +} + +func TestCombinationGenerator(t *testing.T) { + for n := 0; n <= 10; n++ { + for k := 1; k <= n; k++ { + combinations := Combinations(n, k) + cg := NewCombinationGenerator(n, k) + genCombs := make([][]int, 0, len(combinations)) + for cg.Next() { + genCombs = append(genCombs, cg.Combination(nil)) + } + if !intSosMatch(combinations, genCombs) { + t.Errorf("Combinations and generated combinations do not match. n = %v, k = %v", n, k) + } + } + } +} diff --git a/stat/distmat/general.go b/stat/distmat/general.go new file mode 100644 index 00000000..9e778ef6 --- /dev/null +++ b/stat/distmat/general.go @@ -0,0 +1,8 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package distmat provides probability distributions over matrices. +package distmat + +var badDim = "distmat: dimension mismatch" diff --git a/stat/distmat/wishart.go b/stat/distmat/wishart.go new file mode 100644 index 00000000..f384c30c --- /dev/null +++ b/stat/distmat/wishart.go @@ -0,0 +1,210 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmat + +import ( + "math" + "math/rand" + "sync" + + "gonum.org/v1/gonum/mathext" + "gonum.org/v1/gonum/matrix" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat/distuv" +) + +// Wishart is a distribution over d×d positive symmetric definite matrices. It +// is parametrized by a scalar degrees of freedom parameter ν and a d×d positive +// definite matrix V. +// +// The Wishart PDF is given by +// p(X) = [|X|^((ν-d-1)/2) * exp(-tr(V^-1 * X)/2)] / [2^(ν*d/2) * |V|^(ν/2) * Γ_d(ν/2)] +// where X is a d×d PSD matrix, ν > d-1, |·| denotes the determinant, tr is the +// trace and Γ_d is the multivariate gamma function. +// +// See https://en.wikipedia.org/wiki/Wishart_distribution for more information. +type Wishart struct { + nu float64 + src *rand.Rand + + dim int + cholv mat64.Cholesky + logdetv float64 + upper mat64.TriDense + + once sync.Once + v *mat64.SymDense // only stored if needed +} + +// NewWishart returns a new Wishart distribution with the given shape matrix and +// degrees of freedom parameter. NewWishart returns whether the creation was +// successful. +// +// NewWishart panics if nu <= d - 1 where d is the order of v. +func NewWishart(v mat64.Symmetric, nu float64, src *rand.Rand) (*Wishart, bool) { + dim := v.Symmetric() + if nu <= float64(dim-1) { + panic("wishart: nu must be greater than dim-1") + } + var chol mat64.Cholesky + ok := chol.Factorize(v) + if !ok { + return nil, false + } + + var u mat64.TriDense + u.UFromCholesky(&chol) + + w := &Wishart{ + nu: nu, + src: src, + + dim: dim, + cholv: chol, + logdetv: chol.LogDet(), + upper: u, + } + return w, true +} + +// MeanSym returns the mean matrix of the distribution as a symmetric matrix. +// If x is nil, a new matrix is allocated and returned. If x is not nil, the +// result is stored in-place into x and MeanSym will panic if the order of x +// is not equal to the order of the receiver. +func (w *Wishart) MeanSym(x *mat64.SymDense) *mat64.SymDense { + if x == nil { + x = mat64.NewSymDense(w.dim, nil) + } + d := x.Symmetric() + if d != w.dim { + panic(badDim) + } + w.setV() + x.CopySym(w.v) + x.ScaleSym(w.nu, x) + return x +} + +// ProbSym returns the probability of the symmetric matrix x. If x is not positive +// definite (the Cholesky decomposition fails), it has 0 probability. +func (w *Wishart) ProbSym(x mat64.Symmetric) float64 { + return math.Exp(w.LogProbSym(x)) +} + +// LogProbSym returns the log of the probability of the input symmetric matrix. +// +// LogProbSym returns -∞ if the input matrix is not positive definite (the Cholesky +// decomposition fails). +func (w *Wishart) LogProbSym(x mat64.Symmetric) float64 { + dim := x.Symmetric() + if dim != w.dim { + panic(badDim) + } + var chol mat64.Cholesky + ok := chol.Factorize(x) + if !ok { + return math.Inf(-1) + } + return w.logProbSymChol(&chol) +} + +// LogProbSymChol returns the log of the probability of the input symmetric matrix +// given its Cholesky decomposition. +func (w *Wishart) LogProbSymChol(cholX *mat64.Cholesky) float64 { + dim := cholX.Size() + if dim != w.dim { + panic(badDim) + } + return w.logProbSymChol(cholX) +} + +func (w *Wishart) logProbSymChol(cholX *mat64.Cholesky) float64 { + // The PDF is + // p(X) = [|X|^((ν-d-1)/2) * exp(-tr(V^-1 * X)/2)] / [2^(ν*d/2) * |V|^(ν/2) * Γ_d(ν/2)] + // The LogPDF is thus + // (ν-d-1)/2 * log(|X|) - tr(V^-1 * X)/2 - (ν*d/2)*log(2) - ν/2 * log(|V|) - log(Γ_d(ν/2)) + logdetx := cholX.LogDet() + + // Compute tr(V^-1 * X), using the fact that X = U^T * U. + var u mat64.TriDense + u.UFromCholesky(cholX) + + var vinvx mat64.Dense + err := vinvx.SolveCholesky(&w.cholv, u.T()) + if err != nil { + return math.Inf(-1) + } + vinvx.Mul(&vinvx, &u) + tr := mat64.Trace(&vinvx) + + fnu := float64(w.nu) + fdim := float64(w.dim) + + return 0.5*((fnu-fdim-1)*logdetx-tr-fnu*fdim*math.Ln2-fnu*w.logdetv) - mathext.MvLgamma(0.5*fnu, w.dim) +} + +// RandSym generates a random symmetric matrix from the distribution. +func (w *Wishart) RandSym(x *mat64.SymDense) *mat64.SymDense { + if x == nil { + x = &mat64.SymDense{} + } + var c mat64.Cholesky + w.RandChol(&c) + x.FromCholesky(&c) + return x +} + +// RandChol generates the Cholesky decomposition of a random matrix from the distribution. +func (w *Wishart) RandChol(c *mat64.Cholesky) *mat64.Cholesky { + // TODO(btracey): Modify the code if the underlying data from c is exposed + // to avoid the dim^2 allocation here. + + // Use the Bartlett Decomposition, which says that + // X ~ L A A^T L^T + // Where A is a lower triangular matrix in which the diagonal of A is + // generated from the square roots of χ^2 random variables, and the + // off-diagonals are generated from standard normal variables. + // The above gives the cholesky decomposition of X, where L_x = L A. + // + // mat64 works with the upper triagular decomposition, so we would like to do + // the same. We can instead say that + // U_x = L_x^T = (L * A)^T = A^T * L^T = A^T * U + // Instead, generate A^T, by using the procedure above, except as an upper + // triangular matrix. + norm := distuv.Normal{ + Mu: 0, + Sigma: 1, + Source: w.src, + } + + t := mat64.NewTriDense(w.dim, matrix.Upper, nil) + for i := 0; i < w.dim; i++ { + v := distuv.ChiSquared{ + K: w.nu - float64(i), + Src: w.src, + }.Rand() + t.SetTri(i, i, math.Sqrt(v)) + } + for i := 0; i < w.dim; i++ { + for j := i + 1; j < w.dim; j++ { + t.SetTri(i, j, norm.Rand()) + } + } + + t.MulTri(t, &w.upper) + if c == nil { + c = &mat64.Cholesky{} + } + c.SetFromU(t) + return c +} + +// setV computes and stores the covariance matrix of the distribution. +func (w *Wishart) setV() { + w.once.Do(func() { + w.v = mat64.NewSymDense(w.dim, nil) + w.v.FromCholesky(&w.cholv) + }) +} diff --git a/stat/distmat/wishart_test.go b/stat/distmat/wishart_test.go new file mode 100644 index 00000000..0245bf96 --- /dev/null +++ b/stat/distmat/wishart_test.go @@ -0,0 +1,129 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmat + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +func TestWishart(t *testing.T) { + for c, test := range []struct { + v *mat64.SymDense + nu float64 + xs []*mat64.SymDense + lps []float64 + }{ + // Logprob data compared with scipy. + { + v: mat64.NewSymDense(2, []float64{1, 0, 0, 1}), + nu: 4, + xs: []*mat64.SymDense{ + mat64.NewSymDense(2, []float64{0.9, 0.1, 0.1, 0.9}), + }, + lps: []float64{-4.2357432031863409}, + }, + { + v: mat64.NewSymDense(2, []float64{0.8, -0.2, -0.2, 0.7}), + nu: 5, + xs: []*mat64.SymDense{ + mat64.NewSymDense(2, []float64{0.9, 0.1, 0.1, 0.9}), + mat64.NewSymDense(2, []float64{0.3, -0.1, -0.1, 0.7}), + }, + lps: []float64{-4.2476495605333575, -4.9993285370378633}, + }, + { + v: mat64.NewSymDense(3, []float64{0.8, 0.3, 0.1, 0.3, 0.7, -0.1, 0.1, -0.1, 7}), + nu: 5, + xs: []*mat64.SymDense{ + mat64.NewSymDense(3, []float64{1, 0.2, -0.3, 0.2, 0.6, -0.2, -0.3, -0.2, 6}), + }, + lps: []float64{-11.010982249229421}, + }, + } { + w, ok := NewWishart(test.v, test.nu, nil) + if !ok { + panic("bad test") + } + for i, x := range test.xs { + lp := w.LogProbSym(x) + + var chol mat64.Cholesky + ok := chol.Factorize(x) + if !ok { + panic("bad test") + } + lpc := w.LogProbSymChol(&chol) + + if math.Abs(lp-lpc) > 1e-14 { + t.Errorf("Case %d, test %d: probability mismatch between chol and not", c, i) + } + if !floats.EqualWithinAbsOrRel(lp, test.lps[i], 1e-14, 1e-14) { + t.Errorf("Case %d, test %d: got %v, want %v", c, i, lp, test.lps[i]) + } + } + + ch := w.RandChol(nil) + w.RandChol(ch) + + s := w.RandSym(nil) + w.RandSym(s) + + } +} + +func TestWishartRand(t *testing.T) { + for c, test := range []struct { + v *mat64.SymDense + nu float64 + samples int + tol float64 + }{ + { + v: mat64.NewSymDense(2, []float64{0.8, -0.2, -0.2, 0.7}), + nu: 5, + samples: 30000, + tol: 3e-2, + }, + { + v: mat64.NewSymDense(3, []float64{0.8, 0.3, 0.1, 0.3, 0.7, -0.1, 0.1, -0.1, 7}), + nu: 5, + samples: 300000, + tol: 3e-2, + }, + { + v: mat64.NewSymDense(4, []float64{ + 0.8, 0.3, 0.1, -0.2, + 0.3, 0.7, -0.1, 0.4, + 0.1, -0.1, 7, 1, + -0.2, -0.1, 1, 6}), + nu: 6, + samples: 300000, + tol: 3e-2, + }, + } { + rnd := rand.New(rand.NewSource(1)) + dim := test.v.Symmetric() + w, ok := NewWishart(test.v, test.nu, rnd) + if !ok { + panic("bad test") + } + mean := mat64.NewSymDense(dim, nil) + x := mat64.NewSymDense(dim, nil) + for i := 0; i < test.samples; i++ { + w.RandSym(x) + x.ScaleSym(1/float64(test.samples), x) + mean.AddSym(mean, x) + } + trueMean := w.MeanSym(nil) + if !mat64.EqualApprox(trueMean, mean, test.tol) { + t.Errorf("Case %d: Mismatch between estimated and true mean. Got\n%0.4v\nWant\n%0.4v\n", c, mat64.Formatted(mean), mat64.Formatted(trueMean)) + } + } +} diff --git a/stat/distmv/dirichlet.go b/stat/distmv/dirichlet.go new file mode 100644 index 00000000..a13810c9 --- /dev/null +++ b/stat/distmv/dirichlet.go @@ -0,0 +1,144 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat/distuv" +) + +// Dirichlet implements the Dirichlet probability distribution. +// +// The Dirichlet distribution is a continuous probability distribution that +// generates elements over the probability simplex, i.e. ||x||_1 = 1. The Dirichlet +// distribution is the conjugate prior to the categorical distribution and the +// multivariate version of the beta distribution. The probability of a point x is +// 1/Beta(α) \prod_i x_i^(α_i - 1) +// where Beta(α) is the multivariate Beta function (see the mathext package). +// +// For more information see https://en.wikipedia.org/wiki/Dirichlet_distribution +type Dirichlet struct { + alpha []float64 + dim int + src *rand.Rand + + lbeta float64 + sumAlpha float64 +} + +// NewDirichlet creates a new dirichlet distribution with the given parameters alpha. +// NewDirichlet will panic if len(alpha) == 0, or if any alpha is <= 0. +func NewDirichlet(alpha []float64, src *rand.Rand) *Dirichlet { + dim := len(alpha) + if dim == 0 { + panic(badZeroDimension) + } + for _, v := range alpha { + if v <= 0 { + panic("dirichlet: non-positive alpha") + } + } + a := make([]float64, len(alpha)) + copy(a, alpha) + d := &Dirichlet{ + alpha: a, + dim: dim, + src: src, + } + d.lbeta, d.sumAlpha = d.genLBeta(a) + return d +} + +// CovarianceMatrix returns the covariance matrix of the distribution. Upon +// return, the value at element {i, j} of the covariance matrix is equal to +// the covariance of the i^th and j^th variables. +// covariance(i, j) = E[(x_i - E[x_i])(x_j - E[x_j])] +// If the input matrix is nil a new matrix is allocated, otherwise the result +// is stored in-place into the input. +func (d *Dirichlet) CovarianceMatrix(cov *mat64.SymDense) *mat64.SymDense { + if cov == nil { + cov = mat64.NewSymDense(d.Dim(), nil) + } else if cov.Symmetric() == 0 { + *cov = *(cov.GrowSquare(d.dim).(*mat64.SymDense)) + } else if cov.Symmetric() != d.dim { + panic("normal: input matrix size mismatch") + } + scale := 1 / (d.sumAlpha * d.sumAlpha * (d.sumAlpha + 1)) + for i := 0; i < d.dim; i++ { + ai := d.alpha[i] + v := ai * (d.sumAlpha - ai) * scale + cov.SetSym(i, i, v) + for j := i + 1; j < d.dim; j++ { + aj := d.alpha[j] + v := -ai * aj * scale + cov.SetSym(i, j, v) + } + } + return cov +} + +// genLBeta computes the generalized LBeta function. +func (d *Dirichlet) genLBeta(alpha []float64) (lbeta, sumAlpha float64) { + for _, alpha := range d.alpha { + lg, _ := math.Lgamma(alpha) + lbeta += lg + sumAlpha += alpha + } + lg, _ := math.Lgamma(sumAlpha) + return lbeta - lg, sumAlpha +} + +// Dim returns the dimension of the distribution. +func (d *Dirichlet) Dim() int { + return d.dim +} + +// LogProb computes the log of the pdf of the point x. +// +// It does not check that ||x||_1 = 1. +func (d *Dirichlet) LogProb(x []float64) float64 { + dim := d.dim + if len(x) != dim { + panic(badSizeMismatch) + } + var lprob float64 + for i, x := range x { + lprob += (d.alpha[i] - 1) * math.Log(x) + } + lprob -= d.lbeta + return lprob +} + +// Mean returns the mean of the probability distribution at x. If the +// input argument is nil, a new slice will be allocated, otherwise the result +// will be put in-place into the receiver. +func (d *Dirichlet) Mean(x []float64) []float64 { + x = reuseAs(x, d.dim) + copy(x, d.alpha) + floats.Scale(1/d.sumAlpha, x) + return x +} + +// Prob computes the value of the probability density function at x. +func (d *Dirichlet) Prob(x []float64) float64 { + return math.Exp(d.LogProb(x)) +} + +// Rand generates a random number according to the distributon. +// If the input slice is nil, new memory is allocated, otherwise the result is stored +// in place. +func (d *Dirichlet) Rand(x []float64) []float64 { + x = reuseAs(x, d.dim) + for i := range x { + x[i] = distuv.Gamma{Alpha: d.alpha[i], Beta: 1, Source: d.src}.Rand() + } + sum := floats.Sum(x) + floats.Scale(1/sum, x) + return x +} diff --git a/stat/distmv/dirichlet_test.go b/stat/distmv/dirichlet_test.go new file mode 100644 index 00000000..9542e193 --- /dev/null +++ b/stat/distmv/dirichlet_test.go @@ -0,0 +1,72 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/matrix/mat64" +) + +func TestDirichlet(t *testing.T) { + // Data from Scipy. + for cas, test := range []struct { + Dir *Dirichlet + x []float64 + prob float64 + }{ + { + NewDirichlet([]float64{1, 1, 1}, nil), + []float64{0.2, 0.3, 0.5}, + 2.0, + }, + { + NewDirichlet([]float64{0.6, 10, 8.7}, nil), + []float64{0.2, 0.3, 0.5}, + 0.24079612737071665, + }, + } { + p := test.Dir.Prob(test.x) + if math.Abs(p-test.prob) > 1e-14 { + t.Errorf("Probablility mismatch. Case %v. Got %v, want %v", cas, p, test.prob) + } + } + + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + Dir *Dirichlet + N int + }{ + { + NewDirichlet([]float64{1, 1, 1}, rnd), + 1e6, + }, + { + NewDirichlet([]float64{2, 3}, rnd), + 1e6, + }, + { + NewDirichlet([]float64{0.2, 0.3}, rnd), + 1e6, + }, + { + NewDirichlet([]float64{0.2, 4}, rnd), + 1e6, + }, + { + NewDirichlet([]float64{0.1, 4, 20}, rnd), + 1e6, + }, + } { + d := test.Dir + dim := d.Dim() + x := mat64.NewDense(test.N, dim, nil) + generateSamples(x, d) + checkMean(t, cas, x, d, 1e-3) + checkCov(t, cas, x, d, 1e-3) + } +} diff --git a/stat/distmv/general.go b/stat/distmv/general.go new file mode 100644 index 00000000..a7734a1f --- /dev/null +++ b/stat/distmv/general.go @@ -0,0 +1,31 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package distmv provides multivariate random distribution types. +package distmv + +var ( + badQuantile = "distmv: quantile not between 0 and 1" + badReceiver = "distmv: input slice is not nil or the correct length" + badSizeMismatch = "distmv: size mismatch" + badZeroDimension = "distmv: zero dimensional input" + nonPosDimension = "distmv: non-positive dimension input" +) + +const logTwoPi = 1.8378770664093454835606594728112352797227949472755668 + +// useAs gets a slice of size n. If len(x) == n, x is returned, if len(x) == 0 +// then a slice is returned of length n. +func reuseAs(x []float64, n int) []float64 { + if len(x) == n { + return x + } + if len(x) == 0 { + if cap(x) >= n { + return x[:n] + } + return make([]float64, n) + } + panic(badReceiver) +} diff --git a/stat/distmv/general_test.go b/stat/distmv/general_test.go new file mode 100644 index 00000000..bcfa733f --- /dev/null +++ b/stat/distmv/general_test.go @@ -0,0 +1,96 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat" +) + +type prober interface { + Prob(x []float64) float64 + LogProb(x []float64) float64 +} + +type probCase struct { + dist prober + loc []float64 + logProb float64 +} + +func testProbability(t *testing.T, cases []probCase) { + for _, test := range cases { + logProb := test.dist.LogProb(test.loc) + if math.Abs(logProb-test.logProb) > 1e-14 { + t.Errorf("LogProb mismatch: want: %v, got: %v", test.logProb, logProb) + } + prob := test.dist.Prob(test.loc) + if math.Abs(prob-math.Exp(test.logProb)) > 1e-14 { + t.Errorf("Prob mismatch: want: %v, got: %v", math.Exp(test.logProb), prob) + } + } +} + +func generateSamples(x *mat64.Dense, r Rander) { + n, _ := x.Dims() + for i := 0; i < n; i++ { + r.Rand(x.RawRowView(i)) + } +} + +type Meaner interface { + Mean([]float64) []float64 +} + +func checkMean(t *testing.T, cas int, x *mat64.Dense, m Meaner, tol float64) { + mean := m.Mean(nil) + + // Check that the answer is identical when using nil or non-nil. + mean2 := make([]float64, len(mean)) + m.Mean(mean2) + if !floats.Equal(mean, mean2) { + t.Errorf("Mean mismatch when providing nil and slice. Case %v", cas) + } + + // Check that the mean matches the samples. + r, _ := x.Dims() + col := make([]float64, r) + meanEst := make([]float64, len(mean)) + for i := range meanEst { + meanEst[i] = stat.Mean(mat64.Col(col, i, x), nil) + } + if !floats.EqualApprox(mean, meanEst, tol) { + t.Errorf("Returned mean and sample mean mismatch. Case %v. Empirical %v, returned %v", cas, meanEst, mean) + } +} + +type Cover interface { + CovarianceMatrix(*mat64.SymDense) *mat64.SymDense +} + +func checkCov(t *testing.T, cas int, x *mat64.Dense, c Cover, tol float64) { + cov := c.CovarianceMatrix(nil) + n := cov.Symmetric() + cov2 := mat64.NewSymDense(n, nil) + c.CovarianceMatrix(cov2) + if !mat64.Equal(cov, cov2) { + t.Errorf("Cov mismatch when providing nil and matrix. Case %v", cas) + } + var cov3 mat64.SymDense + c.CovarianceMatrix(&cov3) + if !mat64.Equal(cov, &cov3) { + t.Errorf("Cov mismatch when providing zero matrix. Case %v", cas) + } + + // Check that the covariance matrix matches the samples + covEst := stat.CovarianceMatrix(nil, x, nil) + if !mat64.EqualApprox(covEst, cov, tol) { + t.Errorf("Return cov and sample cov mismatch. Cas %v.\nGot:\n%0.4v\nWant:\n%0.4v", cas, mat64.Formatted(cov), mat64.Formatted(covEst)) + } +} diff --git a/stat/distmv/interfaces.go b/stat/distmv/interfaces.go new file mode 100644 index 00000000..57411933 --- /dev/null +++ b/stat/distmv/interfaces.go @@ -0,0 +1,33 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +// Quantiler returns the multi-dimensional inverse cumulative distribution function. +// len(x) must equal len(p), and if x is non-nil, len(x) must also equal len(p). +// If x is nil, a new slice will be allocated and returned, otherwise the quantile +// will be stored in-place into x. All of the values of p must be between 0 and 1, +// or Quantile will panic. +type Quantiler interface { + Quantile(x, p []float64) []float64 +} + +// LogProber computes the log of the probability of the point x. +type LogProber interface { + LogProb(x []float64) float64 +} + +// Rander generates a random number according to the distributon. +// If the input is non-nil, len(x) must equal len(p) and the dimension of the distribution, +// otherwise Quantile will panic. +// If the input is nil, a new slice will be allocated and returned. +type Rander interface { + Rand(x []float64) []float64 +} + +// RandLogProber is both a Rander and a LogProber. +type RandLogProber interface { + Rander + LogProber +} diff --git a/stat/distmv/normal.go b/stat/distmv/normal.go new file mode 100644 index 00000000..55a6df5f --- /dev/null +++ b/stat/distmv/normal.go @@ -0,0 +1,316 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat" + "gonum.org/v1/gonum/stat/distuv" +) + +var ( + badInputLength = "distmv: input slice length mismatch" +) + +// Normal is a multivariate normal distribution (also known as the multivariate +// Gaussian distribution). Its pdf in k dimensions is given by +// (2 π)^(-k/2) |Σ|^(-1/2) exp(-1/2 (x-μ)'Σ^-1(x-μ)) +// where μ is the mean vector and Σ the covariance matrix. Σ must be symmetric +// and positive definite. Use NewNormal to construct. +type Normal struct { + mu []float64 + + sigma mat64.SymDense + + chol mat64.Cholesky + lower mat64.TriDense + logSqrtDet float64 + dim int + + src *rand.Rand +} + +// NewNormal creates a new Normal with the given mean and covariance matrix. +// NewNormal panics if len(mu) == 0, or if len(mu) != sigma.N. If the covariance +// matrix is not positive-definite, the returned boolean is false. +func NewNormal(mu []float64, sigma mat64.Symmetric, src *rand.Rand) (*Normal, bool) { + if len(mu) == 0 { + panic(badZeroDimension) + } + dim := sigma.Symmetric() + if dim != len(mu) { + panic(badSizeMismatch) + } + n := &Normal{ + src: src, + dim: dim, + mu: make([]float64, dim), + } + copy(n.mu, mu) + ok := n.chol.Factorize(sigma) + if !ok { + return nil, false + } + n.sigma = *mat64.NewSymDense(dim, nil) + n.sigma.CopySym(sigma) + n.lower.LFromCholesky(&n.chol) + n.logSqrtDet = 0.5 * n.chol.LogDet() + return n, true +} + +// NewNormalChol creates a new Normal distribution with the given mean and +// covariance matrix represented by its Cholesky decomposition. NewNormalChol +// panics if len(mu) is not equal to chol.Size(). +func NewNormalChol(mu []float64, chol *mat64.Cholesky, src *rand.Rand) *Normal { + dim := len(mu) + if dim != chol.Size() { + panic(badSizeMismatch) + } + n := &Normal{ + src: src, + dim: dim, + mu: make([]float64, dim), + } + n.chol.Clone(chol) + copy(n.mu, mu) + n.lower.LFromCholesky(chol) + n.logSqrtDet = 0.5 * n.chol.LogDet() + return n +} + +// NewNormalPrecision creates a new Normal distribution with the given mean and +// precision matrix (inverse of the covariance matrix). NewNormalPrecision +// panics if len(mu) is not equal to prec.Symmetric(). If the precision matrix +// is not positive-definite, NewNormalPrecision returns nil for norm and false +// for ok. +func NewNormalPrecision(mu []float64, prec *mat64.SymDense, src *rand.Rand) (norm *Normal, ok bool) { + if len(mu) == 0 { + panic(badZeroDimension) + } + dim := prec.Symmetric() + if dim != len(mu) { + panic(badSizeMismatch) + } + // TODO(btracey): Computing a matrix inverse is generally numerically instable. + // This only has to compute the inverse of a positive definite matrix, which + // is much better, but this still loses precision. It is worth considering if + // instead the precision matrix should be stored explicitly and used instead + // of the Cholesky decomposition of the covariance matrix where appropriate. + var chol mat64.Cholesky + ok = chol.Factorize(prec) + if !ok { + return nil, false + } + var sigma mat64.SymDense + sigma.InverseCholesky(&chol) + return NewNormal(mu, &sigma, src) +} + +// ConditionNormal returns the Normal distribution that is the receiver conditioned +// on the input evidence. The returned multivariate normal has dimension +// n - len(observed), where n is the dimension of the original receiver. The updated +// mean and covariance are +// mu = mu_un + sigma_{ob,un}^T * sigma_{ob,ob}^-1 (v - mu_ob) +// sigma = sigma_{un,un} - sigma_{ob,un}^T * sigma_{ob,ob}^-1 * sigma_{ob,un} +// where mu_un and mu_ob are the original means of the unobserved and observed +// variables respectively, sigma_{un,un} is the unobserved subset of the covariance +// matrix, sigma_{ob,ob} is the observed subset of the covariance matrix, and +// sigma_{un,ob} are the cross terms. The elements of x_2 have been observed with +// values v. The dimension order is preserved during conditioning, so if the value +// of dimension 1 is observed, the returned normal represents dimensions {0, 2, ...} +// of the original Normal distribution. +// +// ConditionNormal returns {nil, false} if there is a failure during the update. +// Mathematically this is impossible, but can occur with finite precision arithmetic. +func (n *Normal) ConditionNormal(observed []int, values []float64, src *rand.Rand) (*Normal, bool) { + if len(observed) == 0 { + panic("normal: no observed value") + } + if len(observed) != len(values) { + panic(badInputLength) + } + for _, v := range observed { + if v < 0 || v >= n.Dim() { + panic("normal: observed value out of bounds") + } + } + + _, mu1, sigma11 := studentsTConditional(observed, values, math.Inf(1), n.mu, &n.sigma) + if mu1 == nil { + return nil, false + } + return NewNormal(mu1, sigma11, src) +} + +// CovarianceMatrix returns the covariance matrix of the distribution. Upon +// return, the value at element {i, j} of the covariance matrix is equal to +// the covariance of the i^th and j^th variables. +// covariance(i, j) = E[(x_i - E[x_i])(x_j - E[x_j])] +// If the input matrix is nil a new matrix is allocated, otherwise the result +// is stored in-place into the input. +func (n *Normal) CovarianceMatrix(s *mat64.SymDense) *mat64.SymDense { + if s == nil { + s = mat64.NewSymDense(n.Dim(), nil) + } + sn := s.Symmetric() + if sn != n.Dim() { + panic("normal: input matrix size mismatch") + } + s.CopySym(&n.sigma) + return s +} + +// Dim returns the dimension of the distribution. +func (n *Normal) Dim() int { + return n.dim +} + +// Entropy returns the differential entropy of the distribution. +func (n *Normal) Entropy() float64 { + return float64(n.dim)/2*(1+logTwoPi) + n.logSqrtDet +} + +// LogProb computes the log of the pdf of the point x. +func (n *Normal) LogProb(x []float64) float64 { + dim := n.dim + if len(x) != dim { + panic(badSizeMismatch) + } + c := -0.5*float64(dim)*logTwoPi - n.logSqrtDet + dst := stat.Mahalanobis(mat64.NewVector(dim, x), mat64.NewVector(dim, n.mu), &n.chol) + return c - 0.5*dst*dst +} + +// MarginalNormal returns the marginal distribution of the given input variables. +// That is, MarginalNormal returns +// p(x_i) = \int_{x_o} p(x_i | x_o) p(x_o) dx_o +// where x_i are the dimensions in the input, and x_o are the remaining dimensions. +// See https://en.wikipedia.org/wiki/Marginal_distribution for more information. +// +// The input src is passed to the call to NewNormal. +func (n *Normal) MarginalNormal(vars []int, src *rand.Rand) (*Normal, bool) { + newMean := make([]float64, len(vars)) + for i, v := range vars { + newMean[i] = n.mu[v] + } + var s mat64.SymDense + s.SubsetSym(&n.sigma, vars) + return NewNormal(newMean, &s, src) +} + +// MarginalNormalSingle returns the marginal of the given input variable. +// That is, MarginalNormal returns +// p(x_i) = \int_{x_¬i} p(x_i | x_¬i) p(x_¬i) dx_¬i +// where i is the input index. +// See https://en.wikipedia.org/wiki/Marginal_distribution for more information. +// +// The input src is passed to the constructed distuv.Normal. +func (n *Normal) MarginalNormalSingle(i int, src *rand.Rand) distuv.Normal { + return distuv.Normal{ + Mu: n.mu[i], + Sigma: math.Sqrt(n.sigma.At(i, i)), + Source: src, + } +} + +// Mean returns the mean of the probability distribution at x. If the +// input argument is nil, a new slice will be allocated, otherwise the result +// will be put in-place into the receiver. +func (n *Normal) Mean(x []float64) []float64 { + x = reuseAs(x, n.dim) + copy(x, n.mu) + return x +} + +// Prob computes the value of the probability density function at x. +func (n *Normal) Prob(x []float64) float64 { + return math.Exp(n.LogProb(x)) +} + +// Quantile returns the multi-dimensional inverse cumulative distribution function. +// If x is nil, a new slice will be allocated and returned. If x is non-nil, +// len(x) must equal len(p) and the quantile will be stored in-place into x. +// All of the values of p must be between 0 and 1, inclusive, or Quantile will panic. +func (n *Normal) Quantile(x, p []float64) []float64 { + dim := n.Dim() + if len(p) != dim { + panic(badInputLength) + } + if x == nil { + x = make([]float64, dim) + } + if len(x) != len(p) { + panic(badInputLength) + } + + // Transform to a standard normal and then transform to a multivariate Gaussian. + tmp := make([]float64, len(x)) + for i, v := range p { + tmp[i] = distuv.UnitNormal.Quantile(v) + } + n.TransformNormal(x, tmp) + return x +} + +// Rand generates a random number according to the distributon. +// If the input slice is nil, new memory is allocated, otherwise the result is stored +// in place. +func (n *Normal) Rand(x []float64) []float64 { + x = reuseAs(x, n.dim) + tmp := make([]float64, n.dim) + if n.src == nil { + for i := range x { + tmp[i] = rand.NormFloat64() + } + } else { + for i := range x { + tmp[i] = n.src.NormFloat64() + } + } + n.transformNormal(x, tmp) + return x +} + +// SetMean changes the mean of the normal distribution. SetMean panics if len(mu) +// does not equal the dimension of the normal distribution. +func (n *Normal) SetMean(mu []float64) { + if len(mu) != n.Dim() { + panic(badSizeMismatch) + } + copy(n.mu, mu) +} + +// TransformNormal transforms the vector, normal, generated from a standard +// multidimensional normal into a vector that has been generated under the +// distribution of the receiver. +// +// If dst is non-nil, the result will be stored into dst, otherwise a new slice +// will be allocated. TransformNormal will panic if the length of normal is not +// the dimension of the receiver, or if dst is non-nil and len(dist) != len(normal). +func (n *Normal) TransformNormal(dst, normal []float64) []float64 { + if len(normal) != n.dim { + panic(badInputLength) + } + dst = reuseAs(dst, n.dim) + if len(dst) != len(normal) { + panic(badInputLength) + } + n.transformNormal(dst, normal) + return dst +} + +// transformNormal performs the same operation as TransformNormal except no +// safety checks are performed and both input slices must be non-nil. +func (n *Normal) transformNormal(dst, normal []float64) []float64 { + srcVec := mat64.NewVector(n.dim, normal) + dstVec := mat64.NewVector(n.dim, dst) + dstVec.MulVec(&n.lower, srcVec) + floats.Add(dst, n.mu) + return dst +} diff --git a/stat/distmv/normal_test.go b/stat/distmv/normal_test.go new file mode 100644 index 00000000..a855077f --- /dev/null +++ b/stat/distmv/normal_test.go @@ -0,0 +1,538 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat" +) + +type mvTest struct { + Mu []float64 + Sigma *mat64.SymDense + Loc []float64 + Logprob float64 + Prob float64 +} + +func TestNormProbs(t *testing.T) { + dist1, ok := NewNormal([]float64{0, 0}, mat64.NewSymDense(2, []float64{1, 0, 0, 1}), nil) + if !ok { + t.Errorf("bad test") + } + dist2, ok := NewNormal([]float64{6, 7}, mat64.NewSymDense(2, []float64{8, 2, 0, 4}), nil) + if !ok { + t.Errorf("bad test") + } + testProbability(t, []probCase{ + { + dist: dist1, + loc: []float64{0, 0}, + logProb: -1.837877066409345, + }, + { + dist: dist2, + loc: []float64{6, 7}, + logProb: -3.503979321496947, + }, + { + dist: dist2, + loc: []float64{1, 2}, + logProb: -7.075407892925519, + }, + }) +} + +func TestNewNormalChol(t *testing.T) { + for _, test := range []struct { + mean []float64 + cov *mat64.SymDense + }{ + { + mean: []float64{2, 3}, + cov: mat64.NewSymDense(2, []float64{1, 0.1, 0.1, 1}), + }, + } { + var chol mat64.Cholesky + ok := chol.Factorize(test.cov) + if !ok { + panic("bad test") + } + n := NewNormalChol(test.mean, &chol, nil) + // Generate a random number and calculate probability to ensure things + // have been set properly. See issue #426. + x := n.Rand(nil) + _ = n.Prob(x) + } +} + +func TestNormRand(t *testing.T) { + for _, test := range []struct { + mean []float64 + cov []float64 + }{ + { + mean: []float64{0, 0}, + cov: []float64{ + 1, 0, + 0, 1, + }, + }, + { + mean: []float64{0, 0}, + cov: []float64{ + 1, 0.9, + 0.9, 1, + }, + }, + { + mean: []float64{6, 7}, + cov: []float64{ + 5, 0.9, + 0.9, 2, + }, + }, + } { + dim := len(test.mean) + cov := mat64.NewSymDense(dim, test.cov) + n, ok := NewNormal(test.mean, cov, nil) + if !ok { + t.Errorf("bad covariance matrix") + } + + nSamples := 1000000 + samps := mat64.NewDense(nSamples, dim, nil) + for i := 0; i < nSamples; i++ { + n.Rand(samps.RawRowView(i)) + } + estMean := make([]float64, dim) + for i := range estMean { + estMean[i] = stat.Mean(mat64.Col(nil, i, samps), nil) + } + if !floats.EqualApprox(estMean, test.mean, 1e-2) { + t.Errorf("Mean mismatch: want: %v, got %v", test.mean, estMean) + } + estCov := stat.CovarianceMatrix(nil, samps, nil) + if !mat64.EqualApprox(estCov, cov, 1e-2) { + t.Errorf("Cov mismatch: want: %v, got %v", cov, estCov) + } + } +} + +func TestNormalQuantile(t *testing.T) { + for _, test := range []struct { + mean []float64 + cov []float64 + }{ + { + mean: []float64{6, 7}, + cov: []float64{ + 5, 0.9, + 0.9, 2, + }, + }, + } { + dim := len(test.mean) + cov := mat64.NewSymDense(dim, test.cov) + n, ok := NewNormal(test.mean, cov, nil) + if !ok { + t.Errorf("bad covariance matrix") + } + + nSamples := 1000000 + rnd := rand.New(rand.NewSource(1)) + samps := mat64.NewDense(nSamples, dim, nil) + tmp := make([]float64, dim) + for i := 0; i < nSamples; i++ { + for j := range tmp { + tmp[j] = rnd.Float64() + } + n.Quantile(samps.RawRowView(i), tmp) + } + estMean := make([]float64, dim) + for i := range estMean { + estMean[i] = stat.Mean(mat64.Col(nil, i, samps), nil) + } + if !floats.EqualApprox(estMean, test.mean, 1e-2) { + t.Errorf("Mean mismatch: want: %v, got %v", test.mean, estMean) + } + estCov := stat.CovarianceMatrix(nil, samps, nil) + if !mat64.EqualApprox(estCov, cov, 1e-2) { + t.Errorf("Cov mismatch: want: %v, got %v", cov, estCov) + } + } +} + +func TestConditionNormal(t *testing.T) { + // Uncorrelated values shouldn't influence the updated values. + for _, test := range []struct { + mu []float64 + sigma *mat64.SymDense + observed []int + values []float64 + + newMu []float64 + newSigma *mat64.SymDense + }{ + { + mu: []float64{2, 3}, + sigma: mat64.NewSymDense(2, []float64{2, 0, 0, 5}), + observed: []int{0}, + values: []float64{10}, + + newMu: []float64{3}, + newSigma: mat64.NewSymDense(1, []float64{5}), + }, + { + mu: []float64{2, 3}, + sigma: mat64.NewSymDense(2, []float64{2, 0, 0, 5}), + observed: []int{1}, + values: []float64{10}, + + newMu: []float64{2}, + newSigma: mat64.NewSymDense(1, []float64{2}), + }, + { + mu: []float64{2, 3, 4}, + sigma: mat64.NewSymDense(3, []float64{2, 0, 0, 0, 5, 0, 0, 0, 10}), + observed: []int{1}, + values: []float64{10}, + + newMu: []float64{2, 4}, + newSigma: mat64.NewSymDense(2, []float64{2, 0, 0, 10}), + }, + { + mu: []float64{2, 3, 4}, + sigma: mat64.NewSymDense(3, []float64{2, 0, 0, 0, 5, 0, 0, 0, 10}), + observed: []int{0, 1}, + values: []float64{10, 15}, + + newMu: []float64{4}, + newSigma: mat64.NewSymDense(1, []float64{10}), + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat64.NewSymDense(4, []float64{2, 0.5, 0, 0, 0.5, 5, 0, 0, 0, 0, 10, 2, 0, 0, 2, 3}), + observed: []int{0, 1}, + values: []float64{10, 15}, + + newMu: []float64{4, 5}, + newSigma: mat64.NewSymDense(2, []float64{10, 2, 2, 3}), + }, + } { + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Fatalf("Bad test, original sigma not positive definite") + } + newNormal, ok := normal.ConditionNormal(test.observed, test.values, nil) + if !ok { + t.Fatalf("Bad test, update failure") + } + + if !floats.EqualApprox(test.newMu, newNormal.mu, 1e-12) { + t.Errorf("Updated mean mismatch. Want %v, got %v.", test.newMu, newNormal.mu) + } + + var sigma mat64.SymDense + sigma.FromCholesky(&newNormal.chol) + if !mat64.EqualApprox(test.newSigma, &sigma, 1e-12) { + t.Errorf("Updated sigma mismatch\n.Want:\n% v\nGot:\n% v\n", test.newSigma, sigma) + } + } + + // Test bivariate case where the update rule is analytic + for _, test := range []struct { + mu []float64 + std []float64 + rho float64 + value float64 + }{ + { + mu: []float64{2, 3}, + std: []float64{3, 5}, + rho: 0.9, + value: 1000, + }, + { + mu: []float64{2, 3}, + std: []float64{3, 5}, + rho: -0.9, + value: 1000, + }, + } { + std := test.std + rho := test.rho + sigma := mat64.NewSymDense(2, []float64{std[0] * std[0], std[0] * std[1] * rho, std[0] * std[1] * rho, std[1] * std[1]}) + normal, ok := NewNormal(test.mu, sigma, nil) + if !ok { + t.Fatalf("Bad test, original sigma not positive definite") + } + newNormal, ok := normal.ConditionNormal([]int{1}, []float64{test.value}, nil) + if !ok { + t.Fatalf("Bad test, update failed") + } + var newSigma mat64.SymDense + newSigma.FromCholesky(&newNormal.chol) + trueMean := test.mu[0] + rho*(std[0]/std[1])*(test.value-test.mu[1]) + if math.Abs(trueMean-newNormal.mu[0]) > 1e-14 { + t.Errorf("Mean mismatch. Want %v, got %v", trueMean, newNormal.mu[0]) + } + trueVar := (1 - rho*rho) * std[0] * std[0] + if math.Abs(trueVar-newSigma.At(0, 0)) > 1e-14 { + t.Errorf("Std mismatch. Want %v, got %v", trueMean, newNormal.mu[0]) + } + } + + // Test via sampling. + for _, test := range []struct { + mu []float64 + sigma *mat64.SymDense + observed []int + unobserved []int + value []float64 + }{ + // The indices in unobserved must be in ascending order for this test. + { + mu: []float64{2, 3, 4}, + sigma: mat64.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + + observed: []int{0}, + unobserved: []int{1, 2}, + value: []float64{1.9}, + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat64.NewSymDense(4, []float64{2, 0.5, 3, 0.1, 0.5, 1, 0.6, 0.2, 3, 0.6, 10, 0.3, 0.1, 0.2, 0.3, 3}), + + observed: []int{0, 3}, + unobserved: []int{1, 2}, + value: []float64{1.9, 2.9}, + }, + } { + totalSamp := 4000000 + var nSamp int + samples := mat64.NewDense(totalSamp, len(test.mu), nil) + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Errorf("bad test") + } + sample := make([]float64, len(test.mu)) + for i := 0; i < totalSamp; i++ { + normal.Rand(sample) + isClose := true + for i, v := range test.observed { + if math.Abs(sample[v]-test.value[i]) > 1e-1 { + isClose = false + break + } + } + if isClose { + samples.SetRow(nSamp, sample) + nSamp++ + } + } + + if nSamp < 100 { + t.Errorf("bad test, not enough samples") + continue + } + samples = samples.View(0, 0, nSamp, len(test.mu)).(*mat64.Dense) + + // Compute mean and covariance matrix. + estMean := make([]float64, len(test.mu)) + for i := range estMean { + estMean[i] = stat.Mean(mat64.Col(nil, i, samples), nil) + } + estCov := stat.CovarianceMatrix(nil, samples, nil) + + // Compute update rule. + newNormal, ok := normal.ConditionNormal(test.observed, test.value, nil) + if !ok { + t.Fatalf("Bad test, update failure") + } + + var subEstMean []float64 + for _, v := range test.unobserved { + + subEstMean = append(subEstMean, estMean[v]) + } + subEstCov := mat64.NewSymDense(len(test.unobserved), nil) + for i := 0; i < len(test.unobserved); i++ { + for j := i; j < len(test.unobserved); j++ { + subEstCov.SetSym(i, j, estCov.At(test.unobserved[i], test.unobserved[j])) + } + } + + for i, v := range subEstMean { + if math.Abs(newNormal.mu[i]-v) > 5e-2 { + t.Errorf("Mean mismatch. Want %v, got %v.", newNormal.mu[i], v) + } + } + var sigma mat64.SymDense + sigma.FromCholesky(&newNormal.chol) + if !mat64.EqualApprox(&sigma, subEstCov, 1e-1) { + t.Errorf("Covariance mismatch. Want:\n%0.8v\nGot:\n%0.8v\n", subEstCov, sigma) + } + } +} + +func TestCovarianceMatrix(t *testing.T) { + for _, test := range []struct { + mu []float64 + sigma *mat64.SymDense + }{ + { + mu: []float64{2, 3, 4}, + sigma: mat64.NewSymDense(3, []float64{1, 0.5, 3, 0.5, 8, -1, 3, -1, 15}), + }, + } { + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Fatalf("Bad test, covariance matrix not positive definite") + } + cov := normal.CovarianceMatrix(nil) + if !mat64.EqualApprox(cov, test.sigma, 1e-14) { + t.Errorf("Covariance mismatch with nil input") + } + dim := test.sigma.Symmetric() + cov = mat64.NewSymDense(dim, nil) + normal.CovarianceMatrix(cov) + if !mat64.EqualApprox(cov, test.sigma, 1e-14) { + t.Errorf("Covariance mismatch with supplied input") + } + } +} + +func TestMarginal(t *testing.T) { + for _, test := range []struct { + mu []float64 + sigma *mat64.SymDense + marginal []int + }{ + { + mu: []float64{2, 3, 4}, + sigma: mat64.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + marginal: []int{0}, + }, + { + mu: []float64{2, 3, 4}, + sigma: mat64.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + marginal: []int{0, 2}, + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat64.NewSymDense(4, []float64{2, 0.5, 3, 0.1, 0.5, 1, 0.6, 0.2, 3, 0.6, 10, 0.3, 0.1, 0.2, 0.3, 3}), + + marginal: []int{0, 3}, + }, + } { + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Fatalf("Bad test, covariance matrix not positive definite") + } + marginal, ok := normal.MarginalNormal(test.marginal, nil) + if !ok { + t.Fatalf("Bad test, marginal matrix not positive definite") + } + dim := normal.Dim() + nSamples := 1000000 + samps := mat64.NewDense(nSamples, dim, nil) + for i := 0; i < nSamples; i++ { + normal.Rand(samps.RawRowView(i)) + } + estMean := make([]float64, dim) + for i := range estMean { + estMean[i] = stat.Mean(mat64.Col(nil, i, samps), nil) + } + for i, v := range test.marginal { + if math.Abs(marginal.mu[i]-estMean[v]) > 1e-2 { + t.Errorf("Mean mismatch: want: %v, got %v", estMean[v], marginal.mu[i]) + } + } + + marginalCov := marginal.CovarianceMatrix(nil) + estCov := stat.CovarianceMatrix(nil, samps, nil) + for i, v1 := range test.marginal { + for j, v2 := range test.marginal { + c := marginalCov.At(i, j) + ec := estCov.At(v1, v2) + if math.Abs(c-ec) > 5e-2 { + t.Errorf("Cov mismatch element i = %d, j = %d: want: %v, got %v", i, j, c, ec) + } + } + } + } +} + +func TestMarginalSingle(t *testing.T) { + for _, test := range []struct { + mu []float64 + sigma *mat64.SymDense + }{ + { + mu: []float64{2, 3, 4}, + sigma: mat64.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat64.NewSymDense(4, []float64{2, 0.5, 3, 0.1, 0.5, 1, 0.6, 0.2, 3, 0.6, 10, 0.3, 0.1, 0.2, 0.3, 3}), + }, + } { + normal, ok := NewNormal(test.mu, test.sigma, nil) + if !ok { + t.Fatalf("Bad test, covariance matrix not positive definite") + } + for i, mean := range test.mu { + norm := normal.MarginalNormalSingle(i, nil) + if norm.Mean() != mean { + t.Errorf("Mean mismatch nil Sigma, idx %v: want %v, got %v.", i, mean, norm.Mean()) + } + std := math.Sqrt(test.sigma.At(i, i)) + if math.Abs(norm.StdDev()-std) > 1e-14 { + t.Errorf("StdDev mismatch nil Sigma, idx %v: want %v, got %v.", i, std, norm.StdDev()) + } + } + } + + // Test matching with TestMarginal. + rnd := rand.New(rand.NewSource(1)) + for cas := 0; cas < 10; cas++ { + dim := rnd.Intn(10) + 1 + mu := make([]float64, dim) + for i := range mu { + mu[i] = rnd.Float64() + } + x := make([]float64, dim*dim) + for i := range x { + x[i] = rnd.Float64() + } + mat := mat64.NewDense(dim, dim, x) + var sigma mat64.SymDense + sigma.SymOuterK(1, mat) + + normal, ok := NewNormal(mu, &sigma, nil) + if !ok { + t.Fatal("bad test") + } + for i := 0; i < dim; i++ { + single := normal.MarginalNormalSingle(i, nil) + mult, ok := normal.MarginalNormal([]int{i}, nil) + if !ok { + t.Fatal("bad test") + } + if math.Abs(single.Mean()-mult.Mean(nil)[0]) > 1e-14 { + t.Errorf("Mean mismatch") + } + if math.Abs(single.Variance()-mult.CovarianceMatrix(nil).At(0, 0)) > 1e-14 { + t.Errorf("Variance mismatch") + } + } + } +} diff --git a/stat/distmv/normalbench_test.go b/stat/distmv/normalbench_test.go new file mode 100644 index 00000000..645f4f3e --- /dev/null +++ b/stat/distmv/normalbench_test.go @@ -0,0 +1,73 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "log" + "math/rand" + "testing" + + "gonum.org/v1/gonum/matrix/mat64" +) + +func BenchmarkMarginalNormal10(b *testing.B) { + sz := 10 + rnd := rand.New(rand.NewSource(1)) + normal := randomNormal(sz, rnd) + _ = normal.CovarianceMatrix(nil) // pre-compute sigma + b.ResetTimer() + for i := 0; i < b.N; i++ { + marg, ok := normal.MarginalNormal([]int{1}, nil) + if !ok { + b.Error("bad test") + } + _ = marg + } +} + +func BenchmarkMarginalNormalReset10(b *testing.B) { + sz := 10 + rnd := rand.New(rand.NewSource(1)) + normal := randomNormal(sz, rnd) + b.ResetTimer() + for i := 0; i < b.N; i++ { + marg, ok := normal.MarginalNormal([]int{1}, nil) + if !ok { + b.Error("bad test") + } + _ = marg + } +} + +func BenchmarkMarginalNormalSingle10(b *testing.B) { + sz := 10 + rnd := rand.New(rand.NewSource(1)) + normal := randomNormal(sz, rnd) + b.ResetTimer() + for i := 0; i < b.N; i++ { + marg := normal.MarginalNormalSingle(1, nil) + _ = marg + } +} + +func randomNormal(sz int, rnd *rand.Rand) *Normal { + mu := make([]float64, sz) + for i := range mu { + mu[i] = rnd.Float64() + } + data := make([]float64, sz*sz) + for i := range data { + data[i] = rnd.Float64() + } + dM := mat64.NewDense(sz, sz, data) + var sigma mat64.SymDense + sigma.SymOuterK(1, dM) + + normal, ok := NewNormal(mu, &sigma, nil) + if !ok { + log.Fatal("bad test, not pos def") + } + return normal +} diff --git a/stat/distmv/statdist.go b/stat/distmv/statdist.go new file mode 100644 index 00000000..478fc88e --- /dev/null +++ b/stat/distmv/statdist.go @@ -0,0 +1,252 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat" +) + +// Bhattacharyya is a type for computing the Bhattacharyya distance between +// probability distributions. +// +// The Battachara distance is defined as +// D_B = -ln(BC(l,r)) +// BC = \int_x (p(x)q(x))^(1/2) dx +// Where BC is known as the Bhattacharyya coefficient. +// The Bhattacharyya distance is related to the Hellinger distance by +// H = sqrt(1-BC) +// For more information, see +// https://en.wikipedia.org/wiki/Bhattacharyya_distance +type Bhattacharyya struct{} + +// DistNormal computes the Bhattacharyya distance between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +// +// For Normal distributions, the Bhattacharyya distance is +// Σ = (Σ_l + Σ_r)/2 +// D_B = (1/8)*(μ_l - μ_r)^T*Σ^-1*(μ_l - μ_r) + (1/2)*ln(det(Σ)/(det(Σ_l)*det(Σ_r))^(1/2)) +func (Bhattacharyya) DistNormal(l, r *Normal) float64 { + dim := l.Dim() + if dim != r.Dim() { + panic(badSizeMismatch) + } + + var sigma mat64.SymDense + sigma.AddSym(&l.sigma, &r.sigma) + sigma.ScaleSym(0.5, &sigma) + + var chol mat64.Cholesky + chol.Factorize(&sigma) + + mahalanobis := stat.Mahalanobis(mat64.NewVector(dim, l.mu), mat64.NewVector(dim, r.mu), &chol) + mahalanobisSq := mahalanobis * mahalanobis + + dl := l.chol.LogDet() + dr := r.chol.LogDet() + ds := chol.LogDet() + + return 0.125*mahalanobisSq + 0.5*ds - 0.25*dl - 0.25*dr +} + +// DistUniform computes the Bhattacharyya distance between uniform distributions l and r. +// The dimensions of the input distributions must match or DistUniform will panic. +func (Bhattacharyya) DistUniform(l, r *Uniform) float64 { + if len(l.bounds) != len(r.bounds) { + panic(badSizeMismatch) + } + // BC = \int \sqrt(p(x)q(x)), which for uniform distributions is a constant + // over the volume where both distributions have positive probability. + // Compute the overlap and the value of sqrt(p(x)q(x)). The entropy is the + // negative log probability of the distribution (use instead of LogProb so + // it is not necessary to construct an x value). + // + // BC = volume * sqrt(p(x)q(x)) + // logBC = log(volume) + 0.5*(logP + logQ) + // D_B = -logBC + return -unifLogVolOverlap(l.bounds, r.bounds) + 0.5*(l.Entropy()+r.Entropy()) +} + +// unifLogVolOverlap computes the log of the volume of the hyper-rectangle where +// both uniform distributions have positive probability. +func unifLogVolOverlap(b1, b2 []Bound) float64 { + var logVolOverlap float64 + for dim, v1 := range b1 { + v2 := b2[dim] + // If the surfaces don't overlap, then the volume is 0 + if v1.Max <= v2.Min || v2.Max <= v1.Min { + return math.Inf(-1) + } + vol := math.Min(v1.Max, v2.Max) - math.Max(v1.Min, v2.Min) + logVolOverlap += math.Log(vol) + } + return logVolOverlap +} + +// CrossEntropy is a type for computing the cross-entropy between probability +// distributions. +// +// The cross-entropy is defined as +// - \int_x l(x) log(r(x)) dx = KL(l || r) + H(l) +// where KL is the Kullback-Leibler divergence and H is the entropy. +// For more information, see +// https://en.wikipedia.org/wiki/Cross_entropy +type CrossEntropy struct{} + +// DistNormal returns the cross-entropy between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +func (CrossEntropy) DistNormal(l, r *Normal) float64 { + if l.Dim() != r.Dim() { + panic(badSizeMismatch) + } + kl := KullbackLeibler{}.DistNormal(l, r) + return kl + l.Entropy() +} + +// Hellinger is a type for computing the Hellinger distance between probability +// distributions. +// +// The Hellinger distance is defined as +// H^2(l,r) = 1/2 * int_x (\sqrt(l(x)) - \sqrt(r(x)))^2 dx +// and is bounded between 0 and 1. +// The Hellinger distance is related to the Bhattacharyya distance by +// H^2 = 1 - exp(-Db) +// For more information, see +// https://en.wikipedia.org/wiki/Hellinger_distance +type Hellinger struct{} + +// DistNormal returns the Hellinger distance between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +// +// See the documentation of Bhattacharyya.DistNormal for the formula for Normal +// distributions. +func (Hellinger) DistNormal(l, r *Normal) float64 { + if l.Dim() != r.Dim() { + panic(badSizeMismatch) + } + db := Bhattacharyya{}.DistNormal(l, r) + bc := math.Exp(-db) + return math.Sqrt(1 - bc) +} + +// KullbackLiebler is a type for computing the Kullback-Leibler divergence from l to r. +// The dimensions of the input distributions must match or the function will panic. +// +// The Kullback-Liebler divergence is defined as +// D_KL(l || r ) = \int_x p(x) log(p(x)/q(x)) dx +// Note that the Kullback-Liebler divergence is not symmetric with respect to +// the order of the input arguments. +type KullbackLeibler struct{} + +// DistNormal returns the KullbackLeibler distance between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +// +// For two normal distributions, the KL divergence is computed as +// D_KL(l || r) = 0.5*[ln(|Σ_r|) - ln(|Σ_l|) + (μ_l - μ_r)^T*Σ_r^-1*(μ_l - μ_r) + tr(Σ_r^-1*Σ_l)-d] +func (KullbackLeibler) DistNormal(l, r *Normal) float64 { + dim := l.Dim() + if dim != r.Dim() { + panic(badSizeMismatch) + } + + mahalanobis := stat.Mahalanobis(mat64.NewVector(dim, l.mu), mat64.NewVector(dim, r.mu), &r.chol) + mahalanobisSq := mahalanobis * mahalanobis + + // TODO(btracey): Optimize where there is a SolveCholeskySym + // TODO(btracey): There may be a more efficient way to just compute the trace + // Compute tr(Σ_r^-1*Σ_l) using the fact that Σ_l = U^T * U + var u mat64.TriDense + u.UFromCholesky(&l.chol) + var m mat64.Dense + err := m.SolveCholesky(&r.chol, u.T()) + if err != nil { + return math.NaN() + } + m.Mul(&m, &u) + tr := mat64.Trace(&m) + + return r.logSqrtDet - l.logSqrtDet + 0.5*(mahalanobisSq+tr-float64(l.dim)) +} + +// DistUniform returns the KullbackLeibler distance between uniform distributions +// l and r. The dimensions of the input distributions must match or DistUniform +// will panic. +func (KullbackLeibler) DistUniform(l, r *Uniform) float64 { + bl := l.Bounds(nil) + br := r.Bounds(nil) + if len(bl) != len(br) { + panic(badSizeMismatch) + } + + // The KL is ∞ if l is not completely contained within r, because then + // r(x) is zero when l(x) is non-zero for some x. + contained := true + for i, v := range bl { + if v.Min < br[i].Min || br[i].Max < v.Max { + contained = false + break + } + } + if !contained { + return math.Inf(1) + } + + // The KL divergence is finite. + // + // KL defines 0*ln(0) = 0, so there is no contribution to KL where l(x) = 0. + // Inside the region, l(x) and r(x) are constant (uniform distribution), and + // this constant is integrated over l(x), which integrates out to one. + // The entropy is -log(p(x)). + logPx := -l.Entropy() + logQx := -r.Entropy() + return logPx - logQx +} + +// Wasserstein is a type for computing the Wasserstein distance between two +// probability distributions. +// +// The Wasserstein distance is defined as +// W(l,r) := inf 𝔼(||X-Y||_2^2)^1/2 +// For more information, see +// https://en.wikipedia.org/wiki/Wasserstein_metric +type Wasserstein struct{} + +// DistNormal returns the Wasserstein distance between normal distributions l and r. +// The dimensions of the input distributions must match or DistNormal will panic. +// +// The Wasserstein distance for Normal distributions is +// d^2 = ||m_l - m_r||_2^2 + Tr(Σ_l + Σ_r - 2(Σ_l^(1/2)*Σ_r*Σ_l^(1/2))^(1/2)) +// For more information, see +// http://djalil.chafai.net/blog/2010/04/30/wasserstein-distance-between-two-gaussians/ +func (Wasserstein) DistNormal(l, r *Normal) float64 { + dim := l.Dim() + if dim != r.Dim() { + panic(badSizeMismatch) + } + + d := floats.Distance(l.mu, r.mu, 2) + d = d * d + + // Compute Σ_l^(1/2) + var ssl mat64.SymDense + ssl.PowPSD(&l.sigma, 0.5) + // Compute Σ_l^(1/2)*Σ_r*Σ_l^(1/2) + var mean mat64.Dense + mean.Mul(&ssl, &r.sigma) + mean.Mul(&mean, &ssl) + + // Reinterpret as symdense, and take Σ^(1/2) + meanSym := mat64.NewSymDense(dim, mean.RawMatrix().Data) + ssl.PowPSD(meanSym, 0.5) + + tr := mat64.Trace(&r.sigma) + tl := mat64.Trace(&l.sigma) + tm := mat64.Trace(&ssl) + + return d + tl + tr - 2*tm +} diff --git a/stat/distmv/statdist_test.go b/stat/distmv/statdist_test.go new file mode 100644 index 00000000..bb2dbb32 --- /dev/null +++ b/stat/distmv/statdist_test.go @@ -0,0 +1,261 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +func TestBhattacharyyaNormal(t *testing.T) { + for cas, test := range []struct { + am, bm []float64 + ac, bc *mat64.SymDense + samples int + tol float64 + }{ + { + am: []float64{2, 3}, + ac: mat64.NewSymDense(2, []float64{3, -1, -1, 2}), + bm: []float64{-1, 1}, + bc: mat64.NewSymDense(2, []float64{1.5, 0.2, 0.2, 0.9}), + samples: 100000, + tol: 1e-2, + }, + } { + rnd := rand.New(rand.NewSource(1)) + a, ok := NewNormal(test.am, test.ac, rnd) + if !ok { + panic("bad test") + } + b, ok := NewNormal(test.bm, test.bc, rnd) + if !ok { + panic("bad test") + } + want := bhattacharyyaSample(a.Dim(), test.samples, a, b) + got := Bhattacharyya{}.DistNormal(a, b) + if math.Abs(want-got) > test.tol { + t.Errorf("Bhattacharyya mismatch, case %d: got %v, want %v", cas, got, want) + } + + // Bhattacharyya should by symmetric + got2 := Bhattacharyya{}.DistNormal(b, a) + if math.Abs(got-got2) > 1e-14 { + t.Errorf("Bhattacharyya distance not symmetric") + } + } +} + +func TestBhattacharyyaUniform(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + a, b *Uniform + samples int + tol float64 + }{ + { + a: NewUniform([]Bound{{-3, 2}, {-5, 8}}, rnd), + b: NewUniform([]Bound{{-4, 1}, {-7, 10}}, rnd), + samples: 100000, + tol: 1e-2, + }, + { + a: NewUniform([]Bound{{-3, 2}, {-5, 8}}, rnd), + b: NewUniform([]Bound{{-5, -4}, {-7, 10}}, rnd), + samples: 100000, + tol: 1e-2, + }, + } { + a, b := test.a, test.b + want := bhattacharyyaSample(a.Dim(), test.samples, a, b) + got := Bhattacharyya{}.DistUniform(a, b) + if math.Abs(want-got) > test.tol { + t.Errorf("Bhattacharyya mismatch, case %d: got %v, want %v", cas, got, want) + } + // Bhattacharyya should by symmetric + got2 := Bhattacharyya{}.DistUniform(b, a) + if math.Abs(got-got2) > 1e-14 { + t.Errorf("Bhattacharyya distance not symmetric") + } + } +} + +// bhattacharyyaSample finds an estimate of the Bhattacharyya coefficient through +// sampling. +func bhattacharyyaSample(dim, samples int, l RandLogProber, r LogProber) float64 { + lBhatt := make([]float64, samples) + x := make([]float64, dim) + for i := 0; i < samples; i++ { + // Do importance sampling over a: \int sqrt(a*b)/a * a dx + l.Rand(x) + pa := l.LogProb(x) + pb := r.LogProb(x) + lBhatt[i] = 0.5*pb - 0.5*pa + } + logBc := floats.LogSumExp(lBhatt) - math.Log(float64(samples)) + return -logBc +} + +func TestCrossEntropyNormal(t *testing.T) { + for cas, test := range []struct { + am, bm []float64 + ac, bc *mat64.SymDense + samples int + tol float64 + }{ + { + am: []float64{2, 3}, + ac: mat64.NewSymDense(2, []float64{3, -1, -1, 2}), + bm: []float64{-1, 1}, + bc: mat64.NewSymDense(2, []float64{1.5, 0.2, 0.2, 0.9}), + samples: 100000, + tol: 1e-2, + }, + } { + rnd := rand.New(rand.NewSource(1)) + a, ok := NewNormal(test.am, test.ac, rnd) + if !ok { + panic("bad test") + } + b, ok := NewNormal(test.bm, test.bc, rnd) + if !ok { + panic("bad test") + } + var ce float64 + x := make([]float64, a.Dim()) + for i := 0; i < test.samples; i++ { + a.Rand(x) + ce -= b.LogProb(x) + } + ce /= float64(test.samples) + got := CrossEntropy{}.DistNormal(a, b) + if math.Abs(ce-got) > test.tol { + t.Errorf("CrossEntropy mismatch, case %d: got %v, want %v", cas, got, ce) + } + } +} + +func TestHellingerNormal(t *testing.T) { + for cas, test := range []struct { + am, bm []float64 + ac, bc *mat64.SymDense + samples int + tol float64 + }{ + { + am: []float64{2, 3}, + ac: mat64.NewSymDense(2, []float64{3, -1, -1, 2}), + bm: []float64{-1, 1}, + bc: mat64.NewSymDense(2, []float64{1.5, 0.2, 0.2, 0.9}), + samples: 100000, + tol: 5e-1, + }, + } { + rnd := rand.New(rand.NewSource(1)) + a, ok := NewNormal(test.am, test.ac, rnd) + if !ok { + panic("bad test") + } + b, ok := NewNormal(test.bm, test.bc, rnd) + if !ok { + panic("bad test") + } + lAitchEDoubleHockeySticks := make([]float64, test.samples) + x := make([]float64, a.Dim()) + for i := 0; i < test.samples; i++ { + // Do importance sampling over a: \int (\sqrt(a)-\sqrt(b))^2/a * a dx + a.Rand(x) + pa := a.LogProb(x) + pb := b.LogProb(x) + d := math.Exp(0.5*pa) - math.Exp(0.5*pb) + d = d * d + lAitchEDoubleHockeySticks[i] = math.Log(d) - pa + } + want := math.Sqrt(0.5 * math.Exp(floats.LogSumExp(lAitchEDoubleHockeySticks)-math.Log(float64(test.samples)))) + got := Hellinger{}.DistNormal(a, b) + if math.Abs(want-got) > test.tol { + t.Errorf("Hellinger mismatch, case %d: got %v, want %v", cas, got, want) + } + } +} + +func TestKullbackLeiblerNormal(t *testing.T) { + for cas, test := range []struct { + am, bm []float64 + ac, bc *mat64.SymDense + samples int + tol float64 + }{ + { + am: []float64{2, 3}, + ac: mat64.NewSymDense(2, []float64{3, -1, -1, 2}), + bm: []float64{-1, 1}, + bc: mat64.NewSymDense(2, []float64{1.5, 0.2, 0.2, 0.9}), + samples: 10000, + tol: 1e-2, + }, + } { + rnd := rand.New(rand.NewSource(1)) + a, ok := NewNormal(test.am, test.ac, rnd) + if !ok { + panic("bad test") + } + b, ok := NewNormal(test.bm, test.bc, rnd) + if !ok { + panic("bad test") + } + want := klSample(a.Dim(), test.samples, a, b) + got := KullbackLeibler{}.DistNormal(a, b) + if !floats.EqualWithinAbsOrRel(want, got, test.tol, test.tol) { + t.Errorf("Case %d, KL mismatch: got %v, want %v", cas, got, want) + } + } +} + +func TestKullbackLeiblerUniform(t *testing.T) { + rnd := rand.New(rand.NewSource(1)) + for cas, test := range []struct { + a, b *Uniform + samples int + tol float64 + }{ + { + a: NewUniform([]Bound{{-5, 2}, {-7, 12}}, rnd), + b: NewUniform([]Bound{{-4, 1}, {-7, 10}}, rnd), + samples: 100000, + tol: 1e-2, + }, + { + a: NewUniform([]Bound{{-5, 2}, {-7, 12}}, rnd), + b: NewUniform([]Bound{{-9, -6}, {-7, 10}}, rnd), + samples: 100000, + tol: 1e-2, + }, + } { + a, b := test.a, test.b + want := klSample(a.Dim(), test.samples, a, b) + got := KullbackLeibler{}.DistUniform(a, b) + if math.Abs(want-got) > test.tol { + t.Errorf("Kullback-Leibler mismatch, case %d: got %v, want %v", cas, got, want) + } + } +} + +// klSample finds an estimate of the Kullback-Leibler Divergence through sampling. +func klSample(dim, samples int, l RandLogProber, r LogProber) float64 { + var klmc float64 + x := make([]float64, dim) + for i := 0; i < samples; i++ { + l.Rand(x) + pa := l.LogProb(x) + pb := r.LogProb(x) + klmc += pa - pb + } + return klmc / float64(samples) +} diff --git a/stat/distmv/studentst.go b/stat/distmv/studentst.go new file mode 100644 index 00000000..0b8d50f3 --- /dev/null +++ b/stat/distmv/studentst.go @@ -0,0 +1,354 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "math/rand" + "sort" + + "golang.org/x/tools/container/intsets" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat/distuv" +) + +// StudentsT is a multivariate Student's T distribution. It is a distribution over +// ℝ^n with the probability density +// p(y) = (Γ((ν+n)/2) / Γ(ν/2)) * (νπ)^(-n/2) * |Ʃ|^(-1/2) * +// (1 + 1/ν * (y-μ)^T * Ʃ^-1 * (y-μ))^(-(ν+n)/2) +// where ν is a scalar greater than 2, μ is a vector in ℝ^n, and Ʃ is an n×n +// symmetric positive definite matrix. +// +// In this distribution, ν sets the spread of the distribution, similar to +// the degrees of freedom in a univariate Student's T distribution. As ν → ∞, +// the distribution approaches a multi-variate normal distribution. +// μ is the mean of the distribution, and the covariance is ν/(ν-2)*Ʃ. +// +// See https://en.wikipedia.org/wiki/Student%27s_t-distribution and +// http://users.isy.liu.se/en/rt/roth/student.pdf for more information. +type StudentsT struct { + nu float64 + mu []float64 + src *rand.Rand + + sigma mat64.SymDense // only stored if needed + + chol mat64.Cholesky + lower mat64.TriDense + logSqrtDet float64 + dim int +} + +// NewStudentsT creates a new StudentsT with the given nu, mu, and sigma +// parameters. +// +// NewStudentsT panics if len(mu) == 0, or if len(mu) != sigma.Symmetric(). If +// the covariance matrix is not positive-definite, nil is returned and ok is false. +func NewStudentsT(mu []float64, sigma mat64.Symmetric, nu float64, src *rand.Rand) (dist *StudentsT, ok bool) { + if len(mu) == 0 { + panic(badZeroDimension) + } + dim := sigma.Symmetric() + if dim != len(mu) { + panic(badSizeMismatch) + } + + s := &StudentsT{ + nu: nu, + mu: make([]float64, dim), + dim: dim, + src: src, + } + copy(s.mu, mu) + + ok = s.chol.Factorize(sigma) + if !ok { + return nil, false + } + s.sigma = *mat64.NewSymDense(dim, nil) + s.sigma.CopySym(sigma) + s.lower.LFromCholesky(&s.chol) + s.logSqrtDet = 0.5 * s.chol.LogDet() + return s, true +} + +// ConditionStudentsT returns the Student's T distribution that is the receiver +// conditioned on the input evidence, and the success of the operation. +// The returned Student's T has dimension +// n - len(observed), where n is the dimension of the original receiver. +// The dimension order is preserved during conditioning, so if the value +// of dimension 1 is observed, the returned normal represents dimensions {0, 2, ...} +// of the original Student's T distribution. +// +// ok indicates whether there was a failure during the update. If ok is false +// the operation failed and dist is not usable. +// Mathematically this is impossible, but can occur with finite precision arithmetic. +func (s *StudentsT) ConditionStudentsT(observed []int, values []float64, src *rand.Rand) (dist *StudentsT, ok bool) { + if len(observed) == 0 { + panic("studentst: no observed value") + } + if len(observed) != len(values) { + panic(badInputLength) + } + + for _, v := range observed { + if v < 0 || v >= s.dim { + panic("studentst: observed value out of bounds") + } + } + + newNu, newMean, newSigma := studentsTConditional(observed, values, s.nu, s.mu, &s.sigma) + if newMean == nil { + return nil, false + } + + return NewStudentsT(newMean, newSigma, newNu, src) + +} + +// studentsTConditional updates a Student's T distribution based on the observed samples +// (see documentation for the public function). The Gaussian conditional update +// is treated as a special case when nu == math.Inf(1). +func studentsTConditional(observed []int, values []float64, nu float64, mu []float64, sigma mat64.Symmetric) (newNu float64, newMean []float64, newSigma *mat64.SymDense) { + dim := len(mu) + ob := len(observed) + + unobserved := findUnob(observed, dim) + + unob := len(unobserved) + if unob == 0 { + panic("stat: all dimensions observed") + } + + mu1 := make([]float64, unob) + for i, v := range unobserved { + mu1[i] = mu[v] + } + mu2 := make([]float64, ob) // really v - mu2 + for i, v := range observed { + mu2[i] = values[i] - mu[v] + } + + var sigma11, sigma22 mat64.SymDense + sigma11.SubsetSym(sigma, unobserved) + sigma22.SubsetSym(sigma, observed) + + sigma21 := mat64.NewDense(ob, unob, nil) + for i, r := range observed { + for j, c := range unobserved { + v := sigma.At(r, c) + sigma21.Set(i, j, v) + } + } + + var chol mat64.Cholesky + ok := chol.Factorize(&sigma22) + if !ok { + return math.NaN(), nil, nil + } + + // Compute mu_1 + sigma_{2,1}^T * sigma_{2,2}^-1 (v - mu_2). + v := mat64.NewVector(ob, mu2) + var tmp, tmp2 mat64.Vector + err := tmp.SolveCholeskyVec(&chol, v) + if err != nil { + return math.NaN(), nil, nil + } + tmp2.MulVec(sigma21.T(), &tmp) + + for i := range mu1 { + mu1[i] += tmp2.At(i, 0) + } + + // Compute tmp4 = sigma_{2,1}^T * sigma_{2,2}^-1 * sigma_{2,1}. + // TODO(btracey): Should this be a method of SymDense? + var tmp3, tmp4 mat64.Dense + err = tmp3.SolveCholesky(&chol, sigma21) + if err != nil { + return math.NaN(), nil, nil + } + tmp4.Mul(sigma21.T(), &tmp3) + + // Compute sigma_{1,1} - tmp4 + // TODO(btracey): If tmp4 can constructed with a method, then this can be + // replaced with SubSym. + for i := 0; i < len(unobserved); i++ { + for j := i; j < len(unobserved); j++ { + v := sigma11.At(i, j) + sigma11.SetSym(i, j, v-tmp4.At(i, j)) + } + } + + // The computed variables are accurate for a Normal. + if math.IsInf(nu, 1) { + return nu, mu1, &sigma11 + } + + // Compute beta = (v - mu_2)^T * sigma_{2,2}^-1 * (v - mu_2)^T + beta := mat64.Dot(v, &tmp) + + // Scale the covariance matrix + sigma11.ScaleSym((nu+beta)/(nu+float64(ob)), &sigma11) + + return nu + float64(ob), mu1, &sigma11 +} + +// findUnob returns the unobserved variables (the complementary set to observed). +// findUnob panics if any value repeated in observed. +func findUnob(observed []int, dim int) (unobserved []int) { + var setOb intsets.Sparse + for _, v := range observed { + setOb.Insert(v) + } + var setAll intsets.Sparse + for i := 0; i < dim; i++ { + setAll.Insert(i) + } + var setUnob intsets.Sparse + setUnob.Difference(&setAll, &setOb) + unobserved = setUnob.AppendTo(nil) + sort.Ints(unobserved) + return unobserved +} + +// CovarianceMatrix returns the covariance matrix of the distribution. Upon +// return, the value at element {i, j} of the covariance matrix is equal to +// the covariance of the i^th and j^th variables. +// covariance(i, j) = E[(x_i - E[x_i])(x_j - E[x_j])] +// If the input matrix is nil a new matrix is allocated, otherwise the result +// is stored in-place into the input. +func (st *StudentsT) CovarianceMatrix(s *mat64.SymDense) *mat64.SymDense { + if s == nil { + s = mat64.NewSymDense(st.dim, nil) + } + sn := s.Symmetric() + if sn != st.dim { + panic("normal: input matrix size mismatch") + } + s.CopySym(&st.sigma) + s.ScaleSym(st.nu/(st.nu-2), s) + return s +} + +// Dim returns the dimension of the distribution. +func (s *StudentsT) Dim() int { + return s.dim +} + +// LogProb computes the log of the pdf of the point x. +func (s *StudentsT) LogProb(y []float64) float64 { + if len(y) != s.dim { + panic(badInputLength) + } + + nu := s.nu + n := float64(s.dim) + lg1, _ := math.Lgamma((nu + n) / 2) + lg2, _ := math.Lgamma(nu / 2) + + t1 := lg1 - lg2 - n/2*math.Log(nu*math.Pi) - s.logSqrtDet + + shift := make([]float64, len(y)) + copy(shift, y) + floats.Sub(shift, s.mu) + + x := mat64.NewVector(s.dim, shift) + + var tmp mat64.Vector + tmp.SolveCholeskyVec(&s.chol, x) + + dot := mat64.Dot(&tmp, x) + + return t1 - ((nu+n)/2)*math.Log(1+dot/nu) +} + +// MarginalStudentsT returns the marginal distribution of the given input variables, +// and the success of the operation. +// That is, MarginalStudentsT returns +// p(x_i) = \int_{x_o} p(x_i | x_o) p(x_o) dx_o +// where x_i are the dimensions in the input, and x_o are the remaining dimensions. +// See https://en.wikipedia.org/wiki/Marginal_distribution for more information. +// +// The input src is passed to the created StudentsT. +// +// ok indicates whether there was a failure during the marginalization. If ok is false +// the operation failed and dist is not usable. +// Mathematically this is impossible, but can occur with finite precision arithmetic. +func (s *StudentsT) MarginalStudentsT(vars []int, src *rand.Rand) (dist *StudentsT, ok bool) { + newMean := make([]float64, len(vars)) + for i, v := range vars { + newMean[i] = s.mu[v] + } + var newSigma mat64.SymDense + newSigma.SubsetSym(&s.sigma, vars) + return NewStudentsT(newMean, &newSigma, s.nu, src) +} + +// MarginalStudentsT returns the marginal distribution of the given input variable. +// That is, MarginalStudentsT returns +// p(x_i) = \int_{x_o} p(x_i | x_o) p(x_o) dx_o +// where i is the input index, and x_o are the remaining dimensions. +// See https://en.wikipedia.org/wiki/Marginal_distribution for more information. +// +// The input src is passed to the call to NewStudentsT. +func (s *StudentsT) MarginalStudentsTSingle(i int, src *rand.Rand) distuv.StudentsT { + return distuv.StudentsT{ + Mu: s.mu[i], + Sigma: math.Sqrt(s.sigma.At(i, i)), + Nu: s.nu, + Src: src, + } +} + +// TODO(btracey): Implement marginal single. Need to modify univariate StudentsT +// to be three-parameter. + +// Mean returns the mean of the probability distribution at x. If the +// input argument is nil, a new slice will be allocated, otherwise the result +// will be put in-place into the receiver. +func (s *StudentsT) Mean(x []float64) []float64 { + x = reuseAs(x, s.dim) + copy(x, s.mu) + return x +} + +// Prob computes the value of the probability density function at x. +func (s *StudentsT) Prob(y []float64) float64 { + return math.Exp(s.LogProb(y)) +} + +// Rand generates a random number according to the distributon. +// If the input slice is nil, new memory is allocated, otherwise the result is stored +// in place. +func (s *StudentsT) Rand(x []float64) []float64 { + // If Y is distributed according to N(0,Sigma), and U is chi^2 with + // parameter ν, then + // X = mu + Y * sqrt(nu / U) + // X is distributed according to this distribution. + + // Generate Y. + x = reuseAs(x, s.dim) + tmp := make([]float64, s.dim) + if s.src == nil { + for i := range x { + tmp[i] = rand.NormFloat64() + } + } else { + for i := range x { + tmp[i] = s.src.NormFloat64() + } + } + xVec := mat64.NewVector(s.dim, x) + tmpVec := mat64.NewVector(s.dim, tmp) + xVec.MulVec(&s.lower, tmpVec) + + u := distuv.ChiSquared{K: s.nu, Src: s.src}.Rand() + floats.Scale(math.Sqrt(s.nu/u), x) + + floats.Add(x, s.mu) + return x +} diff --git a/stat/distmv/studentst_test.go b/stat/distmv/studentst_test.go new file mode 100644 index 00000000..28c749f1 --- /dev/null +++ b/stat/distmv/studentst_test.go @@ -0,0 +1,262 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat" +) + +func TestStudentTProbs(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for _, test := range []struct { + nu float64 + mu []float64 + sigma *mat64.SymDense + + x [][]float64 + probs []float64 + }{ + { + nu: 3, + mu: []float64{0, 0}, + sigma: mat64.NewSymDense(2, []float64{1, 0, 0, 1}), + + x: [][]float64{ + {0, 0}, + {1, -1}, + {3, 4}, + {-1, -2}, + }, + // Outputs compared with WolframAlpha. + probs: []float64{ + 0.159154943091895335768883, + 0.0443811199724279860006777747927, + 0.0005980371870904696541052658, + 0.01370560783418571283428283, + }, + }, + { + nu: 4, + mu: []float64{2, -3}, + sigma: mat64.NewSymDense(2, []float64{8, -1, -1, 5}), + + x: [][]float64{ + {0, 0}, + {1, -1}, + {3, 4}, + {-1, -2}, + {2, -3}, + }, + // Outputs compared with WolframAlpha. + probs: []float64{ + 0.007360810111491788657953608191001, + 0.0143309905845607117740440592999, + 0.0005307774290578041397794096037035009801668903, + 0.0115657422475668739943625904793879, + 0.0254851872062589062995305736215, + }, + }, + } { + s, ok := NewStudentsT(test.mu, test.sigma, test.nu, src) + if !ok { + t.Fatal("bad test") + } + for i, x := range test.x { + xcpy := make([]float64, len(x)) + copy(xcpy, x) + p := s.Prob(x) + if !floats.Same(x, xcpy) { + t.Errorf("X modified during call to prob, %v, %v", x, xcpy) + } + if !floats.EqualWithinAbsOrRel(p, test.probs[i], 1e-10, 1e-10) { + t.Errorf("Probability mismatch. X = %v. Got %v, want %v.", x, p, test.probs[i]) + } + } + } +} + +func TestStudentsTRand(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for _, test := range []struct { + mean []float64 + cov *mat64.SymDense + nu float64 + tolcov float64 + }{ + { + mean: []float64{0, 0}, + cov: mat64.NewSymDense(2, []float64{1, 0, 0, 1}), + nu: 3, + tolcov: 1e-2, + }, + { + mean: []float64{3, 4}, + cov: mat64.NewSymDense(2, []float64{5, 1.2, 1.2, 6}), + nu: 8, + tolcov: 1e-2, + }, + { + mean: []float64{3, 4, -2}, + cov: mat64.NewSymDense(3, []float64{5, 1.2, -0.8, 1.2, 6, 0.4, -0.8, 0.4, 2}), + nu: 8, + tolcov: 1e-2, + }, + } { + s, ok := NewStudentsT(test.mean, test.cov, test.nu, src) + if !ok { + t.Fatal("bad test") + } + nSamples := 10000000 + dim := len(test.mean) + samps := mat64.NewDense(nSamples, dim, nil) + for i := 0; i < nSamples; i++ { + s.Rand(samps.RawRowView(i)) + } + estMean := make([]float64, dim) + for i := range estMean { + estMean[i] = stat.Mean(mat64.Col(nil, i, samps), nil) + } + mean := s.Mean(nil) + if !floats.EqualApprox(estMean, mean, 1e-2) { + t.Errorf("Mean mismatch: want: %v, got %v", test.mean, estMean) + } + cov := s.CovarianceMatrix(nil) + estCov := stat.CovarianceMatrix(nil, samps, nil) + if !mat64.EqualApprox(estCov, cov, test.tolcov) { + t.Errorf("Cov mismatch: want: %v, got %v", cov, estCov) + } + } +} + +func TestStudentsTConditional(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for _, test := range []struct { + mean []float64 + cov *mat64.SymDense + nu float64 + + idx []int + value []float64 + tolcov float64 + }{ + { + mean: []float64{3, 4, -2}, + cov: mat64.NewSymDense(3, []float64{5, 1.2, -0.8, 1.2, 6, 0.4, -0.8, 0.4, 2}), + nu: 8, + idx: []int{0}, + value: []float64{6}, + + tolcov: 1e-2, + }, + } { + s, ok := NewStudentsT(test.mean, test.cov, test.nu, src) + if !ok { + t.Fatal("bad test") + } + + sUp, ok := s.ConditionStudentsT(test.idx, test.value, src) + + // Compute the other values by hand the inefficient way to compare + newNu := test.nu + float64(len(test.idx)) + if newNu != sUp.nu { + t.Errorf("Updated nu mismatch. Got %v, want %v", s.nu, newNu) + } + dim := len(test.mean) + unob := findUnob(test.idx, dim) + ob := test.idx + + muUnob := make([]float64, len(unob)) + for i, v := range unob { + muUnob[i] = test.mean[v] + } + muOb := make([]float64, len(ob)) + for i, v := range ob { + muOb[i] = test.mean[v] + } + + var sig11, sig22 mat64.SymDense + sig11.SubsetSym(&s.sigma, unob) + sig22.SubsetSym(&s.sigma, ob) + + sig12 := mat64.NewDense(len(unob), len(ob), nil) + for i := range unob { + for j := range ob { + sig12.Set(i, j, s.sigma.At(unob[i], ob[j])) + } + } + + shift := make([]float64, len(ob)) + copy(shift, test.value) + floats.Sub(shift, muOb) + + newMu := make([]float64, len(muUnob)) + newMuVec := mat64.NewVector(len(muUnob), newMu) + shiftVec := mat64.NewVector(len(shift), shift) + var tmp mat64.Vector + tmp.SolveVec(&sig22, shiftVec) + newMuVec.MulVec(sig12, &tmp) + floats.Add(newMu, muUnob) + + if !floats.EqualApprox(newMu, sUp.mu, 1e-10) { + t.Errorf("Mu mismatch. Got %v, want %v", sUp.mu, newMu) + } + + var tmp2 mat64.Dense + tmp2.Solve(&sig22, sig12.T()) + + var tmp3 mat64.Dense + tmp3.Mul(sig12, &tmp2) + tmp3.Sub(&sig11, &tmp3) + + dot := mat64.Dot(shiftVec, &tmp) + tmp3.Scale((test.nu+dot)/(test.nu+float64(len(ob))), &tmp3) + if !mat64.EqualApprox(&tmp3, &sUp.sigma, 1e-10) { + t.Errorf("Sigma mismatch") + } + } +} + +func TestStudentsTMarginalSingle(t *testing.T) { + for _, test := range []struct { + mu []float64 + sigma *mat64.SymDense + nu float64 + }{ + { + mu: []float64{2, 3, 4}, + sigma: mat64.NewSymDense(3, []float64{2, 0.5, 3, 0.5, 1, 0.6, 3, 0.6, 10}), + nu: 5, + }, + { + mu: []float64{2, 3, 4, 5}, + sigma: mat64.NewSymDense(4, []float64{2, 0.5, 3, 0.1, 0.5, 1, 0.6, 0.2, 3, 0.6, 10, 0.3, 0.1, 0.2, 0.3, 3}), + nu: 6, + }, + } { + studentst, ok := NewStudentsT(test.mu, test.sigma, test.nu, nil) + if !ok { + t.Fatalf("Bad test, covariance matrix not positive definite") + } + for i, mean := range test.mu { + st := studentst.MarginalStudentsTSingle(i, nil) + if st.Mean() != mean { + t.Errorf("Mean mismatch nil Sigma, idx %v: want %v, got %v.", i, mean, st.Mean()) + } + std := math.Sqrt(test.sigma.At(i, i)) + if math.Abs(st.Sigma-std) > 1e-14 { + t.Errorf("StdDev mismatch nil Sigma, idx %v: want %v, got %v.", i, std, st.StdDev()) + } + if st.Nu != test.nu { + t.Errorf("Nu mismatch nil Sigma, idx %v: want %v, got %v ", i, test.nu, st.Nu) + } + } + } +} diff --git a/stat/distmv/uniform.go b/stat/distmv/uniform.go new file mode 100644 index 00000000..c28a0232 --- /dev/null +++ b/stat/distmv/uniform.go @@ -0,0 +1,196 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "math/rand" +) + +type Bound struct { + Min float64 + Max float64 +} + +// Uniform represents a multivariate uniform distribution. +type Uniform struct { + bounds []Bound + dim int + src *rand.Rand +} + +// NewUniform creates a new uniform distribution with the given bounds. +func NewUniform(bnds []Bound, src *rand.Rand) *Uniform { + dim := len(bnds) + if dim == 0 { + panic(badZeroDimension) + } + for _, b := range bnds { + if b.Max < b.Min { + panic("uniform: maximum less than minimum") + } + } + u := &Uniform{ + bounds: make([]Bound, dim), + dim: dim, + src: src, + } + for i, b := range bnds { + u.bounds[i].Min = b.Min + u.bounds[i].Max = b.Max + } + return u +} + +// NewUnitUniform creates a new Uniform distribution over the dim-dimensional +// unit hypercube. That is, a uniform distribution where each dimension has +// Min = 0 and Max = 1. +func NewUnitUniform(dim int, src *rand.Rand) *Uniform { + if dim <= 0 { + panic(nonPosDimension) + } + bounds := make([]Bound, dim) + for i := range bounds { + bounds[i].Min = 0 + bounds[i].Max = 1 + } + return &Uniform{ + bounds: bounds, + dim: dim, + src: src, + } +} + +// Bounds returns the bounds on the variables of the distribution. If the input +// is nil, a new slice is allocated and returned. If the input is non-nil, then +// the bounds are stored in-place into the input argument, and Bounds will panic +// if len(bounds) != u.Dim(). +func (u *Uniform) Bounds(bounds []Bound) []Bound { + if bounds == nil { + bounds = make([]Bound, u.Dim()) + } + if len(bounds) != u.Dim() { + panic(badInputLength) + } + copy(bounds, u.bounds) + return bounds +} + +// CDF returns the multidimensional cumulative distribution function of the +// probability distribution at the point x. If p is non-nil, the CDF is stored +// in-place into the first argument, otherwise a new slice is allocated and +// returned. +// +// CDF will panic if len(x) is not equal to the dimension of the distribution, +// or if p is non-nil and len(p) is not equal to the dimension of the distribution. +func (u *Uniform) CDF(p, x []float64) []float64 { + if len(x) != u.dim { + panic(badSizeMismatch) + } + if p == nil { + p = make([]float64, u.dim) + } + if len(p) != u.dim { + panic(badSizeMismatch) + } + for i, v := range x { + if v < u.bounds[i].Min { + p[i] = 0 + } else if v > u.bounds[i].Max { + p[i] = 1 + } else { + p[i] = (v - u.bounds[i].Min) / (u.bounds[i].Max - u.bounds[i].Min) + } + } + return p +} + +// Dim returns the dimension of the distribution. +func (u *Uniform) Dim() int { + return u.dim +} + +// Entropy returns the differential entropy of the distribution. +func (u *Uniform) Entropy() float64 { + // Entropy is log of the volume. + var logVol float64 + for _, b := range u.bounds { + logVol += math.Log(b.Max - b.Min) + } + return logVol +} + +// LogProb computes the log of the pdf of the point x. +func (u *Uniform) LogProb(x []float64) float64 { + dim := u.dim + if len(x) != dim { + panic(badSizeMismatch) + } + var logprob float64 + for i, b := range u.bounds { + if x[i] < b.Min || x[i] > b.Max { + return math.Inf(-1) + } + logprob -= math.Log(b.Max - b.Min) + } + return logprob +} + +// Mean returns the mean of the probability distribution at x. If the +// input argument is nil, a new slice will be allocated, otherwise the result +// will be put in-place into the receiver. +func (u *Uniform) Mean(x []float64) []float64 { + x = reuseAs(x, u.dim) + for i, b := range u.bounds { + x[i] = (b.Max + b.Min) / 2 + } + return x +} + +// Prob computes the value of the probability density function at x. +func (u *Uniform) Prob(x []float64) float64 { + return math.Exp(u.LogProb(x)) +} + +// Rand generates a random number according to the distributon. +// If the input slice is nil, new memory is allocated, otherwise the result is stored +// in place. +func (u *Uniform) Rand(x []float64) []float64 { + x = reuseAs(x, u.dim) + if u.src == nil { + for i, b := range u.bounds { + x[i] = rand.Float64()*(b.Max-b.Min) + b.Min + } + return x + } + for i, b := range u.bounds { + x[i] = rand.Float64()*(b.Max-b.Min) + b.Min + } + return x +} + +// Quantile returns the multi-dimensional inverse cumulative distribution function. +// len(x) must equal len(p), and if x is non-nil, len(x) must also equal len(p). +// If x is nil, a new slice will be allocated and returned, otherwise the quantile +// will be stored in-place into x. All of the values of p must be between 0 and 1, +// or Quantile will panic. +func (u *Uniform) Quantile(x, p []float64) []float64 { + if len(p) != u.dim { + panic(badSizeMismatch) + } + if x == nil { + x = make([]float64, u.dim) + } + if len(x) != u.dim { + panic(badSizeMismatch) + } + for i, v := range p { + if v < 0 || v > 1 { + panic(badQuantile) + } + x[i] = v*(u.bounds[i].Max-u.bounds[i].Min) + u.bounds[i].Min + } + return x +} diff --git a/stat/distmv/uniform_test.go b/stat/distmv/uniform_test.go new file mode 100644 index 00000000..c52e09a9 --- /dev/null +++ b/stat/distmv/uniform_test.go @@ -0,0 +1,31 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distmv + +import ( + "math" + "testing" +) + +func TestUniformEntropy(t *testing.T) { + for _, test := range []struct { + Uniform *Uniform + Entropy float64 + }{ + { + NewUniform([]Bound{{0, 1}, {0, 1}}, nil), + 0, + }, + { + NewUniform([]Bound{{-1, 3}, {2, 8}, {-5, -3}}, nil), + math.Log(48), + }, + } { + ent := test.Uniform.Entropy() + if math.Abs(ent-test.Entropy) > 1e-14 { + t.Errorf("Entropy mismatch. Got %v, want %v", ent, test.Entropy) + } + } +} diff --git a/stat/distuv/bernoulli.go b/stat/distuv/bernoulli.go new file mode 100644 index 00000000..c03578f1 --- /dev/null +++ b/stat/distuv/bernoulli.go @@ -0,0 +1,131 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" +) + +// Bernoulli represents a random variable whose value is 1 with probability p and +// value of zero with probability 1-P. The value of P must be between 0 and 1. +// More information at https://en.wikipedia.org/wiki/Bernoulli_distribution. +type Bernoulli struct { + P float64 + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (b Bernoulli) CDF(x float64) float64 { + if x < 0 { + return 0 + } + if x < 1 { + return 1 - b.P + } + return 1 +} + +// Entropy returns the entropy of the distribution. +func (b Bernoulli) Entropy() float64 { + if b.P == 0 { + return 0 + } + if b.P == 1 { + return 1 + } + q := 1 - b.P + return -b.P*math.Log(b.P) - q*math.Log(q) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (b Bernoulli) ExKurtosis() float64 { + pq := b.P * (1 - b.P) + return (1 - 6*pq) / pq +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (b Bernoulli) LogProb(x float64) float64 { + if x == 0 { + return math.Log(1 - b.P) + } + if x == 1 { + return math.Log(b.P) + } + return math.Inf(-1) +} + +// Mean returns the mean of the probability distribution. +func (b Bernoulli) Mean() float64 { + return b.P +} + +// Median returns the median of the probability distribution. +func (b Bernoulli) Median() float64 { + p := b.P + switch { + case p < 0.5: + return 0 + case p > 0.5: + return 1 + default: + return 0.5 + } +} + +// NumParameters returns the number of parameters in the distribution. +func (Bernoulli) NumParameters() int { + return 1 +} + +// Prob computes the value of the probability distribution at x. +func (b Bernoulli) Prob(x float64) float64 { + return math.Exp(b.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (b Bernoulli) Quantile(p float64) float64 { + if p < 0 || 1 < p { + panic(badPercentile) + } + if p < 1-b.P { + return 0 + } + return 1 +} + +// Rand returns a random sample drawn from the distribution. +func (b Bernoulli) Rand() float64 { + var rnd float64 + if b.Source == nil { + rnd = rand.Float64() + } else { + rnd = b.Source.Float64() + } + if rnd < b.P { + return 1 + } + return 0 +} + +// Skewness returns the skewness of the distribution. +func (b Bernoulli) Skewness() float64 { + return (1 - 2*b.P) / math.Sqrt(b.P*(1-b.P)) +} + +// StdDev returns the standard deviation of the probability distribution. +func (b Bernoulli) StdDev() float64 { + return math.Sqrt(b.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (b Bernoulli) Survival(x float64) float64 { + return 1 - b.CDF(x) +} + +// Variance returns the variance of the probability distribution. +func (b Bernoulli) Variance() float64 { + return b.P * (1 - b.P) +} diff --git a/stat/distuv/bernoulli_test.go b/stat/distuv/bernoulli_test.go new file mode 100644 index 00000000..107135ec --- /dev/null +++ b/stat/distuv/bernoulli_test.go @@ -0,0 +1,23 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import "testing" + +func TestBernoulli(t *testing.T) { + for i, dist := range []Bernoulli{ + { + P: 0.5, + }, + { + P: 0.9, + }, + { + P: 0.2, + }, + } { + testFullDist(t, dist, i, false) + } +} diff --git a/stat/distuv/beta.go b/stat/distuv/beta.go new file mode 100644 index 00000000..7c456009 --- /dev/null +++ b/stat/distuv/beta.go @@ -0,0 +1,126 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +// Beta implements the Beta distribution, a two-parameter continuous distribution +// with support between 0 and 1. +// +// The beta distribution has density function +// x^(α-1) * (1-x)^(β-1) * Γ(α+β) / (Γ(α)*Γ(β)) +// +// For more information, see https://en.wikipedia.org/wiki/Beta_distribution +type Beta struct { + // Alpha is the left shape parameter of the distribution. Alpha must be greater + // than 0. + Alpha float64 + // Beta is the right shape parameter of the distribution. Beta must be greater + // than 0. + Beta float64 + + Source *rand.Rand +} + +// CDF computes the value of the cumulative distribution function at x. +func (b Beta) CDF(x float64) float64 { + if x <= 0 { + return 0 + } + if x >= 1 { + return 1 + } + return mathext.RegIncBeta(b.Alpha, b.Beta, x) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (b Beta) ExKurtosis() float64 { + num := 6 * ((b.Alpha-b.Beta)*(b.Alpha-b.Beta)*(b.Alpha+b.Beta+1) - b.Alpha*b.Beta*(b.Alpha+b.Beta+2)) + den := b.Alpha * b.Beta * (b.Alpha + b.Beta + 2) * (b.Alpha + b.Beta + 3) + return num / den +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (b Beta) LogProb(x float64) float64 { + if x < 0 || x > 1 { + return math.Inf(-1) + } + + if b.Alpha <= 0 || b.Beta <= 0 { + panic("beta: negative parameters") + } + + lab, _ := math.Lgamma(b.Alpha + b.Beta) + la, _ := math.Lgamma(b.Alpha) + lb, _ := math.Lgamma(b.Beta) + return lab - la - lb + (b.Alpha-1)*math.Log(x) + (b.Beta-1)*math.Log(1-x) +} + +// Mean returns the mean of the probability distribution. +func (b Beta) Mean() float64 { + return b.Alpha / (b.Alpha + b.Beta) +} + +// Mode returns the mode of the distribution. +// +// Mode returns NaN if either parameter is less than or equal to 1 as a special case. +func (b Beta) Mode() float64 { + if b.Alpha <= 1 || b.Beta <= 1 { + return math.NaN() + } + return (b.Alpha - 1) / (b.Alpha + b.Beta - 2) +} + +// NumParameters returns the number of parameters in the distribution. +func (b Beta) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (b Beta) Prob(x float64) float64 { + return math.Exp(b.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative distribution function. +func (b Beta) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return mathext.InvRegIncBeta(b.Alpha, b.Beta, p) +} + +// Rand returns a random sample drawn from the distribution. +func (b Beta) Rand() float64 { + ga := Gamma{Alpha: b.Alpha, Beta: 1, Source: b.Source}.Rand() + gb := Gamma{Alpha: b.Beta, Beta: 1, Source: b.Source}.Rand() + return ga / (ga + gb) +} + +// StdDev returns the standard deviation of the probability distribution. +func (b Beta) StdDev() float64 { + return math.Sqrt(b.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (b Beta) Survival(x float64) float64 { + switch { + case x <= 0: + return 1 + case x >= 1: + return 0 + } + return mathext.RegIncBeta(b.Beta, b.Alpha, 1-x) +} + +// Variance returns the variance of the probability distribution. +func (b Beta) Variance() float64 { + return b.Alpha * b.Beta / ((b.Alpha + b.Beta) * (b.Alpha + b.Beta) * (b.Alpha + b.Beta + 1)) +} diff --git a/stat/distuv/beta_test.go b/stat/distuv/beta_test.go new file mode 100644 index 00000000..30295288 --- /dev/null +++ b/stat/distuv/beta_test.go @@ -0,0 +1,61 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestBetaProb(t *testing.T) { + // Values a comparison with scipy + for _, test := range []struct { + x, alpha, beta, want float64 + }{ + {0.1, 2, 0.5, 0.079056941504209499}, + {0.5, 1, 5.1, 0.29740426605235754}, + {0.1, 0.5, 0.5, 1.0610329539459691}, + {1, 0.5, 0.5, math.Inf(1)}, + {-1, 0.5, 0.5, 0}, + } { + pdf := Beta{Alpha: test.alpha, Beta: test.beta}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Pdf mismatch. Got %v, want %v", pdf, test.want) + } + } +} + +func TestBetaRand(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for i, b := range []Beta{ + {Alpha: 0.5, Beta: 0.5, Source: src}, + {Alpha: 5, Beta: 1, Source: src}, + {Alpha: 2, Beta: 2, Source: src}, + {Alpha: 2, Beta: 5, Source: src}, + } { + testBeta(t, b, i) + } +} + +func testBeta(t *testing.T, b Beta, i int) { + tol := 1e-2 + const n = 1e6 + const bins = 10 + x := make([]float64, n) + generateSamples(x, b) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, 0, x, b, tol, bins) + checkMean(t, i, x, b, tol) + checkVarAndStd(t, i, x, b, tol) + checkExKurtosis(t, i, x, b, 5e-2) + checkProbContinuous(t, i, x, b, 1e-3) + checkQuantileCDFSurvival(t, i, x, b, tol) + checkProbQuantContinuous(t, i, x, b, tol) +} diff --git a/stat/distuv/categorical.go b/stat/distuv/categorical.go new file mode 100644 index 00000000..165a0565 --- /dev/null +++ b/stat/distuv/categorical.go @@ -0,0 +1,184 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" +) + +// Categorical is an extension of the Bernouilli distribution where x takes +// values {0, 1, ..., len(w)-1} where w is the weight vector. Categorical must +// be initialized with NewCategorical. +type Categorical struct { + weights []float64 + + // heap is a weight heap. + // + // It keeps a heap-organised sum of remaining + // index weights that are available to be taken + // from. + // + // Each element holds the sum of weights for + // the corresponding index, plus the sum of + // of its children's weights; the children + // of an element i can be found at positions + // 2*(i+1)-1 and 2*(i+1). The root of the + // weight heap is at element 0. + // + // See comments in container/heap for an + // explanation of the layout of a heap. + heap []float64 + + src *rand.Rand +} + +// NewCategorical constructs a new categorical distribution where the probability +// that x equals i is proportional to w[i]. All of the weights must be +// nonnegative, and at least one of the weights must be positive. +func NewCategorical(w []float64, src *rand.Rand) Categorical { + c := Categorical{ + weights: make([]float64, len(w)), + heap: make([]float64, len(w)), + src: src, + } + c.ReweightAll(w) + return c +} + +// CDF computes the value of the cumulative density function at x. +func (c Categorical) CDF(x float64) float64 { + var cdf float64 + for i, w := range c.weights { + if x < float64(i) { + break + } + cdf += w + } + return cdf / c.heap[0] +} + +// Entropy returns the entropy of the distribution. +func (c Categorical) Entropy() float64 { + var ent float64 + for _, w := range c.weights { + if w == 0 { + continue + } + p := w / c.heap[0] + ent += p * math.Log(p) + } + return -ent +} + +// Len returns the number of values x could possibly take (the length of the +// initial supplied weight vector). +func (c Categorical) Len() int { + return len(c.weights) +} + +// Mean returns the mean of the probability distribution. +func (c Categorical) Mean() float64 { + var mean float64 + for i, v := range c.weights { + mean += float64(i) * v + } + return mean / c.heap[0] +} + +// Prob computes the value of the probability density function at x. +func (c Categorical) Prob(x float64) float64 { + xi := int(x) + if float64(xi) != x { + return 0 + } + if xi < 0 || xi > len(c.weights)-1 { + return 0 + } + return c.weights[xi] / c.heap[0] +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (c Categorical) LogProb(x float64) float64 { + return math.Log(c.Prob(x)) +} + +// Rand returns a random draw from the categorical distribution. +func (c Categorical) Rand() float64 { + var r float64 + if c.src == nil { + r = c.heap[0] * rand.Float64() + } else { + r = c.heap[0] * c.src.Float64() + } + i := 1 + last := -1 + left := len(c.weights) + for { + if r -= c.weights[i-1]; r <= 0 { + break // Fall within item i-1. + } + i <<= 1 // Move to left child. + if d := c.heap[i-1]; r > d { + r -= d + // If enough r to pass left child, + // move to right child state will + // be caught at break above. + i++ + } + if i == last || left < 0 { + panic("categorical: bad sample") + } + last = i + left-- + } + return float64(i - 1) +} + +// Reweight sets the weight of item idx to w. The input weight must be +// non-negative, and after reweighting at least one of the weights must be +// positive. +func (c Categorical) Reweight(idx int, w float64) { + if w < 0 { + panic("categorical: negative weight") + } + w, c.weights[idx] = c.weights[idx]-w, w + idx++ + for idx > 0 { + c.heap[idx-1] -= w + idx >>= 1 + } + if c.heap[0] <= 0 { + panic("categorical: sum of the weights non-positive") + } +} + +// ReweightAll resets the weights of the distribution. ReweightAll panics if +// len(w) != c.Len. All of the weights must be nonnegative, and at least one of +// the weights must be positive. +func (c Categorical) ReweightAll(w []float64) { + if len(w) != c.Len() { + panic("categorical: length of the slices do not match") + } + for _, v := range w { + if v < 0 { + panic("categorical: negative weight") + } + } + copy(c.weights, w) + c.reset() +} + +func (c Categorical) reset() { + copy(c.heap, c.weights) + for i := len(c.heap) - 1; i > 0; i-- { + // Sometimes 1-based counting makes sense. + c.heap[((i+1)>>1)-1] += c.heap[i] + } + // TODO(btracey): Renormalization for weird weights? + if c.heap[0] <= 0 { + panic("categorical: sum of the weights non-positive") + } +} diff --git a/stat/distuv/categorical_test.go b/stat/distuv/categorical_test.go new file mode 100644 index 00000000..decd181d --- /dev/null +++ b/stat/distuv/categorical_test.go @@ -0,0 +1,196 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestCategoricalProb(t *testing.T) { + for _, test := range [][]float64{ + {1, 2, 3, 0}, + } { + dist := NewCategorical(test, nil) + norm := make([]float64, len(test)) + floats.Scale(1/floats.Sum(norm), norm) + for i, v := range norm { + p := dist.Prob(float64(i)) + if math.Abs(p-v) > 1e-14 { + t.Errorf("Probability mismatch element %d", i) + } + p = dist.Prob(float64(i) + 0.5) + if p != 0 { + t.Errorf("Non-zero probability for non-integer x") + } + } + p := dist.Prob(-1) + if p != 0 { + t.Errorf("Non-zero probability for -1") + } + p = dist.Prob(float64(len(test))) + if p != 0 { + t.Errorf("Non-zero probability for len(test)") + } + } +} + +func TestCategoricalRand(t *testing.T) { + for _, test := range [][]float64{ + {1, 2, 3, 0}, + } { + dist := NewCategorical(test, nil) + nSamples := 2000000 + counts := sampleCategorical(t, dist, nSamples) + + probs := make([]float64, len(test)) + for i := range probs { + probs[i] = dist.Prob(float64(i)) + } + same := samedDistCategorical(dist, counts, probs, 1e-2) + if !same { + t.Errorf("Probability mismatch. Want %v, got %v", probs, counts) + } + + dist.Reweight(len(test)-1, 10) + counts = sampleCategorical(t, dist, nSamples) + probs = make([]float64, len(test)) + for i := range probs { + probs[i] = dist.Prob(float64(i)) + } + same = samedDistCategorical(dist, counts, probs, 1e-2) + if !same { + t.Errorf("Probability mismatch after Reweight. Want %v, got %v", probs, counts) + } + + w := make([]float64, len(test)) + for i := range w { + w[i] = rand.Float64() + } + + dist.ReweightAll(w) + counts = sampleCategorical(t, dist, nSamples) + probs = make([]float64, len(test)) + for i := range probs { + probs[i] = dist.Prob(float64(i)) + } + same = samedDistCategorical(dist, counts, probs, 1e-2) + if !same { + t.Errorf("Probability mismatch after ReweightAll. Want %v, got %v", probs, counts) + } + } +} + +func sampleCategorical(t *testing.T, dist Categorical, nSamples int) []float64 { + counts := make([]float64, dist.Len()) + for i := 0; i < nSamples; i++ { + v := dist.Rand() + if float64(int(v)) != v { + t.Fatalf("Random number is not an integer") + } + counts[int(v)]++ + } + sum := floats.Sum(counts) + floats.Scale(1/sum, counts) + return counts +} + +func samedDistCategorical(dist Categorical, counts, probs []float64, tol float64) bool { + same := true + for i, prob := range probs { + if prob == 0 && counts[i] != 0 { + same = false + break + } + if !floats.EqualWithinAbsOrRel(prob, counts[i], tol, tol) { + same = false + break + } + } + return same +} + +func TestCategoricalCDF(t *testing.T) { + for _, test := range [][]float64{ + {1, 2, 3, 0, 4}, + } { + c := make([]float64, len(test)) + copy(c, test) + floats.Scale(1/floats.Sum(c), c) + sum := make([]float64, len(test)) + floats.CumSum(sum, c) + + dist := NewCategorical(test, nil) + cdf := dist.CDF(-0.5) + if cdf != 0 { + t.Errorf("CDF of negative number not zero") + } + for i := range c { + cdf := dist.CDF(float64(i)) + if math.Abs(cdf-sum[i]) > 1e-14 { + t.Errorf("CDF mismatch %v. Want %v, got %v.", float64(i), sum[i], cdf) + } + cdfp := dist.CDF(float64(i) + 0.5) + if cdfp != cdf { + t.Errorf("CDF mismatch for non-integer input") + } + } + } +} + +func TestCategoricalEntropy(t *testing.T) { + for _, test := range []struct { + weights []float64 + entropy float64 + }{ + { + weights: []float64{1, 1}, + entropy: math.Ln2, + }, + { + weights: []float64{1, 1, 1, 1}, + entropy: math.Log(4), + }, + { + weights: []float64{0, 0, 1, 1, 0, 0}, + entropy: math.Ln2, + }, + } { + dist := NewCategorical(test.weights, nil) + entropy := dist.Entropy() + if math.IsNaN(entropy) || math.Abs(entropy-test.entropy) > 1e-14 { + t.Errorf("Entropy mismatch. Want %v, got %v.", test.entropy, entropy) + } + } +} + +func TestCategoricalMean(t *testing.T) { + for _, test := range []struct { + weights []float64 + mean float64 + }{ + { + weights: []float64{10, 0, 0, 0}, + mean: 0, + }, + { + weights: []float64{0, 10, 0, 0}, + mean: 1, + }, + { + weights: []float64{1, 2, 3, 4}, + mean: 2, + }, + } { + dist := NewCategorical(test.weights, nil) + mean := dist.Mean() + if math.IsNaN(mean) || math.Abs(mean-test.mean) > 1e-14 { + t.Errorf("Entropy mismatch. Want %v, got %v.", test.mean, mean) + } + } +} diff --git a/stat/distuv/chisquared.go b/stat/distuv/chisquared.go new file mode 100644 index 00000000..2c9827b7 --- /dev/null +++ b/stat/distuv/chisquared.go @@ -0,0 +1,99 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +// ChiSquared implements the χ² distribution, a one parameter distribution +// with support on the positive numbers. +// +// The density function is given by +// 1/(2^{k/2} * Γ(k/2)) * x^{k/2 - 1} * e^{-x/2} +// It is a special case of the Gamma distribution, Γ(k/2, 1/2). +// +// For more information, see https://en.wikipedia.org/wiki/Chi-squared_distribution. +type ChiSquared struct { + // K is the shape parameter, corresponding to the degrees of freedom. Must + // be greater than 0. + K float64 + + Src *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (c ChiSquared) CDF(x float64) float64 { + return mathext.GammaInc(c.K/2, x/2) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (c ChiSquared) ExKurtosis() float64 { + return 12 / c.K +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (c ChiSquared) LogProb(x float64) float64 { + if x < 0 { + return math.Inf(-1) + } + lg, _ := math.Lgamma(c.K / 2) + return (c.K/2-1)*math.Log(x) - x/2 - (c.K/2)*math.Ln2 - lg +} + +// Mean returns the mean of the probability distribution. +func (c ChiSquared) Mean() float64 { + return c.K +} + +// Mode returns the mode of the distribution. +func (c ChiSquared) Mode() float64 { + return math.Min(c.K-2, 0) +} + +// NumParameters returns the number of parameters in the distribution. +func (c ChiSquared) NumParameters() int { + return 1 +} + +// Prob computes the value of the probability density function at x. +func (c ChiSquared) Prob(x float64) float64 { + return math.Exp(c.LogProb(x)) +} + +// Rand returns a random sample drawn from the distribution. +func (c ChiSquared) Rand() float64 { + return Gamma{c.K / 2, 0.5, c.Src}.Rand() +} + +// Quantile returns the inverse of the cumulative distribution function. +func (c ChiSquared) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return mathext.GammaIncInv(0.5*c.K, p) * 2 +} + +// StdDev returns the standard deviation of the probability distribution. +func (c ChiSquared) StdDev() float64 { + return math.Sqrt(c.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (c ChiSquared) Survival(x float64) float64 { + if x < 0 { + return 1 + } + return mathext.GammaIncComp(0.5*c.K, 0.5*x) +} + +// Variance returns the variance of the probability distribution. +func (c ChiSquared) Variance() float64 { + return 2 * c.K +} diff --git a/stat/distuv/chisquared_test.go b/stat/distuv/chisquared_test.go new file mode 100644 index 00000000..a4d13bba --- /dev/null +++ b/stat/distuv/chisquared_test.go @@ -0,0 +1,78 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestChiSquaredProb(t *testing.T) { + for _, test := range []struct { + x, k, want float64 + }{ + {10, 3, 0.0085003666025203432}, + {2.3, 3, 0.19157345407042367}, + {0.8, 0.2, 0.080363259903912673}, + } { + pdf := ChiSquared{test.k, nil}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Pdf mismatch, x = %v, K = %v. Got %v, want %v", test.x, test.k, pdf, test.want) + } + } +} + +func TestChiSquaredCDF(t *testing.T) { + for _, test := range []struct { + x, k, want float64 + }{ + // Values calculated with scipy.stats.chi2.cdf + {0, 1, 0}, + {0.01, 5, 5.3002700426865167e-07}, + {0.05, 3, 0.002929332764619924}, + {0.5, 2, 0.22119921692859512}, + {0.95, 3, 0.1866520918701263}, + {0.99, 5, 0.036631697220869196}, + {1, 1, 0.68268949213708596}, + {1.5, 4, 0.17335853270322427}, + {10, 10, 0.55950671493478743}, + {25, 15, 0.95005656637357172}, + } { + cdf := ChiSquared{test.k, nil}.CDF(test.x) + if !floats.EqualWithinAbsOrRel(cdf, test.want, 1e-10, 1e-10) { + t.Errorf("CDF mismatch, x = %v, K = %v. Got %v, want %v", test.x, test.k, cdf, test.want) + } + } +} + +func TestChiSquared(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for i, b := range []ChiSquared{ + {3, src}, + {1.5, src}, + {0.9, src}, + } { + testChiSquared(t, b, i) + } +} + +func testChiSquared(t *testing.T, c ChiSquared, i int) { + tol := 1e-2 + const n = 2e6 + const bins = 50 + x := make([]float64, n) + generateSamples(x, c) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, 0, x, c, tol, bins) + checkMean(t, i, x, c, tol) + checkVarAndStd(t, i, x, c, tol) + checkExKurtosis(t, i, x, c, 5e-2) + checkProbContinuous(t, i, x, c, 1e-3) + checkQuantileCDFSurvival(t, i, x, c, 1e-3) +} diff --git a/stat/distuv/constants.go b/stat/distuv/constants.go new file mode 100644 index 00000000..9de7d4dc --- /dev/null +++ b/stat/distuv/constants.go @@ -0,0 +1,24 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +const ( + // oneOverRoot2Pi is the value of 1/(2Pi)^(1/2) + // http://www.wolframalpha.com/input/?i=1%2F%282+*+pi%29%5E%281%2F2%29 + oneOverRoot2Pi = 0.39894228040143267793994605993438186847585863116493465766592582967065792589930183850125233390730693643030255886263518268 + + //LogRoot2Pi is the value of log(sqrt(2*Pi)) + logRoot2Pi = 0.91893853320467274178032973640561763986139747363778341281715154048276569592726039769474329863595419762200564662463433744 + negLogRoot2Pi = -logRoot2Pi + log2Pi = 1.8378770664093454835606594728112352797227949472755668 + ln2 = 0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102057068573368552023 + + // Euler–Mascheroni constant. + eulerGamma = 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495146314472498070824809605 +) + +const ( + panicNameMismatch = "parameter name mismatch" +) diff --git a/stat/distuv/distribution_test.go b/stat/distuv/distribution_test.go new file mode 100644 index 00000000..722c438a --- /dev/null +++ b/stat/distuv/distribution_test.go @@ -0,0 +1,293 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/integrate/quad" + "gonum.org/v1/gonum/stat" +) + +type meaner interface { + Mean() float64 +} + +type quantiler interface { + Quantile(float64) float64 +} + +type medianer interface { + quantiler + Median() float64 +} + +type varStder interface { + StdDev() float64 + Variance() float64 +} + +type entropyer interface { + LogProber + Entropy() float64 +} + +type exKurtosiser interface { + ExKurtosis() float64 + Mean() float64 +} + +type skewnesser interface { + StdDev() float64 + Mean() float64 + Skewness() float64 +} + +type cumulanter interface { + Quantiler + CDF(x float64) float64 + Survival(x float64) float64 +} + +func generateSamples(x []float64, r Rander) { + for i := range x { + x[i] = r.Rand() + } +} + +type probLogprober interface { + Prob(x float64) float64 + LogProb(x float64) float64 +} + +type cumulantProber interface { + cumulanter + probLogprober +} + +func checkMean(t *testing.T, i int, x []float64, m meaner, tol float64) { + mean := stat.Mean(x, nil) + if !floats.EqualWithinAbsOrRel(mean, m.Mean(), tol, tol) { + t.Errorf("Mean mismatch case %v: want: %v, got: %v", i, mean, m.Mean()) + } +} + +func checkMedian(t *testing.T, i int, x []float64, m medianer, tol float64) { + median := stat.Quantile(0.5, stat.Empirical, x, nil) + if !floats.EqualWithinAbsOrRel(median, m.Median(), tol, tol) { + t.Errorf("Median mismatch case %v: want: %v, got: %v", i, median, m.Median()) + } +} + +func checkVarAndStd(t *testing.T, i int, x []float64, v varStder, tol float64) { + variance := stat.Variance(x, nil) + if !floats.EqualWithinAbsOrRel(variance, v.Variance(), tol, tol) { + t.Errorf("Variance mismatch case %v: want: %v, got: %v", i, variance, v.Variance()) + } + std := math.Sqrt(variance) + if !floats.EqualWithinAbsOrRel(std, v.StdDev(), tol, tol) { + t.Errorf("StdDev mismatch case %v: want: %v, got: %v", i, std, v.StdDev()) + } +} + +func checkEntropy(t *testing.T, i int, x []float64, e entropyer, tol float64) { + tmp := make([]float64, len(x)) + for i, v := range x { + tmp[i] = -e.LogProb(v) + } + entropy := stat.Mean(tmp, nil) + if !floats.EqualWithinAbsOrRel(entropy, e.Entropy(), tol, tol) { + t.Errorf("Entropy mismatch case %v: want: %v, got: %v", i, entropy, e.Entropy()) + } +} + +func checkExKurtosis(t *testing.T, i int, x []float64, e exKurtosiser, tol float64) { + mean := e.Mean() + tmp := make([]float64, len(x)) + for i, x := range x { + tmp[i] = math.Pow(x-mean, 4) + } + variance := stat.Variance(x, nil) + mu4 := stat.Mean(tmp, nil) + kurtosis := mu4/(variance*variance) - 3 + if !floats.EqualWithinAbsOrRel(kurtosis, e.ExKurtosis(), tol, tol) { + t.Errorf("ExKurtosis mismatch case %v: want: %v, got: %v", i, kurtosis, e.ExKurtosis()) + } +} + +func checkSkewness(t *testing.T, i int, x []float64, s skewnesser, tol float64) { + mean := s.Mean() + std := s.StdDev() + tmp := make([]float64, len(x)) + for i, v := range x { + tmp[i] = math.Pow(v-mean, 3) + } + mu3 := stat.Mean(tmp, nil) + skewness := mu3 / math.Pow(std, 3) + if !floats.EqualWithinAbsOrRel(skewness, s.Skewness(), tol, tol) { + t.Errorf("Skewness mismatch case %v: want: %v, got: %v", i, skewness, s.Skewness()) + } +} + +func checkQuantileCDFSurvival(t *testing.T, i int, xs []float64, c cumulanter, tol float64) { + // Quantile, CDF, and survival check. + for i, p := range []float64{0.1, 0.25, 0.5, 0.75, 0.9} { + x := c.Quantile(p) + cdf := c.CDF(x) + estCDF := stat.CDF(x, stat.Empirical, xs, nil) + if !floats.EqualWithinAbsOrRel(cdf, estCDF, tol, tol) { + t.Errorf("CDF mismatch case %v: want: %v, got: %v", i, estCDF, cdf) + } + if !floats.EqualWithinAbsOrRel(cdf, p, tol, tol) { + t.Errorf("Quantile/CDF mismatch case %v: want: %v, got: %v", i, p, cdf) + } + if math.Abs(1-cdf-c.Survival(x)) > 1e-14 { + t.Errorf("Survival/CDF mismatch case %v: want: %v, got: %v", i, 1-cdf, c.Survival(x)) + } + } +} + +func checkProbContinuous(t *testing.T, i int, x []float64, p probLogprober, tol float64) { + // Check that the PDF is consistent (integrates to 1). + q := quad.Fixed(p.Prob, math.Inf(-1), math.Inf(1), 1000000, nil, 0) + if math.Abs(q-1) > tol { + t.Errorf("Probability distribution doesn't integrate to 1. Case %v: Got %v", i, q) + } + + // Check that PDF and LogPDF are consistent. + for i, v := range x { + if math.Abs(math.Log(p.Prob(v))-p.LogProb(v)) > 1e-14 { + t.Errorf("Prob and LogProb mismatch case %v at %v: want %v, got %v", i, v, math.Log(v), p.LogProb(v)) + break + } + } +} + +// checkProbQuantContinuous checks that the Prob, Rand, and Quantile are all consistent. +// checkProbContinuous only checks that Prob is a valid distribution (integrates +// to 1 and greater than 0). However, this is also true if the PDF of a different +// distribution is used. This checks that PDF is also consistent with the +// CDF implementation and the random samples. +func checkProbQuantContinuous(t *testing.T, i int, xs []float64, c cumulantProber, tol float64) { + ps := make([]float64, 101) + floats.Span(ps, 0, 1) + + var xp, x float64 + for i, p := range ps { + x = c.Quantile(p) + if p == 0 { + xp = x + if floats.Min(xs) < x { + t.Errorf("Sample of x less than Quantile(0). Case %v.", i) + break + } + continue + } + if p == 1 { + if floats.Max(xs) > x { + t.Errorf("Sample of x greater than Quantile(1). Case %v.", i) + break + } + } + + // The integral of the PDF between xp and x should be the difference in + // the quantiles. + q := quad.Fixed(c.Prob, xp, x, 1000, nil, 0) + if math.Abs(q-(p-ps[i-1])) > 1e-5 { + t.Errorf("Integral of PDF doesn't match quantile. Case %v. Want %v, got %v.", i, p-ps[i-1], q) + break + } + + pEst := stat.CDF(x, stat.Empirical, xs, nil) + if math.Abs(pEst-p) > tol { + t.Errorf("Empirical CDF doesn't match quantile. Case %v.", i) + } + xp = x + } +} + +// checkProbDiscrete confirms that PDF and Rand are consistent for discrete distributions. +func checkProbDiscrete(t *testing.T, i int, xs []float64, p probLogprober, tol float64) { + // Make a map of all of the unique samples. + m := make(map[float64]int) + for _, v := range xs { + m[v]++ + } + for x, count := range m { + prob := float64(count) / float64(len(xs)) + if math.Abs(prob-p.Prob(x)) > tol { + t.Errorf("PDF mismatch case %v at %v: want %v, got %v", i, x, prob, p.Prob(x)) + } + if math.Abs(math.Log(p.Prob(x))-p.LogProb(x)) > 1e-14 { + t.Errorf("Prob and LogProb mismatch case %v at %v: want %v, got %v", i, x, math.Log(x), p.LogProb(x)) + } + } +} + +// dist is a type that implements the standard set of routines. +type fullDist interface { + CDF(x float64) float64 + Entropy() float64 + ExKurtosis() float64 + LogProb(x float64) float64 + Mean() float64 + Median() float64 + NumParameters() int + Prob(x float64) float64 + Quantile(p float64) float64 + Rand() float64 + Skewness() float64 + StdDev() float64 + Survival(x float64) float64 + Variance() float64 +} + +// testFullDist tests all of the functions of a fullDist. +func testFullDist(t *testing.T, f fullDist, i int, continuous bool) { + tol := 1e-2 + const n = 1e6 + x := make([]float64, n) + generateSamples(x, f) + sort.Float64s(x) + + checkMean(t, i, x, f, tol) + checkVarAndStd(t, i, x, f, tol) + checkEntropy(t, i, x, f, tol) + checkExKurtosis(t, i, x, f, tol) + checkSkewness(t, i, x, f, tol) + if continuous { + // In a discrete distribution, the median may not have positive probability. + checkMedian(t, i, x, f, tol) + // In a discrete distribution, the CDF and Quantile may not be perfect mappings. + checkQuantileCDFSurvival(t, i, x, f, tol) + // Integrate over the PDF + checkProbContinuous(t, i, x, f, 1e-10) + checkProbQuantContinuous(t, i, x, f, tol) + } else { + // Check against empirical PDF. + checkProbDiscrete(t, i, x, f, tol) + } +} + +// testRandLogProb tests that LogProb and Rand give consistent results. This +// can be used when the distribution does not implement CDF. +func testRandLogProbContinuous(t *testing.T, i int, min float64, x []float64, f LogProber, tol float64, bins int) { + for cdf := 1 / float64(bins); cdf <= 1-1/float64(bins); cdf += 1 / float64(bins) { + // Get the estimated CDF from the samples + pt := stat.Quantile(cdf, stat.Empirical, x, nil) + + prob := func(x float64) float64 { + return math.Exp(f.LogProb(x)) + } + // Integrate the PDF to find the CDF + estCDF := quad.Fixed(prob, min, pt, 1000, nil, 0) + if !floats.EqualWithinAbsOrRel(cdf, estCDF, tol, tol) { + t.Errorf("Mismatch between integral of PDF and empirical CDF. Case %v. Want %v, got %v", i, cdf, estCDF) + } + } +} diff --git a/stat/distuv/exponential.go b/stat/distuv/exponential.go new file mode 100644 index 00000000..a249b0cc --- /dev/null +++ b/stat/distuv/exponential.go @@ -0,0 +1,259 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/stat" +) + +// Exponential represents the exponential distribution (https://en.wikipedia.org/wiki/Exponential_distribution). +type Exponential struct { + Rate float64 + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (e Exponential) CDF(x float64) float64 { + if x < 0 { + return 0 + } + return 1 - math.Exp(-e.Rate*x) +} + +// ConjugateUpdate updates the parameters of the distribution from the sufficient +// statistics of a set of samples. The sufficient statistics, suffStat, have been +// observed with nSamples observations. The prior values of the distribution are those +// currently in the distribution, and have been observed with priorStrength samples. +// +// For the exponential distribution, the sufficient statistic is the inverse of +// the mean of the samples. +// The prior is having seen priorStrength[0] samples with inverse mean Exponential.Rate +// As a result of this function, Exponential.Rate is updated based on the weighted +// samples, and priorStrength is modified to include the new number of samples observed. +// +// This function panics if len(suffStat) != 1 or len(priorStrength) != 1. +func (e *Exponential) ConjugateUpdate(suffStat []float64, nSamples float64, priorStrength []float64) { + if len(suffStat) != 1 { + panic("exponential: incorrect suffStat length") + } + if len(priorStrength) != 1 { + panic("exponential: incorrect priorStrength length") + } + + totalSamples := nSamples + priorStrength[0] + + totalSum := nSamples / suffStat[0] + if !(priorStrength[0] == 0) { + totalSum += priorStrength[0] / e.Rate + } + e.Rate = totalSamples / totalSum + priorStrength[0] = totalSamples +} + +// Entropy returns the entropy of the distribution. +func (e Exponential) Entropy() float64 { + return 1 - math.Log(e.Rate) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (Exponential) ExKurtosis() float64 { + return 6 +} + +// Fit sets the parameters of the probability distribution from the +// data samples x with relative weights w. +// If weights is nil, then all the weights are 1. +// If weights is not nil, then the len(weights) must equal len(samples). +func (e *Exponential) Fit(samples, weights []float64) { + suffStat := make([]float64, e.NumSuffStat()) + nSamples := e.SuffStat(samples, weights, suffStat) + e.ConjugateUpdate(suffStat, nSamples, make([]float64, e.NumSuffStat())) +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (e Exponential) LogProb(x float64) float64 { + if x < 0 { + return math.Inf(-1) + } + return math.Log(e.Rate) - e.Rate*x +} + +// Mean returns the mean of the probability distribution. +func (e Exponential) Mean() float64 { + return 1 / e.Rate +} + +// Median returns the median of the probability distribution. +func (e Exponential) Median() float64 { + return math.Ln2 / e.Rate +} + +// Mode returns the mode of the probability distribution. +func (Exponential) Mode() float64 { + return 0 +} + +// NumParameters returns the number of parameters in the distribution. +func (Exponential) NumParameters() int { + return 1 +} + +// NumSuffStat returns the number of sufficient statistics for the distribution. +func (Exponential) NumSuffStat() int { + return 1 +} + +// Prob computes the value of the probability density function at x. +func (e Exponential) Prob(x float64) float64 { + return math.Exp(e.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (e Exponential) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return -math.Log(1-p) / e.Rate +} + +// Rand returns a random sample drawn from the distribution. +func (e Exponential) Rand() float64 { + var rnd float64 + if e.Source == nil { + rnd = rand.ExpFloat64() + } else { + rnd = e.Source.ExpFloat64() + } + return rnd / e.Rate +} + +// Score returns the score function with respect to the parameters of the +// distribution at the input location x. The score function is the derivative +// of the log-likelihood at x with respect to the parameters +// (∂/∂θ) log(p(x;θ)) +// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise +// Score will panic, and the derivative is stored in-place into deriv. If deriv +// is nil a new slice will be allocated and returned. +// +// The order is [∂LogProb / ∂Rate]. +// +// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. +// +// Special cases: +// Score(0) = [NaN] +func (e Exponential) Score(deriv []float64, x float64) []float64 { + if deriv == nil { + deriv = make([]float64, e.NumParameters()) + } + if len(deriv) != e.NumParameters() { + panic(badLength) + } + if x > 0 { + deriv[0] = 1/e.Rate - x + return deriv + } + if x < 0 { + deriv[0] = 0 + return deriv + } + deriv[0] = math.NaN() + return deriv +} + +// ScoreInput returns the score function with respect to the input of the +// distribution at the input location specified by x. The score function is the +// derivative of the log-likelihood +// (d/dx) log(p(x)) . +// Special cases: +// ScoreInput(0) = NaN +func (e Exponential) ScoreInput(x float64) float64 { + if x > 0 { + return -e.Rate + } + if x < 0 { + return 0 + } + return math.NaN() +} + +// Skewness returns the skewness of the distribution. +func (Exponential) Skewness() float64 { + return 2 +} + +// StdDev returns the standard deviation of the probability distribution. +func (e Exponential) StdDev() float64 { + return 1 / e.Rate +} + +// SuffStat computes the sufficient statistics of set of samples to update +// the distribution. The sufficient statistics are stored in place, and the +// effective number of samples are returned. +// +// The exponential distribution has one sufficient statistic, the average rate +// of the samples. +// +// If weights is nil, the weights are assumed to be 1, otherwise panics if +// len(samples) != len(weights). Panics if len(suffStat) != NumSuffStat(). +func (Exponential) SuffStat(samples, weights, suffStat []float64) (nSamples float64) { + if len(weights) != 0 && len(samples) != len(weights) { + panic(badLength) + } + + if len(suffStat) != (Exponential{}).NumSuffStat() { + panic(badSuffStat) + } + + if len(weights) == 0 { + nSamples = float64(len(samples)) + } else { + nSamples = floats.Sum(weights) + } + + mean := stat.Mean(samples, weights) + suffStat[0] = 1 / mean + return nSamples +} + +// Survival returns the survival function (complementary CDF) at x. +func (e Exponential) Survival(x float64) float64 { + if x < 0 { + return 1 + } + return math.Exp(-e.Rate * x) +} + +// setParameters modifies the parameters of the distribution. +func (e *Exponential) setParameters(p []Parameter) { + if len(p) != e.NumParameters() { + panic("exponential: incorrect number of parameters to set") + } + if p[0].Name != "Rate" { + panic("exponential: " + panicNameMismatch) + } + e.Rate = p[0].Value +} + +// Variance returns the variance of the probability distribution. +func (e Exponential) Variance() float64 { + return 1 / (e.Rate * e.Rate) +} + +// parameters returns the parameters of the distribution. +func (e Exponential) parameters(p []Parameter) []Parameter { + nParam := e.NumParameters() + if p == nil { + p = make([]Parameter, nParam) + } else if len(p) != nParam { + panic("exponential: improper parameter length") + } + p[0].Name = "Rate" + p[0].Value = e.Rate + return p +} diff --git a/stat/distuv/exponential_test.go b/stat/distuv/exponential_test.go new file mode 100644 index 00000000..9c389702 --- /dev/null +++ b/stat/distuv/exponential_test.go @@ -0,0 +1,71 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "testing" +) + +func TestExponentialProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 1, + cumProb: 0, + logProb: 0, + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: math.Inf(-1), + }, + { + loc: 1, + prob: 1 / (math.E), + cumProb: 0.6321205588285576784044762298385391325541888689682321654921631983025385042551001966428527256540803563, + logProb: -1, + }, + { + loc: 20, + prob: math.Exp(-20), + cumProb: 0.999999997938846377561442172034059619844179023624192724400896307027755338370835976215440646720089072, + logProb: -20, + }, + } + testDistributionProbs(t, Exponential{Rate: 1}, "Exponential", pts) +} + +func TestExponentialFitPrior(t *testing.T) { + testConjugateUpdate(t, func() ConjugateUpdater { return &Exponential{Rate: 13.7} }) +} + +func TestExponentialScore(t *testing.T) { + for _, test := range []*Exponential{ + { + Rate: 1, + }, + { + Rate: 0.35, + }, + { + Rate: 4.6, + }, + } { + testDerivParam(t, test) + } +} + +func TestExponentialFitPanic(t *testing.T) { + e := Exponential{Rate: 2} + defer func() { + r := recover() + if r != nil { + t.Errorf("unexpected panic for Fit call: %v", r) + } + }() + e.Fit(make([]float64, 10), nil) +} diff --git a/stat/distuv/f.go b/stat/distuv/f.go new file mode 100644 index 00000000..6e689e6e --- /dev/null +++ b/stat/distuv/f.go @@ -0,0 +1,132 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +// F implements the F-distribution, a two-parameter continuous distribution +// with support over the positive real numbers. +// +// The F-distribution has density function +// sqrt(((d1*x)^d1) * d2^d2 / ((d1*x+d2)^(d1+d2))) / (x * B(d1/2,d2/2)) +// where B is the beta function. +// +// For more information, see https://en.wikipedia.org/wiki/F-distribution +type F struct { + D1 float64 // Degrees of freedom for the numerator + D2 float64 // Degrees of freedom for the denominator + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (f F) CDF(x float64) float64 { + return mathext.RegIncBeta(f.D1/2, f.D2/2, f.D1*x/(f.D1*x+f.D2)) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +// +// ExKurtosis returns NaN if the D2 parameter is less or equal to 8. +func (f F) ExKurtosis() float64 { + if f.D2 <= 8 { + return math.NaN() + } + return (12 / (f.D2 - 6)) * ((5*f.D2-22)/(f.D2-8) + ((f.D2-4)/f.D1)*((f.D2-2)/(f.D2-8))*((f.D2-2)/(f.D1+f.D2-2))) +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (f F) LogProb(x float64) float64 { + return 0.5*(f.D1*math.Log(f.D1*x)+f.D2*math.Log(f.D2)-(f.D1+f.D2)*math.Log(f.D1*x+f.D2)) - math.Log(x) - mathext.Lbeta(f.D1/2, f.D2/2) +} + +// Mean returns the mean of the probability distribution. +// +// Mean returns NaN if the D2 parameter is less than or equal to 2. +func (f F) Mean() float64 { + if f.D2 <= 2 { + return math.NaN() + } + return f.D2 / (f.D2 - 2) +} + +// Mode returns the mode of the distribution. +// +// Mode returns NaN if the D1 parameter is less than or equal to 2. +func (f F) Mode() float64 { + if f.D1 <= 2 { + return math.NaN() + } + return ((f.D1 - 2) / f.D1) * (f.D2 / (f.D2 + 2)) +} + +// NumParameters returns the number of parameters in the distribution. +func (f F) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (f F) Prob(x float64) float64 { + return math.Exp(f.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative distribution function. +func (f F) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + y := mathext.InvRegIncBeta(0.5*f.D1, 0.5*f.D2, p) + return f.D2 * y / (f.D1 * (1 - y)) +} + +// Rand returns a random sample drawn from the distribution. +func (f F) Rand() float64 { + u1 := ChiSquared{f.D1, f.Source}.Rand() + u2 := ChiSquared{f.D2, f.Source}.Rand() + return (u1 / f.D1) / (u2 / f.D2) +} + +// Skewness returns the skewness of the distribution. +// +// Skewness returns NaN if the D2 parameter is less than or equal to 6. +func (f F) Skewness() float64 { + if f.D2 <= 6 { + return math.NaN() + } + num := (2*f.D1 + f.D2 - 2) * math.Sqrt(8*(f.D2-4)) + den := (f.D2 - 6) * math.Sqrt(f.D1*(f.D1+f.D2-2)) + return num / den +} + +// StdDev returns the standard deviation of the probability distribution. +// +// StdDev returns NaN if the D2 parameter is less than or equal to 4. +func (f F) StdDev() float64 { + if f.D2 <= 4 { + return math.NaN() + } + return math.Sqrt(f.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (f F) Survival(x float64) float64 { + return 1 - f.CDF(x) +} + +// Variance returns the variance of the probability distribution. +// +// Variance returns NaN if the D2 parameter is less than or equal to 4. +func (f F) Variance() float64 { + if f.D2 <= 4 { + return math.NaN() + } + num := 2 * f.D2 * f.D2 * (f.D1 + f.D2 - 2) + den := f.D1 * (f.D2 - 2) * (f.D2 - 2) * (f.D2 - 4) + return num / den +} diff --git a/stat/distuv/f_test.go b/stat/distuv/f_test.go new file mode 100644 index 00000000..7494d7c7 --- /dev/null +++ b/stat/distuv/f_test.go @@ -0,0 +1,89 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestFProb(t *testing.T) { + for _, test := range []struct { + x, d1, d2, want float64 + }{ + // Values calculated with scipy.stats.f + {0.0001, 4, 6, 0.00053315559110558126}, + {0.1, 1, 1, 0.91507658371794609}, + {0.5, 11, 7, 0.66644660411410883}, + {0.9, 20, 15, 0.88293424959522437}, + {1, 1, 1, 0.15915494309189535}, + {2, 15, 12, 0.16611971273429088}, + {5, 4, 8, 0.013599775603702537}, + {10, 12, 9, 0.00032922887567957289}, + {100, 7, 7, 6.08037637806889e-08}, + {1000, 2, 1, 1.1171959870312232e-05}, + } { + pdf := F{test.d1, test.d2, nil}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Prob mismatch, x = %v, d1 = %v, d2 = %v. Got %v, want %v", test.x, test.d1, test.d2, pdf, test.want) + } + } +} + +func TestFCDF(t *testing.T) { + for _, test := range []struct { + x, d1, d2, want float64 + }{ + // Values calculated with scipy.stats.f + {0.0001, 4, 6, 2.6660741629519019e-08}, + {0.1, 1, 1, 0.19498222904213672}, + {0.5, 11, 7, 0.14625028471336987}, + {0.9, 20, 15, 0.40567939897287852}, + {1, 1, 1, 0.50000000000000011}, + {2, 15, 12, 0.8839384428956264}, + {5, 4, 8, 0.97429642410900219}, + {10, 12, 9, 0.99915733385467187}, + {100, 7, 7, 0.99999823560259171}, + {1000, 2, 1, 0.97764490829950534}, + } { + cdf := F{test.d1, test.d2, nil}.CDF(test.x) + if !floats.EqualWithinAbsOrRel(cdf, test.want, 1e-10, 1e-10) { + t.Errorf("CDF mismatch, x = %v, d1 = %v, d2 = %v. Got %v, want %v", test.x, test.d1, test.d2, cdf, test.want) + } + } +} + +func TestF(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for i, b := range []F{ + {13, 16, src}, + {42, 31, src}, + {77, 92, src}, + } { + testF(t, b, i) + } +} + +func testF(t *testing.T, f F, i int) { + const ( + tol = 1e-2 + n = 2e6 + bins = 50 + ) + x := make([]float64, n) + generateSamples(x, f) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, 0, x, f, tol, bins) + checkProbContinuous(t, i, x, f, 1e-3) + checkMean(t, i, x, f, tol) + checkVarAndStd(t, i, x, f, tol) + checkExKurtosis(t, i, x, f, 5e-2) + checkSkewness(t, i, x, f, tol) + checkQuantileCDFSurvival(t, i, x, f, 1e-3) +} diff --git a/stat/distuv/gamma.go b/stat/distuv/gamma.go new file mode 100644 index 00000000..650ad6c8 --- /dev/null +++ b/stat/distuv/gamma.go @@ -0,0 +1,244 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +// Gamma implements the Gamma distribution, a two-parameter continuous distribution +// with support over the positive real numbers. +// +// The gamma distribution has density function +// β^α / Γ(α) x^(α-1)e^(-βx) +// +// For more information, see https://en.wikipedia.org/wiki/Gamma_distribution +type Gamma struct { + // Alpha is the shape parameter of the distribution. Alpha must be greater + // than 0. If Alpha == 1, this is equivalent to an exponential distribution. + Alpha float64 + // Beta is the rate parameter of the distribution. Beta must be greater than 0. + // If Beta == 2, this is equivalent to a Chi-Squared distribution. + Beta float64 + + Source *rand.Rand +} + +// CDF computes the value of the cumulative distribution function at x. +func (g Gamma) CDF(x float64) float64 { + if x < 0 { + return 0 + } + return mathext.GammaInc(g.Alpha, g.Beta*x) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (g Gamma) ExKurtosis() float64 { + return 6 / g.Alpha +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (g Gamma) LogProb(x float64) float64 { + if x <= 0 { + return math.Inf(-1) + } + a := g.Alpha + b := g.Beta + lg, _ := math.Lgamma(a) + return a*math.Log(b) - lg + (a-1)*math.Log(x) - b*x +} + +// Mean returns the mean of the probability distribution. +func (g Gamma) Mean() float64 { + return g.Alpha / g.Beta +} + +// Mode returns the mode of the normal distribution. +// +// The mode is NaN in the special case where the Alpha (shape) parameter +// is less than 1. +func (g Gamma) Mode() float64 { + if g.Alpha < 1 { + return math.NaN() + } + return (g.Alpha - 1) / g.Beta +} + +// NumParameters returns the number of parameters in the distribution. +func (Gamma) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (g Gamma) Prob(x float64) float64 { + return math.Exp(g.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative distribution function. +func (g Gamma) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return mathext.GammaIncInv(g.Alpha, p) / g.Beta +} + +// Rand returns a random sample drawn from the distribution. +// +// Rand panics if either alpha or beta is <= 0. +func (g Gamma) Rand() float64 { + if g.Beta <= 0 { + panic("gamma: beta <= 0") + } + + unifrnd := rand.Float64 + exprnd := rand.ExpFloat64 + normrnd := rand.NormFloat64 + if g.Source != nil { + unifrnd = g.Source.Float64 + exprnd = g.Source.ExpFloat64 + normrnd = g.Source.NormFloat64 + } + + a := g.Alpha + b := g.Beta + switch { + case a <= 0: + panic("gamma: alpha < 0") + case a == 1: + // Generate from exponential + return exprnd() / b + case a < 0.3: + // Generate using + // Liu, Chuanhai, Martin, Ryan and Syring, Nick. "Simulating from a + // gamma distribution with small shape parameter" + // https://arxiv.org/abs/1302.1884 + // use this reference: http://link.springer.com/article/10.1007/s00180-016-0692-0 + + // Algorithm adjusted to work in log space as much as possible. + lambda := 1/a - 1 + lw := math.Log(a) - 1 - math.Log(1-a) + lr := -math.Log(1 + math.Exp(lw)) + lc, _ := math.Lgamma(a + 1) + for { + e := exprnd() + var z float64 + if e >= -lr { + z = e + lr + } else { + z = -exprnd() / lambda + } + lh := lc - z - math.Exp(-z/a) + var lEta float64 + if z >= 0 { + lEta = lc - z + } else { + lEta = lc + lw + math.Log(lambda) + lambda*z + } + if lh-lEta > -exprnd() { + return math.Exp(-z/a) / b + } + } + case a >= 0.3 && a < 1: + // Generate using: + // Kundu, Debasis, and Rameshwar D. Gupta. "A convenient way of generating + // gamma random variables using generalized exponential distribution." + // Computational Statistics & Data Analysis 51.6 (2007): 2796-2802. + + // TODO(btracey): Change to using Algorithm 3 if we can find the bug in + // the implementation below. + + // Algorithm 2. + alpha := g.Alpha + a := math.Pow(1-expNegOneHalf, alpha) / (math.Pow(1-expNegOneHalf, alpha) + alpha*math.Exp(-1)/math.Pow(2, alpha)) + b := math.Pow(1-expNegOneHalf, alpha) + alpha/math.E/math.Pow(2, alpha) + var x float64 + for { + u := unifrnd() + if u <= a { + x = -2 * math.Log(1-math.Pow(u*b, 1/alpha)) + } else { + x = -math.Log(math.Pow(2, alpha) / alpha * b * (1 - u)) + } + v := unifrnd() + if x <= 1 { + if v <= math.Pow(x, alpha-1)*math.Exp(-x/2)/(math.Pow(2, alpha-1)*math.Pow(1-math.Exp(-x/2), alpha-1)) { + break + } + } else { + if v <= math.Pow(x, alpha-1) { + break + } + } + } + return x / g.Beta + + /* + // Algorithm 3. + d := 1.0334 - 0.0766*math.Exp(2.2942*alpha) + a := math.Pow(2, alpha) * math.Pow(1-math.Exp(-d/2), alpha) + b := alpha * math.Pow(d, alpha-1) * math.Exp(-d) + c := a + b + var x float64 + for { + u := unifrnd() + if u <= a/(a+b) { + x = -2 * math.Log(1-math.Pow(c*u, 1/a)/2) + } else { + x = -math.Log(c * (1 - u) / (alpha * math.Pow(d, alpha-1))) + } + v := unifrnd() + if x <= d { + if v <= (math.Pow(x, alpha-1)*math.Exp(-x/2))/(math.Pow(2, alpha-1)*math.Pow(1-math.Exp(-x/2), alpha-1)) { + break + } + } else { + if v <= math.Pow(d/x, 1-alpha) { + break + } + } + } + return x / g.Beta + */ + case a > 1: + // Generate using: + // Marsaglia, George, and Wai Wan Tsang. "A simple method for generating + // gamma variables." ACM Transactions on Mathematical Software (TOMS) + // 26.3 (2000): 363-372. + d := a - 1.0/3 + c := 1 / (3 * math.Sqrt(d)) + for { + u := -exprnd() + x := normrnd() + v := 1 + x*c + v = v * v * v + if u < 0.5*x*x+d*(1-v+math.Log(v)) { + return d * v / b + } + } + } + panic("unreachable") +} + +// Survival returns the survival function (complementary CDF) at x. +func (g Gamma) Survival(x float64) float64 { + if x < 0 { + return 1 + } + return mathext.GammaIncComp(g.Alpha, g.Beta*x) +} + +// StdDev returns the standard deviation of the probability distribution. +func (g Gamma) StdDev() float64 { + return math.Sqrt(g.Variance()) +} + +// Variance returns the variance of the probability distribution. +func (g Gamma) Variance() float64 { + return g.Alpha / g.Beta / g.Beta +} diff --git a/stat/distuv/gamma_test.go b/stat/distuv/gamma_test.go new file mode 100644 index 00000000..ca7aa609 --- /dev/null +++ b/stat/distuv/gamma_test.go @@ -0,0 +1,63 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestGamma(t *testing.T) { + // Values a comparison with scipy + for _, test := range []struct { + x, alpha, want float64 + }{ + {0.9, 0.1, 0.046986817861555757}, + {0.9, 0.01, 0.0045384353289090401}, + {0.45, 0.01, 0.014137035997241795}, + } { + pdf := Gamma{Alpha: test.alpha, Beta: 1}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Pdf mismatch. Got %v, want %v", pdf, test.want) + } + } + src := rand.New(rand.NewSource(1)) + for i, g := range []Gamma{ + + {Alpha: 0.5, Beta: 0.8, Source: src}, + {Alpha: 0.9, Beta: 6, Source: src}, + {Alpha: 0.9, Beta: 500, Source: src}, + + {Alpha: 1, Beta: 1, Source: src}, + + {Alpha: 1.6, Beta: 0.4, Source: src}, + {Alpha: 2.6, Beta: 1.5, Source: src}, + {Alpha: 5.6, Beta: 0.5, Source: src}, + {Alpha: 30, Beta: 1.7, Source: src}, + {Alpha: 30.2, Beta: 1.7, Source: src}, + } { + testGamma(t, g, i) + } +} + +func testGamma(t *testing.T, f Gamma, i int) { + // TODO(btracey): Replace this when Gamma implements FullDist. + tol := 2e-3 + const n = 1e6 + const bins = 50 + x := make([]float64, n) + generateSamples(x, f) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, 0, x, f, tol, bins) + checkMean(t, i, x, f, tol) + checkVarAndStd(t, i, x, f, 2e-2) + checkExKurtosis(t, i, x, f, 5e-2) + checkProbContinuous(t, i, x, f, 1e-3) + checkQuantileCDFSurvival(t, i, x, f, 1e-2) +} diff --git a/stat/distuv/general.go b/stat/distuv/general.go new file mode 100644 index 00000000..8411c85e --- /dev/null +++ b/stat/distuv/general.go @@ -0,0 +1,25 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package distuv provides univariate random distribution types. +package distuv + +import "math" + +// Parameter represents a parameter of a probability distribution +type Parameter struct { + Name string + Value float64 +} + +var ( + badPercentile = "distuv: percentile out of bounds" + badLength = "distuv: slice length mismatch" + badSuffStat = "distuv: wrong suffStat length" + badNoSamples = "distuv: must have at least one sample" +) + +var ( + expNegOneHalf = math.Exp(-0.5) +) diff --git a/stat/distuv/general_test.go b/stat/distuv/general_test.go new file mode 100644 index 00000000..ee5b4b3f --- /dev/null +++ b/stat/distuv/general_test.go @@ -0,0 +1,205 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "fmt" + "math" + "testing" + + "gonum.org/v1/gonum/diff/fd" + "gonum.org/v1/gonum/floats" +) + +type univariateProbPoint struct { + loc float64 + logProb float64 + cumProb float64 + prob float64 +} + +type UniProbDist interface { + Prob(float64) float64 + CDF(float64) float64 + LogProb(float64) float64 + Quantile(float64) float64 + Survival(float64) float64 +} + +func absEq(a, b float64) bool { + if math.Abs(a-b) > 1e-14 { + return false + } + return true +} + +// TODO: Implement a better test for Quantile +func testDistributionProbs(t *testing.T, dist UniProbDist, name string, pts []univariateProbPoint) { + for _, pt := range pts { + logProb := dist.LogProb(pt.loc) + if !absEq(logProb, pt.logProb) { + t.Errorf("Log probability doesnt match for "+name+". Expected %v. Found %v", pt.logProb, logProb) + } + prob := dist.Prob(pt.loc) + if !absEq(prob, pt.prob) { + t.Errorf("Probability doesn't match for "+name+". Expected %v. Found %v", pt.prob, prob) + } + cumProb := dist.CDF(pt.loc) + if !absEq(cumProb, pt.cumProb) { + t.Errorf("Cumulative Probability doesn't match for "+name+". Expected %v. Found %v", pt.cumProb, cumProb) + } + if !absEq(dist.Survival(pt.loc), 1-pt.cumProb) { + t.Errorf("Survival doesn't match for %v. Expected %v, Found %v", name, 1-pt.cumProb, dist.Survival(pt.loc)) + } + if pt.prob != 0 { + if math.Abs(dist.Quantile(pt.cumProb)-pt.loc) > 1e-4 { + fmt.Println("true =", pt.loc) + fmt.Println("calculated=", dist.Quantile(pt.cumProb)) + t.Errorf("Quantile doesn't match for "+name+", loc = %v", pt.loc) + } + } + } +} + +type ConjugateUpdater interface { + NumParameters() int + parameters([]Parameter) []Parameter + + NumSuffStat() int + SuffStat([]float64, []float64, []float64) float64 + ConjugateUpdate([]float64, float64, []float64) + + Rand() float64 +} + +func testConjugateUpdate(t *testing.T, newFittable func() ConjugateUpdater) { + for i, test := range []struct { + samps []float64 + weights []float64 + }{ + { + samps: randn(newFittable(), 10), + weights: nil, + }, + { + samps: randn(newFittable(), 10), + weights: ones(10), + }, + { + samps: randn(newFittable(), 10), + weights: randn(&Exponential{Rate: 1}, 10), + }, + } { + // ensure that conjugate produces the same result both incrementally and all at once + incDist := newFittable() + stats := make([]float64, incDist.NumSuffStat()) + prior := make([]float64, incDist.NumParameters()) + for j := range test.samps { + var incWeights, allWeights []float64 + if test.weights != nil { + incWeights = test.weights[j : j+1] + allWeights = test.weights[0 : j+1] + } + nsInc := incDist.SuffStat(test.samps[j:j+1], incWeights, stats) + incDist.ConjugateUpdate(stats, nsInc, prior) + + allDist := newFittable() + nsAll := allDist.SuffStat(test.samps[0:j+1], allWeights, stats) + allDist.ConjugateUpdate(stats, nsAll, make([]float64, allDist.NumParameters())) + if !parametersEqual(incDist.parameters(nil), allDist.parameters(nil), 1e-12) { + t.Errorf("prior doesn't match after incremental update for (%d, %d). Incremental is %v, all at once is %v", i, j, incDist, allDist) + } + + if test.weights == nil { + onesDist := newFittable() + nsOnes := onesDist.SuffStat(test.samps[0:j+1], ones(j+1), stats) + onesDist.ConjugateUpdate(stats, nsOnes, make([]float64, onesDist.NumParameters())) + if !parametersEqual(onesDist.parameters(nil), incDist.parameters(nil), 1e-14) { + t.Errorf("nil and uniform weighted prior doesn't match for incremental update for (%d, %d). Uniform weighted is %v, nil is %v", i, j, onesDist, incDist) + } + if !parametersEqual(onesDist.parameters(nil), allDist.parameters(nil), 1e-14) { + t.Errorf("nil and uniform weighted prior doesn't match for all at once update for (%d, %d). Uniform weighted is %v, nil is %v", i, j, onesDist, incDist) + } + } + } + } +} + +// randn generates a specified number of random samples +func randn(dist Rander, n int) []float64 { + x := make([]float64, n) + for i := range x { + x[i] = dist.Rand() + } + return x +} + +func ones(n int) []float64 { + x := make([]float64, n) + for i := range x { + x[i] = 1 + } + return x +} + +func parametersEqual(p1, p2 []Parameter, tol float64) bool { + for i, p := range p1 { + if p.Name != p2[i].Name { + return false + } + if math.Abs(p.Value-p2[i].Value) > tol { + return false + } + } + return true +} + +type derivParamTester interface { + LogProb(x float64) float64 + Score(deriv []float64, x float64) []float64 + Quantile(p float64) float64 + NumParameters() int + parameters([]Parameter) []Parameter + setParameters([]Parameter) +} + +func testDerivParam(t *testing.T, d derivParamTester) { + // Tests that the derivative matches for a number of different quantiles + // along the distribution. + nTest := 10 + quantiles := make([]float64, nTest) + floats.Span(quantiles, 0.1, 0.9) + + deriv := make([]float64, d.NumParameters()) + fdDeriv := make([]float64, d.NumParameters()) + + initParams := d.parameters(nil) + init := make([]float64, d.NumParameters()) + for i, v := range initParams { + init[i] = v.Value + } + for _, v := range quantiles { + d.setParameters(initParams) + x := d.Quantile(v) + d.Score(deriv, x) + f := func(p []float64) float64 { + params := d.parameters(nil) + for i, v := range p { + params[i].Value = v + } + d.setParameters(params) + return d.LogProb(x) + } + fd.Gradient(fdDeriv, f, init, nil) + if !floats.EqualApprox(deriv, fdDeriv, 1e-6) { + t.Fatal("Derivative mismatch. Want", fdDeriv, ", got", deriv, ".") + } + d.setParameters(initParams) + d2 := d.Score(nil, x) + if !floats.EqualApprox(d2, deriv, 1e-14) { + t.Errorf("Derivative mismatch when input nil Want %v, got %v", d2, deriv) + } + } +} diff --git a/stat/distuv/interfaces.go b/stat/distuv/interfaces.go new file mode 100644 index 00000000..b2eb80ba --- /dev/null +++ b/stat/distuv/interfaces.go @@ -0,0 +1,22 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +type LogProber interface { + LogProb(float64) float64 +} + +type Rander interface { + Rand() float64 +} + +type RandLogProber interface { + Rander + LogProber +} + +type Quantiler interface { + Quantile(p float64) float64 +} diff --git a/stat/distuv/laplace.go b/stat/distuv/laplace.go new file mode 100644 index 00000000..3686a2fa --- /dev/null +++ b/stat/distuv/laplace.go @@ -0,0 +1,252 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + "sort" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/stat" +) + +// Laplace represents the Laplace distribution (https://en.wikipedia.org/wiki/Laplace_distribution). +type Laplace struct { + Mu float64 // Mean of the Laplace distribution + Scale float64 // Scale of the Laplace distribution + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (l Laplace) CDF(x float64) float64 { + if x < l.Mu { + return 0.5 * math.Exp((x-l.Mu)/l.Scale) + } + return 1 - 0.5*math.Exp(-(x-l.Mu)/l.Scale) +} + +// Entropy returns the entropy of the distribution. +func (l Laplace) Entropy() float64 { + return 1 + math.Log(2*l.Scale) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (l Laplace) ExKurtosis() float64 { + return 3 +} + +// Fit sets the parameters of the probability distribution from the +// data samples x with relative weights w. +// If weights is nil, then all the weights are 1. +// If weights is not nil, then the len(weights) must equal len(samples). +// +// Note: Laplace distribution has no FitPrior because it has no sufficient +// statistics. +func (l *Laplace) Fit(samples, weights []float64) { + if len(samples) != len(weights) { + panic(badLength) + } + + if len(samples) == 0 { + panic(badNoSamples) + } + if len(samples) == 1 { + l.Mu = samples[0] + l.Scale = 0 + return + } + + var ( + sortedSamples []float64 + sortedWeights []float64 + ) + if sort.Float64sAreSorted(samples) { + sortedSamples = samples + sortedWeights = weights + } else { + // Need to copy variables so the input variables aren't effected by the sorting + sortedSamples = make([]float64, len(samples)) + copy(sortedSamples, samples) + sortedWeights := make([]float64, len(samples)) + copy(sortedWeights, weights) + + stat.SortWeighted(sortedSamples, sortedWeights) + } + + // The (weighted) median of the samples is the maximum likelihood estimate + // of the mean parameter + // TODO: Rethink quantile type when stat has more options + l.Mu = stat.Quantile(0.5, stat.Empirical, sortedSamples, sortedWeights) + + sumWeights := floats.Sum(weights) + + // The scale parameter is the average absolute distance + // between the sample and the mean + absError := stat.MomentAbout(1, samples, l.Mu, weights) + + l.Scale = absError / sumWeights +} + +// LogProb computes the natural logarithm of the value of the probability density +// function at x. +func (l Laplace) LogProb(x float64) float64 { + return -math.Ln2 - math.Log(l.Scale) - math.Abs(x-l.Mu)/l.Scale +} + +// MarshalParameters implements the ParameterMarshaler interface +func (l Laplace) MarshalParameters(p []Parameter) { + if len(p) != l.NumParameters() { + panic(badLength) + } + p[0].Name = "Mu" + p[0].Value = l.Mu + p[1].Name = "Scale" + p[1].Value = l.Scale + return +} + +// Mean returns the mean of the probability distribution. +func (l Laplace) Mean() float64 { + return l.Mu +} + +// Median returns the median of the LaPlace distribution. +func (l Laplace) Median() float64 { + return l.Mu +} + +// Mode returns the mode of the LaPlace distribution. +func (l Laplace) Mode() float64 { + return l.Mu +} + +// NumParameters returns the number of parameters in the distribution. +func (l Laplace) NumParameters() int { + return 2 +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (l Laplace) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + if p < 0.5 { + return l.Mu + l.Scale*math.Log(1+2*(p-0.5)) + } + return l.Mu - l.Scale*math.Log(1-2*(p-0.5)) +} + +// Prob computes the value of the probability density function at x. +func (l Laplace) Prob(x float64) float64 { + return math.Exp(l.LogProb(x)) +} + +// Rand returns a random sample drawn from the distribution. +func (l Laplace) Rand() float64 { + var rnd float64 + if l.Source == nil { + rnd = rand.Float64() + } else { + rnd = l.Source.Float64() + } + u := rnd - 0.5 + if u < 0 { + return l.Mu + l.Scale*math.Log(1+2*u) + } + return l.Mu - l.Scale*math.Log(1-2*u) +} + +// Score returns the score function with respect to the parameters of the +// distribution at the input location x. The score function is the derivative +// of the log-likelihood at x with respect to the parameters +// (∂/∂θ) log(p(x;θ)) +// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise +// Score will panic, and the derivative is stored in-place into deriv. If deriv +// is nil a new slice will be allocated and returned. +// +// The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Scale]. +// +// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. +// +// Special cases: +// Score(0) = [0, -0.5/l.Scale] +func (l Laplace) Score(deriv []float64, x float64) []float64 { + if deriv == nil { + deriv = make([]float64, l.NumParameters()) + } + if len(deriv) != l.NumParameters() { + panic(badLength) + } + diff := x - l.Mu + if diff > 0 { + deriv[0] = 1 / l.Scale + } else if diff < 0 { + deriv[0] = -1 / l.Scale + } else if diff == 0 { + deriv[0] = 0 + } else { + // must be NaN + deriv[0] = math.NaN() + } + + deriv[1] = math.Abs(diff)/(l.Scale*l.Scale) - 0.5/(l.Scale) + return deriv +} + +// ScoreInput returns the score function with respect to the input of the +// distribution at the input location specified by x. The score function is the +// derivative of the log-likelihood +// (d/dx) log(p(x)) . +// Special cases: +// ScoreInput(l.Mu) = 0 +func (l Laplace) ScoreInput(x float64) float64 { + diff := x - l.Mu + if diff == 0 { + return 0 + } + if diff > 0 { + return -1 / l.Scale + } + return 1 / l.Scale +} + +// Skewness returns the skewness of the distribution. +func (Laplace) Skewness() float64 { + return 0 +} + +// StdDev returns the standard deviation of the distribution. +func (l Laplace) StdDev() float64 { + return math.Sqrt2 * l.Scale +} + +// Survival returns the survival function (complementary CDF) at x. +func (l Laplace) Survival(x float64) float64 { + if x < l.Mu { + return 1 - 0.5*math.Exp((x-l.Mu)/l.Scale) + } + return 0.5 * math.Exp(-(x-l.Mu)/l.Scale) +} + +// UnmarshalParameters implements the ParameterMarshaler interface +func (l *Laplace) UnmarshalParameters(p []Parameter) { + if len(p) != l.NumParameters() { + panic(badLength) + } + if p[0].Name != "Mu" { + panic("laplace: " + panicNameMismatch) + } + if p[1].Name != "Scale" { + panic("laplace: " + panicNameMismatch) + } + l.Mu = p[0].Value + l.Scale = p[1].Value +} + +// Variance returns the variance of the probability distribution. +func (l Laplace) Variance() float64 { + return 2 * l.Scale * l.Scale +} diff --git a/stat/distuv/laplace_test.go b/stat/distuv/laplace_test.go new file mode 100644 index 00000000..0cbb2594 --- /dev/null +++ b/stat/distuv/laplace_test.go @@ -0,0 +1,58 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "testing" +) + +func TestLaplaceProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 0.5, + cumProb: 0.5, + logProb: math.Log(0.5), + }, + { + loc: -1, + prob: 1 / (2 * math.E), + cumProb: 0.1839397205857211607977618850807304337229055655158839172539184008487307478724499016785736371729598219, + logProb: math.Log(1 / (2 * math.E)), + }, + { + loc: 1, + prob: 1 / (2 * math.E), + cumProb: 0.8160602794142788392022381149192695662770944344841160827460815991512692521275500983214263628270401781, + logProb: math.Log(1 / (2 * math.E)), + }, + { + loc: -7, + prob: 1 / (2 * math.Pow(math.E, 7)), + cumProb: 0.0004559409827772581040015680422046413132368622637180269204080667109447399446551532646631395032324502210, + logProb: math.Log(1 / (2 * math.Pow(math.E, 7))), + }, + { + loc: 7, + prob: 1 / (2 * math.Pow(math.E, 7)), + cumProb: 0.9995440590172227418959984319577953586867631377362819730795919332890552600553448467353368604967675498, + logProb: math.Log(1 / (2 * math.Pow(math.E, 7))), + }, + { + loc: -20, + prob: math.Exp(-20.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641869), + cumProb: 1.030576811219278913982970190077910488187903637799551846486122330814582011892279676639955463952790684 * 1e-9, + logProb: -20.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641869, + }, + { + loc: 20, + prob: math.Exp(-20.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641869), + cumProb: 0.999999998969423188780721086017029809922089511812096362200448153513877669185417988107720323360044536, + logProb: -20.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641869, + }, + } + testDistributionProbs(t, Laplace{Mu: 0, Scale: 1}, "Laplace", pts) +} diff --git a/stat/distuv/lognormal.go b/stat/distuv/lognormal.go new file mode 100644 index 00000000..e13afce5 --- /dev/null +++ b/stat/distuv/lognormal.go @@ -0,0 +1,112 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" +) + +// LogNormal represents a random variable whose log is normally distributed. +// The probability density function is given by +// 1/(x σ √2π) exp(-(ln(x)-μ)^2)/(2σ^2)) +type LogNormal struct { + Mu float64 + Sigma float64 + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (l LogNormal) CDF(x float64) float64 { + return 0.5 + 0.5*math.Erf((math.Log(x)-l.Mu)/(math.Sqrt2*l.Sigma)) +} + +// Entropy returns the differential entropy of the distribution. +func (l LogNormal) Entropy() float64 { + return 0.5 + 0.5*math.Log(2*math.Pi*l.Sigma*l.Sigma) + l.Mu +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (l LogNormal) ExKurtosis() float64 { + s2 := l.Sigma * l.Sigma + return math.Exp(4*s2) + 2*math.Exp(3*s2) + 3*math.Exp(2*s2) - 6 +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (l LogNormal) LogProb(x float64) float64 { + if x < 0 { + return math.Inf(-1) + } + logx := math.Log(x) + normdiff := (logx - l.Mu) / l.Sigma + return -0.5*normdiff*normdiff - logx - math.Log(l.Sigma) - logRoot2Pi +} + +// Mean returns the mean of the probability distribution. +func (l LogNormal) Mean() float64 { + return math.Exp(l.Mu + 0.5*l.Sigma*l.Sigma) +} + +// Median returns the median of the probability distribution. +func (l LogNormal) Median() float64 { + return math.Exp(l.Mu) +} + +// Mode returns the mode of the probability distribution. +func (l LogNormal) Mode() float64 { + return l.Mu +} + +// NumParameters returns the number of parameters in the distribution. +func (LogNormal) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (l LogNormal) Prob(x float64) float64 { + return math.Exp(l.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (l LogNormal) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + // Formula from http://www.math.uah.edu/stat/special/LogNormal.html. + return math.Exp(l.Mu + l.Sigma*UnitNormal.Quantile(p)) +} + +// Rand returns a random sample drawn from the distribution. +func (l LogNormal) Rand() float64 { + var rnd float64 + if l.Source == nil { + rnd = rand.NormFloat64() + } else { + rnd = l.Source.NormFloat64() + } + return math.Exp(rnd*l.Sigma + l.Mu) +} + +// Skewness returns the skewness of the distribution. +func (l LogNormal) Skewness() float64 { + s2 := l.Sigma * l.Sigma + return (math.Exp(s2) + 2) * math.Sqrt(math.Exp(s2)-1) +} + +// StdDev returns the standard deviation of the probability distribution. +func (l LogNormal) StdDev() float64 { + return math.Sqrt(l.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (l LogNormal) Survival(x float64) float64 { + return 0.5 * (1 - math.Erf((math.Log(x)-l.Mu)/(math.Sqrt2*l.Sigma))) +} + +// Variance returns the variance of the probability distribution. +func (l LogNormal) Variance() float64 { + s2 := l.Sigma * l.Sigma + return (math.Exp(s2) - 1) * math.Exp(2*l.Mu+s2) +} diff --git a/stat/distuv/lognormal_test.go b/stat/distuv/lognormal_test.go new file mode 100644 index 00000000..85872854 --- /dev/null +++ b/stat/distuv/lognormal_test.go @@ -0,0 +1,26 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import "testing" + +func TestLognormal(t *testing.T) { + for i, dist := range []LogNormal{ + { + Mu: 0.1, + Sigma: 0.3, + }, + { + Mu: 0.01, + Sigma: 0.01, + }, + { + Mu: 2, + Sigma: 0.01, + }, + } { + testFullDist(t, dist, i, true) + } +} diff --git a/stat/distuv/norm.go b/stat/distuv/norm.go new file mode 100644 index 00000000..97cf1461 --- /dev/null +++ b/stat/distuv/norm.go @@ -0,0 +1,254 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/mathext" + "gonum.org/v1/gonum/stat" +) + +// UnitNormal is an instantiation of the normal distribution with Mu = 0 and Sigma = 1. +var UnitNormal = Normal{Mu: 0, Sigma: 1} + +// Normal respresents a normal (Gaussian) distribution (https://en.wikipedia.org/wiki/Normal_distribution). +type Normal struct { + Mu float64 // Mean of the normal distribution + Sigma float64 // Standard deviation of the normal distribution + Source *rand.Rand + + // Needs to be Mu and Sigma and not Mean and StdDev because Normal has functions + // Mean and StdDev +} + +// CDF computes the value of the cumulative density function at x. +func (n Normal) CDF(x float64) float64 { + return 0.5 * (1 + math.Erf((x-n.Mu)/(n.Sigma*math.Sqrt2))) +} + +// ConjugateUpdate updates the parameters of the distribution from the sufficient +// statistics of a set of samples. The sufficient statistics, suffStat, have been +// observed with nSamples observations. The prior values of the distribution are those +// currently in the distribution, and have been observed with priorStrength samples. +// +// For the normal distribution, the sufficient statistics are the mean and +// uncorrected standard deviation of the samples. +// The prior is having seen strength[0] samples with mean Normal.Mu +// and strength[1] samples with standard deviation Normal.Sigma. As a result of +// this function, Normal.Mu and Normal.Sigma are updated based on the weighted +// samples, and strength is modified to include the new number of samples observed. +// +// This function panics if len(suffStat) != 2 or len(priorStrength) != 2. +func (n *Normal) ConjugateUpdate(suffStat []float64, nSamples float64, priorStrength []float64) { + + // TODO: Support prior strength with math.Inf(1) to allow updating with + // a known mean/standard deviation + + totalMeanSamples := nSamples + priorStrength[0] + totalSum := suffStat[0]*nSamples + n.Mu*priorStrength[0] + + totalVarianceSamples := nSamples + priorStrength[1] + // sample variance + totalVariance := nSamples * suffStat[1] * suffStat[1] + // add prior variance + totalVariance += priorStrength[1] * n.Sigma * n.Sigma + // add cross variance from the difference of the means + meanDiff := (suffStat[0] - n.Mu) + totalVariance += priorStrength[0] * nSamples * meanDiff * meanDiff / totalMeanSamples + + n.Mu = totalSum / totalMeanSamples + n.Sigma = math.Sqrt(totalVariance / totalVarianceSamples) + floats.AddConst(nSamples, priorStrength) +} + +// Entropy returns the differential entropy of the distribution. +func (n Normal) Entropy() float64 { + return 0.5 * (log2Pi + 1 + 2*math.Log(n.Sigma)) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (Normal) ExKurtosis() float64 { + return 0 +} + +// Fit sets the parameters of the probability distribution from the +// data samples x with relative weights w. If weights is nil, then all the weights +// are 1. If weights is not nil, then the len(weights) must equal len(samples). +func (n *Normal) Fit(samples, weights []float64) { + suffStat := make([]float64, n.NumSuffStat()) + nSamples := n.SuffStat(samples, weights, suffStat) + n.ConjugateUpdate(suffStat, nSamples, make([]float64, n.NumSuffStat())) +} + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (n Normal) LogProb(x float64) float64 { + return negLogRoot2Pi - math.Log(n.Sigma) - (x-n.Mu)*(x-n.Mu)/(2*n.Sigma*n.Sigma) +} + +// Mean returns the mean of the probability distribution. +func (n Normal) Mean() float64 { + return n.Mu +} + +// Median returns the median of the normal distribution. +func (n Normal) Median() float64 { + return n.Mu +} + +// Mode returns the mode of the normal distribution. +func (n Normal) Mode() float64 { + return n.Mu +} + +// NumParameters returns the number of parameters in the distribution. +func (Normal) NumParameters() int { + return 2 +} + +// NumSuffStat returns the number of sufficient statistics for the distribution. +func (Normal) NumSuffStat() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (n Normal) Prob(x float64) float64 { + return math.Exp(n.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (n Normal) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return n.Mu + n.Sigma*mathext.NormalQuantile(p) +} + +// Rand returns a random sample drawn from the distribution. +func (n Normal) Rand() float64 { + var rnd float64 + if n.Source == nil { + rnd = rand.NormFloat64() + } else { + rnd = n.Source.NormFloat64() + } + return rnd*n.Sigma + n.Mu +} + +// Score returns the score function with respect to the parameters of the +// distribution at the input location x. The score function is the derivative +// of the log-likelihood at x with respect to the parameters +// (∂/∂θ) log(p(x;θ)) +// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise +// Score will panic, and the derivative is stored in-place into deriv. If deriv +// is nil a new slice will be allocated and returned. +// +// The order is [∂LogProb / ∂Mu, ∂LogProb / ∂Sigma]. +// +// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. +func (n Normal) Score(deriv []float64, x float64) []float64 { + if deriv == nil { + deriv = make([]float64, n.NumParameters()) + } + if len(deriv) != n.NumParameters() { + panic(badLength) + } + deriv[0] = (x - n.Mu) / (n.Sigma * n.Sigma) + deriv[1] = 1 / n.Sigma * (-1 + ((x-n.Mu)/n.Sigma)*((x-n.Mu)/n.Sigma)) + return deriv +} + +// ScoreInput returns the score function with respect to the input of the +// distribution at the input location specified by x. The score function is the +// derivative of the log-likelihood +// (d/dx) log(p(x)) . +func (n Normal) ScoreInput(x float64) float64 { + return -(1 / (2 * n.Sigma * n.Sigma)) * 2 * (x - n.Mu) +} + +// Skewness returns the skewness of the distribution. +func (Normal) Skewness() float64 { + return 0 +} + +// StdDev returns the standard deviation of the probability distribution. +func (n Normal) StdDev() float64 { + return n.Sigma +} + +// SuffStat computes the sufficient statistics of a set of samples to update +// the distribution. The sufficient statistics are stored in place, and the +// effective number of samples are returned. +// +// The normal distribution has two sufficient statistics, the mean of the samples +// and the standard deviation of the samples. +// +// If weights is nil, the weights are assumed to be 1, otherwise panics if +// len(samples) != len(weights). Panics if len(suffStat) != NumSuffStat(). +func (Normal) SuffStat(samples, weights, suffStat []float64) (nSamples float64) { + lenSamp := len(samples) + if len(weights) != 0 && len(samples) != len(weights) { + panic(badLength) + } + if len(suffStat) != (Normal{}).NumSuffStat() { + panic(badSuffStat) + } + + if len(weights) == 0 { + nSamples = float64(lenSamp) + } else { + nSamples = floats.Sum(weights) + } + + mean := stat.Mean(samples, weights) + suffStat[0] = mean + + // Use Moment and not StdDev because we want it to be uncorrected + variance := stat.MomentAbout(2, samples, mean, weights) + suffStat[1] = math.Sqrt(variance) + return nSamples +} + +// Survival returns the survival function (complementary CDF) at x. +func (n Normal) Survival(x float64) float64 { + return 0.5 * (1 - math.Erf((x-n.Mu)/(n.Sigma*math.Sqrt2))) +} + +// setParameters modifies the parameters of the distribution. +func (n *Normal) setParameters(p []Parameter) { + if len(p) != n.NumParameters() { + panic("normal: incorrect number of parameters to set") + } + if p[0].Name != "Mu" { + panic("normal: " + panicNameMismatch) + } + if p[1].Name != "Sigma" { + panic("normal: " + panicNameMismatch) + } + n.Mu = p[0].Value + n.Sigma = p[1].Value +} + +// Variance returns the variance of the probability distribution. +func (n Normal) Variance() float64 { + return n.Sigma * n.Sigma +} + +// parameters returns the parameters of the distribution. +func (n Normal) parameters(p []Parameter) []Parameter { + nParam := n.NumParameters() + if p == nil { + p = make([]Parameter, nParam) + } else if len(p) != nParam { + panic("normal: improper parameter length") + } + p[0].Name = "Mu" + p[0].Value = n.Mu + p[1].Name = "Sigma" + p[1].Value = n.Sigma + return p +} diff --git a/stat/distuv/norm_example_test.go b/stat/distuv/norm_example_test.go new file mode 100644 index 00000000..b913282f --- /dev/null +++ b/stat/distuv/norm_example_test.go @@ -0,0 +1,35 @@ +// Copyright ©2017 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv_test + +import ( + "fmt" + + "gonum.org/v1/gonum/stat" + "gonum.org/v1/gonum/stat/distuv" +) + +func ExampleNormal() { + // Create a normal distribution + dist := distuv.Normal{ + Mu: 2, + Sigma: 5, + } + + data := make([]float64, 1e5) + + // Draw some random values from the standard normal distribution + for i := range data { + data[i] = dist.Rand() + } + + mean, std := stat.MeanStdDev(data, nil) + meanErr := stat.StdErr(std, float64(len(data))) + + fmt.Printf("mean= %1.1f ± %0.1v\n", mean, meanErr) + + // Output: + // mean= 2.0 ± 0.02 +} diff --git a/stat/distuv/norm_test.go b/stat/distuv/norm_test.go new file mode 100644 index 00000000..0179e173 --- /dev/null +++ b/stat/distuv/norm_test.go @@ -0,0 +1,171 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "testing" + + "gonum.org/v1/gonum/floats" +) + +// TestNormalProbs tests LogProb, Prob, CumProb, and Quantile +func TestNormalProbs(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: oneOverRoot2Pi, + cumProb: 0.5, + logProb: -0.91893853320467274178032973640561763986139747363778341281715, + }, + { + loc: -1, + prob: 0.2419707245191433497978301929355606548286719707374350254875550842811000635700832945083112946939424047, + cumProb: 0.158655253931457051414767454367962077522087033273395609012605, + logProb: math.Log(0.2419707245191433497978301929355606548286719707374350254875550842811000635700832945083112946939424047), + }, + { + loc: 1, + prob: 0.2419707245191433497978301929355606548286719707374350254875550842811000635700832945083112946939424047, + cumProb: 0.841344746068542948585232545632037922477912966726604390987394, + logProb: math.Log(0.2419707245191433497978301929355606548286719707374350254875550842811000635700832945083112946939424047), + }, + { + loc: -7, + prob: 9.134720408364593342868613916794233023000190834851937054490546361277622761970225469305158915808284566e-12, + cumProb: 1.279812543885835004383623690780832998032844154198717929e-12, + logProb: math.Log(9.134720408364593342868613916794233023000190834851937054490546361277622761970225469305158915808284566e-12), + }, + { + loc: 7, + prob: 9.134720408364593342868613916794233023000190834851937054490546361277622761970225469305158915808284566e-12, + cumProb: 0.99999999999872018745611416499561637630921916700196715584580, + logProb: math.Log(9.134720408364593342868613916794233023000190834851937054490546361277622761970225469305158915808284566e-12), + }, + } + testDistributionProbs(t, Normal{Mu: 0, Sigma: 1}, "normal", pts) + + pts = []univariateProbPoint{ + { + loc: 2, + prob: 0.07978845608028653558798921198687637369517172623298693153318516593413158517986036770025046678146138729, + cumProb: 0.5, + logProb: math.Log(0.07978845608028653558798921198687637369517172623298693153318516593413158517986036770025046678146138729), + }, + { + loc: -3, + prob: 0.04839414490382866995956603858711213096573439414748700509751101685622001271401665890166225893878848095, + cumProb: 0.158655253931457051414767454367962077522087033273395609012605, + logProb: math.Log(0.04839414490382866995956603858711213096573439414748700509751101685622001271401665890166225893878848095), + }, + { + loc: 7, + prob: 0.04839414490382866995956603858711213096573439414748700509751101685622001271401665890166225893878848095, + cumProb: 0.841344746068542948585232545632037922477912966726604390987394, + logProb: math.Log(0.04839414490382866995956603858711213096573439414748700509751101685622001271401665890166225893878848095), + }, + { + loc: -33, + prob: 1.826944081672918668573722783358846604600038166970387410898109272255524552394045093861031783161656913e-12, + cumProb: 1.279812543885835004383623690780832998032844154198717929e-12, + logProb: math.Log(1.826944081672918668573722783358846604600038166970387410898109272255524552394045093861031783161656913e-12), + }, + { + loc: 37, + prob: 1.826944081672918668573722783358846604600038166970387410898109272255524552394045093861031783161656913e-12, + cumProb: 0.99999999999872018745611416499561637630921916700196715584580, + logProb: math.Log(1.826944081672918668573722783358846604600038166970387410898109272255524552394045093861031783161656913e-12), + }, + } + testDistributionProbs(t, Normal{Mu: 2, Sigma: 5}, "normal", pts) +} + +func TestNormFitPrior(t *testing.T) { + testConjugateUpdate(t, func() ConjugateUpdater { return &Normal{Mu: -10, Sigma: 6} }) +} + +func TestNormScore(t *testing.T) { + for _, test := range []*Normal{ + { + Mu: 0, + Sigma: 1, + }, + { + Mu: 0.32238, + Sigma: 13.69, + }, + } { + testDerivParam(t, test) + } +} + +func TestNormalQuantile(t *testing.T) { + // Values from https://www.johndcook.com/blog/normal_cdf_inverse/ + p := []float64{ + 0.0000001, + 0.00001, + 0.001, + 0.05, + 0.15, + 0.25, + 0.35, + 0.45, + 0.55, + 0.65, + 0.75, + 0.85, + 0.95, + 0.999, + 0.99999, + 0.9999999, + } + ans := []float64{ + -5.199337582187471, + -4.264890793922602, + -3.090232306167813, + -1.6448536269514729, + -1.0364333894937896, + -0.6744897501960817, + -0.38532046640756773, + -0.12566134685507402, + 0.12566134685507402, + 0.38532046640756773, + 0.6744897501960817, + 1.0364333894937896, + 1.6448536269514729, + 3.090232306167813, + 4.264890793922602, + 5.199337582187471, + } + for i, v := range p { + got := UnitNormal.Quantile(v) + if !floats.EqualWithinAbsOrRel(got, ans[i], 1e-10, 1e-10) { + t.Errorf("Quantile mismatch. Case %d, want: %v, got: %v", i, ans[i], got) + } + } +} + +func TestNormFitPanic(t *testing.T) { + n := Normal{Mu: 0, Sigma: 1} + defer func() { + r := recover() + if r != nil { + t.Errorf("unexpected panic for Fit call: %v", r) + } + }() + n.Fit(make([]float64, 10), nil) +} + +func BenchmarkNormalQuantile(b *testing.B) { + n := Normal{Mu: 2, Sigma: 3.1} + ps := make([]float64, 1000) // ensure there are small values + floats.Span(ps, 0, 1) + for i := 0; i < b.N; i++ { + for _, v := range ps { + x := n.Quantile(v) + _ = x + } + } +} diff --git a/stat/distuv/studentst.go b/stat/distuv/studentst.go new file mode 100644 index 00000000..84b6b6e2 --- /dev/null +++ b/stat/distuv/studentst.go @@ -0,0 +1,160 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/mathext" +) + +const logPi = 1.1447298858494001741 // http://oeis.org/A053510 + +// StudentsT implements the three-parameter Student's T distribution, a distribution +// over the real numbers. +// +// The Student's T distribution has density function +// Γ((ν+1)/2) / (sqrt(νπ) Γ(ν/2) σ) (1 + 1/ν * ((x-μ)/σ)^2)^(-(ν+1)/2) +// +// The Student's T distribution approaches the normal distribution as ν → ∞. +// +// For more information, see https://en.wikipedia.org/wiki/Student%27s_t-distribution, +// specifically https://en.wikipedia.org/wiki/Student%27s_t-distribution#Non-standardized_Student.27s_t-distribution . +// +// The standard Student's T distribution is with Mu = 0, and Sigma = 1. +type StudentsT struct { + // Mu is the location parameter of the distribution, and the mean of the + // distribution + Mu float64 + + // Sigma is the scale parameter of the distribution. It is related to the + // standard deviation by std = Sigma * sqrt(Nu/(Nu-2)) + Sigma float64 + + // Nu is the shape prameter of the distribution, representing the number of + // degrees of the distribution, and one less than the number of observations + // from a Normal distribution. + Nu float64 + + Src *rand.Rand +} + +// CDF computes the value of the cumulative distribution function at x. +func (s StudentsT) CDF(x float64) float64 { + // transform to standard normal + y := (x - s.Mu) / s.Sigma + if y == 0 { + return 0.5 + } + // For t > 0 + // F(y) = 1 - 0.5 * I_t(y)(nu/2, 1/2) + // t(y) = nu/(y^2 + nu) + // and 1 - F(y) for t < 0 + t := s.Nu / (y*y + s.Nu) + if y > 0 { + return 1 - 0.5*mathext.RegIncBeta(0.5*s.Nu, 0.5, t) + } + return 0.5 * mathext.RegIncBeta(s.Nu/2, 0.5, t) +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. +func (s StudentsT) LogProb(x float64) float64 { + g1, _ := math.Lgamma((s.Nu + 1) / 2) + g2, _ := math.Lgamma(s.Nu / 2) + z := (x - s.Mu) / s.Sigma + return g1 - g2 - 0.5*math.Log(s.Nu) - 0.5*logPi - math.Log(s.Sigma) - ((s.Nu+1)/2)*math.Log(1+z*z/s.Nu) +} + +// Mean returns the mean of the probability distribution. +func (s StudentsT) Mean() float64 { + return s.Mu +} + +// Mode returns the mode of the distribution. +func (s StudentsT) Mode() float64 { + return s.Mu +} + +// NumParameters returns the number of parameters in the distribution. +func (StudentsT) NumParameters() int { + return 3 +} + +// Prob computes the value of the probability density function at x. +func (s StudentsT) Prob(x float64) float64 { + return math.Exp(s.LogProb(x)) +} + +// Quantile returns the inverse of the cumulative distribution function. +func (s StudentsT) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + // F(x) = 1 - 0.5 * I_t(x)(nu/2, 1/2) + // t(x) = nu/(t^2 + nu) + if p == 0.5 { + return s.Mu + } + var y float64 + if p > 0.5 { + // Know t > 0 + t := mathext.InvRegIncBeta(s.Nu/2, 0.5, 2*(1-p)) + y = math.Sqrt(s.Nu * (1 - t) / t) + } else { + t := mathext.InvRegIncBeta(s.Nu/2, 0.5, 2*p) + y = -math.Sqrt(s.Nu * (1 - t) / t) + } + // Convert out of standard normal + return y*s.Sigma + s.Mu +} + +// Rand returns a random sample drawn from the distribution. +func (s StudentsT) Rand() float64 { + // http://www.math.uah.edu/stat/special/Student.html + n := Normal{0, 1, s.Src}.Rand() + c := Gamma{s.Nu / 2, 0.5, s.Src}.Rand() + z := n / math.Sqrt(c/s.Nu) + return z*s.Sigma + s.Mu +} + +// StdDev returns the standard deviation of the probability distribution. +// +// The standard deviation is undefined for ν <= 1, and this returns math.NaN(). +func (s StudentsT) StdDev() float64 { + return math.Sqrt(s.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (s StudentsT) Survival(x float64) float64 { + // transform to standard normal + y := (x - s.Mu) / s.Sigma + if y == 0 { + return 0.5 + } + // For t > 0 + // F(y) = 1 - 0.5 * I_t(y)(nu/2, 1/2) + // t(y) = nu/(y^2 + nu) + // and 1 - F(y) for t < 0 + t := s.Nu / (y*y + s.Nu) + if y > 0 { + return 0.5 * mathext.RegIncBeta(s.Nu/2, 0.5, t) + } + return 1 - 0.5*mathext.RegIncBeta(s.Nu/2, 0.5, t) +} + +// Variance returns the variance of the probability distribution. +// +// The variance is undefined for ν <= 1, and this returns math.NaN(). +func (s StudentsT) Variance() float64 { + if s.Nu < 1 { + return math.NaN() + } + if s.Nu <= 2 { + return math.Inf(1) + } + return s.Sigma * s.Sigma * s.Nu / (s.Nu - 2) +} diff --git a/stat/distuv/studentst_test.go b/stat/distuv/studentst_test.go new file mode 100644 index 00000000..4b522a20 --- /dev/null +++ b/stat/distuv/studentst_test.go @@ -0,0 +1,83 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" + "sort" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func TestStudentsTProb(t *testing.T) { + for _, test := range []struct { + x, mu, sigma, nu, want float64 + }{ + // Values comparison with scipy. + {0.01, 0, 1, 2.74, 0.364778548181318}, + {-0.01, 0, 1, 2.74, 0.364778548181318}, + {0.4, 0, 1, 1.6, 0.30376391362582678}, + {-0.4, 0, 1, 1.6, 0.30376391362582678}, + {0.2, 15, 5, 10, 0.0024440848858034393}, + } { + pdf := StudentsT{test.mu, test.sigma, test.nu, nil}.Prob(test.x) + if !floats.EqualWithinAbsOrRel(pdf, test.want, 1e-10, 1e-10) { + t.Errorf("Pdf mismatch, x = %v, Nu = %v. Got %v, want %v", test.x, test.nu, pdf, test.want) + } + } +} + +func TestStudentsT(t *testing.T) { + src := rand.New(rand.NewSource(1)) + for i, b := range []StudentsT{ + {0, 1, 3.3, src}, + {0, 1, 7.2, src}, + {0, 1, 12, src}, + {0.9, 0.8, 6, src}, + } { + testStudentsT(t, b, i) + } +} + +func testStudentsT(t *testing.T, c StudentsT, i int) { + tol := 1e-2 + const n = 1e6 + const bins = 50 + x := make([]float64, n) + generateSamples(x, c) + sort.Float64s(x) + + testRandLogProbContinuous(t, i, math.Inf(-1), x, c, tol, bins) + checkMean(t, i, x, c, tol) + if c.Nu > 2 { + checkVarAndStd(t, i, x, c, tol) + } + checkProbContinuous(t, i, x, c, 1e-3) + checkQuantileCDFSurvival(t, i, x, c, tol) + checkProbQuantContinuous(t, i, x, c, tol) +} + +func TestStudentsTQuantile(t *testing.T) { + nSteps := 101 + probs := make([]float64, nSteps) + floats.Span(probs, 0, 1) + for i, b := range []StudentsT{ + {0, 1, 3.3, nil}, + {0, 1, 7.2, nil}, + {0, 1, 12, nil}, + {0.9, 0.8, 6, nil}, + } { + for _, p := range probs { + x := b.Quantile(p) + p2 := b.CDF(x) + if !floats.EqualWithinAbsOrRel(p, p2, 1e-10, 1e-10) { + t.Errorf("mismatch between CDF and Quantile. Case %v. Want %v, got %v", i, p, p2) + break + } + } + } +} diff --git a/stat/distuv/uniform.go b/stat/distuv/uniform.go new file mode 100644 index 00000000..4c9dec96 --- /dev/null +++ b/stat/distuv/uniform.go @@ -0,0 +1,159 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/rand" +) + +// UnitUniform is an instantiation of the uniform distribution with Min = 0 +// and Max = 1. +var UnitUniform = Uniform{Min: 0, Max: 1} + +// Uniform represents a continuous uniform distribution (https://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29). +type Uniform struct { + Min float64 + Max float64 + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (u Uniform) CDF(x float64) float64 { + if x < u.Min { + return 0 + } + if x > u.Max { + return 1 + } + return (x - u.Min) / (u.Max - u.Min) +} + +// Uniform doesn't have any of the DLogProbD? because the derivative is 0 everywhere +// except where it's undefined + +// Entropy returns the entropy of the distribution. +func (u Uniform) Entropy() float64 { + return math.Log(u.Max - u.Min) +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (Uniform) ExKurtosis() float64 { + return -6.0 / 5.0 +} + +// Uniform doesn't have Fit because it's a bad idea to fit a uniform from data. + +// LogProb computes the natural logarithm of the value of the probability density function at x. +func (u Uniform) LogProb(x float64) float64 { + if x < u.Min { + return math.Inf(-1) + } + if x > u.Max { + return math.Inf(-1) + } + return -math.Log(u.Max - u.Min) +} + +// MarshalParameters implements the ParameterMarshaler interface +func (u Uniform) MarshalParameters(p []Parameter) { + if len(p) != u.NumParameters() { + panic("uniform: improper parameter length") + } + p[0].Name = "Min" + p[0].Value = u.Min + p[1].Name = "Max" + p[1].Value = u.Max + return +} + +// Mean returns the mean of the probability distribution. +func (u Uniform) Mean() float64 { + return (u.Max + u.Min) / 2 +} + +// Median returns the median of the probability distribution. +func (u Uniform) Median() float64 { + return (u.Max + u.Min) / 2 +} + +// Uniform doesn't have a mode because it's any value in the distribution + +// NumParameters returns the number of parameters in the distribution. +func (Uniform) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (u Uniform) Prob(x float64) float64 { + if x < u.Min { + return 0 + } + if x > u.Max { + return 0 + } + return 1 / (u.Max - u.Min) +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (u Uniform) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return p*(u.Max-u.Min) + u.Min +} + +// Rand returns a random sample drawn from the distribution. +func (u Uniform) Rand() float64 { + var rnd float64 + if u.Source == nil { + rnd = rand.Float64() + } else { + rnd = u.Source.Float64() + } + return rnd*(u.Max-u.Min) + u.Min +} + +// Skewness returns the skewness of the distribution. +func (Uniform) Skewness() float64 { + return 0 +} + +// StdDev returns the standard deviation of the probability distribution. +func (u Uniform) StdDev() float64 { + return math.Sqrt(u.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (u Uniform) Survival(x float64) float64 { + if x < u.Min { + return 1 + } + if x > u.Max { + return 0 + } + return (u.Max - x) / (u.Max - u.Min) +} + +// UnmarshalParameters implements the ParameterMarshaler interface +func (u *Uniform) UnmarshalParameters(p []Parameter) { + if len(p) != u.NumParameters() { + panic("uniform: incorrect number of parameters to set") + } + if p[0].Name != "Min" { + panic("uniform: " + panicNameMismatch) + } + if p[1].Name != "Max" { + panic("uniform: " + panicNameMismatch) + } + + u.Min = p[0].Value + u.Max = p[1].Value +} + +// Variance returns the variance of the probability distribution. +func (u Uniform) Variance() float64 { + return 1.0 / 12.0 * (u.Max - u.Min) * (u.Max - u.Min) +} diff --git a/stat/distuv/weibull.go b/stat/distuv/weibull.go new file mode 100644 index 00000000..72f7f97a --- /dev/null +++ b/stat/distuv/weibull.go @@ -0,0 +1,247 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "math/cmplx" + "math/rand" +) + +// Weibull distribution. Valid range for x is [0,+∞). +type Weibull struct { + // Shape parameter of the distribution. A value of 1 represents + // the exponential distribution. A value of 2 represents the + // Rayleigh distribution. Valid range is (0,+∞). + K float64 + // Scale parameter of the distribution. Valid range is (0,+∞). + Lambda float64 + // Source of random numbers + Source *rand.Rand +} + +// CDF computes the value of the cumulative density function at x. +func (w Weibull) CDF(x float64) float64 { + if x < 0 { + return 0 + } else { + return 1 - cmplx.Abs(cmplx.Exp(w.LogCDF(x))) + } +} + +// Entropy returns the entropy of the distribution. +func (w Weibull) Entropy() float64 { + return eulerGamma*(1-1/w.K) + math.Log(w.Lambda/w.K) + 1 +} + +// ExKurtosis returns the excess kurtosis of the distribution. +func (w Weibull) ExKurtosis() float64 { + return (-6*w.gammaIPow(1, 4) + 12*w.gammaIPow(1, 2)*math.Gamma(1+2/w.K) - 3*w.gammaIPow(2, 2) - 4*math.Gamma(1+1/w.K)*math.Gamma(1+3/w.K) + math.Gamma(1+4/w.K)) / math.Pow(math.Gamma(1+2/w.K)-w.gammaIPow(1, 2), 2) +} + +// gammIPow is a shortcut for computing the gamma function to a power. +func (w Weibull) gammaIPow(i, pow float64) float64 { + return math.Pow(math.Gamma(1+i/w.K), pow) +} + +// LogCDF computes the value of the log of the cumulative density function at x. +func (w Weibull) LogCDF(x float64) complex128 { + if x < 0 { + return 0 + } else { + return cmplx.Log(-1) + complex(-math.Pow(x/w.Lambda, w.K), 0) + } +} + +// LogProb computes the natural logarithm of the value of the probability +// density function at x. Zero is returned if x is less than zero. +// +// Special cases occur when x == 0, and the result depends on the shape +// parameter as follows: +// If 0 < K < 1, LogProb returns +Inf. +// If K == 1, LogProb returns 0. +// If K > 1, LogProb returns -Inf. +func (w Weibull) LogProb(x float64) float64 { + if x < 0 { + return 0 + } else { + return math.Log(w.K) - math.Log(w.Lambda) + (w.K-1)*(math.Log(x)-math.Log(w.Lambda)) - math.Pow(x/w.Lambda, w.K) + } +} + +// Survival returns the log of the survival function (complementary CDF) at x. +func (w Weibull) LogSurvival(x float64) float64 { + if x < 0 { + return 0 + } else { + return -math.Pow(x/w.Lambda, w.K) + } +} + +// Mean returns the mean of the probability distribution. +func (w Weibull) Mean() float64 { + return w.Lambda * math.Gamma(1+1/w.K) +} + +// Median returns the median of the normal distribution. +func (w Weibull) Median() float64 { + return w.Lambda * math.Pow(ln2, 1/w.K) +} + +// Mode returns the mode of the normal distribution. +// +// The mode is NaN in the special case where the K (shape) parameter +// is less than 1. +func (w Weibull) Mode() float64 { + if w.K > 1 { + return w.Lambda * math.Pow((w.K-1)/w.K, 1/w.K) + } else if w.K == 1 { + return 0 + } else { + return math.NaN() + } +} + +// NumParameters returns the number of parameters in the distribution. +func (Weibull) NumParameters() int { + return 2 +} + +// Prob computes the value of the probability density function at x. +func (w Weibull) Prob(x float64) float64 { + if x < 0 { + return 0 + } else { + return math.Exp(w.LogProb(x)) + } +} + +// Quantile returns the inverse of the cumulative probability distribution. +func (w Weibull) Quantile(p float64) float64 { + if p < 0 || p > 1 { + panic(badPercentile) + } + return w.Lambda * math.Pow(-math.Log(1-p), 1/w.K) +} + +// Rand returns a random sample drawn from the distribution. +func (w Weibull) Rand() float64 { + var rnd float64 + if w.Source == nil { + rnd = rand.Float64() + } else { + rnd = w.Source.Float64() + } + return w.Quantile(rnd) +} + +// Score returns the score function with respect to the parameters of the +// distribution at the input location x. The score function is the derivative +// of the log-likelihood at x with respect to the parameters +// (∂/∂θ) log(p(x;θ)) +// If deriv is non-nil, len(deriv) must equal the number of parameters otherwise +// Score will panic, and the derivative is stored in-place into deriv. If deriv +// is nil a new slice will be allocated and returned. +// +// The order is [∂LogProb / ∂K, ∂LogProb / ∂λ]. +// +// For more information, see https://en.wikipedia.org/wiki/Score_%28statistics%29. +// +// Special cases: +// Score(0) = [NaN, NaN] +func (w Weibull) Score(deriv []float64, x float64) []float64 { + if deriv == nil { + deriv = make([]float64, w.NumParameters()) + } + if len(deriv) != w.NumParameters() { + panic(badLength) + } + if x > 0 { + deriv[0] = 1/w.K + math.Log(x) - math.Log(w.Lambda) - (math.Log(x)-math.Log(w.Lambda))*math.Pow(x/w.Lambda, w.K) + deriv[1] = (w.K * (math.Pow(x/w.Lambda, w.K) - 1)) / w.Lambda + return deriv + } + if x < 0 { + deriv[0] = 0 + deriv[1] = 0 + return deriv + } + deriv[0] = math.NaN() + deriv[0] = math.NaN() + return deriv +} + +// ScoreInput returns the score function with respect to the input of the +// distribution at the input location specified by x. The score function is the +// derivative of the log-likelihood +// (d/dx) log(p(x)) . +// +// Special cases: +// ScoreInput(0) = NaN +func (w Weibull) ScoreInput(x float64) float64 { + if x > 0 { + return (-w.K*math.Pow(x/w.Lambda, w.K) + w.K - 1) / x + } + if x < 0 { + return 0 + } + return math.NaN() +} + +// Skewness returns the skewness of the distribution. +func (w Weibull) Skewness() float64 { + stdDev := w.StdDev() + firstGamma, firstGammaSign := math.Lgamma(1 + 3/w.K) + logFirst := firstGamma + 3*(math.Log(w.Lambda)-math.Log(stdDev)) + logSecond := math.Log(3) + math.Log(w.Mean()) + 2*math.Log(stdDev) - 3*math.Log(stdDev) + logThird := 3 * (math.Log(w.Mean()) - math.Log(stdDev)) + return float64(firstGammaSign)*math.Exp(logFirst) - math.Exp(logSecond) - math.Exp(logThird) +} + +// StdDev returns the standard deviation of the probability distribution. +func (w Weibull) StdDev() float64 { + return math.Sqrt(w.Variance()) +} + +// Survival returns the survival function (complementary CDF) at x. +func (w Weibull) Survival(x float64) float64 { + return math.Exp(w.LogSurvival(x)) +} + +// setParameters modifies the parameters of the distribution. +func (w *Weibull) setParameters(p []Parameter) { + if len(p) != w.NumParameters() { + panic("weibull: incorrect number of parameters to set") + } + if p[0].Name != "K" { + panic("weibull: " + panicNameMismatch) + } + if p[1].Name != "λ" { + panic("weibull: " + panicNameMismatch) + } + w.K = p[0].Value + w.Lambda = p[1].Value +} + +// Variance returns the variance of the probability distribution. +func (w Weibull) Variance() float64 { + return math.Pow(w.Lambda, 2) * (math.Gamma(1+2/w.K) - w.gammaIPow(1, 2)) +} + +// parameters returns the parameters of the distribution. +func (w Weibull) parameters(p []Parameter) []Parameter { + nParam := w.NumParameters() + if p == nil { + p = make([]Parameter, nParam) + } else if len(p) != nParam { + panic("weibull: improper parameter length") + } + p[0].Name = "K" + p[0].Value = w.K + p[1].Name = "λ" + p[1].Value = w.Lambda + return p + +} diff --git a/stat/distuv/weibull_test.go b/stat/distuv/weibull_test.go new file mode 100644 index 00000000..cd78f49f --- /dev/null +++ b/stat/distuv/weibull_test.go @@ -0,0 +1,209 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package distuv + +import ( + "math" + "testing" +) + +func TestHalfKStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: math.Inf(1), + cumProb: 0, + logProb: math.Inf(1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.183939720585721, + cumProb: 0.632120558828558, + logProb: -1.693147180559950, + }, + { + loc: 20, + prob: 0.001277118038048, + cumProb: 0.988577109006533, + logProb: -6.663149272336520, + }, + } + testDistributionProbs(t, Weibull{K: 0.5, Lambda: 1}, "0.5K Standard Weibull", pts) +} + +func TestExponentialStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 1, + cumProb: 0, + logProb: math.Inf(1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.367879441171442, + cumProb: 0.632120558828558, + logProb: -1.0, + }, + { + loc: 20, + prob: 0.000000002061154, + cumProb: 0.999999997938846, + logProb: -20.0, + }, + } + testDistributionProbs(t, Weibull{K: 1, Lambda: 1}, "1K (Exponential) Standard Weibull", pts) +} + +func TestRayleighStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 0, + cumProb: 0, + logProb: math.Inf(-1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.735758882342885, + cumProb: 0.632120558828558, + logProb: -0.306852819440055, + }, + { + loc: 20, + prob: 0, + cumProb: 1, + logProb: -396.31112054588607, + }, + } + testDistributionProbs(t, Weibull{K: 2, Lambda: 1}, "2K (Rayleigh) Standard Weibull", pts) +} + +func TestFiveKStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: 0, + cumProb: 0, + logProb: math.Inf(-1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 1.839397205857210, + cumProb: 0.632120558828558, + logProb: 0.609437912434100, + }, + { + loc: 20, + prob: 0, + cumProb: 1, + logProb: -3199986.4076329935, + }, + } + testDistributionProbs(t, Weibull{K: 5, Lambda: 1}, "5K Standard Weibull", pts) +} + +func TestScaledUpHalfKStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: math.Inf(1), + cumProb: 0, + logProb: math.Inf(1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.180436508682207, + cumProb: 0.558022622759326, + logProb: -1.712376315541750, + }, + { + loc: 20, + prob: 0.002369136850928, + cumProb: 0.974047406098605, + logProb: -6.045229588092130, + }, + } + testDistributionProbs(t, Weibull{K: 0.5, Lambda: 1.5}, "0.5K 1.5λ Weibull", pts) +} + +func TestScaledDownHalfKStandardWeibullProb(t *testing.T) { + pts := []univariateProbPoint{ + { + loc: 0, + prob: math.Inf(1), + cumProb: 0, + logProb: math.Inf(1), + }, + { + loc: -1, + prob: 0, + cumProb: 0, + logProb: 0, + }, + { + loc: 1, + prob: 0.171909491538362, + cumProb: 0.756883265565786, + logProb: -1.760787152653070, + }, + { + loc: 20, + prob: 0.000283302579100, + cumProb: 0.998208237166091, + logProb: -8.168995047393730, + }, + } + testDistributionProbs(t, Weibull{K: 0.5, Lambda: 0.5}, "0.5K 0.5λ Weibull", pts) +} + +func TestWeibullScore(t *testing.T) { + for _, test := range []*Weibull{ + { + K: 1, + Lambda: 1, + }, + { + K: 2, + Lambda: 3.6, + }, + { + K: 3.4, + Lambda: 8, + }, + } { + testDerivParam(t, test) + } +} diff --git a/stat/faithful_test.go b/stat/faithful_test.go new file mode 100644 index 00000000..981eff1c --- /dev/null +++ b/stat/faithful_test.go @@ -0,0 +1,81 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat + +// faithful is the faithful data set from R. +var faithful = struct{ waiting, eruptions []float64 }{ + waiting: []float64{ + 79, 54, 74, 62, 85, 55, 88, 85, + 51, 85, 54, 84, 78, 47, 83, 52, + 62, 84, 52, 79, 51, 47, 78, 69, + 74, 83, 55, 76, 78, 79, 73, 77, + 66, 80, 74, 52, 48, 80, 59, 90, + 80, 58, 84, 58, 73, 83, 64, 53, + 82, 59, 75, 90, 54, 80, 54, 83, + 71, 64, 77, 81, 59, 84, 48, 82, + 60, 92, 78, 78, 65, 73, 82, 56, + 79, 71, 62, 76, 60, 78, 76, 83, + 75, 82, 70, 65, 73, 88, 76, 80, + 48, 86, 60, 90, 50, 78, 63, 72, + 84, 75, 51, 82, 62, 88, 49, 83, + 81, 47, 84, 52, 86, 81, 75, 59, + 89, 79, 59, 81, 50, 85, 59, 87, + 53, 69, 77, 56, 88, 81, 45, 82, + 55, 90, 45, 83, 56, 89, 46, 82, + 51, 86, 53, 79, 81, 60, 82, 77, + 76, 59, 80, 49, 96, 53, 77, 77, + 65, 81, 71, 70, 81, 93, 53, 89, + 45, 86, 58, 78, 66, 76, 63, 88, + 52, 93, 49, 57, 77, 68, 81, 81, + 73, 50, 85, 74, 55, 77, 83, 83, + 51, 78, 84, 46, 83, 55, 81, 57, + 76, 84, 77, 81, 87, 77, 51, 78, + 60, 82, 91, 53, 78, 46, 77, 84, + 49, 83, 71, 80, 49, 75, 64, 76, + 53, 94, 55, 76, 50, 82, 54, 75, + 78, 79, 78, 78, 70, 79, 70, 54, + 86, 50, 90, 54, 54, 77, 79, 64, + 75, 47, 86, 63, 85, 82, 57, 82, + 67, 74, 54, 83, 73, 73, 88, 80, + 71, 83, 56, 79, 78, 84, 58, 83, + 43, 60, 75, 81, 46, 90, 46, 74, + }, + eruptions: []float64{ + 3.600, 1.800, 3.333, 2.283, 4.533, 2.883, 4.700, 3.600, + 1.950, 4.350, 1.833, 3.917, 4.200, 1.750, 4.700, 2.167, + 1.750, 4.800, 1.600, 4.250, 1.800, 1.750, 3.450, 3.067, + 4.533, 3.600, 1.967, 4.083, 3.850, 4.433, 4.300, 4.467, + 3.367, 4.033, 3.833, 2.017, 1.867, 4.833, 1.833, 4.783, + 4.350, 1.883, 4.567, 1.750, 4.533, 3.317, 3.833, 2.100, + 4.633, 2.000, 4.800, 4.716, 1.833, 4.833, 1.733, 4.883, + 3.717, 1.667, 4.567, 4.317, 2.233, 4.500, 1.750, 4.800, + 1.817, 4.400, 4.167, 4.700, 2.067, 4.700, 4.033, 1.967, + 4.500, 4.000, 1.983, 5.067, 2.017, 4.567, 3.883, 3.600, + 4.133, 4.333, 4.100, 2.633, 4.067, 4.933, 3.950, 4.517, + 2.167, 4.000, 2.200, 4.333, 1.867, 4.817, 1.833, 4.300, + 4.667, 3.750, 1.867, 4.900, 2.483, 4.367, 2.100, 4.500, + 4.050, 1.867, 4.700, 1.783, 4.850, 3.683, 4.733, 2.300, + 4.900, 4.417, 1.700, 4.633, 2.317, 4.600, 1.817, 4.417, + 2.617, 4.067, 4.250, 1.967, 4.600, 3.767, 1.917, 4.500, + 2.267, 4.650, 1.867, 4.167, 2.800, 4.333, 1.833, 4.383, + 1.883, 4.933, 2.033, 3.733, 4.233, 2.233, 4.533, 4.817, + 4.333, 1.983, 4.633, 2.017, 5.100, 1.800, 5.033, 4.000, + 2.400, 4.600, 3.567, 4.000, 4.500, 4.083, 1.800, 3.967, + 2.200, 4.150, 2.000, 3.833, 3.500, 4.583, 2.367, 5.000, + 1.933, 4.617, 1.917, 2.083, 4.583, 3.333, 4.167, 4.333, + 4.500, 2.417, 4.000, 4.167, 1.883, 4.583, 4.250, 3.767, + 2.033, 4.433, 4.083, 1.833, 4.417, 2.183, 4.800, 1.833, + 4.800, 4.100, 3.966, 4.233, 3.500, 4.366, 2.250, 4.667, + 2.100, 4.350, 4.133, 1.867, 4.600, 1.783, 4.367, 3.850, + 1.933, 4.500, 2.383, 4.700, 1.867, 3.833, 3.417, 4.233, + 2.400, 4.800, 2.000, 4.150, 1.867, 4.267, 1.750, 4.483, + 4.000, 4.117, 4.083, 4.267, 3.917, 4.550, 4.083, 2.417, + 4.183, 2.217, 4.450, 1.883, 1.850, 4.283, 3.950, 2.333, + 4.150, 2.350, 4.933, 2.900, 4.583, 3.833, 2.083, 4.367, + 2.133, 4.350, 2.200, 4.450, 3.567, 4.500, 4.150, 3.817, + 3.917, 4.450, 2.000, 4.283, 4.767, 4.533, 1.850, 4.250, + 1.983, 2.250, 4.750, 4.117, 2.150, 4.417, 1.817, 4.467, + }, +} diff --git a/stat/moments_bench_test.go b/stat/moments_bench_test.go new file mode 100644 index 00000000..6df41394 --- /dev/null +++ b/stat/moments_bench_test.go @@ -0,0 +1,611 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// a set of benchmarks to evaluate the performance of the various +// moment statistics: Mean, Variance, StdDev, MeanVariance, MeanStdDev, +// Covariance, Correlation, Skew, ExKurtosis, Moment, MomentAbout, ... +// +// It tests both weighted and unweighted versions by using a slice of +// all ones. + +package stat + +import ( + "math/rand" + "testing" +) + +const ( + small = 10 + medium = 1000 + large = 100000 + huge = 10000000 +) + +// tests for unweighted versions + +func RandomSlice(l int) []float64 { + s := make([]float64, l) + for i := range s { + s[i] = rand.Float64() + } + return s +} + +func benchmarkMean(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Mean(s, wts) + } +} + +func BenchmarkMeanSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMean(b, s, nil) +} + +func BenchmarkMeanMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMean(b, s, nil) +} + +func BenchmarkMeanLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMean(b, s, nil) +} + +func BenchmarkMeanHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMean(b, s, nil) +} + +func BenchmarkMeanSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMean(b, s, wts) +} + +func BenchmarkMeanMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMean(b, s, wts) +} + +func BenchmarkMeanLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMean(b, s, wts) +} + +func BenchmarkMeanHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMean(b, s, wts) +} + +func benchmarkVariance(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Variance(s, wts) + } +} + +func BenchmarkVarianceSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkVariance(b, s, nil) +} + +func BenchmarkVarianceMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkVariance(b, s, nil) +} + +func BenchmarkVarianceLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkVariance(b, s, nil) +} + +func BenchmarkVarianceHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkVariance(b, s, nil) +} + +func BenchmarkVarianceSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkVariance(b, s, wts) +} + +func BenchmarkVarianceMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkVariance(b, s, wts) +} + +func BenchmarkVarianceLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkVariance(b, s, wts) +} + +func BenchmarkVarianceHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkVariance(b, s, wts) +} + +func benchmarkStdDev(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + StdDev(s, wts) + } +} + +func BenchmarkStdDevSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkStdDev(b, s, nil) +} + +func BenchmarkStdDevMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkStdDev(b, s, nil) +} + +func BenchmarkStdDevLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkStdDev(b, s, nil) +} + +func BenchmarkStdDevHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkStdDev(b, s, nil) +} + +func BenchmarkStdDevSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkStdDev(b, s, wts) +} + +func BenchmarkStdDevMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkStdDev(b, s, wts) +} + +func BenchmarkStdDevLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkStdDev(b, s, wts) +} + +func BenchmarkStdDevHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkStdDev(b, s, wts) +} + +func benchmarkMeanVariance(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MeanVariance(s, wts) + } +} + +func BenchmarkMeanVarianceSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMeanVariance(b, s, nil) +} + +func BenchmarkMeanVarianceMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMeanVariance(b, s, nil) +} + +func BenchmarkMeanVarianceLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMeanVariance(b, s, nil) +} + +func BenchmarkMeanVarianceHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMeanVariance(b, s, nil) +} + +func BenchmarkMeanVarianceSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMeanVariance(b, s, wts) +} + +func BenchmarkMeanVarianceMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMeanVariance(b, s, wts) +} + +func BenchmarkMeanVarianceLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMeanVariance(b, s, wts) +} + +func BenchmarkMeanVarianceHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMeanVariance(b, s, wts) +} + +func benchmarkMeanStdDev(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MeanStdDev(s, wts) + } +} + +func BenchmarkMeanStdDevSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMeanStdDev(b, s, nil) +} + +func BenchmarkMeanStdDevMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMeanStdDev(b, s, nil) +} + +func BenchmarkMeanStdDevLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMeanStdDev(b, s, nil) +} + +func BenchmarkMeanStdDevHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMeanStdDev(b, s, nil) +} + +func BenchmarkMeanStdDevSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMeanStdDev(b, s, wts) +} + +func BenchmarkMeanStdDevMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMeanStdDev(b, s, wts) +} + +func BenchmarkMeanStdDevLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMeanStdDev(b, s, wts) +} + +func BenchmarkMeanStdDevHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMeanStdDev(b, s, wts) +} + +func benchmarkCovariance(b *testing.B, s1, s2, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Covariance(s1, s2, wts) + } +} + +func BenchmarkCovarianceSmall(b *testing.B) { + s1 := RandomSlice(small) + s2 := RandomSlice(small) + benchmarkCovariance(b, s1, s2, nil) +} + +func BenchmarkCovarianceMedium(b *testing.B) { + s1 := RandomSlice(medium) + s2 := RandomSlice(medium) + benchmarkCovariance(b, s1, s2, nil) +} + +func BenchmarkCovarianceLarge(b *testing.B) { + s1 := RandomSlice(large) + s2 := RandomSlice(large) + benchmarkCovariance(b, s1, s2, nil) +} + +func BenchmarkCovarianceHuge(b *testing.B) { + s1 := RandomSlice(huge) + s2 := RandomSlice(huge) + benchmarkCovariance(b, s1, s2, nil) +} + +func BenchmarkCovarianceSmallWeighted(b *testing.B) { + s1 := RandomSlice(small) + s2 := RandomSlice(small) + wts := RandomSlice(small) + benchmarkCovariance(b, s1, s2, wts) +} + +func BenchmarkCovarianceMediumWeighted(b *testing.B) { + s1 := RandomSlice(medium) + s2 := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkCovariance(b, s1, s2, wts) +} + +func BenchmarkCovarianceLargeWeighted(b *testing.B) { + s1 := RandomSlice(large) + s2 := RandomSlice(large) + wts := RandomSlice(large) + benchmarkCovariance(b, s1, s2, wts) +} + +func BenchmarkCovarianceHugeWeighted(b *testing.B) { + s1 := RandomSlice(huge) + s2 := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkCovariance(b, s1, s2, wts) +} + +func benchmarkCorrelation(b *testing.B, s1, s2, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Correlation(s1, s2, wts) + } +} + +func BenchmarkCorrelationSmall(b *testing.B) { + s1 := RandomSlice(small) + s2 := RandomSlice(small) + benchmarkCorrelation(b, s1, s2, nil) +} + +func BenchmarkCorrelationMedium(b *testing.B) { + s1 := RandomSlice(medium) + s2 := RandomSlice(medium) + benchmarkCorrelation(b, s1, s2, nil) +} + +func BenchmarkCorrelationLarge(b *testing.B) { + s1 := RandomSlice(large) + s2 := RandomSlice(large) + benchmarkCorrelation(b, s1, s2, nil) +} + +func BenchmarkCorrelationHuge(b *testing.B) { + s1 := RandomSlice(huge) + s2 := RandomSlice(huge) + benchmarkCorrelation(b, s1, s2, nil) +} + +func BenchmarkCorrelationSmallWeighted(b *testing.B) { + s1 := RandomSlice(small) + s2 := RandomSlice(small) + wts := RandomSlice(small) + benchmarkCorrelation(b, s1, s2, wts) +} + +func BenchmarkCorrelationMediumWeighted(b *testing.B) { + s1 := RandomSlice(medium) + s2 := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkCorrelation(b, s1, s2, wts) +} + +func BenchmarkCorrelationLargeWeighted(b *testing.B) { + s1 := RandomSlice(large) + s2 := RandomSlice(large) + wts := RandomSlice(large) + benchmarkCorrelation(b, s1, s2, wts) +} + +func BenchmarkCorrelationHugeWeighted(b *testing.B) { + s1 := RandomSlice(huge) + s2 := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkCorrelation(b, s1, s2, wts) +} + +func benchmarkSkew(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Skew(s, wts) + } +} + +func BenchmarkSkewSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkSkew(b, s, nil) +} + +func BenchmarkSkewMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkSkew(b, s, nil) +} + +func BenchmarkSkewLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkSkew(b, s, nil) +} + +func BenchmarkSkewHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkSkew(b, s, nil) +} + +func BenchmarkSkewSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkSkew(b, s, wts) +} + +func BenchmarkSkewMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkSkew(b, s, wts) +} + +func BenchmarkSkewLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkSkew(b, s, wts) +} + +func BenchmarkSkewHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkSkew(b, s, wts) +} + +func benchmarkExKurtosis(b *testing.B, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + ExKurtosis(s, wts) + } +} + +func BenchmarkExKurtosisSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkExKurtosis(b, s, nil) +} + +func BenchmarkExKurtosisMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkExKurtosis(b, s, nil) +} + +func BenchmarkExKurtosisLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkExKurtosis(b, s, nil) +} + +func BenchmarkExKurtosisHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkExKurtosis(b, s, nil) +} + +func BenchmarkExKurtosisSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkExKurtosis(b, s, wts) +} + +func BenchmarkExKurtosisMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkExKurtosis(b, s, wts) +} + +func BenchmarkExKurtosisLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkExKurtosis(b, s, wts) +} + +func BenchmarkExKurtosisHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkExKurtosis(b, s, wts) +} + +func benchmarkMoment(b *testing.B, n float64, s, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Moment(n, s, wts) + } +} + +func BenchmarkMomentSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMoment(b, 5, s, nil) +} + +func BenchmarkMomentMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMoment(b, 5, s, nil) +} + +func BenchmarkMomentLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMoment(b, 5, s, nil) +} + +func BenchmarkMomentHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMoment(b, 5, s, nil) +} + +func BenchmarkMomentSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMoment(b, 5, s, wts) +} + +func BenchmarkMomentMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMoment(b, 5, s, wts) +} + +func BenchmarkMomentLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMoment(b, 5, s, wts) +} + +func BenchmarkMomentHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMoment(b, 5, s, wts) +} + +func benchmarkMomentAbout(b *testing.B, n float64, s []float64, mean float64, wts []float64) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MomentAbout(n, s, mean, wts) + } +} + +func BenchmarkMomentAboutSmall(b *testing.B) { + s := RandomSlice(small) + benchmarkMomentAbout(b, 5, s, 0, nil) +} + +func BenchmarkMomentAboutMedium(b *testing.B) { + s := RandomSlice(medium) + benchmarkMomentAbout(b, 5, s, 0, nil) +} + +func BenchmarkMomentAboutLarge(b *testing.B) { + s := RandomSlice(large) + benchmarkMomentAbout(b, 5, s, 0, nil) +} + +func BenchmarkMomentAboutHuge(b *testing.B) { + s := RandomSlice(huge) + benchmarkMomentAbout(b, 5, s, 0, nil) +} + +func BenchmarkMomentAboutSmallWeighted(b *testing.B) { + s := RandomSlice(small) + wts := RandomSlice(small) + benchmarkMomentAbout(b, 5, s, 0, wts) +} + +func BenchmarkMomentAboutMediumWeighted(b *testing.B) { + s := RandomSlice(medium) + wts := RandomSlice(medium) + benchmarkMomentAbout(b, 5, s, 0, wts) +} + +func BenchmarkMomentAboutLargeWeighted(b *testing.B) { + s := RandomSlice(large) + wts := RandomSlice(large) + benchmarkMomentAbout(b, 5, s, 0, wts) +} + +func BenchmarkMomentAboutHugeWeighted(b *testing.B) { + s := RandomSlice(huge) + wts := RandomSlice(huge) + benchmarkMomentAbout(b, 5, s, 0, wts) +} diff --git a/stat/pca_cca.go b/stat/pca_cca.go new file mode 100644 index 00000000..5675520e --- /dev/null +++ b/stat/pca_cca.go @@ -0,0 +1,320 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat + +import ( + "errors" + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix" + "gonum.org/v1/gonum/matrix/mat64" +) + +// PC is a type for computing and extracting the principal components of a +// matrix. The results of the principal components analysis are only valid +// if the call to PrincipalComponents was successful. +type PC struct { + n, d int + weights []float64 + svd *mat64.SVD + ok bool +} + +// PrincipalComponents performs a weighted principal components analysis on the +// matrix of the input data which is represented as an n×d matrix a where each +// row is an observation and each column is a variable. +// +// PrincipalComponents centers the variables but does not scale the variance. +// +// The weights slice is used to weight the observations. If weights is nil, each +// weight is considered to have a value of one, otherwise the length of weights +// must match the number of observations or PrincipalComponents will panic. +// +// PrincipalComponents returns whether the analysis was successful. +func (c *PC) PrincipalComponents(a mat64.Matrix, weights []float64) (ok bool) { + c.n, c.d = a.Dims() + if weights != nil && len(weights) != c.n { + panic("stat: len(weights) != observations") + } + + c.svd, c.ok = svdFactorizeCentered(c.svd, a, weights) + if c.ok { + c.weights = append(c.weights[:0], weights...) + } + return c.ok +} + +// Vectors returns the component direction vectors of a principal components +// analysis. The vectors are returned in the columns of a d×min(n, d) matrix. +// If dst is not nil it must either be zero-sized or be a d×min(n, d) matrix. +// dst will be used as the destination for the direction vector data. If dst +// is nil, a new mat64.Dense is allocated for the destination. +func (c *PC) Vectors(dst *mat64.Dense) *mat64.Dense { + if !c.ok { + panic("stat: use of unsuccessful principal components analysis") + } + + if dst == nil { + dst = &mat64.Dense{} + } else if d, n := dst.Dims(); (n != 0 || d != 0) && (d != c.d || n != min(c.n, c.d)) { + panic(matrix.ErrShape) + } + dst.VFromSVD(c.svd) + return dst +} + +// Vars returns the column variances of the principal component scores, +// b * vecs, where b is a matrix with centered columns. Variances are returned +// in descending order. +// If dst is not nil it is used to store the variances and returned. +// Vars will panic if the receiver has not successfully performed a principal +// components analysis or dst is not nil and the length of dst is not min(n, d). +func (c *PC) Vars(dst []float64) []float64 { + if !c.ok { + panic("stat: use of unsuccessful principal components analysis") + } + if dst != nil && len(dst) != min(c.n, c.d) { + panic("stat: length of slice does not match analysis") + } + + dst = c.svd.Values(dst) + var f float64 + if c.weights == nil { + f = 1 / float64(c.n-1) + } else { + f = 1 / (floats.Sum(c.weights) - 1) + } + for i, v := range dst { + dst[i] = f * v * v + } + return dst +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// CC is a type for computing the canonical correlations of a pair of matrices. +// The results of the canonical correlation analysis are only valid +// if the call to CanonicalCorrelations was successful. +type CC struct { + // n is the number of observations used to + // construct the canonical correlations. + n int + + // xd and yd are used for size checks. + xd, yd int + + x, y, c *mat64.SVD + ok bool +} + +// CanonicalCorrelations returns a CC which can provide the results of canonical +// correlation analysis of the input data x and y, columns of which should be +// interpretable as two sets of measurements on the same observations (rows). +// These observations are optionally weighted by weights. +// +// Canonical correlation analysis finds associations between two sets of +// variables on the same observations by finding linear combinations of the two +// sphered datasets that maximize the correlation between them. +// +// Some notation: let Xc and Yc denote the centered input data matrices x +// and y (column means subtracted from each column), let Sx and Sy denote the +// sample covariance matrices within x and y respectively, and let Sxy denote +// the covariance matrix between x and y. The sphered data can then be expressed +// as Xc * Sx^{-1/2} and Yc * Sy^{-1/2} respectively, and the correlation matrix +// between the sphered data is called the canonical correlation matrix, +// Sx^{-1/2} * Sxy * Sy^{-1/2}. In cases where S^{-1/2} is ambiguous for some +// covariance matrix S, S^{-1/2} is taken to be E * D^{-1/2} * E^T where S can +// be eigendecomposed as S = E * D * E^T. +// +// The canonical correlations are the correlations between the corresponding +// pairs of canonical variables and can be obtained with c.Corrs(). Canonical +// variables can be obtained by projecting the sphered data into the left and +// right eigenvectors of the canonical correlation matrix, and these +// eigenvectors can be obtained with c.Left(m, true) and c.Right(m, true) +// respectively. The canonical variables can also be obtained directly from the +// centered raw data by using the back-transformed eigenvectors which can be +// obtained with c.Left(m, false) and c.Right(m, false) respectively. +// +// The first pair of left and right eigenvectors of the canonical correlation +// matrix can be interpreted as directions into which the respective sphered +// data can be projected such that the correlation between the two projections +// is maximized. The second pair and onwards solve the same optimization but +// under the constraint that they are uncorrelated (orthogonal in sphered space) +// to previous projections. +// +// CanonicalCorrelations will panic if the inputs x and y do not have the same +// number of rows. +// +// The slice weights is used to weight the observations. If weights is nil, each +// weight is considered to have a value of one, otherwise the length of weights +// must match the number of observations (rows of both x and y) or +// CanonicalCorrelations will panic. +// +// More details can be found at +// https://en.wikipedia.org/wiki/Canonical_correlation +// or in Chapter 3 of +// Koch, Inge. Analysis of multivariate and high-dimensional data. +// Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939 +func (c *CC) CanonicalCorrelations(x, y mat64.Matrix, weights []float64) error { + var yn int + c.n, c.xd = x.Dims() + yn, c.yd = y.Dims() + if c.n != yn { + panic("stat: unequal number of observations") + } + if weights != nil && len(weights) != c.n { + panic("stat: len(weights) != observations") + } + + // Center and factorize x and y. + c.x, c.ok = svdFactorizeCentered(c.x, x, weights) + if !c.ok { + return errors.New("stat: failed to factorize x") + } + c.y, c.ok = svdFactorizeCentered(c.y, y, weights) + if !c.ok { + return errors.New("stat: failed to factorize y") + } + var xu, xv, yu, yv mat64.Dense + xu.UFromSVD(c.x) + xv.VFromSVD(c.x) + yu.UFromSVD(c.y) + yv.VFromSVD(c.y) + + // Calculate and factorise the canonical correlation matrix. + var ccor mat64.Dense + ccor.Product(&xv, xu.T(), &yu, yv.T()) + if c.c == nil { + c.c = &mat64.SVD{} + } + c.ok = c.c.Factorize(&ccor, matrix.SVDThin) + if !c.ok { + return errors.New("stat: failed to factorize ccor") + } + return nil +} + +// Corrs returns the canonical correlations, using dst if it is not nil. +// If dst is not nil and len(dst) does not match the number of columns in +// the y input matrix, Corrs will panic. +func (c *CC) Corrs(dst []float64) []float64 { + if !c.ok { + panic("stat: canonical correlations missing or invalid") + } + + if dst != nil && len(dst) != c.yd { + panic("stat: length of destination does not match input dimension") + } + return c.c.Values(dst) +} + +// Left returns the left eigenvectors of the canonical correlation matrix if +// spheredSpace is true. If spheredSpace is false it returns these eigenvectors +// back-transformed to the original data space. +// If dst is not nil it must either be zero-sized or be an xd×yd matrix where xd +// and yd are the number of variables in the input x and y matrices. dst will +// be used as the destination for the vector data. If dst is nil, a new +// mat64.Dense is allocated for the destination. +func (c *CC) Left(dst *mat64.Dense, spheredSpace bool) *mat64.Dense { + if !c.ok || c.n < 2 { + panic("stat: canonical correlations missing or invalid") + } + + if dst == nil { + dst = &mat64.Dense{} + } else if d, n := dst.Dims(); (n != 0 || d != 0) && (n != c.yd || d != c.xd) { + panic(matrix.ErrShape) + } + dst.UFromSVD(c.c) + if spheredSpace { + return dst + } + + var xv mat64.Dense + xs := c.x.Values(nil) + xv.VFromSVD(c.x) + + scaleColsReciSqrt(&xv, xs) + + dst.Product(&xv, xv.T(), dst) + dst.Scale(math.Sqrt(float64(c.n-1)), dst) + return dst +} + +// Right returns the right eigenvectors of the canonical correlation matrix if +// spheredSpace is true. If spheredSpace is false it returns these eigenvectors +// back-transformed to the original data space. +// If dst is not nil it must either be zero-sized or be an yd×yd matrix where yd +// is the number of variables in the input y matrix. dst will +// be used as the destination for the vector data. If dst is nil, a new +// mat64.Dense is allocated for the destination. +func (c *CC) Right(dst *mat64.Dense, spheredSpace bool) *mat64.Dense { + if !c.ok || c.n < 2 { + panic("stat: canonical correlations missing or invalid") + } + + if dst == nil { + dst = &mat64.Dense{} + } else if d, n := dst.Dims(); (n != 0 || d != 0) && (n != c.yd || d != c.yd) { + panic(matrix.ErrShape) + } + dst.VFromSVD(c.c) + if spheredSpace { + return dst + } + + var yv mat64.Dense + ys := c.y.Values(nil) + yv.VFromSVD(c.y) + + scaleColsReciSqrt(&yv, ys) + + dst.Product(&yv, yv.T(), dst) + dst.Scale(math.Sqrt(float64(c.n-1)), dst) + return dst +} + +func svdFactorizeCentered(work *mat64.SVD, m mat64.Matrix, weights []float64) (svd *mat64.SVD, ok bool) { + n, d := m.Dims() + centered := mat64.NewDense(n, d, nil) + col := make([]float64, n) + for j := 0; j < d; j++ { + mat64.Col(col, j, m) + floats.AddConst(-Mean(col, weights), col) + centered.SetCol(j, col) + } + for i, w := range weights { + floats.Scale(math.Sqrt(w), centered.RawRowView(i)) + } + if work == nil { + work = &mat64.SVD{} + } + ok = work.Factorize(centered, matrix.SVDThin) + return work, ok +} + +// scaleColsReciSqrt scales the columns of cols +// by the reciprocal square-root of vals. +func scaleColsReciSqrt(cols *mat64.Dense, vals []float64) { + if cols == nil { + panic("stat: input nil") + } + n, d := cols.Dims() + if len(vals) != d { + panic("stat: input length mismatch") + } + col := make([]float64, n) + for j := 0; j < d; j++ { + mat64.Col(col, j, cols) + floats.Scale(math.Sqrt(1/vals[j]), col) + cols.SetCol(j, col) + } +} diff --git a/stat/pca_example_test.go b/stat/pca_example_test.go new file mode 100644 index 00000000..33582362 --- /dev/null +++ b/stat/pca_example_test.go @@ -0,0 +1,60 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat_test + +import ( + "fmt" + + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat" +) + +func ExamplePrincipalComponents() { + // iris is a truncated sample of the Fisher's Iris dataset. + n := 10 + d := 4 + iris := mat64.NewDense(n, d, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }) + + // Calculate the principal component direction vectors + // and variances. + var pc stat.PC + ok := pc.PrincipalComponents(iris, nil) + if !ok { + return + } + fmt.Printf("variances = %.4f\n\n", pc.Vars(nil)) + + // Project the data onto the first 2 principal components. + k := 2 + var proj mat64.Dense + proj.Mul(iris, pc.Vectors(nil).Slice(0, d, 0, k)) + + fmt.Printf("proj = %.4f", mat64.Formatted(&proj, mat64.Prefix(" "))) + + // Output: + // variances = [0.1666 0.0207 0.0079 0.0019] + // + // proj = ⎡-6.1686 1.4659⎤ + // ⎢-5.6767 1.6459⎥ + // ⎢-5.6699 1.3642⎥ + // ⎢-5.5643 1.3816⎥ + // ⎢-6.1734 1.3309⎥ + // ⎢-6.7278 1.4021⎥ + // ⎢-5.7743 1.1498⎥ + // ⎢-6.0466 1.4714⎥ + // ⎢-5.2709 1.3570⎥ + // ⎣-5.7533 1.6207⎦ +} diff --git a/stat/pca_test.go b/stat/pca_test.go new file mode 100644 index 00000000..f54985f6 --- /dev/null +++ b/stat/pca_test.go @@ -0,0 +1,183 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat + +import ( + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +func TestPrincipalComponents(t *testing.T) { +tests: + for i, test := range []struct { + data mat64.Matrix + weights []float64 + wantVecs *mat64.Dense + wantVars []float64 + epsilon float64 + }{ + // Test results verified using R. + { + data: mat64.NewDense(3, 3, []float64{ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }), + wantVecs: mat64.NewDense(3, 3, []float64{ + 0.5773502691896258, 0.8164965809277261, 0, + 0.577350269189626, -0.4082482904638632, -0.7071067811865476, + 0.5773502691896258, -0.4082482904638631, 0.7071067811865475, + }), + wantVars: []float64{27, 0, 0}, + epsilon: 1e-12, + }, + { // Truncated iris data. + data: mat64.NewDense(10, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }), + wantVecs: mat64.NewDense(4, 4, []float64{ + -0.6681110197952722, 0.7064764857539533, -0.14026590216895132, -0.18666578956412125, + -0.7166344774801547, -0.6427036135482664, -0.135650285905254, 0.23444848208629923, + -0.164411275166307, 0.11898477441068218, 0.9136367900709548, 0.35224901970831746, + -0.11415613655453069, -0.2714141920887426, 0.35664028439226514, -0.8866286823515034, + }), + wantVars: []float64{0.1665786313282786, 0.02065509475412993, 0.007944620317765855, 0.0019327647109368329}, + epsilon: 1e-12, + }, + { // Truncated iris data to form wide matrix. + data: mat64.NewDense(3, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + }), + wantVecs: mat64.NewDense(4, 3, []float64{ + -0.5705187254552365, -0.7505979435049239, 0.08084520834544455, + -0.8166537769529318, 0.5615147645527523, -0.032338083338177705, + -0.08709186238359454, -0.3482870890450082, -0.22636658336724505, + 0, 0, -0.9701425001453315, + }), + wantVars: []float64{0.0844692361537822, 0.022197430512884326, 0}, + epsilon: 1e-12, + }, + { // Truncated iris data transposed to check for operation on fat input. + data: mat64.NewDense(10, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }).T(), + wantVecs: mat64.NewDense(10, 4, []float64{ + -0.3366602459946619, -0.1373634006401213, 0.3465102523547623, -0.10290179303893479, + -0.31381852053861975, 0.5197145790632827, 0.5567296129086686, -0.15923062170153618, + -0.30857197637565165, -0.07670930360819002, 0.36159923003337235, 0.3342301027853355, + -0.29527124351656137, 0.16885455995353074, -0.5056204762881208, 0.32580913261444344, + -0.3327611073694004, -0.39365834489416474, 0.04900050959307464, 0.46812879383236555, + -0.34445484362044815, -0.2985206914561878, -0.1009714701361799, -0.16803618186050803, + -0.2986246350957691, -0.4222037823717799, -0.11838613462182519, -0.580283530375069, + -0.325911246223126, 0.024366468758217238, -0.12082035131864265, 0.16756027181337868, + -0.2814284432361538, 0.240812316260054, -0.24061437569068145, -0.365034616264623, + -0.31906138507685167, 0.4423912824105986, -0.2906412122303604, 0.027551046870337714, + }), + wantVars: []float64{41.8851906634233, 0.07762619213464989, 0.010516477775373585, 0}, + epsilon: 1e-12, + }, + { // Truncated iris data unitary weights. + data: mat64.NewDense(10, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }), + weights: []float64{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + wantVecs: mat64.NewDense(4, 4, []float64{ + -0.6681110197952722, 0.7064764857539533, -0.14026590216895132, -0.18666578956412125, + -0.7166344774801547, -0.6427036135482664, -0.135650285905254, 0.23444848208629923, + -0.164411275166307, 0.11898477441068218, 0.9136367900709548, 0.35224901970831746, + -0.11415613655453069, -0.2714141920887426, 0.35664028439226514, -0.8866286823515034, + }), + wantVars: []float64{0.1665786313282786, 0.02065509475412993, 0.007944620317765855, 0.0019327647109368329}, + epsilon: 1e-12, + }, + { // Truncated iris data non-unitary weights. + data: mat64.NewDense(10, 4, []float64{ + 5.1, 3.5, 1.4, 0.2, + 4.9, 3.0, 1.4, 0.2, + 4.7, 3.2, 1.3, 0.2, + 4.6, 3.1, 1.5, 0.2, + 5.0, 3.6, 1.4, 0.2, + 5.4, 3.9, 1.7, 0.4, + 4.6, 3.4, 1.4, 0.3, + 5.0, 3.4, 1.5, 0.2, + 4.4, 2.9, 1.4, 0.2, + 4.9, 3.1, 1.5, 0.1, + }), + weights: []float64{2, 3, 1, 1, 1, 1, 1, 1, 1, 2}, + wantVecs: mat64.NewDense(4, 4, []float64{ + -0.618936145422414, 0.763069301531647, 0.124857741232537, 0.138035623677211, + -0.763958271606519, -0.603881770702898, 0.118267155321333, -0.194184052457746, + -0.143552119754944, 0.090014599564871, -0.942209377020044, -0.289018426115945, + -0.112599271966947, -0.212012782487076, -0.287515067921680, 0.927203898682805, + }), + wantVars: []float64{0.129621985550623, 0.022417487771598, 0.006454461065715, 0.002495076601075}, + epsilon: 1e-12, + }, + } { + var pc PC + var vecs *mat64.Dense + var vars []float64 + for j := 0; j < 2; j++ { + ok := pc.PrincipalComponents(test.data, test.weights) + vecs = pc.Vectors(vecs) + vars = pc.Vars(vars) + if !ok { + t.Errorf("unexpected SVD failure for test %d use %d", i, j) + continue tests + } + if !mat64.EqualApprox(vecs, test.wantVecs, test.epsilon) { + t.Errorf("%d use %d: unexpected PCA result got:\n%v\nwant:\n%v", + i, j, mat64.Formatted(vecs), mat64.Formatted(test.wantVecs)) + } + if !approxEqual(vars, test.wantVars, test.epsilon) { + t.Errorf("%d use %d: unexpected variance result got:%v, want:%v", + i, j, vars, test.wantVars) + } + } + } +} + +func approxEqual(a, b []float64, epsilon float64) bool { + if len(a) != len(b) { + return false + } + for i, v := range a { + if !floats.EqualWithinAbsOrRel(v, b[i], epsilon, epsilon) { + return false + } + } + return true +} diff --git a/stat/roc.go b/stat/roc.go new file mode 100644 index 00000000..73584b61 --- /dev/null +++ b/stat/roc.go @@ -0,0 +1,121 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat + +import "sort" + +// ROC returns paired false positive rate (FPR) and true positive rate +// (TPR) values corresponding to n cutoffs spanning the relative +// (or receiver) operator characteristic (ROC) curve obtained when y is +// treated as a binary classifier for classes with weights. +// +// Cutoffs are equally spaced from eps less than the minimum value of y +// to the maximum value of y, including both endpoints meaning that the +// resulting ROC curve will always begin at (0,0) and end at (1,1). +// +// The input y must be sorted, and SortWeightedLabeled can be used in +// order to sort y together with classes and weights. +// +// For a given cutoff value, observations corresponding to entries in y +// greater than the cutoff value are classified as false, while those +// below (or equal to) the cutoff value are classified as true. These +// assigned class labels are compared with the true values in the classes +// slice and used to calculate the FPR and TPR. +// +// If weights is nil, all weights are treated as 1. +// +// When n is zero all possible cutoffs are calculated, resulting +// in fpr and tpr having length one greater than the number of unique +// values in y. When n is greater than one fpr and tpr will be returned +// with length n. ROC will panic if n is equal to one or less than 0. +// +// More details about ROC curves are available at +// https://en.wikipedia.org/wiki/Receiver_operating_characteristic +func ROC(n int, y []float64, classes []bool, weights []float64) (tpr, fpr []float64) { + if len(y) != len(classes) { + panic("stat: slice length mismatch") + } + if weights != nil && len(y) != len(weights) { + panic("stat: slice length mismatch") + } + if !sort.Float64sAreSorted(y) { + panic("stat: input must be sorted") + } + + var incWidth, tol float64 + if n == 0 { + if len(y) == 0 { + return nil, nil + } + tpr = make([]float64, len(y)+1) + fpr = make([]float64, len(y)+1) + } else { + if n < 2 { + panic("stat: cannot calculate fewer than 2 points on a ROC curve") + } + if len(y) == 0 { + return nil, nil + } + tpr = make([]float64, n) + fpr = make([]float64, n) + incWidth = (y[len(y)-1] - y[0]) / float64(n-1) + tol = y[0] + incWidth + if incWidth == 0 { + tpr[n-1] = 1 + fpr[n-1] = 1 + return + } + } + + var bin int = 1 // the initial bin is known to have 0 fpr and 0 tpr + var nPos, nNeg float64 + for i, u := range classes { + var posWeight, negWeight float64 = 0, 1 + if weights != nil { + negWeight = weights[i] + } + if u { + posWeight, negWeight = negWeight, posWeight + } + nPos += posWeight + nNeg += negWeight + tpr[bin] += posWeight + fpr[bin] += negWeight + + // Assess if the bin needs to be updated. If n is zero, + // the bin is always updated, unless consecutive y values + // are equal. Otherwise, the bin must be updated until it + // matches the next y value (skipping empty bins). + if n == 0 { + if i != (len(y)-1) && y[i] != y[i+1] { + bin++ + tpr[bin] = tpr[bin-1] + fpr[bin] = fpr[bin-1] + } + } else { + for i != (len(y)-1) && y[i+1] > tol { + tol += incWidth + bin++ + tpr[bin] = tpr[bin-1] + fpr[bin] = fpr[bin-1] + } + } + } + if n == 0 { + tpr = tpr[:(bin + 1)] + fpr = fpr[:(bin + 1)] + } + + invNeg := 1 / nNeg + invPos := 1 / nPos + for i := range tpr { + tpr[i] *= invPos + fpr[i] *= invNeg + } + tpr[len(tpr)-1] = 1 + fpr[len(fpr)-1] = 1 + + return tpr, fpr +} diff --git a/stat/roc_example_test.go b/stat/roc_example_test.go new file mode 100644 index 00000000..7f34b8d8 --- /dev/null +++ b/stat/roc_example_test.go @@ -0,0 +1,56 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat_test + +import ( + "fmt" + + "gonum.org/v1/gonum/integrate" + "gonum.org/v1/gonum/stat" +) + +func ExampleROC_unweighted() { + y := []float64{0, 3, 5, 6, 7.5, 8} + classes := []bool{true, false, true, false, false, false} + weights := []float64{4, 1, 6, 3, 2, 2} + + tpr, fpr := stat.ROC(0, y, classes, weights) + fmt.Printf("true positive rate: %v\n", tpr) + fmt.Printf("false positive rate: %v\n", fpr) + + // Output: + // true positive rate: [0 0.4 0.4 1 1 1 1] + // false positive rate: [0 0 0.125 0.125 0.5 0.75 1] +} + +func ExampleROC_weighted() { + y := []float64{0, 3, 5, 6, 7.5, 8} + classes := []bool{true, false, true, false, false, false} + + tpr, fpr := stat.ROC(0, y, classes, nil) + fmt.Printf("true positive rate: %v\n", tpr) + fmt.Printf("false positive rate: %v\n", fpr) + + // Output: + // true positive rate: [0 0.5 0.5 1 1 1 1] + // false positive rate: [0 0 0.25 0.25 0.5 0.75 1] +} + +func ExampleROC_aUC() { + y := []float64{0.1, 0.35, 0.4, 0.8} + classes := []bool{true, false, true, false} + + tpr, fpr := stat.ROC(0, y, classes, nil) + // compute Area Under Curve + auc := integrate.Trapezoidal(fpr, tpr) + fmt.Printf("true positive rate: %v\n", tpr) + fmt.Printf("false positive rate: %v\n", fpr) + fmt.Printf("auc: %v\n", auc) + + // Output: + // true positive rate: [0 0.5 0.5 1 1] + // false positive rate: [0 0 0.5 0.5 1] + // auc: 0.75 +} diff --git a/stat/roc_test.go b/stat/roc_test.go new file mode 100644 index 00000000..99fdae13 --- /dev/null +++ b/stat/roc_test.go @@ -0,0 +1,178 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat + +import ( + "testing" + + "gonum.org/v1/gonum/floats" +) + +// Test cases where calculated manually. +func TestROC(t *testing.T) { + cases := []struct { + y []float64 + c []bool + w []float64 + n int + wantTPR []float64 + wantFPR []float64 + }{ + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + wantTPR: []float64{0, 0.5, 0.5, 1, 1, 1, 1}, + wantFPR: []float64{0, 0, 0.25, 0.25, 0.5, 0.75, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + wantTPR: []float64{0, 0.4, 0.4, 1, 1, 1, 1}, + wantFPR: []float64{0, 0, 0.125, 0.125, 0.5, 0.75, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + n: int(5), + wantTPR: []float64{0, 0.5, 0.5, 1, 1}, + wantFPR: []float64{0, 0, 0.25, 0.5, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + n: int(9), + wantTPR: []float64{0, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1}, + wantFPR: []float64{0, 0, 0, 0.25, 0.25, 0.25, 0.5, 0.5, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + n: int(5), + wantTPR: []float64{0, 0.4, 0.4, 1, 1}, + wantFPR: []float64{0, 0, 0.125, 0.5, 1}, + }, + { + y: []float64{0, 3, 5, 6, 7.5, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + n: int(9), + wantTPR: []float64{0, 0.4, 0.4, 0.4, 0.4, 1, 1, 1, 1}, + wantFPR: []float64{0, 0, 0, 0.125, 0.125, 0.125, 0.5, 0.5, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + wantTPR: []float64{0, 0.5, 0.5, 1, 1}, + wantFPR: []float64{0, 0, 0.25, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + wantTPR: []float64{0, 0.4, 0.4, 1, 1}, + wantFPR: []float64{0, 0, 0.125, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + n: int(5), + wantTPR: []float64{0, 0.5, 0.5, 1, 1}, + wantFPR: []float64{0, 0, 0.25, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + n: int(9), + wantTPR: []float64{0, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1}, + wantFPR: []float64{0, 0, 0, 0.25, 0.25, 0.25, 0.75, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + n: int(5), + wantTPR: []float64{0, 0.4, 0.4, 1, 1}, + wantFPR: []float64{0, 0, 0.125, 0.75, 1}, + }, + { + y: []float64{0, 3, 6, 6, 6, 8}, + c: []bool{true, false, true, false, false, false}, + w: []float64{4, 1, 6, 3, 2, 2}, + n: int(9), + wantTPR: []float64{0, 0.4, 0.4, 0.4, 0.4, 0.4, 1, 1, 1}, + wantFPR: []float64{0, 0, 0, 0.125, 0.125, 0.125, 0.75, 0.75, 1}, + }, + { + y: []float64{1, 2}, + c: []bool{true, true}, + wantTPR: []float64{0, 0.5, 1}, + wantFPR: []float64{0, 0, 1}, + }, + { + y: []float64{1, 2}, + c: []bool{true, true}, + n: int(2), + wantTPR: []float64{0, 1}, + wantFPR: []float64{0, 1}, + }, + { + y: []float64{1, 2}, + c: []bool{true, true}, + n: int(7), + wantTPR: []float64{0, 0.5, 0.5, 0.5, 0.5, 0.5, 1}, + wantFPR: []float64{0, 0, 0, 0, 0, 0, 1}, + }, + { + y: []float64{1}, + c: []bool{true}, + wantTPR: []float64{0, 1}, + wantFPR: []float64{0, 1}, + }, + { + y: []float64{1}, + c: []bool{true}, + n: int(2), + wantTPR: []float64{0, 1}, + wantFPR: []float64{0, 1}, + }, + { + y: []float64{1}, + c: []bool{false}, + wantTPR: []float64{0, 1}, + wantFPR: []float64{0, 1}, + }, + { + y: []float64{0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 10}, + c: []bool{true, false, true, true, false, false, true}, + n: int(5), + wantTPR: []float64{0, 0.75, 0.75, 0.75, 1}, + wantFPR: []float64{0, 1, 1, 1, 1}, + }, + { + y: []float64{}, + c: []bool{}, + wantTPR: nil, + wantFPR: nil, + }, + { + y: []float64{}, + c: []bool{}, + n: int(5), + wantTPR: nil, + wantFPR: nil, + }, + } + for i, test := range cases { + gotTPR, gotFPR := ROC(test.n, test.y, test.c, test.w) + if !floats.Same(gotTPR, test.wantTPR) { + t.Errorf("%d: unexpected TPR got:%v want:%v", i, gotTPR, test.wantTPR) + } + if !floats.Same(gotFPR, test.wantFPR) { + t.Errorf("%d: unexpected FPR got:%v want:%v", i, gotFPR, test.wantFPR) + } + } +} diff --git a/stat/samplemv/metropolishastings.go b/stat/samplemv/metropolishastings.go new file mode 100644 index 00000000..9c4d09c6 --- /dev/null +++ b/stat/samplemv/metropolishastings.go @@ -0,0 +1,221 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package samplemv + +import ( + "math" + "math/rand" + + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat/distmv" +) + +var _ Sampler = MetropolisHastingser{} + +// MHProposal defines a proposal distribution for Metropolis Hastings. +type MHProposal interface { + // ConditionalLogProb returns the probability of the first argument + // conditioned on being at the second argument. + // p(x|y) + // ConditionalLogProb panics if the input slices are not the same length. + ConditionalLogProb(x, y []float64) (prob float64) + + // ConditionalRand generates a new random location conditioned being at the + // location y. If the first arguement is nil, a new slice is allocated and + // returned. Otherwise, the random location is stored in-place into the first + // argument, and ConditionalRand will panic if the input slice lengths differ. + ConditionalRand(x, y []float64) []float64 +} + +// MetropolisHastingser is a wrapper around the MetropolisHastings sampling type. +// +// BurnIn sets the number of samples to discard before keeping the first sample. +// A properly set BurnIn rate will decorrelate the sampling chain from the initial +// location. The proper BurnIn value will depend on the mixing time of the +// Markov chain defined by the target and proposal distributions. +// +// Rate sets the number of samples to discard in between each kept sample. A +// higher rate will better approximate independently and identically distributed +// samples, while a lower rate will keep more information (at the cost of +// higher correlation between samples). If Rate is 0 it is defaulted to 1. +// +// The initial value is NOT changed during calls to Sample. +type MetropolisHastingser struct { + Initial []float64 + Target distmv.LogProber + Proposal MHProposal + Src *rand.Rand + + BurnIn int + Rate int +} + +// Sample generates rows(batch) samples using the Metropolis Hastings sample +// generation method. The initial location is NOT updated during the call to Sample. +// +// The number of columns in batch must equal len(m.Initial), otherwise Sample +// will panic. +func (m MetropolisHastingser) Sample(batch *mat64.Dense) { + burnIn := m.BurnIn + rate := m.Rate + if rate == 0 { + rate = 1 + } + r, c := batch.Dims() + if len(m.Initial) != c { + panic("metropolishastings: length mismatch") + } + + // Use the optimal size for the temporary memory to allow the fewest calls + // to MetropolisHastings. The case where tmp shadows samples must be + // aligned with the logic after burn-in so that tmp does not shadow samples + // during the rate portion. + tmp := batch + if rate > r { + tmp = mat64.NewDense(rate, c, nil) + } + rTmp, _ := tmp.Dims() + + // Perform burn-in. + remaining := burnIn + initial := make([]float64, c) + copy(initial, m.Initial) + for remaining != 0 { + newSamp := min(rTmp, remaining) + MetropolisHastings(tmp.View(0, 0, newSamp, c).(*mat64.Dense), initial, m.Target, m.Proposal, m.Src) + copy(initial, tmp.RawRowView(newSamp-1)) + remaining -= newSamp + } + + if rate == 1 { + MetropolisHastings(batch, initial, m.Target, m.Proposal, m.Src) + return + } + + if rTmp <= r { + tmp = mat64.NewDense(rate, c, nil) + } + + // Take a single sample from the chain. + MetropolisHastings(batch.View(0, 0, 1, c).(*mat64.Dense), initial, m.Target, m.Proposal, m.Src) + + copy(initial, batch.RawRowView(0)) + // For all of the other samples, first generate Rate samples and then actually + // accept the last one. + for i := 1; i < r; i++ { + MetropolisHastings(tmp, initial, m.Target, m.Proposal, m.Src) + v := tmp.RawRowView(rate - 1) + batch.SetRow(i, v) + copy(initial, v) + } +} + +// MetropolisHastings generates rows(batch) samples using the Metropolis Hastings +// algorithm (http://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithm), +// with the given target and proposal distributions, starting at the intial location +// and storing the results in-place into samples. If src != nil, it will be used to generate random +// numbers, otherwise rand.Float64 will be used. +// +// Metropolis-Hastings is a Markov-chain Monte Carlo algorithm that generates +// samples according to the distribution specified by target by using the Markov +// chain implicitly defined by the proposal distribution. At each +// iteration, a proposal point is generated randomly from the current location. +// This proposal point is accepted with probability +// p = min(1, (target(new) * proposal(current|new)) / (target(current) * proposal(new|current))) +// If the new location is accepted, it is stored into batch and becomes the +// new current location. If it is rejected, the current location remains and +// is stored into samples. Thus, a location is stored into batch at every iteration. +// +// The samples in Metropolis Hastings are correlated with one another through the +// Markov chain. As a result, the initial value can have a significant influence +// on the early samples, and so, typically, the first samples generated by the chain +// are ignored. This is known as "burn-in", and can be accomplished with slicing. +// The best choice for burn-in length will depend on the sampling and target +// distributions. +// +// Many choose to have a sampling "rate" where a number of samples +// are ignored in between each kept sample. This helps decorrelate +// the samples from one another, but also reduces the number of available samples. +// A sampling rate can be implemented with successive calls to MetropolisHastings. +func MetropolisHastings(batch *mat64.Dense, initial []float64, target distmv.LogProber, proposal MHProposal, src *rand.Rand) { + f64 := rand.Float64 + if src != nil { + f64 = src.Float64 + } + if len(initial) == 0 { + panic("metropolishastings: zero length initial") + } + r, _ := batch.Dims() + current := make([]float64, len(initial)) + copy(current, initial) + proposed := make([]float64, len(initial)) + currentLogProb := target.LogProb(initial) + for i := 0; i < r; i++ { + proposal.ConditionalRand(proposed, current) + proposedLogProb := target.LogProb(proposed) + probTo := proposal.ConditionalLogProb(proposed, current) + probBack := proposal.ConditionalLogProb(current, proposed) + + accept := math.Exp(proposedLogProb + probBack - probTo - currentLogProb) + if accept > f64() { + copy(current, proposed) + currentLogProb = proposedLogProb + } + batch.SetRow(i, current) + } +} + +// ProposalNormal is a sampling distribution for Metropolis-Hastings. It has a +// fixed covariance matrix and changes the mean based on the current sampling +// location. +type ProposalNormal struct { + normal *distmv.Normal +} + +// NewProposalNormal constructs a new ProposalNormal for use as a proposal +// distribution for Metropolis-Hastings. ProposalNormal is a multivariate normal +// distribution (implemented by distmv.Normal) where the covariance matrix is fixed +// and the mean of the distribution changes. +// +// NewProposalNormal returns {nil, false} if the covariance matrix is not positive-definite. +func NewProposalNormal(sigma *mat64.SymDense, src *rand.Rand) (*ProposalNormal, bool) { + mu := make([]float64, sigma.Symmetric()) + normal, ok := distmv.NewNormal(mu, sigma, src) + if !ok { + return nil, false + } + p := &ProposalNormal{ + normal: normal, + } + return p, true +} + +// ConditionalLogProb returns the probability of the first argument conditioned on +// being at the second argument. +// p(x|y) +// ConditionalLogProb panics if the input slices are not the same length or +// are not equal to the dimension of the covariance matrix. +func (p *ProposalNormal) ConditionalLogProb(x, y []float64) (prob float64) { + // Either SetMean or LogProb will panic if the slice lengths are innaccurate. + p.normal.SetMean(y) + return p.normal.LogProb(x) +} + +// ConditionalRand generates a new random location conditioned being at the +// location y. If the first arguement is nil, a new slice is allocated and +// returned. Otherwise, the random location is stored in-place into the first +// argument, and ConditionalRand will panic if the input slice lengths differ or +// if they are not equal to the dimension of the covariance matrix. +func (p *ProposalNormal) ConditionalRand(x, y []float64) []float64 { + if x == nil { + x = make([]float64, p.normal.Dim()) + } + if len(x) != len(y) { + panic(badLengthMismatch) + } + p.normal.SetMean(y) + p.normal.Rand(x) + return x +} diff --git a/stat/samplemv/sample_test.go b/stat/samplemv/sample_test.go new file mode 100644 index 00000000..bb48ad11 --- /dev/null +++ b/stat/samplemv/sample_test.go @@ -0,0 +1,280 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package samplemv + +import ( + "fmt" + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat" + "gonum.org/v1/gonum/stat/distmv" +) + +type lhDist interface { + Quantile(x, p []float64) []float64 + CDF(p, x []float64) []float64 + Dim() int +} + +func TestLatinHypercube(t *testing.T) { + for _, nSamples := range []int{1, 2, 5, 10, 20} { + for _, dist := range []lhDist{ + distmv.NewUniform([]distmv.Bound{{0, 3}}, nil), + distmv.NewUniform([]distmv.Bound{{0, 3}, {-1, 5}, {-4, -1}}, nil), + } { + dim := dist.Dim() + batch := mat64.NewDense(nSamples, dim, nil) + LatinHypercube(batch, dist, nil) + // Latin hypercube should have one entry per hyperrow. + present := make([][]bool, nSamples) + for i := range present { + present[i] = make([]bool, dim) + } + cdf := make([]float64, dim) + for i := 0; i < nSamples; i++ { + dist.CDF(cdf, batch.RawRowView(i)) + for j := 0; j < dim; j++ { + p := cdf[j] + quadrant := int(math.Floor(p * float64(nSamples))) + present[quadrant][j] = true + } + } + allPresent := true + for i := 0; i < nSamples; i++ { + for j := 0; j < dim; j++ { + if present[i][j] == false { + allPresent = false + } + } + } + if !allPresent { + t.Errorf("All quadrants not present") + } + } + } +} + +func TestImportance(t *testing.T) { + // Test by finding the expected value of a multi-variate normal. + dim := 3 + target, ok := randomNormal(dim) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + muImp := make([]float64, dim) + sigmaImp := mat64.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigmaImp.SetSym(i, i, 3) + } + proposal, ok := distmv.NewNormal(muImp, sigmaImp, nil) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + nSamples := 100000 + batch := mat64.NewDense(nSamples, dim, nil) + weights := make([]float64, nSamples) + Importance(batch, weights, target, proposal) + + compareNormal(t, target, batch, weights) +} + +func TestRejection(t *testing.T) { + // Test by finding the expected value of a uniform. + dim := 3 + bounds := make([]distmv.Bound, dim) + for i := 0; i < dim; i++ { + min := rand.NormFloat64() + max := rand.NormFloat64() + if min > max { + min, max = max, min + } + bounds[i].Min = min + bounds[i].Max = max + } + target := distmv.NewUniform(bounds, nil) + mu := target.Mean(nil) + + muImp := make([]float64, dim) + sigmaImp := mat64.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigmaImp.SetSym(i, i, 6) + } + proposal, ok := distmv.NewNormal(muImp, sigmaImp, nil) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + nSamples := 1000 + batch := mat64.NewDense(nSamples, dim, nil) + weights := make([]float64, nSamples) + _, ok = Rejection(batch, target, proposal, 1000, nil) + if !ok { + t.Error("Bad test, nan samples") + } + + for i := 0; i < dim; i++ { + col := mat64.Col(nil, i, batch) + ev := stat.Mean(col, weights) + if math.Abs(ev-mu[i]) > 1e-2 { + t.Errorf("Mean mismatch: Want %v, got %v", mu[i], ev) + } + } +} + +func TestMetropolisHastings(t *testing.T) { + // Test by finding the expected value of a normal distribution. + dim := 3 + target, ok := randomNormal(dim) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + sigmaImp := mat64.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigmaImp.SetSym(i, i, 0.25) + } + proposal, ok := NewProposalNormal(sigmaImp, nil) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + nSamples := 1000000 + burnin := 5000 + batch := mat64.NewDense(nSamples, dim, nil) + initial := make([]float64, dim) + MetropolisHastings(batch, initial, target, proposal, nil) + batch = batch.View(burnin, 0, nSamples-burnin, dim).(*mat64.Dense) + + compareNormal(t, target, batch, nil) +} + +// randomNormal constructs a random Normal distribution. +func randomNormal(dim int) (*distmv.Normal, bool) { + data := make([]float64, dim*dim) + for i := range data { + data[i] = rand.Float64() + } + a := mat64.NewDense(dim, dim, data) + var sigma mat64.SymDense + sigma.SymOuterK(1, a) + mu := make([]float64, dim) + for i := range mu { + mu[i] = rand.NormFloat64() + } + return distmv.NewNormal(mu, &sigma, nil) +} + +func compareNormal(t *testing.T, want *distmv.Normal, batch *mat64.Dense, weights []float64) { + dim := want.Dim() + mu := want.Mean(nil) + sigma := want.CovarianceMatrix(nil) + n, _ := batch.Dims() + if weights == nil { + weights = make([]float64, n) + for i := range weights { + weights[i] = 1 + } + } + for i := 0; i < dim; i++ { + col := mat64.Col(nil, i, batch) + ev := stat.Mean(col, weights) + if math.Abs(ev-mu[i]) > 1e-2 { + t.Errorf("Mean mismatch: Want %v, got %v", mu[i], ev) + } + } + + cov := stat.CovarianceMatrix(nil, batch, weights) + if !mat64.EqualApprox(cov, sigma, 1.5e-1) { + t.Errorf("Covariance matrix mismatch") + } +} + +func TestMetropolisHastingser(t *testing.T) { + for seed, test := range []struct { + dim, burnin, rate, samples int + }{ + {3, 10, 1, 1}, + {3, 10, 2, 1}, + {3, 10, 1, 2}, + {3, 10, 3, 2}, + {3, 10, 7, 4}, + {3, 10, 7, 4}, + + {3, 11, 51, 103}, + {3, 11, 103, 51}, + {3, 51, 11, 103}, + {3, 51, 103, 11}, + {3, 103, 11, 51}, + {3, 103, 51, 11}, + } { + dim := test.dim + + initial := make([]float64, dim) + target, ok := randomNormal(dim) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + sigmaImp := mat64.NewSymDense(dim, nil) + for i := 0; i < dim; i++ { + sigmaImp.SetSym(i, i, 0.25) + } + proposal, ok := NewProposalNormal(sigmaImp, nil) + if !ok { + t.Fatal("bad test, sigma not pos def") + } + + // Test the Metropolis Hastingser by generating all the samples, then generating + // the same samples with a burnin and rate. + rand.Seed(int64(seed)) + mh := MetropolisHastingser{ + Initial: initial, + Target: target, + Proposal: proposal, + Src: nil, + BurnIn: 0, + Rate: 0, + } + samples := test.samples + burnin := test.burnin + rate := test.rate + fullBatch := mat64.NewDense(1+burnin+rate*(samples-1), dim, nil) + mh.Sample(fullBatch) + mh = MetropolisHastingser{ + Initial: initial, + Target: target, + Proposal: proposal, + Src: nil, + BurnIn: burnin, + Rate: rate, + } + rand.Seed(int64(seed)) + batch := mat64.NewDense(samples, dim, nil) + mh.Sample(batch) + + same := true + count := burnin + for i := 0; i < samples; i++ { + if !floats.Equal(batch.RawRowView(i), fullBatch.RawRowView(count)) { + fmt.Println("sample ", i, "is different") + same = false + break + } + count += rate + } + + if !same { + fmt.Printf("%v\n", mat64.Formatted(batch)) + fmt.Printf("%v\n", mat64.Formatted(fullBatch)) + + t.Errorf("sampling mismatch: dim = %v, burnin = %v, rate = %v, samples = %v", dim, burnin, rate, samples) + } + } +} diff --git a/stat/samplemv/samplemv.go b/stat/samplemv/samplemv.go new file mode 100644 index 00000000..3181e3d7 --- /dev/null +++ b/stat/samplemv/samplemv.go @@ -0,0 +1,282 @@ +// Copyright ©2016 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package samplemv implements advanced sampling routines from explicit and implicit +// probability distributions. +// +// Each sampling routine is implemented as a stateless function with a +// complementary wrapper type. The wrapper types allow the sampling routines +// to implement interfaces. +package samplemv + +import ( + "errors" + "math" + "math/rand" + + "gonum.org/v1/gonum/matrix/mat64" + "gonum.org/v1/gonum/stat/distmv" +) + +var ( + badLengthMismatch = "samplemv: slice length mismatch" +) + +var ( + _ Sampler = LatinHypercuber{} + _ Sampler = (*Rejectioner)(nil) + _ Sampler = IIDer{} + + _ WeightedSampler = SampleUniformWeighted{} + _ WeightedSampler = Importancer{} +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// Sampler generates a batch of samples according to the rule specified by the +// implementing type. The number of samples generated is equal to rows(batch), +// and the samples are stored in-place into the input. +type Sampler interface { + Sample(batch *mat64.Dense) +} + +// WeightedSampler generates a batch of samples and their relative weights +// according to the rule specified by the implementing type. The number of samples +// generated is equal to rows(batch), and the samples and weights +// are stored in-place into the inputs. The length of weights must equal +// rows(batch), otherwise SampleWeighted will panic. +type WeightedSampler interface { + SampleWeighted(batch *mat64.Dense, weights []float64) +} + +// SampleUniformWeighted wraps a Sampler type to create a WeightedSampler where all +// weights are equal. +type SampleUniformWeighted struct { + Sampler +} + +// SampleWeighted generates rows(batch) samples from the embedded Sampler type +// and sets all of the weights equal to 1. If rows(batch) and len(weights) +// of weights are not equal, SampleWeighted will panic. +func (w SampleUniformWeighted) SampleWeighted(batch *mat64.Dense, weights []float64) { + r, _ := batch.Dims() + if r != len(weights) { + panic(badLengthMismatch) + } + w.Sample(batch) + for i := range weights { + weights[i] = 1 + } +} + +// LatinHypercuber is a wrapper around the LatinHypercube sampling generation +// method. +type LatinHypercuber struct { + Q distmv.Quantiler + Src *rand.Rand +} + +// Sample generates rows(batch) samples using the LatinHypercube generation +// procedure. +func (l LatinHypercuber) Sample(batch *mat64.Dense) { + LatinHypercube(batch, l.Q, l.Src) +} + +// LatinHypercube generates rows(batch) samples using Latin hypercube sampling +// from the given distribution. If src is not nil, it will be used to generate +// random numbers, otherwise rand.Float64 will be used. +// +// Latin hypercube sampling divides the cumulative distribution function into equally +// spaced bins and guarantees that one sample is generated per bin. Within each bin, +// the location is randomly sampled. The distmv.NewUnitUniform function can be used +// for easy sampling from the unit hypercube. +func LatinHypercube(batch *mat64.Dense, q distmv.Quantiler, src *rand.Rand) { + r, c := batch.Dims() + var f64 func() float64 + var perm func(int) []int + if src != nil { + f64 = src.Float64 + perm = src.Perm + } else { + f64 = rand.Float64 + perm = rand.Perm + } + r64 := float64(r) + for i := 0; i < c; i++ { + p := perm(r) + for j := 0; j < r; j++ { + var v float64 + v = f64() + v = v/r64 + float64(j)/r64 + batch.Set(p[j], i, v) + } + } + p := make([]float64, c) + for i := 0; i < r; i++ { + copy(p, batch.RawRowView(i)) + q.Quantile(batch.RawRowView(i), p) + } +} + +// Importancer is a wrapper around the Importance sampling generation method. +type Importancer struct { + Target distmv.LogProber + Proposal distmv.RandLogProber +} + +// SampleWeighted generates rows(batch) samples using the Importance sampling +// generation procedure. +func (l Importancer) SampleWeighted(batch *mat64.Dense, weights []float64) { + Importance(batch, weights, l.Target, l.Proposal) +} + +// Importance sampling generates rows(batch) samples from the proposal distribution, +// and stores the locations and importance sampling weights in place. +// +// Importance sampling is a variance reduction technique where samples are +// generated from a proposal distribution, q(x), instead of the target distribution +// p(x). This allows relatively unlikely samples in p(x) to be generated more frequently. +// +// The importance sampling weight at x is given by p(x)/q(x). To reduce variance, +// a good proposal distribution will bound this sampling weight. This implies the +// support of q(x) should be at least as broad as p(x), and q(x) should be "fatter tailed" +// than p(x). +// +// If weights is nil, the weights are not stored. The length of weights must equal +// the length of batch, otherwise Importance will panic. +func Importance(batch *mat64.Dense, weights []float64, target distmv.LogProber, proposal distmv.RandLogProber) { + r, _ := batch.Dims() + if r != len(weights) { + panic(badLengthMismatch) + } + for i := 0; i < r; i++ { + v := batch.RawRowView(i) + proposal.Rand(v) + weights[i] = math.Exp(target.LogProb(v) - proposal.LogProb(v)) + } +} + +// ErrRejection is returned when the constant in Rejection is not sufficiently high. +var ErrRejection = errors.New("rejection: acceptance ratio above 1") + +// Rejectioner is a wrapper around the Rejection sampling generation procedure. +// If the rejection sampling fails during the call to Sample, all samples will +// be set to math.NaN() and a call to Err will return a non-nil value. +type Rejectioner struct { + C float64 + Target distmv.LogProber + Proposal distmv.RandLogProber + Src *rand.Rand + + err error + proposed int +} + +// Err returns nil if the most recent call to sample was successful, and returns +// ErrRejection if it was not. +func (r *Rejectioner) Err() error { + return r.err +} + +// Proposed returns the number of samples proposed during the most recent call to +// Sample. +func (r *Rejectioner) Proposed() int { + return r.proposed +} + +// Sample generates rows(batch) using the Rejection sampling generation procedure. +// Rejection sampling may fail if the constant is insufficiently high, as described +// in the function comment for Rejection. If the generation fails, the samples +// are set to math.NaN(), and a call to Err will return a non-nil value. +func (r *Rejectioner) Sample(batch *mat64.Dense) { + r.err = nil + r.proposed = 0 + proposed, ok := Rejection(batch, r.Target, r.Proposal, r.C, r.Src) + if !ok { + r.err = ErrRejection + } + r.proposed = proposed +} + +// Rejection generates rows(batch) samples using the rejection sampling algorithm and +// stores them in place into samples. +// Sampling continues until batch is filled. Rejection returns the total number of proposed +// locations and a boolean indicating if the rejection sampling assumption is +// violated (see details below). If the returned boolean is false, all elements +// of samples are set to NaN. If src != nil, it will be used to generate random +// numbers, otherwise rand.Float64 will be used. +// +// Rejection sampling generates points from the target distribution by using +// the proposal distribution. At each step of the algorithm, the proposaed point +// is accepted with probability +// p = target(x) / (proposal(x) * c) +// where target(x) is the probability of the point according to the target distribution +// and proposal(x) is the probability according to the proposal distribution. +// The constant c must be chosen such that target(x) < proposal(x) * c for all x. +// The expected number of proposed samples is len(samples) * c. +// +// Target may return the true (log of) the probablity of the location, or it may return +// a value that is proportional to the probability (logprob + constant). This is +// useful for cases where the probability distribution is only known up to a normalization +// constant. +func Rejection(batch *mat64.Dense, target distmv.LogProber, proposal distmv.RandLogProber, c float64, src *rand.Rand) (nProposed int, ok bool) { + if c < 1 { + panic("rejection: acceptance constant must be greater than 1") + } + f64 := rand.Float64 + if src != nil { + f64 = src.Float64 + } + r, dim := batch.Dims() + v := make([]float64, dim) + var idx int + for { + nProposed++ + proposal.Rand(v) + qx := proposal.LogProb(v) + px := target.LogProb(v) + accept := math.Exp(px-qx) / c + if accept > 1 { + // Invalidate the whole result and return a failure. + for i := 0; i < r; i++ { + for j := 0; j < dim; j++ { + batch.Set(i, j, math.NaN()) + } + } + return nProposed, false + } + if accept > f64() { + batch.SetRow(idx, v) + idx++ + if idx == r { + break + } + } + } + return nProposed, true +} + +// IIDer is a wrapper around the IID sample generation method. +type IIDer struct { + Dist distmv.Rander +} + +// Sample generates a set of identically and independently distributed samples. +func (iid IIDer) Sample(batch *mat64.Dense) { + IID(batch, iid.Dist) +} + +// IID generates a set of independently and identically distributed samples from +// the input distribution. +func IID(batch *mat64.Dense, d distmv.Rander) { + r, _ := batch.Dims() + for i := 0; i < r; i++ { + d.Rand(batch.RawRowView(i)) + } +} diff --git a/stat/sampleuv/example_burnin_test.go b/stat/sampleuv/example_burnin_test.go new file mode 100644 index 00000000..db1d1c31 --- /dev/null +++ b/stat/sampleuv/example_burnin_test.go @@ -0,0 +1,39 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sampleuv + +import "gonum.org/v1/gonum/stat/distuv" + +type ProposalDist struct { + Sigma float64 +} + +func (p ProposalDist) ConditionalRand(y float64) float64 { + return distuv.Normal{Mu: y, Sigma: p.Sigma}.Rand() +} + +func (p ProposalDist) ConditionalLogProb(x, y float64) float64 { + return distuv.Normal{Mu: y, Sigma: p.Sigma}.LogProb(x) +} + +func ExampleMetropolisHastings_burnin() { + n := 1000 // The number of samples to generate. + burnin := 50 // Number of samples to ignore at the start. + var initial float64 + // target is the distribution from which we would like to sample. + target := distuv.Weibull{K: 5, Lambda: 0.5} + // proposal is the proposal distribution. Here, we are choosing + // a tight Gaussian distribution around the current location. In + // typical problems, if Sigma is too small, it takes a lot of samples + // to move around the distribution. If Sigma is too large, it can be hard + // to find acceptable samples. + proposal := ProposalDist{Sigma: 0.2} + + samples := make([]float64, n+burnin) + MetropolisHastings(samples, initial, target, proposal, nil) + + // Remove the initial samples through slicing. + samples = samples[burnin:] +} diff --git a/stat/sampleuv/example_rate_test.go b/stat/sampleuv/example_rate_test.go new file mode 100644 index 00000000..86917998 --- /dev/null +++ b/stat/sampleuv/example_rate_test.go @@ -0,0 +1,49 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sampleuv + +import "gonum.org/v1/gonum/stat/distuv" + +func max(a, b int) int { + if a < b { + return b + } + return a +} + +func ExampleMetropolisHastings_samplingRate() { + // See Burnin example for a description of these quantities. + n := 1000 + burnin := 300 + var initial float64 + target := distuv.Weibull{K: 5, Lambda: 0.5} + proposal := ProposalDist{Sigma: 0.2} + + // Successive samples are correlated with one another through the + // Markov Chain defined by the proposal distribution. To get less + // correlated samples, one may use a sampling rate, in which only + // one sample from every few is accepted from the chain. This can + // be accomplished through a for loop. + rate := 50 + + tmp := make([]float64, max(rate, burnin)) + + // First deal with burnin. + tmp = tmp[:burnin] + MetropolisHastings(tmp, initial, target, proposal, nil) + // The final sample in tmp in the final point in the chain. + // Use it as the new initial location. + initial = tmp[len(tmp)-1] + + // Now, generate samples by using one every rate samples. + tmp = tmp[:rate] + samples := make([]float64, n) + samples[0] = initial + for i := 1; i < len(samples); i++ { + MetropolisHastings(tmp, initial, target, proposal, nil) + initial = tmp[len(tmp)-1] + samples[i] = initial + } +} diff --git a/stat/sampleuv/sample.go b/stat/sampleuv/sample.go new file mode 100644 index 00000000..e6137b95 --- /dev/null +++ b/stat/sampleuv/sample.go @@ -0,0 +1,399 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sampleuv implements advanced sampling routines from explicit and implicit +// probability distributions. +// +// Each sampling routine is implemented as a stateless function with a +// complementary wrapper type. The wrapper types allow the sampling routines +// to implement interfaces. +package sampleuv + +import ( + "errors" + "math" + "math/rand" + + "gonum.org/v1/gonum/stat/distuv" +) + +var ( + badLengthMismatch = "sample: slice length mismatch" +) + +var ( + _ Sampler = LatinHypercuber{} + _ Sampler = MetropolisHastingser{} + _ Sampler = (*Rejectioner)(nil) + _ Sampler = IIDer{} + + _ WeightedSampler = SampleUniformWeighted{} + _ WeightedSampler = Importancer{} +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +// Sampler generates a batch of samples according to the rule specified by the +// implementing type. The number of samples generated is equal to len(batch), +// and the samples are stored in-place into the input. +type Sampler interface { + Sample(batch []float64) +} + +// WeightedSampler generates a batch of samples and their relative weights +// according to the rule specified by the implementing type. The number of samples +// generated is equal to len(batch), and the samples and weights +// are stored in-place into the inputs. The length of weights must equal +// len(batch), otherwise SampleWeighted will panic. +type WeightedSampler interface { + SampleWeighted(batch, weights []float64) +} + +// SampleUniformWeighted wraps a Sampler type to create a WeightedSampler where all +// weights are equal. +type SampleUniformWeighted struct { + Sampler +} + +// SampleWeighted generates len(batch) samples from the embedded Sampler type +// and sets all of the weights equal to 1. If len(batch) and len(weights) +// are not equal, SampleWeighted will panic. +func (w SampleUniformWeighted) SampleWeighted(batch, weights []float64) { + if len(batch) != len(weights) { + panic(badLengthMismatch) + } + w.Sample(batch) + for i := range weights { + weights[i] = 1 + } +} + +// LatinHypercuber is a wrapper around the LatinHypercube sampling generation +// method. +type LatinHypercuber struct { + Q distuv.Quantiler + Src *rand.Rand +} + +// Sample generates len(batch) samples using the LatinHypercube generation +// procedure. +func (l LatinHypercuber) Sample(batch []float64) { + LatinHypercube(batch, l.Q, l.Src) +} + +// LatinHypercube generates len(batch) samples using Latin hypercube sampling +// from the given distribution. If src != nil, it will be used to generate +// random numbers, otherwise rand.Float64 will be used. +// +// Latin hypercube sampling divides the cumulative distribution function into equally +// spaced bins and guarantees that one sample is generated per bin. Within each bin, +// the location is randomly sampled. The distuv.UnitUniform variable can be used +// for easy generation from the unit interval. +func LatinHypercube(batch []float64, q distuv.Quantiler, src *rand.Rand) { + n := len(batch) + var perm []int + var f64 func() float64 + if src != nil { + f64 = src.Float64 + perm = src.Perm(n) + } else { + f64 = rand.Float64 + perm = rand.Perm(n) + } + for i := range batch { + v := f64()/float64(n) + float64(i)/float64(n) + batch[perm[i]] = q.Quantile(v) + } +} + +// Importancer is a wrapper around the Importance sampling generation method. +type Importancer struct { + Target distuv.LogProber + Proposal distuv.RandLogProber +} + +// Sample generates len(batch) samples using the Importance sampling generation +// procedure. +func (l Importancer) SampleWeighted(batch, weights []float64) { + Importance(batch, weights, l.Target, l.Proposal) +} + +// Importance sampling generates len(batch) samples from the proposal distribution, +// and stores the locations and importance sampling weights in place. +// +// Importance sampling is a variance reduction technique where samples are +// generated from a proposal distribution, q(x), instead of the target distribution +// p(x). This allows relatively unlikely samples in p(x) to be generated more frequently. +// +// The importance sampling weight at x is given by p(x)/q(x). To reduce variance, +// a good proposal distribution will bound this sampling weight. This implies the +// support of q(x) should be at least as broad as p(x), and q(x) should be "fatter tailed" +// than p(x). +// +// If weights is nil, the weights are not stored. The length of weights must equal +// the length of batch, otherwise Importance will panic. +func Importance(batch, weights []float64, target distuv.LogProber, proposal distuv.RandLogProber) { + if len(batch) != len(weights) { + panic(badLengthMismatch) + } + for i := range batch { + v := proposal.Rand() + batch[i] = v + weights[i] = math.Exp(target.LogProb(v) - proposal.LogProb(v)) + } +} + +// ErrRejection is returned when the constant in Rejection is not sufficiently high. +var ErrRejection = errors.New("rejection: acceptance ratio above 1") + +// Rejectioner is a wrapper around the Rejection sampling generation procedure. +// If the rejection sampling fails during the call to Sample, all samples will +// be set to math.NaN() and a call to Err will return a non-nil value. +type Rejectioner struct { + C float64 + Target distuv.LogProber + Proposal distuv.RandLogProber + Src *rand.Rand + + err error + proposed int +} + +// Err returns nil if the most recent call to sample was successful, and returns +// ErrRejection if it was not. +func (r *Rejectioner) Err() error { + return r.err +} + +// Proposed returns the number of samples proposed during the most recent call to +// Sample. +func (r *Rejectioner) Proposed() int { + return r.proposed +} + +// Sample generates len(batch) using the Rejection sampling generation procedure. +// Rejection sampling may fail if the constant is insufficiently high, as described +// in the function comment for Rejection. If the generation fails, the samples +// are set to math.NaN(), and a call to Err will return a non-nil value. +func (r *Rejectioner) Sample(batch []float64) { + r.err = nil + r.proposed = 0 + proposed, ok := Rejection(batch, r.Target, r.Proposal, r.C, r.Src) + if !ok { + r.err = ErrRejection + } + r.proposed = proposed +} + +// Rejection generates len(batch) samples using the rejection sampling algorithm +// and stores them in place into samples. Sampling continues until batch is +// filled. Rejection returns the total number of proposed locations and a boolean +// indicating if the rejection sampling assumption is violated (see details +// below). If the returned boolean is false, all elements of samples are set to +// NaN. If src is not nil, it will be used to generate random numbers, otherwise +// rand.Float64 will be used. +// +// Rejection sampling generates points from the target distribution by using +// the proposal distribution. At each step of the algorithm, the proposed point +// is accepted with probability +// p = target(x) / (proposal(x) * c) +// where target(x) is the probability of the point according to the target distribution +// and proposal(x) is the probability according to the proposal distribution. +// The constant c must be chosen such that target(x) < proposal(x) * c for all x. +// The expected number of proposed samples is len(samples) * c. +// +// Target may return the true (log of) the probablity of the location, or it may return +// a value that is proportional to the probability (logprob + constant). This is +// useful for cases where the probability distribution is only known up to a normalization +// constant. +func Rejection(batch []float64, target distuv.LogProber, proposal distuv.RandLogProber, c float64, src *rand.Rand) (nProposed int, ok bool) { + if c < 1 { + panic("rejection: acceptance constant must be greater than 1") + } + f64 := rand.Float64 + if src != nil { + f64 = src.Float64 + } + var idx int + for { + nProposed++ + v := proposal.Rand() + qx := proposal.LogProb(v) + px := target.LogProb(v) + accept := math.Exp(px-qx) / c + if accept > 1 { + // Invalidate the whole result and return a failure. + for i := range batch { + batch[i] = math.NaN() + } + return nProposed, false + } + if accept > f64() { + batch[idx] = v + idx++ + if idx == len(batch) { + break + } + } + } + return nProposed, true +} + +// MHProposal defines a proposal distribution for Metropolis Hastings. +type MHProposal interface { + // ConditionalDist returns the probability of the first argument conditioned on + // being at the second argument + // p(x|y) + ConditionalLogProb(x, y float64) (prob float64) + + // ConditionalRand generates a new random location conditioned being at the + // location y. + ConditionalRand(y float64) (x float64) +} + +// MetropolisHastingser is a wrapper around the MetropolisHastings sampling type. +// +// BurnIn sets the number of samples to discard before keeping the first sample. +// A properly set BurnIn rate will decorrelate the sampling chain from the initial +// location. The proper BurnIn value will depend on the mixing time of the +// Markov chain defined by the target and proposal distributions. +// +// Rate sets the number of samples to discard in between each kept sample. A +// higher rate will better approximate independently and identically distributed +// samples, while a lower rate will keep more information (at the cost of +// higher correlation between samples). If Rate is 0 it is defaulted to 1. +// +// The initial value is NOT changed during calls to Sample. +type MetropolisHastingser struct { + Initial float64 + Target distuv.LogProber + Proposal MHProposal + Src *rand.Rand + + BurnIn int + Rate int +} + +// Sample generates len(batch) samples using the Metropolis Hastings sample +// generation method. The initial location is NOT updated during the call to Sample. +func (m MetropolisHastingser) Sample(batch []float64) { + burnIn := m.BurnIn + rate := m.Rate + if rate == 0 { + rate = 1 + } + + // Use the optimal size for the temporary memory to allow the fewest calls + // to MetropolisHastings. The case where tmp shadows samples must be + // aligned with the logic after burn-in so that tmp does not shadow samples + // during the rate portion. + tmp := batch + if rate > len(batch) { + tmp = make([]float64, rate) + } + + // Perform burn-in. + remaining := burnIn + initial := m.Initial + for remaining != 0 { + newSamp := min(len(tmp), remaining) + MetropolisHastings(tmp[newSamp:], initial, m.Target, m.Proposal, m.Src) + initial = tmp[newSamp-1] + remaining -= newSamp + } + + if rate == 1 { + MetropolisHastings(batch, initial, m.Target, m.Proposal, m.Src) + return + } + + if len(tmp) <= len(batch) { + tmp = make([]float64, rate) + } + + // Take a single sample from the chain + MetropolisHastings(batch[0:1], initial, m.Target, m.Proposal, m.Src) + initial = batch[0] + + // For all of the other samples, first generate Rate samples and then actually + // accept the last one. + for i := 1; i < len(batch); i++ { + MetropolisHastings(tmp, initial, m.Target, m.Proposal, m.Src) + v := tmp[rate-1] + batch[i] = v + initial = v + } +} + +// MetropolisHastings generates len(batch) samples using the Metropolis Hastings +// algorithm (http://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithm), +// with the given target and proposal distributions, starting at the intial location +// and storing the results in-place into samples. If src != nil, it will be used to generate random +// numbers, otherwise rand.Float64 will be used. +// +// Metropolis-Hastings is a Markov-chain Monte Carlo algorithm that generates +// samples according to the distribution specified by target by using the Markov +// chain implicitly defined by the proposal distribution. At each +// iteration, a proposal point is generated randomly from the current location. +// This proposal point is accepted with probability +// p = min(1, (target(new) * proposal(current|new)) / (target(current) * proposal(new|current))) +// If the new location is accepted, it is stored into batch and becomes the +// new current location. If it is rejected, the current location remains and +// is stored into samples. Thus, a location is stored into batch at every iteration. +// +// The samples in Metropolis Hastings are correlated with one another through the +// Markov chain. As a result, the initial value can have a significant influence +// on the early samples, and so, typically, the first samples generated by the chain +// are ignored. This is known as "burn-in", and can be accomplished with slicing. +// The best choice for burn-in length will depend on the sampling and target +// distributions. +// +// Many choose to have a sampling "rate" where a number of samples +// are ignored in between each kept sample. This helps decorrelate +// the samples from one another, but also reduces the number of available samples. +// A sampling rate can be implemented with successive calls to MetropolisHastings. +func MetropolisHastings(batch []float64, initial float64, target distuv.LogProber, proposal MHProposal, src *rand.Rand) { + f64 := rand.Float64 + if src != nil { + f64 = src.Float64 + } + current := initial + currentLogProb := target.LogProb(initial) + for i := range batch { + proposed := proposal.ConditionalRand(current) + proposedLogProb := target.LogProb(proposed) + probTo := proposal.ConditionalLogProb(proposed, current) + probBack := proposal.ConditionalLogProb(current, proposed) + + accept := math.Exp(proposedLogProb + probBack - probTo - currentLogProb) + if accept > f64() { + current = proposed + currentLogProb = proposedLogProb + } + batch[i] = current + } +} + +// IIDer is a wrapper around the IID sample generation method. +type IIDer struct { + Dist distuv.Rander +} + +// Sample generates a set of identically and independently distributed samples. +func (iid IIDer) Sample(batch []float64) { + IID(batch, iid.Dist) +} + +// IID generates a set of independently and identically distributed samples from +// the input distribution. +func IID(batch []float64, d distuv.Rander) { + for i := range batch { + batch[i] = d.Rand() + } +} diff --git a/stat/sampleuv/sample_test.go b/stat/sampleuv/sample_test.go new file mode 100644 index 00000000..014c558d --- /dev/null +++ b/stat/sampleuv/sample_test.go @@ -0,0 +1,99 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sampleuv + +import ( + "math" + "sort" + "testing" + + "gonum.org/v1/gonum/stat" + "gonum.org/v1/gonum/stat/distuv" +) + +type lhDist interface { + Quantile(float64) float64 + CDF(float64) float64 +} + +func TestLatinHypercube(t *testing.T) { + for _, nSamples := range []int{1, 2, 5, 10, 20} { + samples := make([]float64, nSamples) + for _, dist := range []lhDist{ + distuv.Uniform{Min: 0, Max: 1}, + distuv.Uniform{Min: 0, Max: 10}, + distuv.Normal{Mu: 5, Sigma: 3}, + } { + LatinHypercube(samples, dist, nil) + sort.Float64s(samples) + for i, v := range samples { + p := dist.CDF(v) + if p < float64(i)/float64(nSamples) || p > float64(i+1)/float64(nSamples) { + t.Errorf("probability out of bounds") + } + } + } + } +} + +func TestImportance(t *testing.T) { + // Test by finding the expected value of a Normal. + trueMean := 3.0 + target := distuv.Normal{Mu: trueMean, Sigma: 2} + proposal := distuv.Normal{Mu: 0, Sigma: 5} + nSamples := 100000 + x := make([]float64, nSamples) + weights := make([]float64, nSamples) + Importance(x, weights, target, proposal) + ev := stat.Mean(x, weights) + if math.Abs(ev-trueMean) > 1e-2 { + t.Errorf("Mean mismatch: Want %v, got %v", trueMean, ev) + } +} + +func TestRejection(t *testing.T) { + // Test by finding the expected value of a Normal. + trueMean := 3.0 + target := distuv.Normal{Mu: trueMean, Sigma: 2} + proposal := distuv.Normal{Mu: 0, Sigma: 5} + + nSamples := 100000 + x := make([]float64, nSamples) + Rejection(x, target, proposal, 100, nil) + ev := stat.Mean(x, nil) + if math.Abs(ev-trueMean) > 1e-2 { + t.Errorf("Mean mismatch: Want %v, got %v", trueMean, ev) + } +} + +type condNorm struct { + Sigma float64 +} + +func (c condNorm) ConditionalRand(y float64) float64 { + return distuv.Normal{Mu: y, Sigma: c.Sigma}.Rand() +} + +func (c condNorm) ConditionalLogProb(x, y float64) float64 { + return distuv.Normal{Mu: y, Sigma: c.Sigma}.LogProb(x) +} + +func TestMetropolisHastings(t *testing.T) { + // Test by finding the expected value of a Normal. + trueMean := 3.0 + target := distuv.Normal{Mu: trueMean, Sigma: 2} + proposal := condNorm{Sigma: 5} + + burnin := 500 + nSamples := 100000 + burnin + x := make([]float64, nSamples) + MetropolisHastings(x, 100, target, proposal, nil) + // Remove burnin + x = x[burnin:] + ev := stat.Mean(x, nil) + if math.Abs(ev-trueMean) > 1e-2 { + t.Errorf("Mean mismatch: Want %v, got %v", trueMean, ev) + } +} diff --git a/stat/sampleuv/weighted.go b/stat/sampleuv/weighted.go new file mode 100644 index 00000000..9a96589c --- /dev/null +++ b/stat/sampleuv/weighted.go @@ -0,0 +1,137 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package sampleuv + +import ( + "math/rand" + + "gonum.org/v1/gonum/floats" +) + +// Weighted provides sampling without replacement from a collection of items with +// non-uniform probability. +type Weighted struct { + weights []float64 + // heap is a weight heap. + // + // It keeps a heap-organised sum of remaining + // index weights that are available to be taken + // from. + // + // Each element holds the sum of weights for + // the corresponding index, plus the sum of + // of its children's weights; the children + // of an element i can be found at positions + // 2*(i+1)-1 and 2*(i+1). The root of the + // weight heap is at element 0. + // + // See comments in container/heap for an + // explanation of the layout of a heap. + heap []float64 + src *rand.Rand +} + +// NewWeighted returns a Weighted for the weights w. If src is nil, rand.Rand is +// used as the random source. +// +// Note that sampling from weights with a high variance or overall low absolute +// value sum may result in problems with numerical stability. +func NewWeighted(w []float64, src *rand.Rand) Weighted { + s := Weighted{ + weights: make([]float64, len(w)), + heap: make([]float64, len(w)), + } + s.ReweightAll(w) + return s +} + +// Len returns the number of items held by the Weighted, including items +// already taken. +func (s Weighted) Len() int { return len(s.weights) } + +// Take returns an index from the Weighted with probability proportional +// to the weight of the item. The weight of the item is then set to zero. +// Take returns false if there are no items remaining. +func (s Weighted) Take() (idx int, ok bool) { + const small = 1e-12 + if floats.EqualWithinAbsOrRel(s.heap[0], 0, small, small) { + return -1, false + } + + var r float64 + if s.src == nil { + r = s.heap[0] * rand.Float64() + } else { + r = s.heap[0] * s.src.Float64() + } + i := 1 + last := -1 + left := len(s.weights) + for { + if r -= s.weights[i-1]; r <= 0 { + break // Fall within item i-1. + } + i <<= 1 // Move to left child. + if d := s.heap[i-1]; r > d { + r -= d + // If enough r to pass left child + // move to right child state will + // be caught at break above. + i++ + } + if i == last || left < 0 { + // No progression. + return -1, false + } + last = i + left-- + } + + w, idx := s.weights[i-1], i-1 + + s.weights[i-1] = 0 + for i > 0 { + s.heap[i-1] -= w + // The following condition is necessary to + // handle floating point error. If we see + // a heap value below zero, we know we need + // to rebuild it. + if s.heap[i-1] < 0 { + s.reset() + return idx, true + } + i >>= 1 + } + + return idx, true +} + +// Reweight sets the weight of item idx to w. +func (s Weighted) Reweight(idx int, w float64) { + w, s.weights[idx] = s.weights[idx]-w, w + idx++ + for idx > 0 { + s.heap[idx-1] -= w + idx >>= 1 + } +} + +// ReweightAll sets the weight of all items in the Weighted. ReweightAll +// panics if len(w) != s.Len. +func (s Weighted) ReweightAll(w []float64) { + if len(w) != s.Len() { + panic("floats: length of the slices do not match") + } + copy(s.weights, w) + s.reset() +} + +func (s Weighted) reset() { + copy(s.heap, s.weights) + for i := len(s.heap) - 1; i > 0; i-- { + // Sometimes 1-based counting makes sense. + s.heap[((i+1)>>1)-1] += s.heap[i] + } +} diff --git a/stat/sampleuv/weighted_test.go b/stat/sampleuv/weighted_test.go new file mode 100644 index 00000000..24ed9555 --- /dev/null +++ b/stat/sampleuv/weighted_test.go @@ -0,0 +1,267 @@ +// Copyright ©2015 The gonum Authors. All rights reserved. +// Use of this code is governed by a BSD-style +// license that can be found in the LICENSE file + +package sampleuv + +import ( + "flag" + "math/rand" + "reflect" + "testing" + "time" + + "gonum.org/v1/gonum/floats" +) + +var prob = flag.Bool("prob", false, "enables probabilistic testing of the random weighted sampler") + +const sigChi2 = 16.92 // p = 0.05 df = 9 + +var ( + newExp = func() []float64 { + return []float64{1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7, 1 << 8, 1 << 9} + } + exp = newExp() + + obt = []float64{973, 1937, 3898, 7897, 15769, 31284, 62176, 125408, 250295, 500363} +) + +func newTestWeighted() Weighted { + weights := make([]float64, len(obt)) + for i := range weights { + weights[i] = float64(int(1) << uint(i)) + } + return NewWeighted(weights, nil) +} + +func TestWeightedUnseeded(t *testing.T) { + rand.Seed(0) + + want := Weighted{ + weights: []float64{1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7, 1 << 8, 1 << 9}, + heap: []float64{ + exp[0] + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9] + exp[2] + exp[5] + exp[6], + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9], + exp[2] + exp[5] + exp[6], + exp[3] + exp[7] + exp[8], + exp[4] + exp[9], + exp[5], + exp[6], + exp[7], + exp[8], + exp[9], + }, + } + + ts := newTestWeighted() + if !reflect.DeepEqual(ts, want) { + t.Fatalf("unexpected new Weighted value:\ngot: %#v\nwant:%#v", ts, want) + } + + f := make([]float64, len(obt)) + for i := 0; i < 1e6; i++ { + item, ok := newTestWeighted().Take() + if !ok { + t.Fatal("Weighted unexpectedly empty") + } + f[item]++ + } + + exp := newExp() + fac := floats.Sum(f) / floats.Sum(exp) + for i := range f { + exp[i] *= fac + } + + if !reflect.DeepEqual(f, obt) { + t.Fatalf("unexpected selection:\ngot: %#v\nwant:%#v", f, obt) + } + + // Check that this is within statistical expectations - we know this is true for this set. + X := chi2(f, exp) + if X >= sigChi2 { + t.Errorf("H₀: d(Sample) = d(Expect), H₁: d(S) ≠ d(Expect). df = %d, p = 0.05, X² threshold = %.2f, X² = %f", len(f)-1, sigChi2, X) + } +} + +func TestWeightedTimeSeeded(t *testing.T) { + if !*prob { + t.Skip("probabilistic testing not requested") + } + t.Log("Note: This test is stochastic and is expected to fail with probability ≈ 0.05.") + + rand.Seed(time.Now().Unix()) + + f := make([]float64, len(obt)) + for i := 0; i < 1e6; i++ { + item, ok := newTestWeighted().Take() + if !ok { + t.Fatal("Weighted unexpectedly empty") + } + f[item]++ + } + + exp := newExp() + fac := floats.Sum(f) / floats.Sum(exp) + for i := range f { + exp[i] *= fac + } + + // Check that our obtained values are within statistical expectations for p = 0.05. + // This will not be true approximately 1 in 20 tests. + X := chi2(f, exp) + if X >= sigChi2 { + t.Errorf("H₀: d(Sample) = d(Expect), H₁: d(S) ≠ d(Expect). df = %d, p = 0.05, X² threshold = %.2f, X² = %f", len(f)-1, sigChi2, X) + } +} + +func TestWeightZero(t *testing.T) { + rand.Seed(0) + + want := Weighted{ + weights: []float64{1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 0, 1 << 7, 1 << 8, 1 << 9}, + heap: []float64{ + exp[0] + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9] + exp[2] + exp[5], + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9], + exp[2] + exp[5], + exp[3] + exp[7] + exp[8], + exp[4] + exp[9], + exp[5], + 0, + exp[7], + exp[8], + exp[9], + }, + } + + ts := newTestWeighted() + ts.Reweight(6, 0) + if !reflect.DeepEqual(ts, want) { + t.Fatalf("unexpected new Weighted value:\ngot: %#v\nwant:%#v", ts, want) + } + + f := make([]float64, len(obt)) + for i := 0; i < 1e6; i++ { + ts := newTestWeighted() + ts.Reweight(6, 0) + item, ok := ts.Take() + if !ok { + t.Fatal("Weighted unexpectedly empty") + } + f[item]++ + } + + exp := newExp() + fac := floats.Sum(f) / floats.Sum(exp) + for i := range f { + exp[i] *= fac + } + + if f[6] != 0 { + t.Errorf("unexpected selection rate for zero-weighted item: got: %v want:%v", f[6], 0) + } + if reflect.DeepEqual(f[:6], obt[:6]) { + t.Fatal("unexpected selection: too few elements chosen in range:\ngot: %v\nwant:%v", + f[:6], obt[:6]) + } + if reflect.DeepEqual(f[7:], obt[7:]) { + t.Fatal("unexpected selection: too few elements chosen in range:\ngot: %v\nwant:%v", + f[7:], obt[7:]) + } +} + +func TestWeightIncrease(t *testing.T) { + rand.Seed(0) + + want := Weighted{ + weights: []float64{1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 9 * 2, 1 << 7, 1 << 8, 1 << 9}, + heap: []float64{ + exp[0] + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9] + exp[2] + exp[5] + exp[9]*2, + exp[1] + exp[3] + exp[4] + exp[7] + exp[8] + exp[9], + exp[2] + exp[5] + exp[9]*2, + exp[3] + exp[7] + exp[8], + exp[4] + exp[9], + exp[5], + exp[9] * 2, + exp[7], + exp[8], + exp[9], + }, + } + + ts := newTestWeighted() + ts.Reweight(6, ts.weights[len(ts.weights)-1]*2) + if !reflect.DeepEqual(ts, want) { + t.Fatalf("unexpected new Weighted value:\ngot: %#v\nwant:%#v", ts, want) + } + + f := make([]float64, len(obt)) + for i := 0; i < 1e6; i++ { + ts := newTestWeighted() + ts.Reweight(6, ts.weights[len(ts.weights)-1]*2) + item, ok := ts.Take() + if !ok { + t.Fatal("Weighted unexpectedly empty") + } + f[item]++ + } + + exp := newExp() + fac := floats.Sum(f) / floats.Sum(exp) + for i := range f { + exp[i] *= fac + } + + if f[6] < f[9] { + t.Errorf("unexpected selection rate for re-weighted item: got: %v want:%v", f[6], f[9]) + } + if reflect.DeepEqual(f[:6], obt[:6]) { + t.Fatal("unexpected selection: too many elements chosen in range:\ngot: %v\nwant:%v", + f[:6], obt[:6]) + } + if reflect.DeepEqual(f[7:], obt[7:]) { + t.Fatal("unexpected selection: too many elements chosen in range:\ngot: %v\nwant:%v", + f[7:], obt[7:]) + } +} + +func chi2(ob, ex []float64) (sum float64) { + for i := range ob { + x := ob[i] - ex[i] + sum += (x * x) / ex[i] + } + + return sum +} + +func TestWeightedNoResample(t *testing.T) { + const ( + tries = 10 + n = 10e5 + ) + ts := NewWeighted(make([]float64, n), nil) + w := make([]float64, n) + for i := 0; i < tries; i++ { + for j := range w { + w[j] = rand.Float64() * n + } + ts.ReweightAll(w) + taken := make(map[int]struct{}) + var c int + for { + item, ok := ts.Take() + if !ok { + if c != n { + t.Errorf("unexpected number of items: got: %d want: %d", c, n) + } + break + } + c++ + if _, exists := taken[item]; exists { + t.Errorf("unexpected duplicate sample for item: %d", item) + } + taken[item] = struct{}{} + } + } +} diff --git a/stat/stat.go b/stat/stat.go new file mode 100644 index 00000000..e02778b0 --- /dev/null +++ b/stat/stat.go @@ -0,0 +1,1161 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package stat provides generalized statistical functions. +package stat + +import ( + "math" + "sort" + + "gonum.org/v1/gonum/floats" +) + +// CumulantKind specifies the behavior for calculating the empirical CDF or Quantile +type CumulantKind int + +const ( + // Constant values should match the R nomenclature. See + // https://en.wikipedia.org/wiki/Quantile#Estimating_the_quantiles_of_a_population + + // Empirical treats the distribution as the actual empirical distribution. + Empirical CumulantKind = 1 +) + +// bhattacharyyaCoeff computes the Bhattacharyya Coefficient for probability distributions given by: +// \sum_i \sqrt{p_i q_i} +// +// It is assumed that p and q have equal length. +func bhattacharyyaCoeff(p, q []float64) float64 { + var bc float64 + for i, a := range p { + bc += math.Sqrt(a * q[i]) + } + return bc +} + +// Bhattacharyya computes the distance between the probability distributions p and q given by: +// -\ln ( \sum_i \sqrt{p_i q_i} ) +// +// The lengths of p and q must be equal. It is assumed that p and q sum to 1. +func Bhattacharyya(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + bc := bhattacharyyaCoeff(p, q) + return -math.Log(bc) +} + +// CDF returns the empirical cumulative distribution function value of x, that is +// the fraction of the samples less than or equal to q. The +// exact behavior is determined by the CumulantKind. CDF is theoretically +// the inverse of the Quantile function, though it may not be the actual inverse +// for all values q and CumulantKinds. +// +// The x data must be sorted in increasing order. If weights is nil then all +// of the weights are 1. If weights is not nil, then len(x) must equal len(weights). +// +// CumulantKind behaviors: +// - Empirical: Returns the lowest fraction for which q is greater than or equal +// to that fraction of samples +func CDF(q float64, c CumulantKind, x, weights []float64) float64 { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + if floats.HasNaN(x) { + return math.NaN() + } + if !sort.Float64sAreSorted(x) { + panic("x data are not sorted") + } + + if q < x[0] { + return 0 + } + if q >= x[len(x)-1] { + return 1 + } + + var sumWeights float64 + if weights == nil { + sumWeights = float64(len(x)) + } else { + sumWeights = floats.Sum(weights) + } + + // Calculate the index + switch c { + case Empirical: + // Find the smallest value that is greater than that percent of the samples + var w float64 + for i, v := range x { + if v > q { + return w / sumWeights + } + if weights == nil { + w++ + } else { + w += weights[i] + } + } + panic("impossible") + default: + panic("stat: bad cumulant kind") + } +} + +// ChiSquare computes the chi-square distance between the observed frequences 'obs' and +// expected frequences 'exp' given by: +// \sum_i (obs_i-exp_i)^2 / exp_i +// +// The lengths of obs and exp must be equal. +func ChiSquare(obs, exp []float64) float64 { + if len(obs) != len(exp) { + panic("stat: slice length mismatch") + } + var result float64 + for i, a := range obs { + b := exp[i] + if a == 0 && b == 0 { + continue + } + result += (a - b) * (a - b) / b + } + return result +} + +// CircularMean returns the circular mean of the dataset. +// atan2(\sum_i w_i * sin(alpha_i), \sum_i w_i * cos(alpha_i)) +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func CircularMean(x, weights []float64) float64 { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + + var aX, aY float64 + if weights != nil { + for i, v := range x { + aX += weights[i] * math.Cos(v) + aY += weights[i] * math.Sin(v) + } + } else { + for _, v := range x { + aX += math.Cos(v) + aY += math.Sin(v) + } + } + + return math.Atan2(aY, aX) +} + +// Correlation returns the weighted correlation between the samples of x and y +// with the given means. +// sum_i {w_i (x_i - meanX) * (y_i - meanY)} / (stdX * stdY) +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func Correlation(x, y, weights []float64) float64 { + // This is a two-pass corrected implementation. It is an adaptation of the + // algorithm used in the MeanVariance function, which applies a correction + // to the typical two pass approach. + + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + xu := Mean(x, weights) + yu := Mean(y, weights) + var ( + sxx float64 + syy float64 + sxy float64 + xcompensation float64 + ycompensation float64 + ) + if weights == nil { + for i, xv := range x { + yv := y[i] + xd := xv - xu + yd := yv - yu + sxx += xd * xd + syy += yd * yd + sxy += xd * yd + xcompensation += xd + ycompensation += yd + } + // xcompensation and ycompensation are from Chan, et. al. + // referenced in the MeanVariance function. They are analogous + // to the second term in (1.7) in that paper. + sxx -= xcompensation * xcompensation / float64(len(x)) + syy -= ycompensation * ycompensation / float64(len(x)) + + return (sxy - xcompensation*ycompensation/float64(len(x))) / math.Sqrt(sxx*syy) + + } + + var sumWeights float64 + for i, xv := range x { + w := weights[i] + yv := y[i] + xd := xv - xu + wxd := w * xd + yd := yv - yu + wyd := w * yd + sxx += wxd * xd + syy += wyd * yd + sxy += wxd * yd + xcompensation += wxd + ycompensation += wyd + sumWeights += w + } + // xcompensation and ycompensation are from Chan, et. al. + // referenced in the MeanVariance function. They are analogous + // to the second term in (1.7) in that paper, except they use + // the sumWeights instead of the sample count. + sxx -= xcompensation * xcompensation / sumWeights + syy -= ycompensation * ycompensation / sumWeights + + return (sxy - xcompensation*ycompensation/sumWeights) / math.Sqrt(sxx*syy) +} + +// Covariance returns the weighted covariance between the samples of x and y. +// sum_i {w_i (x_i - meanX) * (y_i - meanY)} / (sum_j {w_j} - 1) +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func Covariance(x, y, weights []float64) float64 { + // This is a two-pass corrected implementation. It is an adaptation of the + // algorithm used in the MeanVariance function, which applies a correction + // to the typical two pass approach. + + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + xu := Mean(x, weights) + yu := Mean(y, weights) + var ( + ss float64 + xcompensation float64 + ycompensation float64 + ) + if weights == nil { + for i, xv := range x { + yv := y[i] + xd := xv - xu + yd := yv - yu + ss += xd * yd + xcompensation += xd + ycompensation += yd + } + // xcompensation and ycompensation are from Chan, et. al. + // referenced in the MeanVariance function. They are analogous + // to the second term in (1.7) in that paper. + return (ss - xcompensation*ycompensation/float64(len(x))) / float64(len(x)-1) + } + + var sumWeights float64 + + for i, xv := range x { + w := weights[i] + yv := y[i] + wxd := w * (xv - xu) + yd := (yv - yu) + ss += wxd * yd + xcompensation += wxd + ycompensation += w * yd + sumWeights += w + } + // xcompensation and ycompensation are from Chan, et. al. + // referenced in the MeanVariance function. They are analogous + // to the second term in (1.7) in that paper, except they use + // the sumWeights instead of the sample count. + return (ss - xcompensation*ycompensation/sumWeights) / (sumWeights - 1) +} + +// CrossEntropy computes the cross-entropy between the two distributions specified +// in p and q. +func CrossEntropy(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + var ce float64 + for i, v := range p { + if v != 0 { + ce -= v * math.Log(q[i]) + } + } + return ce +} + +// Entropy computes the Shannon entropy of a distribution or the distance between +// two distributions. The natural logarithm is used. +// - sum_i (p_i * log_e(p_i)) +func Entropy(p []float64) float64 { + var e float64 + for _, v := range p { + if v != 0 { // Entropy needs 0 * log(0) == 0 + e -= v * math.Log(v) + } + } + return e +} + +// ExKurtosis returns the population excess kurtosis of the sample. +// The kurtosis is defined by the 4th moment of the mean divided by the squared +// variance. The excess kurtosis subtracts 3.0 so that the excess kurtosis of +// the normal distribution is zero. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func ExKurtosis(x, weights []float64) float64 { + mean, std := MeanStdDev(x, weights) + if weights == nil { + var e float64 + for _, v := range x { + z := (v - mean) / std + e += z * z * z * z + } + mul, offset := kurtosisCorrection(float64(len(x))) + return e*mul - offset + } + + var ( + e float64 + sumWeights float64 + ) + for i, v := range x { + z := (v - mean) / std + e += weights[i] * z * z * z * z + sumWeights += weights[i] + } + mul, offset := kurtosisCorrection(sumWeights) + return e*mul - offset +} + +// n is the number of samples +// see https://en.wikipedia.org/wiki/Kurtosis +func kurtosisCorrection(n float64) (mul, offset float64) { + return ((n + 1) / (n - 1)) * (n / (n - 2)) * (1 / (n - 3)), 3 * ((n - 1) / (n - 2)) * ((n - 1) / (n - 3)) +} + +// GeometricMean returns the weighted geometric mean of the dataset +// \prod_i {x_i ^ w_i} +// This only applies with positive x and positive weights. If weights is nil +// then all of the weights are 1. If weights is not nil, then len(x) must equal +// len(weights). +func GeometricMean(x, weights []float64) float64 { + if weights == nil { + var s float64 + for _, v := range x { + s += math.Log(v) + } + s /= float64(len(x)) + return math.Exp(s) + } + if len(x) != len(weights) { + panic("stat: slice length mismatch") + } + var ( + s float64 + sumWeights float64 + ) + for i, v := range x { + s += weights[i] * math.Log(v) + sumWeights += weights[i] + } + s /= sumWeights + return math.Exp(s) +} + +// HarmonicMean returns the weighted harmonic mean of the dataset +// \sum_i {w_i} / ( sum_i {w_i / x_i} ) +// This only applies with positive x and positive weights. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func HarmonicMean(x, weights []float64) float64 { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + // TODO: Fix this to make it more efficient and avoid allocation + + // This can be numerically unstable (for example if x is very small) + // W = \sum_i {w_i} + // hm = exp(log(W) - log(\sum_i w_i / x_i)) + + logs := make([]float64, len(x)) + var W float64 + for i := range x { + if weights == nil { + logs[i] = -math.Log(x[i]) + W++ + continue + } + logs[i] = math.Log(weights[i]) - math.Log(x[i]) + W += weights[i] + } + + // Sum all of the logs + v := floats.LogSumExp(logs) // this computes log(\sum_i { w_i / x_i}) + return math.Exp(math.Log(W) - v) +} + +// Hellinger computes the distance between the probability distributions p and q given by: +// \sqrt{ 1 - \sum_i \sqrt{p_i q_i} } +// +// The lengths of p and q must be equal. It is assumed that p and q sum to 1. +func Hellinger(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + bc := bhattacharyyaCoeff(p, q) + return math.Sqrt(1 - bc) +} + +// Histogram sums up the weighted number of data points in each bin. +// The weight of data point x[i] will be placed into count[j] if +// dividers[j] <= x < dividers[j+1]. The "span" function in the floats package can assist +// with bin creation. +// +// The following conditions on the inputs apply: +// - The count variable must either be nil or have length of one less than dividers. +// - The values in dividers must be sorted (use the sort package). +// - The x values must be sorted. +// - If weights is nil then all of the weights are 1. +// - If weights is not nil, then len(x) must equal len(weights). +func Histogram(count, dividers, x, weights []float64) []float64 { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + if count == nil { + count = make([]float64, len(dividers)-1) + } + if len(dividers) < 2 { + panic("histogram: fewer than two dividers") + } + if len(count) != len(dividers)-1 { + panic("histogram: bin count mismatch") + } + if !sort.Float64sAreSorted(dividers) { + panic("histogram: dividers are not sorted") + } + if !sort.Float64sAreSorted(x) { + panic("histogram: x data are not sorted") + } + for i := range count { + count[i] = 0 + } + if len(x) == 0 { + return count + } + if x[0] < dividers[0] { + panic("histogram: minimum x value is less than lowest divider") + } + if x[len(x)-1] >= dividers[len(dividers)-1] { + panic("histogram: minimum x value is greater than highest divider") + } + + idx := 0 + comp := dividers[idx+1] + if weights == nil { + for _, v := range x { + if v < comp { + // Still in the current bucket + count[idx]++ + continue + } + // Find the next divider where v is less than the divider + for j := idx + 1; j < len(dividers); j++ { + if v < dividers[j+1] { + idx = j + comp = dividers[j+1] + break + } + } + count[idx]++ + } + return count + } + + for i, v := range x { + if v < comp { + // Still in the current bucket + count[idx] += weights[i] + continue + } + // Need to find the next divider where v is less than the divider. + for j := idx + 1; j < len(count); j++ { + if v < dividers[j+1] { + idx = j + comp = dividers[j+1] + break + } + } + count[idx] += weights[i] + } + return count +} + +// JensenShannon computes the JensenShannon divergence between the distributions +// p and q. The Jensen-Shannon divergence is defined as +// m = 0.5 * (p + q) +// JS(p, q) = 0.5 ( KL(p, m) + KL(q, m) ) +// Unlike Kullback-Liebler, the Jensen-Shannon distance is symmetric. The value +// is between 0 and ln(2). +func JensenShannon(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + var js float64 + for i, v := range p { + qi := q[i] + m := 0.5 * (v + qi) + if v != 0 { + // add kl from p to m + js += 0.5 * v * (math.Log(v) - math.Log(m)) + } + if qi != 0 { + // add kl from q to m + js += 0.5 * qi * (math.Log(qi) - math.Log(m)) + } + } + return js +} + +// KolmogorovSmirnov computes the largest distance between two empirical CDFs. +// Each dataset x and y consists of sample locations and counts, xWeights and +// yWeights, respectively. +// +// x and y may have different lengths, though len(x) must equal len(xWeights), and +// len(y) must equal len(yWeights). Both x and y must be sorted. +// +// Special cases are: +// = 0 if len(x) == len(y) == 0 +// = 1 if len(x) == 0, len(y) != 0 or len(x) != 0 and len(y) == 0 +func KolmogorovSmirnov(x, xWeights, y, yWeights []float64) float64 { + if xWeights != nil && len(x) != len(xWeights) { + panic("stat: slice length mismatch") + } + if yWeights != nil && len(y) != len(yWeights) { + panic("stat: slice length mismatch") + } + if len(x) == 0 || len(y) == 0 { + if len(x) == 0 && len(y) == 0 { + return 0 + } + return 1 + } + + if floats.HasNaN(x) { + return math.NaN() + } + if floats.HasNaN(y) { + return math.NaN() + } + + if !sort.Float64sAreSorted(x) { + panic("x data are not sorted") + } + if !sort.Float64sAreSorted(y) { + panic("y data are not sorted") + } + + xWeightsNil := xWeights == nil + yWeightsNil := yWeights == nil + + var ( + maxDist float64 + xSum, ySum float64 + xCdf, yCdf float64 + xIdx, yIdx int + ) + + if xWeightsNil { + xSum = float64(len(x)) + } else { + xSum = floats.Sum(xWeights) + } + + if yWeightsNil { + ySum = float64(len(y)) + } else { + ySum = floats.Sum(yWeights) + } + + xVal := x[0] + yVal := y[0] + + // Algorithm description: + // The goal is to find the maximum difference in the empirical CDFs for the + // two datasets. The CDFs are piecewise-constant, and thus the distance + // between the CDFs will only change at the values themselves. + // + // To find the maximum distance, step through the data in ascending order + // of value between the two datasets. At each step, compute the empirical CDF + // and compare the local distance with the maximum distance. + // Due to some corner cases, equal data entries must be tallied simultaneously. + for { + switch { + case xVal < yVal: + xVal, xCdf, xIdx = updateKS(xIdx, xCdf, xSum, x, xWeights, xWeightsNil) + case yVal < xVal: + yVal, yCdf, yIdx = updateKS(yIdx, yCdf, ySum, y, yWeights, yWeightsNil) + case xVal == yVal: + newX := x[xIdx] + newY := y[yIdx] + if newX < newY { + xVal, xCdf, xIdx = updateKS(xIdx, xCdf, xSum, x, xWeights, xWeightsNil) + } else if newY < newX { + yVal, yCdf, yIdx = updateKS(yIdx, yCdf, ySum, y, yWeights, yWeightsNil) + } else { + // Update them both, they'll be equal next time and the right + // thing will happen + xVal, xCdf, xIdx = updateKS(xIdx, xCdf, xSum, x, xWeights, xWeightsNil) + yVal, yCdf, yIdx = updateKS(yIdx, yCdf, ySum, y, yWeights, yWeightsNil) + } + default: + panic("unreachable") + } + + dist := math.Abs(xCdf - yCdf) + if dist > maxDist { + maxDist = dist + } + + // Both xCdf and yCdf will equal 1 at the end, so if we have reached the + // end of either sample list, the distance is as large as it can be. + if xIdx == len(x) || yIdx == len(y) { + return maxDist + } + } +} + +// updateKS gets the next data point from one of the set. In doing so, it combines +// the weight of all the data points of equal value. Upon return, val is the new +// value of the data set, newCdf is the total combined CDF up until this point, +// and newIdx is the index of the next location in that sample to examine. +func updateKS(idx int, cdf, sum float64, values, weights []float64, isNil bool) (val, newCdf float64, newIdx int) { + // Sum up all the weights of consecutive values that are equal + if isNil { + newCdf = cdf + 1/sum + } else { + newCdf = cdf + weights[idx]/sum + } + newIdx = idx + 1 + for { + if newIdx == len(values) { + return values[newIdx-1], newCdf, newIdx + } + if values[newIdx-1] != values[newIdx] { + return values[newIdx], newCdf, newIdx + } + if isNil { + newCdf += 1 / sum + } else { + newCdf += weights[newIdx] / sum + } + newIdx++ + } +} + +// KullbackLeibler computes the Kullback-Leibler distance between the +// distributions p and q. The natural logarithm is used. +// sum_i(p_i * log(p_i / q_i)) +// Note that the Kullback-Leibler distance is not symmetric; +// KullbackLeibler(p,q) != KullbackLeibler(q,p) +func KullbackLeibler(p, q []float64) float64 { + if len(p) != len(q) { + panic("stat: slice length mismatch") + } + var kl float64 + for i, v := range p { + if v != 0 { // Entropy needs 0 * log(0) == 0 + kl += v * (math.Log(v) - math.Log(q[i])) + } + } + return kl +} + +// LinearRegression computes the best-fit line +// y = alpha + beta*x +// to the data in x and y with the given weights. If origin is true, the +// regression is forced to pass through the origin. +// +// Specifically, LinearRegression computes the values of alpha and +// beta such that the total residual +// \sum_i w[i]*(y[i] - alpha - beta*x[i])^2 +// is minimized. If origin is true, then alpha is forced to be zero. +// +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func LinearRegression(x, y, weights []float64, origin bool) (alpha, beta float64) { + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + if weights != nil && len(weights) != len(x) { + panic("stat: slice length mismatch") + } + + w := 1.0 + if origin { + var x2Sum, xySum float64 + for i, xi := range x { + if weights != nil { + w = weights[i] + } + yi := y[i] + xySum += w * xi * yi + x2Sum += w * xi * xi + } + beta = xySum / x2Sum + + return 0, beta + } + + beta = Covariance(x, y, weights) / Variance(x, weights) + alpha = Mean(y, weights) - beta*Mean(x, weights) + return alpha, beta +} + +// RSquared returns the coefficient of determination defined as +// R^2 = 1 - \sum_i w[i]*(y[i] - alpha - beta*x[i])^2 / \sum_i w[i]*(y[i] - mean(y))^2 +// for the line +// y = alpha + beta*x +// and the data in x and y with the given weights. +// +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func RSquared(x, y, weights []float64, alpha, beta float64) float64 { + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + if weights != nil && len(weights) != len(x) { + panic("stat: slice length mismatch") + } + + w := 1.0 + yMean := Mean(y, weights) + var res, tot, d float64 + for i, xi := range x { + if weights != nil { + w = weights[i] + } + yi := y[i] + fi := alpha + beta*xi + d = yi - fi + res += w * d * d + d = yi - yMean + tot += w * d * d + } + return 1 - res/tot +} + +// RSquaredFrom returns the coefficient of determination defined as +// R^2 = 1 - \sum_i w[i]*(estimate[i] - value[i])^2 / \sum_i w[i]*(value[i] - mean(values))^2 +// and the data in estimates and values with the given weights. +// +// The lengths of estimates and values must be equal. If weights is nil then +// all of the weights are 1. If weights is not nil, then len(values) must +// equal len(weights). +func RSquaredFrom(estimates, values, weights []float64) float64 { + if len(estimates) != len(values) { + panic("stat: slice length mismatch") + } + if weights != nil && len(weights) != len(values) { + panic("stat: slice length mismatch") + } + + w := 1.0 + mean := Mean(values, weights) + var res, tot, d float64 + for i, val := range values { + if weights != nil { + w = weights[i] + } + d = val - estimates[i] + res += w * d * d + d = val - mean + tot += w * d * d + } + return 1 - res/tot +} + +// RNoughtSquared returns the coefficient of determination defined as +// R₀^2 = \sum_i w[i]*(beta*x[i])^2 / \sum_i w[i]*y[i]^2 +// for the line +// y = beta*x +// and the data in x and y with the given weights. RNoughtSquared should +// only be used for best-fit lines regressed through the origin. +// +// The lengths of x and y must be equal. If weights is nil then all of the +// weights are 1. If weights is not nil, then len(x) must equal len(weights). +func RNoughtSquared(x, y, weights []float64, beta float64) float64 { + if len(x) != len(y) { + panic("stat: slice length mismatch") + } + if weights != nil && len(weights) != len(x) { + panic("stat: slice length mismatch") + } + + w := 1.0 + var ssr, tot float64 + for i, xi := range x { + if weights != nil { + w = weights[i] + } + fi := beta * xi + ssr += w * fi * fi + yi := y[i] + tot += w * yi * yi + } + return ssr / tot +} + +// Mean computes the weighted mean of the data set. +// sum_i {w_i * x_i} / sum_i {w_i} +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func Mean(x, weights []float64) float64 { + if weights == nil { + return floats.Sum(x) / float64(len(x)) + } + if len(x) != len(weights) { + panic("stat: slice length mismatch") + } + var ( + sumValues float64 + sumWeights float64 + ) + for i, w := range weights { + sumValues += w * x[i] + sumWeights += w + } + return sumValues / sumWeights +} + +// Mode returns the most common value in the dataset specified by x and the +// given weights. Strict float64 equality is used when comparing values, so users +// should take caution. If several values are the mode, any of them may be returned. +func Mode(x, weights []float64) (val float64, count float64) { + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + if len(x) == 0 { + return 0, 0 + } + m := make(map[float64]float64) + if weights == nil { + for _, v := range x { + m[v]++ + } + } else { + for i, v := range x { + m[v] += weights[i] + } + } + var ( + maxCount float64 + max float64 + ) + for val, count := range m { + if count > maxCount { + maxCount = count + max = val + } + } + return max, maxCount +} + +// Moment computes the weighted n^th moment of the samples, +// E[(x - μ)^N] +// No degrees of freedom correction is done. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func Moment(moment float64, x, weights []float64) float64 { + mean := Mean(x, weights) + if weights == nil { + var m float64 + for _, v := range x { + m += math.Pow(v-mean, moment) + } + return m / float64(len(x)) + } + var ( + m float64 + sumWeights float64 + ) + for i, v := range x { + m += weights[i] * math.Pow(v-mean, moment) + sumWeights += weights[i] + } + return m / sumWeights +} + +// MomentAbout computes the weighted n^th weighted moment of the samples about +// the given mean \mu, +// E[(x - μ)^N] +// No degrees of freedom correction is done. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func MomentAbout(moment float64, x []float64, mean float64, weights []float64) float64 { + if weights == nil { + var m float64 + for _, v := range x { + m += math.Pow(v-mean, moment) + } + m /= float64(len(x)) + return m + } + if len(weights) != len(x) { + panic("stat: slice length mismatch") + } + var ( + m float64 + sumWeights float64 + ) + for i, v := range x { + m += weights[i] * math.Pow(v-mean, moment) + sumWeights += weights[i] + } + return m / sumWeights +} + +// Quantile returns the sample of x such that x is greater than or +// equal to the fraction p of samples. The exact behavior is determined by the +// CumulantKind, and p should be a number between 0 and 1. Quantile is theoretically +// the inverse of the CDF function, though it may not be the actual inverse +// for all values p and CumulantKinds. +// +// The x data must be sorted in increasing order. If weights is nil then all +// of the weights are 1. If weights is not nil, then len(x) must equal len(weights). +// +// CumulantKind behaviors: +// - Empirical: Returns the lowest value q for which q is greater than or equal +// to the fraction p of samples +func Quantile(p float64, c CumulantKind, x, weights []float64) float64 { + if !(p >= 0 && p <= 1) { + panic("stat: percentile out of bounds") + } + + if weights != nil && len(x) != len(weights) { + panic("stat: slice length mismatch") + } + if floats.HasNaN(x) { + return math.NaN() // This is needed because the algorithm breaks otherwise + } + if !sort.Float64sAreSorted(x) { + panic("x data are not sorted") + } + + var sumWeights float64 + if weights == nil { + sumWeights = float64(len(x)) + } else { + sumWeights = floats.Sum(weights) + } + switch c { + case Empirical: + var cumsum float64 + fidx := p * sumWeights + for i := range x { + if weights == nil { + cumsum++ + } else { + cumsum += weights[i] + } + if cumsum >= fidx { + return x[i] + } + } + panic("impossible") + default: + panic("stat: bad cumulant kind") + } +} + +// Skew computes the skewness of the sample data. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func Skew(x, weights []float64) float64 { + + mean, std := MeanStdDev(x, weights) + if weights == nil { + var s float64 + for _, v := range x { + z := (v - mean) / std + s += z * z * z + } + return s * skewCorrection(float64(len(x))) + } + var ( + s float64 + sumWeights float64 + ) + for i, v := range x { + z := (v - mean) / std + s += weights[i] * z * z * z + sumWeights += weights[i] + } + return s * skewCorrection(sumWeights) +} + +// From: http://www.amstat.org/publications/jse/v19n2/doane.pdf page 7 +func skewCorrection(n float64) float64 { + return (n / (n - 1)) * (1 / (n - 2)) +} + +// SortWeighted rearranges the data in x along with their corresponding +// weights so that the x data are sorted. The data is sorted in place. +// Weights may be nil, but if weights is non-nil then it must have the same +// length as x. +func SortWeighted(x, weights []float64) { + if weights == nil { + sort.Float64s(x) + return + } + if len(x) != len(weights) { + panic("stat: slice length mismatch") + } + sort.Sort(weightSorter{ + x: x, + w: weights, + }) +} + +type weightSorter struct { + x []float64 + w []float64 +} + +func (w weightSorter) Len() int { return len(w.x) } +func (w weightSorter) Less(i, j int) bool { return w.x[i] < w.x[j] } +func (w weightSorter) Swap(i, j int) { + w.x[i], w.x[j] = w.x[j], w.x[i] + w.w[i], w.w[j] = w.w[j], w.w[i] +} + +// SortWeightedLabeled rearranges the data in x along with their +// corresponding weights and boolean labels so that the x data are sorted. +// The data is sorted in place. Weights and labels may be nil, if either +// is non-nil it must have the same length as x. +func SortWeightedLabeled(x []float64, labels []bool, weights []float64) { + if labels == nil { + SortWeighted(x, weights) + return + } + if weights == nil { + if len(x) != len(labels) { + panic("stat: slice length mismatch") + } + sort.Sort(labelSorter{ + x: x, + l: labels, + }) + return + } + if len(x) != len(labels) || len(x) != len(weights) { + panic("stat: slice length mismatch") + } + sort.Sort(weightLabelSorter{ + x: x, + l: labels, + w: weights, + }) +} + +type labelSorter struct { + x []float64 + l []bool +} + +func (a labelSorter) Len() int { return len(a.x) } +func (a labelSorter) Less(i, j int) bool { return a.x[i] < a.x[j] } +func (a labelSorter) Swap(i, j int) { + a.x[i], a.x[j] = a.x[j], a.x[i] + a.l[i], a.l[j] = a.l[j], a.l[i] +} + +type weightLabelSorter struct { + x []float64 + l []bool + w []float64 +} + +func (a weightLabelSorter) Len() int { return len(a.x) } +func (a weightLabelSorter) Less(i, j int) bool { return a.x[i] < a.x[j] } +func (a weightLabelSorter) Swap(i, j int) { + a.x[i], a.x[j] = a.x[j], a.x[i] + a.l[i], a.l[j] = a.l[j], a.l[i] + a.w[i], a.w[j] = a.w[j], a.w[i] +} + +// StdDev returns the sample standard deviation. +func StdDev(x, weights []float64) float64 { + _, std := MeanStdDev(x, weights) + return std +} + +// MeanStdDev returns the sample mean and standard deviation +func MeanStdDev(x, weights []float64) (mean, std float64) { + mean, variance := MeanVariance(x, weights) + return mean, math.Sqrt(variance) +} + +// StdErr returns the standard error in the mean with the given values. +func StdErr(std, sampleSize float64) float64 { + return std / math.Sqrt(sampleSize) +} + +// StdScore returns the standard score (a.k.a. z-score, z-value) for the value x +// with the givem mean and standard deviation, i.e. +// (x - mean) / std +func StdScore(x, mean, std float64) float64 { + return (x - mean) / std +} + +// Variance computes the weighted sample variance: +// \sum_i w_i (x_i - mean)^2 / (sum_i w_i - 1) +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func Variance(x, weights []float64) float64 { + _, variance := MeanVariance(x, weights) + return variance +} + +// MeanVariance computes the sample mean and variance, where the mean and variance are +// \sum_i w_i * x_i / (sum_i w_i) +// \sum_i w_i (x_i - mean)^2 / (sum_i w_i - 1) +// respectively. +// If weights is nil then all of the weights are 1. If weights is not nil, then +// len(x) must equal len(weights). +func MeanVariance(x, weights []float64) (mean, variance float64) { + + // This uses the corrected two-pass algorithm (1.7), from "Algorithms for computing + // the sample variance: Analysis and recommendations" by Chan, Tony F., Gene H. Golub, + // and Randall J. LeVeque. + + // note that this will panic if the slice lengths do not match + mean = Mean(x, weights) + var ( + ss float64 + compensation float64 + ) + if weights == nil { + for _, v := range x { + d := v - mean + ss += d * d + compensation += d + } + variance = (ss - compensation*compensation/float64(len(x))) / float64(len(x)-1) + return + } + + var sumWeights float64 + for i, v := range x { + w := weights[i] + d := v - mean + wd := w * d + ss += wd * d + compensation += wd + sumWeights += w + } + variance = (ss - compensation*compensation/sumWeights) / (sumWeights - 1) + return +} diff --git a/stat/stat_test.go b/stat/stat_test.go new file mode 100644 index 00000000..bdb24dd3 --- /dev/null +++ b/stat/stat_test.go @@ -0,0 +1,1569 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat + +import ( + "fmt" + "math" + "reflect" + "testing" + + "gonum.org/v1/gonum/floats" +) + +func ExampleCircularMean() { + x := []float64{0, 0.25 * math.Pi, 0.75 * math.Pi} + weights := []float64{1, 2, 2.5} + cmean := CircularMean(x, weights) + + fmt.Printf("The circular mean is %.5f.\n", cmean) + // Output: + // The circular mean is 1.37037. +} + +func TestCircularMean(t *testing.T) { + for i, test := range []struct { + x []float64 + wts []float64 + ans float64 + }{ + // Values compared against scipy. + { + x: []float64{0, 2 * math.Pi}, + ans: 0, + }, + { + x: []float64{0, 0.5 * math.Pi}, + ans: 0.78539816339744, + }, + { + x: []float64{-1.5 * math.Pi, 0.5 * math.Pi, 2.5 * math.Pi}, + wts: []float64{1, 2, 3}, + ans: 0.5 * math.Pi, + }, + { + x: []float64{0, 0.5 * math.Pi}, + wts: []float64{1, 2}, + ans: 1.10714871779409, + }, + } { + c := CircularMean(test.x, test.wts) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Circular mean mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { CircularMean(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("CircularMean did not panic with x, wts length mismatch") + } +} + +func ExampleCorrelation() { + x := []float64{8, -3, 7, 8, -4} + y := []float64{10, 5, 6, 3, -1} + w := []float64{2, 1.5, 3, 3, 2} + + fmt.Println("Correlation computes the degree to which two datasets move together") + fmt.Println("about their mean. For example, x and y above move similarly.") + + c := Correlation(x, y, w) + fmt.Printf("Correlation is %.5f\n", c) + + // Output: + // Correlation computes the degree to which two datasets move together + // about their mean. For example, x and y above move similarly. + // Correlation is 0.59915 +} + +func TestCorrelation(t *testing.T) { + for i, test := range []struct { + x []float64 + y []float64 + w []float64 + ans float64 + }{ + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{8, -3, 7, 8, -4}, + w: nil, + ans: 1, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{8, -3, 7, 8, -4}, + w: []float64{1, 1, 1, 1, 1}, + ans: 1, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{8, -3, 7, 8, -4}, + w: []float64{1, 6, 7, 0.8, 2.1}, + ans: 1, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{10, 15, 4, 5, -1}, + w: nil, + ans: 0.0093334660769059, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{10, 15, 4, 5, -1}, + w: nil, + ans: 0.0093334660769059, + }, + { + x: []float64{8, -3, 7, 8, -4}, + y: []float64{10, 15, 4, 5, -1}, + w: []float64{1, 3, 1, 2, 2}, + ans: -0.13966633352689, + }, + } { + c := Correlation(test.x, test.y, test.w) + if math.Abs(test.ans-c) > 1e-14 { + t.Errorf("Correlation mismatch case %d. Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { Correlation(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) { + t.Errorf("Correlation did not panic with length mismatch") + } + if !Panics(func() { Correlation(make([]float64, 2), make([]float64, 3), nil) }) { + t.Errorf("Correlation did not panic with length mismatch") + } + if !Panics(func() { Correlation(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Correlation did not panic with weights length mismatch") + } +} + +func ExampleCovariance() { + fmt.Println("Covariance computes the degree to which datasets move together") + fmt.Println("about their mean.") + x := []float64{8, -3, 7, 8, -4} + y := []float64{10, 2, 2, 4, 1} + cov := Covariance(x, y, nil) + fmt.Printf("Cov = %.4f\n", cov) + fmt.Println("If datasets move perfectly together, the variance equals the covariance") + y2 := []float64{12, 1, 11, 12, 0} + cov2 := Covariance(x, y2, nil) + varX := Variance(x, nil) + fmt.Printf("Cov2 is %.4f, VarX is %.4f", cov2, varX) + // Output: + // Covariance computes the degree to which datasets move together + // about their mean. + // Cov = 13.8000 + // If datasets move perfectly together, the variance equals the covariance + // Cov2 is 37.7000, VarX is 37.7000 +} + +func TestCovariance(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + weights []float64 + ans float64 + }{ + { + p: []float64{0.75, 0.1, 0.05}, + q: []float64{0.5, 0.25, 0.25}, + ans: 0.05625, + }, + { + p: []float64{1, 2, 3}, + q: []float64{2, 4, 6}, + ans: 2, + }, + { + p: []float64{1, 2, 3}, + q: []float64{1, 4, 9}, + ans: 4, + }, + { + p: []float64{1, 2, 3}, + q: []float64{1, 4, 9}, + weights: []float64{1, 1.5, 1}, + ans: 3.2, + }, + { + p: []float64{1, 4, 9}, + q: []float64{1, 4, 9}, + weights: []float64{1, 1.5, 1}, + ans: 13.142857142857146, + }, + } { + c := Covariance(test.p, test.q, test.weights) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Covariance mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + + // test the panic states + if !Panics(func() { Covariance(make([]float64, 2), make([]float64, 3), nil) }) { + t.Errorf("Covariance did not panic with x, y length mismatch") + } + if !Panics(func() { Covariance(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Covariance did not panic with x, weights length mismatch") + } + +} + +func TestCrossEntropy(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + ans float64 + }{ + { + p: []float64{0.75, 0.1, 0.05}, + q: []float64{0.5, 0.25, 0.25}, + ans: 0.7278045395879426, + }, + { + p: []float64{0.75, 0.1, 0.05, 0, 0, 0}, + q: []float64{0.5, 0.25, 0.25, 0, 0, 0}, + ans: 0.7278045395879426, + }, + { + p: []float64{0.75, 0.1, 0.05, 0, 0, 0.1}, + q: []float64{0.5, 0.25, 0.25, 0, 0, 0}, + ans: math.Inf(1), + }, + { + p: nil, + q: nil, + ans: 0, + }, + } { + c := CrossEntropy(test.p, test.q) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Cross entropy mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { CrossEntropy(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("CrossEntropy did not panic with p, q length mismatch") + } +} + +func ExampleEntropy() { + + p := []float64{0.05, 0.1, 0.9, 0.05} + entP := Entropy(p) + + q := []float64{0.2, 0.4, 0.25, 0.15} + entQ := Entropy(q) + + r := []float64{0.2, 0, 0, 0.5, 0, 0.2, 0.1, 0, 0, 0} + entR := Entropy(r) + + s := []float64{0, 0, 1, 0} + entS := Entropy(s) + + fmt.Println("Entropy is a measure of the amount of uncertainty in a distribution") + fmt.Printf("The second bin of p is very likely to occur. It's entropy is %.4f\n", entP) + fmt.Printf("The distribution of q is more spread out. It's entropy is %.4f\n", entQ) + fmt.Println("Adding buckets with zero probability does not change the entropy.") + fmt.Printf("The entropy of r is: %.4f\n", entR) + fmt.Printf("A distribution with no uncertainty has entropy %.4f\n", entS) + // Output: + // Entropy is a measure of the amount of uncertainty in a distribution + // The second bin of p is very likely to occur. It's entropy is 0.6247 + // The distribution of q is more spread out. It's entropy is 1.3195 + // Adding buckets with zero probability does not change the entropy. + // The entropy of r is: 1.2206 + // A distribution with no uncertainty has entropy 0.0000 +} + +func ExampleExKurtosis() { + fmt.Println(`Kurtosis is a measure of the 'peakedness' of a distribution, and the +excess kurtosis is the kurtosis above or below that of the standard normal +distribution`) + x := []float64{5, 4, -3, -2} + kurt := ExKurtosis(x, nil) + fmt.Printf("ExKurtosis = %.5f\n", kurt) + weights := []float64{1, 2, 3, 5} + wKurt := ExKurtosis(x, weights) + fmt.Printf("Weighted ExKurtosis is %.4f", wKurt) + // Output: + // Kurtosis is a measure of the 'peakedness' of a distribution, and the + // excess kurtosis is the kurtosis above or below that of the standard normal + // distribution + // ExKurtosis = -5.41200 + // Weighted ExKurtosis is -0.6779 +} + +func TestExKurtosis(t *testing.T) { + // the example does a good job, this just has to cover the panic + if !Panics(func() { ExKurtosis(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("ExKurtosis did not panic with x, weights length mismatch") + } +} + +func ExampleGeometricMean() { + x := []float64{8, 2, 9, 15, 4} + weights := []float64{2, 2, 6, 7, 1} + mean := Mean(x, weights) + gmean := GeometricMean(x, weights) + + logx := make([]float64, len(x)) + for i, v := range x { + logx[i] = math.Log(v) + } + expMeanLog := math.Exp(Mean(logx, weights)) + fmt.Printf("The arithmetic mean is %.4f, but the geometric mean is %.4f.\n", mean, gmean) + fmt.Printf("The exponential of the mean of the logs is %.4f\n", expMeanLog) + // Output: + // The arithmetic mean is 10.1667, but the geometric mean is 8.7637. + // The exponential of the mean of the logs is 8.7637 +} + +func TestGeometricMean(t *testing.T) { + for i, test := range []struct { + x []float64 + wts []float64 + ans float64 + }{ + { + x: []float64{2, 8}, + ans: 4, + }, + { + x: []float64{3, 81}, + wts: []float64{2, 1}, + ans: 9, + }, + } { + c := GeometricMean(test.x, test.wts) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Geometric mean mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { GeometricMean(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("GeometricMean did not panic with x, wts length mismatch") + } +} + +func ExampleHarmonicMean() { + x := []float64{8, 2, 9, 15, 4} + weights := []float64{2, 2, 6, 7, 1} + mean := Mean(x, weights) + hmean := HarmonicMean(x, weights) + + fmt.Printf("The arithmetic mean is %.5f, but the harmonic mean is %.4f.\n", mean, hmean) + // Output: + // The arithmetic mean is 10.16667, but the harmonic mean is 6.8354. +} + +func TestHarmonicMean(t *testing.T) { + for i, test := range []struct { + x []float64 + wts []float64 + ans float64 + }{ + { + x: []float64{.5, .125}, + ans: .2, + }, + { + x: []float64{.5, .125}, + wts: []float64{2, 1}, + ans: .25, + }, + } { + c := HarmonicMean(test.x, test.wts) + if math.Abs(c-test.ans) > 1e-14 { + t.Errorf("Harmonic mean mismatch case %d: Expected %v, Found %v", i, test.ans, c) + } + } + if !Panics(func() { HarmonicMean(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("HarmonicMean did not panic with x, wts length mismatch") + } +} + +func TestHistogram(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + dividers []float64 + ans []float64 + }{ + { + x: []float64{1, 3, 5, 6, 7, 8}, + dividers: []float64{0, 2, 4, 6, 7, 9}, + ans: []float64{1, 1, 1, 1, 2}, + }, + { + x: []float64{1, 3, 5, 6, 7, 8}, + dividers: []float64{1, 2, 4, 6, 7, 9}, + weights: []float64{1, 2, 1, 1, 1, 2}, + ans: []float64{1, 2, 1, 1, 3}, + }, + { + x: []float64{1, 8}, + dividers: []float64{0, 2, 4, 6, 7, 9}, + weights: []float64{1, 2}, + ans: []float64{1, 0, 0, 0, 2}, + }, + { + x: []float64{1, 8}, + dividers: []float64{0, 2, 4, 6, 7, 9}, + ans: []float64{1, 0, 0, 0, 1}, + }, + { + x: []float64{}, + dividers: []float64{1, 3}, + ans: []float64{0}, + }, + } { + hist := Histogram(nil, test.dividers, test.x, test.weights) + if !floats.Equal(hist, test.ans) { + t.Errorf("Hist mismatch case %d. Expected %v, Found %v", i, test.ans, hist) + } + // Test with non-zero values + Histogram(hist, test.dividers, test.x, test.weights) + if !floats.Equal(hist, test.ans) { + t.Errorf("Hist mismatch case %d. Expected %v, Found %v", i, test.ans, hist) + } + } + // panic cases + for _, test := range []struct { + name string + x []float64 + weights []float64 + dividers []float64 + count []float64 + }{ + { + name: "len(x) != len(weights)", + x: []float64{1, 3, 5, 6, 7, 8}, + weights: []float64{1, 1, 1, 1}, + }, + { + name: "len(count) != len(dividers) - 1", + x: []float64{1, 3, 5, 6, 7, 8}, + dividers: []float64{1, 4, 9}, + count: make([]float64, 6), + }, + { + name: "dividers not sorted", + x: []float64{1, 3, 5, 6, 7, 8}, + dividers: []float64{0, -1, 0}, + }, + { + name: "x not sorted", + x: []float64{1, 5, 2, 9, 7, 8}, + dividers: []float64{1, 4, 9}, + }, + { + name: "fewer than 2 dividers", + x: []float64{1, 2, 3}, + dividers: []float64{5}, + }, + { + name: "x too large", + x: []float64{1, 2, 3}, + dividers: []float64{1, 3}, + }, + { + name: "x too small", + x: []float64{1, 2, 3}, + dividers: []float64{2, 3}, + }, + } { + if !Panics(func() { Histogram(test.count, test.dividers, test.x, test.weights) }) { + t.Errorf("Histogram did not panic when %s", test.name) + } + } +} + +func ExampleHistogram() { + x := make([]float64, 101) + for i := range x { + x[i] = 1.1 * float64(i) // x data ranges from 0 to 110 + } + dividers := []float64{0, 7, 20, 100, 1000} + fmt.Println(`Histogram counts the amount of data in the bins specified by +the dividers. In this data set, there are 7 data points less than 7 (between dividers[0] +and dividers[1]), 12 data points between 7 and 20 (dividers[1] and dividers[2]), +and 0 data points above 1000. Since dividers has length 5, there will be 4 bins.`) + hist := Histogram(nil, dividers, x, nil) + fmt.Printf("Hist = %v\n", hist) + + fmt.Println() + fmt.Println("For ease, the floats Span function can be used to set the dividers") + nBins := 10 + dividers = make([]float64, nBins+1) + min := floats.Min(x) + max := floats.Max(x) + // Increase the maximum divider so that the maximum value of x is contained + // within the last bucket. + max += 1 + floats.Span(dividers, min, max) + // Span includes the min and the max. Trim the dividers to create 10 buckets + hist = Histogram(nil, dividers, x, nil) + fmt.Printf("Hist = %v\n", hist) + fmt.Println() + fmt.Println(`Histogram also works with weighted data, and allows reusing of +the count field in order to avoid extra garbage`) + weights := make([]float64, len(x)) + for i := range weights { + weights[i] = float64(i + 1) + } + Histogram(hist, dividers, x, weights) + fmt.Printf("Weighted Hist = %v\n", hist) + + // Output: + // Histogram counts the amount of data in the bins specified by + // the dividers. In this data set, there are 7 data points less than 7 (between dividers[0] + // and dividers[1]), 12 data points between 7 and 20 (dividers[1] and dividers[2]), + // and 0 data points above 1000. Since dividers has length 5, there will be 4 bins. + // Hist = [7 12 72 10] + // + // For ease, the floats Span function can be used to set the dividers + // Hist = [11 10 10 10 10 10 10 10 10 10] + // + // Histogram also works with weighted data, and allows reusing of + // the count field in order to avoid extra garbage + // Weighted Hist = [66 165 265 365 465 565 665 765 865 965] +} + +func TestJensenShannon(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + }{ + { + p: []float64{0.5, 0.1, 0.3, 0.1}, + q: []float64{0.1, 0.4, 0.25, 0.25}, + }, + { + p: []float64{0.4, 0.6, 0.0}, + q: []float64{0.2, 0.2, 0.6}, + }, + { + p: []float64{0.1, 0.1, 0.0, 0.8}, + q: []float64{0.6, 0.3, 0.0, 0.1}, + }, + { + p: []float64{0.5, 0.1, 0.3, 0.1}, + q: []float64{0.5, 0, 0.25, 0.25}, + }, + { + p: []float64{0.5, 0.1, 0, 0.4}, + q: []float64{0.1, 0.4, 0.25, 0.25}, + }, + } { + + m := make([]float64, len(test.p)) + p := test.p + q := test.q + floats.Add(m, p) + floats.Add(m, q) + floats.Scale(0.5, m) + + js1 := 0.5*KullbackLeibler(p, m) + 0.5*KullbackLeibler(q, m) + js2 := JensenShannon(p, q) + + if math.IsNaN(js2) { + t.Errorf("In case %v, JS distance is NaN", i) + } + + if math.Abs(js1-js2) > 1e-14 { + t.Errorf("JS mismatch case %v. Expected %v, found %v.", i, js1, js2) + } + } + if !Panics(func() { JensenShannon(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("JensenShannon did not panic with p, q length mismatch") + } +} + +func TestKolmogorovSmirnov(t *testing.T) { + for i, test := range []struct { + x []float64 + xWeights []float64 + y []float64 + yWeights []float64 + dist float64 + }{ + + { + dist: 0, + }, + { + x: []float64{1}, + dist: 1, + }, + { + y: []float64{1}, + dist: 1, + }, + { + x: []float64{1}, + xWeights: []float64{8}, + dist: 1, + }, + { + y: []float64{1}, + yWeights: []float64{8}, + dist: 1, + }, + { + x: []float64{1}, + xWeights: []float64{8}, + y: []float64{1}, + yWeights: []float64{8}, + dist: 0, + }, + { + x: []float64{1, 1, 1}, + xWeights: []float64{2, 3, 7}, + y: []float64{1}, + yWeights: []float64{8}, + dist: 0, + }, + { + x: []float64{1, 1, 1, 1, 1}, + y: []float64{1, 1, 1}, + yWeights: []float64{2, 5, 2}, + dist: 0, + }, + + { + x: []float64{1, 2, 3}, + y: []float64{1, 2, 3}, + dist: 0, + }, + { + x: []float64{1, 2, 3}, + y: []float64{1, 2, 3}, + yWeights: []float64{1, 1, 1}, + dist: 0, + }, + + { + x: []float64{1, 2, 3}, + xWeights: []float64{1, 1, 1}, + y: []float64{1, 2, 3}, + yWeights: []float64{1, 1, 1}, + dist: 0, + }, + { + x: []float64{1, 2}, + xWeights: []float64{2, 5}, + y: []float64{1, 1, 2, 2, 2, 2, 2}, + dist: 0, + }, + { + x: []float64{1, 1, 2, 2, 2, 2, 2}, + y: []float64{1, 2}, + yWeights: []float64{2, 5}, + dist: 0, + }, + { + x: []float64{1, 1, 2, 2, 2}, + xWeights: []float64{0.5, 1.5, 1, 2, 2}, + y: []float64{1, 2}, + yWeights: []float64{2, 5}, + dist: 0, + }, + { + x: []float64{1, 2, 3, 4}, + y: []float64{5, 6}, + dist: 1, + }, + { + x: []float64{5, 6}, + y: []float64{1, 2, 3, 4}, + dist: 1, + }, + { + x: []float64{5, 6}, + xWeights: []float64{8, 7}, + y: []float64{1, 2, 3, 4}, + dist: 1, + }, + { + x: []float64{5, 6}, + xWeights: []float64{8, 7}, + y: []float64{1, 2, 3, 4}, + yWeights: []float64{9, 2, 1, 6}, + dist: 1, + }, + { + x: []float64{-4, 5, 6}, + xWeights: []float64{0, 8, 7}, + y: []float64{1, 2, 3, 4}, + yWeights: []float64{9, 2, 1, 6}, + dist: 1, + }, + { + x: []float64{-4, -2, -2, 5, 6}, + xWeights: []float64{0, 0, 0, 8, 7}, + y: []float64{1, 2, 3, 4}, + yWeights: []float64{9, 2, 1, 6}, + dist: 1, + }, + { + x: []float64{1, 2, 3}, + y: []float64{1, 1, 3}, + dist: 1.0 / 3.0, + }, + { + x: []float64{1, 2, 3}, + y: []float64{1, 3}, + yWeights: []float64{2, 1}, + dist: 1.0 / 3.0, + }, + { + x: []float64{1, 2, 3}, + xWeights: []float64{2, 2, 2}, + y: []float64{1, 3}, + yWeights: []float64{2, 1}, + dist: 1.0 / 3.0, + }, + { + x: []float64{2, 3, 4}, + y: []float64{1, 5}, + dist: 1.0 / 2.0, + }, + { + x: []float64{1, 2, math.NaN()}, + y: []float64{1, 1, 3}, + dist: math.NaN(), + }, + { + x: []float64{1, 2, 3}, + y: []float64{1, 1, math.NaN()}, + dist: math.NaN(), + }, + } { + dist := KolmogorovSmirnov(test.x, test.xWeights, test.y, test.yWeights) + if math.Abs(dist-test.dist) > 1e-14 && !(math.IsNaN(test.dist) && math.IsNaN(dist)) { + t.Errorf("Distance mismatch case %v: Expected: %v, Found: %v", i, test.dist, dist) + } + } + // panic cases + for _, test := range []struct { + name string + x []float64 + xWeights []float64 + y []float64 + yWeights []float64 + }{ + { + name: "len(x) != len(xWeights)", + x: []float64{1, 3, 5, 6, 7, 8}, + xWeights: []float64{1, 1, 1, 1}, + }, + { + name: "len(y) != len(yWeights)", + x: []float64{1, 3, 5, 6, 7, 8}, + y: []float64{1, 3, 5, 6, 7, 8}, + yWeights: []float64{1, 1, 1, 1}, + }, + { + name: "x not sorted", + x: []float64{10, 3, 5, 6, 7, 8}, + y: []float64{1, 3, 5, 6, 7, 8}, + }, + { + name: "y not sorted", + x: []float64{1, 3, 5, 6, 7, 8}, + y: []float64{10, 3, 5, 6, 7, 8}, + }, + } { + if !Panics(func() { KolmogorovSmirnov(test.x, test.xWeights, test.y, test.yWeights) }) { + t.Errorf("KolmogorovSmirnov did not panic when %s", test.name) + } + } +} + +func ExampleKullbackLeibler() { + + p := []float64{0.05, 0.1, 0.9, 0.05} + q := []float64{0.2, 0.4, 0.25, 0.15} + s := []float64{0, 0, 1, 0} + + klPQ := KullbackLeibler(p, q) + klPS := KullbackLeibler(p, s) + klPP := KullbackLeibler(p, p) + + fmt.Println("Kullback-Leibler is one measure of the difference between two distributions") + fmt.Printf("The K-L distance between p and q is %.4f\n", klPQ) + fmt.Println("It is impossible for s and p to be the same distribution, because") + fmt.Println("the first bucket has zero probability in s and non-zero in p. Thus,") + fmt.Printf("the K-L distance between them is %.4f\n", klPS) + fmt.Printf("The K-L distance between identical distributions is %.4f\n", klPP) + + // Kullback-Leibler is one measure of the difference between two distributions + // The K-L distance between p and q is 0.8900 + // It is impossible for s and p to be the same distribution, because + // the first bucket has zero probability in s and non-zero in p. Thus, + // the K-L distance between them is +Inf + // The K-L distance between identical distributions is 0.0000 +} + +func TestKullbackLeibler(t *testing.T) { + if !Panics(func() { KullbackLeibler(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("KullbackLeibler did not panic with p, q length mismatch") + } +} + +var linearRegressionTests = []struct { + name string + + x, y []float64 + weights []float64 + origin bool + + alpha float64 + beta float64 + r float64 + + tol float64 +}{ + { + name: "faithful", + + x: faithful.waiting, + y: faithful.eruptions, + + // Values calculated by R using lm(eruptions ~ waiting, data=faithful). + alpha: -1.87402, + beta: 0.07563, + r: 0.8114608, + + tol: 1e-5, + }, + { + name: "faithful through origin", + + x: faithful.waiting, + y: faithful.eruptions, + origin: true, + + // Values calculated by R using lm(eruptions ~ waiting - 1, data=faithful). + alpha: 0, + beta: 0.05013, + r: 0.9726036, + + tol: 1e-5, + }, + { + name: "faithful explicit weights", + + x: faithful.waiting, + y: faithful.eruptions, + weights: func() []float64 { + w := make([]float64, len(faithful.eruptions)) + for i := range w { + w[i] = 1 + } + return w + }(), + + // Values calculated by R using lm(eruptions ~ waiting, data=faithful). + alpha: -1.87402, + beta: 0.07563, + r: 0.8114608, + + tol: 1e-5, + }, + { + name: "faithful non-uniform weights", + + x: faithful.waiting, + y: faithful.eruptions, + weights: faithful.waiting, // Just an arbitrary set of non-uniform weights. + + // Values calculated by R using lm(eruptions ~ waiting, data=faithful, weights=faithful$waiting). + alpha: -1.79268, + beta: 0.07452, + r: 0.7840372, + + tol: 1e-5, + }, +} + +func TestLinearRegression(t *testing.T) { + for _, test := range linearRegressionTests { + alpha, beta := LinearRegression(test.x, test.y, test.weights, test.origin) + var r float64 + if test.origin { + r = RNoughtSquared(test.x, test.y, test.weights, beta) + } else { + r = RSquared(test.x, test.y, test.weights, alpha, beta) + ests := make([]float64, len(test.y)) + for i, x := range test.x { + ests[i] = alpha + beta*x + } + rvals := RSquaredFrom(ests, test.y, test.weights) + if r != rvals { + t.Errorf("%s: RSquared and RSquaredFrom mismatch: %v != %v", test.name, r, rvals) + } + } + if !floats.EqualWithinAbsOrRel(alpha, test.alpha, test.tol, test.tol) { + t.Errorf("%s: unexpected alpha estimate: want:%v got:%v", test.name, test.alpha, alpha) + } + if !floats.EqualWithinAbsOrRel(beta, test.beta, test.tol, test.tol) { + t.Errorf("%s: unexpected beta estimate: want:%v got:%v", test.name, test.beta, beta) + } + if !floats.EqualWithinAbsOrRel(r, test.r, test.tol, test.tol) { + t.Errorf("%s: unexpected r estimate: want:%v got:%v", test.name, test.r, r) + } + } +} + +func TestChiSquare(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + res float64 + }{ + { + p: []float64{16, 18, 16, 14, 12, 12}, + q: []float64{16, 16, 16, 16, 16, 8}, + res: 3.5, + }, + { + p: []float64{16, 18, 16, 14, 12, 12}, + q: []float64{8, 20, 20, 16, 12, 12}, + res: 9.25, + }, + { + p: []float64{40, 60, 30, 45}, + q: []float64{50, 50, 50, 50}, + res: 12.5, + }, + { + p: []float64{40, 60, 30, 45, 0, 0}, + q: []float64{50, 50, 50, 50, 0, 0}, + res: 12.5, + }, + } { + resultpq := ChiSquare(test.p, test.q) + + if math.Abs(resultpq-test.res) > 1e-10 { + t.Errorf("ChiSquare distance mismatch in case %d. Expected %v, Found %v", i, test.res, resultpq) + } + } + if !Panics(func() { ChiSquare(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("ChiSquare did not panic with length mismatch") + } +} + +// Panics returns true if the called function panics during evaluation. +func Panics(fun func()) (b bool) { + defer func() { + err := recover() + if err != nil { + b = true + } + }() + fun() + return +} + +func TestBhattacharyya(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + res float64 + }{ + { + p: []float64{0.5, 0.1, 0.3, 0.1}, + q: []float64{0.1, 0.4, 0.25, 0.25}, + res: 0.15597338718671386, + }, + { + p: []float64{0.4, 0.6, 0.0}, + q: []float64{0.2, 0.2, 0.6}, + res: 0.46322207765351153, + }, + { + p: []float64{0.1, 0.1, 0.0, 0.8}, + q: []float64{0.6, 0.3, 0.0, 0.1}, + res: 0.3552520032137785, + }, + } { + resultpq := Bhattacharyya(test.p, test.q) + resultqp := Bhattacharyya(test.q, test.p) + + if math.Abs(resultpq-test.res) > 1e-10 { + t.Errorf("Bhattacharyya distance mismatch in case %d. Expected %v, Found %v", i, test.res, resultpq) + } + if math.Abs(resultpq-resultqp) > 1e-10 { + t.Errorf("Bhattacharyya distance is assymmetric in case %d.", i) + } + } + // Bhattacharyya should panic if the inputs have different length + if !Panics(func() { Bhattacharyya(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Bhattacharyya did not panic with length mismatch") + } +} + +func TestHellinger(t *testing.T) { + for i, test := range []struct { + p []float64 + q []float64 + res float64 + }{ + { + p: []float64{0.5, 0.1, 0.3, 0.1}, + q: []float64{0.1, 0.4, 0.25, 0.25}, + res: 0.3800237367441919, + }, + { + p: []float64{0.4, 0.6, 0.0}, + q: []float64{0.2, 0.2, 0.6}, + res: 0.6088900771170487, + }, + { + p: []float64{0.1, 0.1, 0.0, 0.8}, + q: []float64{0.6, 0.3, 0.0, 0.1}, + res: 0.5468118803484205, + }, + } { + resultpq := Hellinger(test.p, test.q) + resultqp := Hellinger(test.q, test.p) + + if math.Abs(resultpq-test.res) > 1e-10 { + t.Errorf("Hellinger distance mismatch in case %d. Expected %v, Found %v", i, test.res, resultpq) + } + if math.Abs(resultpq-resultqp) > 1e-10 { + t.Errorf("Hellinger distance is assymmetric in case %d.", i) + } + } + if !Panics(func() { Hellinger(make([]float64, 2), make([]float64, 3)) }) { + t.Errorf("Hellinger did not panic with length mismatch") + } +} + +func ExampleMean() { + x := []float64{8.2, -6, 5, 7} + mean := Mean(x, nil) + fmt.Printf("The mean of the samples is %.4f\n", mean) + w := []float64{2, 6, 3, 5} + weightedMean := Mean(x, w) + fmt.Printf("The weighted mean of the samples is %.4f\n", weightedMean) + x2 := []float64{8.2, 8.2, -6, -6, -6, -6, -6, -6, 5, 5, 5, 7, 7, 7, 7, 7} + mean2 := Mean(x2, nil) + fmt.Printf("The mean of x2 is %.4f\n", mean2) + fmt.Println("The weights act as if there were more samples of that number") + // Output: + // The mean of the samples is 3.5500 + // The weighted mean of the samples is 1.9000 + // The mean of x2 is 1.9000 + // The weights act as if there were more samples of that number +} +func TestMean(t *testing.T) { + if !Panics(func() { Mean(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Mean did not panic with x, weights length mismatch") + } +} + +func TestMode(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + ans float64 + count float64 + }{ + {}, + { + x: []float64{1, 6, 1, 9, -2}, + ans: 1, + count: 2, + }, + { + x: []float64{1, 6, 1, 9, -2}, + weights: []float64{1, 7, 3, 5, 0}, + ans: 6, + count: 7, + }, + } { + m, count := Mode(test.x, test.weights) + if test.ans != m { + t.Errorf("Mode mismatch case %d. Expected %v, found %v", i, test.ans, m) + } + if test.count != count { + t.Errorf("Mode count mismatch case %d. Expected %v, found %v", i, test.count, count) + } + } + if !Panics(func() { Mode(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Mode did not panic with x, weights length mismatch") + } +} + +func TestMoment(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + moment float64 + ans float64 + }{ + { + x: []float64{6, 2, 4, 8, 10}, + moment: 5, + ans: 0, + }, + { + x: []float64{6, 2, 4, 8, 10}, + weights: []float64{1, 2, 2, 2, 1}, + moment: 5, + ans: 121.875, + }, + } { + m := Moment(test.moment, test.x, test.weights) + if math.Abs(test.ans-m) > 1e-14 { + t.Errorf("Moment mismatch case %d. Expected %v, found %v", i, test.ans, m) + } + } + if !Panics(func() { Moment(1, make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Moment did not panic with x, weights length mismatch") + } +} + +func TestMomentAbout(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + moment float64 + mean float64 + ans float64 + }{ + { + x: []float64{6, 2, 4, 8, 9}, + mean: 3, + moment: 5, + ans: 2.2288e3, + }, + { + x: []float64{6, 2, 4, 8, 9}, + weights: []float64{1, 2, 2, 2, 1}, + mean: 3, + moment: 5, + ans: 1.783625e3, + }, + } { + m := MomentAbout(test.moment, test.x, test.mean, test.weights) + if math.Abs(test.ans-m) > 1e-14 { + t.Errorf("MomentAbout mismatch case %d. Expected %v, found %v", i, test.ans, m) + } + } + if !Panics(func() { MomentAbout(1, make([]float64, 3), 0, make([]float64, 2)) }) { + t.Errorf("MomentAbout did not panic with x, weights length mismatch") + } +} + +func TestCDF(t *testing.T) { + cumulantKinds := []CumulantKind{Empirical} + for i, test := range []struct { + q []float64 + x []float64 + weights []float64 + ans [][]float64 + }{ + {}, + { + q: []float64{0, 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1}, + x: []float64{1, 2, 3, 4, 5}, + ans: [][]float64{{0, 0, 0.2, 0.2, 0.4, 0.6, 0.6, 0.8, 1, 1}}, + }, + { + q: []float64{0, 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1}, + x: []float64{1, 2, 3, 4, 5}, + weights: []float64{1, 1, 1, 1, 1}, + ans: [][]float64{{0, 0, 0.2, 0.2, 0.4, 0.6, 0.6, 0.8, 1, 1}}, + }, + { + q: []float64{0, 0.9, 1}, + x: []float64{math.NaN()}, + ans: [][]float64{{math.NaN(), math.NaN(), math.NaN()}}, + }, + } { + copyX := make([]float64, len(test.x)) + copy(copyX, test.x) + var copyW []float64 + if test.weights != nil { + copyW = make([]float64, len(test.weights)) + copy(copyW, test.weights) + } + for j, q := range test.q { + for k, kind := range cumulantKinds { + v := CDF(q, kind, test.x, test.weights) + if !floats.Equal(copyX, test.x) && !math.IsNaN(v) { + t.Errorf("x changed for case %d kind %d percentile %v", i, k, q) + } + if !floats.Equal(copyW, test.weights) { + t.Errorf("x changed for case %d kind %d percentile %v", i, k, q) + } + if v != test.ans[k][j] && !(math.IsNaN(v) && math.IsNaN(test.ans[k][j])) { + t.Errorf("mismatch case %d kind %d percentile %v. Expected: %v, found: %v", i, k, q, test.ans[k][j], v) + } + } + } + } + + // these test cases should all result in a panic + for i, test := range []struct { + name string + q float64 + kind CumulantKind + x []float64 + weights []float64 + }{ + { + name: "len(x) != len(weights)", + q: 1.5, + kind: Empirical, + x: []float64{1, 2, 3, 4, 5}, + weights: []float64{1, 2, 3}, + }, + { + name: "unsorted x", + q: 1.5, + kind: Empirical, + x: []float64{3, 2, 1}, + }, + { + name: "unknown CumulantKind", + q: 1.5, + kind: CumulantKind(1000), // bogus + x: []float64{1, 2, 3}, + }, + } { + if !Panics(func() { CDF(test.q, test.kind, test.x, test.weights) }) { + t.Errorf("did not panic as expected with %s for case %d kind %d percentile %v x %v weights %v", test.name, i, test.kind, test.q, test.x, test.weights) + } + } + +} + +func TestQuantile(t *testing.T) { + cumulantKinds := []CumulantKind{Empirical} + for i, test := range []struct { + p []float64 + x []float64 + w []float64 + ans [][]float64 + }{ + { + p: []float64{0, 0.05, 0.1, 0.15, 0.45, 0.5, 0.55, 0.85, 0.9, 0.95, 1}, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + w: nil, + ans: [][]float64{{1, 1, 1, 2, 5, 5, 6, 9, 9, 10, 10}}, + }, + { + p: []float64{0, 0.05, 0.1, 0.15, 0.45, 0.5, 0.55, 0.85, 0.9, 0.95, 1}, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + w: []float64{3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + ans: [][]float64{{1, 1, 1, 2, 5, 5, 6, 9, 9, 10, 10}}, + }, + { + p: []float64{0.5}, + x: []float64{1, 2, 3, 4, 5, 6, 7, 8, math.NaN(), 10}, + ans: [][]float64{{math.NaN()}}, + }, + } { + copyX := make([]float64, len(test.x)) + copy(copyX, test.x) + var copyW []float64 + if test.w != nil { + copyW = make([]float64, len(test.w)) + copy(copyW, test.w) + } + for j, p := range test.p { + for k, kind := range cumulantKinds { + v := Quantile(p, kind, test.x, test.w) + if !floats.Same(copyX, test.x) { + t.Errorf("x changed for case %d kind %d percentile %v", i, k, p) + } + if !floats.Same(copyW, test.w) { + t.Errorf("x changed for case %d kind %d percentile %v", i, k, p) + } + if v != test.ans[k][j] && !(math.IsNaN(v) && math.IsNaN(test.ans[k][j])) { + t.Errorf("mismatch case %d kind %d percentile %v. Expected: %v, found: %v", i, k, p, test.ans[k][j], v) + } + } + } + } + // panic cases + for _, test := range []struct { + name string + p float64 + c CumulantKind + x []float64 + w []float64 + }{ + { + name: "p < 0", + c: Empirical, + p: -1, + }, + { + name: "p > 1", + c: Empirical, + p: 2, + }, + { + name: "p is NaN", + c: Empirical, + p: math.NaN(), + }, + { + name: "len(x) != len(weights)", + c: Empirical, + p: .5, + x: make([]float64, 4), + w: make([]float64, 2), + }, + { + name: "x not sorted", + c: Empirical, + p: .5, + x: []float64{3, 2, 1}, + }, + { + name: "CumulantKind is unknown", + c: CumulantKind(1000), + p: .5, + x: []float64{1, 2, 3}, + }, + } { + if !Panics(func() { Quantile(test.p, test.c, test.x, test.w) }) { + t.Errorf("Quantile did not panic when %s", test.name) + } + } +} + +func ExampleStdDev() { + x := []float64{8, 2, -9, 15, 4} + stdev := StdDev(x, nil) + fmt.Printf("The standard deviation of the samples is %.4f\n", stdev) + + weights := []float64{2, 2, 6, 7, 1} + weightedStdev := StdDev(x, weights) + fmt.Printf("The weighted standard deviation of the samples is %.4f\n", weightedStdev) + // Output: + // The standard deviation of the samples is 8.8034 + // The weighted standard deviation of the samples is 10.5733 +} + +func ExampleStdErr() { + x := []float64{8, 2, -9, 15, 4} + weights := []float64{2, 2, 6, 7, 1} + mean := Mean(x, weights) + stdev := StdDev(x, weights) + nSamples := floats.Sum(weights) + stdErr := StdErr(stdev, nSamples) + fmt.Printf("The standard deviation is %.4f and there are %g samples, so the mean\nis likely %.4f ± %.4f.", stdev, nSamples, mean, stdErr) + // Output: + // The standard deviation is 10.5733 and there are 18 samples, so the mean + // is likely 4.1667 ± 2.4921. +} + +func TestSkew(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + ans float64 + }{ + { + x: []float64{8, 3, 7, 8, 4}, + weights: nil, + ans: -0.581456499151665, + }, + { + x: []float64{8, 3, 7, 8, 4}, + weights: []float64{1, 1, 1, 1, 1}, + ans: -0.581456499151665, + }, + { + x: []float64{8, 3, 7, 8, 4}, + weights: []float64{2, 1, 2, 1, 1}, + ans: -1.12066646837198, + }, + } { + skew := Skew(test.x, test.weights) + if math.Abs(skew-test.ans) > 1e-14 { + t.Errorf("Skew mismatch case %d. Expected %v, Found %v", i, test.ans, skew) + } + } + if !Panics(func() { Skew(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Skew did not panic with x, weights length mismatch") + } +} + +func TestSortWeighted(t *testing.T) { + for i, test := range []struct { + x []float64 + w []float64 + ansx []float64 + answ []float64 + }{ + { + x: []float64{8, 3, 7, 8, 4}, + ansx: []float64{3, 4, 7, 8, 8}, + }, + { + x: []float64{8, 3, 7, 8, 4}, + w: []float64{.5, 1, 1, .5, 1}, + ansx: []float64{3, 4, 7, 8, 8}, + answ: []float64{1, 1, 1, .5, .5}, + }, + } { + SortWeighted(test.x, test.w) + if !floats.Same(test.x, test.ansx) { + t.Errorf("SortWeighted mismatch case %d. Expected x %v, Found x %v", i, test.ansx, test.x) + } + if !(test.w == nil) && !floats.Same(test.w, test.answ) { + t.Errorf("SortWeighted mismatch case %d. Expected w %v, Found w %v", i, test.answ, test.w) + } + } + if !Panics(func() { SortWeighted(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("SortWeighted did not panic with x, weights length mismatch") + } +} + +func TestSortWeightedLabeled(t *testing.T) { + for i, test := range []struct { + x []float64 + l []bool + w []float64 + ansx []float64 + ansl []bool + answ []float64 + }{ + { + x: []float64{8, 3, 7, 8, 4}, + ansx: []float64{3, 4, 7, 8, 8}, + }, + { + x: []float64{8, 3, 7, 8, 4}, + w: []float64{.5, 1, 1, .5, 1}, + ansx: []float64{3, 4, 7, 8, 8}, + answ: []float64{1, 1, 1, .5, .5}, + }, + { + x: []float64{8, 3, 7, 8, 4}, + l: []bool{false, false, true, false, true}, + ansx: []float64{3, 4, 7, 8, 8}, + ansl: []bool{false, true, true, false, false}, + }, + { + x: []float64{8, 3, 7, 8, 4}, + l: []bool{false, false, true, false, true}, + w: []float64{.5, 1, 1, .5, 1}, + ansx: []float64{3, 4, 7, 8, 8}, + ansl: []bool{false, true, true, false, false}, + answ: []float64{1, 1, 1, .5, .5}, + }, + } { + SortWeightedLabeled(test.x, test.l, test.w) + if !floats.Same(test.x, test.ansx) { + t.Errorf("SortWeightedLabelled mismatch case %d. Expected x %v, Found x %v", i, test.ansx, test.x) + } + if (test.l != nil) && !reflect.DeepEqual(test.l, test.ansl) { + t.Errorf("SortWeightedLabelled mismatch case %d. Expected l %v, Found l %v", i, test.ansl, test.l) + } + if (test.w != nil) && !floats.Same(test.w, test.answ) { + t.Errorf("SortWeightedLabelled mismatch case %d. Expected w %v, Found w %v", i, test.answ, test.w) + } + } + if !Panics(func() { SortWeightedLabeled(make([]float64, 3), make([]bool, 2), make([]float64, 3)) }) { + t.Errorf("SortWeighted did not panic with x, labels length mismatch") + } + if !Panics(func() { SortWeightedLabeled(make([]float64, 3), make([]bool, 2), nil) }) { + t.Errorf("SortWeighted did not panic with x, labels length mismatch") + } + if !Panics(func() { SortWeightedLabeled(make([]float64, 3), make([]bool, 3), make([]float64, 2)) }) { + t.Errorf("SortWeighted did not panic with x, weights length mismatch") + } + if !Panics(func() { SortWeightedLabeled(make([]float64, 3), nil, make([]float64, 2)) }) { + t.Errorf("SortWeighted did not panic with x, weights length mismatch") + } +} + +func TestVariance(t *testing.T) { + for i, test := range []struct { + x []float64 + weights []float64 + ans float64 + }{ + { + x: []float64{8, -3, 7, 8, -4}, + weights: nil, + ans: 37.7, + }, + { + x: []float64{8, -3, 7, 8, -4}, + weights: []float64{1, 1, 1, 1, 1}, + ans: 37.7, + }, + { + x: []float64{8, 3, 7, 8, 4}, + weights: []float64{2, 1, 2, 1, 1}, + ans: 4.2857142857142865, + }, + { + x: []float64{1, 4, 9}, + weights: []float64{1, 1.5, 1}, + ans: 13.142857142857146, + }, + { + x: []float64{1, 2, 3}, + weights: []float64{1, 1.5, 1}, + ans: .8, + }, + } { + variance := Variance(test.x, test.weights) + if math.Abs(variance-test.ans) > 1e-14 { + t.Errorf("Variance mismatch case %d. Expected %v, Found %v", i, test.ans, variance) + } + } + if !Panics(func() { Variance(make([]float64, 3), make([]float64, 2)) }) { + t.Errorf("Variance did not panic with x, weights length mismatch") + } + +} + +func ExampleVariance() { + x := []float64{8, 2, -9, 15, 4} + variance := Variance(x, nil) + fmt.Printf("The variance of the samples is %.4f\n", variance) + + weights := []float64{2, 2, 6, 7, 1} + weightedVariance := Variance(x, weights) + fmt.Printf("The weighted variance of the samples is %.4f\n", weightedVariance) + // Output: + // The variance of the samples is 77.5000 + // The weighted variance of the samples is 111.7941 +} + +func TestStdScore(t *testing.T) { + for i, test := range []struct { + x float64 + u float64 + s float64 + z float64 + }{ + { + x: 4, + u: -6, + s: 5, + z: 2, + }, + { + x: 1, + u: 0, + s: 1, + z: 1, + }, + } { + z := StdScore(test.x, test.u, test.s) + if math.Abs(z-test.z) > 1e-14 { + t.Errorf("StdScore mismatch case %d. Expected %v, Found %v", i, test.z, z) + } + } + +} diff --git a/stat/statmat.go b/stat/statmat.go new file mode 100644 index 00000000..a0d9078c --- /dev/null +++ b/stat/statmat.go @@ -0,0 +1,147 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat + +import ( + "math" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix" + "gonum.org/v1/gonum/matrix/mat64" +) + +// CovarianceMatrix returns the covariance matrix (also known as the +// variance-covariance matrix) calculated from a matrix of data, x, using +// a two-pass algorithm. +// +// If weights is not nil the weighted covariance of x is calculated. weights +// must have length equal to the number of rows in input data matrix and +// must not contain negative elements. +// If cov is not nil it must either be zero-sized or have the same number of +// columns as the input data matrix. cov will be used as the destination for +// the covariance data. If cov is nil, a new mat64.SymDense is allocated for +// the destination. +func CovarianceMatrix(cov *mat64.SymDense, x mat64.Matrix, weights []float64) *mat64.SymDense { + // This is the matrix version of the two-pass algorithm. It doesn't use the + // additional floating point error correction that the Covariance function uses + // to reduce the impact of rounding during centering. + + r, c := x.Dims() + + if cov == nil { + cov = mat64.NewSymDense(c, nil) + } else if n := cov.Symmetric(); n != c && n != 0 { + panic(matrix.ErrShape) + } + + var xt mat64.Dense + xt.Clone(x.T()) + // Subtract the mean of each of the columns. + for i := 0; i < c; i++ { + v := xt.RawRowView(i) + // This will panic with ErrShape if len(weights) != len(v), so + // we don't have to check the size later. + mean := Mean(v, weights) + floats.AddConst(-mean, v) + } + + if weights == nil { + // Calculate the normalization factor + // scaled by the sample size. + cov.SymOuterK(1/(float64(r)-1), &xt) + return cov + } + + // Multiply by the sqrt of the weights, so that multiplication is symmetric. + sqrtwts := make([]float64, r) + for i, w := range weights { + if w < 0 { + panic("stat: negative covariance matrix weights") + } + sqrtwts[i] = math.Sqrt(w) + } + // Weight the rows. + for i := 0; i < c; i++ { + v := xt.RawRowView(i) + floats.Mul(v, sqrtwts) + } + + // Calculate the normalization factor + // scaled by the weighted sample size. + cov.SymOuterK(1/(floats.Sum(weights)-1), &xt) + return cov +} + +// CorrelationMatrix returns the correlation matrix calculated from a matrix +// of data, x, using a two-pass algorithm. +// +// If weights is not nil the weighted correlation of x is calculated. weights +// must have length equal to the number of rows in input data matrix and +// must not contain negative elements. +// If corr is not nil it must either be zero-sized or have the same number of +// columns as the input data matrix. corr will be used as the destination for +// the correlation data. If corr is nil, a new mat64.SymDense is allocated for +// the destination. +func CorrelationMatrix(corr *mat64.SymDense, x mat64.Matrix, weights []float64) *mat64.SymDense { + // This will panic if the sizes don't match, or if weights is the wrong size. + corr = CovarianceMatrix(corr, x, weights) + covToCorr(corr) + return corr +} + +// covToCorr converts a covariance matrix to a correlation matrix. +func covToCorr(c *mat64.SymDense) { + r := c.Symmetric() + + s := make([]float64, r) + for i := 0; i < r; i++ { + s[i] = 1 / math.Sqrt(c.At(i, i)) + } + for i, sx := range s { + // Ensure that the diagonal has exactly ones. + c.SetSym(i, i, 1) + for j := i + 1; j < r; j++ { + v := c.At(i, j) + c.SetSym(i, j, v*sx*s[j]) + } + } +} + +// corrToCov converts a correlation matrix to a covariance matrix. +// The input sigma should be vector of standard deviations corresponding +// to the covariance. It will panic if len(sigma) is not equal to the +// number of rows in the correlation matrix. +func corrToCov(c *mat64.SymDense, sigma []float64) { + r, _ := c.Dims() + + if r != len(sigma) { + panic(matrix.ErrShape) + } + for i, sx := range sigma { + // Ensure that the diagonal has exactly sigma squared. + c.SetSym(i, i, sx*sx) + for j := i + 1; j < r; j++ { + v := c.At(i, j) + c.SetSym(i, j, v*sx*sigma[j]) + } + } +} + +// Mahalanobis computes the Mahalanobis distance +// D = sqrt((x-y)^T * Σ^-1 * (x-y)) +// between the vectors x and y given the cholesky decomposition of Σ. +// Mahalanobis returns NaN if the linear solve fails. +// +// See https://en.wikipedia.org/wiki/Mahalanobis_distance for more information. +func Mahalanobis(x, y *mat64.Vector, chol *mat64.Cholesky) float64 { + var diff mat64.Vector + diff.SubVec(x, y) + var tmp mat64.Vector + err := tmp.SolveCholeskyVec(chol, &diff) + if err != nil { + return math.NaN() + } + return math.Sqrt(mat64.Dot(&tmp, &diff)) +} diff --git a/stat/statmat_test.go b/stat/statmat_test.go new file mode 100644 index 00000000..4022314f --- /dev/null +++ b/stat/statmat_test.go @@ -0,0 +1,463 @@ +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package stat + +import ( + "math" + "math/rand" + "testing" + + "gonum.org/v1/gonum/floats" + "gonum.org/v1/gonum/matrix/mat64" +) + +func TestCovarianceMatrix(t *testing.T) { + // An alternative way to test this is to call the Variance and + // Covariance functions and ensure that the results are identical. + for i, test := range []struct { + data *mat64.Dense + weights []float64 + ans *mat64.Dense + }{ + { + data: mat64.NewDense(5, 2, []float64{ + -2, -4, + -1, 2, + 0, 0, + 1, -2, + 2, 4, + }), + weights: nil, + ans: mat64.NewDense(2, 2, []float64{ + 2.5, 3, + 3, 10, + }), + }, { + data: mat64.NewDense(3, 2, []float64{ + 1, 1, + 2, 4, + 3, 9, + }), + weights: []float64{ + 1, + 1.5, + 1, + }, + ans: mat64.NewDense(2, 2, []float64{ + .8, 3.2, + 3.2, 13.142857142857146, + }), + }, + } { + // Make a copy of the data to check that it isn't changing. + r := test.data.RawMatrix() + d := make([]float64, len(r.Data)) + copy(d, r.Data) + + w := make([]float64, len(test.weights)) + if test.weights != nil { + copy(w, test.weights) + } + for _, cov := range []*mat64.SymDense{nil, &mat64.SymDense{}} { + c := CovarianceMatrix(cov, test.data, test.weights) + if !mat64.Equal(c, test.ans) { + t.Errorf("%d: expected cov %v, found %v", i, test.ans, c) + } + if !floats.Equal(d, r.Data) { + t.Errorf("%d: data was modified during execution", i) + } + if !floats.Equal(w, test.weights) { + t.Errorf("%d: weights was modified during execution", i) + } + + // compare with call to Covariance + _, cols := c.Dims() + for ci := 0; ci < cols; ci++ { + for cj := 0; cj < cols; cj++ { + x := mat64.Col(nil, ci, test.data) + y := mat64.Col(nil, cj, test.data) + cov := Covariance(x, y, test.weights) + if math.Abs(cov-c.At(ci, cj)) > 1e-14 { + t.Errorf("CovMat does not match at (%v, %v). Want %v, got %v.", ci, cj, cov, c.At(ci, cj)) + } + } + } + } + + } + if !Panics(func() { CovarianceMatrix(nil, mat64.NewDense(5, 2, nil), []float64{}) }) { + t.Errorf("CovarianceMatrix did not panic with weight size mismatch") + } + if !Panics(func() { CovarianceMatrix(mat64.NewSymDense(1, nil), mat64.NewDense(5, 2, nil), nil) }) { + t.Errorf("CovarianceMatrix did not panic with preallocation size mismatch") + } + if !Panics(func() { CovarianceMatrix(nil, mat64.NewDense(2, 2, []float64{1, 2, 3, 4}), []float64{1, -1}) }) { + t.Errorf("CovarianceMatrix did not panic with negative weights") + } +} + +func TestCorrelationMatrix(t *testing.T) { + for i, test := range []struct { + data *mat64.Dense + weights []float64 + ans *mat64.Dense + }{ + { + data: mat64.NewDense(3, 3, []float64{ + 1, 2, 3, + 3, 4, 5, + 5, 6, 7, + }), + weights: nil, + ans: mat64.NewDense(3, 3, []float64{ + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + }), + }, + { + data: mat64.NewDense(5, 2, []float64{ + -2, -4, + -1, 2, + 0, 0, + 1, -2, + 2, 4, + }), + weights: nil, + ans: mat64.NewDense(2, 2, []float64{ + 1, 0.6, + 0.6, 1, + }), + }, { + data: mat64.NewDense(3, 2, []float64{ + 1, 1, + 2, 4, + 3, 9, + }), + weights: []float64{ + 1, + 1.5, + 1, + }, + ans: mat64.NewDense(2, 2, []float64{ + 1, 0.9868703275903379, + 0.9868703275903379, 1, + }), + }, + } { + // Make a copy of the data to check that it isn't changing. + r := test.data.RawMatrix() + d := make([]float64, len(r.Data)) + copy(d, r.Data) + + w := make([]float64, len(test.weights)) + if test.weights != nil { + copy(w, test.weights) + } + for _, corr := range []*mat64.SymDense{nil, &mat64.SymDense{}} { + c := CorrelationMatrix(corr, test.data, test.weights) + if !mat64.Equal(c, test.ans) { + t.Errorf("%d: expected corr %v, found %v", i, test.ans, c) + } + if !floats.Equal(d, r.Data) { + t.Errorf("%d: data was modified during execution", i) + } + if !floats.Equal(w, test.weights) { + t.Errorf("%d: weights was modified during execution", i) + } + + // compare with call to Covariance + _, cols := c.Dims() + for ci := 0; ci < cols; ci++ { + for cj := 0; cj < cols; cj++ { + x := mat64.Col(nil, ci, test.data) + y := mat64.Col(nil, cj, test.data) + corr := Correlation(x, y, test.weights) + if math.Abs(corr-c.At(ci, cj)) > 1e-14 { + t.Errorf("CorrMat does not match at (%v, %v). Want %v, got %v.", ci, cj, corr, c.At(ci, cj)) + } + } + } + } + + } + if !Panics(func() { CorrelationMatrix(nil, mat64.NewDense(5, 2, nil), []float64{}) }) { + t.Errorf("CorrelationMatrix did not panic with weight size mismatch") + } + if !Panics(func() { CorrelationMatrix(mat64.NewSymDense(1, nil), mat64.NewDense(5, 2, nil), nil) }) { + t.Errorf("CorrelationMatrix did not panic with preallocation size mismatch") + } + if !Panics(func() { CorrelationMatrix(nil, mat64.NewDense(2, 2, []float64{1, 2, 3, 4}), []float64{1, -1}) }) { + t.Errorf("CorrelationMatrix did not panic with negative weights") + } +} + +func TestCorrCov(t *testing.T) { + // test both Cov2Corr and Cov2Corr + for i, test := range []struct { + data *mat64.Dense + weights []float64 + }{ + { + data: mat64.NewDense(3, 3, []float64{ + 1, 2, 3, + 3, 4, 5, + 5, 6, 7, + }), + weights: nil, + }, + { + data: mat64.NewDense(5, 2, []float64{ + -2, -4, + -1, 2, + 0, 0, + 1, -2, + 2, 4, + }), + weights: nil, + }, { + data: mat64.NewDense(3, 2, []float64{ + 1, 1, + 2, 4, + 3, 9, + }), + weights: []float64{ + 1, + 1.5, + 1, + }, + }, + } { + corr := CorrelationMatrix(nil, test.data, test.weights) + cov := CovarianceMatrix(nil, test.data, test.weights) + + r := cov.Symmetric() + + // Get the diagonal elements from cov to determine the sigmas. + sigmas := make([]float64, r) + for i := range sigmas { + sigmas[i] = math.Sqrt(cov.At(i, i)) + } + + covFromCorr := mat64.NewSymDense(corr.Symmetric(), nil) + covFromCorr.CopySym(corr) + corrToCov(covFromCorr, sigmas) + + corrFromCov := mat64.NewSymDense(cov.Symmetric(), nil) + corrFromCov.CopySym(cov) + covToCorr(corrFromCov) + + if !mat64.EqualApprox(corr, corrFromCov, 1e-14) { + t.Errorf("%d: corrToCov did not match direct Correlation calculation. Want: %v, got: %v. ", i, corr, corrFromCov) + } + if !mat64.EqualApprox(cov, covFromCorr, 1e-14) { + t.Errorf("%d: covToCorr did not match direct Covariance calculation. Want: %v, got: %v. ", i, cov, covFromCorr) + } + + if !Panics(func() { corrToCov(mat64.NewSymDense(2, nil), []float64{}) }) { + t.Errorf("CorrelationMatrix did not panic with sigma size mismatch") + } + } +} + +func TestMahalanobis(t *testing.T) { + // Comparison with scipy. + for cas, test := range []struct { + x, y *mat64.Vector + Sigma *mat64.SymDense + ans float64 + }{ + { + x: mat64.NewVector(3, []float64{1, 2, 3}), + y: mat64.NewVector(3, []float64{0.8, 1.1, -1}), + Sigma: mat64.NewSymDense(3, + []float64{ + 0.8, 0.3, 0.1, + 0.3, 0.7, -0.1, + 0.1, -0.1, 7}), + ans: 1.9251757377680914, + }, + } { + var chol mat64.Cholesky + ok := chol.Factorize(test.Sigma) + if !ok { + panic("bad test") + } + ans := Mahalanobis(test.x, test.y, &chol) + if math.Abs(ans-test.ans) > 1e-14 { + t.Errorf("Cas %d: got %v, want %v", cas, ans, test.ans) + } + } +} + +// benchmarks + +func randMat(r, c int) mat64.Matrix { + x := make([]float64, r*c) + for i := range x { + x[i] = rand.Float64() + } + return mat64.NewDense(r, c, x) +} + +func benchmarkCovarianceMatrix(b *testing.B, m mat64.Matrix) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + CovarianceMatrix(nil, m, nil) + } +} +func benchmarkCovarianceMatrixWeighted(b *testing.B, m mat64.Matrix) { + r, _ := m.Dims() + wts := make([]float64, r) + for i := range wts { + wts[i] = 0.5 + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + CovarianceMatrix(nil, m, wts) + } +} +func benchmarkCovarianceMatrixInPlace(b *testing.B, m mat64.Matrix) { + _, c := m.Dims() + res := mat64.NewSymDense(c, nil) + b.ResetTimer() + for i := 0; i < b.N; i++ { + CovarianceMatrix(res, m, nil) + } +} + +func BenchmarkCovarianceMatrixSmallxSmall(b *testing.B) { + // 10 * 10 elements + x := randMat(small, small) + benchmarkCovarianceMatrix(b, x) +} +func BenchmarkCovarianceMatrixSmallxMedium(b *testing.B) { + // 10 * 1000 elements + x := randMat(small, medium) + benchmarkCovarianceMatrix(b, x) +} + +func BenchmarkCovarianceMatrixMediumxSmall(b *testing.B) { + // 1000 * 10 elements + x := randMat(medium, small) + benchmarkCovarianceMatrix(b, x) +} +func BenchmarkCovarianceMatrixMediumxMedium(b *testing.B) { + // 1000 * 1000 elements + x := randMat(medium, medium) + benchmarkCovarianceMatrix(b, x) +} + +func BenchmarkCovarianceMatrixLargexSmall(b *testing.B) { + // 1e5 * 10 elements + x := randMat(large, small) + benchmarkCovarianceMatrix(b, x) +} + +func BenchmarkCovarianceMatrixHugexSmall(b *testing.B) { + // 1e7 * 10 elements + x := randMat(huge, small) + benchmarkCovarianceMatrix(b, x) +} + +func BenchmarkCovarianceMatrixSmallxSmallWeighted(b *testing.B) { + // 10 * 10 elements + x := randMat(small, small) + benchmarkCovarianceMatrixWeighted(b, x) +} +func BenchmarkCovarianceMatrixSmallxMediumWeighted(b *testing.B) { + // 10 * 1000 elements + x := randMat(small, medium) + benchmarkCovarianceMatrixWeighted(b, x) +} + +func BenchmarkCovarianceMatrixMediumxSmallWeighted(b *testing.B) { + // 1000 * 10 elements + x := randMat(medium, small) + benchmarkCovarianceMatrixWeighted(b, x) +} +func BenchmarkCovarianceMatrixMediumxMediumWeighted(b *testing.B) { + // 1000 * 1000 elements + x := randMat(medium, medium) + benchmarkCovarianceMatrixWeighted(b, x) +} + +func BenchmarkCovarianceMatrixLargexSmallWeighted(b *testing.B) { + // 1e5 * 10 elements + x := randMat(large, small) + benchmarkCovarianceMatrixWeighted(b, x) +} + +func BenchmarkCovarianceMatrixHugexSmallWeighted(b *testing.B) { + // 1e7 * 10 elements + x := randMat(huge, small) + benchmarkCovarianceMatrixWeighted(b, x) +} + +func BenchmarkCovarianceMatrixSmallxSmallInPlace(b *testing.B) { + // 10 * 10 elements + x := randMat(small, small) + benchmarkCovarianceMatrixInPlace(b, x) +} +func BenchmarkCovarianceMatrixSmallxMediumInPlace(b *testing.B) { + // 10 * 1000 elements + x := randMat(small, medium) + benchmarkCovarianceMatrixInPlace(b, x) +} + +func BenchmarkCovarianceMatrixMediumxSmallInPlace(b *testing.B) { + // 1000 * 10 elements + x := randMat(medium, small) + benchmarkCovarianceMatrixInPlace(b, x) +} +func BenchmarkCovarianceMatrixMediumxMediumInPlace(b *testing.B) { + // 1000 * 1000 elements + x := randMat(medium, medium) + benchmarkCovarianceMatrixInPlace(b, x) +} + +func BenchmarkCovarianceMatrixLargexSmallInPlace(b *testing.B) { + // 1e5 * 10 elements + x := randMat(large, small) + benchmarkCovarianceMatrixInPlace(b, x) +} + +func BenchmarkCovarianceMatrixHugexSmallInPlace(b *testing.B) { + // 1e7 * 10 elements + x := randMat(huge, small) + benchmarkCovarianceMatrixInPlace(b, x) +} + +func BenchmarkCovToCorr(b *testing.B) { + // generate a 10x10 covariance matrix + m := randMat(small, small) + c := CovarianceMatrix(nil, m, nil) + cc := mat64.NewSymDense(c.Symmetric(), nil) + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + cc.CopySym(c) + b.StartTimer() + covToCorr(cc) + } +} + +func BenchmarkCorrToCov(b *testing.B) { + // generate a 10x10 correlation matrix + m := randMat(small, small) + c := CorrelationMatrix(nil, m, nil) + cc := mat64.NewSymDense(c.Symmetric(), nil) + sigma := make([]float64, small) + for i := range sigma { + sigma[i] = 2 + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + cc.CopySym(c) + b.StartTimer() + corrToCov(cc, sigma) + } +} diff --git a/unit/README.md b/unit/README.md new file mode 100644 index 00000000..467aa869 --- /dev/null +++ b/unit/README.md @@ -0,0 +1,13 @@ +# Gonum unit [![Build Status](https://travis-ci.org/gonum/unit.svg)](https://travis-ci.org/gonum/unit) [![Coverage Status](https://coveralls.io/repos/gonum/unit/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/unit?branch=master) [![GoDoc](https://godoc.org/github.com/gonum/unit?status.svg)](https://godoc.org/github.com/gonum/unit) + +Package unit provides a set of types and constants that facilitate the use of the International System of Units (SI). + +## Issues + +If you find any bugs, feel free to file an issue on the github issue tracker. Discussions on API changes, added features, code review, or similar requests are preferred on the gonum-dev Google Group. + +https://groups.google.com/forum/#!forum/gonum-dev + +## License + +Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. diff --git a/unit/autogen/autogen.go b/unit/autogen/autogen.go new file mode 100644 index 00000000..881180fa --- /dev/null +++ b/unit/autogen/autogen.go @@ -0,0 +1,356 @@ +package main + +import ( + "bytes" + "go/format" + "log" + "os" + "path/filepath" + "strings" + "text/template" +) + +type Unit struct { + Name string + Receiver string + Offset int // From normal (for example, mass base unit is kg, not kg) + PrintString string // print string for the unit (kg for mass) + ExtraConstant []Constant + Suffix string + Singular string + TypeComment string // Text to comment the type + Dimensions []Dimension + ErForm string //For Xxxer interface +} + +type Dimension struct { + Name string + Power int +} + +const ( + TimeName string = "TimeDim" + LengthName string = "LengthDim" + MassName string = "MassDim" +) + +type Constant struct { + Name string + Value string +} + +type Prefix struct { + Name string + Power int +} + +var Prefixes = []Prefix{ + { + Name: "Yotta", + Power: 24, + }, + { + Name: "Zetta", + Power: 21, + }, + { + Name: "Exa", + Power: 18, + }, + { + Name: "Peta", + Power: 15, + }, + { + Name: "Tera", + Power: 12, + }, + { + Name: "Giga", + Power: 9, + }, + { + Name: "Mega", + Power: 6, + }, + { + Name: "Kilo", + Power: 3, + }, + { + Name: "Hecto", + Power: 2, + }, + { + Name: "Deca", + Power: 1, + }, + { + Name: "", + Power: 0, + }, + { + Name: "Deci", + Power: -1, + }, + { + Name: "Centi", + Power: -2, + }, + { + Name: "Milli", + Power: -3, + }, + { + Name: "Micro", + Power: -6, + }, + { + Name: "Nano", + Power: -9, + }, + { + Name: "Pico", + Power: -12, + }, + { + Name: "Femto", + Power: -15, + }, + { + Name: "Atto", + Power: -18, + }, + { + Name: "Zepto", + Power: -21, + }, + { + Name: "Yocto", + Power: -24, + }, +} + +var Units = []Unit{ + { + Name: "Mass", + Receiver: "m", + Offset: -3, + PrintString: "kg", + Suffix: "gram", + Singular: "Gram", + TypeComment: "Mass represents a mass in kilograms", + Dimensions: []Dimension{ + { + Name: MassName, + Power: 1, + }, + }, + }, + { + Name: "Length", + Receiver: "l", + PrintString: "m", + Suffix: "meter", + Singular: "Meter", + TypeComment: "Length represents a length in meters", + Dimensions: []Dimension{ + { + Name: LengthName, + Power: 1, + }, + }, + }, + { + Name: "Time", + Receiver: "t", + PrintString: "s", + Suffix: "second", + Singular: "Second", + TypeComment: "Time represents a time in seconds", + ExtraConstant: []Constant{ + { + Name: "Hour", + Value: "3600", + }, + { + Name: "Minute", + Value: "60", + }, + }, + Dimensions: []Dimension{ + { + Name: TimeName, + Power: 1, + }, + }, + ErForm: "Timer", + }, +} + +var gopath string +var unitPkgPath string + +func init() { + gopath = os.Getenv("GOPATH") + if gopath == "" { + log.Fatal("no gopath") + } + + unitPkgPath = filepath.Join(gopath, "src", "github.com", "gonum", "unit") +} + +// Generate generates a file for each of the units +func main() { + for _, unit := range Units { + generate(unit) + } +} + +const headerTemplate = `// This file is autogenerated by github.com/gonum/unit/autogen +// Changes should be made to the autogenerated template rather than this one + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unit + +import ( + "errors" + "fmt" + "math" +) + +// {{.TypeComment}} +type {{.Name}} float64 +` + +var header = template.Must(template.New("header").Parse(headerTemplate)) + +const constTemplate = ` +const( + {{$unit := .Unit}} + {{range $unit.ExtraConstant}} {{.Name}} {{$unit.Name}} = {{.Value}} + {{end}} + {{$prefixes := .Prefixes}} + {{range $prefixes}} {{if .Name}} {{.Name}}{{$unit.Suffix}} {{else}} {{$unit.Singular}} {{end}} {{$unit.Name}} = {{if .Power}} 1e{{.Power}} {{else}} 1.0 {{end}} + {{end}} +) +` + +var prefix = template.Must(template.New("prefix").Parse(constTemplate)) + +const methodTemplate = ` +// Unit converts the {{.Name}} to a *Unit +func ({{.Receiver}} {{.Name}}) Unit() *Unit{ + return New(float64({{.Receiver}}), Dimensions{ + {{range .Dimensions}} {{.Name}}: {{.Power}}, + {{end}} + }) +} + +// {{.Name}} allows {{.Name}} to implement a {{if .ErForm}}{{.ErForm}}{{else}}{{.Name}}er{{end}} interface +func ({{.Receiver}} {{.Name}}) {{.Name}}() {{.Name}} { + return {{.Receiver}} +} + +// From converts the unit into the receiver. From returns an +// error if there is a mismatch in dimension +func ({{.Receiver}} *{{.Name}}) From(u Uniter) error{ + if !DimensionsMatch(u, {{.Singular}}){ + *{{.Receiver}} = {{.Name}}(math.NaN()) + return errors.New("Dimension mismatch") + } + *{{.Receiver}} = {{.Name}}(u.Unit().Value()) + return nil +} +` + +var methods = template.Must(template.New("methods").Parse(methodTemplate)) + +const formatTemplate = ` +func ({{.Receiver}} {{.Name}}) Format(fs fmt.State, c rune){ + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", {{.Receiver}}, float64({{.Receiver}})) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + if !pOk { + p = -1 + } + w, wOk := fs.Width() + if !wOk { + w = -1 + } + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64({{.Receiver}})) + fmt.Fprint(fs, " {{.PrintString}}") + default: + fmt.Fprintf(fs, "%%!%c(%T=%g {{.PrintString}})", c, {{.Receiver}}, float64({{.Receiver}})) + return +} +} +` + +var form = template.Must(template.New("format").Parse(formatTemplate)) + +func generate(unit Unit) { + lowerName := strings.ToLower(unit.Name) + filename := filepath.Join(unitPkgPath, lowerName+".go") + f, err := os.Create(filename) + if err != nil { + log.Fatal(err) + } + defer f.Close() + + // Need to define new prefixes because text/template can't do math. + // Need to do math because kilogram = 1 not 10^3 + + prefixes := make([]Prefix, len(Prefixes)) + for i, p := range Prefixes { + prefixes[i].Name = p.Name + prefixes[i].Power = p.Power + unit.Offset + } + + data := struct { + Prefixes []Prefix + Unit Unit + }{ + prefixes, + unit, + } + + buf := bytes.NewBuffer(make([]byte, 0)) + + err = header.Execute(buf, unit) + if err != nil { + log.Fatal(err) + } + + err = prefix.Execute(buf, data) + if err != nil { + log.Fatal(err) + } + + err = methods.Execute(buf, unit) + if err != nil { + log.Fatal(err) + } + + err = form.Execute(buf, unit) + if err != nil { + log.Fatal(err) + } + + b, err := format.Source(buf.Bytes()) + if err != nil { + f.Write(buf.Bytes()) // This is here to debug bad format + log.Fatalf("error formatting: %s", err) + } + + f.Write(b) +} diff --git a/unit/dimless.go b/unit/dimless.go new file mode 100644 index 00000000..5c6ce36e --- /dev/null +++ b/unit/dimless.go @@ -0,0 +1,66 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unit + +import ( + "errors" + "fmt" + "math" +) + +// Dimless represents a dimensionless constant +type Dimless float64 + +const ( + One Dimless = 1.0 +) + +// Unit converts the Dimless to a unit +func (d Dimless) Unit() *Unit { + return New(float64(d), Dimensions{}) +} + +// Dimless allows Dimless to implement a Dimlesser interface +func (d Dimless) Dimless() Dimless { + return d +} + +// From converts the unit to a dimless. Returns an error if there +// is a mismatch in dimension +func (d *Dimless) From(u *Unit) error { + if !DimensionsMatch(u, One) { + (*d) = Dimless(math.NaN()) + return errors.New("Dimension mismatch") + } + (*d) = Dimless(u.Unit().Value()) + return nil +} + +func (d Dimless) Format(fs fmt.State, c rune) { + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", d, float64(d)) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64(d)) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, float64(d)) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, float64(d)) + default: + fmt.Fprintf(fs, "%"+string(c), float64(d)) + } + default: + fmt.Fprintf(fs, "%%!%c(%T=%g)", c, d, float64(d)) + return + } +} diff --git a/unit/doc.go b/unit/doc.go new file mode 100644 index 00000000..a559e29a --- /dev/null +++ b/unit/doc.go @@ -0,0 +1,93 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package unit provides a set of types and constants that facilitate +// the use of the International System of Units (SI). +// +// Unit provides two main functionalities. +// +// 1) +// It provides a number of types representing either an SI base unit +// or a common combination of base units, named for the unit it +// represents (Length, Mass, Pressure, etc.). Each type has +// a float64 as the underlying unit, and its value represents the +// number of that underlying unit (Kilogram, Meter, Pascal, etc.). +// For example, +// height := 1.6 * unit.Meter +// acc := unit.Acceleration(9.8) +// creates a variable named 'height' with a value of 1.6 meters, and +// a variable named 'acc' with a value of 9.8 meters per second squared. +// These types can be used to add compile-time safety to code. For +// example, +// func UnitDensity(t unit.Temperature, pressure unit.Pressure) (unit.Density){ +// ... +// } +// func main(){ +// t := 300 * unit.Kelvin +// p := 5 * unit.Bar +// rho := UnitDensity(p, t) // gives compile-time error +// } +// gives a compile-time error (temperature type does not match pressure type) +// while the corresponding code using float64 runs without error. +// func Float64Density(temperature, pressure float64) (float64){ +// ... +// } +// func main(){ +// t := 300.0 // degrees kelvin +// p := 50000.0 // Pascals +// rho := Float64Density(p, t) // no error +// } +// Many types have constants defined representing named SI units (Meter, +// Kilogram, etc. ) or SI derived units (Bar, Milligram, etc.). These are +// all defined as multiples of the base unit, so, for example, the following +// are euqivalent +// l := 0.001 * unit.Meter +// k := 1 * unit.Millimeter +// j := unit.Length(0.001) +// +// 2) +// Unit provides the type "Unit", meant to represent a general dimensional +// value. unit.Unit can be used to help prevent errors of dimensionality +// when multiplying or dividing dimensional numbers. This package also +// provides the "Uniter" interface which is satisfied by any type which can +// be converted to a unit. New varibles of type Unit can be created with +// the New function and the Dimensions map. For example, the code +// acc := New(9.81, Dimensions{LengthDim:1, TimeDim: -2}) +// creates a variable "acc" which has a value of 9.81 m/s^2. Methods of +// unit can be used to modify this value, for example: +// acc.Mul(1.0 * unit.Kilogram).Mul(1 * unit.Meter) +// To convert the unit back into a typed float64 value, the From methods +// of the dimensional types should be used. From will return an error if the +// dimensions do not match. +// var energy unit.Energy +// err := (*energy).From(acc) +// Domain-specific problems may need custom dimensions, and for this purpose +// NewDimension should be used to help avoid accidental overlap between +// packages. For example, results from a blood test may be measured in +// "White blood cells per slide". In this case, NewDimension should be +// used to create a 'WhiteBloodCell' dimension. NewDimension takes in a +// string which will be used for printing that dimension, and will return +// a unique dimension number. NewDimension should not be +// used, however, to create the unit of 'Slide', because in this case slide +// is just a measurement of area. Instead, a constant could be defined. +// const Slide unit.Area = 0.001875 // m^2 +// var WhiteBloodCellDim unit.Dimension +// func init(){ +// WhiteBloodCellDim = unit.NewDimension("wbc") +// } +// type WbcPerArea float64 +// func (w WbcPerArea) Unit() *Unit{ +// return unit.New(float64(w), unit.Dimensions{WhiteBloodCellDim: 1, unit.LengthDim: -2}) +// } +// func main(){ +// v := WbcPerArea(15) +// fmt.Println(v.Unit()) // prints: 1.5e+01 m^-2 wbc +// } +// Please note that Unit cannot catch all errors related to dimensionality. +// Different physical ideas are sometimes expressed with the same dimensions +// and Unit is incapable of catching these mismatches. For example, energy and +// torque are both expressed as force times distance (Newton-meters in SI), +// but it is wrong to say that a torque of 10 N-m is the same as 10 J, even +// though the dimensions agree. +package unit diff --git a/unit/length.go b/unit/length.go new file mode 100644 index 00000000..671d4328 --- /dev/null +++ b/unit/length.go @@ -0,0 +1,92 @@ +// This file is autogenerated by github.com/gonum/unit/autogen +// Changes should be made to the autogenerated template rather than this one + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unit + +import ( + "errors" + "fmt" + "math" +) + +// Length represents a length in meters +type Length float64 + +const ( + Yottameter Length = 1e24 + Zettameter Length = 1e21 + Exameter Length = 1e18 + Petameter Length = 1e15 + Terameter Length = 1e12 + Gigameter Length = 1e9 + Megameter Length = 1e6 + Kilometer Length = 1e3 + Hectometer Length = 1e2 + Decameter Length = 1e1 + Meter Length = 1.0 + Decimeter Length = 1e-1 + Centimeter Length = 1e-2 + Millimeter Length = 1e-3 + Micrometer Length = 1e-6 + Nanometer Length = 1e-9 + Picometer Length = 1e-12 + Femtometer Length = 1e-15 + Attometer Length = 1e-18 + Zeptometer Length = 1e-21 + Yoctometer Length = 1e-24 +) + +// Unit converts the Length to a *Unit +func (l Length) Unit() *Unit { + return New(float64(l), Dimensions{ + LengthDim: 1, + }) +} + +// Length allows Length to implement a Lengther interface +func (l Length) Length() Length { + return l +} + +// From converts the unit into the receiver. From returns an +// error if there is a mismatch in dimension +func (l *Length) From(u Uniter) error { + if !DimensionsMatch(u, Meter) { + *l = Length(math.NaN()) + return errors.New("Dimension mismatch") + } + *l = Length(u.Unit().Value()) + return nil +} + +func (l Length) Format(fs fmt.State, c rune) { + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", l, float64(l)) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64(l)) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, float64(l)) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, float64(l)) + default: + fmt.Fprintf(fs, "%"+string(c), float64(l)) + } + fmt.Fprint(fs, " m") + default: + fmt.Fprintf(fs, "%%!%c(%T=%g m)", c, l, float64(l)) + return + } +} diff --git a/unit/mass.go b/unit/mass.go new file mode 100644 index 00000000..d3334551 --- /dev/null +++ b/unit/mass.go @@ -0,0 +1,92 @@ +// This file is autogenerated by github.com/gonum/unit/autogen +// Changes should be made to the autogenerated template rather than this one + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unit + +import ( + "errors" + "fmt" + "math" +) + +// Mass represents a mass in kilograms +type Mass float64 + +const ( + Yottagram Mass = 1e21 + Zettagram Mass = 1e18 + Exagram Mass = 1e15 + Petagram Mass = 1e12 + Teragram Mass = 1e9 + Gigagram Mass = 1e6 + Megagram Mass = 1e3 + Kilogram Mass = 1.0 + Hectogram Mass = 1e-1 + Decagram Mass = 1e-2 + Gram Mass = 1e-3 + Decigram Mass = 1e-4 + Centigram Mass = 1e-5 + Milligram Mass = 1e-6 + Microgram Mass = 1e-9 + Nanogram Mass = 1e-12 + Picogram Mass = 1e-15 + Femtogram Mass = 1e-18 + Attogram Mass = 1e-21 + Zeptogram Mass = 1e-24 + Yoctogram Mass = 1e-27 +) + +// Unit converts the Mass to a *Unit +func (m Mass) Unit() *Unit { + return New(float64(m), Dimensions{ + MassDim: 1, + }) +} + +// Mass allows Mass to implement a Masser interface +func (m Mass) Mass() Mass { + return m +} + +// From converts the unit into the receiver. From returns an +// error if there is a mismatch in dimension +func (m *Mass) From(u Uniter) error { + if !DimensionsMatch(u, Gram) { + *m = Mass(math.NaN()) + return errors.New("Dimension mismatch") + } + *m = Mass(u.Unit().Value()) + return nil +} + +func (m Mass) Format(fs fmt.State, c rune) { + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", m, float64(m)) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64(m)) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, float64(m)) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, float64(m)) + default: + fmt.Fprintf(fs, "%"+string(c), float64(m)) + } + fmt.Fprint(fs, " kg") + default: + fmt.Fprintf(fs, "%%!%c(%T=%g kg)", c, m, float64(m)) + return + } +} diff --git a/unit/time.go b/unit/time.go new file mode 100644 index 00000000..8e841793 --- /dev/null +++ b/unit/time.go @@ -0,0 +1,95 @@ +// This file is autogenerated by github.com/gonum/unit/autogen +// Changes should be made to the autogenerated template rather than this one + +// Copyright ©2014 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unit + +import ( + "errors" + "fmt" + "math" +) + +// Time represents a time in seconds +type Time float64 + +const ( + Hour Time = 3600 + Minute Time = 60 + + Yottasecond Time = 1e24 + Zettasecond Time = 1e21 + Exasecond Time = 1e18 + Petasecond Time = 1e15 + Terasecond Time = 1e12 + Gigasecond Time = 1e9 + Megasecond Time = 1e6 + Kilosecond Time = 1e3 + Hectosecond Time = 1e2 + Decasecond Time = 1e1 + Second Time = 1.0 + Decisecond Time = 1e-1 + Centisecond Time = 1e-2 + Millisecond Time = 1e-3 + Microsecond Time = 1e-6 + Nanosecond Time = 1e-9 + Picosecond Time = 1e-12 + Femtosecond Time = 1e-15 + Attosecond Time = 1e-18 + Zeptosecond Time = 1e-21 + Yoctosecond Time = 1e-24 +) + +// Unit converts the Time to a *Unit +func (t Time) Unit() *Unit { + return New(float64(t), Dimensions{ + TimeDim: 1, + }) +} + +// Time allows Time to implement a Timer interface +func (t Time) Time() Time { + return t +} + +// From converts the unit into the receiver. From returns an +// error if there is a mismatch in dimension +func (t *Time) From(u Uniter) error { + if !DimensionsMatch(u, Second) { + *t = Time(math.NaN()) + return errors.New("Dimension mismatch") + } + *t = Time(u.Unit().Value()) + return nil +} + +func (t Time) Format(fs fmt.State, c rune) { + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "%T(%v)", t, float64(t)) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, float64(t)) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, float64(t)) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, float64(t)) + default: + fmt.Fprintf(fs, "%"+string(c), float64(t)) + } + fmt.Fprint(fs, " s") + default: + fmt.Fprintf(fs, "%%!%c(%T=%g s)", c, t, float64(t)) + return + } +} diff --git a/unit/unit_test.go b/unit/unit_test.go new file mode 100644 index 00000000..4f01a0cc --- /dev/null +++ b/unit/unit_test.go @@ -0,0 +1,350 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unit + +import ( + "fmt" + "math" + "testing" +) + +var formatTests = []struct { + unit Uniter + format string + expect string +}{ + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2}), "%f", "9.810000 kg s^-2"}, + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2}), "%1.f", "10 kg s^-2"}, + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2}), "%.1f", "9.8 kg s^-2"}, + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2, LengthDim: 0}), "%f", "9.810000 kg s^-2"}, + {New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1}), "%e", "6.626070e-34 kg^2 s^-1"}, + {New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1}), "%.3e", "6.626e-34 kg^2 s^-1"}, + {New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1}), "%v", "6.62606957e-34 kg^2 s^-1"}, + {New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1}), "%s", "%!s(*Unit=6.62606957e-34 kg^2 s^-1)"}, + {Dimless(math.E), "%v", "2.718281828459045"}, + {Dimless(math.E), "%#v", "unit.Dimless(2.718281828459045)"}, + {Dimless(math.E), "%s", "%!s(unit.Dimless=2.718281828459045)"}, + {Mass(1), "%v", "1 kg"}, + {Mass(1), "%#v", "unit.Mass(1)"}, + {Mass(1), "%s", "%!s(unit.Mass=1 kg)"}, + {Length(1.61619926e-35), "%v", "1.61619926e-35 m"}, + {Length(1.61619926e-35), "%#v", "unit.Length(1.61619926e-35)"}, + {Length(1.61619926e-35), "%s", "%!s(unit.Length=1.61619926e-35 m)"}, + {Time(15.2), "%v", "15.2 s"}, + {Time(15.2), "%#v", "unit.Time(15.2)"}, + {Time(15.2), "%s", "%!s(unit.Time=15.2 s)"}, +} + +func TestFormat(t *testing.T) { + for _, ts := range formatTests { + if r := fmt.Sprintf(ts.format, ts.unit); r != ts.expect { + t.Errorf("Format %q: got: %q expected: %q", ts.format, r, ts.expect) + } + } +} + +func TestGoStringFormat(t *testing.T) { + expect1 := `&unit.Unit{dimensions:unit.Dimensions{4:2, 6:-1}, formatted:"", value:6.62606957e-34}` + expect2 := `&unit.Unit{dimensions:unit.Dimensions{6:-1, 4:2}, formatted:"", value:6.62606957e-34}` + if r := fmt.Sprintf("%#v", New(6.62606957e-34, Dimensions{MassDim: 2, TimeDim: -1})); r != expect1 && r != expect2 { + t.Errorf("Format %q: got: %q expected: %q", "%#v", r, expect1) + } +} + +var initializationTests = []struct { + unit *Unit + expValue float64 + expMap map[Dimension]int +}{ + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2}), 9.81, Dimensions{MassDim: 1, TimeDim: -2}}, + {New(9.81, Dimensions{MassDim: 1, TimeDim: -2, LengthDim: 0, CurrentDim: 0}), 9.81, Dimensions{MassDim: 1, TimeDim: -2}}, +} + +func TestInitialization(t *testing.T) { + for _, ts := range initializationTests { + if ts.expValue != ts.unit.value { + t.Errorf("Value wrong on initialization: got: %v expected: %v", ts.unit.value, ts.expValue) + } + if len(ts.expMap) != len(ts.unit.dimensions) { + t.Errorf("Map mismatch: got: %#v expected: %#v", ts.unit.dimensions, ts.expMap) + } + for key, val := range ts.expMap { + if ts.unit.dimensions[key] != val { + t.Errorf("Map mismatch: got: %#v expected: %#v", ts.unit.dimensions, ts.expMap) + } + } + } +} + +var dimensionEqualityTests = []struct { + name string + a Uniter + b Uniter + shouldMatch bool +}{ + {"same_empty", New(1.0, Dimensions{}), New(1.0, Dimensions{}), true}, + {"same_one", New(1.0, Dimensions{TimeDim: 1}), New(1.0, Dimensions{TimeDim: 1}), true}, + {"same_mult", New(1.0, Dimensions{TimeDim: 1, LengthDim: -2}), New(1.0, Dimensions{TimeDim: 1, LengthDim: -2}), true}, + {"diff_one_empty", New(1.0, Dimensions{}), New(1.0, Dimensions{TimeDim: 1, LengthDim: -2}), false}, + {"diff_same_dim", New(1.0, Dimensions{TimeDim: 1}), New(1.0, Dimensions{TimeDim: 2}), false}, + {"diff_same_pow", New(1.0, Dimensions{LengthDim: 1}), New(1.0, Dimensions{TimeDim: 1}), false}, + {"diff_numdim", New(1.0, Dimensions{TimeDim: 1, LengthDim: 2}), New(1.0, Dimensions{TimeDim: 2}), false}, + {"diff_one_same_dim", New(1.0, Dimensions{LengthDim: 1, TimeDim: 1}), New(1.0, Dimensions{LengthDim: 1, TimeDim: 2}), false}, +} + +func TestDimensionEquality(t *testing.T) { + for _, ts := range dimensionEqualityTests { + if DimensionsMatch(ts.a, ts.b) != ts.shouldMatch { + t.Errorf("Dimension comparison incorrect for case %s. got: %v, expected: %v", ts.name, !ts.shouldMatch, ts.shouldMatch) + } + } +} + +type UnitStructer interface { + UnitStruct() *UnitStruct +} + +type UnitStruct struct { + current int + length int + luminosity int + mass int + temperature int + time int + chemamt int // For mol + value float64 +} + +// Check if the dimensions of two units are the same +func DimensionsMatchStruct(aU, bU UnitStructer) bool { + a := aU.UnitStruct() + b := bU.UnitStruct() + if a.length != b.length { + return false + } + if a.time != b.time { + return false + } + if a.mass != b.mass { + return false + } + if a.current != b.current { + return false + } + if a.temperature != b.temperature { + return false + } + if a.luminosity != b.luminosity { + return false + } + if a.chemamt != b.chemamt { + return false + } + return true +} + +func (u *UnitStruct) UnitStruct() *UnitStruct { + return u +} + +func (u *UnitStruct) Add(aU UnitStructer) *UnitStruct { + a := aU.UnitStruct() + if !DimensionsMatchStruct(a, u) { + panic("dimension mismatch") + } + u.value += a.value + return u +} + +func (u *UnitStruct) Mul(aU UnitStructer) *UnitStruct { + a := aU.UnitStruct() + u.length += a.length + u.time += a.time + u.mass += a.mass + u.current += a.current + u.temperature += a.temperature + u.luminosity += a.luminosity + u.chemamt += a.chemamt + u.value *= a.value + return u +} + +var u3 *UnitStruct + +func BenchmarkAddStruct(b *testing.B) { + u1 := &UnitStruct{current: 1, chemamt: 5, value: 10} + u2 := &UnitStruct{current: 1, chemamt: 5, value: 100} + for i := 0; i < b.N; i++ { + u2.Add(u1) + } +} + +func BenchmarkMulStruct(b *testing.B) { + u1 := &UnitStruct{current: 1, chemamt: 5, value: 10} + u2 := &UnitStruct{mass: 1, time: 1, value: 100} + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} + +type UnitMapper interface { + UnitMap() *UnitMap +} + +type dimensionMap int + +const ( + LengthB dimensionMap = iota + TimeB + MassB + CurrentB + TemperatureB + LuminosityB + ChemAmtB +) + +type UnitMap struct { + dimension map[dimensionMap]int + value float64 +} + +// Check if the dimensions of two units are the same +func DimensionsMatchMap(aU, bU UnitMapper) bool { + a := aU.UnitMap() + b := bU.UnitMap() + if len(a.dimension) != len(b.dimension) { + panic("Unequal dimension") + } + for key, dimA := range a.dimension { + dimB, ok := b.dimension[key] + if !ok || dimA != dimB { + panic("Unequal dimension") + } + } + return true +} + +func (u *UnitMap) UnitMap() *UnitMap { + return u +} + +func (u *UnitMap) Add(aU UnitMapper) *UnitMap { + a := aU.UnitMap() + if !DimensionsMatchMap(a, u) { + panic("dimension mismatch") + } + u.value += a.value + return u +} + +func (u *UnitMap) Mul(aU UnitMapper) *UnitMap { + a := aU.UnitMap() + for key, val := range a.dimension { + u.dimension[key] += val + } + u.value *= a.value + return u +} + +func BenchmarkAddFloat(b *testing.B) { + a := 0.0 + c := 10.0 + for i := 0; i < b.N; i++ { + a += c + } +} + +func BenchmarkMulFloat(b *testing.B) { + a := 0.0 + c := 10.0 + for i := 0; i < b.N; i++ { + a *= c + } +} + +func BenchmarkAddMapSmall(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[CurrentB] = 1 + u1.dimension[ChemAmtB] = 5 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[CurrentB] = 1 + u2.dimension[ChemAmtB] = 5 + for i := 0; i < b.N; i++ { + u2.Add(u1) + } +} + +func BenchmarkMulMapSmallDiff(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[LengthB] = 1 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[MassB] = 1 + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} + +func BenchmarkMulMapSmallSame(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[LengthB] = 1 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[LengthB] = 2 + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} + +func BenchmarkMulMapLargeDiff(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[LengthB] = 1 + u1.dimension[MassB] = 1 + u1.dimension[ChemAmtB] = 1 + u1.dimension[TemperatureB] = 1 + u1.dimension[LuminosityB] = 1 + u1.dimension[TimeB] = 1 + u1.dimension[CurrentB] = 1 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[MassB] = 1 + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} + +func BenchmarkMulMapLargeSame(b *testing.B) { + u1 := &UnitMap{value: 10} + u1.dimension = make(map[dimensionMap]int) + u1.dimension[LengthB] = 2 + u1.dimension[MassB] = 2 + u1.dimension[ChemAmtB] = 2 + u1.dimension[TemperatureB] = 2 + u1.dimension[LuminosityB] = 2 + u1.dimension[TimeB] = 2 + u1.dimension[CurrentB] = 2 + + u2 := &UnitMap{value: 10} + u2.dimension = make(map[dimensionMap]int) + u2.dimension[LengthB] = 3 + u2.dimension[MassB] = 3 + u2.dimension[ChemAmtB] = 3 + u2.dimension[TemperatureB] = 3 + u2.dimension[LuminosityB] = 3 + u2.dimension[TimeB] = 3 + u2.dimension[CurrentB] = 3 + for i := 0; i < b.N; i++ { + u2.Mul(u1) + } +} diff --git a/unit/unittype.go b/unit/unittype.go new file mode 100644 index 00000000..d91899b2 --- /dev/null +++ b/unit/unittype.go @@ -0,0 +1,349 @@ +// Copyright ©2013 The gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package unit + +import ( + "bytes" + "fmt" + "sort" +) + +// Uniter is an interface representing a type that can be converted +// to a unit. +type Uniter interface { + Unit() *Unit +} + +// Dimension is a type representing an SI base dimension or other +// orthogonal dimension. If a new dimension is desired for a +// domain-specific problem, NewDimension should be used. Integers +// should never be cast as type dimension +// // Good: Create a package constant with an init function +// var MyDimension unit.Dimension +// init(){ +// MyDimension = NewDimension("my") +// } +// main(){ +// var := MyDimension(28.2) +// } +type Dimension int + +func (d Dimension) String() string { + switch { + case d == reserved: + return "reserved" + case d < Dimension(len(symbols)): + return symbols[d] + default: + panic("unit: illegal dimension") + } +} + +const ( + // SI Base Units + reserved Dimension = iota + CurrentDim + LengthDim + LuminousIntensityDim + MassDim + TemperatureDim + TimeDim + // Other common SI Dimensions + AngleDim // e.g. radians +) + +var ( + symbols = []string{ + CurrentDim: "A", + LengthDim: "m", + LuminousIntensityDim: "cd", + MassDim: "kg", + TemperatureDim: "K", + TimeDim: "s", + AngleDim: "rad", + } + + // for guaranteeing there aren't two identical symbols + dimensions = map[string]Dimension{ + "A": CurrentDim, + "m": LengthDim, + "cd": LuminousIntensityDim, + "kg": MassDim, + "K": TemperatureDim, + "s": TimeDim, + "rad": AngleDim, + + // Reserve common SI symbols + // base units + "mol": reserved, + // prefixes + "Y": reserved, + "Z": reserved, + "E": reserved, + "P": reserved, + "T": reserved, + "G": reserved, + "M": reserved, + "k": reserved, + "h": reserved, + "da": reserved, + "d": reserved, + "c": reserved, + "μ": reserved, + "n": reserved, + "p": reserved, + "f": reserved, + "a": reserved, + "z": reserved, + "y": reserved, + // SI Derived units with special symbols + "sr": reserved, + "F": reserved, + "C": reserved, + "S": reserved, + "H": reserved, + "V": reserved, + "Ω": reserved, + "J": reserved, + "N": reserved, + "Hz": reserved, + "lx": reserved, + "lm": reserved, + "Wb": reserved, + "W": reserved, + "Pa": reserved, + "Bq": reserved, + "Gy": reserved, + "Sv": reserved, + "kat": reserved, + // Units in use with SI + "ha": reserved, + "L": reserved, + "l": reserved, + // Units in Use Temporarily with SI + "bar": reserved, + "b": reserved, + "Ci": reserved, + "R": reserved, + "rd": reserved, + "rem": reserved, + } +) + +// TODO: Should we actually reserve "common" SI unit symbols ("N", "J", etc.) so there isn't confusion +// TODO: If we have a fancier ParseUnit, maybe the 'reserved' symbols should be a different map +// map[string]string which says how they go? + +// Dimensions represent the dimensionality of the unit in powers +// of that dimension. If a key is not present, the power of that +// dimension is zero. Dimensions is used in conjuction with New. +type Dimensions map[Dimension]int + +func (d Dimensions) String() string { + // Map iterates randomly, but print should be in a fixed order. Can't use + // dimension number, because for user-defined dimension that number may + // not be fixed from run to run. + atoms := make(unitPrinters, 0, len(d)) + for dimension, power := range d { + if power != 0 { + atoms = append(atoms, atom{dimension, power}) + } + } + sort.Sort(atoms) + var b bytes.Buffer + for i, a := range atoms { + if i > 0 { + b.WriteByte(' ') + } + fmt.Fprintf(&b, "%s", a.Dimension) + if a.pow != 1 { + fmt.Fprintf(&b, "^%d", a.pow) + } + } + + return b.String() +} + +type atom struct { + Dimension + pow int +} + +type unitPrinters []atom + +func (u unitPrinters) Len() int { + return len(u) +} + +func (u unitPrinters) Less(i, j int) bool { + return (u[i].pow > 0 && u[j].pow < 0) || u[i].String() < u[j].String() +} + +func (u unitPrinters) Swap(i, j int) { + u[i], u[j] = u[j], u[i] +} + +// NewDimension returns a new dimension variable which will have a +// unique representation across packages to prevent accidental overlap. +// The input string represents a symbol name which will be used for printing +// Unit types. This symbol may not overlap with any of the SI base units +// or other symbols of common use in SI ("kg", "J", "μ", etc.). A list of +// such symbols can be found at http://lamar.colostate.edu/~hillger/basic.htm or +// by consulting the package source. Furthermore, the provided symbol is also +// forbidden from overlapping with other packages calling NewDimension. NewDimension +// is expecting to be used only during initialization, and as such it will panic +// if the symbol matching an existing symbol +// NewDimension should only be called for unit types that are actually orthogonal +// to the base dimensions defined in this package. Please see the package-level +// documentation for further explanation. Calls to NewDimension are not thread safe. +func NewDimension(symbol string) Dimension { + _, ok := dimensions[symbol] + if ok { + panic("unit: dimension string \"" + symbol + "\" already used") + } + symbols = append(symbols, symbol) + d := Dimension(len(symbols)) + dimensions[symbol] = d + return d +} + +// Unit is a type a value with generic SI units. Most useful for +// translating between dimensions, for example, by multiplying +// an acceleration with a mass to get a force. Please see the +// package documentation for further explanation. +type Unit struct { + dimensions Dimensions // Map for custom dimensions + formatted string + value float64 +} + +// New creates a new variable of type Unit which has the value +// specified by value and the dimensions specified by the +// base units struct. The value is always in SI Units. +// +// Example: To create an acceleration of 3 m/s^2, one could do +// myvar := CreateUnit(3.0, &Dimensions{unit.LengthDim: 1, unit.TimeDim: -2}) +func New(value float64, d Dimensions) *Unit { + u := &Unit{ + dimensions: make(map[Dimension]int), + value: value, + } + for key, val := range d { + if val != 0 { + u.dimensions[key] = val + } + } + return u +} + +// DimensionsMatch checks if the dimensions of two Uniters are the same. +func DimensionsMatch(a, b Uniter) bool { + aUnit := a.Unit() + bUnit := b.Unit() + if len(aUnit.dimensions) != len(bUnit.dimensions) { + return false + } + for key, val := range aUnit.dimensions { + if bUnit.dimensions[key] != val { + return false + } + } + return true +} + +// Add adds the function argument to the reciever. Panics if the units of +// the receiver and the argument don't match. +func (u *Unit) Add(uniter Uniter) *Unit { + a := uniter.Unit() + if !DimensionsMatch(u, a) { + panic("unit: mismatched dimensions in addition") + } + u.value += a.value + return u +} + +// Unit implements the Uniter interface +func (u *Unit) Unit() *Unit { + return u +} + +// Mul multiply the receiver by the input changing the dimensions +// of the receiver as appropriate. The input is not changed. +func (u *Unit) Mul(uniter Uniter) *Unit { + a := uniter.Unit() + for key, val := range a.dimensions { + if d := u.dimensions[key]; d == -val { + delete(u.dimensions, key) + } else { + u.dimensions[key] = d + val + } + } + u.formatted = "" + u.value *= a.value + return u +} + +// Div divides the receiver by the argument changing the +// dimensions of the receiver as appropriate. +func (u *Unit) Div(uniter Uniter) *Unit { + a := uniter.Unit() + u.value /= a.value + for key, val := range a.dimensions { + if d := u.dimensions[key]; d == val { + delete(u.dimensions, key) + } else { + u.dimensions[key] = d - val + } + } + u.formatted = "" + return u +} + +// Value return the raw value of the unit as a float64. Use of this +// method is, in general, not recommended, though it can be useful +// for printing. Instead, the From type of a specific dimension +// should be used to guarantee dimension consistency. +func (u *Unit) Value() float64 { + return u.value +} + +// Format makes Unit satisfy the fmt.Formatter interface. The unit is formatted +// with dimensions appended. If the power if the dimension is not zero or one, +// symbol^power is appended, if the power is one, just the symbol is appended +// and if the power is zero, nothing is appended. Dimensions are appended +// in order by symbol name with positive powers ahead of negative powers. +func (u *Unit) Format(fs fmt.State, c rune) { + if u == nil { + fmt.Fprint(fs, "") + } + switch c { + case 'v': + if fs.Flag('#') { + fmt.Fprintf(fs, "&%#v", *u) + return + } + fallthrough + case 'e', 'E', 'f', 'F', 'g', 'G': + p, pOk := fs.Precision() + w, wOk := fs.Width() + switch { + case pOk && wOk: + fmt.Fprintf(fs, "%*.*"+string(c), w, p, u.value) + case pOk: + fmt.Fprintf(fs, "%.*"+string(c), p, u.value) + case wOk: + fmt.Fprintf(fs, "%*"+string(c), w, u.value) + default: + fmt.Fprintf(fs, "%"+string(c), u.value) + } + default: + fmt.Fprintf(fs, "%%!%c(*Unit=%g)", c, u) + return + } + if u.formatted == "" && len(u.dimensions) > 0 { + u.formatted = u.dimensions.String() + } + fmt.Fprintf(fs, " %s", u.formatted) +}